Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

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 $";