Rewrote version.pl, and added some tests
[nasm/perl-rewrite.git] / lcc / x86nasm.md
blob54d0be6c6fd1b9d538dc78661f9e087730ed1f28
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];
36 static int cseg;
38 static Symbol quo, rem;
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
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"
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"
138 mr:   reg  "%0"
139 mr:   mem  "%0"
141 mrc0: mem  "%0"
142 mrc0: rc   "%0"
143 mrc1: mem  "%0"  1
144 mrc1: rc   "%0"
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)
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
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
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)
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
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"
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
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
261 reg: CVID(INDIRI(addr))  "fild dword %0\n"  10
262 reg: CVID(reg)  "push %0\nfild dword [esp]\nadd esp,4\n"  12
264 addrj: ADDRGP  "%a"
265 addrj: reg     "%0"  2
266 addrj: mem     "%0"  2
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
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"
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"
311 stmt: RETI(reg)  "# ret\n"
312 stmt: RETF(reg)  "# ret\n"
313 stmt: RETD(reg)  "# ret\n"
315 static void progbeg(argc, argv) int argc; char *argv[]; {
316         int i;
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);
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;
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");
373 static void progend() {
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         }
420 static void clobber(p) Node p; {
421         static int nstack = 0;
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         }
439 #define isfp(p) (optype((p)->op)==F || optype((p)->op)==D)
441 static int ckstack(p, n) Node p; int n; {
442         int i;
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;
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;
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]);
472 static void emit2(p) Node p; {
473 #define preg(f) ((f)[getregnum(p->x.kids[0])]->x.name)
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         }
496 static void doarg(p) Node p; {
497         assert(p && p->syms[0]);
498         mkactual(4, p->syms[0]->u.c.v.i);
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);
512 static void function(f, caller, callee, n)
513 Symbol f, callee[], caller[]; int n; {
514         int i;
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");
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;
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         }
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);
595 static void defaddress(p) Symbol p; {
596         print("dd %s\n", p->x.name);
598 static void defstring(n, str) int n; char *str; {
599         char *s;
600         int inquote = 1;
602         print("db '");
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");
627 static void export(p) Symbol p; {
628         print("[global %s]\n", p->x.name);
630 static void import(p) Symbol p; {
631         if (p->ref > 0) {
632                 print("[extern %s]\n", p->x.name);
633         }
635 static void global(p) Symbol p; {
636         int i;
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);
648 static void space(n) int n; {
649         int i;
651         if (cseg != BSS)
652                 print("times %d db 0\n", n);
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,