#include "lib9.h"#include "isa.h"#include "interp.h"#include "raise.h" #define T(r) *((void**)(R.r)) #define SRR(op,c,r1,r2) gen((op)|((c)<<6)|((r1)<<16)|((r2)<<11))#define RRR(op,r1,r2,r3) gen((op)|((r1)<<16)|((r2)<<21)|((r3)<<11))#define FRRR(op,r1,r2,r3) gen((op)|((r1)<<16)|((r2)<<11)|((r3)<<6))#define FI(op,c) gen((op)|((c)&0xffff))#define IRR(op,c,r1,r2) gen((op)|((c)&0xffff)|((r1)<<21)|((r2)<<16))#define BRRI(op,r1,r2,c) gen((op)|((r1)<<21)|((r2)<<16)|((c)&0xffff))#define BRI(op,r,c) gen((op)|((r)<<21)|((c)&0xffff))#define JR(op,r) gen((op)|((r)<<21))#define J(op,c) gen((op)|(((ulong)(c)>>2)&0x3FFFFFFUL)) enum{ Rzero = 0, Ro1 = 8, Ro2 = 9, Ro3 = 10, Ri = 11, Rj = 12, Rmp = 13, Rfp = 14, Rreg = 15, Rpic = 25, Rlink = 31, Rf1 = 4, Rf2 = 6, Olw = 0x23<<26, Olbu = 0x24<<26, Olhu = 0x25<<26, Osw = 0x2b<<26, Osb = 0x28<<26, Oaddui = 0x09<<26, Olui = 0x0f<<26, Oori = 0x0d<<26, Odiv = (0x00<<26) | 0x1a, Omul = (0x00<<26) | 0x18, Omfhi = (0x00<<26) | 0x10, Omflo = (0x00<<26) | 0x12, Osubu = (0x00<<26) | 0x23, Oaddu = (0x00<<26) | 0x21, Oand = (0x00<<26) | 0x24, Oor = (0x00<<26) | 0x25, Oxor = (0x00<<26) | 0x26, Odelay = (0x00<<26) | 0x27, Osll = (0x00<<26) | 0x00, Osrl = (0x00<<26) | 0x02, Osra = (0x00<<26) | 0x03, Osllv = (0x00<<26) | 0x04, Osrlv = (0x00<<26) | 0x06, Osrav = (0x00<<26) | 0x07, Oslt = (0x00<<26) | 0x2a, Osltu = (0x00<<26) | 0x2b, Obeq = 0x04<<26, Obne = 0x05<<26, Obltz = (0x01<<26) | (0x0<<16), Obgtz = (0x07<<26) | (0x0<<16), Oblez = (0x06<<26) | (0x0<<16), Obgez = (0x01<<26) | (0x1<<16), Ojr = (0x00<<26) | 0x08, Ojalr = (0x00<<26) | 0x09 | (Rlink<<11), Oj = (0x02<<26), Ojal = (0x03<<26), Olea = Oaddui, // pseudo op Olf = 0x31<<26, Osf = 0x39<<26, Oaddf = (0x11<<26) | (17<<21) | 0, Osubf = (0x11<<26) | (17<<21) | 1, Omulf = (0x11<<26) | (17<<21) | 2, Odivf = (0x11<<26) | (17<<21) | 3, Onegf = (0x11<<26) | (17<<21) | 7, Ocvtwf = (0x11<<26) | (20<<21) | 33, Ocvtfw = (0x11<<26) | (17<<21) | 36, Ofeq = (0x11<<26) | (17<<21) | (3<<4) | 2, Oflt = (0x11<<26) | (17<<21) | (3<<4) | 12, Obrf = (0x11<<26) | (0x100<<16), Obrt = (0x11<<26) | (0x101<<16), SRCOP = (1<<0), DSTOP = (1<<1), WRTPC = (1<<2), TCHECK = (1<<3), NEWPC = (1<<4), DBRAN = (1<<5), THREOP = (1<<6), ANDAND = 1, OROR, EQAND, XOR, IOR, AND, ADD, SUB, OMASK = (1<<4) - 1, REV1 = 1<<4, REV2 = 1<<5, MacRET = 0, MacFRP, MacINDX, MacCASE, MacLENA, MacFRAM, MacMOVM, MacCOLR, MacMCAL, MacMFRA, MacEND, NMACRO}; extern char Tmodule[]; void (*comvec)(void);extern void das(ulong*);static ulong* code;static ulong* base;static ulong* patch;static int pass;static int regdelay;static Module* mod;static ulong* tinit;static ulong* litpool;static int nlit;static ulong macro[NMACRO];static void rdestroy(void);static void macret(void);static void macfrp(void);static void macindx(void);static void maccase(void);static void maclena(void);static void macfram(void);static void macmovm(void);static void maccvtfw(void);static void maccolr(void);static void macend(void);static void macmcal(void);static void macmfra(void); struct{ int o; void (*f)(void);} macinit[] ={ MacFRP, macfrp, /* decrement and free pointer */ MacRET, macret, /* return instruction */ MacCASE, maccase, /* case instruction */ MacCOLR, maccolr, /* increment and color pointer */ MacFRAM, macfram, /* frame instruction */ MacMCAL, macmcal, /* mcall bottom half */ MacMFRA, macmfra, /* punt mframe because t->initialize==0 */ MacMOVM, macmovm, MacLENA, maclena, MacINDX, macindx, MacEND, macend, 0}; static voidrdestroy(void){ destroy(R.s);} static voidrmcall(void){ Prog *p; Frame *f; 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; t = (Type*)R.s; 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;} voidurk(char *s){ print("urk: %s\n", s); exits(0);} voidgen(ulong o){ *code++ = o;} voiddelay(void){ gen(Odelay);} intbigc(long c){ c >>= 15; if(c == 0 || c == -1) return 0; return 1;} voidldbigc(ulong c, int reg){ IRR(Olui, c>>16,Rzero,reg); IRR(Oori, c,reg,reg);} voidldc(ulong c, int reg){ if(bigc(c)) ldbigc(c, reg); else IRR(Oaddui, c,Rzero, reg);} voidxchg(void){ ulong t; t = code[-1]; code[-1] = code[-2]; code[-2] = t;} voidopx(int mode, Adr *a, int op, int reg, int del){ ulong c; int r, rx; switch(mode) { case AFP: c = a->ind; if(bigc(c)) urk("bigc op1b 1"); if(regdelay == Rfp) delay(); IRR(op, c,Rfp, reg); break; case AMP: c = a->ind; if(bigc(c)) urk("bigc op1b 2"); if(regdelay == Rmp) delay(); IRR(op, c,Rmp, reg); break; case AIMM: if(op == Olea) { if(a->imm != 0) { ldc(a->imm, reg); IRR(Osw, O(REG,st),Rreg, reg); } else IRR(Osw, O(REG,st),Rreg, Rzero); IRR(Oaddui, O(REG,st),Rreg, reg); } else ldc(a->imm, reg); return; case AIND|AFP: r = Rfp; goto offset; case AIND|AMP: r = Rmp; offset: if(regdelay == r) delay(); c = a->i.s; rx = Ri; if(op == Olea || op == Olw) rx = reg; IRR(Olw, a->i.f,r, rx); if(c != 0 || op != Oaddui) { delay(); IRR(op, c,rx, reg); } break; } if(op != Olea && del) delay(); regdelay = 0;} voidop1(Inst *i, int op, int reg, int del){ opx(USRC(i->add), &i->s, op, reg, del);} voidop3(Inst *i, int op, int reg, int del){ opx(UDST(i->add), &i->d, op, reg, del);} voidop2(Inst *i, int op, int reg, int del){ switch(i->add & ARM) { case AXNON: op3(i, op, reg, del); return; case AXIMM: if(op == Olea) { if((short)i->reg != 0) { ldc((short)i->reg, reg); IRR(Osw, O(REG,t),Rreg, reg); } else IRR(Osw, O(REG,t),Rreg, Rzero); IRR(Oaddui, O(REG,t),Rreg, reg); } else ldc((short)i->reg, reg); return; case AXINF: IRR(op, i->reg,Rfp, reg); break; case AXINM: IRR(op, i->reg,Rmp, reg); break; } if(op != Olea && del) delay();} ulongbranch(Inst *i){ ulong rel; if(base == 0) return 0; rel = patch[(Inst*)i->d.imm - mod->prog]; rel += (base - code) - 1; return rel & 0xffff;} static voidliteral(ulong imm, int roff){ nlit++; ldbigc((ulong)litpool, Ro1); IRR(Osw, roff, Rreg, Ro1); if(pass == 0) return; *litpool = imm; litpool++; } voidpunt(Inst *i, int m, void (*fn)(void)){ ulong *cp, pc; if(m & SRCOP) { op1(i, Olea, Ro1, 1); IRR(Osw, O(REG,s),Rreg, Ro1); } if(m & DSTOP) { op3(i, Olea, Ro3, 1); IRR(Osw, O(REG,d),Rreg, Ro3); } if(m & WRTPC) { pc = patch[i-mod->prog+1]; ldbigc((ulong)(base+pc), Ro1); IRR(Osw, O(REG,PC),Rreg, Ro1); } if(m & DBRAN) { pc = patch[(Inst*)i->d.imm-mod->prog]; literal((ulong)(base+pc), O(REG, d)); } if((i->add&ARM) == AXNON) { if(m & THREOP) { delay(); IRR(Olw, O(REG,d),Rreg, Ro2); delay(); IRR(Osw, O(REG,m),Rreg, Ro2); } } else { op2(i, Olea, Ro2, 1); IRR(Osw, O(REG,m),Rreg, Ro2); } ldc((ulong)fn, Rpic); JR(Ojalr, Rpic); IRR(Osw, O(REG,FP),Rreg, Rfp); ldc((ulong)&R, Rreg); IRR(Olw, O(REG,FP),Rreg, Rfp); IRR(Olw, O(REG,MP),Rreg, Rmp); regdelay = Rmp; if(m & TCHECK) { IRR(Olw, O(REG,t),Rreg, Ro1); xchg(); cp = code; BRRI(Obeq,Ro1,Rzero,0); IRR(Olw, O(REG,xpc),Rreg, Ro2); delay(); JR(Ojr, Ro2); delay(); *cp |= (code - cp) - 1; regdelay = 0; } if(m & NEWPC) { IRR(Olw, O(REG,PC),Rreg, Ro1); if(m & TCHECK) delay(); else xchg(); JR(Ojr, Ro1); delay(); regdelay = 0; }} static voidcomgoto(Inst *i){ WORD *t, *e; op1(i, Olw, Ro2, 0); op3(i, Olea, Ro3, 0); SRR(Osll, 2, Ro2, Ro2); RRR(Oaddu, Ro2, Ro3, Ro3); IRR(Olw, 0,Ro3, Ro1); delay(); JR(Ojr, Ro1); delay(); if(pass == 0) return; t = (WORD*)(mod->origmp+i->d.ind); e = t + t[-1]; t[-1] = 0; while(t < e) { t[0] = (ulong)(base + patch[t[0]]); t++;Lines 1–500 of 1955. Load more
#include "lib9.h" #include "isa.h" #include "interp.h" #include "raise.h" #define T(r) *((void**)(R.r)) #define SRR(op,c,r1,r2) gen((op)|((c)<<6)|((r1)<<16)|((r2)<<11)) #define RRR(op,r1,r2,r3) gen((op)|((r1)<<16)|((r2)<<21)|((r3)<<11)) #define FRRR(op,r1,r2,r3) gen((op)|((r1)<<16)|((r2)<<11)|((r3)<<6)) #define FI(op,c) gen((op)|((c)&0xffff)) #define IRR(op,c,r1,r2) gen((op)|((c)&0xffff)|((r1)<<21)|((r2)<<16)) #define BRRI(op,r1,r2,c) gen((op)|((r1)<<21)|((r2)<<16)|((c)&0xffff)) #define BRI(op,r,c) gen((op)|((r)<<21)|((c)&0xffff)) #define JR(op,r) gen((op)|((r)<<21)) #define J(op,c) gen((op)|(((ulong)(c)>>2)&0x3FFFFFFUL)) enum { Rzero = 0, Ro1 = 8, Ro2 = 9, Ro3 = 10, Ri = 11, Rj = 12, Rmp = 13, Rfp = 14, Rreg = 15, Rpic = 25, Rlink = 31, Rf1 = 4, Rf2 = 6, Olw = 0x23<<26, Olbu = 0x24<<26, Olhu = 0x25<<26, Osw = 0x2b<<26, Osb = 0x28<<26, Oaddui = 0x09<<26, Olui = 0x0f<<26, Oori = 0x0d<<26, Odiv = (0x00<<26) | 0x1a, Omul = (0x00<<26) | 0x18, Omfhi = (0x00<<26) | 0x10, Omflo = (0x00<<26) | 0x12, Osubu = (0x00<<26) | 0x23, Oaddu = (0x00<<26) | 0x21, Oand = (0x00<<26) | 0x24, Oor = (0x00<<26) | 0x25, Oxor = (0x00<<26) | 0x26, Odelay = (0x00<<26) | 0x27, Osll = (0x00<<26) | 0x00, Osrl = (0x00<<26) | 0x02, Osra = (0x00<<26) | 0x03, Osllv = (0x00<<26) | 0x04, Osrlv = (0x00<<26) | 0x06, Osrav = (0x00<<26) | 0x07, Oslt = (0x00<<26) | 0x2a, Osltu = (0x00<<26) | 0x2b, Obeq = 0x04<<26, Obne = 0x05<<26, Obltz = (0x01<<26) | (0x0<<16), Obgtz = (0x07<<26) | (0x0<<16), Oblez = (0x06<<26) | (0x0<<16), Obgez = (0x01<<26) | (0x1<<16), Ojr = (0x00<<26) | 0x08, Ojalr = (0x00<<26) | 0x09 | (Rlink<<11), Oj = (0x02<<26), Ojal = (0x03<<26), Olea = Oaddui, // pseudo op Olf = 0x31<<26, Osf = 0x39<<26, Oaddf = (0x11<<26) | (17<<21) | 0, Osubf = (0x11<<26) | (17<<21) | 1, Omulf = (0x11<<26) | (17<<21) | 2, Odivf = (0x11<<26) | (17<<21) | 3, Onegf = (0x11<<26) | (17<<21) | 7, Ocvtwf = (0x11<<26) | (20<<21) | 33, Ocvtfw = (0x11<<26) | (17<<21) | 36, Ofeq = (0x11<<26) | (17<<21) | (3<<4) | 2, Oflt = (0x11<<26) | (17<<21) | (3<<4) | 12, Obrf = (0x11<<26) | (0x100<<16), Obrt = (0x11<<26) | (0x101<<16), SRCOP = (1<<0), DSTOP = (1<<1), WRTPC = (1<<2), TCHECK = (1<<3), NEWPC = (1<<4), DBRAN = (1<<5), THREOP = (1<<6), ANDAND = 1, OROR, EQAND, XOR, IOR, AND, ADD, SUB, OMASK = (1<<4) - 1, REV1 = 1<<4, REV2 = 1<<5, MacRET = 0, MacFRP, MacINDX, MacCASE, MacLENA, MacFRAM, MacMOVM, MacCOLR, MacMCAL, MacMFRA, MacEND, NMACRO }; extern char Tmodule[]; void (*comvec)(void); extern void das(ulong*); static ulong* code; static ulong* base; static ulong* patch; static int pass; static int regdelay; static Module* mod; static ulong* tinit; static ulong* litpool; static int nlit; static ulong macro[NMACRO]; static void rdestroy(void); static void macret(void); static void macfrp(void); static void macindx(void); static void maccase(void); static void maclena(void); static void macfram(void); static void macmovm(void); static void maccvtfw(void); static void maccolr(void); static void macend(void); static void macmcal(void); static void macmfra(void); struct { int o; void (*f)(void); } macinit[] = { MacFRP, macfrp, /* decrement and free pointer */ MacRET, macret, /* return instruction */ MacCASE, maccase, /* case instruction */ MacCOLR, maccolr, /* increment and color pointer */ MacFRAM, macfram, /* frame instruction */ MacMCAL, macmcal, /* mcall bottom half */ MacMFRA, macmfra, /* punt mframe because t->initialize==0 */ MacMOVM, macmovm, MacLENA, maclena, MacINDX, macindx, MacEND, macend, 0 }; static void rdestroy(void) { destroy(R.s); } static void rmcall(void) { Prog *p; Frame *f; 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; t = (Type*)R.s; 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; } void urk(char *s) { print("urk: %s\n", s); exits(0); } void gen(ulong o) { *code++ = o; } void delay(void) { gen(Odelay); } int bigc(long c) { c >>= 15; if(c == 0 || c == -1) return 0; return 1; } void ldbigc(ulong c, int reg) { IRR(Olui, c>>16,Rzero,reg); IRR(Oori, c,reg,reg); } void ldc(ulong c, int reg) { if(bigc(c)) ldbigc(c, reg); else IRR(Oaddui, c,Rzero, reg); } void xchg(void) { ulong t; t = code[-1]; code[-1] = code[-2]; code[-2] = t; } void opx(int mode, Adr *a, int op, int reg, int del) { ulong c; int r, rx; switch(mode) { case AFP: c = a->ind; if(bigc(c)) urk("bigc op1b 1"); if(regdelay == Rfp) delay(); IRR(op, c,Rfp, reg); break; case AMP: c = a->ind; if(bigc(c)) urk("bigc op1b 2"); if(regdelay == Rmp) delay(); IRR(op, c,Rmp, reg); break; case AIMM: if(op == Olea) { if(a->imm != 0) { ldc(a->imm, reg); IRR(Osw, O(REG,st),Rreg, reg); } else IRR(Osw, O(REG,st),Rreg, Rzero); IRR(Oaddui, O(REG,st),Rreg, reg); } else ldc(a->imm, reg); return; case AIND|AFP: r = Rfp; goto offset; case AIND|AMP: r = Rmp; offset: if(regdelay == r) delay(); c = a->i.s; rx = Ri; if(op == Olea || op == Olw) rx = reg; IRR(Olw, a->i.f,r, rx); if(c != 0 || op != Oaddui) { delay(); IRR(op, c,rx, reg); } break; } if(op != Olea && del) delay(); regdelay = 0; } void op1(Inst *i, int op, int reg, int del) { opx(USRC(i->add), &i->s, op, reg, del); } void op3(Inst *i, int op, int reg, int del) { opx(UDST(i->add), &i->d, op, reg, del); } void op2(Inst *i, int op, int reg, int del) { switch(i->add & ARM) { case AXNON: op3(i, op, reg, del); return; case AXIMM: if(op == Olea) { if((short)i->reg != 0) { ldc((short)i->reg, reg); IRR(Osw, O(REG,t),Rreg, reg); } else IRR(Osw, O(REG,t),Rreg, Rzero); IRR(Oaddui, O(REG,t),Rreg, reg); } else ldc((short)i->reg, reg); return; case AXINF: IRR(op, i->reg,Rfp, reg); break; case AXINM: IRR(op, i->reg,Rmp, reg); break; } if(op != Olea && del) delay(); } ulong branch(Inst *i) { ulong rel; if(base == 0) return 0; rel = patch[(Inst*)i->d.imm - mod->prog]; rel += (base - code) - 1; return rel & 0xffff; } static void literal(ulong imm, int roff) { nlit++; ldbigc((ulong)litpool, Ro1); IRR(Osw, roff, Rreg, Ro1); if(pass == 0) return; *litpool = imm; litpool++; } void punt(Inst *i, int m, void (*fn)(void)) { ulong *cp, pc; if(m & SRCOP) { op1(i, Olea, Ro1, 1); IRR(Osw, O(REG,s),Rreg, Ro1); } if(m & DSTOP) { op3(i, Olea, Ro3, 1); IRR(Osw, O(REG,d),Rreg, Ro3); } if(m & WRTPC) { pc = patch[i-mod->prog+1]; ldbigc((ulong)(base+pc), Ro1); IRR(Osw, O(REG,PC),Rreg, Ro1); } if(m & DBRAN) { pc = patch[(Inst*)i->d.imm-mod->prog]; literal((ulong)(base+pc), O(REG, d)); } if((i->add&ARM) == AXNON) { if(m & THREOP) { delay(); IRR(Olw, O(REG,d),Rreg, Ro2); delay(); IRR(Osw, O(REG,m),Rreg, Ro2); } } else { op2(i, Olea, Ro2, 1); IRR(Osw, O(REG,m),Rreg, Ro2); } ldc((ulong)fn, Rpic); JR(Ojalr, Rpic); IRR(Osw, O(REG,FP),Rreg, Rfp); ldc((ulong)&R, Rreg); IRR(Olw, O(REG,FP),Rreg, Rfp); IRR(Olw, O(REG,MP),Rreg, Rmp); regdelay = Rmp; if(m & TCHECK) { IRR(Olw, O(REG,t),Rreg, Ro1); xchg(); cp = code; BRRI(Obeq,Ro1,Rzero,0); IRR(Olw, O(REG,xpc),Rreg, Ro2); delay(); JR(Ojr, Ro2); delay(); *cp |= (code - cp) - 1; regdelay = 0; } if(m & NEWPC) { IRR(Olw, O(REG,PC),Rreg, Ro1); if(m & TCHECK) delay(); else xchg(); JR(Ojr, Ro1); delay(); regdelay = 0; } } static void comgoto(Inst *i) { WORD *t, *e; op1(i, Olw, Ro2, 0); op3(i, Olea, Ro3, 0); SRR(Osll, 2, Ro2, Ro2); RRR(Oaddu, Ro2, Ro3, Ro3); IRR(Olw, 0,Ro3, Ro1); delay(); JR(Ojr, Ro1); delay(); if(pass == 0) return; t = (WORD*)(mod->origmp+i->d.ind); e = t + t[-1]; t[-1] = 0; while(t < e) { t[0] = (ulong)(base + patch[t[0]]); t++;