#include "lib9.h"#include "isa.h"#include "interp.h"#include "raise.h" /* * to do: * eliminate litpool? * eliminate long constants in comi/comd * enable and check inline FP code (not much point with fpemu) */ #define RESCHED 1 /* check for interpreter reschedule */ enum{ R0 = 0, R1 = 1, R2 = 2, R3 = 3, R4 = 4, R5 = 5, R6 = 6, R7 = 7, R8 = 8, R9 = 9, R10 = 10, R11 = 11, R12 = 12, /* C's SB */ R13 = 13, /* C's SP */ R14 = 14, /* Link Register */ R15 = 15, /* PC */ RLINK = 14, RFP = R9, /* Frame Pointer */ RMP = R8, /* Module Pointer */ RTA = R7, /* Intermediate address for double indirect */ RCON = R6, /* Constant builder */ RREG = R5, /* Pointer to REG */ RA3 = R4, /* gpr 3 */ RA2 = R3, /* gpr 2 2+3 = L */ RA1 = R2, /* gpr 1 */ RA0 = R1, /* gpr 0 0+1 = L */ FA2 = 2, /* Floating */ FA3 = 3, FA4 = 4, FA5 = 5, EQ = 0, NE = 1, CS = 2, CC = 3, MI = 4, PL = 5, VS = 6, VC = 7, HI = 8, LS = 9, GE = 10, LT = 11, GT = 12, LE = 13, AL = 14, NV = 15, HS = CS, LO = CC, And = 0, Eor = 1, Sub = 2, Rsb = 3, Add = 4, Adc = 5, Sbc = 6, Rsc = 7, Tst = 8, Teq = 9, Cmp = 10, Cmn = 11, Orr = 12, Mov = 13, Bic = 14, Mvn = 15, Adf = 0, Muf = 1, Suf = 2, Rsf = 3, Dvf = 4, Rdf = 5, Rmf = 8, Mvf = 0, Mnf = 1, Abs = 2, Rnd = 3, Flt = 0, Fix = 1, Cmf = 4, Cnf = 5, Lea = 100, /* macro memory ops */ Ldw, Ldb, Stw, Stb, Ldf, Stf, Ldh, Blo = 0, /* offset of low order word in big */ Bhi = 4, /* offset of high order word in big */ NCON = (0xFFC-8)/4, SRCOP = (1<<0), DSTOP = (1<<1), WRTPC = (1<<2), TCHECK = (1<<3), NEWPC = (1<<4), DBRAN = (1<<5), THREOP = (1<<6), ANDAND = 1, OROR = 2, EQAND = 3, MacFRP = 0, MacRET, MacCASE, MacCOLR, MacMCAL, MacFRAM, MacMFRA, MacRELQ, NMACRO}; #define BITS(B) (1<<B)#define IMM(O) (O & ((1<<12)-1))#define SBIT (1<<20)#define PBIT (1<<24)#define UPBIT (1<<23) #define LDW(C, Rn, Rd, O) *code++ = (C<<28)|(1<<26)|(1<<24)|(1<<23)|(1<<20)|\ (Rn<<16)|(Rd<<12)|IMM(O)#define STW(C, Rn, Rd, O) *code++ = (C<<28)|(1<<26)|(1<<24)|(1<<23)|\ (Rn<<16)|(Rd<<12)|IMM(O)#define LDB(C, Rn, Rd, O) *code++ = (C<<28)|(1<<26)|(1<<24)|(1<<23)|(1<<20)|(1<<22)|\ (Rn<<16)|(Rd<<12)|IMM(O)#define STB(C, Rn, Rd, O) *code++ = (C<<28)|(1<<26)|(1<<24)|(1<<23)|(1<<22)|\ (Rn<<16)|(Rd<<12)|IMM(O) #define LDxP(C, Rn, Rd, O, B) *code++ = (C<<28)|(1<<26)|(B<<22)|(1<<23)|(1<<20)|\ (Rn<<16)|(Rd<<12)|IMM(O)#define STxP(C, Rn, Rd, O, B) *code++ = (C<<28)|(1<<26)|(B<<22)|(1<<23)|\ (Rn<<16)|(Rd<<12)|IMM(O)#define LDRW(C, Rn, Rd, SH, R) *code++ = (C<<28)|(3<<25)|(1<<24)|(1<<23)|(1<<20)|\ (Rn<<16)|(Rd<<12)|(SH<<4)|R#define STRW(C, Rn, Rd, SH, R) *code++ = (C<<28)|(3<<25)|(1<<24)|(1<<23)|\ (Rn<<16)|(Rd<<12)|(SH<<4)|R#define LDRB(C, Rn, Rd, SH, R) *code++ = (C<<28)|(3<<25)|(1<<24)|(1<<23)|(1<<20)|(1<<22)|\ (Rn<<16)|(Rd<<12)|(SH<<4)|R#define STRB(C, Rn, Rd, SH, R) *code++ = (C<<28)|(3<<25)|(1<<24)|(1<<23)|(1<<22)|\ (Rn<<16)|(Rd<<12)|(SH<<4)|R #define DPI(C, Op, Rn, Rd, RO, O) *code++ = (C<<28)|(1<<25)|(Op<<21)|\ (Rn<<16)|(Rd<<12)|(RO<<8)|((O)&0xff)#define DP(C, Op, Rn, Rd, Sh, Ro) *code++ = (C<<28)|(Op<<21)|(Rn<<16)|\ (Rd<<12)|((Sh)<<4)|Ro#define CMPI(C, Rn, Rd, RO, O) *code++ = (C<<28)|(1<<25)|(Cmp<<21)|(1<<20)|\ (Rn<<16)|(Rd<<12)|(RO<<8)|((O)&0xff)#define CMNI(C, Rn, Rd, RO, O) *code++ = (C<<28)|(1<<25)|(Cmn<<21)|(1<<20)|\ (Rn<<16)|(Rd<<12)|(RO<<8)|((O)&0xff)#define CMP(C, Rn, Rd, Sh, Ro) *code++ = (C<<28)|(Cmp<<21)|(Rn<<16)|(1<<20)|\ (Rd<<12)|((Sh)<<4)|Ro#define CMN(C, Rn, Rd, Sh, Ro) *code++ = (C<<28)|(Cmn<<21)|(Rn<<16)|(1<<20)|\ (Rd<<12)|((Sh)<<4)|Ro#define MUL(C, Rm, Rs, Rd) *code++ = (C<<28)|(Rd<<16)|(Rm<<0)|(Rs<<8)|\ (9<<4) #define LDF(C, Rn, Fd, O) *code++ = (C<<28)|(6<<25)|(1<<24)|(1<<23)|(1<<20)|\ (Rn<<16)|(1<<15)|(Fd<<12)|(1<<8)|((O)&0xff)#define STF(C, Rn, Fd, O) *code++ = (C<<28)|(6<<25)|(1<<24)|(1<<23)|\ (Rn<<16)|(1<<15)|(Fd<<12)|(1<<8)|((O)&0xff)#define CMF(C, Fn, Fm) *code++ = (C<<28)|(7<<25)|(4<<21)|(1<<20)|(Fn<<16)|\ (0xF<<12)|(1<<8)|(1<<4)|(Fm) #define LDH(C, Rn, Rd, O) *code++ = (C<<28)|(0<<25)|(1<<24)|(1<<23)|(1<<22)|(1<<20)|\ (Rn<<16)|(Rd<<12)|(((O)&0xf0)<<4)|(0xb<<4)|((O)&0xf)#define LDRH(C, Rn, Rd, Rm) *code++ = (C<<28)|(0<<25)|(1<<24)|(1<<23)|(1<<20)|\ (Rn<<16)|(Rd<<12)|(0xb<<4)|Rm #define CPDO2(C, Op, Fn, Fd, Fm) *code++ = (C<<28)|(0xE<<24)|(Op<<20)|(Fn<<16)|(Fd<<12)|(1<<8)|(1<<7)|(Fm)#define CPDO1(C, Op, Fd, Fm) CPDO2((C),(Op),0,(Fd),(Fm))|(1<<15)#define CPFLT(C, Fn, Rd) *code++ = (C<<28)|(0xE<<24)|(0<<20)|(Fn<<16)|(Rd<<12)|(1<<8)|(9<<4)#define CPFIX(C, Rd, Fm) *code++ = (C<<28)|(0xE<<24)|(1<<20)|(0<<16)|(Rd<<12)|(1<<8)|(9<<4)|(Fm) #define BRAW(C, o) ((C<<28)|(5<<25)|((o) & 0x00ffffff))#define BRA(C, o) gen(BRAW((C),(o)))#define IA(s, o) (ulong)(base+s[o])#define BRADIS(C, o) BRA(C, (IA(patch, o)-(ulong)code-8)>>2)#define BRAMAC(r, o) BRA(r, (IA(macro, o)-(ulong)code-8)>>2)#define BRANCH(C, o) gen(BRAW(C, ((ulong)(o)-(ulong)code-8)>>2))#define CALL(o) gen(BRAW(AL, ((ulong)(o)-(ulong)code-8)>>2)|(1<<24))#define CCALL(C,o) gen(BRAW((C), ((ulong)(o)-(ulong)code-8)>>2)|(1<<24))#define CALLMAC(C,o) gen(BRAW((C), (IA(macro, o)-(ulong)code-8)>>2)|(1<<24))#define RELPC(pc) (ulong)(base+(pc))#define RETURN DPI(AL, Add, RLINK, R15, 0, 0) #define CRETURN(C) DPI(C, Add, RLINK, R15, 0, 0) #define PATCH(ptr) *ptr |= (((ulong)code-(ulong)(ptr)-8)>>2) & 0x00ffffff #define MOV(src, dst) DP(AL, Mov, 0, dst, 0, src)#define FITS8(v) ((ulong)(v)<BITS(8))#define FITS5(v) ((ulong)(v)<BITS(5)) /* assumes H==-1 */#define CMPH(C, r) CMNI(C, r, 0, 0, 1)#define NOTNIL(r) (CMPH(AL, (r)), CCALL(EQ, bounds)) /* array bounds checking */#define BCK(r, rb) (CMP(AL, rb, 0, 0, r), CCALL(LS, bounds))#define BCKI(i, rb) (CMPI(AL, rb, 0, 0, i), CCALL(LS, bounds)) static ulong* code;static ulong* base;static ulong* patch;static ulong codeoff;static int pass;static int puntpc = 1;static Module* mod;static uchar* tinit;static ulong* litpool;static int nlit;static ulong macro[NMACRO]; void (*comvec)(void);static void macfrp(void);static void macret(void);static void maccase(void);static void maccolr(void);static void macmcal(void);static void macfram(void);static void macmfra(void);static void macrelq(void);static void movmem(Inst*);static void mid(Inst*, int, int);extern void das(ulong*, int); #define T(r) *((void**)(R.r)) struct{ int idx; void (*gen)(void); char* name;} mactab[] ={ MacFRP, macfrp, "FRP", /* decrement and free pointer */ MacRET, macret, "RET", /* return instruction */ MacCASE, maccase, "CASE", /* case instruction */ MacCOLR, maccolr, "COLR", /* increment and color pointer */ MacMCAL, macmcal, "MCAL", /* mcall bottom half */ MacFRAM, macfram, "FRAM", /* frame instruction */ MacMFRA, macmfra, "MFRA", /* punt mframe because t->initialize==0 */ MacRELQ, macrelq, /* reschedule */}; typedef struct Const Const;struct Const{ ulong o; ulong* code; ulong* pc;}; typedef struct Con Con;struct Con{ int ptr; Const table[NCON]; };static Con rcon; static voidrdestroy(void){ destroy(R.s);} static voidrmcall(void){ Frame *f; Prog *p; if((void*)R.dt == H) error(exModule); f = (Frame*)R.FP; if(f == H) error(exModule); f->mr = nil; ((void(*)(Frame*))R.dt)(f); R.SP = (uchar*)f; R.FP = f->fp; if(f->t == nil) unextend(f); else freeptrs(f, f->t); p = currun(); if(p->kill != nil) error(p->kill);} static voidrmfram(void){ Type *t; Frame *f; uchar *nsp; if(R.d == H) error(exModule); t = (Type*)R.s; if(t == H) error(exModule); nsp = R.SP + t->size; if(nsp >= R.TS) { R.s = t; extend(); T(d) = R.s; return; } f = (Frame*)R.SP; R.SP = nsp; f->t = t; f->mr = nil; initmem(t, f); T(d) = f;} static voidurk(char *s){ USED(s); error(exCompile); //production //panic("compile failed: urk: %s\n", s); //debugging} static voidgen(ulong w){ *code++ = w;} static longimmrot(ulong v){ int i; for(i=0; i<16; i++) { if((v & ~0xff) == 0) return (i<<8) | v | (1<<25); v = (v<<2) | (v>>30); } return 0;} static longimmaddr(long v){ if(v >= 0 && v <= 0xfff) return (v & 0xfff) | (1<<24) | /* pre indexing */ (1<<23); /* pre indexing, up */ if(v >= -0xfff && v < 0) return (-v & 0xfff) | (1<<24); /* pre indexing */ return 0;} static voidflushcon(int genbr){ int i; Const *c; ulong disp; if(rcon.ptr == 0) return; if(genbr){ if(0)print("BR %d(PC)=%8.8p (len=%d)\n", (rcon.ptr*4+4-8)>>2, code+rcon.ptr+1, rcon.ptr); BRA(AL, (rcon.ptr*4+4-8)>>2); } c = &rcon.table[0]; for(i = 0; i < rcon.ptr; i++) { if(pass){ disp = (code - c->code) * sizeof(*code) - 8; if(disp >= BITS(12)) print("INVALID constant range %lud", disp); 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); *c->code |= (disp&0xfff); } *code++ = c->o; c++; } rcon.ptr = 0;} static voidflushchk(void){ 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 if(0)print("flushed constant table: len %ux disp %ld\n", rcon.ptr, (code+codeoff-rcon.table[0].pc)*sizeof(*code)-8); flushcon(1); }} static voidccon(int cc, ulong o, int r, int opt){ ulong u; Const *c; if(opt != 0) { u = o & ~0xff; if(u == 0) { DPI(cc, Mov, 0, r, 0, o); return; } if(u == ~0xff) { DPI(cc, Mvn, 0, r, 0, ~o); return; } u = immrot(o); if(u) { DPI(cc, Mov, 0, r, 0, 0) | u; return; } u = o & ~0xffff; if(u == 0) { DPI(cc, Mov, 0, r, 0, o); DPI(cc, Orr, r, r, (24/2), o>>8); return; } } flushchk(); c = &rcon.table[rcon.ptr++]; c->o = o; c->code = code; c->pc = code+codeoff; LDW(cc, R15, r, 0);} static voidmemc(int c, int inst, ulong disp, int rm, int r){ int bit; if(inst == Lea) { if(disp < BITS(8)) { DPI(c, Add, rm, r, 0, disp); return; } if(-disp < BITS(8)) { DPI(c, Sub, rm, r, 0, -disp); return; } bit = immrot(disp); if(bit) { DPI(c, Add, rm, r, 0, 0) | bit; return; } ccon(c, disp, RCON, 1); DP(c, Add, rm, r, 0, RCON); return; } if(disp < BITS(12) || -disp < BITS(12)) { /* Direct load */ if(disp < BITS(12)) bit = 0; else { disp = -disp; bit = UPBIT; } switch(inst) { case Ldw: LDW(c, rm, r, disp); break; case Ldb: LDB(c, rm, r, disp); break;Lines 1–500 of 2258. Load more
#include "lib9.h" #include "isa.h" #include "interp.h" #include "raise.h" /* * to do: * eliminate litpool? * eliminate long constants in comi/comd * enable and check inline FP code (not much point with fpemu) */ #define RESCHED 1 /* check for interpreter reschedule */ enum { R0 = 0, R1 = 1, R2 = 2, R3 = 3, R4 = 4, R5 = 5, R6 = 6, R7 = 7, R8 = 8, R9 = 9, R10 = 10, R11 = 11, R12 = 12, /* C's SB */ R13 = 13, /* C's SP */ R14 = 14, /* Link Register */ R15 = 15, /* PC */ RLINK = 14, RFP = R9, /* Frame Pointer */ RMP = R8, /* Module Pointer */ RTA = R7, /* Intermediate address for double indirect */ RCON = R6, /* Constant builder */ RREG = R5, /* Pointer to REG */ RA3 = R4, /* gpr 3 */ RA2 = R3, /* gpr 2 2+3 = L */ RA1 = R2, /* gpr 1 */ RA0 = R1, /* gpr 0 0+1 = L */ FA2 = 2, /* Floating */ FA3 = 3, FA4 = 4, FA5 = 5, EQ = 0, NE = 1, CS = 2, CC = 3, MI = 4, PL = 5, VS = 6, VC = 7, HI = 8, LS = 9, GE = 10, LT = 11, GT = 12, LE = 13, AL = 14, NV = 15, HS = CS, LO = CC, And = 0, Eor = 1, Sub = 2, Rsb = 3, Add = 4, Adc = 5, Sbc = 6, Rsc = 7, Tst = 8, Teq = 9, Cmp = 10, Cmn = 11, Orr = 12, Mov = 13, Bic = 14, Mvn = 15, Adf = 0, Muf = 1, Suf = 2, Rsf = 3, Dvf = 4, Rdf = 5, Rmf = 8, Mvf = 0, Mnf = 1, Abs = 2, Rnd = 3, Flt = 0, Fix = 1, Cmf = 4, Cnf = 5, Lea = 100, /* macro memory ops */ Ldw, Ldb, Stw, Stb, Ldf, Stf, Ldh, Blo = 0, /* offset of low order word in big */ Bhi = 4, /* offset of high order word in big */ NCON = (0xFFC-8)/4, SRCOP = (1<<0), DSTOP = (1<<1), WRTPC = (1<<2), TCHECK = (1<<3), NEWPC = (1<<4), DBRAN = (1<<5), THREOP = (1<<6), ANDAND = 1, OROR = 2, EQAND = 3, MacFRP = 0, MacRET, MacCASE, MacCOLR, MacMCAL, MacFRAM, MacMFRA, MacRELQ, NMACRO }; #define BITS(B) (1<<B) #define IMM(O) (O & ((1<<12)-1)) #define SBIT (1<<20) #define PBIT (1<<24) #define UPBIT (1<<23) #define LDW(C, Rn, Rd, O) *code++ = (C<<28)|(1<<26)|(1<<24)|(1<<23)|(1<<20)|\ (Rn<<16)|(Rd<<12)|IMM(O) #define STW(C, Rn, Rd, O) *code++ = (C<<28)|(1<<26)|(1<<24)|(1<<23)|\ (Rn<<16)|(Rd<<12)|IMM(O) #define LDB(C, Rn, Rd, O) *code++ = (C<<28)|(1<<26)|(1<<24)|(1<<23)|(1<<20)|(1<<22)|\ (Rn<<16)|(Rd<<12)|IMM(O) #define STB(C, Rn, Rd, O) *code++ = (C<<28)|(1<<26)|(1<<24)|(1<<23)|(1<<22)|\ (Rn<<16)|(Rd<<12)|IMM(O) #define LDxP(C, Rn, Rd, O, B) *code++ = (C<<28)|(1<<26)|(B<<22)|(1<<23)|(1<<20)|\ (Rn<<16)|(Rd<<12)|IMM(O) #define STxP(C, Rn, Rd, O, B) *code++ = (C<<28)|(1<<26)|(B<<22)|(1<<23)|\ (Rn<<16)|(Rd<<12)|IMM(O) #define LDRW(C, Rn, Rd, SH, R) *code++ = (C<<28)|(3<<25)|(1<<24)|(1<<23)|(1<<20)|\ (Rn<<16)|(Rd<<12)|(SH<<4)|R #define STRW(C, Rn, Rd, SH, R) *code++ = (C<<28)|(3<<25)|(1<<24)|(1<<23)|\ (Rn<<16)|(Rd<<12)|(SH<<4)|R #define LDRB(C, Rn, Rd, SH, R) *code++ = (C<<28)|(3<<25)|(1<<24)|(1<<23)|(1<<20)|(1<<22)|\ (Rn<<16)|(Rd<<12)|(SH<<4)|R #define STRB(C, Rn, Rd, SH, R) *code++ = (C<<28)|(3<<25)|(1<<24)|(1<<23)|(1<<22)|\ (Rn<<16)|(Rd<<12)|(SH<<4)|R #define DPI(C, Op, Rn, Rd, RO, O) *code++ = (C<<28)|(1<<25)|(Op<<21)|\ (Rn<<16)|(Rd<<12)|(RO<<8)|((O)&0xff) #define DP(C, Op, Rn, Rd, Sh, Ro) *code++ = (C<<28)|(Op<<21)|(Rn<<16)|\ (Rd<<12)|((Sh)<<4)|Ro #define CMPI(C, Rn, Rd, RO, O) *code++ = (C<<28)|(1<<25)|(Cmp<<21)|(1<<20)|\ (Rn<<16)|(Rd<<12)|(RO<<8)|((O)&0xff) #define CMNI(C, Rn, Rd, RO, O) *code++ = (C<<28)|(1<<25)|(Cmn<<21)|(1<<20)|\ (Rn<<16)|(Rd<<12)|(RO<<8)|((O)&0xff) #define CMP(C, Rn, Rd, Sh, Ro) *code++ = (C<<28)|(Cmp<<21)|(Rn<<16)|(1<<20)|\ (Rd<<12)|((Sh)<<4)|Ro #define CMN(C, Rn, Rd, Sh, Ro) *code++ = (C<<28)|(Cmn<<21)|(Rn<<16)|(1<<20)|\ (Rd<<12)|((Sh)<<4)|Ro #define MUL(C, Rm, Rs, Rd) *code++ = (C<<28)|(Rd<<16)|(Rm<<0)|(Rs<<8)|\ (9<<4) #define LDF(C, Rn, Fd, O) *code++ = (C<<28)|(6<<25)|(1<<24)|(1<<23)|(1<<20)|\ (Rn<<16)|(1<<15)|(Fd<<12)|(1<<8)|((O)&0xff) #define STF(C, Rn, Fd, O) *code++ = (C<<28)|(6<<25)|(1<<24)|(1<<23)|\ (Rn<<16)|(1<<15)|(Fd<<12)|(1<<8)|((O)&0xff) #define CMF(C, Fn, Fm) *code++ = (C<<28)|(7<<25)|(4<<21)|(1<<20)|(Fn<<16)|\ (0xF<<12)|(1<<8)|(1<<4)|(Fm) #define LDH(C, Rn, Rd, O) *code++ = (C<<28)|(0<<25)|(1<<24)|(1<<23)|(1<<22)|(1<<20)|\ (Rn<<16)|(Rd<<12)|(((O)&0xf0)<<4)|(0xb<<4)|((O)&0xf) #define LDRH(C, Rn, Rd, Rm) *code++ = (C<<28)|(0<<25)|(1<<24)|(1<<23)|(1<<20)|\ (Rn<<16)|(Rd<<12)|(0xb<<4)|Rm #define CPDO2(C, Op, Fn, Fd, Fm) *code++ = (C<<28)|(0xE<<24)|(Op<<20)|(Fn<<16)|(Fd<<12)|(1<<8)|(1<<7)|(Fm) #define CPDO1(C, Op, Fd, Fm) CPDO2((C),(Op),0,(Fd),(Fm))|(1<<15) #define CPFLT(C, Fn, Rd) *code++ = (C<<28)|(0xE<<24)|(0<<20)|(Fn<<16)|(Rd<<12)|(1<<8)|(9<<4) #define CPFIX(C, Rd, Fm) *code++ = (C<<28)|(0xE<<24)|(1<<20)|(0<<16)|(Rd<<12)|(1<<8)|(9<<4)|(Fm) #define BRAW(C, o) ((C<<28)|(5<<25)|((o) & 0x00ffffff)) #define BRA(C, o) gen(BRAW((C),(o))) #define IA(s, o) (ulong)(base+s[o]) #define BRADIS(C, o) BRA(C, (IA(patch, o)-(ulong)code-8)>>2) #define BRAMAC(r, o) BRA(r, (IA(macro, o)-(ulong)code-8)>>2) #define BRANCH(C, o) gen(BRAW(C, ((ulong)(o)-(ulong)code-8)>>2)) #define CALL(o) gen(BRAW(AL, ((ulong)(o)-(ulong)code-8)>>2)|(1<<24)) #define CCALL(C,o) gen(BRAW((C), ((ulong)(o)-(ulong)code-8)>>2)|(1<<24)) #define CALLMAC(C,o) gen(BRAW((C), (IA(macro, o)-(ulong)code-8)>>2)|(1<<24)) #define RELPC(pc) (ulong)(base+(pc)) #define RETURN DPI(AL, Add, RLINK, R15, 0, 0) #define CRETURN(C) DPI(C, Add, RLINK, R15, 0, 0) #define PATCH(ptr) *ptr |= (((ulong)code-(ulong)(ptr)-8)>>2) & 0x00ffffff #define MOV(src, dst) DP(AL, Mov, 0, dst, 0, src) #define FITS8(v) ((ulong)(v)<BITS(8)) #define FITS5(v) ((ulong)(v)<BITS(5)) /* assumes H==-1 */ #define CMPH(C, r) CMNI(C, r, 0, 0, 1) #define NOTNIL(r) (CMPH(AL, (r)), CCALL(EQ, bounds)) /* array bounds checking */ #define BCK(r, rb) (CMP(AL, rb, 0, 0, r), CCALL(LS, bounds)) #define BCKI(i, rb) (CMPI(AL, rb, 0, 0, i), CCALL(LS, bounds)) static ulong* code; static ulong* base; static ulong* patch; static ulong codeoff; static int pass; static int puntpc = 1; static Module* mod; static uchar* tinit; static ulong* litpool; static int nlit; static ulong macro[NMACRO]; void (*comvec)(void); static void macfrp(void); static void macret(void); static void maccase(void); static void maccolr(void); static void macmcal(void); static void macfram(void); static void macmfra(void); static void macrelq(void); static void movmem(Inst*); static void mid(Inst*, int, int); extern void das(ulong*, int); #define T(r) *((void**)(R.r)) struct { int idx; void (*gen)(void); char* name; } mactab[] = { MacFRP, macfrp, "FRP", /* decrement and free pointer */ MacRET, macret, "RET", /* return instruction */ MacCASE, maccase, "CASE", /* case instruction */ MacCOLR, maccolr, "COLR", /* increment and color pointer */ MacMCAL, macmcal, "MCAL", /* mcall bottom half */ MacFRAM, macfram, "FRAM", /* frame instruction */ MacMFRA, macmfra, "MFRA", /* punt mframe because t->initialize==0 */ MacRELQ, macrelq, /* reschedule */ }; typedef struct Const Const; struct Const { ulong o; ulong* code; ulong* pc; }; typedef struct Con Con; struct Con { int ptr; Const table[NCON]; }; static Con rcon; static void rdestroy(void) { destroy(R.s); } static void rmcall(void) { Frame *f; Prog *p; if((void*)R.dt == H) error(exModule); f = (Frame*)R.FP; if(f == H) error(exModule); f->mr = nil; ((void(*)(Frame*))R.dt)(f); R.SP = (uchar*)f; R.FP = f->fp; if(f->t == nil) unextend(f); else freeptrs(f, f->t); p = currun(); if(p->kill != nil) error(p->kill); } static void rmfram(void) { Type *t; Frame *f; uchar *nsp; if(R.d == H) error(exModule); t = (Type*)R.s; if(t == H) error(exModule); nsp = R.SP + t->size; if(nsp >= R.TS) { R.s = t; extend(); T(d) = R.s; return; } f = (Frame*)R.SP; R.SP = nsp; f->t = t; f->mr = nil; initmem(t, f); T(d) = f; } static void urk(char *s) { USED(s); error(exCompile); //production //panic("compile failed: urk: %s\n", s); //debugging } static void gen(ulong w) { *code++ = w; } static long immrot(ulong v) { int i; for(i=0; i<16; i++) { if((v & ~0xff) == 0) return (i<<8) | v | (1<<25); v = (v<<2) | (v>>30); } return 0; } static long immaddr(long v) { if(v >= 0 && v <= 0xfff) return (v & 0xfff) | (1<<24) | /* pre indexing */ (1<<23); /* pre indexing, up */ if(v >= -0xfff && v < 0) return (-v & 0xfff) | (1<<24); /* pre indexing */ return 0; } static void flushcon(int genbr) { int i; Const *c; ulong disp; if(rcon.ptr == 0) return; if(genbr){ if(0)print("BR %d(PC)=%8.8p (len=%d)\n", (rcon.ptr*4+4-8)>>2, code+rcon.ptr+1, rcon.ptr); BRA(AL, (rcon.ptr*4+4-8)>>2); } c = &rcon.table[0]; for(i = 0; i < rcon.ptr; i++) { if(pass){ disp = (code - c->code) * sizeof(*code) - 8; if(disp >= BITS(12)) print("INVALID constant range %lud", disp); 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); *c->code |= (disp&0xfff); } *code++ = c->o; c++; } rcon.ptr = 0; } static void flushchk(void) { 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 if(0)print("flushed constant table: len %ux disp %ld\n", rcon.ptr, (code+codeoff-rcon.table[0].pc)*sizeof(*code)-8); flushcon(1); } } static void ccon(int cc, ulong o, int r, int opt) { ulong u; Const *c; if(opt != 0) { u = o & ~0xff; if(u == 0) { DPI(cc, Mov, 0, r, 0, o); return; } if(u == ~0xff) { DPI(cc, Mvn, 0, r, 0, ~o); return; } u = immrot(o); if(u) { DPI(cc, Mov, 0, r, 0, 0) | u; return; } u = o & ~0xffff; if(u == 0) { DPI(cc, Mov, 0, r, 0, o); DPI(cc, Orr, r, r, (24/2), o>>8); return; } } flushchk(); c = &rcon.table[rcon.ptr++]; c->o = o; c->code = code; c->pc = code+codeoff; LDW(cc, R15, r, 0); } static void memc(int c, int inst, ulong disp, int rm, int r) { int bit; if(inst == Lea) { if(disp < BITS(8)) { DPI(c, Add, rm, r, 0, disp); return; } if(-disp < BITS(8)) { DPI(c, Sub, rm, r, 0, -disp); return; } bit = immrot(disp); if(bit) { DPI(c, Add, rm, r, 0, 0) | bit; return; } ccon(c, disp, RCON, 1); DP(c, Add, rm, r, 0, RCON); return; } if(disp < BITS(12) || -disp < BITS(12)) { /* Direct load */ if(disp < BITS(12)) bit = 0; else { disp = -disp; bit = UPBIT; } switch(inst) { case Ldw: LDW(c, rm, r, disp); break; case Ldb: LDB(c, rm, r, disp); break;