1 #include "lib9.h" 2 #include "isa.h" 3 #include "interp.h" 4 #include "raise.h" 5 6 /* 7 * Copyright © 1997 C H Forsyth (forsyth@terzarima.net) 8 */ 9 10 #define ROMABLE 0 /* costs something to zero patch vectors */ 11 #define RESCHED 1 /* check for interpreter reschedule */ 12 13 #define PATCH(ptr) *ptr |= ((ulong)code-(ulong)ptr) & 0xfffc 14 15 #define T(r) *((void**)(R.r)) 16 17 #define XO(o,xo) (((o)<<26)|((xo)<<1)) 18 19 /* botch: ARRR, AIRR, LRRR, etc have dest first (will fix soon) */ 20 21 #define OPARRR(o,d,a,b) ((o)|((d)<<21)|((a)<<16)|((b)<<11)) 22 #define ARRR(o,d,a,b) gen((o)|((d)<<21)|((a)<<16)|((b)<<11)) 23 #define AIRR(o,d,a,v) gen((o)|((d)<<21)|((a)<<16)|((v)&0xFFFF)) 24 #define IRR(o,v,a,d) AIRR((o),(d),(a),(v)) 25 #define RRR(o,b,a,d) ARRR((o),(d),(a),(b)) 26 #define LRRR(o,a,s,b) ARRR((o),(s),(a),(b)) 27 #define LIRR(o,a,s,v) AIRR((o),(s),(a),(v)) 28 #define Bx(li,aa) gen((18<<26)|((li)&0x3FFFFFC)|((aa)<<1)) 29 #define RLW(op,a,s,sh,mb,me) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((sh)&31L)<<11)|\ 30 (((mb)&31L)<<6)|(((me)&31L)<<1)) 31 #define MFSPR(s, d) gen(XO(31,339) | ((d)<<21) | ((s)<<11)) 32 #define MTSPR(s, d) gen(XO(31,467) | ((s)<<21) | ((d)<<11)); 33 34 #define MFCR(d) gen(XO(31,19) | ((d)<<21)) 35 #define MTCRF(s, mask) gen(XO(31,144) | ((s)<<21) | ((mask)<<12)) 36 #define MTCR(s) MTCRF(s, 0xff) 37 38 #define SLWI(d,a,n) gen(slw((d),(a),(n),0)) 39 #define LRET() gen(Oblr) 40 41 #define SETR0() if(macjit){ AIRR(Oaddi, Rzero, 0, 0); } /* set R0 to 0 */ 42 43 /* assumes H can be formed from signed halfword */ 44 #define CMPH(r) AIRR(Ocmpi, Rcrf0, (r), (ulong)H); 45 #define NOTNIL(r) (CMPH((r)), CCALL(EQ, bounds)) 46 47 enum 48 { 49 Rzero = 0, /* zero by design, not definition (P9/Inferno) */ 50 51 Rsp = 1, 52 Rsb = 2, 53 Rarg = 3, 54 55 Ro1 = 8, 56 Ro2 = 9, 57 Ro3 = 10, 58 Ri = 11, 59 Rj = 12, 60 61 Rmp = 13, 62 Rfp = 14, 63 Rreg = 15, 64 Rta = 16, /* unused */ 65 Rpic = 17, /* address for computed goto, for move to CTR or LR */ 66 67 Rcon = 26, /* constant builder; temporary */ 68 /* 27, 28, 29, 30 are potentially external registers (P9/Inferno) */ 69 Rlink = 31, /* holds copies of LR; linker temp */ 70 71 Rfret = 0, 72 Rf1 = 4, 73 Rf2 = 6, 74 Rfcvi = 27, /* floating conversion constant (P9/Inferno) */ 75 Rfzero = 28, /* 0.0 (P9/Inferno) */ 76 Rfhalf = 29, /* 0.5 (P9/Inferno) */ 77 78 Rlr = 8<<5, /* SPR(LR) */ 79 Rctr = 9<<5, /* SPR(CTR) */ 80 81 Rcrf0 = 0, /* condition code field 0 */ 82 Rcrf1 = 1<<2, /* condition code field 1 */ 83 84 Rcrbrel = 31, /* condition code bit set to force relinquish */ 85 86 Olwz = XO(32, 0), 87 Olwzu = XO(33, 0), 88 Olwzx = XO(31, 23), 89 Olbz = XO(34, 0), 90 Olbzu = XO(35, 0), 91 Olbzx = XO(31, 87), 92 Olfd = XO(50, 0), 93 Olhz = XO(40, 0), 94 Olhzx = XO(31, 279), 95 Ostw = XO(36, 0), 96 Ostwu = XO(37, 0), 97 Ostwx = XO(31, 151), 98 Ostb = XO(38, 0), 99 Ostbu = XO(39, 0), 100 Ostbx = XO(31, 215), 101 Osth = XO(44,0), 102 Osthx = XO(31, 407), 103 Ostfd = XO(54, 0), 104 Ostfdu = XO(55, 0), 105 106 Oaddc = XO(31,10), 107 Oadde = XO(31, 138), 108 Oaddi = XO(14, 0), /* simm */ 109 Oaddic_ = XO(13, 0), 110 Oaddis = XO(15, 0), 111 Ocrxor = XO(19, 193), 112 Ofadd = XO(63, 21), 113 Ofcmpo = XO(63, 32), 114 Ofctiwz = XO(63, 15), 115 Ofsub = XO(63, 20), 116 Ofmr = XO(63, 72), 117 Ofmul = XO(63, 25), 118 Ofdiv = XO(63, 18), 119 Ofneg = XO(63, 40), 120 Oori = XO(24,0), /* uimm */ 121 Ooris = XO(25,0), /* uimm */ 122 Odivw = XO(31, 491), 123 Odivwu = XO(31, 459), 124 Omulhw = XO(31, 75), 125 Omulhwu = XO(31, 11), 126 Omulli = XO(7, 0), 127 Omullw = XO(31, 235), 128 Osubf = XO(31, 40), 129 Osubfc = XO(31,8), 130 Osubfe = XO(31,136), 131 Osubfic = XO(8, 0), 132 Oadd = XO(31, 266), 133 Oand = XO(31, 28), 134 Oneg = XO(31, 104), 135 Oor = XO(31, 444), 136 Oxor = XO(31, 316), 137 138 Ocmpi = XO(11, 0), 139 Ocmp = XO(31, 0), 140 Ocmpl = XO(31, 32), 141 Ocmpli = XO(10,0), 142 143 Orlwinm = XO(21, 0), 144 Oslw = XO(31, 24), 145 Osraw = XO(31,792), 146 Osrawi = XO(31,824), 147 Osrw = XO(31,536), 148 149 Cnone = OPARRR(0,20,0,0), /* unconditional */ 150 Ceq = OPARRR(0,12,2,0), 151 Cle = OPARRR(0,4,1,0), 152 Clt = OPARRR(0,12,0,0), 153 Cdnz = OPARRR(0,16,0,0), 154 Cgt = OPARRR(0,12,1,0), 155 Cne = OPARRR(0,4,2,0), 156 Cge = OPARRR(0,4,0,0), 157 Cle1 = OPARRR(0,4,5,0), /* Cle on CR1 */ 158 Crelq = OPARRR(0,12,Rcrbrel,0), /* relinquish */ 159 Cnrelq = OPARRR(0,4,Rcrbrel,0), /* not relinquish */ 160 Cpredict = OPARRR(0,1,0,0), /* reverse prediction */ 161 Lk = 1, 162 Aa = 2, 163 164 Obeq = OPARRR(16<<26,12,2,0), 165 Obge = OPARRR(16<<26,4,0,0), 166 Obgt = OPARRR(16<<26,12,1,0), 167 Oble = OPARRR(16<<26,4,1,0), 168 Oblt = OPARRR(16<<26,12,0,0), 169 Obne = OPARRR(16<<26,4,2,0), 170 171 Ob = XO(18, 0), 172 Obc = XO(16, 0), 173 Obcctr = XO(19,528), 174 Obcctrl = Obcctr | Lk, 175 Obctr = Obcctr | Cnone, 176 Obctrl = Obctr | Lk, 177 Obclr = XO(19, 16), 178 Oblr = Obclr | Cnone, 179 Oblrl = Oblr | Lk, 180 181 Olea = 100, // pseudo op 182 183 SRCOP = (1<<0), 184 DSTOP = (1<<1), 185 WRTPC = (1<<2), /* update R.PC */ 186 TCHECK = (1<<3), /* check R.t for continue/ret */ 187 NEWPC = (1<<4), /* goto R.PC */ 188 DBRAN = (1<<5), /* dest is branch */ 189 THREOP = (1<<6), 190 191 Lg2Rune = sizeof(Rune)==4? 2: 1, 192 ANDAND = 1, 193 OROR, 194 EQAND, 195 196 MacRET = 0, 197 MacFRP, 198 MacCASE, 199 MacFRAM, 200 MacCOLR, 201 MacMCAL, 202 MacMFRA, 203 MacCVTFW, 204 MacRELQ, 205 MacEND, 206 NMACRO 207 }; 208 209 void (*comvec)(void); 210 int macjit; 211 extern long das(ulong*); 212 static ulong* code; 213 static ulong* base; 214 static ulong* patch; 215 static int pass; 216 static Module* mod; 217 static ulong* tinit; 218 static ulong* litpool; 219 static int nlit; 220 static ulong macro[NMACRO]; 221 static void ldbigc(long, int); 222 static void rdestroy(void); 223 static void macret(void); 224 static void macfrp(void); 225 static void maccase(void); 226 static void maccvtfw(void); 227 static void macfram(void); 228 static void maccolr(void); 229 static void macend(void); 230 static void macmcal(void); 231 static void macmfra(void); 232 static void macrelq(void); 233 static void movmem(Inst*); 234 235 struct 236 { 237 int o; 238 void (*f)(void); 239 } macinit[] = 240 { 241 MacFRP, macfrp, /* decrement and free pointer */ 242 MacRET, macret, /* return instruction */ 243 MacCASE, maccase, /* case instruction */ 244 MacCOLR, maccolr, /* increment and color pointer */ 245 MacFRAM, macfram, /* frame instruction */ 246 MacMCAL, macmcal, /* mcall bottom half */ 247 MacMFRA, macmfra, /* punt mframe because t->initialize==0 */ 248 MacCVTFW, maccvtfw, 249 MacRELQ, macrelq, /* reschedule */ 250 MacEND, macend, 251 0 252 }; 253 254 static void 255 rdestroy(void) 256 { 257 destroy(R.s); 258 } 259 260 static void 261 rmcall(void) 262 { 263 Frame *f; 264 Prog *p; 265 266 if((void*)R.dt == H) 267 error(exModule); 268 269 f = (Frame*)R.FP; 270 if(f == H) 271 error(exModule); 272 273 f->mr = nil; 274 ((void(*)(Frame*))R.dt)(f); 275 R.SP = (uchar*)f; 276 R.FP = f->fp; 277 if(f->t == nil) 278 unextend(f); 279 else 280 freeptrs(f, f->t); 281 p = currun(); 282 if(p->kill != nil) 283 error(p->kill); 284 } 285 286 static void 287 rmfram(void) 288 { 289 Type *t; 290 Frame *f; 291 uchar *nsp; 292 293 t = (Type*)R.s; 294 if(t == H) 295 error(exModule); 296 nsp = R.SP + t->size; 297 if(nsp >= R.TS) { 298 R.s = t; 299 extend(); 300 T(d) = R.s; 301 return; 302 } 303 f = (Frame*)R.SP; 304 R.SP = nsp; 305 f->t = t; 306 f->mr = nil; 307 initmem(t, f); 308 T(d) = f; 309 } 310 311 void 312 urk(char *s) 313 { 314 print("compile failed: %s\n", s); // debugging 315 error(exCompile); // production 316 } 317 318 static void 319 gen(ulong o) 320 { 321 *code++ = o; 322 } 323 324 static void 325 br(ulong op, ulong disp) 326 { 327 *code++ = op | (disp & 0xfffc); 328 } 329 330 static void 331 mfspr(int d, int s) 332 { 333 MFSPR(s, d); 334 } 335 336 static void 337 mtspr(int d, int s) 338 { 339 MTSPR(s, d); 340 } 341 342 static ulong 343 slw(int d, int s, int v, int rshift) 344 { 345 int m0, m1; 346 347 if(v < 0 || v > 32) 348 urk("slw v"); 349 if(v < 0) 350 v = 0; 351 else if(v > 32) 352 v = 32; 353 if(rshift) { /* shift right */ 354 m0 = v; 355 m1 = 31; 356 v = 32-v; 357 } else { 358 m0 = 0; 359 m1 = 31-v; 360 } 361 return RLW(Orlwinm, d, s, v, m0, m1); 362 } 363 364 static void 365 jr(int reg) 366 { 367 mtspr(Rctr, reg); /* code would be faster if this were loaded well before branch */ 368 gen(Obctr); 369 } 370 371 static void 372 jrl(int reg) 373 { 374 mtspr(Rctr, reg); 375 gen(Obctrl); 376 } 377 378 static void 379 jrc(int op, int reg) 380 { 381 mtspr(Rctr, reg); 382 gen(Obcctr | op); 383 } 384 385 static long 386 brdisp(ulong *dest) 387 { 388 ulong d, top; 389 390 d = (ulong)dest - (ulong)code; 391 if(!ROMABLE) 392 return d & 0x3fffffc; 393 top = d>>25; 394 if(top == 0 || top == 0x7F){ 395 /* fits in 26-bit signed displacement */ 396 return d & 0x3fffffc; 397 } 398 return -1; 399 } 400 401 static void 402 jmp(ulong *dest) 403 { 404 long d; 405 406 if((d = brdisp(dest)) < 0){ 407 ldbigc((ulong)dest, Rpic); /* Rpic & Rctr must be free */ 408 jr(Rpic); 409 } else 410 gen(Ob | d); 411 } 412 413 static void 414 jmpl(ulong *dest) 415 { 416 long d; 417 418 if((d = brdisp(dest)) < 0){ 419 ldbigc((ulong)dest, Rpic); /* Rpic must be free */ 420 jrl(Rpic); 421 } else 422 gen(Ob | d | Lk); 423 } 424 425 static void 426 jmpc(int op, ulong *dest) 427 { 428 ldbigc((ulong)dest, Rpic); 429 jrc(op, Rpic); 430 } 431 432 static int 433 bigc(long c) 434 { 435 if(c >= -0x8000 && c <= 0x7FFF) 436 return 0; 437 return 1; 438 } 439 440 static void 441 ldbigc(long c, int reg) 442 { 443 AIRR(Oaddis, reg,Rzero,c>>16); 444 LIRR(Oori, reg,reg,c); 445 } 446 447 static void 448 ldc(long c, int reg) 449 { 450 if(!bigc(c)) 451 AIRR(Oaddi, reg, Rzero, c); 452 else if((ulong)c <= 0xFFFF) 453 LIRR(Oori, reg, Rzero, c); 454 else if((c&0xFFFF) == 0) 455 LIRR(Ooris, reg, Rzero, c>>16); 456 else { 457 AIRR(Oaddis, reg,Rzero,c>>16); 458 LIRR(Oori, reg,reg,c); 459 } 460 } 461 462 static void 463 mem(int inst, long disp, int rm, int r) 464 { 465 if(bigc(disp)) { 466 ldc(disp, Rcon); 467 switch(inst){ 468 default: urk("mem op"); break; 469 case Olea: inst = Oadd; break; 470 case Olwz: inst = Olwzx; break; 471 case Olbz: inst = Olbzx; break; 472 case Olhz: inst = Olhzx; break; 473 case Ostw: inst = Ostwx; break; 474 case Ostb: inst = Ostbx; break; 475 case Osth: inst = Osthx; break; 476 } 477 ARRR(inst, r, Rcon, rm); 478 } else { 479 if(inst == Olea) 480 inst = Oaddi; 481 AIRR(inst, r, rm,disp); 482 } 483 } 484 485 static void 486 opx(int mode, Adr *a, int op, int reg) 487 { 488 ulong c; 489 int r, rx, lea; 490 491 lea = 0; 492 if(op == Olea){ 493 lea = 1; 494 op = Oaddi; 495 } 496 switch(mode) { 497 case AFP: 498 c = a->ind; 499 if(bigc(c)) 500 urk("bigc op1b 1"); 501 AIRR(op, reg, Rfp,c); 502 break; 503 case AMP: 504 c = a->ind; 505 if(bigc(c)) 506 urk("bigc op1b 2"); 507 AIRR(op, reg, Rmp,c); 508 break; 509 case AIMM: 510 if(lea) { 511 if(a->imm != 0) { 512 ldc(a->imm, reg); 513 AIRR(Ostw, reg, Rreg,O(REG,st)); 514 } else 515 AIRR(Ostw, Rzero, Rreg,O(REG,st)); 516 AIRR(Oaddi, reg, Rreg,O(REG,st)); 517 } else 518 ldc(a->imm, reg); 519 return; 520 case AIND|AFP: 521 r = Rfp; 522 goto offset; 523 case AIND|AMP: 524 r = Rmp; 525 offset: 526 c = a->i.s; 527 rx = Ri; 528 if(lea || op == Olwz) 529 rx = reg; 530 AIRR(Olwz, rx, r,a->i.f); 531 if(!lea || c != 0) 532 AIRR(op, reg, rx,c); 533 break; 534 } 535 } 536 537 static void 538 opwld(Inst *i, int op, int reg) 539 { 540 opx(USRC(i->add), &i->s, op, reg); 541 } 542 543 static void 544 opwst(Inst *i, int op, int reg) 545 { 546 opx(UDST(i->add), &i->d, op, reg); 547 } 548 549 static void 550 op2(Inst *i, int op, int reg) 551 { 552 int lea; 553 554 lea = 0; 555 if(op == Olea){ 556 op = Oaddi; 557 lea = 1; 558 } 559 switch(i->add & ARM) { 560 case AXNON: 561 if(lea) 562 op = Olea; 563 opwst(i, op, reg); 564 return; 565 case AXIMM: 566 if(lea) 567 urk("op2/lea"); 568 ldc((short)i->reg, reg); 569 return; 570 case AXINF: 571 IRR(op, i->reg,Rfp, reg); 572 break; 573 case AXINM: 574 IRR(op, i->reg,Rmp, reg); 575 break; 576 } 577 } 578 579 static void 580 op12(Inst *i, int b1flag, int b2flag) 581 { 582 int o1, o2; 583 584 o1 = Olwz; 585 if(b1flag) 586 o1 = Olbz; 587 o2 = Olwz; 588 if(b2flag) 589 o2 = Olbz; 590 if((i->add & ARM) == AXIMM) { 591 opwld(i, o1, Ro1); 592 op2(i, o2, Ro2); 593 } else { 594 op2(i, o2, Ro2); 595 opwld(i, o1, Ro1); 596 } 597 } 598 599 static void 600 op13(Inst *i, int o1, int o2) 601 { 602 opwld(i, o1, Ro1); 603 opwst(i, o2, Ro1); 604 } 605 606 static ulong 607 branch(Inst *i) 608 { 609 ulong rel; 610 611 if(base == 0) 612 return 0; 613 rel = (ulong)(base+patch[i->d.ins - mod->prog]); 614 rel -= (ulong)code; 615 if(rel & 3 || (long)rel <= -(1<<16) || (long)rel >= 1<<16) 616 urk("branch off"); 617 return rel & 0xfffc; 618 } 619 620 static void 621 schedcheck(Inst *i) 622 { 623 ulong *cp; 624 625 if(i != nil && i->d.ins != nil && i->d.ins > i) 626 return; /* only backwards jumps can loop: needn't check forward ones */ 627 cp = code; 628 gen(Obc | Cnrelq | Cpredict); 629 jmpl(base+macro[MacRELQ]); 630 PATCH(cp); 631 } 632 633 static void 634 literal(ulong imm, int roff) 635 { 636 nlit++; 637 638 ldbigc((ulong)litpool, Ro1); 639 IRR(Ostw, roff, Rreg, Ro1); 640 641 if(pass == 0) 642 return; 643 644 *litpool = imm; 645 litpool++; 646 } 647 648 static void 649 bounds(void) 650 { 651 /* mem(Ostw, O(REG,FP), Rreg, Rfp); */ 652 error(exBounds); 653 } 654 655 static void 656 punt(Inst *i, int m, void (*fn)(void)) 657 { 658 ulong pc; 659 660 if(m & SRCOP) { 661 if(UXSRC(i->add) == SRC(AIMM)) 662 literal(i->s.imm, O(REG, s)); 663 else { 664 opwld(i, Olea, Ro1); 665 mem(Ostw, O(REG, s), Rreg, Ro1); 666 } 667 } 668 if(m & DSTOP) { 669 opwst(i, Olea, Ro3); 670 IRR(Ostw, O(REG,d),Rreg, Ro3); 671 } 672 if(m & WRTPC) { 673 pc = patch[i-mod->prog+1]; 674 ldbigc((ulong)(base+pc), Ro1); 675 IRR(Ostw, O(REG,PC),Rreg, Ro1); 676 } 677 if(m & DBRAN) { 678 pc = patch[i->d.ins-mod->prog]; 679 literal((ulong)(base+pc), O(REG, d)); 680 } 681 682 switch(i->add&ARM) { 683 case AXNON: 684 if(m & THREOP) { 685 IRR(Olwz, O(REG,d),Rreg, Ro2); 686 IRR(Ostw, O(REG,m),Rreg, Ro2); 687 } 688 break; 689 case AXIMM: 690 literal((short)i->reg, O(REG,m)); 691 break; 692 case AXINF: 693 mem(Olea, i->reg, Rfp, Ro2); 694 mem(Ostw, O(REG, m), Rreg, Ro2); 695 break; 696 case AXINM: 697 mem(Olea, i->reg, Rmp, Ro2); 698 mem(Ostw, O(REG, m), Rreg, Ro2); 699 break; 700 } 701 IRR(Ostw, O(REG,FP),Rreg, Rfp); 702 703 jmpl((ulong*)fn); 704 705 ldc((ulong)&R, Rreg); 706 SETR0(); 707 if(m & TCHECK) { 708 IRR(Olwz, O(REG,t),Rreg, Ro1); 709 IRR(Olwz, O(REG,xpc),Rreg, Ro2); 710 IRR(Ocmpi, 0, Ro1, Rcrf0); 711 mtspr(Rctr, Ro2); 712 gen(Obcctr | Cne); 713 } 714 IRR(Olwz, O(REG,FP),Rreg, Rfp); 715 IRR(Olwz, O(REG,MP),Rreg, Rmp); 716 717 if(m & NEWPC) { 718 IRR(Olwz, O(REG,PC),Rreg, Ro1); 719 jr(Ro1); 720 } 721 } 722 723 static void 724 comgoto(Inst *i) 725 { 726 WORD *t, *e; 727 728 opwld(i, Olwz, Ro2); 729 opwst(i, Olea, Ro3); 730 SLWI(Ro2, Ro2, 2); 731 ARRR(Olwzx, Ro1, Ro3,Ro2); 732 jr(Ro1); 733 734 if(pass == 0) 735 return; 736 737 t = (WORD*)(mod->origmp+i->d.ind); 738 e = t + t[-1]; 739 t[-1] = 0; 740 while(t < e) { 741 t[0] = (ulong)(base + patch[t[0]]); 742 t++; 743 } 744 } 745 746 static void 747 comcase(Inst *i, int w) 748 { 749 int l; 750 WORD *t, *e; 751 752 if(w != 0) { 753 opwld(i, Olwz, Ro1); // v 754 opwst(i, Olea, Ro3); // table 755 jmp(base+macro[MacCASE]); 756 } 757 758 t = (WORD*)(mod->origmp+i->d.ind+4); 759 l = t[-1]; 760 761 /* have to take care not to relocate the same table twice - 762 * the limbo compiler can duplicate a case instruction 763 * during its folding phase 764 */ 765 766 if(pass == 0) { 767 if(l >= 0) 768 t[-1] = -l-1; /* Mark it not done */ 769 return; 770 } 771 if(l >= 0) /* Check pass 2 done */ 772 return; 773 t[-1] = -l-1; /* Set real count */ 774 e = t + t[-1]*3; 775 while(t < e) { 776 t[2] = (ulong)(base + patch[t[2]]); 777 t += 3; 778 } 779 t[0] = (ulong)(base + patch[t[0]]); 780 } 781 782 static void 783 comcasel(Inst *i) 784 { 785 int l; 786 WORD *t, *e; 787 788 t = (WORD*)(mod->origmp+i->d.ind+8); 789 l = t[-2]; 790 if(pass == 0) { 791 if(l >= 0) 792 t[-2] = -l-1; /* Mark it not done */ 793 return; 794 } 795 if(l >= 0) /* Check pass 2 done */ 796 return; 797 t[-2] = -l-1; /* Set real count */ 798 e = t + t[-2]*6; 799 while(t < e) { 800 t[4] = (ulong)base + patch[t[4]]; 801 t += 6; 802 } 803 t[0] = (ulong)base + patch[t[0]]; 804 } 805 806 static void 807 commframe(Inst *i) 808 { 809 ulong *cp1, *cp2; 810 811 opwld(i, Olwz, Ri); // must use Ri for MacFRAM 812 CMPH(Ri); 813 cp1 = code; 814 br(Obeq, 0); 815 816 if((i->add&ARM) == AXIMM) { 817 mem(Olwz, OA(Modlink, links)+i->reg*sizeof(Modl)+O(Modl, frame), Ri, Ri); 818 } else { 819 op2(i, Olwz, Ro2); 820 SLWI(Ro2, Ro2, 3); // assumes sizeof(Modl) == 8 821 ARRR(Oadd, Ri, Ro2, Ro2); 822 mem(Olwz, OA(Modlink, links)+O(Modl, frame), Ri, Ri); 823 } 824 825 AIRR(Olwz, Ro2, Ri,O(Type,initialize)); 826 AIRR(Ocmpi, Rcrf0, Ro2, 0); 827 cp2 = code; 828 br(Obne, 0); 829 830 opwst(i, Olea, Rj); 831 832 PATCH(cp1); 833 ldbigc((ulong)(base+patch[i-mod->prog+1]), Rpic); 834 mtspr(Rlr, Rpic); 835 jmp(base+macro[MacMFRA]); 836 837 PATCH(cp2); 838 jmpl(base+macro[MacFRAM]); 839 opwst(i, Ostw, Ro1); 840 } 841 842 static void 843 commcall(Inst *i) 844 { 845 opwld(i, Olwz, Ro1); // f in Ro1 846 AIRR(Olwz, Ro3, Rreg,O(REG,M)); 847 AIRR(Ostw, Rfp, Ro1,O(Frame,fp)); // f->fp = R.FP 848 AIRR(Ostw, Ro3, Ro1,O(Frame,mr)); // f->mr = R.M 849 opwst(i, Olwz, Ri); 850 if((i->add&ARM) == AXIMM) { 851 mem(Olwz, OA(Modlink, links)+i->reg*sizeof(Modl)+O(Modl, u.pc), Ri, Rj); // ml->entry in Rj 852 } else { 853 op2(i, Olwz, Rj); 854 SLWI(Rj, Rj, 3); // assumes sizeof(Modl) == 8 855 ARRR(Oadd, Ri, Rj, Rj); 856 mem(Olwz, OA(Modlink, links)+O(Modl, u.pc), Rj, Rj); 857 } 858 jmpl(base+macro[MacMCAL]); 859 } 860 861 static int 862 swapbraop(int b) 863 { 864 switch(b) { 865 case Obge: 866 return Oble; 867 case Oble: 868 return Obge; 869 case Obgt: 870 return Oblt; 871 case Oblt: 872 return Obgt; 873 } 874 return b; 875 } 876 877 static void 878 cbra(Inst *i, int op) 879 { 880 if(RESCHED) 881 schedcheck(i); 882 if(UXSRC(i->add) == SRC(AIMM) && !bigc(i->s.imm)) { 883 op2(i, Olwz, Ro1); 884 AIRR(Ocmpi, Rcrf0, Ro1, i->s.imm); 885 op = swapbraop(op); 886 } else if((i->add & ARM) == AXIMM) { 887 opwld(i, Olwz, Ro1); 888 AIRR(Ocmpi, Rcrf0, Ro1, i->reg); 889 } else { 890 op12(i, 0, 0); 891 ARRR(Ocmp, Rcrf0, Ro1, Ro2); 892 } 893 br(op, branch(i)); 894 } 895 896 static void 897 cbrab(Inst *i, int op) 898 { 899 if(RESCHED) 900 schedcheck(i); 901 if(UXSRC(i->add) == SRC(AIMM)) { 902 op2(i, Olbz, Ro1); 903 AIRR(Ocmpi, Rcrf0, Ro1, i->s.imm&0xFF); 904 op = swapbraop(op); 905 } else if((i->add & ARM) == AXIMM) { 906 opwld(i, Olbz, Ro1); 907 AIRR(Ocmpi, Rcrf0, Ro1, i->reg&0xFF); // mask i->reg? 908 } else { 909 op12(i, 1, 1); 910 ARRR(Ocmp, Rcrf0, Ro1, Ro2); 911 } 912 br(op, branch(i)); 913 } 914 915 static void 916 cbraf(Inst *i, int op) 917 { 918 if(RESCHED) 919 schedcheck(i); 920 opwld(i, Olfd, Rf1); 921 op2(i, Olfd, Rf2); 922 ARRR(Ofcmpo, Rcrf0, Rf1, Rf2); 923 br(op, branch(i)); 924 } 925 926 static void 927 cbral(Inst *i, int cms, int cls, int mode) 928 { 929 ulong *cp; 930 931 if(RESCHED) 932 schedcheck(i); 933 cp = nil; 934 opwld(i, Olea, Ri); 935 op2(i, Olea, Rj); 936 IRR(Olwz, 0,Ri, Ro1); 937 IRR(Olwz, 0,Rj, Ro2); 938 ARRR(Ocmp, Rcrf0, Ro1, Ro2); 939 switch(mode) { 940 case ANDAND: 941 cp = code; 942 br(cms, 0); 943 break; 944 case OROR: 945 br(cms, branch(i)); 946 break; 947 case EQAND: 948 br(cms, branch(i)); 949 cp = code; 950 br(Obne, 0); 951 break; 952 } 953 IRR(Olwz, 4,Ri, Ro1); 954 IRR(Olwz, 4,Rj, Ro2); 955 ARRR(Ocmpl, Rcrf0, Ro1, Ro2); 956 br(cls, branch(i)); 957 if(cp) 958 PATCH(cp); 959 } 960 961 static void 962 shrl(Inst *i) 963 { 964 // int c; 965 966 // if(USRC(i->add) != AIMM) { 967 punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); 968 return; 969 // } 970 /* 971 c = i->s.imm; 972 op2(i, Olea, Ro3); 973 IRR(Olwz, 0,Ro3, Ro1); 974 if(c >= 32) { 975 if((i->add&ARM) != AXNON) 976 opwst(i, Olea, Ro3); 977 SRR(Osra, 31, Ro1, Ro2); 978 IRR(Ostw, 0,Ro3, Ro2); 979 if(c >= 64) { 980 IRR(Ostw, 4,Ro3, Ro2); 981 return; 982 } 983 if(c > 32) 984 SRR(Osra, c-32, Ro1, Ro1); 985 IRR(Ostw, 4,Ro3, Ro1); 986 return; 987 } 988 IRR(Olwz, 4,Ro3, Ro2); 989 if((i->add&ARM) != AXNON) 990 opwst(i, Olea, Ro3); 991 if(c != 0) { 992 SRR(Osll, 32-c, Ro1, Ri); 993 SRR(Osra, c, Ro1, Ro1); 994 SRR(Osrl, c, Ro2, Ro2); 995 RRR(Oor, Ri, Ro2, Ro2); 996 } 997 IRR(Ostw, 4,Ro3, Ro2); 998 IRR(Ostw, 0,Ro3, Ro1); 999 */ 1000 } 1001 1002 static void 1003 shll(Inst *i) 1004 { 1005 // int c; 1006 1007 // if(USRC(i->add) != AIMM) { 1008 punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); 1009 return; 1010 // } 1011 /* 1012 c = i->s.imm; 1013 if(c >= 64) { 1014 opwst(i, Olea, Ro3); 1015 IRR(Ostw, 0,Ro3, Rzero); 1016 IRR(Ostw, 4,Ro3, Rzero); 1017 return; 1018 } 1019 op2(i, Olea, Ro3); 1020 if(c >= 32) { 1021 IRR(Olwz, 4,Ro3, Ro1); 1022 if((i->add&ARM) != AXNON) 1023 opwst(i, Olea, Ro3); 1024 IRR(Ostw, 4,Ro3, Rzero); 1025 if(c > 32) 1026 SRR(Osll, c-32, Ro1, Ro1); 1027 IRR(Ostw, 0,Ro3, Ro1); 1028 return; 1029 } 1030 IRR(Olwz, 4,Ro3, Ro2); 1031 IRR(Olwz, 0,Ro3, Ro1); 1032 if((i->add&ARM) != AXNON) 1033 opwst(i, Olea, Ro3); 1034 if(c != 0) { 1035 SRR(Osrl, 32-c, Ro2, Ri); 1036 SRR(Osll, c, Ro2, Ro2); 1037 SRR(Osll, c, Ro1, Ro1); 1038 RRR(Oor, Ri, Ro1, Ro1); 1039 } 1040 IRR(Ostw, 4,Ro3, Ro2); 1041 IRR(Ostw, 0,Ro3, Ro1); 1042 */ 1043 } 1044 1045 static void 1046 compdbg(void) 1047 { 1048 print("%s:%lud@%.8lux\n", R.M->m->name, *(ulong*)R.m, *(ulong*)R.s); 1049 } 1050 1051 static void 1052 comp(Inst *i) 1053 { 1054 int o, q, b; 1055 ulong *cp, *cp1; 1056 char buf[64]; 1057 1058 if(0) { 1059 Inst xx; 1060 xx.add = AXIMM|SRC(AIMM); 1061 xx.s.imm = (ulong)code; 1062 xx.reg = i-mod->prog; 1063 punt(&xx, SRCOP, compdbg); 1064 } 1065 1066 switch(i->op) { 1067 default: 1068 snprint(buf, sizeof buf, "%s compile, no '%D'", mod->name, i); 1069 error(buf); 1070 break; 1071 case IMCALL: 1072 if((i->add&ARM) == AXIMM) 1073 commcall(i); 1074 else 1075 punt(i, SRCOP|DSTOP|THREOP|WRTPC|NEWPC, optab[i->op]); 1076 break; 1077 case ISEND: 1078 case IRECV: 1079 case IALT: 1080 punt(i, SRCOP|DSTOP|TCHECK|WRTPC, optab[i->op]); 1081 break; 1082 case ISPAWN: 1083 punt(i, SRCOP|DBRAN, optab[i->op]); 1084 break; 1085 case IBNEC: 1086 case IBEQC: 1087 case IBLTC: 1088 case IBLEC: 1089 case IBGTC: 1090 case IBGEC: 1091 punt(i, SRCOP|DBRAN|NEWPC|WRTPC, optab[i->op]); 1092 break; 1093 case ICASEC: 1094 comcase(i, 0); 1095 punt(i, SRCOP|DSTOP|NEWPC, optab[i->op]); 1096 break; 1097 case ICASEL: 1098 comcasel(i); 1099 punt(i, SRCOP|DSTOP|NEWPC, optab[i->op]); 1100 break; 1101 case IADDC: 1102 case IMULL: 1103 case IDIVL: 1104 case IMODL: 1105 case IMNEWZ: 1106 case ILSRW: 1107 case ILSRL: 1108 punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); 1109 break; 1110 case IMFRAME: 1111 if((i->add&ARM) == AXIMM) 1112 commframe(i); 1113 else 1114 punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); 1115 break; 1116 case ILOAD: 1117 case INEWA: 1118 case INEWAZ: 1119 case INEW: 1120 case INEWZ: 1121 case ISLICEA: 1122 case ISLICELA: 1123 case ICONSB: 1124 case ICONSW: 1125 case ICONSL: 1126 case ICONSF: 1127 case ICONSM: 1128 case ICONSMP: 1129 case ICONSP: 1130 case IMOVMP: 1131 case IHEADMP: 1132 case IINSC: 1133 case ICVTAC: 1134 case ICVTCW: 1135 case ICVTWC: 1136 case ICVTCL: 1137 case ICVTLC: 1138 case ICVTFC: 1139 case ICVTCF: 1140 case ICVTFL: 1141 case ICVTLF: 1142 case ICVTRF: 1143 case ICVTFR: 1144 case ICVTWS: 1145 case ICVTSW: 1146 case IMSPAWN: 1147 case ICVTCA: 1148 case ISLICEC: 1149 case INBALT: 1150 punt(i, SRCOP|DSTOP, optab[i->op]); 1151 break; 1152 case INEWCM: 1153 case INEWCMP: 1154 punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); 1155 break; 1156 case INEWCB: 1157 case INEWCW: 1158 case INEWCF: 1159 case INEWCP: 1160 case INEWCL: 1161 punt(i, DSTOP|THREOP, optab[i->op]); 1162 break; 1163 case IEXIT: 1164 punt(i, 0, optab[i->op]); 1165 break; 1166 case ICVTWB: 1167 op13(i, Olwz, Ostb); 1168 break; 1169 case ICVTBW: 1170 op13(i, Olbz, Ostw); 1171 break; 1172 case IMOVB: 1173 if(USRC(i->add) == AIMM && i->s.imm == 0) { 1174 opwst(i, Ostb, Rzero); 1175 break; 1176 } 1177 op13(i, Olbz, Ostb); 1178 break; 1179 case IMOVW: 1180 if(USRC(i->add) == AIMM && i->s.imm == 0) { 1181 opwst(i, Ostw, Rzero); 1182 break; 1183 } 1184 op13(i, Olwz, Ostw); 1185 break; 1186 case ICVTLW: 1187 opwld(i, Olea, Ro1); 1188 AIRR(Olwz, Ro2, Ro1,4); 1189 opwst(i, Ostw, Ro2); 1190 break; 1191 case ICVTWL: 1192 opwld(i, Olwz, Ro1); 1193 opwst(i, Olea, Ro2); 1194 LRRR(Osrawi, Ro3, Ro1, 31); 1195 AIRR(Ostw, Ro1, Ro2,4); 1196 AIRR(Ostw, Ro3, Ro2,0); 1197 break; 1198 case IHEADM: 1199 opwld(i, Olwz, Ro1); 1200 AIRR(Oaddi, Ro1, Ro1,OA(List,data)); 1201 movmem(i); 1202 break; 1203 case IMOVM: 1204 opwld(i, Olea, Ro1); 1205 movmem(i); 1206 break; 1207 case IRET: 1208 jmp(base+macro[MacRET]); 1209 break; 1210 case IFRAME: 1211 if(UXSRC(i->add) != SRC(AIMM)) { 1212 punt(i, SRCOP|DSTOP, optab[i->op]); 1213 break; 1214 } 1215 tinit[i->s.imm] = 1; 1216 ldc((ulong)mod->type[i->s.imm], Ri); 1217 jmpl(base+macro[MacFRAM]); 1218 opwst(i, Ostw, Ro1); 1219 break; 1220 case ILEA: 1221 op13(i, Olea, Ostw); 1222 break; 1223 case IHEADW: 1224 opwld(i, Olwz, Ro1); 1225 AIRR(Olwz, Ro1, Ro1,OA(List,data)); 1226 opwst(i, Ostw, Ro1); 1227 break; 1228 case IHEADF: 1229 opwld(i, Olwz, Ro1); 1230 AIRR(Olfd, Rf1, Ro1,OA(List,data)); 1231 opwst(i, Ostfd, Rf1); 1232 break; 1233 case IHEADB: 1234 opwld(i, Olwz, Ro1); 1235 AIRR(Olbz, Ro1, Ro1,OA(List,data)); 1236 opwst(i, Ostb, Ro1); 1237 break; 1238 case ITAIL: 1239 opwld(i, Olwz, Ro1); 1240 AIRR(Olwz, Ro1, Ro1,O(List,tail)); 1241 goto movp; 1242 case IMOVP: 1243 opwld(i, Olwz, Ro1); 1244 goto movp; 1245 case IHEADP: 1246 opwld(i, Olwz, Ro1); 1247 AIRR(Olwz, Ro1, Ro1,OA(List,data)); 1248 movp: 1249 CMPH(Ro1); 1250 cp = code; 1251 br(Obeq, 0); 1252 jmpl(base+macro[MacCOLR]); 1253 PATCH(cp); 1254 opwst(i, Olea, Ro3); 1255 AIRR(Olwz, Ri, Ro3,0); 1256 AIRR(Ostw, Ro1, Ro3,0); 1257 jmpl(base+macro[MacFRP]); 1258 break; 1259 case ILENA: 1260 opwld(i, Olwz, Ri); 1261 ldc(0, Ro1); 1262 CMPH(Ri); 1263 cp = code; 1264 br(Obeq, 0); 1265 AIRR(Olwz, Ro1, Ri,O(Array,len)); 1266 PATCH(cp); 1267 opwst(i, Ostw, Ro1); 1268 break; 1269 case ILENC: 1270 opwld(i, Olwz, Ri); 1271 ldc(0, Ro1); 1272 CMPH(Ri); 1273 cp = code; 1274 br(Obeq, 0); 1275 AIRR(Olwz, Ro1, Ri,O(String,len)); 1276 AIRR(Ocmpi, Rcrf0, Ro1, 0); 1277 br(Obge, 2*4); // BGE 2(PC); skip 1278 ARRR(Oneg, Ro1, Ro1, 0); 1279 PATCH(cp); 1280 opwst(i, Ostw, Ro1); 1281 break; 1282 case ILENL: 1283 opwld(i, Olwz, Ro1); 1284 ldc(0, Ro3); 1285 CMPH(Ro1); 1286 cp = code; 1287 br(Obeq, 0); 1288 1289 cp1 = code; 1290 AIRR(Olwz, Ro1, Ro1,O(List,tail)); 1291 AIRR(Oaddi, Ro3, Ro3, 1); 1292 CMPH(Ro1); 1293 br(Obne, ((ulong)cp1-(ulong)code)); 1294 1295 PATCH(cp); 1296 opwst(i, Ostw, Ro3); 1297 break; 1298 case IMOVL: 1299 opwld(i, Olea, Ro1); 1300 AIRR(Olwz, Ro2, Ro1,0); 1301 AIRR(Olwz, Ro3, Ro1,4); 1302 opwst(i, Olea, Ro1); 1303 AIRR(Ostw, Ro2, Ro1,0); 1304 AIRR(Ostw, Ro3, Ro1,4); 1305 break; 1306 case IMOVF: 1307 opwld(i, Olfd, Rf1); 1308 opwst(i, Ostfd, Rf1); 1309 break; 1310 case ICVTFW: 1311 if(!macjit){ 1312 opwld(i, Olfd, Rf1); 1313 jmpl(base+macro[MacCVTFW]); 1314 opwst(i, Ostw, Ro1); 1315 break; 1316 } 1317 case ICVTWF: 1318 punt(i, SRCOP|DSTOP, optab[i->op]); 1319 break; 1320 case INEGF: 1321 opwld(i, Olfd, Rf1); 1322 ARRR(Ofneg, Rf2, 0, Rf1); 1323 opwst(i, Ostfd, Rf2); 1324 break; 1325 case IXORL: 1326 case IORL: 1327 case IANDL: 1328 case IADDL: 1329 case ISUBL: 1330 opwld(i, Olea, Ro1); 1331 op2(i, Olea, Ro3); 1332 1333 AIRR(Olwz, Rj, Ro1,4); /* ls */ 1334 AIRR(Olwz, Ro2, Ro3,4); 1335 AIRR(Olwz, Ri, Ro1,0); /* ms */ 1336 AIRR(Olwz, Ro1, Ro3,0); 1337 1338 switch(i->op) { 1339 case IXORL: 1340 o = Oxor; 1341 goto l1; 1342 case IORL: 1343 o = Oor; 1344 goto l1; 1345 case IANDL: 1346 o = Oand; 1347 l1: 1348 LRRR(o, Ro1, Ri, Ro1); 1349 LRRR(o, Ro2, Rj, Ro2); 1350 break; 1351 case IADDL: 1352 RRR(Oaddc, Rj,Ro2, Ro2); 1353 RRR(Oadde, Ri,Ro1, Ro1); 1354 break; 1355 case ISUBL: 1356 RRR(Osubfc, Ro2,Rj, Ro2); 1357 RRR(Osubfe, Ro1,Ri, Ro1); 1358 break; 1359 } 1360 if((i->add&ARM) != AXNON) 1361 opwst(i, Olea, Ro3); 1362 IRR(Ostw, 0,Ro3, Ro1); 1363 IRR(Ostw, 4,Ro3, Ro2); 1364 break; 1365 case ISHLL: 1366 shll(i); 1367 break; 1368 case ISHRL: 1369 shrl(i); 1370 break; 1371 case IADDF: o = Ofadd; goto f1; 1372 case ISUBF: o = Ofsub; goto f1; 1373 case IMULF: o = Ofmul; goto f1; 1374 case IDIVF: o = Ofdiv; goto f1; 1375 f1: 1376 opwld(i, Olfd, Rf1); 1377 op2(i, Olfd, Rf2); 1378 if(o == Ofmul) 1379 gen(o | (Rf2<<21) | (Rf2<<16) | (Rf1<<6)); /* odd one out: op D,A,-,C */ 1380 else 1381 ARRR(o, Rf2, Rf2, Rf1); 1382 opwst(i, Ostfd, Rf2); 1383 break; 1384 1385 case IBEQF: 1386 cbraf(i, Obeq); 1387 break; 1388 case IBGEF: 1389 cbraf(i, Obge); 1390 case IBGTF: 1391 cbraf(i, Obgt); 1392 break; 1393 case IBLEF: 1394 cbraf(i, Oble); 1395 break; 1396 case IBLTF: 1397 cbraf(i, Oblt); 1398 break; 1399 case IBNEF: 1400 cbraf(i, Obne); 1401 break; 1402 1403 case IBLTB: 1404 cbrab(i, Oblt); 1405 break; 1406 case IBLEB: 1407 cbrab(i, Oble); 1408 break; 1409 case IBGTB: 1410 cbrab(i, Obgt); 1411 break; 1412 case IBGEB: 1413 cbrab(i, Obge); 1414 break; 1415 case IBEQB: 1416 cbrab(i, Obeq); 1417 break; 1418 case IBNEB: 1419 cbrab(i, Obne); 1420 break; 1421 1422 case IBLTW: 1423 cbra(i, Oblt); 1424 break; 1425 case IBLEW: 1426 cbra(i, Oble); 1427 break; 1428 case IBGTW: 1429 cbra(i, Obgt); 1430 break; 1431 case IBGEW: 1432 cbra(i, Obge); 1433 break; 1434 case IBEQW: 1435 cbra(i, Obeq); 1436 break; 1437 case IBNEW: 1438 cbra(i, Obne); 1439 break; 1440 1441 case IBEQL: 1442 cbral(i, Obne, Obeq, ANDAND); 1443 break; 1444 case IBNEL: 1445 cbral(i, Obne, Obne, OROR); 1446 break; 1447 case IBLTL: 1448 cbral(i, Oblt, Oblt, EQAND); 1449 break; 1450 case IBLEL: 1451 cbral(i, Oblt, Oble, EQAND); 1452 break; 1453 case IBGTL: 1454 cbral(i, Obgt, Obgt, EQAND); 1455 break; 1456 case IBGEL: 1457 cbral(i, Obgt, Obge, EQAND); 1458 break; 1459 1460 case ISUBB: 1461 case IADDB: 1462 case IANDB: 1463 case IORB: 1464 case IXORB: 1465 case IMODB: 1466 case IDIVB: 1467 case IMULB: 1468 b = 1; 1469 op12(i, b, b); 1470 goto s2; 1471 case ISHLB: 1472 case ISHRB: 1473 b = 1; 1474 op12(i, 0, b); 1475 goto s2; 1476 case ISUBW: 1477 case IADDW: 1478 case IANDW: 1479 case IORW: 1480 case IXORW: 1481 case ISHLW: 1482 case ISHRW: 1483 case IMODW: 1484 case IDIVW: 1485 case IMULW: 1486 b = 0; 1487 op12(i, b, b); 1488 s2: 1489 q = 0; 1490 switch(i->op) { 1491 case ISUBB: 1492 case ISUBW: o = Osubf; q = Osubfic; 1493 // TO DO: if immediate operand, should use opcode q 1494 USED(q); 1495 ARRR(o, Ro3, Ro1, Ro2); 1496 break; 1497 case IADDB: 1498 case IADDW: o = Oadd; q = Oaddi; goto c1; 1499 case IMULB: 1500 case IMULW: o = Omullw; q = Omulli; goto c1; 1501 case IDIVB: 1502 case IDIVW: o = Odivw; goto c1; 1503 c1: 1504 // TO DO: if immediate operand, should use opcode q 1505 USED(q); 1506 ARRR(o, Ro3, Ro2, Ro1); 1507 break; 1508 case IANDB: 1509 case IANDW: o = Oand; goto c2; 1510 case IORB: 1511 case IORW: o = Oor; goto c2; 1512 case IXORB: 1513 case IXORW: o = Oxor; goto c2; 1514 case ISHLB: 1515 case ISHLW: o = Oslw; goto c2; 1516 case ISHRB: 1517 case ISHRW: o = Osraw; goto c2; 1518 c2: 1519 LRRR(o, Ro3,Ro2,Ro1); 1520 break; 1521 case IMODB: 1522 case IMODW: 1523 ARRR(Odivw, Ro3, Ro2, Ro1); 1524 ARRR(Omullw, Ro3, Ro3, Ro1); 1525 ARRR(Osubf, Ro3, Ro3, Ro2); 1526 break; 1527 } 1528 opwst(i, b? Ostb: Ostw, Ro3); 1529 break; 1530 case ICALL: 1531 opwld(i, Olwz, Ro1); /* f = T(s) */ 1532 ldbigc((ulong)(base+patch[i-mod->prog+1]), Ro2); /* R.pc */ 1533 AIRR(Ostw, Rfp, Ro1,O(Frame,fp)); /* f->fp = R.fp */ 1534 AIRR(Ostw, Ro2, Ro1,O(Frame,lr)); /* f->lr = R.pc */ 1535 AIRR(Oaddi, Rfp, Ro1, 0); /* R.fp = (uchar*)f */ 1536 jmp(base+patch[i->d.ins - mod->prog]); 1537 break; 1538 case IJMP: 1539 if(RESCHED) 1540 schedcheck(i); 1541 jmp(base+patch[i->d.ins - mod->prog]); 1542 break; 1543 case IGOTO: 1544 comgoto(i); 1545 break; 1546 case IINDC: 1547 opwld(i, Olwz, Ro1); // Ro1 = string 1548 if((i->add&ARM) != AXIMM) 1549 op2(i, Olwz, Ro2); // Ro2 = i 1550 AIRR(Olwz, Ri, Ro1,O(String,len)); // len<0 => index Runes, otherwise bytes 1551 AIRR(Oaddi, Ro1, Ro1,O(String,data)); 1552 AIRR(Ocmpi, Rcrf0, Ri, 0); 1553 if(bflag){ 1554 br(Obge, 2*4); 1555 ARRR(Oneg, Ri, Ri, 0); 1556 if((i->add&ARM) != AXIMM) 1557 ARRR(Ocmpl, Rcrf1, Ri, Ro2); /* CMPU len, i */ 1558 else 1559 AIRR(Ocmpli, Rcrf1, Ri, i->reg); /* CMPU len, i */ 1560 jmpc(Cle1, (ulong*)bounds); 1561 } 1562 cp = code; 1563 br(Obge, 0); 1564 if((i->add&ARM) != AXIMM){ 1565 SLWI(Ro2, Ro2, Lg2Rune); 1566 if(sizeof(Rune) == 4) 1567 ARRR(Olwz, Ro3, Ro1, Ro2); 1568 else 1569 ARRR(Olhzx, Ro3, Ro1, Ro2); 1570 } else 1571 mem(Olwz, (short)i->reg<<Lg2Rune, Ro1, Ro3); /* BUG: TO DO: 16-bit signed displacement */ 1572 gen(Ob | (2*4)); // skip 1573 PATCH(cp); 1574 if((i->add&ARM) != AXIMM) 1575 ARRR(Olbzx, Ro3, Ro1, Ro2); 1576 else 1577 AIRR(Olbz, Ro3, Ro1,i->reg); 1578 opwst(i, Ostw, Ro3); 1579 break; 1580 case IINDX: 1581 case IINDB: 1582 case IINDF: 1583 case IINDW: 1584 case IINDL: 1585 opwld(i, Olwz, Ro1); /* Ro1 = a */ 1586 opwst(i, Olwz, Ro3); /* Ro3 = i */ 1587 if(bflag){ 1588 AIRR(Olwz, Ro2, Ro1, O(Array, len)); /* Ro2 = a->len */ 1589 ARRR(Ocmpl, Rcrf0, Ro3, Ro2); /* CMPU i, len */ 1590 jmpc(Cge, (ulong*)bounds); 1591 } 1592 // TO DO: check a != H 1593 AIRR(Olwz, Ro2, Ro1,O(Array,data)); /* Ro2 = a->data */ 1594 switch(i->op) { 1595 case IINDX: 1596 AIRR(Olwz, Ri, Ro1,O(Array,t)); // Ri = a->t 1597 AIRR(Olwz, Ro1, Ri,O(Type,size)); // Ro1 = a->t->size 1598 ARRR(Omullw, Ro3, Ro3, Ro1); // Ro3 = i*size 1599 break; 1600 case IINDL: 1601 case IINDF: 1602 SLWI(Ro3, Ro3, 3); /* Ro3 = i*8 */ 1603 break; 1604 case IINDW: 1605 SLWI(Ro3, Ro3, 2); /* Ro3 = i*4 */ 1606 break; 1607 case IINDB: 1608 /* no further work */ 1609 break; 1610 } 1611 ARRR(Oadd, Ro2, Ro2, Ro3); /* Ro2 = i*size + data */ 1612 op2(i, Ostw, Ro2); 1613 break; 1614 case ICASE: 1615 comcase(i, 1); 1616 break; 1617 case IRAISE: 1618 punt(i, SRCOP|WRTPC|NEWPC, optab[i->op]); 1619 break; 1620 case IMULX: 1621 case IDIVX: 1622 case ICVTXX: 1623 case IMULX0: 1624 case IDIVX0: 1625 case ICVTXX0: 1626 case IMULX1: 1627 case IDIVX1: 1628 case ICVTXX1: 1629 case ICVTFX: 1630 case ICVTXF: 1631 case IEXPW: 1632 case IEXPL: 1633 case IEXPF: 1634 punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); 1635 break; 1636 case ISELF: 1637 punt(i, DSTOP, optab[i->op]); 1638 break; 1639 } 1640 } 1641 1642 enum { 1643 PREFLEN = 64, /* max instruction words in comvec */ 1644 }; 1645 1646 static void 1647 preamble(void) 1648 { 1649 ulong *s; 1650 1651 if(comvec != nil) 1652 return; 1653 s = code = malloc(PREFLEN*sizeof(*code)); 1654 if(s == nil) 1655 error(exNomem); 1656 1657 #ifdef __ELF__ 1658 if(macjit) { 1659 ulong *cp; 1660 int r; 1661 1662 /* 1663 * ELF frame: 1664 * 0(%sp) - back chain 1665 * 4(%sp) - callee's LR save slot 1666 * 8(%sp) to 36(%sp) - 8 words of parameter list area 1667 * 40(%sp) to 48(%sp) - pad to 16 byte alignment/local vars 1668 */ 1669 mfspr(Ro1, Rlr); 1670 AIRR(Ostw, Ro1, Rsp,4); 1671 AIRR(Ostwu, Rsp, Rsp,-128); 1672 1673 MFCR(Ro1); 1674 AIRR(Ostw, Ro1, Rsp,52); 1675 for (r = 14; r < 32; ++r) 1676 AIRR(Ostw, r, Rsp,r*4); 1677 1678 cp = code; 1679 gen(Ob | Lk); 1680 1681 AIRR(Olwz, Ro1, Rsp,52); 1682 MTCR(Ro1); 1683 for (r = 14; r < 32; ++r) 1684 AIRR(Olwz, r, Rsp,r*4); 1685 AIRR(Oaddi, Rsp, Rsp, 128); 1686 1687 AIRR(Olwz, Ro1, Rsp,4); 1688 mtspr(Rlr, Ro1); 1689 LRET(); 1690 1691 PATCH(cp); 1692 } 1693 #endif /* __ELF__ */ 1694 1695 ldc((ulong)&R, Rreg); 1696 SETR0(); 1697 mfspr(Rlink, Rlr); 1698 AIRR(Ostw, Rlink, Rreg,O(REG,xpc)); 1699 AIRR(Olwz, Ri, Rreg,O(REG,PC)); 1700 mtspr(Rctr, Ri); 1701 AIRR(Olwz, Rfp, Rreg,O(REG,FP)); 1702 AIRR(Olwz, Rmp, Rreg,O(REG,MP)); 1703 gen(Obctr); 1704 if(code >= (ulong*)(s + PREFLEN)) 1705 urk("preamble"); 1706 comvec = (void*)s; 1707 segflush(s, PREFLEN*sizeof(*s)); 1708 if(cflag > 3) { 1709 print("comvec\n"); 1710 while(s < code) 1711 s += das(s); 1712 } 1713 } 1714 1715 static void 1716 macfrp(void) 1717 { 1718 CMPH(Ri); 1719 gen(Obclr | Ceq); // arg == $H? => return 1720 1721 AIRR(Olwz, Ro2, Ri,O(Heap,ref)-sizeof(Heap)); 1722 AIRR(Oaddic_, Rj, Ro2, -1); // ref(arg)-- and test 1723 AIRR(Ostw, Rj, Ri,O(Heap,ref)-sizeof(Heap)); 1724 gen(Obclr | Cne); // ref(arg) nonzero? => return 1725 1726 AIRR(Ostw, Ro2, Ri,O(Heap,ref)-sizeof(Heap)); // restore ref count of 1 for destroy 1727 mfspr(Rlink, Rlr); 1728 AIRR(Ostw, Rlink, Rreg,O(REG,st)); 1729 AIRR(Ostw, Rfp, Rreg,O(REG,FP)); 1730 AIRR(Ostw, Ri, Rreg,O(REG,s)); 1731 1732 jmpl((ulong*)rdestroy); // CALL destroy 1733 1734 ldc((ulong)&R, Rreg); 1735 SETR0(); 1736 AIRR(Olwz, Rlink, Rreg,O(REG,st)); 1737 mtspr(Rlr, Rlink); 1738 AIRR(Olwz, Rfp, Rreg,O(REG,FP)); 1739 AIRR(Olwz, Rmp, Rreg,O(REG,MP)); 1740 LRET(); 1741 } 1742 1743 static void 1744 macret(void) 1745 { 1746 ulong *cp1, *cp2, *cp3, *cp4, *cp5, *linterp; 1747 Inst i; 1748 1749 AIRR(Olwz, Ro1, Rfp,O(Frame,t)); 1750 AIRR(Ocmpi, Rcrf0, Ro1, 0); 1751 cp1 = code; 1752 br(Obeq, 0); // t(Rfp) == 0 1753 1754 AIRR(Olwz, Rpic, Ro1,O(Type,destroy)); 1755 AIRR(Ocmpi, Rcrf0, Rpic, 0); 1756 cp2 = code; 1757 br(Obeq, 0); // destroy(t(fp)) == 0 1758 1759 AIRR(Olwz, Ro2, Rfp,O(Frame,fp)); 1760 AIRR(Ocmpi, Rcrf0, Ro2, 0); 1761 cp3 = code; 1762 br(Obeq, 0); // fp(Rfp) == 0 1763 1764 AIRR(Olwz, Ro3, Rfp,O(Frame,mr)); 1765 AIRR(Ocmpi, Rcrf0, Ro3, 0); 1766 cp4 = code; 1767 br(Obeq, 0); // mr(Rfp) == 0 1768 1769 AIRR(Olwz, Ro2, Rreg,O(REG,M)); 1770 AIRR(Olwz, Ro3, Ro2,O(Heap,ref)-sizeof(Heap)); 1771 AIRR(Oaddic_, Ro3, Ro3, -1); // --ref(arg), set cc 1772 cp5 = code; 1773 br(Obeq, 0); // --ref(arg) == 0? 1774 AIRR(Ostw, Ro3, Ro2,O(Heap,ref)-sizeof(Heap)); 1775 1776 AIRR(Olwz, Ro1, Rfp,O(Frame,mr)); 1777 AIRR(Ostw, Ro1, Rreg,O(REG,M)); 1778 AIRR(Olwz, Rmp, Ro1,O(Modlink,MP)); 1779 AIRR(Ostw, Rmp, Rreg,O(REG,MP)); 1780 AIRR(Olwz, Ro3, Ro1,O(Modlink,compiled)); // R.M->compiled? 1781 AIRR(Ocmpi, Rcrf0, Ro3, 0); 1782 linterp = code; 1783 br(Obeq, 0); 1784 1785 PATCH(cp4); 1786 jrl(Rpic); // call destroy(t(fp)) 1787 AIRR(Ostw, Rfp, Rreg,O(REG,SP)); 1788 AIRR(Olwz, Ro1, Rfp,O(Frame,lr)); 1789 AIRR(Olwz, Rfp, Rfp,O(Frame,fp)); 1790 AIRR(Ostw, Rfp, Rreg,O(REG,FP)); // R.FP = Rfp 1791 jr(Ro1); // goto lr(Rfp) 1792 1793 PATCH(linterp); 1794 jrl(Rpic); // call destroy(t(fp)) 1795 AIRR(Ostw, Rfp, Rreg,O(REG,SP)); 1796 AIRR(Olwz, Ro1, Rfp,O(Frame,lr)); 1797 AIRR(Olwz, Rfp, Rfp,O(Frame,fp)); 1798 AIRR(Ostw, Ro1, Rreg,O(REG,PC)); // R.PC = fp->lr 1799 AIRR(Ostw, Rfp, Rreg,O(REG,FP)); // R.FP = Rfp 1800 AIRR(Olwz, Rpic, Rreg,O(REG,xpc)); 1801 mtspr(Rlr, Rpic); 1802 gen(Oblr); // return to xec uncompiled code 1803 1804 PATCH(cp1); 1805 PATCH(cp2); 1806 PATCH(cp3); 1807 PATCH(cp5); 1808 i.add = AXNON; 1809 punt(&i, TCHECK|NEWPC, optab[IRET]); 1810 } 1811 1812 static void 1813 maccase(void) 1814 { 1815 ulong *cp1, *cp2, *cp3, *loop; 1816 1817 /* 1818 * Ro1 = value (input arg), t 1819 * Ro2 = count, n 1820 * Ro3 = table pointer (input arg) 1821 * Ri = n/2, n2 1822 * Rj = pivot element t+n/2*3, l 1823 */ 1824 1825 IRR(Olwz, 0,Ro3, Ro2); // count 1826 IRR(Oaddi, 0,Ro3, Rlink); // initial table pointer 1827 1828 loop = code; // loop: 1829 AIRR(Ocmpi, Rcrf0, Ro2, 0); 1830 cp1 = code; 1831 br(Oble, 0); // n <= 0? goto out 1832 LRRR(Osrawi, Ri, Ro2, 1); // n2 = n>>1 1833 SLWI(Rj, Ri, 1); 1834 ARRR(Oadd, Rj, Rj, Ri); 1835 SLWI(Rj, Rj, 2); 1836 ARRR(Oadd, Rj, Rj, Ro3); // l = t + n2*3; 1837 AIRR(Olwz, Rpic, Rj,4); 1838 ARRR(Ocmp, Rcrf0, Ro1, Rpic); 1839 cp2 = code; 1840 br(Oblt, 0); // v < l[1]? goto low 1841 1842 IRR(Olwz, 8,Rj, Rpic); 1843 ARRR(Ocmp, Rcrf0, Ro1, Rpic); 1844 cp3 = code; 1845 br(Obge, 0); // v >= l[2]? goto high 1846 1847 IRR(Olwz, 12,Rj, Ro3); // found 1848 jr(Ro3); 1849 1850 PATCH(cp2); // low: 1851 IRR(Oaddi, 0, Ri, Ro2); // n = n2 1852 jmp(loop); 1853 1854 PATCH(cp3); // high: 1855 IRR(Oaddi, 12, Rj, Ro3); // t = l+3; 1856 IRR(Oaddi, 1, Ri, Rpic); 1857 RRR(Osubf, Ro2, Rpic, Ro2); // n -= n2 + 1 1858 jmp(loop); 1859 1860 PATCH(cp1); // out: 1861 IRR(Olwz, 0,Rlink, Ro2); // initial n 1862 SLWI(Ro3, Ro2, 1); 1863 RRR(Oadd, Ro3, Ro2, Ro2); 1864 SLWI(Ro2, Ro2, 2); 1865 RRR(Oadd, Ro2, Rlink, Rlink); 1866 IRR(Olwz, 4,Rlink, Ro3); // (initial t)[n*3+1] 1867 jr(Ro3); 1868 } 1869 1870 static void 1871 macmcal(void) 1872 { 1873 ulong *cp; 1874 1875 AIRR(Olwz, Ro2, Ri,O(Modlink,prog)); 1876 mfspr(Rlink, Rlr); 1877 AIRR(Ostw, Rlink, Ro1,O(Frame,lr)); // f->lr = return 1878 AIRR(Ocmpi, Rcrf0, Ro2, 0); 1879 AIRR(Oaddi, Rfp, Ro1, 0); // R.FP = f 1880 cp = code; 1881 br(Obne, 0); // CMPL ml->m->prog != 0 1882 1883 AIRR(Ostw, Rlink, Rreg,O(REG,st)); 1884 AIRR(Ostw, Ro1, Rreg,O(REG,FP)); 1885 AIRR(Ostw, Rj, Rreg,O(REG,dt)); 1886 jmpl((ulong*)rmcall); // CALL rmcall 1887 ldc((ulong)&R, Rreg); 1888 SETR0(); 1889 AIRR(Olwz, Rlink, Rreg,O(REG,st)); 1890 mtspr(Rlr, Rlink); 1891 AIRR(Olwz, Rfp, Rreg,O(REG,FP)); 1892 AIRR(Olwz, Rmp, Rreg,O(REG,MP)); 1893 gen(Oblr); // RET 1894 1895 PATCH(cp); 1896 AIRR(Olwz, Ro2, Ri,O(Heap,ref)-sizeof(Heap)); 1897 AIRR(Ostw, Ri, Rreg,O(REG,M)); 1898 AIRR(Oaddi, Ro2, Ro2, 1); 1899 AIRR(Olwz, Rmp, Ri,O(Modlink,MP)); 1900 AIRR(Ostw, Ro2, Ri,O(Heap,ref)-sizeof(Heap)); 1901 AIRR(Ostw, Rmp, Rreg,O(REG,MP)); 1902 AIRR(Olwz, Ro2, Ri,O(Modlink,compiled)); 1903 AIRR(Ocmpi, Rcrf0, Ro2, 0); 1904 mtspr(Rctr, Rj); 1905 gen(Obcctr | Cne); // return to compiled code 1906 1907 AIRR(Ostw, Rfp, Rreg,O(REG,FP)); // R.FP = Rfp 1908 AIRR(Ostw, Rj, Rreg,O(REG,PC)); // R.PC = Rj 1909 AIRR(Olwz, Rpic, Rreg,O(REG,xpc)); 1910 mtspr(Rlr, Rpic); 1911 gen(Oblr); // return to xec uncompiled code 1912 } 1913 1914 static void 1915 macmfra(void) 1916 { 1917 mfspr(Rlink, Rlr); 1918 AIRR(Ostw, Rlink, Rreg,O(REG,st)); 1919 AIRR(Ostw, Rfp, Rreg,O(REG,FP)); 1920 AIRR(Ostw, Ri, Rreg,O(REG,s)); 1921 AIRR(Ostw, Rj, Rreg,O(REG,d)); 1922 jmpl((ulong*)rmfram); 1923 ldc((ulong)&R, Rreg); 1924 SETR0(); 1925 AIRR(Olwz, Rlink, Rreg,O(REG,st)); 1926 mtspr(Rlr, Rlink); 1927 AIRR(Olwz, Rfp, Rreg,O(REG,FP)); 1928 AIRR(Olwz, Rmp, Rreg,O(REG,MP)); 1929 gen(Oblr); 1930 } 1931 1932 static void 1933 macfram(void) 1934 { 1935 ulong *cp; 1936 1937 /* 1938 * Ri has t 1939 */ 1940 AIRR(Olwz, Ro2, Ri,O(Type,size)); // MOVW t->size, Ro3 1941 AIRR(Olwz, Ro1, Rreg,O(REG,SP)); // MOVW R.SP, Ro1 (=(Frame*)R.SP) 1942 AIRR(Olwz, Ro3, Rreg,O(REG,TS)); // MOVW R.TS, tmp 1943 ARRR(Oadd, Ro2, Ro2, Ro1); // ADD Ro1, t->size, nsp 1944 ARRR(Ocmpl, Rcrf0, Ro2, Ro3); // CMPU nsp,tmp (nsp >= R.TS?) 1945 cp = code; 1946 br(Obge, 0); // BGE expand 1947 1948 AIRR(Olwz, Rj, Ri,O(Type,initialize)); 1949 mtspr(Rctr, Rj); 1950 AIRR(Ostw, Ro2, Rreg,O(REG,SP)); // R.SP = nsp 1951 AIRR(Ostw, Rzero, Ro1,O(Frame,mr)); // Ro1->mr = nil 1952 AIRR(Ostw, Ri, Ro1,O(Frame,t)); // Ro1->t = t 1953 gen(Obctr); // become t->init(Ro1), returning Ro1 1954 1955 PATCH(cp); // expand: 1956 AIRR(Ostw, Ri, Rreg,O(REG,s)); // MOVL t, R.s 1957 mfspr(Rlink, Rlr); 1958 AIRR(Ostw, Rlink, Rreg,O(REG,st)); // MOVL Rlink, R.st 1959 AIRR(Ostw, Rfp, Rreg,O(REG,FP)); // MOVL RFP, R.FP 1960 jmpl((ulong*)extend); // CALL extend 1961 ldc((ulong)&R, Rreg); 1962 SETR0(); 1963 AIRR(Olwz, Rlink, Rreg,O(REG,st)); // reload registers 1964 mtspr(Rlr, Rlink); 1965 AIRR(Olwz, Rfp, Rreg,O(REG,FP)); 1966 AIRR(Olwz, Rmp, Rreg,O(REG,MP)); 1967 AIRR(Olwz, Ro1, Rreg,O(REG,s)); // return R.s set by extend 1968 LRET(); // RET 1969 } 1970 1971 static void 1972 movloop(int ldu, int stu, int adj) 1973 { 1974 ulong *cp; 1975 1976 AIRR(Oaddi, Ro1, Ro1, -adj); // adjust for update ld/st 1977 AIRR(Oaddi, Ro3, Ro3, -adj); 1978 mtspr(Rctr, Ro2); 1979 1980 cp = code; // l0: 1981 AIRR(ldu, Ri, Ro1,adj); 1982 AIRR(stu, Ri, Ro3,adj); 1983 br(Obc | Cdnz, ((ulong)cp-(ulong)code)); // DBNZ l0 1984 } 1985 1986 static void 1987 movmem(Inst *i) 1988 { 1989 ulong *cp; 1990 1991 // source address already in Ro1 1992 if((i->add&ARM) != AXIMM){ 1993 op2(i, Olwz, Ro2); 1994 AIRR(Ocmpi, Rcrf0, Ro2, 0); 1995 cp = code; 1996 br(Oble, 0); 1997 opwst(i, Olea, Ro3); 1998 movloop(Olbzu, Ostbu, 1); 1999 PATCH(cp); 2000 return; 2001 } 2002 switch(i->reg){ 2003 case 4: 2004 AIRR(Olwz, Ro2, Ro1,0); 2005 opwst(i, Ostw, Ro2); 2006 break; 2007 case 8: 2008 AIRR(Olwz, Ro2, Ro1,0); 2009 opwst(i, Olea, Ro3); 2010 AIRR(Olwz, Ro1, Ro1,4); 2011 AIRR(Ostw, Ro2, Ro3,0); 2012 AIRR(Ostw, Ro1, Ro3,4); 2013 break; 2014 default: 2015 // could use lwsi/stwsi loop... 2016 opwst(i, Olea, Ro3); 2017 if((i->reg&3) == 0) { 2018 ldc(i->reg>>2, Ro2); 2019 movloop(Olwzu, Ostwu, 4); 2020 } else { 2021 ldc(i->reg, Ro2); 2022 movloop(Olbzu, Ostbu, 1); 2023 } 2024 break; 2025 } 2026 } 2027 2028 static void 2029 maccolr(void) 2030 { 2031 ldbigc((ulong)&mutator, Ri); 2032 AIRR(Olwz, Ri, Ri,0); 2033 AIRR(Olwz, Ro3, Ro1,O(Heap,color)-sizeof(Heap)); // h->color 2034 2035 AIRR(Olwz, Ro2, Ro1,O(Heap,ref)-sizeof(Heap)); // h->ref 2036 2037 ARRR(Ocmp, Rcrf0, Ri, Ro3); 2038 AIRR(Oaddi, Ro2, Ro2, 1); // h->ref++ 2039 AIRR(Ostw, Ro2, Ro1,O(Heap,ref)-sizeof(Heap)); 2040 gen(Obclr | Ceq); // return if h->color == mutator 2041 2042 ldc(propagator, Ro3); 2043 AIRR(Ostw, Ro3, Ro1,O(Heap,color)-sizeof(Heap)); // h->color = propagator 2044 ldc((ulong)&nprop, Ro3); 2045 AIRR(Ostw, Ro1, Ro3,0); // nprop = !0 2046 LRET(); 2047 } 2048 2049 static void 2050 maccvtfw(void) 2051 { 2052 ulong *cp; 2053 2054 ARRR(Ofcmpo, Rcrf0, Rf1, Rfzero); 2055 ARRR(Ofneg, Rf2, 0, Rfhalf); 2056 cp = code; 2057 br(Oblt, 0); 2058 ARRR(Ofmr, Rf2, 0, Rfhalf); 2059 PATCH(cp); 2060 ARRR(Ofadd, Rf1, Rf1, Rf2); //x<0? x-.5: x+.5 2061 ARRR(Ofctiwz, Rf2, 0, Rf1); 2062 /* avoid using Ostfdu for now, since software emulation will run on same stack */ 2063 if(0){ 2064 AIRR(Ostfdu, Rf2, Rsp,-8); // MOVDU Rf2, -8(R1) (store in temp) 2065 }else{ 2066 AIRR(Oaddi, Rsp, Rsp, -8); // SUB $8, R1 2067 AIRR(Ostfd, Rf2, Rsp,0); // MOVD Rf2, 0(R1) (store in temp) 2068 } 2069 AIRR(Olwz, Ro1, Rsp,4); // MOVW 4(R1), Ro1 2070 AIRR(Oaddi, Rsp, Rsp, 8); // ADD $8, R1 2071 LRET(); 2072 } 2073 2074 static void 2075 macrelq(void) 2076 { 2077 ARRR(Ocrxor, Rcrbrel, Rcrbrel, Rcrbrel); /* clear the relinquish condition */ 2078 mfspr(Rlink, Rlr); 2079 IRR(Ostw, O(REG,FP),Rreg, Rfp); 2080 IRR(Ostw, O(REG,PC),Rreg, Rlink); 2081 IRR(Olwz, O(REG,xpc),Rreg, Ro2); 2082 jr(Ro2); 2083 } 2084 2085 static void 2086 macend(void) 2087 { 2088 } 2089 2090 void 2091 comd(Type *t) 2092 { 2093 int i, j, m, c; 2094 2095 mfspr(Rlink, Rlr); 2096 AIRR(Ostw, Rlink, Rreg,O(REG,dt)); 2097 for(i = 0; i < t->np; i++) { 2098 c = t->map[i]; 2099 j = i<<5; 2100 for(m = 0x80; m != 0; m >>= 1) { 2101 if(c & m) { 2102 mem(Olwz, j, Rfp, Ri); 2103 jmpl(base+macro[MacFRP]); 2104 } 2105 j += sizeof(WORD*); 2106 } 2107 } 2108 AIRR(Olwz, Rlink, Rreg,O(REG,dt)); 2109 mtspr(Rlr, Rlink); 2110 gen(Oblr); 2111 } 2112 2113 void 2114 comi(Type *t) 2115 { 2116 int i, j, m, c; 2117 2118 ldc((ulong)H, Ri); 2119 for(i = 0; i < t->np; i++) { 2120 c = t->map[i]; 2121 j = i<<5; 2122 for(m = 0x80; m != 0; m >>= 1) { 2123 if(c & m) 2124 mem(Ostw, j, Ro1, Ri); 2125 j += sizeof(WORD*); 2126 } 2127 } 2128 LRET(); 2129 } 2130 2131 void 2132 typecom(Type *t) 2133 { 2134 int n; 2135 ulong *tmp, *start; 2136 2137 if(t == nil || t->initialize != 0) 2138 return; 2139 2140 tmp = mallocz(4096*sizeof(ulong), 0); 2141 if(tmp == nil) 2142 error(exNomem); 2143 2144 code = tmp; 2145 comi(t); 2146 n = code - tmp; 2147 code = tmp; 2148 comd(t); 2149 n += code - tmp; 2150 free(tmp); 2151 2152 n *= sizeof(*code); 2153 code = mallocz(n, 0); 2154 if(code == nil) 2155 return; 2156 2157 start = code; 2158 t->initialize = code; 2159 comi(t); 2160 t->destroy = code; 2161 comd(t); 2162 2163 segflush(start, n); 2164 2165 if(cflag > 3) 2166 print("typ= %.8lux %4d i %.8lux d %.8lux asm=%d\n", 2167 (ulong)t, t->size, (ulong)t->initialize, (ulong)t->destroy, n); 2168 } 2169 2170 static void 2171 patchex(Module *m, ulong *p) 2172 { 2173 Handler *h; 2174 Except *e; 2175 2176 if((h = m->htab) == nil) 2177 return; 2178 for( ; h->etab != nil; h++){ 2179 h->pc1 = p[h->pc1]; 2180 h->pc2 = p[h->pc2]; 2181 for(e = h->etab; e->s != nil; e++) 2182 e->pc = p[e->pc]; 2183 if(e->pc != -1) 2184 e->pc = p[e->pc]; 2185 } 2186 } 2187 2188 int 2189 compile(Module *m, int size, Modlink *ml) 2190 { 2191 Link *l; 2192 Modl *e; 2193 int i, n; 2194 ulong *s, *tmp; 2195 2196 base = nil; 2197 patch = mallocz(size*sizeof(*patch), ROMABLE); 2198 tinit = malloc(m->ntype*sizeof(*tinit)); 2199 tmp = malloc(4096*sizeof(ulong)); 2200 if(tinit == nil || patch == nil || tmp == nil) 2201 goto bad; 2202 2203 preamble(); 2204 2205 mod = m; 2206 n = 0; 2207 pass = 0; 2208 nlit = 0; 2209 2210 for(i = 0; i < size; i++) { 2211 code = tmp; 2212 comp(&m->prog[i]); 2213 if(code >= &tmp[4096]) { 2214 print("%3d %D\n", i, &m->prog[i]); 2215 urk("tmp ovflo"); 2216 } 2217 patch[i] = n; 2218 n += code - tmp; 2219 } 2220 2221 for(i=0; macinit[i].f; i++) { 2222 code = tmp; 2223 (*macinit[i].f)(); 2224 macro[macinit[i].o] = n; 2225 n += code - tmp; 2226 } 2227 2228 base = mallocz((n+nlit)*sizeof(*base), 0); 2229 if(base == nil) 2230 goto bad; 2231 2232 if(cflag > 3) 2233 print("dis=%5d %5d ppc=%5d asm=%.8lux lit=%d: %s\n", 2234 size, size*sizeof(Inst), n, (ulong)base, nlit, m->name); 2235 2236 pass++; 2237 nlit = 0; 2238 litpool = base+n; 2239 code = base; 2240 n = 0; 2241 2242 for(i = 0; i < size; i++) { 2243 s = code; 2244 comp(&m->prog[i]); 2245 if(patch[i] != n) { 2246 print("%3d %D\n", i, &m->prog[i]); 2247 urk("phase error"); 2248 } 2249 n += code - s; 2250 if(cflag > 3) { 2251 print("%3d %D\n", i, &m->prog[i]); 2252 while(s < code) 2253 s += das(s); 2254 }/**/ 2255 } 2256 2257 for(i=0; macinit[i].f; i++) { 2258 if(macro[macinit[i].o] != n) { 2259 print("macinit %d\n", macinit[i].o); 2260 urk("phase error"); 2261 } 2262 s = code; 2263 (*macinit[i].f)(); 2264 n += code - s; 2265 if(cflag > 3) { 2266 print("macinit %d\n", macinit[i].o); 2267 while(s < code) 2268 s += das(s); 2269 }/**/ 2270 } 2271 2272 for(l = m->ext; l->name; l++) { 2273 l->u.pc = (Inst*)(base+patch[l->u.pc-m->prog]); 2274 typecom(l->frame); 2275 } 2276 if(ml != nil) { 2277 e = &ml->links[0]; 2278 for(i = 0; i < ml->nlinks; i++) { 2279 e->u.pc = (Inst*)(base+patch[e->u.pc-m->prog]); 2280 typecom(e->frame); 2281 e++; 2282 } 2283 } 2284 for(i = 0; i < m->ntype; i++) { 2285 if(tinit[i] != 0) 2286 typecom(m->type[i]); 2287 } 2288 patchex(m, patch); 2289 m->entry = (Inst*)(base+patch[mod->entry-mod->prog]); 2290 free(patch); 2291 free(tinit); 2292 free(tmp); 2293 free(m->prog); 2294 m->prog = (Inst*)base; 2295 m->compiled = 1; 2296 segflush(base, n*sizeof(*base)); 2297 return 1; 2298 bad: 2299 free(patch); 2300 free(tinit); 2301 free(base); 2302 free(tmp); 2303 return 0; 2304 } 2305