diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /libinterp/comp-sparc.c | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'libinterp/comp-sparc.c')
| -rw-r--r-- | libinterp/comp-sparc.c | 1882 |
1 files changed, 1882 insertions, 0 deletions
diff --git a/libinterp/comp-sparc.c b/libinterp/comp-sparc.c new file mode 100644 index 00000000..f6ca2aa6 --- /dev/null +++ b/libinterp/comp-sparc.c @@ -0,0 +1,1882 @@ +#include "lib9.h" +#include "isa.h" +#include "interp.h" +#include "raise.h" + +enum +{ + R8 = 8, /* SUN calls these %o0 - %o7 */ + R9 = 9, + R10 = 10, + R11 = 11, + R12 = 12, + R13 = 13, + R14 = 14, /* SUN %sp */ + R15 = 15, /* R15/%o7 is the default link register */ + + R16 = 16, /* SUN calls these %l0 - %l7 */ + R17 = 17, + R18 = 18, + R19 = 19, + R20 = 20, + R21 = 21, + R22 = 22, + R23 = 23, + RLINK = 15, + + RZ = 0, /* Always 0 */ + RFP = R23, /* Frame Pointer */ + RMP = R22, /* Module Pointer */ + RTA = R21, /* Intermediate address for double indirect */ + RREG = R20, /* Pointer to REG */ + RA3 = R19, /* gpr 3 */ + RA2 = R18, /* gpr 2 2+3 = L */ + RA1 = R17, /* gpr 1 */ + RA0 = R16, /* gpr 0 0+1 = L */ + + RCON = R8, /* Constant builder */ + + FA2 = 2, /* Floating */ + FA3 = 3, + FA4 = 4, + FA5 = 5, + + Olea = (1<<20), /* Pseudo op */ + Owry = 48, + Omul = 11, + Oumul = 10, + Osdiv = 15, + Osll = 37, + Osra = 39, + Osrl = 38, + Osethi = 4, + Oadd = 0, + Oaddcc = 16, + Oaddx = 8, + Osub = 4, + Osubcc = 20, + Osubx = 12, + Oor = 2, + Oand = 1, + Oxor = 3, + Oldw = 0, + Oldsh = 10, + Ostw = 4, + Osth = 6, + Ojmpl = 56, + Ocall = 1, + Ocmp = 20, /* subcc */ + Oldbu = 1, + Ostb = 5, + Oba = 8, + Obn = 0, + Obne = 9, + Obe = 1, + Obg = 10, + Oble = 2, + Obge = 11, + Obl = 3, + Obgu = 12, + Obleu = 4, + Obcc = 13, + Obcs = 5, + Obpos = 14, + Obneg = 6, + Obvc = 15, + Obvs = 7, + OfaddD = 66, + OfsubD = 70, + OfdivD = 78, + OfmulD = 74, + Oldf = 32, + Ostf = 36, + OfDtoQ = 206, + OfnegS = 5, + OfcmpD = 82, + Ofba = 8, + Ofbe = 9, + Ofbg = 6, + Ofbge = 11, + Ofbl = 4, + Ofble = 13, + Ofbne = 1, + OfWtoD = 200, + OfDtoW = 210, + Osave = 60, + Orestore= 61, + + 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 = 1, + MacCASE = 2, + MacCOLR = 3, + MacMCAL = 4, + MacFRAM = 5, + MacMFRA = 6, + NMACRO +}; + +#define OP(n) (n<<30) +#define I13(i) ((i)&0x1fff) +#define D22(i) ((i)&0x3fffff) +#define PC30(pc) (((ulong)(pc) - (ulong)code)>>2) + +#define CALL(addr) *code=OP(1)|PC30(addr); code++ +#define FM2I(op2, i, rd) *code=OP(0)|(rd<<25)|(op2<<22)|D22(i); code++ +#define BRA(cond, disp) *code=OP(0)|(cond<<25)|(2<<22)|D22((disp)); code++ +#define BRAF(cond, disp) *code=OP(0)|(cond<<25)|(6<<22)|D22((disp)); code++ +#define BRADIS(r, o) BRA(r, ((ulong)(base+patch[o])-(ulong)code)>>2) +#define BRAFDIS(r, o) BRAF(r, ((ulong)(base+patch[o])-(ulong)code)>>2) +#define BRAMAC(r, o) BRA(r, ((ulong)(base+macro[o])-(ulong)code)>>2); +#define FM3I(op, op3, i, rs1, rd) *code++=OP(op)|(rd<<25)|(op3<<19)|(rs1<<14)|\ + (1<<13)|I13(i) +#define FM3(op, op3, rs2, rs1, rd) *code++=OP(op)|(rd<<25)|(op3<<19)|(rs1<<14)|rs2 +#define FMF1(opf, rs2, rs1, rd) *code++=OP(2)|(rd<<25)|(52<<19)|(rs1<<14)|(opf<<5)|rs2 +#define FMF2(opf, rs2, rs1, rd) *code++=OP(2)|(rd<<25)|(53<<19)|(rs1<<14)|(opf<<5)|rs2 +#define NOOP *code++=(4<<22) +#define RETURN FM3I(2, Ojmpl, 8, RLINK, RZ); +#define MOV(s, d) FM3(2, Oor, s, RZ, d) + +#define RELPC(pc) (ulong)(base+pc) +#define PATCH(ptr) *ptr |= (code-ptr) & 0x3fffff + +static ulong* code; +static ulong* base; +static ulong* patch; +static int pass; +static int puntpc = 1; +static Module* mod; +static uchar* tinit; +static ulong* litpool; +static int nlit; +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 ulong macro[NMACRO]; + void (*comvec)(void); +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 */ +}; + +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; + + 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(void) +{ + error(exCompile); +} + +static int +bc(long c) +{ + c &= ~0xfffL; + if (c == 0 || c == ~0xfffL) + return 1; + + return 0; +} + +static void +con(ulong o, int r, int opt) +{ + if(opt != 0) { + if(bc(o)) { + FM3I(2, Oadd, o & 0x1fff, RZ, r); + return; + } + if((o & 0x3ff) == 0) { + FM2I(Osethi, o>>10, r); + return; + } + } + FM2I(Osethi, o>>10, r); + FM3I(2, Oadd, o & 0x3ff, r, r); +} + +static void +mem(int inst, ulong disp, int rm, int r) +{ + int op; + + op = 3; + if(inst == Olea) { + op = 2; + inst = Oadd; + } + if(bc(disp)) { + FM3I(op, inst, disp, rm, r); + return; + } + con(disp, RCON, 1); + FM3(op, inst, RCON, rm, r); +} + +static void +opwld(Inst *i, int mi, int r) +{ + int ir, rta; + + switch(UXSRC(i->add)) { + default: + print("%D\n", i); + urk(); + case SRC(AFP): + mem(mi, i->s.ind, RFP, r); + return; + case SRC(AMP): + mem(mi, i->s.ind, RMP, r); + return; + case SRC(AIMM): + con(i->s.imm, r, 1); + if(mi == Olea) { + mem(Ostw, O(REG, st), RREG, r); + con((ulong)&R.st, r, 1); + } + return; + case SRC(AIND|AFP): + ir = RFP; + break; + case SRC(AIND|AMP): + ir = RMP; + break; + } + rta = RTA; + if(mi == Olea) + rta = r; + mem(Oldw, i->s.i.f, ir, rta); + mem(mi, i->s.i.s, rta, r); +} + +static void +opwst(Inst *i, int mi, int r) +{ + int ir, rta; + + switch(UXDST(i->add)) { + default: + print("%D\n", i); + urk(); + case DST(AIMM): + con(i->d.imm, r, 1); + return; + case DST(AFP): + mem(mi, i->d.ind, RFP, r); + return; + case DST(AMP): + mem(mi, i->d.ind, RMP, r); + return; + case DST(AIND|AFP): + ir = RFP; + break; + case DST(AIND|AMP): + ir = RMP; + break; + } + rta = RTA; + if(mi == Olea) + rta = r; + mem(Oldw, i->d.i.f, ir, rta); + mem(mi, i->d.i.s, rta, r); +} + +static void +opfl(Adr *a, int am, int mi, int r) +{ + int ir; + + switch(am) { + default: + urk(); + case AFP: + mem(mi, a->ind, RFP, r); + mem(mi, a->ind+4, RFP, r+1); + return; + case AMP: + mem(mi, a->ind, RMP, r); + mem(mi, a->ind+4, RMP, r+1); + return; + case AIND|AFP: + ir = RFP; + break; + case AIND|AMP: + ir = RMP; + break; + } + mem(Oldw, a->i.f, ir, RTA); + mem(mi, a->i.s, RTA, r); + mem(mi, a->i.s+4, RTA, r+1); +} + +static void +opflld(Inst *i, int mi, int r) +{ + opfl(&i->s, USRC(i->add), mi, r); +} + +static void +opflst(Inst *i, int mi, int r) +{ + opfl(&i->d, UDST(i->add), mi, r); +} + +static void +literal(ulong imm, int roff) +{ + nlit++; + + con((ulong)litpool, RTA, 0); + mem(Ostw, roff, RREG, RTA); + + if(pass == 0) + return; + + *litpool = imm; + litpool++; +} + +static void +punt(Inst *i, int m, void (*fn)(void)) +{ + ulong pc; + + if(m & SRCOP) { + if(UXSRC(i->add) == SRC(AIMM)) + literal(i->s.imm, O(REG, s)); + else { + opwld(i, Olea, RA0); + mem(Ostw, O(REG, s), RREG, RA0); + } + } + + if(m & DSTOP) { + opwst(i, Olea, RA0); + mem(Ostw, O(REG, d), RREG, RA0); + } + if(m & WRTPC) { + con(RELPC(patch[i-mod->prog+1]), RA0, 0); + mem(Ostw, O(REG, PC), RREG, RA0); + } + if(m & DBRAN) { + pc = patch[(Inst*)i->d.imm-mod->prog]; + literal(RELPC(pc), O(REG, d)); + } + + switch(i->add&ARM) { + case AXNON: + if(m & THREOP) { + mem(Oldw, O(REG, d), RREG, RA0); + mem(Ostw, O(REG, m), RREG, RA0); + } + break; + case AXIMM: + literal((short)i->reg, O(REG, m)); + break; + case AXINF: + mem(Olea, i->reg, RFP, RA0); + mem(Ostw, O(REG, m), RREG, RA0); + break; + case AXINM: + mem(Olea, i->reg, RMP, RA0); + mem(Ostw, O(REG, m), RREG, RA0); + break; + } + + CALL(fn); + mem(Ostw, O(REG, FP), RREG, RFP); + + con((ulong)&R, RREG, 1); + if(m & TCHECK) { + mem(Oldw, O(REG, t), RREG, RA0); + FM3I(2, Ocmp, 0, RA0, RZ); + BRA(Obe, 5); + NOOP; + mem(Oldw, O(REG, xpc), RREG, RLINK); + RETURN; + NOOP; + } + + mem(Oldw, O(REG, FP), RREG, RFP); + mem(Oldw, O(REG, MP), RREG, RMP); + + if(m & NEWPC) { + mem(Oldw, O(REG, PC), RREG, RA0); + FM3I(2, Ojmpl, 0, RA0, RZ); + NOOP; + } +} + +static void +midfl(Inst *i, int mi, int r) +{ + int ir; + + switch(i->add&ARM) { + default: + opflst(i, mi, r); + return; + case AXIMM: + con((short)i->reg, r, 1); + return; + case AXINF: + ir = RFP; + break; + case AXINM: + ir = RMP; + break; + } + mem(mi, i->reg, ir, r); + mem(mi, i->reg+4, ir, r+1); +} + +static void +mid(Inst *i, int mi, int r) +{ + int ir; + + switch(i->add&ARM) { + default: + opwst(i, mi, r); + return; + case AXIMM: + con((short)i->reg, r, 1); + return; + case AXINF: + ir = RFP; + break; + case AXINM: + ir = RMP; + break; + } + mem(mi, i->reg, ir, r); +} + +static void +cbral(Inst *i, int jmsw, int jlsw, int mode) +{ + ulong dst, *label; + + opwld(i, Olea, RA1); + mid(i, Olea, RA3); + mem(Oldw, 0, RA1, RA2); + mem(Oldw, 0, RA3, RA0); + FM3(2, Ocmp, RA0, RA2, RZ); + label = nil; + dst = i->d.ins-mod->prog; + switch(mode) { + case ANDAND: + label = code; + BRA(jmsw, 0); + break; + case OROR: + BRADIS(jmsw, dst); + break; + case EQAND: + BRADIS(jmsw, dst); + NOOP; + label = code; + BRA(Obne, 0); + break; + } + NOOP; + mem(Oldw, 4, RA3, RA0); + mem(Oldw, 4, RA1, RA2); + FM3(2, Ocmp, RA0, RA2, RZ); + BRADIS(jlsw, dst); + if(label != nil) + PATCH(label); +} + +static void +comcase(Inst *i, int w) +{ + int l; + WORD *t, *e; + + if(w != 0) { + opwld(i, Oldw, RA0); // v + opwst(i, Olea, RCON); // table + BRAMAC(Oba, MacCASE); + NOOP; + } + + t = (WORD*)(mod->origmp+i->d.ind+4); + l = t[-1]; + + /* have to take care not to relocate the same table twice - + * the limbo compiler can duplicate a case instruction + * during its folding phase + */ + + if(pass == 0) { + if(l >= 0) + t[-1] = -l-1; /* Mark it not done */ + return; + } + if(l >= 0) /* Check pass 2 done */ + return; + t[-1] = -l-1; /* Set real count */ + e = t + t[-1]*3; + while(t < e) { + t[2] = RELPC(patch[t[2]]); + t += 3; + } + t[0] = RELPC(patch[t[0]]); +} + +static void +comcasel(Inst *i) +{ + int l; + WORD *t, *e; + + t = (WORD*)(mod->origmp+i->d.ind+8); + l = t[-2]; + if(pass == 0) { + if(l >= 0) + t[-2] = -l-1; /* Mark it not done */ + return; + } + if(l >= 0) /* Check pass 2 done */ + return; + t[-2] = -l-1; /* Set real count */ + e = t + t[-2]*6; + while(t < e) { + t[4] = RELPC(patch[t[4]]); + t += 6; + } + t[0] = RELPC(patch[t[0]]); +} + +static void +commframe(Inst *i) +{ + int o; + ulong *punt, *mlnil; + + opwld(i, Oldw, RA0); + FM3I(2, Ocmp, -1, RA0, RZ); + mlnil = code; + BRA(Obe, 0); + NOOP; + + if((i->add&ARM) == AXIMM) { + o = OA(Modlink, links)+i->reg*sizeof(Modl)+O(Modl, frame); + mem(Oldw, o, RA0, RA3); + } else { + mid(i, Oldw, RA1); + FM3I(2, Osll, 3, RA1, RA1); // assumes sizeof(Modl) == 8 + FM3(2, Oadd, RA0, RA1, RA1); + o = OA(Modlink, links)+O(Modl, frame); + mem(Oldw, o, RA1, RA3); + } + mem(Oldw, O(Type, initialize), RA3, RA1); + FM3I(2, Ocmp, 0, RA1, RZ); + punt = code; + BRA(Obne, 0); + NOOP; + + opwst(i, Olea, RA0); + + /* Type in RA3, destination in RA0 */ + PATCH(mlnil); + con(RELPC(patch[i-mod->prog+1])-8, RLINK, 0); + BRAMAC(Oba, MacMFRA); + NOOP; + + /* Type in RA3 */ + PATCH(punt); + CALL(base+macro[MacFRAM]); + NOOP; + opwst(i, Ostw, RA2); +} + +static void +commcall(Inst *i) +{ + opwld(i, Oldw, RA2); + con(RELPC(patch[i-mod->prog+1]), RA0, 0); + mem(Ostw, O(Frame, lr), RA2, RA0); + mem(Ostw, O(Frame, fp), RA2, RFP); + mem(Oldw, O(REG, M), RREG, RA3); + mem(Ostw, O(Frame, mr), RA2, RA3); + opwst(i, Oldw, RA3); + if((i->add&ARM) == AXIMM) { + CALL(base+macro[MacMCAL]); + mem(Oldw, OA(Modlink, links)+i->reg*sizeof(Modl)+O(Modl, u.pc), RA3, RA0); + } else { + mid(i, Oldw, RA1); + FM3I(2, Osll, 3, RA1, RA1); // assumes sizeof(Modl) == 8 + FM3(2, Oadd, RA1, RA3, RA0); + CALL(base+macro[MacMCAL]); + mem(Oldw, OA(Modlink, links)+O(Modl, u.pc), RA0, RA0); + } +} + +static void +larith(Inst *i, int op, int opc) +{ + opflld(i, Oldw, RA0); + midfl(i, Oldw, RA2); + FM3(2, op, RA1, RA3, RA1); + FM3(2, opc, RA0, RA2, RA0); + opflst(i, Ostw, RA0); +} + +static void +movloop(Inst *i, int ld, int st) +{ + int s; + + s = 1; + if(ld == Oldw) + s = 4; + opwld(i, Olea, RA1); + opwst(i, Olea, RA2); + mem(ld, 0, RA1, RA0); + mem(st, 0, RA2, RA0); + FM3I(2, Oadd, s, RA2, RA2); + FM3I(2, Oaddcc, -1, RA3, RA3); + BRA(Obne, -4); + FM3I(2, Oadd, s, RA1, RA1); +} + +static +void +compdbg(void) +{ + print("%s:%d@%.8ux\n", R.M->m->name, R.t, R.st); +} + +static void +shll(Inst *i) +{ + ulong *lab0, *lab1, *lab2; + + opwld(i, Oldw, RA2); + midfl(i, Oldw, RA0); + FM3I(2, Ocmp, RZ, RA2, RZ); + lab0 = code; + BRA(Obe, 0); + FM3I(2, Ocmp, 32, RA2, RZ); + lab1 = code; + BRA(Obl, 0); + NOOP; + FM3I(2, Osub, 32, RA2, RA2); + FM3(2, Osll, RA2, RA1, RA0); + lab2 = code; + BRA(Oba, 0); + MOV(RZ, RA1); + + PATCH(lab1); + FM3(2, Osll, RA2, RA0, RA0); + con(32, RA3, 1); + FM3(2, Osub, RA2, RA3, RA3); + FM3(2, Osrl, RA3, RA1, RA3); + FM3(2, Oor, RA0, RA3, RA0); + FM3(2, Osll, RA2, RA1, RA1); + + PATCH(lab0); + PATCH(lab2); + opflst(i, Ostw, RA0); +} + +static void +comp(Inst *i) +{ + int r; + WORD *t, *e; + char buf[64]; + + if(0) { + Inst xx; + xx.add = AXIMM|SRC(AIMM); + xx.s.imm = (ulong)code; + xx.reg = i-mod->prog; + puntpc = 0; + punt(&xx, SRCOP, compdbg); + puntpc = 1; + } + + switch(i->op) { + default: + snprint(buf, sizeof buf, "%s compile, no '%D'", mod->name, i); + error(buf); + break; + case IMCALL: + if((i->add&ARM) == AXIMM) + commcall(i); + else + punt(i, SRCOP|DSTOP|THREOP|WRTPC|NEWPC, optab[i->op]); + break; + case ISEND: + case IRECV: + case IALT: + punt(i, SRCOP|DSTOP|TCHECK|WRTPC, optab[i->op]); + break; + case ISPAWN: + punt(i, SRCOP|DBRAN, optab[i->op]); + break; + case IBNEC: + case IBEQC: + case IBLTC: + case IBLEC: + case IBGTC: + case IBGEC: + punt(i, SRCOP|DBRAN|NEWPC|WRTPC, optab[i->op]); + break; + case ICASEC: + comcase(i, 0); + punt(i, SRCOP|DSTOP|NEWPC, optab[i->op]); + break; + case ICASEL: + comcasel(i); + punt(i, SRCOP|DSTOP|NEWPC, optab[i->op]); + break; + case IADDC: + case IMULL: + case IDIVL: + case IMODL: + case IMODW: + case IMODB: + case IMNEWZ: + punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); + break; + case ILOAD: + case INEWA: + case INEWAZ: + case INEW: + case INEWZ: + case ISLICEA: + case ISLICELA: + case ICONSB: + case ICONSW: + case ICONSL: + case ICONSF: + case ICONSM: + case ICONSMP: + case ICONSP: + case IMOVMP: + case IHEADMP: + case IHEADM: + case IHEADB: + case IHEADW: + case IHEADL: + case IHEADF: + case IINDC: + case ILENC: + case IINSC: + case ICVTAC: + case ICVTCW: + case ICVTWC: + case ICVTLC: + case ICVTCL: + case ICVTFC: + case ICVTCF: + case ICVTRF: + case ICVTFR: + case IMSPAWN: + case ICVTCA: + case ISLICEC: + case INBALT: + punt(i, SRCOP|DSTOP, optab[i->op]); + break; + case INEWCM: + case INEWCMP: + punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); + break; + case IMFRAME: + if((i->add&ARM) == AXIMM) + commframe(i); + else + punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); + break; + case ICASE: + comcase(i, 1); + break; + case IGOTO: + opwld(i, Oldw, RA1); + opwst(i, Olea, RA0); + FM3I(2, Osll, 2, RA1, RA1); + FM3(3, Oldw, RA1, RA0, RA0); + FM3I(2, Ojmpl, 0, RA0, RZ); + NOOP; + + if(pass == 0) + break; + + t = (WORD*)(mod->origmp+i->d.ind); + e = t + t[-1]; + t[-1] = 0; + while(t < e) { + t[0] = RELPC(patch[t[0]]); + t++; + } + break; + case IMOVL: + movl: + opflld(i, Oldw, RA0); + opflst(i, Ostw, RA0); + break; + case IMOVM: + if((i->add&ARM) == AXIMM) { + if(i->reg == 8) + goto movl; + if((i->reg&3) == 0) { + con(i->reg>>2, RA3, 1); + movloop(i, Oldw, Ostw); + break; + } + } + mid(i, Oldw, RA3); + movloop(i, Oldbu, Ostb); + break; + case IFRAME: + if(UXSRC(i->add) != SRC(AIMM)) { + punt(i, SRCOP|DSTOP, optab[i->op]); + break; + } + tinit[i->s.imm] = 1; + con((ulong)mod->type[i->s.imm], RA3, 1); + CALL(base+macro[MacFRAM]); + NOOP; + opwst(i, Ostw, RA2); + break; + case INEWCB: + case INEWCW: + case INEWCF: + case INEWCP: + case INEWCL: + punt(i, DSTOP|THREOP, optab[i->op]); + break; + case IEXIT: + punt(i, 0, optab[i->op]); + break; + case ICVTBW: + opwld(i, Oldbu, RA0); + opwst(i, Ostw, RA0); + break; + case ICVTWB: + opwld(i, Oldw, RA0); + opwst(i, Ostb, RA0); + break; + case ILEA: + opwld(i, Olea, RA0); + opwst(i, Ostw, RA0); + break; + case IMOVW: + opwld(i, Oldw, RA0); + opwst(i, Ostw, RA0); + break; + case IMOVB: + opwld(i, Oldbu, RA0); + opwst(i, Ostb, RA0); + break; + case ICVTSW: + opwld(i, Oldsh, RA0); + opwst(i, Ostw, RA0); + break; + case ICVTWS: + opwld(i, Oldw, RA0); + opwst(i, Osth, RA0); + break; + case ITAIL: + opwld(i, Oldw, RA0); + mem(Oldw, O(List, tail), RA0, RA1); + goto movp; + case IMOVP: + case IHEADP: + opwld(i, Oldw, RA1); + if(i->op == IHEADP) + mem(Oldw, OA(List, data), RA1, RA1); + movp: + FM3I(2, Ocmp, (ulong)H, RA1, RZ); + BRA(Obe, 5); + con((ulong)&mutator, RA2, 1); + CALL(base+macro[MacCOLR]); + mem(Oldw, O(Heap, ref)-sizeof(Heap), RA1, RA0); + opwst(i, Oldw, RA0); + opwst(i, Ostw, RA1); + CALL(base+macro[MacFRP]); + NOOP; + break; + case ILENA: + opwld(i, Oldw, RA1); + FM3I(2, Ocmp, (ulong)H, RA1, RZ); + BRA(Obe, 3); + con(0, RA0, 1); + mem(Oldw, O(Array, len), RA1, RA0); + opwst(i, Ostw, RA0); + break; + case ILENL: + con(0, RA0, 1); + opwld(i, Oldw, RA1); + FM3I(2, Ocmp, (ulong)H, RA1, RZ); + BRA(Obe, 5); + NOOP; + mem(Oldw, O(List, tail), RA1, RA1); + BRA(Oba, -4); + FM3I(2, Oadd, 1, RA0, RA0); + opwst(i, Ostw, RA0); + break; + case ICALL: + opwld(i, Oldw, RA0); + con(RELPC(patch[i-mod->prog+1]), RA1, 0); + mem(Ostw, O(Frame, lr), RA0, RA1); + mem(Ostw, O(Frame, fp), RA0, RFP); + BRADIS(Oba, i->d.ins-mod->prog); + MOV(RA0, RFP); + break; + case IJMP: + BRADIS(Oba, i->d.ins-mod->prog); + NOOP; + break; + case IBEQW: + r = Obe; + braw: + opwld(i, Oldw, RA1); + mid(i, Oldw, RA0); + FM3(2, Ocmp, RA0, RA1, RZ); + BRADIS(r, i->d.ins-mod->prog); + NOOP; + break; + case IBNEW: + r = Obne; + goto braw; + case IBLTW: + r = Obl; + goto braw; + case IBLEW: + r = Oble; + goto braw; + case IBGTW: + r = Obg; + goto braw; + case IBGEW: + r = Obge; + goto braw; + case IBEQB: + r = Obe; + brab: + opwld(i, Oldbu, RA1); + mid(i, Oldbu, RA0); + FM3(2, Ocmp, RA0, RA1, RZ); + BRADIS(r, i->d.ins-mod->prog); + NOOP; + break; + case IBNEB: + r = Obne; + goto brab; + case IBLTB: + r = Obl; + goto brab; + case IBLEB: + r = Oble; + goto brab; + case IBGTB: + r = Obg; + goto brab; + case IBGEB: + r = Obge; + goto brab; + case IBEQF: + r = Ofbe; + braf: + opflld(i, Oldf, FA4); + midfl(i, Oldf, FA2); + FMF2(OfcmpD, FA2, FA4, 0); + NOOP; + BRAFDIS(r, i->d.ins-mod->prog); + NOOP; + break; + case IBNEF: + r = Ofbne; + goto braf; + case IBLTF: + r = Ofbl; + goto braf; + case IBLEF: + r = Ofble; + goto braf; + case IBGTF: + r = Ofbg; + goto braf; + case IBGEF: + r = Ofbge; + goto braf; + case IRET: + BRAMAC(Oba, MacRET); + mem(Oldw, O(Frame,t), RFP, RA1); + break; + case IORW: + r = Oor; + goto arithw; + case IANDW: + r = Oand; + goto arithw; + case IXORW: + r = Oxor; + goto arithw; + case ISUBW: + r = Osub; + goto arithw; + case ISHRW: + r = Osra; + goto arithw; + case ISHLW: + r = Osll; + goto arithw; + case ILSRW: + r = Osrl; + goto arithw; + case IMULW: + r = Omul; + goto arithw; + case IDIVW: + r = Osdiv; + goto arithw; + case IADDW: + r = Oadd; + arithw: + mid(i, Oldw, RA1); + if(i->op == IDIVW) { + FM3I(2, Osra, 31, RA1, RA0); + FM3(2, Owry, RZ, RA0, 0); + } + if(UXSRC(i->add) == SRC(AIMM) && bc(i->s.imm)) + FM3I(2, r, i->s.imm, RA1, RA0); + else { + opwld(i, Oldw, RA0); + FM3(2, r, RA0, RA1, RA0); + } + opwst(i, Ostw, RA0); + break; + case IORB: + r = Oor; + goto arithb; + case IANDB: + r = Oand; + goto arithb; + case IXORB: + r = Oxor; + goto arithb; + case ISUBB: + r = Osub; + goto arithb; + case IMULB: + r = Omul; + goto arithb; + case IDIVB: + FM3(2, Owry, RZ, RZ, 0); + r = Osdiv; + goto arithb; + case IADDB: + r = Oadd; + arithb: + mid(i, Oldbu, RA1); + opwld(i, Oldbu, RA0); + FM3(2, r, RA0, RA1, RA0); + opwst(i, Ostb, RA0); + break; + case ISHRB: + r = Osra; + goto shiftb; + case ISHLB: + r = Osll; + shiftb: + mid(i, Oldbu, RA1); + if(UXSRC(i->add) == SRC(AIMM) && bc(i->s.imm)) + FM3I(2, r, i->s.imm, RA1, RA0); + else { + opwld(i, Oldw, RA0); + FM3(2, r, RA0, RA1, RA0); + } + opwst(i, Ostb, RA0); + break; + case IINDL: + case IINDF: + case IINDW: + case IINDB: + opwld(i, Oldw, RA0); /* a */ + r = 0; + switch(i->op) { + case IINDL: + case IINDF: + r = 3; + break; + case IINDW: + r = 2; + break; + } + if(UXDST(i->add) == DST(AIMM) && bc(i->d.imm<<r)) { + mem(Oldw, O(Array, data), RA0, RA0); + FM3I(2, Oadd, (i->d.imm<<r), RA0, RA0); + } + else { + opwst(i, Oldw, RA1); + mem(Oldw, O(Array, data), RA0, RA0); + if(r != 0) + FM3I(2, Osll, r, RA1, RA1); + FM3(2, Oadd, RA0, RA1, RA0); + } + r = RMP; + if((i->add&ARM) == AXINF) + r = RFP; + mem(Ostw, i->reg, r, RA0); + break; + case IINDX: + opwld(i, Oldw, RA0); /* a */ + /* + r = 0; + if(UXDST(i->add) == DST(AIMM) && bc(i->d.imm<<r)) + r = i->d.imm<<r; + else + */ + opwst(i, Oldw, RA1); /* i */ + mem(Oldw, O(Array, t), RA0, RA2); + mem(Oldw, O(Array, data), RA0, RA0); + mem(Oldw, O(Type, size), RA2, RA2); + /* + if(r != 0) + FM3I(2, Oumul, r, RA2, RA1); + else + */ + FM3(2, Oumul, RA1, RA2, RA1); + FM3(2, Oadd, RA0, RA1, RA0); + r = RMP; + if((i->add&ARM) == AXINF) + r = RFP; + mem(Ostw, i->reg, r, RA0); + break; + case IADDL: + larith(i, Oaddcc, Oaddx); + break; + case ISUBL: + larith(i, Osubcc, Osubx); + break; + case IORL: + larith(i, Oor, Oor); + break; + case IANDL: + larith(i, Oand, Oand); + break; + case IXORL: + larith(i, Oxor, Oxor); + break; + case ICVTWL: + opwld(i, Oldw, RA1); + FM3I(2, Osra, 31, RA1, RA0); + opflst(i, Ostw, RA0); + break; + case ICVTLW: + opwld(i, Olea, RA0); + mem(Oldw, 4, RA0, RA0); + opwst(i, Ostw, RA0); + break; + case IBEQL: + cbral(i, Obne, Obe, ANDAND); + break; + case IBNEL: + cbral(i, Obne, Obne, OROR); + break; + case IBLEL: + cbral(i, Obl, Obleu, EQAND); + break; + case IBGTL: + cbral(i, Obg, Obgu, EQAND); + break; + case IBLTL: + cbral(i, Obl, Obcs, EQAND); + break; + case IBGEL: + cbral(i, Obg, Obcc, EQAND); + break; + case IMOVF: + opflld(i, Oldf, FA2); + opflst(i, Ostf, FA2); + break; + case IDIVF: + r = OfdivD; + goto arithf; + case IMULF: + r = OfmulD; + goto arithf; + case ISUBF: + r = OfsubD; + goto arithf; + case IADDF: + r = OfaddD; + arithf: + opflld(i, Oldf, FA2); + midfl(i, Oldf, FA4); + FMF1(r, FA2, FA4, FA4); + opflst(i, Ostf, FA4); + break; + case INEGF: + opflld(i, Oldf, FA2); + FMF1(OfnegS, FA2, 0, FA2); + opflst(i, Ostf, FA2); + break; + case ICVTFL: + // >= Sparc 8 + // opflld(i, Oldf, FA2); + // FMF1(OfDtoQ, FA2, 0, FA2); + // opflst(i, Ostf, FA2); + punt(i, SRCOP|DSTOP, optab[i->op]); + break; + case ICVTLF: + // >= Sparc 8 + // opflld(i, Oldf, FA2); + // FMF1(OfQtoD, FA2, 0, FA2); + // opflst(i, Ostf, FA2); + punt(i, SRCOP|DSTOP, optab[i->op]); + break; + case ICVTWF: + opwld(i, Oldf, FA2); + FMF1(OfWtoD, FA2, 0, FA2); + opflst(i, Ostf, FA2); + break; + case ICVTFW: + opflld(i, Oldf, FA2); + FMF1(OfDtoW, FA2, 0, FA2); + opwst(i, Ostf, FA2); + break; + case ISHLL: + shll(i); + break; + case ISHRL: + case ILSRL: + punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); + break; + case IRAISE: + punt(i, SRCOP|WRTPC|NEWPC, optab[i->op]); + break; + case IMULX: + case IDIVX: + case ICVTXX: + case IMULX0: + case IDIVX0: + case ICVTXX0: + case IMULX1: + case IDIVX1: + case ICVTXX1: + case ICVTFX: + case ICVTXF: + case IEXPW: + case IEXPL: + case IEXPF: + punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); + break; + case ISELF: + punt(i, DSTOP, optab[i->op]); + break; + } +} + +static void +preamble(void) +{ + ulong *start; + + if(comvec) + return; + + comvec = malloc(10 * sizeof(*code)); + if(comvec == nil) + error(exNomem); + code = (ulong*)comvec; + start = code; + + con((ulong)&R, RREG, 1); + mem(Ostw, O(REG, xpc), RREG, RLINK); + mem(Oldw, O(REG, PC), RREG, RA0); + mem(Oldw, O(REG, FP), RREG, RFP); + FM3I(2, Ojmpl, 0, RA0, RZ); + mem(Oldw, O(REG, MP), RREG, RMP); + + segflush(comvec, 10 * sizeof(*code)); + + if(cflag > 4) { + print("comvec:\n"); + das(start, code-start); + } +} + +static void +maccase(void) +{ + ulong *loop, *def, *lab1; + + mem(Oldw, 0, RCON, RA3); // n = t[0] + FM3I(2, Oadd, 4, RCON, RCON); + MOV(RA3, RA1); + FM3I(2, Osll, 1, RA1, RA1); + FM3(2, Oadd, RA3, RA1, RA1); + FM3I(2, Osll, 2, RA1, RA1); + FM3(3, Oldw, RCON, RA1, RLINK); + + loop = code; + FM3(2, Ocmp, RZ, RA3, RZ); + def = code; + BRA(Oble, 0); + NOOP; + + MOV(RA3, RA2); // MOVL DX, CX n2 = n + FM3I(2, Osra, 1, RA2, RA2); // SHR CX,1 n2 = n2>>1 + MOV(RA2, RA1); + FM3I(2, Osll, 1, RA1, RA1); + FM3(2, Oadd, RA2, RA1, RA1); + FM3I(2, Osll, 2, RA1, RA1); + + FM3(3, Oldw, RA1, RCON, RTA); // MOV (RA1+RCON), RTA + FM3(2, Ocmp, RTA, RA0, RZ); + lab1 = code; + BRA(Obge, 0); + NOOP; + MOV(RA2, RA3); // n = n2 + BRA(Oba, loop-code); + NOOP; + + PATCH(lab1); + FM3I(2, Oadd, 4, RA1, RTA); + FM3(3, Oldw, RTA, RCON, RTA); // MOV (RA1+RCON), RTA + FM3(2, Ocmp, RTA, RA0, RZ); + lab1 = code; + BRA(Obl, 0); + NOOP; + + FM3I(2, Oadd, 12, RA1, RTA); + FM3(2, Oadd, RTA, RCON, RCON); + FM3(2, Osub, RA2, RA3, RA3); // SUBL CX, DX n -= n2 + FM3I(2, Oadd, -1, RA3, RA3); // DECL DX n -= 1 + BRA(Oba, loop-code); + NOOP; + + PATCH(lab1); + FM3I(2, Oadd, 8, RA1, RTA); + FM3(3, Oldw, RTA, RCON, RLINK); + + PATCH(def); + FM3I(2, Ojmpl, 0, RLINK, RZ); + NOOP; +} + +static void +macfrp(void) +{ + ulong *lab1, *lab2; + + /* destroy the pointer in RA0 */ + FM3I(2, Ocmp, -1, RA0, RZ); + lab1 = code; + BRA(Obe, 0); + NOOP; + mem(Oldw, O(Heap, ref)-sizeof(Heap), RA0, RA2); + FM3I(2, Oadd, -1, RA2, RA2); + FM3I(2, Ocmp, 0, RA2, RZ); + lab2 = code; + BRA(Obne, 0); + NOOP; + mem(Ostw, O(REG, FP), RREG, RFP); + mem(Ostw, O(REG, st), RREG, RLINK); + CALL(rdestroy); + mem(Ostw, O(REG, s), RREG, RA0); + con((ulong)&R, RREG, 1); + mem(Oldw, O(REG, st), RREG, RLINK); + mem(Oldw, O(REG, FP), RREG, RFP); + RETURN; + mem(Oldw, O(REG, MP), RREG, RMP); + PATCH(lab2); + mem(Ostw, O(Heap, ref)-sizeof(Heap), RA0, RA2); + PATCH(lab1); + RETURN; + NOOP; +} + +static void +macret(void) +{ + Inst i; + ulong *cp1, *cp2, *cp3, *cp4, *cp5, *cp6; + + FM3I(2, Ocmp, 0, RA1, RZ); + cp1 = code; + BRA(Obe, 0); // t(Rfp) == 0 + NOOP; + + mem(Oldw, O(Type,destroy),RA1, RA0); + FM3I(2, Ocmp, 0, RA0, RZ); + cp2 = code; + BRA(Obe, 0); // destroy(t(fp)) == 0 + NOOP; + + mem(Oldw, O(Frame,fp),RFP, RA2); + FM3I(2, Ocmp, 0, RA2, RZ); + cp3 = code; + BRA(Obe, 0); // fp(Rfp) == 0 + NOOP; + + mem(Oldw, O(Frame,mr),RFP, RA3); + FM3I(2, Ocmp, 0, RA3, RZ); + cp4 = code; + BRA(Obe, 0); // mr(Rfp) == 0 + NOOP; + + mem(Oldw, O(REG,M),RREG, RA2); + mem(Oldw, O(Heap,ref)-sizeof(Heap),RA2, RA3); + FM3I(2, Oaddcc, -1, RA3, RA3); + cp5 = code; + BRA(Obe, 0); // --ref(arg) == 0 + NOOP; + mem(Ostw, O(Heap,ref)-sizeof(Heap),RA2, RA3); + + mem(Oldw, O(Frame,mr),RFP, RA1); + mem(Ostw, O(REG,M),RREG, RA1); + mem(Oldw, O(Modlink,compiled),RA1, RA2); // check for uncompiled code + mem(Oldw, O(Modlink,MP),RA1, RMP); + FM3I(2, Ocmp, 0, RA2, RZ); + cp6 = code; + BRA(Obe, 0); + NOOP; + mem(Ostw, O(REG,MP),RREG, RMP); + + PATCH(cp4); + FM3I(2, Ojmpl, 0, RA0, RLINK); // call destroy(t(fp)) + NOOP; + mem(Ostw, O(REG,SP),RREG, RFP); + mem(Oldw, O(Frame,lr),RFP, RA1); + mem(Oldw, O(Frame,fp),RFP, RFP); + mem(Ostw, O(REG,FP),RREG, RFP); + FM3I(2, Ojmpl, 0, RA1, RZ); // goto lr(Rfp) + NOOP; + + PATCH(cp6); + FM3I(2, Ojmpl, 0, RA0, RLINK); // call destroy(t(fp)) + NOOP; + mem(Ostw, O(REG,SP),RREG, RFP); + mem(Oldw, O(Frame,lr),RFP, RA1); + mem(Oldw, O(Frame,fp),RFP, RFP); + mem(Ostw, O(REG,FP),RREG, RFP); + mem(Oldw, O(REG,xpc),RREG, RA2); + FM3I(2, Oadd, 0x8, RA2, RA2); + FM3I(2, Ojmpl, 0, RA2, RZ); // return to uncompiled code + mem(Ostw, O(REG,PC),RREG, RA1); + + PATCH(cp1); + PATCH(cp2); + PATCH(cp3); + PATCH(cp5); + i.add = AXNON; + punt(&i, TCHECK|NEWPC, optab[IRET]); +} + +static void +maccolr(void) +{ + ulong *br; + + /* color the pointer in RA1 */ + FM3I(2, Oadd, 1, RA0, RA0); + mem(Ostw, O(Heap, ref)-sizeof(Heap), RA1, RA0); + mem(Oldw, O(Heap, color)-sizeof(Heap), RA1, RA0); + mem(Oldw, 0, RA2, RA2); + FM3(2, Ocmp, RA0, RA2, RZ); + br = code; + BRA(Obe, 0); + con(propagator, RA2, 1); + mem(Ostw, O(Heap, color)-sizeof(Heap), RA1, RA2); + con((ulong)&nprop, RA2, 1); + RETURN; + mem(Ostw, 0, RA2, RA2); + PATCH(br); + RETURN; + NOOP; +} + +static void +macmcal(void) +{ + ulong *lab1, *lab2; + + mem(Oldw, O(Modlink, prog), RA3, RA1); + FM3I(2, Ocmp, 0, RA1, RZ); + lab1 = code; + BRA(Obne, 0); + NOOP; + + mem(Ostw, O(REG, st), RREG, RLINK); + mem(Ostw, O(REG, FP), RREG, RA2); + CALL(rmcall); // CALL rmcall + mem(Ostw, O(REG, dt), RREG, RA0); + + con((ulong)&R, RREG, 1); // MOVL $R, RREG + mem(Oldw, O(REG, st), RREG, RLINK); + mem(Oldw, O(REG, FP), RREG, RFP); + mem(Oldw, O(REG, MP), RREG, RMP); + RETURN; + NOOP; + + PATCH(lab1); // patch: + FM3(2, Oor, RA2, RZ, RFP); + mem(Ostw, O(REG, M), RREG, RA3); // MOVL RA3, R.M + mem(Oldw, O(Heap, ref)-sizeof(Heap), RA3, RA1); + FM3I(2, Oadd, 1, RA1, RA1); + mem(Ostw, O(Heap, ref)-sizeof(Heap), RA3, RA1); + mem(Oldw, O(Modlink, compiled), RA3, RA1); + mem(Oldw, O(Modlink, MP), RA3, RMP); // MOVL R.M->MP, RMP + FM3I(2, Ocmp, 0, RA1, RZ); + lab2 = code; + BRA(Obe, 0); + mem(Ostw, O(REG, MP), RREG, RMP); // MOVL RA3, R.MP R.MP = ml->MP + + FM3I(2, Ojmpl, 0, RA0, RZ); + NOOP; + + PATCH(lab2); + mem(Ostw, O(REG,FP),RREG, RFP); + mem(Oldw, O(REG,xpc),RREG, RA1); + FM3I(2, Oadd, 0x8, RA1, RA1); + FM3I(2, Ojmpl, 0, RA1, RZ); // call to uncompiled code + mem(Ostw, O(REG,PC),RREG, RA0); +} + +static void +macfram(void) +{ + ulong *lab1; + + mem(Oldw, O(REG, SP), RREG, RA0); // MOVL R.SP, RA0 + mem(Oldw, O(Type, size), RA3, RA1); + FM3(2, Oadd, RA0, RA1, RA0); + mem(Oldw, O(REG, TS), RREG, RA1); + FM3(2, Ocmp, RA1, RA0, RZ); + lab1 = code; + BRA(Obl, 0); + NOOP; + + mem(Ostw, O(REG, s), RREG, RA3); + mem(Ostw, O(REG, st), RREG, RLINK); + CALL(extend); // CALL extend + mem(Ostw, O(REG, FP), RREG, RFP); // MOVL RFP, R.FP + + con((ulong)&R, RREG, 1); + mem(Oldw, O(REG, st), RREG, RLINK); + mem(Oldw, O(REG, FP), RREG, RFP); // MOVL R.MP, RMP + mem(Oldw, O(REG, s), RREG, RA2); // MOVL R.s, *R.d + mem(Oldw, O(REG, MP), RREG, RMP); // MOVL R.MP, RMP + RETURN; // RET + NOOP; + + PATCH(lab1); + mem(Oldw, O(REG, SP), RREG, RA2); // MOVL R.SP, RA2 + mem(Ostw, O(REG, SP), RREG, RA0); // MOVL RA0, R.SP + + mem(Ostw, O(Frame, t), RA2, RA3); // MOVL RA3, t(RA2) f->t = t + mem(Oldw, O(Type, initialize), RA3, RA3); + FM3I(2, Ojmpl, 0, RA3, RZ); + mem(Ostw, REGMOD*4, RA2, RZ); // MOVL $0, mr(RA2) f->mr +} + +static void +macmfra(void) +{ + mem(Ostw, O(REG, st), RREG, RLINK); + mem(Ostw, O(REG, s), RREG, RA3); // Save type + mem(Ostw, O(REG, d), RREG, RA0); // Save destination + CALL(rmfram); // CALL rmfram + mem(Ostw, O(REG, FP), RREG, RFP); + + con((ulong)&R, RREG, 1); + mem(Oldw, O(REG, st), RREG, RLINK); + mem(Oldw, O(REG, FP), RREG, RFP); + mem(Oldw, O(REG, MP), RREG, RMP); + RETURN; + NOOP; +} + +void +comd(Type *t) +{ + int i, j, m, c; + + mem(Ostw, O(REG, dt), RREG, RLINK); + for(i = 0; i < t->np; i++) { + c = t->map[i]; + j = i<<5; + for(m = 0x80; m != 0; m >>= 1) { + if(c & m) { + CALL(base+macro[MacFRP]); + mem(Oldw, j, RFP, RA0); + } + j += sizeof(WORD*); + } + } + mem(Oldw, O(REG, dt), RREG, RLINK); + RETURN; + NOOP; +} + +void +comi(Type *t) +{ + int i, j, m, c; + + con((ulong)H, RA0, 1); + for(i = 0; i < t->np; i++) { + c = t->map[i]; + j = i<<5; + for(m = 0x80; m != 0; m >>= 1) { + if(c & m) + mem(Ostw, j, RA2, RA0); + j += sizeof(WORD*); + } + } + RETURN; + NOOP; +} + +void +typecom(Type *t) +{ + int n; + ulong *tmp, *start; + + if(t == nil || t->initialize != 0) + return; + + tmp = mallocz(4096*sizeof(ulong), 0); + if(tmp == nil) + error(exNomem); + + code = tmp; + comi(t); + n = code - tmp; + code = tmp; + comd(t); + n += code - tmp; + free(tmp); + + n *= sizeof(*code); + code = mallocz(n, 0); + if(code == nil) + return; + + start = code; + t->initialize = code; + comi(t); + t->destroy = code; + comd(t); + + segflush(start, n); + + if(cflag > 1) + print("typ= %.8p %4d i %.8p d %.8p asm=%d\n", + t, t->size, t->initialize, t->destroy, n); +} + +static void +patchex(Module *m, ulong *p) +{ + Handler *h; + Except *e; + + if((h = m->htab) == nil) + return; + for( ; h->etab != nil; h++){ + h->pc1 = p[h->pc1]; + h->pc2 = p[h->pc2]; + for(e = h->etab; e->s != nil; e++) + e->pc = p[e->pc]; + if(e->pc != -1) + e->pc = p[e->pc]; + } +} + +int +compile(Module *m, int size, Modlink *ml) +{ + Link *l; + Modl *e; + int i, n; + ulong *s, *tmp; + + base = nil; + patch = mallocz(size*sizeof(*patch), 0); + tinit = malloc(m->ntype*sizeof(*tinit)); + tmp = mallocz(1024*sizeof(ulong), 0); + if(tinit == nil || patch == nil || tmp == nil) + goto bad; + + preamble(); + + mod = m; + n = 0; + pass = 0; + nlit = 0; + + for(i = 0; i < size; i++) { + code = tmp; + comp(&m->prog[i]); + patch[i] = n; + n += code - tmp; + } + + for(i = 0; i < nelem(mactab); i++) { + code = tmp; + mactab[i].gen(); + macro[mactab[i].idx] = n; + n += code - tmp; + } + + base = mallocz((n+nlit)*sizeof(*code), 0); + if(base == nil) + goto bad; + + if(cflag > 1) + print("dis=%5d %5d sparc=%5d asm=%.8p lit=%d: %s\n", + size, size*sizeof(Inst), n, base, nlit, m->name); + + pass++; + nlit = 0; + litpool = base+n; + code = base; + + for(i = 0; i < size; i++) { + s = code; + comp(&m->prog[i]); + if(cflag > 2) { + print("%d %D\n", i, &m->prog[i]); + das(s, code-s); + } + } + + for(i = 0; i < nelem(mactab); i++) { + s = code; + mactab[i].gen(); + if(cflag > 2) { + print("%s:\n", mactab[i].name); + das(s, code-s); + } + } + + if(n != (code - base)) + error(exCphase); + + for(l = m->ext; l->name; l++) { + l->u.pc = (Inst*)RELPC(patch[l->u.pc-m->prog]); + typecom(l->frame); + } + if(ml != nil) { + e = &ml->links[0]; + for(i = 0; i < ml->nlinks; i++) { + e->u.pc = (Inst*)RELPC(patch[e->u.pc-m->prog]); + typecom(e->frame); + e++; + } + } + for(i = 0; i < m->ntype; i++) { + if(tinit[i] != 0) + typecom(m->type[i]); + } + patchex(m, patch); + m->entry = (Inst*)RELPC(patch[mod->entry-mod->prog]); + free(patch); + free(tinit); + free(tmp); + free(m->prog); + m->prog = (Inst*)base; + m->compiled = 1; + segflush(base, n*sizeof(*base)); + return 1; +bad: + free(patch); + free(tinit); + free(tmp); + free(base); + return 0; +} |
