mips.md (34675B)
1 %{ 2 #define INTTMP 0x0100ff00 3 #define INTVAR 0x40ff0000 4 #define FLTTMP 0x000f0ff0 5 #define FLTVAR 0xfff00000 6 7 #define INTRET 0x00000004 8 #define FLTRET 0x00000003 9 10 #define readsreg(p) \ 11 (generic((p)->op)==INDIR && (p)->kids[0]->op==VREG+P) 12 #define setsrc(d) ((d) && (d)->x.regnode && \ 13 (d)->x.regnode->set == src->x.regnode->set && \ 14 (d)->x.regnode->mask&src->x.regnode->mask) 15 16 #define relink(a, b) ((b)->x.prev = (a), (a)->x.next = (b)) 17 18 #include "c.h" 19 #define NODEPTR_TYPE Node 20 #define OP_LABEL(p) ((p)->op) 21 #define LEFT_CHILD(p) ((p)->kids[0]) 22 #define RIGHT_CHILD(p) ((p)->kids[1]) 23 #define STATE_LABEL(p) ((p)->x.state) 24 static void address(Symbol, Symbol, long); 25 static void blkfetch(int, int, int, int); 26 static void blkloop(int, int, int, int, int, int[]); 27 static void blkstore(int, int, int, int); 28 static void defaddress(Symbol); 29 static void defconst(int, int, Value); 30 static void defstring(int, char *); 31 static void defsymbol(Symbol); 32 static void doarg(Node); 33 static void emit2(Node); 34 static void export(Symbol); 35 static void clobber(Node); 36 static void function(Symbol, Symbol [], Symbol [], int); 37 static void global(Symbol); 38 static void import(Symbol); 39 static void local(Symbol); 40 static void progbeg(int, char **); 41 static void progend(void); 42 static void segment(int); 43 static void space(int); 44 static void target(Node); 45 static int bitcount (unsigned); 46 static Symbol argreg (int, int, int, int, int); 47 48 static Symbol ireg[32], freg2[32], d6; 49 static Symbol iregw, freg2w; 50 static int tmpregs[] = {3, 9, 10}; 51 static Symbol blkreg; 52 53 static int gnum = 8; 54 static int pic; 55 56 static int cseg; 57 %} 58 %start stmt 59 %term CNSTF4=4113 60 %term CNSTF8=8209 61 %term CNSTF16=16401 62 %term CNSTI1=1045 63 %term CNSTI2=2069 64 %term CNSTI4=4117 65 %term CNSTI8=8213 66 %term CNSTP4=4119 67 %term CNSTP8=8215 68 %term CNSTU1=1046 69 %term CNSTU2=2070 70 %term CNSTU4=4118 71 %term CNSTU8=8214 72 73 %term ARGB=41 74 %term ARGF4=4129 75 %term ARGF8=8225 76 %term ARGF16=16417 77 %term ARGI4=4133 78 %term ARGI8=8229 79 %term ARGP4=4135 80 %term ARGP8=8231 81 %term ARGU4=4134 82 %term ARGU8=8230 83 84 %term ASGNB=57 85 %term ASGNF4=4145 86 %term ASGNF8=8241 87 %term ASGNF16=16433 88 %term ASGNI1=1077 89 %term ASGNI2=2101 90 %term ASGNI4=4149 91 %term ASGNI8=8245 92 %term ASGNP4=4151 93 %term ASGNP8=8247 94 %term ASGNU1=1078 95 %term ASGNU2=2102 96 %term ASGNU4=4150 97 %term ASGNU8=8246 98 99 %term INDIRB=73 100 %term INDIRF4=4161 101 %term INDIRF8=8257 102 %term INDIRF16=16449 103 %term INDIRI1=1093 104 %term INDIRI2=2117 105 %term INDIRI4=4165 106 %term INDIRI8=8261 107 %term INDIRP4=4167 108 %term INDIRP8=8263 109 %term INDIRU1=1094 110 %term INDIRU2=2118 111 %term INDIRU4=4166 112 %term INDIRU8=8262 113 114 %term CVFF4=4209 115 %term CVFF8=8305 116 %term CVFF16=16497 117 %term CVFI4=4213 118 %term CVFI8=8309 119 120 %term CVIF4=4225 121 %term CVIF8=8321 122 %term CVIF16=16513 123 %term CVII1=1157 124 %term CVII2=2181 125 %term CVII4=4229 126 %term CVII8=8325 127 %term CVIU1=1158 128 %term CVIU2=2182 129 %term CVIU4=4230 130 %term CVIU8=8326 131 132 %term CVPP4=4247 133 %term CVPP8=8343 134 %term CVPP16=16535 135 %term CVPU4=4246 136 %term CVPU8=8342 137 138 %term CVUI1=1205 139 %term CVUI2=2229 140 %term CVUI4=4277 141 %term CVUI8=8373 142 %term CVUP4=4279 143 %term CVUP8=8375 144 %term CVUP16=16567 145 %term CVUU1=1206 146 %term CVUU2=2230 147 %term CVUU4=4278 148 %term CVUU8=8374 149 150 %term NEGF4=4289 151 %term NEGF8=8385 152 %term NEGF16=16577 153 %term NEGI4=4293 154 %term NEGI8=8389 155 156 %term CALLB=217 157 %term CALLF4=4305 158 %term CALLF8=8401 159 %term CALLF16=16593 160 %term CALLI4=4309 161 %term CALLI8=8405 162 %term CALLP4=4311 163 %term CALLP8=8407 164 %term CALLU4=4310 165 %term CALLU8=8406 166 %term CALLV=216 167 168 %term RETF4=4337 169 %term RETF8=8433 170 %term RETF16=16625 171 %term RETI4=4341 172 %term RETI8=8437 173 %term RETP4=4343 174 %term RETP8=8439 175 %term RETU4=4342 176 %term RETU8=8438 177 %term RETV=248 178 179 %term ADDRGP4=4359 180 %term ADDRGP8=8455 181 182 %term ADDRFP4=4375 183 %term ADDRFP8=8471 184 185 %term ADDRLP4=4391 186 %term ADDRLP8=8487 187 188 %term ADDF4=4401 189 %term ADDF8=8497 190 %term ADDF16=16689 191 %term ADDI4=4405 192 %term ADDI8=8501 193 %term ADDP4=4407 194 %term ADDP8=8503 195 %term ADDU4=4406 196 %term ADDU8=8502 197 198 %term SUBF4=4417 199 %term SUBF8=8513 200 %term SUBF16=16705 201 %term SUBI4=4421 202 %term SUBI8=8517 203 %term SUBP4=4423 204 %term SUBP8=8519 205 %term SUBU4=4422 206 %term SUBU8=8518 207 208 %term LSHI4=4437 209 %term LSHI8=8533 210 %term LSHU4=4438 211 %term LSHU8=8534 212 213 %term MODI4=4453 214 %term MODI8=8549 215 %term MODU4=4454 216 %term MODU8=8550 217 218 %term RSHI4=4469 219 %term RSHI8=8565 220 %term RSHU4=4470 221 %term RSHU8=8566 222 223 %term BANDI4=4485 224 %term BANDI8=8581 225 %term BANDU4=4486 226 %term BANDU8=8582 227 228 %term BCOMI4=4501 229 %term BCOMI8=8597 230 %term BCOMU4=4502 231 %term BCOMU8=8598 232 233 %term BORI4=4517 234 %term BORI8=8613 235 %term BORU4=4518 236 %term BORU8=8614 237 238 %term BXORI4=4533 239 %term BXORI8=8629 240 %term BXORU4=4534 241 %term BXORU8=8630 242 243 %term DIVF4=4545 244 %term DIVF8=8641 245 %term DIVF16=16833 246 %term DIVI4=4549 247 %term DIVI8=8645 248 %term DIVU4=4550 249 %term DIVU8=8646 250 251 %term MULF4=4561 252 %term MULF8=8657 253 %term MULF16=16849 254 %term MULI4=4565 255 %term MULI8=8661 256 %term MULU4=4566 257 %term MULU8=8662 258 259 %term EQF4=4577 260 %term EQF8=8673 261 %term EQF16=16865 262 %term EQI4=4581 263 %term EQI8=8677 264 %term EQU4=4582 265 %term EQU8=8678 266 267 %term GEF4=4593 268 %term GEF8=8689 269 %term GEI4=4597 270 %term GEI8=8693 271 %term GEI16=16885 272 %term GEU4=4598 273 %term GEU8=8694 274 275 %term GTF4=4609 276 %term GTF8=8705 277 %term GTF16=16897 278 %term GTI4=4613 279 %term GTI8=8709 280 %term GTU4=4614 281 %term GTU8=8710 282 283 %term LEF4=4625 284 %term LEF8=8721 285 %term LEF16=16913 286 %term LEI4=4629 287 %term LEI8=8725 288 %term LEU4=4630 289 %term LEU8=8726 290 291 %term LTF4=4641 292 %term LTF8=8737 293 %term LTF16=16929 294 %term LTI4=4645 295 %term LTI8=8741 296 %term LTU4=4646 297 %term LTU8=8742 298 299 %term NEF4=4657 300 %term NEF8=8753 301 %term NEF16=16945 302 %term NEI4=4661 303 %term NEI8=8757 304 %term NEU4=4662 305 %term NEU8=8758 306 307 %term JUMPV=584 308 309 %term LABELV=600 310 311 %term LOADB=233 312 %term LOADF4=4321 313 %term LOADF8=8417 314 %term LOADF16=16609 315 %term LOADI1=1253 316 %term LOADI2=2277 317 %term LOADI4=4325 318 %term LOADI8=8421 319 %term LOADP4=4327 320 %term LOADP8=8423 321 %term LOADU1=1254 322 %term LOADU2=2278 323 %term LOADU4=4326 324 %term LOADU8=8422 325 326 %term VREGP=711 327 %% 328 reg: INDIRI1(VREGP) "# read register\n" 329 reg: INDIRU1(VREGP) "# read register\n" 330 331 reg: INDIRI2(VREGP) "# read register\n" 332 reg: INDIRU2(VREGP) "# read register\n" 333 334 reg: INDIRF4(VREGP) "# read register\n" 335 reg: INDIRI4(VREGP) "# read register\n" 336 reg: INDIRP4(VREGP) "# read register\n" 337 reg: INDIRU4(VREGP) "# read register\n" 338 339 reg: INDIRF8(VREGP) "# read register\n" 340 reg: INDIRI8(VREGP) "# read register\n" 341 reg: INDIRP8(VREGP) "# read register\n" 342 reg: INDIRU8(VREGP) "# read register\n" 343 344 stmt: ASGNI1(VREGP,reg) "# write register\n" 345 stmt: ASGNU1(VREGP,reg) "# write register\n" 346 347 stmt: ASGNI2(VREGP,reg) "# write register\n" 348 stmt: ASGNU2(VREGP,reg) "# write register\n" 349 350 stmt: ASGNF4(VREGP,reg) "# write register\n" 351 stmt: ASGNI4(VREGP,reg) "# write register\n" 352 stmt: ASGNP4(VREGP,reg) "# write register\n" 353 stmt: ASGNU4(VREGP,reg) "# write register\n" 354 355 stmt: ASGNF8(VREGP,reg) "# write register\n" 356 stmt: ASGNI8(VREGP,reg) "# write register\n" 357 stmt: ASGNP8(VREGP,reg) "# write register\n" 358 stmt: ASGNU8(VREGP,reg) "# write register\n" 359 con: CNSTI1 "%a" 360 con: CNSTU1 "%a" 361 362 con: CNSTI2 "%a" 363 con: CNSTU2 "%a" 364 365 con: CNSTI4 "%a" 366 con: CNSTU4 "%a" 367 con: CNSTP4 "%a" 368 369 con: CNSTI8 "%a" 370 con: CNSTU8 "%a" 371 con: CNSTP8 "%a" 372 stmt: reg "" 373 acon: con "%0" 374 acon: ADDRGP4 "%a" 375 addr: ADDI4(reg,acon) "%1($%0)" 376 addr: ADDU4(reg,acon) "%1($%0)" 377 addr: ADDP4(reg,acon) "%1($%0)" 378 addr: acon "%0" 379 addr: reg "($%0)" 380 addr: ADDRFP4 "%a+%F($sp)" 381 addr: ADDRLP4 "%a+%F($sp)" 382 reg: addr "la $%c,%0\n" 1 383 reg: CNSTI1 "# reg\n" range(a, 0, 0) 384 reg: CNSTI2 "# reg\n" range(a, 0, 0) 385 reg: CNSTI4 "# reg\n" range(a, 0, 0) 386 reg: CNSTU1 "# reg\n" range(a, 0, 0) 387 reg: CNSTU2 "# reg\n" range(a, 0, 0) 388 reg: CNSTU4 "# reg\n" range(a, 0, 0) 389 reg: CNSTP4 "# reg\n" range(a, 0, 0) 390 stmt: ASGNI1(addr,reg) "sb $%1,%0\n" 1 391 stmt: ASGNU1(addr,reg) "sb $%1,%0\n" 1 392 stmt: ASGNI2(addr,reg) "sh $%1,%0\n" 1 393 stmt: ASGNU2(addr,reg) "sh $%1,%0\n" 1 394 stmt: ASGNI4(addr,reg) "sw $%1,%0\n" 1 395 stmt: ASGNU4(addr,reg) "sw $%1,%0\n" 1 396 stmt: ASGNP4(addr,reg) "sw $%1,%0\n" 1 397 reg: INDIRI1(addr) "lb $%c,%0\n" 1 398 reg: INDIRU1(addr) "lbu $%c,%0\n" 1 399 reg: INDIRI2(addr) "lh $%c,%0\n" 1 400 reg: INDIRU2(addr) "lhu $%c,%0\n" 1 401 reg: INDIRI4(addr) "lw $%c,%0\n" 1 402 reg: INDIRU4(addr) "lw $%c,%0\n" 1 403 reg: INDIRP4(addr) "lw $%c,%0\n" 1 404 405 reg: CVII4(INDIRI1(addr)) "lb $%c,%0\n" 1 406 reg: CVII4(INDIRI2(addr)) "lh $%c,%0\n" 1 407 reg: CVUU4(INDIRU1(addr)) "lbu $%c,%0\n" 1 408 reg: CVUU4(INDIRU2(addr)) "lhu $%c,%0\n" 1 409 reg: CVUI4(INDIRU1(addr)) "lbu $%c,%0\n" 1 410 reg: CVUI4(INDIRU2(addr)) "lhu $%c,%0\n" 1 411 reg: INDIRF4(addr) "l.s $f%c,%0\n" 1 412 reg: INDIRF8(addr) "l.d $f%c,%0\n" 1 413 stmt: ASGNF4(addr,reg) "s.s $f%1,%0\n" 1 414 stmt: ASGNF8(addr,reg) "s.d $f%1,%0\n" 1 415 reg: DIVI4(reg,reg) "div $%c,$%0,$%1\n" 1 416 reg: DIVU4(reg,reg) "divu $%c,$%0,$%1\n" 1 417 reg: MODI4(reg,reg) "rem $%c,$%0,$%1\n" 1 418 reg: MODU4(reg,reg) "remu $%c,$%0,$%1\n" 1 419 reg: MULI4(reg,reg) "mul $%c,$%0,$%1\n" 1 420 reg: MULU4(reg,reg) "mul $%c,$%0,$%1\n" 1 421 rc: con "%0" 422 rc: reg "$%0" 423 424 reg: ADDI4(reg,rc) "addu $%c,$%0,%1\n" 1 425 reg: ADDP4(reg,rc) "addu $%c,$%0,%1\n" 1 426 reg: ADDU4(reg,rc) "addu $%c,$%0,%1\n" 1 427 reg: BANDI4(reg,rc) "and $%c,$%0,%1\n" 1 428 reg: BORI4(reg,rc) "or $%c,$%0,%1\n" 1 429 reg: BXORI4(reg,rc) "xor $%c,$%0,%1\n" 1 430 reg: BANDU4(reg,rc) "and $%c,$%0,%1\n" 1 431 reg: BORU4(reg,rc) "or $%c,$%0,%1\n" 1 432 reg: BXORU4(reg,rc) "xor $%c,$%0,%1\n" 1 433 reg: SUBI4(reg,rc) "subu $%c,$%0,%1\n" 1 434 reg: SUBP4(reg,rc) "subu $%c,$%0,%1\n" 1 435 reg: SUBU4(reg,rc) "subu $%c,$%0,%1\n" 1 436 rc5: CNSTI4 "%a" range(a,0,31) 437 rc5: reg "$%0" 438 439 reg: LSHI4(reg,rc5) "sll $%c,$%0,%1\n" 1 440 reg: LSHU4(reg,rc5) "sll $%c,$%0,%1\n" 1 441 reg: RSHI4(reg,rc5) "sra $%c,$%0,%1\n" 1 442 reg: RSHU4(reg,rc5) "srl $%c,$%0,%1\n" 1 443 reg: BCOMI4(reg) "not $%c,$%0\n" 1 444 reg: BCOMU4(reg) "not $%c,$%0\n" 1 445 reg: NEGI4(reg) "negu $%c,$%0\n" 1 446 reg: LOADI1(reg) "move $%c,$%0\n" move(a) 447 reg: LOADU1(reg) "move $%c,$%0\n" move(a) 448 reg: LOADI2(reg) "move $%c,$%0\n" move(a) 449 reg: LOADU2(reg) "move $%c,$%0\n" move(a) 450 reg: LOADI4(reg) "move $%c,$%0\n" move(a) 451 reg: LOADP4(reg) "move $%c,$%0\n" move(a) 452 reg: LOADU4(reg) "move $%c,$%0\n" move(a) 453 reg: ADDF4(reg,reg) "add.s $f%c,$f%0,$f%1\n" 1 454 reg: ADDF8(reg,reg) "add.d $f%c,$f%0,$f%1\n" 1 455 reg: DIVF4(reg,reg) "div.s $f%c,$f%0,$f%1\n" 1 456 reg: DIVF8(reg,reg) "div.d $f%c,$f%0,$f%1\n" 1 457 reg: MULF4(reg,reg) "mul.s $f%c,$f%0,$f%1\n" 1 458 reg: MULF8(reg,reg) "mul.d $f%c,$f%0,$f%1\n" 1 459 reg: SUBF4(reg,reg) "sub.s $f%c,$f%0,$f%1\n" 1 460 reg: SUBF8(reg,reg) "sub.d $f%c,$f%0,$f%1\n" 1 461 reg: LOADF4(reg) "mov.s $f%c,$f%0\n" move(a) 462 reg: LOADF8(reg) "mov.d $f%c,$f%0\n" move(a) 463 reg: NEGF4(reg) "neg.s $f%c,$f%0\n" 1 464 reg: NEGF8(reg) "neg.d $f%c,$f%0\n" 1 465 reg: CVII4(reg) "sll $%c,$%0,8*(4-%a); sra $%c,$%c,8*(4-%a)\n" 2 466 reg: CVUI4(reg) "and $%c,$%0,(1<<(8*%a))-1\n" 1 467 reg: CVUU4(reg) "and $%c,$%0,(1<<(8*%a))-1\n" 1 468 reg: CVFF4(reg) "cvt.s.d $f%c,$f%0\n" 1 469 reg: CVFF8(reg) "cvt.d.s $f%c,$f%0\n" 1 470 reg: CVIF4(reg) "mtc1 $%0,$f%c; cvt.s.w $f%c,$f%c\n" 2 471 reg: CVIF8(reg) "mtc1 $%0,$f%c; cvt.d.w $f%c,$f%c\n" 2 472 reg: CVFI4(reg) "trunc.w.s $f2,$f%0,$%c; mfc1 $%c,$f2\n" (a->syms[0]->u.c.v.i==4?2:LBURG_MAX) 473 reg: CVFI4(reg) "trunc.w.d $f2,$f%0,$%c; mfc1 $%c,$f2\n" (a->syms[0]->u.c.v.i==8?2:LBURG_MAX) 474 stmt: LABELV "%a:\n" 475 stmt: JUMPV(acon) "b %0\n" 1 476 stmt: JUMPV(reg) ".cpadd $%0\nj $%0\n" !pic 477 stmt: JUMPV(reg) "j $%0\n" pic 478 stmt: EQI4(reg,reg) "beq $%0,$%1,%a\n" 1 479 stmt: EQU4(reg,reg) "beq $%0,$%1,%a\n" 1 480 stmt: GEI4(reg,reg) "bge $%0,$%1,%a\n" 1 481 stmt: GEU4(reg,reg) "bgeu $%0,$%1,%a\n" 1 482 stmt: GTI4(reg,reg) "bgt $%0,$%1,%a\n" 1 483 stmt: GTU4(reg,reg) "bgtu $%0,$%1,%a\n" 1 484 stmt: LEI4(reg,reg) "ble $%0,$%1,%a\n" 1 485 stmt: LEU4(reg,reg) "bleu $%0,$%1,%a\n" 1 486 stmt: LTI4(reg,reg) "blt $%0,$%1,%a\n" 1 487 stmt: LTU4(reg,reg) "bltu $%0,$%1,%a\n" 1 488 stmt: NEI4(reg,reg) "bne $%0,$%1,%a\n" 1 489 stmt: NEU4(reg,reg) "bne $%0,$%1,%a\n" 1 490 stmt: EQF4(reg,reg) "c.eq.s $f%0,$f%1; bc1t %a\n" 2 491 stmt: EQF8(reg,reg) "c.eq.d $f%0,$f%1; bc1t %a\n" 2 492 stmt: LEF4(reg,reg) "c.le.s $f%0,$f%1; bc1t %a\n" 2 493 stmt: LEF8(reg,reg) "c.le.d $f%0,$f%1; bc1t %a\n" 2 494 stmt: LTF4(reg,reg) "c.lt.s $f%0,$f%1; bc1t %a\n" 2 495 stmt: LTF8(reg,reg) "c.lt.d $f%0,$f%1; bc1t %a\n" 2 496 stmt: GEF4(reg,reg) "c.lt.s $f%0,$f%1; bc1f %a\n" 2 497 stmt: GEF8(reg,reg) "c.lt.d $f%0,$f%1; bc1f %a\n" 2 498 stmt: GTF4(reg,reg) "c.le.s $f%0,$f%1; bc1f %a\n" 2 499 stmt: GTF8(reg,reg) "c.le.d $f%0,$f%1; bc1f %a\n" 2 500 stmt: NEF4(reg,reg) "c.eq.s $f%0,$f%1; bc1f %a\n" 2 501 stmt: NEF8(reg,reg) "c.eq.d $f%0,$f%1; bc1f %a\n" 2 502 ar: ADDRGP4 "%a" 503 504 reg: CALLF4(ar) "jal %0\n" 1 505 reg: CALLF8(ar) "jal %0\n" 1 506 reg: CALLI4(ar) "jal %0\n" 1 507 reg: CALLP4(ar) "jal %0\n" 1 508 reg: CALLU4(ar) "jal %0\n" 1 509 stmt: CALLV(ar) "jal %0\n" 1 510 ar: reg "$%0" 511 ar: CNSTP4 "%a" range(a, 0, 0x0fffffff) 512 stmt: RETF4(reg) "# ret\n" 1 513 stmt: RETF8(reg) "# ret\n" 1 514 stmt: RETI4(reg) "# ret\n" 1 515 stmt: RETU4(reg) "# ret\n" 1 516 stmt: RETP4(reg) "# ret\n" 1 517 stmt: RETV(reg) "# ret\n" 1 518 stmt: ARGF4(reg) "# arg\n" 1 519 stmt: ARGF8(reg) "# arg\n" 1 520 stmt: ARGI4(reg) "# arg\n" 1 521 stmt: ARGP4(reg) "# arg\n" 1 522 stmt: ARGU4(reg) "# arg\n" 1 523 524 stmt: ARGB(INDIRB(reg)) "# argb %0\n" 1 525 stmt: ASGNB(reg,INDIRB(reg)) "# asgnb %0 %1\n" 1 526 %% 527 static void progend(void){} 528 static void progbeg(int argc, char *argv[]) { 529 int i; 530 531 { 532 union { 533 char c; 534 int i; 535 } u; 536 u.i = 0; 537 u.c = 1; 538 swap = ((int)(u.i == 1)) != IR->little_endian; 539 } 540 print(".set reorder\n"); 541 pic = !IR->little_endian; 542 parseflags(argc, argv); 543 for (i = 0; i < argc; i++) 544 if (strncmp(argv[i], "-G", 2) == 0) 545 gnum = atoi(argv[i] + 2); 546 else if (strcmp(argv[i], "-pic=1") == 0 547 || strcmp(argv[i], "-pic=0") == 0) 548 pic = argv[i][5]-'0'; 549 for (i = 0; i < 31; i += 2) 550 freg2[i] = mkreg("%d", i, 3, FREG); 551 for (i = 0; i < 32; i++) 552 ireg[i] = mkreg("%d", i, 1, IREG); 553 ireg[29]->x.name = "sp"; 554 d6 = mkreg("6", 6, 3, IREG); 555 freg2w = mkwildcard(freg2); 556 iregw = mkwildcard(ireg); 557 tmask[IREG] = INTTMP; tmask[FREG] = FLTTMP; 558 vmask[IREG] = INTVAR; vmask[FREG] = FLTVAR; 559 blkreg = mkreg("8", 8, 7, IREG); 560 } 561 static Symbol rmap(int opk) { 562 switch (optype(opk)) { 563 case I: case U: case P: case B: 564 return iregw; 565 case F: 566 return freg2w; 567 default: 568 return 0; 569 } 570 } 571 static void target(Node p) { 572 assert(p); 573 switch (specific(p->op)) { 574 case CNST+I: case CNST+U: case CNST+P: 575 if (range(p, 0, 0) == 0) { 576 setreg(p, ireg[0]); 577 p->x.registered = 1; 578 } 579 break; 580 case CALL+V: 581 rtarget(p, 0, ireg[25]); 582 break; 583 case CALL+F: 584 rtarget(p, 0, ireg[25]); 585 setreg(p, freg2[0]); 586 break; 587 case CALL+I: case CALL+P: case CALL+U: 588 rtarget(p, 0, ireg[25]); 589 setreg(p, ireg[2]); 590 break; 591 case RET+F: 592 rtarget(p, 0, freg2[0]); 593 break; 594 case RET+I: case RET+U: case RET+P: 595 rtarget(p, 0, ireg[2]); 596 break; 597 case ARG+F: case ARG+I: case ARG+P: case ARG+U: { 598 static int ty0; 599 int ty = optype(p->op); 600 Symbol q; 601 602 q = argreg(p->x.argno, p->syms[2]->u.c.v.i, ty, opsize(p->op), ty0); 603 if (p->x.argno == 0) 604 ty0 = ty; 605 if (q && 606 !(ty == F && q->x.regnode->set == IREG)) 607 rtarget(p, 0, q); 608 break; 609 } 610 case ASGN+B: rtarget(p->kids[1], 0, blkreg); break; 611 case ARG+B: rtarget(p->kids[0], 0, blkreg); break; 612 } 613 } 614 static void clobber(Node p) { 615 assert(p); 616 switch (specific(p->op)) { 617 case CALL+F: 618 spill(INTTMP | INTRET, IREG, p); 619 spill(FLTTMP, FREG, p); 620 break; 621 case CALL+I: case CALL+P: case CALL+U: 622 spill(INTTMP, IREG, p); 623 spill(FLTTMP | FLTRET, FREG, p); 624 break; 625 case CALL+V: 626 spill(INTTMP | INTRET, IREG, p); 627 spill(FLTTMP | FLTRET, FREG, p); 628 break; 629 } 630 } 631 static void emit2(Node p) { 632 int dst, n, src, sz, ty; 633 static int ty0; 634 Symbol q; 635 636 switch (specific(p->op)) { 637 case ARG+F: case ARG+I: case ARG+P: case ARG+U: 638 ty = optype(p->op); 639 sz = opsize(p->op); 640 if (p->x.argno == 0) 641 ty0 = ty; 642 q = argreg(p->x.argno, p->syms[2]->u.c.v.i, ty, sz, ty0); 643 src = getregnum(p->x.kids[0]); 644 if (q == NULL && ty == F && sz == 4) 645 print("s.s $f%d,%d($sp)\n", src, p->syms[2]->u.c.v.i); 646 else if (q == NULL && ty == F) 647 print("s.d $f%d,%d($sp)\n", src, p->syms[2]->u.c.v.i); 648 else if (q == NULL) 649 print("sw $%d,%d($sp)\n", src, p->syms[2]->u.c.v.i); 650 else if (ty == F && sz == 4 && q->x.regnode->set == IREG) 651 print("mfc1 $%d,$f%d\n", q->x.regnode->number, src); 652 else if (ty == F && q->x.regnode->set == IREG) 653 print("mfc1.d $%d,$f%d\n", q->x.regnode->number, src); 654 break; 655 case ASGN+B: 656 dalign = salign = p->syms[1]->u.c.v.i; 657 blkcopy(getregnum(p->x.kids[0]), 0, 658 getregnum(p->x.kids[1]), 0, 659 p->syms[0]->u.c.v.i, tmpregs); 660 break; 661 case ARG+B: 662 dalign = 4; 663 salign = p->syms[1]->u.c.v.i; 664 blkcopy(29, p->syms[2]->u.c.v.i, 665 getregnum(p->x.kids[0]), 0, 666 p->syms[0]->u.c.v.i, tmpregs); 667 n = p->syms[2]->u.c.v.i + p->syms[0]->u.c.v.i; 668 dst = p->syms[2]->u.c.v.i; 669 for ( ; dst <= 12 && dst < n; dst += 4) 670 print("lw $%d,%d($sp)\n", (dst/4)+4, dst); 671 break; 672 } 673 } 674 static Symbol argreg(int argno, int offset, int ty, int sz, int ty0) { 675 assert((offset&3) == 0); 676 if (offset > 12) 677 return NULL; 678 else if (argno == 0 && ty == F) 679 return freg2[12]; 680 else if (argno == 1 && ty == F && ty0 == F) 681 return freg2[14]; 682 else if (argno == 1 && ty == F && sz == 8) 683 return d6; /* Pair! */ 684 else 685 return ireg[(offset/4) + 4]; 686 } 687 static void doarg(Node p) { 688 static int argno; 689 int align; 690 691 if (argoffset == 0) 692 argno = 0; 693 p->x.argno = argno++; 694 align = p->syms[1]->u.c.v.i < 4 ? 4 : p->syms[1]->u.c.v.i; 695 p->syms[2] = intconst(mkactual(align, 696 p->syms[0]->u.c.v.i)); 697 } 698 static void local(Symbol p) { 699 if (askregvar(p, rmap(ttob(p->type))) == 0) 700 mkauto(p); 701 } 702 static void function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) { 703 int i, saved, sizefsave, sizeisave, varargs; 704 Symbol r, argregs[4]; 705 706 usedmask[0] = usedmask[1] = 0; 707 freemask[0] = freemask[1] = ~(unsigned)0; 708 offset = maxoffset = maxargoffset = 0; 709 for (i = 0; callee[i]; i++) 710 ; 711 varargs = variadic(f->type) 712 || i > 0 && strcmp(callee[i-1]->name, "va_alist") == 0; 713 for (i = 0; callee[i]; i++) { 714 Symbol p = callee[i]; 715 Symbol q = caller[i]; 716 assert(q); 717 offset = roundup(offset, q->type->align); 718 p->x.offset = q->x.offset = offset; 719 p->x.name = q->x.name = stringd(offset); 720 r = argreg(i, offset, optype(ttob(q->type)), q->type->size, optype(ttob(caller[0]->type))); 721 if (i < 4) 722 argregs[i] = r; 723 offset = roundup(offset + q->type->size, 4); 724 if (varargs) 725 p->sclass = AUTO; 726 else if (r && ncalls == 0 && 727 !isstruct(q->type) && !p->addressed && 728 !(isfloat(q->type) && r->x.regnode->set == IREG) 729 ) { 730 p->sclass = q->sclass = REGISTER; 731 askregvar(p, r); 732 assert(p->x.regnode && p->x.regnode->vbl == p); 733 q->x = p->x; 734 q->type = p->type; 735 } 736 else if (askregvar(p, rmap(ttob(p->type))) 737 && r != NULL 738 && (isint(p->type) || p->type == q->type)) { 739 assert(q->sclass != REGISTER); 740 p->sclass = q->sclass = REGISTER; 741 q->type = p->type; 742 } 743 } 744 assert(!caller[i]); 745 offset = 0; 746 gencode(caller, callee); 747 if (ncalls) 748 usedmask[IREG] |= ((unsigned)1)<<31; 749 usedmask[IREG] &= 0xc0ff0000; 750 usedmask[FREG] &= 0xfff00000; 751 if (pic && ncalls) 752 usedmask[IREG] |= 1<<25; 753 maxargoffset = roundup(maxargoffset, usedmask[FREG] ? 8 : 4); 754 if (ncalls && maxargoffset < 16) 755 maxargoffset = 16; 756 sizefsave = 4*bitcount(usedmask[FREG]); 757 sizeisave = 4*bitcount(usedmask[IREG]); 758 framesize = roundup(maxargoffset + sizefsave 759 + sizeisave + maxoffset, 8); 760 segment(CODE); 761 print(".align 2\n"); 762 print(".ent %s\n", f->x.name); 763 print("%s:\n", f->x.name); 764 i = maxargoffset + sizefsave - framesize; 765 print(".frame $sp,%d,$31\n", framesize); 766 if (pic) 767 print(".set noreorder\n.cpload $25\n.set reorder\n"); 768 if (framesize > 0) 769 print("addu $sp,$sp,%d\n", -framesize); 770 if (usedmask[FREG]) 771 print(".fmask 0x%x,%d\n", usedmask[FREG], i - 8); 772 if (usedmask[IREG]) 773 print(".mask 0x%x,%d\n", usedmask[IREG], 774 i + sizeisave - 4); 775 saved = maxargoffset; 776 for (i = 20; i <= 30; i += 2) 777 if (usedmask[FREG]&(3<<i)) { 778 print("s.d $f%d,%d($sp)\n", i, saved); 779 saved += 8; 780 } 781 782 for (i = 16; i <= 31; i++) 783 if (usedmask[IREG]&(1<<i)) { 784 if (i == 25) 785 print(".cprestore %d\n", saved); 786 else 787 print("sw $%d,%d($sp)\n", i, saved); 788 saved += 4; 789 } 790 for (i = 0; i < 4 && callee[i]; i++) { 791 r = argregs[i]; 792 if (r && r->x.regnode != callee[i]->x.regnode) { 793 Symbol out = callee[i]; 794 Symbol in = caller[i]; 795 int rn = r->x.regnode->number; 796 int rs = r->x.regnode->set; 797 int tyin = ttob(in->type); 798 799 assert(out && in && r && r->x.regnode); 800 assert(out->sclass != REGISTER || out->x.regnode); 801 if (out->sclass == REGISTER 802 && (isint(out->type) || out->type == in->type)) { 803 int outn = out->x.regnode->number; 804 if (rs == FREG && tyin == F+sizeop(8)) 805 print("mov.d $f%d,$f%d\n", outn, rn); 806 else if (rs == FREG && tyin == F+sizeop(4)) 807 print("mov.s $f%d,$f%d\n", outn, rn); 808 else if (rs == IREG && tyin == F+sizeop(8)) 809 print("mtc1.d $%d,$f%d\n", rn, outn); 810 else if (rs == IREG && tyin == F+sizeop(4)) 811 print("mtc1 $%d,$f%d\n", rn, outn); 812 else 813 print("move $%d,$%d\n", outn, rn); 814 } else { 815 int off = in->x.offset + framesize; 816 if (rs == FREG && tyin == F+sizeop(8)) 817 print("s.d $f%d,%d($sp)\n", rn, off); 818 else if (rs == FREG && tyin == F+sizeop(4)) 819 print("s.s $f%d,%d($sp)\n", rn, off); 820 else { 821 int i, n = (in->type->size + 3)/4; 822 for (i = rn; i < rn+n && i <= 7; i++) 823 print("sw $%d,%d($sp)\n", i, off + (i-rn)*4); 824 } 825 } 826 } 827 } 828 if (varargs && callee[i-1]) { 829 i = callee[i-1]->x.offset + callee[i-1]->type->size; 830 for (i = roundup(i, 4)/4; i <= 3; i++) 831 print("sw $%d,%d($sp)\n", i + 4, framesize + 4*i); 832 } 833 emitcode(); 834 saved = maxargoffset; 835 for (i = 20; i <= 30; i += 2) 836 if (usedmask[FREG]&(3<<i)) { 837 print("l.d $f%d,%d($sp)\n", i, saved); 838 saved += 8; 839 } 840 for (i = 16; i <= 31; i++) 841 if (usedmask[IREG]&(1<<i)) { 842 print("lw $%d,%d($sp)\n", i, saved); 843 saved += 4; 844 } 845 if (framesize > 0) 846 print("addu $sp,$sp,%d\n", framesize); 847 print("j $31\n"); 848 print(".end %s\n", f->x.name); 849 } 850 static void defconst(int suffix, int size, Value v) { 851 if (suffix == F && size == 4) { 852 float f = v.d; 853 print(".word 0x%x\n", *(unsigned *)&f); 854 } 855 else if (suffix == F && size == 8) { 856 double d = v.d; 857 unsigned *p = (unsigned *)&d; 858 print(".word 0x%x\n.word 0x%x\n", p[swap], p[!swap]); 859 } 860 else if (suffix == P) 861 print(".word 0x%x\n", v.p); 862 else if (size == 1) 863 print(".byte 0x%x\n", suffix == I ? v.i : v.u); 864 else if (size == 2) 865 print(".half 0x%x\n", suffix == I ? v.i : v.u); 866 else if (size == 4) 867 print(".word 0x%x\n", suffix == I ? v.i : v.u); 868 } 869 static void defaddress(Symbol p) { 870 if (pic && p->scope == LABELS) 871 print(".gpword %s\n", p->x.name); 872 else 873 print(".word %s\n", p->x.name); 874 } 875 static void defstring(int n, char *str) { 876 char *s; 877 878 for (s = str; s < str + n; s++) 879 print(".byte %d\n", (*s)&0377); 880 } 881 static void export(Symbol p) { 882 print(".globl %s\n", p->x.name); 883 } 884 static void import(Symbol p) { 885 if (!isfunc(p->type)) 886 print(".extern %s %d\n", p->name, p->type->size); 887 } 888 static void defsymbol(Symbol p) { 889 if (p->scope >= LOCAL && p->sclass == STATIC) 890 p->x.name = stringf("L.%d", genlabel(1)); 891 else if (p->generated) 892 p->x.name = stringf("L.%s", p->name); 893 else 894 assert(p->scope != CONSTANTS || isint(p->type) || isptr(p->type)), 895 p->x.name = p->name; 896 } 897 static void address(Symbol q, Symbol p, long n) { 898 if (p->scope == GLOBAL 899 || p->sclass == STATIC || p->sclass == EXTERN) 900 q->x.name = stringf("%s%s%D", p->x.name, 901 n >= 0 ? "+" : "", n); 902 else { 903 assert(n <= INT_MAX && n >= INT_MIN); 904 q->x.offset = p->x.offset + n; 905 q->x.name = stringd(q->x.offset); 906 } 907 } 908 static void global(Symbol p) { 909 if (p->u.seg == BSS) { 910 if (p->sclass == STATIC || Aflag >= 2) 911 print(".lcomm %s,%d\n", p->x.name, p->type->size); 912 else 913 print( ".comm %s,%d\n", p->x.name, p->type->size); 914 } else { 915 if (p->u.seg == DATA 916 && (p->type->size == 0 || p->type->size > gnum)) 917 print(".data\n"); 918 else if (p->u.seg == DATA) 919 print(".sdata\n"); 920 print(".align %c\n", ".01.2...3"[p->type->align]); 921 print("%s:\n", p->x.name); 922 } 923 } 924 static void segment(int n) { 925 cseg = n; 926 switch (n) { 927 case CODE: print(".text\n"); break; 928 case LIT: print(".rdata\n"); break; 929 } 930 } 931 static void space(int n) { 932 if (cseg != BSS) 933 print(".space %d\n", n); 934 } 935 static void blkloop(int dreg, int doff, int sreg, int soff, int size, int tmps[]) { 936 int lab = genlabel(1); 937 938 print("addu $%d,$%d,%d\n", sreg, sreg, size&~7); 939 print("addu $%d,$%d,%d\n", tmps[2], dreg, size&~7); 940 blkcopy(tmps[2], doff, sreg, soff, size&7, tmps); 941 print("L.%d:\n", lab); 942 print("addu $%d,$%d,%d\n", sreg, sreg, -8); 943 print("addu $%d,$%d,%d\n", tmps[2], tmps[2], -8); 944 blkcopy(tmps[2], doff, sreg, soff, 8, tmps); 945 print("bltu $%d,$%d,L.%d\n", dreg, tmps[2], lab); 946 } 947 static void blkfetch(int size, int off, int reg, int tmp) { 948 assert(size == 1 || size == 2 || size == 4); 949 if (size == 1) 950 print("lbu $%d,%d($%d)\n", tmp, off, reg); 951 else if (salign >= size && size == 2) 952 print("lhu $%d,%d($%d)\n", tmp, off, reg); 953 else if (salign >= size) 954 print("lw $%d,%d($%d)\n", tmp, off, reg); 955 else if (size == 2) 956 print("ulhu $%d,%d($%d)\n", tmp, off, reg); 957 else 958 print("ulw $%d,%d($%d)\n", tmp, off, reg); 959 } 960 static void blkstore(int size, int off, int reg, int tmp) { 961 if (size == 1) 962 print("sb $%d,%d($%d)\n", tmp, off, reg); 963 else if (dalign >= size && size == 2) 964 print("sh $%d,%d($%d)\n", tmp, off, reg); 965 else if (dalign >= size) 966 print("sw $%d,%d($%d)\n", tmp, off, reg); 967 else if (size == 2) 968 print("ush $%d,%d($%d)\n", tmp, off, reg); 969 else 970 print("usw $%d,%d($%d)\n", tmp, off, reg); 971 } 972 static void stabinit(char *, int, char *[]); 973 static void stabline(Coordinate *); 974 static void stabsym(Symbol); 975 976 static char *currentfile; 977 978 static int bitcount(unsigned mask) { 979 unsigned i, n = 0; 980 981 for (i = 1; i; i <<= 1) 982 if (mask&i) 983 n++; 984 return n; 985 } 986 987 /* stabinit - initialize stab output */ 988 static void stabinit(char *file, int argc, char *argv[]) { 989 if (file) { 990 print(".file 2,\"%s\"\n", file); 991 currentfile = file; 992 } 993 } 994 995 /* stabline - emit stab entry for source coordinate *cp */ 996 static void stabline(Coordinate *cp) { 997 if (cp->file && cp->file != currentfile) { 998 print(".file 2,\"%s\"\n", cp->file); 999 currentfile = cp->file; 1000 } 1001 print(".loc 2,%d\n", cp->y); 1002 } 1003 1004 /* stabsym - output a stab entry for symbol p */ 1005 static void stabsym(Symbol p) { 1006 if (p == cfunc && IR->stabline) 1007 (*IR->stabline)(&p->src); 1008 } 1009 Interface mipsebIR = { 1010 1, 1, 0, /* char */ 1011 2, 2, 0, /* short */ 1012 4, 4, 0, /* int */ 1013 4, 4, 0, /* long */ 1014 4, 4, 0, /* long long */ 1015 4, 4, 1, /* float */ 1016 8, 8, 1, /* double */ 1017 8, 8, 1, /* long double */ 1018 4, 4, 0, /* T * */ 1019 0, 1, 0, /* struct */ 1020 0, /* little_endian */ 1021 0, /* mulops_calls */ 1022 0, /* wants_callb */ 1023 1, /* wants_argb */ 1024 1, /* left_to_right */ 1025 0, /* wants_dag */ 1026 0, /* unsigned_char */ 1027 address, 1028 blockbeg, 1029 blockend, 1030 defaddress, 1031 defconst, 1032 defstring, 1033 defsymbol, 1034 emit, 1035 export, 1036 function, 1037 gen, 1038 global, 1039 import, 1040 local, 1041 progbeg, 1042 progend, 1043 segment, 1044 space, 1045 0, 0, 0, stabinit, stabline, stabsym, 0, 1046 { 1047 4, /* max_unaligned_load */ 1048 rmap, 1049 blkfetch, blkstore, blkloop, 1050 _label, 1051 _rule, 1052 _nts, 1053 _kids, 1054 _string, 1055 _templates, 1056 _isinstruction, 1057 _ntname, 1058 emit2, 1059 doarg, 1060 target, 1061 clobber, 1062 1063 } 1064 }, mipselIR = { 1065 1, 1, 0, /* char */ 1066 2, 2, 0, /* short */ 1067 4, 4, 0, /* int */ 1068 4, 4, 0, /* long */ 1069 4, 4, 0, /* long long */ 1070 4, 4, 1, /* float */ 1071 8, 8, 1, /* double */ 1072 8, 8, 1, /* long double */ 1073 4, 4, 0, /* T * */ 1074 0, 1, 0, /* struct */ 1075 1, /* little_endian */ 1076 0, /* mulops_calls */ 1077 0, /* wants_callb */ 1078 1, /* wants_argb */ 1079 1, /* left_to_right */ 1080 0, /* wants_dag */ 1081 0, /* unsigned_char */ 1082 address, 1083 blockbeg, 1084 blockend, 1085 defaddress, 1086 defconst, 1087 defstring, 1088 defsymbol, 1089 emit, 1090 export, 1091 function, 1092 gen, 1093 global, 1094 import, 1095 local, 1096 progbeg, 1097 progend, 1098 segment, 1099 space, 1100 0, 0, 0, stabinit, stabline, stabsym, 0, 1101 { 1102 4, /* max_unaligned_load */ 1103 rmap, 1104 blkfetch, blkstore, blkloop, 1105 _label, 1106 _rule, 1107 _nts, 1108 _kids, 1109 _string, 1110 _templates, 1111 _isinstruction, 1112 _ntname, 1113 emit2, 1114 doarg, 1115 target, 1116 clobber, 1117 1118 } 1119 }; 1120 static char rcsid[] = "$Id: mips.md 145 2001-10-17 21:53:10Z timo $";