137da2899SCharles.Forsyth #include "lib9.h"
237da2899SCharles.Forsyth #include "isa.h"
337da2899SCharles.Forsyth #include "interp.h"
437da2899SCharles.Forsyth #include "raise.h"
537da2899SCharles.Forsyth
637da2899SCharles.Forsyth /*
737da2899SCharles.Forsyth * to do:
837da2899SCharles.Forsyth * eliminate litpool?
937da2899SCharles.Forsyth * eliminate long constants in comi/comd
1037da2899SCharles.Forsyth * enable and check inline FP code (not much point with fpemu)
1137da2899SCharles.Forsyth */
1237da2899SCharles.Forsyth
1337da2899SCharles.Forsyth #define RESCHED 1 /* check for interpreter reschedule */
14*1414757bSCharles Forsyth #define SOFTFP 1
1537da2899SCharles.Forsyth
1637da2899SCharles.Forsyth enum
1737da2899SCharles.Forsyth {
1837da2899SCharles.Forsyth R0 = 0,
1937da2899SCharles.Forsyth R1 = 1,
2037da2899SCharles.Forsyth R2 = 2,
2137da2899SCharles.Forsyth R3 = 3,
2237da2899SCharles.Forsyth R4 = 4,
2337da2899SCharles.Forsyth R5 = 5,
2437da2899SCharles.Forsyth R6 = 6,
2537da2899SCharles.Forsyth R7 = 7,
2637da2899SCharles.Forsyth R8 = 8,
2737da2899SCharles.Forsyth R9 = 9,
2837da2899SCharles.Forsyth R10 = 10,
2937da2899SCharles.Forsyth R11 = 11,
3037da2899SCharles.Forsyth R12 = 12, /* C's SB */
3137da2899SCharles.Forsyth R13 = 13, /* C's SP */
3237da2899SCharles.Forsyth R14 = 14, /* Link Register */
3337da2899SCharles.Forsyth R15 = 15, /* PC */
3437da2899SCharles.Forsyth
3537da2899SCharles.Forsyth RLINK = 14,
3637da2899SCharles.Forsyth
3737da2899SCharles.Forsyth RFP = R9, /* Frame Pointer */
3837da2899SCharles.Forsyth RMP = R8, /* Module Pointer */
3937da2899SCharles.Forsyth RTA = R7, /* Intermediate address for double indirect */
4037da2899SCharles.Forsyth RCON = R6, /* Constant builder */
4137da2899SCharles.Forsyth RREG = R5, /* Pointer to REG */
4237da2899SCharles.Forsyth RA3 = R4, /* gpr 3 */
4337da2899SCharles.Forsyth RA2 = R3, /* gpr 2 2+3 = L */
4437da2899SCharles.Forsyth RA1 = R2, /* gpr 1 */
4537da2899SCharles.Forsyth RA0 = R1, /* gpr 0 0+1 = L */
4637da2899SCharles.Forsyth
4737da2899SCharles.Forsyth
4837da2899SCharles.Forsyth FA2 = 2, /* Floating */
4937da2899SCharles.Forsyth FA3 = 3,
5037da2899SCharles.Forsyth FA4 = 4,
5137da2899SCharles.Forsyth FA5 = 5,
5237da2899SCharles.Forsyth
5337da2899SCharles.Forsyth EQ = 0,
5437da2899SCharles.Forsyth NE = 1,
5537da2899SCharles.Forsyth CS = 2,
5637da2899SCharles.Forsyth CC = 3,
5737da2899SCharles.Forsyth MI = 4,
5837da2899SCharles.Forsyth PL = 5,
5937da2899SCharles.Forsyth VS = 6,
6037da2899SCharles.Forsyth VC = 7,
6137da2899SCharles.Forsyth HI = 8,
6237da2899SCharles.Forsyth LS = 9,
6337da2899SCharles.Forsyth GE = 10,
6437da2899SCharles.Forsyth LT = 11,
6537da2899SCharles.Forsyth GT = 12,
6637da2899SCharles.Forsyth LE = 13,
6737da2899SCharles.Forsyth AL = 14,
6837da2899SCharles.Forsyth NV = 15,
6937da2899SCharles.Forsyth
7037da2899SCharles.Forsyth HS = CS,
7137da2899SCharles.Forsyth LO = CC,
7237da2899SCharles.Forsyth
7337da2899SCharles.Forsyth And = 0,
7437da2899SCharles.Forsyth Eor = 1,
7537da2899SCharles.Forsyth Sub = 2,
7637da2899SCharles.Forsyth Rsb = 3,
7737da2899SCharles.Forsyth Add = 4,
7837da2899SCharles.Forsyth Adc = 5,
7937da2899SCharles.Forsyth Sbc = 6,
8037da2899SCharles.Forsyth Rsc = 7,
8137da2899SCharles.Forsyth Tst = 8,
8237da2899SCharles.Forsyth Teq = 9,
8337da2899SCharles.Forsyth Cmp = 10,
8437da2899SCharles.Forsyth Cmn = 11,
8537da2899SCharles.Forsyth Orr = 12,
8637da2899SCharles.Forsyth Mov = 13,
8737da2899SCharles.Forsyth Bic = 14,
8837da2899SCharles.Forsyth Mvn = 15,
8937da2899SCharles.Forsyth
9037da2899SCharles.Forsyth Adf = 0,
9137da2899SCharles.Forsyth Muf = 1,
9237da2899SCharles.Forsyth Suf = 2,
9337da2899SCharles.Forsyth Rsf = 3,
9437da2899SCharles.Forsyth Dvf = 4,
9537da2899SCharles.Forsyth Rdf = 5,
9637da2899SCharles.Forsyth Rmf = 8,
9737da2899SCharles.Forsyth
9837da2899SCharles.Forsyth Mvf = 0,
9937da2899SCharles.Forsyth Mnf = 1,
10037da2899SCharles.Forsyth Abs = 2,
10137da2899SCharles.Forsyth Rnd = 3,
10237da2899SCharles.Forsyth
10337da2899SCharles.Forsyth Flt = 0,
10437da2899SCharles.Forsyth Fix = 1,
10537da2899SCharles.Forsyth
10637da2899SCharles.Forsyth Cmf = 4,
10737da2899SCharles.Forsyth Cnf = 5,
10837da2899SCharles.Forsyth
10937da2899SCharles.Forsyth Lea = 100, /* macro memory ops */
11037da2899SCharles.Forsyth Ldw,
11137da2899SCharles.Forsyth Ldb,
11237da2899SCharles.Forsyth Stw,
11337da2899SCharles.Forsyth Stb,
11437da2899SCharles.Forsyth Ldf,
11537da2899SCharles.Forsyth Stf,
11637da2899SCharles.Forsyth Ldh,
11737da2899SCharles.Forsyth
1187b3bf63cSCharles.Forsyth Blo = 0, /* offset of low order word in big */
1197b3bf63cSCharles.Forsyth Bhi = 4, /* offset of high order word in big */
1207b3bf63cSCharles.Forsyth
121*1414757bSCharles Forsyth Lg2Rune = 2,
122*1414757bSCharles Forsyth
12337da2899SCharles.Forsyth NCON = (0xFFC-8)/4,
12437da2899SCharles.Forsyth
12537da2899SCharles.Forsyth SRCOP = (1<<0),
12637da2899SCharles.Forsyth DSTOP = (1<<1),
12737da2899SCharles.Forsyth WRTPC = (1<<2),
12837da2899SCharles.Forsyth TCHECK = (1<<3),
12937da2899SCharles.Forsyth NEWPC = (1<<4),
13037da2899SCharles.Forsyth DBRAN = (1<<5),
13137da2899SCharles.Forsyth THREOP = (1<<6),
13237da2899SCharles.Forsyth
13337da2899SCharles.Forsyth ANDAND = 1,
13437da2899SCharles.Forsyth OROR = 2,
13537da2899SCharles.Forsyth EQAND = 3,
13637da2899SCharles.Forsyth
13737da2899SCharles.Forsyth MacFRP = 0,
13837da2899SCharles.Forsyth MacRET,
13937da2899SCharles.Forsyth MacCASE,
14037da2899SCharles.Forsyth MacCOLR,
14137da2899SCharles.Forsyth MacMCAL,
14237da2899SCharles.Forsyth MacFRAM,
14337da2899SCharles.Forsyth MacMFRA,
14437da2899SCharles.Forsyth MacRELQ,
14537da2899SCharles.Forsyth NMACRO
14637da2899SCharles.Forsyth };
14737da2899SCharles.Forsyth
14837da2899SCharles.Forsyth #define BITS(B) (1<<B)
14937da2899SCharles.Forsyth #define IMM(O) (O & ((1<<12)-1))
15037da2899SCharles.Forsyth #define SBIT (1<<20)
15137da2899SCharles.Forsyth #define PBIT (1<<24)
15237da2899SCharles.Forsyth #define UPBIT (1<<23)
15337da2899SCharles.Forsyth
15437da2899SCharles.Forsyth #define LDW(C, Rn, Rd, O) *code++ = (C<<28)|(1<<26)|(1<<24)|(1<<23)|(1<<20)|\
15537da2899SCharles.Forsyth (Rn<<16)|(Rd<<12)|IMM(O)
15637da2899SCharles.Forsyth #define STW(C, Rn, Rd, O) *code++ = (C<<28)|(1<<26)|(1<<24)|(1<<23)|\
15737da2899SCharles.Forsyth (Rn<<16)|(Rd<<12)|IMM(O)
15837da2899SCharles.Forsyth #define LDB(C, Rn, Rd, O) *code++ = (C<<28)|(1<<26)|(1<<24)|(1<<23)|(1<<20)|(1<<22)|\
15937da2899SCharles.Forsyth (Rn<<16)|(Rd<<12)|IMM(O)
16037da2899SCharles.Forsyth #define STB(C, Rn, Rd, O) *code++ = (C<<28)|(1<<26)|(1<<24)|(1<<23)|(1<<22)|\
16137da2899SCharles.Forsyth (Rn<<16)|(Rd<<12)|IMM(O)
16237da2899SCharles.Forsyth
16337da2899SCharles.Forsyth #define LDxP(C, Rn, Rd, O, B) *code++ = (C<<28)|(1<<26)|(B<<22)|(1<<23)|(1<<20)|\
16437da2899SCharles.Forsyth (Rn<<16)|(Rd<<12)|IMM(O)
16537da2899SCharles.Forsyth #define STxP(C, Rn, Rd, O, B) *code++ = (C<<28)|(1<<26)|(B<<22)|(1<<23)|\
16637da2899SCharles.Forsyth (Rn<<16)|(Rd<<12)|IMM(O)
16737da2899SCharles.Forsyth #define LDRW(C, Rn, Rd, SH, R) *code++ = (C<<28)|(3<<25)|(1<<24)|(1<<23)|(1<<20)|\
16837da2899SCharles.Forsyth (Rn<<16)|(Rd<<12)|(SH<<4)|R
16937da2899SCharles.Forsyth #define STRW(C, Rn, Rd, SH, R) *code++ = (C<<28)|(3<<25)|(1<<24)|(1<<23)|\
17037da2899SCharles.Forsyth (Rn<<16)|(Rd<<12)|(SH<<4)|R
17137da2899SCharles.Forsyth #define LDRB(C, Rn, Rd, SH, R) *code++ = (C<<28)|(3<<25)|(1<<24)|(1<<23)|(1<<20)|(1<<22)|\
17237da2899SCharles.Forsyth (Rn<<16)|(Rd<<12)|(SH<<4)|R
17337da2899SCharles.Forsyth #define STRB(C, Rn, Rd, SH, R) *code++ = (C<<28)|(3<<25)|(1<<24)|(1<<23)|(1<<22)|\
17437da2899SCharles.Forsyth (Rn<<16)|(Rd<<12)|(SH<<4)|R
17537da2899SCharles.Forsyth
17637da2899SCharles.Forsyth #define DPI(C, Op, Rn, Rd, RO, O) *code++ = (C<<28)|(1<<25)|(Op<<21)|\
17737da2899SCharles.Forsyth (Rn<<16)|(Rd<<12)|(RO<<8)|((O)&0xff)
17837da2899SCharles.Forsyth #define DP(C, Op, Rn, Rd, Sh, Ro) *code++ = (C<<28)|(Op<<21)|(Rn<<16)|\
17937da2899SCharles.Forsyth (Rd<<12)|((Sh)<<4)|Ro
18037da2899SCharles.Forsyth #define CMPI(C, Rn, Rd, RO, O) *code++ = (C<<28)|(1<<25)|(Cmp<<21)|(1<<20)|\
18137da2899SCharles.Forsyth (Rn<<16)|(Rd<<12)|(RO<<8)|((O)&0xff)
18237da2899SCharles.Forsyth #define CMNI(C, Rn, Rd, RO, O) *code++ = (C<<28)|(1<<25)|(Cmn<<21)|(1<<20)|\
18337da2899SCharles.Forsyth (Rn<<16)|(Rd<<12)|(RO<<8)|((O)&0xff)
18437da2899SCharles.Forsyth #define CMP(C, Rn, Rd, Sh, Ro) *code++ = (C<<28)|(Cmp<<21)|(Rn<<16)|(1<<20)|\
18537da2899SCharles.Forsyth (Rd<<12)|((Sh)<<4)|Ro
18637da2899SCharles.Forsyth #define CMN(C, Rn, Rd, Sh, Ro) *code++ = (C<<28)|(Cmn<<21)|(Rn<<16)|(1<<20)|\
18737da2899SCharles.Forsyth (Rd<<12)|((Sh)<<4)|Ro
18837da2899SCharles.Forsyth #define MUL(C, Rm, Rs, Rd) *code++ = (C<<28)|(Rd<<16)|(Rm<<0)|(Rs<<8)|\
18937da2899SCharles.Forsyth (9<<4)
19037da2899SCharles.Forsyth
19137da2899SCharles.Forsyth #define LDF(C, Rn, Fd, O) *code++ = (C<<28)|(6<<25)|(1<<24)|(1<<23)|(1<<20)|\
19237da2899SCharles.Forsyth (Rn<<16)|(1<<15)|(Fd<<12)|(1<<8)|((O)&0xff)
19337da2899SCharles.Forsyth #define STF(C, Rn, Fd, O) *code++ = (C<<28)|(6<<25)|(1<<24)|(1<<23)|\
19437da2899SCharles.Forsyth (Rn<<16)|(1<<15)|(Fd<<12)|(1<<8)|((O)&0xff)
19537da2899SCharles.Forsyth #define CMF(C, Fn, Fm) *code++ = (C<<28)|(7<<25)|(4<<21)|(1<<20)|(Fn<<16)|\
19637da2899SCharles.Forsyth (0xF<<12)|(1<<8)|(1<<4)|(Fm)
19737da2899SCharles.Forsyth
19837da2899SCharles.Forsyth #define LDH(C, Rn, Rd, O) *code++ = (C<<28)|(0<<25)|(1<<24)|(1<<23)|(1<<22)|(1<<20)|\
19937da2899SCharles.Forsyth (Rn<<16)|(Rd<<12)|(((O)&0xf0)<<4)|(0xb<<4)|((O)&0xf)
20037da2899SCharles.Forsyth #define LDRH(C, Rn, Rd, Rm) *code++ = (C<<28)|(0<<25)|(1<<24)|(1<<23)|(1<<20)|\
20137da2899SCharles.Forsyth (Rn<<16)|(Rd<<12)|(0xb<<4)|Rm
20237da2899SCharles.Forsyth
20337da2899SCharles.Forsyth #define CPDO2(C, Op, Fn, Fd, Fm) *code++ = (C<<28)|(0xE<<24)|(Op<<20)|(Fn<<16)|(Fd<<12)|(1<<8)|(1<<7)|(Fm)
20437da2899SCharles.Forsyth #define CPDO1(C, Op, Fd, Fm) CPDO2((C),(Op),0,(Fd),(Fm))|(1<<15)
20537da2899SCharles.Forsyth #define CPFLT(C, Fn, Rd) *code++ = (C<<28)|(0xE<<24)|(0<<20)|(Fn<<16)|(Rd<<12)|(1<<8)|(9<<4)
20637da2899SCharles.Forsyth #define CPFIX(C, Rd, Fm) *code++ = (C<<28)|(0xE<<24)|(1<<20)|(0<<16)|(Rd<<12)|(1<<8)|(9<<4)|(Fm)
20737da2899SCharles.Forsyth
20837da2899SCharles.Forsyth #define BRAW(C, o) ((C<<28)|(5<<25)|((o) & 0x00ffffff))
20937da2899SCharles.Forsyth #define BRA(C, o) gen(BRAW((C),(o)))
21037da2899SCharles.Forsyth #define IA(s, o) (ulong)(base+s[o])
21137da2899SCharles.Forsyth #define BRADIS(C, o) BRA(C, (IA(patch, o)-(ulong)code-8)>>2)
21237da2899SCharles.Forsyth #define BRAMAC(r, o) BRA(r, (IA(macro, o)-(ulong)code-8)>>2)
21337da2899SCharles.Forsyth #define BRANCH(C, o) gen(BRAW(C, ((ulong)(o)-(ulong)code-8)>>2))
21437da2899SCharles.Forsyth #define CALL(o) gen(BRAW(AL, ((ulong)(o)-(ulong)code-8)>>2)|(1<<24))
21537da2899SCharles.Forsyth #define CCALL(C,o) gen(BRAW((C), ((ulong)(o)-(ulong)code-8)>>2)|(1<<24))
21637da2899SCharles.Forsyth #define CALLMAC(C,o) gen(BRAW((C), (IA(macro, o)-(ulong)code-8)>>2)|(1<<24))
21737da2899SCharles.Forsyth #define RELPC(pc) (ulong)(base+(pc))
21837da2899SCharles.Forsyth #define RETURN DPI(AL, Add, RLINK, R15, 0, 0)
21937da2899SCharles.Forsyth #define CRETURN(C) DPI(C, Add, RLINK, R15, 0, 0)
22037da2899SCharles.Forsyth #define PATCH(ptr) *ptr |= (((ulong)code-(ulong)(ptr)-8)>>2) & 0x00ffffff
22137da2899SCharles.Forsyth
22237da2899SCharles.Forsyth #define MOV(src, dst) DP(AL, Mov, 0, dst, 0, src)
223*1414757bSCharles Forsyth
224*1414757bSCharles Forsyth #define FITS12(v) ((ulong)(v)<BITS(12))
22537da2899SCharles.Forsyth #define FITS8(v) ((ulong)(v)<BITS(8))
22637da2899SCharles.Forsyth #define FITS5(v) ((ulong)(v)<BITS(5))
22737da2899SCharles.Forsyth
22837da2899SCharles.Forsyth /* assumes H==-1 */
22937da2899SCharles.Forsyth #define CMPH(C, r) CMNI(C, r, 0, 0, 1)
230*1414757bSCharles Forsyth #define NOTNIL(r) (CMPH(AL, (r)), CCALL(EQ, nullity))
23137da2899SCharles.Forsyth
23237da2899SCharles.Forsyth /* array bounds checking */
23337da2899SCharles.Forsyth #define BCK(r, rb) (CMP(AL, rb, 0, 0, r), CCALL(LS, bounds))
23437da2899SCharles.Forsyth #define BCKI(i, rb) (CMPI(AL, rb, 0, 0, i), CCALL(LS, bounds))
235*1414757bSCharles Forsyth #define BCKR(i, rb) (CMPI(AL, rb, 0, 0, 0)|(i), CCALL(LS, bounds))
23637da2899SCharles.Forsyth
23737da2899SCharles.Forsyth static ulong* code;
23837da2899SCharles.Forsyth static ulong* base;
23937da2899SCharles.Forsyth static ulong* patch;
24037da2899SCharles.Forsyth static ulong codeoff;
24137da2899SCharles.Forsyth static int pass;
24237da2899SCharles.Forsyth static int puntpc = 1;
24337da2899SCharles.Forsyth static Module* mod;
24437da2899SCharles.Forsyth static uchar* tinit;
24537da2899SCharles.Forsyth static ulong* litpool;
24637da2899SCharles.Forsyth static int nlit;
24737da2899SCharles.Forsyth static ulong macro[NMACRO];
24837da2899SCharles.Forsyth void (*comvec)(void);
24937da2899SCharles.Forsyth static void macfrp(void);
25037da2899SCharles.Forsyth static void macret(void);
25137da2899SCharles.Forsyth static void maccase(void);
25237da2899SCharles.Forsyth static void maccolr(void);
25337da2899SCharles.Forsyth static void macmcal(void);
25437da2899SCharles.Forsyth static void macfram(void);
25537da2899SCharles.Forsyth static void macmfra(void);
25637da2899SCharles.Forsyth static void macrelq(void);
25737da2899SCharles.Forsyth static void movmem(Inst*);
25837da2899SCharles.Forsyth static void mid(Inst*, int, int);
25937da2899SCharles.Forsyth extern void das(ulong*, int);
26037da2899SCharles.Forsyth
26137da2899SCharles.Forsyth #define T(r) *((void**)(R.r))
26237da2899SCharles.Forsyth
26337da2899SCharles.Forsyth struct
26437da2899SCharles.Forsyth {
26537da2899SCharles.Forsyth int idx;
26637da2899SCharles.Forsyth void (*gen)(void);
26737da2899SCharles.Forsyth char* name;
26837da2899SCharles.Forsyth } mactab[] =
26937da2899SCharles.Forsyth {
27037da2899SCharles.Forsyth MacFRP, macfrp, "FRP", /* decrement and free pointer */
27137da2899SCharles.Forsyth MacRET, macret, "RET", /* return instruction */
27237da2899SCharles.Forsyth MacCASE, maccase, "CASE", /* case instruction */
27337da2899SCharles.Forsyth MacCOLR, maccolr, "COLR", /* increment and color pointer */
27437da2899SCharles.Forsyth MacMCAL, macmcal, "MCAL", /* mcall bottom half */
27537da2899SCharles.Forsyth MacFRAM, macfram, "FRAM", /* frame instruction */
27637da2899SCharles.Forsyth MacMFRA, macmfra, "MFRA", /* punt mframe because t->initialize==0 */
27737da2899SCharles.Forsyth MacRELQ, macrelq, /* reschedule */
27837da2899SCharles.Forsyth };
27937da2899SCharles.Forsyth
28037da2899SCharles.Forsyth typedef struct Const Const;
28137da2899SCharles.Forsyth struct Const
28237da2899SCharles.Forsyth {
28337da2899SCharles.Forsyth ulong o;
28437da2899SCharles.Forsyth ulong* code;
28537da2899SCharles.Forsyth ulong* pc;
28637da2899SCharles.Forsyth };
28737da2899SCharles.Forsyth
28837da2899SCharles.Forsyth typedef struct Con Con;
28937da2899SCharles.Forsyth struct Con
29037da2899SCharles.Forsyth {
29137da2899SCharles.Forsyth int ptr;
29237da2899SCharles.Forsyth Const table[NCON];
29337da2899SCharles.Forsyth };
29437da2899SCharles.Forsyth static Con rcon;
29537da2899SCharles.Forsyth
29637da2899SCharles.Forsyth static void
rdestroy(void)29737da2899SCharles.Forsyth rdestroy(void)
29837da2899SCharles.Forsyth {
29937da2899SCharles.Forsyth destroy(R.s);
30037da2899SCharles.Forsyth }
30137da2899SCharles.Forsyth
30237da2899SCharles.Forsyth static void
rmcall(void)30337da2899SCharles.Forsyth rmcall(void)
30437da2899SCharles.Forsyth {
30537da2899SCharles.Forsyth Frame *f;
30637da2899SCharles.Forsyth Prog *p;
30737da2899SCharles.Forsyth
30837da2899SCharles.Forsyth if((void*)R.dt == H)
30937da2899SCharles.Forsyth error(exModule);
31037da2899SCharles.Forsyth
31137da2899SCharles.Forsyth f = (Frame*)R.FP;
31237da2899SCharles.Forsyth if(f == H)
31337da2899SCharles.Forsyth error(exModule);
31437da2899SCharles.Forsyth
31537da2899SCharles.Forsyth f->mr = nil;
31637da2899SCharles.Forsyth ((void(*)(Frame*))R.dt)(f);
31737da2899SCharles.Forsyth R.SP = (uchar*)f;
31837da2899SCharles.Forsyth R.FP = f->fp;
31937da2899SCharles.Forsyth if(f->t == nil)
32037da2899SCharles.Forsyth unextend(f);
32137da2899SCharles.Forsyth else
32237da2899SCharles.Forsyth freeptrs(f, f->t);
32337da2899SCharles.Forsyth p = currun();
32437da2899SCharles.Forsyth if(p->kill != nil)
32537da2899SCharles.Forsyth error(p->kill);
32637da2899SCharles.Forsyth }
32737da2899SCharles.Forsyth
32837da2899SCharles.Forsyth static void
rmfram(void)32937da2899SCharles.Forsyth rmfram(void)
33037da2899SCharles.Forsyth {
33137da2899SCharles.Forsyth Type *t;
33237da2899SCharles.Forsyth Frame *f;
33337da2899SCharles.Forsyth uchar *nsp;
33437da2899SCharles.Forsyth
33537da2899SCharles.Forsyth if(R.d == H)
33637da2899SCharles.Forsyth error(exModule);
33737da2899SCharles.Forsyth t = (Type*)R.s;
33837da2899SCharles.Forsyth if(t == H)
33937da2899SCharles.Forsyth error(exModule);
34037da2899SCharles.Forsyth nsp = R.SP + t->size;
34137da2899SCharles.Forsyth if(nsp >= R.TS) {
34237da2899SCharles.Forsyth R.s = t;
34337da2899SCharles.Forsyth extend();
34437da2899SCharles.Forsyth T(d) = R.s;
34537da2899SCharles.Forsyth return;
34637da2899SCharles.Forsyth }
34737da2899SCharles.Forsyth f = (Frame*)R.SP;
34837da2899SCharles.Forsyth R.SP = nsp;
34937da2899SCharles.Forsyth f->t = t;
35037da2899SCharles.Forsyth f->mr = nil;
35137da2899SCharles.Forsyth initmem(t, f);
35237da2899SCharles.Forsyth T(d) = f;
35337da2899SCharles.Forsyth }
35437da2899SCharles.Forsyth
35537da2899SCharles.Forsyth static void
urk(char * s)35637da2899SCharles.Forsyth urk(char *s)
35737da2899SCharles.Forsyth {
35837da2899SCharles.Forsyth USED(s);
35937da2899SCharles.Forsyth error(exCompile); //production
36037da2899SCharles.Forsyth //panic("compile failed: urk: %s\n", s); //debugging
36137da2899SCharles.Forsyth }
36237da2899SCharles.Forsyth
36337da2899SCharles.Forsyth static void
gen(ulong w)36437da2899SCharles.Forsyth gen(ulong w)
36537da2899SCharles.Forsyth {
36637da2899SCharles.Forsyth *code++ = w;
36737da2899SCharles.Forsyth }
36837da2899SCharles.Forsyth
36937da2899SCharles.Forsyth static long
immrot(ulong v)37037da2899SCharles.Forsyth immrot(ulong v)
37137da2899SCharles.Forsyth {
37237da2899SCharles.Forsyth int i;
37337da2899SCharles.Forsyth
37437da2899SCharles.Forsyth for(i=0; i<16; i++) {
37537da2899SCharles.Forsyth if((v & ~0xff) == 0)
37637da2899SCharles.Forsyth return (i<<8) | v | (1<<25);
37737da2899SCharles.Forsyth v = (v<<2) | (v>>30);
37837da2899SCharles.Forsyth }
37937da2899SCharles.Forsyth return 0;
38037da2899SCharles.Forsyth }
38137da2899SCharles.Forsyth
38237da2899SCharles.Forsyth static long
immaddr(long v)38337da2899SCharles.Forsyth immaddr(long v)
38437da2899SCharles.Forsyth {
38537da2899SCharles.Forsyth
38637da2899SCharles.Forsyth if(v >= 0 && v <= 0xfff)
38737da2899SCharles.Forsyth return (v & 0xfff) |
38837da2899SCharles.Forsyth (1<<24) | /* pre indexing */
38937da2899SCharles.Forsyth (1<<23); /* pre indexing, up */
39037da2899SCharles.Forsyth if(v >= -0xfff && v < 0)
39137da2899SCharles.Forsyth return (-v & 0xfff) |
39237da2899SCharles.Forsyth (1<<24); /* pre indexing */
39337da2899SCharles.Forsyth return 0;
39437da2899SCharles.Forsyth }
39537da2899SCharles.Forsyth
39637da2899SCharles.Forsyth static void
flushcon(int genbr)39737da2899SCharles.Forsyth flushcon(int genbr)
39837da2899SCharles.Forsyth {
39937da2899SCharles.Forsyth int i;
40037da2899SCharles.Forsyth Const *c;
40137da2899SCharles.Forsyth ulong disp;
40237da2899SCharles.Forsyth
40337da2899SCharles.Forsyth if(rcon.ptr == 0)
40437da2899SCharles.Forsyth return;
40537da2899SCharles.Forsyth if(genbr){
40637da2899SCharles.Forsyth if(0)print("BR %d(PC)=%8.8p (len=%d)\n", (rcon.ptr*4+4-8)>>2, code+rcon.ptr+1, rcon.ptr);
40737da2899SCharles.Forsyth BRA(AL, (rcon.ptr*4+4-8)>>2);
40837da2899SCharles.Forsyth }
40937da2899SCharles.Forsyth c = &rcon.table[0];
41037da2899SCharles.Forsyth for(i = 0; i < rcon.ptr; i++) {
41137da2899SCharles.Forsyth if(pass){
41237da2899SCharles.Forsyth disp = (code - c->code) * sizeof(*code) - 8;
41337da2899SCharles.Forsyth if(disp >= BITS(12))
41437da2899SCharles.Forsyth print("INVALID constant range %lud", disp);
41537da2899SCharles.Forsyth 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);
41637da2899SCharles.Forsyth *c->code |= (disp&0xfff);
41737da2899SCharles.Forsyth }
41837da2899SCharles.Forsyth *code++ = c->o;
41937da2899SCharles.Forsyth c++;
42037da2899SCharles.Forsyth }
42137da2899SCharles.Forsyth rcon.ptr = 0;
42237da2899SCharles.Forsyth }
42337da2899SCharles.Forsyth
42437da2899SCharles.Forsyth static void
flushchk(void)42537da2899SCharles.Forsyth flushchk(void)
42637da2899SCharles.Forsyth {
42737da2899SCharles.Forsyth 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
42837da2899SCharles.Forsyth if(0)print("flushed constant table: len %ux disp %ld\n", rcon.ptr, (code+codeoff-rcon.table[0].pc)*sizeof(*code)-8);
42937da2899SCharles.Forsyth flushcon(1);
43037da2899SCharles.Forsyth }
43137da2899SCharles.Forsyth }
43237da2899SCharles.Forsyth
43337da2899SCharles.Forsyth static void
ccon(int cc,ulong o,int r,int opt)43437da2899SCharles.Forsyth ccon(int cc, ulong o, int r, int opt)
43537da2899SCharles.Forsyth {
43637da2899SCharles.Forsyth ulong u;
43737da2899SCharles.Forsyth Const *c;
43837da2899SCharles.Forsyth
43937da2899SCharles.Forsyth if(opt != 0) {
44037da2899SCharles.Forsyth u = o & ~0xff;
44137da2899SCharles.Forsyth if(u == 0) {
44237da2899SCharles.Forsyth DPI(cc, Mov, 0, r, 0, o);
44337da2899SCharles.Forsyth return;
44437da2899SCharles.Forsyth }
44537da2899SCharles.Forsyth if(u == ~0xff) {
44637da2899SCharles.Forsyth DPI(cc, Mvn, 0, r, 0, ~o);
44737da2899SCharles.Forsyth return;
44837da2899SCharles.Forsyth }
44937da2899SCharles.Forsyth u = immrot(o);
45037da2899SCharles.Forsyth if(u) {
45137da2899SCharles.Forsyth DPI(cc, Mov, 0, r, 0, 0) | u;
45237da2899SCharles.Forsyth return;
45337da2899SCharles.Forsyth }
45437da2899SCharles.Forsyth u = o & ~0xffff;
45537da2899SCharles.Forsyth if(u == 0) {
45637da2899SCharles.Forsyth DPI(cc, Mov, 0, r, 0, o);
45737da2899SCharles.Forsyth DPI(cc, Orr, r, r, (24/2), o>>8);
45837da2899SCharles.Forsyth return;
45937da2899SCharles.Forsyth }
46037da2899SCharles.Forsyth }
46137da2899SCharles.Forsyth flushchk();
46237da2899SCharles.Forsyth c = &rcon.table[rcon.ptr++];
46337da2899SCharles.Forsyth c->o = o;
46437da2899SCharles.Forsyth c->code = code;
46537da2899SCharles.Forsyth c->pc = code+codeoff;
46637da2899SCharles.Forsyth LDW(cc, R15, r, 0);
46737da2899SCharles.Forsyth }
46837da2899SCharles.Forsyth
46937da2899SCharles.Forsyth static void
memc(int c,int inst,ulong disp,int rm,int r)47037da2899SCharles.Forsyth memc(int c, int inst, ulong disp, int rm, int r)
47137da2899SCharles.Forsyth {
47237da2899SCharles.Forsyth int bit;
47337da2899SCharles.Forsyth
47437da2899SCharles.Forsyth if(inst == Lea) {
47537da2899SCharles.Forsyth if(disp < BITS(8)) {
476*1414757bSCharles Forsyth if(disp != 0 || rm != r)
47737da2899SCharles.Forsyth DPI(c, Add, rm, r, 0, disp);
47837da2899SCharles.Forsyth return;
47937da2899SCharles.Forsyth }
48037da2899SCharles.Forsyth if(-disp < BITS(8)) {
48137da2899SCharles.Forsyth DPI(c, Sub, rm, r, 0, -disp);
48237da2899SCharles.Forsyth return;
48337da2899SCharles.Forsyth }
48437da2899SCharles.Forsyth bit = immrot(disp);
48537da2899SCharles.Forsyth if(bit) {
48637da2899SCharles.Forsyth DPI(c, Add, rm, r, 0, 0) | bit;
48737da2899SCharles.Forsyth return;
48837da2899SCharles.Forsyth }
48937da2899SCharles.Forsyth ccon(c, disp, RCON, 1);
49037da2899SCharles.Forsyth DP(c, Add, rm, r, 0, RCON);
49137da2899SCharles.Forsyth return;
49237da2899SCharles.Forsyth }
49337da2899SCharles.Forsyth
49437da2899SCharles.Forsyth if(disp < BITS(12) || -disp < BITS(12)) { /* Direct load */
49537da2899SCharles.Forsyth if(disp < BITS(12))
49637da2899SCharles.Forsyth bit = 0;
49737da2899SCharles.Forsyth else {
49837da2899SCharles.Forsyth disp = -disp;
49937da2899SCharles.Forsyth bit = UPBIT;
50037da2899SCharles.Forsyth }
50137da2899SCharles.Forsyth switch(inst) {
50237da2899SCharles.Forsyth case Ldw:
50337da2899SCharles.Forsyth LDW(c, rm, r, disp);
50437da2899SCharles.Forsyth break;
50537da2899SCharles.Forsyth case Ldb:
50637da2899SCharles.Forsyth LDB(c, rm, r, disp);
50737da2899SCharles.Forsyth break;
50837da2899SCharles.Forsyth case Stw:
50937da2899SCharles.Forsyth STW(c, rm, r, disp);
51037da2899SCharles.Forsyth break;
51137da2899SCharles.Forsyth case Stb:
51237da2899SCharles.Forsyth STB(c, rm, r, disp);
51337da2899SCharles.Forsyth break;
51437da2899SCharles.Forsyth }
51537da2899SCharles.Forsyth if(bit)
51637da2899SCharles.Forsyth code[-1] ^= bit;
51737da2899SCharles.Forsyth return;
51837da2899SCharles.Forsyth }
51937da2899SCharles.Forsyth
52037da2899SCharles.Forsyth ccon(c, disp, RCON, 1);
52137da2899SCharles.Forsyth switch(inst) {
52237da2899SCharles.Forsyth case Ldw:
52337da2899SCharles.Forsyth LDRW(c, rm, r, 0, RCON);
52437da2899SCharles.Forsyth break;
52537da2899SCharles.Forsyth case Ldb:
52637da2899SCharles.Forsyth LDRB(c, rm, r, 0, RCON);
52737da2899SCharles.Forsyth break;
52837da2899SCharles.Forsyth case Stw:
52937da2899SCharles.Forsyth STRW(c, rm, r, 0, RCON);
53037da2899SCharles.Forsyth break;
53137da2899SCharles.Forsyth case Stb:
53237da2899SCharles.Forsyth STRB(c, rm, r, 0, RCON);
53337da2899SCharles.Forsyth break;
53437da2899SCharles.Forsyth }
53537da2899SCharles.Forsyth }
53637da2899SCharles.Forsyth
53737da2899SCharles.Forsyth static void
con(ulong o,int r,int opt)53837da2899SCharles.Forsyth con(ulong o, int r, int opt)
53937da2899SCharles.Forsyth {
54037da2899SCharles.Forsyth ccon(AL, o, r, opt);
54137da2899SCharles.Forsyth }
54237da2899SCharles.Forsyth
54337da2899SCharles.Forsyth static void
mem(int inst,ulong disp,int rm,int r)54437da2899SCharles.Forsyth mem(int inst, ulong disp, int rm, int r)
54537da2899SCharles.Forsyth {
54637da2899SCharles.Forsyth memc(AL, inst, disp, rm, r);
54737da2899SCharles.Forsyth }
54837da2899SCharles.Forsyth
54937da2899SCharles.Forsyth static void
opx(int mode,Adr * a,int mi,int r,int li)55037da2899SCharles.Forsyth opx(int mode, Adr *a, int mi, int r, int li)
55137da2899SCharles.Forsyth {
55237da2899SCharles.Forsyth int ir, rta;
55337da2899SCharles.Forsyth
55437da2899SCharles.Forsyth switch(mode) {
55537da2899SCharles.Forsyth default:
55637da2899SCharles.Forsyth urk("opx");
55737da2899SCharles.Forsyth case AFP:
55837da2899SCharles.Forsyth mem(mi, a->ind, RFP, r);
55937da2899SCharles.Forsyth return;
56037da2899SCharles.Forsyth case AMP:
56137da2899SCharles.Forsyth mem(mi, a->ind, RMP, r);
56237da2899SCharles.Forsyth return;
56337da2899SCharles.Forsyth case AIMM:
56437da2899SCharles.Forsyth con(a->imm, r, 1);
56537da2899SCharles.Forsyth if(mi == Lea) { /* could be simpler if con generates reachable literal */
56637da2899SCharles.Forsyth mem(Stw, li, RREG, r);
56737da2899SCharles.Forsyth mem(Lea, li, RREG, r);
56837da2899SCharles.Forsyth }
56937da2899SCharles.Forsyth return;
57037da2899SCharles.Forsyth case AIND|AFP:
57137da2899SCharles.Forsyth ir = RFP;
57237da2899SCharles.Forsyth break;
57337da2899SCharles.Forsyth case AIND|AMP:
57437da2899SCharles.Forsyth ir = RMP;
57537da2899SCharles.Forsyth break;
57637da2899SCharles.Forsyth }
57737da2899SCharles.Forsyth rta = RTA;
57837da2899SCharles.Forsyth if(mi == Lea)
57937da2899SCharles.Forsyth rta = r;
58037da2899SCharles.Forsyth mem(Ldw, a->i.f, ir, rta);
58137da2899SCharles.Forsyth mem(mi, a->i.s, rta, r);
58237da2899SCharles.Forsyth }
58337da2899SCharles.Forsyth
58437da2899SCharles.Forsyth static void
opwld(Inst * i,int op,int reg)58537da2899SCharles.Forsyth opwld(Inst *i, int op, int reg)
58637da2899SCharles.Forsyth {
58737da2899SCharles.Forsyth opx(USRC(i->add), &i->s, op, reg, O(REG, st));
58837da2899SCharles.Forsyth }
58937da2899SCharles.Forsyth
59037da2899SCharles.Forsyth static void
opwst(Inst * i,int op,int reg)59137da2899SCharles.Forsyth opwst(Inst *i, int op, int reg)
59237da2899SCharles.Forsyth {
59337da2899SCharles.Forsyth opx(UDST(i->add), &i->d, op, reg, O(REG, dt));
59437da2899SCharles.Forsyth }
59537da2899SCharles.Forsyth
59637da2899SCharles.Forsyth static void
memfl(int cc,int inst,ulong disp,int rm,int r)59737da2899SCharles.Forsyth memfl(int cc, int inst, ulong disp, int rm, int r)
59837da2899SCharles.Forsyth {
59937da2899SCharles.Forsyth int bit, wd;
60037da2899SCharles.Forsyth
60137da2899SCharles.Forsyth wd = (disp&03)==0;
60237da2899SCharles.Forsyth bit = 0;
60337da2899SCharles.Forsyth if(wd && disp < BITS(10))
60437da2899SCharles.Forsyth disp >>= 2; /* direct load */
60537da2899SCharles.Forsyth else if(wd && -disp < BITS(10)){
60637da2899SCharles.Forsyth bit = UPBIT;
60737da2899SCharles.Forsyth disp = -disp >> 2;
60837da2899SCharles.Forsyth }else{
60937da2899SCharles.Forsyth ccon(cc, disp, RCON, 1);
61037da2899SCharles.Forsyth DP(cc, Add, RCON, RCON, 0, rm);
61137da2899SCharles.Forsyth rm = RCON;
61237da2899SCharles.Forsyth disp = 0;
61337da2899SCharles.Forsyth }
61437da2899SCharles.Forsyth switch(inst) {
61537da2899SCharles.Forsyth case Ldf:
61637da2899SCharles.Forsyth LDF(cc, rm, r, disp);
61737da2899SCharles.Forsyth break;
61837da2899SCharles.Forsyth case Stf:
61937da2899SCharles.Forsyth STF(cc, rm, r, disp);
62037da2899SCharles.Forsyth break;
62137da2899SCharles.Forsyth }
62237da2899SCharles.Forsyth if(bit)
62337da2899SCharles.Forsyth code[-1] ^= bit;
62437da2899SCharles.Forsyth }
62537da2899SCharles.Forsyth
62637da2899SCharles.Forsyth static void
opfl(Adr * a,int am,int mi,int r)62737da2899SCharles.Forsyth opfl(Adr *a, int am, int mi, int r)
62837da2899SCharles.Forsyth {
62937da2899SCharles.Forsyth int ir;
63037da2899SCharles.Forsyth
63137da2899SCharles.Forsyth switch(am) {
63237da2899SCharles.Forsyth default:
63337da2899SCharles.Forsyth urk("opfl");
63437da2899SCharles.Forsyth case AFP:
63537da2899SCharles.Forsyth memfl(AL, mi, a->ind, RFP, r);
63637da2899SCharles.Forsyth return;
63737da2899SCharles.Forsyth case AMP:
63837da2899SCharles.Forsyth memfl(AL, mi, a->ind, RMP, r);
63937da2899SCharles.Forsyth return;
64037da2899SCharles.Forsyth case AIND|AFP:
64137da2899SCharles.Forsyth ir = RFP;
64237da2899SCharles.Forsyth break;
64337da2899SCharles.Forsyth case AIND|AMP:
64437da2899SCharles.Forsyth ir = RMP;
64537da2899SCharles.Forsyth break;
64637da2899SCharles.Forsyth }
64737da2899SCharles.Forsyth mem(Ldw, a->i.f, ir, RTA);
64837da2899SCharles.Forsyth memfl(AL, mi, a->i.s, RTA, r);
64937da2899SCharles.Forsyth }
65037da2899SCharles.Forsyth
65137da2899SCharles.Forsyth static void
opflld(Inst * i,int mi,int r)65237da2899SCharles.Forsyth opflld(Inst *i, int mi, int r)
65337da2899SCharles.Forsyth {
65437da2899SCharles.Forsyth opfl(&i->s, USRC(i->add), mi, r);
65537da2899SCharles.Forsyth }
65637da2899SCharles.Forsyth
65737da2899SCharles.Forsyth static void
opflst(Inst * i,int mi,int r)65837da2899SCharles.Forsyth opflst(Inst *i, int mi, int r)
65937da2899SCharles.Forsyth {
66037da2899SCharles.Forsyth opfl(&i->d, UDST(i->add), mi, r);
66137da2899SCharles.Forsyth }
66237da2899SCharles.Forsyth
66337da2899SCharles.Forsyth static void
literal(ulong imm,int roff)66437da2899SCharles.Forsyth literal(ulong imm, int roff)
66537da2899SCharles.Forsyth {
66637da2899SCharles.Forsyth nlit++;
66737da2899SCharles.Forsyth
66837da2899SCharles.Forsyth con((ulong)litpool, RTA, 0);
66937da2899SCharles.Forsyth mem(Stw, roff, RREG, RTA);
67037da2899SCharles.Forsyth
67137da2899SCharles.Forsyth if(pass == 0)
67237da2899SCharles.Forsyth return;
67337da2899SCharles.Forsyth
67437da2899SCharles.Forsyth *litpool = imm;
67537da2899SCharles.Forsyth litpool++;
67637da2899SCharles.Forsyth }
67737da2899SCharles.Forsyth
67837da2899SCharles.Forsyth static void
schedcheck(Inst * i)67937da2899SCharles.Forsyth schedcheck(Inst *i)
68037da2899SCharles.Forsyth {
68137da2899SCharles.Forsyth if(RESCHED && i->d.ins <= i){
68237da2899SCharles.Forsyth mem(Ldw, O(REG, IC), RREG, RA0);
68337da2899SCharles.Forsyth DPI(AL, Sub, RA0, RA0, 0, 1) | SBIT;
68437da2899SCharles.Forsyth mem(Stw, O(REG, IC), RREG, RA0);
68537da2899SCharles.Forsyth /* CMPI(AL, RA0, 0, 0, 1); */
68637da2899SCharles.Forsyth CALLMAC(LE, MacRELQ);
68737da2899SCharles.Forsyth }
68837da2899SCharles.Forsyth }
68937da2899SCharles.Forsyth
69037da2899SCharles.Forsyth static void
bounds(void)69137da2899SCharles.Forsyth bounds(void)
69237da2899SCharles.Forsyth {
69337da2899SCharles.Forsyth /* mem(Stw, O(REG,FP), RREG, RFP); */
69437da2899SCharles.Forsyth error(exBounds);
69537da2899SCharles.Forsyth }
69637da2899SCharles.Forsyth
69737da2899SCharles.Forsyth static void
nullity(void)698*1414757bSCharles Forsyth nullity(void)
699*1414757bSCharles Forsyth {
700*1414757bSCharles Forsyth /* mem(Stw, O(REG,FP), RREG, RFP); */
701*1414757bSCharles Forsyth error(exNilref);
702*1414757bSCharles Forsyth }
703*1414757bSCharles Forsyth
704*1414757bSCharles Forsyth static void
punt(Inst * i,int m,void (* fn)(void))70537da2899SCharles.Forsyth punt(Inst *i, int m, void (*fn)(void))
70637da2899SCharles.Forsyth {
70737da2899SCharles.Forsyth ulong pc;
70837da2899SCharles.Forsyth
70937da2899SCharles.Forsyth if(m & SRCOP) {
71037da2899SCharles.Forsyth if(UXSRC(i->add) == SRC(AIMM))
71137da2899SCharles.Forsyth literal(i->s.imm, O(REG, s));
71237da2899SCharles.Forsyth else {
71337da2899SCharles.Forsyth opwld(i, Lea, RA0);
71437da2899SCharles.Forsyth mem(Stw, O(REG, s), RREG, RA0);
71537da2899SCharles.Forsyth }
71637da2899SCharles.Forsyth }
71737da2899SCharles.Forsyth
71837da2899SCharles.Forsyth if(m & DSTOP) {
71937da2899SCharles.Forsyth opwst(i, Lea, RA0);
72037da2899SCharles.Forsyth mem(Stw, O(REG, d), RREG, RA0);
72137da2899SCharles.Forsyth }
72237da2899SCharles.Forsyth if(m & WRTPC) {
72337da2899SCharles.Forsyth con(RELPC(patch[i-mod->prog+1]), RA0, 0);
72437da2899SCharles.Forsyth mem(Stw, O(REG, PC), RREG, RA0);
72537da2899SCharles.Forsyth }
72637da2899SCharles.Forsyth if(m & DBRAN) {
72737da2899SCharles.Forsyth pc = patch[i->d.ins-mod->prog];
72837da2899SCharles.Forsyth literal((ulong)(base+pc), O(REG, d));
72937da2899SCharles.Forsyth }
73037da2899SCharles.Forsyth
73137da2899SCharles.Forsyth switch(i->add&ARM) {
73237da2899SCharles.Forsyth case AXNON:
73337da2899SCharles.Forsyth if(m & THREOP) {
73437da2899SCharles.Forsyth mem(Ldw, O(REG, d), RREG, RA0);
73537da2899SCharles.Forsyth mem(Stw, O(REG, m), RREG, RA0);
73637da2899SCharles.Forsyth }
73737da2899SCharles.Forsyth break;
73837da2899SCharles.Forsyth case AXIMM:
73937da2899SCharles.Forsyth literal((short)i->reg, O(REG,m));
74037da2899SCharles.Forsyth break;
74137da2899SCharles.Forsyth case AXINF:
74237da2899SCharles.Forsyth mem(Lea, i->reg, RFP, RA2);
74337da2899SCharles.Forsyth mem(Stw, O(REG, m), RREG, RA2);
74437da2899SCharles.Forsyth break;
74537da2899SCharles.Forsyth case AXINM:
74637da2899SCharles.Forsyth mem(Lea, i->reg, RMP, RA2);
74737da2899SCharles.Forsyth mem(Stw, O(REG, m), RREG, RA2);
74837da2899SCharles.Forsyth break;
74937da2899SCharles.Forsyth }
75037da2899SCharles.Forsyth mem(Stw, O(REG, FP), RREG, RFP);
75137da2899SCharles.Forsyth
75237da2899SCharles.Forsyth CALL(fn);
75337da2899SCharles.Forsyth
75437da2899SCharles.Forsyth con((ulong)&R, RREG, 1);
75537da2899SCharles.Forsyth if(m & TCHECK) {
75637da2899SCharles.Forsyth mem(Ldw, O(REG, t), RREG, RA0);
75737da2899SCharles.Forsyth CMPI(AL, RA0, 0, 0, 0);
75837da2899SCharles.Forsyth memc(NE, Ldw, O(REG, xpc), RREG, RLINK);
75937da2899SCharles.Forsyth CRETURN(NE); /* if(R.t) goto(R.xpc) */
76037da2899SCharles.Forsyth }
76137da2899SCharles.Forsyth mem(Ldw, O(REG, FP), RREG, RFP);
76237da2899SCharles.Forsyth mem(Ldw, O(REG, MP), RREG, RMP);
76337da2899SCharles.Forsyth
76437da2899SCharles.Forsyth if(m & NEWPC){
76537da2899SCharles.Forsyth mem(Ldw, O(REG, PC), RREG, R15);
76637da2899SCharles.Forsyth flushcon(0);
76737da2899SCharles.Forsyth }
76837da2899SCharles.Forsyth }
76937da2899SCharles.Forsyth
77037da2899SCharles.Forsyth static void
midfl(Inst * i,int mi,int r)77137da2899SCharles.Forsyth midfl(Inst *i, int mi, int r)
77237da2899SCharles.Forsyth {
77337da2899SCharles.Forsyth int ir;
77437da2899SCharles.Forsyth
77537da2899SCharles.Forsyth switch(i->add&ARM) {
77637da2899SCharles.Forsyth default:
77737da2899SCharles.Forsyth opflst(i, mi, r);
77837da2899SCharles.Forsyth return;
77937da2899SCharles.Forsyth case AXIMM:
78037da2899SCharles.Forsyth con((short)i->reg, r, 1); // BUG
78137da2899SCharles.Forsyth return;
78237da2899SCharles.Forsyth case AXINF:
78337da2899SCharles.Forsyth ir = RFP;
78437da2899SCharles.Forsyth break;
78537da2899SCharles.Forsyth case AXINM:
78637da2899SCharles.Forsyth ir = RMP;
78737da2899SCharles.Forsyth break;
78837da2899SCharles.Forsyth }
78937da2899SCharles.Forsyth memfl(AL, mi, i->reg, ir, r);
79037da2899SCharles.Forsyth }
79137da2899SCharles.Forsyth
79237da2899SCharles.Forsyth static void
mid(Inst * i,int mi,int r)79337da2899SCharles.Forsyth mid(Inst *i, int mi, int r)
79437da2899SCharles.Forsyth {
79537da2899SCharles.Forsyth int ir;
79637da2899SCharles.Forsyth
79737da2899SCharles.Forsyth switch(i->add&ARM) {
79837da2899SCharles.Forsyth default:
79937da2899SCharles.Forsyth opwst(i, mi, r);
80037da2899SCharles.Forsyth return;
80137da2899SCharles.Forsyth case AXIMM:
80237da2899SCharles.Forsyth if(mi == Lea)
80337da2899SCharles.Forsyth urk("mid/lea");
80437da2899SCharles.Forsyth con((short)i->reg, r, 1);
80537da2899SCharles.Forsyth return;
80637da2899SCharles.Forsyth case AXINF:
80737da2899SCharles.Forsyth ir = RFP;
80837da2899SCharles.Forsyth break;
80937da2899SCharles.Forsyth case AXINM:
81037da2899SCharles.Forsyth ir = RMP;
81137da2899SCharles.Forsyth break;
81237da2899SCharles.Forsyth }
81337da2899SCharles.Forsyth mem(mi, i->reg, ir, r);
81437da2899SCharles.Forsyth }
81537da2899SCharles.Forsyth
81637da2899SCharles.Forsyth static int
swapbraop(int b)81737da2899SCharles.Forsyth swapbraop(int b)
81837da2899SCharles.Forsyth {
81937da2899SCharles.Forsyth switch(b) {
82037da2899SCharles.Forsyth case GE:
82137da2899SCharles.Forsyth return LE;
82237da2899SCharles.Forsyth case LE:
82337da2899SCharles.Forsyth return GE;
82437da2899SCharles.Forsyth case GT:
82537da2899SCharles.Forsyth return LT;
82637da2899SCharles.Forsyth case LT:
82737da2899SCharles.Forsyth return GT;
82837da2899SCharles.Forsyth }
82937da2899SCharles.Forsyth return b;
83037da2899SCharles.Forsyth }
83137da2899SCharles.Forsyth
83237da2899SCharles.Forsyth static void
cbra(Inst * i,int r)83337da2899SCharles.Forsyth cbra(Inst *i, int r)
83437da2899SCharles.Forsyth {
83537da2899SCharles.Forsyth if(RESCHED)
83637da2899SCharles.Forsyth schedcheck(i);
83737da2899SCharles.Forsyth if(UXSRC(i->add) == SRC(AIMM) && FITS8(i->s.imm)) {
83837da2899SCharles.Forsyth mid(i, Ldw, RA1);
83937da2899SCharles.Forsyth CMPI(AL, RA1, 0, 0, i->s.imm);
84037da2899SCharles.Forsyth r = swapbraop(r);
84137da2899SCharles.Forsyth } else if(UXSRC(i->add) == SRC(AIMM) && FITS8(-i->s.imm)) {
84237da2899SCharles.Forsyth mid(i, Ldw, RA1);
84337da2899SCharles.Forsyth CMNI(AL, RA1, 0, 0, -i->s.imm);
84437da2899SCharles.Forsyth r = swapbraop(r);
84537da2899SCharles.Forsyth } else if((i->add & ARM) == AXIMM && FITS8(i->reg)) {
84637da2899SCharles.Forsyth opwld(i, Ldw, RA1);
84737da2899SCharles.Forsyth CMPI(AL, RA1, 0, 0, i->reg);
84837da2899SCharles.Forsyth } else if((i->add & ARM) == AXIMM && FITS8(-(short)i->reg)) {
84937da2899SCharles.Forsyth opwld(i, Ldw, RA1);
85037da2899SCharles.Forsyth CMNI(AL, RA1, 0, 0, -(short)i->reg);
85137da2899SCharles.Forsyth } else {
85237da2899SCharles.Forsyth opwld(i, Ldw, RA0);
85337da2899SCharles.Forsyth mid(i, Ldw, RA1);
85437da2899SCharles.Forsyth CMP(AL, RA0, 0, 0, RA1);
85537da2899SCharles.Forsyth }
85637da2899SCharles.Forsyth BRADIS(r, i->d.ins-mod->prog);
85737da2899SCharles.Forsyth }
85837da2899SCharles.Forsyth
85937da2899SCharles.Forsyth static void
cbrab(Inst * i,int r)86037da2899SCharles.Forsyth cbrab(Inst *i, int r)
86137da2899SCharles.Forsyth {
86237da2899SCharles.Forsyth if(RESCHED)
86337da2899SCharles.Forsyth schedcheck(i);
86437da2899SCharles.Forsyth if(UXSRC(i->add) == SRC(AIMM)) {
86537da2899SCharles.Forsyth mid(i, Ldb, RA1);
86637da2899SCharles.Forsyth CMPI(AL, RA1, 0, 0, i->s.imm&0xFF);
86737da2899SCharles.Forsyth r = swapbraop(r);
86837da2899SCharles.Forsyth } else if((i->add & ARM) == AXIMM) {
86937da2899SCharles.Forsyth opwld(i, Ldb, RA1);
87037da2899SCharles.Forsyth CMPI(AL, RA1, 0, 0, i->reg&0xFF);
87137da2899SCharles.Forsyth } else {
87237da2899SCharles.Forsyth opwld(i, Ldb, RA0);
87337da2899SCharles.Forsyth mid(i, Ldb, RA1);
87437da2899SCharles.Forsyth CMP(AL, RA0, 0, 0, RA1);
87537da2899SCharles.Forsyth }
87637da2899SCharles.Forsyth BRADIS(r, i->d.ins-mod->prog);
87737da2899SCharles.Forsyth }
87837da2899SCharles.Forsyth
87937da2899SCharles.Forsyth static void
cbral(Inst * i,int jmsw,int jlsw,int mode)88037da2899SCharles.Forsyth cbral(Inst *i, int jmsw, int jlsw, int mode)
88137da2899SCharles.Forsyth {
88237da2899SCharles.Forsyth ulong dst, *label;
88337da2899SCharles.Forsyth
88437da2899SCharles.Forsyth if(RESCHED)
88537da2899SCharles.Forsyth schedcheck(i);
88637da2899SCharles.Forsyth opwld(i, Lea, RA1);
88737da2899SCharles.Forsyth mid(i, Lea, RA3);
8887b3bf63cSCharles.Forsyth mem(Ldw, Bhi, RA1, RA2);
8897b3bf63cSCharles.Forsyth mem(Ldw, Bhi, RA3, RA0);
89037da2899SCharles.Forsyth CMP(AL, RA2, 0, 0, RA0);
89137da2899SCharles.Forsyth label = nil;
89237da2899SCharles.Forsyth dst = i->d.ins-mod->prog;
89337da2899SCharles.Forsyth switch(mode) {
89437da2899SCharles.Forsyth case ANDAND:
89537da2899SCharles.Forsyth label = code;
89637da2899SCharles.Forsyth BRA(jmsw, 0);
89737da2899SCharles.Forsyth break;
89837da2899SCharles.Forsyth case OROR:
89937da2899SCharles.Forsyth BRADIS(jmsw, dst);
90037da2899SCharles.Forsyth break;
90137da2899SCharles.Forsyth case EQAND:
90237da2899SCharles.Forsyth BRADIS(jmsw, dst);
90337da2899SCharles.Forsyth label = code;
90437da2899SCharles.Forsyth BRA(NE, 0);
90537da2899SCharles.Forsyth break;
90637da2899SCharles.Forsyth }
9077b3bf63cSCharles.Forsyth mem(Ldw, Blo, RA3, RA0);
9087b3bf63cSCharles.Forsyth mem(Ldw, Blo, RA1, RA2);
90937da2899SCharles.Forsyth CMP(AL, RA2, 0, 0, RA0);
91037da2899SCharles.Forsyth BRADIS(jlsw, dst);
91137da2899SCharles.Forsyth if(label != nil)
91237da2899SCharles.Forsyth PATCH(label);
91337da2899SCharles.Forsyth }
91437da2899SCharles.Forsyth
91537da2899SCharles.Forsyth static void
cbraf(Inst * i,int r)91637da2899SCharles.Forsyth cbraf(Inst *i, int r)
91737da2899SCharles.Forsyth {
91837da2899SCharles.Forsyth if(RESCHED)
91937da2899SCharles.Forsyth schedcheck(i);
920*1414757bSCharles Forsyth if(!SOFTFP){
92137da2899SCharles.Forsyth ulong *s=code;
92237da2899SCharles.Forsyth opflld(i, Ldf, FA4);
92337da2899SCharles.Forsyth midfl(i, Ldf, FA2);
92437da2899SCharles.Forsyth CMF(AL, FA4, FA2);
92537da2899SCharles.Forsyth BRADIS(r, i->d.ins-mod->prog);
92637da2899SCharles.Forsyth if(pass){print("%D\n", i); das(s, code-s);}
92737da2899SCharles.Forsyth }else
92837da2899SCharles.Forsyth punt(i, SRCOP|THREOP|DBRAN|NEWPC|WRTPC, optab[i->op]);
92937da2899SCharles.Forsyth }
93037da2899SCharles.Forsyth
93137da2899SCharles.Forsyth static void
comcase(Inst * i,int w)93237da2899SCharles.Forsyth comcase(Inst *i, int w)
93337da2899SCharles.Forsyth {
93437da2899SCharles.Forsyth int l;
93537da2899SCharles.Forsyth WORD *t, *e;
93637da2899SCharles.Forsyth
93737da2899SCharles.Forsyth if(w != 0) {
93837da2899SCharles.Forsyth opwld(i, Ldw, RA1); // v
93937da2899SCharles.Forsyth opwst(i, Lea, RA3); // table
94037da2899SCharles.Forsyth BRAMAC(AL, MacCASE);
94137da2899SCharles.Forsyth }
94237da2899SCharles.Forsyth
94337da2899SCharles.Forsyth t = (WORD*)(mod->origmp+i->d.ind+4);
94437da2899SCharles.Forsyth l = t[-1];
94537da2899SCharles.Forsyth
94637da2899SCharles.Forsyth /* have to take care not to relocate the same table twice -
94737da2899SCharles.Forsyth * the limbo compiler can duplicate a case instruction
94837da2899SCharles.Forsyth * during its folding phase
94937da2899SCharles.Forsyth */
95037da2899SCharles.Forsyth
95137da2899SCharles.Forsyth if(pass == 0) {
95237da2899SCharles.Forsyth if(l >= 0)
95337da2899SCharles.Forsyth t[-1] = -l-1; /* Mark it not done */
95437da2899SCharles.Forsyth return;
95537da2899SCharles.Forsyth }
95637da2899SCharles.Forsyth if(l >= 0) /* Check pass 2 done */
95737da2899SCharles.Forsyth return;
95837da2899SCharles.Forsyth t[-1] = -l-1; /* Set real count */
95937da2899SCharles.Forsyth e = t + t[-1]*3;
96037da2899SCharles.Forsyth while(t < e) {
96137da2899SCharles.Forsyth t[2] = RELPC(patch[t[2]]);
96237da2899SCharles.Forsyth t += 3;
96337da2899SCharles.Forsyth }
96437da2899SCharles.Forsyth t[0] = RELPC(patch[t[0]]);
96537da2899SCharles.Forsyth }
96637da2899SCharles.Forsyth
96737da2899SCharles.Forsyth static void
comcasel(Inst * i)96837da2899SCharles.Forsyth comcasel(Inst *i)
96937da2899SCharles.Forsyth {
97037da2899SCharles.Forsyth int l;
97137da2899SCharles.Forsyth WORD *t, *e;
97237da2899SCharles.Forsyth
97337da2899SCharles.Forsyth t = (WORD*)(mod->origmp+i->d.ind+8);
97437da2899SCharles.Forsyth l = t[-2];
97537da2899SCharles.Forsyth if(pass == 0) {
97637da2899SCharles.Forsyth if(l >= 0)
97737da2899SCharles.Forsyth t[-2] = -l-1; /* Mark it not done */
97837da2899SCharles.Forsyth return;
97937da2899SCharles.Forsyth }
98037da2899SCharles.Forsyth if(l >= 0) /* Check pass 2 done */
98137da2899SCharles.Forsyth return;
98237da2899SCharles.Forsyth t[-2] = -l-1; /* Set real count */
98337da2899SCharles.Forsyth e = t + t[-2]*6;
98437da2899SCharles.Forsyth while(t < e) {
98537da2899SCharles.Forsyth t[4] = RELPC(patch[t[4]]);
98637da2899SCharles.Forsyth t += 6;
98737da2899SCharles.Forsyth }
98837da2899SCharles.Forsyth t[0] = RELPC(patch[t[0]]);
98937da2899SCharles.Forsyth }
99037da2899SCharles.Forsyth
99137da2899SCharles.Forsyth static void
commframe(Inst * i)99237da2899SCharles.Forsyth commframe(Inst *i)
99337da2899SCharles.Forsyth {
99437da2899SCharles.Forsyth ulong *punt, *mlnil;
99537da2899SCharles.Forsyth
99637da2899SCharles.Forsyth opwld(i, Ldw, RA0);
99737da2899SCharles.Forsyth CMPH(AL, RA0);
99837da2899SCharles.Forsyth mlnil = code;
99937da2899SCharles.Forsyth BRA(EQ, 0);
100037da2899SCharles.Forsyth
100137da2899SCharles.Forsyth if((i->add&ARM) == AXIMM) {
100237da2899SCharles.Forsyth mem(Ldw, OA(Modlink, links)+i->reg*sizeof(Modl)+O(Modl, frame), RA0, RA3);
100337da2899SCharles.Forsyth } else {
100437da2899SCharles.Forsyth mid(i, Ldw, RA1);
100537da2899SCharles.Forsyth DP(AL, Add, RA0, RA1, (3<<3), RA1); // assumes sizeof(Modl) == 8
100637da2899SCharles.Forsyth mem(Ldw, OA(Modlink, links)+O(Modl, frame), RA1, RA3);
100737da2899SCharles.Forsyth }
100837da2899SCharles.Forsyth
100937da2899SCharles.Forsyth mem(Ldw, O(Type, initialize), RA3, RA1);
101037da2899SCharles.Forsyth CMPI(AL, RA1, 0, 0, 0);
101137da2899SCharles.Forsyth punt = code;
101237da2899SCharles.Forsyth BRA(NE, 0);
101337da2899SCharles.Forsyth
101437da2899SCharles.Forsyth opwst(i, Lea, RA0);
101537da2899SCharles.Forsyth
101637da2899SCharles.Forsyth /* Type in RA3, destination in RA0 */
101737da2899SCharles.Forsyth PATCH(mlnil);
101837da2899SCharles.Forsyth con(RELPC(patch[i-mod->prog+1]), RLINK, 0);
101937da2899SCharles.Forsyth BRAMAC(AL, MacMFRA);
102037da2899SCharles.Forsyth
102137da2899SCharles.Forsyth /* Type in RA3 */
102237da2899SCharles.Forsyth PATCH(punt);
102337da2899SCharles.Forsyth CALLMAC(AL, MacFRAM);
102437da2899SCharles.Forsyth opwst(i, Stw, RA2);
102537da2899SCharles.Forsyth }
102637da2899SCharles.Forsyth
102737da2899SCharles.Forsyth static void
commcall(Inst * i)102837da2899SCharles.Forsyth commcall(Inst *i)
102937da2899SCharles.Forsyth {
103037da2899SCharles.Forsyth ulong *mlnil;
103137da2899SCharles.Forsyth
103237da2899SCharles.Forsyth opwld(i, Ldw, RA2);
103337da2899SCharles.Forsyth con(RELPC(patch[i-mod->prog+1]), RA0, 0);
103437da2899SCharles.Forsyth mem(Stw, O(Frame, lr), RA2, RA0);
103537da2899SCharles.Forsyth mem(Stw, O(Frame, fp), RA2, RFP);
103637da2899SCharles.Forsyth mem(Ldw, O(REG, M), RREG, RA3);
103737da2899SCharles.Forsyth mem(Stw, O(Frame, mr), RA2, RA3);
103837da2899SCharles.Forsyth opwst(i, Ldw, RA3);
103937da2899SCharles.Forsyth CMPH(AL, RA3);
104037da2899SCharles.Forsyth mlnil = code;
104137da2899SCharles.Forsyth BRA(EQ, 0);
104237da2899SCharles.Forsyth if((i->add&ARM) == AXIMM) {
104337da2899SCharles.Forsyth mem(Ldw, OA(Modlink, links)+i->reg*sizeof(Modl)+O(Modl, u.pc), RA3, RA0);
104437da2899SCharles.Forsyth } else {
104537da2899SCharles.Forsyth mid(i, Ldw, RA1);
104637da2899SCharles.Forsyth DP(AL, Add, RA3, RA1, (3<<3), RA1); // assumes sizeof(Modl) == 8
104737da2899SCharles.Forsyth mem(Ldw, OA(Modlink, links)+O(Modl, u.pc), RA1, RA0);
104837da2899SCharles.Forsyth }
104937da2899SCharles.Forsyth PATCH(mlnil);
105037da2899SCharles.Forsyth CALLMAC(AL, MacMCAL);
105137da2899SCharles.Forsyth }
105237da2899SCharles.Forsyth
105337da2899SCharles.Forsyth static void
larith(Inst * i,int op,int opc)105437da2899SCharles.Forsyth larith(Inst *i, int op, int opc)
105537da2899SCharles.Forsyth {
105637da2899SCharles.Forsyth opwld(i, Lea, RA0);
105737da2899SCharles.Forsyth mid(i, Lea, RA3);
10587b3bf63cSCharles.Forsyth mem(Ldw, Blo, RA0, RA1); // ls
10597b3bf63cSCharles.Forsyth mem(Ldw, Blo, RA3, RA2);
106037da2899SCharles.Forsyth DP(AL, op, RA2, RA2, 0, RA1) | SBIT; // ls: RA2 = RA2 op RA1
10617b3bf63cSCharles.Forsyth mem(Ldw, Bhi, RA0, RA1);
10627b3bf63cSCharles.Forsyth mem(Ldw, Bhi, RA3, RA0);
106337da2899SCharles.Forsyth DP(AL, opc, RA0, RA0, 0, RA1); // ms: RA0 = RA0 opc RA1
106437da2899SCharles.Forsyth if((i->add&ARM) != AXNON)
106537da2899SCharles.Forsyth opwst(i, Lea, RA3);
10667b3bf63cSCharles.Forsyth mem(Stw, Blo, RA3, RA2);
10677b3bf63cSCharles.Forsyth mem(Stw, Bhi, RA3, RA0);
106837da2899SCharles.Forsyth }
106937da2899SCharles.Forsyth
107037da2899SCharles.Forsyth static void
movloop(Inst * i,int s)107137da2899SCharles.Forsyth movloop(Inst *i, int s)
107237da2899SCharles.Forsyth {
107337da2899SCharles.Forsyth int b;
107437da2899SCharles.Forsyth
107537da2899SCharles.Forsyth b = (s==1);
107637da2899SCharles.Forsyth opwst(i, Lea, RA2);
107737da2899SCharles.Forsyth LDxP(AL, RA1, RA0, s, b);
107837da2899SCharles.Forsyth STxP(AL, RA2, RA0, s, b);
107937da2899SCharles.Forsyth DPI(AL, Sub, RA3, RA3, 0, 1) | SBIT;
108037da2899SCharles.Forsyth BRA(NE, (-3*4-8)>>2);
108137da2899SCharles.Forsyth }
108237da2899SCharles.Forsyth
108337da2899SCharles.Forsyth static void
movmem(Inst * i)108437da2899SCharles.Forsyth movmem(Inst *i)
108537da2899SCharles.Forsyth {
108637da2899SCharles.Forsyth ulong *cp;
108737da2899SCharles.Forsyth
108837da2899SCharles.Forsyth // source address already in RA1
108937da2899SCharles.Forsyth if((i->add&ARM) != AXIMM){
109037da2899SCharles.Forsyth mid(i, Ldw, RA3);
109137da2899SCharles.Forsyth CMPI(AL, RA3, 0, 0, 0);
109237da2899SCharles.Forsyth cp = code;
109337da2899SCharles.Forsyth BRA(LE, 0);
109437da2899SCharles.Forsyth movloop(i, 1);
109537da2899SCharles.Forsyth PATCH(cp);
109637da2899SCharles.Forsyth return;
109737da2899SCharles.Forsyth }
109837da2899SCharles.Forsyth switch(i->reg){
109937da2899SCharles.Forsyth case 0:
110037da2899SCharles.Forsyth break;
110137da2899SCharles.Forsyth case 4:
110237da2899SCharles.Forsyth LDW(AL, RA1, RA2, 0);
110337da2899SCharles.Forsyth opwst(i, Stw, RA2);
110437da2899SCharles.Forsyth break;
110537da2899SCharles.Forsyth case 8:
110637da2899SCharles.Forsyth LDW(AL, RA1, RA2, 0);
110737da2899SCharles.Forsyth opwst(i, Lea, RA3);
110837da2899SCharles.Forsyth LDW(AL, RA1, RA1, 4);
110937da2899SCharles.Forsyth STW(AL, RA3, RA2, 0);
111037da2899SCharles.Forsyth STW(AL, RA3, RA1, 4);
111137da2899SCharles.Forsyth break;
111237da2899SCharles.Forsyth default:
111337da2899SCharles.Forsyth // could use ldm/stm loop...
111437da2899SCharles.Forsyth if((i->reg&3) == 0) {
111537da2899SCharles.Forsyth con(i->reg>>2, RA3, 1);
111637da2899SCharles.Forsyth movloop(i, 4);
111737da2899SCharles.Forsyth } else {
111837da2899SCharles.Forsyth con(i->reg, RA3, 1);
111937da2899SCharles.Forsyth movloop(i, 1);
112037da2899SCharles.Forsyth }
112137da2899SCharles.Forsyth break;
112237da2899SCharles.Forsyth }
112337da2899SCharles.Forsyth }
112437da2899SCharles.Forsyth
112537da2899SCharles.Forsyth static
112637da2899SCharles.Forsyth void
compdbg(void)112737da2899SCharles.Forsyth compdbg(void)
112837da2899SCharles.Forsyth {
112937da2899SCharles.Forsyth print("%s:%lud@%.8lux\n", R.M->m->name, *(ulong*)R.m, *(ulong*)R.s);
113037da2899SCharles.Forsyth }
113137da2899SCharles.Forsyth
113237da2899SCharles.Forsyth static void
comgoto(Inst * i)113337da2899SCharles.Forsyth comgoto(Inst *i)
113437da2899SCharles.Forsyth {
113537da2899SCharles.Forsyth WORD *t, *e;
113637da2899SCharles.Forsyth
113737da2899SCharles.Forsyth opwld(i, Ldw, RA1);
113837da2899SCharles.Forsyth opwst(i, Lea, RA0);
113937da2899SCharles.Forsyth LDRW(AL, RA0, R15, (2<<3), RA1);
114037da2899SCharles.Forsyth flushcon(0);
114137da2899SCharles.Forsyth
114237da2899SCharles.Forsyth if(pass == 0)
114337da2899SCharles.Forsyth return;
114437da2899SCharles.Forsyth
114537da2899SCharles.Forsyth t = (WORD*)(mod->origmp+i->d.ind);
114637da2899SCharles.Forsyth e = t + t[-1];
114737da2899SCharles.Forsyth t[-1] = 0;
114837da2899SCharles.Forsyth while(t < e) {
114937da2899SCharles.Forsyth t[0] = RELPC(patch[t[0]]);
115037da2899SCharles.Forsyth t++;
115137da2899SCharles.Forsyth }
115237da2899SCharles.Forsyth }
115337da2899SCharles.Forsyth
115437da2899SCharles.Forsyth static void
comp(Inst * i)115537da2899SCharles.Forsyth comp(Inst *i)
115637da2899SCharles.Forsyth {
115737da2899SCharles.Forsyth int r, imm;
115837da2899SCharles.Forsyth char buf[64];
115937da2899SCharles.Forsyth //ulong *s = code;
116037da2899SCharles.Forsyth if(0) {
116137da2899SCharles.Forsyth Inst xx;
116237da2899SCharles.Forsyth xx.add = AXIMM|SRC(AIMM);
116337da2899SCharles.Forsyth xx.s.imm = (ulong)code;
116437da2899SCharles.Forsyth xx.reg = i-mod->prog;
116537da2899SCharles.Forsyth puntpc = 0;
116637da2899SCharles.Forsyth punt(&xx, SRCOP, compdbg);
116737da2899SCharles.Forsyth puntpc = 1;
116837da2899SCharles.Forsyth flushcon(1);
116937da2899SCharles.Forsyth }
117037da2899SCharles.Forsyth flushchk();
117137da2899SCharles.Forsyth
117237da2899SCharles.Forsyth switch(i->op) {
117337da2899SCharles.Forsyth default:
117437da2899SCharles.Forsyth snprint(buf, sizeof buf, "%s compile, no '%D'", mod->name, i);
117537da2899SCharles.Forsyth error(buf);
117637da2899SCharles.Forsyth break;
117737da2899SCharles.Forsyth case IMCALL:
117837da2899SCharles.Forsyth if((i->add&ARM) == AXIMM)
117937da2899SCharles.Forsyth commcall(i);
118037da2899SCharles.Forsyth else
118137da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|THREOP|WRTPC|NEWPC, optab[i->op]);
118237da2899SCharles.Forsyth break;
118337da2899SCharles.Forsyth case ISEND:
118437da2899SCharles.Forsyth case IRECV:
118537da2899SCharles.Forsyth case IALT:
118637da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|TCHECK|WRTPC, optab[i->op]);
118737da2899SCharles.Forsyth break;
118837da2899SCharles.Forsyth case ISPAWN:
118937da2899SCharles.Forsyth punt(i, SRCOP|DBRAN, optab[i->op]);
119037da2899SCharles.Forsyth break;
119137da2899SCharles.Forsyth case IBNEC:
119237da2899SCharles.Forsyth case IBEQC:
119337da2899SCharles.Forsyth case IBLTC:
119437da2899SCharles.Forsyth case IBLEC:
119537da2899SCharles.Forsyth case IBGTC:
119637da2899SCharles.Forsyth case IBGEC:
119737da2899SCharles.Forsyth punt(i, SRCOP|DBRAN|NEWPC|WRTPC, optab[i->op]);
119837da2899SCharles.Forsyth break;
119937da2899SCharles.Forsyth case ICASEC:
120037da2899SCharles.Forsyth comcase(i, 0);
120137da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|NEWPC, optab[i->op]);
120237da2899SCharles.Forsyth break;
120337da2899SCharles.Forsyth case ICASEL:
120437da2899SCharles.Forsyth comcasel(i);
120537da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|NEWPC, optab[i->op]);
120637da2899SCharles.Forsyth break;
120737da2899SCharles.Forsyth case IADDC:
120837da2899SCharles.Forsyth case IMULL:
120937da2899SCharles.Forsyth case IDIVL:
121037da2899SCharles.Forsyth case IMODL:
121137da2899SCharles.Forsyth case IMNEWZ:
121237da2899SCharles.Forsyth case ILSRW:
121337da2899SCharles.Forsyth case ILSRL:
121437da2899SCharles.Forsyth case IMODW:
121537da2899SCharles.Forsyth case IMODB:
121637da2899SCharles.Forsyth case IDIVW:
121737da2899SCharles.Forsyth case IDIVB:
121837da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
121937da2899SCharles.Forsyth break;
122037da2899SCharles.Forsyth case ILOAD:
122137da2899SCharles.Forsyth case INEWA:
122237da2899SCharles.Forsyth case INEWAZ:
122337da2899SCharles.Forsyth case INEW:
122437da2899SCharles.Forsyth case INEWZ:
122537da2899SCharles.Forsyth case ISLICEA:
122637da2899SCharles.Forsyth case ISLICELA:
122737da2899SCharles.Forsyth case ICONSB:
122837da2899SCharles.Forsyth case ICONSW:
122937da2899SCharles.Forsyth case ICONSL:
123037da2899SCharles.Forsyth case ICONSF:
123137da2899SCharles.Forsyth case ICONSM:
123237da2899SCharles.Forsyth case ICONSMP:
123337da2899SCharles.Forsyth case ICONSP:
123437da2899SCharles.Forsyth case IMOVMP:
123537da2899SCharles.Forsyth case IHEADMP:
123637da2899SCharles.Forsyth case IHEADB:
123737da2899SCharles.Forsyth case IHEADW:
123837da2899SCharles.Forsyth case IHEADL:
123937da2899SCharles.Forsyth case IINSC:
124037da2899SCharles.Forsyth case ICVTAC:
124137da2899SCharles.Forsyth case ICVTCW:
124237da2899SCharles.Forsyth case ICVTWC:
124337da2899SCharles.Forsyth case ICVTLC:
124437da2899SCharles.Forsyth case ICVTCL:
124537da2899SCharles.Forsyth case ICVTFC:
124637da2899SCharles.Forsyth case ICVTCF:
124737da2899SCharles.Forsyth case ICVTRF:
124837da2899SCharles.Forsyth case ICVTFR:
124937da2899SCharles.Forsyth case ICVTWS:
125037da2899SCharles.Forsyth case ICVTSW:
125137da2899SCharles.Forsyth case IMSPAWN:
125237da2899SCharles.Forsyth case ICVTCA:
125337da2899SCharles.Forsyth case ISLICEC:
125437da2899SCharles.Forsyth case INBALT:
125537da2899SCharles.Forsyth punt(i, SRCOP|DSTOP, optab[i->op]);
125637da2899SCharles.Forsyth break;
125737da2899SCharles.Forsyth case INEWCM:
125837da2899SCharles.Forsyth case INEWCMP:
125937da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
126037da2899SCharles.Forsyth break;
126137da2899SCharles.Forsyth case IMFRAME:
126237da2899SCharles.Forsyth if((i->add&ARM) == AXIMM)
126337da2899SCharles.Forsyth commframe(i);
126437da2899SCharles.Forsyth else
126537da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
126637da2899SCharles.Forsyth break;
126737da2899SCharles.Forsyth case ICASE:
126837da2899SCharles.Forsyth comcase(i, 1);
126937da2899SCharles.Forsyth break;
127037da2899SCharles.Forsyth case IGOTO:
127137da2899SCharles.Forsyth comgoto(i);
127237da2899SCharles.Forsyth break;
127337da2899SCharles.Forsyth case IMOVF:
1274*1414757bSCharles Forsyth if(!SOFTFP){
127537da2899SCharles.Forsyth opflld(i, Ldf, FA2);
127637da2899SCharles.Forsyth opflst(i, Stf, FA2);
127737da2899SCharles.Forsyth break;
127837da2899SCharles.Forsyth }
127937da2899SCharles.Forsyth /* if no hardware, just fall through */
128037da2899SCharles.Forsyth case IMOVL:
128137da2899SCharles.Forsyth opwld(i, Lea, RA1);
128237da2899SCharles.Forsyth LDW(AL, RA1, RA2, 0);
128337da2899SCharles.Forsyth LDW(AL, RA1, RA3, 4);
128437da2899SCharles.Forsyth opwst(i, Lea, RA1);
128537da2899SCharles.Forsyth STW(AL, RA1, RA2, 0);
128637da2899SCharles.Forsyth STW(AL, RA1, RA3, 4);
128737da2899SCharles.Forsyth break;
128837da2899SCharles.Forsyth break;
128937da2899SCharles.Forsyth case IHEADM:
129037da2899SCharles.Forsyth opwld(i, Ldw, RA1);
129137da2899SCharles.Forsyth NOTNIL(RA1);
1292*1414757bSCharles Forsyth if(OA(List,data) != 0)
129337da2899SCharles.Forsyth DPI(AL, Add, RA1, RA1, 0, OA(List,data));
129437da2899SCharles.Forsyth movmem(i);
129537da2899SCharles.Forsyth break;
129637da2899SCharles.Forsyth /*
129737da2899SCharles.Forsyth case IHEADW:
129837da2899SCharles.Forsyth opwld(i, Ldw, RA0);
129937da2899SCharles.Forsyth NOTNIL(RA0);
130037da2899SCharles.Forsyth mem(Ldw, OA(List, data), RA0, RA0);
130137da2899SCharles.Forsyth opwst(i, Stw, RA0);
130237da2899SCharles.Forsyth break;
130337da2899SCharles.Forsyth */
130437da2899SCharles.Forsyth case IMOVM:
130537da2899SCharles.Forsyth opwld(i, Lea, RA1);
130637da2899SCharles.Forsyth movmem(i);
130737da2899SCharles.Forsyth break;
130837da2899SCharles.Forsyth case IFRAME:
130937da2899SCharles.Forsyth if(UXSRC(i->add) != SRC(AIMM)) {
131037da2899SCharles.Forsyth punt(i, SRCOP|DSTOP, optab[i->op]);
131137da2899SCharles.Forsyth break;
131237da2899SCharles.Forsyth }
131337da2899SCharles.Forsyth tinit[i->s.imm] = 1;
131437da2899SCharles.Forsyth con((ulong)mod->type[i->s.imm], RA3, 1);
131537da2899SCharles.Forsyth CALL(base+macro[MacFRAM]);
131637da2899SCharles.Forsyth opwst(i, Stw, RA2);
131737da2899SCharles.Forsyth break;
131837da2899SCharles.Forsyth case INEWCB:
131937da2899SCharles.Forsyth case INEWCW:
132037da2899SCharles.Forsyth case INEWCF:
132137da2899SCharles.Forsyth case INEWCP:
132237da2899SCharles.Forsyth case INEWCL:
132337da2899SCharles.Forsyth punt(i, DSTOP|THREOP, optab[i->op]);
132437da2899SCharles.Forsyth break;
132537da2899SCharles.Forsyth case IEXIT:
132637da2899SCharles.Forsyth punt(i, 0, optab[i->op]);
132737da2899SCharles.Forsyth break;
132837da2899SCharles.Forsyth case ICVTBW:
132937da2899SCharles.Forsyth opwld(i, Ldb, RA0);
133037da2899SCharles.Forsyth opwst(i, Stw, RA0);
133137da2899SCharles.Forsyth break;
133237da2899SCharles.Forsyth case ICVTWB:
133337da2899SCharles.Forsyth opwld(i, Ldw, RA0);
133437da2899SCharles.Forsyth opwst(i, Stb, RA0);
133537da2899SCharles.Forsyth break;
133637da2899SCharles.Forsyth case ILEA:
133737da2899SCharles.Forsyth opwld(i, Lea, RA0);
133837da2899SCharles.Forsyth opwst(i, Stw, RA0);
133937da2899SCharles.Forsyth break;
134037da2899SCharles.Forsyth case IMOVW:
134137da2899SCharles.Forsyth opwld(i, Ldw, RA0);
134237da2899SCharles.Forsyth opwst(i, Stw, RA0);
134337da2899SCharles.Forsyth break;
134437da2899SCharles.Forsyth case IMOVB:
134537da2899SCharles.Forsyth opwld(i, Ldb, RA0);
134637da2899SCharles.Forsyth opwst(i, Stb, RA0);
134737da2899SCharles.Forsyth break;
134837da2899SCharles.Forsyth case ITAIL:
134937da2899SCharles.Forsyth opwld(i, Ldw, RA0);
135037da2899SCharles.Forsyth NOTNIL(RA0);
135137da2899SCharles.Forsyth mem(Ldw, O(List, tail), RA0, RA1);
135237da2899SCharles.Forsyth goto movp;
135337da2899SCharles.Forsyth case IMOVP:
135437da2899SCharles.Forsyth opwld(i, Ldw, RA1);
135537da2899SCharles.Forsyth goto movp;
135637da2899SCharles.Forsyth case IHEADP:
135737da2899SCharles.Forsyth opwld(i, Ldw, RA0);
135837da2899SCharles.Forsyth NOTNIL(RA0);
135937da2899SCharles.Forsyth mem(Ldw, OA(List, data), RA0, RA1);
136037da2899SCharles.Forsyth movp:
136137da2899SCharles.Forsyth CMPH(AL, RA1);
136237da2899SCharles.Forsyth CALLMAC(NE, MacCOLR); // colour if not H
136337da2899SCharles.Forsyth opwst(i, Lea, RA2);
136437da2899SCharles.Forsyth mem(Ldw, 0,RA2, RA0);
136537da2899SCharles.Forsyth mem(Stw, 0,RA2, RA1);
136637da2899SCharles.Forsyth CALLMAC(AL, MacFRP);
136737da2899SCharles.Forsyth break;
136837da2899SCharles.Forsyth case ILENA:
136937da2899SCharles.Forsyth opwld(i, Ldw, RA1);
137037da2899SCharles.Forsyth con(0, RA0, 1);
137137da2899SCharles.Forsyth CMPH(AL, RA1);
137237da2899SCharles.Forsyth LDW(NE, RA1, RA0, O(Array,len));
137337da2899SCharles.Forsyth opwst(i, Stw, RA0);
137437da2899SCharles.Forsyth break;
137537da2899SCharles.Forsyth case ILENC:
137637da2899SCharles.Forsyth opwld(i, Ldw, RA1);
137737da2899SCharles.Forsyth con(0, RA0, 1);
137837da2899SCharles.Forsyth CMPH(AL, RA1);
137937da2899SCharles.Forsyth memc(NE, Ldw, O(String,len),RA1, RA0);
138037da2899SCharles.Forsyth CMPI(AL, RA0, 0, 0, 0);
138137da2899SCharles.Forsyth DPI(LT, Rsb, RA0, RA0, 0, 0);
138237da2899SCharles.Forsyth opwst(i, Stw, RA0);
138337da2899SCharles.Forsyth break;
138437da2899SCharles.Forsyth case ILENL:
138537da2899SCharles.Forsyth con(0, RA0, 1);
138637da2899SCharles.Forsyth opwld(i, Ldw, RA1);
138737da2899SCharles.Forsyth
138837da2899SCharles.Forsyth CMPH(AL, RA1);
138937da2899SCharles.Forsyth LDW(NE, RA1, RA1, O(List, tail));
139037da2899SCharles.Forsyth DPI(NE, Add, RA0, RA0, 0, 1);
139137da2899SCharles.Forsyth BRA(NE, (-4*3-8)>>2);
139237da2899SCharles.Forsyth
139337da2899SCharles.Forsyth opwst(i, Stw, RA0);
139437da2899SCharles.Forsyth break;
139537da2899SCharles.Forsyth case ICALL:
139637da2899SCharles.Forsyth opwld(i, Ldw, RA0);
139737da2899SCharles.Forsyth con(RELPC(patch[i-mod->prog+1]), RA1, 0);
139837da2899SCharles.Forsyth mem(Stw, O(Frame, lr), RA0, RA1);
139937da2899SCharles.Forsyth mem(Stw, O(Frame, fp), RA0, RFP);
140037da2899SCharles.Forsyth MOV(RA0, RFP);
140137da2899SCharles.Forsyth BRADIS(AL, i->d.ins-mod->prog);
140237da2899SCharles.Forsyth flushcon(0);
140337da2899SCharles.Forsyth break;
140437da2899SCharles.Forsyth case IJMP:
140537da2899SCharles.Forsyth if(RESCHED)
140637da2899SCharles.Forsyth schedcheck(i);
140737da2899SCharles.Forsyth BRADIS(AL, i->d.ins-mod->prog);
140837da2899SCharles.Forsyth flushcon(0);
140937da2899SCharles.Forsyth break;
141037da2899SCharles.Forsyth case IBEQW:
141137da2899SCharles.Forsyth cbra(i, EQ);
141237da2899SCharles.Forsyth break;
141337da2899SCharles.Forsyth case IBNEW:
141437da2899SCharles.Forsyth cbra(i, NE);
141537da2899SCharles.Forsyth break;
141637da2899SCharles.Forsyth case IBLTW:
141737da2899SCharles.Forsyth cbra(i, LT);
141837da2899SCharles.Forsyth break;
141937da2899SCharles.Forsyth case IBLEW:
142037da2899SCharles.Forsyth cbra(i, LE);
142137da2899SCharles.Forsyth break;
142237da2899SCharles.Forsyth case IBGTW:
142337da2899SCharles.Forsyth cbra(i, GT);
142437da2899SCharles.Forsyth break;
142537da2899SCharles.Forsyth case IBGEW:
142637da2899SCharles.Forsyth cbra(i, GE);
142737da2899SCharles.Forsyth break;
142837da2899SCharles.Forsyth case IBEQB:
142937da2899SCharles.Forsyth cbrab(i, EQ);
143037da2899SCharles.Forsyth break;
143137da2899SCharles.Forsyth case IBNEB:
143237da2899SCharles.Forsyth cbrab(i, NE);
143337da2899SCharles.Forsyth break;
143437da2899SCharles.Forsyth case IBLTB:
143537da2899SCharles.Forsyth cbrab(i, LT);
143637da2899SCharles.Forsyth break;
143737da2899SCharles.Forsyth case IBLEB:
143837da2899SCharles.Forsyth cbrab(i, LE);
143937da2899SCharles.Forsyth break;
144037da2899SCharles.Forsyth case IBGTB:
144137da2899SCharles.Forsyth cbrab(i, GT);
144237da2899SCharles.Forsyth break;
144337da2899SCharles.Forsyth case IBGEB:
144437da2899SCharles.Forsyth cbrab(i, GE);
144537da2899SCharles.Forsyth break;
144637da2899SCharles.Forsyth case IBEQF:
144737da2899SCharles.Forsyth cbraf(i, EQ);
144837da2899SCharles.Forsyth break;
144937da2899SCharles.Forsyth case IBNEF:
145037da2899SCharles.Forsyth cbraf(i, NE);
145137da2899SCharles.Forsyth break;
145237da2899SCharles.Forsyth case IBLTF:
145337da2899SCharles.Forsyth cbraf(i, LT);
145437da2899SCharles.Forsyth break;
145537da2899SCharles.Forsyth case IBLEF:
145637da2899SCharles.Forsyth cbraf(i, LE);
145737da2899SCharles.Forsyth break;
145837da2899SCharles.Forsyth case IBGTF:
145937da2899SCharles.Forsyth cbraf(i, GT);
146037da2899SCharles.Forsyth break;
146137da2899SCharles.Forsyth case IBGEF:
146237da2899SCharles.Forsyth cbraf(i, GE);
146337da2899SCharles.Forsyth break;
146437da2899SCharles.Forsyth case IRET:
146537da2899SCharles.Forsyth mem(Ldw, O(Frame,t), RFP, RA1);
146637da2899SCharles.Forsyth BRAMAC(AL, MacRET);
146737da2899SCharles.Forsyth break;
146837da2899SCharles.Forsyth case IMULW:
146937da2899SCharles.Forsyth opwld(i, Ldw, RA1);
147037da2899SCharles.Forsyth mid(i, Ldw, RA0);
147137da2899SCharles.Forsyth MUL(AL, RA1, RA0, RA0);
147237da2899SCharles.Forsyth opwst(i, Stw, RA0);
147337da2899SCharles.Forsyth break;
147437da2899SCharles.Forsyth case IMULB:
147537da2899SCharles.Forsyth opwld(i, Ldb, RA1);
147637da2899SCharles.Forsyth mid(i, Ldb, RA0);
147737da2899SCharles.Forsyth MUL(AL, RA1, RA0, RA0);
147837da2899SCharles.Forsyth opwst(i, Stb, RA0);
147937da2899SCharles.Forsyth break;
148037da2899SCharles.Forsyth case IORW:
148137da2899SCharles.Forsyth r = Orr;
148237da2899SCharles.Forsyth goto arithw;
148337da2899SCharles.Forsyth case IANDW:
148437da2899SCharles.Forsyth r = And;
148537da2899SCharles.Forsyth goto arithw;
148637da2899SCharles.Forsyth case IXORW:
148737da2899SCharles.Forsyth r = Eor;
148837da2899SCharles.Forsyth goto arithw;
148937da2899SCharles.Forsyth case ISUBW:
149037da2899SCharles.Forsyth r = Sub;
149137da2899SCharles.Forsyth goto arithw;
149237da2899SCharles.Forsyth case IADDW:
149337da2899SCharles.Forsyth r = Add;
149437da2899SCharles.Forsyth arithw:
149537da2899SCharles.Forsyth mid(i, Ldw, RA1);
149637da2899SCharles.Forsyth if(UXSRC(i->add) == SRC(AIMM) && FITS8(i->s.imm))
149737da2899SCharles.Forsyth DPI(AL, r, RA1, RA0, 0, i->s.imm);
149837da2899SCharles.Forsyth else if(UXSRC(i->add) == SRC(AIMM) && immrot(i->s.imm)){
149937da2899SCharles.Forsyth DPI(AL, r, RA1, RA0, 0, 0) | immrot(i->s.imm);
150037da2899SCharles.Forsyth //print("rot: %ux %ux\n", i->s.imm, immrot(i->s.imm)); das(code-1, 1);
150137da2899SCharles.Forsyth } else {
150237da2899SCharles.Forsyth opwld(i, Ldw, RA0);
150337da2899SCharles.Forsyth DP(AL, r, RA1, RA0, 0, RA0);
150437da2899SCharles.Forsyth }
150537da2899SCharles.Forsyth opwst(i, Stw, RA0);
150637da2899SCharles.Forsyth break;
150737da2899SCharles.Forsyth case ISHRW:
150837da2899SCharles.Forsyth r = 2;
150937da2899SCharles.Forsyth shiftw:
151037da2899SCharles.Forsyth mid(i, Ldw, RA1);
151137da2899SCharles.Forsyth if(UXSRC(i->add) == SRC(AIMM) && FITS5(i->s.imm))
151237da2899SCharles.Forsyth DP(AL, Mov, 0, RA0, ((i->s.imm&0x3F)<<3)|(r<<1), RA1);
151337da2899SCharles.Forsyth else {
151437da2899SCharles.Forsyth opwld(i, Ldw, RA0);
151537da2899SCharles.Forsyth DP(AL, Mov, 0, RA0, (RA0<<4)|(r<<1)|1, RA1);
151637da2899SCharles.Forsyth }
151737da2899SCharles.Forsyth opwst(i, Stw, RA0);
151837da2899SCharles.Forsyth break;
151937da2899SCharles.Forsyth case ISHLW:
152037da2899SCharles.Forsyth r = 0;
152137da2899SCharles.Forsyth goto shiftw;
152237da2899SCharles.Forsyth break;
152337da2899SCharles.Forsyth case IORB:
152437da2899SCharles.Forsyth r = Orr;
152537da2899SCharles.Forsyth goto arithb;
152637da2899SCharles.Forsyth case IANDB:
152737da2899SCharles.Forsyth r = And;
152837da2899SCharles.Forsyth goto arithb;
152937da2899SCharles.Forsyth case IXORB:
153037da2899SCharles.Forsyth r = Eor;
153137da2899SCharles.Forsyth goto arithb;
153237da2899SCharles.Forsyth case ISUBB:
153337da2899SCharles.Forsyth r = Sub;
153437da2899SCharles.Forsyth goto arithb;
153537da2899SCharles.Forsyth case IADDB:
153637da2899SCharles.Forsyth r = Add;
153737da2899SCharles.Forsyth arithb:
153837da2899SCharles.Forsyth mid(i, Ldb, RA1);
153937da2899SCharles.Forsyth if(UXSRC(i->add) == SRC(AIMM))
154037da2899SCharles.Forsyth DPI(AL, r, RA1, RA0, 0, i->s.imm);
154137da2899SCharles.Forsyth else {
154237da2899SCharles.Forsyth opwld(i, Ldb, RA0);
154337da2899SCharles.Forsyth DP(AL, r, RA1, RA0, 0, RA0);
154437da2899SCharles.Forsyth }
154537da2899SCharles.Forsyth opwst(i, Stb, RA0);
154637da2899SCharles.Forsyth break;
154737da2899SCharles.Forsyth case ISHRB:
154837da2899SCharles.Forsyth r = 2;
154937da2899SCharles.Forsyth goto shiftb;
155037da2899SCharles.Forsyth case ISHLB:
155137da2899SCharles.Forsyth r = 0;
155237da2899SCharles.Forsyth shiftb:
155337da2899SCharles.Forsyth mid(i, Ldb, RA1);
155437da2899SCharles.Forsyth if(UXSRC(i->add) == SRC(AIMM) && FITS5(i->s.imm))
155537da2899SCharles.Forsyth DP(AL, Mov, 0, RA0, ((i->s.imm&0x3F)<<3)|(r<<1), RA1);
155637da2899SCharles.Forsyth else {
155737da2899SCharles.Forsyth opwld(i, Ldw, RA0);
155837da2899SCharles.Forsyth DP(AL, Mov, 0, RA0, (RA0<<4)|(r<<1)|1, RA1);
155937da2899SCharles.Forsyth }
156037da2899SCharles.Forsyth opwst(i, Stb, RA0);
156137da2899SCharles.Forsyth break;
156237da2899SCharles.Forsyth case IINDC:
156337da2899SCharles.Forsyth opwld(i, Ldw, RA1); // RA1 = string
156437da2899SCharles.Forsyth NOTNIL(RA1);
156537da2899SCharles.Forsyth imm = 1;
1566*1414757bSCharles Forsyth if((i->add&ARM) != AXIMM || !FITS12((short)i->reg<<Lg2Rune) || immrot((short)i->reg) == 0){
156737da2899SCharles.Forsyth mid(i, Ldw, RA2); // RA2 = i
156837da2899SCharles.Forsyth imm = 0;
156937da2899SCharles.Forsyth }
157037da2899SCharles.Forsyth mem(Ldw, O(String,len),RA1, RA0); // len<0 => index Runes, otherwise bytes
1571*1414757bSCharles Forsyth if(bflag){
1572*1414757bSCharles Forsyth DPI(AL, Orr, RA0, RA3, 0, 0);
1573*1414757bSCharles Forsyth DPI(LT, Rsb, RA3, RA3, 0, 0);
1574*1414757bSCharles Forsyth if(imm)
1575*1414757bSCharles Forsyth BCKR(immrot((short)i->reg), RA3);
1576*1414757bSCharles Forsyth else
1577*1414757bSCharles Forsyth BCK(RA2, RA3);
1578*1414757bSCharles Forsyth }
157937da2899SCharles.Forsyth DPI(AL, Add, RA1, RA1, 0, O(String,data));
158037da2899SCharles.Forsyth CMPI(AL, RA0, 0, 0, 0);
158137da2899SCharles.Forsyth if(imm){
158237da2899SCharles.Forsyth LDB(GE, RA1, RA3, i->reg);
1583*1414757bSCharles Forsyth LDW(LT, RA1, RA3, (short)i->reg<<Lg2Rune);
158437da2899SCharles.Forsyth } else {
158537da2899SCharles.Forsyth LDRB(GE, RA1, RA3, 0, RA2);
1586*1414757bSCharles Forsyth DP(LT, Mov, 0, RA2, (Lg2Rune<<3), RA2);
15879289f13aSforsyth LDRW(LT, RA1, RA3, 0, RA2);
158837da2899SCharles.Forsyth }
158937da2899SCharles.Forsyth opwst(i, Stw, RA3);
1590*1414757bSCharles Forsyth //if(pass){print("%D\n", i); das(s, code-s);}
159137da2899SCharles.Forsyth break;
159237da2899SCharles.Forsyth case IINDL:
159337da2899SCharles.Forsyth case IINDF:
159437da2899SCharles.Forsyth case IINDW:
159537da2899SCharles.Forsyth case IINDB:
159637da2899SCharles.Forsyth opwld(i, Ldw, RA0); /* a */
159737da2899SCharles.Forsyth NOTNIL(RA0);
159837da2899SCharles.Forsyth if(bflag)
159937da2899SCharles.Forsyth mem(Ldw, O(Array, len), RA0, RA2);
1600*1414757bSCharles Forsyth mem(Ldw, O(Array, data), RA0, RA0);
160137da2899SCharles.Forsyth r = 0;
160237da2899SCharles.Forsyth switch(i->op) {
160337da2899SCharles.Forsyth case IINDL:
160437da2899SCharles.Forsyth case IINDF:
160537da2899SCharles.Forsyth r = 3;
160637da2899SCharles.Forsyth break;
160737da2899SCharles.Forsyth case IINDW:
160837da2899SCharles.Forsyth r = 2;
160937da2899SCharles.Forsyth break;
161037da2899SCharles.Forsyth }
1611*1414757bSCharles Forsyth if(UXDST(i->add) == DST(AIMM) && (imm = immrot(i->d.imm)) != 0) {
161237da2899SCharles.Forsyth if(bflag)
1613*1414757bSCharles Forsyth BCKR(imm, RA2);
1614*1414757bSCharles Forsyth if(i->d.imm != 0)
1615*1414757bSCharles Forsyth DPI(AL, Add, RA0, RA0, 0, 0) | immrot(i->d.imm<<r);
161637da2899SCharles.Forsyth } else {
161737da2899SCharles.Forsyth opwst(i, Ldw, RA1);
161837da2899SCharles.Forsyth if(bflag)
161937da2899SCharles.Forsyth BCK(RA1, RA2);
162037da2899SCharles.Forsyth DP(AL, Add, RA0, RA0, r<<3, RA1);
162137da2899SCharles.Forsyth }
162237da2899SCharles.Forsyth mid(i, Stw, RA0);
1623*1414757bSCharles Forsyth //if(pass){print("%D\n", i); das(s, code-s);}
162437da2899SCharles.Forsyth break;
162537da2899SCharles.Forsyth case IINDX:
162637da2899SCharles.Forsyth opwld(i, Ldw, RA0); /* a */
162737da2899SCharles.Forsyth NOTNIL(RA0);
162837da2899SCharles.Forsyth opwst(i, Ldw, RA1); /* i */
162937da2899SCharles.Forsyth
163037da2899SCharles.Forsyth if(bflag){
163137da2899SCharles.Forsyth mem(Ldw, O(Array, len), RA0, RA2);
163237da2899SCharles.Forsyth BCK(RA1, RA2);
163337da2899SCharles.Forsyth }
163437da2899SCharles.Forsyth mem(Ldw, O(Array, t), RA0, RA2);
163537da2899SCharles.Forsyth mem(Ldw, O(Array, data), RA0, RA0);
163637da2899SCharles.Forsyth mem(Ldw, O(Type, size), RA2, RA2);
163737da2899SCharles.Forsyth MUL(AL, RA2, RA1, RA1);
163837da2899SCharles.Forsyth DP(AL, Add, RA1, RA0, 0, RA0);
163937da2899SCharles.Forsyth mid(i, Stw, RA0);
1640*1414757bSCharles Forsyth //if(pass){print("%D\n", i); das(s, code-s);}
164137da2899SCharles.Forsyth break;
164237da2899SCharles.Forsyth case IADDL:
164337da2899SCharles.Forsyth larith(i, Add, Adc);
164437da2899SCharles.Forsyth break;
164537da2899SCharles.Forsyth case ISUBL:
164637da2899SCharles.Forsyth larith(i, Sub, Sbc);
164737da2899SCharles.Forsyth break;
164837da2899SCharles.Forsyth case IORL:
164937da2899SCharles.Forsyth larith(i, Orr, Orr);
165037da2899SCharles.Forsyth break;
165137da2899SCharles.Forsyth case IANDL:
165237da2899SCharles.Forsyth larith(i, And, And);
165337da2899SCharles.Forsyth break;
165437da2899SCharles.Forsyth case IXORL:
165537da2899SCharles.Forsyth larith(i, Eor, Eor);
165637da2899SCharles.Forsyth break;
165737da2899SCharles.Forsyth case ICVTWL:
165837da2899SCharles.Forsyth opwld(i, Ldw, RA1);
165937da2899SCharles.Forsyth opwst(i, Lea, RA2);
166037da2899SCharles.Forsyth DP(AL, Mov, 0, RA0, (0<<3)|(2<<1), RA1); // ASR 32
16617b3bf63cSCharles.Forsyth STW(AL, RA2, RA1, Blo);
16627b3bf63cSCharles.Forsyth STW(AL, RA2, RA0, Bhi);
166337da2899SCharles.Forsyth break;
166437da2899SCharles.Forsyth case ICVTLW:
166537da2899SCharles.Forsyth opwld(i, Lea, RA0);
16667b3bf63cSCharles.Forsyth mem(Ldw, Blo, RA0, RA0);
166737da2899SCharles.Forsyth opwst(i, Stw, RA0);
166837da2899SCharles.Forsyth break;
166937da2899SCharles.Forsyth case IBEQL:
167037da2899SCharles.Forsyth cbral(i, NE, EQ, ANDAND);
167137da2899SCharles.Forsyth break;
167237da2899SCharles.Forsyth case IBNEL:
167337da2899SCharles.Forsyth cbral(i, NE, NE, OROR);
167437da2899SCharles.Forsyth break;
167537da2899SCharles.Forsyth case IBLEL:
167637da2899SCharles.Forsyth cbral(i, LT, LS, EQAND);
167737da2899SCharles.Forsyth break;
167837da2899SCharles.Forsyth case IBGTL:
167937da2899SCharles.Forsyth cbral(i, GT, HI, EQAND);
168037da2899SCharles.Forsyth break;
168137da2899SCharles.Forsyth case IBLTL:
168237da2899SCharles.Forsyth cbral(i, LT, CC, EQAND);
168337da2899SCharles.Forsyth break;
168437da2899SCharles.Forsyth case IBGEL:
168537da2899SCharles.Forsyth cbral(i, GT, CS, EQAND);
168637da2899SCharles.Forsyth break;
168737da2899SCharles.Forsyth case ICVTFL:
168837da2899SCharles.Forsyth case ICVTLF:
168937da2899SCharles.Forsyth punt(i, SRCOP|DSTOP, optab[i->op]);
169037da2899SCharles.Forsyth break;
169137da2899SCharles.Forsyth case IDIVF:
169237da2899SCharles.Forsyth r = Dvf;
169337da2899SCharles.Forsyth goto arithf;
169437da2899SCharles.Forsyth case IMULF:
169537da2899SCharles.Forsyth r = Muf;
169637da2899SCharles.Forsyth goto arithf;
169737da2899SCharles.Forsyth case ISUBF:
169837da2899SCharles.Forsyth r = Suf;
169937da2899SCharles.Forsyth goto arithf;
170037da2899SCharles.Forsyth case IADDF:
170137da2899SCharles.Forsyth r = Adf;
170237da2899SCharles.Forsyth arithf:
1703*1414757bSCharles Forsyth if(SOFTFP){
170437da2899SCharles.Forsyth /* software fp */
1705*1414757bSCharles Forsyth USED(r);
170637da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
170737da2899SCharles.Forsyth break;
170837da2899SCharles.Forsyth }
170937da2899SCharles.Forsyth opflld(i, Ldf, FA2);
171037da2899SCharles.Forsyth midfl(i, Ldf, FA4);
171137da2899SCharles.Forsyth CPDO2(AL, r, FA4, FA4, FA2);
171237da2899SCharles.Forsyth opflst(i, Stf, FA4);
171337da2899SCharles.Forsyth break;
171437da2899SCharles.Forsyth case INEGF:
1715*1414757bSCharles Forsyth if(SOFTFP){
171637da2899SCharles.Forsyth punt(i, SRCOP|DSTOP, optab[i->op]);
171737da2899SCharles.Forsyth break;
171837da2899SCharles.Forsyth }
171937da2899SCharles.Forsyth opflld(i, Ldf, FA2);
172037da2899SCharles.Forsyth CPDO1(AL, Mnf, FA2, FA2);
172137da2899SCharles.Forsyth opflst(i, Stf, FA2);
172237da2899SCharles.Forsyth //if(pass){print("%D\n", i); das(s, code-s);}
172337da2899SCharles.Forsyth break;
172437da2899SCharles.Forsyth case ICVTWF:
1725*1414757bSCharles Forsyth if(SOFTFP){
172637da2899SCharles.Forsyth punt(i, SRCOP|DSTOP, optab[i->op]);
172737da2899SCharles.Forsyth break;
172837da2899SCharles.Forsyth }
172937da2899SCharles.Forsyth opwld(i, Ldw, RA2);
173037da2899SCharles.Forsyth CPFLT(AL, FA2, RA2);
173137da2899SCharles.Forsyth opflst(i, Stf, FA2);
173237da2899SCharles.Forsyth //if(pass){print("%D\n", i); das(s, code-s);}
173337da2899SCharles.Forsyth break;
173437da2899SCharles.Forsyth case ICVTFW:
1735*1414757bSCharles Forsyth if(SOFTFP){
173637da2899SCharles.Forsyth punt(i, SRCOP|DSTOP, optab[i->op]);
173737da2899SCharles.Forsyth break;
173837da2899SCharles.Forsyth }
173937da2899SCharles.Forsyth opflld(i, Ldf, FA2);
174037da2899SCharles.Forsyth CPFIX(AL, RA2, FA2);
174137da2899SCharles.Forsyth opwst(i, Stw, RA2);
174237da2899SCharles.Forsyth //if(pass){print("%D\n", i); das(s, code-s);}
174337da2899SCharles.Forsyth break;
174437da2899SCharles.Forsyth case ISHLL:
17457b3bf63cSCharles.Forsyth /* should do better */
174637da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
174737da2899SCharles.Forsyth break;
174837da2899SCharles.Forsyth case ISHRL:
17497b3bf63cSCharles.Forsyth /* should do better */
175037da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
175137da2899SCharles.Forsyth break;
175237da2899SCharles.Forsyth case IRAISE:
175337da2899SCharles.Forsyth punt(i, SRCOP|WRTPC|NEWPC, optab[i->op]);
175437da2899SCharles.Forsyth break;
175537da2899SCharles.Forsyth case IMULX:
175637da2899SCharles.Forsyth case IDIVX:
175737da2899SCharles.Forsyth case ICVTXX:
175837da2899SCharles.Forsyth case IMULX0:
175937da2899SCharles.Forsyth case IDIVX0:
176037da2899SCharles.Forsyth case ICVTXX0:
176137da2899SCharles.Forsyth case IMULX1:
176237da2899SCharles.Forsyth case IDIVX1:
176337da2899SCharles.Forsyth case ICVTXX1:
176437da2899SCharles.Forsyth case ICVTFX:
176537da2899SCharles.Forsyth case ICVTXF:
176637da2899SCharles.Forsyth case IEXPW:
176737da2899SCharles.Forsyth case IEXPL:
176837da2899SCharles.Forsyth case IEXPF:
176937da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
177037da2899SCharles.Forsyth break;
177137da2899SCharles.Forsyth case ISELF:
177237da2899SCharles.Forsyth punt(i, DSTOP, optab[i->op]);
177337da2899SCharles.Forsyth break;
177437da2899SCharles.Forsyth }
177537da2899SCharles.Forsyth }
177637da2899SCharles.Forsyth
177737da2899SCharles.Forsyth static void
preamble(void)177837da2899SCharles.Forsyth preamble(void)
177937da2899SCharles.Forsyth {
178037da2899SCharles.Forsyth if(comvec)
178137da2899SCharles.Forsyth return;
178237da2899SCharles.Forsyth
178337da2899SCharles.Forsyth comvec = malloc(10 * sizeof(*code));
178437da2899SCharles.Forsyth if(comvec == nil)
178537da2899SCharles.Forsyth error(exNomem);
178637da2899SCharles.Forsyth code = (ulong*)comvec;
178737da2899SCharles.Forsyth
178837da2899SCharles.Forsyth con((ulong)&R, RREG, 0);
178937da2899SCharles.Forsyth mem(Stw, O(REG, xpc), RREG, RLINK);
179037da2899SCharles.Forsyth mem(Ldw, O(REG, FP), RREG, RFP);
179137da2899SCharles.Forsyth mem(Ldw, O(REG, MP), RREG, RMP);
179237da2899SCharles.Forsyth mem(Ldw, O(REG, PC), RREG, R15);
179337da2899SCharles.Forsyth pass++;
179437da2899SCharles.Forsyth flushcon(0);
179537da2899SCharles.Forsyth pass--;
179637da2899SCharles.Forsyth
179737da2899SCharles.Forsyth segflush(comvec, 10 * sizeof(*code));
179837da2899SCharles.Forsyth }
179937da2899SCharles.Forsyth
180037da2899SCharles.Forsyth static void
maccase(void)180137da2899SCharles.Forsyth maccase(void)
180237da2899SCharles.Forsyth {
180337da2899SCharles.Forsyth ulong *cp1, *loop, *inner;
180437da2899SCharles.Forsyth /*
180537da2899SCharles.Forsyth * RA1 = value (input arg), t
180637da2899SCharles.Forsyth * RA2 = count, n
180737da2899SCharles.Forsyth * RA3 = table pointer (input arg)
180837da2899SCharles.Forsyth * RA0 = n/2, n2
180937da2899SCharles.Forsyth * RCON = pivot element t+n/2*3, l
181037da2899SCharles.Forsyth */
181137da2899SCharles.Forsyth LDW(AL, RA3, RA2, 0); // count from table
181237da2899SCharles.Forsyth MOV(RA3, RLINK); // initial table pointer
181337da2899SCharles.Forsyth
181437da2899SCharles.Forsyth loop = code; // loop:
181537da2899SCharles.Forsyth CMPI(AL, RA2, 0, 0, 0);
181637da2899SCharles.Forsyth cp1 = code;
181737da2899SCharles.Forsyth BRA(LE, 0); // n <= 0? goto out
181837da2899SCharles.Forsyth
181937da2899SCharles.Forsyth inner = code;
182037da2899SCharles.Forsyth DP(AL, Mov, 0, RA0, (1<<3)|2, RA2); // n2 = n>>1
182137da2899SCharles.Forsyth DP(AL, Add, RA0, RCON, (1<<3), RA0); // n' = n2+(n2<<1) = 3*n2
182237da2899SCharles.Forsyth DP(AL, Add, RA3, RCON, (2<<3), RCON); // l = t + n2*3;
182337da2899SCharles.Forsyth
182437da2899SCharles.Forsyth LDW(AL, RCON, RTA, 4);
182537da2899SCharles.Forsyth CMP(AL, RA1, 0, 0, RTA);
182637da2899SCharles.Forsyth DP(LT, Mov, 0, RA2, 0, RA0); // v < l[1]? n=n2
182737da2899SCharles.Forsyth BRANCH(LT, loop); // v < l[1]? goto loop
182837da2899SCharles.Forsyth
182937da2899SCharles.Forsyth LDW(AL, RCON, RTA, 8);
183037da2899SCharles.Forsyth CMP(AL, RA1, 0, 0, RTA);
183137da2899SCharles.Forsyth LDW(LT, RCON, R15, 12); // v >= l[1] && v < l[2] => found; goto l[3]
183237da2899SCharles.Forsyth
183337da2899SCharles.Forsyth // v >= l[2] (high)
183437da2899SCharles.Forsyth DPI(AL, Add, RCON, RA3, 0, 12); // t = l+3;
183537da2899SCharles.Forsyth DPI(AL, Add, RA0, RTA, 0, 1);
183637da2899SCharles.Forsyth DP(AL, Sub, RA2, RA2, 0, RTA) | SBIT; // n -= n2+1
183737da2899SCharles.Forsyth BRANCH(GT, inner); // n > 0? goto loop
183837da2899SCharles.Forsyth
183937da2899SCharles.Forsyth PATCH(cp1); // out:
184037da2899SCharles.Forsyth LDW(AL, RLINK, RA2, 0); // initial n
184137da2899SCharles.Forsyth DP(AL, Add, RA2, RA2, (1<<3), RA2); // n = n+(n<<1) = 3*n
184237da2899SCharles.Forsyth DP(AL, Add, RLINK, RLINK, (2<<3), RA2); // t' = &(initial t)[n*3]
184337da2899SCharles.Forsyth LDW(AL, RLINK, R15, 4); // goto (initial t)[n*3+1]
184437da2899SCharles.Forsyth }
184537da2899SCharles.Forsyth
184637da2899SCharles.Forsyth static void
macfrp(void)184737da2899SCharles.Forsyth macfrp(void)
184837da2899SCharles.Forsyth {
184937da2899SCharles.Forsyth /* destroy the pointer in RA0 */
185037da2899SCharles.Forsyth CMPH(AL, RA0);
185137da2899SCharles.Forsyth CRETURN(EQ); // arg == H? => return
185237da2899SCharles.Forsyth
185337da2899SCharles.Forsyth mem(Ldw, O(Heap, ref)-sizeof(Heap), RA0, RA2);
185437da2899SCharles.Forsyth DPI(AL, Sub, RA2, RA2, 0, 1) | SBIT;
185537da2899SCharles.Forsyth memc(NE, Stw, O(Heap, ref)-sizeof(Heap), RA0, RA2);
185637da2899SCharles.Forsyth CRETURN(NE); // --h->ref != 0 => return
185737da2899SCharles.Forsyth
185837da2899SCharles.Forsyth mem(Stw, O(REG, FP), RREG, RFP);
185937da2899SCharles.Forsyth mem(Stw, O(REG, st), RREG, RLINK);
186037da2899SCharles.Forsyth mem(Stw, O(REG, s), RREG, RA0);
186137da2899SCharles.Forsyth CALL(rdestroy);
186237da2899SCharles.Forsyth con((ulong)&R, RREG, 1);
186337da2899SCharles.Forsyth mem(Ldw, O(REG, st), RREG, RLINK);
186437da2899SCharles.Forsyth mem(Ldw, O(REG, FP), RREG, RFP);
186537da2899SCharles.Forsyth mem(Ldw, O(REG, MP), RREG, RMP);
186637da2899SCharles.Forsyth RETURN;
186737da2899SCharles.Forsyth flushcon(0);
186837da2899SCharles.Forsyth }
186937da2899SCharles.Forsyth
187037da2899SCharles.Forsyth static void
maccolr(void)187137da2899SCharles.Forsyth maccolr(void)
187237da2899SCharles.Forsyth {
187337da2899SCharles.Forsyth /* color the pointer in RA1 */
187437da2899SCharles.Forsyth mem(Ldw, O(Heap, ref)-sizeof(Heap), RA1, RA0);
187537da2899SCharles.Forsyth DPI(AL, Add, RA0, RA0, 0, 1);
187637da2899SCharles.Forsyth mem(Stw, O(Heap, ref)-sizeof(Heap), RA1, RA0); // h->ref++
187737da2899SCharles.Forsyth con((ulong)&mutator, RA2, 1);
187837da2899SCharles.Forsyth mem(Ldw, O(Heap, color)-sizeof(Heap), RA1, RA0);
187937da2899SCharles.Forsyth mem(Ldw, 0, RA2, RA2);
188037da2899SCharles.Forsyth CMP(AL, RA0, 0, 0, RA2);
188137da2899SCharles.Forsyth CRETURN(EQ); // return if h->color == mutator
188237da2899SCharles.Forsyth con(propagator, RA2, 1);
188337da2899SCharles.Forsyth mem(Stw, O(Heap, color)-sizeof(Heap), RA1, RA2); // h->color = propagator
188437da2899SCharles.Forsyth con((ulong)&nprop, RA2, 1);
188537da2899SCharles.Forsyth mem(Stw, 0, RA2, RA2); // nprop = !0
188637da2899SCharles.Forsyth RETURN;
188737da2899SCharles.Forsyth flushcon(0);
188837da2899SCharles.Forsyth }
188937da2899SCharles.Forsyth
189037da2899SCharles.Forsyth static void
macret(void)189137da2899SCharles.Forsyth macret(void)
189237da2899SCharles.Forsyth {
189337da2899SCharles.Forsyth Inst i;
189437da2899SCharles.Forsyth ulong *cp1, *cp2, *cp3, *cp4, *cp5, *linterp;
189537da2899SCharles.Forsyth
189637da2899SCharles.Forsyth CMPI(AL, RA1, 0, 0, 0);
189737da2899SCharles.Forsyth cp1 = code;
189837da2899SCharles.Forsyth BRA(EQ, 0); // t(Rfp) == 0
189937da2899SCharles.Forsyth
190037da2899SCharles.Forsyth mem(Ldw, O(Type,destroy),RA1, RA0);
190137da2899SCharles.Forsyth CMPI(AL, RA0, 0, 0, 0);
190237da2899SCharles.Forsyth cp2 = code;
190337da2899SCharles.Forsyth BRA(EQ, 0); // destroy(t(fp)) == 0
190437da2899SCharles.Forsyth
190537da2899SCharles.Forsyth mem(Ldw, O(Frame,fp),RFP, RA2);
190637da2899SCharles.Forsyth CMPI(AL, RA2, 0, 0, 0);
190737da2899SCharles.Forsyth cp3 = code;
190837da2899SCharles.Forsyth BRA(EQ, 0); // fp(Rfp) == 0
190937da2899SCharles.Forsyth
191037da2899SCharles.Forsyth mem(Ldw, O(Frame,mr),RFP, RA3);
191137da2899SCharles.Forsyth CMPI(AL, RA3, 0, 0, 0);
191237da2899SCharles.Forsyth cp4 = code;
191337da2899SCharles.Forsyth BRA(EQ, 0); // mr(Rfp) == 0
191437da2899SCharles.Forsyth
191537da2899SCharles.Forsyth mem(Ldw, O(REG,M),RREG, RA2);
191637da2899SCharles.Forsyth mem(Ldw, O(Heap,ref)-sizeof(Heap),RA2, RA3);
191737da2899SCharles.Forsyth DPI(AL, Sub, RA3, RA3, 0, 1) | SBIT;
191837da2899SCharles.Forsyth cp5 = code;
191937da2899SCharles.Forsyth BRA(EQ, 0); // --ref(arg) == 0
192037da2899SCharles.Forsyth mem(Stw, O(Heap,ref)-sizeof(Heap),RA2, RA3);
192137da2899SCharles.Forsyth
192237da2899SCharles.Forsyth mem(Ldw, O(Frame,mr),RFP, RA1);
192337da2899SCharles.Forsyth mem(Stw, O(REG,M),RREG, RA1);
192437da2899SCharles.Forsyth mem(Ldw, O(Modlink,MP),RA1, RMP);
192537da2899SCharles.Forsyth mem(Stw, O(REG,MP),RREG, RMP);
192637da2899SCharles.Forsyth mem(Ldw, O(Modlink,compiled), RA1, RA3); // R.M->compiled
192737da2899SCharles.Forsyth CMPI(AL, RA3, 0, 0, 0);
192837da2899SCharles.Forsyth linterp = code;
192937da2899SCharles.Forsyth BRA(EQ, 0);
193037da2899SCharles.Forsyth
193137da2899SCharles.Forsyth PATCH(cp4);
193237da2899SCharles.Forsyth MOV(R15, R14); // call destroy(t(fp))
193337da2899SCharles.Forsyth MOV(RA0, R15);
193437da2899SCharles.Forsyth
193537da2899SCharles.Forsyth mem(Stw, O(REG,SP),RREG, RFP);
193637da2899SCharles.Forsyth mem(Ldw, O(Frame,lr),RFP, RA1);
193737da2899SCharles.Forsyth mem(Ldw, O(Frame,fp),RFP, RFP);
193837da2899SCharles.Forsyth mem(Stw, O(REG,FP),RREG, RFP); // R.FP = RFP
193937da2899SCharles.Forsyth DP(AL, Mov, 0, R15, 0, RA1); // goto lr(Rfp), if compiled
194037da2899SCharles.Forsyth
194137da2899SCharles.Forsyth PATCH(linterp);
194237da2899SCharles.Forsyth MOV(R15, R14); // call destroy(t(fp))
194337da2899SCharles.Forsyth MOV(RA0, R15);
194437da2899SCharles.Forsyth
194537da2899SCharles.Forsyth mem(Stw, O(REG,SP),RREG, RFP);
194637da2899SCharles.Forsyth mem(Ldw, O(Frame,lr),RFP, RA1);
194737da2899SCharles.Forsyth mem(Ldw, O(Frame,fp),RFP, RFP);
194837da2899SCharles.Forsyth mem(Stw, O(REG,PC),RREG, RA1); // R.PC = fp->lr
194937da2899SCharles.Forsyth mem(Stw, O(REG,FP),RREG, RFP); // R.FP = RFP
195037da2899SCharles.Forsyth mem(Ldw, O(REG, xpc), RREG, RLINK);
195137da2899SCharles.Forsyth RETURN; // return to xec uncompiled code
195237da2899SCharles.Forsyth
195337da2899SCharles.Forsyth PATCH(cp1);
195437da2899SCharles.Forsyth PATCH(cp2);
195537da2899SCharles.Forsyth PATCH(cp3);
195637da2899SCharles.Forsyth PATCH(cp5);
195737da2899SCharles.Forsyth i.add = AXNON;
195837da2899SCharles.Forsyth punt(&i, TCHECK|NEWPC, optab[IRET]);
195937da2899SCharles.Forsyth }
196037da2899SCharles.Forsyth
196137da2899SCharles.Forsyth static void
macmcal(void)196237da2899SCharles.Forsyth macmcal(void)
196337da2899SCharles.Forsyth {
196437da2899SCharles.Forsyth ulong *lab;
196537da2899SCharles.Forsyth
196637da2899SCharles.Forsyth CMPH(AL, RA0);
196737da2899SCharles.Forsyth memc(NE, Ldw, O(Modlink, prog), RA3, RA1); // RA0 != H
196837da2899SCharles.Forsyth CMPI(NE, RA1, 0, 0, 0); // RA0 != H
196937da2899SCharles.Forsyth lab = code;
197037da2899SCharles.Forsyth BRA(NE, 0); // RA0 != H && m->prog!=0
197137da2899SCharles.Forsyth
197237da2899SCharles.Forsyth mem(Stw, O(REG, st), RREG, RLINK);
197337da2899SCharles.Forsyth mem(Stw, O(REG, FP), RREG, RA2);
197437da2899SCharles.Forsyth mem(Stw, O(REG, dt), RREG, RA0);
197537da2899SCharles.Forsyth CALL(rmcall); // CALL rmcall
197637da2899SCharles.Forsyth
197737da2899SCharles.Forsyth con((ulong)&R, RREG, 1); // MOVL $R, RREG
197837da2899SCharles.Forsyth mem(Ldw, O(REG, st), RREG, RLINK);
197937da2899SCharles.Forsyth mem(Ldw, O(REG, FP), RREG, RFP);
198037da2899SCharles.Forsyth mem(Ldw, O(REG, MP), RREG, RMP);
198137da2899SCharles.Forsyth RETURN;
198237da2899SCharles.Forsyth
198337da2899SCharles.Forsyth PATCH(lab); // patch:
198437da2899SCharles.Forsyth DP(AL, Mov, 0, RFP, 0, RA2);
198537da2899SCharles.Forsyth mem(Stw, O(REG, M), RREG, RA3); // MOVL RA3, R.M
198637da2899SCharles.Forsyth mem(Ldw, O(Heap, ref)-sizeof(Heap), RA3, RA1);
198737da2899SCharles.Forsyth DPI(AL, Add, RA1, RA1, 0, 1);
198837da2899SCharles.Forsyth mem(Stw, O(Heap, ref)-sizeof(Heap), RA3, RA1);
198937da2899SCharles.Forsyth mem(Ldw, O(Modlink, MP), RA3, RMP); // MOVL R.M->mp, RMP
199037da2899SCharles.Forsyth mem(Stw, O(REG, MP), RREG, RMP); // MOVL RA3, R.MP R.MP = ml->m
199137da2899SCharles.Forsyth mem(Ldw, O(Modlink,compiled), RA3, RA1); // M.compiled?
199237da2899SCharles.Forsyth CMPI(AL, RA1, 0, 0, 0);
199337da2899SCharles.Forsyth DP(NE, Mov, 0, R15, 0, RA0); // return to compiled code
199437da2899SCharles.Forsyth mem(Stw, O(REG,FP),RREG, RFP); // R.FP = RFP
199537da2899SCharles.Forsyth mem(Stw, O(REG,PC),RREG, RA0); // R.PC = RPC
199637da2899SCharles.Forsyth mem(Ldw, O(REG, xpc), RREG, RLINK);
199737da2899SCharles.Forsyth RETURN; // return to xec uncompiled code
199837da2899SCharles.Forsyth flushcon(0);
199937da2899SCharles.Forsyth }
200037da2899SCharles.Forsyth
200137da2899SCharles.Forsyth static void
macfram(void)200237da2899SCharles.Forsyth macfram(void)
200337da2899SCharles.Forsyth {
200437da2899SCharles.Forsyth ulong *lab1;
200537da2899SCharles.Forsyth
200637da2899SCharles.Forsyth mem(Ldw, O(REG, SP), RREG, RA0); // MOVL R.SP, RA0
200737da2899SCharles.Forsyth mem(Ldw, O(Type, size), RA3, RA1);
200837da2899SCharles.Forsyth DP(AL, Add, RA0, RA0, 0, RA1); // nsp = R.SP + t->size
200937da2899SCharles.Forsyth mem(Ldw, O(REG, TS), RREG, RA1);
201037da2899SCharles.Forsyth CMP(AL, RA0, 0, 0, RA1); // nsp :: R.TS
201137da2899SCharles.Forsyth lab1 = code;
201237da2899SCharles.Forsyth BRA(CS, 0); // nsp >= R.TS; must expand
201337da2899SCharles.Forsyth
201437da2899SCharles.Forsyth mem(Ldw, O(REG, SP), RREG, RA2); // MOVL R.SP, RA2
201537da2899SCharles.Forsyth mem(Stw, O(REG, SP), RREG, RA0); // MOVL RA0, R.SP
201637da2899SCharles.Forsyth
201737da2899SCharles.Forsyth mem(Stw, O(Frame, t), RA2, RA3); // MOVL RA3, t(RA2) f->t = t
201837da2899SCharles.Forsyth con(0, RA0, 1);
201937da2899SCharles.Forsyth mem(Stw, O(Frame,mr), RA2, RA0); // MOVL $0, mr(RA2) f->mr
202037da2899SCharles.Forsyth mem(Ldw, O(Type, initialize), RA3, R15); // become t->init(RA2), returning RA2
202137da2899SCharles.Forsyth
202237da2899SCharles.Forsyth PATCH(lab1);
202337da2899SCharles.Forsyth mem(Stw, O(REG, s), RREG, RA3);
202437da2899SCharles.Forsyth mem(Stw, O(REG, st), RREG, RLINK);
202537da2899SCharles.Forsyth mem(Stw, O(REG, FP), RREG, RFP); // MOVL RFP, R.FP
202637da2899SCharles.Forsyth CALL(extend); // CALL extend
202737da2899SCharles.Forsyth
202837da2899SCharles.Forsyth con((ulong)&R, RREG, 1);
202937da2899SCharles.Forsyth mem(Ldw, O(REG, st), RREG, RLINK);
203037da2899SCharles.Forsyth mem(Ldw, O(REG, FP), RREG, RFP); // MOVL R.FP, RFP
203137da2899SCharles.Forsyth mem(Ldw, O(REG, s), RREG, RA2); // MOVL R.s, *R.d
203237da2899SCharles.Forsyth mem(Ldw, O(REG, MP), RREG, RMP); // MOVL R.MP, RMP
203337da2899SCharles.Forsyth RETURN; // RET
203437da2899SCharles.Forsyth }
203537da2899SCharles.Forsyth
203637da2899SCharles.Forsyth static void
macmfra(void)203737da2899SCharles.Forsyth macmfra(void)
203837da2899SCharles.Forsyth {
203937da2899SCharles.Forsyth mem(Stw, O(REG, st), RREG, RLINK);
204037da2899SCharles.Forsyth mem(Stw, O(REG, s), RREG, RA3); // Save type
204137da2899SCharles.Forsyth mem(Stw, O(REG, d), RREG, RA0); // Save destination
204237da2899SCharles.Forsyth mem(Stw, O(REG, FP), RREG, RFP);
204337da2899SCharles.Forsyth CALL(rmfram); // CALL rmfram
204437da2899SCharles.Forsyth
204537da2899SCharles.Forsyth con((ulong)&R, RREG, 1);
204637da2899SCharles.Forsyth mem(Ldw, O(REG, st), RREG, RLINK);
204737da2899SCharles.Forsyth mem(Ldw, O(REG, FP), RREG, RFP);
204837da2899SCharles.Forsyth mem(Ldw, O(REG, MP), RREG, RMP);
204937da2899SCharles.Forsyth RETURN;
205037da2899SCharles.Forsyth }
205137da2899SCharles.Forsyth
205237da2899SCharles.Forsyth static void
macrelq(void)205337da2899SCharles.Forsyth macrelq(void)
205437da2899SCharles.Forsyth {
205537da2899SCharles.Forsyth mem(Stw, O(REG,FP),RREG, RFP); // R.FP = RFP
205637da2899SCharles.Forsyth mem(Stw, O(REG,PC),RREG, RLINK); // R.PC = RLINK
205737da2899SCharles.Forsyth mem(Ldw, O(REG, xpc), RREG, RLINK);
205837da2899SCharles.Forsyth RETURN;
205937da2899SCharles.Forsyth }
206037da2899SCharles.Forsyth
206137da2899SCharles.Forsyth void
comd(Type * t)206237da2899SCharles.Forsyth comd(Type *t)
206337da2899SCharles.Forsyth {
206437da2899SCharles.Forsyth int i, j, m, c;
206537da2899SCharles.Forsyth
206637da2899SCharles.Forsyth mem(Stw, O(REG, dt), RREG, RLINK);
206737da2899SCharles.Forsyth for(i = 0; i < t->np; i++) {
206837da2899SCharles.Forsyth c = t->map[i];
206937da2899SCharles.Forsyth j = i<<5;
207037da2899SCharles.Forsyth for(m = 0x80; m != 0; m >>= 1) {
207137da2899SCharles.Forsyth if(c & m) {
207237da2899SCharles.Forsyth mem(Ldw, j, RFP, RA0);
207337da2899SCharles.Forsyth CALL(base+macro[MacFRP]);
207437da2899SCharles.Forsyth }
207537da2899SCharles.Forsyth j += sizeof(WORD*);
207637da2899SCharles.Forsyth }
207737da2899SCharles.Forsyth flushchk();
207837da2899SCharles.Forsyth }
207937da2899SCharles.Forsyth mem(Ldw, O(REG, dt), RREG, RLINK);
208037da2899SCharles.Forsyth RETURN;
208137da2899SCharles.Forsyth flushcon(0);
208237da2899SCharles.Forsyth }
208337da2899SCharles.Forsyth
208437da2899SCharles.Forsyth void
comi(Type * t)208537da2899SCharles.Forsyth comi(Type *t)
208637da2899SCharles.Forsyth {
208737da2899SCharles.Forsyth int i, j, m, c;
208837da2899SCharles.Forsyth
208937da2899SCharles.Forsyth con((ulong)H, RA0, 1);
209037da2899SCharles.Forsyth for(i = 0; i < t->np; i++) {
209137da2899SCharles.Forsyth c = t->map[i];
209237da2899SCharles.Forsyth j = i<<5;
209337da2899SCharles.Forsyth for(m = 0x80; m != 0; m >>= 1) {
209437da2899SCharles.Forsyth if(c & m)
209537da2899SCharles.Forsyth mem(Stw, j, RA2, RA0);
209637da2899SCharles.Forsyth j += sizeof(WORD*);
209737da2899SCharles.Forsyth }
209837da2899SCharles.Forsyth flushchk();
209937da2899SCharles.Forsyth }
210037da2899SCharles.Forsyth RETURN;
210137da2899SCharles.Forsyth flushcon(0);
210237da2899SCharles.Forsyth }
210337da2899SCharles.Forsyth
210437da2899SCharles.Forsyth void
typecom(Type * t)210537da2899SCharles.Forsyth typecom(Type *t)
210637da2899SCharles.Forsyth {
210737da2899SCharles.Forsyth int n;
210837da2899SCharles.Forsyth ulong *tmp, *start;
210937da2899SCharles.Forsyth
211037da2899SCharles.Forsyth if(t == nil || t->initialize != 0)
211137da2899SCharles.Forsyth return;
211237da2899SCharles.Forsyth
211337da2899SCharles.Forsyth tmp = mallocz(4096*sizeof(ulong), 0);
211437da2899SCharles.Forsyth if(tmp == nil)
211537da2899SCharles.Forsyth error(exNomem);
211637da2899SCharles.Forsyth
211737da2899SCharles.Forsyth code = tmp;
211837da2899SCharles.Forsyth comi(t);
211937da2899SCharles.Forsyth n = code - tmp;
212037da2899SCharles.Forsyth code = tmp;
212137da2899SCharles.Forsyth comd(t);
212237da2899SCharles.Forsyth n += code - tmp;
212337da2899SCharles.Forsyth free(tmp);
212437da2899SCharles.Forsyth
212537da2899SCharles.Forsyth n *= sizeof(*code);
212637da2899SCharles.Forsyth code = mallocz(n, 0);
212737da2899SCharles.Forsyth if(code == nil)
212837da2899SCharles.Forsyth return;
212937da2899SCharles.Forsyth
213037da2899SCharles.Forsyth start = code;
213137da2899SCharles.Forsyth t->initialize = code;
213237da2899SCharles.Forsyth comi(t);
213337da2899SCharles.Forsyth t->destroy = code;
213437da2899SCharles.Forsyth comd(t);
213537da2899SCharles.Forsyth
213637da2899SCharles.Forsyth segflush(start, n);
213737da2899SCharles.Forsyth
213837da2899SCharles.Forsyth if(cflag > 3)
213937da2899SCharles.Forsyth print("typ= %.8p %4d i %.8p d %.8p asm=%d\n",
214037da2899SCharles.Forsyth t, t->size, t->initialize, t->destroy, n);
214137da2899SCharles.Forsyth }
214237da2899SCharles.Forsyth
214337da2899SCharles.Forsyth static void
patchex(Module * m,ulong * p)214437da2899SCharles.Forsyth patchex(Module *m, ulong *p)
214537da2899SCharles.Forsyth {
214637da2899SCharles.Forsyth Handler *h;
214737da2899SCharles.Forsyth Except *e;
214837da2899SCharles.Forsyth
214937da2899SCharles.Forsyth if((h = m->htab) == nil)
215037da2899SCharles.Forsyth return;
215137da2899SCharles.Forsyth for( ; h->etab != nil; h++){
215237da2899SCharles.Forsyth h->pc1 = p[h->pc1];
215337da2899SCharles.Forsyth h->pc2 = p[h->pc2];
215437da2899SCharles.Forsyth for(e = h->etab; e->s != nil; e++)
215537da2899SCharles.Forsyth e->pc = p[e->pc];
215637da2899SCharles.Forsyth if(e->pc != -1)
215737da2899SCharles.Forsyth e->pc = p[e->pc];
215837da2899SCharles.Forsyth }
215937da2899SCharles.Forsyth }
216037da2899SCharles.Forsyth
216137da2899SCharles.Forsyth int
compile(Module * m,int size,Modlink * ml)216237da2899SCharles.Forsyth compile(Module *m, int size, Modlink *ml)
216337da2899SCharles.Forsyth {
216437da2899SCharles.Forsyth Link *l;
216537da2899SCharles.Forsyth Modl *e;
216637da2899SCharles.Forsyth int i, n;
216737da2899SCharles.Forsyth ulong *s, *tmp;
216837da2899SCharles.Forsyth
216937da2899SCharles.Forsyth base = nil;
217037da2899SCharles.Forsyth patch = mallocz(size*sizeof(*patch), 0);
217137da2899SCharles.Forsyth tinit = malloc(m->ntype*sizeof(*tinit));
217237da2899SCharles.Forsyth tmp = malloc(4096*sizeof(ulong));
217337da2899SCharles.Forsyth if(tinit == nil || patch == nil || tmp == nil)
217437da2899SCharles.Forsyth goto bad;
217537da2899SCharles.Forsyth
217637da2899SCharles.Forsyth preamble();
217737da2899SCharles.Forsyth
217837da2899SCharles.Forsyth mod = m;
217937da2899SCharles.Forsyth n = 0;
218037da2899SCharles.Forsyth pass = 0;
218137da2899SCharles.Forsyth nlit = 0;
218237da2899SCharles.Forsyth
218337da2899SCharles.Forsyth for(i = 0; i < size; i++) {
218437da2899SCharles.Forsyth codeoff = n;
218537da2899SCharles.Forsyth code = tmp;
218637da2899SCharles.Forsyth comp(&m->prog[i]);
218737da2899SCharles.Forsyth patch[i] = n;
218837da2899SCharles.Forsyth n += code - tmp;
218937da2899SCharles.Forsyth }
219037da2899SCharles.Forsyth
219137da2899SCharles.Forsyth for(i = 0; i < nelem(mactab); i++) {
219237da2899SCharles.Forsyth codeoff = n;
219337da2899SCharles.Forsyth code = tmp;
219437da2899SCharles.Forsyth mactab[i].gen();
219537da2899SCharles.Forsyth macro[mactab[i].idx] = n;
219637da2899SCharles.Forsyth n += code - tmp;
219737da2899SCharles.Forsyth }
219837da2899SCharles.Forsyth code = tmp;
219937da2899SCharles.Forsyth flushcon(0);
220037da2899SCharles.Forsyth n += code - tmp;
220137da2899SCharles.Forsyth
220237da2899SCharles.Forsyth base = mallocz((n+nlit)*sizeof(*code), 0);
220337da2899SCharles.Forsyth if(base == nil)
220437da2899SCharles.Forsyth goto bad;
220537da2899SCharles.Forsyth
220637da2899SCharles.Forsyth if(cflag > 3)
220737da2899SCharles.Forsyth print("dis=%5d %5d 386=%5d asm=%.8p: %s\n",
220837da2899SCharles.Forsyth size, size*sizeof(Inst), n, base, m->name);
220937da2899SCharles.Forsyth
221037da2899SCharles.Forsyth pass++;
221137da2899SCharles.Forsyth nlit = 0;
221237da2899SCharles.Forsyth litpool = base+n;
221337da2899SCharles.Forsyth code = base;
221437da2899SCharles.Forsyth n = 0;
221537da2899SCharles.Forsyth codeoff = 0;
221637da2899SCharles.Forsyth for(i = 0; i < size; i++) {
221737da2899SCharles.Forsyth s = code;
221837da2899SCharles.Forsyth comp(&m->prog[i]);
221937da2899SCharles.Forsyth if(patch[i] != n) {
222037da2899SCharles.Forsyth print("%3d %D\n", i, &m->prog[i]);
222137da2899SCharles.Forsyth print("%lud != %d\n", patch[i], n);
222237da2899SCharles.Forsyth urk("phase error");
222337da2899SCharles.Forsyth }
222437da2899SCharles.Forsyth n += code - s;
222537da2899SCharles.Forsyth if(cflag > 4) {
222637da2899SCharles.Forsyth print("%3d %D\n", i, &m->prog[i]);
222737da2899SCharles.Forsyth das(s, code-s);
222837da2899SCharles.Forsyth }
222937da2899SCharles.Forsyth }
223037da2899SCharles.Forsyth
223137da2899SCharles.Forsyth for(i = 0; i < nelem(mactab); i++) {
223237da2899SCharles.Forsyth s = code;
223337da2899SCharles.Forsyth mactab[i].gen();
223437da2899SCharles.Forsyth if(macro[mactab[i].idx] != n){
223537da2899SCharles.Forsyth print("mac phase err: %lud != %d\n", macro[mactab[i].idx], n);
223637da2899SCharles.Forsyth urk("phase error");
223737da2899SCharles.Forsyth }
223837da2899SCharles.Forsyth n += code - s;
223937da2899SCharles.Forsyth if(cflag > 4) {
224037da2899SCharles.Forsyth print("%s:\n", mactab[i].name);
224137da2899SCharles.Forsyth das(s, code-s);
224237da2899SCharles.Forsyth }
224337da2899SCharles.Forsyth }
224437da2899SCharles.Forsyth s = code;
224537da2899SCharles.Forsyth flushcon(0);
224637da2899SCharles.Forsyth n += code - s;
224737da2899SCharles.Forsyth
224837da2899SCharles.Forsyth for(l = m->ext; l->name; l++) {
224937da2899SCharles.Forsyth l->u.pc = (Inst*)RELPC(patch[l->u.pc-m->prog]);
225037da2899SCharles.Forsyth typecom(l->frame);
225137da2899SCharles.Forsyth }
225237da2899SCharles.Forsyth if(ml != nil) {
225337da2899SCharles.Forsyth e = &ml->links[0];
225437da2899SCharles.Forsyth for(i = 0; i < ml->nlinks; i++) {
225537da2899SCharles.Forsyth e->u.pc = (Inst*)RELPC(patch[e->u.pc-m->prog]);
225637da2899SCharles.Forsyth typecom(e->frame);
225737da2899SCharles.Forsyth e++;
225837da2899SCharles.Forsyth }
225937da2899SCharles.Forsyth }
226037da2899SCharles.Forsyth for(i = 0; i < m->ntype; i++) {
226137da2899SCharles.Forsyth if(tinit[i] != 0)
226237da2899SCharles.Forsyth typecom(m->type[i]);
226337da2899SCharles.Forsyth }
226437da2899SCharles.Forsyth patchex(m, patch);
226537da2899SCharles.Forsyth m->entry = (Inst*)RELPC(patch[mod->entry-mod->prog]);
226637da2899SCharles.Forsyth free(patch);
226737da2899SCharles.Forsyth free(tinit);
226837da2899SCharles.Forsyth free(tmp);
226937da2899SCharles.Forsyth free(m->prog);
227037da2899SCharles.Forsyth m->prog = (Inst*)base;
227137da2899SCharles.Forsyth m->compiled = 1;
227237da2899SCharles.Forsyth segflush(base, n*sizeof(*base));
227337da2899SCharles.Forsyth return 1;
227437da2899SCharles.Forsyth bad:
227537da2899SCharles.Forsyth free(patch);
227637da2899SCharles.Forsyth free(tinit);
227737da2899SCharles.Forsyth free(base);
227837da2899SCharles.Forsyth free(tmp);
227937da2899SCharles.Forsyth return 0;
228037da2899SCharles.Forsyth }
2281