home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / nasm097.zip / LCC / X86NASM.MD < prev   
Text File  |  1997-10-01  |  21KB  |  704 lines

  1. %{
  2. enum { EAX=0, ECX=1, EDX=2, EBX=3, ESI=6, EDI=7 };
  3. #include "c.h"
  4. #define NODEPTR_TYPE Node
  5. #define OP_LABEL(p) ((p)->op)
  6. #define LEFT_CHILD(p) ((p)->kids[0])
  7. #define RIGHT_CHILD(p) ((p)->kids[1])
  8. #define STATE_LABEL(p) ((p)->x.state)
  9. static void address     ARGS((Symbol, Symbol, int));
  10. static void blkfetch    ARGS((int, int, int, int));
  11. static void blkloop     ARGS((int, int, int, int, int, int[]));
  12. static void blkstore    ARGS((int, int, int, int));
  13. static void defaddress  ARGS((Symbol));
  14. static void defconst    ARGS((int, Value));
  15. static void defstring   ARGS((int, char *));
  16. static void defsymbol   ARGS((Symbol));
  17. static void doarg       ARGS((Node));
  18. static void emit2       ARGS((Node));
  19. static void export      ARGS((Symbol));
  20. static void clobber     ARGS((Node));
  21. static void function    ARGS((Symbol, Symbol [], Symbol [], int));
  22. static void global      ARGS((Symbol));
  23. static void import      ARGS((Symbol));
  24. static void local       ARGS((Symbol));
  25. static void progbeg     ARGS((int, char **));
  26. static void progend     ARGS((void));
  27. static void segment     ARGS((int));
  28. static void space       ARGS((int));
  29. static void target      ARGS((Node));
  30. static int ckstack ARGS((Node, int));
  31. static int memop ARGS((Node));
  32. static int sametree ARGS((Node, Node));
  33. static Symbol charreg[32], shortreg[32], intreg[32];
  34. static Symbol fltreg[32];
  35.  
  36. static int cseg;
  37.  
  38. static Symbol quo, rem;
  39.  
  40. %}
  41. %start stmt
  42. %term ADDD=306 ADDF=305 ADDI=309 ADDP=311 ADDU=310
  43. %term ADDRFP=279
  44. %term ADDRGP=263
  45. %term ADDRLP=295
  46. %term ARGB=41 ARGD=34 ARGF=33 ARGI=37 ARGP=39
  47. %term ASGNB=57 ASGNC=51 ASGND=50 ASGNF=49 ASGNI=53 ASGNP=55 ASGNS=52
  48. %term BANDU=390
  49. %term BCOMU=406
  50. %term BORU=422
  51. %term BXORU=438
  52. %term CALLB=217 CALLD=210 CALLF=209 CALLI=213 CALLV=216
  53. %term CNSTC=19 CNSTD=18 CNSTF=17 CNSTI=21 CNSTP=23 CNSTS=20 CNSTU=22
  54. %term CVCI=85 CVCU=86
  55. %term CVDF=97 CVDI=101
  56. %term CVFD=114
  57. %term CVIC=131 CVID=130 CVIS=132 CVIU=134
  58. %term CVPU=150
  59. %term CVSI=165 CVSU=166
  60. %term CVUC=179 CVUI=181 CVUP=183 CVUS=180
  61. %term DIVD=450 DIVF=449 DIVI=453 DIVU=454
  62. %term EQD=482 EQF=481 EQI=485
  63. %term GED=498 GEF=497 GEI=501 GEU=502
  64. %term GTD=514 GTF=513 GTI=517 GTU=518
  65. %term INDIRB=73 INDIRC=67 INDIRD=66 INDIRF=65 INDIRI=69 INDIRP=71 INDIRS=68
  66. %term JUMPV=584
  67. %term LABELV=600
  68. %term LED=530 LEF=529 LEI=533 LEU=534
  69. %term LOADB=233 LOADC=227 LOADD=226 LOADF=225 LOADI=229 LOADP=231 LOADS=228 LOADU=230
  70. %term LSHI=341 LSHU=342
  71. %term LTD=546 LTF=545 LTI=549 LTU=550
  72. %term MODI=357 MODU=358
  73. %term MULD=466 MULF=465 MULI=469 MULU=470
  74. %term NED=562 NEF=561 NEI=565
  75. %term NEGD=194 NEGF=193 NEGI=197
  76. %term RETD=242 RETF=241 RETI=245
  77. %term RSHI=373 RSHU=374
  78. %term SUBD=322 SUBF=321 SUBI=325 SUBP=327 SUBU=326
  79. %term VREGP=615
  80. %%
  81. reg:  INDIRC(VREGP)     "# read register\n"
  82. reg:  INDIRD(VREGP)     "# read register\n"
  83. reg:  INDIRF(VREGP)     "# read register\n"
  84. reg:  INDIRI(VREGP)     "# read register\n"
  85. reg:  INDIRP(VREGP)     "# read register\n"
  86. reg:  INDIRS(VREGP)     "# read register\n"
  87. stmt: ASGNC(VREGP,reg)  "# write register\n"
  88. stmt: ASGND(VREGP,reg)  "# write register\n"
  89. stmt: ASGNF(VREGP,reg)  "# write register\n"
  90. stmt: ASGNI(VREGP,reg)  "# write register\n"
  91. stmt: ASGNP(VREGP,reg)  "# write register\n"
  92. stmt: ASGNS(VREGP,reg)  "# write register\n"
  93. con: CNSTC  "%a"
  94. con: CNSTI  "%a"
  95. con: CNSTP  "%a"
  96. con: CNSTS  "%a"
  97. con: CNSTU  "%a"
  98. stmt: reg  ""
  99. reg: CVIU(reg)  "%0"  notarget(a)
  100. reg: CVPU(reg)  "%0"  notarget(a)
  101. reg: CVUI(reg)  "%0"  notarget(a)
  102. reg: CVUP(reg)  "%0"  notarget(a)
  103. acon: ADDRGP  "%a"
  104. acon: con     "%0"
  105. base: ADDRGP          "%a"
  106. base: reg             "%0"
  107. base: ADDI(reg,acon)  "%0 + (%1)"
  108. base: ADDP(reg,acon)  "%0 + (%1)"
  109. base: ADDU(reg,acon)  "%0 + (%1)"
  110. base: ADDRFP  "ebp + %a"
  111. base: ADDRLP  "ebp + %a"
  112. index: reg "%0"
  113. index: LSHI(reg,con1)  "%0*2"
  114. index: LSHI(reg,con2)  "%0*4"
  115. index: LSHI(reg,con3)  "%0*8"
  116.  
  117. con1:  CNSTI  "1"  range(a, 1, 1)
  118. con1:  CNSTU  "1"  range(a, 1, 1)
  119. con2:  CNSTI  "2"  range(a, 2, 2)
  120. con2:  CNSTU  "2"  range(a, 2, 2)
  121. con3:  CNSTI  "3"  range(a, 3, 3)
  122. con3:  CNSTU  "3"  range(a, 3, 3)
  123. index: LSHU(reg,con1)  "%0*2"
  124. index: LSHU(reg,con2)  "%0*4"
  125. index: LSHU(reg,con3)  "%0*8"
  126. addr: base              "[%0]"
  127. addr: ADDI(index,base)  "[%1 + %0]"
  128. addr: ADDP(index,base)  "[%1 + %0]"
  129. addr: ADDU(index,base)  "[%1 + %0]"
  130. addr: index  "[%0]"
  131. mem: INDIRC(addr)  "byte %0"
  132. mem: INDIRI(addr)  "dword %0"
  133. mem: INDIRP(addr)  "dword %0"
  134. mem: INDIRS(addr)  "word %0"
  135. rc:   reg  "%0"
  136. rc:   con  "%0"
  137.  
  138. mr:   reg  "%0"
  139. mr:   mem  "%0"
  140.  
  141. mrc0: mem  "%0"
  142. mrc0: rc   "%0"
  143. mrc1: mem  "%0"  1
  144. mrc1: rc   "%0"
  145.  
  146. mrc3: mem  "%0"  3
  147. mrc3: rc   "%0"
  148. reg: addr        "lea %c,%0\n"  1
  149. reg: mrc0        "mov %c,%0\n"  1
  150. reg: LOADC(reg)  "mov %c,%0\n"  move(a)
  151. reg: LOADI(reg)  "mov %c,%0\n"  move(a)
  152. reg: LOADP(reg)  "mov %c,%0\n"  move(a)
  153. reg: LOADS(reg)  "mov %c,%0\n"  move(a)
  154. reg: LOADU(reg)  "mov %c,%0\n"  move(a)
  155. reg: ADDI(reg,mrc1)  "?mov %c,%0\nadd %c,%1\n"  1
  156. reg: ADDP(reg,mrc1)  "?mov %c,%0\nadd %c,%1\n"  1
  157. reg: ADDU(reg,mrc1)  "?mov %c,%0\nadd %c,%1\n"  1
  158. reg: SUBI(reg,mrc1)  "?mov %c,%0\nsub %c,%1\n"  1
  159. reg: SUBP(reg,mrc1)  "?mov %c,%0\nsub %c,%1\n"  1
  160. reg: SUBU(reg,mrc1)  "?mov %c,%0\nsub %c,%1\n"  1
  161. reg: BANDU(reg,mrc1)  "?mov %c,%0\nand %c,%1\n"  1
  162. reg: BORU(reg,mrc1)   "?mov %c,%0\nor %c,%1\n"   1
  163. reg: BXORU(reg,mrc1)  "?mov %c,%0\nxor %c,%1\n"  1
  164. stmt: ASGNI(addr,ADDI(mem,con1))  "inc %1\n"  memop(a)
  165. stmt: ASGNI(addr,ADDU(mem,con1))  "inc %1\n"  memop(a)
  166. stmt: ASGNP(addr,ADDP(mem,con1))  "inc %1\n"  memop(a)
  167. stmt: ASGNI(addr,SUBI(mem,con1))  "dec %1\n"  memop(a)
  168. stmt: ASGNI(addr,SUBU(mem,con1))  "dec %1\n"  memop(a)
  169. stmt: ASGNP(addr,SUBP(mem,con1))  "dec %1\n"  memop(a)
  170. stmt: ASGNI(addr,ADDI(mem,rc))   "add %1,%2\n"  memop(a)
  171. stmt: ASGNI(addr,ADDU(mem,rc))   "add %1,%2\n"  memop(a)
  172. stmt: ASGNI(addr,SUBI(mem,rc))   "sub %1,%2\n"  memop(a)
  173. stmt: ASGNI(addr,SUBU(mem,rc))   "sub %1,%2\n"  memop(a)
  174.  
  175. stmt: ASGNI(addr,BANDU(mem,rc))  "and %1,%2\n"  memop(a)
  176. stmt: ASGNI(addr,BORU(mem,rc))   "or %1,%2\n"   memop(a)
  177. stmt: ASGNI(addr,BXORU(mem,rc))  "xor %1,%2\n"  memop(a)
  178. reg: BCOMU(reg)  "?mov %c,%0\nnot %c\n"  2
  179. reg: NEGI(reg)   "?mov %c,%0\nneg %c\n"  2
  180.  
  181. stmt: ASGNI(addr,BCOMU(mem))  "not %1\n"  memop(a)
  182. stmt: ASGNI(addr,NEGI(mem))   "neg %1\n"  memop(a)
  183. reg: LSHI(reg,rc5)  "?mov %c,%0\nsal %c,%1\n"  2
  184. reg: LSHU(reg,rc5)  "?mov %c,%0\nshl %c,%1\n"  2
  185. reg: RSHI(reg,rc5)  "?mov %c,%0\nsar %c,%1\n"  2
  186. reg: RSHU(reg,rc5)  "?mov %c,%0\nshr %c,%1\n"  2
  187.  
  188. stmt: ASGNI(addr,LSHI(mem,rc5))  "sal %1,%2\n"  memop(a)
  189. stmt: ASGNI(addr,LSHU(mem,rc5))  "shl %1,%2\n"  memop(a)
  190. stmt: ASGNI(addr,RSHI(mem,rc5))  "sar %1,%2\n"  memop(a)
  191. stmt: ASGNI(addr,RSHU(mem,rc5))  "shr %1,%2\n"  memop(a)
  192.  
  193. rc5: CNSTI  "%a"  range(a, 0, 31)
  194. rc5: reg    "cl"
  195. reg: MULI(reg,mrc3)  "?mov %c,%0\nimul %c,%1\n"  14
  196. reg: MULI(con,mr)    "imul %c,%1,%0\n"  13
  197. reg: MULU(reg,mr)  "mul %1\n"  13
  198. reg: DIVU(reg,reg)  "xor edx,edx\ndiv %1\n"
  199. reg: MODU(reg,reg)  "xor edx,edx\ndiv %1\n"
  200. reg: DIVI(reg,reg)  "cdq\nidiv %1\n"
  201. reg: MODI(reg,reg)  "cdq\nidiv %1\n"
  202. reg: CVIU(reg)  "mov %c,%0\n"  move(a)
  203. reg: CVPU(reg)  "mov %c,%0\n"  move(a)
  204. reg: CVUI(reg)  "mov %c,%0\n"  move(a)
  205. reg: CVUP(reg)  "mov %c,%0\n"  move(a)
  206. reg: CVCI(INDIRC(addr))  "movsx %c,byte %0\n"  3
  207. reg: CVCU(INDIRC(addr))  "movzx %c,byte %0\n"  3
  208. reg: CVSI(INDIRS(addr))  "movsx %c,word %0\n"  3
  209. reg: CVSU(INDIRS(addr))  "movzx %c,word %0\n"  3
  210. reg: CVCI(reg)  "# extend\n"  3
  211. reg: CVCU(reg)  "# extend\n"  3
  212. reg: CVSI(reg)  "# extend\n"  3
  213. reg: CVSU(reg)  "# extend\n"  3
  214.  
  215. reg: CVIC(reg)  "# truncate\n"  1
  216. reg: CVIS(reg)  "# truncate\n"  1
  217. reg: CVUC(reg)  "# truncate\n"  1
  218. reg: CVUS(reg)  "# truncate\n"  1
  219. stmt: ASGNC(addr,rc)  "mov byte %0,%1\n"   1
  220. stmt: ASGNI(addr,rc)  "mov dword %0,%1\n"  1
  221. stmt: ASGNP(addr,rc)  "mov dword %0,%1\n"  1
  222. stmt: ASGNS(addr,rc)  "mov word %0,%1\n"   1
  223. stmt: ARGI(mrc3)  "push dword %0\n"  1
  224. stmt: ARGP(mrc3)  "push dword %0\n"  1
  225. stmt: ASGNB(reg,INDIRB(reg))  "mov ecx,%a\nrep movsb\n"
  226. stmt: ARGB(INDIRB(reg))  "sub esp,%a\nmov edi,esp\nmov ecx,%a\nrep movsb\n"
  227.  
  228. memf: INDIRD(addr)        "qword %0"
  229. memf: INDIRF(addr)        "dword %0"
  230. memf: CVFD(INDIRF(addr))  "dword %0"
  231. reg: memf  "fld %0\n"  3
  232. stmt: ASGND(addr,reg)        "fstp qword %0\n"  7
  233. stmt: ASGNF(addr,reg)        "fstp dword %0\n"  7
  234. stmt: ASGNF(addr,CVDF(reg))  "fstp dword %0\n"  7
  235. stmt: ARGD(reg)  "sub esp,8\nfstp qword [esp]\n"
  236. stmt: ARGF(reg)  "sub esp,4\nfstp dword [esp]\n"
  237. reg: NEGD(reg)  "fchs\n"
  238. reg: NEGF(reg)  "fchs\n"
  239. reg: ADDD(reg,memf)  "fadd %1\n"
  240. reg: ADDD(reg,reg)  "faddp st1\n"
  241. reg: ADDF(reg,memf)  "fadd %1\n"
  242. reg: ADDF(reg,reg)  "faddp st1\n"
  243. reg: DIVD(reg,memf)  "fdiv %1\n"
  244. reg: DIVD(reg,reg)  "fdivp st1\n"
  245. reg: DIVF(reg,memf)  "fdiv %1\n"
  246. reg: DIVF(reg,reg)  "fdivp st1\n"
  247. reg: MULD(reg,memf)  "fmul %1\n"
  248. reg: MULD(reg,reg)  "fmulp st1\n"
  249. reg: MULF(reg,memf)  "fmul %1\n"
  250. reg: MULF(reg,reg)  "fmulp st1\n"
  251. reg: SUBD(reg,memf)  "fsub %1\n"
  252. reg: SUBD(reg,reg)  "fsubp st1\n"
  253. reg: SUBF(reg,memf)  "fsub %1\n"
  254. reg: SUBF(reg,reg)  "fsubp st1\n"
  255. reg: CVFD(reg)  "# CVFD\n"
  256. reg: CVDF(reg)  "sub esp,4\nfstp dword [esp]\nfld dword [esp]\nadd esp,4\n"  12
  257.  
  258. stmt: ASGNI(addr,CVDI(reg))  "fistp dword %0\n"  29
  259. reg: CVDI(reg)  "sub esp,4\nfistp dword [esp]\npop %c\n" 31
  260.  
  261. reg: CVID(INDIRI(addr))  "fild dword %0\n"  10
  262. reg: CVID(reg)  "push %0\nfild dword [esp]\nadd esp,4\n"  12
  263.  
  264. addrj: ADDRGP  "%a"
  265. addrj: reg     "%0"  2
  266. addrj: mem     "%0"  2
  267.  
  268. stmt:  JUMPV(addrj)  "jmp %0\n"  3
  269. stmt:  LABELV        "%a:\n"
  270. stmt: EQI(mem,rc)  "cmp %0,%1\nje near %a\n"   5
  271. stmt: GEI(mem,rc)  "cmp %0,%1\njge near %a\n"  5
  272. stmt: GTI(mem,rc)  "cmp %0,%1\njg near %a\n"   5
  273. stmt: LEI(mem,rc)  "cmp %0,%1\njle near %a\n"  5
  274. stmt: LTI(mem,rc)  "cmp %0,%1\njl near %a\n"   5
  275. stmt: NEI(mem,rc)  "cmp %0,%1\njne near %a\n"  5
  276. stmt: GEU(mem,rc)  "cmp %0,%1\njae near %a\n"  5
  277. stmt: GTU(mem,rc)  "cmp %0,%1\nja  near %a\n"  5
  278. stmt: LEU(mem,rc)  "cmp %0,%1\njbe near %a\n"  5
  279. stmt: LTU(mem,rc)  "cmp %0,%1\njb  near %a\n"  5
  280. stmt: EQI(reg,mrc1)  "cmp %0,%1\nje near %a\n"   4
  281. stmt: GEI(reg,mrc1)  "cmp %0,%1\njge near %a\n"  4
  282. stmt: GTI(reg,mrc1)  "cmp %0,%1\njg near %a\n"   4
  283. stmt: LEI(reg,mrc1)  "cmp %0,%1\njle near %a\n"  4
  284. stmt: LTI(reg,mrc1)  "cmp %0,%1\njl near %a\n"   4
  285. stmt: NEI(reg,mrc1)  "cmp %0,%1\njne near %a\n"  4
  286.  
  287. stmt: GEU(reg,mrc1)  "cmp %0,%1\njae near %a\n"  4
  288. stmt: GTU(reg,mrc1)  "cmp %0,%1\nja near %a\n"   4
  289. stmt: LEU(reg,mrc1)  "cmp %0,%1\njbe near %a\n"  4
  290. stmt: LTU(reg,mrc1)  "cmp %0,%1\njb near %a\n"   4
  291. cmpf: memf  " %0"
  292. cmpf: reg   "p"
  293. stmt: EQD(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\nje near %a\n"
  294. stmt: GED(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\njbe near %a\n"
  295. stmt: GTD(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\njb near %a\n"
  296. stmt: LED(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\njae near %a\n"
  297. stmt: LTD(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\nja near %a\n"
  298. stmt: NED(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\njne near %a\n"
  299.  
  300. stmt: EQF(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\nje near %a\n"
  301. stmt: GEF(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\njbe near %a\n"
  302. stmt: GTF(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\njb near %a\n"
  303. stmt: LEF(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\njae near %a\n"
  304. stmt: LTF(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\nja near %a\n"
  305. stmt: NEF(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\njne near %a\n"
  306. reg:  CALLI(addrj)  "call %0\nadd esp,%a\n"
  307. stmt: CALLV(addrj)  "call %0\nadd esp,%a\n"
  308. reg: CALLF(addrj)  "call %0\nadd esp,%a\n"
  309. reg: CALLD(addrj)  "call %0\nadd esp,%a\n"
  310.  
  311. stmt: RETI(reg)  "# ret\n"
  312. stmt: RETF(reg)  "# ret\n"
  313. stmt: RETD(reg)  "# ret\n"
  314. %%
  315. static void progbeg(argc, argv) int argc; char *argv[]; {
  316.     int i;
  317.  
  318.     {
  319.         union {
  320.             char c;
  321.             int i;
  322.         } u;
  323.         u.i = 0;
  324.         u.c = 1;
  325.         swap = (u.i == 1) != IR->little_endian;
  326.     }
  327.     parseflags(argc, argv);
  328.     intreg[EAX] = mkreg("eax", EAX, 1, IREG);
  329.     intreg[EDX] = mkreg("edx", EDX, 1, IREG);
  330.     intreg[ECX] = mkreg("ecx", ECX, 1, IREG);
  331.     intreg[EBX] = mkreg("ebx", EBX, 1, IREG);
  332.     intreg[ESI] = mkreg("esi", ESI, 1, IREG);
  333.     intreg[EDI] = mkreg("edi", EDI, 1, IREG);
  334.     shortreg[EAX] = mkreg("ax", EAX, 1, IREG);
  335.     shortreg[ECX] = mkreg("cx", ECX, 1, IREG);
  336.     shortreg[EDX] = mkreg("dx", EDX, 1, IREG);
  337.     shortreg[EBX] = mkreg("bx", EBX, 1, IREG);
  338.     shortreg[ESI] = mkreg("si", ESI, 1, IREG);
  339.     shortreg[EDI] = mkreg("di", EDI, 1, IREG);
  340.  
  341.     charreg[EAX]  = mkreg("al", EAX, 1, IREG);
  342.     charreg[ECX]  = mkreg("cl", ECX, 1, IREG);
  343.     charreg[EDX]  = mkreg("dl", EDX, 1, IREG);
  344.     charreg[EBX]  = mkreg("bl", EBX, 1, IREG);
  345.     for (i = 0; i < 8; i++)
  346.         fltreg[i] = mkreg("%d", i, 0, FREG);
  347.     rmap[C] = mkwildcard(charreg);
  348.     rmap[S] = mkwildcard(shortreg);
  349.     rmap[P] = rmap[B] = rmap[U] = rmap[I] = mkwildcard(intreg);
  350.     rmap[F] = rmap[D] = mkwildcard(fltreg);
  351.     tmask[IREG] = (1<<EDI) | (1<<ESI) | (1<<EBX)
  352.                 | (1<<EDX) | (1<<ECX) | (1<<EAX);
  353.     vmask[IREG] = 0;
  354.     tmask[FREG] = 0xff;
  355.     vmask[FREG] = 0;
  356.     cseg = 0;
  357.     quo = mkreg("eax", EAX, 1, IREG);
  358.     quo->x.regnode->mask |= 1<<EDX;
  359.     rem = mkreg("edx", EDX, 1, IREG);
  360.     rem->x.regnode->mask |= 1<<EAX;
  361. }
  362. static void segment(n) int n; {
  363.     if (n == cseg)
  364.         return;
  365.     cseg = n;
  366.     if (cseg == CODE)
  367.         print("[section .text]\n");
  368.     else if (cseg == DATA || cseg == LIT)
  369.         print("[section .data]\n");
  370.     else if (cseg == BSS)
  371.         print("[section .bss]\n");
  372. }
  373. static void progend() {
  374.  
  375. }
  376. static void target(p) Node p; {
  377.     assert(p);
  378.     switch (p->op) {
  379.     case RSHI: case RSHU: case LSHI: case LSHU:
  380.         if (generic(p->kids[1]->op) != CNST
  381.         && !(   generic(p->kids[1]->op) == INDIR
  382.              && p->kids[1]->kids[0]->op == VREG+P
  383.              && p->kids[1]->syms[RX]->u.t.cse
  384.              && generic(p->kids[1]->syms[RX]->u.t.cse->op) == CNST
  385. )) {
  386.             rtarget(p, 1, intreg[ECX]);
  387.             setreg(p, intreg[EAX]);
  388.         }
  389.         break;
  390.     case MULU:
  391.         setreg(p, quo);
  392.         rtarget(p, 0, intreg[EAX]);
  393.         break;
  394.     case DIVI: case DIVU:
  395.         setreg(p, quo);
  396.         rtarget(p, 0, intreg[EAX]);
  397.         rtarget(p, 1, intreg[ECX]);
  398.         break;
  399.     case MODI: case MODU:
  400.         setreg(p, rem);
  401.         rtarget(p, 0, intreg[EAX]);
  402.         rtarget(p, 1, intreg[ECX]);
  403.         break;
  404.     case ASGNB:
  405.         rtarget(p, 0, intreg[EDI]);
  406.         rtarget(p->kids[1], 0, intreg[ESI]);
  407.         break;
  408.     case ARGB:
  409.         rtarget(p->kids[0], 0, intreg[ESI]);
  410.         break;
  411.     case CALLI: case CALLV:
  412.         setreg(p, intreg[EAX]);
  413.         break;
  414.     case RETI:
  415.         rtarget(p, 0, intreg[EAX]);
  416.         break;
  417.     }
  418. }
  419.  
  420. static void clobber(p) Node p; {
  421.     static int nstack = 0;
  422.  
  423.     assert(p);
  424.     nstack = ckstack(p, nstack);
  425.     assert(p->count > 0 || nstack == 0);
  426.     switch (p->op) {
  427.     case ASGNB: case ARGB:
  428.         spill(1<<ECX | 1<<ESI | 1<<EDI, IREG, p);
  429.         break;
  430.     case EQD: case LED: case GED: case LTD: case GTD: case NED:
  431.     case EQF: case LEF: case GEF: case LTF: case GTF: case NEF:
  432.         spill(1<<EAX, IREG, p);
  433.         break;
  434.     case CALLD: case CALLF:
  435.         spill(1<<EDX | 1<<EAX, IREG, p);
  436.         break;
  437.     }
  438. }
  439. #define isfp(p) (optype((p)->op)==F || optype((p)->op)==D)
  440.  
  441. static int ckstack(p, n) Node p; int n; {
  442.     int i;
  443.  
  444.     for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++)
  445.         if (isfp(p->x.kids[i]))
  446.             n--;
  447.     if (isfp(p) && p->count > 0)
  448.         n++;
  449.     if (n > 8)
  450.         error("expression too complicated\n");
  451.     debug(fprint(2, "(ckstack(%x)=%d)\n", p, n));
  452.     assert(n >= 0);
  453.     return n;
  454. }
  455. static int memop(p) Node p; {
  456.     assert(p);
  457.     assert(generic(p->op) == ASGN);
  458.     assert(p->kids[0]);
  459.     assert(p->kids[1]);
  460.     if (generic(p->kids[1]->kids[0]->op) == INDIR
  461.     && sametree(p->kids[0], p->kids[1]->kids[0]->kids[0]))
  462.         return 3;
  463.     else
  464.         return LBURG_MAX;
  465. }
  466. static int sametree(p, q) Node p, q; {
  467.     return p == NULL && q == NULL
  468.     || p && q && p->op == q->op && p->syms[0] == q->syms[0]
  469.         && sametree(p->kids[0], q->kids[0])
  470.         && sametree(p->kids[1], q->kids[1]);
  471. }
  472. static void emit2(p) Node p; {
  473. #define preg(f) ((f)[getregnum(p->x.kids[0])]->x.name)
  474.  
  475.     if (p->op == CVCI)
  476.         print("movsx %s,%s\n", p->syms[RX]->x.name
  477. , preg(charreg));
  478.     else if (p->op == CVCU)
  479.         print("movzx %s,%s\n", p->syms[RX]->x.name
  480. , preg(charreg));
  481.     else if (p->op == CVSI)
  482.         print("movsx %s,%s\n", p->syms[RX]->x.name
  483. , preg(shortreg));
  484.     else if (p->op == CVSU)
  485.         print("movzx %s,%s\n", p->syms[RX]->x.name
  486. , preg(shortreg));
  487.     else if (p->op == CVIC || p->op == CVIS
  488.           || p->op == CVUC || p->op == CVUS) {
  489.         char *dst = shortreg[getregnum(p)]->x.name;
  490.         char *src = preg(shortreg);
  491.         if (dst != src)
  492.             print("mov %s,%s\n", dst, src);
  493.     }
  494. }
  495.  
  496. static void doarg(p) Node p; {
  497.     assert(p && p->syms[0]);
  498.     mkactual(4, p->syms[0]->u.c.v.i);
  499. }
  500. static void blkfetch(k, off, reg, tmp)
  501. int k, off, reg, tmp; {}
  502. static void blkstore(k, off, reg, tmp)
  503. int k, off, reg, tmp; {}
  504. static void blkloop(dreg, doff, sreg, soff, size, tmps)
  505. int dreg, doff, sreg, soff, size, tmps[]; {}
  506. static void local(p) Symbol p; {
  507.     if (isfloat(p->type))
  508.         p->sclass = AUTO;
  509.     if (askregvar(p, rmap[ttob(p->type)]) == 0)
  510.         mkauto(p);
  511. }
  512. static void function(f, caller, callee, n)
  513. Symbol f, callee[], caller[]; int n; {
  514.     int i;
  515.  
  516.     print("%s:\n", f->x.name);
  517.     print("push ebx\n");
  518.     print("push esi\n");
  519.     print("push edi\n");
  520.     print("push ebp\n");
  521.     print("mov ebp,esp\n");
  522. usedmask[0] = usedmask[1] = 0;
  523. freemask[0] = freemask[1] = ~(unsigned)0;
  524.     offset = 16 + 4;
  525.     for (i = 0; callee[i]; i++) {
  526.         Symbol p = callee[i];
  527.         Symbol q = caller[i];
  528.         assert(q);
  529.         p->x.offset = q->x.offset = offset;
  530.         p->x.name = q->x.name = stringf("%d", p->x.offset);
  531.         p->sclass = q->sclass = AUTO;
  532.         offset += roundup(q->type->size, 4);
  533.     }
  534.     assert(caller[i] == 0);
  535.     offset = maxoffset = 0;
  536.     gencode(caller, callee);
  537.     framesize = roundup(maxoffset, 4);
  538.     if (framesize > 0)
  539.         print("sub esp,%d\n", framesize);
  540.     emitcode();
  541.     print("mov esp,ebp\n");
  542.     print("pop ebp\n");
  543.     print("pop edi\n");
  544.     print("pop esi\n");
  545.     print("pop ebx\n");
  546.     print("ret\n");
  547. }
  548. static void defsymbol(p) Symbol p; {
  549.     if (p->scope >= LOCAL && p->sclass == STATIC)
  550.         p->x.name = stringf("L%d", genlabel(1));
  551.     else if (p->generated)
  552.         p->x.name = stringf("$L%s", p->name);
  553.     else if (p->scope == GLOBAL || p->sclass == EXTERN)
  554.     /* CHANGE THIS FOR a.out */
  555. #if 0
  556.         p->x.name = stringf("$_%s", p->name);
  557. #else
  558.         p->x.name = stringf("$%s", p->name);
  559. #endif
  560.     else if (p->scope == CONSTANTS
  561.     && (isint(p->type) || isptr(p->type))
  562.     && p->name[0] == '0' && p->name[1] == 'x')
  563.         p->x.name = stringf("0%sH", &p->name[2]);
  564.     else
  565.         p->x.name = p->name;
  566. }
  567. static void address(q, p, n) Symbol q, p; int n; {
  568.     if (p->scope == GLOBAL
  569.     || p->sclass == STATIC || p->sclass == EXTERN)
  570.         q->x.name = stringf("%s%s%d",
  571.             p->x.name, n >= 0 ? "+" : "", n);
  572.     else {
  573.         q->x.offset = p->x.offset + n;
  574.         q->x.name = stringd(q->x.offset);
  575.     }
  576. }
  577. static void defconst(ty, v) int ty; Value v; {
  578.     switch (ty) {
  579.         case C: print("db %d\n",   v.uc); return;
  580.         case S: print("dw %d\n",   v.ss); return;
  581.         case I: print("dd %d\n",   v.i ); return;
  582.         case U: print("dd 0%xH\n", v.u ); return;
  583.         case P: print("dd 0%xH\n", v.p ); return;
  584.         case F:
  585.             print("dd 0%xH\n", *(unsigned *)&v.f);
  586.             return;
  587.         case D: {
  588.             unsigned *p = (unsigned *)&v.d;
  589.             print("dd 0%xH,0%xH\n", p[swap], p[1 - swap]);
  590.             return;
  591.             }
  592.     }
  593.     assert(0);
  594. }
  595. static void defaddress(p) Symbol p; {
  596.     print("dd %s\n", p->x.name);
  597. }
  598. static void defstring(n, str) int n; char *str; {
  599.     char *s;
  600.     int inquote = 1;
  601.  
  602.     print("db '");
  603.  
  604.     for (s = str; s < str + n; s++)
  605.     {
  606.         if ((*s & 0x7F) == *s && *s >= ' ' && *s != '\'') {
  607.             if (!inquote){
  608.                 print(", '");
  609.                 inquote = 1;
  610.             }
  611.             print("%c",*s);
  612.         }
  613.         else
  614.         {
  615.             if (inquote){
  616.                 print("', ");
  617.                 inquote = 0;
  618.             }
  619.             else
  620.                 print(", ");
  621.             print("%d",*s);
  622.         }
  623.     }
  624.     if (inquote) print("'");
  625.     print("\n");
  626. }
  627. static void export(p) Symbol p; {
  628.     print("[global %s]\n", p->x.name);
  629. }
  630. static void import(p) Symbol p; {
  631.     if (p->ref > 0) {
  632.         print("[extern %s]\n", p->x.name);
  633.     }
  634. }
  635. static void global(p) Symbol p; {
  636.     int i;
  637.  
  638.     if (p->u.seg == BSS)
  639.         print("resb ($-$$) & %d\n",
  640.             p->type->align > 4 ? 3 : p->type->align-1);
  641.     else
  642.         print("times ($-$$) & %d nop\n",
  643.             p->type->align > 4 ? 3 : p->type->align-1);
  644.     print("%s:\n", p->x.name);
  645.     if (p->u.seg == BSS)
  646.         print("resb %d\n", p->type->size);
  647. }
  648. static void space(n) int n; {
  649.     int i;
  650.  
  651.     if (cseg != BSS)
  652.         print("times %d db 0\n", n);
  653. }
  654. Interface x86nasmIR = {
  655.     1, 1, 0,  /* char */
  656.     2, 2, 0,  /* short */
  657.     4, 4, 0,  /* int */
  658.     4, 4, 1,  /* float */
  659.     8, 4, 1,  /* double */
  660.     4, 4, 0,  /* T * */
  661.     0, 4, 0,  /* struct; so that ARGB keeps stack aligned */
  662.     1,        /* little_endian */
  663.     0,        /* mulops_calls */
  664.     0,        /* wants_callb */
  665.     1,        /* wants_argb */
  666.     0,        /* left_to_right */
  667.     0,        /* wants_dag */
  668.     address,
  669.     blockbeg,
  670.     blockend,
  671.     defaddress,
  672.     defconst,
  673.     defstring,
  674.     defsymbol,
  675.     emit,
  676.     export,
  677.     function,
  678.     gen,
  679.     global,
  680.     import,
  681.     local,
  682.     progbeg,
  683.     progend,
  684.     segment,
  685.     space,
  686.     0, 0, 0, 0, 0, 0, 0,
  687.     {1, blkfetch, blkstore, blkloop,
  688.         _label,
  689.         _rule,
  690.         _nts,
  691.         _kids,
  692.         _opname,
  693.         _arity,
  694.         _string,
  695.         _templates,
  696.         _isinstruction,
  697.         _ntname,
  698.         emit2,
  699.         doarg,
  700.         target,
  701.         clobber,
  702. }
  703. };
  704.