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