137da2899SCharles.Forsyth #include "lib9.h"
237da2899SCharles.Forsyth #include "isa.h"
337da2899SCharles.Forsyth #include "interp.h"
437da2899SCharles.Forsyth #include "raise.h"
537da2899SCharles.Forsyth
637da2899SCharles.Forsyth #define DOT ((ulong)code)
737da2899SCharles.Forsyth
837da2899SCharles.Forsyth #define RESCHED 1 /* check for interpreter reschedule */
937da2899SCharles.Forsyth
1037da2899SCharles.Forsyth enum
1137da2899SCharles.Forsyth {
1237da2899SCharles.Forsyth RAX = 0,
1337da2899SCharles.Forsyth RAH = 4,
1437da2899SCharles.Forsyth RCX = 1,
1537da2899SCharles.Forsyth RDX = 2,
1637da2899SCharles.Forsyth RBX = 3,
1737da2899SCharles.Forsyth RSP = 4,
1837da2899SCharles.Forsyth RBP = 5,
1937da2899SCharles.Forsyth RSI = 6,
2037da2899SCharles.Forsyth RDI = 7,
2137da2899SCharles.Forsyth
2237da2899SCharles.Forsyth RFP = RSI,
2337da2899SCharles.Forsyth RMP = RDI,
2437da2899SCharles.Forsyth RTA = RDX,
2537da2899SCharles.Forsyth RTMP = RBX,
2637da2899SCharles.Forsyth
2737da2899SCharles.Forsyth Omovzxb = 0xb6,
2837da2899SCharles.Forsyth Omovzxw = 0xb7,
2937da2899SCharles.Forsyth Osal = 0xd1,
3037da2899SCharles.Forsyth Oaddf = 0xdc,
3137da2899SCharles.Forsyth Ocall = 0xe8,
3237da2899SCharles.Forsyth Ocallrm = 0xff,
3337da2899SCharles.Forsyth Ocdq = 0x99,
3437da2899SCharles.Forsyth Ocld = 0xfc,
3537da2899SCharles.Forsyth Ocmpb = 0x38,
3637da2899SCharles.Forsyth Ocmpw = 0x39,
3737da2899SCharles.Forsyth Ocmpi = 0x83,
3837da2899SCharles.Forsyth Odecrm = 0xff,
3937da2899SCharles.Forsyth Oincr = 0x40,
4037da2899SCharles.Forsyth Oincrm = 0xff,
4137da2899SCharles.Forsyth Ojccl = 0x83,
4237da2899SCharles.Forsyth Ojcsl = 0x82,
4337da2899SCharles.Forsyth Ojeqb = 0x74,
4437da2899SCharles.Forsyth Ojeql = 0x84,
4537da2899SCharles.Forsyth Ojgel = 0x8d,
4637da2899SCharles.Forsyth Ojgtl = 0x8f,
4737da2899SCharles.Forsyth Ojhil = 0x87,
4837da2899SCharles.Forsyth Ojlel = 0x8e,
4937da2899SCharles.Forsyth Ojlsl = 0x86,
5037da2899SCharles.Forsyth Ojltl = 0x8c,
5137da2899SCharles.Forsyth Ojol = 0x80,
5237da2899SCharles.Forsyth Ojnol = 0x81,
5337da2899SCharles.Forsyth Ojbl = 0x82,
5437da2899SCharles.Forsyth Ojael = 0x83,
5537da2899SCharles.Forsyth Ojal = 0x87,
5637da2899SCharles.Forsyth Ojnel = 0x85,
5737da2899SCharles.Forsyth Ojbel = 0x86,
5837da2899SCharles.Forsyth Ojneb = 0x75,
5937da2899SCharles.Forsyth Ojgtb = 0x7f,
6037da2899SCharles.Forsyth Ojgeb = 0x7d,
6137da2899SCharles.Forsyth Ojleb = 0x7e,
6237da2899SCharles.Forsyth Ojltb = 0x7c,
6337da2899SCharles.Forsyth Ojmp = 0xe9,
6437da2899SCharles.Forsyth Ojmpb = 0xeb,
6537da2899SCharles.Forsyth Ojmprm = 0xff,
6637da2899SCharles.Forsyth Oldb = 0x8a,
6737da2899SCharles.Forsyth Olds = 0x89,
6837da2899SCharles.Forsyth Oldw = 0x8b,
6937da2899SCharles.Forsyth Olea = 0x8d,
7037da2899SCharles.Forsyth Otestib = 0xf6,
7137da2899SCharles.Forsyth Oshld = 0xa5,
7237da2899SCharles.Forsyth Oshrd = 0xad,
7337da2899SCharles.Forsyth Osar = 0xd3,
7437da2899SCharles.Forsyth Osarimm = 0xc1,
7537da2899SCharles.Forsyth Omov = 0xc7,
7637da2899SCharles.Forsyth Omovf = 0xdd,
7737da2899SCharles.Forsyth Omovimm = 0xb8,
7837da2899SCharles.Forsyth Omovsb = 0xa4,
7937da2899SCharles.Forsyth Orep = 0xf3,
8037da2899SCharles.Forsyth Oret = 0xc3,
8137da2899SCharles.Forsyth Oshl = 0xd3,
8237da2899SCharles.Forsyth Oshr = 0xd1,
8337da2899SCharles.Forsyth Ostb = 0x88,
8437da2899SCharles.Forsyth Ostw = 0x89,
8537da2899SCharles.Forsyth Osubf = 0xdc,
8637da2899SCharles.Forsyth Oxchg = 0x87,
8737da2899SCharles.Forsyth OxchgAX = 0x90,
8837da2899SCharles.Forsyth Oxor = 0x31,
8937da2899SCharles.Forsyth Opopl = 0x58,
9037da2899SCharles.Forsyth Opushl = 0x50,
9137da2899SCharles.Forsyth Opushrm = 0xff,
9237da2899SCharles.Forsyth Oneg = 0xf7,
9337da2899SCharles.Forsyth
9437da2899SCharles.Forsyth SRCOP = (1<<0),
9537da2899SCharles.Forsyth DSTOP = (1<<1),
9637da2899SCharles.Forsyth WRTPC = (1<<2),
9737da2899SCharles.Forsyth TCHECK = (1<<3),
9837da2899SCharles.Forsyth NEWPC = (1<<4),
9937da2899SCharles.Forsyth DBRAN = (1<<5),
10037da2899SCharles.Forsyth THREOP = (1<<6),
10137da2899SCharles.Forsyth
10237da2899SCharles.Forsyth ANDAND = 1,
10337da2899SCharles.Forsyth OROR = 2,
10437da2899SCharles.Forsyth EQAND = 3,
10537da2899SCharles.Forsyth
10637da2899SCharles.Forsyth MacFRP = 0,
10737da2899SCharles.Forsyth MacRET = 1,
10837da2899SCharles.Forsyth MacCASE = 2,
10937da2899SCharles.Forsyth MacCOLR = 3,
11037da2899SCharles.Forsyth MacMCAL = 4,
11137da2899SCharles.Forsyth MacFRAM = 5,
11237da2899SCharles.Forsyth MacMFRA = 6,
11337da2899SCharles.Forsyth MacRELQ = 7,
11437da2899SCharles.Forsyth NMACRO
11537da2899SCharles.Forsyth };
11637da2899SCharles.Forsyth
11737da2899SCharles.Forsyth static uchar* code;
11837da2899SCharles.Forsyth static uchar* base;
11937da2899SCharles.Forsyth static ulong* patch;
12037da2899SCharles.Forsyth static int pass;
12137da2899SCharles.Forsyth static Module* mod;
12237da2899SCharles.Forsyth static uchar* tinit;
12337da2899SCharles.Forsyth static ulong* litpool;
12437da2899SCharles.Forsyth static int nlit;
12537da2899SCharles.Forsyth static void macfrp(void);
12637da2899SCharles.Forsyth static void macret(void);
12737da2899SCharles.Forsyth static void maccase(void);
12837da2899SCharles.Forsyth static void maccolr(void);
12937da2899SCharles.Forsyth static void macmcal(void);
13037da2899SCharles.Forsyth static void macfram(void);
13137da2899SCharles.Forsyth static void macmfra(void);
13237da2899SCharles.Forsyth static void macrelq(void);
13337da2899SCharles.Forsyth static ulong macro[NMACRO];
13437da2899SCharles.Forsyth void (*comvec)(void);
13537da2899SCharles.Forsyth extern void das(uchar*, int);
13637da2899SCharles.Forsyth
13737da2899SCharles.Forsyth #define T(r) *((void**)(R.r))
13837da2899SCharles.Forsyth
13937da2899SCharles.Forsyth struct
14037da2899SCharles.Forsyth {
14137da2899SCharles.Forsyth int idx;
14237da2899SCharles.Forsyth void (*gen)(void);
14337da2899SCharles.Forsyth } mactab[] =
14437da2899SCharles.Forsyth {
14537da2899SCharles.Forsyth MacFRP, macfrp, /* decrement and free pointer */
14637da2899SCharles.Forsyth MacRET, macret, /* return instruction */
14737da2899SCharles.Forsyth MacCASE, maccase, /* case instruction */
14837da2899SCharles.Forsyth MacCOLR, maccolr, /* increment and color pointer */
14937da2899SCharles.Forsyth MacMCAL, macmcal, /* mcall bottom half */
15037da2899SCharles.Forsyth MacFRAM, macfram, /* frame instruction */
15137da2899SCharles.Forsyth MacMFRA, macmfra, /* punt mframe because t->initialize==0 */
15237da2899SCharles.Forsyth MacRELQ, macrelq, /* reschedule */
15337da2899SCharles.Forsyth };
15437da2899SCharles.Forsyth
15537da2899SCharles.Forsyth static void
bounds(void)15637da2899SCharles.Forsyth bounds(void)
15737da2899SCharles.Forsyth {
15837da2899SCharles.Forsyth error(exBounds);
15937da2899SCharles.Forsyth }
16037da2899SCharles.Forsyth
16137da2899SCharles.Forsyth static void
rdestroy(void)16237da2899SCharles.Forsyth rdestroy(void)
16337da2899SCharles.Forsyth {
16437da2899SCharles.Forsyth destroy(R.s);
16537da2899SCharles.Forsyth }
16637da2899SCharles.Forsyth
16737da2899SCharles.Forsyth static void
rmcall(void)16837da2899SCharles.Forsyth rmcall(void)
16937da2899SCharles.Forsyth {
17037da2899SCharles.Forsyth Prog *p;
17137da2899SCharles.Forsyth Frame *f;
17237da2899SCharles.Forsyth
17337da2899SCharles.Forsyth if((void*)R.dt == H)
17437da2899SCharles.Forsyth error(exModule);
17537da2899SCharles.Forsyth
17637da2899SCharles.Forsyth f = (Frame*)R.FP;
17737da2899SCharles.Forsyth if(f == H)
17837da2899SCharles.Forsyth error(exModule);
17937da2899SCharles.Forsyth
18037da2899SCharles.Forsyth f->mr = nil;
18137da2899SCharles.Forsyth ((void(*)(Frame*))R.dt)(f);
18237da2899SCharles.Forsyth R.SP = (uchar*)f;
18337da2899SCharles.Forsyth R.FP = f->fp;
18437da2899SCharles.Forsyth if(f->t == nil)
18537da2899SCharles.Forsyth unextend(f);
18637da2899SCharles.Forsyth else
18737da2899SCharles.Forsyth freeptrs(f, f->t);
18837da2899SCharles.Forsyth p = currun();
18937da2899SCharles.Forsyth if(p->kill != nil)
19037da2899SCharles.Forsyth error(p->kill);
19137da2899SCharles.Forsyth }
19237da2899SCharles.Forsyth
19337da2899SCharles.Forsyth static void
rmfram(void)19437da2899SCharles.Forsyth rmfram(void)
19537da2899SCharles.Forsyth {
19637da2899SCharles.Forsyth Type *t;
19737da2899SCharles.Forsyth Frame *f;
19837da2899SCharles.Forsyth uchar *nsp;
19937da2899SCharles.Forsyth
20037da2899SCharles.Forsyth t = (Type*)R.s;
20137da2899SCharles.Forsyth if(t == H)
20237da2899SCharles.Forsyth error(exModule);
20337da2899SCharles.Forsyth
20437da2899SCharles.Forsyth nsp = R.SP + t->size;
20537da2899SCharles.Forsyth if(nsp >= R.TS) {
20637da2899SCharles.Forsyth R.s = t;
20737da2899SCharles.Forsyth extend();
20837da2899SCharles.Forsyth T(d) = R.s;
20937da2899SCharles.Forsyth return;
21037da2899SCharles.Forsyth }
21137da2899SCharles.Forsyth f = (Frame*)R.SP;
21237da2899SCharles.Forsyth R.SP = nsp;
21337da2899SCharles.Forsyth f->t = t;
21437da2899SCharles.Forsyth f->mr = nil;
21537da2899SCharles.Forsyth initmem(t, f);
21637da2899SCharles.Forsyth T(d) = f;
21737da2899SCharles.Forsyth }
21837da2899SCharles.Forsyth
21937da2899SCharles.Forsyth static int
bc(int o)22037da2899SCharles.Forsyth bc(int o)
22137da2899SCharles.Forsyth {
22237da2899SCharles.Forsyth if(o < 127 && o > -128)
22337da2899SCharles.Forsyth return 1;
22437da2899SCharles.Forsyth return 0;
22537da2899SCharles.Forsyth }
22637da2899SCharles.Forsyth
22737da2899SCharles.Forsyth static void
urk(void)22837da2899SCharles.Forsyth urk(void)
22937da2899SCharles.Forsyth {
23037da2899SCharles.Forsyth error(exCompile);
23137da2899SCharles.Forsyth }
23237da2899SCharles.Forsyth
23337da2899SCharles.Forsyth static void
genb(uchar o)23437da2899SCharles.Forsyth genb(uchar o)
23537da2899SCharles.Forsyth {
23637da2899SCharles.Forsyth *code++ = o;
23737da2899SCharles.Forsyth }
23837da2899SCharles.Forsyth
23937da2899SCharles.Forsyth static void
gen2(uchar o1,uchar o2)24037da2899SCharles.Forsyth gen2(uchar o1, uchar o2)
24137da2899SCharles.Forsyth {
24237da2899SCharles.Forsyth code[0] = o1;
24337da2899SCharles.Forsyth code[1] = o2;
24437da2899SCharles.Forsyth code += 2;
24537da2899SCharles.Forsyth }
24637da2899SCharles.Forsyth
24737da2899SCharles.Forsyth static void
genw(ulong o)24837da2899SCharles.Forsyth genw(ulong o)
24937da2899SCharles.Forsyth {
25037da2899SCharles.Forsyth *(ulong*)code = o;
25137da2899SCharles.Forsyth code += 4;
25237da2899SCharles.Forsyth }
25337da2899SCharles.Forsyth
25437da2899SCharles.Forsyth static void
modrm(int inst,ulong disp,int rm,int r)25537da2899SCharles.Forsyth modrm(int inst, ulong disp, int rm, int r)
25637da2899SCharles.Forsyth {
25737da2899SCharles.Forsyth *code++ = inst;
25837da2899SCharles.Forsyth if(disp == 0) {
25937da2899SCharles.Forsyth *code++ = (0<<6)|(r<<3)|rm;
26037da2899SCharles.Forsyth return;
26137da2899SCharles.Forsyth }
26237da2899SCharles.Forsyth if(bc(disp)) {
26337da2899SCharles.Forsyth code[0] = (1<<6)|(r<<3)|rm;
26437da2899SCharles.Forsyth code[1] = disp;
26537da2899SCharles.Forsyth code += 2;
26637da2899SCharles.Forsyth return;
26737da2899SCharles.Forsyth }
26837da2899SCharles.Forsyth *code++ = (2<<6)|(r<<3)|rm;
26937da2899SCharles.Forsyth *(ulong*)code = disp;
27037da2899SCharles.Forsyth code += 4;
27137da2899SCharles.Forsyth }
27237da2899SCharles.Forsyth
27337da2899SCharles.Forsyth static void
con(ulong o,int r)27437da2899SCharles.Forsyth con(ulong o, int r)
27537da2899SCharles.Forsyth {
27637da2899SCharles.Forsyth if(o == 0) {
27737da2899SCharles.Forsyth gen2(Oxor, (3<<6)|(r<<3)|r);
27837da2899SCharles.Forsyth return;
27937da2899SCharles.Forsyth }
28037da2899SCharles.Forsyth genb(Omovimm+r);
28137da2899SCharles.Forsyth genw(o);
28237da2899SCharles.Forsyth }
28337da2899SCharles.Forsyth
28437da2899SCharles.Forsyth static void
opwld(Inst * i,int mi,int r)28537da2899SCharles.Forsyth opwld(Inst *i, int mi, int r)
28637da2899SCharles.Forsyth {
28737da2899SCharles.Forsyth int ir, rta;
28837da2899SCharles.Forsyth
28937da2899SCharles.Forsyth switch(UXSRC(i->add)) {
29037da2899SCharles.Forsyth default:
29137da2899SCharles.Forsyth print("%D\n", i);
29237da2899SCharles.Forsyth urk();
29337da2899SCharles.Forsyth case SRC(AFP):
29437da2899SCharles.Forsyth modrm(mi, i->s.ind, RFP, r);
29537da2899SCharles.Forsyth return;
29637da2899SCharles.Forsyth case SRC(AMP):
29737da2899SCharles.Forsyth modrm(mi, i->s.ind, RMP, r);
29837da2899SCharles.Forsyth return;
29937da2899SCharles.Forsyth case SRC(AIMM):
30037da2899SCharles.Forsyth con(i->s.imm, r);
30137da2899SCharles.Forsyth return;
30237da2899SCharles.Forsyth case SRC(AIND|AFP):
30337da2899SCharles.Forsyth ir = RFP;
30437da2899SCharles.Forsyth break;
30537da2899SCharles.Forsyth case SRC(AIND|AMP):
30637da2899SCharles.Forsyth ir = RMP;
30737da2899SCharles.Forsyth break;
30837da2899SCharles.Forsyth }
30937da2899SCharles.Forsyth rta = RTA;
31037da2899SCharles.Forsyth if(mi == Olea)
31137da2899SCharles.Forsyth rta = r;
31237da2899SCharles.Forsyth modrm(Oldw, i->s.i.f, ir, rta);
31337da2899SCharles.Forsyth modrm(mi, i->s.i.s, rta, r);
31437da2899SCharles.Forsyth }
31537da2899SCharles.Forsyth
31637da2899SCharles.Forsyth static void
opwst(Inst * i,int mi,int r)31737da2899SCharles.Forsyth opwst(Inst *i, int mi, int r)
31837da2899SCharles.Forsyth {
31937da2899SCharles.Forsyth int ir, rta;
32037da2899SCharles.Forsyth
32137da2899SCharles.Forsyth switch(UXDST(i->add)) {
32237da2899SCharles.Forsyth default:
32337da2899SCharles.Forsyth print("%D\n", i);
32437da2899SCharles.Forsyth urk();
32537da2899SCharles.Forsyth case DST(AIMM):
32637da2899SCharles.Forsyth con(i->d.imm, r);
32737da2899SCharles.Forsyth return;
32837da2899SCharles.Forsyth case DST(AFP):
32937da2899SCharles.Forsyth modrm(mi, i->d.ind, RFP, r);
33037da2899SCharles.Forsyth return;
33137da2899SCharles.Forsyth case DST(AMP):
33237da2899SCharles.Forsyth modrm(mi, i->d.ind, RMP, r);
33337da2899SCharles.Forsyth return;
33437da2899SCharles.Forsyth case DST(AIND|AFP):
33537da2899SCharles.Forsyth ir = RFP;
33637da2899SCharles.Forsyth break;
33737da2899SCharles.Forsyth case DST(AIND|AMP):
33837da2899SCharles.Forsyth ir = RMP;
33937da2899SCharles.Forsyth break;
34037da2899SCharles.Forsyth }
34137da2899SCharles.Forsyth rta = RTA;
34237da2899SCharles.Forsyth if(mi == Olea)
34337da2899SCharles.Forsyth rta = r;
34437da2899SCharles.Forsyth modrm(Oldw, i->d.i.f, ir, rta);
34537da2899SCharles.Forsyth modrm(mi, i->d.i.s, rta, r);
34637da2899SCharles.Forsyth }
34737da2899SCharles.Forsyth
34837da2899SCharles.Forsyth static void
bra(ulong dst,int op)34937da2899SCharles.Forsyth bra(ulong dst, int op)
35037da2899SCharles.Forsyth {
35137da2899SCharles.Forsyth dst -= (DOT+5);
35237da2899SCharles.Forsyth genb(op);
35337da2899SCharles.Forsyth genw(dst);
35437da2899SCharles.Forsyth }
35537da2899SCharles.Forsyth
35637da2899SCharles.Forsyth static void
rbra(ulong dst,int op)35737da2899SCharles.Forsyth rbra(ulong dst, int op)
35837da2899SCharles.Forsyth {
35937da2899SCharles.Forsyth dst += (ulong)base;
36037da2899SCharles.Forsyth dst -= DOT+5;
36137da2899SCharles.Forsyth genb(op);
36237da2899SCharles.Forsyth genw(dst);
36337da2899SCharles.Forsyth }
36437da2899SCharles.Forsyth
36537da2899SCharles.Forsyth static void
literal(ulong imm,int roff)36637da2899SCharles.Forsyth literal(ulong imm, int roff)
36737da2899SCharles.Forsyth {
36837da2899SCharles.Forsyth nlit++;
36937da2899SCharles.Forsyth
37037da2899SCharles.Forsyth genb(Omovimm+RAX);
37137da2899SCharles.Forsyth genw((ulong)litpool);
37237da2899SCharles.Forsyth modrm(Ostw, roff, RTMP, RAX);
37337da2899SCharles.Forsyth
37437da2899SCharles.Forsyth if(pass == 0)
37537da2899SCharles.Forsyth return;
37637da2899SCharles.Forsyth
37737da2899SCharles.Forsyth *litpool = imm;
37837da2899SCharles.Forsyth litpool++;
37937da2899SCharles.Forsyth }
38037da2899SCharles.Forsyth
38137da2899SCharles.Forsyth static void
punt(Inst * i,int m,void (* fn)(void))38237da2899SCharles.Forsyth punt(Inst *i, int m, void (*fn)(void))
38337da2899SCharles.Forsyth {
38437da2899SCharles.Forsyth ulong pc;
38537da2899SCharles.Forsyth
38637da2899SCharles.Forsyth con((ulong)&R, RTMP);
38737da2899SCharles.Forsyth
38837da2899SCharles.Forsyth if(m & SRCOP) {
38937da2899SCharles.Forsyth if(UXSRC(i->add) == SRC(AIMM))
39037da2899SCharles.Forsyth literal(i->s.imm, O(REG, s));
39137da2899SCharles.Forsyth else {
39237da2899SCharles.Forsyth opwld(i, Olea, RAX);
39337da2899SCharles.Forsyth modrm(Ostw, O(REG, s), RTMP, RAX);
39437da2899SCharles.Forsyth }
39537da2899SCharles.Forsyth }
39637da2899SCharles.Forsyth
39737da2899SCharles.Forsyth if(m & DSTOP) {
39837da2899SCharles.Forsyth opwst(i, Olea, 0);
39937da2899SCharles.Forsyth modrm(Ostw, O(REG, d), RTMP, RAX);
40037da2899SCharles.Forsyth }
40137da2899SCharles.Forsyth if(m & WRTPC) {
40237da2899SCharles.Forsyth modrm(Omov, O(REG, PC), RTMP, 0);
40337da2899SCharles.Forsyth pc = patch[i-mod->prog+1];
40437da2899SCharles.Forsyth genw((ulong)base + pc);
40537da2899SCharles.Forsyth }
40637da2899SCharles.Forsyth if(m & DBRAN) {
40737da2899SCharles.Forsyth pc = patch[(Inst*)i->d.imm-mod->prog];
40837da2899SCharles.Forsyth literal((ulong)base+pc, O(REG, d));
40937da2899SCharles.Forsyth }
41037da2899SCharles.Forsyth
41137da2899SCharles.Forsyth switch(i->add&ARM) {
41237da2899SCharles.Forsyth case AXNON:
41337da2899SCharles.Forsyth if(m & THREOP) {
41437da2899SCharles.Forsyth modrm(Oldw, O(REG, d), RTMP, RAX);
41537da2899SCharles.Forsyth modrm(Ostw, O(REG, m), RTMP, RAX);
41637da2899SCharles.Forsyth }
41737da2899SCharles.Forsyth break;
41837da2899SCharles.Forsyth case AXIMM:
41937da2899SCharles.Forsyth literal((short)i->reg, O(REG, m));
42037da2899SCharles.Forsyth break;
42137da2899SCharles.Forsyth case AXINF:
42237da2899SCharles.Forsyth modrm(Olea, i->reg, RFP, RAX);
42337da2899SCharles.Forsyth modrm(Ostw, O(REG, m), RTMP, RAX);
42437da2899SCharles.Forsyth break;
42537da2899SCharles.Forsyth case AXINM:
42637da2899SCharles.Forsyth modrm(Olea, i->reg, RMP, RAX);
42737da2899SCharles.Forsyth modrm(Ostw, O(REG, m), RTMP, RAX);
42837da2899SCharles.Forsyth break;
42937da2899SCharles.Forsyth }
43037da2899SCharles.Forsyth modrm(Ostw, O(REG, FP), RTMP, RFP);
43137da2899SCharles.Forsyth
43237da2899SCharles.Forsyth bra((ulong)fn, Ocall);
43337da2899SCharles.Forsyth
43437da2899SCharles.Forsyth con((ulong)&R, RTMP);
43537da2899SCharles.Forsyth if(m & TCHECK) {
43637da2899SCharles.Forsyth modrm(Ocmpi, O(REG, t), RTMP, 7);// CMPL $0, R.t
43737da2899SCharles.Forsyth genb(0x00);
43837da2899SCharles.Forsyth gen2(Ojeqb, 0x06); // JEQ .+6
43937da2899SCharles.Forsyth genb(Opopl+RDI);
44037da2899SCharles.Forsyth genb(Opopl+RSI);
44137da2899SCharles.Forsyth genb(Opopl+RDX);
44237da2899SCharles.Forsyth genb(Opopl+RCX);
44337da2899SCharles.Forsyth genb(Opopl+RBX);
44437da2899SCharles.Forsyth genb(Oret);
44537da2899SCharles.Forsyth }
44637da2899SCharles.Forsyth
44737da2899SCharles.Forsyth modrm(Oldw, O(REG, FP), RTMP, RFP);
44837da2899SCharles.Forsyth modrm(Oldw, O(REG, MP), RTMP, RMP);
44937da2899SCharles.Forsyth
45037da2899SCharles.Forsyth if(m & NEWPC) {
45137da2899SCharles.Forsyth modrm(Oldw, O(REG, PC), RTMP, RAX);
45237da2899SCharles.Forsyth gen2(Ojmprm, (3<<6)|(4<<3)|RAX);
45337da2899SCharles.Forsyth }
45437da2899SCharles.Forsyth }
45537da2899SCharles.Forsyth
45637da2899SCharles.Forsyth static void
mid(Inst * i,uchar mi,int r)45737da2899SCharles.Forsyth mid(Inst *i, uchar mi, int r)
45837da2899SCharles.Forsyth {
45937da2899SCharles.Forsyth int ir;
46037da2899SCharles.Forsyth
46137da2899SCharles.Forsyth switch(i->add&ARM) {
46237da2899SCharles.Forsyth default:
46337da2899SCharles.Forsyth opwst(i, mi, r);
46437da2899SCharles.Forsyth return;
46537da2899SCharles.Forsyth case AXIMM:
46637da2899SCharles.Forsyth con((short)i->reg, r);
46737da2899SCharles.Forsyth return;
46837da2899SCharles.Forsyth case AXINF:
46937da2899SCharles.Forsyth ir = RFP;
47037da2899SCharles.Forsyth break;
47137da2899SCharles.Forsyth case AXINM:
47237da2899SCharles.Forsyth ir = RMP;
47337da2899SCharles.Forsyth break;
47437da2899SCharles.Forsyth }
47537da2899SCharles.Forsyth modrm(mi, i->reg, ir, r);
47637da2899SCharles.Forsyth }
47737da2899SCharles.Forsyth
47837da2899SCharles.Forsyth static void
arith(Inst * i,int op2,int rm)47937da2899SCharles.Forsyth arith(Inst *i, int op2, int rm)
48037da2899SCharles.Forsyth {
48137da2899SCharles.Forsyth if(UXSRC(i->add) != SRC(AIMM)) {
48237da2899SCharles.Forsyth if(i->add&ARM) {
48337da2899SCharles.Forsyth mid(i, Oldw, RAX);
48437da2899SCharles.Forsyth opwld(i, op2|2, 0);
48537da2899SCharles.Forsyth opwst(i, Ostw, 0);
48637da2899SCharles.Forsyth return;
48737da2899SCharles.Forsyth }
48837da2899SCharles.Forsyth opwld(i, Oldw, RAX);
48937da2899SCharles.Forsyth opwst(i, op2, 0);
49037da2899SCharles.Forsyth return;
49137da2899SCharles.Forsyth }
49237da2899SCharles.Forsyth if(i->add&ARM) {
49337da2899SCharles.Forsyth mid(i, Oldw, RAX);
49437da2899SCharles.Forsyth if(bc(i->s.imm)) {
49537da2899SCharles.Forsyth gen2(0x83, (3<<6)|(rm<<3)|RAX);
49637da2899SCharles.Forsyth genb(i->s.imm);
49737da2899SCharles.Forsyth }
49837da2899SCharles.Forsyth else {
49937da2899SCharles.Forsyth gen2(0x81, (3<<6)|(rm<<3)|RAX);
50037da2899SCharles.Forsyth genw(i->s.imm);
50137da2899SCharles.Forsyth }
50237da2899SCharles.Forsyth opwst(i, Ostw, RAX);
50337da2899SCharles.Forsyth return;
50437da2899SCharles.Forsyth }
50537da2899SCharles.Forsyth if(bc(i->s.imm)) {
50637da2899SCharles.Forsyth opwst(i, 0x83, rm);
50737da2899SCharles.Forsyth genb(i->s.imm);
50837da2899SCharles.Forsyth return;
50937da2899SCharles.Forsyth }
51037da2899SCharles.Forsyth opwst(i, 0x81, rm);
51137da2899SCharles.Forsyth genw(i->s.imm);
51237da2899SCharles.Forsyth }
51337da2899SCharles.Forsyth
51437da2899SCharles.Forsyth static void
arithb(Inst * i,int op2)51537da2899SCharles.Forsyth arithb(Inst *i, int op2)
51637da2899SCharles.Forsyth {
51737da2899SCharles.Forsyth if(UXSRC(i->add) == SRC(AIMM))
51837da2899SCharles.Forsyth urk();
51937da2899SCharles.Forsyth
52037da2899SCharles.Forsyth if(i->add&ARM) {
52137da2899SCharles.Forsyth mid(i, Oldb, RAX);
52237da2899SCharles.Forsyth opwld(i, op2|2, 0);
52337da2899SCharles.Forsyth opwst(i, Ostb, 0);
52437da2899SCharles.Forsyth return;
52537da2899SCharles.Forsyth }
52637da2899SCharles.Forsyth opwld(i, Oldb, RAX);
52737da2899SCharles.Forsyth opwst(i, op2, RAX);
52837da2899SCharles.Forsyth }
52937da2899SCharles.Forsyth
53037da2899SCharles.Forsyth static void
shift(Inst * i,int ld,int st,int op,int r)53137da2899SCharles.Forsyth shift(Inst *i, int ld, int st, int op, int r)
53237da2899SCharles.Forsyth {
53337da2899SCharles.Forsyth mid(i, ld, RAX);
53437da2899SCharles.Forsyth opwld(i, Oldw, RCX);
53537da2899SCharles.Forsyth gen2(op, (3<<6)|(r<<3)|RAX);
53637da2899SCharles.Forsyth opwst(i, st, RAX);
53737da2899SCharles.Forsyth }
53837da2899SCharles.Forsyth
53937da2899SCharles.Forsyth static void
arithf(Inst * i,int op)54037da2899SCharles.Forsyth arithf(Inst *i, int op)
54137da2899SCharles.Forsyth {
54237da2899SCharles.Forsyth opwld(i, Omovf, 0);
54337da2899SCharles.Forsyth mid(i, 0xdc, op);
54437da2899SCharles.Forsyth opwst(i, Omovf, 3);
54537da2899SCharles.Forsyth }
54637da2899SCharles.Forsyth
54737da2899SCharles.Forsyth static void
cmpl(int r,ulong v)54837da2899SCharles.Forsyth cmpl(int r, ulong v)
54937da2899SCharles.Forsyth {
55037da2899SCharles.Forsyth if(bc(v)) {
55137da2899SCharles.Forsyth gen2(0x83, (3<<6)|(7<<3)|r);
55237da2899SCharles.Forsyth genb(v);
55337da2899SCharles.Forsyth return;
55437da2899SCharles.Forsyth }
55537da2899SCharles.Forsyth gen2(0x81, (3<<6)|(7<<3)|r);
55637da2899SCharles.Forsyth genw(v);
55737da2899SCharles.Forsyth }
55837da2899SCharles.Forsyth
55937da2899SCharles.Forsyth static int
swapbraop(int b)56037da2899SCharles.Forsyth swapbraop(int b)
56137da2899SCharles.Forsyth {
56237da2899SCharles.Forsyth switch(b) {
56337da2899SCharles.Forsyth case Ojgel:
56437da2899SCharles.Forsyth return Ojlel;
56537da2899SCharles.Forsyth case Ojlel:
56637da2899SCharles.Forsyth return Ojgel;
56737da2899SCharles.Forsyth case Ojgtl:
56837da2899SCharles.Forsyth return Ojltl;
56937da2899SCharles.Forsyth case Ojltl:
57037da2899SCharles.Forsyth return Ojgtl;
57137da2899SCharles.Forsyth }
57237da2899SCharles.Forsyth return b;
57337da2899SCharles.Forsyth }
57437da2899SCharles.Forsyth
57537da2899SCharles.Forsyth static void
schedcheck(Inst * i)57637da2899SCharles.Forsyth schedcheck(Inst *i)
57737da2899SCharles.Forsyth {
57837da2899SCharles.Forsyth if(RESCHED && i->d.ins <= i){
57937da2899SCharles.Forsyth con((ulong)&R, RTMP);
58037da2899SCharles.Forsyth /* sub $1, R.IC */
58137da2899SCharles.Forsyth modrm(0x83, O(REG, IC), RTMP, 5);
58237da2899SCharles.Forsyth genb(1);
58337da2899SCharles.Forsyth gen2(Ojgtb, 5);
58437da2899SCharles.Forsyth rbra(macro[MacRELQ], Ocall);
58537da2899SCharles.Forsyth }
58637da2899SCharles.Forsyth }
58737da2899SCharles.Forsyth
58837da2899SCharles.Forsyth static void
cbra(Inst * i,int jmp)58937da2899SCharles.Forsyth cbra(Inst *i, int jmp)
59037da2899SCharles.Forsyth {
59137da2899SCharles.Forsyth if(RESCHED)
59237da2899SCharles.Forsyth schedcheck(i);
59337da2899SCharles.Forsyth mid(i, Oldw, RAX);
59437da2899SCharles.Forsyth if(UXSRC(i->add) == SRC(AIMM)) {
59537da2899SCharles.Forsyth cmpl(RAX, i->s.imm);
59637da2899SCharles.Forsyth jmp = swapbraop(jmp);
59737da2899SCharles.Forsyth }
59837da2899SCharles.Forsyth else
59937da2899SCharles.Forsyth opwld(i, Ocmpw, RAX);
60037da2899SCharles.Forsyth genb(0x0f);
60137da2899SCharles.Forsyth rbra(patch[i->d.ins-mod->prog], jmp);
60237da2899SCharles.Forsyth }
60337da2899SCharles.Forsyth
60437da2899SCharles.Forsyth static void
cbral(Inst * i,int jmsw,int jlsw,int mode)60537da2899SCharles.Forsyth cbral(Inst *i, int jmsw, int jlsw, int mode)
60637da2899SCharles.Forsyth {
60737da2899SCharles.Forsyth ulong dst;
60837da2899SCharles.Forsyth uchar *label;
60937da2899SCharles.Forsyth
61037da2899SCharles.Forsyth if(RESCHED)
61137da2899SCharles.Forsyth schedcheck(i);
61237da2899SCharles.Forsyth opwld(i, Olea, RTMP);
61337da2899SCharles.Forsyth mid(i, Olea, RTA);
61437da2899SCharles.Forsyth modrm(Oldw, 4, RTA, RAX);
61537da2899SCharles.Forsyth modrm(Ocmpw, 4, RTMP, RAX);
61637da2899SCharles.Forsyth label = 0;
61737da2899SCharles.Forsyth dst = patch[i->d.ins-mod->prog];
61837da2899SCharles.Forsyth switch(mode) {
61937da2899SCharles.Forsyth case ANDAND:
62037da2899SCharles.Forsyth gen2(Ojneb, 0);
62137da2899SCharles.Forsyth label = code-1;
62237da2899SCharles.Forsyth break;
62337da2899SCharles.Forsyth case OROR:
62437da2899SCharles.Forsyth genb(0x0f);
62537da2899SCharles.Forsyth rbra(dst, jmsw);
62637da2899SCharles.Forsyth break;
62737da2899SCharles.Forsyth case EQAND:
62837da2899SCharles.Forsyth genb(0x0f);
62937da2899SCharles.Forsyth rbra(dst, jmsw);
63037da2899SCharles.Forsyth gen2(Ojneb, 0);
63137da2899SCharles.Forsyth label = code-1;
63237da2899SCharles.Forsyth break;
63337da2899SCharles.Forsyth }
63437da2899SCharles.Forsyth modrm(Oldw, 0, RTA, RAX);
63537da2899SCharles.Forsyth modrm(Ocmpw, 0, RTMP, RAX);
63637da2899SCharles.Forsyth genb(0x0f);
63737da2899SCharles.Forsyth rbra(dst, jlsw);
63837da2899SCharles.Forsyth if(label != nil)
63937da2899SCharles.Forsyth *label = code-label-1;
64037da2899SCharles.Forsyth }
64137da2899SCharles.Forsyth
64237da2899SCharles.Forsyth static void
cbrab(Inst * i,int jmp)64337da2899SCharles.Forsyth cbrab(Inst *i, int jmp)
64437da2899SCharles.Forsyth {
64537da2899SCharles.Forsyth if(RESCHED)
64637da2899SCharles.Forsyth schedcheck(i);
64737da2899SCharles.Forsyth mid(i, Oldb, RAX);
64837da2899SCharles.Forsyth if(UXSRC(i->add) == SRC(AIMM))
64937da2899SCharles.Forsyth urk();
65037da2899SCharles.Forsyth
65137da2899SCharles.Forsyth opwld(i, Ocmpb, RAX);
65237da2899SCharles.Forsyth genb(0x0f);
65337da2899SCharles.Forsyth rbra(patch[i->d.ins-mod->prog], jmp);
65437da2899SCharles.Forsyth }
65537da2899SCharles.Forsyth
65637da2899SCharles.Forsyth static void
cbraf(Inst * i,int jmp)65737da2899SCharles.Forsyth cbraf(Inst *i, int jmp)
65837da2899SCharles.Forsyth {
65937da2899SCharles.Forsyth if(RESCHED)
66037da2899SCharles.Forsyth schedcheck(i);
66137da2899SCharles.Forsyth opwld(i, Omovf, 0);
66237da2899SCharles.Forsyth mid(i, 0xdc, 3); // FCOMP
66337da2899SCharles.Forsyth genb(0x9b); // FWAIT
66437da2899SCharles.Forsyth gen2(0xdf, 0xe0); // FSTSW AX
66537da2899SCharles.Forsyth genb(0x9e); // SAHF
66637da2899SCharles.Forsyth
66737da2899SCharles.Forsyth genb(0x0f);
66837da2899SCharles.Forsyth rbra(patch[i->d.ins-mod->prog], jmp);
66937da2899SCharles.Forsyth }
67037da2899SCharles.Forsyth
67137da2899SCharles.Forsyth static void
comcase(Inst * i,int w)67237da2899SCharles.Forsyth comcase(Inst *i, int w)
67337da2899SCharles.Forsyth {
67437da2899SCharles.Forsyth int l;
67537da2899SCharles.Forsyth WORD *t, *e;
67637da2899SCharles.Forsyth
67737da2899SCharles.Forsyth if(w != 0) {
67837da2899SCharles.Forsyth opwld(i, Oldw, RAX); // v
67937da2899SCharles.Forsyth genb(Opushl+RSI);
68037da2899SCharles.Forsyth opwst(i, Olea, RSI); // table
68137da2899SCharles.Forsyth rbra(macro[MacCASE], Ojmp);
68237da2899SCharles.Forsyth }
68337da2899SCharles.Forsyth
68437da2899SCharles.Forsyth t = (WORD*)(mod->origmp+i->d.ind+4);
68537da2899SCharles.Forsyth l = t[-1];
68637da2899SCharles.Forsyth
68737da2899SCharles.Forsyth /* have to take care not to relocate the same table twice -
68837da2899SCharles.Forsyth * the limbo compiler can duplicate a case instruction
68937da2899SCharles.Forsyth * during its folding phase
69037da2899SCharles.Forsyth */
69137da2899SCharles.Forsyth
69237da2899SCharles.Forsyth if(pass == 0) {
69337da2899SCharles.Forsyth if(l >= 0)
69437da2899SCharles.Forsyth t[-1] = -l-1; /* Mark it not done */
69537da2899SCharles.Forsyth return;
69637da2899SCharles.Forsyth }
69737da2899SCharles.Forsyth if(l >= 0) /* Check pass 2 done */
69837da2899SCharles.Forsyth return;
69937da2899SCharles.Forsyth t[-1] = -l-1; /* Set real count */
70037da2899SCharles.Forsyth e = t + t[-1]*3;
70137da2899SCharles.Forsyth while(t < e) {
70237da2899SCharles.Forsyth t[2] = (ulong)base + patch[t[2]];
70337da2899SCharles.Forsyth t += 3;
70437da2899SCharles.Forsyth }
70537da2899SCharles.Forsyth t[0] = (ulong)base + patch[t[0]];
70637da2899SCharles.Forsyth }
70737da2899SCharles.Forsyth
70837da2899SCharles.Forsyth static void
comcasel(Inst * i)70937da2899SCharles.Forsyth comcasel(Inst *i)
71037da2899SCharles.Forsyth {
71137da2899SCharles.Forsyth int l;
71237da2899SCharles.Forsyth WORD *t, *e;
71337da2899SCharles.Forsyth
71437da2899SCharles.Forsyth t = (WORD*)(mod->origmp+i->d.ind+8);
71537da2899SCharles.Forsyth l = t[-2];
71637da2899SCharles.Forsyth if(pass == 0) {
71737da2899SCharles.Forsyth if(l >= 0)
71837da2899SCharles.Forsyth t[-2] = -l-1; /* Mark it not done */
71937da2899SCharles.Forsyth return;
72037da2899SCharles.Forsyth }
72137da2899SCharles.Forsyth if(l >= 0) /* Check pass 2 done */
72237da2899SCharles.Forsyth return;
72337da2899SCharles.Forsyth t[-2] = -l-1; /* Set real count */
72437da2899SCharles.Forsyth e = t + t[-2]*6;
72537da2899SCharles.Forsyth while(t < e) {
72637da2899SCharles.Forsyth t[4] = (ulong)base + patch[t[4]];
72737da2899SCharles.Forsyth t += 6;
72837da2899SCharles.Forsyth }
72937da2899SCharles.Forsyth t[0] = (ulong)base + patch[t[0]];
73037da2899SCharles.Forsyth }
73137da2899SCharles.Forsyth
73237da2899SCharles.Forsyth static void
commframe(Inst * i)73337da2899SCharles.Forsyth commframe(Inst *i)
73437da2899SCharles.Forsyth {
73537da2899SCharles.Forsyth int o;
73637da2899SCharles.Forsyth uchar *punt, *mlnil;
73737da2899SCharles.Forsyth
73837da2899SCharles.Forsyth opwld(i, Oldw, RAX);
73937da2899SCharles.Forsyth cmpl(RAX, (ulong)H);
74037da2899SCharles.Forsyth gen2(Ojeqb, 0);
74137da2899SCharles.Forsyth mlnil = code - 1;
74237da2899SCharles.Forsyth if((i->add&ARM) == AXIMM) {
74337da2899SCharles.Forsyth o = OA(Modlink, links)+i->reg*sizeof(Modl)+O(Modl, frame);
74437da2899SCharles.Forsyth modrm(Oldw, o, RAX, RTA);
74537da2899SCharles.Forsyth } else {
74637da2899SCharles.Forsyth gen2(Oldw, (3<<6)|(RTMP<<3)|RAX); // MOVL AX, RTMP
74737da2899SCharles.Forsyth mid(i, Oldw, RCX); // index
74837da2899SCharles.Forsyth gen2(Olea, (0<<6)|(0<<3)|4); // lea (AX)(RCX*8)
74937da2899SCharles.Forsyth genb((3<<6)|(RCX<<3)|RAX); // assumes sizeof(Modl) == 8 hence 3
75037da2899SCharles.Forsyth o = OA(Modlink, links)+O(Modl, frame);
75137da2899SCharles.Forsyth modrm(Oldw, o, RAX, RTA); // frame
75237da2899SCharles.Forsyth genb(OxchgAX+RTMP); // get old AX back
75337da2899SCharles.Forsyth }
75437da2899SCharles.Forsyth modrm(0x83, O(Type, initialize), RTA, 7);
75537da2899SCharles.Forsyth genb(0);
75637da2899SCharles.Forsyth gen2(Ojneb, 0);
75737da2899SCharles.Forsyth punt = code - 1;
75837da2899SCharles.Forsyth genb(OxchgAX+RTA);
75937da2899SCharles.Forsyth opwst(i, Olea, RTA);
76037da2899SCharles.Forsyth *mlnil = code-mlnil-1;
76137da2899SCharles.Forsyth rbra(macro[MacMFRA], Ocall);
76237da2899SCharles.Forsyth rbra(patch[i-mod->prog+1], Ojmp);
76337da2899SCharles.Forsyth
76437da2899SCharles.Forsyth *punt = code-punt-1;
76537da2899SCharles.Forsyth rbra(macro[MacFRAM], Ocall);
76637da2899SCharles.Forsyth opwst(i, Ostw, RCX);
76737da2899SCharles.Forsyth }
76837da2899SCharles.Forsyth
76937da2899SCharles.Forsyth static void
commcall(Inst * i)77037da2899SCharles.Forsyth commcall(Inst *i)
77137da2899SCharles.Forsyth {
77237da2899SCharles.Forsyth uchar *mlnil;
77337da2899SCharles.Forsyth
77437da2899SCharles.Forsyth con((ulong)&R, RTMP); // MOVL $R, RTMP
77537da2899SCharles.Forsyth opwld(i, Oldw, RCX);
77637da2899SCharles.Forsyth modrm(Omov, O(Frame, lr), RCX, 0); // MOVL $.+1, lr(CX) f->lr = R.PC
77737da2899SCharles.Forsyth genw((ulong)base+patch[i-mod->prog+1]);
77837da2899SCharles.Forsyth modrm(Ostw, O(Frame, fp), RCX, RFP); // MOVL RFP, fp(CX) f->fp = R.FP
77937da2899SCharles.Forsyth modrm(Oldw, O(REG, M), RTMP, RTA); // MOVL R.M, RTA
78037da2899SCharles.Forsyth modrm(Ostw, O(Frame, mr), RCX, RTA); // MOVL RTA, mr(CX) f->mr = R.M
78137da2899SCharles.Forsyth opwst(i, Oldw, RTA); // MOVL ml, RTA
78237da2899SCharles.Forsyth cmpl(RTA, (ulong)H);
78337da2899SCharles.Forsyth gen2(Ojeqb, 0);
78437da2899SCharles.Forsyth mlnil = code - 1;
78537da2899SCharles.Forsyth if((i->add&ARM) == AXIMM)
78637da2899SCharles.Forsyth modrm(Oldw, OA(Modlink, links)+i->reg*sizeof(Modl)+O(Modl, u.pc), RTA, RAX);
78737da2899SCharles.Forsyth else {
78837da2899SCharles.Forsyth genb(Opushl+RCX);
78937da2899SCharles.Forsyth mid(i, Oldw, RCX); // index
79037da2899SCharles.Forsyth gen2(Olea, (0<<6)|(0<<3)|4); // lea (RTA)(RCX*8)
79137da2899SCharles.Forsyth genb((3<<6)|(RCX<<3)|RTA); // assumes sizeof(Modl) == 8 hence 3
79237da2899SCharles.Forsyth modrm(Oldw, OA(Modlink, links)+O(Modl, u.pc), RAX, RAX);
79337da2899SCharles.Forsyth genb(Opopl+RCX);
79437da2899SCharles.Forsyth }
79537da2899SCharles.Forsyth *mlnil = code-mlnil-1;
79637da2899SCharles.Forsyth rbra(macro[MacMCAL], Ocall);
79737da2899SCharles.Forsyth }
79837da2899SCharles.Forsyth
79937da2899SCharles.Forsyth static void
larith(Inst * i,int op,int opc)80037da2899SCharles.Forsyth larith(Inst *i, int op, int opc)
80137da2899SCharles.Forsyth {
80237da2899SCharles.Forsyth opwld(i, Olea, RTMP);
80337da2899SCharles.Forsyth mid(i, Olea, RTA);
80437da2899SCharles.Forsyth modrm(Oldw, 0, RTA, RAX); // MOVL 0(RTA), AX
80537da2899SCharles.Forsyth modrm(op, 0, RTMP, RAX); // ADDL 0(RTMP), AX
80637da2899SCharles.Forsyth modrm(Oldw, 4, RTA, RCX); // MOVL 4(RTA), CX
80737da2899SCharles.Forsyth modrm(opc, 4, RTMP, RCX); // ADCL 4(RTMP), CX
80837da2899SCharles.Forsyth if((i->add&ARM) != AXNON)
80937da2899SCharles.Forsyth opwst(i, Olea, RTA);
81037da2899SCharles.Forsyth modrm(Ostw, 0, RTA, RAX);
81137da2899SCharles.Forsyth modrm(Ostw, 4, RTA, RCX);
81237da2899SCharles.Forsyth }
81337da2899SCharles.Forsyth
81437da2899SCharles.Forsyth static void
shll(Inst * i)81537da2899SCharles.Forsyth shll(Inst *i)
81637da2899SCharles.Forsyth {
81737da2899SCharles.Forsyth uchar *label, *label1;
81837da2899SCharles.Forsyth
81937da2899SCharles.Forsyth opwld(i, Oldw, RCX);
82037da2899SCharles.Forsyth mid(i, Olea, RTA);
82137da2899SCharles.Forsyth gen2(Otestib, (3<<6)|(0<<3)|RCX);
82237da2899SCharles.Forsyth genb(0x20);
82337da2899SCharles.Forsyth gen2(Ojneb, 0);
82437da2899SCharles.Forsyth label = code-1;
82537da2899SCharles.Forsyth modrm(Oldw, 0, RTA, RAX);
82637da2899SCharles.Forsyth modrm(Oldw, 4, RTA, RBX);
82737da2899SCharles.Forsyth genb(0x0f);
82837da2899SCharles.Forsyth gen2(Oshld, (3<<6)|(RAX<<3)|RBX);
82937da2899SCharles.Forsyth gen2(Oshl, (3<<6)|(4<<3)|RAX);
83037da2899SCharles.Forsyth gen2(Ojmpb, 0);
83137da2899SCharles.Forsyth label1 = code-1;
83237da2899SCharles.Forsyth *label = code-label-1;
83337da2899SCharles.Forsyth modrm(Oldw, 0, RTA, RBX);
83437da2899SCharles.Forsyth con(0, RAX);
83537da2899SCharles.Forsyth gen2(Oshl, (3<<6)|(4<<3)|RBX);
83637da2899SCharles.Forsyth *label1 = code-label1-1;
83737da2899SCharles.Forsyth opwst(i, Olea, RTA);
83837da2899SCharles.Forsyth modrm(Ostw, 0, RTA, RAX);
83937da2899SCharles.Forsyth modrm(Ostw, 4, RTA, RBX);
84037da2899SCharles.Forsyth }
84137da2899SCharles.Forsyth
84237da2899SCharles.Forsyth static void
shrl(Inst * i)84337da2899SCharles.Forsyth shrl(Inst *i)
84437da2899SCharles.Forsyth {
84537da2899SCharles.Forsyth uchar *label, *label1;
84637da2899SCharles.Forsyth
84737da2899SCharles.Forsyth opwld(i, Oldw, RCX);
84837da2899SCharles.Forsyth mid(i, Olea, RTA);
84937da2899SCharles.Forsyth gen2(Otestib, (3<<6)|(0<<3)|RCX);
85037da2899SCharles.Forsyth genb(0x20);
85137da2899SCharles.Forsyth gen2(Ojneb, 0);
85237da2899SCharles.Forsyth label = code-1;
85337da2899SCharles.Forsyth modrm(Oldw, 0, RTA, RAX);
85437da2899SCharles.Forsyth modrm(Oldw, 4, RTA, RBX);
85537da2899SCharles.Forsyth genb(0x0f);
85637da2899SCharles.Forsyth gen2(Oshrd, (3<<6)|(RBX<<3)|RAX);
85737da2899SCharles.Forsyth gen2(Osar, (3<<6)|(7<<3)|RBX);
85837da2899SCharles.Forsyth gen2(Ojmpb, 0);
85937da2899SCharles.Forsyth label1 = code-1;
86037da2899SCharles.Forsyth *label = code-label-1;
86137da2899SCharles.Forsyth modrm(Oldw, 4, RTA, RBX);
86237da2899SCharles.Forsyth gen2(Oldw, (3<<6)|(RAX<<3)|RBX);
86337da2899SCharles.Forsyth gen2(Osarimm, (3<<6)|(7<<3)|RBX);
86437da2899SCharles.Forsyth genb(0x1f);
86537da2899SCharles.Forsyth gen2(Osar, (3<<6)|(7<<3)|RAX);
86637da2899SCharles.Forsyth *label1 = code-label1-1;
86737da2899SCharles.Forsyth opwst(i, Olea, RTA);
86837da2899SCharles.Forsyth modrm(Ostw, 0, RTA, RAX);
86937da2899SCharles.Forsyth modrm(Ostw, 4, RTA, RBX);
87037da2899SCharles.Forsyth }
87137da2899SCharles.Forsyth
87237da2899SCharles.Forsyth static
87337da2899SCharles.Forsyth void
compdbg(void)87437da2899SCharles.Forsyth compdbg(void)
87537da2899SCharles.Forsyth {
87637da2899SCharles.Forsyth print("%s:%lud@%.8lux\n", R.M->m->name, *(ulong*)R.m, *(ulong*)R.s);
87737da2899SCharles.Forsyth }
87837da2899SCharles.Forsyth
87937da2899SCharles.Forsyth static void
comp(Inst * i)88037da2899SCharles.Forsyth comp(Inst *i)
88137da2899SCharles.Forsyth {
88237da2899SCharles.Forsyth int r;
88337da2899SCharles.Forsyth WORD *t, *e;
88437da2899SCharles.Forsyth char buf[64];
88537da2899SCharles.Forsyth
88637da2899SCharles.Forsyth if(0) {
88737da2899SCharles.Forsyth Inst xx;
88837da2899SCharles.Forsyth xx.add = AXIMM|SRC(AIMM);
88937da2899SCharles.Forsyth xx.s.imm = (ulong)code;
89037da2899SCharles.Forsyth xx.reg = i-mod->prog;
89137da2899SCharles.Forsyth punt(&xx, SRCOP, compdbg);
89237da2899SCharles.Forsyth }
89337da2899SCharles.Forsyth
89437da2899SCharles.Forsyth switch(i->op) {
89537da2899SCharles.Forsyth default:
89637da2899SCharles.Forsyth snprint(buf, sizeof buf, "%s compile, no '%D'", mod->name, i);
89737da2899SCharles.Forsyth error(buf);
89837da2899SCharles.Forsyth break;
89937da2899SCharles.Forsyth case IMCALL:
90037da2899SCharles.Forsyth if((i->add&ARM) == AXIMM)
90137da2899SCharles.Forsyth commcall(i);
90237da2899SCharles.Forsyth else
90337da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|THREOP|WRTPC|NEWPC, optab[i->op]);
90437da2899SCharles.Forsyth break;
90537da2899SCharles.Forsyth case ISEND:
90637da2899SCharles.Forsyth case IRECV:
90737da2899SCharles.Forsyth case IALT:
90837da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|TCHECK|WRTPC, optab[i->op]);
90937da2899SCharles.Forsyth break;
91037da2899SCharles.Forsyth case ISPAWN:
91137da2899SCharles.Forsyth punt(i, SRCOP|DBRAN, optab[i->op]);
91237da2899SCharles.Forsyth break;
91337da2899SCharles.Forsyth case IBNEC:
91437da2899SCharles.Forsyth case IBEQC:
91537da2899SCharles.Forsyth case IBLTC:
91637da2899SCharles.Forsyth case IBLEC:
91737da2899SCharles.Forsyth case IBGTC:
91837da2899SCharles.Forsyth case IBGEC:
91937da2899SCharles.Forsyth punt(i, SRCOP|DBRAN|NEWPC|WRTPC, optab[i->op]);
92037da2899SCharles.Forsyth break;
92137da2899SCharles.Forsyth case ICASEC:
92237da2899SCharles.Forsyth comcase(i, 0);
92337da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|NEWPC, optab[i->op]);
92437da2899SCharles.Forsyth break;
92537da2899SCharles.Forsyth case ICASEL:
92637da2899SCharles.Forsyth comcasel(i);
92737da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|NEWPC, optab[i->op]);
92837da2899SCharles.Forsyth break;
92937da2899SCharles.Forsyth case IADDC:
93037da2899SCharles.Forsyth case IMULL:
93137da2899SCharles.Forsyth case IDIVL:
93237da2899SCharles.Forsyth case IMODL:
93337da2899SCharles.Forsyth case IMNEWZ:
93437da2899SCharles.Forsyth case ILSRW:
93537da2899SCharles.Forsyth case ILSRL:
93637da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
93737da2899SCharles.Forsyth break;
93837da2899SCharles.Forsyth case ILOAD:
93937da2899SCharles.Forsyth case INEWA:
94037da2899SCharles.Forsyth case INEWAZ:
94137da2899SCharles.Forsyth case INEW:
94237da2899SCharles.Forsyth case INEWZ:
94337da2899SCharles.Forsyth case ISLICEA:
94437da2899SCharles.Forsyth case ISLICELA:
94537da2899SCharles.Forsyth case ICONSB:
94637da2899SCharles.Forsyth case ICONSW:
94737da2899SCharles.Forsyth case ICONSL:
94837da2899SCharles.Forsyth case ICONSF:
94937da2899SCharles.Forsyth case ICONSM:
95037da2899SCharles.Forsyth case ICONSMP:
95137da2899SCharles.Forsyth case ICONSP:
95237da2899SCharles.Forsyth case IMOVMP:
95337da2899SCharles.Forsyth case IHEADMP:
95437da2899SCharles.Forsyth case IHEADL:
95537da2899SCharles.Forsyth case IINSC:
95637da2899SCharles.Forsyth case ICVTAC:
95737da2899SCharles.Forsyth case ICVTCW:
95837da2899SCharles.Forsyth case ICVTWC:
95937da2899SCharles.Forsyth case ICVTLC:
96037da2899SCharles.Forsyth case ICVTCL:
96137da2899SCharles.Forsyth case ICVTFC:
96237da2899SCharles.Forsyth case ICVTCF:
96337da2899SCharles.Forsyth case ICVTRF:
96437da2899SCharles.Forsyth case ICVTFR:
96537da2899SCharles.Forsyth case ICVTWS:
96637da2899SCharles.Forsyth case ICVTSW:
96737da2899SCharles.Forsyth case IMSPAWN:
96837da2899SCharles.Forsyth case ICVTCA:
96937da2899SCharles.Forsyth case ISLICEC:
97037da2899SCharles.Forsyth case INBALT:
97137da2899SCharles.Forsyth punt(i, SRCOP|DSTOP, optab[i->op]);
97237da2899SCharles.Forsyth break;
97337da2899SCharles.Forsyth case INEWCM:
97437da2899SCharles.Forsyth case INEWCMP:
97537da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
97637da2899SCharles.Forsyth break;
97737da2899SCharles.Forsyth case IMFRAME:
97837da2899SCharles.Forsyth if((i->add&ARM) == AXIMM)
97937da2899SCharles.Forsyth commframe(i);
98037da2899SCharles.Forsyth else
98137da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
98237da2899SCharles.Forsyth break;
98337da2899SCharles.Forsyth case INEWCB:
98437da2899SCharles.Forsyth case INEWCW:
98537da2899SCharles.Forsyth case INEWCF:
98637da2899SCharles.Forsyth case INEWCP:
98737da2899SCharles.Forsyth case INEWCL:
98837da2899SCharles.Forsyth punt(i, DSTOP|THREOP, optab[i->op]);
98937da2899SCharles.Forsyth break;
99037da2899SCharles.Forsyth case IEXIT:
99137da2899SCharles.Forsyth punt(i, 0, optab[i->op]);
99237da2899SCharles.Forsyth break;
99337da2899SCharles.Forsyth case ICVTBW:
99437da2899SCharles.Forsyth opwld(i, Oldb, RAX);
99537da2899SCharles.Forsyth genb(0x0f);
99637da2899SCharles.Forsyth gen2(0xb6, (3<<6)|(RAX<<3)|RAX);
99737da2899SCharles.Forsyth opwst(i, Ostw, RAX);
99837da2899SCharles.Forsyth break;
99937da2899SCharles.Forsyth case ICVTWB:
100037da2899SCharles.Forsyth opwld(i, Oldw, RAX);
100137da2899SCharles.Forsyth opwst(i, Ostb, RAX);
100237da2899SCharles.Forsyth break;
100337da2899SCharles.Forsyth case ICVTFW:
100437da2899SCharles.Forsyth if(1){
100537da2899SCharles.Forsyth punt(i, SRCOP|DSTOP, optab[i->op]);
100637da2899SCharles.Forsyth break;
100737da2899SCharles.Forsyth }
100837da2899SCharles.Forsyth opwld(i, Omovf, 0);
100937da2899SCharles.Forsyth opwst(i, 0xdb, 3);
101037da2899SCharles.Forsyth break;
101137da2899SCharles.Forsyth case ICVTWF:
101237da2899SCharles.Forsyth if(1){
101337da2899SCharles.Forsyth punt(i, SRCOP|DSTOP, optab[i->op]);
101437da2899SCharles.Forsyth break;
101537da2899SCharles.Forsyth }
101637da2899SCharles.Forsyth opwld(i, 0xdb, 0);
101737da2899SCharles.Forsyth opwst(i, Omovf, 3);
101837da2899SCharles.Forsyth break;
101937da2899SCharles.Forsyth case ICVTLF:
102037da2899SCharles.Forsyth if(1){
102137da2899SCharles.Forsyth punt(i, SRCOP|DSTOP, optab[i->op]);
102237da2899SCharles.Forsyth break;
102337da2899SCharles.Forsyth }
102437da2899SCharles.Forsyth opwld(i, 0xdf, 5);
102537da2899SCharles.Forsyth opwst(i, Omovf, 3);
102637da2899SCharles.Forsyth break;
102737da2899SCharles.Forsyth case ICVTFL:
102837da2899SCharles.Forsyth if(1){
102937da2899SCharles.Forsyth punt(i, SRCOP|DSTOP, optab[i->op]);
103037da2899SCharles.Forsyth break;
103137da2899SCharles.Forsyth }
103237da2899SCharles.Forsyth opwld(i, Omovf, 0);
103337da2899SCharles.Forsyth opwst(i, 0xdf, 7);
103437da2899SCharles.Forsyth break;
103537da2899SCharles.Forsyth case IHEADM:
103637da2899SCharles.Forsyth opwld(i, Oldw, RAX);
103737da2899SCharles.Forsyth modrm(Olea, OA(List, data), RAX, RAX);
103837da2899SCharles.Forsyth goto movm;
103937da2899SCharles.Forsyth case IMOVM:
104037da2899SCharles.Forsyth opwld(i, Olea, RAX);
104137da2899SCharles.Forsyth movm:
104237da2899SCharles.Forsyth opwst(i, Olea, RBX);
104337da2899SCharles.Forsyth mid(i, Oldw, RCX);
104437da2899SCharles.Forsyth genb(OxchgAX+RSI);
104537da2899SCharles.Forsyth gen2(Oxchg, (3<<6)|(RDI<<3)|RBX);
104637da2899SCharles.Forsyth genb(Ocld);
104737da2899SCharles.Forsyth gen2(Orep, Omovsb);
104837da2899SCharles.Forsyth genb(OxchgAX+RSI);
104937da2899SCharles.Forsyth gen2(Oxchg, (3<<6)|(RDI<<3)|RBX);
105037da2899SCharles.Forsyth break;
105137da2899SCharles.Forsyth case IRET:
105237da2899SCharles.Forsyth rbra(macro[MacRET], Ojmp);
105337da2899SCharles.Forsyth break;
105437da2899SCharles.Forsyth case IFRAME:
105537da2899SCharles.Forsyth if(UXSRC(i->add) != SRC(AIMM)) {
105637da2899SCharles.Forsyth punt(i, SRCOP|DSTOP, optab[i->op]);
105737da2899SCharles.Forsyth break;
105837da2899SCharles.Forsyth }
105937da2899SCharles.Forsyth tinit[i->s.imm] = 1;
106037da2899SCharles.Forsyth con((ulong)mod->type[i->s.imm], RTA);
106137da2899SCharles.Forsyth rbra(macro[MacFRAM], Ocall);
106237da2899SCharles.Forsyth opwst(i, Ostw, RCX);
106337da2899SCharles.Forsyth break;
106437da2899SCharles.Forsyth case ILEA:
106537da2899SCharles.Forsyth if(UXSRC(i->add) == SRC(AIMM)) {
106637da2899SCharles.Forsyth gen2(Ojmpb, 4);
106737da2899SCharles.Forsyth genw(i->s.imm);
106837da2899SCharles.Forsyth con((ulong)(code-4), RAX);
106937da2899SCharles.Forsyth }
107037da2899SCharles.Forsyth else
107137da2899SCharles.Forsyth opwld(i, Olea, RAX);
107237da2899SCharles.Forsyth opwst(i, Ostw, RAX);
107337da2899SCharles.Forsyth break;
107437da2899SCharles.Forsyth case IHEADW:
107537da2899SCharles.Forsyth opwld(i, Oldw, RAX);
107637da2899SCharles.Forsyth modrm(Oldw, OA(List, data), RAX, RAX);
107737da2899SCharles.Forsyth opwst(i, Ostw, RAX);
107837da2899SCharles.Forsyth break;
107937da2899SCharles.Forsyth case IHEADF:
108037da2899SCharles.Forsyth opwld(i, Oldw, RAX);
108137da2899SCharles.Forsyth modrm(Omovf, OA(List, data), RAX, 0);
108237da2899SCharles.Forsyth opwst(i, Omovf, 3);
108337da2899SCharles.Forsyth break;
108437da2899SCharles.Forsyth case IHEADB:
108537da2899SCharles.Forsyth opwld(i, Oldw, RAX);
108637da2899SCharles.Forsyth modrm(Oldb, OA(List, data), RAX, RAX);
108737da2899SCharles.Forsyth opwst(i, Ostb, RAX);
108837da2899SCharles.Forsyth break;
108937da2899SCharles.Forsyth case ITAIL:
109037da2899SCharles.Forsyth opwld(i, Oldw, RAX);
109137da2899SCharles.Forsyth modrm(Oldw, O(List, tail), RAX, RBX);
109237da2899SCharles.Forsyth goto movp;
109337da2899SCharles.Forsyth case IMOVP:
109437da2899SCharles.Forsyth case IHEADP:
109537da2899SCharles.Forsyth opwld(i, Oldw, RBX);
109637da2899SCharles.Forsyth if(i->op == IHEADP)
109737da2899SCharles.Forsyth modrm(Oldw, OA(List, data), RBX, RBX);
109837da2899SCharles.Forsyth movp:
109937da2899SCharles.Forsyth cmpl(RBX, (ulong)H);
110037da2899SCharles.Forsyth gen2(Ojeqb, 0x05);
110137da2899SCharles.Forsyth rbra(macro[MacCOLR], Ocall);
110237da2899SCharles.Forsyth opwst(i, Oldw, RAX);
110337da2899SCharles.Forsyth opwst(i, Ostw, RBX);
110437da2899SCharles.Forsyth rbra(macro[MacFRP], Ocall);
110537da2899SCharles.Forsyth break;
110637da2899SCharles.Forsyth case ILENA:
110737da2899SCharles.Forsyth opwld(i, Oldw, RBX);
110837da2899SCharles.Forsyth con(0, RAX);
110937da2899SCharles.Forsyth cmpl(RBX, (ulong)H);
111037da2899SCharles.Forsyth gen2(Ojeqb, 0x02);
111137da2899SCharles.Forsyth modrm(Oldw, O(Array, len), RBX, RAX);
111237da2899SCharles.Forsyth opwst(i, Ostw, RAX);
111337da2899SCharles.Forsyth break;
111437da2899SCharles.Forsyth case ILENC:
111537da2899SCharles.Forsyth opwld(i, Oldw, RBX);
111637da2899SCharles.Forsyth con(0, RAX);
111737da2899SCharles.Forsyth cmpl(RBX, (ulong)H);
111837da2899SCharles.Forsyth gen2(Ojeqb, 0x09);
111937da2899SCharles.Forsyth modrm(Oldw, O(String, len), RBX, RAX);
112037da2899SCharles.Forsyth cmpl(RAX, 0);
112137da2899SCharles.Forsyth gen2(Ojgeb, 0x02);
112237da2899SCharles.Forsyth gen2(Oneg, (3<<6)|(3<<3)|RAX);
112337da2899SCharles.Forsyth opwst(i, Ostw, RAX);
112437da2899SCharles.Forsyth break;
112537da2899SCharles.Forsyth case ILENL:
112637da2899SCharles.Forsyth con(0, RAX);
112737da2899SCharles.Forsyth opwld(i, Oldw, RBX);
112837da2899SCharles.Forsyth cmpl(RBX, (ulong)H);
112937da2899SCharles.Forsyth gen2(Ojeqb, 0x05);
113037da2899SCharles.Forsyth modrm(Oldw, O(List, tail), RBX, RBX);
113137da2899SCharles.Forsyth genb(Oincr+RAX);
113237da2899SCharles.Forsyth gen2(Ojmpb, 0xf6);
113337da2899SCharles.Forsyth opwst(i, Ostw, RAX);
113437da2899SCharles.Forsyth break;
113537da2899SCharles.Forsyth case IBEQF:
113637da2899SCharles.Forsyth cbraf(i, Ojeql);
113737da2899SCharles.Forsyth break;
113837da2899SCharles.Forsyth case IBNEF:
113937da2899SCharles.Forsyth cbraf(i, Ojnel);
114037da2899SCharles.Forsyth break;
114137da2899SCharles.Forsyth case IBLEF:
114237da2899SCharles.Forsyth cbraf(i, Ojlsl);
114337da2899SCharles.Forsyth break;
114437da2899SCharles.Forsyth case IBLTF:
114537da2899SCharles.Forsyth cbraf(i, Ojcsl);
114637da2899SCharles.Forsyth break;
114737da2899SCharles.Forsyth case IBGEF:
114837da2899SCharles.Forsyth cbraf(i, Ojccl);
114937da2899SCharles.Forsyth break;
115037da2899SCharles.Forsyth case IBGTF:
115137da2899SCharles.Forsyth cbraf(i, Ojhil);
115237da2899SCharles.Forsyth break;
115337da2899SCharles.Forsyth case IBEQW:
115437da2899SCharles.Forsyth cbra(i, Ojeql);
115537da2899SCharles.Forsyth break;
115637da2899SCharles.Forsyth case IBLEW:
115737da2899SCharles.Forsyth cbra(i, Ojlel);
115837da2899SCharles.Forsyth break;
115937da2899SCharles.Forsyth case IBNEW:
116037da2899SCharles.Forsyth cbra(i, Ojnel);
116137da2899SCharles.Forsyth break;
116237da2899SCharles.Forsyth case IBGTW:
116337da2899SCharles.Forsyth cbra(i, Ojgtl);
116437da2899SCharles.Forsyth break;
116537da2899SCharles.Forsyth case IBLTW:
116637da2899SCharles.Forsyth cbra(i, Ojltl);
116737da2899SCharles.Forsyth break;
116837da2899SCharles.Forsyth case IBGEW:
116937da2899SCharles.Forsyth cbra(i, Ojgel);
117037da2899SCharles.Forsyth break;
117137da2899SCharles.Forsyth case IBEQB:
117237da2899SCharles.Forsyth cbrab(i, Ojeql);
117337da2899SCharles.Forsyth break;
117437da2899SCharles.Forsyth case IBLEB:
117537da2899SCharles.Forsyth cbrab(i, Ojlsl);
117637da2899SCharles.Forsyth break;
117737da2899SCharles.Forsyth case IBNEB:
117837da2899SCharles.Forsyth cbrab(i, Ojnel);
117937da2899SCharles.Forsyth break;
118037da2899SCharles.Forsyth case IBGTB:
118137da2899SCharles.Forsyth cbrab(i, Ojhil);
118237da2899SCharles.Forsyth break;
118337da2899SCharles.Forsyth case IBLTB:
118437da2899SCharles.Forsyth cbrab(i, Ojbl);
118537da2899SCharles.Forsyth break;
118637da2899SCharles.Forsyth case IBGEB:
118737da2899SCharles.Forsyth cbrab(i, Ojael);
118837da2899SCharles.Forsyth break;
118937da2899SCharles.Forsyth case ISUBW:
119037da2899SCharles.Forsyth arith(i, 0x29, 5);
119137da2899SCharles.Forsyth break;
119237da2899SCharles.Forsyth case ISUBB:
119337da2899SCharles.Forsyth arithb(i, 0x28);
119437da2899SCharles.Forsyth break;
119537da2899SCharles.Forsyth case ISUBF:
119637da2899SCharles.Forsyth arithf(i, 5);
119737da2899SCharles.Forsyth break;
119837da2899SCharles.Forsyth case IADDW:
119937da2899SCharles.Forsyth arith(i, 0x01, 0);
120037da2899SCharles.Forsyth break;
120137da2899SCharles.Forsyth case IADDB:
120237da2899SCharles.Forsyth arithb(i, 0x00);
120337da2899SCharles.Forsyth break;
120437da2899SCharles.Forsyth case IADDF:
120537da2899SCharles.Forsyth arithf(i, 0);
120637da2899SCharles.Forsyth break;
120737da2899SCharles.Forsyth case IORW:
120837da2899SCharles.Forsyth arith(i, 0x09, 1);
120937da2899SCharles.Forsyth break;
121037da2899SCharles.Forsyth case IORB:
121137da2899SCharles.Forsyth arithb(i, 0x08);
121237da2899SCharles.Forsyth break;
121337da2899SCharles.Forsyth case IANDW:
121437da2899SCharles.Forsyth arith(i, 0x21, 4);
121537da2899SCharles.Forsyth break;
121637da2899SCharles.Forsyth case IANDB:
121737da2899SCharles.Forsyth arithb(i, 0x20);
121837da2899SCharles.Forsyth break;
121937da2899SCharles.Forsyth case IXORW:
122037da2899SCharles.Forsyth arith(i, Oxor, 6);
122137da2899SCharles.Forsyth break;
122237da2899SCharles.Forsyth case IXORB:
122337da2899SCharles.Forsyth arithb(i, 0x30);
122437da2899SCharles.Forsyth break;
122537da2899SCharles.Forsyth case ISHLW:
122637da2899SCharles.Forsyth shift(i, Oldw, Ostw, 0xd3, 4);
122737da2899SCharles.Forsyth break;
122837da2899SCharles.Forsyth case ISHLB:
122937da2899SCharles.Forsyth shift(i, Oldb, Ostb, 0xd2, 4);
123037da2899SCharles.Forsyth break;
123137da2899SCharles.Forsyth case ISHRW:
123237da2899SCharles.Forsyth shift(i, Oldw, Ostw, 0xd3, 7);
123337da2899SCharles.Forsyth break;
123437da2899SCharles.Forsyth case ISHRB:
123537da2899SCharles.Forsyth shift(i, Oldb, Ostb, 0xd2, 5);
123637da2899SCharles.Forsyth break;
123737da2899SCharles.Forsyth case IMOVF:
123837da2899SCharles.Forsyth opwld(i, Omovf, 0);
123937da2899SCharles.Forsyth opwst(i, Omovf, 3);
124037da2899SCharles.Forsyth break;
124137da2899SCharles.Forsyth case INEGF:
124237da2899SCharles.Forsyth opwld(i, Omovf, 0);
124337da2899SCharles.Forsyth genb(0xd9);
124437da2899SCharles.Forsyth genb(0xe0);
124537da2899SCharles.Forsyth opwst(i, Omovf, 3);
124637da2899SCharles.Forsyth break;
124737da2899SCharles.Forsyth case IMOVB:
124837da2899SCharles.Forsyth opwld(i, Oldb, RAX);
124937da2899SCharles.Forsyth opwst(i, Ostb, RAX);
125037da2899SCharles.Forsyth break;
125137da2899SCharles.Forsyth case IMOVW:
125237da2899SCharles.Forsyth case ICVTLW: // Little endian
125337da2899SCharles.Forsyth if(UXSRC(i->add) == SRC(AIMM)) {
125437da2899SCharles.Forsyth opwst(i, Omov, RAX);
125537da2899SCharles.Forsyth genw(i->s.imm);
125637da2899SCharles.Forsyth break;
125737da2899SCharles.Forsyth }
125837da2899SCharles.Forsyth opwld(i, Oldw, RAX);
125937da2899SCharles.Forsyth opwst(i, Ostw, RAX);
126037da2899SCharles.Forsyth break;
126137da2899SCharles.Forsyth case ICVTWL:
126237da2899SCharles.Forsyth opwst(i, Olea, RTMP);
126337da2899SCharles.Forsyth opwld(i, Oldw, RAX);
126437da2899SCharles.Forsyth modrm(Ostw, 0, RTMP, RAX);
126537da2899SCharles.Forsyth genb(0x99);
126637da2899SCharles.Forsyth modrm(Ostw, 4, RTMP, RDX);
126737da2899SCharles.Forsyth break;
126837da2899SCharles.Forsyth case ICALL:
126937da2899SCharles.Forsyth if(UXDST(i->add) != DST(AIMM))
127037da2899SCharles.Forsyth opwst(i, Oldw, RTA);
127137da2899SCharles.Forsyth opwld(i, Oldw, RAX);
127237da2899SCharles.Forsyth modrm(Omov, O(Frame, lr), RAX, 0); // MOVL $.+1, lr(AX)
127337da2899SCharles.Forsyth genw((ulong)base+patch[i-mod->prog+1]);
127437da2899SCharles.Forsyth modrm(Ostw, O(Frame, fp), RAX, RFP); // MOVL RFP, fp(AX)
127537da2899SCharles.Forsyth gen2(Oldw, (3<<6)|(RFP<<3)|RAX); // MOVL AX,RFP
127637da2899SCharles.Forsyth if(UXDST(i->add) != DST(AIMM)){
127737da2899SCharles.Forsyth gen2(Ojmprm, (3<<6)|(4<<3)|RTA);
127837da2899SCharles.Forsyth break;
127937da2899SCharles.Forsyth }
128037da2899SCharles.Forsyth /* no break */
128137da2899SCharles.Forsyth case IJMP:
128237da2899SCharles.Forsyth if(RESCHED)
128337da2899SCharles.Forsyth schedcheck(i);
128437da2899SCharles.Forsyth rbra(patch[i->d.ins-mod->prog], Ojmp);
128537da2899SCharles.Forsyth break;
128637da2899SCharles.Forsyth case IMOVPC:
128737da2899SCharles.Forsyth opwst(i, Omov, RAX);
128837da2899SCharles.Forsyth genw(patch[i->s.imm]+(ulong)base);
128937da2899SCharles.Forsyth break;
129037da2899SCharles.Forsyth case IGOTO:
129137da2899SCharles.Forsyth opwst(i, Olea, RBX);
129237da2899SCharles.Forsyth opwld(i, Oldw, RAX);
129337da2899SCharles.Forsyth gen2(Ojmprm, (0<<6)|(4<<3)|4);
129437da2899SCharles.Forsyth genb((2<<6)|(RAX<<3)|RBX);
129537da2899SCharles.Forsyth
129637da2899SCharles.Forsyth if(pass == 0)
129737da2899SCharles.Forsyth break;
129837da2899SCharles.Forsyth
129937da2899SCharles.Forsyth t = (WORD*)(mod->origmp+i->d.ind);
130037da2899SCharles.Forsyth e = t + t[-1];
130137da2899SCharles.Forsyth t[-1] = 0;
130237da2899SCharles.Forsyth while(t < e) {
130337da2899SCharles.Forsyth t[0] = (ulong)base + patch[t[0]];
130437da2899SCharles.Forsyth t++;
130537da2899SCharles.Forsyth }
130637da2899SCharles.Forsyth break;
130737da2899SCharles.Forsyth case IMULF:
130837da2899SCharles.Forsyth arithf(i, 1);
130937da2899SCharles.Forsyth break;
131037da2899SCharles.Forsyth case IDIVF:
131137da2899SCharles.Forsyth arithf(i, 7);
131237da2899SCharles.Forsyth break;
131337da2899SCharles.Forsyth case IMODW:
131437da2899SCharles.Forsyth case IDIVW:
131537da2899SCharles.Forsyth case IMULW:
131637da2899SCharles.Forsyth mid(i, Oldw, RAX);
131737da2899SCharles.Forsyth opwld(i, Oldw, RTMP);
131837da2899SCharles.Forsyth if(i->op == IMULW)
131937da2899SCharles.Forsyth gen2(0xf7, (3<<6)|(4<<3)|RTMP);
132037da2899SCharles.Forsyth else {
132137da2899SCharles.Forsyth genb(Ocdq);
132237da2899SCharles.Forsyth gen2(0xf7, (3<<6)|(7<<3)|RTMP); // IDIV AX, RTMP
132337da2899SCharles.Forsyth if(i->op == IMODW)
132437da2899SCharles.Forsyth genb(0x90+RDX); // XCHG AX, DX
132537da2899SCharles.Forsyth }
132637da2899SCharles.Forsyth opwst(i, Ostw, RAX);
132737da2899SCharles.Forsyth break;
132837da2899SCharles.Forsyth case IMODB:
132937da2899SCharles.Forsyth case IDIVB:
133037da2899SCharles.Forsyth case IMULB:
133137da2899SCharles.Forsyth mid(i, Oldb, RAX);
133237da2899SCharles.Forsyth opwld(i, Oldb, RTMP);
133337da2899SCharles.Forsyth if(i->op == IMULB)
133437da2899SCharles.Forsyth gen2(0xf6, (3<<6)|(4<<3)|RTMP);
133537da2899SCharles.Forsyth else {
133637da2899SCharles.Forsyth genb(Ocdq);
133737da2899SCharles.Forsyth gen2(0xf6, (3<<6)|(7<<3)|RTMP); // IDIV AX, RTMP
133837da2899SCharles.Forsyth if(i->op == IMODB)
133937da2899SCharles.Forsyth genb(0x90+RDX); // XCHG AX, DX
134037da2899SCharles.Forsyth }
134137da2899SCharles.Forsyth opwst(i, Ostb, RAX);
134237da2899SCharles.Forsyth break;
134337da2899SCharles.Forsyth case IINDX:
134437da2899SCharles.Forsyth opwld(i, Oldw, RTMP); // MOVW xx(s), BX
134537da2899SCharles.Forsyth
134637da2899SCharles.Forsyth if(bflag){
134737da2899SCharles.Forsyth opwst(i, Oldw, RAX);
134837da2899SCharles.Forsyth modrm(0x3b, O(Array, len), RTMP, RAX); /* CMP index, len */
134937da2899SCharles.Forsyth gen2(0x72, 5); /* JB */
135037da2899SCharles.Forsyth bra((ulong)bounds, Ocall);
135137da2899SCharles.Forsyth modrm(Oldw, O(Array, t), RTMP, RTA);
135237da2899SCharles.Forsyth modrm(0xf7, O(Type, size), RTA, 5); /* IMULL AX, xx(t) */
135337da2899SCharles.Forsyth }
135437da2899SCharles.Forsyth else{
135537da2899SCharles.Forsyth modrm(Oldw, O(Array, t), RTMP, RAX); // MOVW t(BX), AX
135637da2899SCharles.Forsyth modrm(Oldw, O(Type, size), RAX, RAX); // MOVW size(AX), AX
135737da2899SCharles.Forsyth if(UXDST(i->add) == DST(AIMM)) {
135837da2899SCharles.Forsyth gen2(0x69, (3<<6)|(RAX<<3)|0);
135937da2899SCharles.Forsyth genw(i->d.imm);
136037da2899SCharles.Forsyth }
136137da2899SCharles.Forsyth else
136237da2899SCharles.Forsyth opwst(i, 0xf7, 5); // IMULL AX,xx(d)
136337da2899SCharles.Forsyth }
136437da2899SCharles.Forsyth
136537da2899SCharles.Forsyth modrm(0x03, O(Array, data), RBX, RAX); // ADDL data(BX), AX
136637da2899SCharles.Forsyth r = RMP;
136737da2899SCharles.Forsyth if((i->add&ARM) == AXINF)
136837da2899SCharles.Forsyth r = RFP;
136937da2899SCharles.Forsyth modrm(Ostw, i->reg, r, RAX);
137037da2899SCharles.Forsyth break;
137137da2899SCharles.Forsyth case IINDB:
137237da2899SCharles.Forsyth r = 0;
137337da2899SCharles.Forsyth goto idx;
137437da2899SCharles.Forsyth case IINDF:
137537da2899SCharles.Forsyth case IINDL:
137637da2899SCharles.Forsyth r = 3;
137737da2899SCharles.Forsyth goto idx;
137837da2899SCharles.Forsyth case IINDW:
137937da2899SCharles.Forsyth r = 2;
138037da2899SCharles.Forsyth idx:
138137da2899SCharles.Forsyth opwld(i, Oldw, RAX);
138237da2899SCharles.Forsyth opwst(i, Oldw, RTMP);
138337da2899SCharles.Forsyth if(bflag){
138437da2899SCharles.Forsyth modrm(0x3b, O(Array, len), RAX, RTMP); /* CMP index, len */
138537da2899SCharles.Forsyth gen2(0x72, 5); /* JB */
138637da2899SCharles.Forsyth bra((ulong)bounds, Ocall);
138737da2899SCharles.Forsyth }
138837da2899SCharles.Forsyth modrm(Oldw, O(Array, data), RAX, RAX);
138937da2899SCharles.Forsyth gen2(Olea, (0<<6)|(0<<3)|4); /* lea (AX)(RTMP*r) */
139037da2899SCharles.Forsyth genb((r<<6)|(RTMP<<3)|RAX);
139137da2899SCharles.Forsyth r = RMP;
139237da2899SCharles.Forsyth if((i->add&ARM) == AXINF)
139337da2899SCharles.Forsyth r = RFP;
139437da2899SCharles.Forsyth modrm(Ostw, i->reg, r, RAX);
139537da2899SCharles.Forsyth break;
139637da2899SCharles.Forsyth case IINDC:
139737da2899SCharles.Forsyth opwld(i, Oldw, RAX); // string
139837da2899SCharles.Forsyth mid(i, Oldw, RBX); // index
139937da2899SCharles.Forsyth if(bflag){
140037da2899SCharles.Forsyth modrm(Oldw, O(String, len), RAX, RTA);
140137da2899SCharles.Forsyth cmpl(RTA, 0);
140237da2899SCharles.Forsyth gen2(Ojltb, 16);
140337da2899SCharles.Forsyth gen2(0x3b, (3<<6)|(RBX<<3)|RTA); /* cmp index, len */
140437da2899SCharles.Forsyth gen2(0x72, 5); /* JB */
140537da2899SCharles.Forsyth bra((ulong)bounds, Ocall);
140637da2899SCharles.Forsyth genb(0x0f);
140737da2899SCharles.Forsyth gen2(Omovzxb, (1<<6)|(0<<3)|4);
140837da2899SCharles.Forsyth gen2((0<<6)|(RBX<<3)|RAX, O(String, data));
1409*4a425662SCharles Forsyth gen2(Ojmpb, sizeof(Rune)==4? 10: 11);
141037da2899SCharles.Forsyth gen2(Oneg, (3<<6)|(3<<3)|RTA);
141137da2899SCharles.Forsyth gen2(0x3b, (3<<6)|(RBX<<3)|RTA); /* cmp index, len */
141237da2899SCharles.Forsyth gen2(0x73, 0xee); /* JNB */
1413*4a425662SCharles Forsyth if(sizeof(Rune) == 4){
1414*4a425662SCharles Forsyth gen2(Oldw, (1<<6)|(0<<3)|4);
1415*4a425662SCharles Forsyth gen2((2<<6)|(RBX<<3)|RAX, O(String, data));
1416*4a425662SCharles Forsyth }else{
141737da2899SCharles.Forsyth genb(0x0f);
141837da2899SCharles.Forsyth gen2(Omovzxw, (1<<6)|(0<<3)|4);
141937da2899SCharles.Forsyth gen2((1<<6)|(RBX<<3)|RAX, O(String, data));
1420*4a425662SCharles Forsyth }
142137da2899SCharles.Forsyth opwst(i, Ostw, RAX);
142237da2899SCharles.Forsyth break;
142337da2899SCharles.Forsyth }
142437da2899SCharles.Forsyth modrm(Ocmpi, O(String, len), RAX, 7);
142537da2899SCharles.Forsyth genb(0);
142637da2899SCharles.Forsyth gen2(Ojltb, 7);
142737da2899SCharles.Forsyth genb(0x0f);
142837da2899SCharles.Forsyth gen2(Omovzxb, (1<<6)|(0<<3)|4); /* movzbx 12(AX)(RBX*1), RAX */
142937da2899SCharles.Forsyth gen2((0<<6)|(RBX<<3)|RAX, O(String, data));
1430*4a425662SCharles Forsyth if(sizeof(Rune) == 4){
1431*4a425662SCharles Forsyth gen2(Ojmpb, 4);
1432*4a425662SCharles Forsyth gen2(Oldw, (1<<6)|(0<<3)|4); /* movl 12(AX)(RBX*4), RAX */
1433*4a425662SCharles Forsyth gen2((2<<6)|(RBX<<3)|RAX, O(String, data));
1434*4a425662SCharles Forsyth }else{
143537da2899SCharles.Forsyth gen2(Ojmpb, 5);
143637da2899SCharles.Forsyth genb(0x0f);
14376fd26240SCharles Forsyth gen2(Omovzxw, (1<<6)|(0<<3)|4); /* movzwx 12(AX)(RBX*2), RAX */
143837da2899SCharles.Forsyth gen2((1<<6)|(RBX<<3)|RAX, O(String, data));
1439*4a425662SCharles Forsyth }
144037da2899SCharles.Forsyth opwst(i, Ostw, RAX);
144137da2899SCharles.Forsyth break;
144237da2899SCharles.Forsyth case ICASE:
144337da2899SCharles.Forsyth comcase(i, 1);
144437da2899SCharles.Forsyth break;
144537da2899SCharles.Forsyth case IMOVL:
144637da2899SCharles.Forsyth opwld(i, Olea, RTA);
144737da2899SCharles.Forsyth opwst(i, Olea, RTMP);
144837da2899SCharles.Forsyth modrm(Oldw, 0, RTA, RAX);
144937da2899SCharles.Forsyth modrm(Ostw, 0, RTMP, RAX);
145037da2899SCharles.Forsyth modrm(Oldw, 4, RTA, RAX);
145137da2899SCharles.Forsyth modrm(Ostw, 4, RTMP, RAX);
145237da2899SCharles.Forsyth break;
145337da2899SCharles.Forsyth case IADDL:
145437da2899SCharles.Forsyth larith(i, 0x03, 0x13);
145537da2899SCharles.Forsyth break;
145637da2899SCharles.Forsyth case ISUBL:
145737da2899SCharles.Forsyth larith(i, 0x2b, 0x1b);
145837da2899SCharles.Forsyth break;
145937da2899SCharles.Forsyth case IORL:
146037da2899SCharles.Forsyth larith(i, 0x0b, 0x0b);
146137da2899SCharles.Forsyth break;
146237da2899SCharles.Forsyth case IANDL:
146337da2899SCharles.Forsyth larith(i, 0x23, 0x23);
146437da2899SCharles.Forsyth break;
146537da2899SCharles.Forsyth case IXORL:
146637da2899SCharles.Forsyth larith(i, 0x33, 0x33);
146737da2899SCharles.Forsyth break;
146837da2899SCharles.Forsyth case IBEQL:
146937da2899SCharles.Forsyth cbral(i, Ojnel, Ojeql, ANDAND);
147037da2899SCharles.Forsyth break;
147137da2899SCharles.Forsyth case IBNEL:
147237da2899SCharles.Forsyth cbral(i, Ojnel, Ojnel, OROR);
147337da2899SCharles.Forsyth break;
147437da2899SCharles.Forsyth case IBLEL:
147537da2899SCharles.Forsyth cbral(i, Ojltl, Ojbel, EQAND);
147637da2899SCharles.Forsyth break;
147737da2899SCharles.Forsyth case IBGTL:
147837da2899SCharles.Forsyth cbral(i, Ojgtl, Ojal, EQAND);
147937da2899SCharles.Forsyth break;
148037da2899SCharles.Forsyth case IBLTL:
148137da2899SCharles.Forsyth cbral(i, Ojltl, Ojbl, EQAND);
148237da2899SCharles.Forsyth break;
148337da2899SCharles.Forsyth case IBGEL:
148437da2899SCharles.Forsyth cbral(i, Ojgtl, Ojael, EQAND);
148537da2899SCharles.Forsyth break;
148637da2899SCharles.Forsyth case ISHLL:
148737da2899SCharles.Forsyth shll(i);
148837da2899SCharles.Forsyth break;
148937da2899SCharles.Forsyth case ISHRL:
149037da2899SCharles.Forsyth shrl(i);
149137da2899SCharles.Forsyth break;
149237da2899SCharles.Forsyth case IRAISE:
149337da2899SCharles.Forsyth punt(i, SRCOP|WRTPC|NEWPC, optab[i->op]);
149437da2899SCharles.Forsyth break;
149537da2899SCharles.Forsyth case IMULX:
149637da2899SCharles.Forsyth case IDIVX:
149737da2899SCharles.Forsyth case ICVTXX:
149837da2899SCharles.Forsyth case IMULX0:
149937da2899SCharles.Forsyth case IDIVX0:
150037da2899SCharles.Forsyth case ICVTXX0:
150137da2899SCharles.Forsyth case IMULX1:
150237da2899SCharles.Forsyth case IDIVX1:
150337da2899SCharles.Forsyth case ICVTXX1:
150437da2899SCharles.Forsyth case ICVTFX:
150537da2899SCharles.Forsyth case ICVTXF:
150637da2899SCharles.Forsyth case IEXPW:
150737da2899SCharles.Forsyth case IEXPL:
150837da2899SCharles.Forsyth case IEXPF:
150937da2899SCharles.Forsyth punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
151037da2899SCharles.Forsyth break;
151137da2899SCharles.Forsyth case ISELF:
151237da2899SCharles.Forsyth punt(i, DSTOP, optab[i->op]);
151337da2899SCharles.Forsyth break;
151437da2899SCharles.Forsyth }
151537da2899SCharles.Forsyth }
151637da2899SCharles.Forsyth
151737da2899SCharles.Forsyth static void
preamble(void)151837da2899SCharles.Forsyth preamble(void)
151937da2899SCharles.Forsyth {
152037da2899SCharles.Forsyth if(comvec)
152137da2899SCharles.Forsyth return;
152237da2899SCharles.Forsyth
152337da2899SCharles.Forsyth comvec = malloc(32);
152437da2899SCharles.Forsyth if(comvec == nil)
152537da2899SCharles.Forsyth error(exNomem);
152637da2899SCharles.Forsyth code = (uchar*)comvec;
152737da2899SCharles.Forsyth
152837da2899SCharles.Forsyth genb(Opushl+RBX);
152937da2899SCharles.Forsyth genb(Opushl+RCX);
153037da2899SCharles.Forsyth genb(Opushl+RDX);
153137da2899SCharles.Forsyth genb(Opushl+RSI);
153237da2899SCharles.Forsyth genb(Opushl+RDI);
153337da2899SCharles.Forsyth con((ulong)&R, RTMP);
153437da2899SCharles.Forsyth modrm(Oldw, O(REG, FP), RTMP, RFP);
153537da2899SCharles.Forsyth modrm(Oldw, O(REG, MP), RTMP, RMP);
153637da2899SCharles.Forsyth modrm(Ojmprm, O(REG, PC), RTMP, 4);
1537132f29a5Sforsyth
1538132f29a5Sforsyth segflush(comvec, 32);
153937da2899SCharles.Forsyth }
154037da2899SCharles.Forsyth
154137da2899SCharles.Forsyth static void
maccase(void)154237da2899SCharles.Forsyth maccase(void)
154337da2899SCharles.Forsyth {
154437da2899SCharles.Forsyth uchar *loop, *def, *lab1;
154537da2899SCharles.Forsyth
154637da2899SCharles.Forsyth modrm(Oldw, 0, RSI, RDX); // n = t[0]
154737da2899SCharles.Forsyth modrm(Olea, 4, RSI, RSI); // t = &t[1]
154837da2899SCharles.Forsyth gen2(Oldw, (3<<6)|(RBX<<3)|RDX); // MOVL DX, BX
154937da2899SCharles.Forsyth gen2(Oshr, (3<<6)|(4<<3)|RBX); // SHL BX,1
155037da2899SCharles.Forsyth gen2(0x01, (3<<6)|(RDX<<3)|RBX); // ADDL DX, BX BX = n*3
155137da2899SCharles.Forsyth gen2(Opushrm, (0<<6)|(6<<3)|4);
155237da2899SCharles.Forsyth genb((2<<6)|(RBX<<3)|RSI); // PUSHL 0(SI)(BX*4)
155337da2899SCharles.Forsyth loop = code;
155437da2899SCharles.Forsyth cmpl(RDX, 0);
155537da2899SCharles.Forsyth gen2(Ojleb, 0);
155637da2899SCharles.Forsyth def = code-1;
155737da2899SCharles.Forsyth gen2(Oldw, (3<<6)|(RCX<<3)|RDX); // MOVL DX, CX n2 = n
155837da2899SCharles.Forsyth gen2(Oshr, (3<<6)|(5<<3)|RCX); // SHR CX,1 n2 = n2>>1
155937da2899SCharles.Forsyth gen2(Oldw, (3<<6)|(RBX<<3)|RCX); // MOVL CX, BX
156037da2899SCharles.Forsyth gen2(Oshr, (3<<6)|(4<<3)|RBX); // SHL BX,1
156137da2899SCharles.Forsyth gen2(0x01, (3<<6)|(RCX<<3)|RBX); // ADDL CX, BX BX = n2*3
156237da2899SCharles.Forsyth gen2(0x3b, (0<<6)|(RAX<<3)|4);
156337da2899SCharles.Forsyth genb((2<<6)|(RBX<<3)|RSI); // CMPL AX, 0(SI)(BX*4)
156437da2899SCharles.Forsyth gen2(Ojgeb, 0); // JGE lab1
156537da2899SCharles.Forsyth lab1 = code-1;
156637da2899SCharles.Forsyth gen2(Oldw, (3<<6)|(RDX<<3)|RCX);
156737da2899SCharles.Forsyth gen2(Ojmpb, loop-code-2);
156837da2899SCharles.Forsyth *lab1 = code-lab1-1; // lab1:
156937da2899SCharles.Forsyth gen2(0x3b, (1<<6)|(RAX<<3)|4);
157037da2899SCharles.Forsyth gen2((2<<6)|(RBX<<3)|RSI, 4); // CMPL AX, 4(SI)(BX*4)
157137da2899SCharles.Forsyth gen2(Ojltb, 0);
157237da2899SCharles.Forsyth lab1 = code-1;
157337da2899SCharles.Forsyth gen2(Olea, (1<<6)|(RSI<<3)|4);
157437da2899SCharles.Forsyth gen2((2<<6)|(RBX<<3)|RSI, 12); // LEA 12(SI)(RBX*4), RSI
157537da2899SCharles.Forsyth gen2(0x2b, (3<<6)|(RDX<<3)|RCX); // SUBL CX, DX n -= n2
157637da2899SCharles.Forsyth gen2(Odecrm, (3<<6)|(1<<3)|RDX); // DECL DX n -= 1
157737da2899SCharles.Forsyth gen2(Ojmpb, loop-code-2);
157837da2899SCharles.Forsyth *lab1 = code-lab1-1; // lab1:
157937da2899SCharles.Forsyth gen2(Oldw, (1<<6)|(RAX<<3)|4);
158037da2899SCharles.Forsyth gen2((2<<6)|(RBX<<3)|RSI, 8); // MOVL 8(SI)(BX*4), AX
158137da2899SCharles.Forsyth genb(Opopl+RSI); // ditch default
158237da2899SCharles.Forsyth genb(Opopl+RSI);
158337da2899SCharles.Forsyth gen2(Ojmprm, (3<<6)|(4<<3)|RAX); // JMP*L AX
158437da2899SCharles.Forsyth *def = code-def-1; // def:
158537da2899SCharles.Forsyth genb(Opopl+RAX); // ditch default
158637da2899SCharles.Forsyth genb(Opopl+RSI);
158737da2899SCharles.Forsyth gen2(Ojmprm, (3<<6)|(4<<3)|RAX);
158837da2899SCharles.Forsyth }
158937da2899SCharles.Forsyth
159037da2899SCharles.Forsyth static void
macfrp(void)159137da2899SCharles.Forsyth macfrp(void)
159237da2899SCharles.Forsyth {
159337da2899SCharles.Forsyth cmpl(RAX, (ulong)H); // CMPL AX, $H
159437da2899SCharles.Forsyth gen2(Ojneb, 0x01); // JNE .+1
159537da2899SCharles.Forsyth genb(Oret); // RET
159637da2899SCharles.Forsyth modrm(0x83, O(Heap, ref)-sizeof(Heap), RAX, 7);
159737da2899SCharles.Forsyth genb(0x01); // CMP AX.ref, $1
159837da2899SCharles.Forsyth gen2(Ojeqb, 0x04); // JNE .+4
159937da2899SCharles.Forsyth modrm(Odecrm, O(Heap, ref)-sizeof(Heap), RAX, 1);
160037da2899SCharles.Forsyth genb(Oret); // DEC AX.ref
160137da2899SCharles.Forsyth // RET
160237da2899SCharles.Forsyth con((ulong)&R, RTMP); // MOV $R, RTMP
160337da2899SCharles.Forsyth modrm(Ostw, O(REG, FP), RTMP, RFP); // MOVL RFP, R.FP
160437da2899SCharles.Forsyth modrm(Ostw, O(REG, s), RTMP, RAX); // MOVL RAX, R.s
160537da2899SCharles.Forsyth bra((ulong)rdestroy, Ocall); // CALL rdestroy
160637da2899SCharles.Forsyth con((ulong)&R, RTMP); // MOVL $R, RTMP
160737da2899SCharles.Forsyth modrm(Oldw, O(REG, FP), RTMP, RFP); // MOVL R.MP, RMP
160837da2899SCharles.Forsyth modrm(Oldw, O(REG, MP), RTMP, RMP); // MOVL R.FP, RFP
160937da2899SCharles.Forsyth genb(Oret);
161037da2899SCharles.Forsyth }
161137da2899SCharles.Forsyth
161237da2899SCharles.Forsyth static void
macret(void)161337da2899SCharles.Forsyth macret(void)
161437da2899SCharles.Forsyth {
161537da2899SCharles.Forsyth Inst i;
161637da2899SCharles.Forsyth uchar *s;
161737da2899SCharles.Forsyth static ulong lpunt, lnomr, lfrmr, linterp;
161837da2899SCharles.Forsyth
161937da2899SCharles.Forsyth s = code;
162037da2899SCharles.Forsyth
162137da2899SCharles.Forsyth lpunt -= 2;
162237da2899SCharles.Forsyth lnomr -= 2;
162337da2899SCharles.Forsyth lfrmr -= 2;
162437da2899SCharles.Forsyth linterp -= 2;
162537da2899SCharles.Forsyth
162637da2899SCharles.Forsyth con(0, RBX); // MOVL $0, RBX
162737da2899SCharles.Forsyth modrm(Oldw, O(Frame, t), RFP, RAX); // MOVL t(FP), RAX
162837da2899SCharles.Forsyth gen2(Ocmpw, (3<<6)|(RAX<<3)|RBX); // CMPL RAX, RBX
162937da2899SCharles.Forsyth gen2(Ojeqb, lpunt-(code-s)); // JEQ lpunt
163037da2899SCharles.Forsyth modrm(Oldw, O(Type, destroy), RAX, RAX);// MOVL destroy(RAX), RAX
163137da2899SCharles.Forsyth gen2(Ocmpw, (3<<6)|(RAX<<3)|RBX); // CMPL RAX, RBX
163237da2899SCharles.Forsyth gen2(Ojeqb, lpunt-(code-s)); // JEQ lpunt
163337da2899SCharles.Forsyth modrm(Ocmpw, O(Frame, fp), RFP, RBX); // CMPL fp(FP), RBX
163437da2899SCharles.Forsyth gen2(Ojeqb, lpunt-(code-s)); // JEQ lpunt
163537da2899SCharles.Forsyth modrm(Ocmpw, O(Frame, mr), RFP, RBX); // CMPL mr(FP), RBX
163637da2899SCharles.Forsyth gen2(Ojeqb, lnomr-(code-s)); // JEQ lnomr
163737da2899SCharles.Forsyth con((ulong)&R, RTMP); // MOVL $R, RTMP
163837da2899SCharles.Forsyth modrm(Oldw, O(REG, M), RTMP, RTA); // MOVL R.M, RTA
163937da2899SCharles.Forsyth modrm(Odecrm, O(Heap, ref)-sizeof(Heap), RTA, 1);
164037da2899SCharles.Forsyth gen2(Ojneb, lfrmr-(code-s)); // JNE lfrmr
164137da2899SCharles.Forsyth modrm(Oincrm, O(Heap, ref)-sizeof(Heap), RTA, 0);
164237da2899SCharles.Forsyth gen2(Ojmpb, lpunt-(code-s)); // JMP lpunt
164337da2899SCharles.Forsyth lfrmr = code - s;
164437da2899SCharles.Forsyth modrm(Oldw, O(Frame, mr), RFP, RTA); // MOVL mr(FP), RTA
164537da2899SCharles.Forsyth modrm(Ostw, O(REG, M), RTMP, RTA); // MOVL RTA, R.M
164637da2899SCharles.Forsyth modrm(Oldw, O(Modlink, MP), RTA, RMP); // MOVL MP(RTA), RMP
164737da2899SCharles.Forsyth modrm(Ostw, O(REG, MP), RTMP, RMP); // MOVL RMP, R.MP
164837da2899SCharles.Forsyth modrm(Ocmpi, O(Modlink, compiled), RTA, 7);// CMPL $0, M.compiled
164937da2899SCharles.Forsyth genb(0x00);
165037da2899SCharles.Forsyth gen2(Ojeqb, linterp-(code-s)); // JEQ linterp
165137da2899SCharles.Forsyth lnomr = code - s;
165237da2899SCharles.Forsyth gen2(Ocallrm, (3<<6)|(2<<3)|RAX); // CALL* AX
165337da2899SCharles.Forsyth con((ulong)&R, RTMP); // MOVL $R, RTMP
165437da2899SCharles.Forsyth modrm(Ostw, O(REG, SP), RTMP, RFP); // MOVL RFP, R.SP
165537da2899SCharles.Forsyth modrm(Oldw, O(Frame, lr), RFP, RAX); // MOVL lr(RFP), RAX
165637da2899SCharles.Forsyth modrm(Oldw, O(Frame, fp), RFP, RFP); // MOVL fp(RFP), RFP
165737da2899SCharles.Forsyth modrm(Ostw, O(REG, FP), RTMP, RFP); // MOVL RFP, R.FP
165837da2899SCharles.Forsyth gen2(Ojmprm, (3<<6)|(4<<3)|RAX); // JMP*L AX
165937da2899SCharles.Forsyth
166037da2899SCharles.Forsyth linterp = code - s; // return to uncompiled code
166137da2899SCharles.Forsyth gen2(Ocallrm, (3<<6)|(2<<3)|RAX); // CALL* AX
166237da2899SCharles.Forsyth con((ulong)&R, RTMP); // MOVL $R, RTMP
166337da2899SCharles.Forsyth modrm(Ostw, O(REG, SP), RTMP, RFP); // MOVL RFP, R.SP
166437da2899SCharles.Forsyth modrm(Oldw, O(Frame, lr), RFP, RAX); // MOVL lr(RFP), RAX
166537da2899SCharles.Forsyth modrm(Ostw, O(REG, PC), RTMP, RAX); // MOVL RAX, R.PC
166637da2899SCharles.Forsyth modrm(Oldw, O(Frame, fp), RFP, RFP); // MOVL fp(RFP), RFP
166737da2899SCharles.Forsyth modrm(Ostw, O(REG, FP), RTMP, RFP); // MOVL RFP, R.FP
166837da2899SCharles.Forsyth genb(Opopl+RDI); // return to uncompiled code
166937da2899SCharles.Forsyth genb(Opopl+RSI);
167037da2899SCharles.Forsyth genb(Opopl+RDX);
167137da2899SCharles.Forsyth genb(Opopl+RCX);
167237da2899SCharles.Forsyth genb(Opopl+RBX);
167337da2899SCharles.Forsyth genb(Oret);
167437da2899SCharles.Forsyth // label:
167537da2899SCharles.Forsyth lpunt = code - s;
167637da2899SCharles.Forsyth
167737da2899SCharles.Forsyth i.add = AXNON;
167837da2899SCharles.Forsyth punt(&i, TCHECK|NEWPC, optab[IRET]);
167937da2899SCharles.Forsyth }
168037da2899SCharles.Forsyth
168137da2899SCharles.Forsyth static void
maccolr(void)168237da2899SCharles.Forsyth maccolr(void)
168337da2899SCharles.Forsyth {
168437da2899SCharles.Forsyth modrm(Oincrm, O(Heap, ref)-sizeof(Heap), RBX, 0);
168537da2899SCharles.Forsyth gen2(Oldw, (0<<6)|(RAX<<3)|5); // INCL ref(BX)
168637da2899SCharles.Forsyth genw((ulong)&mutator); // MOVL mutator, RAX
168737da2899SCharles.Forsyth modrm(Ocmpw, O(Heap, color)-sizeof(Heap), RBX, RAX);
168837da2899SCharles.Forsyth gen2(Ojneb, 0x01); // CMPL color(BX), RAX
168937da2899SCharles.Forsyth genb(Oret); // MOVL $propagator,RTMP
169037da2899SCharles.Forsyth con(propagator, RAX); // MOVL RTMP, color(BX)
169137da2899SCharles.Forsyth modrm(Ostw, O(Heap, color)-sizeof(Heap), RBX, RAX);
169237da2899SCharles.Forsyth gen2(Ostw, (0<<6)|(RAX<<3)|5); // can be any !0 value
169337da2899SCharles.Forsyth genw((ulong)&nprop); // MOVL RBX, nprop
169437da2899SCharles.Forsyth genb(Oret);
169537da2899SCharles.Forsyth }
169637da2899SCharles.Forsyth
169737da2899SCharles.Forsyth static void
macmcal(void)169837da2899SCharles.Forsyth macmcal(void)
169937da2899SCharles.Forsyth {
170037da2899SCharles.Forsyth uchar *label, *mlnil, *interp;
170137da2899SCharles.Forsyth
170237da2899SCharles.Forsyth cmpl(RAX, (ulong)H);
170337da2899SCharles.Forsyth gen2(Ojeqb, 0);
170437da2899SCharles.Forsyth mlnil = code - 1;
170537da2899SCharles.Forsyth modrm(0x83, O(Modlink, prog), RTA, 7); // CMPL $0, ml->prog
170637da2899SCharles.Forsyth genb(0x00);
170737da2899SCharles.Forsyth gen2(Ojneb, 0); // JNE patch
170837da2899SCharles.Forsyth label = code-1;
170937da2899SCharles.Forsyth *mlnil = code-mlnil-1;
171037da2899SCharles.Forsyth modrm(Ostw, O(REG, FP), RTMP, RCX);
171137da2899SCharles.Forsyth modrm(Ostw, O(REG, dt), RTMP, RAX);
171237da2899SCharles.Forsyth bra((ulong)rmcall, Ocall); // CALL rmcall
171337da2899SCharles.Forsyth con((ulong)&R, RTMP); // MOVL $R, RTMP
171437da2899SCharles.Forsyth modrm(Oldw, O(REG, FP), RTMP, RFP);
171537da2899SCharles.Forsyth modrm(Oldw, O(REG, MP), RTMP, RMP);
171637da2899SCharles.Forsyth genb(Oret); // RET
171737da2899SCharles.Forsyth *label = code-label-1; // patch:
171837da2899SCharles.Forsyth gen2(Oldw, (3<<6)|(RFP<<3)|RCX); // MOVL CX, RFP R.FP = f
171937da2899SCharles.Forsyth modrm(Ostw, O(REG, M), RTMP, RTA); // MOVL RTA, R.M
172037da2899SCharles.Forsyth modrm(Oincrm, O(Heap, ref)-sizeof(Heap), RTA, 0);
172137da2899SCharles.Forsyth modrm(Oldw, O(Modlink, MP), RTA, RMP); // MOVL R.M->mp, RMP
172237da2899SCharles.Forsyth modrm(Ostw, O(REG, MP), RTMP, RMP); // MOVL RMP, R.MP R.MP = ml->MP
172337da2899SCharles.Forsyth modrm(Ocmpi, O(Modlink, compiled), RTA, 7);// CMPL $0, M.compiled
172437da2899SCharles.Forsyth genb(0x00);
172537da2899SCharles.Forsyth genb(Opopl+RTA); // balance call
172637da2899SCharles.Forsyth gen2(Ojeqb, 0); // JEQ interp
172737da2899SCharles.Forsyth interp = code-1;
172837da2899SCharles.Forsyth gen2(Ojmprm, (3<<6)|(4<<3)|RAX); // JMP*L AX
172937da2899SCharles.Forsyth *interp = code-interp-1; // interp:
173037da2899SCharles.Forsyth modrm(Ostw, O(REG, FP), RTMP, RFP); // MOVL FP, R.FP
173137da2899SCharles.Forsyth modrm(Ostw, O(REG, PC), RTMP, RAX); // MOVL PC, R.PC
173237da2899SCharles.Forsyth genb(Opopl+RDI); // call to uncompiled code
173337da2899SCharles.Forsyth genb(Opopl+RSI);
173437da2899SCharles.Forsyth genb(Opopl+RDX);
173537da2899SCharles.Forsyth genb(Opopl+RCX);
173637da2899SCharles.Forsyth genb(Opopl+RBX);
173737da2899SCharles.Forsyth genb(Oret);
173837da2899SCharles.Forsyth }
173937da2899SCharles.Forsyth
174037da2899SCharles.Forsyth static void
macfram(void)174137da2899SCharles.Forsyth macfram(void)
174237da2899SCharles.Forsyth {
174337da2899SCharles.Forsyth uchar *label;
174437da2899SCharles.Forsyth
174537da2899SCharles.Forsyth con((ulong)&R, RTMP); // MOVL $R, RTMP
174637da2899SCharles.Forsyth modrm(Oldw, O(REG, SP), RTMP, RAX); // MOVL R.SP, AX
174737da2899SCharles.Forsyth modrm(0x03, O(Type, size), RTA, RAX); // ADDL size(RCX), RAX
174837da2899SCharles.Forsyth modrm(0x3b, O(REG, TS), RTMP, RAX); // CMPL AX, R.TS
174937da2899SCharles.Forsyth gen2(0x7c, 0x00); // JL .+(patch)
175037da2899SCharles.Forsyth label = code-1;
175137da2899SCharles.Forsyth
175237da2899SCharles.Forsyth modrm(Ostw, O(REG, s), RTMP, RTA);
175337da2899SCharles.Forsyth modrm(Ostw, O(REG, FP), RTMP, RFP); // MOVL RFP, R.FP
175437da2899SCharles.Forsyth bra((ulong)extend, Ocall); // CALL extend
175537da2899SCharles.Forsyth con((ulong)&R, RTMP);
175637da2899SCharles.Forsyth modrm(Oldw, O(REG, FP), RTMP, RFP); // MOVL R.MP, RMP
175737da2899SCharles.Forsyth modrm(Oldw, O(REG, MP), RTMP, RMP); // MOVL R.FP, RFP
175837da2899SCharles.Forsyth modrm(Oldw, O(REG, s), RTMP, RCX); // MOVL R.s, *R.d
175937da2899SCharles.Forsyth genb(Oret); // RET
176037da2899SCharles.Forsyth *label = code-label-1;
176137da2899SCharles.Forsyth modrm(Oldw, O(REG, SP), RTMP, RCX); // MOVL R.SP, CX
176237da2899SCharles.Forsyth modrm(Ostw, O(REG, SP), RTMP, RAX); // MOVL AX, R.SP
176337da2899SCharles.Forsyth
176437da2899SCharles.Forsyth modrm(Ostw, O(Frame, t), RCX, RTA); // MOVL RTA, t(CX) f->t = t
176537da2899SCharles.Forsyth modrm(Omov, REGMOD*4, RCX, 0); // MOVL $0, mr(CX) f->mr
176637da2899SCharles.Forsyth genw(0);
176737da2899SCharles.Forsyth modrm(Oldw, O(Type, initialize), RTA, RTA);
176837da2899SCharles.Forsyth gen2(Ojmprm, (3<<6)|(4<<3)|RTA); // JMP*L RTA
176937da2899SCharles.Forsyth genb(Oret); // RET
177037da2899SCharles.Forsyth }
177137da2899SCharles.Forsyth
177237da2899SCharles.Forsyth static void
macmfra(void)177337da2899SCharles.Forsyth macmfra(void)
177437da2899SCharles.Forsyth {
177537da2899SCharles.Forsyth con((ulong)&R, RTMP); // MOVL $R, RTMP
177637da2899SCharles.Forsyth modrm(Ostw, O(REG, FP), RTMP, RFP);
177737da2899SCharles.Forsyth modrm(Ostw, O(REG, s), RTMP, RAX); // Save type
177837da2899SCharles.Forsyth modrm(Ostw, O(REG, d), RTMP, RTA); // Save destination
177937da2899SCharles.Forsyth bra((ulong)rmfram, Ocall); // CALL rmfram
178037da2899SCharles.Forsyth con((ulong)&R, RTMP); // MOVL $R, RTMP
178137da2899SCharles.Forsyth modrm(Oldw, O(REG, FP), RTMP, RFP);
178237da2899SCharles.Forsyth modrm(Oldw, O(REG, MP), RTMP, RMP);
178337da2899SCharles.Forsyth genb(Oret); // RET
178437da2899SCharles.Forsyth }
178537da2899SCharles.Forsyth
178637da2899SCharles.Forsyth static void
macrelq(void)178737da2899SCharles.Forsyth macrelq(void)
178837da2899SCharles.Forsyth {
178937da2899SCharles.Forsyth modrm(Ostw, O(REG, FP), RTMP, RFP); // MOVL FP, R.FP
179037da2899SCharles.Forsyth genb(Opopl+RAX);
179137da2899SCharles.Forsyth modrm(Ostw, O(REG, PC), RTMP, RAX); // MOVL PC, R.PC
179237da2899SCharles.Forsyth genb(Opopl+RDI);
179337da2899SCharles.Forsyth genb(Opopl+RSI);
179437da2899SCharles.Forsyth genb(Opopl+RDX);
179537da2899SCharles.Forsyth genb(Opopl+RCX);
179637da2899SCharles.Forsyth genb(Opopl+RBX);
179737da2899SCharles.Forsyth genb(Oret);
179837da2899SCharles.Forsyth }
179937da2899SCharles.Forsyth
180037da2899SCharles.Forsyth void
comd(Type * t)180137da2899SCharles.Forsyth comd(Type *t)
180237da2899SCharles.Forsyth {
180337da2899SCharles.Forsyth int i, j, m, c;
180437da2899SCharles.Forsyth
180537da2899SCharles.Forsyth for(i = 0; i < t->np; i++) {
180637da2899SCharles.Forsyth c = t->map[i];
180737da2899SCharles.Forsyth j = i<<5;
180837da2899SCharles.Forsyth for(m = 0x80; m != 0; m >>= 1) {
180937da2899SCharles.Forsyth if(c & m) {
181037da2899SCharles.Forsyth modrm(Oldw, j, RFP, RAX);
181137da2899SCharles.Forsyth rbra(macro[MacFRP], Ocall);
181237da2899SCharles.Forsyth }
181337da2899SCharles.Forsyth j += sizeof(WORD*);
181437da2899SCharles.Forsyth }
181537da2899SCharles.Forsyth }
181637da2899SCharles.Forsyth genb(Oret);
181737da2899SCharles.Forsyth }
181837da2899SCharles.Forsyth
181937da2899SCharles.Forsyth void
comi(Type * t)182037da2899SCharles.Forsyth comi(Type *t)
182137da2899SCharles.Forsyth {
182237da2899SCharles.Forsyth int i, j, m, c;
182337da2899SCharles.Forsyth
182437da2899SCharles.Forsyth con((ulong)H, RAX);
182537da2899SCharles.Forsyth for(i = 0; i < t->np; i++) {
182637da2899SCharles.Forsyth c = t->map[i];
182737da2899SCharles.Forsyth j = i<<5;
182837da2899SCharles.Forsyth for(m = 0x80; m != 0; m >>= 1) {
182937da2899SCharles.Forsyth if(c & m)
183037da2899SCharles.Forsyth modrm(Ostw, j, RCX, RAX);
183137da2899SCharles.Forsyth j += sizeof(WORD*);
183237da2899SCharles.Forsyth }
183337da2899SCharles.Forsyth }
183437da2899SCharles.Forsyth genb(Oret);
183537da2899SCharles.Forsyth }
183637da2899SCharles.Forsyth
183737da2899SCharles.Forsyth void
typecom(Type * t)183837da2899SCharles.Forsyth typecom(Type *t)
183937da2899SCharles.Forsyth {
184037da2899SCharles.Forsyth int n;
184137da2899SCharles.Forsyth uchar *tmp;
184237da2899SCharles.Forsyth
184337da2899SCharles.Forsyth if(t == nil || t->initialize != 0)
184437da2899SCharles.Forsyth return;
184537da2899SCharles.Forsyth
184637da2899SCharles.Forsyth tmp = mallocz(4096*sizeof(uchar), 0);
184737da2899SCharles.Forsyth if(tmp == nil)
184837da2899SCharles.Forsyth error(exNomem);
184937da2899SCharles.Forsyth
185037da2899SCharles.Forsyth code = tmp;
185137da2899SCharles.Forsyth comi(t);
185237da2899SCharles.Forsyth n = code - tmp;
185337da2899SCharles.Forsyth code = tmp;
185437da2899SCharles.Forsyth comd(t);
185537da2899SCharles.Forsyth n += code - tmp;
185637da2899SCharles.Forsyth free(tmp);
185737da2899SCharles.Forsyth
185837da2899SCharles.Forsyth code = mallocz(n, 0);
185937da2899SCharles.Forsyth if(code == nil)
186037da2899SCharles.Forsyth return;
186137da2899SCharles.Forsyth
186237da2899SCharles.Forsyth t->initialize = code;
186337da2899SCharles.Forsyth comi(t);
186437da2899SCharles.Forsyth t->destroy = code;
186537da2899SCharles.Forsyth comd(t);
186637da2899SCharles.Forsyth
186737da2899SCharles.Forsyth if(cflag > 3)
186837da2899SCharles.Forsyth print("typ= %.8lux %4d i %.8lux d %.8lux asm=%d\n",
186937da2899SCharles.Forsyth (ulong)t, t->size, (ulong)t->initialize, (ulong)t->destroy, n);
1870132f29a5Sforsyth
1871132f29a5Sforsyth segflush(t->initialize, n);
187237da2899SCharles.Forsyth }
187337da2899SCharles.Forsyth
187437da2899SCharles.Forsyth static void
patchex(Module * m,ulong * p)187537da2899SCharles.Forsyth patchex(Module *m, ulong *p)
187637da2899SCharles.Forsyth {
187737da2899SCharles.Forsyth Handler *h;
187837da2899SCharles.Forsyth Except *e;
187937da2899SCharles.Forsyth
188037da2899SCharles.Forsyth if((h = m->htab) == nil)
188137da2899SCharles.Forsyth return;
188237da2899SCharles.Forsyth for( ; h->etab != nil; h++){
188337da2899SCharles.Forsyth h->pc1 = p[h->pc1];
188437da2899SCharles.Forsyth h->pc2 = p[h->pc2];
188537da2899SCharles.Forsyth for(e = h->etab; e->s != nil; e++)
188637da2899SCharles.Forsyth e->pc = p[e->pc];
188737da2899SCharles.Forsyth if(e->pc != -1)
188837da2899SCharles.Forsyth e->pc = p[e->pc];
188937da2899SCharles.Forsyth }
189037da2899SCharles.Forsyth }
189137da2899SCharles.Forsyth
189237da2899SCharles.Forsyth int
compile(Module * m,int size,Modlink * ml)189337da2899SCharles.Forsyth compile(Module *m, int size, Modlink *ml)
189437da2899SCharles.Forsyth {
189537da2899SCharles.Forsyth ulong v;
189637da2899SCharles.Forsyth Modl *e;
189737da2899SCharles.Forsyth Link *l;
189837da2899SCharles.Forsyth int i, n;
189937da2899SCharles.Forsyth uchar *s, *tmp;
190037da2899SCharles.Forsyth
190137da2899SCharles.Forsyth base = nil;
190237da2899SCharles.Forsyth patch = mallocz(size*sizeof(*patch), 0);
190337da2899SCharles.Forsyth tinit = malloc(m->ntype*sizeof(*tinit));
190437da2899SCharles.Forsyth tmp = mallocz(4096*sizeof(uchar),0);
190537da2899SCharles.Forsyth if(tinit == nil || patch == nil || tmp == nil)
190637da2899SCharles.Forsyth goto bad;
190737da2899SCharles.Forsyth
190837da2899SCharles.Forsyth preamble();
190937da2899SCharles.Forsyth
191037da2899SCharles.Forsyth mod = m;
191137da2899SCharles.Forsyth n = 0;
191237da2899SCharles.Forsyth pass = 0;
191337da2899SCharles.Forsyth nlit = 0;
191437da2899SCharles.Forsyth
191537da2899SCharles.Forsyth for(i = 0; i < size; i++) {
191637da2899SCharles.Forsyth code = tmp;
191737da2899SCharles.Forsyth comp(&m->prog[i]);
191837da2899SCharles.Forsyth patch[i] = n;
191937da2899SCharles.Forsyth n += code - tmp;
192037da2899SCharles.Forsyth }
192137da2899SCharles.Forsyth
192237da2899SCharles.Forsyth for(i = 0; i < nelem(mactab); i++) {
192337da2899SCharles.Forsyth code = tmp;
192437da2899SCharles.Forsyth mactab[i].gen();
192537da2899SCharles.Forsyth macro[mactab[i].idx] = n;
192637da2899SCharles.Forsyth n += code - tmp;
192737da2899SCharles.Forsyth }
192837da2899SCharles.Forsyth
192937da2899SCharles.Forsyth n = (n+3)&~3;
193037da2899SCharles.Forsyth
193137da2899SCharles.Forsyth nlit *= sizeof(ulong);
193237da2899SCharles.Forsyth base = mallocz(n + nlit, 0);
193337da2899SCharles.Forsyth if(base == nil)
193437da2899SCharles.Forsyth goto bad;
193537da2899SCharles.Forsyth
193637da2899SCharles.Forsyth if(cflag > 3)
193737da2899SCharles.Forsyth print("dis=%5d %5d 386=%5d asm=%.8lux lit=%d: %s\n",
193837da2899SCharles.Forsyth size, size*sizeof(Inst), n, (ulong)base, nlit, m->name);
193937da2899SCharles.Forsyth
194037da2899SCharles.Forsyth pass++;
194137da2899SCharles.Forsyth nlit = 0;
194237da2899SCharles.Forsyth litpool = (ulong*)(base+n);
194337da2899SCharles.Forsyth code = base;
194437da2899SCharles.Forsyth
194537da2899SCharles.Forsyth for(i = 0; i < size; i++) {
194637da2899SCharles.Forsyth s = code;
194737da2899SCharles.Forsyth comp(&m->prog[i]);
194837da2899SCharles.Forsyth if(cflag > 4) {
194937da2899SCharles.Forsyth print("%D\n", &m->prog[i]);
195037da2899SCharles.Forsyth das(s, code-s);
195137da2899SCharles.Forsyth }
195237da2899SCharles.Forsyth }
195337da2899SCharles.Forsyth
195437da2899SCharles.Forsyth for(i = 0; i < nelem(mactab); i++)
195537da2899SCharles.Forsyth mactab[i].gen();
195637da2899SCharles.Forsyth
195737da2899SCharles.Forsyth v = (ulong)base;
195837da2899SCharles.Forsyth for(l = m->ext; l->name; l++) {
195937da2899SCharles.Forsyth l->u.pc = (Inst*)(v+patch[l->u.pc-m->prog]);
196037da2899SCharles.Forsyth typecom(l->frame);
196137da2899SCharles.Forsyth }
196237da2899SCharles.Forsyth if(ml != nil) {
196337da2899SCharles.Forsyth e = &ml->links[0];
196437da2899SCharles.Forsyth for(i = 0; i < ml->nlinks; i++) {
196537da2899SCharles.Forsyth e->u.pc = (Inst*)(v+patch[e->u.pc-m->prog]);
196637da2899SCharles.Forsyth typecom(e->frame);
196737da2899SCharles.Forsyth e++;
196837da2899SCharles.Forsyth }
196937da2899SCharles.Forsyth }
197037da2899SCharles.Forsyth for(i = 0; i < m->ntype; i++) {
197137da2899SCharles.Forsyth if(tinit[i] != 0)
197237da2899SCharles.Forsyth typecom(m->type[i]);
197337da2899SCharles.Forsyth }
197437da2899SCharles.Forsyth patchex(m, patch);
197537da2899SCharles.Forsyth m->entry = (Inst*)(v+patch[mod->entry-mod->prog]);
197637da2899SCharles.Forsyth free(patch);
197737da2899SCharles.Forsyth free(tinit);
197837da2899SCharles.Forsyth free(tmp);
197937da2899SCharles.Forsyth free(m->prog);
198037da2899SCharles.Forsyth m->prog = (Inst*)base;
198137da2899SCharles.Forsyth m->compiled = 1;
1982132f29a5Sforsyth segflush(base, n*sizeof(base));
198337da2899SCharles.Forsyth return 1;
198437da2899SCharles.Forsyth bad:
198537da2899SCharles.Forsyth free(patch);
198637da2899SCharles.Forsyth free(tinit);
198737da2899SCharles.Forsyth free(tmp);
198837da2899SCharles.Forsyth free(base);
198937da2899SCharles.Forsyth return 0;
199037da2899SCharles.Forsyth }
199137da2899SCharles.Forsyth
1992