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

Subversion Repositories zipcpu

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

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 69 dgisselq
//              Gisselquist Technology, LLC
13 13 dgisselq
//
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 143 dgisselq
#include "twoc.h"
44 13 dgisselq
 
45
extern  void    yyerror(const char *str);
46
 
47
unsigned int    ILINE::eval(const int lno) {
48
        return (lno==0)?m_in:DEFAULT_LINE;
49
}
50
 
51
unsigned int    VLINE::eval(const int lno) {
52
        return DEFAULT_LINE;
53
}
54
 
55
unsigned int    DLINE::eval(const int lno) {
56
        return (lno==0)?m_data:DEFAULT_LINE;
57
}
58
 
59
void LLINE::addline(ASMLINE *line) {
60
        if (m_lines != NULL) {
61
                ASMLINE **nwlines = new ASMLINE *[m_nlines+1];
62
                for(int i=0; i<m_nlines; i++)
63
                        nwlines[i] = m_lines[i];
64
                delete[] m_lines;
65
                nwlines[m_nlines++] = line;
66
 
67
                m_lines = nwlines;
68
        } else {
69
                m_lines = new ASMLINE *[1];
70
                m_lines[m_nlines++] = line;
71
        }
72 26 dgisselq
 
73
        if (m_lineno > line->m_lineno)
74
                m_lineno = line->m_lineno;
75 13 dgisselq
};
76
 
77
bool    LLINE::isdefined(void) {
78
        for(int i=0; i<m_nlines; i++)
79
                if (!m_lines[i]->isdefined())
80
                return false;
81
        return true;
82
};
83
 
84
LLINE::~LLINE(void) {
85
        for(int i=0; i<m_nlines; i++)
86
                delete m_lines[i];
87
        delete m_lines;
88
}
89
 
90
unsigned int    LLINE::eval(const int lno) {
91
        return (lno < m_nlines)?m_lines[lno]->eval(0) : DEFAULT_LINE;
92
}
93
 
94
// int  m_op; // An operator
95
// AST  *m_left, *m_right;
96
 
97
int     AST_BRANCH::eval(void) {
98
        int     lft = m_left->eval(), rht = m_right->eval();
99
 
100
        switch(m_op) {
101
                case '+':       return lft + rht;
102
                case '-':       return lft - rht;
103
                case '*':       return lft * rht;
104
                case '/':       return lft / rht;
105
                case '%':       return lft % rht;
106
                case '^':       return lft ^ rht;
107
                case '|':       return lft | rht;
108
                case '&':       return lft & rht;
109
                case '~':       return ~lft;
110
                default:        yyerror("Unknown operation"); return lft;
111
        }
112
} void  AST_BRANCH::reduce(void) {
113
        if ((m_left)&&(m_left->m_node_type != 'N')&&(m_left->isdefined())) {
114
                int     val = m_left->eval();
115
                delete  m_left;
116
                m_left = new AST_NUMBER(val);
117
        } else
118
                m_left->reduce();
119
        if ((m_right)&&(m_right->m_node_type != 'N')&&(m_right->isdefined())) {
120
                int     val = m_right->eval();
121
                delete  m_right;
122
                m_right = new AST_NUMBER(val);
123
        } else
124
                m_right->reduce();
125
}
126
 
127
AST_IDENTIFIER::AST_IDENTIFIER(AST *ida, const char *idb) {
128
        m_node_type = 'I';
129
        m_id = ((AST_IDENTIFIER*)ida)->m_id + "." + std::string(idb);
130
        delete ida;
131
}
132
 
133
bool    AST_IDENTIFIER::isdefined(void) {
134
        bool    answer = stb_isdefined(m_id);
135
        return answer;
136
} int   AST_IDENTIFIER::eval(void) {
137
        return stb_value(m_id);
138
} void  AST_IDENTIFIER::reduce(void) {}
139
 
140
bool    AST_LABEL::isdefined(void) {
141
        bool    answer = stb_isdefined(m_label);
142
        return answer;
143
} int   AST_LABEL::eval(void) {
144
        return stb_value(m_label);
145
} void  AST_LABEL::reduce(void) {}
146
 
147
 
148
int     AST_NUMBER::eval(void) {
149
        return m_val;
150
} void  AST_NUMBER::reduce(void) {}
151
 
152
void    OBJFILE::open(const char *fname) {
153
        if ((m_fp != NULL)||(m_pc != 0l)) {
154
                fprintf(stderr, "Error: Can only change file names at startup\n");
155
                exit(-2);
156
        }
157
        m_fp = fopen(fname, "w");
158
        if (m_fp == NULL) {
159
                fprintf(stderr, "Cannot open %s for writing\n", fname);
160
                perror("O/S Err:");
161
                m_fp = fopen("/dev/null","w");
162
        }
163
}
164
 
165
void    OBJFILE::operator+=(ASMLINE *ln) {
166
        unsigned int    buf[1];
167
        int             nlines = ln->nlines();
168
 
169
        if (!ln->isdefined()) {
170
                // fprintf(stderr, "%08x: Adding undefined line:\n", m_pc);
171
                // ((TLINE *)ln)->dump(stderr);
172
                m_tbl.insert(m_tbl.end(), SAVED_ASMLINE(m_pc,ln));
173
        /*
174
        } else {
175
                fprintf(stderr, "%08x: Adding to file:\n", m_pc);
176
                ((TLINE *)ln)->dump(stderr);
177
        */
178
        }
179
        for(int i=0; i<nlines; i++) {
180
                buf[0] = ln->eval(i);
181
                if (m_fp) fwrite(buf, sizeof(ZIPI), 1, m_fp);
182
                m_pc++;
183
        }
184
}
185
 
186
bool    OBJFILE::reduce(void) {
187
        SVDTBL::iterator        i;
188
        bool    all_reduced = true;
189
 
190
        // printf("Checking for reductions\n");
191
        unsigned int tmp = m_pc;
192
        for(i=m_tbl.begin(); i != m_tbl.end(); i++) {
193
                // printf("LINE %08x\n", i->m_pc);
194
                ASMLINE *ln = i->m_ln;
195
                m_pc = i->m_pc;
196
                if (ln->isdefined()) {
197
                        // printf("PC = 0x%08x reduces\n", i->m_pc);
198
                        fseek(m_fp, sizeof(ZIPI)*i->m_pc, SEEK_SET);
199
                        for(int k=0; k< ln->nlines(); k++) {
200
                                ZIPI    buf[1];
201
                                m_pc = i->m_pc+k;
202
                                buf[0] = ln->eval(k);
203
                                // printf("\t0x%08x -> %08x\n", i->m_pc+k,
204
                                        // buf[0]);
205
                                fwrite(buf, sizeof(ZIPI), 1, m_fp);
206
                        }
207
                } else {
208 26 dgisselq
                        fprintf(stderr, "Line %d contains an undefined symbol: ", ln->m_lineno);
209 13 dgisselq
                        fprintf(stderr, "PC = 0x%08x isn\'t ready yet\n", i->m_pc);
210
                        i->m_ln->dump(stderr);
211
                        all_reduced = false;
212
                }
213
        } m_pc = tmp;
214
        return all_reduced;
215
}
216
 
217
bool    fitsin(const int v, const int b) {
218
        if (v>0)
219
                return (v < (1<<(b-1)));
220
        else
221
                return (-v <= (1<<b));
222
}
223
 
224
#define BLD_DUALOP(OP)                                                  \
225
        if (m_opa == zp.ZIP_Rnone)                                      \
226
                yyerror("Err: Dual Ops need a result register");        \
227
        if (m_opb != zp.ZIP_Rnone) {                                    \
228 69 dgisselq
                if(!fitsin(imm, 14))                                    \
229
                        yyerror("14-bit: Immediate out of range");      \
230 13 dgisselq
                in = zp.OP(m_cond,imm,m_opb,m_opa);                     \
231
        } else {                                                        \
232 69 dgisselq
                if(!fitsin(imm, 18))                                    \
233
                        yyerror("18-bit: Immediate out of range");      \
234 13 dgisselq
                in = zp.OP(m_cond,imm,m_opa);                           \
235
        }
236
 
237
#define BLD_BRANCH(OP,CND)                                              \
238 69 dgisselq
        if (fitsin(offset, 13))                                         \
239 13 dgisselq
                in = zp.OP(offset);                                     \
240 69 dgisselq
        else if (fitsin(offset, 18))                                    \
241 13 dgisselq
                in = zp.op_add(zp.CND, offset, zp.ZIP_PC);              \
242
        else { in = zp.OP(offset); yyerror("LONG JUMP NOT SUPPORTED"); }
243
 
244
ASMLINE *TLINE::eval(void) {
245
        ZIPI    in;
246
        ZPARSER zp;
247
        int     offset = 0, imm = 0;
248
 
249
        if (m_opcode != OP_MOV) {
250
                if ( ((m_opa!=zp.ZIP_Rnone)&&(m_opa > zp.ZIP_PC))
251
                        || ((m_opb!=zp.ZIP_Rnone)&&(m_opb > zp.ZIP_PC))  )
252
                        yyerror("Only move instructions can reference user regs");
253
        }
254
 
255
        // Offset used in jumps
256
        if (m_imm) {
257
                imm = m_imm->eval();
258
                offset = imm-objcode.pc()-1;
259
 
260
                if (m_opb == zp.ZIP_PC)
261
                        imm = offset;
262
        }
263
 
264
        switch(m_opcode) {
265
                case OP_CMP:
266
                        BLD_DUALOP(op_cmp)
267
                        break;
268
                case OP_TST:
269
                        BLD_DUALOP(op_tst)
270
                        break;
271
                case OP_MOV:
272
                        if ((m_opa == zp.ZIP_Rnone)||(m_opb == zp.ZIP_Rnone)) {
273
                                yyerror("Moves can only occurr between registers");
274
                                fprintf(stderr, "m_opa = %d, m_opb = %d\n", m_opa, m_opb);
275
                                fprintf(stderr, "m_imm = %d\n", imm);
276 69 dgisselq
                        } else if (!fitsin(imm, 13))
277 13 dgisselq
                                yyerror("Immediate overflow on move");
278
                        in = zp.op_mov(m_cond, imm, m_opb, m_opa);
279
                        break;
280 143 dgisselq
#ifdef  LONG_MPY
281
                case OP_MPY:
282
                        BLD_DUALOP(op_mpy);
283
                        break;
284
#else
285 13 dgisselq
                case OP_LDIHI:
286
                        if ((imm & (-1<<16))!=0)
287
                                yyerror("16-bit Immediate out of range");
288
                        if (m_opb != zp.ZIP_Rnone)
289
                                yyerror("LDIHI cannot accept OP-B registers");
290
                        if (m_opa == zp.ZIP_Rnone)
291
                                yyerror("LDIHI needs a register result");
292
                        in = zp.op_ldihi(m_cond, imm, m_opa);
293
                        break;
294 143 dgisselq
#endif
295 13 dgisselq
                case OP_LDILO:
296
                        if ((imm & (-1<<16))!=0)
297
                                yyerror("16-bit Immediate out of range");
298
                        if (m_opb != zp.ZIP_Rnone)
299
                                yyerror("LDIHI cannot accept OP-B registers");
300
                        if (m_opa == zp.ZIP_Rnone)
301
                                yyerror("LDIHI needs a register result");
302
                        if ((imm & (-1<<16))!=0)
303
                                yyerror("16-bit Immediate out of range");
304
                        in = zp.op_ldilo(m_cond, imm, m_opa);
305
                        break;
306 143 dgisselq
#ifdef  LONG_MPY
307
                case OP_MPYUHI:
308
                        BLD_DUALOP(op_mpyuhi);
309
                        break;
310
                case OP_MPYSHI:
311
                        BLD_DUALOP(op_mpyshi);
312
                        break;
313
#else
314 26 dgisselq
                case OP_MPYU:
315
                        if ((m_opb == zp.ZIP_PC)||(m_opb == zp.ZIP_CC)
316
                                ||(m_opa == zp.ZIP_PC)||(m_opa == zp.ZIP_CC))
317
                                yyerror("MPYU does not support PC or CC register operands or results");
318
                        else if (m_opb == zp.ZIP_Rnone)
319
                                in = zp.op_mpyu(m_cond, imm, m_opa);
320
                        else
321
                                in = zp.op_mpyu(m_cond, imm, m_opb, m_opa);
322 13 dgisselq
                        break;
323 26 dgisselq
                case OP_MPYS:
324
                        if ((m_opb == zp.ZIP_PC)||(m_opb == zp.ZIP_CC)
325
                                ||(m_opa == zp.ZIP_PC)||(m_opa == zp.ZIP_CC))
326
                                yyerror("MPYS does not support PC or CC register operands or results");
327
                        else if (m_opb == zp.ZIP_Rnone)
328
                                in = zp.op_mpys(m_cond, imm, m_opa);
329
                        else
330
                                in = zp.op_mpys(m_cond, imm, m_opb, m_opa);
331
                        break;
332 143 dgisselq
#endif
333 13 dgisselq
                case OP_ROL:
334
                        if (m_opa == zp.ZIP_Rnone)
335
                                yyerror("ROL needs a register result");
336
                        if (m_opb != zp.ZIP_Rnone)
337
                                in = zp.op_rol(m_cond, imm, m_opb, m_opa);
338
                        else
339
                                in = zp.op_rol(m_cond, imm, m_opa);
340
                        break;
341
                case OP_SUB:
342
                        BLD_DUALOP(op_sub)
343
                        break;
344
                case OP_AND:
345
                        BLD_DUALOP(op_and)
346
                        break;
347
                case OP_ADD:
348
                        BLD_DUALOP(op_add)
349
                        break;
350
                case OP_OR:
351
                        BLD_DUALOP(op_or)
352
                        break;
353
                case OP_XOR:
354
                        BLD_DUALOP(op_xor)
355
                        break;
356
                case OP_LSL:
357
                        BLD_DUALOP(op_lsl)
358
                        break;
359
                case OP_ASR:
360
                        BLD_DUALOP(op_asr)
361
                        break;
362
                case OP_LSR:
363
                        BLD_DUALOP(op_lsr)
364
                        break;
365
                case OP_LOD:
366
                        if (m_opb != zp.ZIP_Rnone)
367
                                in = zp.op_lod(m_cond, imm, m_opb, m_opa);
368
                        else
369
                                in = zp.op_lod(m_cond, imm, m_opa);
370
                        break;
371
                case OP_STO:
372
                        if (m_opb != zp.ZIP_Rnone)
373
                                in = zp.op_sto(m_cond, m_opa, imm, m_opb);
374
                        else
375
                                in = zp.op_sto(m_cond, m_opa, imm);
376
                        break;
377 69 dgisselq
                case OP_BREV:
378
                        BLD_DUALOP(op_brev);
379
                        break;
380
                case OP_POPC:
381
                        BLD_DUALOP(op_popc);
382
                        break;
383 13 dgisselq
                case OP_LDI:
384 143 dgisselq
                        if (fitsin(zp.brev(imm),18)) {
385
                                imm = zp.brev(imm);
386
                                BLD_DUALOP(op_brev);
387
                        } else if ((!fitsin(imm, 23))||(m_cond != zp.ZIPC_ALWAYS)) {
388 13 dgisselq
                                if (m_opa == zp.ZIP_PC)
389
                                        yyerror("Cannot LDI 32-bit addresses into PC register!");
390
                                LLINE *lln = new LLINE;
391 143 dgisselq
#ifdef  LONG_MPY
392
                                lln->addline(new ILINE(zp.op_brev(m_cond, sbits(zp.brev(imm),18), m_opa)));
393
#else
394 13 dgisselq
                                lln->addline(new ILINE(zp.op_ldihi(m_cond, (imm>>16)&0x0ffff, m_opa)));
395 143 dgisselq
#endif
396 13 dgisselq
                                lln->addline(new ILINE(zp.op_ldilo(m_cond, imm&0x0ffff, m_opa)));
397 26 dgisselq
                                lln->m_lineno = m_lineno;
398 13 dgisselq
                                return lln;
399
                        } else
400
                                in = zp.op_ldi(imm, m_opa);
401
                        break;
402 69 dgisselq
                case OP_DIVU:
403
                        BLD_DUALOP(op_divu);
404
                        break;
405
                case OP_DIVS:
406
                        BLD_DUALOP(op_divs);
407
                        break;
408 13 dgisselq
                case OP_CLRF:
409
                        in = zp.op_clrf(m_cond, m_opb);
410
                        break;
411
                case OP_NOT:
412
                        in = zp.op_not(m_cond, m_opb);
413
                        break;
414 26 dgisselq
                case OP_NEG:
415
                        if (m_cond != zp.ZIPC_ALWAYS) {
416 36 dgisselq
                                LLINE *lln = new LLINE;
417
                                lln->addline(new ILINE(zp.op_mov(m_cond,-1,m_opb,m_opb)));
418
                                lln->addline(new ILINE(zp.op_not(m_cond,m_opb)));
419
                                return lln;
420 26 dgisselq
                        } else {
421
                                LLINE *lln = new LLINE;
422
                                lln->addline(new ILINE(zp.op_not(m_opb)));
423
                                lln->addline(new ILINE(zp.op_add(1,m_opb)));
424
                                return lln;
425
                        }break;
426 13 dgisselq
                case OP_JMP:
427 60 dgisselq
                        if (m_opb == zp.ZIP_Rnone) {
428 13 dgisselq
                                if (m_cond != zp.ZIPC_ALWAYS)
429
                                        yyerror("JMP: Conditions are not allowed for absolute jumps.");
430 69 dgisselq
                                imm &= (1<<23)-1;
431
                                if (!fitsin(imm, 23))
432 13 dgisselq
                                        yyerror("JMP: Absolute jump address out of range");
433 60 dgisselq
                                in = zp.op_ldi(imm, zp.ZIP_PC);
434 69 dgisselq
                        } else if (fitsin(imm,13)) {
435 60 dgisselq
                                in = zp.op_mov(m_cond, imm, m_opb, zp.ZIP_PC);
436 69 dgisselq
                        } else if (fitsin(imm,18))
437 60 dgisselq
                                in = zp.op_add(m_cond, imm, m_opb, zp.ZIP_PC);
438
                        else
439
                                yyerror("JMP: Immediate out of range");
440
                        break;
441 13 dgisselq
                case OP_BRA:
442
                        BLD_BRANCH(op_bra,ZIPC_ALWAYS)
443
                        break;
444
                case OP_BZ:
445
                        BLD_BRANCH(op_brz,ZIPC_Z)
446
                        break;
447
                case OP_BNZ:
448
                        BLD_BRANCH(op_bnz,ZIPC_NZ)
449
                        break;
450
                case OP_BGE:
451
                        BLD_BRANCH(op_bge,ZIPC_GE)
452
                        break;
453
                case OP_BGT:
454
                        BLD_BRANCH(op_bgt,ZIPC_GT)
455
                        break;
456
                case OP_BLT:
457
                        BLD_BRANCH(op_blt,ZIPC_LT)
458
                        break;
459
                case OP_BRC:
460
                        BLD_BRANCH(op_brc,ZIPC_C)
461
                        break;
462
                case OP_BRV:
463
                        BLD_BRANCH(op_brv,ZIPC_V)
464
                        break;
465
                case OP_CLR:
466 46 dgisselq
                        if((m_cond == zp.ZIPC_ALWAYS))
467
                                in = zp.op_clr(m_opb);
468
                        else
469
                                in = zp.op_clrf(m_cond, m_opb);
470 13 dgisselq
                        break;
471
                case OP_TRAP:
472
                        if((m_opb == zp.ZIP_Rnone)&&(m_cond == zp.ZIPC_ALWAYS))
473
                                in = zp.op_ldi(imm, zp.ZIP_CC);
474 60 dgisselq
                        else if((m_opb == zp.ZIP_Rnone)&&((imm&0x0ffdf)==imm))
475
                                in = zp.op_ldilo(m_cond, imm & 0x0ffdf, zp.ZIP_CC);
476 69 dgisselq
                        else if((m_opb != zp.ZIP_Rnone)&&(fitsin(imm, 13)))
477 13 dgisselq
                                in = zp.op_mov(m_cond, imm, m_opb, zp.ZIP_CC);
478
                        else {
479
                                yyerror("Illegal trap!");
480
                                in = zp.op_trap(m_cond, 0);
481
                        }
482
                        break;
483 69 dgisselq
                case OP_RETN:   // yywarn("RETN opcode is deprecated");
484
                                in = zp.op_lod(m_cond, imm, m_opb, m_opa);
485
                                in = zp.op_lod(m_cond, -1, zp.ZIP_SP, zp.ZIP_PC);
486
                        break;
487 13 dgisselq
                case OP_HALT:   in = zp.op_halt(m_cond); break;
488
                case OP_RTU:    in = zp.op_rtu(m_cond); break;
489
                case OP_BUSY:   in = zp.op_busy(m_cond); break;
490 69 dgisselq
                case OP_NOOP:   in = zp.op_noop(); break;
491 13 dgisselq
                case OP_BREAK:  in = zp.op_break(); break;
492 69 dgisselq
                case OP_LOCK:   in = zp.op_lock(); break;
493 96 dgisselq
                case OP_LJMP:   in = zp.op_ljmp(); break;
494 13 dgisselq
                case OP_NONE:
495
                default:        { char ebuf[256]; sprintf(ebuf, "Unrecognized OP-Code, %d, NONE = %d, CLR=%d", m_opcode, OP_NONE, OP_CLR);
496
                                yyerror(ebuf);
497
                                in = zp.op_noop(); break;
498
                                }
499 26 dgisselq
        }
500
        ILINE   *rs = new ILINE(in);
501
        rs->m_lineno = m_lineno;
502 13 dgisselq
}
503
 
504
int     TLINE::nlines(void)  {
505
        if ((m_opcode == OP_LDI)&&( (!(m_imm->isdefined()))
506
                        || (m_cond != ZPARSER::ZIPC_ALWAYS)
507 69 dgisselq
                        || (!fitsin(m_imm->eval(), 23)) )) {
508 13 dgisselq
                return 2;
509
        }
510
        return 1;
511
}
512
 
513
unsigned int    TLINE::eval(const int lno) {
514
        if (!isdefined())
515
                return DEFAULT_LINE;
516
        else {
517
                ASMLINE *ln = this->eval();
518
                unsigned int val = ln->eval(lno);
519
                delete ln;
520
                return val;
521
        }
522
}
523
 
524
void    TLINE::dump(FILE *fp) {
525
        if (m_state == 'V')
526 26 dgisselq
                fprintf(fp, "Void @%d\n", m_lineno);
527 13 dgisselq
        else if (m_state != 'T')
528
                fprintf(fp, "TLINE state != T (== %c)\n", m_state);
529
        else {
530 26 dgisselq
                fprintf(fp, "TLINE @%d\n", m_lineno);
531 13 dgisselq
                switch(m_opcode) {
532
                case OP_CMP: fprintf(fp, "\tTLINE OP   = CMP\n");
533
                        break;
534
                case OP_TST: fprintf(fp, "\tTLINE OP   = TST\n");
535
                        break;
536
                case OP_MOV: fprintf(fp, "\tTLINE OP   = MOV\n");
537
                        break;
538 143 dgisselq
#ifdef  LONG_MPY
539
                case OP_MPY: fprintf(fp,"\tTLINE OP   = MPY\n");
540
                        break;
541
#else
542 26 dgisselq
                case OP_LDIHI:fprintf(fp,"\tTLINE OP   = LDIHI\n");
543 13 dgisselq
                        break;
544 143 dgisselq
#endif
545 26 dgisselq
                case OP_LDILO:fprintf(fp,"\tTLINE OP   = LDILO\n");
546 13 dgisselq
                        break;
547 143 dgisselq
#ifdef  LONG_MPY
548
                case OP_MPYUHI: fprintf(fp,"\tTLINE OP   = MPYUHI\n");
549
                        break;
550
                case OP_MPYSHI: fprintf(fp,"\tTLINE OP   = MPYSHI\n");
551
                        break;
552
#else
553 26 dgisselq
                case OP_MPYU: fprintf(fp,"\tTLINE OP   = MPYU\n");
554 13 dgisselq
                        break;
555 26 dgisselq
                case OP_MPYS: fprintf(fp,"\tTLINE OP   = MPYS\n");
556
                        break;
557 143 dgisselq
#endif
558 13 dgisselq
                case OP_ROL: fprintf(fp, "\tTLINE OP   = ROL\n");
559
                        break;
560
                case OP_SUB: fprintf(fp, "\tTLINE OP   = SUB\n");
561
                        break;
562
                case OP_AND: fprintf(fp, "\tTLINE OP   = AND\n");
563
                        break;
564
                case OP_ADD: fprintf(fp, "\tTLINE OP   = ADD\n");
565
                        break;
566
                case OP_OR: fprintf(fp, "\tTLINE OP   = OR\n");
567
                        break;
568
                case OP_XOR: fprintf(fp, "\tTLINE OP   = XOR\n");
569
                        break;
570
                case OP_LSL: fprintf(fp, "\tTLINE OP   = LSL\n");
571
                        break;
572
                case OP_ASR: fprintf(fp, "\tTLINE OP   = ASR\n");
573
                        break;
574
                case OP_LSR: fprintf(fp, "\tTLINE OP   = LSR\n");
575
                        break;
576
                case OP_LOD: fprintf(fp, "\tTLINE OP   = LOD\n");
577
                        break;
578
                case OP_STO: fprintf(fp, "\tTLINE OP   = STO\n");
579
                        break;
580
                case OP_LDI: fprintf(fp, "\tTLINE OP   = LDI\n");
581
                        break;
582
                case OP_CLRF: fprintf(fp, "\tTLINE OP   = CLRF\n");
583
                        break;
584
                case OP_NOT: fprintf(fp, "\tTLINE OP   = NOT\n");
585
                        break;
586
                case OP_JMP: fprintf(fp, "\tTLINE OP   = JMP\n");
587
                        break;
588
                case OP_BRA: fprintf(fp, "\tTLINE OP   = BRA\n");
589
                        break;
590
                case OP_BZ:
591
                case OP_BNZ:
592
                case OP_BGE:
593
                case OP_BGT:
594
                case OP_BLT:
595
                case OP_BRC:
596
                case OP_BRV:
597
                        fprintf(fp, "\tTLINE OP   = BRA.C\n");
598
                        break;
599
                case OP_CLR: fprintf(fp, "\tTLINE OP   = CLR\n");
600
                        break;
601 26 dgisselq
                case OP_NEG: fprintf(fp, "\tTLINE OP   = NEG\n");
602
                        break;
603 13 dgisselq
                case OP_TRAP: fprintf(fp, "\tTLINE OP   = TRAP\n");
604
                        break;
605
                case OP_HALT: fprintf(fp, "\tTLINE OP   = HALT\n");
606
                        break;
607
                case OP_RTU: fprintf(fp, "\tTLINE OP   = RTU\n");
608
                        break;
609
                case OP_BUSY: fprintf(fp, "\tTLINE OP   = BUSY\n");
610
                        break;
611
                case OP_BREAK: fprintf(fp, "\tTLINE OP   = BREAK\n");
612
                        break;
613
                case OP_NOOP: fprintf(fp, "\tTLINE OP   = NOOP\n");
614 69 dgisselq
                case OP_LOCK: fprintf(fp, "\tTLINE OP   = LOCK\n");
615 13 dgisselq
                        break;
616
                case OP_NONE:
617
                default:
618
                        fprintf(fp, "\tTLINE OP   = (Unrecognized, %d)\n", m_opcode);
619
                                break;
620
                }
621 34 dgisselq
                if (m_cond == 0)
622
                        fprintf(fp, "\tTLINE COND = (Always)\n");
623
                else
624
                        fprintf(fp, "\tTLINE COND = %s\n", zop_ccstr[m_cond&0x07]);
625 13 dgisselq
                if (m_imm == NULL)
626
                        fprintf(fp, "\tTLINE imm  = (NULL)\n");
627
                else if (!m_imm->isdefined()) {
628
                        m_imm->reduce();
629
                        fprintf(fp, "\tTLINE imm  = ");
630
                        m_imm->dump(fp);
631
                        fprintf(fp, "\n");
632
                } else
633
                        fprintf(fp, "\tTLINE imm  = %d\n", m_imm->eval());
634 34 dgisselq
                if (m_opb != ZPARSER::ZIP_Rnone)
635
                        fprintf(fp, "\tTLINE opb  = %d\n", m_opb);
636
                if (m_opa != ZPARSER::ZIP_Rnone)
637
                        fprintf(fp, "\tTLINE opa  = %d\n", m_opa);
638 13 dgisselq
        }
639
}
640
 
641
 
642
// Now, for our symbol table
643
class   SYMTABLE_ENTRY {
644
private:
645
        int     m_recursion_check;
646
 
647
        std::string     &trim(std::string &s) {
648
                std::string::iterator   ptr = s.end()-1;
649
 
650
                while((ptr >= s.begin())&&(isspace(*ptr)))
651
                        *ptr-- = '\0';
652
                if (*ptr == ':')
653
                        *ptr-- = '\0';
654
 
655
                // printf("STORING: %s\n", s.c_str());
656
 
657
                return s;
658
        }
659
 
660
public:
661
        std::string     m_name;
662
        AST             *m_value;
663
        SYMTABLE_ENTRY(const char *str) : m_recursion_check(0), m_name(str), m_value(NULL) {
664
                trim(m_name);
665
        } SYMTABLE_ENTRY(const char *str, AST *v) : m_recursion_check(0), m_name(str), m_value(v) {
666
                trim(m_name);
667
        } ~SYMTABLE_ENTRY(void) {
668 46 dgisselq
                if (m_value)
669
                        delete m_value;
670 13 dgisselq
        }
671
 
672
        SYMTABLE_ENTRY &operator=(AST *new_value) {
673
                if (m_value)
674
                        delete  m_value;
675
                m_value = new_value;
676
        }
677
 
678
        bool    isdefined(void) {
679
                if (m_recursion_check > 0) {
680
                        fprintf(stderr, "RECURSION DETECTED! Symbol: %s\n",
681
                                m_name.c_str());
682
                        return false;
683
                }
684
                m_recursion_check = 1;
685
                if (m_value->m_node_type != 'N')
686
                        m_value->reduce();
687
                bool    answer = m_value->isdefined();
688
                m_recursion_check = 0;
689
                return answer;
690
        }
691
        int     val(void) {
692
                if ((m_value->isdefined())&&(m_value->m_node_type != 'N')) {
693
                        int     v = m_value->eval();
694
                        AST     *tmp;
695
                        tmp = m_value;
696
                        m_value = new AST_NUMBER(v);
697
                        delete tmp;
698
                } return (m_value->eval());
699
        }
700
        void    dump(FILE *fp) { m_value->dump(fp); }
701
};
702
 
703
class   SYMBOL_TABLE    {
704
private:
705
        typedef SYMTABLE_ENTRY  *TBLV;
706
        typedef std::list<TBLV> TBLT;
707
 
708
        TBLT    m_tbl;
709
 
710
        TBLT::iterator  lookup(const char *str) {
711
                TBLT::iterator  i = m_tbl.begin();
712
                for(; (i!=m_tbl.end())&&(strcmp(str, (*i)->m_name.c_str())>0);
713
                                i++)
714
                        ;
715
                if ((i != m_tbl.end())&&(strcmp(str,(*i)->m_name.c_str())==0))
716
                        return i;
717
                return  m_tbl.end();
718
        }
719
 
720
public:
721
        SYMBOL_TABLE(void) {}
722
        ~SYMBOL_TABLE(void) {
723
                TBLT::iterator i = m_tbl.begin();
724
                while(i != m_tbl.end()) {
725
                        delete (*i);
726 46 dgisselq
                        i = m_tbl.erase(i);
727 13 dgisselq
                }
728
        }
729
 
730
        void    define(const char *key, AST *value) {
731
                SYMTABLE_ENTRY  *v = new SYMTABLE_ENTRY(key, value);
732
                TBLT::iterator  i = m_tbl.begin();
733
                for(; (i!=m_tbl.end())&&(strcmp(key, (*i)->m_name.c_str())>0);
734
                                i++)
735
                        ;
736
                m_tbl.insert(i, v);
737
 
738
                /*
739
                fprintf(stderr, "Defining: %s = ", key);
740
                value->dump(stderr);
741
                fprintf(stderr, "\n");
742
                */
743
        }
744
 
745
        bool    isdefined(const char *key) {
746
                TBLT::iterator  i = lookup(key);
747
                if (i == m_tbl.end()) {
748
                        // fprintf(stderr, "%s is not in the symbol table\n", key);
749
                        return false;
750
                } else {
751
                        bool    defined = (*i)->isdefined();
752
                        /*
753
                        if (!defined) {
754
                                fprintf(stderr, "KEY: %s = ", key);
755
                                (*i)->dump(stderr);
756
                                fprintf(stderr, " is not yet defined\n");
757
                        } */
758
                        return (*i)->isdefined();
759
                }
760
        }
761
 
762
        int     value(const char *key) {
763
                TBLT::iterator  i = lookup(key);
764
                if (i == m_tbl.end())
765
                        return 0;
766
                else
767
                        return (*i)->val();
768
        }
769
};
770
 
771
SYMBOL_TABLE    *global_context = NULL, *file_context = NULL;
772
 
773
bool    stb_isdefined(const char *key) {
774
        if ((file_context)&&(file_context->isdefined(key)))
775
                return true;
776
        else
777
                return global_context->isdefined(key);
778
} int   stb_value(const char *key) {
779 46 dgisselq
        if ((file_context)&&(file_context->isdefined(key)))
780 13 dgisselq
                return file_context->value(key);
781
        else
782
                return global_context->value(key);
783
} void  stb_define(const char *key, AST *value) {
784
        file_context->define(key, value);
785
} void  gbl_define(const char *key, AST *value) {
786
        global_context->define(key, value);
787
}
788
 
789
void    create_new_context(void) {
790
        if (global_context == NULL)
791
                global_context = new SYMBOL_TABLE;
792
        if (file_context != NULL)
793
                delete file_context;
794
        file_context = new SYMBOL_TABLE;
795
}
796
 
797
 
798
// Convenience functions for accessing the symbol table
799
bool    stb_isdefined(const std::string &key) {
800
        bool answer = stb_isdefined(key.c_str());
801
        return answer;
802
} int   stb_value(const std::string &key) {
803
        return stb_value(key.c_str());
804
} void  stb_define(const std::string &key, AST *value) {
805
        stb_define(key.c_str(), value);
806
} void  gbl_define(const std::string &key, AST *value) {
807
        gbl_define(key.c_str(), value);
808
}
809
 
810
 

powered by: WebSVN 2.1.0

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