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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [sw/] [zasm/] [asmdata.cpp] - Diff between revs 69 and 96

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 69 Rev 96
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// Filename:    asmdata.cpp
// Filename:    asmdata.cpp
//
//
// Project:     Zip CPU -- a small, lightweight, RISC CPU core
// Project:     Zip CPU -- a small, lightweight, RISC CPU core
//
//
// Purpose:     Like asmdata.h, this contains necessary data structures for the
// Purpose:     Like asmdata.h, this contains necessary data structures for the
//              assembler.  Specifically, in C/C++ fashion, this contains most
//              assembler.  Specifically, in C/C++ fashion, this contains most
//              of the code for actually building such structures.
//              of the code for actually building such structures.
//
//
// Creator:     Dan Gisselquist, Ph.D.
// Creator:     Dan Gisselquist, Ph.D.
//              Gisselquist Technology, LLC
//              Gisselquist Technology, LLC
//
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// Copyright (C) 2015, Gisselquist Technology, LLC
// Copyright (C) 2015, Gisselquist Technology, LLC
//
//
// This program is free software (firmware): you can redistribute it and/or
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of  the GNU General Public License as published
// modify it under the terms of  the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
// your option) any later version.
//
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
// for more details.
//
//
// You should have received a copy of the GNU General Public License along
// You should have received a copy of the GNU General Public License along
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.)  If not, see
// target there if the PDF file isn't present.)  If not, see
// <http://www.gnu.org/licenses/> for a copy.
// <http://www.gnu.org/licenses/> for a copy.
//
//
// License:     GPL, v3, as defined and found on www.gnu.org,
// License:     GPL, v3, as defined and found on www.gnu.org,
//              http://www.gnu.org/licenses/gpl.html
//              http://www.gnu.org/licenses/gpl.html
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
 
 
#include <stdlib.h>
#include <stdlib.h>
#include <assert.h>
#include <assert.h>
#include <string.h>
#include <string.h>
#include "asmdata.h"
#include "asmdata.h"
 
 
extern  void    yyerror(const char *str);
extern  void    yyerror(const char *str);
 
 
unsigned int    ILINE::eval(const int lno) {
unsigned int    ILINE::eval(const int lno) {
        return (lno==0)?m_in:DEFAULT_LINE;
        return (lno==0)?m_in:DEFAULT_LINE;
}
}
 
 
unsigned int    VLINE::eval(const int lno) {
unsigned int    VLINE::eval(const int lno) {
        return DEFAULT_LINE;
        return DEFAULT_LINE;
}
}
 
 
unsigned int    DLINE::eval(const int lno) {
unsigned int    DLINE::eval(const int lno) {
        return (lno==0)?m_data:DEFAULT_LINE;
        return (lno==0)?m_data:DEFAULT_LINE;
}
}
 
 
void LLINE::addline(ASMLINE *line) {
void LLINE::addline(ASMLINE *line) {
        if (m_lines != NULL) {
        if (m_lines != NULL) {
                ASMLINE **nwlines = new ASMLINE *[m_nlines+1];
                ASMLINE **nwlines = new ASMLINE *[m_nlines+1];
                for(int i=0; i<m_nlines; i++)
                for(int i=0; i<m_nlines; i++)
                        nwlines[i] = m_lines[i];
                        nwlines[i] = m_lines[i];
                delete[] m_lines;
                delete[] m_lines;
                nwlines[m_nlines++] = line;
                nwlines[m_nlines++] = line;
 
 
                m_lines = nwlines;
                m_lines = nwlines;
        } else {
        } else {
                m_lines = new ASMLINE *[1];
                m_lines = new ASMLINE *[1];
                m_lines[m_nlines++] = line;
                m_lines[m_nlines++] = line;
        }
        }
 
 
        if (m_lineno > line->m_lineno)
        if (m_lineno > line->m_lineno)
                m_lineno = line->m_lineno;
                m_lineno = line->m_lineno;
};
};
 
 
bool    LLINE::isdefined(void) {
bool    LLINE::isdefined(void) {
        for(int i=0; i<m_nlines; i++)
        for(int i=0; i<m_nlines; i++)
                if (!m_lines[i]->isdefined())
                if (!m_lines[i]->isdefined())
                return false;
                return false;
        return true;
        return true;
};
};
 
 
LLINE::~LLINE(void) {
LLINE::~LLINE(void) {
        for(int i=0; i<m_nlines; i++)
        for(int i=0; i<m_nlines; i++)
                delete m_lines[i];
                delete m_lines[i];
        delete m_lines;
        delete m_lines;
}
}
 
 
unsigned int    LLINE::eval(const int lno) {
unsigned int    LLINE::eval(const int lno) {
        return (lno < m_nlines)?m_lines[lno]->eval(0) : DEFAULT_LINE;
        return (lno < m_nlines)?m_lines[lno]->eval(0) : DEFAULT_LINE;
}
}
 
 
// int  m_op; // An operator
// int  m_op; // An operator
// AST  *m_left, *m_right;
// AST  *m_left, *m_right;
 
 
int     AST_BRANCH::eval(void) {
int     AST_BRANCH::eval(void) {
        int     lft = m_left->eval(), rht = m_right->eval();
        int     lft = m_left->eval(), rht = m_right->eval();
 
 
        switch(m_op) {
        switch(m_op) {
                case '+':       return lft + rht;
                case '+':       return lft + rht;
                case '-':       return lft - rht;
                case '-':       return lft - rht;
                case '*':       return lft * rht;
                case '*':       return lft * rht;
                case '/':       return lft / rht;
                case '/':       return lft / rht;
                case '%':       return lft % rht;
                case '%':       return lft % rht;
                case '^':       return lft ^ rht;
                case '^':       return lft ^ rht;
                case '|':       return lft | rht;
                case '|':       return lft | rht;
                case '&':       return lft & rht;
                case '&':       return lft & rht;
                case '~':       return ~lft;
                case '~':       return ~lft;
                default:        yyerror("Unknown operation"); return lft;
                default:        yyerror("Unknown operation"); return lft;
        }
        }
} void  AST_BRANCH::reduce(void) {
} void  AST_BRANCH::reduce(void) {
        if ((m_left)&&(m_left->m_node_type != 'N')&&(m_left->isdefined())) {
        if ((m_left)&&(m_left->m_node_type != 'N')&&(m_left->isdefined())) {
                int     val = m_left->eval();
                int     val = m_left->eval();
                delete  m_left;
                delete  m_left;
                m_left = new AST_NUMBER(val);
                m_left = new AST_NUMBER(val);
        } else
        } else
                m_left->reduce();
                m_left->reduce();
        if ((m_right)&&(m_right->m_node_type != 'N')&&(m_right->isdefined())) {
        if ((m_right)&&(m_right->m_node_type != 'N')&&(m_right->isdefined())) {
                int     val = m_right->eval();
                int     val = m_right->eval();
                delete  m_right;
                delete  m_right;
                m_right = new AST_NUMBER(val);
                m_right = new AST_NUMBER(val);
        } else
        } else
                m_right->reduce();
                m_right->reduce();
}
}
 
 
AST_IDENTIFIER::AST_IDENTIFIER(AST *ida, const char *idb) {
AST_IDENTIFIER::AST_IDENTIFIER(AST *ida, const char *idb) {
        m_node_type = 'I';
        m_node_type = 'I';
        m_id = ((AST_IDENTIFIER*)ida)->m_id + "." + std::string(idb);
        m_id = ((AST_IDENTIFIER*)ida)->m_id + "." + std::string(idb);
        delete ida;
        delete ida;
}
}
 
 
bool    AST_IDENTIFIER::isdefined(void) {
bool    AST_IDENTIFIER::isdefined(void) {
        bool    answer = stb_isdefined(m_id);
        bool    answer = stb_isdefined(m_id);
        return answer;
        return answer;
} int   AST_IDENTIFIER::eval(void) {
} int   AST_IDENTIFIER::eval(void) {
        return stb_value(m_id);
        return stb_value(m_id);
} void  AST_IDENTIFIER::reduce(void) {}
} void  AST_IDENTIFIER::reduce(void) {}
 
 
bool    AST_LABEL::isdefined(void) {
bool    AST_LABEL::isdefined(void) {
        bool    answer = stb_isdefined(m_label);
        bool    answer = stb_isdefined(m_label);
        return answer;
        return answer;
} int   AST_LABEL::eval(void) {
} int   AST_LABEL::eval(void) {
        return stb_value(m_label);
        return stb_value(m_label);
} void  AST_LABEL::reduce(void) {}
} void  AST_LABEL::reduce(void) {}
 
 
 
 
int     AST_NUMBER::eval(void) {
int     AST_NUMBER::eval(void) {
        return m_val;
        return m_val;
} void  AST_NUMBER::reduce(void) {}
} void  AST_NUMBER::reduce(void) {}
 
 
void    OBJFILE::open(const char *fname) {
void    OBJFILE::open(const char *fname) {
        if ((m_fp != NULL)||(m_pc != 0l)) {
        if ((m_fp != NULL)||(m_pc != 0l)) {
                fprintf(stderr, "Error: Can only change file names at startup\n");
                fprintf(stderr, "Error: Can only change file names at startup\n");
                exit(-2);
                exit(-2);
        }
        }
        m_fp = fopen(fname, "w");
        m_fp = fopen(fname, "w");
        if (m_fp == NULL) {
        if (m_fp == NULL) {
                fprintf(stderr, "Cannot open %s for writing\n", fname);
                fprintf(stderr, "Cannot open %s for writing\n", fname);
                perror("O/S Err:");
                perror("O/S Err:");
                m_fp = fopen("/dev/null","w");
                m_fp = fopen("/dev/null","w");
        }
        }
}
}
 
 
void    OBJFILE::operator+=(ASMLINE *ln) {
void    OBJFILE::operator+=(ASMLINE *ln) {
        unsigned int    buf[1];
        unsigned int    buf[1];
        int             nlines = ln->nlines();
        int             nlines = ln->nlines();
 
 
        if (!ln->isdefined()) {
        if (!ln->isdefined()) {
                // fprintf(stderr, "%08x: Adding undefined line:\n", m_pc);
                // fprintf(stderr, "%08x: Adding undefined line:\n", m_pc);
                // ((TLINE *)ln)->dump(stderr);
                // ((TLINE *)ln)->dump(stderr);
                m_tbl.insert(m_tbl.end(), SAVED_ASMLINE(m_pc,ln));
                m_tbl.insert(m_tbl.end(), SAVED_ASMLINE(m_pc,ln));
        /*
        /*
        } else {
        } else {
                fprintf(stderr, "%08x: Adding to file:\n", m_pc);
                fprintf(stderr, "%08x: Adding to file:\n", m_pc);
                ((TLINE *)ln)->dump(stderr);
                ((TLINE *)ln)->dump(stderr);
        */
        */
        }
        }
        for(int i=0; i<nlines; i++) {
        for(int i=0; i<nlines; i++) {
                buf[0] = ln->eval(i);
                buf[0] = ln->eval(i);
                if (m_fp) fwrite(buf, sizeof(ZIPI), 1, m_fp);
                if (m_fp) fwrite(buf, sizeof(ZIPI), 1, m_fp);
                m_pc++;
                m_pc++;
        }
        }
}
}
 
 
bool    OBJFILE::reduce(void) {
bool    OBJFILE::reduce(void) {
        SVDTBL::iterator        i;
        SVDTBL::iterator        i;
        bool    all_reduced = true;
        bool    all_reduced = true;
 
 
        // printf("Checking for reductions\n");
        // printf("Checking for reductions\n");
        unsigned int tmp = m_pc;
        unsigned int tmp = m_pc;
        for(i=m_tbl.begin(); i != m_tbl.end(); i++) {
        for(i=m_tbl.begin(); i != m_tbl.end(); i++) {
                // printf("LINE %08x\n", i->m_pc);
                // printf("LINE %08x\n", i->m_pc);
                ASMLINE *ln = i->m_ln;
                ASMLINE *ln = i->m_ln;
                m_pc = i->m_pc;
                m_pc = i->m_pc;
                if (ln->isdefined()) {
                if (ln->isdefined()) {
                        // printf("PC = 0x%08x reduces\n", i->m_pc);
                        // printf("PC = 0x%08x reduces\n", i->m_pc);
                        fseek(m_fp, sizeof(ZIPI)*i->m_pc, SEEK_SET);
                        fseek(m_fp, sizeof(ZIPI)*i->m_pc, SEEK_SET);
                        for(int k=0; k< ln->nlines(); k++) {
                        for(int k=0; k< ln->nlines(); k++) {
                                ZIPI    buf[1];
                                ZIPI    buf[1];
                                m_pc = i->m_pc+k;
                                m_pc = i->m_pc+k;
                                buf[0] = ln->eval(k);
                                buf[0] = ln->eval(k);
                                // printf("\t0x%08x -> %08x\n", i->m_pc+k,
                                // printf("\t0x%08x -> %08x\n", i->m_pc+k,
                                        // buf[0]);
                                        // buf[0]);
                                fwrite(buf, sizeof(ZIPI), 1, m_fp);
                                fwrite(buf, sizeof(ZIPI), 1, m_fp);
                        }
                        }
                } else {
                } else {
                        fprintf(stderr, "Line %d contains an undefined symbol: ", ln->m_lineno);
                        fprintf(stderr, "Line %d contains an undefined symbol: ", ln->m_lineno);
                        fprintf(stderr, "PC = 0x%08x isn\'t ready yet\n", i->m_pc);
                        fprintf(stderr, "PC = 0x%08x isn\'t ready yet\n", i->m_pc);
                        i->m_ln->dump(stderr);
                        i->m_ln->dump(stderr);
                        all_reduced = false;
                        all_reduced = false;
                }
                }
        } m_pc = tmp;
        } m_pc = tmp;
        return all_reduced;
        return all_reduced;
}
}
 
 
bool    fitsin(const int v, const int b) {
bool    fitsin(const int v, const int b) {
        if (v>0)
        if (v>0)
                return (v < (1<<(b-1)));
                return (v < (1<<(b-1)));
        else
        else
                return (-v <= (1<<b));
                return (-v <= (1<<b));
}
}
 
 
#define BLD_DUALOP(OP)                                                  \
#define BLD_DUALOP(OP)                                                  \
        if (m_opa == zp.ZIP_Rnone)                                      \
        if (m_opa == zp.ZIP_Rnone)                                      \
                yyerror("Err: Dual Ops need a result register");        \
                yyerror("Err: Dual Ops need a result register");        \
        if (m_opb != zp.ZIP_Rnone) {                                    \
        if (m_opb != zp.ZIP_Rnone) {                                    \
                if(!fitsin(imm, 14))                                    \
                if(!fitsin(imm, 14))                                    \
                        yyerror("14-bit: Immediate out of range");      \
                        yyerror("14-bit: Immediate out of range");      \
                in = zp.OP(m_cond,imm,m_opb,m_opa);                     \
                in = zp.OP(m_cond,imm,m_opb,m_opa);                     \
        } else {                                                        \
        } else {                                                        \
                if(!fitsin(imm, 18))                                    \
                if(!fitsin(imm, 18))                                    \
                        yyerror("18-bit: Immediate out of range");      \
                        yyerror("18-bit: Immediate out of range");      \
                in = zp.OP(m_cond,imm,m_opa);                           \
                in = zp.OP(m_cond,imm,m_opa);                           \
        }
        }
 
 
#define BLD_BRANCH(OP,CND)                                              \
#define BLD_BRANCH(OP,CND)                                              \
        if (fitsin(offset, 13))                                         \
        if (fitsin(offset, 13))                                         \
                in = zp.OP(offset);                                     \
                in = zp.OP(offset);                                     \
        else if (fitsin(offset, 18))                                    \
        else if (fitsin(offset, 18))                                    \
                in = zp.op_add(zp.CND, offset, zp.ZIP_PC);              \
                in = zp.op_add(zp.CND, offset, zp.ZIP_PC);              \
        else { in = zp.OP(offset); yyerror("LONG JUMP NOT SUPPORTED"); }
        else { in = zp.OP(offset); yyerror("LONG JUMP NOT SUPPORTED"); }
 
 
ASMLINE *TLINE::eval(void) {
ASMLINE *TLINE::eval(void) {
        ZIPI    in;
        ZIPI    in;
        ZPARSER zp;
        ZPARSER zp;
        int     offset = 0, imm = 0;
        int     offset = 0, imm = 0;
 
 
        if (m_opcode != OP_MOV) {
        if (m_opcode != OP_MOV) {
                if ( ((m_opa!=zp.ZIP_Rnone)&&(m_opa > zp.ZIP_PC))
                if ( ((m_opa!=zp.ZIP_Rnone)&&(m_opa > zp.ZIP_PC))
                        || ((m_opb!=zp.ZIP_Rnone)&&(m_opb > zp.ZIP_PC))  )
                        || ((m_opb!=zp.ZIP_Rnone)&&(m_opb > zp.ZIP_PC))  )
                        yyerror("Only move instructions can reference user regs");
                        yyerror("Only move instructions can reference user regs");
        }
        }
 
 
        // Offset used in jumps
        // Offset used in jumps
        if (m_imm) {
        if (m_imm) {
                imm = m_imm->eval();
                imm = m_imm->eval();
                offset = imm-objcode.pc()-1;
                offset = imm-objcode.pc()-1;
 
 
                if (m_opb == zp.ZIP_PC)
                if (m_opb == zp.ZIP_PC)
                        imm = offset;
                        imm = offset;
        }
        }
 
 
        switch(m_opcode) {
        switch(m_opcode) {
                case OP_CMP:
                case OP_CMP:
                        BLD_DUALOP(op_cmp)
                        BLD_DUALOP(op_cmp)
                        break;
                        break;
                case OP_TST:
                case OP_TST:
                        BLD_DUALOP(op_tst)
                        BLD_DUALOP(op_tst)
                        break;
                        break;
                case OP_MOV:
                case OP_MOV:
                        if ((m_opa == zp.ZIP_Rnone)||(m_opb == zp.ZIP_Rnone)) {
                        if ((m_opa == zp.ZIP_Rnone)||(m_opb == zp.ZIP_Rnone)) {
                                yyerror("Moves can only occurr between registers");
                                yyerror("Moves can only occurr between registers");
                                fprintf(stderr, "m_opa = %d, m_opb = %d\n", m_opa, m_opb);
                                fprintf(stderr, "m_opa = %d, m_opb = %d\n", m_opa, m_opb);
                                fprintf(stderr, "m_imm = %d\n", imm);
                                fprintf(stderr, "m_imm = %d\n", imm);
                        } else if (!fitsin(imm, 13))
                        } else if (!fitsin(imm, 13))
                                yyerror("Immediate overflow on move");
                                yyerror("Immediate overflow on move");
                        in = zp.op_mov(m_cond, imm, m_opb, m_opa);
                        in = zp.op_mov(m_cond, imm, m_opb, m_opa);
                        break;
                        break;
                case OP_LDIHI:
                case OP_LDIHI:
                        if ((imm & (-1<<16))!=0)
                        if ((imm & (-1<<16))!=0)
                                yyerror("16-bit Immediate out of range");
                                yyerror("16-bit Immediate out of range");
                        if (m_opb != zp.ZIP_Rnone)
                        if (m_opb != zp.ZIP_Rnone)
                                yyerror("LDIHI cannot accept OP-B registers");
                                yyerror("LDIHI cannot accept OP-B registers");
                        if (m_opa == zp.ZIP_Rnone)
                        if (m_opa == zp.ZIP_Rnone)
                                yyerror("LDIHI needs a register result");
                                yyerror("LDIHI needs a register result");
                        in = zp.op_ldihi(m_cond, imm, m_opa);
                        in = zp.op_ldihi(m_cond, imm, m_opa);
                        break;
                        break;
                case OP_LDILO:
                case OP_LDILO:
                        if ((imm & (-1<<16))!=0)
                        if ((imm & (-1<<16))!=0)
                                yyerror("16-bit Immediate out of range");
                                yyerror("16-bit Immediate out of range");
                        if (m_opb != zp.ZIP_Rnone)
                        if (m_opb != zp.ZIP_Rnone)
                                yyerror("LDIHI cannot accept OP-B registers");
                                yyerror("LDIHI cannot accept OP-B registers");
                        if (m_opa == zp.ZIP_Rnone)
                        if (m_opa == zp.ZIP_Rnone)
                                yyerror("LDIHI needs a register result");
                                yyerror("LDIHI needs a register result");
                        if ((imm & (-1<<16))!=0)
                        if ((imm & (-1<<16))!=0)
                                yyerror("16-bit Immediate out of range");
                                yyerror("16-bit Immediate out of range");
                        in = zp.op_ldilo(m_cond, imm, m_opa);
                        in = zp.op_ldilo(m_cond, imm, m_opa);
                        break;
                        break;
                case OP_MPYU:
                case OP_MPYU:
                        if ((m_opb == zp.ZIP_PC)||(m_opb == zp.ZIP_CC)
                        if ((m_opb == zp.ZIP_PC)||(m_opb == zp.ZIP_CC)
                                ||(m_opa == zp.ZIP_PC)||(m_opa == zp.ZIP_CC))
                                ||(m_opa == zp.ZIP_PC)||(m_opa == zp.ZIP_CC))
                                yyerror("MPYU does not support PC or CC register operands or results");
                                yyerror("MPYU does not support PC or CC register operands or results");
                        else if (m_opb == zp.ZIP_Rnone)
                        else if (m_opb == zp.ZIP_Rnone)
                                in = zp.op_mpyu(m_cond, imm, m_opa);
                                in = zp.op_mpyu(m_cond, imm, m_opa);
                        else
                        else
                                in = zp.op_mpyu(m_cond, imm, m_opb, m_opa);
                                in = zp.op_mpyu(m_cond, imm, m_opb, m_opa);
                        break;
                        break;
                case OP_MPYS:
                case OP_MPYS:
                        if ((m_opb == zp.ZIP_PC)||(m_opb == zp.ZIP_CC)
                        if ((m_opb == zp.ZIP_PC)||(m_opb == zp.ZIP_CC)
                                ||(m_opa == zp.ZIP_PC)||(m_opa == zp.ZIP_CC))
                                ||(m_opa == zp.ZIP_PC)||(m_opa == zp.ZIP_CC))
                                yyerror("MPYS does not support PC or CC register operands or results");
                                yyerror("MPYS does not support PC or CC register operands or results");
                        else if (m_opb == zp.ZIP_Rnone)
                        else if (m_opb == zp.ZIP_Rnone)
                                in = zp.op_mpys(m_cond, imm, m_opa);
                                in = zp.op_mpys(m_cond, imm, m_opa);
                        else
                        else
                                in = zp.op_mpys(m_cond, imm, m_opb, m_opa);
                                in = zp.op_mpys(m_cond, imm, m_opb, m_opa);
                        break;
                        break;
                case OP_ROL:
                case OP_ROL:
                        if (m_opa == zp.ZIP_Rnone)
                        if (m_opa == zp.ZIP_Rnone)
                                yyerror("ROL needs a register result");
                                yyerror("ROL needs a register result");
                        if (m_opb != zp.ZIP_Rnone)
                        if (m_opb != zp.ZIP_Rnone)
                                in = zp.op_rol(m_cond, imm, m_opb, m_opa);
                                in = zp.op_rol(m_cond, imm, m_opb, m_opa);
                        else
                        else
                                in = zp.op_rol(m_cond, imm, m_opa);
                                in = zp.op_rol(m_cond, imm, m_opa);
                        break;
                        break;
                case OP_SUB:
                case OP_SUB:
                        BLD_DUALOP(op_sub)
                        BLD_DUALOP(op_sub)
                        break;
                        break;
                case OP_AND:
                case OP_AND:
                        BLD_DUALOP(op_and)
                        BLD_DUALOP(op_and)
                        break;
                        break;
                case OP_ADD:
                case OP_ADD:
                        BLD_DUALOP(op_add)
                        BLD_DUALOP(op_add)
                        break;
                        break;
                case OP_OR:
                case OP_OR:
                        BLD_DUALOP(op_or)
                        BLD_DUALOP(op_or)
                        break;
                        break;
                case OP_XOR:
                case OP_XOR:
                        BLD_DUALOP(op_xor)
                        BLD_DUALOP(op_xor)
                        break;
                        break;
                case OP_LSL:
                case OP_LSL:
                        BLD_DUALOP(op_lsl)
                        BLD_DUALOP(op_lsl)
                        break;
                        break;
                case OP_ASR:
                case OP_ASR:
                        BLD_DUALOP(op_asr)
                        BLD_DUALOP(op_asr)
                        break;
                        break;
                case OP_LSR:
                case OP_LSR:
                        BLD_DUALOP(op_lsr)
                        BLD_DUALOP(op_lsr)
                        break;
                        break;
                case OP_LOD:
                case OP_LOD:
                        if (m_opb != zp.ZIP_Rnone)
                        if (m_opb != zp.ZIP_Rnone)
                                in = zp.op_lod(m_cond, imm, m_opb, m_opa);
                                in = zp.op_lod(m_cond, imm, m_opb, m_opa);
                        else
                        else
                                in = zp.op_lod(m_cond, imm, m_opa);
                                in = zp.op_lod(m_cond, imm, m_opa);
                        break;
                        break;
                case OP_STO:
                case OP_STO:
                        if (m_opb != zp.ZIP_Rnone)
                        if (m_opb != zp.ZIP_Rnone)
                                in = zp.op_sto(m_cond, m_opa, imm, m_opb);
                                in = zp.op_sto(m_cond, m_opa, imm, m_opb);
                        else
                        else
                                in = zp.op_sto(m_cond, m_opa, imm);
                                in = zp.op_sto(m_cond, m_opa, imm);
                        break;
                        break;
                case OP_BREV:
                case OP_BREV:
                        BLD_DUALOP(op_brev);
                        BLD_DUALOP(op_brev);
                        break;
                        break;
                case OP_POPC:
                case OP_POPC:
                        BLD_DUALOP(op_popc);
                        BLD_DUALOP(op_popc);
                        break;
                        break;
                case OP_LDI:
                case OP_LDI:
                        if ((!fitsin(imm, 23))||(m_cond != zp.ZIPC_ALWAYS)) {
                        if ((!fitsin(imm, 23))||(m_cond != zp.ZIPC_ALWAYS)) {
                                if (m_opa == zp.ZIP_PC)
                                if (m_opa == zp.ZIP_PC)
                                        yyerror("Cannot LDI 32-bit addresses into PC register!");
                                        yyerror("Cannot LDI 32-bit addresses into PC register!");
                                LLINE *lln = new LLINE;
                                LLINE *lln = new LLINE;
                                lln->addline(new ILINE(zp.op_ldihi(m_cond, (imm>>16)&0x0ffff, m_opa)));
                                lln->addline(new ILINE(zp.op_ldihi(m_cond, (imm>>16)&0x0ffff, m_opa)));
                                lln->addline(new ILINE(zp.op_ldilo(m_cond, imm&0x0ffff, m_opa)));
                                lln->addline(new ILINE(zp.op_ldilo(m_cond, imm&0x0ffff, m_opa)));
                                lln->m_lineno = m_lineno;
                                lln->m_lineno = m_lineno;
                                return lln;
                                return lln;
                        } else
                        } else
                                in = zp.op_ldi(imm, m_opa);
                                in = zp.op_ldi(imm, m_opa);
                        break;
                        break;
                case OP_DIVU:
                case OP_DIVU:
                        BLD_DUALOP(op_divu);
                        BLD_DUALOP(op_divu);
                        break;
                        break;
                case OP_DIVS:
                case OP_DIVS:
                        BLD_DUALOP(op_divs);
                        BLD_DUALOP(op_divs);
                        break;
                        break;
                case OP_CLRF:
                case OP_CLRF:
                        in = zp.op_clrf(m_cond, m_opb);
                        in = zp.op_clrf(m_cond, m_opb);
                        break;
                        break;
                case OP_NOT:
                case OP_NOT:
                        in = zp.op_not(m_cond, m_opb);
                        in = zp.op_not(m_cond, m_opb);
                        break;
                        break;
                case OP_NEG:
                case OP_NEG:
                        if (m_cond != zp.ZIPC_ALWAYS) {
                        if (m_cond != zp.ZIPC_ALWAYS) {
                                LLINE *lln = new LLINE;
                                LLINE *lln = new LLINE;
                                lln->addline(new ILINE(zp.op_mov(m_cond,-1,m_opb,m_opb)));
                                lln->addline(new ILINE(zp.op_mov(m_cond,-1,m_opb,m_opb)));
                                lln->addline(new ILINE(zp.op_not(m_cond,m_opb)));
                                lln->addline(new ILINE(zp.op_not(m_cond,m_opb)));
                                return lln;
                                return lln;
                        } else {
                        } else {
                                LLINE *lln = new LLINE;
                                LLINE *lln = new LLINE;
                                lln->addline(new ILINE(zp.op_not(m_opb)));
                                lln->addline(new ILINE(zp.op_not(m_opb)));
                                lln->addline(new ILINE(zp.op_add(1,m_opb)));
                                lln->addline(new ILINE(zp.op_add(1,m_opb)));
                                return lln;
                                return lln;
                        }break;
                        }break;
                case OP_JMP:
                case OP_JMP:
                        if (m_opb == zp.ZIP_Rnone) {
                        if (m_opb == zp.ZIP_Rnone) {
                                if (m_cond != zp.ZIPC_ALWAYS)
                                if (m_cond != zp.ZIPC_ALWAYS)
                                        yyerror("JMP: Conditions are not allowed for absolute jumps.");
                                        yyerror("JMP: Conditions are not allowed for absolute jumps.");
                                imm &= (1<<23)-1;
                                imm &= (1<<23)-1;
                                if (!fitsin(imm, 23))
                                if (!fitsin(imm, 23))
                                        yyerror("JMP: Absolute jump address out of range");
                                        yyerror("JMP: Absolute jump address out of range");
                                in = zp.op_ldi(imm, zp.ZIP_PC);
                                in = zp.op_ldi(imm, zp.ZIP_PC);
                        } else if (fitsin(imm,13)) {
                        } else if (fitsin(imm,13)) {
                                in = zp.op_mov(m_cond, imm, m_opb, zp.ZIP_PC);
                                in = zp.op_mov(m_cond, imm, m_opb, zp.ZIP_PC);
                        } else if (fitsin(imm,18))
                        } else if (fitsin(imm,18))
                                in = zp.op_add(m_cond, imm, m_opb, zp.ZIP_PC);
                                in = zp.op_add(m_cond, imm, m_opb, zp.ZIP_PC);
                        else
                        else
                                yyerror("JMP: Immediate out of range");
                                yyerror("JMP: Immediate out of range");
                        break;
                        break;
                case OP_BRA:
                case OP_BRA:
                        BLD_BRANCH(op_bra,ZIPC_ALWAYS)
                        BLD_BRANCH(op_bra,ZIPC_ALWAYS)
                        break;
                        break;
                case OP_BZ:
                case OP_BZ:
                        BLD_BRANCH(op_brz,ZIPC_Z)
                        BLD_BRANCH(op_brz,ZIPC_Z)
                        break;
                        break;
                case OP_BNZ:
                case OP_BNZ:
                        BLD_BRANCH(op_bnz,ZIPC_NZ)
                        BLD_BRANCH(op_bnz,ZIPC_NZ)
                        break;
                        break;
                case OP_BGE:
                case OP_BGE:
                        BLD_BRANCH(op_bge,ZIPC_GE)
                        BLD_BRANCH(op_bge,ZIPC_GE)
                        break;
                        break;
                case OP_BGT:
                case OP_BGT:
                        BLD_BRANCH(op_bgt,ZIPC_GT)
                        BLD_BRANCH(op_bgt,ZIPC_GT)
                        break;
                        break;
                case OP_BLT:
                case OP_BLT:
                        BLD_BRANCH(op_blt,ZIPC_LT)
                        BLD_BRANCH(op_blt,ZIPC_LT)
                        break;
                        break;
                case OP_BRC:
                case OP_BRC:
                        BLD_BRANCH(op_brc,ZIPC_C)
                        BLD_BRANCH(op_brc,ZIPC_C)
                        break;
                        break;
                case OP_BRV:
                case OP_BRV:
                        BLD_BRANCH(op_brv,ZIPC_V)
                        BLD_BRANCH(op_brv,ZIPC_V)
                        break;
                        break;
                case OP_CLR:
                case OP_CLR:
                        if((m_cond == zp.ZIPC_ALWAYS))
                        if((m_cond == zp.ZIPC_ALWAYS))
                                in = zp.op_clr(m_opb);
                                in = zp.op_clr(m_opb);
                        else
                        else
                                in = zp.op_clrf(m_cond, m_opb);
                                in = zp.op_clrf(m_cond, m_opb);
                        break;
                        break;
                case OP_TRAP:
                case OP_TRAP:
                        if((m_opb == zp.ZIP_Rnone)&&(m_cond == zp.ZIPC_ALWAYS))
                        if((m_opb == zp.ZIP_Rnone)&&(m_cond == zp.ZIPC_ALWAYS))
                                in = zp.op_ldi(imm, zp.ZIP_CC);
                                in = zp.op_ldi(imm, zp.ZIP_CC);
                        else if((m_opb == zp.ZIP_Rnone)&&((imm&0x0ffdf)==imm))
                        else if((m_opb == zp.ZIP_Rnone)&&((imm&0x0ffdf)==imm))
                                in = zp.op_ldilo(m_cond, imm & 0x0ffdf, zp.ZIP_CC);
                                in = zp.op_ldilo(m_cond, imm & 0x0ffdf, zp.ZIP_CC);
                        else if((m_opb != zp.ZIP_Rnone)&&(fitsin(imm, 13)))
                        else if((m_opb != zp.ZIP_Rnone)&&(fitsin(imm, 13)))
                                in = zp.op_mov(m_cond, imm, m_opb, zp.ZIP_CC);
                                in = zp.op_mov(m_cond, imm, m_opb, zp.ZIP_CC);
                        else {
                        else {
                                yyerror("Illegal trap!");
                                yyerror("Illegal trap!");
                                in = zp.op_trap(m_cond, 0);
                                in = zp.op_trap(m_cond, 0);
                        }
                        }
                        break;
                        break;
                case OP_RETN:   // yywarn("RETN opcode is deprecated");
                case OP_RETN:   // yywarn("RETN opcode is deprecated");
                                in = zp.op_lod(m_cond, imm, m_opb, m_opa);
                                in = zp.op_lod(m_cond, imm, m_opb, m_opa);
                                in = zp.op_lod(m_cond, -1, zp.ZIP_SP, zp.ZIP_PC);
                                in = zp.op_lod(m_cond, -1, zp.ZIP_SP, zp.ZIP_PC);
                        break;
                        break;
                case OP_HALT:   in = zp.op_halt(m_cond); break;
                case OP_HALT:   in = zp.op_halt(m_cond); break;
                case OP_RTU:    in = zp.op_rtu(m_cond); break;
                case OP_RTU:    in = zp.op_rtu(m_cond); break;
                case OP_BUSY:   in = zp.op_busy(m_cond); break;
                case OP_BUSY:   in = zp.op_busy(m_cond); break;
                case OP_NOOP:   in = zp.op_noop(); break;
                case OP_NOOP:   in = zp.op_noop(); break;
                case OP_BREAK:  in = zp.op_break(); break;
                case OP_BREAK:  in = zp.op_break(); break;
                case OP_LOCK:   in = zp.op_lock(); break;
                case OP_LOCK:   in = zp.op_lock(); break;
                // OP_LJMP:
                case OP_LJMP:   in = zp.op_ljmp(); break;
                case OP_NONE:
                case OP_NONE:
                default:        { char ebuf[256]; sprintf(ebuf, "Unrecognized OP-Code, %d, NONE = %d, CLR=%d", m_opcode, OP_NONE, OP_CLR);
                default:        { char ebuf[256]; sprintf(ebuf, "Unrecognized OP-Code, %d, NONE = %d, CLR=%d", m_opcode, OP_NONE, OP_CLR);
                                yyerror(ebuf);
                                yyerror(ebuf);
                                in = zp.op_noop(); break;
                                in = zp.op_noop(); break;
                                }
                                }
        }
        }
        ILINE   *rs = new ILINE(in);
        ILINE   *rs = new ILINE(in);
        rs->m_lineno = m_lineno;
        rs->m_lineno = m_lineno;
}
}
 
 
int     TLINE::nlines(void)  {
int     TLINE::nlines(void)  {
        if ((m_opcode == OP_LDI)&&( (!(m_imm->isdefined()))
        if ((m_opcode == OP_LDI)&&( (!(m_imm->isdefined()))
                        || (m_cond != ZPARSER::ZIPC_ALWAYS)
                        || (m_cond != ZPARSER::ZIPC_ALWAYS)
                        || (!fitsin(m_imm->eval(), 23)) )) {
                        || (!fitsin(m_imm->eval(), 23)) )) {
                return 2;
                return 2;
        }
        }
        return 1;
        return 1;
}
}
 
 
unsigned int    TLINE::eval(const int lno) {
unsigned int    TLINE::eval(const int lno) {
        if (!isdefined())
        if (!isdefined())
                return DEFAULT_LINE;
                return DEFAULT_LINE;
        else {
        else {
                ASMLINE *ln = this->eval();
                ASMLINE *ln = this->eval();
                unsigned int val = ln->eval(lno);
                unsigned int val = ln->eval(lno);
                delete ln;
                delete ln;
                return val;
                return val;
        }
        }
}
}
 
 
void    TLINE::dump(FILE *fp) {
void    TLINE::dump(FILE *fp) {
        if (m_state == 'V')
        if (m_state == 'V')
                fprintf(fp, "Void @%d\n", m_lineno);
                fprintf(fp, "Void @%d\n", m_lineno);
        else if (m_state != 'T')
        else if (m_state != 'T')
                fprintf(fp, "TLINE state != T (== %c)\n", m_state);
                fprintf(fp, "TLINE state != T (== %c)\n", m_state);
        else {
        else {
                fprintf(fp, "TLINE @%d\n", m_lineno);
                fprintf(fp, "TLINE @%d\n", m_lineno);
                switch(m_opcode) {
                switch(m_opcode) {
                case OP_CMP: fprintf(fp, "\tTLINE OP   = CMP\n");
                case OP_CMP: fprintf(fp, "\tTLINE OP   = CMP\n");
                        break;
                        break;
                case OP_TST: fprintf(fp, "\tTLINE OP   = TST\n");
                case OP_TST: fprintf(fp, "\tTLINE OP   = TST\n");
                        break;
                        break;
                case OP_MOV: fprintf(fp, "\tTLINE OP   = MOV\n");
                case OP_MOV: fprintf(fp, "\tTLINE OP   = MOV\n");
                        break;
                        break;
                case OP_LDIHI:fprintf(fp,"\tTLINE OP   = LDIHI\n");
                case OP_LDIHI:fprintf(fp,"\tTLINE OP   = LDIHI\n");
                        break;
                        break;
                case OP_LDILO:fprintf(fp,"\tTLINE OP   = LDILO\n");
                case OP_LDILO:fprintf(fp,"\tTLINE OP   = LDILO\n");
                        break;
                        break;
                case OP_MPYU: fprintf(fp,"\tTLINE OP   = MPYU\n");
                case OP_MPYU: fprintf(fp,"\tTLINE OP   = MPYU\n");
                        break;
                        break;
                case OP_MPYS: fprintf(fp,"\tTLINE OP   = MPYS\n");
                case OP_MPYS: fprintf(fp,"\tTLINE OP   = MPYS\n");
                        break;
                        break;
                case OP_ROL: fprintf(fp, "\tTLINE OP   = ROL\n");
                case OP_ROL: fprintf(fp, "\tTLINE OP   = ROL\n");
                        break;
                        break;
                case OP_SUB: fprintf(fp, "\tTLINE OP   = SUB\n");
                case OP_SUB: fprintf(fp, "\tTLINE OP   = SUB\n");
                        break;
                        break;
                case OP_AND: fprintf(fp, "\tTLINE OP   = AND\n");
                case OP_AND: fprintf(fp, "\tTLINE OP   = AND\n");
                        break;
                        break;
                case OP_ADD: fprintf(fp, "\tTLINE OP   = ADD\n");
                case OP_ADD: fprintf(fp, "\tTLINE OP   = ADD\n");
                        break;
                        break;
                case OP_OR: fprintf(fp, "\tTLINE OP   = OR\n");
                case OP_OR: fprintf(fp, "\tTLINE OP   = OR\n");
                        break;
                        break;
                case OP_XOR: fprintf(fp, "\tTLINE OP   = XOR\n");
                case OP_XOR: fprintf(fp, "\tTLINE OP   = XOR\n");
                        break;
                        break;
                case OP_LSL: fprintf(fp, "\tTLINE OP   = LSL\n");
                case OP_LSL: fprintf(fp, "\tTLINE OP   = LSL\n");
                        break;
                        break;
                case OP_ASR: fprintf(fp, "\tTLINE OP   = ASR\n");
                case OP_ASR: fprintf(fp, "\tTLINE OP   = ASR\n");
                        break;
                        break;
                case OP_LSR: fprintf(fp, "\tTLINE OP   = LSR\n");
                case OP_LSR: fprintf(fp, "\tTLINE OP   = LSR\n");
                        break;
                        break;
                case OP_LOD: fprintf(fp, "\tTLINE OP   = LOD\n");
                case OP_LOD: fprintf(fp, "\tTLINE OP   = LOD\n");
                        break;
                        break;
                case OP_STO: fprintf(fp, "\tTLINE OP   = STO\n");
                case OP_STO: fprintf(fp, "\tTLINE OP   = STO\n");
                        break;
                        break;
                case OP_LDI: fprintf(fp, "\tTLINE OP   = LDI\n");
                case OP_LDI: fprintf(fp, "\tTLINE OP   = LDI\n");
                        break;
                        break;
                case OP_CLRF: fprintf(fp, "\tTLINE OP   = CLRF\n");
                case OP_CLRF: fprintf(fp, "\tTLINE OP   = CLRF\n");
                        break;
                        break;
                case OP_NOT: fprintf(fp, "\tTLINE OP   = NOT\n");
                case OP_NOT: fprintf(fp, "\tTLINE OP   = NOT\n");
                        break;
                        break;
                case OP_JMP: fprintf(fp, "\tTLINE OP   = JMP\n");
                case OP_JMP: fprintf(fp, "\tTLINE OP   = JMP\n");
                        break;
                        break;
                case OP_BRA: fprintf(fp, "\tTLINE OP   = BRA\n");
                case OP_BRA: fprintf(fp, "\tTLINE OP   = BRA\n");
                        break;
                        break;
                case OP_BZ:
                case OP_BZ:
                case OP_BNZ:
                case OP_BNZ:
                case OP_BGE:
                case OP_BGE:
                case OP_BGT:
                case OP_BGT:
                case OP_BLT:
                case OP_BLT:
                case OP_BRC:
                case OP_BRC:
                case OP_BRV:
                case OP_BRV:
                        fprintf(fp, "\tTLINE OP   = BRA.C\n");
                        fprintf(fp, "\tTLINE OP   = BRA.C\n");
                        break;
                        break;
                case OP_CLR: fprintf(fp, "\tTLINE OP   = CLR\n");
                case OP_CLR: fprintf(fp, "\tTLINE OP   = CLR\n");
                        break;
                        break;
                case OP_NEG: fprintf(fp, "\tTLINE OP   = NEG\n");
                case OP_NEG: fprintf(fp, "\tTLINE OP   = NEG\n");
                        break;
                        break;
                case OP_TRAP: fprintf(fp, "\tTLINE OP   = TRAP\n");
                case OP_TRAP: fprintf(fp, "\tTLINE OP   = TRAP\n");
                        break;
                        break;
                case OP_HALT: fprintf(fp, "\tTLINE OP   = HALT\n");
                case OP_HALT: fprintf(fp, "\tTLINE OP   = HALT\n");
                        break;
                        break;
                case OP_RTU: fprintf(fp, "\tTLINE OP   = RTU\n");
                case OP_RTU: fprintf(fp, "\tTLINE OP   = RTU\n");
                        break;
                        break;
                case OP_BUSY: fprintf(fp, "\tTLINE OP   = BUSY\n");
                case OP_BUSY: fprintf(fp, "\tTLINE OP   = BUSY\n");
                        break;
                        break;
                case OP_BREAK: fprintf(fp, "\tTLINE OP   = BREAK\n");
                case OP_BREAK: fprintf(fp, "\tTLINE OP   = BREAK\n");
                        break;
                        break;
                case OP_NOOP: fprintf(fp, "\tTLINE OP   = NOOP\n");
                case OP_NOOP: fprintf(fp, "\tTLINE OP   = NOOP\n");
                case OP_LOCK: fprintf(fp, "\tTLINE OP   = LOCK\n");
                case OP_LOCK: fprintf(fp, "\tTLINE OP   = LOCK\n");
                        break;
                        break;
                // OP_LJMP:
 
                case OP_NONE:
                case OP_NONE:
                default:
                default:
                        fprintf(fp, "\tTLINE OP   = (Unrecognized, %d)\n", m_opcode);
                        fprintf(fp, "\tTLINE OP   = (Unrecognized, %d)\n", m_opcode);
                                break;
                                break;
                }
                }
                if (m_cond == 0)
                if (m_cond == 0)
                        fprintf(fp, "\tTLINE COND = (Always)\n");
                        fprintf(fp, "\tTLINE COND = (Always)\n");
                else
                else
                        fprintf(fp, "\tTLINE COND = %s\n", zop_ccstr[m_cond&0x07]);
                        fprintf(fp, "\tTLINE COND = %s\n", zop_ccstr[m_cond&0x07]);
                if (m_imm == NULL)
                if (m_imm == NULL)
                        fprintf(fp, "\tTLINE imm  = (NULL)\n");
                        fprintf(fp, "\tTLINE imm  = (NULL)\n");
                else if (!m_imm->isdefined()) {
                else if (!m_imm->isdefined()) {
                        m_imm->reduce();
                        m_imm->reduce();
                        fprintf(fp, "\tTLINE imm  = ");
                        fprintf(fp, "\tTLINE imm  = ");
                        m_imm->dump(fp);
                        m_imm->dump(fp);
                        fprintf(fp, "\n");
                        fprintf(fp, "\n");
                } else
                } else
                        fprintf(fp, "\tTLINE imm  = %d\n", m_imm->eval());
                        fprintf(fp, "\tTLINE imm  = %d\n", m_imm->eval());
                if (m_opb != ZPARSER::ZIP_Rnone)
                if (m_opb != ZPARSER::ZIP_Rnone)
                        fprintf(fp, "\tTLINE opb  = %d\n", m_opb);
                        fprintf(fp, "\tTLINE opb  = %d\n", m_opb);
                if (m_opa != ZPARSER::ZIP_Rnone)
                if (m_opa != ZPARSER::ZIP_Rnone)
                        fprintf(fp, "\tTLINE opa  = %d\n", m_opa);
                        fprintf(fp, "\tTLINE opa  = %d\n", m_opa);
        }
        }
}
}
 
 
 
 
// Now, for our symbol table
// Now, for our symbol table
class   SYMTABLE_ENTRY {
class   SYMTABLE_ENTRY {
private:
private:
        int     m_recursion_check;
        int     m_recursion_check;
 
 
        std::string     &trim(std::string &s) {
        std::string     &trim(std::string &s) {
                std::string::iterator   ptr = s.end()-1;
                std::string::iterator   ptr = s.end()-1;
 
 
                while((ptr >= s.begin())&&(isspace(*ptr)))
                while((ptr >= s.begin())&&(isspace(*ptr)))
                        *ptr-- = '\0';
                        *ptr-- = '\0';
                if (*ptr == ':')
                if (*ptr == ':')
                        *ptr-- = '\0';
                        *ptr-- = '\0';
 
 
                // printf("STORING: %s\n", s.c_str());
                // printf("STORING: %s\n", s.c_str());
 
 
                return s;
                return s;
        }
        }
 
 
public:
public:
        std::string     m_name;
        std::string     m_name;
        AST             *m_value;
        AST             *m_value;
        SYMTABLE_ENTRY(const char *str) : m_recursion_check(0), m_name(str), m_value(NULL) {
        SYMTABLE_ENTRY(const char *str) : m_recursion_check(0), m_name(str), m_value(NULL) {
                trim(m_name);
                trim(m_name);
        } SYMTABLE_ENTRY(const char *str, AST *v) : m_recursion_check(0), m_name(str), m_value(v) {
        } SYMTABLE_ENTRY(const char *str, AST *v) : m_recursion_check(0), m_name(str), m_value(v) {
                trim(m_name);
                trim(m_name);
        } ~SYMTABLE_ENTRY(void) {
        } ~SYMTABLE_ENTRY(void) {
                if (m_value)
                if (m_value)
                        delete m_value;
                        delete m_value;
        }
        }
 
 
        SYMTABLE_ENTRY &operator=(AST *new_value) {
        SYMTABLE_ENTRY &operator=(AST *new_value) {
                if (m_value)
                if (m_value)
                        delete  m_value;
                        delete  m_value;
                m_value = new_value;
                m_value = new_value;
        }
        }
 
 
        bool    isdefined(void) {
        bool    isdefined(void) {
                if (m_recursion_check > 0) {
                if (m_recursion_check > 0) {
                        fprintf(stderr, "RECURSION DETECTED! Symbol: %s\n",
                        fprintf(stderr, "RECURSION DETECTED! Symbol: %s\n",
                                m_name.c_str());
                                m_name.c_str());
                        return false;
                        return false;
                }
                }
                m_recursion_check = 1;
                m_recursion_check = 1;
                if (m_value->m_node_type != 'N')
                if (m_value->m_node_type != 'N')
                        m_value->reduce();
                        m_value->reduce();
                bool    answer = m_value->isdefined();
                bool    answer = m_value->isdefined();
                m_recursion_check = 0;
                m_recursion_check = 0;
                return answer;
                return answer;
        }
        }
        int     val(void) {
        int     val(void) {
                if ((m_value->isdefined())&&(m_value->m_node_type != 'N')) {
                if ((m_value->isdefined())&&(m_value->m_node_type != 'N')) {
                        int     v = m_value->eval();
                        int     v = m_value->eval();
                        AST     *tmp;
                        AST     *tmp;
                        tmp = m_value;
                        tmp = m_value;
                        m_value = new AST_NUMBER(v);
                        m_value = new AST_NUMBER(v);
                        delete tmp;
                        delete tmp;
                } return (m_value->eval());
                } return (m_value->eval());
        }
        }
        void    dump(FILE *fp) { m_value->dump(fp); }
        void    dump(FILE *fp) { m_value->dump(fp); }
};
};
 
 
class   SYMBOL_TABLE    {
class   SYMBOL_TABLE    {
private:
private:
        typedef SYMTABLE_ENTRY  *TBLV;
        typedef SYMTABLE_ENTRY  *TBLV;
        typedef std::list<TBLV> TBLT;
        typedef std::list<TBLV> TBLT;
 
 
        TBLT    m_tbl;
        TBLT    m_tbl;
 
 
        TBLT::iterator  lookup(const char *str) {
        TBLT::iterator  lookup(const char *str) {
                TBLT::iterator  i = m_tbl.begin();
                TBLT::iterator  i = m_tbl.begin();
                for(; (i!=m_tbl.end())&&(strcmp(str, (*i)->m_name.c_str())>0);
                for(; (i!=m_tbl.end())&&(strcmp(str, (*i)->m_name.c_str())>0);
                                i++)
                                i++)
                        ;
                        ;
                if ((i != m_tbl.end())&&(strcmp(str,(*i)->m_name.c_str())==0))
                if ((i != m_tbl.end())&&(strcmp(str,(*i)->m_name.c_str())==0))
                        return i;
                        return i;
                return  m_tbl.end();
                return  m_tbl.end();
        }
        }
 
 
public:
public:
        SYMBOL_TABLE(void) {}
        SYMBOL_TABLE(void) {}
        ~SYMBOL_TABLE(void) {
        ~SYMBOL_TABLE(void) {
                TBLT::iterator i = m_tbl.begin();
                TBLT::iterator i = m_tbl.begin();
                while(i != m_tbl.end()) {
                while(i != m_tbl.end()) {
                        delete (*i);
                        delete (*i);
                        i = m_tbl.erase(i);
                        i = m_tbl.erase(i);
                }
                }
        }
        }
 
 
        void    define(const char *key, AST *value) {
        void    define(const char *key, AST *value) {
                SYMTABLE_ENTRY  *v = new SYMTABLE_ENTRY(key, value);
                SYMTABLE_ENTRY  *v = new SYMTABLE_ENTRY(key, value);
                TBLT::iterator  i = m_tbl.begin();
                TBLT::iterator  i = m_tbl.begin();
                for(; (i!=m_tbl.end())&&(strcmp(key, (*i)->m_name.c_str())>0);
                for(; (i!=m_tbl.end())&&(strcmp(key, (*i)->m_name.c_str())>0);
                                i++)
                                i++)
                        ;
                        ;
                m_tbl.insert(i, v);
                m_tbl.insert(i, v);
 
 
                /*
                /*
                fprintf(stderr, "Defining: %s = ", key);
                fprintf(stderr, "Defining: %s = ", key);
                value->dump(stderr);
                value->dump(stderr);
                fprintf(stderr, "\n");
                fprintf(stderr, "\n");
                */
                */
        }
        }
 
 
        bool    isdefined(const char *key) {
        bool    isdefined(const char *key) {
                TBLT::iterator  i = lookup(key);
                TBLT::iterator  i = lookup(key);
                if (i == m_tbl.end()) {
                if (i == m_tbl.end()) {
                        // fprintf(stderr, "%s is not in the symbol table\n", key);
                        // fprintf(stderr, "%s is not in the symbol table\n", key);
                        return false;
                        return false;
                } else {
                } else {
                        bool    defined = (*i)->isdefined();
                        bool    defined = (*i)->isdefined();
                        /*
                        /*
                        if (!defined) {
                        if (!defined) {
                                fprintf(stderr, "KEY: %s = ", key);
                                fprintf(stderr, "KEY: %s = ", key);
                                (*i)->dump(stderr);
                                (*i)->dump(stderr);
                                fprintf(stderr, " is not yet defined\n");
                                fprintf(stderr, " is not yet defined\n");
                        } */
                        } */
                        return (*i)->isdefined();
                        return (*i)->isdefined();
                }
                }
        }
        }
 
 
        int     value(const char *key) {
        int     value(const char *key) {
                TBLT::iterator  i = lookup(key);
                TBLT::iterator  i = lookup(key);
                if (i == m_tbl.end())
                if (i == m_tbl.end())
                        return 0;
                        return 0;
                else
                else
                        return (*i)->val();
                        return (*i)->val();
        }
        }
};
};
 
 
SYMBOL_TABLE    *global_context = NULL, *file_context = NULL;
SYMBOL_TABLE    *global_context = NULL, *file_context = NULL;
 
 
bool    stb_isdefined(const char *key) {
bool    stb_isdefined(const char *key) {
        if ((file_context)&&(file_context->isdefined(key)))
        if ((file_context)&&(file_context->isdefined(key)))
                return true;
                return true;
        else
        else
                return global_context->isdefined(key);
                return global_context->isdefined(key);
} int   stb_value(const char *key) {
} int   stb_value(const char *key) {
        if ((file_context)&&(file_context->isdefined(key)))
        if ((file_context)&&(file_context->isdefined(key)))
                return file_context->value(key);
                return file_context->value(key);
        else
        else
                return global_context->value(key);
                return global_context->value(key);
} void  stb_define(const char *key, AST *value) {
} void  stb_define(const char *key, AST *value) {
        file_context->define(key, value);
        file_context->define(key, value);
} void  gbl_define(const char *key, AST *value) {
} void  gbl_define(const char *key, AST *value) {
        global_context->define(key, value);
        global_context->define(key, value);
}
}
 
 
void    create_new_context(void) {
void    create_new_context(void) {
        if (global_context == NULL)
        if (global_context == NULL)
                global_context = new SYMBOL_TABLE;
                global_context = new SYMBOL_TABLE;
        if (file_context != NULL)
        if (file_context != NULL)
                delete file_context;
                delete file_context;
        file_context = new SYMBOL_TABLE;
        file_context = new SYMBOL_TABLE;
}
}
 
 
 
 
// Convenience functions for accessing the symbol table
// Convenience functions for accessing the symbol table
bool    stb_isdefined(const std::string &key) {
bool    stb_isdefined(const std::string &key) {
        bool answer = stb_isdefined(key.c_str());
        bool answer = stb_isdefined(key.c_str());
        return answer;
        return answer;
} int   stb_value(const std::string &key) {
} int   stb_value(const std::string &key) {
        return stb_value(key.c_str());
        return stb_value(key.c_str());
} void  stb_define(const std::string &key, AST *value) {
} void  stb_define(const std::string &key, AST *value) {
        stb_define(key.c_str(), value);
        stb_define(key.c_str(), value);
} void  gbl_define(const std::string &key, AST *value) {
} void  gbl_define(const std::string &key, AST *value) {
        gbl_define(key.c_str(), value);
        gbl_define(key.c_str(), value);
}
}
 
 
 
 
 
 

powered by: WebSVN 2.1.0

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