OpenCores
URL https://opencores.org/ocsvn/zipcpu/zipcpu/trunk

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [sw/] [zasm/] [asmdata.cpp] - Blame information for rev 14

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 13 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    asmdata.cpp
4
//
5
// Project:     Zip CPU -- a small, lightweight, RISC CPU core
6
//
7
// Purpose:     Like asmdata.h, this contains necessary data structures for the
8
//              assembler.  Specifically, in C/C++ fashion, this contains most
9
//              of the code for actually building such structures.
10
//
11
// Creator:     Dan Gisselquist, Ph.D.
12
//              Gisselquist Tecnology, LLC
13
//
14
////////////////////////////////////////////////////////////////////////////////
15
//
16
// Copyright (C) 2015, Gisselquist Technology, LLC
17
//
18
// This program is free software (firmware): you can redistribute it and/or
19
// modify it under the terms of  the GNU General Public License as published
20
// by the Free Software Foundation, either version 3 of the License, or (at
21
// your option) any later version.
22
//
23
// This program is distributed in the hope that it will be useful, but WITHOUT
24
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
25
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
26
// for more details.
27
//
28
// You should have received a copy of the GNU General Public License along
29
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
30
// target there if the PDF file isn't present.)  If not, see
31
// <http://www.gnu.org/licenses/> for a copy.
32
//
33
// License:     GPL, v3, as defined and found on www.gnu.org,
34
//              http://www.gnu.org/licenses/gpl.html
35
//
36
//
37
////////////////////////////////////////////////////////////////////////////////
38
 
39
#include <stdlib.h>
40
#include <assert.h>
41
#include <string.h>
42
#include "asmdata.h"
43
 
44
extern  void    yyerror(const char *str);
45
 
46
unsigned int    ILINE::eval(const int lno) {
47
        return (lno==0)?m_in:DEFAULT_LINE;
48
}
49
 
50
unsigned int    VLINE::eval(const int lno) {
51
        return DEFAULT_LINE;
52
}
53
 
54
unsigned int    DLINE::eval(const int lno) {
55
        return (lno==0)?m_data:DEFAULT_LINE;
56
}
57
 
58
void LLINE::addline(ASMLINE *line) {
59
        if (m_lines != NULL) {
60
                ASMLINE **nwlines = new ASMLINE *[m_nlines+1];
61
                for(int i=0; i<m_nlines; i++)
62
                        nwlines[i] = m_lines[i];
63
                delete[] m_lines;
64
                nwlines[m_nlines++] = line;
65
 
66
                m_lines = nwlines;
67
        } else {
68
                m_lines = new ASMLINE *[1];
69
                m_lines[m_nlines++] = line;
70
        }
71
};
72
 
73
bool    LLINE::isdefined(void) {
74
        for(int i=0; i<m_nlines; i++)
75
                if (!m_lines[i]->isdefined())
76
                return false;
77
        return true;
78
};
79
 
80
LLINE::~LLINE(void) {
81
        for(int i=0; i<m_nlines; i++)
82
                delete m_lines[i];
83
        delete m_lines;
84
}
85
 
86
unsigned int    LLINE::eval(const int lno) {
87
        return (lno < m_nlines)?m_lines[lno]->eval(0) : DEFAULT_LINE;
88
}
89
 
90
// int  m_op; // An operator
91
// AST  *m_left, *m_right;
92
 
93
int     AST_BRANCH::eval(void) {
94
        int     lft = m_left->eval(), rht = m_right->eval();
95
 
96
        switch(m_op) {
97
                case '+':       return lft + rht;
98
                case '-':       return lft - rht;
99
                case '*':       return lft * rht;
100
                case '/':       return lft / rht;
101
                case '%':       return lft % rht;
102
                case '^':       return lft ^ rht;
103
                case '|':       return lft | rht;
104
                case '&':       return lft & rht;
105
                case '~':       return ~lft;
106
                default:        yyerror("Unknown operation"); return lft;
107
        }
108
} void  AST_BRANCH::reduce(void) {
109
        if ((m_left)&&(m_left->m_node_type != 'N')&&(m_left->isdefined())) {
110
                int     val = m_left->eval();
111
                delete  m_left;
112
                m_left = new AST_NUMBER(val);
113
        } else
114
                m_left->reduce();
115
        if ((m_right)&&(m_right->m_node_type != 'N')&&(m_right->isdefined())) {
116
                int     val = m_right->eval();
117
                delete  m_right;
118
                m_right = new AST_NUMBER(val);
119
        } else
120
                m_right->reduce();
121
}
122
 
123
AST_IDENTIFIER::AST_IDENTIFIER(AST *ida, const char *idb) {
124
        m_node_type = 'I';
125
        m_id = ((AST_IDENTIFIER*)ida)->m_id + "." + std::string(idb);
126
        delete ida;
127
}
128
 
129
bool    AST_IDENTIFIER::isdefined(void) {
130
        bool    answer = stb_isdefined(m_id);
131
        return answer;
132
} int   AST_IDENTIFIER::eval(void) {
133
        return stb_value(m_id);
134
} void  AST_IDENTIFIER::reduce(void) {}
135
 
136
bool    AST_LABEL::isdefined(void) {
137
        bool    answer = stb_isdefined(m_label);
138
        return answer;
139
} int   AST_LABEL::eval(void) {
140
        return stb_value(m_label);
141
} void  AST_LABEL::reduce(void) {}
142
 
143
 
144
int     AST_NUMBER::eval(void) {
145
        return m_val;
146
} void  AST_NUMBER::reduce(void) {}
147
 
148
void    OBJFILE::open(const char *fname) {
149
        if ((m_fp != NULL)||(m_pc != 0l)) {
150
                fprintf(stderr, "Error: Can only change file names at startup\n");
151
                exit(-2);
152
        }
153
        m_fp = fopen(fname, "w");
154
        if (m_fp == NULL) {
155
                fprintf(stderr, "Cannot open %s for writing\n", fname);
156
                perror("O/S Err:");
157
                m_fp = fopen("/dev/null","w");
158
        }
159
}
160
 
161
void    OBJFILE::operator+=(ASMLINE *ln) {
162
        unsigned int    buf[1];
163
        int             nlines = ln->nlines();
164
 
165
        if (!ln->isdefined()) {
166
                // fprintf(stderr, "%08x: Adding undefined line:\n", m_pc);
167
                // ((TLINE *)ln)->dump(stderr);
168
                m_tbl.insert(m_tbl.end(), SAVED_ASMLINE(m_pc,ln));
169
        /*
170
        } else {
171
                fprintf(stderr, "%08x: Adding to file:\n", m_pc);
172
                ((TLINE *)ln)->dump(stderr);
173
        */
174
        }
175
        for(int i=0; i<nlines; i++) {
176
                buf[0] = ln->eval(i);
177
                if (m_fp) fwrite(buf, sizeof(ZIPI), 1, m_fp);
178
                m_pc++;
179
        }
180
}
181
 
182
bool    OBJFILE::reduce(void) {
183
        SVDTBL::iterator        i;
184
        bool    all_reduced = true;
185
 
186
        // printf("Checking for reductions\n");
187
        unsigned int tmp = m_pc;
188
        for(i=m_tbl.begin(); i != m_tbl.end(); i++) {
189
                // printf("LINE %08x\n", i->m_pc);
190
                ASMLINE *ln = i->m_ln;
191
                m_pc = i->m_pc;
192
                if (ln->isdefined()) {
193
                        // printf("PC = 0x%08x reduces\n", i->m_pc);
194
                        fseek(m_fp, sizeof(ZIPI)*i->m_pc, SEEK_SET);
195
                        for(int k=0; k< ln->nlines(); k++) {
196
                                ZIPI    buf[1];
197
                                m_pc = i->m_pc+k;
198
                                buf[0] = ln->eval(k);
199
                                // printf("\t0x%08x -> %08x\n", i->m_pc+k,
200
                                        // buf[0]);
201
                                fwrite(buf, sizeof(ZIPI), 1, m_fp);
202
                        }
203
                } else {
204
                        fprintf(stderr, "PC = 0x%08x isn\'t ready yet\n", i->m_pc);
205
                        i->m_ln->dump(stderr);
206
                        all_reduced = false;
207
                }
208
        } m_pc = tmp;
209
        return all_reduced;
210
}
211
 
212
bool    fitsin(const int v, const int b) {
213
        if (v>0)
214
                return (v < (1<<(b-1)));
215
        else
216
                return (-v <= (1<<b));
217
}
218
 
219
#define BLD_DUALOP(OP)                                                  \
220
        if (m_opa == zp.ZIP_Rnone)                                      \
221
                yyerror("Err: Dual Ops need a result register");        \
222
        if (m_opb != zp.ZIP_Rnone) {                                    \
223
                if(!fitsin(imm, 16))                                    \
224
                        yyerror("16-bit: Immediate out of range");      \
225
                in = zp.OP(m_cond,imm,m_opb,m_opa);                     \
226
        } else {                                                        \
227
                if(!fitsin(imm, 20))                                    \
228
                        yyerror("20-bit: Immediate out of range");      \
229
                in = zp.OP(m_cond,imm,m_opa);                           \
230
        }
231
 
232
#define BLD_BRANCH(OP,CND)                                              \
233
        if (fitsin(offset, 16))                                         \
234
                in = zp.OP(offset);                                     \
235
        else if (fitsin(offset, 20))                                    \
236
                in = zp.op_add(zp.CND, offset, zp.ZIP_PC);              \
237
        else { in = zp.OP(offset); yyerror("LONG JUMP NOT SUPPORTED"); }
238
 
239
ASMLINE *TLINE::eval(void) {
240
        ZIPI    in;
241
        ZPARSER zp;
242
        int     offset = 0, imm = 0;
243
 
244
        if (m_opcode != OP_MOV) {
245
                if ( ((m_opa!=zp.ZIP_Rnone)&&(m_opa > zp.ZIP_PC))
246
                        || ((m_opb!=zp.ZIP_Rnone)&&(m_opb > zp.ZIP_PC))  )
247
                        yyerror("Only move instructions can reference user regs");
248
        }
249
 
250
        // Offset used in jumps
251
        if (m_imm) {
252
                imm = m_imm->eval();
253
                offset = imm-objcode.pc()-1;
254
 
255
                if (m_opb == zp.ZIP_PC)
256
                        imm = offset;
257
        }
258
 
259
        switch(m_opcode) {
260
                case OP_CMP:
261
                        BLD_DUALOP(op_cmp)
262
                        break;
263
                case OP_TST:
264
                        BLD_DUALOP(op_tst)
265
                        break;
266
                case OP_MOV:
267
                        if ((m_opa == zp.ZIP_Rnone)||(m_opb == zp.ZIP_Rnone)) {
268
                                yyerror("Moves can only occurr between registers");
269
                                fprintf(stderr, "m_opa = %d, m_opb = %d\n", m_opa, m_opb);
270
                                fprintf(stderr, "m_imm = %d\n", imm);
271
                        } else if (!fitsin(imm, 16))
272
                                yyerror("Immediate overflow on move");
273
                        in = zp.op_mov(m_cond, imm, m_opb, m_opa);
274
                        break;
275
                case OP_LDIHI:
276
                        if ((imm & (-1<<16))!=0)
277
                                yyerror("16-bit Immediate out of range");
278
                        if (m_opb != zp.ZIP_Rnone)
279
                                yyerror("LDIHI cannot accept OP-B registers");
280
                        if (m_opa == zp.ZIP_Rnone)
281
                                yyerror("LDIHI needs a register result");
282
                        in = zp.op_ldihi(m_cond, imm, m_opa);
283
                        break;
284
                case OP_LDILO:
285
                        if ((imm & (-1<<16))!=0)
286
                                yyerror("16-bit Immediate out of range");
287
                        if (m_opb != zp.ZIP_Rnone)
288
                                yyerror("LDIHI cannot accept OP-B registers");
289
                        if (m_opa == zp.ZIP_Rnone)
290
                                yyerror("LDIHI needs a register result");
291
                        if ((imm & (-1<<16))!=0)
292
                                yyerror("16-bit Immediate out of range");
293
                        in = zp.op_ldilo(m_cond, imm, m_opa);
294
                        break;
295
                case OP_MPY:
296
                        in = zp.op_mpy(m_cond, imm, m_opb, m_opa);
297
                        break;
298
                case OP_ROL:
299
                        if (m_opa == zp.ZIP_Rnone)
300
                                yyerror("ROL needs a register result");
301
                        if (m_opb != zp.ZIP_Rnone)
302
                                in = zp.op_rol(m_cond, imm, m_opb, m_opa);
303
                        else
304
                                in = zp.op_rol(m_cond, imm, m_opa);
305
                        break;
306
                case OP_SUB:
307
                        BLD_DUALOP(op_sub)
308
                        break;
309
                case OP_AND:
310
                        BLD_DUALOP(op_and)
311
                        break;
312
                case OP_ADD:
313
                        BLD_DUALOP(op_add)
314
                        break;
315
                case OP_OR:
316
                        BLD_DUALOP(op_or)
317
                        break;
318
                case OP_XOR:
319
                        BLD_DUALOP(op_xor)
320
                        break;
321
                case OP_LSL:
322
                        BLD_DUALOP(op_lsl)
323
                        break;
324
                case OP_ASR:
325
                        BLD_DUALOP(op_asr)
326
                        break;
327
                case OP_LSR:
328
                        BLD_DUALOP(op_lsr)
329
                        break;
330
                case OP_LOD:
331
                        if (m_opb != zp.ZIP_Rnone)
332
                                in = zp.op_lod(m_cond, imm, m_opb, m_opa);
333
                        else
334
                                in = zp.op_lod(m_cond, imm, m_opa);
335
                        break;
336
                case OP_STO:
337
                        if (m_opb != zp.ZIP_Rnone)
338
                                in = zp.op_sto(m_cond, m_opa, imm, m_opb);
339
                        else
340
                                in = zp.op_sto(m_cond, m_opa, imm);
341
                        break;
342
                case OP_LDI:
343
                        if ((!fitsin(imm, 24))||(m_cond != zp.ZIPC_ALWAYS)) {
344
                                if (m_opa == zp.ZIP_PC)
345
                                        yyerror("Cannot LDI 32-bit addresses into PC register!");
346
                                LLINE *lln = new LLINE;
347
                                lln->addline(new ILINE(zp.op_ldihi(m_cond, (imm>>16)&0x0ffff, m_opa)));
348
                                lln->addline(new ILINE(zp.op_ldilo(m_cond, imm&0x0ffff, m_opa)));
349
                                return lln;
350
                        } else
351
                                in = zp.op_ldi(imm, m_opa);
352
                        break;
353
                case OP_CLRF:
354
                        in = zp.op_clrf(m_cond, m_opb);
355
                        break;
356
                case OP_NOT:
357
                        in = zp.op_not(m_cond, m_opb);
358
                        break;
359
                case OP_JMP:
360
                        if (!fitsin(imm, 16))
361
                                yyerror("JMP: Immediate out of range");
362
                        else if (m_opb == zp.ZIP_Rnone) {
363
                                if (m_cond != zp.ZIPC_ALWAYS)
364
                                        yyerror("JMP: Conditions are not allowed for absolute jumps.");
365
                                imm &= (1<<24)-1;
366
                                if (!fitsin(imm, 24))
367
                                        yyerror("JMP: Absolute jump address out of range");
368
                                zp.op_ldi(imm, zp.ZIP_PC);
369
                        }
370
                        in = zp.op_mov(m_cond, imm, m_opb, zp.ZIP_PC);
371
                case OP_BRA:
372
                        BLD_BRANCH(op_bra,ZIPC_ALWAYS)
373
                        break;
374
                case OP_BZ:
375
                        BLD_BRANCH(op_brz,ZIPC_Z)
376
                        break;
377
                case OP_BNZ:
378
                        BLD_BRANCH(op_bnz,ZIPC_NZ)
379
                        break;
380
                case OP_BGE:
381
                        BLD_BRANCH(op_bge,ZIPC_GE)
382
                        break;
383
                case OP_BGT:
384
                        BLD_BRANCH(op_bgt,ZIPC_GT)
385
                        break;
386
                case OP_BLT:
387
                        BLD_BRANCH(op_blt,ZIPC_LT)
388
                        break;
389
                case OP_BRC:
390
                        BLD_BRANCH(op_brc,ZIPC_C)
391
                        break;
392
                case OP_BRV:
393
                        BLD_BRANCH(op_brv,ZIPC_V)
394
                        break;
395
                case OP_CLR:
396
                        in = zp.op_clr(m_opb);
397
                        break;
398
                case OP_TRAP:
399
                        if((m_opb == zp.ZIP_Rnone)&&(m_cond == zp.ZIPC_ALWAYS))
400
                                in = zp.op_ldi(imm, zp.ZIP_CC);
401
                        else if((m_opb == zp.ZIP_Rnone)&&((imm&0x0ffff)==imm))
402
                                in = zp.op_ldilo(imm, zp.ZIP_CC);
403
                        else if((m_opb != zp.ZIP_Rnone)&&(fitsin(imm, 16)))
404
                                in = zp.op_mov(m_cond, imm, m_opb, zp.ZIP_CC);
405
                        else {
406
                                yyerror("Illegal trap!");
407
                                in = zp.op_trap(m_cond, 0);
408
                        }
409
                        break;
410
                case OP_HALT:   in = zp.op_halt(m_cond); break;
411
                case OP_RTU:    in = zp.op_rtu(m_cond); break;
412
                case OP_BUSY:   in = zp.op_busy(m_cond); break;
413
                case OP_BREAK:  in = zp.op_break(); break;
414
                case OP_NOOP:   in = zp.op_noop(); break;
415
                // OP_LJMP:
416
                case OP_NONE:
417
                default:        { char ebuf[256]; sprintf(ebuf, "Unrecognized OP-Code, %d, NONE = %d, CLR=%d", m_opcode, OP_NONE, OP_CLR);
418
                                yyerror(ebuf);
419
                                in = zp.op_noop(); break;
420
                                }
421
        } return new ILINE(in);
422
}
423
 
424
int     TLINE::nlines(void)  {
425
        if ((m_opcode == OP_LDI)&&( (!(m_imm->isdefined()))
426
                        || (m_cond != ZPARSER::ZIPC_ALWAYS)
427
                        || (!fitsin(m_imm->eval(), 24)) )) {
428
                return 2;
429
        }
430
        return 1;
431
}
432
 
433
unsigned int    TLINE::eval(const int lno) {
434
        if (!isdefined())
435
                return DEFAULT_LINE;
436
        else {
437
                ASMLINE *ln = this->eval();
438
                unsigned int val = ln->eval(lno);
439
                delete ln;
440
                return val;
441
        }
442
}
443
 
444
void    TLINE::dump(FILE *fp) {
445
        if (m_state == 'V')
446
                fprintf(fp, "Void\n");
447
        else if (m_state != 'T')
448
                fprintf(fp, "TLINE state != T (== %c)\n", m_state);
449
        else {
450
                fprintf(fp, "TLINE\n");
451
                switch(m_opcode) {
452
                case OP_CMP: fprintf(fp, "\tTLINE OP   = CMP\n");
453
                        break;
454
                case OP_TST: fprintf(fp, "\tTLINE OP   = TST\n");
455
                        break;
456
                case OP_MOV: fprintf(fp, "\tTLINE OP   = MOV\n");
457
                        break;
458
                case OP_LDIHI: fprintf(fp, "\tTLINE OP   = LDIHI\n");
459
                        break;
460
                case OP_LDILO: fprintf(fp, "\tTLINE OP   = LDILO\n");
461
                        break;
462
                case OP_MPY: fprintf(fp, "\tTLINE OP   = MPY\n");
463
                        break;
464
                case OP_ROL: fprintf(fp, "\tTLINE OP   = ROL\n");
465
                        break;
466
                case OP_SUB: fprintf(fp, "\tTLINE OP   = SUB\n");
467
                        break;
468
                case OP_AND: fprintf(fp, "\tTLINE OP   = AND\n");
469
                        break;
470
                case OP_ADD: fprintf(fp, "\tTLINE OP   = ADD\n");
471
                        break;
472
                case OP_OR: fprintf(fp, "\tTLINE OP   = OR\n");
473
                        break;
474
                case OP_XOR: fprintf(fp, "\tTLINE OP   = XOR\n");
475
                        break;
476
                case OP_LSL: fprintf(fp, "\tTLINE OP   = LSL\n");
477
                        break;
478
                case OP_ASR: fprintf(fp, "\tTLINE OP   = ASR\n");
479
                        break;
480
                case OP_LSR: fprintf(fp, "\tTLINE OP   = LSR\n");
481
                        break;
482
                case OP_LOD: fprintf(fp, "\tTLINE OP   = LOD\n");
483
                        break;
484
                case OP_STO: fprintf(fp, "\tTLINE OP   = STO\n");
485
                        break;
486
                case OP_LDI: fprintf(fp, "\tTLINE OP   = LDI\n");
487
                        break;
488
                case OP_CLRF: fprintf(fp, "\tTLINE OP   = CLRF\n");
489
                        break;
490
                case OP_NOT: fprintf(fp, "\tTLINE OP   = NOT\n");
491
                        break;
492
                case OP_JMP: fprintf(fp, "\tTLINE OP   = JMP\n");
493
                        break;
494
                case OP_BRA: fprintf(fp, "\tTLINE OP   = BRA\n");
495
                        break;
496
                case OP_BZ:
497
                case OP_BNZ:
498
                case OP_BGE:
499
                case OP_BGT:
500
                case OP_BLT:
501
                case OP_BRC:
502
                case OP_BRV:
503
                        fprintf(fp, "\tTLINE OP   = BRA.C\n");
504
                        break;
505
                case OP_CLR: fprintf(fp, "\tTLINE OP   = CLR\n");
506
                        break;
507
                case OP_TRAP: fprintf(fp, "\tTLINE OP   = TRAP\n");
508
                        break;
509
                case OP_HALT: fprintf(fp, "\tTLINE OP   = HALT\n");
510
                        break;
511
                case OP_RTU: fprintf(fp, "\tTLINE OP   = RTU\n");
512
                        break;
513
                case OP_BUSY: fprintf(fp, "\tTLINE OP   = BUSY\n");
514
                        break;
515
                case OP_BREAK: fprintf(fp, "\tTLINE OP   = BREAK\n");
516
                        break;
517
                case OP_NOOP: fprintf(fp, "\tTLINE OP   = NOOP\n");
518
                        break;
519
                // OP_LJMP:
520
                case OP_NONE:
521
                default:
522
                        fprintf(fp, "\tTLINE OP   = (Unrecognized, %d)\n", m_opcode);
523
                                break;
524
                }
525
                fprintf(fp, "\tTLINE COND = %d\n", m_cond);
526
                if (m_imm == NULL)
527
                        fprintf(fp, "\tTLINE imm  = (NULL)\n");
528
                else if (!m_imm->isdefined()) {
529
                        m_imm->reduce();
530
                        fprintf(fp, "\tTLINE imm  = ");
531
                        m_imm->dump(fp);
532
                        fprintf(fp, "\n");
533
                } else
534
                        fprintf(fp, "\tTLINE imm  = %d\n", m_imm->eval());
535
                fprintf(fp, "\tTLINE opb  = %d\n", m_opb);
536
                fprintf(fp, "\tTLINE opa  = %d\n", m_opa);
537
        }
538
}
539
 
540
 
541
// Now, for our symbol table
542
class   SYMTABLE_ENTRY {
543
private:
544
        int     m_recursion_check;
545
 
546
        std::string     &trim(std::string &s) {
547
                std::string::iterator   ptr = s.end()-1;
548
 
549
                while((ptr >= s.begin())&&(isspace(*ptr)))
550
                        *ptr-- = '\0';
551
                if (*ptr == ':')
552
                        *ptr-- = '\0';
553
 
554
                // printf("STORING: %s\n", s.c_str());
555
 
556
                return s;
557
        }
558
 
559
public:
560
        std::string     m_name;
561
        AST             *m_value;
562
        SYMTABLE_ENTRY(const char *str) : m_recursion_check(0), m_name(str), m_value(NULL) {
563
                trim(m_name);
564
        } SYMTABLE_ENTRY(const char *str, AST *v) : m_recursion_check(0), m_name(str), m_value(v) {
565
                trim(m_name);
566
        } ~SYMTABLE_ENTRY(void) {
567
                delete m_value;
568
        }
569
 
570
        SYMTABLE_ENTRY &operator=(AST *new_value) {
571
                if (m_value)
572
                        delete  m_value;
573
                m_value = new_value;
574
        }
575
 
576
        bool    isdefined(void) {
577
                if (m_recursion_check > 0) {
578
                        fprintf(stderr, "RECURSION DETECTED! Symbol: %s\n",
579
                                m_name.c_str());
580
                        return false;
581
                }
582
                m_recursion_check = 1;
583
                if (m_value->m_node_type != 'N')
584
                        m_value->reduce();
585
                bool    answer = m_value->isdefined();
586
                m_recursion_check = 0;
587
                return answer;
588
        }
589
        int     val(void) {
590
                if ((m_value->isdefined())&&(m_value->m_node_type != 'N')) {
591
                        int     v = m_value->eval();
592
                        AST     *tmp;
593
                        tmp = m_value;
594
                        m_value = new AST_NUMBER(v);
595
                        delete tmp;
596
                } return (m_value->eval());
597
        }
598
        void    dump(FILE *fp) { m_value->dump(fp); }
599
};
600
 
601
class   SYMBOL_TABLE    {
602
private:
603
        typedef SYMTABLE_ENTRY  *TBLV;
604
        typedef std::list<TBLV> TBLT;
605
 
606
        TBLT    m_tbl;
607
 
608
        TBLT::iterator  lookup(const char *str) {
609
                TBLT::iterator  i = m_tbl.begin();
610
                for(; (i!=m_tbl.end())&&(strcmp(str, (*i)->m_name.c_str())>0);
611
                                i++)
612
                        ;
613
                if ((i != m_tbl.end())&&(strcmp(str,(*i)->m_name.c_str())==0))
614
                        return i;
615
                return  m_tbl.end();
616
        }
617
 
618
public:
619
        SYMBOL_TABLE(void) {}
620
        ~SYMBOL_TABLE(void) {
621
                TBLT::iterator i = m_tbl.begin();
622
                while(i != m_tbl.end()) {
623
                        delete (*i);
624
                        m_tbl.erase(i);
625
                }
626
        }
627
 
628
        void    define(const char *key, AST *value) {
629
                SYMTABLE_ENTRY  *v = new SYMTABLE_ENTRY(key, value);
630
                TBLT::iterator  i = m_tbl.begin();
631
                for(; (i!=m_tbl.end())&&(strcmp(key, (*i)->m_name.c_str())>0);
632
                                i++)
633
                        ;
634
                m_tbl.insert(i, v);
635
 
636
                /*
637
                fprintf(stderr, "Defining: %s = ", key);
638
                value->dump(stderr);
639
                fprintf(stderr, "\n");
640
                */
641
        }
642
 
643
        bool    isdefined(const char *key) {
644
                TBLT::iterator  i = lookup(key);
645
                if (i == m_tbl.end()) {
646
                        // fprintf(stderr, "%s is not in the symbol table\n", key);
647
                        return false;
648
                } else {
649
                        bool    defined = (*i)->isdefined();
650
                        /*
651
                        if (!defined) {
652
                                fprintf(stderr, "KEY: %s = ", key);
653
                                (*i)->dump(stderr);
654
                                fprintf(stderr, " is not yet defined\n");
655
                        } */
656
                        return (*i)->isdefined();
657
                }
658
        }
659
 
660
        int     value(const char *key) {
661
                TBLT::iterator  i = lookup(key);
662
                if (i == m_tbl.end())
663
                        return 0;
664
                else
665
                        return (*i)->val();
666
        }
667
};
668
 
669
SYMBOL_TABLE    *global_context = NULL, *file_context = NULL;
670
 
671
bool    stb_isdefined(const char *key) {
672
        if ((file_context)&&(file_context->isdefined(key)))
673
                return true;
674
        else
675
                return global_context->isdefined(key);
676
} int   stb_value(const char *key) {
677
        if (file_context->isdefined(key))
678
                return file_context->value(key);
679
        else
680
                return global_context->value(key);
681
} void  stb_define(const char *key, AST *value) {
682
        file_context->define(key, value);
683
} void  gbl_define(const char *key, AST *value) {
684
        global_context->define(key, value);
685
}
686
 
687
void    create_new_context(void) {
688
        if (global_context == NULL)
689
                global_context = new SYMBOL_TABLE;
690
        if (file_context != NULL)
691
                delete file_context;
692
        file_context = new SYMBOL_TABLE;
693
}
694
 
695
 
696
// Convenience functions for accessing the symbol table
697
bool    stb_isdefined(const std::string &key) {
698
        bool answer = stb_isdefined(key.c_str());
699
        return answer;
700
} int   stb_value(const std::string &key) {
701
        return stb_value(key.c_str());
702
} void  stb_define(const std::string &key, AST *value) {
703
        stb_define(key.c_str(), value);
704
} void  gbl_define(const std::string &key, AST *value) {
705
        gbl_define(key.c_str(), value);
706
}
707
 
708
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.