home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2 / DJLSR201.ZIP / src / stub / djasm.y next >
Encoding:
Text File  |  1996-08-12  |  51.6 KB  |  2,103 lines

  1. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  2. %{
  3.  
  4. #define YYDEBUG 1
  5.   
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <coff.h>
  10. #include <fcntl.h>
  11. #include <time.h>
  12.  
  13. #define SMALL_EXE_HEADER 0
  14. #if SMALL_EXE_HEADER
  15. #define EXE_HEADER_SIZE 32
  16. #define EXE_HEADER_BLOCKS 1
  17. #else
  18. #define EXE_HEADER_SIZE 512
  19. #define EXE_HEADER_BLOCKS 32
  20. #endif
  21.  
  22. #define YYERROR_VERBOSE
  23.  
  24. void yyerror(char *s);
  25.  
  26. #define OUT_exe 0
  27. #define OUT_com 1
  28. #define OUT_bin 2
  29. #define OUT_h   3
  30. #define OUT_inc 4
  31. #define OUT_s   5
  32.  
  33. char *ext_types[] = {
  34.   "exe",
  35.   "com",
  36.   "bin",
  37.   "h",
  38.   "inc",
  39.   "ah",
  40.   0
  41. };
  42.  
  43. char *INC_LEADER = "\t.db\t";
  44. char *S_LEADER = "\t.byte\t";
  45.  
  46. int out_type = OUT_exe;
  47. int image_type = OUT_exe;
  48. char *outname = 0;
  49.  
  50. int i;
  51. int lineno = 1;
  52. char *inname;
  53. int total_errors = 0;
  54. char last_token[100];
  55. int last_tret;
  56. char *copyright = 0;
  57.  
  58. int last_align_begin=-1, last_align_end=-1;
  59. int generated_bytes = -1;
  60.  
  61. char strbuf[200];
  62. int strbuflen;
  63.  
  64. typedef struct {
  65.   short line;
  66.   short addr;
  67. } lineaddr_s;
  68.  
  69. lineaddr_s *lineaddr=0;
  70. int num_lineaddr=0;
  71. int max_lineaddr=0;
  72.  
  73. unsigned char *outbin = 0;
  74. int outsize = 0;
  75. int pc = 0;
  76. int bsspc = -1;
  77. int stack_ptr = 0;
  78. int start_ptr = 0;
  79. int movacc = 0;
  80.  
  81. typedef struct Symbol {
  82.   struct Symbol *next;
  83.   char *name;
  84.   int value;
  85.   int defined;
  86.   struct Patch *patches;
  87.   int first_used;
  88.   int type;
  89. } Symbol;
  90.  
  91. #define SYM_unknown    0
  92. #define SYM_abs        1
  93. #define SYM_data    2
  94. #define SYM_code    4
  95. #define SYMTYPES "?ADDTTTT"
  96.  
  97. #define REL_abs        0
  98. #define REL_abs32    1
  99. #define REL_16        2
  100. #define REL_8        3
  101.  
  102. typedef struct Patch {
  103.   struct Patch *next;
  104.   int location;
  105.   int lineno;
  106.   int rel;
  107. } Patch;
  108.  
  109. Symbol *symtab = 0;
  110. Symbol *get_symbol(char *name, int create);
  111. Symbol *set_symbol(Symbol *sym, int value);
  112. Symbol *zerosym;
  113.  
  114. struct {
  115.   int regs;
  116.   int offset;
  117.   int nsyms;
  118.   Symbol *syms[10];
  119. } _modrm = { 0, 0, 0 };
  120.  
  121. unsigned char sreg_overrides[] = {
  122.   0x26, 0x2e, 0x36, 0x3e, 0x64, 0x65
  123. };
  124.  
  125. void emit(void *v, int len);
  126. void emitb(int b);
  127. void emitw(int w);
  128. void emitd(long d);
  129. void emits(Symbol *s, int offset, int rel);
  130. void modrm(int mod, int reg, int rm);
  131. void reg(int reg);
  132. void sortsyms();
  133.  
  134. int istemp(char *symname, char which);
  135. void do_sreg_pop(int sreg);
  136. void do_sreg_push(int sreg);
  137. void do_align(int p2, int val);
  138. void set_lineaddr();
  139. void add_copyright(char *buf);
  140. void add_rcs_ident(char *buf);
  141.  
  142. void set_out_type(char *type);
  143. void set_image_type(char *type);
  144. void do_include(char *fname);
  145. void do_linkcoff(char *fname);
  146.  
  147. %}
  148.  
  149. %expect 2 /* see regmem */
  150.  
  151. %union {
  152.   Symbol *sym;
  153.   int i;
  154.   struct {
  155.     Symbol *sym;
  156.     int ofs;
  157.   } relsym;
  158. }
  159.  
  160. %type <sym> ID
  161. %type <relsym> constID
  162. %type <i> const offset
  163.  
  164. %token <sym> KID UID
  165.  
  166. %left OP_OR '|' '^'
  167. %left OP_AND '&'
  168. %nonassoc '=' '<' '>' OP_NE OP_LE OP_GE
  169. %left OP_SHL OP_SHR
  170. %left '+' '-'
  171. %left '*' '/' '%'
  172. %left OP_NEG OP_LNOT OP_NOT
  173.  
  174. %token <i> NUMBER REG8 REG16 REG32 SREG STRING PC CRREG DRREG TRREG
  175. %token <i> ARITH2 ARITH2B ARITH2D ARITH2W
  176. %token <i> LXS MOVSZX
  177. %token <i> JCC JCCL JCXZ LOOP SETCC
  178. %token <i> SHIFT SHLRD
  179. %token <i> ONEBYTE TWOBYTE ASCADJ
  180. %token <i> BITTEST GROUP3 GROUP3B GROUP3D GROUP3W GROUP6 GROUP7
  181. %token ALIGN
  182. %token BSS
  183. %token CALL CALLF COPYRIGHT
  184. %token DB DD DEC DECB DECD DECW DUP DW
  185. %token IN INC INCB INCD INCW INT INCLUDE
  186. %token JMPW JMPB JMPF
  187. %token LINKCOFF
  188. %token MOV MOVB MOVD MOVW
  189. %token IMUL IMULB IMULD IMULW
  190. %token ORG OUT
  191. %token POP POPW POPD PUSH PUSHW PUSHD
  192. %token RCS_ID RET RETF RETD RETFD
  193. %token STACK START
  194. %token TEST TESTB TESTD TESTW TYPE
  195. %token XCHG
  196.  
  197. %{
  198. #define NO_ATTR -1
  199.  
  200. struct opcode {
  201.   char *name;
  202.   int token;
  203.   int attr;
  204. };
  205.  
  206. struct opcode opcodes[] = {
  207.   "aaa", ONEBYTE, 0x37,
  208.   "aad", ASCADJ, 0xd5,
  209.   "aam", ASCADJ, 0xd4,
  210.   "aas", ONEBYTE, 0x3f,
  211.   "cbw", ONEBYTE, 0x98,
  212.   "cwde", TWOBYTE, 0x6698,
  213.   "clc", ONEBYTE, 0xf8,
  214.   "cld", ONEBYTE, 0xfc,
  215.   "cli", ONEBYTE, 0xfa,
  216.   "clts", TWOBYTE, 0x0f06,
  217.   "cmc", ONEBYTE, 0xf5,
  218.   "cmpsb", ONEBYTE, 0xa6,
  219.   "cmpsw", ONEBYTE, 0xa7,
  220.   "cmpsd", TWOBYTE, 0x66a7,
  221.   "cpuid", TWOBYTE, 0x0fa2,
  222.   "cwd", ONEBYTE, 0x99,
  223.   "cdq", TWOBYTE, 0x6699,
  224.   "daa", ONEBYTE, 0x27,
  225.   "das", ONEBYTE, 0x2f,
  226.   "hlt", ONEBYTE, 0xf4,
  227.   "insb", ONEBYTE, 0x6c,
  228.   "insw", ONEBYTE, 0x6d,
  229.   "insd", TWOBYTE, 0x666d,
  230.   "into", ONEBYTE, 0xce,
  231.   "iret", ONEBYTE, 0xcf,
  232.   "iretd", TWOBYTE, 0x66cf,
  233.   "lahf", ONEBYTE, 0x9f,
  234.   "leave", ONEBYTE, 0xc9,
  235.   "lock", ONEBYTE, 0xf0,
  236.   "lodsb", ONEBYTE, 0xac,
  237.   "lodsw", ONEBYTE, 0xad,
  238.   "lodsd", TWOBYTE, 0x66ad,
  239.   "movsb", ONEBYTE, 0xa4,
  240.   "movsw", ONEBYTE, 0xa5,
  241.   "movsd", TWOBYTE, 0x66a5,
  242.   "nop", ONEBYTE, 0x90,
  243.   "outsb", ONEBYTE, 0x6e,
  244.   "outsw", ONEBYTE, 0x6f,
  245.   "outsd", TWOBYTE, 0x666f,
  246.   "popa", ONEBYTE, 0x61,
  247.   "popad", TWOBYTE, 0x6661,
  248.   "popf", ONEBYTE, 0x9d,
  249.   "popfd", TWOBYTE, 0x669d,
  250.   "pusha", ONEBYTE, 0x60,
  251.   "pushad", TWOBYTE, 0x6660,
  252.   "pushf", ONEBYTE, 0x9c,
  253.   "pushfd", TWOBYTE, 0x669c,
  254.   "rep", ONEBYTE, 0xf3,
  255.   "repe", ONEBYTE, 0xf3,
  256.   "repz", ONEBYTE, 0xf3,
  257.   "repne", ONEBYTE, 0xf2,
  258.   "repnz", ONEBYTE, 0xf2,
  259.   "sahf", ONEBYTE, 0x9e,
  260.   "scasb", ONEBYTE, 0xae,
  261.   "scasw", ONEBYTE, 0xaf,
  262.   "scasd", TWOBYTE, 0x66af,
  263.   "stc", ONEBYTE, 0xf9,
  264.   "std", ONEBYTE, 0xfd,
  265.   "sti", ONEBYTE, 0xfb,
  266.   "stosb", ONEBYTE, 0xaa,
  267.   "stosw", ONEBYTE, 0xab,
  268.   "stosd", TWOBYTE, 0x66ab,
  269.   "wait", ONEBYTE, 0x9b,
  270.   "fwait", ONEBYTE, 0x9b,
  271.   "xlat", ONEBYTE, 0xd7,
  272.   "xlatb", ONEBYTE, 0xd7,
  273.  
  274.   ".addrsize", ONEBYTE, 0x67,
  275.   ".opsize", ONEBYTE, 0x66,
  276.   ".segcs", ONEBYTE, 0x2e,
  277.   ".segds", ONEBYTE, 0x3e,
  278.   ".seges", ONEBYTE, 0x26,
  279.   ".segss", ONEBYTE, 0x36,
  280.   ".segfs", ONEBYTE, 0x64,
  281.   ".seggs", ONEBYTE, 0x65,
  282.  
  283.   ".align", ALIGN, NO_ATTR,
  284.   ".bss", BSS, NO_ATTR,
  285.   ".copyright", COPYRIGHT, NO_ATTR,
  286.   ".db", DB, NO_ATTR,
  287.   ".dd", DD, NO_ATTR,
  288.   ".dup", DUP, NO_ATTR,
  289.   ".dw", DW, NO_ATTR,
  290.   ".id", RCS_ID, NO_ATTR,
  291.   ".include", INCLUDE, NO_ATTR,
  292.   ".linkcoff", LINKCOFF, NO_ATTR,
  293.   ".org", ORG, NO_ATTR,
  294.   ".stack", STACK, NO_ATTR,
  295.   ".start", START, NO_ATTR,
  296.   ".type", TYPE, NO_ATTR,
  297.  
  298.   "adc", ARITH2, 2,
  299.   "adcb", ARITH2B, 2,
  300.   "adcd", ARITH2D, 2,
  301.   "adcw", ARITH2W, 2,
  302.   "add", ARITH2, 0,
  303.   "addb", ARITH2B, 0,
  304.   "addd", ARITH2D, 0,
  305.   "addw", ARITH2W, 0,
  306.   "and", ARITH2, 4,
  307.   "andb", ARITH2B, 4,
  308.   "andd", ARITH2D, 4,
  309.   "andw", ARITH2W, 4,
  310.   "bt", BITTEST, 4,
  311.   "btc", BITTEST, 7,
  312.   "btr", BITTEST, 6,
  313.   "bts", BITTEST, 5,
  314.   "call", CALL, NO_ATTR,
  315.   "callf", CALLF, NO_ATTR,
  316.   "cmp", ARITH2, 7,
  317.   "cmpb", ARITH2B, 7,
  318.   "cmpd", ARITH2D, 7,
  319.   "cmpw", ARITH2W, 7,
  320.   "dec", DEC, NO_ATTR,
  321.   "decb", DECB, NO_ATTR,
  322.   "decd", DECD, NO_ATTR,
  323.   "decw", DECW, NO_ATTR,
  324.   "div", GROUP3, 6,
  325.   "divb", GROUP3B, 6,
  326.   "divd", GROUP3D, 6,
  327.   "divw", GROUP3W, 6,
  328.   "idiv", GROUP3, 7,
  329.   "idivb", GROUP3B, 7,
  330.   "idivd", GROUP3D, 7,
  331.   "idivw", GROUP3W, 7,
  332.   "imul", IMUL, NO_ATTR,
  333.   "imulb", IMULB, NO_ATTR,
  334.   "imuld", IMULD, NO_ATTR,
  335.   "imulw", IMULW, NO_ATTR,
  336.   "in", IN, NO_ATTR,
  337.   "inc", INC, NO_ATTR,
  338.   "incb", INCB, NO_ATTR,
  339.   "incd", INCD, NO_ATTR,
  340.   "incw", INCW, NO_ATTR,
  341.   "int", INT, NO_ATTR,
  342.  
  343.   "jo", JCC, 0,
  344.   "jno", JCC, 1,
  345.   "jb", JCC, 2,
  346.   "jc", JCC, 2,
  347.   "jnae", JCC, 2,
  348.   "jnb", JCC, 3,
  349.   "jnc", JCC, 3,
  350.   "jae", JCC, 3,
  351.   "jz", JCC, 4,
  352.   "je", JCC, 4,
  353.   "jnz", JCC, 5,
  354.   "jne", JCC, 5,
  355.   "jbe", JCC, 6,
  356.   "jna", JCC, 6,
  357.   "jnbe", JCC, 7,
  358.   "ja", JCC, 7,
  359.   "js", JCC, 8,
  360.   "jns", JCC, 9,
  361.   "jp", JCC, 10,
  362.   "jpe", JCC, 10,
  363.   "jnp", JCC, 11,
  364.   "jpo", JCC, 11,
  365.   "jl", JCC, 12,
  366.   "jnge", JCC, 12,
  367.   "jnl", JCC, 13,
  368.   "jge", JCC, 13,
  369.   "jle", JCC, 14,
  370.   "jng", JCC, 14,
  371.   "jnle", JCC, 15,
  372.   "jg", JCC, 15,
  373.  
  374.   "jol", JCCL, 0,
  375.   "jnol", JCCL, 1,
  376.   "jbl", JCCL, 2,
  377.   "jcl", JCCL, 2,
  378.   "jnael", JCCL, 2,
  379.   "jnbl", JCCL, 3,
  380.   "jncl", JCCL, 3,
  381.   "jael", JCCL, 3,
  382.   "jzl", JCCL, 4,
  383.   "jel", JCCL, 4,
  384.   "jnzl", JCCL, 5,
  385.   "jnel", JCCL, 5,
  386.   "jbel", JCCL, 6,
  387.   "jnal", JCCL, 6,
  388.   "jnbel", JCCL, 7,
  389.   "jal", JCCL, 7,
  390.   "jsl", JCCL, 8,
  391.   "jnsl", JCCL, 9,
  392.   "jpl", JCCL, 10,
  393.   "jpel", JCCL, 10,
  394.   "jnpl", JCCL, 11,
  395.   "jpol", JCCL, 11,
  396.   "jll", JCCL, 12,
  397.   "jngel", JCCL, 12,
  398.   "jnll", JCCL, 13,
  399.   "jgel", JCCL, 13,
  400.   "jlel", JCCL, 14,
  401.   "jngl", JCCL, 14,
  402.   "jnlel", JCCL, 15,
  403.   "jgl", JCCL, 15,
  404.  
  405.   "jcxz", JCXZ, 0,
  406.   "jecxz", JCXZ, 1,
  407.  
  408.   "jmp", JMPB, NO_ATTR,
  409.   "jmpf", JMPF, NO_ATTR,
  410.   "jmpl", JMPW, NO_ATTR,
  411.   "lds", LXS, 0xc5,
  412.   "les", LXS, 0xc4,
  413.   "lfs", LXS, 0x0fb4,
  414.   "lgs", LXS, 0x0fb5,
  415.   "lss", LXS, 0x0fb2,
  416.   "lgdt", GROUP7, 2,
  417.   "lidt", GROUP7, 3,
  418.   "lldt", GROUP6, 2,
  419.   "lmsw", GROUP7, 6,
  420.   "loop", LOOP, 0xe2,
  421.   "loope", LOOP, 0xe1,
  422.   "loopne", LOOP, 0xe0,
  423.   "loopnz", LOOP, 0xe0,
  424.   "loopz", LOOP, 0xe1,
  425.   "ltr", GROUP6, 3,
  426.   "mov", MOV, NO_ATTR,
  427.   "movb", MOVB, NO_ATTR,
  428.   "movd", MOVD, NO_ATTR,
  429.   "movw", MOVW, NO_ATTR,
  430.   "movsx", MOVSZX, 0xbe,
  431.   "movzx", MOVSZX, 0xb6,
  432.   "mul", GROUP3, 4,
  433.   "mulb", GROUP3B, 4,
  434.   "muld", GROUP3D, 4,
  435.   "mulw", GROUP3W, 4,
  436.   "not", GROUP3, 2,
  437.   "neg", GROUP3, 3,
  438.   "or", ARITH2, 1,
  439.   "orb", ARITH2B, 1,
  440.   "ord", ARITH2D, 1,
  441.   "orw", ARITH2W, 1,
  442.   "out", OUT, NO_ATTR,
  443.   "pop", POP, NO_ATTR,
  444.   "popw", POPW, NO_ATTR,
  445.   "popd", POPD, NO_ATTR,
  446.   "push", PUSH, NO_ATTR,
  447.   "pushw", PUSHW, NO_ATTR,
  448.   "pushd", PUSHD, NO_ATTR,
  449.   "rcl", SHIFT, 2,
  450.   "rcr", SHIFT, 3,
  451.   "ret", RET, NO_ATTR,
  452.   "retd", RETD, NO_ATTR,
  453.   "retf", RETF, NO_ATTR,
  454.   "retfd", RETFD, NO_ATTR,
  455.   "rol", SHIFT, 0,
  456.   "ror", SHIFT, 1,
  457.   "sar", SHIFT, 7,
  458.   "sbb", ARITH2, 3,
  459.   "sbbb", ARITH2B, 3,
  460.   "sbbd", ARITH2D, 3,
  461.   "sbbw", ARITH2W, 3,
  462.  
  463.   "seto", SETCC, 0,
  464.   "setno", SETCC, 1,
  465.   "setb", SETCC, 2,
  466.   "setc", SETCC, 2,
  467.   "setnae", SETCC, 2,
  468.   "setnb", SETCC, 3,
  469.   "setnc", SETCC, 3,
  470.   "setae", SETCC, 3,
  471.   "setz", SETCC, 4,
  472.   "sete", SETCC, 4,
  473.   "setnz", SETCC, 5,
  474.   "setne", SETCC, 5,
  475.   "setbe", SETCC, 6,
  476.   "setna", SETCC, 6,
  477.   "setnbe", SETCC, 7,
  478.   "seta", SETCC, 7,
  479.   "sets", SETCC, 8,
  480.   "setns", SETCC, 9,
  481.   "setp", SETCC, 10,
  482.   "setpe", SETCC, 10,
  483.   "setnp", SETCC, 11,
  484.   "setpo", SETCC, 11,
  485.   "setl", SETCC, 12,
  486.   "setnge", SETCC, 12,
  487.   "setnl", SETCC, 13,
  488.   "setge", SETCC, 13,
  489.   "setle", SETCC, 14,
  490.   "setng", SETCC, 14,
  491.   "setnle", SETCC, 15,
  492.   "setg", SETCC, 15,
  493.  
  494.   "sgdt", GROUP7, 0,
  495.   "sidt", GROUP7, 1,
  496.   "sldt", GROUP6, 0,
  497.   "sal", SHIFT, 4,
  498.   "shl", SHIFT, 4,
  499.   "shld", SHLRD, 0xa4,
  500.   "shr", SHIFT, 5,
  501.   "shrd", SHLRD, 0xac,
  502.   "smsw", GROUP7, 4,
  503.   "str", GROUP6, 1,
  504.   "sub", ARITH2, 5,
  505.   "subb", ARITH2B, 5,
  506.   "subd", ARITH2D, 5,
  507.   "subw", ARITH2W, 5,
  508.   "test", TEST, NO_ATTR,
  509.   "testb", TESTB, NO_ATTR,
  510.   "testw", TESTW, NO_ATTR,
  511.   "testd", TESTD, NO_ATTR,
  512.   "verr", GROUP6, 4,
  513.   "verw", GROUP6, 5,
  514.   "xchg", XCHG, NO_ATTR,
  515.   "xor", ARITH2, 6,
  516.   "xorb", ARITH2B, 6,
  517.   "xord", ARITH2D, 6,
  518.   "xorw", ARITH2W, 6,
  519.  
  520.   "al", REG8, 0,
  521.   "cl", REG8, 1,
  522.   "dl", REG8, 2,
  523.   "bl", REG8, 3,
  524.   "ah", REG8, 4,
  525.   "ch", REG8, 5,
  526.   "dh", REG8, 6,
  527.   "bh", REG8, 7,
  528.  
  529.   "es", SREG, 0,
  530.   "cs", SREG, 1,
  531.   "ss", SREG, 2,
  532.   "ds", SREG, 3,
  533.   "fs", SREG, 4,
  534.   "gs", SREG, 5,
  535.  
  536.   "ax", REG16, 0,
  537.   "cx", REG16, 1,
  538.   "dx", REG16, 2,
  539.   "bx", REG16, 3,
  540.   "sp", REG16, 4,
  541.   "bp", REG16, 5,
  542.   "si", REG16, 6,
  543.   "di", REG16, 7,
  544.  
  545.   "eax", REG32, 0,
  546.   "ecx", REG32, 1,
  547.   "edx", REG32, 2,
  548.   "ebx", REG32, 3,
  549.   "esp", REG32, 4,
  550.   "ebp", REG32, 5,
  551.   "esi", REG32, 6,
  552.   "edi", REG32, 7,
  553.  
  554.   "cr0", CRREG, 0,
  555.   "cr2", CRREG, 2,
  556.   "cr3", CRREG, 3,
  557.  
  558.   "dr0", DRREG, 0,
  559.   "dr1", DRREG, 1,
  560.   "dr2", DRREG, 2,
  561.   "dr3", DRREG, 3,
  562.   "dr6", DRREG, 6,
  563.   "dr7", DRREG, 7,
  564.  
  565.   "tr3", TRREG, 3,
  566.   "tr4", TRREG, 4,
  567.   "tr5", TRREG, 5,
  568.   "tr6", TRREG, 6,
  569.   "tr7", TRREG, 7};
  570. %}
  571.  
  572. %start lines
  573.  
  574. %% /***********************************************************************/
  575.  
  576. lines
  577.     :
  578.     | lines line '\n'        { lineno++; }
  579.     | lines INCLUDE STRING '\n'    { strbuf[strbuflen]=0; do_include(strbuf); }
  580.     | lines INCLUDE NUMBER '\n'    { strbuf[strbuflen]=0; do_include(strbuf); }
  581.     ;
  582.  
  583. line
  584.     :
  585.  
  586.     | ID ':'            { set_symbol($1, pc)->type |= (pc?SYM_data:SYM_code); }
  587.     | ID '=' const            { set_symbol($1, $3)->type = SYM_abs; }
  588.     | ID '=' PC offset        { set_symbol($1, pc + $4)->type = SYM_abs; }
  589.     | error
  590.  
  591.     | ONEBYTE            { emitb($1); }
  592.     | TWOBYTE            { emitb($1>>8); emitb($1 & 0xff); }
  593.  
  594.     | BSS                { bsspc = pc; generated_bytes = last_align_end == pc ? last_align_begin : pc; }
  595.  
  596.     | SREG ':'            { emitb(sreg_overrides[$1]); }
  597.  
  598.     | ARITH2B regmem ',' const    { emitb(0x80), reg($1); emitb($4); }
  599.     | ARITH2 REG8 ',' const        { if ($2)
  600.                           {emitb(0x80), modrm(3, $1, $2);}
  601.                       else
  602.                           modrm (0,$1,4); 
  603.                       emitb    ($4);
  604.                     }
  605.     | ARITH2 REG8 ',' REG8        { emitb($1*8); modrm(3, $4, $2); }
  606.     | ARITH2 regmem ',' REG8    { emitb($1*8); reg($4); }
  607.     | ARITH2 REG8 ',' regmem    { emitb($1*8+2); reg($2); }
  608.  
  609.     | ARITH2W regmem ',' constID    { emitb(0x81); reg($1); emits($4.sym,$4.ofs,REL_abs); }
  610.     | ARITH2 REG16 ',' constID    { if ($2)
  611.                           {emitb(0x81); modrm(3, $1, $2);}
  612.                       else
  613.                           modrm (0,$1,5);
  614.                       emits($4.sym,$4.ofs,REL_abs);
  615.                     }
  616.     | ARITH2 REG16 ',' REG16    { emitb($1*8+1); modrm(3, $4, $2); }
  617.     | ARITH2 regmem ',' REG16    { emitb($1*8+1); reg($4); }
  618.     | ARITH2 REG16 ',' regmem    { emitb($1*8+3); reg($2); }
  619.  
  620.     | ARITH2D regmem ',' constID    { emitb(0x66); emitb(0x81); reg($1); emits($4.sym,$4.ofs,REL_abs); emitw($4.ofs >> 16); }
  621.     | ARITH2 REG32 ',' constID    { emitb(0x66);
  622.                       if ($2)
  623.                           {emitb(0x81); modrm(3, $1, $2);}
  624.                       else
  625.                           modrm (0,$1,5);
  626.                       emits($4.sym,$4.ofs,REL_abs);    emitw($4.ofs >>    16); }
  627.     | ARITH2 REG32 ',' REG32    { emitb(0x66); emitb($1*8+1); modrm(3, $4, $2); }
  628.     | ARITH2 regmem ',' REG32    { emitb(0x66); emitb($1*8+1); reg($4); }
  629.     | ARITH2 REG32 ',' regmem    { emitb(0x66); emitb($1*8+3); reg($2); }
  630.  
  631.     | ASCADJ            { emitb($1); emitb(0x0a); }
  632.     | ASCADJ const            { emitb($1); emitb($2); }
  633.  
  634.     | ALIGN const            { do_align($2,0x90); }
  635.     | ALIGN const ',' const        { do_align($2,$4); }
  636.  
  637.     | BITTEST REG16 ',' REG16    { emitb(0x0f); emitb($1*8+0x83); modrm(3, $4, $2); }
  638.     | BITTEST regmem ',' REG16    { emitb(0x0f); emitb($1*8+0x83); reg($4); }
  639.     | BITTEST REG32 ',' REG32    { emitb(0x66); emitb(0x0f); emitb($1*8+0x83); modrm(3, $4, $2); }
  640.     | BITTEST regmem ',' REG32    { emitb(0x66); emitb(0x0f); emitb($1*8+0x83); reg($4); }
  641.     | BITTEST REG16 ',' const    { emitb(0x0f); emitb(0xba); modrm(3, $1, $2); emitb($4); }
  642.     | BITTEST regmem ',' const    { emitb(0x0f); emitb(0xba); reg($1); emitb($4); }
  643.     | BITTEST REG32 ',' const    { emitb(0x66); emitb(0x0f); emitb(0xba); modrm(3, $1, $2); emitb($4); }
  644.  
  645.     | CALL ID            { emitb(0xe8); emits($2,0,REL_16); $2->type |= SYM_code; }
  646.     | CALLF regmem            { emitb(0xff); reg(3); }
  647.  
  648.     | COPYRIGHT STRING        { strbuf[strbuflen] = 0; add_copyright(strbuf); }
  649.     | RCS_ID            { strbuf[strbuflen] = 0; add_rcs_ident(strbuf); }
  650.  
  651.     | DB dblist
  652.     | DW dwlist
  653.     | DD ddlist
  654.  
  655.     | DEC REG8            { emitb(0xfe); modrm(3, 1, $2); }
  656.     | DECB regmem            { emitb(0xfe); reg(1); }
  657.     | DEC REG16            { emitb(0x48 + $2); }
  658.     | DEC REG32            { emitb(0x66); emitb(0x48 + $2); }
  659.     | DECW regmem            { emitb(0xff); reg(1); }
  660.     | DECD regmem            { emitb(0x66); emitb(0xff); reg(1); }
  661.  
  662.     | IN REG8 ',' const        { emitb(0xe4); emitb($4); }
  663.     | IN REG16 ',' const        { emitb(0xe5); emitb($4); }
  664.     | IN REG32 ',' const        { emitb(0x66); emitb(0xe5); emitb($4);}
  665.     | IN REG8 ',' REG16        { emitb(0xec); }
  666.     | IN REG16 ',' REG16        { emitb(0xed); }
  667.     | IN REG32 ',' REG16        { emitb(0x66); emitb(0xed); }
  668.  
  669.     | INC REG8            { emitb(0xfe); modrm(3, 0, $2); }
  670.     | INCB regmem            { emitb(0xfe); reg(0); }
  671.     | INC REG16            { emitb(0x40 + $2); }
  672.     | INC REG32            { emitb(0x66); emitb(0x40 + $2); }
  673.     | INCW regmem            { emitb(0xff); reg(0); }
  674.     | INCD regmem            { emitb(0x66); emitb(0xff); reg(0); }
  675.  
  676.     | IMUL REG8            { emitb(0xf6); modrm(3, 5, $2); }
  677.     | IMULB regmem            { emitb(0xf6); reg(5); }
  678.     | IMUL REG16            { emitb(0xf7); modrm(3, 5, $2); }
  679.     | IMULW regmem            { emitb(0xf7); reg(5); }
  680.     | IMUL REG32            { emitb(0x66); emitb(0xf7); modrm(3, 5, $2); }
  681.     | IMULD regmem            { emitb(0x66); emitb(0xf7); reg(5); }
  682.     | IMUL REG16 ',' REG16        { emitb(0x0f); emitb(0xaf); modrm(3, $2, $4);}
  683.     | IMUL REG32 ',' REG32        { emitb(0x66); emitb(0x0f); emitb(0xaf); modrm(3, $2, $4);}
  684.     | IMUL REG16 ',' regmem        { emitb(0x0f); emitb(0xaf); reg($2); }
  685.     | IMUL REG32 ',' regmem        { emitb(0x66); emitb(0x0f); emitb(0xaf); reg($2); }
  686.     | IMUL REG16 ',' regmem ',' const { if ($6>=-128 && $6<=127)
  687.                           emitb(0x6b);
  688.                       else
  689.                           emitb(0x69);
  690.                       reg($2);
  691.                       if ($6>=-128 && $6<=127)
  692.                           emitb($6);
  693.                       else
  694.                           emitw($6);
  695.                     }
  696.     | IMUL REG32 ',' regmem ',' const { emitb(0x66);
  697.                       if ($6>=-128 && $6<=127)
  698.                           emitb(0x6b);
  699.                       else
  700.                           emitb(0x69);
  701.                       reg($2);
  702.                       if ($6>=-128 && $6<=127)
  703.                           emitb($6&0xff);
  704.                       else
  705.                           emitd($6);
  706.                     }
  707.  
  708.     | GROUP3 REG8            { emitb(0xf6); modrm(3, $1, $2); }
  709.     | GROUP3B regmem        { emitb(0xf6); reg($1); }
  710.     | GROUP3 REG16            { emitb(0xf7); modrm(3, $1, $2); }
  711.     | GROUP3W regmem        { emitb(0xf7); reg($1); }
  712.     | GROUP3 REG32            { emitb(0x66); emitb(0xf7); modrm(3, $1, $2); }
  713.     | GROUP3D regmem        { emitb(0x66); emitb(0xf7); reg($1); }
  714.  
  715.     | GROUP6 regmem            { emitb(0x0f); emitb(0x00); reg($1); }
  716.     | GROUP6 REG16            { emitb(0x0f); emitb(0x00); modrm(3, $1, $2); }
  717.     | GROUP7 regmem            { emitb(0x0f); emitb(0x01); reg($1); }
  718.     | GROUP7 REG16            { emitb(0x0f); emitb(0x01); modrm(3, $1, $2); }
  719.  
  720.     | INT const            { if ($2 == 3) emitb(0xcc); else emitb(0xcd), emitb($2); }
  721.  
  722.     | JCC ID                   { emitb(0x70+$1); emits($2,0,REL_8); $2->type |= SYM_code; }
  723.     | JCCL ID            { emitb(0x0f); emitb(0x80+$1); emits($2,0,REL_16); $2->type |= SYM_code; }
  724.  
  725.     | JCXZ ID            { if ($1) emitb(0x66); emitb(0xe3); emits($2,0,REL_8); $2->type |= SYM_code; }
  726.  
  727.     | JMPW ID            { emitb(0xe9); emits($2,0,REL_16); $2->type |= SYM_code; }
  728.     | JMPB ID            { emitb(0xeb); emits($2,0,REL_8); $2->type |= SYM_code; }
  729.     | JMPF regmem            { emitb(0xff); reg(5); }
  730.     | JMPF const ':' constID    { emitb(0xea); emits($4.sym,$4.ofs,REL_abs); emitw($2); }
  731.  
  732.     | LINKCOFF STRING        { strbuf[strbuflen]=0; do_linkcoff(strbuf); }
  733.     | LOOP ID            { emitb($1); emits($2,0,REL_8); }
  734.  
  735.     | LXS REG16 ',' regmem        { if ($1>>8) emitb($1>>8); emitb($1 & 0xff); reg($2); }
  736.     | LXS REG32 ',' regmem        { emitb(0x66); if ($1>>8) emitb($1>>8); emitb($1 & 0xff); reg($2); }
  737.  
  738.     | MOVB regmem ',' const        { emitb(0xc6), reg(0); emitb($4); }
  739.     | MOV REG8 ',' const        { emitb(0xb0+$2); emitb($4); }
  740.     | MOV REG8 ',' REG8        { emitb(0x88), modrm(3, $4, $2); }
  741.     | MOV regmem ',' REG8        { if ($4==0 && _modrm.regs==0)
  742.                           movacc=0xa2;
  743.                       else
  744.                           emitb(0x88); 
  745.                       reg($4); 
  746.                     }
  747.     | MOV REG8 ',' regmem        { if ($2==0 && _modrm.regs==0)
  748.                           movacc=0xa0;
  749.                       else
  750.                           emitb(0x8a);
  751.                       reg($2);
  752.                     }
  753.     | MOVW regmem ',' constID    { emitb(0xc7); reg(0); emits($4.sym,$4.ofs,REL_abs); }
  754.     | MOV REG16 ',' constID        { emitb(0xb8+$2); emits($4.sym,$4.ofs,REL_abs); }
  755.     | MOV REG16 ',' REG16        { emitb(0x89); modrm(3, $4, $2); }
  756.     | MOV regmem ',' REG16        { if ($4==0 && _modrm.regs==0)
  757.                           movacc=0xa3;
  758.                       else
  759.                           emitb(0x89);
  760.                       reg($4); 
  761.                     }
  762.     | MOV REG16 ','    regmem        { if ($2==0 && _modrm.regs==0)
  763.                           movacc=0xa1;
  764.                       else
  765.                           emitb(0x8b);
  766.                       reg($2);
  767.                     }
  768.     | MOVD regmem ',' constID    { emitb(0x66); emitb(0xc7); reg(0); emits($4.sym,$4.ofs,REL_abs); emitw($4.ofs >> 16); }
  769.     | MOV REG32 ',' constID        { emitb(0x66); emitb(0xb8+$2); emits($4.sym,$4.ofs,REL_abs); emitw($4.ofs >> 16); }
  770.     | MOV REG32 ',' REG32        { emitb(0x66); emitb(0x89); modrm(3, $4, $2); }
  771.     | MOV regmem ',' REG32        { emitb(0x66);
  772.                       if ($4==0 && _modrm.regs==0)
  773.                           movacc=0xa3;
  774.                       else
  775.                           emitb(0x89);
  776.                       reg($4);
  777.                     }
  778.     | MOV REG32 ','    regmem        { emitb(0x66);
  779.                       if ($2==0 && _modrm.regs==0)
  780.                           movacc=0xa1;
  781.                       else
  782.                           emitb(0x8b);
  783.                       reg($2);
  784.                     }
  785.     | MOV regmem ',' SREG        { emitb(0x8c); reg($4); }
  786.     | MOV REG16 ',' SREG        { emitb(0x8c); modrm(3, $4, $2); }
  787.     | MOV SREG ',' regmem        { emitb(0x8e); reg($2); }
  788.     | MOV SREG ',' REG16        { emitb(0x8e); modrm(3, $2, $4); }
  789.  
  790.     | MOV CRREG ',' REG32        { emitb(0x0f); emitb(0x22); modrm(3, $2, $4); }
  791.     | MOV DRREG ',' REG32        { emitb(0x0f); emitb(0x23); modrm(3, $2, $4); }
  792.     | MOV TRREG ',' REG32        { emitb(0x0f); emitb(0x26); modrm(3, $2, $4); }
  793.     | MOV REG32 ',' CRREG        { emitb(0x0f); emitb(0x20); modrm(3, $4, $2); }
  794.     | MOV REG32 ',' DRREG        { emitb(0x0f); emitb(0x21); modrm(3, $4, $2); }
  795.     | MOV REG32 ',' TRREG        { emitb(0x0f); emitb(0x24); modrm(3, $4, $2); }
  796.  
  797.     | MOVSZX REG16 ',' REG8        { emitb(0x0f); emitb($1); modrm(3, $2, $4); }
  798.     | MOVSZX REG32 ',' REG8        { emitb(0x66); emitb(0x0f); emitb($1); modrm(3, $2, $4); }
  799.     | MOVSZX REG32 ',' REG16    { emitb(0x66); emitb(0x0f); emitb($1+1); modrm(3, $2, $4); }
  800.  
  801.     | ORG const            { if (pc > $2) yyerror ("Backwards org directive"); else while (pc < $2) emitb(0x90); }
  802.     | ORG const ',' const        { if (pc > $2) yyerror ("Backwards org directive"); else while (pc < $2) emitb($4); }
  803.  
  804.     | OUT const ',' REG8        { emitb(0xe6); emitb($2); }
  805.     | OUT const ',' REG16        { emitb(0xe7); emitb($2); }
  806.     | OUT const ',' REG32        { emitb(0x66); emitb(0xe7); emitb($2);}
  807.     | OUT REG16 ',' REG8        { emitb(0xee); }
  808.     | OUT REG16 ',' REG16        { emitb(0xef); }
  809.     | OUT REG16 ',' REG32        { emitb(0x66); emitb(0xef); }
  810.  
  811.     | POP REG16            { emitb(0x58 + $2); }
  812.     | POP REG32            { emitb(0x66); emitb(0x58 + $2); }
  813.     | POP SREG            { do_sreg_pop($2); }
  814.     | POPW regmem            { emitb(0x8f); reg(0); }
  815.     | POPD regmem            { emitb(0x66); emitb(0x8f); reg(0); }
  816.     | PUSH REG16            { emitb(0x50 + $2); }
  817.     | PUSH REG32            { emitb(0x66); emitb(0x50 + $2); }
  818.     | PUSH SREG            { do_sreg_push($2); }
  819.     | PUSHW regmem            { emitb(0xff); reg(6); }
  820.     | PUSHD regmem            { emitb(0x66); emitb(0xff); reg(6); }
  821.     | PUSHW constID            { emitb(0x68); emits($2.sym,$2.ofs,REL_abs); }
  822.     | PUSHD constID            { emitb(0x66); emitb(0x68); emits($2.sym,$2.ofs,REL_abs); emitw($2.ofs >> 16); }
  823.  
  824.     | RET                { emitb(0xc3); }
  825.     | RET const            { emitb(0xc2); emitw($2); }
  826.     | RETF                { emitb(0xcb); }
  827.     | RETF const            { emitb(0xca); emitw($2); }
  828.     | RETD                { emitb(0x66); emitb(0xc3); }
  829.     | RETD const            { emitb(0x66); emitb(0xc2); emitd($2); }
  830.     | RETFD                { emitb(0x66); emitb(0xcb); }
  831.     | RETFD const            { emitb(0x66); emitb(0xca); emitd($2); }
  832.  
  833.     | SETCC REG8            { emitb(0x0f); emitb(0x90+$1); modrm(3, 0, $2); }
  834.     | SETCC regmem            { emitb(0x0f); emitb(0x90+$1); reg(0); }
  835.  
  836.     | SHIFT REG8 ',' const        { emitb($4 == 1 ? 0xd0 : 0xc0); modrm(3, $1, $2); if ($4 != 1) emitb($4); }
  837.     | SHIFT REG8 ',' REG8        { if ($4 != 1) yyerror ("Non-constant shift count must be `cl'"); emitb(0xd2); modrm(3, $1, $2); }
  838.     | SHIFT REG16 ',' const           { emitb($4 == 1 ? 0xd1 : 0xc1); modrm(3, $1, $2); if ($4 != 1) emitb($4); }
  839.     | SHIFT REG16 ',' REG8        { if ($4 != 1) yyerror ("Non-constant shift count must be `cl'"); emitb(0xd3); modrm(3, $1, $2); }
  840.     | SHIFT REG32 ',' const           { emitb(0x66); emitb($4 == 1 ? 0xd1 : 0xc1); modrm(3, $1, $2); if ($4 != 1) emitb($4); }
  841.     | SHIFT REG32 ',' REG8        { if ($4 != 1) yyerror ("Non-constant shift count must be `cl'"); emitb(0x66); emitb(0xd3); modrm(3, $1, $2); }
  842.  
  843.     | SHLRD REG16 ',' REG16 ',' const
  844.       { emitb(0x0f); emitb($1); modrm(3, $4, $2); emitb($6); }
  845.     | SHLRD REG16 ',' REG16 ',' REG8
  846.       { if ($6 != 1) yyerror ("Non-constant shift count must be `cl'");
  847.         emitb(0x0f); emitb($1+1); modrm(3, $4, $2); }
  848.  
  849.     | STACK                { stack_ptr = pc; }
  850.     | START                { start_ptr = pc; }
  851.  
  852.     | TESTB regmem ',' const    { emitb(0xf6), reg(0); emitb($4); }
  853.     | TEST REG8 ',' const        { emitb(0xf6), modrm(3, 0, $2); emitb($4); }
  854.     | TEST REG8 ',' REG8        { emitb(0x84), modrm(3, $4, $2); }
  855.     | TEST regmem ',' REG8        { emitb(0x84), reg($4); }
  856.     | TEST REG8 ',' regmem        { emitb(0x84), reg($2); }
  857.  
  858.     | TESTW regmem ',' constID    { emitb(0xf7); reg(0); emits($4.sym,$4.ofs,REL_abs); }
  859.     | TEST REG16 ',' constID    { emitb(0xf7); modrm(3, 0, $2); emits($4.sym,$4.ofs,REL_abs); }
  860.     | TEST REG16 ',' REG16        { emitb(0x85); modrm(3, $4, $2); }
  861.     | TEST regmem ',' REG16        { emitb(0x85); reg($4); }
  862.     | TEST REG16 ',' regmem        { emitb(0x85); reg($2); }
  863.  
  864.     | TESTD regmem ',' constID    { emitb(0x66); emitb(0xf7); reg(0); emits($4.sym,$4.ofs,REL_abs); emitw($4.ofs >> 16); }
  865.     | TEST REG32 ',' constID    { emitb(0x66); emitb(0xf7); modrm(3, 0, $2); emits($4.sym,$4.ofs,REL_abs); emitw($4.ofs >> 16); }
  866.     | TEST REG32 ',' REG32        { emitb(0x66); emitb(0x85); modrm(3, $4, $2); }
  867.     | TEST regmem ',' REG32        { emitb(0x66); emitb(0x85); reg($4); }
  868.     | TEST REG32 ',' regmem        { emitb(0x66); emitb(0x85); reg($2); }
  869.  
  870.     | TYPE STRING            { strbuf[strbuflen] = 0; set_image_type(strbuf); }
  871.     | TYPE NUMBER            { if ($2 == 'h') set_out_type("h"); }
  872.  
  873.     | XCHG REG8 ',' REG8        { emitb(0x86); modrm(3, $2, $4); }
  874.     | XCHG REG8 ',' regmem        { emitb(0x86); reg($2); }
  875.     | XCHG regmem ',' REG8        { emitb(0x86); reg($4); }
  876.     | XCHG REG16 ',' REG16        { if (($2==0) ^    ($4==0))
  877.                           emitb(0x90+$2+$4);
  878.                       else
  879.                           {emitb(0x87); modrm(3, $2, $4); }
  880.                     }      
  881.     | XCHG REG16 ',' regmem        { emitb(0x87); reg($2); }
  882.     | XCHG regmem ',' REG16        { emitb(0x87); reg($4); }
  883.     | XCHG REG32 ',' REG32        { emitb(0x66);
  884.                       if (($2==0) ^    ($4==0))
  885.                           emitb(0x90+$2+$4);
  886.                       else
  887.                           {emitb(0x87); modrm(3, $2, $4); }
  888.                     }
  889.     | XCHG REG32 ',' regmem        { emitb(0x66); emitb(0x87); reg($2); }
  890.     | XCHG regmem ',' REG32        { emitb(0x66); emitb(0x87); reg($4); }
  891.     ;
  892.  
  893. dbitem
  894.     : const                { emitb($1); }
  895.     | STRING            { emit(strbuf, strbuflen); }
  896.     | const DUP const        { for (i=0; i<$1; i++) emitb($3); }
  897.     ;
  898.  
  899. dblist
  900.     : dbitem
  901.     | dblist ',' dbitem
  902.     ;
  903.  
  904. dwitem
  905.     : const                { emitw($1); }
  906.     | UID offset            { emits($1,$2,REL_abs); }
  907.     | const DUP const        { for (i=0; i<$1; i++) emitw($3); }
  908.     ;
  909.  
  910. dwlist
  911.     : dwitem
  912.     | dwlist ',' dwitem
  913.     ;
  914.  
  915. dditem
  916.     : const                { emitd($1); }
  917.     | UID offset            { emits($1,$2,REL_abs); emitw(0); }
  918.     | const DUP const        { for (i=0; i<$1; i++) emitd($3); }
  919.     ;
  920.  
  921. ddlist
  922.     : dditem
  923.     | ddlist ',' dditem
  924.     ;
  925.  
  926. regmem
  927.     : regmemitem '[' regmemexpr ']'
  928.     | '[' regmemexpr ']'
  929.     | SREG ':' '[' regmemexpr ']'    { emitb(sreg_overrides[$1]); }
  930.     ;
  931.  
  932. regmemexpr
  933.     : regmemitem
  934.     | regmemexpr '+' regmemexpr
  935.      | regmemexpr '-' const        { _modrm.offset -= $3; }
  936.     ;
  937.  
  938. regmemitem
  939.     : SREG ':' regmemitem        { emitb(sreg_overrides[$1]); }
  940.     | REG16                { _modrm.regs |= (1<<$1); }
  941.     | UID                { _modrm.syms[_modrm.nsyms++] = $1; }
  942.     | const                { _modrm.offset += $1; }
  943.     ;
  944.  
  945. const
  946.     : NUMBER            { $$ = $1; }
  947.     | KID                { $$ = $1->value; }
  948.     | const OP_OR const        { $$ = $1 || $3; }
  949.     | const '|' const        { $$ = $1 | $3; }
  950.     | const '^' const        { $$ = $1 ^ $3; }
  951.     | const OP_AND const        { $$ = $1 && $3; }
  952.     | const '&' const        { $$ = $1 & $3; }
  953.     | const '=' const        { $$ = $1 == $3; }
  954.     | const '>' const        { $$ = $1 > $3; }
  955.     | const '<' const        { $$ = $1 < $3; }
  956.     | const OP_GE const        { $$ = $1 >= $3; }
  957.     | const OP_LE const        { $$ = $1 <= $3; }
  958.     | const OP_NE const        { $$ = $1 != $3; }
  959.     | const OP_SHL const        { $$ = $1 << $3; }
  960.     | const OP_SHR const        { $$ = $1 >> $3; }
  961.     | const '+' const        { $$ = $1 + $3; }
  962.     | const '-' const        { $$ = $1 - $3; }
  963.     | const '*' const        { $$ = $1 * $3; }
  964.     | const '/' const        { $$ = $1 / $3; }
  965.     | const '%' const        { $$ = $1 % $3; }
  966.     | '-' const %prec OP_NEG    { $$ = -$2; }
  967.     | '!' const %prec OP_NOT    { $$ = !$2; }
  968.     | '~' const %prec OP_LNOT    { $$ = ~$2; }
  969.     | '(' const ')'            { $$ = $2; }
  970.     ;
  971.  
  972. ID
  973.     : KID                { $$ = $1; }
  974.     | UID                { $$ = $1; }
  975.     ;
  976.  
  977. constID
  978.     : UID offset            { $$.sym = $1; $$.ofs = $2; }
  979.     | const                { $$.sym = zerosym; $$.ofs = $1; }
  980.     ;
  981.  
  982. offset
  983.     : '+' const            { $$ = $2; }
  984.     | '-' const            { $$ = -$2; }
  985.     |                 { $$ = 0; }
  986.     ;
  987. %% /***********************************************************************/
  988.  
  989. typedef struct FileStack {
  990.   struct FileStack *prev;
  991.   FILE *f;
  992.   int line;
  993.   char *name;
  994. } FileStack;
  995.  
  996. FileStack *file_stack = 0;
  997.  
  998. FILE *infile;
  999. FILE *outfile;
  1000.  
  1001. int scmp_a(void const *a, void const *b)
  1002. {
  1003.   return strcmp((*(Symbol **)a)->name, (*(Symbol **)b)->name);
  1004. }
  1005.  
  1006. int scmp_n(void const *a, void const *b)
  1007. {
  1008.   return (*(Symbol **)a)->value - (*(Symbol **)b)->value;
  1009. }
  1010.  
  1011. static int
  1012. opcode_compare (const void *e1, const void *e2)
  1013. {
  1014.   return strcmp (((struct opcode *)e1)->name, ((struct opcode *)e2)->name);
  1015. }
  1016.  
  1017. main(int argc, char **argv)
  1018. {
  1019.   Symbol *s;
  1020.   Patch *p;
  1021.   unsigned char exe[EXE_HEADER_SIZE+4];
  1022.   int undefs=0;
  1023.   int symcount = 0;
  1024.   int min_uninit;
  1025.   time_t now;
  1026.   char *outfilename, *leader;
  1027.  
  1028.   /* Sort the opcodes now so that we can use `bsearch' later.  */
  1029.   qsort (opcodes,
  1030.      sizeof (opcodes) / sizeof (opcodes[0]),
  1031.      sizeof (opcodes[0]),
  1032.      opcode_compare);
  1033.   zerosym = set_symbol (get_symbol ("__zero__", 1), 0);
  1034.  
  1035.   if (argc < 2)
  1036.   {
  1037.     printf("usage: djasm infile [outfile] [mapfile]\n");
  1038.     exit(1);
  1039.   }
  1040.   inname = argv[1];
  1041.   infile = fopen(argv[1], "r");
  1042.   if (infile == 0)
  1043.   {
  1044.     fprintf(stderr, "Error: cannot open file %s for reading\n", argv[1]);
  1045.     perror("The error was");
  1046.     exit(1);
  1047.   }
  1048.   yyparse();
  1049.   fclose(infile);
  1050.   if (bsspc == -1)
  1051.   {
  1052.     bsspc = pc;
  1053.     generated_bytes = last_align_end==pc ? last_align_begin : pc;
  1054.   }
  1055.  
  1056.   sortsyms(scmp_a);
  1057.  
  1058.   for (s=symtab; s; s=s->next)
  1059.   {
  1060.     if (!istemp(s->name, 0))
  1061.       symcount++;
  1062.     if (!s->defined && s->patches)
  1063.     {
  1064.       fprintf(stderr, "Undefined symbol `%s', first used on line %d\n", s->name, s->first_used);
  1065.       for (p=s->patches; p; p=p->next)
  1066.         printf("\treferenced on line %d\n", p->lineno);
  1067.       undefs++;
  1068.     }
  1069.   }
  1070.   if (undefs)
  1071.     return 1;
  1072.   if (total_errors)
  1073.   {
  1074.     fprintf(stderr, "%d errors\n", total_errors);
  1075.     return 1;
  1076.   }
  1077.  
  1078.   printf("%#x bytes generated, %#x bytes in file, %#x bytes total, %d symbols\n",
  1079.     generated_bytes, bsspc, pc, symcount);
  1080.  
  1081.   min_uninit = (pc-bsspc+15)/16;
  1082.  
  1083.   memset(exe, 0, EXE_HEADER_SIZE+4);
  1084.   exe[0] = 0x4d;        /* MAGIC */
  1085.   exe[1] = 0x5a;
  1086.   exe[2] = bsspc;        /* bytes in last page */
  1087.   exe[3] = (bsspc>>8)&1;
  1088.   exe[4] = (bsspc+1023)>>9;    /* number of sectors */
  1089.   exe[5] = (bsspc+1023)>>17;
  1090.   exe[6] = 0;            /* relocation entries */
  1091.   exe[7] = 0;
  1092.   exe[8] = EXE_HEADER_BLOCKS;    /* blocks in header */
  1093.   exe[9] = 0;
  1094.   exe[10] = min_uninit;        /* min uninitialized paragraphs */
  1095.   exe[11] = (min_uninit>>8);
  1096.   exe[12] = 0xff;        /* max uninitialized paragraphs */
  1097.   exe[13] = 0xff;
  1098.   exe[14] = 0;            /* relative SS */
  1099.   exe[15] = 0;
  1100.   exe[16] = stack_ptr;        /* SP */
  1101.   exe[17] = stack_ptr>>8;
  1102.   exe[18] = 0;            /* checksum */
  1103.   exe[19] = 0;
  1104.   exe[20] = start_ptr;        /* IP */
  1105.   exe[21] = start_ptr >> 8;
  1106.   exe[22] = 0;            /* relative CS */
  1107.   exe[23] = 0;
  1108.  
  1109.   time(&now);
  1110.   sprintf(exe+24, "\r\n%s generated from %s by djasm, on %.24s\r\n", argv[2], argv[1], ctime(&now));
  1111.   if (copyright)
  1112.     strncat(exe+32, copyright, 480-strlen(exe+32));
  1113.   strcat(exe+32, "\r\n\032");
  1114.  
  1115.   if (argv[2] == 0)
  1116.   {
  1117.     char *dot=0, *sl=0, *cp;
  1118.     outfilename = (char *)malloc(strlen(argv[1])+5);
  1119.     strcpy(outfilename, argv[1]);
  1120.     for (cp=outfilename; *cp; cp++)
  1121.     {
  1122.       if (*cp == ':' || *cp == '\\' || *cp == '/')
  1123.       {
  1124.         sl = cp+1;
  1125.         dot = 0;
  1126.       }
  1127.       if (*cp == '.')
  1128.         dot = cp;
  1129.     }
  1130.     if (!dot)
  1131.     {
  1132.       dot = cp;
  1133.       *dot = '.';
  1134.     }
  1135.     strcpy(dot+1, ext_types[out_type]);
  1136.   }
  1137.   else
  1138.   {
  1139.     char *dot=0, *sl=0, *cp;
  1140.     outfilename = argv[2];
  1141.     for (cp=outfilename; *cp; cp++)
  1142.     {
  1143.       if (*cp == ':' || *cp == '\\' || *cp == '/')
  1144.       {
  1145.         sl = cp+1;
  1146.         dot = 0;
  1147.       }
  1148.       if (*cp == '.')
  1149.         dot = cp;
  1150.     }
  1151.     if (!dot)
  1152.     {
  1153.       sl = (char *)malloc(strlen(outfilename)+5);
  1154.       strcpy(sl, outfilename);
  1155.       outfilename = sl;
  1156.       dot = outfilename + strlen(outfilename);
  1157.       *dot = '.';
  1158.       strcpy(dot+1, ext_types[out_type]);
  1159.     }
  1160.     else
  1161.       set_out_type(dot+1);
  1162.   }
  1163.  
  1164.   switch (out_type)
  1165.   {
  1166.     case OUT_exe:
  1167.     case OUT_com:
  1168.     case OUT_bin:
  1169.       outfile = fopen(outfilename, "wb");
  1170.       break;
  1171.     case OUT_h:
  1172.     case OUT_inc:
  1173.     case OUT_s:
  1174.       outfile = fopen(outfilename, "w");
  1175.       break;
  1176.   }
  1177.   if (outfile == 0)
  1178.   {
  1179.     fprintf(stderr, "Error: cannot open file %s for writing\n", outfilename);
  1180.     perror("The error was");
  1181.     exit(1);
  1182.   }
  1183.  
  1184.   switch (out_type)
  1185.   {
  1186.     case OUT_exe:
  1187.       fwrite(exe, EXE_HEADER_SIZE, 1, outfile);
  1188.       fwrite(outbin, bsspc, 1, outfile);
  1189.       break;
  1190.  
  1191.     case OUT_com:
  1192.       fwrite(outbin+256, bsspc-256, 1, outfile);
  1193.       break;
  1194.  
  1195.     case OUT_bin:
  1196.       fwrite(outbin, bsspc, 1, outfile);
  1197.       break;
  1198.  
  1199.     case OUT_h:
  1200.       if (image_type == OUT_exe)
  1201.         for (i=0; i<EXE_HEADER_SIZE; i++)
  1202.         {
  1203.           fprintf(outfile, "0x%02x,", exe[i]);
  1204.           if ((i&15) == 15)
  1205.             fputc('\n', outfile);
  1206.         }
  1207.       for (i=((image_type==OUT_com)?0x100:0); i<bsspc; i++)
  1208.       {
  1209.         fprintf(outfile, "0x%02x", outbin[i]);
  1210.         if (i<bsspc-1)
  1211.           fputc(',', outfile);
  1212.         if ((i&15) == 15)
  1213.           fputc('\n', outfile);
  1214.       }
  1215.       if (i&15)
  1216.         fputc('\n', outfile);
  1217.       break;
  1218.  
  1219.     case OUT_inc:
  1220.     case OUT_s:
  1221.       if (out_type == OUT_inc)
  1222.         leader = INC_LEADER;
  1223.       else
  1224.         leader = S_LEADER;
  1225.       if (image_type == OUT_exe)
  1226.         for (i=0; i<EXE_HEADER_SIZE; i++)
  1227.         {
  1228.       if ((i%15) == 0)
  1229.         fputs(leader, outfile);
  1230.           fprintf(outfile, "0x%02x", exe[i]);
  1231.           if ((i&15) == 15)
  1232.           {
  1233.             fputc('\n', outfile);
  1234.           }
  1235.           else
  1236.             fputc(',', outfile);
  1237.         }
  1238.       for (i=((image_type==OUT_com)?0x100:0); i<bsspc; i++)
  1239.       {
  1240.     if ((i&15) == 0)
  1241.       fputs(leader, outfile);
  1242.         fprintf(outfile, "0x%02x", outbin[i]);
  1243.         if ((i&15) == 15)
  1244.         {
  1245.           fputc('\n', outfile);
  1246.         }
  1247.         else
  1248.           if (i<bsspc-1)
  1249.             fputc(',', outfile);
  1250.       }
  1251.       if (i&15)
  1252.         fputc('\n', outfile);
  1253.       break;
  1254.   }
  1255.   fclose(outfile);
  1256.   
  1257.   if (argc > 3)
  1258.   {
  1259.     FILE *mapfile = fopen(argv[3], "w");
  1260.     fprintf(mapfile, "%#x bytes generated, %#x bytes in file, %#x bytes total, %d symbols\n",
  1261.       generated_bytes, bsspc, pc, symcount);
  1262.  
  1263.     fprintf(mapfile, "\nStart Stop  Length Name Class\n");
  1264.     fprintf(mapfile, "%04XH %04XH %04XH  code code\n", 0, pc-1, pc);
  1265.  
  1266.     fprintf(mapfile, "\nAddress    Symbols by Name\n\n");
  1267.     for (s = symtab; s; s=s->next)
  1268.       if (!istemp(s->name, 0))
  1269.         fprintf(mapfile, "0000:%04X  %s (%c)\n", s->value, s->name, SYMTYPES[s->type]);
  1270.     fprintf(mapfile, "\nAddress    Symbols by Value\n\n");
  1271.     sortsyms(scmp_n);
  1272.     for (s = symtab; s; s=s->next)
  1273.       if (!istemp(s->name, 0))
  1274.         fprintf(mapfile, "0000:%04X  %s (%c)\n", s->value, s->name, SYMTYPES[s->type]);
  1275.     fprintf(mapfile, "\nLine numbers for (%s)\n", argv[1]);
  1276.     for (i=0; i<num_lineaddr; i++)
  1277.     {
  1278.       fprintf(mapfile, "%5d 0000:%04X", lineaddr[i].line, lineaddr[i].addr);
  1279.       if ((i & 3) == 3)
  1280.         fputc('\n', mapfile);
  1281.       else
  1282.         fputc(' ', mapfile);
  1283.     }
  1284.     fputc('\n', mapfile);
  1285.     fclose(mapfile);
  1286.   }
  1287. }
  1288.  
  1289. void yyerror(char *s)
  1290. {
  1291.   fprintf(stderr, "%s:%d: %s\n", inname, lineno, s);
  1292.   strbuf[strbuflen] = 0;
  1293.   fprintf(stderr, "Last token was `%s' (%s)\n", last_token, yytname[yytranslate[last_tret]]);
  1294.   total_errors++;
  1295. }
  1296.  
  1297. Symbol *get_symbol(char *name, int create)
  1298. {
  1299.   Symbol *s;
  1300.   for (s=symtab; s; s=s->next)
  1301.     if (strcmp(name, s->name) == 0)
  1302.       return s;
  1303.   if (!create)
  1304.     return 0;
  1305.   s = (Symbol *)malloc(sizeof(Symbol));
  1306.   s->next = symtab;
  1307.   symtab = s;
  1308.   s->name = (char *)malloc(strlen(name)+1);
  1309.   strcpy(s->name, name);
  1310.   s->value = 0;
  1311.   s->defined = 0;
  1312.   s->patches = 0;
  1313.   s->first_used = lineno;
  1314.   s->type = SYM_unknown;
  1315.   return s;
  1316. }
  1317.  
  1318. Symbol *set_symbol(Symbol *s, int value)
  1319. {
  1320.   if (istemp(s->name, 'b'))
  1321.     s->defined = 0;
  1322.   if (s->defined)
  1323.     printf("Warning: symbol %s redefined\n", s->name);
  1324.   s->value = value;
  1325.   s->defined = 1;
  1326.   while (s->patches)
  1327.   {
  1328.     int v, o;
  1329.     unsigned char *cp;
  1330.     Patch *p = s->patches;
  1331.     s->patches = s->patches->next;
  1332.     switch (p->rel)
  1333.     {
  1334.     case REL_abs:
  1335.     case REL_abs32:
  1336.       v = value;
  1337.       break;
  1338.     case REL_16:
  1339.       v = value - p->location - 2;
  1340.       break;
  1341.     case REL_8:
  1342.       v = value - p->location - 1;
  1343.       break;
  1344.     }
  1345.     cp = outbin + p->location;
  1346.     switch (p->rel)
  1347.     {
  1348.     case REL_abs32:
  1349.       o = *((int *)cp);
  1350.       break;
  1351.     case REL_abs:
  1352.     case REL_16:
  1353.       o = (signed short)(cp[0] | (cp[1] << 8));
  1354.       break;
  1355.     case REL_8:
  1356.       o = (signed char)(cp[0]);
  1357.       break;
  1358.     }
  1359.     o += v;
  1360.     switch (p->rel)
  1361.     {
  1362.     case REL_abs32:
  1363.       *((int *)cp) = o;
  1364.       break;
  1365.     case REL_abs:
  1366.     case REL_16:
  1367.       cp[1] = o>>8;
  1368.       cp[0] = o;
  1369.       break;
  1370.     case REL_8:
  1371.       if (o > 127 || o < -128)
  1372.       {
  1373.     /* So far away from me
  1374.        So far I just can't see
  1375.        So far away from me
  1376.        You're so far away from me
  1377.        -- from `So far away' by Mark Knopfler.  */
  1378.     fprintf(stderr, "%s:%d: 8-bit relocation too big (%d); use long form\n", inname, p->lineno, o);
  1379.     total_errors++;
  1380.       }
  1381.       cp[0] = o;
  1382.       break;
  1383.     }
  1384.     free(p);
  1385.   }
  1386.   if (istemp(s->name, 'f'))
  1387.     s->defined = 0;
  1388.   return s;
  1389. }
  1390.  
  1391. void sortsyms(int (*sortf)(void const *,void const *))
  1392. {
  1393.   int ns, i;
  1394.   Symbol *s, **st;
  1395.   if (!symtab)
  1396.     return;
  1397.   for (s=symtab, ns=0; s; s=s->next)
  1398.     ns ++;
  1399.   st = (Symbol **)malloc(sizeof(Symbol *) * ns);
  1400.   for (s=symtab, ns=0; s; s=s->next, ns++)
  1401.     st[ns] = s;
  1402.   qsort(st, ns, sizeof(Symbol *), sortf);
  1403.   for (i=0; i<ns-1; i++)
  1404.     st[i]->next = st[i+1];
  1405.   st[i]->next = 0;
  1406.   symtab = st[0];
  1407.   free(st);
  1408. }
  1409.  
  1410. void emit(void *ptr, int len)
  1411. {
  1412.   while (pc + len > outsize)
  1413.   {
  1414.     outsize += 512;
  1415.     outbin = realloc(outbin, outsize);
  1416.   }
  1417.   set_lineaddr();
  1418.   memcpy(outbin+pc, ptr, len);
  1419.   pc += len;
  1420. }
  1421.  
  1422. void emitb(int b)
  1423. {
  1424.   emit(&b, 1);
  1425. }
  1426.  
  1427. void emitw(int w)
  1428. {
  1429.   emitb(w);
  1430.   emitb(w>>8);
  1431. }
  1432.  
  1433. void emitd(long d)
  1434. {
  1435.   emitw(d);
  1436.   emitw(d>>16);
  1437. }
  1438.  
  1439. void emits(Symbol *s, int offset, int rel)
  1440. {
  1441.   Patch *p;
  1442.   int v;
  1443.   if (s->defined)
  1444.   {
  1445.     switch (rel)
  1446.     {
  1447.     case REL_abs32:
  1448.       v = s->value + offset;
  1449.       emitd(v);
  1450.       break;
  1451.     case REL_abs:
  1452.       v = s->value + offset;
  1453.       emitw(v);
  1454.       break;
  1455.     case REL_16:
  1456.       v = s->value - pc - 2 + offset;
  1457.       emitw(v);
  1458.       break;
  1459.     case REL_8:
  1460.       v = s->value - pc - 1 + offset;
  1461.       if (v < -128 || v > 127)
  1462.       {
  1463.     fprintf(stderr, "%s:%d: 8-bit relocation too big (%d); use long form", inname, lineno, v);
  1464.     total_errors++;
  1465.       }
  1466.       emitb(v);
  1467.       break;
  1468.     }
  1469.     return;
  1470.   }
  1471.   p = (Patch *)malloc(sizeof(Patch));
  1472.   p->next = s->patches;
  1473.   s->patches = p;
  1474.   p->location = pc;
  1475.   p->lineno = lineno;
  1476.   p->rel = rel;
  1477.   switch (rel)
  1478.   {
  1479.   case REL_abs32:
  1480.     emitd(offset);
  1481.     break;
  1482.   case REL_abs:
  1483.   case REL_16:
  1484.     emitw(offset);
  1485.     break;
  1486.   case REL_8:
  1487.     if (offset < -128 || offset > 127)
  1488.     {
  1489.       fprintf(stderr, "%s:%d: 8-bit relocation offset too big (%d); use long form", inname, lineno, offset);
  1490.       total_errors++;
  1491.     }
  1492.     emitb(offset);
  1493.     break;
  1494.   }
  1495. }
  1496.  
  1497. void modrm(int mod, int reg, int rm)
  1498. {
  1499.   emitb((mod<<6) | (reg<<3) | rm);
  1500. }
  1501.  
  1502. int reg2mbyte[] = { 0x48, 0x88, 0x60, 0xa0, 0x40, 0x80, 0x20, 0x08 };
  1503.  
  1504. void reg(int which)
  1505. {
  1506.   int i;
  1507.   int v;
  1508.   int mbyte = which << 3;
  1509.  
  1510.   if (_modrm.regs == 0)
  1511.   {
  1512.     emitb(movacc ? movacc : mbyte + 6);
  1513.     movacc=0;
  1514.   }
  1515.   else if (_modrm.regs == 0x20 && _modrm.offset == 0 && _modrm.nsyms == 0)
  1516.   {
  1517.     emitb(mbyte + 0x86);
  1518.   }
  1519.   else
  1520.   {
  1521.     for (i=0; i<8; i++)
  1522.       if (reg2mbyte[i] == _modrm.regs)
  1523.       {
  1524.         mbyte |= i;
  1525.         break;
  1526.       }
  1527.     if (i == 8)
  1528.     {
  1529.       printf("%s:%s: Invalid registers in R/M\n", inname, lineno);
  1530.       total_errors ++;
  1531.     }
  1532.     if (_modrm.offset == 0 && _modrm.nsyms == 0)
  1533.     {
  1534.       emitb(mbyte);
  1535.       _modrm.nsyms = _modrm.regs = _modrm.offset = 0;
  1536.       return;
  1537.     }
  1538.     emitb(mbyte + 0x80);
  1539.   }
  1540.   v = _modrm.offset;
  1541.   for (i=0; i<_modrm.nsyms; i++)
  1542.   {
  1543.     Symbol *s = _modrm.syms[i];
  1544.     if (s->defined)
  1545.       v += s->value;
  1546.     else
  1547.     {
  1548.       Patch *p;
  1549.       p = (Patch *)malloc(sizeof(Patch));
  1550.       p->next = s->patches;
  1551.       s->patches = p;
  1552.       p->location = pc;
  1553.       p->lineno = lineno;
  1554.       p->rel = REL_abs;
  1555.     }
  1556.   }   
  1557.   emitw(v);
  1558.   _modrm.nsyms = _modrm.regs = _modrm.offset = 0;
  1559. }
  1560.  
  1561. int yylex()
  1562. {
  1563.   last_tret = yylex1();
  1564.   return last_tret;
  1565. }
  1566.  
  1567. static struct {
  1568.   char c1, c2;
  1569.   int token;
  1570. } twochars[] = {
  1571.   '=', '=', '=',
  1572.   '>', '=', OP_GE,
  1573.   '<', '=', OP_LE,
  1574.   '<', '>', OP_NE,
  1575.   '!', '=', OP_NE,
  1576.   '&', '&', OP_AND,
  1577.   '|', '|', OP_OR,
  1578.   '<', '<', OP_SHL,
  1579.   '>', '>', OP_SHR};
  1580.  
  1581. int yylex1()
  1582. {
  1583.   int c, c2, i, oldc;
  1584.   struct opcode *opp, op;
  1585.  
  1586.   do {
  1587.     c = fgetc(infile);
  1588.   } while (c == ' ' || c == '\t');
  1589.  
  1590.   switch (c)
  1591.   {
  1592.     case EOF:
  1593.       if (file_stack)
  1594.       {
  1595.         FileStack *tmp = file_stack;
  1596.         fclose(infile);
  1597.         free(inname);
  1598.         lineno = file_stack->line + 1; /* Correct for .include line */
  1599.         infile = file_stack->f;
  1600.         inname = file_stack->name;
  1601.         file_stack = file_stack->prev;
  1602.         free(tmp);
  1603.         return yylex1();
  1604.       }
  1605.       return 0;
  1606.  
  1607.     case 'a' ... 'z':
  1608.     case 'A' ... 'Z':
  1609.     case '_':
  1610.     case '$':
  1611.     case '.':
  1612.     case '@':
  1613.       ungetc(c, infile);
  1614.       fscanf(infile, "%[a-zA-Z0-9_$.@]", strbuf);
  1615.       strcpy(last_token, strbuf);
  1616.       if (strcmp(strbuf, ".") == 0)
  1617.         return PC;
  1618.       op.name = strbuf;
  1619.       opp = bsearch (&op,
  1620.              opcodes, 
  1621.              sizeof (opcodes) / sizeof (opcodes[0]),
  1622.              sizeof (opcodes[0]),
  1623.              opcode_compare);
  1624.       if (opp)
  1625.     {
  1626.       yylval.i = opp->attr;
  1627.       return opp->token;
  1628.     }
  1629.       else
  1630.     {
  1631.       yylval.sym = get_symbol(strbuf,1);
  1632.       return yylval.sym->defined ? KID : UID;
  1633.     }
  1634.  
  1635.     case '0' ... '9':
  1636.       ungetc(c, infile);
  1637.       fscanf(infile, "%i", &(yylval.i));
  1638.       sprintf(last_token, "%d", yylval.i);
  1639.       return NUMBER;
  1640.       break;
  1641.  
  1642.     case '>':
  1643.     case '<':
  1644.     case '!':
  1645.     case '&':
  1646.     case '|':
  1647.     case '=':
  1648.       c2 = fgetc (infile);
  1649.       for (i = 0; i < 9; i++)
  1650.     if (c == twochars[i].c1 && c2 == twochars[i].c2)
  1651.       return twochars[i].token;
  1652.       ungetc (c2, infile);
  1653.       return c;
  1654.  
  1655.     case '"':
  1656.     case '\'':
  1657.       oldc = c;
  1658.       i = 0;
  1659.       while (1)
  1660.       {
  1661.         c = fgetc(infile);
  1662.         if (c == oldc)
  1663.         {
  1664.           strcpy(last_token, strbuf);
  1665.           strbuflen = i;
  1666.           if (strbuflen == 1)
  1667.           {
  1668.             yylval.i = strbuf[0];
  1669.             return NUMBER;
  1670.           }
  1671.           return STRING;
  1672.     }
  1673.         switch (c)
  1674.         {
  1675.           case '\\':
  1676.             switch (c = fgetc(infile))
  1677.             {
  1678.               case '0':
  1679.                 strbuf[i++] = 0;
  1680.                 break;
  1681.               case 'n':
  1682.                 strbuf[i++] = '\n';
  1683.                 break;
  1684.               case 'r':
  1685.                 strbuf[i++] = '\r';
  1686.                 break;
  1687.               case 't':
  1688.                 strbuf[i++] = '\t';
  1689.                 break;
  1690.               default:
  1691.                 strbuf[i++] = c;
  1692.                 break;
  1693.             }
  1694.             break;
  1695.           default:
  1696.             strbuf[i++] = c;
  1697.             break;
  1698.         }
  1699.       }
  1700.       abort ();
  1701.     case ';':
  1702.       while (fgetc(infile) != '\n');
  1703.       c = '\n';
  1704.       /* Fall through.  */
  1705.     case '\n':
  1706.       strcpy(last_token, "NL");
  1707.       return c;
  1708.     default:
  1709.       sprintf(last_token, "<%c>", c);
  1710.       return c;
  1711.   }
  1712. }
  1713.  
  1714. int istemp(char *symname, char which)
  1715. {
  1716.   if (symname[0] != '@') return 0;
  1717.   if (which)
  1718.     if (symname[1] != which) return 0;
  1719.   else
  1720.     if (symname[1] != 'f' && symname[1] != 'b') return 0;
  1721.   if (!isdigit(symname[2])) return 0;
  1722.   if (symname[3]) return 0;
  1723.   return 1;
  1724. }
  1725.  
  1726. void do_sreg_pop(int sreg)
  1727. {
  1728.   switch (sreg)
  1729.   {
  1730.     case 0: /* es */
  1731.       emitb(0x07);
  1732.       break;
  1733.     case 1: /* cs */
  1734.       yyerror("Cannot pop CS");
  1735.       break;
  1736.     case 2: /* ss */
  1737.       emitb(0x17);
  1738.       break;
  1739.     case 3: /* ds */
  1740.       emitb(0x1f);
  1741.       break;
  1742.     case 4: /* fs */
  1743.       emitb(0x0f);
  1744.       emitb(0xa1);
  1745.       break;
  1746.     case 5: /* gs */
  1747.       emitb(0x0f);
  1748.       emitb(0xa9);
  1749.       break;
  1750.   }
  1751. }
  1752.  
  1753. void do_sreg_push(int sreg)
  1754. {
  1755.   switch (sreg)
  1756.   {
  1757.     case 0: /* es */
  1758.       emitb(0x06);
  1759.       break;
  1760.     case 1: /* cs */
  1761.       emitb(0x0e);
  1762.       break;
  1763.     case 2: /* ss */
  1764.       emitb(0x16);
  1765.       break;
  1766.     case 3: /* ds */
  1767.       emitb(0x1e);
  1768.       break;
  1769.     case 4: /* fs */
  1770.       emitb(0x0f);
  1771.       emitb(0xa0);
  1772.       break;
  1773.     case 5: /* gs */
  1774.       emitb(0x0f);
  1775.       emitb(0xa8);
  1776.       break;
  1777.   }
  1778. }
  1779.  
  1780. void set_lineaddr()
  1781. {
  1782.   static int last_lineno = -1;
  1783.   if (lineno == last_lineno)
  1784.     return;
  1785.   last_lineno = lineno;
  1786.   if (num_lineaddr == max_lineaddr)
  1787.   {
  1788.     max_lineaddr += 32;
  1789.     if (lineaddr)
  1790.       lineaddr = (lineaddr_s *)realloc(lineaddr, max_lineaddr * sizeof(lineaddr_s));
  1791.     else
  1792.       lineaddr = (lineaddr_s *)malloc(max_lineaddr * sizeof(lineaddr_s));
  1793.   }
  1794.   lineaddr[num_lineaddr].line = lineno;
  1795.   lineaddr[num_lineaddr].addr = pc;
  1796.   num_lineaddr++;
  1797. }
  1798.  
  1799. void do_align(int p2, int val)
  1800. {
  1801.   last_align_begin = pc;
  1802.   while ((pc+EXE_HEADER_SIZE) % p2)
  1803.     emitb(val);
  1804.   last_align_end = pc;
  1805. }
  1806.  
  1807. void add_copyright(char *buf)
  1808. {
  1809.   char *tmp;
  1810.   if (copyright == 0)
  1811.   {
  1812.     copyright = (char *)malloc(strlen(buf)+1);
  1813.     strcpy(copyright, buf);
  1814.     return;
  1815.   }
  1816.   tmp = (char *)malloc(strlen(copyright) + strlen(buf) + 3);
  1817.   strcpy(tmp, copyright);
  1818.   strcat(tmp, "\r\n");
  1819.   strcat(tmp, buf);
  1820.   free(copyright);
  1821.   copyright = tmp;
  1822. }
  1823.  
  1824. void add_rcs_ident(char *buf)
  1825. {
  1826.   char tmp[500];
  1827.   time_t now;
  1828.   struct tm *tm;
  1829.   time(&now);
  1830.   tm = localtime(&now);
  1831.   sprintf(tmp, "$Id: %s built %02d/%02d/%02d %02d:%02d:%02d by djasm $\n",
  1832.       inname,
  1833.       tm->tm_mon + 1,
  1834.       tm->tm_mday,
  1835.       tm->tm_year,
  1836.       tm->tm_hour,
  1837.       tm->tm_min,
  1838.       tm->tm_sec);
  1839.   add_copyright(tmp);
  1840.   sprintf(tmp, "@(#) %s built %02d/%02d/%02d %02d:%02d:%02d by djasm\n",
  1841.       inname,
  1842.       tm->tm_mon + 1,
  1843.       tm->tm_mday,
  1844.       tm->tm_year,
  1845.       tm->tm_hour,
  1846.       tm->tm_min,
  1847.       tm->tm_sec);
  1848.   add_copyright(tmp);
  1849. }
  1850.  
  1851. void set_out_type(char *t)
  1852. {
  1853.   int i;
  1854.   for (i=0; ext_types[i]; i++)
  1855.   {
  1856.     if (strcmp(ext_types[i], t) == 0)
  1857.     {
  1858.       out_type = i;
  1859.       return;
  1860.     }
  1861.   }
  1862.   printf("Unknown output type: `%s'\n", t);
  1863. }
  1864.  
  1865. void set_image_type(char *t)
  1866. {
  1867.   int i;
  1868.   for (i=0; ext_types[i]; i++)
  1869.   {
  1870.     if (strcmp(ext_types[i], t) == 0)
  1871.     {
  1872.       if (i == OUT_com && image_type != OUT_com)
  1873.       {
  1874.         if (pc)
  1875.         {
  1876.           fprintf(stderr, "Cannot make com file without .type \"com\"\n");
  1877.           exit(1);
  1878.         }
  1879.         while (pc < 0x100)
  1880.           emitb(0x90);
  1881.       }
  1882.       image_type = i;
  1883.       return;
  1884.     }
  1885.   }
  1886.   printf("Unknown output type: `%s'\n", t);
  1887. }
  1888.  
  1889. void do_include(char *fname)
  1890. {
  1891.   FILE *f;
  1892.   FileStack *fs;
  1893.   
  1894.   f = fopen(fname, "r");
  1895.   if (!f)
  1896.   {
  1897.     fprintf(stderr, "Error: cannot open %s\n", fname);
  1898.     perror("The error was");
  1899.     return;
  1900.   }
  1901.   fs = (FileStack *)malloc(sizeof(FileStack));
  1902.   fs->line = lineno;
  1903.   fs->prev = file_stack;
  1904.   fs->f = infile;
  1905.   fs->name = inname;
  1906.   file_stack = fs;
  1907.  
  1908.   infile = f;
  1909.   inname = (char *)malloc(strlen(fname)+1);
  1910.   strcpy(inname, fname);
  1911.   lineno = 1;
  1912. }
  1913.  
  1914. /* #define DEBUG_RELOC */
  1915.  
  1916. void do_linkcoff (char *filename)
  1917. {
  1918.   long len;
  1919.   int f;
  1920.   char *data, *p;
  1921.   FILHDR *header;
  1922.   SCNHDR *f_thdr;        /* Text section header */
  1923.   SCNHDR *f_dhdr;        /* Data section header */
  1924.   SCNHDR *f_bhdr;        /* Bss section header */
  1925.   AOUTHDR f_ohdr;        /* Optional file header (a.out) */
  1926.   SYMENT *symbol;
  1927.   RELOC *rp;
  1928.   int cnt, i;
  1929.   void *base;
  1930.   int textbase, database, bssbase, delta;
  1931.   char smallname[9];
  1932.  
  1933.   f = open (filename, O_RDONLY | O_BINARY);
  1934.   if (f < 0)
  1935.     {
  1936.       fprintf (stderr, "Error: cannot open %s\n", filename);
  1937.       perror("The error was");
  1938.       return;
  1939.     }
  1940.   len = lseek (f, 0L, SEEK_END);
  1941.   lseek (f, 0L, SEEK_SET);
  1942.   data = alloca (len);
  1943.   read (f, data, (unsigned)len);
  1944.   close (f);
  1945.  
  1946.   header = (FILHDR *) data;
  1947.   f_thdr = (void *)data + sizeof (FILHDR) + header->f_opthdr;
  1948.   f_dhdr = f_thdr + 1;
  1949.   f_bhdr = f_dhdr + 1;
  1950.   if (I386BADMAG (*header)
  1951.       || header->f_nscns != 3
  1952.       || strcmp (f_thdr->s_name, _TEXT)
  1953.       || strcmp (f_dhdr->s_name, _DATA)
  1954.       || strcmp (f_bhdr->s_name, _BSS))
  1955.     {
  1956.       fprintf (stderr, "The file %s is not a valid COFF file.\n", filename);
  1957.       return;
  1958.     }
  1959.  
  1960.   textbase = pc;
  1961.   emit(data + f_thdr->s_scnptr, f_thdr->s_size);
  1962.   database = pc;
  1963.   emit(data + f_dhdr->s_scnptr, f_dhdr->s_size);
  1964.   bssbase = pc;
  1965.   for (i = 0; i < f_bhdr->s_size; i++)
  1966.     emitb (0);
  1967.  
  1968. #ifdef DEBUG_RELOC
  1969.   printf ("textbase is at %04x\n", textbase);
  1970.   printf ("database is at %04x\n", database);
  1971.   printf ("bssbase  is at %04x\n", bssbase);
  1972. #endif
  1973.  
  1974.   symbol = (void *) data + header->f_symptr;
  1975.   base = (void *) symbol + header->f_nsyms * SYMESZ;
  1976.   for (cnt = header->f_nsyms; cnt > 0; symbol++, cnt--)
  1977.     {
  1978.       if (symbol->e.e.e_zeroes == 0)
  1979.     p = base + symbol->e.e.e_offset;
  1980.       else
  1981.     strncpy (p = smallname, symbol->e.e_name, 8),
  1982.     p[8] = 0;
  1983.  
  1984.       switch (symbol->e_sclass)
  1985.     {
  1986.     case C_EXT:
  1987.       switch (symbol->e_scnum)
  1988.         {
  1989.         case 1:
  1990.           set_symbol (get_symbol (p, 1),
  1991.               textbase + symbol->e_value)->type |= SYM_code;
  1992.           break;
  1993.         case 2:
  1994.           set_symbol (get_symbol (p, 1),
  1995.               textbase + symbol->e_value)->type |= SYM_data;
  1996.           break;
  1997.         case 3:
  1998.           set_symbol (get_symbol (p, 1),
  1999.               textbase + symbol->e_value)->type |= SYM_data;
  2000.           break;
  2001.         case N_UNDEF:
  2002.           if (symbol->e_value == 0)
  2003.         0;  /* Nothing -- external reference.  */
  2004.           else if (!get_symbol (p, 0))
  2005.         {
  2006.           /* New common variable.  */
  2007.           set_symbol (get_symbol (p, 1), pc)->type |= SYM_data;
  2008.           for (i = 0; i < symbol->e_value; i++)
  2009.             emitb (0);
  2010.         }
  2011.           break;
  2012.         }
  2013.       break;
  2014.     }
  2015.       cnt -= symbol->e_numaux;
  2016.       symbol += symbol->e_numaux;
  2017.     }
  2018.  
  2019.   symbol = (void *) data + header->f_symptr;
  2020.   for (i = 0; i < 2; i++)
  2021.     {
  2022.       if (i == 0)
  2023.     rp = (RELOC *) (data + f_thdr->s_relptr),
  2024.     cnt = f_thdr->s_nreloc;
  2025.       else
  2026.     rp = (RELOC *) (data + f_dhdr->s_relptr),
  2027.     cnt = f_dhdr->s_nreloc;
  2028.  
  2029.       for (; cnt > 0; cnt--, rp++)
  2030.     {
  2031.       Symbol *s;
  2032.       int delta;
  2033.  
  2034.       if (symbol[rp->r_symndx].e.e.e_zeroes == 0)
  2035.         p = base + symbol[rp->r_symndx].e.e.e_offset;
  2036.       else
  2037.         strncpy (p = smallname, symbol[rp->r_symndx].e.e_name, 8),
  2038.         p[8] = 0;
  2039.  
  2040. #ifdef DEBUG_RELOC
  2041.       s = get_symbol (p, 0);
  2042.       printf ("ofs=%04x  typ=%02x  sec=%d"
  2043.           "  val=%08x  data=%08x"
  2044.           "  name=%s\n",
  2045.           rp->r_vaddr + textbase,
  2046.           rp->r_type,
  2047.           symbol[rp->r_symndx].e_scnum,
  2048.           s ? s->value : 0, 
  2049.           *((int *) (outbin + textbase + rp->r_vaddr)),
  2050.           p);
  2051. #endif
  2052.       if (!strcmp (p, _TEXT))
  2053.         delta = textbase;
  2054.       else if (!strcmp (p, _DATA))
  2055.         delta = textbase;
  2056.       else if (!strcmp (p, _BSS))
  2057.         delta = textbase;
  2058.       else
  2059.         {
  2060.           s = get_symbol (p, 1);
  2061.           if (!s->defined)
  2062.         {
  2063.           Patch *pat = (Patch *) malloc (sizeof (Patch));
  2064.  
  2065.           if (rp->r_type == RELOC_REL32)
  2066.             fprintf (stderr,
  2067.                  "Call from COFF file to (yet) undefined "
  2068.                  "destination, %s, is not supported.\n", p);
  2069.           pat->next = s->patches;
  2070.           s->patches = pat;
  2071.           pat->location = textbase + rp->r_vaddr;
  2072.           pat->lineno = -1;
  2073.           pat->rel = REL_abs32;
  2074.         }
  2075.         }
  2076.  
  2077.       switch (rp->r_type)
  2078.         {
  2079.         case RELOC_ADDR32:
  2080.           if (symbol[rp->r_symndx].e_scnum > 0)
  2081.         delta = textbase;
  2082.           else
  2083.         delta = s->value - symbol[rp->r_symndx].e_value;
  2084.           break;
  2085.         case RELOC_REL32:
  2086.           if (symbol[rp->r_symndx].e_scnum > 0)
  2087.         delta = 0;
  2088.           else
  2089.         delta = s->value - textbase;
  2090.           break;
  2091.         default:
  2092.           fprintf (stderr,
  2093.                "COFF file %s contains bad relation "
  2094.                "entry type (0x%02x).\n",
  2095.                filename, rp->r_type);
  2096.           delta = 0;
  2097.         }
  2098.       *((int *)(outbin + textbase + rp->r_vaddr)) += delta;
  2099.     }
  2100.     }
  2101. }
  2102.  
  2103.