home *** CD-ROM | disk | FTP | other *** search
/ messroms.de / 2007-01-13_www.messroms.de.zip / VZ200 / TOOLS / AZ80.ZIP / az80.y < prev    next >
Text File  |  1999-12-27  |  23KB  |  1,058 lines

  1. %{
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <stdarg.h>
  6.  
  7. #define CGENIE 0
  8.  
  9. #if CGENIE
  10. #define TAPE_EXT ".cas"
  11. #else
  12. #define TAPE_EXT ".vz"
  13. #endif
  14.  
  15. typedef unsigned char   byte;
  16. typedef    unsigned short    word;
  17.  
  18. typedef    struct    tagSYM {
  19.     struct  tagSYM * next;
  20.     int     pass_no;
  21.     int     value;
  22.     int     refs;
  23.     int     * line_no;
  24.     char    * name;
  25. }   SYM;
  26.  
  27. void emit(void);
  28.  
  29. void addsym(char * name, int value);
  30. int getsym(char * name);
  31.  
  32. int symb_no = 0;
  33. int line_no = 1;
  34. int pass_no = 1;
  35. byte pre = 0x00;
  36. byte xcb = 0x00;
  37. byte cmd = 0x00;
  38. int ofs = 0x00;
  39. byte arg[4096] = {0, };
  40. int expflg  = 0;
  41. int cmdflg  = 0;
  42. int ofsflg  = 0;
  43. int argcnt  = 0;
  44. word exp     = 0;
  45. word PC      = 0;
  46. word end     = 0;
  47.  
  48. char lstbuff[256+1] = "";
  49. char *plst  = NULL;
  50.  
  51. SYM *sym    = NULL;
  52. SYM *sym0   = NULL;
  53.  
  54. char inpname[256+1] = "";
  55. char outname[256+1] = "";
  56. char lstname[256+1] = "";
  57.  
  58. FILE *inpfile = NULL;
  59. FILE *outfile = NULL;
  60. FILE *lstfile = NULL;
  61.  
  62. int f_list  = 0;
  63. int f_tape  = 0;
  64. int f_syms  = 0;
  65. int f_xref  = 0;
  66. int f_first = 0;
  67.  
  68. char tape_name[6+1];
  69. byte tape_buf[256];
  70. byte tape_crc = 0;
  71. byte tape_cnt = 0;
  72. word tape_adr = 0;
  73. word tape_pc  = 0;
  74.  
  75. %}
  76.  
  77. %start    file
  78.  
  79. %union {
  80. int    i;
  81. char*    s;
  82. }
  83.  
  84. %token    EOL,COMMA,COLON,LPAREN,RPAREN,PLUS,MINUS,MUL,DIV,SHL,SHR,AND,OR,XOR,NOT
  85.  
  86. %token    _B,_C,_D,_E,_H,_L,_M,_A,_F,_I,_R
  87. %token    _BC,_DE,_HL,_AF,_SP,_IX,_IY
  88. %token    _cNZ,_cZ,_cNC,_cC,_cPO,_cPE,_cP,_cM
  89. %token    _PORTC
  90.  
  91. %token    <i>    _MX,_MY
  92. %token    <i>    _VAL
  93. %token    <s>    _SYM
  94. %token    <s>    _STR
  95.  
  96. %token    _ADC,_ADD,_AND
  97. %token    _BIT
  98. %token    _CALL,_CCF,_CP,_CPD,_CPDR,_CPI,_CPIR,_CPL
  99. %token    _DAA,_DEC,_DI,_DJNZ
  100. %token    _EI,_EX,_EXX
  101. %token    _HALT
  102. %token    _IM,_IN,_INC,_IND,_INDR,_INI,_INIR
  103. %token    _JP,_JR
  104. %token    _LD,_LDD,_LDDR,_LDI,_LDIR
  105. %token    _NEG,_NOP
  106. %token    _OR,_OTDR,_OTIR,_OUT,_OUTD,_OUTI
  107. %token    _POP,_PUSH
  108. %token    _RES,_RET,_RETI,_RETN,_RL,_RLA,_RLC,_RLCA,_RLD,_RR,_RRA,_RRC,_RRCA,_RRD,_RST
  109. %token    _SBC,_SCF,_SET,_SLA,_SLL,_SRA,_SRL,_SUB
  110. %token    _XOR
  111.  
  112. %token    _DEFB,_DEFL,_DEFM,_DEFS,_DEFW,_END,_EQU,_ORG
  113.  
  114. %type    <i>    expr,simple,term,factor,port
  115.  
  116. %%
  117.  
  118. file    :    line
  119.     |    line error
  120.     ;
  121.  
  122. line    :    line token { emit(); }
  123.     |    token { emit(); }
  124.     ;
  125.  
  126. token    :    EOL
  127.         { cmdflg = 0; }
  128.     |    _SYM
  129.         { cmdflg = 0; addsym($1, PC); free($1); }
  130.     |    _SYM COLON
  131.                 { cmdflg = 0; addsym($1, PC); free($1); }
  132.     |    _SYM    _EQU i16            EOL
  133.         {
  134.             cmdflg = 0;
  135.             argcnt = 0;
  136.             exp = *(word*)arg;
  137.             expflg = 1;
  138.             addsym($1,exp);
  139.             free($1);
  140.         }
  141.     |    _SYM    _DEFL i16            EOL
  142.         {
  143.             cmdflg = 0;
  144.             argcnt = 0;
  145.             expflg = 1;
  146.             exp = *(word*)arg;
  147.             addsym($1, exp);
  148.             free($1);
  149.         }
  150.     |    _ADC    _A COMMA s08            EOL
  151.         { cmd |= 0x88; } 
  152.     |    _ADC    _A COMMA i08            EOL
  153.         { cmd = 0xCE; } 
  154.     |    _ADC    _HL COMMA r16            EOL
  155.         { pre = 0xED; cmd |= 0x4A; } 
  156.     |    _ADD    _A COMMA s08            EOL
  157.         { cmd |= 0x80; } 
  158.     |    _ADD    _A COMMA i08            EOL
  159.         { cmd = 0xC6; } 
  160.     |    _ADD    _HL COMMA r16            EOL
  161.         { cmd |= 0x09; } 
  162.     |    _ADD    _IX COMMA r16x            EOL
  163.         { pre = 0xDD; cmd |= 0x09; } 
  164.     |    _ADD    _IY COMMA r16y            EOL
  165.         { pre = 0xFD; cmd |= 0x09; } 
  166.     |    _AND    s08                EOL
  167.         { cmd |= 0xA0; } 
  168.     |    _AND    i08                EOL
  169.         { cmd = 0xE6; } 
  170.     |    _BIT    bit COMMA s08            EOL
  171.         { xcb = 0xCB; cmd |= 0x40; } 
  172.     |    _CALL    i16                EOL
  173.         { cmd = 0xCD; } 
  174.     |    _CALL    cond COMMA i16            EOL
  175.         { cmd |= 0xC4; } 
  176.     |    _CCF                    EOL
  177.         { cmd = 0x3F; }
  178.     |    _CP    s08                EOL
  179.         { cmd |= 0xB8; } 
  180.     |    _CP    i08                EOL
  181.         { cmd = 0xFE; } 
  182.     |    _CPD                    EOL
  183.         { pre = 0xED; cmd = 0xA9; }
  184.     |    _CPDR                    EOL
  185.         { pre = 0xED; cmd = 0xB9; }
  186.     |    _CPI                    EOL
  187.         { pre = 0xED; cmd = 0xA1; }
  188.     |    _CPIR                    EOL
  189.         { pre = 0xED; cmd = 0xB1; }
  190.     |    _CPL                    EOL
  191.         { cmd = 0x2F; }
  192.     |    _DAA                    EOL
  193.         { cmd = 0x27; }
  194.     |    _DEC    s08                EOL
  195.         { cmd = (cmd << 3) | 0x05; }
  196.     |    _DEC    r16xy                EOL
  197.         { cmd |= 0x0B; } 
  198.     |    _DI                    EOL
  199.         { cmd = 0xF3; }
  200.     |    _DJNZ    ofs8                EOL
  201.         { cmd = 0x10; }
  202.     |    _EI                    EOL
  203.         { cmd = 0xFB; }
  204.     |    _EX    _AF COMMA _AF            EOL
  205.         { cmd = 0x08; }
  206.     |    _EX    _DE COMMA _HL            EOL
  207.          { cmd = 0xEB; }
  208.     |    _EX    LPAREN _SP RPAREN COMMA _HL    EOL
  209.         { cmd = 0xE3; }
  210.     |    _EX    LPAREN _SP RPAREN COMMA _IX    EOL
  211.         { pre = 0xDD; cmd = 0xE3; }
  212.     |    _EX    LPAREN _SP RPAREN COMMA _IY    EOL
  213.         { pre = 0xFD; cmd = 0xE3; }
  214.     |    _EXX                    EOL
  215.         { cmd = 0xD9; }
  216.     |    _HALT                    EOL
  217.         { cmd = 0x76; }
  218.     |    _IM    imode                EOL
  219.         { pre = 0xED; cmd |= 0x56 }
  220.     |    _IN    r08 COMMA port            EOL
  221.         { if( $4 ) { pre = 0xED; cmd |= 0x40; } else cmd = 0xDB; }
  222.         |       _INC    s08                             EOL
  223.         { cmd = (cmd << 3) | 0x04; }
  224.     |    _INC    r16xy                EOL
  225.         { cmd |= 0x03; } 
  226.     |    _IND                    EOL
  227.         { pre = 0xED; cmd = 0xAA; }
  228.     |    _INDR                    EOL
  229.         { pre = 0xED; cmd = 0xBA; }
  230.     |    _INI                    EOL
  231.         { pre = 0xED; cmd = 0xA2; }
  232.     |    _INIR                    EOL
  233.         { pre = 0xED; cmd = 0xB2; }
  234.     |    _JP    _M                EOL
  235.         { cmd = 0xE9; }
  236.     |    _JP    _MX                EOL
  237.         { pre = 0xDD; cmd = 0xE9; }
  238.     |    _JP    _MY                EOL
  239.         { pre = 0xFD; cmd = 0xE9; }
  240.     |    _JP    i16                EOL
  241.         { cmd = 0xC3; }
  242.     |    _JP    cond COMMA i16            EOL
  243.         { cmd |= 0xC2; }
  244.     |    _JR    ofs8                EOL
  245.         { cmd = 0x18; }
  246.     |    _JR    cond1 COMMA ofs8        EOL
  247.         { cmd |= 0x20; }
  248.     |    _LD    _BC COMMA i16            EOL
  249.         { cmd = 0x01; } 
  250.     |    _LD    LPAREN i16 RPAREN COMMA _BC    EOL
  251.         { pre = 0xED; cmd = 0x43; }
  252.     |    _LD    _BC COMMA LPAREN i16 RPAREN    EOL
  253.         { pre = 0xED; cmd = 0x4B; } 
  254.     |    _LD    _DE COMMA i16            EOL
  255.         { cmd = 0x11; } 
  256.     |    _LD    LPAREN i16 RPAREN COMMA _DE    EOL
  257.         { pre = 0xED; cmd = 0x53; }
  258.     |    _LD    _DE COMMA LPAREN i16 RPAREN    EOL
  259.         { pre = 0xED; cmd = 0x5B; } 
  260.     |    _LD    _HL COMMA i16            EOL
  261.         { cmd = 0x21; }
  262.     |    _LD    LPAREN i16 RPAREN COMMA _HL    EOL
  263.         { cmd = 0x22; }
  264.     |    _LD    _HL COMMA LPAREN i16 RPAREN    EOL
  265.         { cmd = 0x2A; }
  266.     |    _LD    _SP COMMA i16            EOL
  267.         { cmd = 0x31; } 
  268.     |    _LD    LPAREN i16 RPAREN COMMA _SP    EOL
  269.         { pre = 0xED; cmd = 0x73; }
  270.     |    _LD    _SP COMMA LPAREN i16 RPAREN    EOL
  271.         { pre = 0xED; cmd = 0x7B; } 
  272.     |    _LD    _SP COMMA _HL            EOL
  273.         { cmd = 0xE3; }
  274.     |    _LD    _SP COMMA _IX            EOL
  275.         { pre = 0xDD; cmd = 0xE3; }
  276.     |    _LD    _SP COMMA _IY            EOL
  277.         { pre = 0xFD; cmd = 0xE3; }
  278.     |    _LD    _IX COMMA i16            EOL
  279.         { pre = 0xDD; cmd = 0x21; }
  280.     |    _LD    LPAREN i16 RPAREN COMMA _IX    EOL
  281.         { pre = 0xDD; cmd = 0x22; }
  282.     |    _LD    _IX COMMA LPAREN i16 RPAREN    EOL
  283.         { pre = 0xDD; cmd = 0x2A; }
  284.     |    _LD    _IY COMMA i16            EOL
  285.         { pre = 0xFD; cmd = 0x21; }
  286.     |    _LD    LPAREN i16 RPAREN COMMA _IY    EOL
  287.         { pre = 0xFD; cmd = 0x22; }
  288.     |    _LD    _IY COMMA LPAREN i16 RPAREN    EOL
  289.         { pre = 0xFD; cmd = 0x2A; }
  290.     |    _LD    _B COMMA s08            EOL
  291.         { cmd |= 0x40; }
  292.     |    _LD    _C COMMA s08            EOL
  293.         { cmd |= 0x48; }
  294.     |    _LD    _D COMMA s08            EOL
  295.         { cmd |= 0x50; }
  296.     |    _LD    _E COMMA s08            EOL
  297.         { cmd |= 0x58; }
  298.     |    _LD    _H COMMA s08            EOL
  299.         { cmd |= 0x60; }
  300.     |    _LD    _L COMMA s08            EOL
  301.         { cmd |= 0x68; }
  302.     |    _LD    _M COMMA s08            EOL
  303.         { cmd |= 0x70; }
  304.     |    _LD    _A COMMA s08            EOL
  305.         { cmd |= 0x78; }
  306.     |    _LD    _MX COMMA s08            EOL
  307.         { pre = 0xDD; cmd |= 0x70; ofs = $2; ofsflg = 1; }
  308.     |    _LD    _MY COMMA s08            EOL
  309.         { pre = 0xFD; cmd |= 0x70; ofs = $2; ofsflg = 1; }
  310.     |    _LD    _B COMMA i08            EOL
  311.         { cmd = 0x06; }
  312.     |    _LD    _C COMMA i08            EOL
  313.         { cmd = 0x0E; }
  314.     |    _LD    _D COMMA i08            EOL
  315.         { cmd = 0x16; }
  316.     |    _LD    _E COMMA i08            EOL
  317.         { cmd = 0x1E; }
  318.     |    _LD    _H COMMA i08            EOL
  319.         { cmd = 0x26; }
  320.     |    _LD    _L COMMA i08            EOL
  321.         { cmd = 0x2E; }
  322.     |    _LD    _M COMMA i08            EOL
  323.         { cmd = 0x36; }
  324.     |    _LD    _A COMMA i08            EOL
  325.         { cmd = 0x3E; }
  326.     |    _LD    _MX COMMA i08            EOL
  327.         { pre = 0xDD; cmd = 0x36; ofs = $2; ofsflg = 1; }
  328.     |    _LD    _MY COMMA i08            EOL
  329.         { pre = 0xFD; cmd = 0x36; ofs = $2; ofsflg = 1; }
  330.     |    _LD    _I COMMA _A            EOL
  331.         { pre = 0xED; cmd = 0x47; }
  332.     |    _LD    _R COMMA _A            EOL
  333.         { pre = 0xED; cmd = 0x4F; }
  334.     |    _LD    _A COMMA _I            EOL
  335.         { pre = 0xED; cmd = 0x57; }
  336.     |    _LD    _A COMMA _R            EOL
  337.         { pre = 0xED; cmd = 0x5F; }
  338.     |    _LD    LPAREN _BC RPAREN COMMA _A    EOL
  339.         { cmd = 0x02; }
  340.     |    _LD    _A COMMA LPAREN _BC RPAREN    EOL
  341.         { cmd = 0x0A; }
  342.     |    _LD    LPAREN _DE RPAREN COMMA _A    EOL
  343.         { cmd = 0x12; }
  344.     |    _LD    _A COMMA LPAREN _DE RPAREN    EOL
  345.         { cmd = 0x1A; }
  346.     |    _LD    LPAREN i16 RPAREN COMMA _A    EOL
  347.         { cmd = 0x32; }
  348.     |    _LD    _A COMMA LPAREN i16 RPAREN    EOL
  349.         { cmd = 0x3A; }
  350.     |    _LDD                    EOL
  351.         { pre = 0xED; cmd = 0xA8; }
  352.     |    _LDDR                    EOL
  353.         { pre = 0xED; cmd = 0xB8; }
  354.     |    _LDI                    EOL
  355.         { pre = 0xED; cmd = 0xA0; }
  356.     |    _LDIR                    EOL
  357.         { pre = 0xED; cmd = 0xB0; }
  358.     |    _NEG                    EOL
  359.         { pre = 0xED; cmd = 0x44; }
  360.     |    _NOP                    EOL
  361.         { cmd = 0x00; }
  362.     |    _OR    s08                EOL
  363.         { cmd |= 0xB0; }
  364.     |    _OR    i08                EOL
  365.         { cmd = 0xF6; }
  366.     |    _OTDR                    EOL
  367.         { pre = 0xED; cmd = 0xBB; }
  368.     |    _OTIR                    EOL
  369.         { pre = 0xED; cmd = 0xB3; }
  370.     |    _OUT    port COMMA r08            EOL
  371.         { if( $2 ) { pre = 0xED; cmd |= 0x41; } else cmd = 0xD3; }
  372.         |       _OUTD                                   EOL
  373.         { pre = 0xED; cmd = 0xAB; }
  374.     |    _OUTI                    EOL
  375.         { pre = 0xED; cmd = 0xA3; }
  376.     |    _POP    r16pp                EOL
  377.         { cmd |= 0xC1; }
  378.     |    _PUSH    r16pp                EOL
  379.         { cmd |= 0xC5; }
  380.     |    _RES    bit COMMA s08            EOL
  381.         { xcb = 0xCB; cmd |= 0x80; } 
  382.     |    _RET                    EOL
  383.         { cmd = 0xC9; }
  384.     |    _RET    cond                EOL
  385.         { cmd |= 0xC0; }
  386.     |    _RETI                    EOL
  387.         { pre = 0xED; cmd = 0x45; }
  388.     |    _RETN                    EOL
  389.         { pre = 0xED; cmd = 0x4D; }
  390.     |    _RL    s08                EOL
  391.         { xcb = 0xCB; cmd |= 0x10; }
  392.     |    _RLA                    EOL
  393.         { cmd = 0x17; }
  394.     |    _RLC    s08                EOL
  395.         { xcb = 0xCB; cmd |= 0x00; }
  396.     |    _RLCA                    EOL
  397.         { cmd = 0x07; }
  398.     |    _RLD                    EOL
  399.         { pre = 0xED; cmd = 0x6F; }
  400.     |    _RR    s08                EOL
  401.         { xcb = 0xCB; cmd |= 0x18; }
  402.     |    _RRA                    EOL
  403.         { cmd = 0x1F; }
  404.     |    _RRC    s08                EOL
  405.         { xcb = 0xCB; cmd |= 0x08; }
  406.     |    _RRCA                    EOL
  407.         { cmd = 0x0F; }
  408.     |    _RRD                    EOL
  409.         { pre = 0xED; cmd = 0x67; }
  410.     |    _RST    rst                EOL
  411.         { cmd |= 0xC7; }
  412.     |    _SBC    _A COMMA s08            EOL
  413.         { cmd |= 0x98; } 
  414.     |    _SBC    _A COMMA i08            EOL
  415.         { cmd = 0xDE; } 
  416.     |    _SBC    _HL COMMA r16            EOL
  417.         { pre = 0xED; cmd |= 0x42; } 
  418.     |    _SCF                    EOL
  419.         { cmd = 0x37; }
  420.     |    _SET    bit COMMA s08            EOL
  421.         { xcb = 0xCB; cmd |= 0xC0; }
  422.     |    _SLA    s08                EOL
  423.         { xcb = 0xCB; cmd |= 0x20; }
  424.     |    _SLL    s08                EOL
  425.         { xcb = 0xCB; cmd |= 0x30; }
  426.     |    _SRA    s08                EOL
  427.         { xcb = 0xCB; cmd |= 0x28; }
  428.     |    _SRL    s08                EOL
  429.         { xcb = 0xCB; cmd |= 0x38; }
  430.     |    _SUB    s08                EOL
  431.         { cmd |= 0x90; } 
  432.     |    _SUB    i08                EOL
  433.         { cmd |= 0xD6; } 
  434.     |    _XOR    s08                EOL
  435.         { cmd |= 0xA8; } 
  436.     |    _XOR    i08                EOL
  437.         { cmd = 0xEE; } 
  438.     |    _DEFB    i08list                EOL
  439.         { cmdflg = 0; }
  440.     |    _DEFS    i08                EOL
  441.         { cmdflg = 0; argcnt = arg[0]; arg[0] = 0x00; }
  442.     |    _DEFM    strlist                EOL
  443.         { cmdflg = 0; }
  444.     |    _DEFW    i16list                EOL
  445.         { cmdflg = 0; }
  446.     |    _ORG    i16                EOL
  447.         {
  448.             cmdflg = 0;
  449.             argcnt = 0;
  450.             expflg = 1;
  451.             exp = *(word *)arg;
  452.             PC = exp;
  453.         }
  454.     |    _END    i16                EOL
  455.         {
  456.             cmdflg = 0;
  457.             argcnt = 0;
  458.             expflg = 1;
  459.             exp = *(word *)arg;
  460.             end = exp;
  461.         }
  462.     ;
  463.  
  464. s08    :    _B { cmd |= 0x00; }    
  465.     |    _C { cmd |= 0x01; }    
  466.     |    _D { cmd |= 0x02; }    
  467.     |    _E { cmd |= 0x03; }
  468.     |    _H { cmd |= 0x04; }
  469.     |    _L { cmd |= 0x05; }
  470.     |    _M { cmd |= 0x06; }
  471.     |    _A { cmd |= 0x07; }
  472.     |    _MX { pre = 0xDD; cmd |= 0x06; ofs = $1; ofsflg = 1; }
  473.     |    _MY { pre = 0xFD; cmd |= 0x06; ofs = $1; ofsflg = 1; }
  474.     ;
  475.  
  476. r08    :    _B { cmd |= 0x00; }
  477.     |    _C { cmd |= 0x08; }
  478.     |    _D { cmd |= 0x10; }
  479.     |    _E { cmd |= 0x18; }
  480.     |    _H { cmd |= 0x20; }
  481.     |    _L { cmd |= 0x28; }
  482.     |    _F { cmd |= 0x30; }
  483.     |    _A { cmd |= 0x38; }
  484.     ;
  485.  
  486. r16    :    _BC { cmd |= 0x00; }
  487.     |    _DE { cmd |= 0x10; }
  488.     |    _HL { cmd |= 0x20; }
  489.     |    _SP { cmd |= 0x30; }
  490.     ;
  491.  
  492. r16x    :    _BC { cmd |= 0x00; }
  493.     |    _DE { cmd |= 0x10; }
  494.     |    _IX { cmd |= 0x20; }
  495.     |    _SP { cmd |= 0x30; }
  496.     ;
  497.  
  498. r16y    :    _BC { cmd |= 0x00; }
  499.     |    _DE { cmd |= 0x10; }
  500.     |    _IY { cmd |= 0x20; }
  501.     |    _SP { cmd |= 0x30; }
  502.     ;
  503.  
  504. r16xy    :    _BC { cmd |= 0x00; }
  505.     |    _DE { cmd |= 0x10; }
  506.     |    _HL { cmd |= 0x20; }
  507.     |    _SP { cmd |= 0x30; }
  508.     |    _IX { pre = 0xDD; cmd |= 0x20; }
  509.     |    _IY { pre = 0xFD; cmd |= 0x20; }
  510.     ;
  511.  
  512. r16pp    :    _BC { cmd |= 0x00; }
  513.     |    _DE { cmd |= 0x10; }
  514.     |    _HL { cmd |= 0x20; }
  515.     |    _AF { cmd |= 0x30; }
  516.     |    _IX { pre = 0xDD; cmd |= 0x20; }
  517.     |    _IY { pre = 0xFD; cmd |= 0x20; }
  518.     ;
  519.  
  520. cond    :    _cNZ    { cmd |= 0x00; }
  521.     |    _cZ    { cmd |= 0x08; }
  522.     |    _cNC    { cmd |= 0x10; }
  523.     |    _cC    { cmd |= 0x18; }
  524.     |    _cPO    { cmd |= 0x20; }
  525.     |    _cPE    { cmd |= 0x28; }
  526.     |    _cP    { cmd |= 0x30; }
  527.     |    _cM    { cmd |= 0x38; }
  528.     ;
  529.  
  530. cond1    :    _cNZ    { cmd |= 0x00; }
  531.     |    _cZ    { cmd |= 0x08; }
  532.     |    _cNC    { cmd |= 0x10; }
  533.     |    _cC    { cmd |= 0x18; }
  534.     ;
  535.  
  536. port    :    _PORTC
  537.         { $$ = 1; }
  538.     |    LPAREN expr RPAREN
  539.         { $$ = 0; arg[argcnt++] = $2; }
  540.     ;
  541.  
  542. expr    :       simple
  543.         { $$ = $1; }
  544.     |    expr SHL simple
  545.         { $$ = $1 << $3; }
  546.     |    expr SHR simple
  547.         { $$ = $1 >> $3; }
  548.     ;
  549.  
  550. simple  :       term
  551.         { $$ = $1; }
  552.     |    simple PLUS LPAREN expr RPAREN
  553.         { $$ = $1 + $4; }
  554.     |    simple MINUS LPAREN expr RPAREN
  555.         { $$ = $1 - $4; }
  556.     |    simple AND LPAREN expr RPAREN
  557.         { $$ = $1 & $4; }
  558.         |       simple PLUS term
  559.         { $$ = $1 + $3; }
  560.     |    simple MINUS term
  561.         { $$ = $1 - $3; }
  562.     |    simple AND term
  563.         { $$ = $1 & $3; }
  564.         ;
  565.  
  566. term    :    factor
  567.         { $$ = $1; }
  568.     |    PLUS factor
  569.         { $$ = $2; }
  570.     |    MINUS factor
  571.         { $$ = -$2; }
  572.     |    NOT factor
  573.         { $$ = ~$2; }
  574.         |       term MUL factor
  575.         { $$ = $1 * $3; }
  576.     |    term DIV factor
  577.         { $$ = $1 / $3; }
  578.     |    term OR factor
  579.         { $$ = $1 | $3; }
  580.     |    term XOR factor
  581.         { $$ = $1 ^ $3; }
  582.         ;
  583.  
  584. factor    :    _VAL
  585.         { $$ = $1; }
  586.     |    _SYM
  587.         { $$ = getsym($1); free($1); }
  588.     ;
  589.  
  590. i08    :    expr
  591.         {
  592.             if( $1 < -255 || $1 > 255 )
  593.             fprintf(stderr, "line (%d) warning: size exceeds BYTE (%d)\n", line_no, $1);
  594.             arg[argcnt++] = $1;
  595.         }
  596.     ;
  597.  
  598. i08list    :    i08 COMMA i08list
  599.     |    i08
  600.     ;
  601.  
  602. i16    :    expr
  603.         {
  604.             if( $1 < -65535 || $1 > 65535 )
  605.             fprintf(stderr, "line (%d) warning: size exceeds WORD (%d)\n", line_no, $1);
  606.             arg[argcnt++] = $1 & 255;
  607.             arg[argcnt++] = $1 / 256;
  608.         }
  609.     ;
  610.  
  611. i16list    :    i16 COMMA i16list
  612.     |    i16
  613.     ;
  614.  
  615. str    :    _STR
  616.         {
  617.             strcpy(arg + argcnt, $1);
  618.             argcnt += strlen($1);
  619.             free($1);
  620.         }
  621.     |    i08
  622.     ;
  623.  
  624. strlist    :    str COMMA strlist
  625.     |    str
  626.     ;
  627.  
  628. ofs8    :    expr
  629.         {
  630.             ofs  = $1 - PC - 2;
  631.             ofsflg = 1;
  632.             if( pass_no > 1 && (ofs < -128 || ofs > +127) )
  633.             fprintf(stderr, "line (%d) warning: JR out of range (%d)\n", line_no, $1 - PC - 2);
  634.         }
  635.     ;
  636.  
  637. bit    :    expr
  638.         {
  639.             if( $1 < 0 || $1 > 7 )
  640.             fprintf(stderr, "line (%d) invalid bit number %d\n", line_no, $1);
  641.             cmd |= ($1 & 7) << 3;
  642.         }
  643.     ;
  644.  
  645. rst    :    expr
  646.         {
  647.             if( $1 < 0 || $1 > 0x38 || $1 & 0x07 )
  648.             fprintf(stderr, "line (%d) invalid rst vector %04XH\n", line_no, $1);
  649.             cmd |= ($1 & 0x38);
  650.         }
  651.     ;
  652.  
  653. imode    :    expr
  654.         {
  655.             if( $1 < 0 || $1 > 2 )
  656.             fprintf(stderr, "line (%d) invalid interrupt mode %d\n", line_no, $1);
  657.             cmd |= ($1 % 3) << 3;
  658.         }
  659. %%
  660.  
  661. int list(char * fmt, ...)
  662. {
  663.     va_list arg;
  664.     int rc = 0;
  665.  
  666.     if( !f_list )
  667.     return rc;
  668.     if( pass_no < 2 )
  669.     return rc;
  670.     va_start(arg, fmt);
  671.     rc = vfprintf(lstfile, fmt, arg);
  672.     va_end(arg);
  673.     return rc;
  674. }
  675.  
  676. void tape_flush(void)
  677. {
  678.     if( !tape_cnt )
  679.     return;
  680. #if CGENIE
  681.     fputc(0x3C, outfile);
  682.     fputc(tape_cnt, outfile);
  683.     fputc(tape_adr & 255, outfile);
  684.     fputc(tape_adr / 256, outfile);
  685.     fwrite(tape_buf, 1, tape_cnt, outfile);
  686.     fputc(tape_crc, outfile);
  687.     tape_crc = 0;
  688. #else
  689.     if( f_first )
  690.     {
  691.     fputc(tape_adr & 255, outfile);
  692.     fputc(tape_adr / 256, outfile);
  693.     f_first = 0;
  694.     }
  695.     fwrite(tape_buf, 1, tape_cnt, outfile);
  696. #endif
  697.     tape_cnt = 0;
  698. }
  699.  
  700. int outch(byte c)
  701. {
  702.     int rc = 0;
  703.     if( pass_no == 1 )
  704.     {
  705.     PC++;
  706.     return rc;
  707.     }
  708.     rc = list("%02X ", c);
  709.     if( f_tape )
  710.     {
  711.     if( PC != tape_pc || tape_cnt == 128 )
  712.     {
  713.         tape_flush();
  714.         tape_pc  = PC;
  715.         tape_adr = PC;
  716.         tape_crc = (tape_adr & 255) + (tape_adr / 256);
  717.     }
  718.     tape_buf[tape_cnt++] = c;
  719.     tape_crc += c;
  720.     tape_pc  += 1;
  721.     }
  722.     else
  723.     {
  724.     fputc(c, outfile);
  725.     }
  726.     PC++;
  727.     return rc;
  728. }
  729.  
  730. void emit(void)
  731. {
  732.     int i;
  733.     int x = 0;
  734.  
  735.     if( cmdflg || argcnt )
  736.     x += list("%04X: ", PC);
  737.  
  738.     if( pre )
  739.     x += outch(pre);
  740.     if( xcb )
  741.     x += outch(xcb);
  742.     if( pre && xcb && ofsflg )
  743.     {
  744.     x += outch(ofs);
  745.     x += outch(cmd);
  746.     }
  747.     else
  748.     {
  749.     if( cmdflg )
  750.         x += outch(cmd);
  751.     if( ofsflg )
  752.         x += outch(ofs);
  753.     }
  754.     for( i = 0; i < argcnt && i < 8; i++ )
  755.     x += outch(arg[i]);
  756.     if( strchr(lstbuff, '\n') )
  757.     {
  758.     if( !(cmdflg || argcnt) && expflg )
  759.         x += list("=%04X ", exp);
  760.     if( x >= 0 && x < 32 )
  761.         list("%*s", 32 - x, " ");
  762.     list("%s", lstbuff);
  763.     }
  764.     if( argcnt > 8 )
  765.     {
  766.     for( i = 8; i < argcnt; i++ )
  767.     {
  768.         if( (i & 7) == 0 )
  769.         x = list("%04X: ", PC);
  770.         x += outch(arg[i]);
  771.         if( (i & 7) == 7 )
  772.         x += list("\n");
  773.     }
  774.     if( i & 7 )
  775.         x += list("\n");
  776.     }
  777.     pre = 0;
  778.     xcb = 0;
  779.     cmd = 0;
  780.     ofs = 0;
  781.     expflg = 0;
  782.     cmdflg = 1;
  783.     ofsflg = 0;
  784.     argcnt = 0;
  785. }
  786.  
  787. void addsym(char * name, int value)
  788. {
  789.     SYM *s, *s0, *s1;
  790.     for( s = sym; (s); s = s->next )
  791.     {
  792.     if( strcasecmp(name, s->name) == 0 )
  793.     {
  794.         if( s->pass_no == pass_no )
  795.         fprintf(stderr, "line (%d) warning: double defined symbol %s\n", line_no, name);
  796.         s->line_no[0] = line_no;
  797.         s->pass_no      = pass_no;
  798.         if( s->value != value )
  799.         fprintf(stderr, "line (%d) warning: %s has different value on pass 2\n", line_no, name);
  800.         s->value   = value;
  801.         return;
  802.     }
  803.     }
  804.     for( s0 = NULL, s1 = sym; (s1); s0 = s1, s1 = s1->next )
  805.     if( stricmp(name, s1->name) <= 0 )
  806.         break;
  807.     s = (SYM *) calloc(1, sizeof(SYM));
  808.     if( !s )
  809.     {
  810.     fprintf(stderr, "error: out of memory!\n");
  811.     exit(1);
  812.     }
  813.     s->next = s1;
  814.     s->pass_no = pass_no;
  815.     s->refs = 0;
  816.     s->line_no = malloc(sizeof(int));
  817.     *s->line_no = line_no;
  818.     s->value = value;
  819.     s->name = strdup(name);
  820.     if( s0 )
  821.     s0->next = s;
  822.     else
  823.     sym    = s;
  824.     symb_no++;
  825. }
  826.  
  827. int getsym(char * name)
  828. {
  829.     SYM *s;
  830.     for( s = sym; (s); s = s->next )
  831.     {
  832.     if( strcasecmp(name, s->name) == 0 )
  833.     {
  834.         if( pass_no > 1 )
  835.         {
  836.         s->refs += 1;
  837.         s->line_no = (int *) realloc(s->line_no, (s->refs + 1) * sizeof(int));
  838.         s->line_no[s->refs] = line_no;
  839.         }
  840.         return s->value;
  841.     }
  842.     }
  843.     if( pass_no > 1 )
  844.     fprintf(stderr, "line (%d) undefined symbol: %s\n", line_no, name);
  845.     return 0;
  846. }
  847.  
  848. void prtsym(FILE * filp)
  849. {
  850.     SYM * s;
  851.     int i;
  852.     for( s = sym; (s); s = s->next )
  853.     {
  854.     fprintf(filp, "%-32.32s%04X line %d, %d references\n", s->name, s->value, s->line_no[0], s->refs);
  855.     if( f_xref )
  856.     {
  857.         if( s->refs > 0 )
  858.         {
  859.         for( i = 0; i < s->refs; i++ )
  860.         {
  861.             if( (i & 7) == 0 )
  862.             fprintf(filp, "     ");
  863.             fprintf(filp, "%d ", s->line_no[i+1]);
  864.             if( (i & 7) == 7 )
  865.             fprintf(filp,"\n");
  866.         }
  867.         if( i & 7 )
  868.             fprintf(filp, "\n");
  869.         }
  870.     }
  871.     }
  872. }
  873.  
  874. int main(int ac, char ** av)
  875. {
  876.     int i;
  877.     char * p;
  878.  
  879.     if( ac < 2 )
  880.     {
  881.     fprintf(stderr, "usage:\taz80 [options] input[.z80] [output[.bin]] [listing[.lst]]\n");
  882.     fprintf(stderr, "options can be one or more of:\n");
  883.     fprintf(stderr, "-d\tgenerate parser debug output to stderr\n");
  884.     fprintf(stderr, "-l\tgenerate listing (to file input.lst)\n");
  885.     fprintf(stderr, "-s\toutput symbol table\n");
  886. #if CGENIE
  887.     fprintf(stderr, "-t[name]\tgenerate Colour Genie tape with load addresses\n");
  888. #else
  889.     fprintf(stderr, "-t[name]\tgenerate VZ200/VZ300 tape with load address\n");
  890. #endif
  891.         fprintf(stderr, "-x\toutput cross reference with symbol table\n");
  892.     exit(1);
  893.     }
  894.     for( i = 1; i < ac; i++ )
  895.     {
  896.     if( av[i][0] == '-' )
  897.     {
  898.         switch (av[i][1])
  899.         {
  900.         case 'd': case 'D':
  901.             yydebug = 1;
  902.             break;
  903.         case 'l': case 'L':
  904.             f_list = 1;
  905.             break;
  906.         case 's': case 'S':
  907.             f_syms = 1;
  908.             break;
  909.         case 'x': case 'X':
  910.             f_xref = 1;
  911.             break;
  912.         case 't': case 'T':
  913.             f_tape = 1;
  914.             strncpy(tape_name, av[i]+2, 6);
  915.             tape_name[6] = '\0';
  916.             break;
  917.         default:
  918.             fprintf(stderr, "illegal option %s\n", av[i]);
  919.             exit(1);
  920.         }
  921.         }
  922.         else
  923.         {
  924.         if( strlen(inpname) )
  925.         {
  926.             if( strlen(outname) )
  927.             {
  928.             if( strlen(lstname) )
  929.             {
  930.                 fprintf(stderr, "additional argument %s ignored\n", av[i]);
  931.             }
  932.             else
  933.             {
  934.                 strcpy(lstname, av[i]);
  935.             }
  936.             }
  937.             else
  938.             {
  939.             strcpy(outname, av[i]);
  940.             }
  941.         }
  942.         else
  943.         {
  944.             strcpy(inpname, av[i]);
  945.         }
  946.         }
  947.     }
  948.     if( !strlen(inpname) )
  949.     {
  950.         fprintf(stderr, "input filename missing!\n");
  951.         exit(1);
  952.     }
  953.     if( !strlen(outname) )
  954.     {
  955.         strcpy(outname, inpname);
  956.         p = strrchr(outname, '.');
  957.         if( p )
  958.         strcpy(p, (f_tape) ? TAPE_EXT : ".bin");
  959.         else
  960.         strcat(outname, (f_tape) ? TAPE_EXT : ".bin");
  961.     }
  962.     if( f_list )
  963.     {
  964.         if( !strlen(lstname) )
  965.         {
  966.         strcpy(lstname, inpname);
  967.         p = strrchr(lstname, '.');
  968.         if( p )
  969.             strcpy(p, ".lst");
  970.         else
  971.             strcat(lstname, ".lst");
  972.         }
  973.     }
  974.     else
  975.     if( strlen(lstname) )
  976.     {
  977.         f_list = 1;
  978.         p = strrchr(lstname, '.');
  979.         if( p )
  980.         strcpy(p, ".lst");
  981.         else
  982.         strcat(lstname, ".lst");
  983.     }
  984.     p = strrchr(inpname, '.');
  985.     if( !p )
  986.         strcat(inpname, ".z80");
  987.     inpfile = fopen(inpname, "r");
  988.     if( !inpfile )
  989.     {
  990.         fprintf(stderr, "can't open %s\n", inpname);
  991.         exit(1);
  992.     }
  993.     outfile = fopen(outname, "wb");
  994.     if( !outfile )
  995.     {
  996.         fprintf(stderr, "can't create %s\n", outname);
  997.         exit(1);
  998.     }
  999.     if( f_list )
  1000.     {
  1001.         lstfile = fopen(lstname, "w");
  1002.         if( !lstfile )
  1003.         {
  1004.         fprintf(stderr, "can't create %s\n", outname);
  1005.         exit(1);
  1006.         }
  1007.         plst = lstbuff;
  1008.         *plst = '\0';
  1009.     }
  1010.     if( f_tape )
  1011.     {
  1012. #if CGENIE
  1013.             fputc(0x66, outfile);
  1014.         fputc(0x55, outfile);
  1015.             p = tape_name;
  1016.         for( i = 0; i < 6; i++ )
  1017.         fputc((*p) ? toupper(*p++) : ' ', outfile);
  1018. #else
  1019.         char vz_name[16+1], *src = tape_name, *dst = vz_name;
  1020.         int i;
  1021.  
  1022.         memset(vz_name, 0, sizeof(vz_name));
  1023.         while( *src && *src != '.' )
  1024.         *dst++ = toupper(*src);
  1025.         fputc(0x20, outfile);   /* magic */
  1026.         fputc(0x20, outfile);
  1027.         fputc(0x00, outfile);
  1028.         fputc(0x00, outfile);
  1029.         for( i = 0; i < sizeof(vz_name); i++ )
  1030.         fputc(vz_name[i], outfile);
  1031.         fputc(0xf1, outfile);   /* magic value */
  1032.         f_first = 1;
  1033. #endif
  1034.     }
  1035.     printf("assembling %s\npass 1\n", inpname);
  1036.     yyrestart(inpfile);
  1037.     yyparse();
  1038.     list("\n");
  1039.     if( f_syms )
  1040.         prtsym((f_list) ? lstfile : stdout);
  1041.     if( f_tape )
  1042.     {
  1043.         tape_flush();
  1044. #if CGENIE
  1045.             fputc(0x78, outfile);
  1046.         fputc(end & 255, outfile);
  1047.         fputc(end / 256, outfile);
  1048. #endif
  1049.         }
  1050.     fclose(inpfile);
  1051.     fclose(outfile);
  1052.     if( f_list )
  1053.         fclose(lstfile);
  1054.     printf("%d lines, %d symbols\n", line_no, symb_no);
  1055.  
  1056.         return 0;
  1057. }
  1058.