1 #include "lib9.h" 2 #include "isa.h" 3 #include "interp.h" 4 #include "raise.h" 5 6 enum 7 { 8 R8 = 8, /* SUN calls these %o0 - %o7 */ 9 R9 = 9, 10 R10 = 10, 11 R11 = 11, 12 R12 = 12, 13 R13 = 13, 14 R14 = 14, /* SUN %sp */ 15 R15 = 15, /* R15/%o7 is the default link register */ 16 17 R16 = 16, /* SUN calls these %l0 - %l7 */ 18 R17 = 17, 19 R18 = 18, 20 R19 = 19, 21 R20 = 20, 22 R21 = 21, 23 R22 = 22, 24 R23 = 23, 25 RLINK = 15, 26 27 RZ = 0, /* Always 0 */ 28 RFP = R23, /* Frame Pointer */ 29 RMP = R22, /* Module Pointer */ 30 RTA = R21, /* Intermediate address for double indirect */ 31 RREG = R20, /* Pointer to REG */ 32 RA3 = R19, /* gpr 3 */ 33 RA2 = R18, /* gpr 2 2+3 = L */ 34 RA1 = R17, /* gpr 1 */ 35 RA0 = R16, /* gpr 0 0+1 = L */ 36 37 RCON = R8, /* Constant builder */ 38 39 FA2 = 2, /* Floating */ 40 FA3 = 3, 41 FA4 = 4, 42 FA5 = 5, 43 44 Olea = (1<<20), /* Pseudo op */ 45 Owry = 48, 46 Omul = 11, 47 Oumul = 10, 48 Osdiv = 15, 49 Osll = 37, 50 Osra = 39, 51 Osrl = 38, 52 Osethi = 4, 53 Oadd = 0, 54 Oaddcc = 16, 55 Oaddx = 8, 56 Osub = 4, 57 Osubcc = 20, 58 Osubx = 12, 59 Oor = 2, 60 Oand = 1, 61 Oxor = 3, 62 Oldw = 0, 63 Oldsh = 10, 64 Ostw = 4, 65 Osth = 6, 66 Ojmpl = 56, 67 Ocall = 1, 68 Ocmp = 20, /* subcc */ 69 Oldbu = 1, 70 Ostb = 5, 71 Oba = 8, 72 Obn = 0, 73 Obne = 9, 74 Obe = 1, 75 Obg = 10, 76 Oble = 2, 77 Obge = 11, 78 Obl = 3, 79 Obgu = 12, 80 Obleu = 4, 81 Obcc = 13, 82 Obcs = 5, 83 Obpos = 14, 84 Obneg = 6, 85 Obvc = 15, 86 Obvs = 7, 87 OfaddD = 66, 88 OfsubD = 70, 89 OfdivD = 78, 90 OfmulD = 74, 91 Oldf = 32, 92 Ostf = 36, 93 OfDtoQ = 206, 94 OfnegS = 5, 95 OfcmpD = 82, 96 Ofba = 8, 97 Ofbe = 9, 98 Ofbg = 6, 99 Ofbge = 11, 100 Ofbl = 4, 101 Ofble = 13, 102 Ofbne = 1, 103 OfWtoD = 200, 104 OfDtoW = 210, 105 Osave = 60, 106 Orestore= 61, 107 108 SRCOP = (1<<0), 109 DSTOP = (1<<1), 110 WRTPC = (1<<2), 111 TCHECK = (1<<3), 112 NEWPC = (1<<4), 113 DBRAN = (1<<5), 114 THREOP = (1<<6), 115 116 ANDAND = 1, 117 OROR = 2, 118 EQAND = 3, 119 120 MacFRP = 0, 121 MacRET = 1, 122 MacCASE = 2, 123 MacCOLR = 3, 124 MacMCAL = 4, 125 MacFRAM = 5, 126 MacMFRA = 6, 127 NMACRO 128 }; 129 130 #define OP(n) (n<<30) 131 #define I13(i) ((i)&0x1fff) 132 #define D22(i) ((i)&0x3fffff) 133 #define PC30(pc) (((ulong)(pc) - (ulong)code)>>2) 134 135 #define CALL(addr) *code=OP(1)|PC30(addr); code++ 136 #define FM2I(op2, i, rd) *code=OP(0)|(rd<<25)|(op2<<22)|D22(i); code++ 137 #define BRA(cond, disp) *code=OP(0)|(cond<<25)|(2<<22)|D22((disp)); code++ 138 #define BRAF(cond, disp) *code=OP(0)|(cond<<25)|(6<<22)|D22((disp)); code++ 139 #define BRADIS(r, o) BRA(r, ((ulong)(base+patch[o])-(ulong)code)>>2) 140 #define BRAFDIS(r, o) BRAF(r, ((ulong)(base+patch[o])-(ulong)code)>>2) 141 #define BRAMAC(r, o) BRA(r, ((ulong)(base+macro[o])-(ulong)code)>>2); 142 #define FM3I(op, op3, i, rs1, rd) *code++=OP(op)|(rd<<25)|(op3<<19)|(rs1<<14)|\ 143 (1<<13)|I13(i) 144 #define FM3(op, op3, rs2, rs1, rd) *code++=OP(op)|(rd<<25)|(op3<<19)|(rs1<<14)|rs2 145 #define FMF1(opf, rs2, rs1, rd) *code++=OP(2)|(rd<<25)|(52<<19)|(rs1<<14)|(opf<<5)|rs2 146 #define FMF2(opf, rs2, rs1, rd) *code++=OP(2)|(rd<<25)|(53<<19)|(rs1<<14)|(opf<<5)|rs2 147 #define NOOP *code++=(4<<22) 148 #define RETURN FM3I(2, Ojmpl, 8, RLINK, RZ); 149 #define MOV(s, d) FM3(2, Oor, s, RZ, d) 150 151 #define RELPC(pc) (ulong)(base+pc) 152 #define PATCH(ptr) *ptr |= (code-ptr) & 0x3fffff 153 154 static ulong* code; 155 static ulong* base; 156 static ulong* patch; 157 static int pass; 158 static int puntpc = 1; 159 static Module* mod; 160 static uchar* tinit; 161 static ulong* litpool; 162 static int nlit; 163 static void macfrp(void); 164 static void macret(void); 165 static void maccase(void); 166 static void maccolr(void); 167 static void macmcal(void); 168 static void macfram(void); 169 static void macmfra(void); 170 static ulong macro[NMACRO]; 171 void (*comvec)(void); 172 extern void das(ulong*, int); 173 174 #define T(r) *((void**)(R.r)) 175 176 struct 177 { 178 int idx; 179 void (*gen)(void); 180 char* name; 181 } mactab[] = 182 { 183 MacFRP, macfrp, "FRP", /* decrement and free pointer */ 184 MacRET, macret, "RET", /* return instruction */ 185 MacCASE, maccase, "CASE", /* case instruction */ 186 MacCOLR, maccolr, "COLR", /* increment and color pointer */ 187 MacMCAL, macmcal, "MCAL", /* mcall bottom half */ 188 MacFRAM, macfram, "FRAM", /* frame instruction */ 189 MacMFRA, macmfra, "MFRA", /* punt mframe because t->initialize==0 */ 190 }; 191 192 static void 193 rdestroy(void) 194 { 195 destroy(R.s); 196 } 197 198 static void 199 rmcall(void) 200 { 201 Prog *p; 202 Frame *f; 203 204 f = (Frame*)R.FP; 205 if(f == H) 206 error(exModule); 207 208 f->mr = nil; 209 ((void(*)(Frame*))R.dt)(f); 210 R.SP = (uchar*)f; 211 R.FP = f->fp; 212 if(f->t == nil) 213 unextend(f); 214 else 215 freeptrs(f, f->t); 216 p = currun(); 217 if(p->kill != nil) 218 error(p->kill); 219 } 220 221 static void 222 rmfram(void) 223 { 224 Type *t; 225 Frame *f; 226 uchar *nsp; 227 228 if(R.d == H) 229 error(exModule); 230 t = (Type*)R.s; 231 if(t == H) 232 error(exModule); 233 234 nsp = R.SP + t->size; 235 if(nsp >= R.TS) { 236 R.s = t; 237 extend(); 238 T(d) = R.s; 239 return; 240 } 241 f = (Frame*)R.SP; 242 R.SP = nsp; 243 f->t = t; 244 f->mr = nil; 245 initmem(t, f); 246 T(d) = f; 247 } 248 249 static void 250 urk(void) 251 { 252 error(exCompile); 253 } 254 255 static int 256 bc(long c) 257 { 258 c &= ~0xfffL; 259 if (c == 0 || c == ~0xfffL) 260 return 1; 261 262 return 0; 263 } 264 265 static void 266 con(ulong o, int r, int opt) 267 { 268 if(opt != 0) { 269 if(bc(o)) { 270 FM3I(2, Oadd, o & 0x1fff, RZ, r); 271 return; 272 } 273 if((o & 0x3ff) == 0) { 274 FM2I(Osethi, o>>10, r); 275 return; 276 } 277 } 278 FM2I(Osethi, o>>10, r); 279 FM3I(2, Oadd, o & 0x3ff, r, r); 280 } 281 282 static void 283 mem(int inst, ulong disp, int rm, int r) 284 { 285 int op; 286 287 op = 3; 288 if(inst == Olea) { 289 op = 2; 290 inst = Oadd; 291 } 292 if(bc(disp)) { 293 FM3I(op, inst, disp, rm, r); 294 return; 295 } 296 con(disp, RCON, 1); 297 FM3(op, inst, RCON, rm, r); 298 } 299 300 static void 301 opwld(Inst *i, int mi, int r) 302 { 303 int ir, rta; 304 305 switch(UXSRC(i->add)) { 306 default: 307 print("%D\n", i); 308 urk(); 309 case SRC(AFP): 310 mem(mi, i->s.ind, RFP, r); 311 return; 312 case SRC(AMP): 313 mem(mi, i->s.ind, RMP, r); 314 return; 315 case SRC(AIMM): 316 con(i->s.imm, r, 1); 317 if(mi == Olea) { 318 mem(Ostw, O(REG, st), RREG, r); 319 con((ulong)&R.st, r, 1); 320 } 321 return; 322 case SRC(AIND|AFP): 323 ir = RFP; 324 break; 325 case SRC(AIND|AMP): 326 ir = RMP; 327 break; 328 } 329 rta = RTA; 330 if(mi == Olea) 331 rta = r; 332 mem(Oldw, i->s.i.f, ir, rta); 333 mem(mi, i->s.i.s, rta, r); 334 } 335 336 static void 337 opwst(Inst *i, int mi, int r) 338 { 339 int ir, rta; 340 341 switch(UXDST(i->add)) { 342 default: 343 print("%D\n", i); 344 urk(); 345 case DST(AIMM): 346 con(i->d.imm, r, 1); 347 return; 348 case DST(AFP): 349 mem(mi, i->d.ind, RFP, r); 350 return; 351 case DST(AMP): 352 mem(mi, i->d.ind, RMP, r); 353 return; 354 case DST(AIND|AFP): 355 ir = RFP; 356 break; 357 case DST(AIND|AMP): 358 ir = RMP; 359 break; 360 } 361 rta = RTA; 362 if(mi == Olea) 363 rta = r; 364 mem(Oldw, i->d.i.f, ir, rta); 365 mem(mi, i->d.i.s, rta, r); 366 } 367 368 static void 369 opfl(Adr *a, int am, int mi, int r) 370 { 371 int ir; 372 373 switch(am) { 374 default: 375 urk(); 376 case AFP: 377 mem(mi, a->ind, RFP, r); 378 mem(mi, a->ind+4, RFP, r+1); 379 return; 380 case AMP: 381 mem(mi, a->ind, RMP, r); 382 mem(mi, a->ind+4, RMP, r+1); 383 return; 384 case AIND|AFP: 385 ir = RFP; 386 break; 387 case AIND|AMP: 388 ir = RMP; 389 break; 390 } 391 mem(Oldw, a->i.f, ir, RTA); 392 mem(mi, a->i.s, RTA, r); 393 mem(mi, a->i.s+4, RTA, r+1); 394 } 395 396 static void 397 opflld(Inst *i, int mi, int r) 398 { 399 opfl(&i->s, USRC(i->add), mi, r); 400 } 401 402 static void 403 opflst(Inst *i, int mi, int r) 404 { 405 opfl(&i->d, UDST(i->add), mi, r); 406 } 407 408 static void 409 literal(ulong imm, int roff) 410 { 411 nlit++; 412 413 con((ulong)litpool, RTA, 0); 414 mem(Ostw, roff, RREG, RTA); 415 416 if(pass == 0) 417 return; 418 419 *litpool = imm; 420 litpool++; 421 } 422 423 static void 424 punt(Inst *i, int m, void (*fn)(void)) 425 { 426 ulong pc; 427 428 if(m & SRCOP) { 429 if(UXSRC(i->add) == SRC(AIMM)) 430 literal(i->s.imm, O(REG, s)); 431 else { 432 opwld(i, Olea, RA0); 433 mem(Ostw, O(REG, s), RREG, RA0); 434 } 435 } 436 437 if(m & DSTOP) { 438 opwst(i, Olea, RA0); 439 mem(Ostw, O(REG, d), RREG, RA0); 440 } 441 if(m & WRTPC) { 442 con(RELPC(patch[i-mod->prog+1]), RA0, 0); 443 mem(Ostw, O(REG, PC), RREG, RA0); 444 } 445 if(m & DBRAN) { 446 pc = patch[(Inst*)i->d.imm-mod->prog]; 447 literal(RELPC(pc), O(REG, d)); 448 } 449 450 switch(i->add&ARM) { 451 case AXNON: 452 if(m & THREOP) { 453 mem(Oldw, O(REG, d), RREG, RA0); 454 mem(Ostw, O(REG, m), RREG, RA0); 455 } 456 break; 457 case AXIMM: 458 literal((short)i->reg, O(REG, m)); 459 break; 460 case AXINF: 461 mem(Olea, i->reg, RFP, RA0); 462 mem(Ostw, O(REG, m), RREG, RA0); 463 break; 464 case AXINM: 465 mem(Olea, i->reg, RMP, RA0); 466 mem(Ostw, O(REG, m), RREG, RA0); 467 break; 468 } 469 470 CALL(fn); 471 mem(Ostw, O(REG, FP), RREG, RFP); 472 473 con((ulong)&R, RREG, 1); 474 if(m & TCHECK) { 475 mem(Oldw, O(REG, t), RREG, RA0); 476 FM3I(2, Ocmp, 0, RA0, RZ); 477 BRA(Obe, 5); 478 NOOP; 479 mem(Oldw, O(REG, xpc), RREG, RLINK); 480 RETURN; 481 NOOP; 482 } 483 484 mem(Oldw, O(REG, FP), RREG, RFP); 485 mem(Oldw, O(REG, MP), RREG, RMP); 486 487 if(m & NEWPC) { 488 mem(Oldw, O(REG, PC), RREG, RA0); 489 FM3I(2, Ojmpl, 0, RA0, RZ); 490 NOOP; 491 } 492 } 493 494 static void 495 midfl(Inst *i, int mi, int r) 496 { 497 int ir; 498 499 switch(i->add&ARM) { 500 default: 501 opflst(i, mi, r); 502 return; 503 case AXIMM: 504 con((short)i->reg, r, 1); 505 return; 506 case AXINF: 507 ir = RFP; 508 break; 509 case AXINM: 510 ir = RMP; 511 break; 512 } 513 mem(mi, i->reg, ir, r); 514 mem(mi, i->reg+4, ir, r+1); 515 } 516 517 static void 518 mid(Inst *i, int mi, int r) 519 { 520 int ir; 521 522 switch(i->add&ARM) { 523 default: 524 opwst(i, mi, r); 525 return; 526 case AXIMM: 527 con((short)i->reg, r, 1); 528 return; 529 case AXINF: 530 ir = RFP; 531 break; 532 case AXINM: 533 ir = RMP; 534 break; 535 } 536 mem(mi, i->reg, ir, r); 537 } 538 539 static void 540 cbral(Inst *i, int jmsw, int jlsw, int mode) 541 { 542 ulong dst, *label; 543 544 opwld(i, Olea, RA1); 545 mid(i, Olea, RA3); 546 mem(Oldw, 0, RA1, RA2); 547 mem(Oldw, 0, RA3, RA0); 548 FM3(2, Ocmp, RA0, RA2, RZ); 549 label = nil; 550 dst = i->d.ins-mod->prog; 551 switch(mode) { 552 case ANDAND: 553 label = code; 554 BRA(jmsw, 0); 555 break; 556 case OROR: 557 BRADIS(jmsw, dst); 558 break; 559 case EQAND: 560 BRADIS(jmsw, dst); 561 NOOP; 562 label = code; 563 BRA(Obne, 0); 564 break; 565 } 566 NOOP; 567 mem(Oldw, 4, RA3, RA0); 568 mem(Oldw, 4, RA1, RA2); 569 FM3(2, Ocmp, RA0, RA2, RZ); 570 BRADIS(jlsw, dst); 571 if(label != nil) 572 PATCH(label); 573 } 574 575 static void 576 comcase(Inst *i, int w) 577 { 578 int l; 579 WORD *t, *e; 580 581 if(w != 0) { 582 opwld(i, Oldw, RA0); // v 583 opwst(i, Olea, RCON); // table 584 BRAMAC(Oba, MacCASE); 585 NOOP; 586 } 587 588 t = (WORD*)(mod->origmp+i->d.ind+4); 589 l = t[-1]; 590 591 /* have to take care not to relocate the same table twice - 592 * the limbo compiler can duplicate a case instruction 593 * during its folding phase 594 */ 595 596 if(pass == 0) { 597 if(l >= 0) 598 t[-1] = -l-1; /* Mark it not done */ 599 return; 600 } 601 if(l >= 0) /* Check pass 2 done */ 602 return; 603 t[-1] = -l-1; /* Set real count */ 604 e = t + t[-1]*3; 605 while(t < e) { 606 t[2] = RELPC(patch[t[2]]); 607 t += 3; 608 } 609 t[0] = RELPC(patch[t[0]]); 610 } 611 612 static void 613 comcasel(Inst *i) 614 { 615 int l; 616 WORD *t, *e; 617 618 t = (WORD*)(mod->origmp+i->d.ind+8); 619 l = t[-2]; 620 if(pass == 0) { 621 if(l >= 0) 622 t[-2] = -l-1; /* Mark it not done */ 623 return; 624 } 625 if(l >= 0) /* Check pass 2 done */ 626 return; 627 t[-2] = -l-1; /* Set real count */ 628 e = t + t[-2]*6; 629 while(t < e) { 630 t[4] = RELPC(patch[t[4]]); 631 t += 6; 632 } 633 t[0] = RELPC(patch[t[0]]); 634 } 635 636 static void 637 commframe(Inst *i) 638 { 639 int o; 640 ulong *punt, *mlnil; 641 642 opwld(i, Oldw, RA0); 643 FM3I(2, Ocmp, -1, RA0, RZ); 644 mlnil = code; 645 BRA(Obe, 0); 646 NOOP; 647 648 if((i->add&ARM) == AXIMM) { 649 o = OA(Modlink, links)+i->reg*sizeof(Modl)+O(Modl, frame); 650 mem(Oldw, o, RA0, RA3); 651 } else { 652 mid(i, Oldw, RA1); 653 FM3I(2, Osll, 3, RA1, RA1); // assumes sizeof(Modl) == 8 654 FM3(2, Oadd, RA0, RA1, RA1); 655 o = OA(Modlink, links)+O(Modl, frame); 656 mem(Oldw, o, RA1, RA3); 657 } 658 mem(Oldw, O(Type, initialize), RA3, RA1); 659 FM3I(2, Ocmp, 0, RA1, RZ); 660 punt = code; 661 BRA(Obne, 0); 662 NOOP; 663 664 opwst(i, Olea, RA0); 665 666 /* Type in RA3, destination in RA0 */ 667 PATCH(mlnil); 668 con(RELPC(patch[i-mod->prog+1])-8, RLINK, 0); 669 BRAMAC(Oba, MacMFRA); 670 NOOP; 671 672 /* Type in RA3 */ 673 PATCH(punt); 674 CALL(base+macro[MacFRAM]); 675 NOOP; 676 opwst(i, Ostw, RA2); 677 } 678 679 static void 680 commcall(Inst *i) 681 { 682 opwld(i, Oldw, RA2); 683 con(RELPC(patch[i-mod->prog+1]), RA0, 0); 684 mem(Ostw, O(Frame, lr), RA2, RA0); 685 mem(Ostw, O(Frame, fp), RA2, RFP); 686 mem(Oldw, O(REG, M), RREG, RA3); 687 mem(Ostw, O(Frame, mr), RA2, RA3); 688 opwst(i, Oldw, RA3); 689 if((i->add&ARM) == AXIMM) { 690 CALL(base+macro[MacMCAL]); 691 mem(Oldw, OA(Modlink, links)+i->reg*sizeof(Modl)+O(Modl, u.pc), RA3, RA0); 692 } else { 693 mid(i, Oldw, RA1); 694 FM3I(2, Osll, 3, RA1, RA1); // assumes sizeof(Modl) == 8 695 FM3(2, Oadd, RA1, RA3, RA0); 696 CALL(base+macro[MacMCAL]); 697 mem(Oldw, OA(Modlink, links)+O(Modl, u.pc), RA0, RA0); 698 } 699 } 700 701 static void 702 larith(Inst *i, int op, int opc) 703 { 704 opflld(i, Oldw, RA0); 705 midfl(i, Oldw, RA2); 706 FM3(2, op, RA1, RA3, RA1); 707 FM3(2, opc, RA0, RA2, RA0); 708 opflst(i, Ostw, RA0); 709 } 710 711 static void 712 movloop(Inst *i, int ld, int st) 713 { 714 int s; 715 716 s = 1; 717 if(ld == Oldw) 718 s = 4; 719 opwld(i, Olea, RA1); 720 opwst(i, Olea, RA2); 721 mem(ld, 0, RA1, RA0); 722 mem(st, 0, RA2, RA0); 723 FM3I(2, Oadd, s, RA2, RA2); 724 FM3I(2, Oaddcc, -1, RA3, RA3); 725 BRA(Obne, -4); 726 FM3I(2, Oadd, s, RA1, RA1); 727 } 728 729 static 730 void 731 compdbg(void) 732 { 733 print("%s:%d@%.8ux\n", R.M->m->name, R.t, R.st); 734 } 735 736 static void 737 shll(Inst *i) 738 { 739 ulong *lab0, *lab1, *lab2; 740 741 opwld(i, Oldw, RA2); 742 midfl(i, Oldw, RA0); 743 FM3I(2, Ocmp, RZ, RA2, RZ); 744 lab0 = code; 745 BRA(Obe, 0); 746 FM3I(2, Ocmp, 32, RA2, RZ); 747 lab1 = code; 748 BRA(Obl, 0); 749 NOOP; 750 FM3I(2, Osub, 32, RA2, RA2); 751 FM3(2, Osll, RA2, RA1, RA0); 752 lab2 = code; 753 BRA(Oba, 0); 754 MOV(RZ, RA1); 755 756 PATCH(lab1); 757 FM3(2, Osll, RA2, RA0, RA0); 758 con(32, RA3, 1); 759 FM3(2, Osub, RA2, RA3, RA3); 760 FM3(2, Osrl, RA3, RA1, RA3); 761 FM3(2, Oor, RA0, RA3, RA0); 762 FM3(2, Osll, RA2, RA1, RA1); 763 764 PATCH(lab0); 765 PATCH(lab2); 766 opflst(i, Ostw, RA0); 767 } 768 769 static void 770 comp(Inst *i) 771 { 772 int r; 773 WORD *t, *e; 774 char buf[64]; 775 776 if(0) { 777 Inst xx; 778 xx.add = AXIMM|SRC(AIMM); 779 xx.s.imm = (ulong)code; 780 xx.reg = i-mod->prog; 781 puntpc = 0; 782 punt(&xx, SRCOP, compdbg); 783 puntpc = 1; 784 } 785 786 switch(i->op) { 787 default: 788 snprint(buf, sizeof buf, "%s compile, no '%D'", mod->name, i); 789 error(buf); 790 break; 791 case IMCALL: 792 if((i->add&ARM) == AXIMM) 793 commcall(i); 794 else 795 punt(i, SRCOP|DSTOP|THREOP|WRTPC|NEWPC, optab[i->op]); 796 break; 797 case ISEND: 798 case IRECV: 799 case IALT: 800 punt(i, SRCOP|DSTOP|TCHECK|WRTPC, optab[i->op]); 801 break; 802 case ISPAWN: 803 punt(i, SRCOP|DBRAN, optab[i->op]); 804 break; 805 case IBNEC: 806 case IBEQC: 807 case IBLTC: 808 case IBLEC: 809 case IBGTC: 810 case IBGEC: 811 punt(i, SRCOP|DBRAN|NEWPC|WRTPC, optab[i->op]); 812 break; 813 case ICASEC: 814 comcase(i, 0); 815 punt(i, SRCOP|DSTOP|NEWPC, optab[i->op]); 816 break; 817 case ICASEL: 818 comcasel(i); 819 punt(i, SRCOP|DSTOP|NEWPC, optab[i->op]); 820 break; 821 case IADDC: 822 case IMULL: 823 case IDIVL: 824 case IMODL: 825 case IMODW: 826 case IMODB: 827 case IMNEWZ: 828 punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); 829 break; 830 case ILOAD: 831 case INEWA: 832 case INEWAZ: 833 case INEW: 834 case INEWZ: 835 case ISLICEA: 836 case ISLICELA: 837 case ICONSB: 838 case ICONSW: 839 case ICONSL: 840 case ICONSF: 841 case ICONSM: 842 case ICONSMP: 843 case ICONSP: 844 case IMOVMP: 845 case IHEADMP: 846 case IHEADM: 847 case IHEADB: 848 case IHEADW: 849 case IHEADL: 850 case IHEADF: 851 case IINDC: 852 case ILENC: 853 case IINSC: 854 case ICVTAC: 855 case ICVTCW: 856 case ICVTWC: 857 case ICVTLC: 858 case ICVTCL: 859 case ICVTFC: 860 case ICVTCF: 861 case ICVTRF: 862 case ICVTFR: 863 case IMSPAWN: 864 case ICVTCA: 865 case ISLICEC: 866 case INBALT: 867 punt(i, SRCOP|DSTOP, optab[i->op]); 868 break; 869 case INEWCM: 870 case INEWCMP: 871 punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); 872 break; 873 case IMFRAME: 874 if((i->add&ARM) == AXIMM) 875 commframe(i); 876 else 877 punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); 878 break; 879 case ICASE: 880 comcase(i, 1); 881 break; 882 case IGOTO: 883 opwld(i, Oldw, RA1); 884 opwst(i, Olea, RA0); 885 FM3I(2, Osll, 2, RA1, RA1); 886 FM3(3, Oldw, RA1, RA0, RA0); 887 FM3I(2, Ojmpl, 0, RA0, RZ); 888 NOOP; 889 890 if(pass == 0) 891 break; 892 893 t = (WORD*)(mod->origmp+i->d.ind); 894 e = t + t[-1]; 895 t[-1] = 0; 896 while(t < e) { 897 t[0] = RELPC(patch[t[0]]); 898 t++; 899 } 900 break; 901 case IMOVL: 902 movl: 903 opflld(i, Oldw, RA0); 904 opflst(i, Ostw, RA0); 905 break; 906 case IMOVM: 907 if((i->add&ARM) == AXIMM) { 908 if(i->reg == 8) 909 goto movl; 910 if((i->reg&3) == 0) { 911 con(i->reg>>2, RA3, 1); 912 movloop(i, Oldw, Ostw); 913 break; 914 } 915 } 916 mid(i, Oldw, RA3); 917 movloop(i, Oldbu, Ostb); 918 break; 919 case IFRAME: 920 if(UXSRC(i->add) != SRC(AIMM)) { 921 punt(i, SRCOP|DSTOP, optab[i->op]); 922 break; 923 } 924 tinit[i->s.imm] = 1; 925 con((ulong)mod->type[i->s.imm], RA3, 1); 926 CALL(base+macro[MacFRAM]); 927 NOOP; 928 opwst(i, Ostw, RA2); 929 break; 930 case INEWCB: 931 case INEWCW: 932 case INEWCF: 933 case INEWCP: 934 case INEWCL: 935 punt(i, DSTOP|THREOP, optab[i->op]); 936 break; 937 case IEXIT: 938 punt(i, 0, optab[i->op]); 939 break; 940 case ICVTBW: 941 opwld(i, Oldbu, RA0); 942 opwst(i, Ostw, RA0); 943 break; 944 case ICVTWB: 945 opwld(i, Oldw, RA0); 946 opwst(i, Ostb, RA0); 947 break; 948 case ILEA: 949 opwld(i, Olea, RA0); 950 opwst(i, Ostw, RA0); 951 break; 952 case IMOVW: 953 opwld(i, Oldw, RA0); 954 opwst(i, Ostw, RA0); 955 break; 956 case IMOVB: 957 opwld(i, Oldbu, RA0); 958 opwst(i, Ostb, RA0); 959 break; 960 case ICVTSW: 961 opwld(i, Oldsh, RA0); 962 opwst(i, Ostw, RA0); 963 break; 964 case ICVTWS: 965 opwld(i, Oldw, RA0); 966 opwst(i, Osth, RA0); 967 break; 968 case ITAIL: 969 opwld(i, Oldw, RA0); 970 mem(Oldw, O(List, tail), RA0, RA1); 971 goto movp; 972 case IMOVP: 973 case IHEADP: 974 opwld(i, Oldw, RA1); 975 if(i->op == IHEADP) 976 mem(Oldw, OA(List, data), RA1, RA1); 977 movp: 978 FM3I(2, Ocmp, (ulong)H, RA1, RZ); 979 BRA(Obe, 5); 980 con((ulong)&mutator, RA2, 1); 981 CALL(base+macro[MacCOLR]); 982 mem(Oldw, O(Heap, ref)-sizeof(Heap), RA1, RA0); 983 opwst(i, Oldw, RA0); 984 opwst(i, Ostw, RA1); 985 CALL(base+macro[MacFRP]); 986 NOOP; 987 break; 988 case ILENA: 989 opwld(i, Oldw, RA1); 990 FM3I(2, Ocmp, (ulong)H, RA1, RZ); 991 BRA(Obe, 3); 992 con(0, RA0, 1); 993 mem(Oldw, O(Array, len), RA1, RA0); 994 opwst(i, Ostw, RA0); 995 break; 996 case ILENL: 997 con(0, RA0, 1); 998 opwld(i, Oldw, RA1); 999 FM3I(2, Ocmp, (ulong)H, RA1, RZ); 1000 BRA(Obe, 5); 1001 NOOP; 1002 mem(Oldw, O(List, tail), RA1, RA1); 1003 BRA(Oba, -4); 1004 FM3I(2, Oadd, 1, RA0, RA0); 1005 opwst(i, Ostw, RA0); 1006 break; 1007 case ICALL: 1008 opwld(i, Oldw, RA0); 1009 con(RELPC(patch[i-mod->prog+1]), RA1, 0); 1010 mem(Ostw, O(Frame, lr), RA0, RA1); 1011 mem(Ostw, O(Frame, fp), RA0, RFP); 1012 BRADIS(Oba, i->d.ins-mod->prog); 1013 MOV(RA0, RFP); 1014 break; 1015 case IJMP: 1016 BRADIS(Oba, i->d.ins-mod->prog); 1017 NOOP; 1018 break; 1019 case IBEQW: 1020 r = Obe; 1021 braw: 1022 opwld(i, Oldw, RA1); 1023 mid(i, Oldw, RA0); 1024 FM3(2, Ocmp, RA0, RA1, RZ); 1025 BRADIS(r, i->d.ins-mod->prog); 1026 NOOP; 1027 break; 1028 case IBNEW: 1029 r = Obne; 1030 goto braw; 1031 case IBLTW: 1032 r = Obl; 1033 goto braw; 1034 case IBLEW: 1035 r = Oble; 1036 goto braw; 1037 case IBGTW: 1038 r = Obg; 1039 goto braw; 1040 case IBGEW: 1041 r = Obge; 1042 goto braw; 1043 case IBEQB: 1044 r = Obe; 1045 brab: 1046 opwld(i, Oldbu, RA1); 1047 mid(i, Oldbu, RA0); 1048 FM3(2, Ocmp, RA0, RA1, RZ); 1049 BRADIS(r, i->d.ins-mod->prog); 1050 NOOP; 1051 break; 1052 case IBNEB: 1053 r = Obne; 1054 goto brab; 1055 case IBLTB: 1056 r = Obl; 1057 goto brab; 1058 case IBLEB: 1059 r = Oble; 1060 goto brab; 1061 case IBGTB: 1062 r = Obg; 1063 goto brab; 1064 case IBGEB: 1065 r = Obge; 1066 goto brab; 1067 case IBEQF: 1068 r = Ofbe; 1069 braf: 1070 opflld(i, Oldf, FA4); 1071 midfl(i, Oldf, FA2); 1072 FMF2(OfcmpD, FA2, FA4, 0); 1073 NOOP; 1074 BRAFDIS(r, i->d.ins-mod->prog); 1075 NOOP; 1076 break; 1077 case IBNEF: 1078 r = Ofbne; 1079 goto braf; 1080 case IBLTF: 1081 r = Ofbl; 1082 goto braf; 1083 case IBLEF: 1084 r = Ofble; 1085 goto braf; 1086 case IBGTF: 1087 r = Ofbg; 1088 goto braf; 1089 case IBGEF: 1090 r = Ofbge; 1091 goto braf; 1092 case IRET: 1093 BRAMAC(Oba, MacRET); 1094 mem(Oldw, O(Frame,t), RFP, RA1); 1095 break; 1096 case IORW: 1097 r = Oor; 1098 goto arithw; 1099 case IANDW: 1100 r = Oand; 1101 goto arithw; 1102 case IXORW: 1103 r = Oxor; 1104 goto arithw; 1105 case ISUBW: 1106 r = Osub; 1107 goto arithw; 1108 case ISHRW: 1109 r = Osra; 1110 goto arithw; 1111 case ISHLW: 1112 r = Osll; 1113 goto arithw; 1114 case ILSRW: 1115 r = Osrl; 1116 goto arithw; 1117 case IMULW: 1118 r = Omul; 1119 goto arithw; 1120 case IDIVW: 1121 r = Osdiv; 1122 goto arithw; 1123 case IADDW: 1124 r = Oadd; 1125 arithw: 1126 mid(i, Oldw, RA1); 1127 if(i->op == IDIVW) { 1128 FM3I(2, Osra, 31, RA1, RA0); 1129 FM3(2, Owry, RZ, RA0, 0); 1130 } 1131 if(UXSRC(i->add) == SRC(AIMM) && bc(i->s.imm)) 1132 FM3I(2, r, i->s.imm, RA1, RA0); 1133 else { 1134 opwld(i, Oldw, RA0); 1135 FM3(2, r, RA0, RA1, RA0); 1136 } 1137 opwst(i, Ostw, RA0); 1138 break; 1139 case IORB: 1140 r = Oor; 1141 goto arithb; 1142 case IANDB: 1143 r = Oand; 1144 goto arithb; 1145 case IXORB: 1146 r = Oxor; 1147 goto arithb; 1148 case ISUBB: 1149 r = Osub; 1150 goto arithb; 1151 case IMULB: 1152 r = Omul; 1153 goto arithb; 1154 case IDIVB: 1155 FM3(2, Owry, RZ, RZ, 0); 1156 r = Osdiv; 1157 goto arithb; 1158 case IADDB: 1159 r = Oadd; 1160 arithb: 1161 mid(i, Oldbu, RA1); 1162 opwld(i, Oldbu, RA0); 1163 FM3(2, r, RA0, RA1, RA0); 1164 opwst(i, Ostb, RA0); 1165 break; 1166 case ISHRB: 1167 r = Osra; 1168 goto shiftb; 1169 case ISHLB: 1170 r = Osll; 1171 shiftb: 1172 mid(i, Oldbu, RA1); 1173 if(UXSRC(i->add) == SRC(AIMM) && bc(i->s.imm)) 1174 FM3I(2, r, i->s.imm, RA1, RA0); 1175 else { 1176 opwld(i, Oldw, RA0); 1177 FM3(2, r, RA0, RA1, RA0); 1178 } 1179 opwst(i, Ostb, RA0); 1180 break; 1181 case IINDL: 1182 case IINDF: 1183 case IINDW: 1184 case IINDB: 1185 opwld(i, Oldw, RA0); /* a */ 1186 r = 0; 1187 switch(i->op) { 1188 case IINDL: 1189 case IINDF: 1190 r = 3; 1191 break; 1192 case IINDW: 1193 r = 2; 1194 break; 1195 } 1196 if(UXDST(i->add) == DST(AIMM) && bc(i->d.imm<<r)) { 1197 mem(Oldw, O(Array, data), RA0, RA0); 1198 FM3I(2, Oadd, (i->d.imm<<r), RA0, RA0); 1199 } 1200 else { 1201 opwst(i, Oldw, RA1); 1202 mem(Oldw, O(Array, data), RA0, RA0); 1203 if(r != 0) 1204 FM3I(2, Osll, r, RA1, RA1); 1205 FM3(2, Oadd, RA0, RA1, RA0); 1206 } 1207 r = RMP; 1208 if((i->add&ARM) == AXINF) 1209 r = RFP; 1210 mem(Ostw, i->reg, r, RA0); 1211 break; 1212 case IINDX: 1213 opwld(i, Oldw, RA0); /* a */ 1214 /* 1215 r = 0; 1216 if(UXDST(i->add) == DST(AIMM) && bc(i->d.imm<<r)) 1217 r = i->d.imm<<r; 1218 else 1219 */ 1220 opwst(i, Oldw, RA1); /* i */ 1221 mem(Oldw, O(Array, t), RA0, RA2); 1222 mem(Oldw, O(Array, data), RA0, RA0); 1223 mem(Oldw, O(Type, size), RA2, RA2); 1224 /* 1225 if(r != 0) 1226 FM3I(2, Oumul, r, RA2, RA1); 1227 else 1228 */ 1229 FM3(2, Oumul, RA1, RA2, RA1); 1230 FM3(2, Oadd, RA0, RA1, RA0); 1231 r = RMP; 1232 if((i->add&ARM) == AXINF) 1233 r = RFP; 1234 mem(Ostw, i->reg, r, RA0); 1235 break; 1236 case IADDL: 1237 larith(i, Oaddcc, Oaddx); 1238 break; 1239 case ISUBL: 1240 larith(i, Osubcc, Osubx); 1241 break; 1242 case IORL: 1243 larith(i, Oor, Oor); 1244 break; 1245 case IANDL: 1246 larith(i, Oand, Oand); 1247 break; 1248 case IXORL: 1249 larith(i, Oxor, Oxor); 1250 break; 1251 case ICVTWL: 1252 opwld(i, Oldw, RA1); 1253 FM3I(2, Osra, 31, RA1, RA0); 1254 opflst(i, Ostw, RA0); 1255 break; 1256 case ICVTLW: 1257 opwld(i, Olea, RA0); 1258 mem(Oldw, 4, RA0, RA0); 1259 opwst(i, Ostw, RA0); 1260 break; 1261 case IBEQL: 1262 cbral(i, Obne, Obe, ANDAND); 1263 break; 1264 case IBNEL: 1265 cbral(i, Obne, Obne, OROR); 1266 break; 1267 case IBLEL: 1268 cbral(i, Obl, Obleu, EQAND); 1269 break; 1270 case IBGTL: 1271 cbral(i, Obg, Obgu, EQAND); 1272 break; 1273 case IBLTL: 1274 cbral(i, Obl, Obcs, EQAND); 1275 break; 1276 case IBGEL: 1277 cbral(i, Obg, Obcc, EQAND); 1278 break; 1279 case IMOVF: 1280 opflld(i, Oldf, FA2); 1281 opflst(i, Ostf, FA2); 1282 break; 1283 case IDIVF: 1284 r = OfdivD; 1285 goto arithf; 1286 case IMULF: 1287 r = OfmulD; 1288 goto arithf; 1289 case ISUBF: 1290 r = OfsubD; 1291 goto arithf; 1292 case IADDF: 1293 r = OfaddD; 1294 arithf: 1295 opflld(i, Oldf, FA2); 1296 midfl(i, Oldf, FA4); 1297 FMF1(r, FA2, FA4, FA4); 1298 opflst(i, Ostf, FA4); 1299 break; 1300 case INEGF: 1301 opflld(i, Oldf, FA2); 1302 FMF1(OfnegS, FA2, 0, FA2); 1303 opflst(i, Ostf, FA2); 1304 break; 1305 case ICVTFL: 1306 // >= Sparc 8 1307 // opflld(i, Oldf, FA2); 1308 // FMF1(OfDtoQ, FA2, 0, FA2); 1309 // opflst(i, Ostf, FA2); 1310 punt(i, SRCOP|DSTOP, optab[i->op]); 1311 break; 1312 case ICVTLF: 1313 // >= Sparc 8 1314 // opflld(i, Oldf, FA2); 1315 // FMF1(OfQtoD, FA2, 0, FA2); 1316 // opflst(i, Ostf, FA2); 1317 punt(i, SRCOP|DSTOP, optab[i->op]); 1318 break; 1319 case ICVTWF: 1320 opwld(i, Oldf, FA2); 1321 FMF1(OfWtoD, FA2, 0, FA2); 1322 opflst(i, Ostf, FA2); 1323 break; 1324 case ICVTFW: 1325 opflld(i, Oldf, FA2); 1326 FMF1(OfDtoW, FA2, 0, FA2); 1327 opwst(i, Ostf, FA2); 1328 break; 1329 case ISHLL: 1330 shll(i); 1331 break; 1332 case ISHRL: 1333 case ILSRL: 1334 punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); 1335 break; 1336 case IRAISE: 1337 punt(i, SRCOP|WRTPC|NEWPC, optab[i->op]); 1338 break; 1339 case IMULX: 1340 case IDIVX: 1341 case ICVTXX: 1342 case IMULX0: 1343 case IDIVX0: 1344 case ICVTXX0: 1345 case IMULX1: 1346 case IDIVX1: 1347 case ICVTXX1: 1348 case ICVTFX: 1349 case ICVTXF: 1350 case IEXPW: 1351 case IEXPL: 1352 case IEXPF: 1353 punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); 1354 break; 1355 case ISELF: 1356 punt(i, DSTOP, optab[i->op]); 1357 break; 1358 } 1359 } 1360 1361 static void 1362 preamble(void) 1363 { 1364 ulong *start; 1365 1366 if(comvec) 1367 return; 1368 1369 comvec = malloc(10 * sizeof(*code)); 1370 if(comvec == nil) 1371 error(exNomem); 1372 code = (ulong*)comvec; 1373 start = code; 1374 1375 con((ulong)&R, RREG, 1); 1376 mem(Ostw, O(REG, xpc), RREG, RLINK); 1377 mem(Oldw, O(REG, PC), RREG, RA0); 1378 mem(Oldw, O(REG, FP), RREG, RFP); 1379 FM3I(2, Ojmpl, 0, RA0, RZ); 1380 mem(Oldw, O(REG, MP), RREG, RMP); 1381 1382 segflush(comvec, 10 * sizeof(*code)); 1383 1384 if(cflag > 4) { 1385 print("comvec:\n"); 1386 das(start, code-start); 1387 } 1388 } 1389 1390 static void 1391 maccase(void) 1392 { 1393 ulong *loop, *def, *lab1; 1394 1395 mem(Oldw, 0, RCON, RA3); // n = t[0] 1396 FM3I(2, Oadd, 4, RCON, RCON); 1397 MOV(RA3, RA1); 1398 FM3I(2, Osll, 1, RA1, RA1); 1399 FM3(2, Oadd, RA3, RA1, RA1); 1400 FM3I(2, Osll, 2, RA1, RA1); 1401 FM3(3, Oldw, RCON, RA1, RLINK); 1402 1403 loop = code; 1404 FM3(2, Ocmp, RZ, RA3, RZ); 1405 def = code; 1406 BRA(Oble, 0); 1407 NOOP; 1408 1409 MOV(RA3, RA2); // MOVL DX, CX n2 = n 1410 FM3I(2, Osra, 1, RA2, RA2); // SHR CX,1 n2 = n2>>1 1411 MOV(RA2, RA1); 1412 FM3I(2, Osll, 1, RA1, RA1); 1413 FM3(2, Oadd, RA2, RA1, RA1); 1414 FM3I(2, Osll, 2, RA1, RA1); 1415 1416 FM3(3, Oldw, RA1, RCON, RTA); // MOV (RA1+RCON), RTA 1417 FM3(2, Ocmp, RTA, RA0, RZ); 1418 lab1 = code; 1419 BRA(Obge, 0); 1420 NOOP; 1421 MOV(RA2, RA3); // n = n2 1422 BRA(Oba, loop-code); 1423 NOOP; 1424 1425 PATCH(lab1); 1426 FM3I(2, Oadd, 4, RA1, RTA); 1427 FM3(3, Oldw, RTA, RCON, RTA); // MOV (RA1+RCON), RTA 1428 FM3(2, Ocmp, RTA, RA0, RZ); 1429 lab1 = code; 1430 BRA(Obl, 0); 1431 NOOP; 1432 1433 FM3I(2, Oadd, 12, RA1, RTA); 1434 FM3(2, Oadd, RTA, RCON, RCON); 1435 FM3(2, Osub, RA2, RA3, RA3); // SUBL CX, DX n -= n2 1436 FM3I(2, Oadd, -1, RA3, RA3); // DECL DX n -= 1 1437 BRA(Oba, loop-code); 1438 NOOP; 1439 1440 PATCH(lab1); 1441 FM3I(2, Oadd, 8, RA1, RTA); 1442 FM3(3, Oldw, RTA, RCON, RLINK); 1443 1444 PATCH(def); 1445 FM3I(2, Ojmpl, 0, RLINK, RZ); 1446 NOOP; 1447 } 1448 1449 static void 1450 macfrp(void) 1451 { 1452 ulong *lab1, *lab2; 1453 1454 /* destroy the pointer in RA0 */ 1455 FM3I(2, Ocmp, -1, RA0, RZ); 1456 lab1 = code; 1457 BRA(Obe, 0); 1458 NOOP; 1459 mem(Oldw, O(Heap, ref)-sizeof(Heap), RA0, RA2); 1460 FM3I(2, Oadd, -1, RA2, RA2); 1461 FM3I(2, Ocmp, 0, RA2, RZ); 1462 lab2 = code; 1463 BRA(Obne, 0); 1464 NOOP; 1465 mem(Ostw, O(REG, FP), RREG, RFP); 1466 mem(Ostw, O(REG, st), RREG, RLINK); 1467 CALL(rdestroy); 1468 mem(Ostw, O(REG, s), RREG, RA0); 1469 con((ulong)&R, RREG, 1); 1470 mem(Oldw, O(REG, st), RREG, RLINK); 1471 mem(Oldw, O(REG, FP), RREG, RFP); 1472 RETURN; 1473 mem(Oldw, O(REG, MP), RREG, RMP); 1474 PATCH(lab2); 1475 mem(Ostw, O(Heap, ref)-sizeof(Heap), RA0, RA2); 1476 PATCH(lab1); 1477 RETURN; 1478 NOOP; 1479 } 1480 1481 static void 1482 macret(void) 1483 { 1484 Inst i; 1485 ulong *cp1, *cp2, *cp3, *cp4, *cp5, *cp6; 1486 1487 FM3I(2, Ocmp, 0, RA1, RZ); 1488 cp1 = code; 1489 BRA(Obe, 0); // t(Rfp) == 0 1490 NOOP; 1491 1492 mem(Oldw, O(Type,destroy),RA1, RA0); 1493 FM3I(2, Ocmp, 0, RA0, RZ); 1494 cp2 = code; 1495 BRA(Obe, 0); // destroy(t(fp)) == 0 1496 NOOP; 1497 1498 mem(Oldw, O(Frame,fp),RFP, RA2); 1499 FM3I(2, Ocmp, 0, RA2, RZ); 1500 cp3 = code; 1501 BRA(Obe, 0); // fp(Rfp) == 0 1502 NOOP; 1503 1504 mem(Oldw, O(Frame,mr),RFP, RA3); 1505 FM3I(2, Ocmp, 0, RA3, RZ); 1506 cp4 = code; 1507 BRA(Obe, 0); // mr(Rfp) == 0 1508 NOOP; 1509 1510 mem(Oldw, O(REG,M),RREG, RA2); 1511 mem(Oldw, O(Heap,ref)-sizeof(Heap),RA2, RA3); 1512 FM3I(2, Oaddcc, -1, RA3, RA3); 1513 cp5 = code; 1514 BRA(Obe, 0); // --ref(arg) == 0 1515 NOOP; 1516 mem(Ostw, O(Heap,ref)-sizeof(Heap),RA2, RA3); 1517 1518 mem(Oldw, O(Frame,mr),RFP, RA1); 1519 mem(Ostw, O(REG,M),RREG, RA1); 1520 mem(Oldw, O(Modlink,compiled),RA1, RA2); // check for uncompiled code 1521 mem(Oldw, O(Modlink,MP),RA1, RMP); 1522 FM3I(2, Ocmp, 0, RA2, RZ); 1523 cp6 = code; 1524 BRA(Obe, 0); 1525 NOOP; 1526 mem(Ostw, O(REG,MP),RREG, RMP); 1527 1528 PATCH(cp4); 1529 FM3I(2, Ojmpl, 0, RA0, RLINK); // call destroy(t(fp)) 1530 NOOP; 1531 mem(Ostw, O(REG,SP),RREG, RFP); 1532 mem(Oldw, O(Frame,lr),RFP, RA1); 1533 mem(Oldw, O(Frame,fp),RFP, RFP); 1534 mem(Ostw, O(REG,FP),RREG, RFP); 1535 FM3I(2, Ojmpl, 0, RA1, RZ); // goto lr(Rfp) 1536 NOOP; 1537 1538 PATCH(cp6); 1539 FM3I(2, Ojmpl, 0, RA0, RLINK); // call destroy(t(fp)) 1540 NOOP; 1541 mem(Ostw, O(REG,SP),RREG, RFP); 1542 mem(Oldw, O(Frame,lr),RFP, RA1); 1543 mem(Oldw, O(Frame,fp),RFP, RFP); 1544 mem(Ostw, O(REG,FP),RREG, RFP); 1545 mem(Oldw, O(REG,xpc),RREG, RA2); 1546 FM3I(2, Oadd, 0x8, RA2, RA2); 1547 FM3I(2, Ojmpl, 0, RA2, RZ); // return to uncompiled code 1548 mem(Ostw, O(REG,PC),RREG, RA1); 1549 1550 PATCH(cp1); 1551 PATCH(cp2); 1552 PATCH(cp3); 1553 PATCH(cp5); 1554 i.add = AXNON; 1555 punt(&i, TCHECK|NEWPC, optab[IRET]); 1556 } 1557 1558 static void 1559 maccolr(void) 1560 { 1561 ulong *br; 1562 1563 /* color the pointer in RA1 */ 1564 FM3I(2, Oadd, 1, RA0, RA0); 1565 mem(Ostw, O(Heap, ref)-sizeof(Heap), RA1, RA0); 1566 mem(Oldw, O(Heap, color)-sizeof(Heap), RA1, RA0); 1567 mem(Oldw, 0, RA2, RA2); 1568 FM3(2, Ocmp, RA0, RA2, RZ); 1569 br = code; 1570 BRA(Obe, 0); 1571 con(propagator, RA2, 1); 1572 mem(Ostw, O(Heap, color)-sizeof(Heap), RA1, RA2); 1573 con((ulong)&nprop, RA2, 1); 1574 RETURN; 1575 mem(Ostw, 0, RA2, RA2); 1576 PATCH(br); 1577 RETURN; 1578 NOOP; 1579 } 1580 1581 static void 1582 macmcal(void) 1583 { 1584 ulong *lab1, *lab2; 1585 1586 mem(Oldw, O(Modlink, prog), RA3, RA1); 1587 FM3I(2, Ocmp, 0, RA1, RZ); 1588 lab1 = code; 1589 BRA(Obne, 0); 1590 NOOP; 1591 1592 mem(Ostw, O(REG, st), RREG, RLINK); 1593 mem(Ostw, O(REG, FP), RREG, RA2); 1594 CALL(rmcall); // CALL rmcall 1595 mem(Ostw, O(REG, dt), RREG, RA0); 1596 1597 con((ulong)&R, RREG, 1); // MOVL $R, RREG 1598 mem(Oldw, O(REG, st), RREG, RLINK); 1599 mem(Oldw, O(REG, FP), RREG, RFP); 1600 mem(Oldw, O(REG, MP), RREG, RMP); 1601 RETURN; 1602 NOOP; 1603 1604 PATCH(lab1); // patch: 1605 FM3(2, Oor, RA2, RZ, RFP); 1606 mem(Ostw, O(REG, M), RREG, RA3); // MOVL RA3, R.M 1607 mem(Oldw, O(Heap, ref)-sizeof(Heap), RA3, RA1); 1608 FM3I(2, Oadd, 1, RA1, RA1); 1609 mem(Ostw, O(Heap, ref)-sizeof(Heap), RA3, RA1); 1610 mem(Oldw, O(Modlink, compiled), RA3, RA1); 1611 mem(Oldw, O(Modlink, MP), RA3, RMP); // MOVL R.M->MP, RMP 1612 FM3I(2, Ocmp, 0, RA1, RZ); 1613 lab2 = code; 1614 BRA(Obe, 0); 1615 mem(Ostw, O(REG, MP), RREG, RMP); // MOVL RA3, R.MP R.MP = ml->MP 1616 1617 FM3I(2, Ojmpl, 0, RA0, RZ); 1618 NOOP; 1619 1620 PATCH(lab2); 1621 mem(Ostw, O(REG,FP),RREG, RFP); 1622 mem(Oldw, O(REG,xpc),RREG, RA1); 1623 FM3I(2, Oadd, 0x8, RA1, RA1); 1624 FM3I(2, Ojmpl, 0, RA1, RZ); // call to uncompiled code 1625 mem(Ostw, O(REG,PC),RREG, RA0); 1626 } 1627 1628 static void 1629 macfram(void) 1630 { 1631 ulong *lab1; 1632 1633 mem(Oldw, O(REG, SP), RREG, RA0); // MOVL R.SP, RA0 1634 mem(Oldw, O(Type, size), RA3, RA1); 1635 FM3(2, Oadd, RA0, RA1, RA0); 1636 mem(Oldw, O(REG, TS), RREG, RA1); 1637 FM3(2, Ocmp, RA1, RA0, RZ); 1638 lab1 = code; 1639 BRA(Obl, 0); 1640 NOOP; 1641 1642 mem(Ostw, O(REG, s), RREG, RA3); 1643 mem(Ostw, O(REG, st), RREG, RLINK); 1644 CALL(extend); // CALL extend 1645 mem(Ostw, O(REG, FP), RREG, RFP); // MOVL RFP, R.FP 1646 1647 con((ulong)&R, RREG, 1); 1648 mem(Oldw, O(REG, st), RREG, RLINK); 1649 mem(Oldw, O(REG, FP), RREG, RFP); // MOVL R.MP, RMP 1650 mem(Oldw, O(REG, s), RREG, RA2); // MOVL R.s, *R.d 1651 mem(Oldw, O(REG, MP), RREG, RMP); // MOVL R.MP, RMP 1652 RETURN; // RET 1653 NOOP; 1654 1655 PATCH(lab1); 1656 mem(Oldw, O(REG, SP), RREG, RA2); // MOVL R.SP, RA2 1657 mem(Ostw, O(REG, SP), RREG, RA0); // MOVL RA0, R.SP 1658 1659 mem(Ostw, O(Frame, t), RA2, RA3); // MOVL RA3, t(RA2) f->t = t 1660 mem(Oldw, O(Type, initialize), RA3, RA3); 1661 FM3I(2, Ojmpl, 0, RA3, RZ); 1662 mem(Ostw, REGMOD*4, RA2, RZ); // MOVL $0, mr(RA2) f->mr 1663 } 1664 1665 static void 1666 macmfra(void) 1667 { 1668 mem(Ostw, O(REG, st), RREG, RLINK); 1669 mem(Ostw, O(REG, s), RREG, RA3); // Save type 1670 mem(Ostw, O(REG, d), RREG, RA0); // Save destination 1671 CALL(rmfram); // CALL rmfram 1672 mem(Ostw, O(REG, FP), RREG, RFP); 1673 1674 con((ulong)&R, RREG, 1); 1675 mem(Oldw, O(REG, st), RREG, RLINK); 1676 mem(Oldw, O(REG, FP), RREG, RFP); 1677 mem(Oldw, O(REG, MP), RREG, RMP); 1678 RETURN; 1679 NOOP; 1680 } 1681 1682 void 1683 comd(Type *t) 1684 { 1685 int i, j, m, c; 1686 1687 mem(Ostw, O(REG, dt), RREG, RLINK); 1688 for(i = 0; i < t->np; i++) { 1689 c = t->map[i]; 1690 j = i<<5; 1691 for(m = 0x80; m != 0; m >>= 1) { 1692 if(c & m) { 1693 CALL(base+macro[MacFRP]); 1694 mem(Oldw, j, RFP, RA0); 1695 } 1696 j += sizeof(WORD*); 1697 } 1698 } 1699 mem(Oldw, O(REG, dt), RREG, RLINK); 1700 RETURN; 1701 NOOP; 1702 } 1703 1704 void 1705 comi(Type *t) 1706 { 1707 int i, j, m, c; 1708 1709 con((ulong)H, RA0, 1); 1710 for(i = 0; i < t->np; i++) { 1711 c = t->map[i]; 1712 j = i<<5; 1713 for(m = 0x80; m != 0; m >>= 1) { 1714 if(c & m) 1715 mem(Ostw, j, RA2, RA0); 1716 j += sizeof(WORD*); 1717 } 1718 } 1719 RETURN; 1720 NOOP; 1721 } 1722 1723 void 1724 typecom(Type *t) 1725 { 1726 int n; 1727 ulong *tmp, *start; 1728 1729 if(t == nil || t->initialize != 0) 1730 return; 1731 1732 tmp = mallocz(4096*sizeof(ulong), 0); 1733 if(tmp == nil) 1734 error(exNomem); 1735 1736 code = tmp; 1737 comi(t); 1738 n = code - tmp; 1739 code = tmp; 1740 comd(t); 1741 n += code - tmp; 1742 free(tmp); 1743 1744 n *= sizeof(*code); 1745 code = mallocz(n, 0); 1746 if(code == nil) 1747 return; 1748 1749 start = code; 1750 t->initialize = code; 1751 comi(t); 1752 t->destroy = code; 1753 comd(t); 1754 1755 segflush(start, n); 1756 1757 if(cflag > 1) 1758 print("typ= %.8p %4d i %.8p d %.8p asm=%d\n", 1759 t, t->size, t->initialize, t->destroy, n); 1760 } 1761 1762 static void 1763 patchex(Module *m, ulong *p) 1764 { 1765 Handler *h; 1766 Except *e; 1767 1768 if((h = m->htab) == nil) 1769 return; 1770 for( ; h->etab != nil; h++){ 1771 h->pc1 = p[h->pc1]; 1772 h->pc2 = p[h->pc2]; 1773 for(e = h->etab; e->s != nil; e++) 1774 e->pc = p[e->pc]; 1775 if(e->pc != -1) 1776 e->pc = p[e->pc]; 1777 } 1778 } 1779 1780 int 1781 compile(Module *m, int size, Modlink *ml) 1782 { 1783 Link *l; 1784 Modl *e; 1785 int i, n; 1786 ulong *s, *tmp; 1787 1788 base = nil; 1789 patch = mallocz(size*sizeof(*patch), 0); 1790 tinit = malloc(m->ntype*sizeof(*tinit)); 1791 tmp = mallocz(1024*sizeof(ulong), 0); 1792 if(tinit == nil || patch == nil || tmp == nil) 1793 goto bad; 1794 1795 preamble(); 1796 1797 mod = m; 1798 n = 0; 1799 pass = 0; 1800 nlit = 0; 1801 1802 for(i = 0; i < size; i++) { 1803 code = tmp; 1804 comp(&m->prog[i]); 1805 patch[i] = n; 1806 n += code - tmp; 1807 } 1808 1809 for(i = 0; i < nelem(mactab); i++) { 1810 code = tmp; 1811 mactab[i].gen(); 1812 macro[mactab[i].idx] = n; 1813 n += code - tmp; 1814 } 1815 1816 base = mallocz((n+nlit)*sizeof(*code), 0); 1817 if(base == nil) 1818 goto bad; 1819 1820 if(cflag > 1) 1821 print("dis=%5d %5d sparc=%5d asm=%.8p lit=%d: %s\n", 1822 size, size*sizeof(Inst), n, base, nlit, m->name); 1823 1824 pass++; 1825 nlit = 0; 1826 litpool = base+n; 1827 code = base; 1828 1829 for(i = 0; i < size; i++) { 1830 s = code; 1831 comp(&m->prog[i]); 1832 if(cflag > 2) { 1833 print("%d %D\n", i, &m->prog[i]); 1834 das(s, code-s); 1835 } 1836 } 1837 1838 for(i = 0; i < nelem(mactab); i++) { 1839 s = code; 1840 mactab[i].gen(); 1841 if(cflag > 2) { 1842 print("%s:\n", mactab[i].name); 1843 das(s, code-s); 1844 } 1845 } 1846 1847 if(n != (code - base)) 1848 error(exCphase); 1849 1850 for(l = m->ext; l->name; l++) { 1851 l->u.pc = (Inst*)RELPC(patch[l->u.pc-m->prog]); 1852 typecom(l->frame); 1853 } 1854 if(ml != nil) { 1855 e = &ml->links[0]; 1856 for(i = 0; i < ml->nlinks; i++) { 1857 e->u.pc = (Inst*)RELPC(patch[e->u.pc-m->prog]); 1858 typecom(e->frame); 1859 e++; 1860 } 1861 } 1862 for(i = 0; i < m->ntype; i++) { 1863 if(tinit[i] != 0) 1864 typecom(m->type[i]); 1865 } 1866 patchex(m, patch); 1867 m->entry = (Inst*)RELPC(patch[mod->entry-mod->prog]); 1868 free(patch); 1869 free(tinit); 1870 free(tmp); 1871 free(m->prog); 1872 m->prog = (Inst*)base; 1873 m->compiled = 1; 1874 segflush(base, n*sizeof(*base)); 1875 return 1; 1876 bad: 1877 free(patch); 1878 free(tinit); 1879 free(tmp); 1880 free(base); 1881 return 0; 1882 } 1883