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 * Copyright © 1997 C H Forsyth (forsyth@terzarima.net)
837da2899SCharles.Forsyth */
937da2899SCharles.Forsyth
1037da2899SCharles.Forsyth #define ROMABLE 0 /* costs something to zero patch vectors */
1137da2899SCharles.Forsyth #define RESCHED 1 /* check for interpreter reschedule */
1237da2899SCharles.Forsyth
1337da2899SCharles.Forsyth #define PATCH(ptr) *ptr |= ((ulong)code-(ulong)ptr) & 0xfffc
1437da2899SCharles.Forsyth
1537da2899SCharles.Forsyth #define T(r) *((void**)(R.r))
1637da2899SCharles.Forsyth
1737da2899SCharles.Forsyth #define XO(o,xo) (((o)<<26)|((xo)<<1))
1837da2899SCharles.Forsyth
1937da2899SCharles.Forsyth /* botch: ARRR, AIRR, LRRR, etc have dest first (will fix soon) */
2037da2899SCharles.Forsyth
2137da2899SCharles.Forsyth #define OPARRR(o,d,a,b) ((o)|((d)<<21)|((a)<<16)|((b)<<11))
2237da2899SCharles.Forsyth #define ARRR(o,d,a,b) gen((o)|((d)<<21)|((a)<<16)|((b)<<11))
2337da2899SCharles.Forsyth #define AIRR(o,d,a,v) gen((o)|((d)<<21)|((a)<<16)|((v)&0xFFFF))
2437da2899SCharles.Forsyth #define IRR(o,v,a,d) AIRR((o),(d),(a),(v))
2537da2899SCharles.Forsyth #define RRR(o,b,a,d) ARRR((o),(d),(a),(b))
2637da2899SCharles.Forsyth #define LRRR(o,a,s,b) ARRR((o),(s),(a),(b))
2737da2899SCharles.Forsyth #define LIRR(o,a,s,v) AIRR((o),(s),(a),(v))
2837da2899SCharles.Forsyth #define Bx(li,aa) gen((18<<26)|((li)&0x3FFFFFC)|((aa)<<1))
2937da2899SCharles.Forsyth #define RLW(op,a,s,sh,mb,me) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((sh)&31L)<<11)|\
3037da2899SCharles.Forsyth (((mb)&31L)<<6)|(((me)&31L)<<1))
3137da2899SCharles.Forsyth #define MFSPR(s, d) gen(XO(31,339) | ((d)<<21) | ((s)<<11))
3237da2899SCharles.Forsyth #define MTSPR(s, d) gen(XO(31,467) | ((s)<<21) | ((d)<<11));
3337da2899SCharles.Forsyth
34*af364d92SValery Ushakov #define MFCR(d) gen(XO(31,19) | ((d)<<21))
35*af364d92SValery Ushakov #define MTCRF(s, mask) gen(XO(31,144) | ((s)<<21) | ((mask)<<12))
36*af364d92SValery Ushakov #define MTCR(s) MTCRF(s, 0xff)
37*af364d92SValery Ushakov
3837da2899SCharles.Forsyth #define SLWI(d,a,n) gen(slw((d),(a),(n),0))
3937da2899SCharles.Forsyth #define LRET() gen(Oblr)
4037da2899SCharles.Forsyth
4137da2899SCharles.Forsyth #define SETR0() if(macjit){ AIRR(Oaddi, Rzero, 0, 0); } /* set R0 to 0 */
4237da2899SCharles.Forsyth
4337da2899SCharles.Forsyth /* assumes H can be formed from signed halfword */
4437da2899SCharles.Forsyth #define CMPH(r) AIRR(Ocmpi, Rcrf0, (r), (ulong)H);
4537da2899SCharles.Forsyth #define NOTNIL(r) (CMPH((r)), CCALL(EQ, bounds))
4637da2899SCharles.Forsyth
4737da2899SCharles.Forsyth enum
4837da2899SCharles.Forsyth {
4937da2899SCharles.Forsyth Rzero = 0, /* zero by design, not definition (P9/Inferno) */
5037da2899SCharles.Forsyth
5137da2899SCharles.Forsyth Rsp = 1,
5237da2899SCharles.Forsyth Rsb = 2,
5337da2899SCharles.Forsyth Rarg = 3,
5437da2899SCharles.Forsyth
5537da2899SCharles.Forsyth Ro1 = 8,
5637da2899SCharles.Forsyth Ro2 = 9,
5737da2899SCharles.Forsyth Ro3 = 10,
5837da2899SCharles.Forsyth Ri = 11,
5937da2899SCharles.Forsyth Rj = 12,
6037da2899SCharles.Forsyth
6137da2899SCharles.Forsyth Rmp = 13,
6237da2899SCharles.Forsyth Rfp = 14,
6337da2899SCharles.Forsyth Rreg = 15,
6437da2899SCharles.Forsyth Rta = 16, /* unused */
6537da2899SCharles.Forsyth Rpic = 17, /* address for computed goto, for move to CTR or LR */
6637da2899SCharles.Forsyth
6737da2899SCharles.Forsyth Rcon = 26, /* constant builder; temporary */
6837da2899SCharles.Forsyth /* 27, 28, 29, 30 are potentially external registers (P9/Inferno) */
6937da2899SCharles.Forsyth Rlink = 31, /* holds copies of LR; linker temp */
7037da2899SCharles.Forsyth
7137da2899SCharles.Forsyth Rfret = 0,
7237da2899SCharles.Forsyth Rf1 = 4,
7337da2899SCharles.Forsyth Rf2 = 6,
7437da2899SCharles.Forsyth Rfcvi = 27, /* floating conversion constant (P9/Inferno) */
7537da2899SCharles.Forsyth Rfzero = 28, /* 0.0 (P9/Inferno) */
7637da2899SCharles.Forsyth Rfhalf = 29, /* 0.5 (P9/Inferno) */
7737da2899SCharles.Forsyth
7837da2899SCharles.Forsyth Rlr = 8<<5, /* SPR(LR) */
7937da2899SCharles.Forsyth Rctr = 9<<5, /* SPR(CTR) */
8037da2899SCharles.Forsyth
8137da2899SCharles.Forsyth Rcrf0 = 0, /* condition code field 0 */
8237da2899SCharles.Forsyth Rcrf1 = 1<<2, /* condition code field 1 */
8337da2899SCharles.Forsyth
8437da2899SCharles.Forsyth Rcrbrel = 31, /* condition code bit set to force relinquish */
8537da2899SCharles.Forsyth
8637da2899SCharles.Forsyth Olwz = XO(32, 0),
8737da2899SCharles.Forsyth Olwzu = XO(33, 0),
8837da2899SCharles.Forsyth Olwzx = XO(31, 23),
8937da2899SCharles.Forsyth Olbz = XO(34, 0),
9037da2899SCharles.Forsyth Olbzu = XO(35, 0),
9137da2899SCharles.Forsyth Olbzx = XO(31, 87),
9237da2899SCharles.Forsyth Olfd = XO(50, 0),
9337da2899SCharles.Forsyth Olhz = XO(40, 0),
9437da2899SCharles.Forsyth Olhzx = XO(31, 279),
9537da2899SCharles.Forsyth Ostw = XO(36, 0),
9637da2899SCharles.Forsyth Ostwu = XO(37, 0),
9737da2899SCharles.Forsyth Ostwx = XO(31, 151),
9837da2899SCharles.Forsyth Ostb = XO(38, 0),
9937da2899SCharles.Forsyth Ostbu = XO(39, 0),
10037da2899SCharles.Forsyth Ostbx = XO(31, 215),
10137da2899SCharles.Forsyth Osth = XO(44,0),
10237da2899SCharles.Forsyth Osthx = XO(31, 407),
10337da2899SCharles.Forsyth Ostfd = XO(54, 0),
10437da2899SCharles.Forsyth Ostfdu = XO(55, 0),
10537da2899SCharles.Forsyth
10637da2899SCharles.Forsyth Oaddc = XO(31,10),
10737da2899SCharles.Forsyth Oadde = XO(31, 138),
10837da2899SCharles.Forsyth Oaddi = XO(14, 0), /* simm */
10937da2899SCharles.Forsyth Oaddic_ = XO(13, 0),
11037da2899SCharles.Forsyth Oaddis = XO(15, 0),
11137da2899SCharles.Forsyth Ocrxor = XO(19, 193),
11237da2899SCharles.Forsyth Ofadd = XO(63, 21),
11337da2899SCharles.Forsyth Ofcmpo = XO(63, 32),
11437da2899SCharles.Forsyth Ofctiwz = XO(63, 15),
11537da2899SCharles.Forsyth Ofsub = XO(63, 20),
11637da2899SCharles.Forsyth Ofmr = XO(63, 72),
11737da2899SCharles.Forsyth Ofmul = XO(63, 25),
11837da2899SCharles.Forsyth Ofdiv = XO(63, 18),
11937da2899SCharles.Forsyth Ofneg = XO(63, 40),
12037da2899SCharles.Forsyth Oori = XO(24,0), /* uimm */
12137da2899SCharles.Forsyth Ooris = XO(25,0), /* uimm */
12237da2899SCharles.Forsyth Odivw = XO(31, 491),
12337da2899SCharles.Forsyth Odivwu = XO(31, 459),
12437da2899SCharles.Forsyth Omulhw = XO(31, 75),
12537da2899SCharles.Forsyth Omulhwu = XO(31, 11),
12637da2899SCharles.Forsyth Omulli = XO(7, 0),
12737da2899SCharles.Forsyth Omullw = XO(31, 235),
12837da2899SCharles.Forsyth Osubf = XO(31, 40),
12937da2899SCharles.Forsyth Osubfc = XO(31,8),
13037da2899SCharles.Forsyth Osubfe = XO(31,136),
13137da2899SCharles.Forsyth Osubfic = XO(8, 0),
13237da2899SCharles.Forsyth Oadd = XO(31, 266),
13337da2899SCharles.Forsyth Oand = XO(31, 28),
13437da2899SCharles.Forsyth Oneg = XO(31, 104),
13537da2899SCharles.Forsyth Oor = XO(31, 444),
13637da2899SCharles.Forsyth Oxor = XO(31, 316),
13737da2899SCharles.Forsyth
13837da2899SCharles.Forsyth Ocmpi = XO(11, 0),
13937da2899SCharles.Forsyth Ocmp = XO(31, 0),
14037da2899SCharles.Forsyth Ocmpl = XO(31, 32),
14137da2899SCharles.Forsyth Ocmpli = XO(10,0),
14237da2899SCharles.Forsyth
14337da2899SCharles.Forsyth Orlwinm = XO(21, 0),
14437da2899SCharles.Forsyth Oslw = XO(31, 24),
14537da2899SCharles.Forsyth Osraw = XO(31,792),
14637da2899SCharles.Forsyth Osrawi = XO(31,824),
14737da2899SCharles.Forsyth Osrw = XO(31,536),
14837da2899SCharles.Forsyth
14937da2899SCharles.Forsyth Cnone = OPARRR(0,20,0,0), /* unconditional */
15037da2899SCharles.Forsyth Ceq = OPARRR(0,12,2,0),
15137da2899SCharles.Forsyth Cle = OPARRR(0,4,1,0),
15237da2899SCharles.Forsyth Clt = OPARRR(0,12,0,0),
15337da2899SCharles.Forsyth Cdnz = OPARRR(0,16,0,0),
15437da2899SCharles.Forsyth Cgt = OPARRR(0,12,1,0),
15537da2899SCharles.Forsyth Cne = OPARRR(0,4,2,0),
15637da2899SCharles.Forsyth Cge = OPARRR(0,4,0,0),
15737da2899SCharles.Forsyth Cle1 = OPARRR(0,4,5,0), /* Cle on CR1 */
15837da2899SCharles.Forsyth Crelq = OPARRR(0,12,Rcrbrel,0), /* relinquish */
15937da2899SCharles.Forsyth Cnrelq = OPARRR(0,4,Rcrbrel,0), /* not relinquish */
16037da2899SCharles.Forsyth Cpredict = OPARRR(0,1,0,0), /* reverse prediction */
16137da2899SCharles.Forsyth Lk = 1,
16237da2899SCharles.Forsyth Aa = 2,
16337da2899SCharles.Forsyth
16437da2899SCharles.Forsyth Obeq = OPARRR(16<<26,12,2,0),
16537da2899SCharles.Forsyth Obge = OPARRR(16<<26,4,0,0),
16637da2899SCharles.Forsyth Obgt = OPARRR(16<<26,12,1,0),
16737da2899SCharles.Forsyth Oble = OPARRR(16<<26,4,1,0),
16837da2899SCharles.Forsyth Oblt = OPARRR(16<<26,12,0,0),
16937da2899SCharles.Forsyth Obne = OPARRR(16<<26,4,2,0),
17037da2899SCharles.Forsyth
17137da2899SCharles.Forsyth Ob = XO(18, 0),
17237da2899SCharles.Forsyth Obc = XO(16, 0),
17337da2899SCharles.Forsyth Obcctr = XO(19,528),
17437da2899SCharles.Forsyth Obcctrl = Obcctr | Lk,
17537da2899SCharles.Forsyth Obctr = Obcctr | Cnone,
17637da2899SCharles.Forsyth Obctrl = Obctr | Lk,
17737da2899SCharles.Forsyth Obclr = XO(19, 16),
17837da2899SCharles.Forsyth Oblr = Obclr | Cnone,
17937da2899SCharles.Forsyth Oblrl = Oblr | Lk,
18037da2899SCharles.Forsyth
18137da2899SCharles.Forsyth Olea = 100, // pseudo op
18237da2899SCharles.Forsyth
18337da2899SCharles.Forsyth SRCOP = (1<<0),
18437da2899SCharles.Forsyth DSTOP = (1<<1),
18537da2899SCharles.Forsyth WRTPC = (1<<2), /* update R.PC */
18637da2899SCharles.Forsyth TCHECK = (1<<3), /* check R.t for continue/ret */
18737da2899SCharles.Forsyth NEWPC = (1<<4), /* goto R.PC */
18837da2899SCharles.Forsyth DBRAN = (1<<5), /* dest is branch */
18937da2899SCharles.Forsyth THREOP = (1<<6),
19037da2899SCharles.Forsyth
1914a425662SCharles Forsyth Lg2Rune = sizeof(Rune)==4? 2: 1,
19237da2899SCharles.Forsyth ANDAND = 1,
19337da2899SCharles.Forsyth OROR,
19437da2899SCharles.Forsyth EQAND,
19537da2899SCharles.Forsyth
19637da2899SCharles.Forsyth MacRET = 0,
19737da2899SCharles.Forsyth MacFRP,
19837da2899SCharles.Forsyth MacCASE,
19937da2899SCharles.Forsyth MacFRAM,
20037da2899SCharles.Forsyth MacCOLR,
20137da2899SCharles.Forsyth MacMCAL,
20237da2899SCharles.Forsyth MacMFRA,
20337da2899SCharles.Forsyth MacCVTFW,
20437da2899SCharles.Forsyth MacRELQ,
20537da2899SCharles.Forsyth MacEND,
20637da2899SCharles.Forsyth NMACRO
20737da2899SCharles.Forsyth };
20837da2899SCharles.Forsyth
20937da2899SCharles.Forsyth void (*comvec)(void);
21037da2899SCharles.Forsyth int macjit;
21137da2899SCharles.Forsyth extern long das(ulong*);
21237da2899SCharles.Forsyth static ulong* code;
21337da2899SCharles.Forsyth static ulong* base;
21437da2899SCharles.Forsyth static ulong* patch;
21537da2899SCharles.Forsyth static int pass;
21637da2899SCharles.Forsyth static Module* mod;
21737da2899SCharles.Forsyth static ulong* tinit;
21837da2899SCharles.Forsyth static ulong* litpool;
21937da2899SCharles.Forsyth static int nlit;
22037da2899SCharles.Forsyth static ulong macro[NMACRO];
22137da2899SCharles.Forsyth static void ldbigc(long, int);
22237da2899SCharles.Forsyth static void rdestroy(void);
22337da2899SCharles.Forsyth static void macret(void);
22437da2899SCharles.Forsyth static void macfrp(void);
22537da2899SCharles.Forsyth static void maccase(void);
22637da2899SCharles.Forsyth static void maccvtfw(void);
22737da2899SCharles.Forsyth static void macfram(void);
22837da2899SCharles.Forsyth static void maccolr(void);
22937da2899SCharles.Forsyth static void macend(void);
23037da2899SCharles.Forsyth static void macmcal(void);
23137da2899SCharles.Forsyth static void macmfra(void);
23237da2899SCharles.Forsyth static void macrelq(void);
23337da2899SCharles.Forsyth static void movmem(Inst*);
23437da2899SCharles.Forsyth
23537da2899SCharles.Forsyth struct
23637da2899SCharles.Forsyth {
23737da2899SCharles.Forsyth int o;
23837da2899SCharles.Forsyth void (*f)(void);
23937da2899SCharles.Forsyth } macinit[] =
24037da2899SCharles.Forsyth {
24137da2899SCharles.Forsyth MacFRP, macfrp, /* decrement and free pointer */
24237da2899SCharles.Forsyth MacRET, macret, /* return instruction */
24337da2899SCharles.Forsyth MacCASE, maccase, /* case instruction */
24437da2899SCharles.Forsyth MacCOLR, maccolr, /* increment and color pointer */
24537da2899SCharles.Forsyth MacFRAM, macfram, /* frame instruction */
24637da2899SCharles.Forsyth MacMCAL, macmcal, /* mcall bottom half */
24737da2899SCharles.Forsyth MacMFRA, macmfra, /* punt mframe because t->initialize==0 */
24837da2899SCharles.Forsyth MacCVTFW, maccvtfw,
24937da2899SCharles.Forsyth MacRELQ, macrelq, /* reschedule */
25037da2899SCharles.Forsyth MacEND, macend,
25137da2899SCharles.Forsyth 0
25237da2899SCharles.Forsyth };
25337da2899SCharles.Forsyth
25437da2899SCharles.Forsyth static void
rdestroy(void)25537da2899SCharles.Forsyth rdestroy(void)
25637da2899SCharles.Forsyth {
25737da2899SCharles.Forsyth destroy(R.s);
25837da2899SCharles.Forsyth }
25937da2899SCharles.Forsyth
26037da2899SCharles.Forsyth static void
rmcall(void)26137da2899SCharles.Forsyth rmcall(void)
26237da2899SCharles.Forsyth {
26337da2899SCharles.Forsyth Frame *f;
26437da2899SCharles.Forsyth Prog *p;
26537da2899SCharles.Forsyth
26637da2899SCharles.Forsyth if((void*)R.dt == H)
26737da2899SCharles.Forsyth error(exModule);
26837da2899SCharles.Forsyth
26937da2899SCharles.Forsyth f = (Frame*)R.FP;
27037da2899SCharles.Forsyth if(f == H)
27137da2899SCharles.Forsyth error(exModule);
27237da2899SCharles.Forsyth
27337da2899SCharles.Forsyth f->mr = nil;
27437da2899SCharles.Forsyth ((void(*)(Frame*))R.dt)(f);
27537da2899SCharles.Forsyth R.SP = (uchar*)f;
27637da2899SCharles.Forsyth R.FP = f->fp;
27737da2899SCharles.Forsyth if(f->t == nil)
27837da2899SCharles.Forsyth unextend(f);
27937da2899SCharles.Forsyth else
28037da2899SCharles.Forsyth freeptrs(f, f->t);
28137da2899SCharles.Forsyth p = currun();
28237da2899SCharles.Forsyth if(p->kill != nil)
28337da2899SCharles.Forsyth error(p->kill);
28437da2899SCharles.Forsyth }
28537da2899SCharles.Forsyth
28637da2899SCharles.Forsyth static void
rmfram(void)28737da2899SCharles.Forsyth rmfram(void)
28837da2899SCharles.Forsyth {
28937da2899SCharles.Forsyth Type *t;
29037da2899SCharles.Forsyth Frame *f;
29137da2899SCharles.Forsyth uchar *nsp;
29237da2899SCharles.Forsyth
29337da2899SCharles.Forsyth t = (Type*)R.s;
29437da2899SCharles.Forsyth if(t == H)
29537da2899SCharles.Forsyth error(exModule);
29637da2899SCharles.Forsyth nsp = R.SP + t->size;
29737da2899SCharles.Forsyth if(nsp >= R.TS) {
29837da2899SCharles.Forsyth R.s = t;
29937da2899SCharles.Forsyth extend();
30037da2899SCharles.Forsyth T(d) = R.s;
30137da2899SCharles.Forsyth return;
30237da2899SCharles.Forsyth }
30337da2899SCharles.Forsyth f = (Frame*)R.SP;
30437da2899SCharles.Forsyth R.SP = nsp;
30537da2899SCharles.Forsyth f->t = t;
30637da2899SCharles.Forsyth f->mr = nil;
30737da2899SCharles.Forsyth initmem(t, f);
30837da2899SCharles.Forsyth T(d) = f;
30937da2899SCharles.Forsyth }
31037da2899SCharles.Forsyth
31137da2899SCharles.Forsyth void
urk(char * s)31237da2899SCharles.Forsyth urk(char *s)
31337da2899SCharles.Forsyth {
31437da2899SCharles.Forsyth print("compile failed: %s\n", s); // debugging
31537da2899SCharles.Forsyth error(exCompile); // production
31637da2899SCharles.Forsyth }
31737da2899SCharles.Forsyth
31837da2899SCharles.Forsyth static void
gen(ulong o)31937da2899SCharles.Forsyth gen(ulong o)
32037da2899SCharles.Forsyth {
32137da2899SCharles.Forsyth *code++ = o;
32237da2899SCharles.Forsyth }
32337da2899SCharles.Forsyth
32437da2899SCharles.Forsyth static void
br(ulong op,ulong disp)32537da2899SCharles.Forsyth br(ulong op, ulong disp)
32637da2899SCharles.Forsyth {
32737da2899SCharles.Forsyth *code++ = op | (disp & 0xfffc);
32837da2899SCharles.Forsyth }
32937da2899SCharles.Forsyth
33037da2899SCharles.Forsyth static void
mfspr(int d,int s)33137da2899SCharles.Forsyth mfspr(int d, int s)
33237da2899SCharles.Forsyth {
33337da2899SCharles.Forsyth MFSPR(s, d);
33437da2899SCharles.Forsyth }
33537da2899SCharles.Forsyth
33637da2899SCharles.Forsyth static void
mtspr(int d,int s)33737da2899SCharles.Forsyth mtspr(int d, int s)
33837da2899SCharles.Forsyth {
33937da2899SCharles.Forsyth MTSPR(s, d);
34037da2899SCharles.Forsyth }
34137da2899SCharles.Forsyth
34237da2899SCharles.Forsyth static ulong
slw(int d,int s,int v,int rshift)34337da2899SCharles.Forsyth slw(int d, int s, int v, int rshift)
34437da2899SCharles.Forsyth {
34537da2899SCharles.Forsyth int m0, m1;
34637da2899SCharles.Forsyth
34737da2899SCharles.Forsyth if(v < 0 || v > 32)
34837da2899SCharles.Forsyth urk("slw v");
34937da2899SCharles.Forsyth if(v < 0)
35037da2899SCharles.Forsyth v = 0;
35137da2899SCharles.Forsyth else if(v > 32)
35237da2899SCharles.Forsyth v = 32;
35337da2899SCharles.Forsyth if(rshift) { /* shift right */
35437da2899SCharles.Forsyth m0 = v;
35537da2899SCharles.Forsyth m1 = 31;
35637da2899SCharles.Forsyth v = 32-v;
35737da2899SCharles.Forsyth } else {
35837da2899SCharles.Forsyth m0 = 0;
35937da2899SCharles.Forsyth m1 = 31-v;
36037da2899SCharles.Forsyth }
36137da2899SCharles.Forsyth return RLW(Orlwinm, d, s, v, m0, m1);
36237da2899SCharles.Forsyth }
36337da2899SCharles.Forsyth
36437da2899SCharles.Forsyth static void
jr(int reg)36537da2899SCharles.Forsyth jr(int reg)
36637da2899SCharles.Forsyth {
36737da2899SCharles.Forsyth mtspr(Rctr, reg); /* code would be faster if this were loaded well before branch */
36837da2899SCharles.Forsyth gen(Obctr);
36937da2899SCharles.Forsyth }
37037da2899SCharles.Forsyth
37137da2899SCharles.Forsyth static void
jrl(int reg)37237da2899SCharles.Forsyth jrl(int reg)
37337da2899SCharles.Forsyth {
37437da2899SCharles.Forsyth mtspr(Rctr, reg);
37537da2899SCharles.Forsyth gen(Obctrl);
37637da2899SCharles.Forsyth }
37737da2899SCharles.Forsyth
37837da2899SCharles.Forsyth static void
jrc(int op,int reg)37937da2899SCharles.Forsyth jrc(int op, int reg)
38037da2899SCharles.Forsyth {
38137da2899SCharles.Forsyth mtspr(Rctr, reg);
38237da2899SCharles.Forsyth gen(Obcctr | op);
38337da2899SCharles.Forsyth }
38437da2899SCharles.Forsyth
38537da2899SCharles.Forsyth static long
brdisp(ulong * dest)38637da2899SCharles.Forsyth brdisp(ulong *dest)
38737da2899SCharles.Forsyth {
38837da2899SCharles.Forsyth ulong d, top;
38937da2899SCharles.Forsyth
39037da2899SCharles.Forsyth d = (ulong)dest - (ulong)code;
39137da2899SCharles.Forsyth if(!ROMABLE)
39237da2899SCharles.Forsyth return d & 0x3fffffc;
39337da2899SCharles.Forsyth top = d>>25;
39437da2899SCharles.Forsyth if(top == 0 || top == 0x7F){
39537da2899SCharles.Forsyth /* fits in 26-bit signed displacement */
39637da2899SCharles.Forsyth return d & 0x3fffffc;
39737da2899SCharles.Forsyth }
39837da2899SCharles.Forsyth return -1;
39937da2899SCharles.Forsyth }
40037da2899SCharles.Forsyth
40137da2899SCharles.Forsyth static void
jmp(ulong * dest)40237da2899SCharles.Forsyth jmp(ulong *dest)
40337da2899SCharles.Forsyth {
40437da2899SCharles.Forsyth long d;
40537da2899SCharles.Forsyth
40637da2899SCharles.Forsyth if((d = brdisp(dest)) < 0){
40737da2899SCharles.Forsyth ldbigc((ulong)dest, Rpic); /* Rpic & Rctr must be free */
40837da2899SCharles.Forsyth jr(Rpic);
40937da2899SCharles.Forsyth } else
41037da2899SCharles.Forsyth gen(Ob | d);
41137da2899SCharles.Forsyth }
41237da2899SCharles.Forsyth
41337da2899SCharles.Forsyth static void
jmpl(ulong * dest)41437da2899SCharles.Forsyth jmpl(ulong *dest)
41537da2899SCharles.Forsyth {
41637da2899SCharles.Forsyth long d;
41737da2899SCharles.Forsyth
41837da2899SCharles.Forsyth if((d = brdisp(dest)) < 0){
41937da2899SCharles.Forsyth ldbigc((ulong)dest, Rpic); /* Rpic must be free */
42037da2899SCharles.Forsyth jrl(Rpic);
42137da2899SCharles.Forsyth } else
42237da2899SCharles.Forsyth gen(Ob | d | Lk);
42337da2899SCharles.Forsyth }
42437da2899SCharles.Forsyth
42537da2899SCharles.Forsyth static void
jmpc(int op,ulong * dest)42637da2899SCharles.Forsyth jmpc(int op, ulong *dest)
42737da2899SCharles.Forsyth {
42837da2899SCharles.Forsyth ldbigc((ulong)dest, Rpic);
42937da2899SCharles.Forsyth jrc(op, Rpic);
43037da2899SCharles.Forsyth }
43137da2899SCharles.Forsyth
43237da2899SCharles.Forsyth static int
bigc(long c)43337da2899SCharles.Forsyth bigc(long c)
43437da2899SCharles.Forsyth {
43537da2899SCharles.Forsyth if(c >= -0x8000 && c <= 0x7FFF)
43637da2899SCharles.Forsyth return 0;
43737da2899SCharles.Forsyth return 1;
43837da2899SCharles.Forsyth }
43937da2899SCharles.Forsyth
44037da2899SCharles.Forsyth static void
ldbigc(long c,int reg)44137da2899SCharles.Forsyth ldbigc(long c, int reg)
44237da2899SCharles.Forsyth {
44337da2899SCharles.Forsyth AIRR(Oaddis, reg,Rzero,c>>16);
44437da2899SCharles.Forsyth LIRR(Oori, reg,reg,c);
44537da2899SCharles.Forsyth }
44637da2899SCharles.Forsyth
44737da2899SCharles.Forsyth static void
ldc(long c,int reg)44837da2899SCharles.Forsyth ldc(long c, int reg)
44937da2899SCharles.Forsyth {
45037da2899SCharles.Forsyth if(!bigc(c))
45137da2899SCharles.Forsyth AIRR(Oaddi, reg, Rzero, c);
45237da2899SCharles.Forsyth else if((ulong)c <= 0xFFFF)
45337da2899SCharles.Forsyth LIRR(Oori, reg, Rzero, c);
45437da2899SCharles.Forsyth else if((c&0xFFFF) == 0)
45537da2899SCharles.Forsyth LIRR(Ooris, reg, Rzero, c>>16);
45637da2899SCharles.Forsyth else {
45737da2899SCharles.Forsyth AIRR(Oaddis, reg,Rzero,c>>16);
45837da2899SCharles.Forsyth LIRR(Oori, reg,reg,c);
45937da2899SCharles.Forsyth }
46037da2899SCharles.Forsyth }
46137da2899SCharles.Forsyth
46237da2899SCharles.Forsyth static void
mem(int inst,long disp,int rm,int r)46337da2899SCharles.Forsyth mem(int inst, long disp, int rm, int r)
46437da2899SCharles.Forsyth {
46537da2899SCharles.Forsyth if(bigc(disp)) {
46637da2899SCharles.Forsyth ldc(disp, Rcon);
46737da2899SCharles.Forsyth switch(inst){
46837da2899SCharles.Forsyth default: urk("mem op"); break;
46937da2899SCharles.Forsyth case Olea: inst = Oadd; break;
47037da2899SCharles.Forsyth case Olwz: inst = Olwzx; break;
47137da2899SCharles.Forsyth case Olbz: inst = Olbzx; break;
47237da2899SCharles.Forsyth case Olhz: inst = Olhzx; break;
47337da2899SCharles.Forsyth case Ostw: inst = Ostwx; break;
47437da2899SCharles.Forsyth case Ostb: inst = Ostbx; break;
47537da2899SCharles.Forsyth case Osth: inst = Osthx; break;
47637da2899SCharles.Forsyth }
47737da2899SCharles.Forsyth ARRR(inst, r, Rcon, rm);
47837da2899SCharles.Forsyth } else {
47937da2899SCharles.Forsyth if(inst == Olea)
48037da2899SCharles.Forsyth inst = Oaddi;
48137da2899SCharles.Forsyth AIRR(inst, r, rm,disp);
48237da2899SCharles.Forsyth }
48337da2899SCharles.Forsyth }
48437da2899SCharles.Forsyth
48537da2899SCharles.Forsyth static void
opx(int mode,Adr * a,int op,int reg)48637da2899SCharles.Forsyth opx(int mode, Adr *a, int op, int reg)
48737da2899SCharles.Forsyth {
48837da2899SCharles.Forsyth ulong c;
48937da2899SCharles.Forsyth int r, rx, lea;
49037da2899SCharles.Forsyth
49137da2899SCharles.Forsyth lea = 0;
49237da2899SCharles.Forsyth if(op == Olea){
49337da2899SCharles.Forsyth lea = 1;
49437da2899SCharles.Forsyth op = Oaddi;
49537da2899SCharles.Forsyth }
49637da2899SCharles.Forsyth switch(mode) {
49737da2899SCharles.Forsyth case AFP:
49837da2899SCharles.Forsyth c = a->ind;
49937da2899SCharles.Forsyth if(bigc(c))
50037da2899SCharles.Forsyth urk("bigc op1b 1");
50137da2899SCharles.Forsyth AIRR(op, reg, Rfp,c);
50237da2899SCharles.Forsyth break;
50337da2899SCharles.Forsyth case AMP:
50437da2899SCharles.Forsyth c = a->ind;
50537da2899SCharles.Forsyth if(bigc(c))
50637da2899SCharles.Forsyth urk("bigc op1b 2");
50737da2899SCharles.Forsyth AIRR(op, reg, Rmp,c);
50837da2899SCharles.Forsyth break;
50937da2899SCharles.Forsyth case AIMM:
51037da2899SCharles.Forsyth if(lea) {
51137da2899SCharles.Forsyth if(a->imm != 0) {
51237da2899SCharles.Forsyth ldc(a->imm, reg);
51337da2899SCharles.Forsyth AIRR(Ostw, reg, Rreg,O(REG,st));
51437da2899SCharles.Forsyth } else
51537da2899SCharles.Forsyth AIRR(Ostw, Rzero, Rreg,O(REG,st));
51637da2899SCharles.Forsyth AIRR(Oaddi, reg, Rreg,O(REG,st));
51737da2899SCharles.Forsyth } else
51837da2899SCharles.Forsyth ldc(a->imm, reg);
51937da2899SCharles.Forsyth return;
52037da2899SCharles.Forsyth case AIND|AFP:
52137da2899SCharles.Forsyth r = Rfp;
52237da2899SCharles.Forsyth goto offset;
52337da2899SCharles.Forsyth case AIND|AMP:
52437da2899SCharles.Forsyth r = Rmp;
52537da2899SCharles.Forsyth offset:
52637da2899SCharles.Forsyth c = a->i.s;
52737da2899SCharles.Forsyth rx = Ri;
52837da2899SCharles.Forsyth if(lea || op == Olwz)
52937da2899SCharles.Forsyth rx = reg;
53037da2899SCharles.Forsyth AIRR(Olwz, rx, r,a->i.f);
53137da2899SCharles.Forsyth if(!lea || c != 0)
53237da2899SCharles.Forsyth AIRR(op, reg, rx,c);
53337da2899SCharles.Forsyth break;
53437da2899SCharles.Forsyth }
53537da2899SCharles.Forsyth }
53637da2899SCharles.Forsyth
53737da2899SCharles.Forsyth static void
opwld(Inst * i,int op,int reg)53837da2899SCharles.Forsyth opwld(Inst *i, int op, int reg)
53937da2899SCharles.Forsyth {
54037da2899SCharles.Forsyth opx(USRC(i->add), &i->s, op, reg);
54137da2899SCharles.Forsyth }
54237da2899SCharles.Forsyth
54337da2899SCharles.Forsyth static void
opwst(Inst * i,int op,int reg)54437da2899SCharles.Forsyth opwst(Inst *i, int op, int reg)
54537da2899SCharles.Forsyth {
54637da2899SCharles.Forsyth opx(UDST(i->add), &i->d, op, reg);
54737da2899SCharles.Forsyth }
54837da2899SCharles.Forsyth
54937da2899SCharles.Forsyth static void
op2(Inst * i,int op,int reg)55037da2899SCharles.Forsyth op2(Inst *i, int op, int reg)
55137da2899SCharles.Forsyth {
55237da2899SCharles.Forsyth int lea;
55337da2899SCharles.Forsyth
55437da2899SCharles.Forsyth lea = 0;
55537da2899SCharles.Forsyth if(op == Olea){
55637da2899SCharles.Forsyth op = Oaddi;
55737da2899SCharles.Forsyth lea = 1;
55837da2899SCharles.Forsyth }
55937da2899SCharles.Forsyth switch(i->add & ARM) {
56037da2899SCharles.Forsyth case AXNON:
56137da2899SCharles.Forsyth if(lea)
56237da2899SCharles.Forsyth op = Olea;
56337da2899SCharles.Forsyth opwst(i, op, reg);
56437da2899SCharles.Forsyth return;
56537da2899SCharles.Forsyth case AXIMM:
56637da2899SCharles.Forsyth if(lea)
56737da2899SCharles.Forsyth urk("op2/lea");
56837da2899SCharles.Forsyth ldc((short)i->reg, reg);
56937da2899SCharles.Forsyth return;
57037da2899SCharles.Forsyth case AXINF:
57137da2899SCharles.Forsyth IRR(op, i->reg,Rfp, reg);
57237da2899SCharles.Forsyth break;
57337da2899SCharles.Forsyth case AXINM:
57437da2899SCharles.Forsyth IRR(op, i->reg,Rmp, reg);
57537da2899SCharles.Forsyth break;
57637da2899SCharles.Forsyth }
57737da2899SCharles.Forsyth }
57837da2899SCharles.Forsyth
57937da2899SCharles.Forsyth static void
op12(Inst * i,int b1flag,int b2flag)58037da2899SCharles.Forsyth op12(Inst *i, int b1flag, int b2flag)
58137da2899SCharles.Forsyth {
58237da2899SCharles.Forsyth int o1, o2;
58337da2899SCharles.Forsyth
58437da2899SCharles.Forsyth o1 = Olwz;
58537da2899SCharles.Forsyth if(b1flag)
58637da2899SCharles.Forsyth o1 = Olbz;
58737da2899SCharles.Forsyth o2 = Olwz;
58837da2899SCharles.Forsyth if(b2flag)
58937da2899SCharles.Forsyth o2 = Olbz;
59037da2899SCharles.Forsyth if((i->add & ARM) == AXIMM) {
59137da2899SCharles.Forsyth opwld(i, o1, Ro1);
59237da2899SCharles.Forsyth op2(i, o2, Ro2);
59337da2899SCharles.Forsyth } else {
59437da2899SCharles.Forsyth op2(i, o2, Ro2);
59537da2899SCharles.Forsyth opwld(i, o1, Ro1);
59637da2899SCharles.Forsyth }
59737da2899SCharles.Forsyth }
59837da2899SCharles.Forsyth
59937da2899SCharles.Forsyth static void
op13(Inst * i,int o1,int o2)60037da2899SCharles.Forsyth op13(Inst *i, int o1, int o2)
60137da2899SCharles.Forsyth {
60237da2899SCharles.Forsyth opwld(i, o1, Ro1);
60337da2899SCharles.Forsyth opwst(i, o2, Ro1);
60437da2899SCharles.Forsyth }
60537da2899SCharles.Forsyth
60637da2899SCharles.Forsyth static ulong
branch(Inst * i)60737da2899SCharles.Forsyth branch(Inst *i)
60837da2899SCharles.Forsyth {
60937da2899SCharles.Forsyth ulong rel;
61037da2899SCharles.Forsyth
61137da2899SCharles.Forsyth if(base == 0)
61237da2899SCharles.Forsyth return 0;
61337da2899SCharles.Forsyth rel = (ulong)(base+patch[i->d.ins - mod->prog]);
61437da2899SCharles.Forsyth rel -= (ulong)code;
61537da2899SCharles.Forsyth if(rel & 3 || (long)rel <= -(1<<16) || (long)rel >= 1<<16)
61637da2899SCharles.Forsyth urk("branch off");
61737da2899SCharles.Forsyth return rel & 0xfffc;
61837da2899SCharles.Forsyth }
61937da2899SCharles.Forsyth
62037da2899SCharles.Forsyth static void
schedcheck(Inst * i)62137da2899SCharles.Forsyth schedcheck(Inst *i)
62237da2899SCharles.Forsyth {
62337da2899SCharles.Forsyth ulong *cp;
62437da2899SCharles.Forsyth
62537da2899SCharles.Forsyth if(i != nil && i->d.ins != nil && i->d.ins > i)
62637da2899SCharles.Forsyth return; /* only backwards jumps can loop: needn't check forward ones */
62737da2899SCharles.Forsyth cp = code;
62837da2899SCharles.Forsyth gen(Obc | Cnrelq | Cpredict);
62937da2899SCharles.Forsyth jmpl(base+macro[MacRELQ]);
63037da2899SCharles.Forsyth PATCH(cp);
63137da2899SCharles.Forsyth }
63237da2899SCharles.Forsyth
63337da2899SCharles.Forsyth static void
literal(ulong imm,int roff)63437da2899SCharles.Forsyth literal(ulong imm, int roff)
63537da2899SCharles.Forsyth {
63637da2899SCharles.Forsyth nlit++;
63737da2899SCharles.Forsyth
63837da2899SCharles.Forsyth ldbigc((ulong)litpool, Ro1);
63937da2899SCharles.Forsyth IRR(Ostw, roff, Rreg, Ro1);
64037da2899SCharles.Forsyth
64137da2899SCharles.Forsyth if(pass == 0)
64237da2899SCharles.Forsyth return;
64337da2899SCharles.Forsyth
64437da2899SCharles.Forsyth *litpool = imm;
64537da2899SCharles.Forsyth litpool++;
64637da2899SCharles.Forsyth }
64737da2899SCharles.Forsyth
64837da2899SCharles.Forsyth static void
bounds(void)64937da2899SCharles.Forsyth bounds(void)
65037da2899SCharles.Forsyth {
65137da2899SCharles.Forsyth /* mem(Ostw, O(REG,FP), Rreg, Rfp); */
65237da2899SCharles.Forsyth error(exBounds);
65337da2899SCharles.Forsyth }
65437da2899SCharles.Forsyth
65537da2899SCharles.Forsyth static void
punt(Inst * i,int m,void (* fn)(void))65637da2899SCharles.Forsyth punt(Inst *i, int m, void (*fn)(void))
65737da2899SCharles.Forsyth {
65837da2899SCharles.Forsyth ulong pc;
65937da2899SCharles.Forsyth
66037da2899SCharles.Forsyth if(m & SRCOP) {
66137da2899SCharles.Forsyth if(UXSRC(i->add) == SRC(AIMM))
66237da2899SCharles.Forsyth literal(i->s.imm, O(REG, s));
66337da2899SCharles.Forsyth else {
66437da2899SCharles.Forsyth opwld(i, Olea, Ro1);
66537da2899SCharles.Forsyth mem(Ostw, O(REG, s), Rreg, Ro1);
66637da2899SCharles.Forsyth }
66737da2899SCharles.Forsyth }
66837da2899SCharles.Forsyth if(m & DSTOP) {
66937da2899SCharles.Forsyth opwst(i, Olea, Ro3);
67037da2899SCharles.Forsyth IRR(Ostw, O(REG,d),Rreg, Ro3);
67137da2899SCharles.Forsyth }
67237da2899SCharles.Forsyth if(m & WRTPC) {
67337da2899SCharles.Forsyth pc = patch[i-mod->prog+1];
67437da2899SCharles.Forsyth ldbigc((ulong)(base+pc), Ro1);
67537da2899SCharles.Forsyth IRR(Ostw, O(REG,PC),Rreg, Ro1);
67637da2899SCharles.Forsyth }
67737da2899SCharles.Forsyth if(m & DBRAN) {
67837da2899SCharles.Forsyth pc = patch[i->d.ins-mod->prog];
67937da2899SCharles.Forsyth literal((ulong)(base+pc), O(REG, d));
68037da2899SCharles.Forsyth }
68137da2899SCharles.Forsyth
68237da2899SCharles.Forsyth switch(i->add&ARM) {
68337da2899SCharles.Forsyth case AXNON:
68437da2899SCharles.Forsyth if(m & THREOP) {
68537da2899SCharles.Forsyth IRR(Olwz, O(REG,d),Rreg, Ro2);
68637da2899SCharles.Forsyth IRR(Ostw, O(REG,m),Rreg, Ro2);
68737da2899SCharles.Forsyth }
68837da2899SCharles.Forsyth break;
68937da2899SCharles.Forsyth case AXIMM:
69037da2899SCharles.Forsyth literal((short)i->reg, O(REG,m));
69137da2899SCharles.Forsyth break;
69237da2899SCharles.Forsyth case AXINF:
69337da2899SCharles.Forsyth mem(Olea, i->reg, Rfp, Ro2);
69437da2899SCharles.Forsyth mem(Ostw, O(REG, m), Rreg, Ro2);
69537da2899SCharles.Forsyth break;
69637da2899SCharles.Forsyth case AXINM:
69737da2899SCharles.Forsyth mem(Olea, i->reg, Rmp, Ro2);
69837da2899SCharles.Forsyth mem(Ostw, O(REG, m), Rreg, Ro2);
69937da2899SCharles.Forsyth break;
70037da2899SCharles.Forsyth }
70137da2899SCharles.Forsyth IRR(Ostw, O(REG,FP),Rreg, Rfp);
70237da2899SCharles.Forsyth
70337da2899SCharles.Forsyth jmpl((ulong*)fn);
70437da2899SCharles.Forsyth
70537da2899SCharles.Forsyth ldc((ulong)&R, Rreg);
70637da2899SCharles.Forsyth SETR0();
70737da2899SCharles.Forsyth if(m & TCHECK) {
70837da2899SCharles.Forsyth IRR(Olwz, O(REG,t),Rreg, Ro1);
70937da2899SCharles.Forsyth IRR(Olwz, O(REG,xpc),Rreg, Ro2);
71037da2899SCharles.Forsyth IRR(Ocmpi, 0, Ro1, Rcrf0);
71137da2899SCharles.Forsyth mtspr(Rctr, Ro2);
71237da2899SCharles.Forsyth gen(Obcctr | Cne);
71337da2899SCharles.Forsyth }
71437da2899SCharles.Forsyth IRR(Olwz, O(REG,FP),Rreg, Rfp);
71537da2899SCharles.Forsyth IRR(Olwz, O(REG,MP),Rreg, Rmp);
71637da2899SCharles.Forsyth
71737da2899SCharles.Forsyth if(m & NEWPC) {
71837da2899SCharles.Forsyth IRR(Olwz, O(REG,PC),Rreg, Ro1);
71937da2899SCharles.Forsyth jr(Ro1);
72037da2899SCharles.Forsyth }
72137da2899SCharles.Forsyth }
72237da2899SCharles.Forsyth
72337da2899SCharles.Forsyth static void
comgoto(Inst * i)72437da2899SCharles.Forsyth comgoto(Inst *i)
72537da2899SCharles.Forsyth {
72637da2899SCharles.Forsyth WORD *t, *e;
72737da2899SCharles.Forsyth
72837da2899SCharles.Forsyth opwld(i, Olwz, Ro2);
72937da2899SCharles.Forsyth opwst(i, Olea, Ro3);
73037da2899SCharles.Forsyth SLWI(Ro2, Ro2, 2);
73137da2899SCharles.Forsyth ARRR(Olwzx, Ro1, Ro3,Ro2);
73237da2899SCharles.Forsyth jr(Ro1);
73337da2899SCharles.Forsyth
73437da2899SCharles.Forsyth if(pass == 0)
73537da2899SCharles.Forsyth return;
73637da2899SCharles.Forsyth
73737da2899SCharles.Forsyth t = (WORD*)(mod->origmp+i->d.ind);
73837da2899SCharles.Forsyth e = t + t[-1];
73937da2899SCharles.Forsyth t[-1] = 0;
74037da2899SCharles.Forsyth while(t < e) {
74137da2899SCharles.Forsyth t[0] = (ulong)(base + patch[t[0]]);
74237da2899SCharles.Forsyth t++;
74337da2899SCharles.Forsyth }
74437da2899SCharles.Forsyth }
74537da2899SCharles.Forsyth
74637da2899SCharles.Forsyth static void
comcase(Inst * i,int w)74737da2899SCharles.Forsyth comcase(Inst *i, int w)
74837da2899SCharles.Forsyth {
74937da2899SCharles.Forsyth int l;
75037da2899SCharles.Forsyth WORD *t, *e;
75137da2899SCharles.Forsyth
75237da2899SCharles.Forsyth if(w != 0) {
75337da2899SCharles.Forsyth opwld(i, Olwz, Ro1); // v
75437da2899SCharles.Forsyth opwst(i, Olea, Ro3); // table
75537da2899SCharles.Forsyth jmp(base+macro[MacCASE]);
75637da2899SCharles.Forsyth }
75737da2899SCharles.Forsyth
75837da2899SCharles.Forsyth t = (WORD*)(mod->origmp+i->d.ind+4);
75937da2899SCharles.Forsyth l = t[-1];
76037da2899SCharles.Forsyth
76137da2899SCharles.Forsyth /* have to take care not to relocate the same table twice -
76237da2899SCharles.Forsyth * the limbo compiler can duplicate a case instruction
76337da2899SCharles.Forsyth * during its folding phase
76437da2899SCharles.Forsyth */
76537da2899SCharles.Forsyth
76637da2899SCharles.Forsyth if(pass == 0) {
76737da2899SCharles.Forsyth if(l >= 0)
76837da2899SCharles.Forsyth t[-1] = -l-1; /* Mark it not done */
76937da2899SCharles.Forsyth return;
77037da2899SCharles.Forsyth }
77137da2899SCharles.Forsyth if(l >= 0) /* Check pass 2 done */
77237da2899SCharles.Forsyth return;
77337da2899SCharles.Forsyth t[-1] = -l-1; /* Set real count */
77437da2899SCharles.Forsyth e = t + t[-1]*3;
77537da2899SCharles.Forsyth while(t < e) {
77637da2899SCharles.Forsyth t[2] = (ulong)(base + patch[t[2]]);
77737da2899SCharles.Forsyth t += 3;
77837da2899SCharles.Forsyth }
77937da2899SCharles.Forsyth t[0] = (ulong)(base + patch[t[0]]);
78037da2899SCharles.Forsyth }
78137da2899SCharles.Forsyth
78237da2899SCharles.Forsyth static void
comcasel(Inst * i)78337da2899SCharles.Forsyth comcasel(Inst *i)
78437da2899SCharles.Forsyth {
78537da2899SCharles.Forsyth int l;
78637da2899SCharles.Forsyth WORD *t, *e;
78737da2899SCharles.Forsyth
78837da2899SCharles.Forsyth t = (WORD*)(mod->origmp+i->d.ind+8);
78937da2899SCharles.Forsyth l = t[-2];
79037da2899SCharles.Forsyth if(pass == 0) {
79137da2899SCharles.Forsyth if(l >= 0)
79237da2899SCharles.Forsyth t[-2] = -l-1; /* Mark it not done */
79337da2899SCharles.Forsyth return;
79437da2899SCharles.Forsyth }
79537da2899SCharles.Forsyth if(l >= 0) /* Check pass 2 done */
79637da2899SCharles.Forsyth return;
79737da2899SCharles.Forsyth t[-2] = -l-1; /* Set real count */
79837da2899SCharles.Forsyth e = t + t[-2]*6;
79937da2899SCharles.Forsyth while(t < e) {
80037da2899SCharles.Forsyth t[4] = (ulong)base + patch[t[4]];
80137da2899SCharles.Forsyth t += 6;
80237da2899SCharles.Forsyth }
80337da2899SCharles.Forsyth t[0] = (ulong)base + patch[t[0]];
80437da2899SCharles.Forsyth }
80537da2899SCharles.Forsyth
80637da2899SCharles.Forsyth static void
commframe(Inst * i)80737da2899SCharles.Forsyth commframe(Inst *i)
80837da2899SCharles.Forsyth {
80937da2899SCharles.Forsyth ulong *cp1, *cp2;
81037da2899SCharles.Forsyth
81137da2899SCharles.Forsyth opwld(i, Olwz, Ri); // must use Ri for MacFRAM
81237da2899SCharles.Forsyth CMPH(Ri);
81337da2899SCharles.Forsyth cp1 = code;
81437da2899SCharles.Forsyth br(Obeq, 0);
81537da2899SCharles.Forsyth
81637da2899SCharles.Forsyth if((i->add&ARM) == AXIMM) {
81737da2899SCharles.Forsyth mem(Olwz, OA(Modlink, links)+i->reg*sizeof(Modl)+O(Modl, frame), Ri, Ri);
81837da2899SCharles.Forsyth } else {
81937da2899SCharles.Forsyth op2(i, Olwz, Ro2);
82037da2899SCharles.Forsyth SLWI(Ro2, Ro2, 3); // assumes sizeof(Modl) == 8
82137da2899SCharles.Forsyth ARRR(Oadd, Ri, Ro2, Ro2);
82237da2899SCharles.Forsyth mem(Olwz, OA(Modlink, links)+O(Modl, frame), Ri, Ri);
82337da2899SCharles.Forsyth }
82437da2899SCharles.Forsyth
82537da2899SCharles.Forsyth AIRR(Olwz, Ro2, Ri,O(Type,initialize));
82637da2899SCharles.Forsyth AIRR(Ocmpi, Rcrf0, Ro2, 0);
82737da2899SCharles.Forsyth cp2 = code;
82837da2899SCharles.Forsyth br(Obne, 0);
82937da2899SCharles.Forsyth
83037da2899SCharles.Forsyth opwst(i, Olea, Rj);
83137da2899SCharles.Forsyth
83237da2899SCharles.Forsyth PATCH(cp1);
83337da2899SCharles.Forsyth ldbigc((ulong)(base+patch[i-mod->prog+1]), Rpic);
83437da2899SCharles.Forsyth mtspr(Rlr, Rpic);
83537da2899SCharles.Forsyth jmp(base+macro[MacMFRA]);
83637da2899SCharles.Forsyth
83737da2899SCharles.Forsyth PATCH(cp2);
83837da2899SCharles.Forsyth jmpl(base+macro[MacFRAM]);
83937da2899SCharles.Forsyth opwst(i, Ostw, Ro1);
84037da2899SCharles.Forsyth }
84137da2899SCharles.Forsyth
84237da2899SCharles.Forsyth static void
commcall(Inst * i)84337da2899SCharles.Forsyth commcall(Inst *i)
84437da2899SCharles.Forsyth {
84537da2899SCharles.Forsyth opwld(i, Olwz, Ro1); // f in Ro1
84637da2899SCharles.Forsyth AIRR(Olwz, Ro3, Rreg,O(REG,M));
84737da2899SCharles.Forsyth AIRR(Ostw, Rfp, Ro1,O(Frame,fp)); // f->fp = R.FP
84837da2899SCharles.Forsyth AIRR(Ostw, Ro3, Ro1,O(Frame,mr)); // f->mr = R.M
84937da2899SCharles.Forsyth opwst(i, Olwz, Ri);
85037da2899SCharles.Forsyth if((i->add&ARM) == AXIMM) {
85137da2899SCharles.Forsyth mem(Olwz, OA(Modlink, links)+i->reg*sizeof(Modl)+O(Modl, u.pc), Ri, Rj); // ml->entry in Rj
85237da2899SCharles.Forsyth } else {
85337da2899SCharles.Forsyth op2(i, Olwz, Rj);
85437da2899SCharles.Forsyth SLWI(Rj, Rj, 3); // assumes sizeof(Modl) == 8
85537da2899SCharles.Forsyth ARRR(Oadd, Ri, Rj, Rj);
85637da2899SCharles.Forsyth mem(Olwz, OA(Modlink, links)+O(Modl, u.pc), Rj, Rj);
85737da2899SCharles.Forsyth }
85837da2899SCharles.Forsyth jmpl(base+macro[MacMCAL]);
85937da2899SCharles.Forsyth }
86037da2899SCharles.Forsyth
86137da2899SCharles.Forsyth static int
swapbraop(int b)86237da2899SCharles.Forsyth swapbraop(int b)
86337da2899SCharles.Forsyth {
86437da2899SCharles.Forsyth switch(b) {
86537da2899SCharles.Forsyth case Obge:
86637da2899SCharles.Forsyth return Oble;
86737da2899SCharles.Forsyth case Oble:
86837da2899SCharles.Forsyth return Obge;
86937da2899SCharles.Forsyth case Obgt:
87037da2899SCharles.Forsyth return Oblt;
87137da2899SCharles.Forsyth case Oblt:
87237da2899SCharles.Forsyth return Obgt;
87337da2899SCharles.Forsyth }
87437da2899SCharles.Forsyth return b;
87537da2899SCharles.Forsyth }
87637da2899SCharles.Forsyth
87737da2899SCharles.Forsyth static void
cbra(Inst * i,int op)87837da2899SCharles.Forsyth cbra(Inst *i, int op)
87937da2899SCharles.Forsyth {
88037da2899SCharles.Forsyth if(RESCHED)
88137da2899SCharles.Forsyth schedcheck(i);
88237da2899SCharles.Forsyth if(UXSRC(i->add) == SRC(AIMM) && !bigc(i->s.imm)) {
88337da2899SCharles.Forsyth op2(i, Olwz, Ro1);
88437da2899SCharles.Forsyth AIRR(Ocmpi, Rcrf0, Ro1, i->s.imm);
88537da2899SCharles.Forsyth op = swapbraop(op);
88637da2899SCharles.Forsyth } else if((i->add & ARM) == AXIMM) {
88737da2899SCharles.Forsyth opwld(i, Olwz, Ro1);
88837da2899SCharles.Forsyth AIRR(Ocmpi, Rcrf0, Ro1, i->reg);
88937da2899SCharles.Forsyth } else {
89037da2899SCharles.Forsyth op12(i, 0, 0);
89137da2899SCharles.Forsyth ARRR(Ocmp, Rcrf0, Ro1, Ro2);
89237da2899SCharles.Forsyth }
89337da2899SCharles.Forsyth br(op, branch(i));
89437da2899SCharles.Forsyth }
89537da2899SCharles.Forsyth
89637da2899SCharles.Forsyth static void
cbrab(Inst * i,int op)89737da2899SCharles.Forsyth cbrab(Inst *i, int op)
89837da2899SCharles.Forsyth {
89937da2899SCharles.Forsyth if(RESCHED)
90037da2899SCharles.Forsyth schedcheck(i);
90137da2899SCharles.Forsyth if(UXSRC(i->add) == SRC(AIMM)) {
90237da2899SCharles.Forsyth op2(i, Olbz, Ro1);
90337da2899SCharles.Forsyth AIRR(Ocmpi, Rcrf0, Ro1, i->s.imm&0xFF);
90437da2899SCharles.Forsyth op = swapbraop(op);
90537da2899SCharles.Forsyth } else if((i->add & ARM) == AXIMM) {
90637da2899SCharles.Forsyth opwld(i, Olbz, Ro1);
90737da2899SCharles.Forsyth AIRR(Ocmpi, Rcrf0, Ro1, i->reg&0xFF); // mask i->reg?
90837da2899SCharles.Forsyth } else {
90937da2899SCharles.Forsyth op12(i, 1, 1);
91037da2899SCharles.Forsyth ARRR(Ocmp, Rcrf0, Ro1, Ro2);
91137da2899SCharles.Forsyth }
91237da2899SCharles.Forsyth br(op, branch(i));
91337da2899SCharles.Forsyth }
91437da2899SCharles.Forsyth
91537da2899SCharles.Forsyth static void
cbraf(Inst * i,int op)91637da2899SCharles.Forsyth cbraf(Inst *i, int op)
91737da2899SCharles.Forsyth {
91837da2899SCharles.Forsyth if(RESCHED)
91937da2899SCharles.Forsyth schedcheck(i);
92037da2899SCharles.Forsyth opwld(i, Olfd, Rf1);
92137da2899SCharles.Forsyth op2(i, Olfd, Rf2);
92237da2899SCharles.Forsyth ARRR(Ofcmpo, Rcrf0, Rf1, Rf2);
92337da2899SCharles.Forsyth br(op, branch(i));
92437da2899SCharles.Forsyth }
92537da2899SCharles.Forsyth
92637da2899SCharles.Forsyth static void
cbral(Inst * i,int cms,int cls,int mode)92737da2899SCharles.Forsyth cbral(Inst *i, int cms, int cls, int mode)
92837da2899SCharles.Forsyth {
92937da2899SCharles.Forsyth ulong *cp;
93037da2899SCharles.Forsyth
93137da2899SCharles.Forsyth if(RESCHED)
93237da2899SCharles.Forsyth schedcheck(i);
93337da2899SCharles.Forsyth cp = nil;
93437da2899SCharles.Forsyth opwld(i, Olea, Ri);
93537da2899SCharles.Forsyth op2(i, Olea, Rj);
93637da2899SCharles.Forsyth IRR(Olwz, 0,Ri, Ro1);
93737da2899SCharles.Forsyth IRR(Olwz, 0,Rj, Ro2);
93837da2899SCharles.Forsyth ARRR(Ocmp, Rcrf0, Ro1, Ro2);
93937da2899SCharles.Forsyth switch(mode) {
94037da2899SCharles.Forsyth case ANDAND:
94137da2899SCharles.Forsyth cp = code;
94237da2899SCharles.Forsyth br(cms, 0);
94337da2899SCharles.Forsyth break;
94437da2899SCharles.Forsyth case OROR:
94537da2899SCharles.Forsyth br(cms, branch(i));
94637da2899SCharles.Forsyth break;
94737da2899SCharles.Forsyth case EQAND:
94837da2899SCharles.Forsyth br(cms, branch(i));
94937da2899SCharles.Forsyth cp = code;
95037da2899SCharles.Forsyth br(Obne, 0);
95137da2899SCharles.Forsyth break;
95237da2899SCharles.Forsyth }
95337da2899SCharles.Forsyth IRR(Olwz, 4,Ri, Ro1);
95437da2899SCharles.Forsyth IRR(Olwz, 4,Rj, Ro2);
95537da2899SCharles.Forsyth ARRR(Ocmpl, Rcrf0, Ro1, Ro2);
95637da2899SCharles.Forsyth br(cls, branch(i));
95737da2899SCharles.Forsyth if(cp)
95837da2899SCharles.Forsyth PATCH(cp);
95937da2899SCharles.Forsyth }
96037da2899SCharles.Forsyth
96137da2899SCharles.Forsyth static void
shrl(Inst * i)96237da2899SCharles.Forsyth shrl(Inst *i)
96337da2899SCharles.Forsyth {
96437da2899SCharles.Forsyth // int c;
96537da2899SCharles.Forsyth
96637da2899SCharles.Forsyth // if(USRC(i->add) != AIMM) {
96737da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
96837da2899SCharles.Forsyth return;
96937da2899SCharles.Forsyth // }
97037da2899SCharles.Forsyth /*
97137da2899SCharles.Forsyth c = i->s.imm;
97237da2899SCharles.Forsyth op2(i, Olea, Ro3);
97337da2899SCharles.Forsyth IRR(Olwz, 0,Ro3, Ro1);
97437da2899SCharles.Forsyth if(c >= 32) {
97537da2899SCharles.Forsyth if((i->add&ARM) != AXNON)
97637da2899SCharles.Forsyth opwst(i, Olea, Ro3);
97737da2899SCharles.Forsyth SRR(Osra, 31, Ro1, Ro2);
97837da2899SCharles.Forsyth IRR(Ostw, 0,Ro3, Ro2);
97937da2899SCharles.Forsyth if(c >= 64) {
98037da2899SCharles.Forsyth IRR(Ostw, 4,Ro3, Ro2);
98137da2899SCharles.Forsyth return;
98237da2899SCharles.Forsyth }
98337da2899SCharles.Forsyth if(c > 32)
98437da2899SCharles.Forsyth SRR(Osra, c-32, Ro1, Ro1);
98537da2899SCharles.Forsyth IRR(Ostw, 4,Ro3, Ro1);
98637da2899SCharles.Forsyth return;
98737da2899SCharles.Forsyth }
98837da2899SCharles.Forsyth IRR(Olwz, 4,Ro3, Ro2);
98937da2899SCharles.Forsyth if((i->add&ARM) != AXNON)
99037da2899SCharles.Forsyth opwst(i, Olea, Ro3);
99137da2899SCharles.Forsyth if(c != 0) {
99237da2899SCharles.Forsyth SRR(Osll, 32-c, Ro1, Ri);
99337da2899SCharles.Forsyth SRR(Osra, c, Ro1, Ro1);
99437da2899SCharles.Forsyth SRR(Osrl, c, Ro2, Ro2);
99537da2899SCharles.Forsyth RRR(Oor, Ri, Ro2, Ro2);
99637da2899SCharles.Forsyth }
99737da2899SCharles.Forsyth IRR(Ostw, 4,Ro3, Ro2);
99837da2899SCharles.Forsyth IRR(Ostw, 0,Ro3, Ro1);
99937da2899SCharles.Forsyth */
100037da2899SCharles.Forsyth }
100137da2899SCharles.Forsyth
100237da2899SCharles.Forsyth static void
shll(Inst * i)100337da2899SCharles.Forsyth shll(Inst *i)
100437da2899SCharles.Forsyth {
100537da2899SCharles.Forsyth // int c;
100637da2899SCharles.Forsyth
100737da2899SCharles.Forsyth // if(USRC(i->add) != AIMM) {
100837da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
100937da2899SCharles.Forsyth return;
101037da2899SCharles.Forsyth // }
101137da2899SCharles.Forsyth /*
101237da2899SCharles.Forsyth c = i->s.imm;
101337da2899SCharles.Forsyth if(c >= 64) {
101437da2899SCharles.Forsyth opwst(i, Olea, Ro3);
101537da2899SCharles.Forsyth IRR(Ostw, 0,Ro3, Rzero);
101637da2899SCharles.Forsyth IRR(Ostw, 4,Ro3, Rzero);
101737da2899SCharles.Forsyth return;
101837da2899SCharles.Forsyth }
101937da2899SCharles.Forsyth op2(i, Olea, Ro3);
102037da2899SCharles.Forsyth if(c >= 32) {
102137da2899SCharles.Forsyth IRR(Olwz, 4,Ro3, Ro1);
102237da2899SCharles.Forsyth if((i->add&ARM) != AXNON)
102337da2899SCharles.Forsyth opwst(i, Olea, Ro3);
102437da2899SCharles.Forsyth IRR(Ostw, 4,Ro3, Rzero);
102537da2899SCharles.Forsyth if(c > 32)
102637da2899SCharles.Forsyth SRR(Osll, c-32, Ro1, Ro1);
102737da2899SCharles.Forsyth IRR(Ostw, 0,Ro3, Ro1);
102837da2899SCharles.Forsyth return;
102937da2899SCharles.Forsyth }
103037da2899SCharles.Forsyth IRR(Olwz, 4,Ro3, Ro2);
103137da2899SCharles.Forsyth IRR(Olwz, 0,Ro3, Ro1);
103237da2899SCharles.Forsyth if((i->add&ARM) != AXNON)
103337da2899SCharles.Forsyth opwst(i, Olea, Ro3);
103437da2899SCharles.Forsyth if(c != 0) {
103537da2899SCharles.Forsyth SRR(Osrl, 32-c, Ro2, Ri);
103637da2899SCharles.Forsyth SRR(Osll, c, Ro2, Ro2);
103737da2899SCharles.Forsyth SRR(Osll, c, Ro1, Ro1);
103837da2899SCharles.Forsyth RRR(Oor, Ri, Ro1, Ro1);
103937da2899SCharles.Forsyth }
104037da2899SCharles.Forsyth IRR(Ostw, 4,Ro3, Ro2);
104137da2899SCharles.Forsyth IRR(Ostw, 0,Ro3, Ro1);
104237da2899SCharles.Forsyth */
104337da2899SCharles.Forsyth }
104437da2899SCharles.Forsyth
104537da2899SCharles.Forsyth static void
compdbg(void)104637da2899SCharles.Forsyth compdbg(void)
104737da2899SCharles.Forsyth {
104837da2899SCharles.Forsyth print("%s:%lud@%.8lux\n", R.M->m->name, *(ulong*)R.m, *(ulong*)R.s);
104937da2899SCharles.Forsyth }
105037da2899SCharles.Forsyth
105137da2899SCharles.Forsyth static void
comp(Inst * i)105237da2899SCharles.Forsyth comp(Inst *i)
105337da2899SCharles.Forsyth {
105437da2899SCharles.Forsyth int o, q, b;
105537da2899SCharles.Forsyth ulong *cp, *cp1;
105637da2899SCharles.Forsyth char buf[64];
105737da2899SCharles.Forsyth
105837da2899SCharles.Forsyth if(0) {
105937da2899SCharles.Forsyth Inst xx;
106037da2899SCharles.Forsyth xx.add = AXIMM|SRC(AIMM);
106137da2899SCharles.Forsyth xx.s.imm = (ulong)code;
106237da2899SCharles.Forsyth xx.reg = i-mod->prog;
106337da2899SCharles.Forsyth punt(&xx, SRCOP, compdbg);
106437da2899SCharles.Forsyth }
106537da2899SCharles.Forsyth
106637da2899SCharles.Forsyth switch(i->op) {
106737da2899SCharles.Forsyth default:
106837da2899SCharles.Forsyth snprint(buf, sizeof buf, "%s compile, no '%D'", mod->name, i);
106937da2899SCharles.Forsyth error(buf);
107037da2899SCharles.Forsyth break;
107137da2899SCharles.Forsyth case IMCALL:
107237da2899SCharles.Forsyth if((i->add&ARM) == AXIMM)
107337da2899SCharles.Forsyth commcall(i);
107437da2899SCharles.Forsyth else
107537da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|THREOP|WRTPC|NEWPC, optab[i->op]);
107637da2899SCharles.Forsyth break;
107737da2899SCharles.Forsyth case ISEND:
107837da2899SCharles.Forsyth case IRECV:
107937da2899SCharles.Forsyth case IALT:
108037da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|TCHECK|WRTPC, optab[i->op]);
108137da2899SCharles.Forsyth break;
108237da2899SCharles.Forsyth case ISPAWN:
108337da2899SCharles.Forsyth punt(i, SRCOP|DBRAN, optab[i->op]);
108437da2899SCharles.Forsyth break;
108537da2899SCharles.Forsyth case IBNEC:
108637da2899SCharles.Forsyth case IBEQC:
108737da2899SCharles.Forsyth case IBLTC:
108837da2899SCharles.Forsyth case IBLEC:
108937da2899SCharles.Forsyth case IBGTC:
109037da2899SCharles.Forsyth case IBGEC:
109137da2899SCharles.Forsyth punt(i, SRCOP|DBRAN|NEWPC|WRTPC, optab[i->op]);
109237da2899SCharles.Forsyth break;
109337da2899SCharles.Forsyth case ICASEC:
109437da2899SCharles.Forsyth comcase(i, 0);
109537da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|NEWPC, optab[i->op]);
109637da2899SCharles.Forsyth break;
109737da2899SCharles.Forsyth case ICASEL:
109837da2899SCharles.Forsyth comcasel(i);
109937da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|NEWPC, optab[i->op]);
110037da2899SCharles.Forsyth break;
110137da2899SCharles.Forsyth case IADDC:
110237da2899SCharles.Forsyth case IMULL:
110337da2899SCharles.Forsyth case IDIVL:
110437da2899SCharles.Forsyth case IMODL:
110537da2899SCharles.Forsyth case IMNEWZ:
110637da2899SCharles.Forsyth case ILSRW:
110737da2899SCharles.Forsyth case ILSRL:
110837da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
110937da2899SCharles.Forsyth break;
111037da2899SCharles.Forsyth case IMFRAME:
111137da2899SCharles.Forsyth if((i->add&ARM) == AXIMM)
111237da2899SCharles.Forsyth commframe(i);
111337da2899SCharles.Forsyth else
111437da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
111537da2899SCharles.Forsyth break;
111637da2899SCharles.Forsyth case ILOAD:
111737da2899SCharles.Forsyth case INEWA:
111837da2899SCharles.Forsyth case INEWAZ:
111937da2899SCharles.Forsyth case INEW:
112037da2899SCharles.Forsyth case INEWZ:
112137da2899SCharles.Forsyth case ISLICEA:
112237da2899SCharles.Forsyth case ISLICELA:
112337da2899SCharles.Forsyth case ICONSB:
112437da2899SCharles.Forsyth case ICONSW:
112537da2899SCharles.Forsyth case ICONSL:
112637da2899SCharles.Forsyth case ICONSF:
112737da2899SCharles.Forsyth case ICONSM:
112837da2899SCharles.Forsyth case ICONSMP:
112937da2899SCharles.Forsyth case ICONSP:
113037da2899SCharles.Forsyth case IMOVMP:
113137da2899SCharles.Forsyth case IHEADMP:
113237da2899SCharles.Forsyth case IINSC:
113337da2899SCharles.Forsyth case ICVTAC:
113437da2899SCharles.Forsyth case ICVTCW:
113537da2899SCharles.Forsyth case ICVTWC:
113637da2899SCharles.Forsyth case ICVTCL:
113737da2899SCharles.Forsyth case ICVTLC:
113837da2899SCharles.Forsyth case ICVTFC:
113937da2899SCharles.Forsyth case ICVTCF:
114037da2899SCharles.Forsyth case ICVTFL:
114137da2899SCharles.Forsyth case ICVTLF:
114237da2899SCharles.Forsyth case ICVTRF:
114337da2899SCharles.Forsyth case ICVTFR:
114437da2899SCharles.Forsyth case ICVTWS:
114537da2899SCharles.Forsyth case ICVTSW:
114637da2899SCharles.Forsyth case IMSPAWN:
114737da2899SCharles.Forsyth case ICVTCA:
114837da2899SCharles.Forsyth case ISLICEC:
114937da2899SCharles.Forsyth case INBALT:
115037da2899SCharles.Forsyth punt(i, SRCOP|DSTOP, optab[i->op]);
115137da2899SCharles.Forsyth break;
115237da2899SCharles.Forsyth case INEWCM:
115337da2899SCharles.Forsyth case INEWCMP:
115437da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
115537da2899SCharles.Forsyth break;
115637da2899SCharles.Forsyth case INEWCB:
115737da2899SCharles.Forsyth case INEWCW:
115837da2899SCharles.Forsyth case INEWCF:
115937da2899SCharles.Forsyth case INEWCP:
116037da2899SCharles.Forsyth case INEWCL:
116137da2899SCharles.Forsyth punt(i, DSTOP|THREOP, optab[i->op]);
116237da2899SCharles.Forsyth break;
116337da2899SCharles.Forsyth case IEXIT:
116437da2899SCharles.Forsyth punt(i, 0, optab[i->op]);
116537da2899SCharles.Forsyth break;
116637da2899SCharles.Forsyth case ICVTWB:
116737da2899SCharles.Forsyth op13(i, Olwz, Ostb);
116837da2899SCharles.Forsyth break;
116937da2899SCharles.Forsyth case ICVTBW:
117037da2899SCharles.Forsyth op13(i, Olbz, Ostw);
117137da2899SCharles.Forsyth break;
117237da2899SCharles.Forsyth case IMOVB:
117337da2899SCharles.Forsyth if(USRC(i->add) == AIMM && i->s.imm == 0) {
117437da2899SCharles.Forsyth opwst(i, Ostb, Rzero);
117537da2899SCharles.Forsyth break;
117637da2899SCharles.Forsyth }
117737da2899SCharles.Forsyth op13(i, Olbz, Ostb);
117837da2899SCharles.Forsyth break;
117937da2899SCharles.Forsyth case IMOVW:
118037da2899SCharles.Forsyth if(USRC(i->add) == AIMM && i->s.imm == 0) {
118137da2899SCharles.Forsyth opwst(i, Ostw, Rzero);
118237da2899SCharles.Forsyth break;
118337da2899SCharles.Forsyth }
118437da2899SCharles.Forsyth op13(i, Olwz, Ostw);
118537da2899SCharles.Forsyth break;
118637da2899SCharles.Forsyth case ICVTLW:
118737da2899SCharles.Forsyth opwld(i, Olea, Ro1);
118837da2899SCharles.Forsyth AIRR(Olwz, Ro2, Ro1,4);
118937da2899SCharles.Forsyth opwst(i, Ostw, Ro2);
119037da2899SCharles.Forsyth break;
119137da2899SCharles.Forsyth case ICVTWL:
119237da2899SCharles.Forsyth opwld(i, Olwz, Ro1);
119337da2899SCharles.Forsyth opwst(i, Olea, Ro2);
119437da2899SCharles.Forsyth LRRR(Osrawi, Ro3, Ro1, 31);
119537da2899SCharles.Forsyth AIRR(Ostw, Ro1, Ro2,4);
119637da2899SCharles.Forsyth AIRR(Ostw, Ro3, Ro2,0);
119737da2899SCharles.Forsyth break;
119837da2899SCharles.Forsyth case IHEADM:
119937da2899SCharles.Forsyth opwld(i, Olwz, Ro1);
120037da2899SCharles.Forsyth AIRR(Oaddi, Ro1, Ro1,OA(List,data));
120137da2899SCharles.Forsyth movmem(i);
120237da2899SCharles.Forsyth break;
120337da2899SCharles.Forsyth case IMOVM:
120437da2899SCharles.Forsyth opwld(i, Olea, Ro1);
120537da2899SCharles.Forsyth movmem(i);
120637da2899SCharles.Forsyth break;
120737da2899SCharles.Forsyth case IRET:
120837da2899SCharles.Forsyth jmp(base+macro[MacRET]);
120937da2899SCharles.Forsyth break;
121037da2899SCharles.Forsyth case IFRAME:
121137da2899SCharles.Forsyth if(UXSRC(i->add) != SRC(AIMM)) {
121237da2899SCharles.Forsyth punt(i, SRCOP|DSTOP, optab[i->op]);
121337da2899SCharles.Forsyth break;
121437da2899SCharles.Forsyth }
121537da2899SCharles.Forsyth tinit[i->s.imm] = 1;
121637da2899SCharles.Forsyth ldc((ulong)mod->type[i->s.imm], Ri);
121737da2899SCharles.Forsyth jmpl(base+macro[MacFRAM]);
121837da2899SCharles.Forsyth opwst(i, Ostw, Ro1);
121937da2899SCharles.Forsyth break;
122037da2899SCharles.Forsyth case ILEA:
122137da2899SCharles.Forsyth op13(i, Olea, Ostw);
122237da2899SCharles.Forsyth break;
122337da2899SCharles.Forsyth case IHEADW:
122437da2899SCharles.Forsyth opwld(i, Olwz, Ro1);
122537da2899SCharles.Forsyth AIRR(Olwz, Ro1, Ro1,OA(List,data));
122637da2899SCharles.Forsyth opwst(i, Ostw, Ro1);
122737da2899SCharles.Forsyth break;
122837da2899SCharles.Forsyth case IHEADF:
122937da2899SCharles.Forsyth opwld(i, Olwz, Ro1);
123037da2899SCharles.Forsyth AIRR(Olfd, Rf1, Ro1,OA(List,data));
123137da2899SCharles.Forsyth opwst(i, Ostfd, Rf1);
123237da2899SCharles.Forsyth break;
123337da2899SCharles.Forsyth case IHEADB:
123437da2899SCharles.Forsyth opwld(i, Olwz, Ro1);
123537da2899SCharles.Forsyth AIRR(Olbz, Ro1, Ro1,OA(List,data));
123637da2899SCharles.Forsyth opwst(i, Ostb, Ro1);
123737da2899SCharles.Forsyth break;
123837da2899SCharles.Forsyth case ITAIL:
123937da2899SCharles.Forsyth opwld(i, Olwz, Ro1);
124037da2899SCharles.Forsyth AIRR(Olwz, Ro1, Ro1,O(List,tail));
124137da2899SCharles.Forsyth goto movp;
124237da2899SCharles.Forsyth case IMOVP:
124337da2899SCharles.Forsyth opwld(i, Olwz, Ro1);
124437da2899SCharles.Forsyth goto movp;
124537da2899SCharles.Forsyth case IHEADP:
124637da2899SCharles.Forsyth opwld(i, Olwz, Ro1);
124737da2899SCharles.Forsyth AIRR(Olwz, Ro1, Ro1,OA(List,data));
124837da2899SCharles.Forsyth movp:
124937da2899SCharles.Forsyth CMPH(Ro1);
125037da2899SCharles.Forsyth cp = code;
125137da2899SCharles.Forsyth br(Obeq, 0);
125237da2899SCharles.Forsyth jmpl(base+macro[MacCOLR]);
125337da2899SCharles.Forsyth PATCH(cp);
125437da2899SCharles.Forsyth opwst(i, Olea, Ro3);
125537da2899SCharles.Forsyth AIRR(Olwz, Ri, Ro3,0);
125637da2899SCharles.Forsyth AIRR(Ostw, Ro1, Ro3,0);
125737da2899SCharles.Forsyth jmpl(base+macro[MacFRP]);
125837da2899SCharles.Forsyth break;
125937da2899SCharles.Forsyth case ILENA:
126037da2899SCharles.Forsyth opwld(i, Olwz, Ri);
126137da2899SCharles.Forsyth ldc(0, Ro1);
126237da2899SCharles.Forsyth CMPH(Ri);
126337da2899SCharles.Forsyth cp = code;
126437da2899SCharles.Forsyth br(Obeq, 0);
126537da2899SCharles.Forsyth AIRR(Olwz, Ro1, Ri,O(Array,len));
126637da2899SCharles.Forsyth PATCH(cp);
126737da2899SCharles.Forsyth opwst(i, Ostw, Ro1);
126837da2899SCharles.Forsyth break;
126937da2899SCharles.Forsyth case ILENC:
127037da2899SCharles.Forsyth opwld(i, Olwz, Ri);
127137da2899SCharles.Forsyth ldc(0, Ro1);
127237da2899SCharles.Forsyth CMPH(Ri);
127337da2899SCharles.Forsyth cp = code;
127437da2899SCharles.Forsyth br(Obeq, 0);
127537da2899SCharles.Forsyth AIRR(Olwz, Ro1, Ri,O(String,len));
127637da2899SCharles.Forsyth AIRR(Ocmpi, Rcrf0, Ro1, 0);
127737da2899SCharles.Forsyth br(Obge, 2*4); // BGE 2(PC); skip
127837da2899SCharles.Forsyth ARRR(Oneg, Ro1, Ro1, 0);
127937da2899SCharles.Forsyth PATCH(cp);
128037da2899SCharles.Forsyth opwst(i, Ostw, Ro1);
128137da2899SCharles.Forsyth break;
128237da2899SCharles.Forsyth case ILENL:
128337da2899SCharles.Forsyth opwld(i, Olwz, Ro1);
128437da2899SCharles.Forsyth ldc(0, Ro3);
128537da2899SCharles.Forsyth CMPH(Ro1);
128637da2899SCharles.Forsyth cp = code;
128737da2899SCharles.Forsyth br(Obeq, 0);
128837da2899SCharles.Forsyth
128937da2899SCharles.Forsyth cp1 = code;
129037da2899SCharles.Forsyth AIRR(Olwz, Ro1, Ro1,O(List,tail));
129137da2899SCharles.Forsyth AIRR(Oaddi, Ro3, Ro3, 1);
129237da2899SCharles.Forsyth CMPH(Ro1);
129337da2899SCharles.Forsyth br(Obne, ((ulong)cp1-(ulong)code));
129437da2899SCharles.Forsyth
129537da2899SCharles.Forsyth PATCH(cp);
129637da2899SCharles.Forsyth opwst(i, Ostw, Ro3);
129737da2899SCharles.Forsyth break;
129837da2899SCharles.Forsyth case IMOVL:
129937da2899SCharles.Forsyth opwld(i, Olea, Ro1);
130037da2899SCharles.Forsyth AIRR(Olwz, Ro2, Ro1,0);
130137da2899SCharles.Forsyth AIRR(Olwz, Ro3, Ro1,4);
130237da2899SCharles.Forsyth opwst(i, Olea, Ro1);
130337da2899SCharles.Forsyth AIRR(Ostw, Ro2, Ro1,0);
130437da2899SCharles.Forsyth AIRR(Ostw, Ro3, Ro1,4);
130537da2899SCharles.Forsyth break;
130637da2899SCharles.Forsyth case IMOVF:
130737da2899SCharles.Forsyth opwld(i, Olfd, Rf1);
130837da2899SCharles.Forsyth opwst(i, Ostfd, Rf1);
130937da2899SCharles.Forsyth break;
131037da2899SCharles.Forsyth case ICVTFW:
131137da2899SCharles.Forsyth if(!macjit){
131237da2899SCharles.Forsyth opwld(i, Olfd, Rf1);
131337da2899SCharles.Forsyth jmpl(base+macro[MacCVTFW]);
131437da2899SCharles.Forsyth opwst(i, Ostw, Ro1);
131537da2899SCharles.Forsyth break;
131637da2899SCharles.Forsyth }
131737da2899SCharles.Forsyth case ICVTWF:
131837da2899SCharles.Forsyth punt(i, SRCOP|DSTOP, optab[i->op]);
131937da2899SCharles.Forsyth break;
132037da2899SCharles.Forsyth case INEGF:
132137da2899SCharles.Forsyth opwld(i, Olfd, Rf1);
132237da2899SCharles.Forsyth ARRR(Ofneg, Rf2, 0, Rf1);
132337da2899SCharles.Forsyth opwst(i, Ostfd, Rf2);
132437da2899SCharles.Forsyth break;
132537da2899SCharles.Forsyth case IXORL:
132637da2899SCharles.Forsyth case IORL:
132737da2899SCharles.Forsyth case IANDL:
132837da2899SCharles.Forsyth case IADDL:
132937da2899SCharles.Forsyth case ISUBL:
133037da2899SCharles.Forsyth opwld(i, Olea, Ro1);
133137da2899SCharles.Forsyth op2(i, Olea, Ro3);
133237da2899SCharles.Forsyth
133337da2899SCharles.Forsyth AIRR(Olwz, Rj, Ro1,4); /* ls */
133437da2899SCharles.Forsyth AIRR(Olwz, Ro2, Ro3,4);
133537da2899SCharles.Forsyth AIRR(Olwz, Ri, Ro1,0); /* ms */
133637da2899SCharles.Forsyth AIRR(Olwz, Ro1, Ro3,0);
133737da2899SCharles.Forsyth
133837da2899SCharles.Forsyth switch(i->op) {
133937da2899SCharles.Forsyth case IXORL:
134037da2899SCharles.Forsyth o = Oxor;
134137da2899SCharles.Forsyth goto l1;
134237da2899SCharles.Forsyth case IORL:
134337da2899SCharles.Forsyth o = Oor;
134437da2899SCharles.Forsyth goto l1;
134537da2899SCharles.Forsyth case IANDL:
134637da2899SCharles.Forsyth o = Oand;
134737da2899SCharles.Forsyth l1:
134837da2899SCharles.Forsyth LRRR(o, Ro1, Ri, Ro1);
134937da2899SCharles.Forsyth LRRR(o, Ro2, Rj, Ro2);
135037da2899SCharles.Forsyth break;
135137da2899SCharles.Forsyth case IADDL:
135237da2899SCharles.Forsyth RRR(Oaddc, Rj,Ro2, Ro2);
135337da2899SCharles.Forsyth RRR(Oadde, Ri,Ro1, Ro1);
135437da2899SCharles.Forsyth break;
135537da2899SCharles.Forsyth case ISUBL:
135637da2899SCharles.Forsyth RRR(Osubfc, Ro2,Rj, Ro2);
135737da2899SCharles.Forsyth RRR(Osubfe, Ro1,Ri, Ro1);
135837da2899SCharles.Forsyth break;
135937da2899SCharles.Forsyth }
136037da2899SCharles.Forsyth if((i->add&ARM) != AXNON)
136137da2899SCharles.Forsyth opwst(i, Olea, Ro3);
136237da2899SCharles.Forsyth IRR(Ostw, 0,Ro3, Ro1);
136337da2899SCharles.Forsyth IRR(Ostw, 4,Ro3, Ro2);
136437da2899SCharles.Forsyth break;
136537da2899SCharles.Forsyth case ISHLL:
136637da2899SCharles.Forsyth shll(i);
136737da2899SCharles.Forsyth break;
136837da2899SCharles.Forsyth case ISHRL:
136937da2899SCharles.Forsyth shrl(i);
137037da2899SCharles.Forsyth break;
137137da2899SCharles.Forsyth case IADDF: o = Ofadd; goto f1;
137237da2899SCharles.Forsyth case ISUBF: o = Ofsub; goto f1;
137337da2899SCharles.Forsyth case IMULF: o = Ofmul; goto f1;
137437da2899SCharles.Forsyth case IDIVF: o = Ofdiv; goto f1;
137537da2899SCharles.Forsyth f1:
137637da2899SCharles.Forsyth opwld(i, Olfd, Rf1);
137737da2899SCharles.Forsyth op2(i, Olfd, Rf2);
137837da2899SCharles.Forsyth if(o == Ofmul)
137937da2899SCharles.Forsyth gen(o | (Rf2<<21) | (Rf2<<16) | (Rf1<<6)); /* odd one out: op D,A,-,C */
138037da2899SCharles.Forsyth else
138137da2899SCharles.Forsyth ARRR(o, Rf2, Rf2, Rf1);
138237da2899SCharles.Forsyth opwst(i, Ostfd, Rf2);
138337da2899SCharles.Forsyth break;
138437da2899SCharles.Forsyth
138537da2899SCharles.Forsyth case IBEQF:
138637da2899SCharles.Forsyth cbraf(i, Obeq);
138737da2899SCharles.Forsyth break;
138837da2899SCharles.Forsyth case IBGEF:
138937da2899SCharles.Forsyth cbraf(i, Obge);
139037da2899SCharles.Forsyth case IBGTF:
139137da2899SCharles.Forsyth cbraf(i, Obgt);
139237da2899SCharles.Forsyth break;
139337da2899SCharles.Forsyth case IBLEF:
139437da2899SCharles.Forsyth cbraf(i, Oble);
139537da2899SCharles.Forsyth break;
139637da2899SCharles.Forsyth case IBLTF:
139737da2899SCharles.Forsyth cbraf(i, Oblt);
139837da2899SCharles.Forsyth break;
139937da2899SCharles.Forsyth case IBNEF:
140037da2899SCharles.Forsyth cbraf(i, Obne);
140137da2899SCharles.Forsyth break;
140237da2899SCharles.Forsyth
140337da2899SCharles.Forsyth case IBLTB:
140437da2899SCharles.Forsyth cbrab(i, Oblt);
140537da2899SCharles.Forsyth break;
140637da2899SCharles.Forsyth case IBLEB:
140737da2899SCharles.Forsyth cbrab(i, Oble);
140837da2899SCharles.Forsyth break;
140937da2899SCharles.Forsyth case IBGTB:
141037da2899SCharles.Forsyth cbrab(i, Obgt);
141137da2899SCharles.Forsyth break;
141237da2899SCharles.Forsyth case IBGEB:
141337da2899SCharles.Forsyth cbrab(i, Obge);
141437da2899SCharles.Forsyth break;
141537da2899SCharles.Forsyth case IBEQB:
141637da2899SCharles.Forsyth cbrab(i, Obeq);
141737da2899SCharles.Forsyth break;
141837da2899SCharles.Forsyth case IBNEB:
141937da2899SCharles.Forsyth cbrab(i, Obne);
142037da2899SCharles.Forsyth break;
142137da2899SCharles.Forsyth
142237da2899SCharles.Forsyth case IBLTW:
142337da2899SCharles.Forsyth cbra(i, Oblt);
142437da2899SCharles.Forsyth break;
142537da2899SCharles.Forsyth case IBLEW:
142637da2899SCharles.Forsyth cbra(i, Oble);
142737da2899SCharles.Forsyth break;
142837da2899SCharles.Forsyth case IBGTW:
142937da2899SCharles.Forsyth cbra(i, Obgt);
143037da2899SCharles.Forsyth break;
143137da2899SCharles.Forsyth case IBGEW:
143237da2899SCharles.Forsyth cbra(i, Obge);
143337da2899SCharles.Forsyth break;
143437da2899SCharles.Forsyth case IBEQW:
143537da2899SCharles.Forsyth cbra(i, Obeq);
143637da2899SCharles.Forsyth break;
143737da2899SCharles.Forsyth case IBNEW:
143837da2899SCharles.Forsyth cbra(i, Obne);
143937da2899SCharles.Forsyth break;
144037da2899SCharles.Forsyth
144137da2899SCharles.Forsyth case IBEQL:
144237da2899SCharles.Forsyth cbral(i, Obne, Obeq, ANDAND);
144337da2899SCharles.Forsyth break;
144437da2899SCharles.Forsyth case IBNEL:
144537da2899SCharles.Forsyth cbral(i, Obne, Obne, OROR);
144637da2899SCharles.Forsyth break;
144737da2899SCharles.Forsyth case IBLTL:
144837da2899SCharles.Forsyth cbral(i, Oblt, Oblt, EQAND);
144937da2899SCharles.Forsyth break;
145037da2899SCharles.Forsyth case IBLEL:
145137da2899SCharles.Forsyth cbral(i, Oblt, Oble, EQAND);
145237da2899SCharles.Forsyth break;
145337da2899SCharles.Forsyth case IBGTL:
145437da2899SCharles.Forsyth cbral(i, Obgt, Obgt, EQAND);
145537da2899SCharles.Forsyth break;
145637da2899SCharles.Forsyth case IBGEL:
145737da2899SCharles.Forsyth cbral(i, Obgt, Obge, EQAND);
145837da2899SCharles.Forsyth break;
145937da2899SCharles.Forsyth
146037da2899SCharles.Forsyth case ISUBB:
146137da2899SCharles.Forsyth case IADDB:
146237da2899SCharles.Forsyth case IANDB:
146337da2899SCharles.Forsyth case IORB:
146437da2899SCharles.Forsyth case IXORB:
146537da2899SCharles.Forsyth case IMODB:
146637da2899SCharles.Forsyth case IDIVB:
146737da2899SCharles.Forsyth case IMULB:
146837da2899SCharles.Forsyth b = 1;
146937da2899SCharles.Forsyth op12(i, b, b);
147037da2899SCharles.Forsyth goto s2;
147137da2899SCharles.Forsyth case ISHLB:
147237da2899SCharles.Forsyth case ISHRB:
147337da2899SCharles.Forsyth b = 1;
147437da2899SCharles.Forsyth op12(i, 0, b);
147537da2899SCharles.Forsyth goto s2;
147637da2899SCharles.Forsyth case ISUBW:
147737da2899SCharles.Forsyth case IADDW:
147837da2899SCharles.Forsyth case IANDW:
147937da2899SCharles.Forsyth case IORW:
148037da2899SCharles.Forsyth case IXORW:
148137da2899SCharles.Forsyth case ISHLW:
148237da2899SCharles.Forsyth case ISHRW:
148337da2899SCharles.Forsyth case IMODW:
148437da2899SCharles.Forsyth case IDIVW:
148537da2899SCharles.Forsyth case IMULW:
148637da2899SCharles.Forsyth b = 0;
148737da2899SCharles.Forsyth op12(i, b, b);
148837da2899SCharles.Forsyth s2:
148937da2899SCharles.Forsyth q = 0;
149037da2899SCharles.Forsyth switch(i->op) {
149137da2899SCharles.Forsyth case ISUBB:
149237da2899SCharles.Forsyth case ISUBW: o = Osubf; q = Osubfic;
149337da2899SCharles.Forsyth // TO DO: if immediate operand, should use opcode q
149437da2899SCharles.Forsyth USED(q);
149537da2899SCharles.Forsyth ARRR(o, Ro3, Ro1, Ro2);
149637da2899SCharles.Forsyth break;
149737da2899SCharles.Forsyth case IADDB:
149837da2899SCharles.Forsyth case IADDW: o = Oadd; q = Oaddi; goto c1;
149937da2899SCharles.Forsyth case IMULB:
150037da2899SCharles.Forsyth case IMULW: o = Omullw; q = Omulli; goto c1;
150137da2899SCharles.Forsyth case IDIVB:
150237da2899SCharles.Forsyth case IDIVW: o = Odivw; goto c1;
150337da2899SCharles.Forsyth c1:
150437da2899SCharles.Forsyth // TO DO: if immediate operand, should use opcode q
150537da2899SCharles.Forsyth USED(q);
150637da2899SCharles.Forsyth ARRR(o, Ro3, Ro2, Ro1);
150737da2899SCharles.Forsyth break;
150837da2899SCharles.Forsyth case IANDB:
150937da2899SCharles.Forsyth case IANDW: o = Oand; goto c2;
151037da2899SCharles.Forsyth case IORB:
151137da2899SCharles.Forsyth case IORW: o = Oor; goto c2;
151237da2899SCharles.Forsyth case IXORB:
151337da2899SCharles.Forsyth case IXORW: o = Oxor; goto c2;
151437da2899SCharles.Forsyth case ISHLB:
151537da2899SCharles.Forsyth case ISHLW: o = Oslw; goto c2;
151637da2899SCharles.Forsyth case ISHRB:
151737da2899SCharles.Forsyth case ISHRW: o = Osraw; goto c2;
151837da2899SCharles.Forsyth c2:
151937da2899SCharles.Forsyth LRRR(o, Ro3,Ro2,Ro1);
152037da2899SCharles.Forsyth break;
152137da2899SCharles.Forsyth case IMODB:
152237da2899SCharles.Forsyth case IMODW:
152337da2899SCharles.Forsyth ARRR(Odivw, Ro3, Ro2, Ro1);
152437da2899SCharles.Forsyth ARRR(Omullw, Ro3, Ro3, Ro1);
152537da2899SCharles.Forsyth ARRR(Osubf, Ro3, Ro3, Ro2);
152637da2899SCharles.Forsyth break;
152737da2899SCharles.Forsyth }
152837da2899SCharles.Forsyth opwst(i, b? Ostb: Ostw, Ro3);
152937da2899SCharles.Forsyth break;
153037da2899SCharles.Forsyth case ICALL:
153137da2899SCharles.Forsyth opwld(i, Olwz, Ro1); /* f = T(s) */
153237da2899SCharles.Forsyth ldbigc((ulong)(base+patch[i-mod->prog+1]), Ro2); /* R.pc */
153337da2899SCharles.Forsyth AIRR(Ostw, Rfp, Ro1,O(Frame,fp)); /* f->fp = R.fp */
153437da2899SCharles.Forsyth AIRR(Ostw, Ro2, Ro1,O(Frame,lr)); /* f->lr = R.pc */
153537da2899SCharles.Forsyth AIRR(Oaddi, Rfp, Ro1, 0); /* R.fp = (uchar*)f */
153637da2899SCharles.Forsyth jmp(base+patch[i->d.ins - mod->prog]);
153737da2899SCharles.Forsyth break;
153837da2899SCharles.Forsyth case IJMP:
153937da2899SCharles.Forsyth if(RESCHED)
154037da2899SCharles.Forsyth schedcheck(i);
154137da2899SCharles.Forsyth jmp(base+patch[i->d.ins - mod->prog]);
154237da2899SCharles.Forsyth break;
154337da2899SCharles.Forsyth case IGOTO:
154437da2899SCharles.Forsyth comgoto(i);
154537da2899SCharles.Forsyth break;
154637da2899SCharles.Forsyth case IINDC:
154737da2899SCharles.Forsyth opwld(i, Olwz, Ro1); // Ro1 = string
154837da2899SCharles.Forsyth if((i->add&ARM) != AXIMM)
154937da2899SCharles.Forsyth op2(i, Olwz, Ro2); // Ro2 = i
155037da2899SCharles.Forsyth AIRR(Olwz, Ri, Ro1,O(String,len)); // len<0 => index Runes, otherwise bytes
155137da2899SCharles.Forsyth AIRR(Oaddi, Ro1, Ro1,O(String,data));
155237da2899SCharles.Forsyth AIRR(Ocmpi, Rcrf0, Ri, 0);
155337da2899SCharles.Forsyth if(bflag){
155437da2899SCharles.Forsyth br(Obge, 2*4);
155537da2899SCharles.Forsyth ARRR(Oneg, Ri, Ri, 0);
155637da2899SCharles.Forsyth if((i->add&ARM) != AXIMM)
155737da2899SCharles.Forsyth ARRR(Ocmpl, Rcrf1, Ri, Ro2); /* CMPU len, i */
155837da2899SCharles.Forsyth else
155937da2899SCharles.Forsyth AIRR(Ocmpli, Rcrf1, Ri, i->reg); /* CMPU len, i */
156037da2899SCharles.Forsyth jmpc(Cle1, (ulong*)bounds);
156137da2899SCharles.Forsyth }
156237da2899SCharles.Forsyth cp = code;
156337da2899SCharles.Forsyth br(Obge, 0);
156437da2899SCharles.Forsyth if((i->add&ARM) != AXIMM){
15654a425662SCharles Forsyth SLWI(Ro2, Ro2, Lg2Rune);
15664a425662SCharles Forsyth if(sizeof(Rune) == 4)
15674a425662SCharles Forsyth ARRR(Olwz, Ro3, Ro1, Ro2);
15684a425662SCharles Forsyth else
156937da2899SCharles.Forsyth ARRR(Olhzx, Ro3, Ro1, Ro2);
157037da2899SCharles.Forsyth } else
1571e3e75046SCharles Forsyth mem(Olwz, (short)i->reg<<Lg2Rune, Ro1, Ro3); /* BUG: TO DO: 16-bit signed displacement */
157237da2899SCharles.Forsyth gen(Ob | (2*4)); // skip
157337da2899SCharles.Forsyth PATCH(cp);
157437da2899SCharles.Forsyth if((i->add&ARM) != AXIMM)
157537da2899SCharles.Forsyth ARRR(Olbzx, Ro3, Ro1, Ro2);
157637da2899SCharles.Forsyth else
157737da2899SCharles.Forsyth AIRR(Olbz, Ro3, Ro1,i->reg);
157837da2899SCharles.Forsyth opwst(i, Ostw, Ro3);
157937da2899SCharles.Forsyth break;
158037da2899SCharles.Forsyth case IINDX:
158137da2899SCharles.Forsyth case IINDB:
158237da2899SCharles.Forsyth case IINDF:
158337da2899SCharles.Forsyth case IINDW:
158437da2899SCharles.Forsyth case IINDL:
158537da2899SCharles.Forsyth opwld(i, Olwz, Ro1); /* Ro1 = a */
158637da2899SCharles.Forsyth opwst(i, Olwz, Ro3); /* Ro3 = i */
158737da2899SCharles.Forsyth if(bflag){
158837da2899SCharles.Forsyth AIRR(Olwz, Ro2, Ro1, O(Array, len)); /* Ro2 = a->len */
158937da2899SCharles.Forsyth ARRR(Ocmpl, Rcrf0, Ro3, Ro2); /* CMPU i, len */
159037da2899SCharles.Forsyth jmpc(Cge, (ulong*)bounds);
159137da2899SCharles.Forsyth }
159237da2899SCharles.Forsyth // TO DO: check a != H
159337da2899SCharles.Forsyth AIRR(Olwz, Ro2, Ro1,O(Array,data)); /* Ro2 = a->data */
159437da2899SCharles.Forsyth switch(i->op) {
159537da2899SCharles.Forsyth case IINDX:
159637da2899SCharles.Forsyth AIRR(Olwz, Ri, Ro1,O(Array,t)); // Ri = a->t
159737da2899SCharles.Forsyth AIRR(Olwz, Ro1, Ri,O(Type,size)); // Ro1 = a->t->size
159837da2899SCharles.Forsyth ARRR(Omullw, Ro3, Ro3, Ro1); // Ro3 = i*size
159937da2899SCharles.Forsyth break;
160037da2899SCharles.Forsyth case IINDL:
160137da2899SCharles.Forsyth case IINDF:
160237da2899SCharles.Forsyth SLWI(Ro3, Ro3, 3); /* Ro3 = i*8 */
160337da2899SCharles.Forsyth break;
160437da2899SCharles.Forsyth case IINDW:
160537da2899SCharles.Forsyth SLWI(Ro3, Ro3, 2); /* Ro3 = i*4 */
160637da2899SCharles.Forsyth break;
160737da2899SCharles.Forsyth case IINDB:
160837da2899SCharles.Forsyth /* no further work */
160937da2899SCharles.Forsyth break;
161037da2899SCharles.Forsyth }
161137da2899SCharles.Forsyth ARRR(Oadd, Ro2, Ro2, Ro3); /* Ro2 = i*size + data */
161237da2899SCharles.Forsyth op2(i, Ostw, Ro2);
161337da2899SCharles.Forsyth break;
161437da2899SCharles.Forsyth case ICASE:
161537da2899SCharles.Forsyth comcase(i, 1);
161637da2899SCharles.Forsyth break;
161737da2899SCharles.Forsyth case IRAISE:
161837da2899SCharles.Forsyth punt(i, SRCOP|WRTPC|NEWPC, optab[i->op]);
161937da2899SCharles.Forsyth break;
162037da2899SCharles.Forsyth case IMULX:
162137da2899SCharles.Forsyth case IDIVX:
162237da2899SCharles.Forsyth case ICVTXX:
162337da2899SCharles.Forsyth case IMULX0:
162437da2899SCharles.Forsyth case IDIVX0:
162537da2899SCharles.Forsyth case ICVTXX0:
162637da2899SCharles.Forsyth case IMULX1:
162737da2899SCharles.Forsyth case IDIVX1:
162837da2899SCharles.Forsyth case ICVTXX1:
162937da2899SCharles.Forsyth case ICVTFX:
163037da2899SCharles.Forsyth case ICVTXF:
163137da2899SCharles.Forsyth case IEXPW:
163237da2899SCharles.Forsyth case IEXPL:
163337da2899SCharles.Forsyth case IEXPF:
163437da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
163537da2899SCharles.Forsyth break;
163637da2899SCharles.Forsyth case ISELF:
163737da2899SCharles.Forsyth punt(i, DSTOP, optab[i->op]);
163837da2899SCharles.Forsyth break;
163937da2899SCharles.Forsyth }
164037da2899SCharles.Forsyth }
164137da2899SCharles.Forsyth
164237da2899SCharles.Forsyth enum {
1643*af364d92SValery Ushakov PREFLEN = 64, /* max instruction words in comvec */
164437da2899SCharles.Forsyth };
164537da2899SCharles.Forsyth
164637da2899SCharles.Forsyth static void
preamble(void)164737da2899SCharles.Forsyth preamble(void)
164837da2899SCharles.Forsyth {
164937da2899SCharles.Forsyth ulong *s;
165037da2899SCharles.Forsyth
165137da2899SCharles.Forsyth if(comvec != nil)
165237da2899SCharles.Forsyth return;
165337da2899SCharles.Forsyth s = code = malloc(PREFLEN*sizeof(*code));
165437da2899SCharles.Forsyth if(s == nil)
165537da2899SCharles.Forsyth error(exNomem);
1656*af364d92SValery Ushakov
1657*af364d92SValery Ushakov #ifdef __ELF__
1658*af364d92SValery Ushakov if(macjit) {
1659*af364d92SValery Ushakov ulong *cp;
1660*af364d92SValery Ushakov int r;
1661*af364d92SValery Ushakov
1662*af364d92SValery Ushakov /*
1663*af364d92SValery Ushakov * ELF frame:
1664*af364d92SValery Ushakov * 0(%sp) - back chain
1665*af364d92SValery Ushakov * 4(%sp) - callee's LR save slot
1666*af364d92SValery Ushakov * 8(%sp) to 36(%sp) - 8 words of parameter list area
1667*af364d92SValery Ushakov * 40(%sp) to 48(%sp) - pad to 16 byte alignment/local vars
1668*af364d92SValery Ushakov */
1669*af364d92SValery Ushakov mfspr(Ro1, Rlr);
1670*af364d92SValery Ushakov AIRR(Ostw, Ro1, Rsp,4);
1671*af364d92SValery Ushakov AIRR(Ostwu, Rsp, Rsp,-128);
1672*af364d92SValery Ushakov
1673*af364d92SValery Ushakov MFCR(Ro1);
1674*af364d92SValery Ushakov AIRR(Ostw, Ro1, Rsp,52);
1675*af364d92SValery Ushakov for (r = 14; r < 32; ++r)
1676*af364d92SValery Ushakov AIRR(Ostw, r, Rsp,r*4);
1677*af364d92SValery Ushakov
1678*af364d92SValery Ushakov cp = code;
1679*af364d92SValery Ushakov gen(Ob | Lk);
1680*af364d92SValery Ushakov
1681*af364d92SValery Ushakov AIRR(Olwz, Ro1, Rsp,52);
1682*af364d92SValery Ushakov MTCR(Ro1);
1683*af364d92SValery Ushakov for (r = 14; r < 32; ++r)
1684*af364d92SValery Ushakov AIRR(Olwz, r, Rsp,r*4);
1685*af364d92SValery Ushakov AIRR(Oaddi, Rsp, Rsp, 128);
1686*af364d92SValery Ushakov
1687*af364d92SValery Ushakov AIRR(Olwz, Ro1, Rsp,4);
1688*af364d92SValery Ushakov mtspr(Rlr, Ro1);
1689*af364d92SValery Ushakov LRET();
1690*af364d92SValery Ushakov
1691*af364d92SValery Ushakov PATCH(cp);
1692*af364d92SValery Ushakov }
1693*af364d92SValery Ushakov #endif /* __ELF__ */
1694*af364d92SValery Ushakov
169537da2899SCharles.Forsyth ldc((ulong)&R, Rreg);
169637da2899SCharles.Forsyth SETR0();
169737da2899SCharles.Forsyth mfspr(Rlink, Rlr);
169837da2899SCharles.Forsyth AIRR(Ostw, Rlink, Rreg,O(REG,xpc));
169937da2899SCharles.Forsyth AIRR(Olwz, Ri, Rreg,O(REG,PC));
170037da2899SCharles.Forsyth mtspr(Rctr, Ri);
170137da2899SCharles.Forsyth AIRR(Olwz, Rfp, Rreg,O(REG,FP));
170237da2899SCharles.Forsyth AIRR(Olwz, Rmp, Rreg,O(REG,MP));
170337da2899SCharles.Forsyth gen(Obctr);
170437da2899SCharles.Forsyth if(code >= (ulong*)(s + PREFLEN))
170537da2899SCharles.Forsyth urk("preamble");
170637da2899SCharles.Forsyth comvec = (void*)s;
170737da2899SCharles.Forsyth segflush(s, PREFLEN*sizeof(*s));
170837da2899SCharles.Forsyth if(cflag > 3) {
170937da2899SCharles.Forsyth print("comvec\n");
171037da2899SCharles.Forsyth while(s < code)
171137da2899SCharles.Forsyth s += das(s);
171237da2899SCharles.Forsyth }
171337da2899SCharles.Forsyth }
171437da2899SCharles.Forsyth
171537da2899SCharles.Forsyth static void
macfrp(void)171637da2899SCharles.Forsyth macfrp(void)
171737da2899SCharles.Forsyth {
171837da2899SCharles.Forsyth CMPH(Ri);
171937da2899SCharles.Forsyth gen(Obclr | Ceq); // arg == $H? => return
172037da2899SCharles.Forsyth
172137da2899SCharles.Forsyth AIRR(Olwz, Ro2, Ri,O(Heap,ref)-sizeof(Heap));
172237da2899SCharles.Forsyth AIRR(Oaddic_, Rj, Ro2, -1); // ref(arg)-- and test
172337da2899SCharles.Forsyth AIRR(Ostw, Rj, Ri,O(Heap,ref)-sizeof(Heap));
172437da2899SCharles.Forsyth gen(Obclr | Cne); // ref(arg) nonzero? => return
172537da2899SCharles.Forsyth
172637da2899SCharles.Forsyth AIRR(Ostw, Ro2, Ri,O(Heap,ref)-sizeof(Heap)); // restore ref count of 1 for destroy
172737da2899SCharles.Forsyth mfspr(Rlink, Rlr);
172837da2899SCharles.Forsyth AIRR(Ostw, Rlink, Rreg,O(REG,st));
172937da2899SCharles.Forsyth AIRR(Ostw, Rfp, Rreg,O(REG,FP));
173037da2899SCharles.Forsyth AIRR(Ostw, Ri, Rreg,O(REG,s));
173137da2899SCharles.Forsyth
173237da2899SCharles.Forsyth jmpl((ulong*)rdestroy); // CALL destroy
173337da2899SCharles.Forsyth
173437da2899SCharles.Forsyth ldc((ulong)&R, Rreg);
173537da2899SCharles.Forsyth SETR0();
173637da2899SCharles.Forsyth AIRR(Olwz, Rlink, Rreg,O(REG,st));
173737da2899SCharles.Forsyth mtspr(Rlr, Rlink);
173837da2899SCharles.Forsyth AIRR(Olwz, Rfp, Rreg,O(REG,FP));
173937da2899SCharles.Forsyth AIRR(Olwz, Rmp, Rreg,O(REG,MP));
174037da2899SCharles.Forsyth LRET();
174137da2899SCharles.Forsyth }
174237da2899SCharles.Forsyth
174337da2899SCharles.Forsyth static void
macret(void)174437da2899SCharles.Forsyth macret(void)
174537da2899SCharles.Forsyth {
174637da2899SCharles.Forsyth ulong *cp1, *cp2, *cp3, *cp4, *cp5, *linterp;
174737da2899SCharles.Forsyth Inst i;
174837da2899SCharles.Forsyth
174937da2899SCharles.Forsyth AIRR(Olwz, Ro1, Rfp,O(Frame,t));
175037da2899SCharles.Forsyth AIRR(Ocmpi, Rcrf0, Ro1, 0);
175137da2899SCharles.Forsyth cp1 = code;
175237da2899SCharles.Forsyth br(Obeq, 0); // t(Rfp) == 0
175337da2899SCharles.Forsyth
175437da2899SCharles.Forsyth AIRR(Olwz, Rpic, Ro1,O(Type,destroy));
175537da2899SCharles.Forsyth AIRR(Ocmpi, Rcrf0, Rpic, 0);
175637da2899SCharles.Forsyth cp2 = code;
175737da2899SCharles.Forsyth br(Obeq, 0); // destroy(t(fp)) == 0
175837da2899SCharles.Forsyth
175937da2899SCharles.Forsyth AIRR(Olwz, Ro2, Rfp,O(Frame,fp));
176037da2899SCharles.Forsyth AIRR(Ocmpi, Rcrf0, Ro2, 0);
176137da2899SCharles.Forsyth cp3 = code;
176237da2899SCharles.Forsyth br(Obeq, 0); // fp(Rfp) == 0
176337da2899SCharles.Forsyth
176437da2899SCharles.Forsyth AIRR(Olwz, Ro3, Rfp,O(Frame,mr));
176537da2899SCharles.Forsyth AIRR(Ocmpi, Rcrf0, Ro3, 0);
176637da2899SCharles.Forsyth cp4 = code;
176737da2899SCharles.Forsyth br(Obeq, 0); // mr(Rfp) == 0
176837da2899SCharles.Forsyth
176937da2899SCharles.Forsyth AIRR(Olwz, Ro2, Rreg,O(REG,M));
177037da2899SCharles.Forsyth AIRR(Olwz, Ro3, Ro2,O(Heap,ref)-sizeof(Heap));
177137da2899SCharles.Forsyth AIRR(Oaddic_, Ro3, Ro3, -1); // --ref(arg), set cc
177237da2899SCharles.Forsyth cp5 = code;
177337da2899SCharles.Forsyth br(Obeq, 0); // --ref(arg) == 0?
177437da2899SCharles.Forsyth AIRR(Ostw, Ro3, Ro2,O(Heap,ref)-sizeof(Heap));
177537da2899SCharles.Forsyth
177637da2899SCharles.Forsyth AIRR(Olwz, Ro1, Rfp,O(Frame,mr));
177737da2899SCharles.Forsyth AIRR(Ostw, Ro1, Rreg,O(REG,M));
177837da2899SCharles.Forsyth AIRR(Olwz, Rmp, Ro1,O(Modlink,MP));
177937da2899SCharles.Forsyth AIRR(Ostw, Rmp, Rreg,O(REG,MP));
178037da2899SCharles.Forsyth AIRR(Olwz, Ro3, Ro1,O(Modlink,compiled)); // R.M->compiled?
178137da2899SCharles.Forsyth AIRR(Ocmpi, Rcrf0, Ro3, 0);
178237da2899SCharles.Forsyth linterp = code;
178337da2899SCharles.Forsyth br(Obeq, 0);
178437da2899SCharles.Forsyth
178537da2899SCharles.Forsyth PATCH(cp4);
178637da2899SCharles.Forsyth jrl(Rpic); // call destroy(t(fp))
178737da2899SCharles.Forsyth AIRR(Ostw, Rfp, Rreg,O(REG,SP));
178837da2899SCharles.Forsyth AIRR(Olwz, Ro1, Rfp,O(Frame,lr));
178937da2899SCharles.Forsyth AIRR(Olwz, Rfp, Rfp,O(Frame,fp));
179037da2899SCharles.Forsyth AIRR(Ostw, Rfp, Rreg,O(REG,FP)); // R.FP = Rfp
179137da2899SCharles.Forsyth jr(Ro1); // goto lr(Rfp)
179237da2899SCharles.Forsyth
179337da2899SCharles.Forsyth PATCH(linterp);
179437da2899SCharles.Forsyth jrl(Rpic); // call destroy(t(fp))
179537da2899SCharles.Forsyth AIRR(Ostw, Rfp, Rreg,O(REG,SP));
179637da2899SCharles.Forsyth AIRR(Olwz, Ro1, Rfp,O(Frame,lr));
179737da2899SCharles.Forsyth AIRR(Olwz, Rfp, Rfp,O(Frame,fp));
179837da2899SCharles.Forsyth AIRR(Ostw, Ro1, Rreg,O(REG,PC)); // R.PC = fp->lr
179937da2899SCharles.Forsyth AIRR(Ostw, Rfp, Rreg,O(REG,FP)); // R.FP = Rfp
180037da2899SCharles.Forsyth AIRR(Olwz, Rpic, Rreg,O(REG,xpc));
180137da2899SCharles.Forsyth mtspr(Rlr, Rpic);
180237da2899SCharles.Forsyth gen(Oblr); // return to xec uncompiled code
180337da2899SCharles.Forsyth
180437da2899SCharles.Forsyth PATCH(cp1);
180537da2899SCharles.Forsyth PATCH(cp2);
180637da2899SCharles.Forsyth PATCH(cp3);
180737da2899SCharles.Forsyth PATCH(cp5);
180837da2899SCharles.Forsyth i.add = AXNON;
180937da2899SCharles.Forsyth punt(&i, TCHECK|NEWPC, optab[IRET]);
181037da2899SCharles.Forsyth }
181137da2899SCharles.Forsyth
181237da2899SCharles.Forsyth static void
maccase(void)181337da2899SCharles.Forsyth maccase(void)
181437da2899SCharles.Forsyth {
181537da2899SCharles.Forsyth ulong *cp1, *cp2, *cp3, *loop;
181637da2899SCharles.Forsyth
181737da2899SCharles.Forsyth /*
181837da2899SCharles.Forsyth * Ro1 = value (input arg), t
181937da2899SCharles.Forsyth * Ro2 = count, n
182037da2899SCharles.Forsyth * Ro3 = table pointer (input arg)
182137da2899SCharles.Forsyth * Ri = n/2, n2
182237da2899SCharles.Forsyth * Rj = pivot element t+n/2*3, l
182337da2899SCharles.Forsyth */
182437da2899SCharles.Forsyth
182537da2899SCharles.Forsyth IRR(Olwz, 0,Ro3, Ro2); // count
182637da2899SCharles.Forsyth IRR(Oaddi, 0,Ro3, Rlink); // initial table pointer
182737da2899SCharles.Forsyth
182837da2899SCharles.Forsyth loop = code; // loop:
182937da2899SCharles.Forsyth AIRR(Ocmpi, Rcrf0, Ro2, 0);
183037da2899SCharles.Forsyth cp1 = code;
183137da2899SCharles.Forsyth br(Oble, 0); // n <= 0? goto out
183237da2899SCharles.Forsyth LRRR(Osrawi, Ri, Ro2, 1); // n2 = n>>1
183337da2899SCharles.Forsyth SLWI(Rj, Ri, 1);
183437da2899SCharles.Forsyth ARRR(Oadd, Rj, Rj, Ri);
183537da2899SCharles.Forsyth SLWI(Rj, Rj, 2);
183637da2899SCharles.Forsyth ARRR(Oadd, Rj, Rj, Ro3); // l = t + n2*3;
183737da2899SCharles.Forsyth AIRR(Olwz, Rpic, Rj,4);
183837da2899SCharles.Forsyth ARRR(Ocmp, Rcrf0, Ro1, Rpic);
183937da2899SCharles.Forsyth cp2 = code;
184037da2899SCharles.Forsyth br(Oblt, 0); // v < l[1]? goto low
184137da2899SCharles.Forsyth
184237da2899SCharles.Forsyth IRR(Olwz, 8,Rj, Rpic);
184337da2899SCharles.Forsyth ARRR(Ocmp, Rcrf0, Ro1, Rpic);
184437da2899SCharles.Forsyth cp3 = code;
184537da2899SCharles.Forsyth br(Obge, 0); // v >= l[2]? goto high
184637da2899SCharles.Forsyth
184737da2899SCharles.Forsyth IRR(Olwz, 12,Rj, Ro3); // found
184837da2899SCharles.Forsyth jr(Ro3);
184937da2899SCharles.Forsyth
185037da2899SCharles.Forsyth PATCH(cp2); // low:
185137da2899SCharles.Forsyth IRR(Oaddi, 0, Ri, Ro2); // n = n2
185237da2899SCharles.Forsyth jmp(loop);
185337da2899SCharles.Forsyth
185437da2899SCharles.Forsyth PATCH(cp3); // high:
185537da2899SCharles.Forsyth IRR(Oaddi, 12, Rj, Ro3); // t = l+3;
185637da2899SCharles.Forsyth IRR(Oaddi, 1, Ri, Rpic);
185737da2899SCharles.Forsyth RRR(Osubf, Ro2, Rpic, Ro2); // n -= n2 + 1
185837da2899SCharles.Forsyth jmp(loop);
185937da2899SCharles.Forsyth
186037da2899SCharles.Forsyth PATCH(cp1); // out:
186137da2899SCharles.Forsyth IRR(Olwz, 0,Rlink, Ro2); // initial n
186237da2899SCharles.Forsyth SLWI(Ro3, Ro2, 1);
186337da2899SCharles.Forsyth RRR(Oadd, Ro3, Ro2, Ro2);
186437da2899SCharles.Forsyth SLWI(Ro2, Ro2, 2);
186537da2899SCharles.Forsyth RRR(Oadd, Ro2, Rlink, Rlink);
186637da2899SCharles.Forsyth IRR(Olwz, 4,Rlink, Ro3); // (initial t)[n*3+1]
186737da2899SCharles.Forsyth jr(Ro3);
186837da2899SCharles.Forsyth }
186937da2899SCharles.Forsyth
187037da2899SCharles.Forsyth static void
macmcal(void)187137da2899SCharles.Forsyth macmcal(void)
187237da2899SCharles.Forsyth {
187337da2899SCharles.Forsyth ulong *cp;
187437da2899SCharles.Forsyth
187537da2899SCharles.Forsyth AIRR(Olwz, Ro2, Ri,O(Modlink,prog));
187637da2899SCharles.Forsyth mfspr(Rlink, Rlr);
187737da2899SCharles.Forsyth AIRR(Ostw, Rlink, Ro1,O(Frame,lr)); // f->lr = return
187837da2899SCharles.Forsyth AIRR(Ocmpi, Rcrf0, Ro2, 0);
187937da2899SCharles.Forsyth AIRR(Oaddi, Rfp, Ro1, 0); // R.FP = f
188037da2899SCharles.Forsyth cp = code;
188137da2899SCharles.Forsyth br(Obne, 0); // CMPL ml->m->prog != 0
188237da2899SCharles.Forsyth
188337da2899SCharles.Forsyth AIRR(Ostw, Rlink, Rreg,O(REG,st));
188437da2899SCharles.Forsyth AIRR(Ostw, Ro1, Rreg,O(REG,FP));
188537da2899SCharles.Forsyth AIRR(Ostw, Rj, Rreg,O(REG,dt));
188637da2899SCharles.Forsyth jmpl((ulong*)rmcall); // CALL rmcall
188737da2899SCharles.Forsyth ldc((ulong)&R, Rreg);
188837da2899SCharles.Forsyth SETR0();
188937da2899SCharles.Forsyth AIRR(Olwz, Rlink, Rreg,O(REG,st));
189037da2899SCharles.Forsyth mtspr(Rlr, Rlink);
189137da2899SCharles.Forsyth AIRR(Olwz, Rfp, Rreg,O(REG,FP));
189237da2899SCharles.Forsyth AIRR(Olwz, Rmp, Rreg,O(REG,MP));
189337da2899SCharles.Forsyth gen(Oblr); // RET
189437da2899SCharles.Forsyth
189537da2899SCharles.Forsyth PATCH(cp);
189637da2899SCharles.Forsyth AIRR(Olwz, Ro2, Ri,O(Heap,ref)-sizeof(Heap));
189737da2899SCharles.Forsyth AIRR(Ostw, Ri, Rreg,O(REG,M));
189837da2899SCharles.Forsyth AIRR(Oaddi, Ro2, Ro2, 1);
189937da2899SCharles.Forsyth AIRR(Olwz, Rmp, Ri,O(Modlink,MP));
190037da2899SCharles.Forsyth AIRR(Ostw, Ro2, Ri,O(Heap,ref)-sizeof(Heap));
190137da2899SCharles.Forsyth AIRR(Ostw, Rmp, Rreg,O(REG,MP));
190237da2899SCharles.Forsyth AIRR(Olwz, Ro2, Ri,O(Modlink,compiled));
190337da2899SCharles.Forsyth AIRR(Ocmpi, Rcrf0, Ro2, 0);
190437da2899SCharles.Forsyth mtspr(Rctr, Rj);
190537da2899SCharles.Forsyth gen(Obcctr | Cne); // return to compiled code
190637da2899SCharles.Forsyth
190737da2899SCharles.Forsyth AIRR(Ostw, Rfp, Rreg,O(REG,FP)); // R.FP = Rfp
190837da2899SCharles.Forsyth AIRR(Ostw, Rj, Rreg,O(REG,PC)); // R.PC = Rj
190937da2899SCharles.Forsyth AIRR(Olwz, Rpic, Rreg,O(REG,xpc));
191037da2899SCharles.Forsyth mtspr(Rlr, Rpic);
191137da2899SCharles.Forsyth gen(Oblr); // return to xec uncompiled code
191237da2899SCharles.Forsyth }
191337da2899SCharles.Forsyth
191437da2899SCharles.Forsyth static void
macmfra(void)191537da2899SCharles.Forsyth macmfra(void)
191637da2899SCharles.Forsyth {
191737da2899SCharles.Forsyth mfspr(Rlink, Rlr);
191837da2899SCharles.Forsyth AIRR(Ostw, Rlink, Rreg,O(REG,st));
191937da2899SCharles.Forsyth AIRR(Ostw, Rfp, Rreg,O(REG,FP));
192037da2899SCharles.Forsyth AIRR(Ostw, Ri, Rreg,O(REG,s));
192137da2899SCharles.Forsyth AIRR(Ostw, Rj, Rreg,O(REG,d));
192237da2899SCharles.Forsyth jmpl((ulong*)rmfram);
192337da2899SCharles.Forsyth ldc((ulong)&R, Rreg);
192437da2899SCharles.Forsyth SETR0();
192537da2899SCharles.Forsyth AIRR(Olwz, Rlink, Rreg,O(REG,st));
192637da2899SCharles.Forsyth mtspr(Rlr, Rlink);
192737da2899SCharles.Forsyth AIRR(Olwz, Rfp, Rreg,O(REG,FP));
192837da2899SCharles.Forsyth AIRR(Olwz, Rmp, Rreg,O(REG,MP));
192937da2899SCharles.Forsyth gen(Oblr);
193037da2899SCharles.Forsyth }
193137da2899SCharles.Forsyth
193237da2899SCharles.Forsyth static void
macfram(void)193337da2899SCharles.Forsyth macfram(void)
193437da2899SCharles.Forsyth {
193537da2899SCharles.Forsyth ulong *cp;
193637da2899SCharles.Forsyth
193737da2899SCharles.Forsyth /*
193837da2899SCharles.Forsyth * Ri has t
193937da2899SCharles.Forsyth */
194037da2899SCharles.Forsyth AIRR(Olwz, Ro2, Ri,O(Type,size)); // MOVW t->size, Ro3
194137da2899SCharles.Forsyth AIRR(Olwz, Ro1, Rreg,O(REG,SP)); // MOVW R.SP, Ro1 (=(Frame*)R.SP)
194237da2899SCharles.Forsyth AIRR(Olwz, Ro3, Rreg,O(REG,TS)); // MOVW R.TS, tmp
194337da2899SCharles.Forsyth ARRR(Oadd, Ro2, Ro2, Ro1); // ADD Ro1, t->size, nsp
194437da2899SCharles.Forsyth ARRR(Ocmpl, Rcrf0, Ro2, Ro3); // CMPU nsp,tmp (nsp >= R.TS?)
194537da2899SCharles.Forsyth cp = code;
194637da2899SCharles.Forsyth br(Obge, 0); // BGE expand
194737da2899SCharles.Forsyth
194837da2899SCharles.Forsyth AIRR(Olwz, Rj, Ri,O(Type,initialize));
194937da2899SCharles.Forsyth mtspr(Rctr, Rj);
195037da2899SCharles.Forsyth AIRR(Ostw, Ro2, Rreg,O(REG,SP)); // R.SP = nsp
195137da2899SCharles.Forsyth AIRR(Ostw, Rzero, Ro1,O(Frame,mr)); // Ro1->mr = nil
195237da2899SCharles.Forsyth AIRR(Ostw, Ri, Ro1,O(Frame,t)); // Ro1->t = t
195337da2899SCharles.Forsyth gen(Obctr); // become t->init(Ro1), returning Ro1
195437da2899SCharles.Forsyth
195537da2899SCharles.Forsyth PATCH(cp); // expand:
195637da2899SCharles.Forsyth AIRR(Ostw, Ri, Rreg,O(REG,s)); // MOVL t, R.s
195737da2899SCharles.Forsyth mfspr(Rlink, Rlr);
195837da2899SCharles.Forsyth AIRR(Ostw, Rlink, Rreg,O(REG,st)); // MOVL Rlink, R.st
195937da2899SCharles.Forsyth AIRR(Ostw, Rfp, Rreg,O(REG,FP)); // MOVL RFP, R.FP
196037da2899SCharles.Forsyth jmpl((ulong*)extend); // CALL extend
196137da2899SCharles.Forsyth ldc((ulong)&R, Rreg);
196237da2899SCharles.Forsyth SETR0();
196337da2899SCharles.Forsyth AIRR(Olwz, Rlink, Rreg,O(REG,st)); // reload registers
196437da2899SCharles.Forsyth mtspr(Rlr, Rlink);
196537da2899SCharles.Forsyth AIRR(Olwz, Rfp, Rreg,O(REG,FP));
196637da2899SCharles.Forsyth AIRR(Olwz, Rmp, Rreg,O(REG,MP));
196737da2899SCharles.Forsyth AIRR(Olwz, Ro1, Rreg,O(REG,s)); // return R.s set by extend
196837da2899SCharles.Forsyth LRET(); // RET
196937da2899SCharles.Forsyth }
197037da2899SCharles.Forsyth
197137da2899SCharles.Forsyth static void
movloop(int ldu,int stu,int adj)197237da2899SCharles.Forsyth movloop(int ldu, int stu, int adj)
197337da2899SCharles.Forsyth {
197437da2899SCharles.Forsyth ulong *cp;
197537da2899SCharles.Forsyth
197637da2899SCharles.Forsyth AIRR(Oaddi, Ro1, Ro1, -adj); // adjust for update ld/st
197737da2899SCharles.Forsyth AIRR(Oaddi, Ro3, Ro3, -adj);
197837da2899SCharles.Forsyth mtspr(Rctr, Ro2);
197937da2899SCharles.Forsyth
198037da2899SCharles.Forsyth cp = code; // l0:
198137da2899SCharles.Forsyth AIRR(ldu, Ri, Ro1,adj);
198237da2899SCharles.Forsyth AIRR(stu, Ri, Ro3,adj);
198337da2899SCharles.Forsyth br(Obc | Cdnz, ((ulong)cp-(ulong)code)); // DBNZ l0
198437da2899SCharles.Forsyth }
198537da2899SCharles.Forsyth
198637da2899SCharles.Forsyth static void
movmem(Inst * i)198737da2899SCharles.Forsyth movmem(Inst *i)
198837da2899SCharles.Forsyth {
198937da2899SCharles.Forsyth ulong *cp;
199037da2899SCharles.Forsyth
199137da2899SCharles.Forsyth // source address already in Ro1
199237da2899SCharles.Forsyth if((i->add&ARM) != AXIMM){
199337da2899SCharles.Forsyth op2(i, Olwz, Ro2);
199437da2899SCharles.Forsyth AIRR(Ocmpi, Rcrf0, Ro2, 0);
199537da2899SCharles.Forsyth cp = code;
199637da2899SCharles.Forsyth br(Oble, 0);
199737da2899SCharles.Forsyth opwst(i, Olea, Ro3);
199837da2899SCharles.Forsyth movloop(Olbzu, Ostbu, 1);
199937da2899SCharles.Forsyth PATCH(cp);
200037da2899SCharles.Forsyth return;
200137da2899SCharles.Forsyth }
200237da2899SCharles.Forsyth switch(i->reg){
200337da2899SCharles.Forsyth case 4:
200437da2899SCharles.Forsyth AIRR(Olwz, Ro2, Ro1,0);
200537da2899SCharles.Forsyth opwst(i, Ostw, Ro2);
200637da2899SCharles.Forsyth break;
200737da2899SCharles.Forsyth case 8:
200837da2899SCharles.Forsyth AIRR(Olwz, Ro2, Ro1,0);
200937da2899SCharles.Forsyth opwst(i, Olea, Ro3);
201037da2899SCharles.Forsyth AIRR(Olwz, Ro1, Ro1,4);
201137da2899SCharles.Forsyth AIRR(Ostw, Ro2, Ro3,0);
201237da2899SCharles.Forsyth AIRR(Ostw, Ro1, Ro3,4);
201337da2899SCharles.Forsyth break;
201437da2899SCharles.Forsyth default:
201537da2899SCharles.Forsyth // could use lwsi/stwsi loop...
201637da2899SCharles.Forsyth opwst(i, Olea, Ro3);
201737da2899SCharles.Forsyth if((i->reg&3) == 0) {
201837da2899SCharles.Forsyth ldc(i->reg>>2, Ro2);
201937da2899SCharles.Forsyth movloop(Olwzu, Ostwu, 4);
202037da2899SCharles.Forsyth } else {
202137da2899SCharles.Forsyth ldc(i->reg, Ro2);
202237da2899SCharles.Forsyth movloop(Olbzu, Ostbu, 1);
202337da2899SCharles.Forsyth }
202437da2899SCharles.Forsyth break;
202537da2899SCharles.Forsyth }
202637da2899SCharles.Forsyth }
202737da2899SCharles.Forsyth
202837da2899SCharles.Forsyth static void
maccolr(void)202937da2899SCharles.Forsyth maccolr(void)
203037da2899SCharles.Forsyth {
203137da2899SCharles.Forsyth ldbigc((ulong)&mutator, Ri);
203237da2899SCharles.Forsyth AIRR(Olwz, Ri, Ri,0);
203337da2899SCharles.Forsyth AIRR(Olwz, Ro3, Ro1,O(Heap,color)-sizeof(Heap)); // h->color
203437da2899SCharles.Forsyth
203537da2899SCharles.Forsyth AIRR(Olwz, Ro2, Ro1,O(Heap,ref)-sizeof(Heap)); // h->ref
203637da2899SCharles.Forsyth
203737da2899SCharles.Forsyth ARRR(Ocmp, Rcrf0, Ri, Ro3);
203837da2899SCharles.Forsyth AIRR(Oaddi, Ro2, Ro2, 1); // h->ref++
203937da2899SCharles.Forsyth AIRR(Ostw, Ro2, Ro1,O(Heap,ref)-sizeof(Heap));
204037da2899SCharles.Forsyth gen(Obclr | Ceq); // return if h->color == mutator
204137da2899SCharles.Forsyth
204237da2899SCharles.Forsyth ldc(propagator, Ro3);
204337da2899SCharles.Forsyth AIRR(Ostw, Ro3, Ro1,O(Heap,color)-sizeof(Heap)); // h->color = propagator
204437da2899SCharles.Forsyth ldc((ulong)&nprop, Ro3);
204537da2899SCharles.Forsyth AIRR(Ostw, Ro1, Ro3,0); // nprop = !0
204637da2899SCharles.Forsyth LRET();
204737da2899SCharles.Forsyth }
204837da2899SCharles.Forsyth
204937da2899SCharles.Forsyth static void
maccvtfw(void)205037da2899SCharles.Forsyth maccvtfw(void)
205137da2899SCharles.Forsyth {
205237da2899SCharles.Forsyth ulong *cp;
205337da2899SCharles.Forsyth
205437da2899SCharles.Forsyth ARRR(Ofcmpo, Rcrf0, Rf1, Rfzero);
205537da2899SCharles.Forsyth ARRR(Ofneg, Rf2, 0, Rfhalf);
205637da2899SCharles.Forsyth cp = code;
205737da2899SCharles.Forsyth br(Oblt, 0);
205837da2899SCharles.Forsyth ARRR(Ofmr, Rf2, 0, Rfhalf);
205937da2899SCharles.Forsyth PATCH(cp);
206037da2899SCharles.Forsyth ARRR(Ofadd, Rf1, Rf1, Rf2); //x<0? x-.5: x+.5
206137da2899SCharles.Forsyth ARRR(Ofctiwz, Rf2, 0, Rf1);
206237da2899SCharles.Forsyth /* avoid using Ostfdu for now, since software emulation will run on same stack */
206337da2899SCharles.Forsyth if(0){
206437da2899SCharles.Forsyth AIRR(Ostfdu, Rf2, Rsp,-8); // MOVDU Rf2, -8(R1) (store in temp)
206537da2899SCharles.Forsyth }else{
206637da2899SCharles.Forsyth AIRR(Oaddi, Rsp, Rsp, -8); // SUB $8, R1
206737da2899SCharles.Forsyth AIRR(Ostfd, Rf2, Rsp,0); // MOVD Rf2, 0(R1) (store in temp)
206837da2899SCharles.Forsyth }
206937da2899SCharles.Forsyth AIRR(Olwz, Ro1, Rsp,4); // MOVW 4(R1), Ro1
207037da2899SCharles.Forsyth AIRR(Oaddi, Rsp, Rsp, 8); // ADD $8, R1
207137da2899SCharles.Forsyth LRET();
207237da2899SCharles.Forsyth }
207337da2899SCharles.Forsyth
207437da2899SCharles.Forsyth static void
macrelq(void)207537da2899SCharles.Forsyth macrelq(void)
207637da2899SCharles.Forsyth {
207737da2899SCharles.Forsyth ARRR(Ocrxor, Rcrbrel, Rcrbrel, Rcrbrel); /* clear the relinquish condition */
207837da2899SCharles.Forsyth mfspr(Rlink, Rlr);
207937da2899SCharles.Forsyth IRR(Ostw, O(REG,FP),Rreg, Rfp);
208037da2899SCharles.Forsyth IRR(Ostw, O(REG,PC),Rreg, Rlink);
208137da2899SCharles.Forsyth IRR(Olwz, O(REG,xpc),Rreg, Ro2);
208237da2899SCharles.Forsyth jr(Ro2);
208337da2899SCharles.Forsyth }
208437da2899SCharles.Forsyth
208537da2899SCharles.Forsyth static void
macend(void)208637da2899SCharles.Forsyth macend(void)
208737da2899SCharles.Forsyth {
208837da2899SCharles.Forsyth }
208937da2899SCharles.Forsyth
209037da2899SCharles.Forsyth void
comd(Type * t)209137da2899SCharles.Forsyth comd(Type *t)
209237da2899SCharles.Forsyth {
209337da2899SCharles.Forsyth int i, j, m, c;
209437da2899SCharles.Forsyth
209537da2899SCharles.Forsyth mfspr(Rlink, Rlr);
209637da2899SCharles.Forsyth AIRR(Ostw, Rlink, Rreg,O(REG,dt));
209737da2899SCharles.Forsyth for(i = 0; i < t->np; i++) {
209837da2899SCharles.Forsyth c = t->map[i];
209937da2899SCharles.Forsyth j = i<<5;
210037da2899SCharles.Forsyth for(m = 0x80; m != 0; m >>= 1) {
210137da2899SCharles.Forsyth if(c & m) {
210237da2899SCharles.Forsyth mem(Olwz, j, Rfp, Ri);
210337da2899SCharles.Forsyth jmpl(base+macro[MacFRP]);
210437da2899SCharles.Forsyth }
210537da2899SCharles.Forsyth j += sizeof(WORD*);
210637da2899SCharles.Forsyth }
210737da2899SCharles.Forsyth }
210837da2899SCharles.Forsyth AIRR(Olwz, Rlink, Rreg,O(REG,dt));
210937da2899SCharles.Forsyth mtspr(Rlr, Rlink);
211037da2899SCharles.Forsyth gen(Oblr);
211137da2899SCharles.Forsyth }
211237da2899SCharles.Forsyth
211337da2899SCharles.Forsyth void
comi(Type * t)211437da2899SCharles.Forsyth comi(Type *t)
211537da2899SCharles.Forsyth {
211637da2899SCharles.Forsyth int i, j, m, c;
211737da2899SCharles.Forsyth
211837da2899SCharles.Forsyth ldc((ulong)H, Ri);
211937da2899SCharles.Forsyth for(i = 0; i < t->np; i++) {
212037da2899SCharles.Forsyth c = t->map[i];
212137da2899SCharles.Forsyth j = i<<5;
212237da2899SCharles.Forsyth for(m = 0x80; m != 0; m >>= 1) {
212337da2899SCharles.Forsyth if(c & m)
212437da2899SCharles.Forsyth mem(Ostw, j, Ro1, Ri);
212537da2899SCharles.Forsyth j += sizeof(WORD*);
212637da2899SCharles.Forsyth }
212737da2899SCharles.Forsyth }
212837da2899SCharles.Forsyth LRET();
212937da2899SCharles.Forsyth }
213037da2899SCharles.Forsyth
213137da2899SCharles.Forsyth void
typecom(Type * t)213237da2899SCharles.Forsyth typecom(Type *t)
213337da2899SCharles.Forsyth {
213437da2899SCharles.Forsyth int n;
213537da2899SCharles.Forsyth ulong *tmp, *start;
213637da2899SCharles.Forsyth
213737da2899SCharles.Forsyth if(t == nil || t->initialize != 0)
213837da2899SCharles.Forsyth return;
213937da2899SCharles.Forsyth
214037da2899SCharles.Forsyth tmp = mallocz(4096*sizeof(ulong), 0);
214137da2899SCharles.Forsyth if(tmp == nil)
214237da2899SCharles.Forsyth error(exNomem);
214337da2899SCharles.Forsyth
214437da2899SCharles.Forsyth code = tmp;
214537da2899SCharles.Forsyth comi(t);
214637da2899SCharles.Forsyth n = code - tmp;
214737da2899SCharles.Forsyth code = tmp;
214837da2899SCharles.Forsyth comd(t);
214937da2899SCharles.Forsyth n += code - tmp;
215037da2899SCharles.Forsyth free(tmp);
215137da2899SCharles.Forsyth
215237da2899SCharles.Forsyth n *= sizeof(*code);
215337da2899SCharles.Forsyth code = mallocz(n, 0);
215437da2899SCharles.Forsyth if(code == nil)
215537da2899SCharles.Forsyth return;
215637da2899SCharles.Forsyth
215737da2899SCharles.Forsyth start = code;
215837da2899SCharles.Forsyth t->initialize = code;
215937da2899SCharles.Forsyth comi(t);
216037da2899SCharles.Forsyth t->destroy = code;
216137da2899SCharles.Forsyth comd(t);
216237da2899SCharles.Forsyth
216337da2899SCharles.Forsyth segflush(start, n);
216437da2899SCharles.Forsyth
216537da2899SCharles.Forsyth if(cflag > 3)
216637da2899SCharles.Forsyth print("typ= %.8lux %4d i %.8lux d %.8lux asm=%d\n",
216737da2899SCharles.Forsyth (ulong)t, t->size, (ulong)t->initialize, (ulong)t->destroy, n);
216837da2899SCharles.Forsyth }
216937da2899SCharles.Forsyth
217037da2899SCharles.Forsyth static void
patchex(Module * m,ulong * p)217137da2899SCharles.Forsyth patchex(Module *m, ulong *p)
217237da2899SCharles.Forsyth {
217337da2899SCharles.Forsyth Handler *h;
217437da2899SCharles.Forsyth Except *e;
217537da2899SCharles.Forsyth
217637da2899SCharles.Forsyth if((h = m->htab) == nil)
217737da2899SCharles.Forsyth return;
217837da2899SCharles.Forsyth for( ; h->etab != nil; h++){
217937da2899SCharles.Forsyth h->pc1 = p[h->pc1];
218037da2899SCharles.Forsyth h->pc2 = p[h->pc2];
218137da2899SCharles.Forsyth for(e = h->etab; e->s != nil; e++)
218237da2899SCharles.Forsyth e->pc = p[e->pc];
218337da2899SCharles.Forsyth if(e->pc != -1)
218437da2899SCharles.Forsyth e->pc = p[e->pc];
218537da2899SCharles.Forsyth }
218637da2899SCharles.Forsyth }
218737da2899SCharles.Forsyth
218837da2899SCharles.Forsyth int
compile(Module * m,int size,Modlink * ml)218937da2899SCharles.Forsyth compile(Module *m, int size, Modlink *ml)
219037da2899SCharles.Forsyth {
219137da2899SCharles.Forsyth Link *l;
219237da2899SCharles.Forsyth Modl *e;
219337da2899SCharles.Forsyth int i, n;
219437da2899SCharles.Forsyth ulong *s, *tmp;
219537da2899SCharles.Forsyth
219637da2899SCharles.Forsyth base = nil;
219737da2899SCharles.Forsyth patch = mallocz(size*sizeof(*patch), ROMABLE);
219837da2899SCharles.Forsyth tinit = malloc(m->ntype*sizeof(*tinit));
219937da2899SCharles.Forsyth tmp = malloc(4096*sizeof(ulong));
220037da2899SCharles.Forsyth if(tinit == nil || patch == nil || tmp == nil)
220137da2899SCharles.Forsyth goto bad;
220237da2899SCharles.Forsyth
220337da2899SCharles.Forsyth preamble();
220437da2899SCharles.Forsyth
220537da2899SCharles.Forsyth mod = m;
220637da2899SCharles.Forsyth n = 0;
220737da2899SCharles.Forsyth pass = 0;
220837da2899SCharles.Forsyth nlit = 0;
220937da2899SCharles.Forsyth
221037da2899SCharles.Forsyth for(i = 0; i < size; i++) {
221137da2899SCharles.Forsyth code = tmp;
221237da2899SCharles.Forsyth comp(&m->prog[i]);
221337da2899SCharles.Forsyth if(code >= &tmp[4096]) {
221437da2899SCharles.Forsyth print("%3d %D\n", i, &m->prog[i]);
221537da2899SCharles.Forsyth urk("tmp ovflo");
221637da2899SCharles.Forsyth }
221737da2899SCharles.Forsyth patch[i] = n;
221837da2899SCharles.Forsyth n += code - tmp;
221937da2899SCharles.Forsyth }
222037da2899SCharles.Forsyth
222137da2899SCharles.Forsyth for(i=0; macinit[i].f; i++) {
222237da2899SCharles.Forsyth code = tmp;
222337da2899SCharles.Forsyth (*macinit[i].f)();
222437da2899SCharles.Forsyth macro[macinit[i].o] = n;
222537da2899SCharles.Forsyth n += code - tmp;
222637da2899SCharles.Forsyth }
222737da2899SCharles.Forsyth
222837da2899SCharles.Forsyth base = mallocz((n+nlit)*sizeof(*base), 0);
222937da2899SCharles.Forsyth if(base == nil)
223037da2899SCharles.Forsyth goto bad;
223137da2899SCharles.Forsyth
223237da2899SCharles.Forsyth if(cflag > 3)
223337da2899SCharles.Forsyth print("dis=%5d %5d ppc=%5d asm=%.8lux lit=%d: %s\n",
223437da2899SCharles.Forsyth size, size*sizeof(Inst), n, (ulong)base, nlit, m->name);
223537da2899SCharles.Forsyth
223637da2899SCharles.Forsyth pass++;
223737da2899SCharles.Forsyth nlit = 0;
223837da2899SCharles.Forsyth litpool = base+n;
223937da2899SCharles.Forsyth code = base;
224037da2899SCharles.Forsyth n = 0;
224137da2899SCharles.Forsyth
224237da2899SCharles.Forsyth for(i = 0; i < size; i++) {
224337da2899SCharles.Forsyth s = code;
224437da2899SCharles.Forsyth comp(&m->prog[i]);
224537da2899SCharles.Forsyth if(patch[i] != n) {
224637da2899SCharles.Forsyth print("%3d %D\n", i, &m->prog[i]);
224737da2899SCharles.Forsyth urk("phase error");
224837da2899SCharles.Forsyth }
224937da2899SCharles.Forsyth n += code - s;
225037da2899SCharles.Forsyth if(cflag > 3) {
225137da2899SCharles.Forsyth print("%3d %D\n", i, &m->prog[i]);
225237da2899SCharles.Forsyth while(s < code)
225337da2899SCharles.Forsyth s += das(s);
225437da2899SCharles.Forsyth }/**/
225537da2899SCharles.Forsyth }
225637da2899SCharles.Forsyth
225737da2899SCharles.Forsyth for(i=0; macinit[i].f; i++) {
225837da2899SCharles.Forsyth if(macro[macinit[i].o] != n) {
225937da2899SCharles.Forsyth print("macinit %d\n", macinit[i].o);
226037da2899SCharles.Forsyth urk("phase error");
226137da2899SCharles.Forsyth }
226237da2899SCharles.Forsyth s = code;
226337da2899SCharles.Forsyth (*macinit[i].f)();
226437da2899SCharles.Forsyth n += code - s;
226537da2899SCharles.Forsyth if(cflag > 3) {
226637da2899SCharles.Forsyth print("macinit %d\n", macinit[i].o);
226737da2899SCharles.Forsyth while(s < code)
226837da2899SCharles.Forsyth s += das(s);
226937da2899SCharles.Forsyth }/**/
227037da2899SCharles.Forsyth }
227137da2899SCharles.Forsyth
227237da2899SCharles.Forsyth for(l = m->ext; l->name; l++) {
227337da2899SCharles.Forsyth l->u.pc = (Inst*)(base+patch[l->u.pc-m->prog]);
227437da2899SCharles.Forsyth typecom(l->frame);
227537da2899SCharles.Forsyth }
227637da2899SCharles.Forsyth if(ml != nil) {
227737da2899SCharles.Forsyth e = &ml->links[0];
227837da2899SCharles.Forsyth for(i = 0; i < ml->nlinks; i++) {
227937da2899SCharles.Forsyth e->u.pc = (Inst*)(base+patch[e->u.pc-m->prog]);
228037da2899SCharles.Forsyth typecom(e->frame);
228137da2899SCharles.Forsyth e++;
228237da2899SCharles.Forsyth }
228337da2899SCharles.Forsyth }
228437da2899SCharles.Forsyth for(i = 0; i < m->ntype; i++) {
228537da2899SCharles.Forsyth if(tinit[i] != 0)
228637da2899SCharles.Forsyth typecom(m->type[i]);
228737da2899SCharles.Forsyth }
228837da2899SCharles.Forsyth patchex(m, patch);
228937da2899SCharles.Forsyth m->entry = (Inst*)(base+patch[mod->entry-mod->prog]);
229037da2899SCharles.Forsyth free(patch);
229137da2899SCharles.Forsyth free(tinit);
229237da2899SCharles.Forsyth free(tmp);
229337da2899SCharles.Forsyth free(m->prog);
229437da2899SCharles.Forsyth m->prog = (Inst*)base;
229537da2899SCharles.Forsyth m->compiled = 1;
229637da2899SCharles.Forsyth segflush(base, n*sizeof(*base));
229737da2899SCharles.Forsyth return 1;
229837da2899SCharles.Forsyth bad:
229937da2899SCharles.Forsyth free(patch);
230037da2899SCharles.Forsyth free(tinit);
230137da2899SCharles.Forsyth free(base);
230237da2899SCharles.Forsyth free(tmp);
230337da2899SCharles.Forsyth return 0;
230437da2899SCharles.Forsyth }
2305