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