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