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

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