x86.md (29325B)
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(Symbol, Symbol, long); 10 static void blkfetch(int, int, int, int); 11 static void blkloop(int, int, int, int, int, int[]); 12 static void blkstore(int, int, int, int); 13 static void defaddress(Symbol); 14 static void defconst(int, int, Value); 15 static void defstring(int, char *); 16 static void defsymbol(Symbol); 17 static void doarg(Node); 18 static void emit2(Node); 19 static void export(Symbol); 20 static void clobber(Node); 21 static void function(Symbol, Symbol [], Symbol [], int); 22 static void global(Symbol); 23 static void import(Symbol); 24 static void local(Symbol); 25 static void progbeg(int, char **); 26 static void progend(void); 27 static void segment(int); 28 static void space(int); 29 static void target(Node); 30 extern int ckstack(Node, int); 31 extern int memop(Node); 32 extern int sametree(Node, Node); 33 static Symbol charreg[32], shortreg[32], intreg[32]; 34 static Symbol fltreg[32]; 35 36 static Symbol charregw, shortregw, intregw, fltregw; 37 38 static int cseg; 39 40 static Symbol quo, rem; 41 42 %} 43 %start stmt 44 %term CNSTF4=4113 45 %term CNSTF8=8209 46 %term CNSTF16=16401 47 %term CNSTI1=1045 48 %term CNSTI2=2069 49 %term CNSTI4=4117 50 %term CNSTI8=8213 51 %term CNSTP4=4119 52 %term CNSTP8=8215 53 %term CNSTU1=1046 54 %term CNSTU2=2070 55 %term CNSTU4=4118 56 %term CNSTU8=8214 57 58 %term ARGB=41 59 %term ARGF4=4129 60 %term ARGF8=8225 61 %term ARGF16=16417 62 %term ARGI4=4133 63 %term ARGI8=8229 64 %term ARGP4=4135 65 %term ARGP8=8231 66 %term ARGU4=4134 67 %term ARGU8=8230 68 69 %term ASGNB=57 70 %term ASGNF4=4145 71 %term ASGNF8=8241 72 %term ASGNF16=16433 73 %term ASGNI1=1077 74 %term ASGNI2=2101 75 %term ASGNI4=4149 76 %term ASGNI8=8245 77 %term ASGNP4=4151 78 %term ASGNP8=8247 79 %term ASGNU1=1078 80 %term ASGNU2=2102 81 %term ASGNU4=4150 82 %term ASGNU8=8246 83 84 %term INDIRB=73 85 %term INDIRF4=4161 86 %term INDIRF8=8257 87 %term INDIRF16=16449 88 %term INDIRI1=1093 89 %term INDIRI2=2117 90 %term INDIRI4=4165 91 %term INDIRI8=8261 92 %term INDIRP4=4167 93 %term INDIRP8=8263 94 %term INDIRU1=1094 95 %term INDIRU2=2118 96 %term INDIRU4=4166 97 %term INDIRU8=8262 98 99 %term CVFF4=4209 100 %term CVFF8=8305 101 %term CVFF16=16497 102 %term CVFI4=4213 103 %term CVFI8=8309 104 105 %term CVIF4=4225 106 %term CVIF8=8321 107 %term CVIF16=16513 108 %term CVII1=1157 109 %term CVII2=2181 110 %term CVII4=4229 111 %term CVII8=8325 112 %term CVIU1=1158 113 %term CVIU2=2182 114 %term CVIU4=4230 115 %term CVIU8=8326 116 117 %term CVPP4=4247 118 %term CVPP8=8343 119 %term CVPP16=16535 120 %term CVPU4=4246 121 %term CVPU8=8342 122 123 %term CVUI1=1205 124 %term CVUI2=2229 125 %term CVUI4=4277 126 %term CVUI8=8373 127 %term CVUP4=4279 128 %term CVUP8=8375 129 %term CVUP16=16567 130 %term CVUU1=1206 131 %term CVUU2=2230 132 %term CVUU4=4278 133 %term CVUU8=8374 134 135 %term NEGF4=4289 136 %term NEGF8=8385 137 %term NEGF16=16577 138 %term NEGI4=4293 139 %term NEGI8=8389 140 141 %term CALLB=217 142 %term CALLF4=4305 143 %term CALLF8=8401 144 %term CALLF16=16593 145 %term CALLI4=4309 146 %term CALLI8=8405 147 %term CALLP4=4311 148 %term CALLP8=8407 149 %term CALLU4=4310 150 %term CALLU8=8406 151 %term CALLV=216 152 153 %term RETF4=4337 154 %term RETF8=8433 155 %term RETF16=16625 156 %term RETI4=4341 157 %term RETI8=8437 158 %term RETP4=4343 159 %term RETP8=8439 160 %term RETU4=4342 161 %term RETU8=8438 162 %term RETV=248 163 164 %term ADDRGP4=4359 165 %term ADDRGP8=8455 166 167 %term ADDRFP4=4375 168 %term ADDRFP8=8471 169 170 %term ADDRLP4=4391 171 %term ADDRLP8=8487 172 173 %term ADDF4=4401 174 %term ADDF8=8497 175 %term ADDF16=16689 176 %term ADDI4=4405 177 %term ADDI8=8501 178 %term ADDP4=4407 179 %term ADDP8=8503 180 %term ADDU4=4406 181 %term ADDU8=8502 182 183 %term SUBF4=4417 184 %term SUBF8=8513 185 %term SUBF16=16705 186 %term SUBI4=4421 187 %term SUBI8=8517 188 %term SUBP4=4423 189 %term SUBP8=8519 190 %term SUBU4=4422 191 %term SUBU8=8518 192 193 %term LSHI4=4437 194 %term LSHI8=8533 195 %term LSHU4=4438 196 %term LSHU8=8534 197 198 %term MODI4=4453 199 %term MODI8=8549 200 %term MODU4=4454 201 %term MODU8=8550 202 203 %term RSHI4=4469 204 %term RSHI8=8565 205 %term RSHU4=4470 206 %term RSHU8=8566 207 208 %term BANDI4=4485 209 %term BANDI8=8581 210 %term BANDU4=4486 211 %term BANDU8=8582 212 213 %term BCOMI4=4501 214 %term BCOMI8=8597 215 %term BCOMU4=4502 216 %term BCOMU8=8598 217 218 %term BORI4=4517 219 %term BORI8=8613 220 %term BORU4=4518 221 %term BORU8=8614 222 223 %term BXORI4=4533 224 %term BXORI8=8629 225 %term BXORU4=4534 226 %term BXORU8=8630 227 228 %term DIVF4=4545 229 %term DIVF8=8641 230 %term DIVF16=16833 231 %term DIVI4=4549 232 %term DIVI8=8645 233 %term DIVU4=4550 234 %term DIVU8=8646 235 236 %term MULF4=4561 237 %term MULF8=8657 238 %term MULF16=16849 239 %term MULI4=4565 240 %term MULI8=8661 241 %term MULU4=4566 242 %term MULU8=8662 243 244 %term EQF4=4577 245 %term EQF8=8673 246 %term EQF16=16865 247 %term EQI4=4581 248 %term EQI8=8677 249 %term EQU4=4582 250 %term EQU8=8678 251 252 %term GEF4=4593 253 %term GEF8=8689 254 %term GEI4=4597 255 %term GEI8=8693 256 %term GEI16=16885 257 %term GEU4=4598 258 %term GEU8=8694 259 260 %term GTF4=4609 261 %term GTF8=8705 262 %term GTF16=16897 263 %term GTI4=4613 264 %term GTI8=8709 265 %term GTU4=4614 266 %term GTU8=8710 267 268 %term LEF4=4625 269 %term LEF8=8721 270 %term LEF16=16913 271 %term LEI4=4629 272 %term LEI8=8725 273 %term LEU4=4630 274 %term LEU8=8726 275 276 %term LTF4=4641 277 %term LTF8=8737 278 %term LTF16=16929 279 %term LTI4=4645 280 %term LTI8=8741 281 %term LTU4=4646 282 %term LTU8=8742 283 284 %term NEF4=4657 285 %term NEF8=8753 286 %term NEF16=16945 287 %term NEI4=4661 288 %term NEI8=8757 289 %term NEU4=4662 290 %term NEU8=8758 291 292 %term JUMPV=584 293 294 %term LABELV=600 295 296 %term LOADB=233 297 %term LOADF4=4321 298 %term LOADF8=8417 299 %term LOADF16=16609 300 %term LOADI1=1253 301 %term LOADI2=2277 302 %term LOADI4=4325 303 %term LOADI8=8421 304 %term LOADP4=4327 305 %term LOADP8=8423 306 %term LOADU1=1254 307 %term LOADU2=2278 308 %term LOADU4=4326 309 %term LOADU8=8422 310 311 %term VREGP=711 312 %% 313 reg: INDIRI1(VREGP) "# read register\n" 314 reg: INDIRU1(VREGP) "# read register\n" 315 316 reg: INDIRI2(VREGP) "# read register\n" 317 reg: INDIRU2(VREGP) "# read register\n" 318 319 reg: INDIRF4(VREGP) "# read register\n" 320 reg: INDIRI4(VREGP) "# read register\n" 321 reg: INDIRP4(VREGP) "# read register\n" 322 reg: INDIRU4(VREGP) "# read register\n" 323 324 reg: INDIRF8(VREGP) "# read register\n" 325 reg: INDIRI8(VREGP) "# read register\n" 326 reg: INDIRP8(VREGP) "# read register\n" 327 reg: INDIRU8(VREGP) "# read register\n" 328 329 stmt: ASGNI1(VREGP,reg) "# write register\n" 330 stmt: ASGNU1(VREGP,reg) "# write register\n" 331 332 stmt: ASGNI2(VREGP,reg) "# write register\n" 333 stmt: ASGNU2(VREGP,reg) "# write register\n" 334 335 stmt: ASGNF4(VREGP,reg) "# write register\n" 336 stmt: ASGNI4(VREGP,reg) "# write register\n" 337 stmt: ASGNP4(VREGP,reg) "# write register\n" 338 stmt: ASGNU4(VREGP,reg) "# write register\n" 339 340 stmt: ASGNF8(VREGP,reg) "# write register\n" 341 stmt: ASGNI8(VREGP,reg) "# write register\n" 342 stmt: ASGNP8(VREGP,reg) "# write register\n" 343 stmt: ASGNU8(VREGP,reg) "# write register\n" 344 con: CNSTI1 "%a" 345 con: CNSTU1 "%a" 346 347 con: CNSTI2 "%a" 348 con: CNSTU2 "%a" 349 350 con: CNSTI4 "%a" 351 con: CNSTU4 "%a" 352 con: CNSTP4 "%a" 353 354 con: CNSTI8 "%a" 355 con: CNSTU8 "%a" 356 con: CNSTP8 "%a" 357 stmt: reg "" 358 acon: ADDRGP4 "(%a)" 359 acon: con "(%0)" 360 base: ADDRGP4 "(%a)" 361 base: reg "[%0]" 362 base: ADDI4(reg,acon) "%1[%0]" 363 base: ADDP4(reg,acon) "%1[%0]" 364 base: ADDU4(reg,acon) "%1[%0]" 365 base: ADDRFP4 "(%a)[ebp]" 366 base: ADDRLP4 "(%a)[ebp]" 367 index: reg "%0" 368 index: LSHI4(reg,con1) "%0*2" 369 index: LSHI4(reg,con2) "%0*4" 370 index: LSHI4(reg,con3) "%0*8" 371 372 con1: CNSTI4 "1" range(a, 1, 1) 373 con1: CNSTU4 "1" range(a, 1, 1) 374 con2: CNSTI4 "2" range(a, 2, 2) 375 con2: CNSTU4 "2" range(a, 2, 2) 376 con3: CNSTI4 "3" range(a, 3, 3) 377 con3: CNSTU4 "3" range(a, 3, 3) 378 index: LSHU4(reg,con1) "%0*2" 379 index: LSHU4(reg,con2) "%0*4" 380 index: LSHU4(reg,con3) "%0*8" 381 addr: base "%0" 382 addr: ADDI4(index,base) "%1[%0]" 383 addr: ADDP4(index,base) "%1[%0]" 384 addr: ADDU4(index,base) "%1[%0]" 385 addr: index "[%0]" 386 mem: INDIRI1(addr) "byte ptr %0" 387 mem: INDIRI2(addr) "word ptr %0" 388 mem: INDIRI4(addr) "dword ptr %0" 389 mem: INDIRU1(addr) "byte ptr %0" 390 mem: INDIRU2(addr) "word ptr %0" 391 mem: INDIRU4(addr) "dword ptr %0" 392 mem: INDIRP4(addr) "dword ptr %0" 393 rc: reg "%0" 394 rc: con "%0" 395 396 mr: reg "%0" 397 mr: mem "%0" 398 399 mrc0: mem "%0" 400 mrc0: rc "%0" 401 mrc1: mem "%0" 1 402 mrc1: rc "%0" 403 404 mrc3: mem "%0" 3 405 mrc3: rc "%0" 406 reg: addr "lea %c,%0\n" 1 407 reg: mrc0 "mov %c,%0\n" 1 408 reg: LOADI1(reg) "# move\n" 1 409 reg: LOADI2(reg) "# move\n" 1 410 reg: LOADI4(reg) "# move\n" move(a) 411 reg: LOADU1(reg) "# move\n" 1 412 reg: LOADU2(reg) "# move\n" 1 413 reg: LOADU4(reg) "# move\n" move(a) 414 reg: LOADP4(reg) "# move\n" move(a) 415 reg: ADDI4(reg,mrc1) "?mov %c,%0\nadd %c,%1\n" 1 416 reg: ADDP4(reg,mrc1) "?mov %c,%0\nadd %c,%1\n" 1 417 reg: ADDU4(reg,mrc1) "?mov %c,%0\nadd %c,%1\n" 1 418 reg: SUBI4(reg,mrc1) "?mov %c,%0\nsub %c,%1\n" 1 419 reg: SUBP4(reg,mrc1) "?mov %c,%0\nsub %c,%1\n" 1 420 reg: SUBU4(reg,mrc1) "?mov %c,%0\nsub %c,%1\n" 1 421 reg: BANDI4(reg,mrc1) "?mov %c,%0\nand %c,%1\n" 1 422 reg: BORI4(reg,mrc1) "?mov %c,%0\nor %c,%1\n" 1 423 reg: BXORI4(reg,mrc1) "?mov %c,%0\nxor %c,%1\n" 1 424 reg: BANDU4(reg,mrc1) "?mov %c,%0\nand %c,%1\n" 1 425 reg: BORU4(reg,mrc1) "?mov %c,%0\nor %c,%1\n" 1 426 reg: BXORU4(reg,mrc1) "?mov %c,%0\nxor %c,%1\n" 1 427 stmt: ASGNI4(addr,ADDI4(mem,con1)) "inc %1\n" memop(a) 428 stmt: ASGNI4(addr,ADDU4(mem,con1)) "inc %1\n" memop(a) 429 stmt: ASGNP4(addr,ADDP4(mem,con1)) "inc %1\n" memop(a) 430 stmt: ASGNI4(addr,SUBI4(mem,con1)) "dec %1\n" memop(a) 431 stmt: ASGNI4(addr,SUBU4(mem,con1)) "dec %1\n" memop(a) 432 stmt: ASGNP4(addr,SUBP4(mem,con1)) "dec %1\n" memop(a) 433 stmt: ASGNI4(addr,ADDI4(mem,rc)) "add %1,%2\n" memop(a) 434 stmt: ASGNI4(addr,SUBI4(mem,rc)) "sub %1,%2\n" memop(a) 435 stmt: ASGNU4(addr,ADDU4(mem,rc)) "add %1,%2\n" memop(a) 436 stmt: ASGNU4(addr,SUBU4(mem,rc)) "sub %1,%2\n" memop(a) 437 438 stmt: ASGNI4(addr,BANDI4(mem,rc)) "and %1,%2\n" memop(a) 439 stmt: ASGNI4(addr,BORI4(mem,rc)) "or %1,%2\n" memop(a) 440 stmt: ASGNI4(addr,BXORI4(mem,rc)) "xor %1,%2\n" memop(a) 441 stmt: ASGNU4(addr,BANDU4(mem,rc)) "and %1,%2\n" memop(a) 442 stmt: ASGNU4(addr,BORU4(mem,rc)) "or %1,%2\n" memop(a) 443 stmt: ASGNU4(addr,BXORU4(mem,rc)) "xor %1,%2\n" memop(a) 444 reg: BCOMI4(reg) "?mov %c,%0\nnot %c\n" 2 445 reg: BCOMU4(reg) "?mov %c,%0\nnot %c\n" 2 446 reg: NEGI4(reg) "?mov %c,%0\nneg %c\n" 2 447 448 stmt: ASGNI4(addr,BCOMI4(mem)) "not %1\n" memop(a) 449 stmt: ASGNU4(addr,BCOMU4(mem)) "not %1\n" memop(a) 450 stmt: ASGNI4(addr,NEGI4(mem)) "neg %1\n" memop(a) 451 reg: LSHI4(reg,con5) "?mov %c,%0\nsal %c,%1\n" 2 452 reg: LSHU4(reg,con5) "?mov %c,%0\nshl %c,%1\n" 2 453 reg: RSHI4(reg,con5) "?mov %c,%0\nsar %c,%1\n" 2 454 reg: RSHU4(reg,con5) "?mov %c,%0\nshr %c,%1\n" 2 455 456 stmt: ASGNI4(addr,LSHI4(mem,con5)) "sal %1,%2\n" memop(a) 457 stmt: ASGNI4(addr,LSHU4(mem,con5)) "shl %1,%2\n" memop(a) 458 stmt: ASGNI4(addr,RSHI4(mem,con5)) "sar %1,%2\n" memop(a) 459 stmt: ASGNI4(addr,RSHU4(mem,con5)) "shr %1,%2\n" memop(a) 460 461 con5: CNSTI4 "%a" range(a, 0, 31) 462 463 reg: LSHI4(reg,reg) "?mov %c,%0\nmov ecx,%1\nsal %c,cl\n" 3 464 reg: LSHU4(reg,reg) "?mov %c,%0\nmov ecx,%1\nshl %c,cl\n" 2 465 reg: RSHI4(reg,reg) "?mov %c,%0\nmov ecx,%1\nsar %c,cl\n" 2 466 reg: RSHU4(reg,reg) "?mov %c,%0\nmov ecx,%1\nshr %c,cl\n" 2 467 reg: MULI4(reg,mrc3) "?mov %c,%0\nimul %c,%1\n" 14 468 reg: MULI4(con,mr) "imul %c,%1,%0\n" 13 469 reg: MULU4(reg,mr) "mul %1\n" 13 470 reg: DIVU4(reg,reg) "xor edx,edx\ndiv %1\n" 471 reg: MODU4(reg,reg) "xor edx,edx\ndiv %1\n" 472 reg: DIVI4(reg,reg) "cdq\nidiv %1\n" 473 reg: MODI4(reg,reg) "cdq\nidiv %1\n" 474 reg: CVPU4(reg) "mov %c,%0\n" move(a) 475 reg: CVUP4(reg) "mov %c,%0\n" move(a) 476 reg: CVII4(INDIRI1(addr)) "movsx %c,byte ptr %0\n" 3 477 reg: CVII4(INDIRI2(addr)) "movsx %c,word ptr %0\n" 3 478 reg: CVUU4(INDIRU1(addr)) "movzx %c,byte ptr %0\n" 3 479 reg: CVUU4(INDIRU2(addr)) "movzx %c,word ptr %0\n" 3 480 reg: CVII4(reg) "# extend\n" 3 481 reg: CVIU4(reg) "# extend\n" 3 482 reg: CVUI4(reg) "# extend\n" 3 483 reg: CVUU4(reg) "# extend\n" 3 484 485 reg: CVII1(reg) "# truncate\n" 1 486 reg: CVII2(reg) "# truncate\n" 1 487 reg: CVUU1(reg) "# truncate\n" 1 488 reg: CVUU2(reg) "# truncate\n" 1 489 stmt: ASGNI1(addr,rc) "mov byte ptr %0,%1\n" 1 490 stmt: ASGNI2(addr,rc) "mov word ptr %0,%1\n" 1 491 stmt: ASGNI4(addr,rc) "mov dword ptr %0,%1\n" 1 492 stmt: ASGNU1(addr,rc) "mov byte ptr %0,%1\n" 1 493 stmt: ASGNU2(addr,rc) "mov word ptr %0,%1\n" 1 494 stmt: ASGNU4(addr,rc) "mov dword ptr %0,%1\n" 1 495 stmt: ASGNP4(addr,rc) "mov dword ptr %0,%1\n" 1 496 stmt: ARGI4(mrc3) "push %0\n" 1 497 stmt: ARGU4(mrc3) "push %0\n" 1 498 stmt: ARGP4(mrc3) "push %0\n" 1 499 stmt: ASGNB(reg,INDIRB(reg)) "mov ecx,%a\nrep movsb\n" 500 stmt: ARGB(INDIRB(reg)) "sub esp,%a\nmov edi,esp\nmov ecx,%a\nrep movsb\n" 501 502 memf: INDIRF8(addr) "qword ptr %0" 503 memf: INDIRF4(addr) "dword ptr %0" 504 memf: CVFF8(INDIRF4(addr)) "dword ptr %0" 505 reg: memf "fld %0\n" 3 506 stmt: ASGNF8(addr,reg) "fstp qword ptr %0\n" 7 507 stmt: ASGNF4(addr,reg) "fstp dword ptr %0\n" 7 508 stmt: ASGNF4(addr,CVFF4(reg)) "fstp dword ptr %0\n" 7 509 stmt: ARGF8(reg) "sub esp,8\nfstp qword ptr [esp]\n" 510 stmt: ARGF4(reg) "sub esp,4\nfstp dword ptr [esp]\n" 511 reg: NEGF8(reg) "fchs\n" 512 reg: NEGF4(reg) "fchs\n" 513 flt: memf " %0" 514 flt: reg "p st(1),st" 515 reg: ADDF8(reg,flt) "fadd%1\n" 516 reg: ADDF4(reg,flt) "fadd%1\n" 517 reg: DIVF8(reg,flt) "fdiv%1\n" 518 reg: DIVF4(reg,flt) "fdiv%1\n" 519 reg: MULF8(reg,flt) "fmul%1\n" 520 reg: MULF4(reg,flt) "fmul%1\n" 521 reg: SUBF8(reg,flt) "fsub%1\n" 522 reg: SUBF4(reg,flt) "fsub%1\n" 523 reg: CVFF8(reg) "# CVFF8\n" 524 reg: CVFF4(reg) "sub esp,4\nfstp dword ptr 0[esp]\nfld dword ptr 0[esp]\nadd esp,4\n" 12 525 526 reg: CVFI4(reg) "call __ftol\n" 31 527 reg: CVIF8(INDIRI4(addr)) "fild dword ptr %0\n" 10 528 reg: CVIF4(reg) "push %0\nfild dword ptr 0[esp]\nadd esp,4\n" 12 529 530 reg: CVIF8(reg) "push %0\nfild dword ptr 0[esp]\nadd esp,4\n" 12 531 532 addrj: ADDRGP4 "%a" 533 addrj: reg "%0" 2 534 addrj: mem "%0" 2 535 536 stmt: JUMPV(addrj) "jmp %0\n" 3 537 stmt: LABELV "%a:\n" 538 stmt: EQI4(mem,rc) "cmp %0,%1\nje %a\n" 5 539 stmt: GEI4(mem,rc) "cmp %0,%1\njge %a\n" 5 540 stmt: GTI4(mem,rc) "cmp %0,%1\njg %a\n" 5 541 stmt: LEI4(mem,rc) "cmp %0,%1\njle %a\n" 5 542 stmt: LTI4(mem,rc) "cmp %0,%1\njl %a\n" 5 543 stmt: NEI4(mem,rc) "cmp %0,%1\njne %a\n" 5 544 stmt: GEU4(mem,rc) "cmp %0,%1\njae %a\n" 5 545 stmt: GTU4(mem,rc) "cmp %0,%1\nja %a\n" 5 546 stmt: LEU4(mem,rc) "cmp %0,%1\njbe %a\n" 5 547 stmt: LTU4(mem,rc) "cmp %0,%1\njb %a\n" 5 548 stmt: EQI4(reg,mrc1) "cmp %0,%1\nje %a\n" 4 549 stmt: GEI4(reg,mrc1) "cmp %0,%1\njge %a\n" 4 550 stmt: GTI4(reg,mrc1) "cmp %0,%1\njg %a\n" 4 551 stmt: LEI4(reg,mrc1) "cmp %0,%1\njle %a\n" 4 552 stmt: LTI4(reg,mrc1) "cmp %0,%1\njl %a\n" 4 553 stmt: NEI4(reg,mrc1) "cmp %0,%1\njne %a\n" 4 554 555 stmt: EQU4(reg,mrc1) "cmp %0,%1\nje %a\n" 4 556 stmt: GEU4(reg,mrc1) "cmp %0,%1\njae %a\n" 4 557 stmt: GTU4(reg,mrc1) "cmp %0,%1\nja %a\n" 4 558 stmt: LEU4(reg,mrc1) "cmp %0,%1\njbe %a\n" 4 559 stmt: LTU4(reg,mrc1) "cmp %0,%1\njb %a\n" 4 560 stmt: NEU4(reg,mrc1) "cmp %0,%1\njne %a\n" 4 561 cmpf: memf " %0" 562 cmpf: reg "p" 563 stmt: EQF8(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\nje %a\n" 564 stmt: GEF8(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njbe %a\n" 565 stmt: GTF8(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njb %a\n" 566 stmt: LEF8(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njae %a\n" 567 stmt: LTF8(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\nja %a\n" 568 stmt: NEF8(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njne %a\n" 569 570 stmt: EQF4(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\nje %a\n" 571 stmt: GEF4(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njbe %a\n" 572 stmt: GTF4(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njb %a\n" 573 stmt: LEF4(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njae %a\n" 574 stmt: LTF4(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\nja %a\n" 575 stmt: NEF4(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njne %a\n" 576 reg: CALLI4(addrj) "call %0\nadd esp,%a\n" 577 reg: CALLU4(addrj) "call %0\nadd esp,%a\n" 578 reg: CALLP4(addrj) "call %0\nadd esp,%a\n" 579 stmt: CALLV(addrj) "call %0\nadd esp,%a\n" 580 reg: CALLF4(addrj) "call %0\nadd esp,%a\n" 581 reg: CALLF8(addrj) "call %0\nadd esp,%a\n" 582 stmt: CALLF4(addrj) "call %0\nadd esp,%a\nfstp\n" 583 stmt: CALLF8(addrj) "call %0\nadd esp,%a\nfstp\n" 584 585 stmt: RETI4(reg) "# ret\n" 586 stmt: RETU4(reg) "# ret\n" 587 stmt: RETP4(reg) "# ret\n" 588 stmt: RETF4(reg) "# ret\n" 589 stmt: RETF8(reg) "# ret\n" 590 %% 591 static void progbeg(int argc, char *argv[]) { 592 int i; 593 594 { 595 union { 596 char c; 597 int i; 598 } u; 599 u.i = 0; 600 u.c = 1; 601 swap = ((int)(u.i == 1)) != IR->little_endian; 602 } 603 parseflags(argc, argv); 604 intreg[EAX] = mkreg("eax", EAX, 1, IREG); 605 intreg[EDX] = mkreg("edx", EDX, 1, IREG); 606 intreg[ECX] = mkreg("ecx", ECX, 1, IREG); 607 intreg[EBX] = mkreg("ebx", EBX, 1, IREG); 608 intreg[ESI] = mkreg("esi", ESI, 1, IREG); 609 intreg[EDI] = mkreg("edi", EDI, 1, IREG); 610 611 shortreg[EAX] = mkreg("ax", EAX, 1, IREG); 612 shortreg[ECX] = mkreg("cx", ECX, 1, IREG); 613 shortreg[EDX] = mkreg("dx", EDX, 1, IREG); 614 shortreg[EBX] = mkreg("bx", EBX, 1, IREG); 615 shortreg[ESI] = mkreg("si", ESI, 1, IREG); 616 shortreg[EDI] = mkreg("di", EDI, 1, IREG); 617 618 charreg[EAX] = mkreg("al", EAX, 1, IREG); 619 charreg[ECX] = mkreg("cl", ECX, 1, IREG); 620 charreg[EDX] = mkreg("dl", EDX, 1, IREG); 621 charreg[EBX] = mkreg("bl", EBX, 1, IREG); 622 for (i = 0; i < 8; i++) 623 fltreg[i] = mkreg("%d", i, 0, FREG); 624 charregw = mkwildcard(charreg); 625 shortregw = mkwildcard(shortreg); 626 intregw = mkwildcard(intreg); 627 fltregw = mkwildcard(fltreg); 628 629 tmask[IREG] = (1<<EDI) | (1<<ESI) | (1<<EBX) 630 | (1<<EDX) | (1<<ECX) | (1<<EAX); 631 vmask[IREG] = 0; 632 tmask[FREG] = 0xff; 633 vmask[FREG] = 0; 634 print(".486\n"); 635 print(".model flat\n"); 636 print("extrn __fltused:near\n"); 637 print("extrn __ftol:near\n"); 638 cseg = 0; 639 quo = mkreg("eax", EAX, 1, IREG); 640 quo->x.regnode->mask |= 1<<EDX; 641 rem = mkreg("edx", EDX, 1, IREG); 642 rem->x.regnode->mask |= 1<<EAX; 643 } 644 static Symbol rmap(int opk) { 645 switch (optype(opk)) { 646 case B: case P: 647 return intregw; 648 case I: case U: 649 if (opsize(opk) == 1) 650 return charregw; 651 else if (opsize(opk) == 2) 652 return shortregw; 653 else 654 return intregw; 655 case F: 656 return fltregw; 657 default: 658 return 0; 659 } 660 } 661 static void segment(int n) { 662 if (n == cseg) 663 return; 664 if (cseg == CODE || cseg == LIT) 665 print("_TEXT ends\n"); 666 else if (cseg == DATA || cseg == BSS) 667 print("_DATA ends\n"); 668 cseg = n; 669 if (cseg == CODE || cseg == LIT) 670 print("_TEXT segment\n"); 671 else if (cseg == DATA || cseg == BSS) 672 print("_DATA segment\n"); 673 } 674 static void progend(void) { 675 segment(0); 676 print("end\n"); 677 } 678 static void target(Node p) { 679 assert(p); 680 switch (specific(p->op)) { 681 case MUL+U: 682 setreg(p, quo); 683 rtarget(p, 0, intreg[EAX]); 684 break; 685 case DIV+I: case DIV+U: 686 setreg(p, quo); 687 rtarget(p, 0, quo); 688 break; 689 case MOD+I: case MOD+U: 690 setreg(p, rem); 691 rtarget(p, 0, quo); 692 break; 693 case ASGN+B: 694 rtarget(p, 0, intreg[EDI]); 695 rtarget(p->kids[1], 0, intreg[ESI]); 696 break; 697 case ARG+B: 698 rtarget(p->kids[0], 0, intreg[ESI]); 699 break; 700 case CVF+I: 701 setreg(p, intreg[EAX]); 702 break; 703 case CALL+I: case CALL+U: case CALL+P: case CALL+V: 704 setreg(p, intreg[EAX]); 705 break; 706 case RET+I: case RET+U: case RET+P: 707 rtarget(p, 0, intreg[EAX]); 708 break; 709 } 710 } 711 712 static void clobber(Node p) { 713 static int nstack = 0; 714 715 assert(p); 716 nstack = ckstack(p, nstack); 717 switch (specific(p->op)) { 718 case RSH+I: case RSH+U: case LSH+I: case LSH+U: 719 if (generic(p->kids[1]->op) != CNST 720 && !( generic(p->kids[1]->op) == INDIR 721 && specific(p->kids[1]->kids[0]->op) == VREG+P 722 && p->kids[1]->syms[RX]->u.t.cse 723 && generic(p->kids[1]->syms[RX]->u.t.cse->op) == CNST 724 )) { 725 spill(1<<ECX, 1, p); 726 } 727 break; 728 case ASGN+B: case ARG+B: 729 spill(1<<ECX | 1<<ESI | 1<<EDI, IREG, p); 730 break; 731 case EQ+F: case LE+F: case GE+F: case LT+F: case GT+F: case NE+F: 732 spill(1<<EAX, IREG, p); 733 break; 734 case CALL+F: 735 spill(1<<EDX | 1<<EAX | 1<<ECX, IREG, p); 736 break; 737 case CALL+I: case CALL+U: case CALL+P: case CALL+V: 738 spill(1<<EDX | 1<<ECX, IREG, p); 739 break; 740 } 741 } 742 #define isfp(p) (optype((p)->op)==F) 743 744 int ckstack(Node p, int n) { 745 int i; 746 747 for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) 748 if (isfp(p->x.kids[i])) 749 n--; 750 if (isfp(p) && p->count > 0) 751 n++; 752 if (n > 8) 753 error("expression too complicated\n"); 754 debug(fprint(stderr, "(ckstack(%x)=%d)\n", p, n)); 755 assert(n >= 0); 756 return n; 757 } 758 int memop(Node p) { 759 assert(p); 760 assert(generic(p->op) == ASGN); 761 assert(p->kids[0]); 762 assert(p->kids[1]); 763 if (generic(p->kids[1]->kids[0]->op) == INDIR 764 && sametree(p->kids[0], p->kids[1]->kids[0]->kids[0])) 765 return 3; 766 else 767 return LBURG_MAX; 768 } 769 int sametree(Node p, Node q) { 770 return p == NULL && q == NULL 771 || p && q && p->op == q->op && p->syms[0] == q->syms[0] 772 && sametree(p->kids[0], q->kids[0]) 773 && sametree(p->kids[1], q->kids[1]); 774 } 775 static void emit2(Node p) { 776 int op = specific(p->op); 777 #define preg(f) ((f)[getregnum(p->x.kids[0])]->x.name) 778 779 if (op == CVI+I && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 1) 780 print("movsx %s,%s\n", p->syms[RX]->x.name 781 , preg(charreg)); 782 else if (op == CVI+U && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 1) 783 print("movsx %s,%s\n", p->syms[RX]->x.name 784 , preg(charreg)); 785 else if (op == CVI+I && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 2) 786 print("movsx %s,%s\n", p->syms[RX]->x.name 787 , preg(shortreg)); 788 else if (op == CVI+U && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 2) 789 print("movsx %s,%s\n", p->syms[RX]->x.name 790 , preg(shortreg)); 791 792 else if (op == CVU+I && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 1) 793 print("movzx %s,%s\n", p->syms[RX]->x.name 794 , preg(charreg)); 795 else if (op == CVU+U && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 1) 796 print("movzx %s,%s\n", p->syms[RX]->x.name 797 , preg(charreg)); 798 else if (op == CVU+I && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 2) 799 print("movzx %s,%s\n", p->syms[RX]->x.name 800 , preg(shortreg)); 801 else if (op == CVU+U && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 2) 802 print("movzx %s,%s\n", p->syms[RX]->x.name 803 , preg(shortreg)); 804 else if (generic(op) == CVI || generic(op) == CVU || generic(op) == LOAD) { 805 char *dst = intreg[getregnum(p)]->x.name; 806 char *src = preg(intreg); 807 assert(opsize(p->op) <= opsize(p->x.kids[0]->op)); 808 if (dst != src) 809 print("mov %s,%s\n", dst, src); 810 } 811 } 812 813 static void doarg(Node p) { 814 assert(p && p->syms[0]); 815 mkactual(4, p->syms[0]->u.c.v.i); 816 } 817 static void blkfetch(int k, int off, int reg, int tmp) {} 818 static void blkstore(int k, int off, int reg, int tmp) {} 819 static void blkloop(int dreg, int doff, int sreg, int soff, 820 int size, int tmps[]) {} 821 static void local(Symbol p) { 822 if (isfloat(p->type)) 823 p->sclass = AUTO; 824 if (askregvar(p, (*IR->x.rmap)(ttob(p->type))) == 0) 825 mkauto(p); 826 } 827 static void function(Symbol f, Symbol caller[], Symbol callee[], int n) { 828 int i; 829 830 print("%s:\n", f->x.name); 831 print("push ebx\n"); 832 print("push esi\n"); 833 print("push edi\n"); 834 print("push ebp\n"); 835 print("mov ebp,esp\n"); 836 usedmask[0] = usedmask[1] = 0; 837 freemask[0] = freemask[1] = ~(unsigned)0; 838 offset = 16 + 4; 839 for (i = 0; callee[i]; i++) { 840 Symbol p = callee[i]; 841 Symbol q = caller[i]; 842 assert(q); 843 p->x.offset = q->x.offset = offset; 844 p->x.name = q->x.name = stringf("%d", p->x.offset); 845 p->sclass = q->sclass = AUTO; 846 offset += roundup(q->type->size, 4); 847 } 848 assert(caller[i] == 0); 849 offset = maxoffset = 0; 850 gencode(caller, callee); 851 framesize = roundup(maxoffset, 4); 852 if (framesize > 0) 853 print("sub esp,%d\n", framesize); 854 emitcode(); 855 print("mov esp,ebp\n"); 856 print("pop ebp\n"); 857 print("pop edi\n"); 858 print("pop esi\n"); 859 print("pop ebx\n"); 860 print("ret\n"); 861 } 862 static void defsymbol(Symbol p) { 863 if (p->scope >= LOCAL && p->sclass == STATIC) 864 p->x.name = stringf("L%d", genlabel(1)); 865 else if (p->generated) 866 p->x.name = stringf("L%s", p->name); 867 else if (p->scope == GLOBAL || p->sclass == EXTERN) 868 p->x.name = stringf("_%s", p->name); 869 else if (p->scope == CONSTANTS 870 && (isint(p->type) || isptr(p->type)) 871 && p->name[0] == '0' && p->name[1] == 'x') 872 p->x.name = stringf("0%sH", &p->name[2]); 873 else 874 p->x.name = p->name; 875 } 876 static void address(Symbol q, Symbol p, long n) { 877 if (p->scope == GLOBAL 878 || p->sclass == STATIC || p->sclass == EXTERN) 879 q->x.name = stringf("%s%s%D", 880 p->x.name, n >= 0 ? "+" : "", n); 881 else { 882 assert(n <= INT_MAX && n >= INT_MIN); 883 q->x.offset = p->x.offset + n; 884 q->x.name = stringd(q->x.offset); 885 } 886 } 887 static void defconst(int suffix, int size, Value v) { 888 if (suffix == I && size == 1) 889 print("db %d\n", v.u); 890 else if (suffix == I && size == 2) 891 print("dw %d\n", v.i); 892 else if (suffix == I && size == 4) 893 print("dd %d\n", v.i); 894 else if (suffix == U && size == 1) 895 print("db 0%xH\n", v.u); 896 else if (suffix == U && size == 2) 897 print("dw 0%xH\n", v.u); 898 else if (suffix == U && size == 4) 899 print("dd 0%xH\n", v.u); 900 else if (suffix == P && size == 4) 901 print("dd 0%xH\n", v.p); 902 else if (suffix == F && size == 4) { 903 float f = v.d; 904 print("dd 0%xH\n", *(unsigned *)&f); 905 } 906 else if (suffix == F && size == 8) { 907 double d = v.d; 908 unsigned *p = (unsigned *)&d; 909 print("dd 0%xH\ndd 0%xH\n", p[swap], p[!swap]); 910 } 911 else assert(0); 912 } 913 static void defaddress(Symbol p) { 914 print("dd %s\n", p->x.name); 915 } 916 static void defstring(int n, char *str) { 917 char *s; 918 919 for (s = str; s < str + n; s++) 920 print("db %d\n", (*s)&0377); 921 } 922 static void export(Symbol p) { 923 print("public %s\n", p->x.name); 924 } 925 static void import(Symbol p) { 926 int oldseg = cseg; 927 928 if (p->ref > 0) { 929 segment(0); 930 print("extrn %s:near\n", p->x.name); 931 segment(oldseg); 932 } 933 } 934 static void global(Symbol p) { 935 print("align %d\n", 936 p->type->align > 4 ? 4 : p->type->align); 937 print("%s label byte\n", p->x.name); 938 if (p->u.seg == BSS) 939 print("db %d dup (0)\n", p->type->size); 940 } 941 static void space(int n) { 942 if (cseg != BSS) 943 print("db %d dup (0)\n", n); 944 } 945 Interface x86IR = { 946 1, 1, 0, /* char */ 947 2, 2, 0, /* short */ 948 4, 4, 0, /* int */ 949 4, 4, 0, /* long */ 950 4, 4, 0, /* long long */ 951 4, 4, 1, /* float */ 952 8, 4, 1, /* double */ 953 8, 4, 1, /* long double */ 954 4, 4, 0, /* T * */ 955 0, 4, 0, /* struct; so that ARGB keeps stack aligned */ 956 1, /* little_endian */ 957 0, /* mulops_calls */ 958 0, /* wants_callb */ 959 1, /* wants_argb */ 960 0, /* left_to_right */ 961 0, /* wants_dag */ 962 0, /* unsigned_char */ 963 address, 964 blockbeg, 965 blockend, 966 defaddress, 967 defconst, 968 defstring, 969 defsymbol, 970 emit, 971 export, 972 function, 973 gen, 974 global, 975 import, 976 local, 977 progbeg, 978 progend, 979 segment, 980 space, 981 0, 0, 0, 0, 0, 0, 0, 982 {1, rmap, 983 blkfetch, blkstore, blkloop, 984 _label, 985 _rule, 986 _nts, 987 _kids, 988 _string, 989 _templates, 990 _isinstruction, 991 _ntname, 992 emit2, 993 doarg, 994 target, 995 clobber, 996 } 997 }; 998 static char rcsid[] = "$Id: x86.md 145 2001-10-17 21:53:10Z timo $";