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

Subversion Repositories c16

[/] [c16/] [trunk/] [asm/] [assembler.bison] - Diff between revs 26 and 30

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

Rev 26 Rev 30
%{
%{
#include 
#include 
 
#include 
#include 
#include 
extern int yylex();
extern int yylex();
extern int yyparse();
extern int yyparse();
extern int yyerror(const char *);
extern int yyerror(const char *);
extern FILE * out;
extern FILE * out;
extern FILE * list;
extern FILE * list;
extern FILE * sym;
extern FILE * sym;
extern FILE * ihx;
extern FILE * ihx;
static void write_intel_hex(FILE * out);
static void write_intel_hex(FILE * out);
int PC          = 0;
int PC          = 0;
int reloc_start = 0;   // first PC
int reloc_start = 0;   // first PC
int reloc_last  = 0;   // last PC
int reloc_last  = 0;   // last PC
int reloc_end   = 0;   // end of reloc
int reloc_end   = 0;   // end of reloc
char memory[0x10000];
char memory[0x10000];
unsigned int mem_idx = 0;
unsigned int mem_idx = 0;
enum ExHow { EX_NAME, EX_NUMBER,
enum ExHow { EX_NAME, EX_NUMBER,
             EX_ADD, EX_SUB, EX_MULT, EX_DIV, EX_MOD };
             EX_ADD, EX_SUB, EX_MULT, EX_DIV, EX_MOD };
class Expression
class Expression
{
{
public:
public:
   Expression(const char * n)
   Expression(const char * n)
   : how(EX_NAME),
   : how(EX_NAME),
     ex(0),
     ex(0),
     name(n),
     name(n),
     number(0)
     number(0)
     {};
     {};
   Expression(int n)
   Expression(int n)
   : how(EX_NUMBER),
   : how(EX_NUMBER),
     ex(0),
     ex(0),
     name(0),
     name(0),
     number(n)
     number(n)
     {};
     {};
   Expression(Expression * e, ExHow h, const char * n)
   Expression(Expression * e, ExHow h, const char * n)
   : how(h),
   : how(h),
     ex(e),
     ex(e),
     name(n),
     name(n),
     number(0)
     number(0)
     {};
     {};
   Expression(Expression * e, ExHow h, int n)
   Expression(Expression * e, ExHow h, int n)
   : how(h),
   : how(h),
     ex(e),
     ex(e),
     name(0),
     name(0),
     number(n)
     number(n)
     {};
     {};
   int GetValue() const;
   int GetValue() const;
   int ListBase() const;
   int ListBase() const;
   bool UsesName() const
   bool UsesName() const
      {
      {
        if (how == EX_NAME)     return true;
        if (how == EX_NAME)     return true;
        if (how == EX_NUMBER)   return false;
        if (how == EX_NUMBER)   return false;
        assert(ex);
        assert(ex);
        return ex->UsesName();
        return ex->UsesName();
      }
      }
private:
private:
   const ExHow  how;
   const ExHow  how;
   Expression * ex;
   Expression * ex;
   const char * name;
   const char * name;
   int          number;
   int          number;
};
};
enum OP_BASE
enum OP_BASE
{
{
   EXPR,
   EXPR,
   REG_RR, REG_RU, REG_RS, REG_R,
   REG_RR, REG_RU, REG_RS, REG_R,
   REG_LL, REG_LU, REG_LS, REG_L,
   REG_LL, REG_LU, REG_LS, REG_L,
   REG_SP,
   REG_SP,
   COND_Z,
   COND_Z,
   COND_NZ
   COND_NZ
};
};
enum OP_ATTR
enum OP_ATTR
{
{
   ATT_NONE,
   ATT_NONE,
   ATT_POSTINC,
   ATT_POSTINC,
   ATT_PREDEC,
   ATT_PREDEC,
   ATT_OFFSET,
   ATT_OFFSET,
   ATT_CONTENT,
   ATT_CONTENT,
   ATT_PORT,
   ATT_PORT,
   ATT_ADDR,
   ATT_ADDR,
   ATT_IMM,
   ATT_IMM,
};
};
enum OP_HOW
enum OP_HOW
{
{
   H_NONE     = 0, // unique opcode
   H_NONE     = 0, // unique opcode
   H_BYTE     = 1,
   H_BYTE     = 1,
   H_PORT     = 2, //                       #byte
   H_PORT     = 2, //                       #byte
   H_WORD     = 3, //                                      #word
   H_WORD     = 3, //                                      #word
   H_sBW      = 4, // signed                #byte (01X) or #word (10X)
   H_sBW      = 4, // signed                #byte (01X) or #word (10X)
   H_uBW      = 5, // unsigned              #byte (01X) or #word (10X)
   H_uBW      = 5, // unsigned              #byte (01X) or #word (10X)
   H_sQBW     = 6, // signed quick       or #byte (01X) or #word (10X)
   H_sQBW     = 6, // signed quick       or #byte (01X) or #word (10X)
   H_uQBW     = 7, // unsigned quick     or #byte (01X) or #word (10X)
   H_uQBW     = 7, // unsigned quick     or #byte (01X) or #word (10X)
};
};
class Operand
class Operand
{
{
public:
public:
   Operand(OP_BASE b, const char * txt)
   Operand(OP_BASE b, const char * txt)
   : base(b), attr(ATT_NONE), expr(0), op_text(txt), offset(0) {};
   : base(b), attr(ATT_NONE), expr(0), op_text(txt), offset(0) {};
   Operand(Expression * ex)
   Operand(Expression * ex)
   : base(EXPR), attr(ATT_NONE), expr(ex), op_text(0), offset(0) {};
   : base(EXPR), attr(ATT_NONE), expr(ex), op_text(0), offset(0) {};
   Operand * PostInc()
   Operand * PostInc()
      {
      {
        assert(attr == ATT_NONE);
        assert(attr == ATT_NONE);
        attr = ATT_POSTINC;
        attr = ATT_POSTINC;
        return this;
        return this;
      };
      };
   Operand * PreDec()
   Operand * PreDec()
      {
      {
        assert(attr == ATT_NONE);
        assert(attr == ATT_NONE);
        attr = ATT_PREDEC;
        attr = ATT_PREDEC;
        return this;
        return this;
      };
      };
   Operand * Content()
   Operand * Content()
      {
      {
        assert(base == REG_RR || base == REG_LL);
        assert(base == REG_RR || base == REG_LL);
        assert(attr == ATT_NONE);
        assert(attr == ATT_NONE);
        attr = ATT_CONTENT;
        attr = ATT_CONTENT;
        return this;
        return this;
      };
      };
   Operand * Offset(Operand * offs)
   Operand * Offset(Operand * offs)
      {
      {
        assert(base != EXPR);
        assert(base != EXPR);
        assert(attr == ATT_NONE);
        assert(attr == ATT_NONE);
        attr = ATT_OFFSET;
        attr = ATT_OFFSET;
        assert(offs->base == EXPR);
        assert(offs->base == EXPR);
        assert(offs->attr == ATT_NONE);
        assert(offs->attr == ATT_NONE);
        assert(offset == 0);
        assert(offset == 0);
        offset = offs;
        offset = offs;
        return this;
        return this;
      };
      };
   Operand * Port()
   Operand * Port()
      {
      {
        assert(base == EXPR);
        assert(base == EXPR);
        assert(attr == ATT_NONE);
        assert(attr == ATT_NONE);
        attr = ATT_PORT;
        attr = ATT_PORT;
        return this;
        return this;
      };
      };
   Operand * AbsAddr()
   Operand * AbsAddr()
      {
      {
        assert(base == EXPR);
        assert(base == EXPR);
        assert(attr == ATT_NONE);
        assert(attr == ATT_NONE);
        attr = ATT_ADDR;
        attr = ATT_ADDR;
        return this;
        return this;
      };
      };
   Operand * Immediate()
   Operand * Immediate()
     {
     {
        assert(base == EXPR);
        assert(base == EXPR);
        assert(attr == ATT_NONE);
        assert(attr == ATT_NONE);
        attr = ATT_IMM;
        attr = ATT_IMM;
        return this;
        return this;
     };
     };
   int  GetLength(OP_HOW how);
   int  GetLength(OP_HOW how);
   int  GetValue();
   int  GetValue();
   int  ListHex(OP_HOW how);
   int  ListHex(OP_HOW how);
   int  List(OP_HOW how);
   int  List(OP_HOW how);
   int  ListBase(OP_HOW how);
   int  ListBase(OP_HOW how);
private:
private:
   OP_BASE      base;
   OP_BASE      base;
   OP_ATTR      attr;
   OP_ATTR      attr;
   Operand    * offset;
   Operand    * offset;
   const char * op_text;   // scanned text
   const char * op_text;   // scanned text
   Expression * expr;
   Expression * expr;
};
};
class Opcode
class Opcode
{
{
public:
public:
   Opcode(OP_HOW how, unsigned int opc, const char * txt,
   Opcode(OP_HOW how, unsigned int opc, const char * txt,
          Operand * op1 = 0, Operand * op2 = 0)
          Operand * op1 = 0, Operand * op2 = 0)
   : op_how(how),
   : op_how(how),
     op_code(opc),
     op_code(opc),
     op_text(txt),
     op_text(txt),
     op_1(op1),
     op_1(op1),
     op_2(op2),
     op_2(op2),
     reloc(reloc_end) {};
     reloc(reloc_end) {};
   int GetLength() const;
   int GetLength() const;
   int GetOpcode(int & len) const;
   int GetOpcode(int & len) const;
   int List(int pc);
   int List(int pc);
   void Error() const;
   void Error() const;
private:
private:
   OP_HOW        op_how;
   OP_HOW        op_how;
   unsigned char op_code;
   unsigned char op_code;
   const char  * op_text;   // opcode text
   const char  * op_text;   // opcode text
   Operand     * op_1;    // oerand 1
   Operand     * op_1;    // oerand 1
   Operand     * op_2;    // oerand 2
   Operand     * op_2;    // oerand 2
   bool          reloc;   // true if relocated
   bool          reloc;   // true if relocated
};
};
int Reloc(bool rloc, int value)
int Reloc(bool rloc, int value)
{
{
  if (!rloc)   return value;
  if (!rloc)   return value;
   return value + reloc_end - reloc_last;
   return value + reloc_end - reloc_last;
}
}
class Symbol
class Symbol
{
{
public:
public:
   static void Add(const char * id, Expression * ex, bool lab, bool reloc);
   static void Add(const char * id, Expression * ex, bool lab, bool reloc);
   static void ListNonlabels();
   static void ListNonlabels();
   static int GetValue(const char * id);
   static int GetValue(const char * id);
   static void Reset()   { current = symbols; };
   static void Reset()   { current = symbols; };
   static void PrintSymbols();
   static void PrintSymbols();
   static void Advance(int pc);
   static void Advance(int pc);
private:
private:
   Symbol(const char * id, Expression * ex, bool lab, bool rloc)
   Symbol(const char * id, Expression * ex, bool lab, bool rloc)
   : identifier(id),
   : identifier(id),
     expr(ex),
     expr(ex),
     label(lab),
     label(lab),
     reloc(rloc),
     reloc(rloc),
     tail(0) {};
     tail(0) {};
   const char * identifier;
   const char * identifier;
   Expression * expr;
   Expression * expr;
   Symbol     * tail;
   Symbol     * tail;
   bool         label;   // true if label
   bool         label;   // true if label
   bool         reloc;   // true if relocated
   bool         reloc;   // true if relocated
   static Symbol * symbols;
   static Symbol * symbols;
   static Symbol * current;
   static Symbol * current;
};
};
class Line
class Line
{
{
public:
public:
   static void Add(Opcode * opc);
   static void Add(Opcode * opc);
   static void List();
   static void List();
private:
private:
   Line(Opcode * opc)
   Line(Opcode * opc)
   : opcode(opc),
   : opcode(opc),
     pc(PC),
     pc(PC),
     tail(0)
     tail(0)
     {};
     {};
   int      pc;
   int      pc;
   Opcode * opcode;
   Opcode * opcode;
   Line   * tail;
   Line   * tail;
   static Line * first;
   static Line * first;
   static Line * last;
   static Line * last;
};
};
%}
%}
%token  _BYTE   _WORD   _OFFSET INT     IDENT   EOL     EOFILE  ERROR
%token  _BYTE   _WORD   _OFFSET INT     IDENT   EOL     EOFILE  ERROR
        _LL     _L      _LS     _LU     _RR     _R      _RS     _RU
        _LL     _L      _LS     _LU     _RR     _R      _RS     _RU
        _RRZ    _RRNZ   _SP     _EXTERN _STATIC
        _RRZ    _RRNZ   _SP     _EXTERN _STATIC
        ADD     AND     ASR     CALL    CLRB    CLRW    DI      DIV_IS
        ADD     AND     ASR     CALL    CLRB    CLRW    DI      DIV_IS
        DIV_IU  EI      HALT    IN      JMP     LNOT    LEA     LSL
        DIV_IU  EI      HALT    IN      JMP     LNOT    LEA     LSL
        LSR     MOVE    MD_STP  MD_FIN  MOD_FIN MUL_IS  MUL_IU  NEG
        LSR     MOVE    MD_STP  MD_FIN  MOD_FIN MUL_IS  MUL_IU  NEG
        NOP     NOT     OUT     OR      RET     RETI    SEQ     SGE
        NOP     NOT     OUT     OR      RET     RETI    SEQ     SGE
        SGT     SLE     SLT     SNE     SHS     SHI     SLS     SLO
        SGT     SLE     SLT     SNE     SHS     SHI     SLS     SLO
        SUB     XOR
        SUB     XOR
%start  all
%start  all
%union  {       int          _num;
%union  {       int          _num;
                const char * _txt;
                const char * _txt;
                Opcode     * _opcode;
                Opcode     * _opcode;
                Operand    * _operand;
                Operand    * _operand;
                Expression * _expression;
                Expression * _expression;
        }
        }
%type   <_num>        INT
%type   <_num>        INT
%type   <_txt>
%type   <_txt>
        IDENT   _BYTE   _WORD
        IDENT   _BYTE   _WORD
        _LL     _LU     _LS     _L      _RR     _RU     _RS     _R
        _LL     _LU     _LS     _L      _RR     _RU     _RS     _R
        _RRZ    _RRNZ   _SP
        _RRZ    _RRNZ   _SP
        ADD     AND     ASR     CALL    CLRB    CLRW    DI      DIV_IS
        ADD     AND     ASR     CALL    CLRB    CLRW    DI      DIV_IS
        DIV_IU  EI      HALT    IN      JMP     LNOT    LEA     LSL
        DIV_IU  EI      HALT    IN      JMP     LNOT    LEA     LSL
        LSR     MOVE    MD_STP  MD_FIN  MOD_FIN MUL_IS  MUL_IU  NEG
        LSR     MOVE    MD_STP  MD_FIN  MOD_FIN MUL_IS  MUL_IU  NEG
        NOP     NOT     OUT     OR      RET     RETI    SEQ     SGE
        NOP     NOT     OUT     OR      RET     RETI    SEQ     SGE
        SGT     SLE     SLT     SNE     SHS     SHI     SLS     SLO
        SGT     SLE     SLT     SNE     SHS     SHI     SLS     SLO
        SUB     XOR
        SUB     XOR
%type   <_opcode>        opcode  rest    line
%type   <_opcode>        opcode  rest    line
%type   <_expression>        expr
%type   <_expression>        expr
%type   <_operand>
%type   <_operand>
        value
        value
        imm
        imm
        cRR RR RU RS R dRR RRi
        cRR RR RU RS R dRR RRi
        cLL LL LU LS L dLL LLi
        cLL LL LU LS L dLL LLi
        SP dSP SPi oSP
        SP dSP SPi oSP
        RRZ RRNZ
        RRZ RRNZ
        port addr
        port addr
%%
%%
all     : lines EOFILE
all     : lines EOFILE
          {
          {
            reloc_last = PC;
            reloc_last = PC;
            Symbol::ListNonlabels();
            Symbol::ListNonlabels();
            Line::List();
            Line::List();
            Symbol::PrintSymbols();
            Symbol::PrintSymbols();
            fwrite(memory, 1, mem_idx, out);
            fwrite(memory, 1, mem_idx, out);
            write_intel_hex(ihx);
            write_intel_hex(ihx);
            return 0;
            return 0;
          }
          }
        ;
        ;
lines
lines
        : line                  { if ($1)   Line::Add($1); }
        : line                  { if ($1)   Line::Add($1); }
        | lines line            { if ($2)   Line::Add($2); }
        | lines line            { if ($2)   Line::Add($2); }
        ;
        ;
line
line
        :            EOL        { $$ =  0; }
        :            EOL        { $$ =  0; }
        | label      EOL        { $$ =  0; }
        | label      EOL        { $$ =  0; }
        |       rest EOL        { $$ = $1; }
        |       rest EOL        { $$ = $1; }
        | label rest EOL        { $$ = $2; }
        | label rest EOL        { $$ = $2; }
        ;
        ;
label   : IDENT ':'
label   : IDENT ':'
          { Symbol::Add($1, new Expression(PC), true, reloc_end); }
          { Symbol::Add($1, new Expression(PC), true, reloc_end); }
        ;
        ;
rest
rest
        : IDENT '='  expr       { $$ = 0;   Symbol::Add($1, $3, false, false); }
        : IDENT '='  expr       { $$ = 0;   Symbol::Add($1, $3, false, false); }
        | _EXTERN IDENT         { $$ = 0;   }
        | _EXTERN IDENT         { $$ = 0;   }
        | _STATIC IDENT         { $$ = 0;   }
        | _STATIC IDENT         { $$ = 0;   }
        | _OFFSET    expr       { $$ = 0;   reloc_end = $2->GetValue();
        | _OFFSET    expr       { $$ = 0;   reloc_end = $2->GetValue();
                                  reloc_start = PC;  }
                                  reloc_start = PC;  }
        | opcode                { $$ = $1 }
        | opcode                { $$ = $1 }
        ;
        ;
expr
expr
        : INT                   { $$ = new Expression($1);               }
        : INT                   { $$ = new Expression($1);               }
        | IDENT                 { $$ = new Expression($1);               }
        | IDENT                 { $$ = new Expression($1);               }
        | expr '+' INT          { $$ = new Expression($1, EX_ADD,  $3);  }
        | expr '+' INT          { $$ = new Expression($1, EX_ADD,  $3);  }
        | expr '-' INT          { $$ = new Expression($1, EX_SUB,  $3);  }
        | expr '-' INT          { $$ = new Expression($1, EX_SUB,  $3);  }
        | expr '*' INT          { $$ = new Expression($1, EX_MULT, $3);  }
        | expr '*' INT          { $$ = new Expression($1, EX_MULT, $3);  }
        | expr '/' INT          { $$ = new Expression($1, EX_DIV,  $3);  }
        | expr '/' INT          { $$ = new Expression($1, EX_DIV,  $3);  }
        | expr '%' INT          { $$ = new Expression($1, EX_MOD,  $3);  }
        | expr '%' INT          { $$ = new Expression($1, EX_MOD,  $3);  }
        | expr '+' IDENT        { $$ = new Expression($1, EX_ADD,  $3);  }
        | expr '+' IDENT        { $$ = new Expression($1, EX_ADD,  $3);  }
        | expr '-' IDENT        { $$ = new Expression($1, EX_SUB,  $3);  }
        | expr '-' IDENT        { $$ = new Expression($1, EX_SUB,  $3);  }
        | expr '*' IDENT        { $$ = new Expression($1, EX_MULT, $3); }
        | expr '*' IDENT        { $$ = new Expression($1, EX_MULT, $3); }
        | expr '/' IDENT        { $$ = new Expression($1, EX_DIV,  $3);  }
        | expr '/' IDENT        { $$ = new Expression($1, EX_DIV,  $3);  }
        | expr '%' IDENT        { $$ = new Expression($1, EX_MOD,  $3);  }
        | expr '%' IDENT        { $$ = new Expression($1, EX_MOD,  $3);  }
        ;
        ;
value
value
        : expr                  { $$ = new Operand($1); }
        : expr                  { $$ = new Operand($1); }
        ;
        ;
imm
imm
        :  '#' value            { $$ = $2->Immediate(); }
        :  '#' value            { $$ = $2->Immediate(); }
        ;
        ;
RR      : _RR                   { $$ = new Operand(REG_RR, $1); }       ;
RR      : _RR                   { $$ = new Operand(REG_RR, $1); }       ;
RU      : _RU                   { $$ = new Operand(REG_RU, $1); }       ;
RU      : _RU                   { $$ = new Operand(REG_RU, $1); }       ;
RS      : _RS                   { $$ = new Operand(REG_RS, $1); }       ;
RS      : _RS                   { $$ = new Operand(REG_RS, $1); }       ;
R       : _R                    { $$ = new Operand(REG_R,  $1); }       ;
R       : _R                    { $$ = new Operand(REG_R,  $1); }       ;
cRR     : '(' RR ')'            { $$ = $2->Content();           }       ;
cRR     : '(' RR ')'            { $$ = $2->Content();           }       ;
RRZ     : _RRZ                  { $$ = new Operand(COND_Z, $1); }       ;
RRZ     : _RRZ                  { $$ = new Operand(COND_Z, $1); }       ;
RRNZ    : _RRNZ                 { $$ = new Operand(COND_NZ, $1); }      ;
RRNZ    : _RRNZ                 { $$ = new Operand(COND_NZ, $1); }      ;
LL      : _LL                   { $$ = new Operand(REG_LL, $1); }       ;
LL      : _LL                   { $$ = new Operand(REG_LL, $1); }       ;
LU      : _LU                   { $$ = new Operand(REG_LU, $1); }       ;
LU      : _LU                   { $$ = new Operand(REG_LU, $1); }       ;
LS      : _LS                   { $$ = new Operand(REG_LS, $1); }       ;
LS      : _LS                   { $$ = new Operand(REG_LS, $1); }       ;
L       : _L                    { $$ = new Operand(REG_L,  $1); }       ;
L       : _L                    { $$ = new Operand(REG_L,  $1); }       ;
cLL     : '(' LL ')'            { $$ = $2->Content();           }       ;
cLL     : '(' LL ')'            { $$ = $2->Content();           }       ;
SP      : _SP                   { $$ = new Operand(REG_SP,  $1); }      ;
SP      : _SP                   { $$ = new Operand(REG_SP,  $1); }      ;
dRR     : '-' '(' RR ')'        { $$ = $3->PreDec();             }      ;
dRR     : '-' '(' RR ')'        { $$ = $3->PreDec();             }      ;
dLL     : '-' '(' LL ')'        { $$ = $3->PreDec();             }      ;
dLL     : '-' '(' LL ')'        { $$ = $3->PreDec();             }      ;
dSP     : '-' '(' SP ')'        { $$ = $3->PreDec();             }      ;
dSP     : '-' '(' SP ')'        { $$ = $3->PreDec();             }      ;
RRi     : '(' RR ')' '+'        { $$ = $2->PostInc();            }      ;
RRi     : '(' RR ')' '+'        { $$ = $2->PostInc();            }      ;
LLi     : '(' LL ')' '+'        { $$ = $2->PostInc();            }      ;
LLi     : '(' LL ')' '+'        { $$ = $2->PostInc();            }      ;
SPi     : '(' SP ')' '+'        { $$ = $2->PostInc();            }      ;
SPi     : '(' SP ')' '+'        { $$ = $2->PostInc();            }      ;
oSP     : value '(' SP ')'      { $$ = $3->Offset($1);           }      ;
oSP     : value '(' SP ')'      { $$ = $3->Offset($1);           }      ;
port    : '(' value ')'         { $$ = $2->Port();               }      ;
port    : '(' value ')'         { $$ = $2->Port();               }      ;
addr    : '(' value ')'         { $$ = $2->AbsAddr();            }      ;
addr    : '(' value ')'         { $$ = $2->AbsAddr();            }      ;
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
opcode
opcode
: _BYTE value           { $$ = new Opcode(H_BYTE, 0x00, $1, $2);       }
: _BYTE value           { $$ = new Opcode(H_BYTE, 0x00, $1, $2);       }
| _WORD value           { $$ = new Opcode(H_WORD, 0x00, $1, $2);       }
| _WORD value           { $$ = new Opcode(H_WORD, 0x00, $1, $2);       }
| HALT                  { $$ = new Opcode(H_NONE,   0x00, $1);         }
| HALT                  { $$ = new Opcode(H_NONE,   0x00, $1);         }
| NOP                   { $$ = new Opcode(H_NONE,   0x01, $1);         }
| NOP                   { $$ = new Opcode(H_NONE,   0x01, $1);         }
| JMP  value            { $$ = new Opcode(H_WORD,   0x02, $1, $2);     }
| JMP  value            { $$ = new Opcode(H_WORD,   0x02, $1, $2);     }
| JMP  RRNZ ',' value   { $$ = new Opcode(H_WORD,   0x03, $1, $2, $4); }
| JMP  RRNZ ',' value   { $$ = new Opcode(H_WORD,   0x03, $1, $2, $4); }
| JMP  RRZ  ',' value   { $$ = new Opcode(H_WORD,   0x04, $1, $2, $4); }
| JMP  RRZ  ',' value   { $$ = new Opcode(H_WORD,   0x04, $1, $2, $4); }
| CALL value            { $$ = new Opcode(H_WORD,   0x05, $1, $2);     }
| CALL value            { $$ = new Opcode(H_WORD,   0x05, $1, $2);     }
| CALL '(' RR ')'       { $$ = new Opcode(H_NONE,   0x06, $1, $3);     }
| CALL '(' RR ')'       { $$ = new Opcode(H_NONE,   0x06, $1, $3);     }
| RET                   { $$ = new Opcode(H_NONE,   0x07, $1);         }
| RET                   { $$ = new Opcode(H_NONE,   0x07, $1);         }
| MOVE SPi  ',' RR      { $$ = new Opcode(H_NONE,   0x08, $1, $2, $4); }
| MOVE SPi  ',' RR      { $$ = new Opcode(H_NONE,   0x08, $1, $2, $4); }
| MOVE SPi  ',' RS      { $$ = new Opcode(H_NONE,   0x09, $1, $2, $4); }
| MOVE SPi  ',' RS      { $$ = new Opcode(H_NONE,   0x09, $1, $2, $4); }
| MOVE SPi  ',' RU      { $$ = new Opcode(H_NONE,   0x0A, $1, $2, $4); }
| MOVE SPi  ',' RU      { $$ = new Opcode(H_NONE,   0x0A, $1, $2, $4); }
| MOVE SPi  ',' LL      { $$ = new Opcode(H_NONE,   0x0B, $1, $2, $4); }
| MOVE SPi  ',' LL      { $$ = new Opcode(H_NONE,   0x0B, $1, $2, $4); }
| MOVE SPi  ',' LS      { $$ = new Opcode(H_NONE,   0x0C, $1, $2, $4); }
| MOVE SPi  ',' LS      { $$ = new Opcode(H_NONE,   0x0C, $1, $2, $4); }
| MOVE SPi  ',' LU      { $$ = new Opcode(H_NONE,   0x0D, $1, $2, $4); }
| MOVE SPi  ',' LU      { $$ = new Opcode(H_NONE,   0x0D, $1, $2, $4); }
| MOVE RR   ',' dSP     { $$ = new Opcode(H_NONE,   0x0E, $1, $2, $4); }
| MOVE RR   ',' dSP     { $$ = new Opcode(H_NONE,   0x0E, $1, $2, $4); }
| MOVE R    ',' dSP     { $$ = new Opcode(H_NONE,   0x0F, $1, $2, $4); }
| MOVE R    ',' dSP     { $$ = new Opcode(H_NONE,   0x0F, $1, $2, $4); }
| AND  RR   ',' imm     { $$ = new Opcode(H_uBW,    0x10, $1, $2, $4); }
| AND  RR   ',' imm     { $$ = new Opcode(H_uBW,    0x10, $1, $2, $4); }
| OR   RR   ',' imm     { $$ = new Opcode(H_uBW,    0x12, $1, $2, $4); }
| OR   RR   ',' imm     { $$ = new Opcode(H_uBW,    0x12, $1, $2, $4); }
| XOR  RR   ',' imm     { $$ = new Opcode(H_uBW,    0x14, $1, $2, $4); }
| XOR  RR   ',' imm     { $$ = new Opcode(H_uBW,    0x14, $1, $2, $4); }
| SEQ  RR   ',' imm     { $$ = new Opcode(H_sBW,    0x16, $1, $2, $4); }
| SEQ  RR   ',' imm     { $$ = new Opcode(H_sBW,    0x16, $1, $2, $4); }
| SNE  RR   ',' imm     { $$ = new Opcode(H_sBW,    0x18, $1, $2, $4); }
| SNE  RR   ',' imm     { $$ = new Opcode(H_sBW,    0x18, $1, $2, $4); }
| SGE  RR   ',' imm     { $$ = new Opcode(H_sBW,    0x1A, $1, $2, $4); }
| SGE  RR   ',' imm     { $$ = new Opcode(H_sBW,    0x1A, $1, $2, $4); }
| SGT  RR   ',' imm     { $$ = new Opcode(H_sBW,    0x1C, $1, $2, $4); }
| SGT  RR   ',' imm     { $$ = new Opcode(H_sBW,    0x1C, $1, $2, $4); }
| SLE  RR   ',' imm     { $$ = new Opcode(H_sBW,    0x1E, $1, $2, $4); }
| SLE  RR   ',' imm     { $$ = new Opcode(H_sBW,    0x1E, $1, $2, $4); }
| SLT  RR   ',' imm     { $$ = new Opcode(H_sBW,    0x20, $1, $2, $4); }
| SLT  RR   ',' imm     { $$ = new Opcode(H_sBW,    0x20, $1, $2, $4); }
| SHS  RR   ',' imm     { $$ = new Opcode(H_uBW,    0x22, $1, $2, $4); }
| SHS  RR   ',' imm     { $$ = new Opcode(H_uBW,    0x22, $1, $2, $4); }
| SHI  RR   ',' imm     { $$ = new Opcode(H_uBW,    0x24, $1, $2, $4); }
| SHI  RR   ',' imm     { $$ = new Opcode(H_uBW,    0x24, $1, $2, $4); }
| SLS  RR   ',' imm     { $$ = new Opcode(H_uBW,    0x26, $1, $2, $4); }
| SLS  RR   ',' imm     { $$ = new Opcode(H_uBW,    0x26, $1, $2, $4); }
| SLO  RR   ',' imm     { $$ = new Opcode(H_uBW,    0x28, $1, $2, $4); }
| SLO  RR   ',' imm     { $$ = new Opcode(H_uBW,    0x28, $1, $2, $4); }
| ADD  SP   ',' imm     { $$ = new Opcode(H_uBW,    0x2A, $1, $2, $4); }
| ADD  SP   ',' imm     { $$ = new Opcode(H_uBW,    0x2A, $1, $2, $4); }
| CLRW dSP              { $$ = new Opcode(H_NONE,   0x2C, $1, $2);     }
| CLRW dSP              { $$ = new Opcode(H_NONE,   0x2C, $1, $2);     }
| CLRB dSP              { $$ = new Opcode(H_NONE,   0x2D, $1, $2);     }
| CLRB dSP              { $$ = new Opcode(H_NONE,   0x2D, $1, $2);     }
| IN   port ',' RU      { $$ = new Opcode(H_PORT,   0x2E, $1, $2, $4); }
| IN   port ',' RU      { $$ = new Opcode(H_PORT,   0x2E, $1, $2, $4); }
| OUT  R    ',' port    { $$ = new Opcode(H_PORT,   0x2F, $1, $2, $4); }
| OUT  R    ',' port    { $$ = new Opcode(H_PORT,   0x2F, $1, $2, $4); }
| AND  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x30, $1, $2, $4); }
| AND  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x30, $1, $2, $4); }
| OR   LL   ',' RR      { $$ = new Opcode(H_NONE,   0x31, $1, $2, $4); }
| OR   LL   ',' RR      { $$ = new Opcode(H_NONE,   0x31, $1, $2, $4); }
| XOR  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x32, $1, $2, $4); }
| XOR  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x32, $1, $2, $4); }
| SEQ  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x33, $1, $2, $4); }
| SEQ  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x33, $1, $2, $4); }
| SNE  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x34, $1, $2, $4); }
| SNE  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x34, $1, $2, $4); }
| SGE  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x35, $1, $2, $4); }
| SGE  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x35, $1, $2, $4); }
| SGT  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x36, $1, $2, $4); }
| SGT  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x36, $1, $2, $4); }
| SLE  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x37, $1, $2, $4); }
| SLE  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x37, $1, $2, $4); }
| SLT  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x38, $1, $2, $4); }
| SLT  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x38, $1, $2, $4); }
| SHS  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x39, $1, $2, $4); }
| SHS  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x39, $1, $2, $4); }
| SHI  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x3A, $1, $2, $4); }
| SHI  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x3A, $1, $2, $4); }
| SLS  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x3B, $1, $2, $4); }
| SLS  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x3B, $1, $2, $4); }
| SLO  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x3C, $1, $2, $4); }
| SLO  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x3C, $1, $2, $4); }
| LNOT RR               { $$ = new Opcode(H_NONE,   0x3D, $1, $2);     }
| LNOT RR               { $$ = new Opcode(H_NONE,   0x3D, $1, $2);     }
| NEG  RR               { $$ = new Opcode(H_NONE,   0x3E, $1, $2);     }
| NEG  RR               { $$ = new Opcode(H_NONE,   0x3E, $1, $2);     }
| NOT  RR               { $$ = new Opcode(H_NONE,   0x3F, $1, $2);     }
| NOT  RR               { $$ = new Opcode(H_NONE,   0x3F, $1, $2);     }
| MOVE LL   ',' RR      { $$ = new Opcode(H_NONE,   0x40, $1, $2, $4); }
| MOVE LL   ',' RR      { $$ = new Opcode(H_NONE,   0x40, $1, $2, $4); }
| MOVE LL   ',' cRR     { $$ = new Opcode(H_NONE,   0x41, $1, $2, $4); }
| MOVE LL   ',' cRR     { $$ = new Opcode(H_NONE,   0x41, $1, $2, $4); }
| MOVE L    ',' cRR     { $$ = new Opcode(H_NONE,   0x42, $1, $2, $4); }
| MOVE L    ',' cRR     { $$ = new Opcode(H_NONE,   0x42, $1, $2, $4); }
| MOVE RR   ',' LL      { $$ = new Opcode(H_NONE,   0x43, $1, $2, $4); }
| MOVE RR   ',' LL      { $$ = new Opcode(H_NONE,   0x43, $1, $2, $4); }
| MOVE RR   ',' cLL     { $$ = new Opcode(H_NONE,   0x44, $1, $2, $4); }
| MOVE RR   ',' cLL     { $$ = new Opcode(H_NONE,   0x44, $1, $2, $4); }
| MOVE R    ',' cLL     { $$ = new Opcode(H_NONE,   0x45, $1, $2, $4); }
| MOVE R    ',' cLL     { $$ = new Opcode(H_NONE,   0x45, $1, $2, $4); }
| MOVE cRR  ',' RR      { $$ = new Opcode(H_NONE,   0x46, $1, $2, $4); }
| MOVE cRR  ',' RR      { $$ = new Opcode(H_NONE,   0x46, $1, $2, $4); }
| MOVE cRR  ',' RS      { $$ = new Opcode(H_NONE,   0x47, $1, $2, $4); }
| MOVE cRR  ',' RS      { $$ = new Opcode(H_NONE,   0x47, $1, $2, $4); }
| MOVE cRR  ',' RU      { $$ = new Opcode(H_NONE,   0x48, $1, $2, $4); }
| MOVE cRR  ',' RU      { $$ = new Opcode(H_NONE,   0x48, $1, $2, $4); }
| MOVE addr ',' RR      { $$ = new Opcode(H_WORD,   0x49, $1, $2, $4); }
| MOVE addr ',' RR      { $$ = new Opcode(H_WORD,   0x49, $1, $2, $4); }
| MOVE addr ',' RS      { $$ = new Opcode(H_WORD,   0x4A, $1, $2, $4); }
| MOVE addr ',' RS      { $$ = new Opcode(H_WORD,   0x4A, $1, $2, $4); }
| MOVE addr ',' RU      { $$ = new Opcode(H_WORD,   0x4B, $1, $2, $4); }
| MOVE addr ',' RU      { $$ = new Opcode(H_WORD,   0x4B, $1, $2, $4); }
| MOVE addr ',' LL      { $$ = new Opcode(H_WORD,   0x4C, $1, $2, $4); }
| MOVE addr ',' LL      { $$ = new Opcode(H_WORD,   0x4C, $1, $2, $4); }
| MOVE addr ',' LS      { $$ = new Opcode(H_WORD,   0x4D, $1, $2, $4); }
| MOVE addr ',' LS      { $$ = new Opcode(H_WORD,   0x4D, $1, $2, $4); }
| MOVE addr ',' LU      { $$ = new Opcode(H_WORD,   0x4E, $1, $2, $4); }
| MOVE addr ',' LU      { $$ = new Opcode(H_WORD,   0x4E, $1, $2, $4); }
| MOVE RR   ',' SP      { $$ = new Opcode(H_NONE,   0x4F, $1, $2, $4); }
| MOVE RR   ',' SP      { $$ = new Opcode(H_NONE,   0x4F, $1, $2, $4); }
| LSL  RR   ',' imm     { $$ = new Opcode(H_BYTE,   0x52, $1, $2, $4); }
| LSL  RR   ',' imm     { $$ = new Opcode(H_BYTE,   0x52, $1, $2, $4); }
| ASR  RR   ',' imm     { $$ = new Opcode(H_BYTE,   0x53, $1, $2, $4); }
| ASR  RR   ',' imm     { $$ = new Opcode(H_BYTE,   0x53, $1, $2, $4); }
| LSR  RR   ',' imm     { $$ = new Opcode(H_BYTE,   0x54, $1, $2, $4); }
| LSR  RR   ',' imm     { $$ = new Opcode(H_BYTE,   0x54, $1, $2, $4); }
| LSL  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x55, $1, $2, $4); }
| LSL  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x55, $1, $2, $4); }
| ASR  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x56, $1, $2, $4); }
| ASR  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x56, $1, $2, $4); }
| LSR  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x57, $1, $2, $4); }
| LSR  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x57, $1, $2, $4); }
| ADD  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x58, $1, $2, $4); }
| ADD  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x58, $1, $2, $4); }
| SUB  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x59, $1, $2, $4); }
| SUB  LL   ',' RR      { $$ = new Opcode(H_NONE,   0x59, $1, $2, $4); }
| MOVE RR   ',' addr    { $$ = new Opcode(H_WORD,   0x5A, $1, $2, $4); }
| MOVE RR   ',' addr    { $$ = new Opcode(H_WORD,   0x5A, $1, $2, $4); }
| MOVE R    ',' addr    { $$ = new Opcode(H_WORD,   0x5B, $1, $2, $4); }
| MOVE R    ',' addr    { $$ = new Opcode(H_WORD,   0x5B, $1, $2, $4); }
| MOVE RR   ',' oSP     { $$ = new Opcode(H_uBW,    0x5C, $1, $2, $4); }
| MOVE RR   ',' oSP     { $$ = new Opcode(H_uBW,    0x5C, $1, $2, $4); }
| MOVE R    ',' oSP     { $$ = new Opcode(H_uBW,    0x5E, $1, $2, $4); }
| MOVE R    ',' oSP     { $$ = new Opcode(H_uBW,    0x5E, $1, $2, $4); }
| MOVE oSP  ',' RR      { $$ = new Opcode(H_uBW,    0x60, $1, $2, $4); }
| MOVE oSP  ',' RR      { $$ = new Opcode(H_uBW,    0x60, $1, $2, $4); }
| MOVE oSP  ',' RS      { $$ = new Opcode(H_uBW,    0x62, $1, $2, $4); }
| MOVE oSP  ',' RS      { $$ = new Opcode(H_uBW,    0x62, $1, $2, $4); }
| MOVE oSP  ',' RU      { $$ = new Opcode(H_uBW,    0x64, $1, $2, $4); }
| MOVE oSP  ',' RU      { $$ = new Opcode(H_uBW,    0x64, $1, $2, $4); }
| MOVE oSP  ',' LL      { $$ = new Opcode(H_uBW,    0x66, $1, $2, $4); }
| MOVE oSP  ',' LL      { $$ = new Opcode(H_uBW,    0x66, $1, $2, $4); }
| MOVE oSP  ',' LS      { $$ = new Opcode(H_uBW,    0x68, $1, $2, $4); }
| MOVE oSP  ',' LS      { $$ = new Opcode(H_uBW,    0x68, $1, $2, $4); }
| MOVE oSP  ',' LU      { $$ = new Opcode(H_uBW,    0x6A, $1, $2, $4); }
| MOVE oSP  ',' LU      { $$ = new Opcode(H_uBW,    0x6A, $1, $2, $4); }
| LEA  oSP  ',' RR      { $$ = new Opcode(H_uBW,    0x6C, $1, $2, $4); }
| LEA  oSP  ',' RR      { $$ = new Opcode(H_uBW,    0x6C, $1, $2, $4); }
| MOVE dRR  ',' dLL     { $$ = new Opcode(H_NONE,   0x6E, $1, $2, $4); }
| MOVE dRR  ',' dLL     { $$ = new Opcode(H_NONE,   0x6E, $1, $2, $4); }
| MOVE RRi  ',' LLi     { $$ = new Opcode(H_NONE,   0x6F, $1, $2, $4); }
| MOVE RRi  ',' LLi     { $$ = new Opcode(H_NONE,   0x6F, $1, $2, $4); }
| MUL_IS                { $$ = new Opcode(H_NONE,   0x70, $1);         }
| MUL_IS                { $$ = new Opcode(H_NONE,   0x70, $1);         }
| MUL_IU                { $$ = new Opcode(H_NONE,   0x71, $1);         }
| MUL_IU                { $$ = new Opcode(H_NONE,   0x71, $1);         }
| DIV_IS                { $$ = new Opcode(H_NONE,   0x72, $1);         }
| DIV_IS                { $$ = new Opcode(H_NONE,   0x72, $1);         }
| DIV_IU                { $$ = new Opcode(H_NONE,   0x73, $1);         }
| DIV_IU                { $$ = new Opcode(H_NONE,   0x73, $1);         }
| MD_STP                { $$ = new Opcode(H_NONE,   0x74, $1);         }
| MD_STP                { $$ = new Opcode(H_NONE,   0x74, $1);         }
| MD_FIN                { $$ = new Opcode(H_NONE,   0x75, $1);         }
| MD_FIN                { $$ = new Opcode(H_NONE,   0x75, $1);         }
| MOD_FIN               { $$ = new Opcode(H_NONE,   0x76, $1);         }
| MOD_FIN               { $$ = new Opcode(H_NONE,   0x76, $1);         }
| EI                    { $$ = new Opcode(H_NONE,   0x77, $1);         }
| EI                    { $$ = new Opcode(H_NONE,   0x77, $1);         }
| RETI                  { $$ = new Opcode(H_NONE,   0x78, $1);         }
| RETI                  { $$ = new Opcode(H_NONE,   0x78, $1);         }
| DI                    { $$ = new Opcode(H_NONE,   0x79, $1);         }
| DI                    { $$ = new Opcode(H_NONE,   0x79, $1);         }
| ADD  RR   ',' imm     { $$ = new Opcode(H_uQBW,   0xA0, $1, $2, $4); }
| ADD  RR   ',' imm     { $$ = new Opcode(H_uQBW,   0xA0, $1, $2, $4); }
| SUB  RR   ',' imm     { $$ = new Opcode(H_uQBW,   0xB0, $1, $2, $4); }
| SUB  RR   ',' imm     { $$ = new Opcode(H_uQBW,   0xB0, $1, $2, $4); }
| MOVE imm  ',' RR      { $$ = new Opcode(H_sQBW,   0xC0, $1, $2, $4); }
| MOVE imm  ',' RR      { $$ = new Opcode(H_sQBW,   0xC0, $1, $2, $4); }
| SEQ  LL   ',' imm     { $$ = new Opcode(H_sQBW,   0xD0, $1, $2, $4); }
| SEQ  LL   ',' imm     { $$ = new Opcode(H_sQBW,   0xD0, $1, $2, $4); }
| MOVE imm  ',' LL      { $$ = new Opcode(H_sQBW,   0xE0, $1, $2, $4); }
| MOVE imm  ',' LL      { $$ = new Opcode(H_sQBW,   0xE0, $1, $2, $4); }
;
;
// Fx mapped from 8X..EX
// Fx mapped from 8X..EX
%%
%%
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void Line::Add(Opcode * opc)
void Line::Add(Opcode * opc)
{
{
   assert(opc);
   assert(opc);
Line * l = new Line(opc);
Line * l = new Line(opc);
   if (first == 0)
   if (first == 0)
      {
      {
        assert(last == 0);
        assert(last == 0);
        first = last = l;
        first = last = l;
      }
      }
   else
   else
      {
      {
        assert(last->tail == 0);
        assert(last->tail == 0);
        last->tail = l;
        last->tail = l;
        last = l;
        last = l;
      }
      }
   PC += opc->GetLength();
   PC += opc->GetLength();
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
Symbol * Symbol::symbols = 0;
Symbol * Symbol::symbols = 0;
Symbol * Symbol::current = 0;
Symbol * Symbol::current = 0;
Line * Line::first = 0;
Line * Line::first = 0;
Line * Line::last  = 0;
Line * Line::last  = 0;
void Symbol::Add(const char * id, Expression * expr, bool lab, bool reloc)
void Symbol::Add(const char * id, Expression * expr, bool lab, bool reloc)
{
{
   for (Symbol * s = symbols; s; s = s->tail)
   for (Symbol * s = symbols; s; s = s->tail)
       {
       {
         if (!strcmp(id, s->identifier))
         if (!strcmp(id, s->identifier))
            {
            {
              fprintf(stderr, "Error: Symbol %s already defined\n", id);
              fprintf(stderr, "Error: Symbol %s already defined\n", id);
              return;
              return;
            }
            }
         if (s->tail == 0)
         if (s->tail == 0)
            {
            {
              s->tail = new Symbol(id, expr, lab, reloc);
              s->tail = new Symbol(id, expr, lab, reloc);
              return;
              return;
            }
            }
       }
       }
   symbols = new Symbol(id, expr, lab, reloc);
   symbols = new Symbol(id, expr, lab, reloc);
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int Operand::GetLength(OP_HOW how)
int Operand::GetLength(OP_HOW how)
{
{
   // how may apply to this or the other argument!
   // how may apply to this or the other argument!
   //
   //
   if (offset)   return offset->GetLength(how);
   if (offset)   return offset->GetLength(how);
   if (base != EXPR)    return 0;
   if (base != EXPR)    return 0;
   assert(expr);
   assert(expr);
   switch(how)
   switch(how)
      {
      {
        case H_BYTE:
        case H_BYTE:
        case H_PORT: return 1;
        case H_PORT: return 1;
        case H_WORD: return 2;
        case H_WORD: return 2;
      }
      }
   if (expr->UsesName())   return 2;   // not yet known
   if (expr->UsesName())   return 2;   // not yet known
   if (GetValue() < 0)    switch(how)
   if (GetValue() < 0)    switch(how)
      {
      {
        case H_uBW:
        case H_uBW:
        case H_uQBW:   return 2;
        case H_uQBW:   return 2;
        case H_sBW:    if (GetValue() >= -128)   return 1;
        case H_sBW:    if (GetValue() >= -128)   return 1;
                       return 2;
                       return 2;
        case H_sQBW:   if (GetValue() >= -8)     return 0;
        case H_sQBW:   if (GetValue() >= -8)     return 0;
                       if (GetValue() >= -128)   return 1;
                       if (GetValue() >= -128)   return 1;
                       return 2;
                       return 2;
        default:        fprintf(stderr, "HOW = %d\n", how);
        default:        fprintf(stderr, "HOW = %d\n", how);
                        assert(0 && "Bad how");
                        assert(0 && "Bad how");
      }
      }
   // here GetValue() >= 0
   // here GetValue() >= 0
   switch(how)
   switch(how)
      {
      {
        case H_uBW:    if (GetValue() <= 255)   return 1;
        case H_uBW:    if (GetValue() <= 255)   return 1;
                       return 2;
                       return 2;
        case H_sBW:    if (GetValue() <= 127)   return 1;
        case H_sBW:    if (GetValue() <= 127)   return 1;
                       return 2;
                       return 2;
        case H_uQBW:   if (GetValue() <= 15)    return 0;
        case H_uQBW:   if (GetValue() <= 15)    return 0;
                       if (GetValue() <= 255)   return 1;
                       if (GetValue() <= 255)   return 1;
                       return 2;
                       return 2;
        case H_sQBW:   if (GetValue() <= 7)     return 0;
        case H_sQBW:   if (GetValue() <= 7)     return 0;
                       if (GetValue() <= 127)   return 1;
                       if (GetValue() <= 127)   return 1;
                       return 2;
                       return 2;
        default:        fprintf(stderr, "HOW = %d\n", how);
        default:        fprintf(stderr, "HOW = %d\n", how);
                        assert(0 && "Bad how");
                        assert(0 && "Bad how");
      }
      }
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int Opcode::GetLength() const
int Opcode::GetLength() const
{
{
int base_len = 1;
int base_len = 1;
   assert(op_text);
   assert(op_text);
   if (*op_text == '.')   base_len = 0;
   if (*op_text == '.')   base_len = 0;
int op1_len  = 0;
int op1_len  = 0;
   if (op_1)   op1_len = op_1->GetLength(op_how);
   if (op_1)   op1_len = op_1->GetLength(op_how);
int op2_len  = 0;
int op2_len  = 0;
   if (op_2)   op2_len = op_2->GetLength(op_how);
   if (op_2)   op2_len = op_2->GetLength(op_how);
   assert(!op1_len || !op2_len);
   assert(!op1_len || !op2_len);
   return base_len + op1_len + op2_len;
   return base_len + op1_len + op2_len;
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void Line::List()
void Line::List()
{
{
   PC = 0;
   PC = 0;
   Symbol::Reset();
   Symbol::Reset();
   for (Line * l = first; l; l = l->tail)
   for (Line * l = first; l; l = l->tail)
       {
       {
         Symbol::Advance(PC);
         Symbol::Advance(PC);
         assert(l->opcode);
         assert(l->opcode);
         assert(l->pc == PC);
         assert(l->pc == PC);
         PC += l->opcode->List(PC);
         PC += l->opcode->List(PC);
       }
       }
   Symbol::Advance(PC);
   Symbol::Advance(PC);
   fprintf(stderr, "Bytes = %d (0x%X)\n", PC, PC);
   fprintf(stderr, "Bytes = %d (0x%X)\n", PC, PC);
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void Symbol::ListNonlabels()
void Symbol::ListNonlabels()
{
{
   for (Symbol * s = symbols; s; s = s->tail)
   for (Symbol * s = symbols; s; s = s->tail)
       {
       {
         if (s->label)   continue;
         if (s->label)   continue;
         assert(s->identifier);
         assert(s->identifier);
         fprintf(list, "%s\t= %d\n",
         fprintf(list, "%s\t= %d\n",
                 s->identifier, s->expr->GetValue() & 0xFFFF);
                 s->identifier, s->expr->GetValue() & 0xFFFF);
       }
       }
   fprintf(list, "\n");
   fprintf(list, "\n");
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void Symbol::PrintSymbols()
void Symbol::PrintSymbols()
{
{
   for (Symbol * s = symbols; s; s = s->tail)
   for (Symbol * s = symbols; s; s = s->tail)
       {
       {
         if (!s->label)   continue;
         if (!s->label)   continue;
         assert(s->identifier);
         assert(s->identifier);
         fprintf(sym, "%4.4X %s\n",
         fprintf(sym, "%4.4X %s\n",
                 s->expr->GetValue() & 0xFFFF, s->identifier);
                 s->expr->GetValue() & 0xFFFF, s->identifier);
       }
       }
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int Symbol::GetValue(const char * id)
int Symbol::GetValue(const char * id)
{
{
   for (Symbol * s = symbols; s; s = s->tail)
   for (Symbol * s = symbols; s; s = s->tail)
       {
       {
         assert(s->identifier);
         assert(s->identifier);
         assert(s->expr);
         assert(s->expr);
         if (strcmp(id, s->identifier))   continue;
         if (strcmp(id, s->identifier))   continue;
         return 0xFFFF & Reloc(s->reloc, s->expr->GetValue());
         return 0xFFFF & Reloc(s->reloc, s->expr->GetValue());
       }
       }
   fprintf(stderr, "Symbol %s not defined\n", id);
   fprintf(stderr, "Symbol %s not defined\n", id);
   assert(0 && "Symbol Not Defined");
   assert(0 && "Symbol Not Defined");
   return 0;
   return 0;
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int Operand::GetValue()
int Operand::GetValue()
{
{
   assert(expr);
   assert(expr);
   return expr->GetValue();
   return expr->GetValue();
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int Expression::ListBase() const
int Expression::ListBase() const
{
{
int ret = 0;
int ret = 0;
   if (ex)   ret += ex->ListBase();
   if (ex)   ret += ex->ListBase();
   switch(how)
   switch(how)
      {
      {
        case EX_NAME:
        case EX_NAME:
             assert(name);
             assert(name);
             assert(!ex);
             assert(!ex);
             return fprintf(list, "%s", name);
             return fprintf(list, "%s", name);
        case EX_NUMBER:
        case EX_NUMBER:
             assert(!name);
             assert(!name);
             assert(!ex);
             assert(!ex);
             return fprintf(list, "%d", 0xFFFF & number);
             return fprintf(list, "%d", 0xFFFF & number);
        case EX_ADD:
        case EX_ADD:
             assert(ex);
             assert(ex);
             ret += fprintf(list, " + ");
             ret += fprintf(list, " + ");
             break;
             break;
        case EX_SUB:
        case EX_SUB:
             assert(ex);
             assert(ex);
             ret += fprintf(list, " - ");
             ret += fprintf(list, " - ");
             break;
             break;
        case EX_MULT:
        case EX_MULT:
             assert(ex);
             assert(ex);
             ret += fprintf(list, " * ");
             ret += fprintf(list, " * ");
             break;
             break;
        case EX_DIV:
        case EX_DIV:
             assert(ex);
             assert(ex);
             ret += fprintf(list, " / ");
             ret += fprintf(list, " / ");
             break;
             break;
        case EX_MOD:
        case EX_MOD:
             assert(ex);
             assert(ex);
             ret += fprintf(list, " / ");
             ret += fprintf(list, " / ");
             break;
             break;
        default: assert(0);
        default: assert(0);
      }
      }
   if (name)   ret += fprintf(list, "%s", name);
   if (name)   ret += fprintf(list, "%s", name);
   else        ret += fprintf(list, "%d", number);
   else        ret += fprintf(list, "%d", number);
   return ret;
   return ret;
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int Expression::GetValue() const
int Expression::GetValue() const
{
{
int ret;
int ret;
int my_val = number;
int my_val = number;
   if (name)   my_val = Symbol::GetValue(name);
   if (name)   my_val = Symbol::GetValue(name);
   switch(how)
   switch(how)
      {
      {
        case EX_NAME:
        case EX_NAME:
             assert(name);
             assert(name);
             assert(!ex);
             assert(!ex);
             ret = 0xFFFF & my_val;
             ret = 0xFFFF & my_val;
             break;
             break;
        case EX_NUMBER:
        case EX_NUMBER:
             assert(!name);
             assert(!name);
             assert(!ex);
             assert(!ex);
             ret = 0xFFFF & my_val;
             ret = 0xFFFF & my_val;
             break;
             break;
        case EX_ADD:
        case EX_ADD:
             assert(ex);
             assert(ex);
             ret = 0xFFFF & (ex->GetValue() + my_val);
             ret = 0xFFFF & (ex->GetValue() + my_val);
             break;
             break;
        case EX_SUB:
        case EX_SUB:
             assert(ex);
             assert(ex);
             ret = 0xFFFF & (ex->GetValue() - my_val);
             ret = 0xFFFF & (ex->GetValue() - my_val);
             break;
             break;
        case EX_MULT:
        case EX_MULT:
             assert(ex);
             assert(ex);
             ret = 0xFFFF & (ex->GetValue() * my_val);
             ret = 0xFFFF & (ex->GetValue() * my_val);
             break;
             break;
        case EX_DIV:
        case EX_DIV:
             assert(ex);
             assert(ex);
             assert(0xFFFF & my_val);
             assert(0xFFFF & my_val);
             ret = 0xFFFF & (ex->GetValue() / my_val);
             ret = 0xFFFF & (ex->GetValue() / my_val);
             break;
             break;
        case EX_MOD:
        case EX_MOD:
             assert(ex);
             assert(ex);
             assert(0xFFFF & my_val);
             assert(0xFFFF & my_val);
             ret = 0xFFFF & (ex->GetValue() % my_val);
             ret = 0xFFFF & (ex->GetValue() % my_val);
             break;
             break;
        default: assert(0);
        default: assert(0);
      }
      }
   return ret;
   return ret;
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void Symbol::Advance(int pc)
void Symbol::Advance(int pc)
{
{
   for (; current; current = current->tail)
   for (; current; current = current->tail)
      {
      {
        if (!current->label)   continue;
        if (!current->label)   continue;
        assert(current->expr);
        assert(current->expr);
        int nxt = current->expr->GetValue();
        int nxt = current->expr->GetValue();
        if (nxt > pc)   return;
        if (nxt > pc)   return;
        if (nxt == pc)
        if (nxt == pc)
           {
           {
             assert(current->identifier);
             assert(current->identifier);
             fprintf(list, "%s:\n", current->identifier);
             fprintf(list, "%s:\n", current->identifier);
             continue;
             continue;
           }
           }
        assert(0);
        assert(0);
      }
      }
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int Opcode::List(int pc)
int Opcode::List(int pc)
{
{
int len = 0;
int len = 0;
int ret = 0;
int ret = 0;
int real_opcode = GetOpcode(ret);
int real_opcode = GetOpcode(ret);
   len += fprintf(list, "   %4.4X: ", 0xFFFF & Reloc(reloc, pc));
   len += fprintf(list, "   %4.4X: ", 0xFFFF & Reloc(reloc, pc));
   assert(op_text);
   assert(op_text);
   if (*op_text != '.')
   if (*op_text != '.')
      {
      {
       len += fprintf(list, "%2.2X ", real_opcode);
       len += fprintf(list, "%2.2X ", real_opcode);
       memory[mem_idx++] = real_opcode;
       memory[mem_idx++] = real_opcode;
      }
      }
   if (op_1)   len += op_1->ListHex(op_how);
   if (op_1)   len += op_1->ListHex(op_how);
   if (op_2)   len += op_2->ListHex(op_how);
   if (op_2)   len += op_2->ListHex(op_how);
   while (len < 20)   len += fprintf(list, " ");
   while (len < 20)   len += fprintf(list, " ");
   len += fprintf(list, "%s ", op_text);
   len += fprintf(list, "%s ", op_text);
   while (len < 22)   len += fprintf(list, " ");
   while (len < 22)   len += fprintf(list, " ");
   if (op_1)   len += op_1->List(op_how);
   if (op_1)   len += op_1->List(op_how);
   if (op_2)
   if (op_2)
      {
      {
        len += fprintf(list, ", ");
        len += fprintf(list, ", ");
        len += op_2->List(op_how);
        len += op_2->List(op_how);
      }
      }
   fprintf(list, "\n");
   fprintf(list, "\n");
   return ret;
   return ret;
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int Operand::ListHex(OP_HOW how)
int Operand::ListHex(OP_HOW how)
{
{
   if (offset)   return offset->ListHex(how);
   if (offset)   return offset->ListHex(how);
   switch(GetLength(how))
   switch(GetLength(how))
      {
      {
        case 0:   return 0;
        case 0:   return 0;
        case 1:   memory[mem_idx++] = GetValue();
        case 1:   memory[mem_idx++] = GetValue();
                  return fprintf(list, "%2.2X ", GetValue() & 0xFF);
                  return fprintf(list, "%2.2X ", GetValue() & 0xFF);
        case 2:   memory[mem_idx++] = GetValue();
        case 2:   memory[mem_idx++] = GetValue();
                  memory[mem_idx++] = GetValue() >> 8;
                  memory[mem_idx++] = GetValue() >> 8;
                  return fprintf(list, "%4.4X ", GetValue() & 0xFFFF);
                  return fprintf(list, "%4.4X ", GetValue() & 0xFFFF);
        default:  assert(0);
        default:  assert(0);
      }
      }
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int Operand::List(OP_HOW how)
int Operand::List(OP_HOW how)
{
{
int len = 0;
int len = 0;
   if (offset)   len += offset->List(how);
   if (offset)   len += offset->List(how);
   switch(attr)
   switch(attr)
      {
      {
        case ATT_NONE:
        case ATT_NONE:
             return len + ListBase(how);
             return len + ListBase(how);
        case ATT_OFFSET:
        case ATT_OFFSET:
             len += fprintf(list, "(");
             len += fprintf(list, "(");
             len += ListBase(how);
             len += ListBase(how);
             return len + fprintf(list, ")");
             return len + fprintf(list, ")");
        case ATT_POSTINC:
        case ATT_POSTINC:
             len += fprintf(list, "(");
             len += fprintf(list, "(");
             len += ListBase(how);
             len += ListBase(how);
             return len + fprintf(list, ")+");
             return len + fprintf(list, ")+");
        case ATT_PREDEC:
        case ATT_PREDEC:
             len += fprintf(list, "-(");
             len += fprintf(list, "-(");
             len += ListBase(how);
             len += ListBase(how);
             return len + fprintf(list, ")");
             return len + fprintf(list, ")");
        case ATT_CONTENT:
        case ATT_CONTENT:
        case ATT_PORT:
        case ATT_PORT:
        case ATT_ADDR:
        case ATT_ADDR:
             len += fprintf(list, "(");
             len += fprintf(list, "(");
             len += ListBase(how);
             len += ListBase(how);
             return len + fprintf(list, ")");
             return len + fprintf(list, ")");
        case ATT_IMM:
        case ATT_IMM:
             len += fprintf(list, "#");
             len += fprintf(list, "#");
             return len + ListBase(how);
             return len + ListBase(how);
        default: assert(0);
        default: assert(0);
      }
      }
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int Operand::ListBase(OP_HOW how)
int Operand::ListBase(OP_HOW how)
{
{
   if (base != EXPR)
   if (base != EXPR)
      {
      {
        assert(op_text);
        assert(op_text);
        return fprintf(list, op_text);
        return fprintf(list, op_text);
     }
     }
   if (expr)   return expr->ListBase();
   if (expr)   return expr->ListBase();
   switch(GetLength(how))
   switch(GetLength(how))
      {
      {
        case 0:  // quick
        case 0:  // quick
        case 1:  return fprintf(list, "%2.2X", GetValue() & 0x0FF);
        case 1:  return fprintf(list, "%2.2X", GetValue() & 0x0FF);
        case 2:  return fprintf(list, "%4.4X", GetValue() & 0x0FFFF);
        case 2:  return fprintf(list, "%4.4X", GetValue() & 0x0FFFF);
      }
      }
   assert(0);
   assert(0);
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int Opcode::GetOpcode(int & len) const
int Opcode::GetOpcode(int & len) const
{
{
   len = GetLength();
   len = GetLength();
   switch(op_how)
   switch(op_how)
      {
      {
        case H_BYTE:
        case H_BYTE:
        case H_WORD: return op_code;
        case H_WORD: return op_code;
        case H_NONE: if (len == 1)    return op_code;
        case H_NONE: if (len == 1)    return op_code;
                     if (len == 2)
                     if (len == 2)
                        {
                        {
                          assert(op_code & 0x0F1 == 0x61);
                          assert(op_code & 0x0F1 == 0x61);
                          return op_code | 0x01;
                          return op_code | 0x01;
                        }
                        }
                     if (len == 3)
                     if (len == 3)
                        {
                        {
                          assert(op_code & 0x0F1 == 0x60);
                          assert(op_code & 0x0F1 == 0x60);
                          return op_code;
                          return op_code;
                        }
                        }
                     assert(0);
                     assert(0);
        case H_PORT: if (len == 2)    return op_code;
        case H_PORT: if (len == 2)    return op_code;
                     assert(0);
                     assert(0);
        case H_sBW:
        case H_sBW:
        case H_uBW:  assert((op_code & 0x01) == 0);
        case H_uBW:  assert((op_code & 0x01) == 0);
                     if (len == 2)   return op_code | 0x01;
                     if (len == 2)   return op_code | 0x01;
                     if (len == 3)   return op_code;
                     if (len == 3)   return op_code;
                     Error();
                     Error();
                     assert(0);
                     assert(0);
        case H_uQBW:
        case H_uQBW:
        case H_sQBW: assert(op_1);
        case H_sQBW: assert(op_1);
                     assert(op_2);
                     assert(op_2);
                     assert((op_code & 0x0F) == 0);
                     assert((op_code & 0x0F) == 0);
                     if (len == 3)   return 0xF0 | op_code >> 3;
                     if (len == 3)   return 0xF0 | op_code >> 3;
                     if (len == 2)   return 0xF1 | op_code >> 3;
                     if (len == 2)   return 0xF1 | op_code >> 3;
                     assert(len == 1);
                     assert(len == 1);
                     if (op_code == 0xC0)   // MOVE #, RR
                     if (op_code == 0xC0)   // MOVE #, RR
                        return op_code | op_1->GetValue() & 0x0F;
                        return op_code | op_1->GetValue() & 0x0F;
                     if (op_code == 0xE0)   // MOVE #, LL
                     if (op_code == 0xE0)   // MOVE #, LL
                        return op_code | op_1->GetValue() & 0x0F;
                        return op_code | op_1->GetValue() & 0x0F;
                     return op_code | op_2->GetValue() & 0x0F;
                     return op_code | op_2->GetValue() & 0x0F;
      }
      }
   assert(0);
   assert(0);
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void Opcode::Error() const
void Opcode::Error() const
{
{
   fprintf(stderr, "Error: ");
   fprintf(stderr, "Error: ");
   if (op_text) fprintf(stderr, "%s ", op_text);
   if (op_text) fprintf(stderr, "%s ", op_text);
   fprintf(stderr, "%X", op_code);
   fprintf(stderr, "%X", op_code);
   fprintf(stderr, "\n");
   fprintf(stderr, "\n");
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void write_intel_record(FILE * out, int adr, int len)
void write_intel_record(FILE * out, int adr, int len)
{
{
char checksum = 0;
char checksum = 0;
   fprintf(out, ":");
   fprintf(out, ":");
   fprintf(out, "%2.2X", len & 0xFF);
   fprintf(out, "%2.2X", len & 0xFF);
   checksum += len;
   checksum += len;
   fprintf(out, "%4.4X", adr & 0xFFFF);
   fprintf(out, "%4.4X", adr & 0xFFFF);
   checksum += adr >> 8;
   checksum += adr >> 8;
   checksum += adr;
   checksum += adr;
   if (len == 0)   { fprintf(out, "01");   checksum ++; }   // end of file
   if (len == 0)   { fprintf(out, "01");   checksum ++; }   // end of file
   else            { fprintf(out, "00");                }   // data
   else            { fprintf(out, "00");                }   // data
   for (int i = adr; i < adr + len; i++)
   for (int i = adr; i < adr + len; i++)
       {
       {
         fprintf(out, "%2.2X", memory[i] & 0xFF);
         fprintf(out, "%2.2X", memory[i] & 0xFF);
         checksum += memory[i];
         checksum += memory[i];
       }
       }
   fprintf(out, "%2.2X", (-checksum) & 0xFF);
   fprintf(out, "%2.2X", (-checksum) & 0xFF);
   fprintf(out, "\n");
   fprintf(out, "\n");
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void write_intel_hex(FILE * out)
void write_intel_hex(FILE * out)
{
{
   for (int i = 0; i < mem_idx; i += 16)
   for (int i = 0; i < mem_idx; i += 16)
       {
       {
         int len = mem_idx - i;
         int len = mem_idx - i;
         if (len > 16)   len = 16;
         if (len > 16)   len = 16;
         write_intel_record(out, i, len);
         write_intel_record(out, i, len);
       }
       }
   write_intel_record(out, 0, 0);
   write_intel_record(out, 0, 0);
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
 
 

powered by: WebSVN 2.1.0

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