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 DP(LT, Mov, 0, RA2, (1<<3), RA2); 1568 LDRH(LT, RA1, RA3, RA2); 1569 if(bflag) 1570 BCK(RA2, RA0); 1571 } 1572 opwst(i, Stw, RA3); 1573 break; 1574 case IINDL: 1575 case IINDF: 1576 case IINDW: 1577 case IINDB: 1578 opwld(i, Ldw, RA0); /* a */ 1579 NOTNIL(RA0); 1580 mem(Ldw, O(Array, data), RA0, RA0); 1581 if(bflag) 1582 mem(Ldw, O(Array, len), RA0, RA2); 1583 r = 0; 1584 switch(i->op) { 1585 case IINDL: 1586 case IINDF: 1587 r = 3; 1588 break; 1589 case IINDW: 1590 r = 2; 1591 break; 1592 } 1593 if(UXDST(i->add) == DST(AIMM) && FITS8(i->d.imm<<r)) { 1594 if(bflag) 1595 BCKI(i->d.imm, RA2); 1596 DPI(AL, Add, RA0, RA0, 0, (i->d.imm<<r)); 1597 } else { 1598 opwst(i, Ldw, RA1); 1599 if(bflag) 1600 BCK(RA1, RA2); 1601 DP(AL, Add, RA0, RA0, r<<3, RA1); 1602 } 1603 mid(i, Stw, RA0); 1604 break; 1605 case IINDX: 1606 opwld(i, Ldw, RA0); /* a */ 1607 NOTNIL(RA0); 1608 opwst(i, Ldw, RA1); /* i */ 1609 1610 if(bflag){ 1611 mem(Ldw, O(Array, len), RA0, RA2); 1612 BCK(RA1, RA2); 1613 } 1614 mem(Ldw, O(Array, t), RA0, RA2); 1615 mem(Ldw, O(Array, data), RA0, RA0); 1616 mem(Ldw, O(Type, size), RA2, RA2); 1617 MUL(AL, RA2, RA1, RA1); 1618 DP(AL, Add, RA1, RA0, 0, RA0); 1619 mid(i, Stw, RA0); 1620 break; 1621 case IADDL: 1622 larith(i, Add, Adc); 1623 break; 1624 case ISUBL: 1625 larith(i, Sub, Sbc); 1626 break; 1627 case IORL: 1628 larith(i, Orr, Orr); 1629 break; 1630 case IANDL: 1631 larith(i, And, And); 1632 break; 1633 case IXORL: 1634 larith(i, Eor, Eor); 1635 break; 1636 case ICVTWL: 1637 opwld(i, Ldw, RA1); 1638 opwst(i, Lea, RA2); 1639 DP(AL, Mov, 0, RA0, (0<<3)|(2<<1), RA1); // ASR 32 1640 STW(AL, RA2, RA1, Blo); 1641 STW(AL, RA2, RA0, Bhi); 1642 break; 1643 case ICVTLW: 1644 opwld(i, Lea, RA0); 1645 mem(Ldw, Blo, RA0, RA0); 1646 opwst(i, Stw, RA0); 1647 break; 1648 case IBEQL: 1649 cbral(i, NE, EQ, ANDAND); 1650 break; 1651 case IBNEL: 1652 cbral(i, NE, NE, OROR); 1653 break; 1654 case IBLEL: 1655 cbral(i, LT, LS, EQAND); 1656 break; 1657 case IBGTL: 1658 cbral(i, GT, HI, EQAND); 1659 break; 1660 case IBLTL: 1661 cbral(i, LT, CC, EQAND); 1662 break; 1663 case IBGEL: 1664 cbral(i, GT, CS, EQAND); 1665 break; 1666 case ICVTFL: 1667 case ICVTLF: 1668 punt(i, SRCOP|DSTOP, optab[i->op]); 1669 break; 1670 case IDIVF: 1671 r = Dvf; 1672 goto arithf; 1673 case IMULF: 1674 r = Muf; 1675 goto arithf; 1676 case ISUBF: 1677 r = Suf; 1678 goto arithf; 1679 case IADDF: 1680 r = Adf; 1681 arithf: 1682 if(1){ 1683 /* software fp */ 1684 punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); 1685 break; 1686 } 1687 opflld(i, Ldf, FA2); 1688 midfl(i, Ldf, FA4); 1689 CPDO2(AL, r, FA4, FA4, FA2); 1690 opflst(i, Stf, FA4); 1691 break; 1692 case INEGF: 1693 if(1){ 1694 punt(i, SRCOP|DSTOP, optab[i->op]); 1695 break; 1696 } 1697 opflld(i, Ldf, FA2); 1698 CPDO1(AL, Mnf, FA2, FA2); 1699 opflst(i, Stf, FA2); 1700 //if(pass){print("%D\n", i); das(s, code-s);} 1701 break; 1702 case ICVTWF: 1703 if(1){ 1704 punt(i, SRCOP|DSTOP, optab[i->op]); 1705 break; 1706 } 1707 opwld(i, Ldw, RA2); 1708 CPFLT(AL, FA2, RA2); 1709 opflst(i, Stf, FA2); 1710 //if(pass){print("%D\n", i); das(s, code-s);} 1711 break; 1712 case ICVTFW: 1713 if(1){ 1714 punt(i, SRCOP|DSTOP, optab[i->op]); 1715 break; 1716 } 1717 opflld(i, Ldf, FA2); 1718 CPFIX(AL, RA2, FA2); 1719 opwst(i, Stw, RA2); 1720 //if(pass){print("%D\n", i); das(s, code-s);} 1721 break; 1722 case ISHLL: 1723 /* should do better */ 1724 punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); 1725 break; 1726 case ISHRL: 1727 /* should do better */ 1728 punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); 1729 break; 1730 case IRAISE: 1731 punt(i, SRCOP|WRTPC|NEWPC, optab[i->op]); 1732 break; 1733 case IMULX: 1734 case IDIVX: 1735 case ICVTXX: 1736 case IMULX0: 1737 case IDIVX0: 1738 case ICVTXX0: 1739 case IMULX1: 1740 case IDIVX1: 1741 case ICVTXX1: 1742 case ICVTFX: 1743 case ICVTXF: 1744 case IEXPW: 1745 case IEXPL: 1746 case IEXPF: 1747 punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); 1748 break; 1749 case ISELF: 1750 punt(i, DSTOP, optab[i->op]); 1751 break; 1752 } 1753 } 1754 1755 static void 1756 preamble(void) 1757 { 1758 if(comvec) 1759 return; 1760 1761 comvec = malloc(10 * sizeof(*code)); 1762 if(comvec == nil) 1763 error(exNomem); 1764 code = (ulong*)comvec; 1765 1766 con((ulong)&R, RREG, 0); 1767 mem(Stw, O(REG, xpc), RREG, RLINK); 1768 mem(Ldw, O(REG, FP), RREG, RFP); 1769 mem(Ldw, O(REG, MP), RREG, RMP); 1770 mem(Ldw, O(REG, PC), RREG, R15); 1771 pass++; 1772 flushcon(0); 1773 pass--; 1774 1775 segflush(comvec, 10 * sizeof(*code)); 1776 } 1777 1778 static void 1779 maccase(void) 1780 { 1781 ulong *cp1, *loop, *inner; 1782 /* 1783 * RA1 = value (input arg), t 1784 * RA2 = count, n 1785 * RA3 = table pointer (input arg) 1786 * RA0 = n/2, n2 1787 * RCON = pivot element t+n/2*3, l 1788 */ 1789 LDW(AL, RA3, RA2, 0); // count from table 1790 MOV(RA3, RLINK); // initial table pointer 1791 1792 loop = code; // loop: 1793 CMPI(AL, RA2, 0, 0, 0); 1794 cp1 = code; 1795 BRA(LE, 0); // n <= 0? goto out 1796 1797 inner = code; 1798 DP(AL, Mov, 0, RA0, (1<<3)|2, RA2); // n2 = n>>1 1799 DP(AL, Add, RA0, RCON, (1<<3), RA0); // n' = n2+(n2<<1) = 3*n2 1800 DP(AL, Add, RA3, RCON, (2<<3), RCON); // l = t + n2*3; 1801 1802 LDW(AL, RCON, RTA, 4); 1803 CMP(AL, RA1, 0, 0, RTA); 1804 DP(LT, Mov, 0, RA2, 0, RA0); // v < l[1]? n=n2 1805 BRANCH(LT, loop); // v < l[1]? goto loop 1806 1807 LDW(AL, RCON, RTA, 8); 1808 CMP(AL, RA1, 0, 0, RTA); 1809 LDW(LT, RCON, R15, 12); // v >= l[1] && v < l[2] => found; goto l[3] 1810 1811 // v >= l[2] (high) 1812 DPI(AL, Add, RCON, RA3, 0, 12); // t = l+3; 1813 DPI(AL, Add, RA0, RTA, 0, 1); 1814 DP(AL, Sub, RA2, RA2, 0, RTA) | SBIT; // n -= n2+1 1815 BRANCH(GT, inner); // n > 0? goto loop 1816 1817 PATCH(cp1); // out: 1818 LDW(AL, RLINK, RA2, 0); // initial n 1819 DP(AL, Add, RA2, RA2, (1<<3), RA2); // n = n+(n<<1) = 3*n 1820 DP(AL, Add, RLINK, RLINK, (2<<3), RA2); // t' = &(initial t)[n*3] 1821 LDW(AL, RLINK, R15, 4); // goto (initial t)[n*3+1] 1822 } 1823 1824 static void 1825 macfrp(void) 1826 { 1827 /* destroy the pointer in RA0 */ 1828 CMPH(AL, RA0); 1829 CRETURN(EQ); // arg == H? => return 1830 1831 mem(Ldw, O(Heap, ref)-sizeof(Heap), RA0, RA2); 1832 DPI(AL, Sub, RA2, RA2, 0, 1) | SBIT; 1833 memc(NE, Stw, O(Heap, ref)-sizeof(Heap), RA0, RA2); 1834 CRETURN(NE); // --h->ref != 0 => return 1835 1836 mem(Stw, O(REG, FP), RREG, RFP); 1837 mem(Stw, O(REG, st), RREG, RLINK); 1838 mem(Stw, O(REG, s), RREG, RA0); 1839 CALL(rdestroy); 1840 con((ulong)&R, RREG, 1); 1841 mem(Ldw, O(REG, st), RREG, RLINK); 1842 mem(Ldw, O(REG, FP), RREG, RFP); 1843 mem(Ldw, O(REG, MP), RREG, RMP); 1844 RETURN; 1845 flushcon(0); 1846 } 1847 1848 static void 1849 maccolr(void) 1850 { 1851 /* color the pointer in RA1 */ 1852 mem(Ldw, O(Heap, ref)-sizeof(Heap), RA1, RA0); 1853 DPI(AL, Add, RA0, RA0, 0, 1); 1854 mem(Stw, O(Heap, ref)-sizeof(Heap), RA1, RA0); // h->ref++ 1855 con((ulong)&mutator, RA2, 1); 1856 mem(Ldw, O(Heap, color)-sizeof(Heap), RA1, RA0); 1857 mem(Ldw, 0, RA2, RA2); 1858 CMP(AL, RA0, 0, 0, RA2); 1859 CRETURN(EQ); // return if h->color == mutator 1860 con(propagator, RA2, 1); 1861 mem(Stw, O(Heap, color)-sizeof(Heap), RA1, RA2); // h->color = propagator 1862 con((ulong)&nprop, RA2, 1); 1863 mem(Stw, 0, RA2, RA2); // nprop = !0 1864 RETURN; 1865 flushcon(0); 1866 } 1867 1868 static void 1869 macret(void) 1870 { 1871 Inst i; 1872 ulong *cp1, *cp2, *cp3, *cp4, *cp5, *linterp; 1873 1874 CMPI(AL, RA1, 0, 0, 0); 1875 cp1 = code; 1876 BRA(EQ, 0); // t(Rfp) == 0 1877 1878 mem(Ldw, O(Type,destroy),RA1, RA0); 1879 CMPI(AL, RA0, 0, 0, 0); 1880 cp2 = code; 1881 BRA(EQ, 0); // destroy(t(fp)) == 0 1882 1883 mem(Ldw, O(Frame,fp),RFP, RA2); 1884 CMPI(AL, RA2, 0, 0, 0); 1885 cp3 = code; 1886 BRA(EQ, 0); // fp(Rfp) == 0 1887 1888 mem(Ldw, O(Frame,mr),RFP, RA3); 1889 CMPI(AL, RA3, 0, 0, 0); 1890 cp4 = code; 1891 BRA(EQ, 0); // mr(Rfp) == 0 1892 1893 mem(Ldw, O(REG,M),RREG, RA2); 1894 mem(Ldw, O(Heap,ref)-sizeof(Heap),RA2, RA3); 1895 DPI(AL, Sub, RA3, RA3, 0, 1) | SBIT; 1896 cp5 = code; 1897 BRA(EQ, 0); // --ref(arg) == 0 1898 mem(Stw, O(Heap,ref)-sizeof(Heap),RA2, RA3); 1899 1900 mem(Ldw, O(Frame,mr),RFP, RA1); 1901 mem(Stw, O(REG,M),RREG, RA1); 1902 mem(Ldw, O(Modlink,MP),RA1, RMP); 1903 mem(Stw, O(REG,MP),RREG, RMP); 1904 mem(Ldw, O(Modlink,compiled), RA1, RA3); // R.M->compiled 1905 CMPI(AL, RA3, 0, 0, 0); 1906 linterp = code; 1907 BRA(EQ, 0); 1908 1909 PATCH(cp4); 1910 MOV(R15, R14); // call destroy(t(fp)) 1911 MOV(RA0, R15); 1912 1913 mem(Stw, O(REG,SP),RREG, RFP); 1914 mem(Ldw, O(Frame,lr),RFP, RA1); 1915 mem(Ldw, O(Frame,fp),RFP, RFP); 1916 mem(Stw, O(REG,FP),RREG, RFP); // R.FP = RFP 1917 DP(AL, Mov, 0, R15, 0, RA1); // goto lr(Rfp), if compiled 1918 1919 PATCH(linterp); 1920 MOV(R15, R14); // call destroy(t(fp)) 1921 MOV(RA0, R15); 1922 1923 mem(Stw, O(REG,SP),RREG, RFP); 1924 mem(Ldw, O(Frame,lr),RFP, RA1); 1925 mem(Ldw, O(Frame,fp),RFP, RFP); 1926 mem(Stw, O(REG,PC),RREG, RA1); // R.PC = fp->lr 1927 mem(Stw, O(REG,FP),RREG, RFP); // R.FP = RFP 1928 mem(Ldw, O(REG, xpc), RREG, RLINK); 1929 RETURN; // return to xec uncompiled code 1930 1931 PATCH(cp1); 1932 PATCH(cp2); 1933 PATCH(cp3); 1934 PATCH(cp5); 1935 i.add = AXNON; 1936 punt(&i, TCHECK|NEWPC, optab[IRET]); 1937 } 1938 1939 static void 1940 macmcal(void) 1941 { 1942 ulong *lab; 1943 1944 CMPH(AL, RA0); 1945 memc(NE, Ldw, O(Modlink, prog), RA3, RA1); // RA0 != H 1946 CMPI(NE, RA1, 0, 0, 0); // RA0 != H 1947 lab = code; 1948 BRA(NE, 0); // RA0 != H && m->prog!=0 1949 1950 mem(Stw, O(REG, st), RREG, RLINK); 1951 mem(Stw, O(REG, FP), RREG, RA2); 1952 mem(Stw, O(REG, dt), RREG, RA0); 1953 CALL(rmcall); // CALL rmcall 1954 1955 con((ulong)&R, RREG, 1); // MOVL $R, RREG 1956 mem(Ldw, O(REG, st), RREG, RLINK); 1957 mem(Ldw, O(REG, FP), RREG, RFP); 1958 mem(Ldw, O(REG, MP), RREG, RMP); 1959 RETURN; 1960 1961 PATCH(lab); // patch: 1962 DP(AL, Mov, 0, RFP, 0, RA2); 1963 mem(Stw, O(REG, M), RREG, RA3); // MOVL RA3, R.M 1964 mem(Ldw, O(Heap, ref)-sizeof(Heap), RA3, RA1); 1965 DPI(AL, Add, RA1, RA1, 0, 1); 1966 mem(Stw, O(Heap, ref)-sizeof(Heap), RA3, RA1); 1967 mem(Ldw, O(Modlink, MP), RA3, RMP); // MOVL R.M->mp, RMP 1968 mem(Stw, O(REG, MP), RREG, RMP); // MOVL RA3, R.MP R.MP = ml->m 1969 mem(Ldw, O(Modlink,compiled), RA3, RA1); // M.compiled? 1970 CMPI(AL, RA1, 0, 0, 0); 1971 DP(NE, Mov, 0, R15, 0, RA0); // return to compiled code 1972 mem(Stw, O(REG,FP),RREG, RFP); // R.FP = RFP 1973 mem(Stw, O(REG,PC),RREG, RA0); // R.PC = RPC 1974 mem(Ldw, O(REG, xpc), RREG, RLINK); 1975 RETURN; // return to xec uncompiled code 1976 flushcon(0); 1977 } 1978 1979 static void 1980 macfram(void) 1981 { 1982 ulong *lab1; 1983 1984 mem(Ldw, O(REG, SP), RREG, RA0); // MOVL R.SP, RA0 1985 mem(Ldw, O(Type, size), RA3, RA1); 1986 DP(AL, Add, RA0, RA0, 0, RA1); // nsp = R.SP + t->size 1987 mem(Ldw, O(REG, TS), RREG, RA1); 1988 CMP(AL, RA0, 0, 0, RA1); // nsp :: R.TS 1989 lab1 = code; 1990 BRA(CS, 0); // nsp >= R.TS; must expand 1991 1992 mem(Ldw, O(REG, SP), RREG, RA2); // MOVL R.SP, RA2 1993 mem(Stw, O(REG, SP), RREG, RA0); // MOVL RA0, R.SP 1994 1995 mem(Stw, O(Frame, t), RA2, RA3); // MOVL RA3, t(RA2) f->t = t 1996 con(0, RA0, 1); 1997 mem(Stw, O(Frame,mr), RA2, RA0); // MOVL $0, mr(RA2) f->mr 1998 mem(Ldw, O(Type, initialize), RA3, R15); // become t->init(RA2), returning RA2 1999 2000 PATCH(lab1); 2001 mem(Stw, O(REG, s), RREG, RA3); 2002 mem(Stw, O(REG, st), RREG, RLINK); 2003 mem(Stw, O(REG, FP), RREG, RFP); // MOVL RFP, R.FP 2004 CALL(extend); // CALL extend 2005 2006 con((ulong)&R, RREG, 1); 2007 mem(Ldw, O(REG, st), RREG, RLINK); 2008 mem(Ldw, O(REG, FP), RREG, RFP); // MOVL R.FP, RFP 2009 mem(Ldw, O(REG, s), RREG, RA2); // MOVL R.s, *R.d 2010 mem(Ldw, O(REG, MP), RREG, RMP); // MOVL R.MP, RMP 2011 RETURN; // RET 2012 } 2013 2014 static void 2015 macmfra(void) 2016 { 2017 mem(Stw, O(REG, st), RREG, RLINK); 2018 mem(Stw, O(REG, s), RREG, RA3); // Save type 2019 mem(Stw, O(REG, d), RREG, RA0); // Save destination 2020 mem(Stw, O(REG, FP), RREG, RFP); 2021 CALL(rmfram); // CALL rmfram 2022 2023 con((ulong)&R, RREG, 1); 2024 mem(Ldw, O(REG, st), RREG, RLINK); 2025 mem(Ldw, O(REG, FP), RREG, RFP); 2026 mem(Ldw, O(REG, MP), RREG, RMP); 2027 RETURN; 2028 } 2029 2030 static void 2031 macrelq(void) 2032 { 2033 mem(Stw, O(REG,FP),RREG, RFP); // R.FP = RFP 2034 mem(Stw, O(REG,PC),RREG, RLINK); // R.PC = RLINK 2035 mem(Ldw, O(REG, xpc), RREG, RLINK); 2036 RETURN; 2037 } 2038 2039 void 2040 comd(Type *t) 2041 { 2042 int i, j, m, c; 2043 2044 mem(Stw, O(REG, dt), RREG, RLINK); 2045 for(i = 0; i < t->np; i++) { 2046 c = t->map[i]; 2047 j = i<<5; 2048 for(m = 0x80; m != 0; m >>= 1) { 2049 if(c & m) { 2050 mem(Ldw, j, RFP, RA0); 2051 CALL(base+macro[MacFRP]); 2052 } 2053 j += sizeof(WORD*); 2054 } 2055 flushchk(); 2056 } 2057 mem(Ldw, O(REG, dt), RREG, RLINK); 2058 RETURN; 2059 flushcon(0); 2060 } 2061 2062 void 2063 comi(Type *t) 2064 { 2065 int i, j, m, c; 2066 2067 con((ulong)H, RA0, 1); 2068 for(i = 0; i < t->np; i++) { 2069 c = t->map[i]; 2070 j = i<<5; 2071 for(m = 0x80; m != 0; m >>= 1) { 2072 if(c & m) 2073 mem(Stw, j, RA2, RA0); 2074 j += sizeof(WORD*); 2075 } 2076 flushchk(); 2077 } 2078 RETURN; 2079 flushcon(0); 2080 } 2081 2082 void 2083 typecom(Type *t) 2084 { 2085 int n; 2086 ulong *tmp, *start; 2087 2088 if(t == nil || t->initialize != 0) 2089 return; 2090 2091 tmp = mallocz(4096*sizeof(ulong), 0); 2092 if(tmp == nil) 2093 error(exNomem); 2094 2095 code = tmp; 2096 comi(t); 2097 n = code - tmp; 2098 code = tmp; 2099 comd(t); 2100 n += code - tmp; 2101 free(tmp); 2102 2103 n *= sizeof(*code); 2104 code = mallocz(n, 0); 2105 if(code == nil) 2106 return; 2107 2108 start = code; 2109 t->initialize = code; 2110 comi(t); 2111 t->destroy = code; 2112 comd(t); 2113 2114 segflush(start, n); 2115 2116 if(cflag > 3) 2117 print("typ= %.8p %4d i %.8p d %.8p asm=%d\n", 2118 t, t->size, t->initialize, t->destroy, n); 2119 } 2120 2121 static void 2122 patchex(Module *m, ulong *p) 2123 { 2124 Handler *h; 2125 Except *e; 2126 2127 if((h = m->htab) == nil) 2128 return; 2129 for( ; h->etab != nil; h++){ 2130 h->pc1 = p[h->pc1]; 2131 h->pc2 = p[h->pc2]; 2132 for(e = h->etab; e->s != nil; e++) 2133 e->pc = p[e->pc]; 2134 if(e->pc != -1) 2135 e->pc = p[e->pc]; 2136 } 2137 } 2138 2139 int 2140 compile(Module *m, int size, Modlink *ml) 2141 { 2142 Link *l; 2143 Modl *e; 2144 int i, n; 2145 ulong *s, *tmp; 2146 2147 base = nil; 2148 patch = mallocz(size*sizeof(*patch), 0); 2149 tinit = malloc(m->ntype*sizeof(*tinit)); 2150 tmp = malloc(4096*sizeof(ulong)); 2151 if(tinit == nil || patch == nil || tmp == nil) 2152 goto bad; 2153 2154 preamble(); 2155 2156 mod = m; 2157 n = 0; 2158 pass = 0; 2159 nlit = 0; 2160 2161 for(i = 0; i < size; i++) { 2162 codeoff = n; 2163 code = tmp; 2164 comp(&m->prog[i]); 2165 patch[i] = n; 2166 n += code - tmp; 2167 } 2168 2169 for(i = 0; i < nelem(mactab); i++) { 2170 codeoff = n; 2171 code = tmp; 2172 mactab[i].gen(); 2173 macro[mactab[i].idx] = n; 2174 n += code - tmp; 2175 } 2176 code = tmp; 2177 flushcon(0); 2178 n += code - tmp; 2179 2180 base = mallocz((n+nlit)*sizeof(*code), 0); 2181 if(base == nil) 2182 goto bad; 2183 2184 if(cflag > 3) 2185 print("dis=%5d %5d 386=%5d asm=%.8p: %s\n", 2186 size, size*sizeof(Inst), n, base, m->name); 2187 2188 pass++; 2189 nlit = 0; 2190 litpool = base+n; 2191 code = base; 2192 n = 0; 2193 codeoff = 0; 2194 for(i = 0; i < size; i++) { 2195 s = code; 2196 comp(&m->prog[i]); 2197 if(patch[i] != n) { 2198 print("%3d %D\n", i, &m->prog[i]); 2199 print("%lud != %d\n", patch[i], n); 2200 urk("phase error"); 2201 } 2202 n += code - s; 2203 if(cflag > 4) { 2204 print("%3d %D\n", i, &m->prog[i]); 2205 das(s, code-s); 2206 } 2207 } 2208 2209 for(i = 0; i < nelem(mactab); i++) { 2210 s = code; 2211 mactab[i].gen(); 2212 if(macro[mactab[i].idx] != n){ 2213 print("mac phase err: %lud != %d\n", macro[mactab[i].idx], n); 2214 urk("phase error"); 2215 } 2216 n += code - s; 2217 if(cflag > 4) { 2218 print("%s:\n", mactab[i].name); 2219 das(s, code-s); 2220 } 2221 } 2222 s = code; 2223 flushcon(0); 2224 n += code - s; 2225 2226 for(l = m->ext; l->name; l++) { 2227 l->u.pc = (Inst*)RELPC(patch[l->u.pc-m->prog]); 2228 typecom(l->frame); 2229 } 2230 if(ml != nil) { 2231 e = &ml->links[0]; 2232 for(i = 0; i < ml->nlinks; i++) { 2233 e->u.pc = (Inst*)RELPC(patch[e->u.pc-m->prog]); 2234 typecom(e->frame); 2235 e++; 2236 } 2237 } 2238 for(i = 0; i < m->ntype; i++) { 2239 if(tinit[i] != 0) 2240 typecom(m->type[i]); 2241 } 2242 patchex(m, patch); 2243 m->entry = (Inst*)RELPC(patch[mod->entry-mod->prog]); 2244 free(patch); 2245 free(tinit); 2246 free(tmp); 2247 free(m->prog); 2248 m->prog = (Inst*)base; 2249 m->compiled = 1; 2250 segflush(base, n*sizeof(*base)); 2251 return 1; 2252 bad: 2253 free(patch); 2254 free(tinit); 2255 free(base); 2256 free(tmp); 2257 return 0; 2258 } 2259