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