xref: /inferno-os/libinterp/comp-sparc.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth #include "lib9.h"
2*37da2899SCharles.Forsyth #include "isa.h"
3*37da2899SCharles.Forsyth #include "interp.h"
4*37da2899SCharles.Forsyth #include "raise.h"
5*37da2899SCharles.Forsyth 
6*37da2899SCharles.Forsyth enum
7*37da2899SCharles.Forsyth {
8*37da2899SCharles.Forsyth 	R8	= 8,		/* SUN calls these %o0 - %o7 */
9*37da2899SCharles.Forsyth 	R9	= 9,
10*37da2899SCharles.Forsyth 	R10	= 10,
11*37da2899SCharles.Forsyth 	R11	= 11,
12*37da2899SCharles.Forsyth 	R12	= 12,
13*37da2899SCharles.Forsyth 	R13	= 13,
14*37da2899SCharles.Forsyth 	R14	= 14,		/* SUN %sp */
15*37da2899SCharles.Forsyth 	R15	= 15,		/* R15/%o7 is the default link register */
16*37da2899SCharles.Forsyth 
17*37da2899SCharles.Forsyth 	R16	= 16,		/* SUN calls these %l0 - %l7 */
18*37da2899SCharles.Forsyth 	R17	= 17,
19*37da2899SCharles.Forsyth 	R18	= 18,
20*37da2899SCharles.Forsyth 	R19	= 19,
21*37da2899SCharles.Forsyth 	R20	= 20,
22*37da2899SCharles.Forsyth 	R21	= 21,
23*37da2899SCharles.Forsyth 	R22	= 22,
24*37da2899SCharles.Forsyth 	R23	= 23,
25*37da2899SCharles.Forsyth 	RLINK	= 15,
26*37da2899SCharles.Forsyth 
27*37da2899SCharles.Forsyth 	RZ	= 0,		/* Always 0 */
28*37da2899SCharles.Forsyth 	RFP	= R23,		/* Frame Pointer */
29*37da2899SCharles.Forsyth 	RMP	= R22,		/* Module Pointer */
30*37da2899SCharles.Forsyth 	RTA	= R21,		/* Intermediate address for double indirect */
31*37da2899SCharles.Forsyth 	RREG	= R20,		/* Pointer to REG */
32*37da2899SCharles.Forsyth 	RA3	= R19,		/* gpr 3 */
33*37da2899SCharles.Forsyth 	RA2	= R18,		/* gpr 2 2+3 = L */
34*37da2899SCharles.Forsyth 	RA1	= R17,		/* gpr 1 */
35*37da2899SCharles.Forsyth 	RA0	= R16,		/* gpr 0 0+1 = L */
36*37da2899SCharles.Forsyth 
37*37da2899SCharles.Forsyth 	RCON	= R8,		/* Constant builder */
38*37da2899SCharles.Forsyth 
39*37da2899SCharles.Forsyth 	FA2	= 2,		/* Floating */
40*37da2899SCharles.Forsyth 	FA3	= 3,
41*37da2899SCharles.Forsyth 	FA4	= 4,
42*37da2899SCharles.Forsyth 	FA5	= 5,
43*37da2899SCharles.Forsyth 
44*37da2899SCharles.Forsyth 	Olea	= (1<<20),	/* Pseudo op */
45*37da2899SCharles.Forsyth 	Owry	= 48,
46*37da2899SCharles.Forsyth 	Omul	= 11,
47*37da2899SCharles.Forsyth 	Oumul	= 10,
48*37da2899SCharles.Forsyth 	Osdiv	= 15,
49*37da2899SCharles.Forsyth 	Osll	= 37,
50*37da2899SCharles.Forsyth 	Osra	= 39,
51*37da2899SCharles.Forsyth 	Osrl	= 38,
52*37da2899SCharles.Forsyth 	Osethi	= 4,
53*37da2899SCharles.Forsyth 	Oadd	= 0,
54*37da2899SCharles.Forsyth 	Oaddcc	= 16,
55*37da2899SCharles.Forsyth 	Oaddx	= 8,
56*37da2899SCharles.Forsyth 	Osub	= 4,
57*37da2899SCharles.Forsyth 	Osubcc	= 20,
58*37da2899SCharles.Forsyth 	Osubx	= 12,
59*37da2899SCharles.Forsyth 	Oor	= 2,
60*37da2899SCharles.Forsyth 	Oand	= 1,
61*37da2899SCharles.Forsyth 	Oxor	= 3,
62*37da2899SCharles.Forsyth 	Oldw	= 0,
63*37da2899SCharles.Forsyth 	Oldsh	= 10,
64*37da2899SCharles.Forsyth 	Ostw	= 4,
65*37da2899SCharles.Forsyth 	Osth	= 6,
66*37da2899SCharles.Forsyth 	Ojmpl	= 56,
67*37da2899SCharles.Forsyth 	Ocall	= 1,
68*37da2899SCharles.Forsyth 	Ocmp	= 20,		/* subcc */
69*37da2899SCharles.Forsyth 	Oldbu	= 1,
70*37da2899SCharles.Forsyth 	Ostb	= 5,
71*37da2899SCharles.Forsyth 	Oba	= 8,
72*37da2899SCharles.Forsyth 	Obn	= 0,
73*37da2899SCharles.Forsyth 	Obne	= 9,
74*37da2899SCharles.Forsyth 	Obe	= 1,
75*37da2899SCharles.Forsyth 	Obg	= 10,
76*37da2899SCharles.Forsyth 	Oble	= 2,
77*37da2899SCharles.Forsyth 	Obge	= 11,
78*37da2899SCharles.Forsyth 	Obl	= 3,
79*37da2899SCharles.Forsyth 	Obgu	= 12,
80*37da2899SCharles.Forsyth 	Obleu	= 4,
81*37da2899SCharles.Forsyth 	Obcc	= 13,
82*37da2899SCharles.Forsyth 	Obcs	= 5,
83*37da2899SCharles.Forsyth 	Obpos	= 14,
84*37da2899SCharles.Forsyth 	Obneg	= 6,
85*37da2899SCharles.Forsyth 	Obvc	= 15,
86*37da2899SCharles.Forsyth 	Obvs	= 7,
87*37da2899SCharles.Forsyth 	OfaddD	= 66,
88*37da2899SCharles.Forsyth 	OfsubD	= 70,
89*37da2899SCharles.Forsyth 	OfdivD	= 78,
90*37da2899SCharles.Forsyth 	OfmulD	= 74,
91*37da2899SCharles.Forsyth 	Oldf	= 32,
92*37da2899SCharles.Forsyth 	Ostf	= 36,
93*37da2899SCharles.Forsyth 	OfDtoQ	= 206,
94*37da2899SCharles.Forsyth 	OfnegS	= 5,
95*37da2899SCharles.Forsyth 	OfcmpD	= 82,
96*37da2899SCharles.Forsyth 	Ofba	= 8,
97*37da2899SCharles.Forsyth 	Ofbe	= 9,
98*37da2899SCharles.Forsyth 	Ofbg	= 6,
99*37da2899SCharles.Forsyth 	Ofbge	= 11,
100*37da2899SCharles.Forsyth 	Ofbl	= 4,
101*37da2899SCharles.Forsyth 	Ofble	= 13,
102*37da2899SCharles.Forsyth 	Ofbne	= 1,
103*37da2899SCharles.Forsyth 	OfWtoD	= 200,
104*37da2899SCharles.Forsyth 	OfDtoW	= 210,
105*37da2899SCharles.Forsyth 	Osave	= 60,
106*37da2899SCharles.Forsyth 	Orestore= 61,
107*37da2899SCharles.Forsyth 
108*37da2899SCharles.Forsyth 	SRCOP	= (1<<0),
109*37da2899SCharles.Forsyth 	DSTOP	= (1<<1),
110*37da2899SCharles.Forsyth 	WRTPC	= (1<<2),
111*37da2899SCharles.Forsyth 	TCHECK	= (1<<3),
112*37da2899SCharles.Forsyth 	NEWPC	= (1<<4),
113*37da2899SCharles.Forsyth 	DBRAN	= (1<<5),
114*37da2899SCharles.Forsyth 	THREOP	= (1<<6),
115*37da2899SCharles.Forsyth 
116*37da2899SCharles.Forsyth 	ANDAND	= 1,
117*37da2899SCharles.Forsyth 	OROR	= 2,
118*37da2899SCharles.Forsyth 	EQAND	= 3,
119*37da2899SCharles.Forsyth 
120*37da2899SCharles.Forsyth 	MacFRP	= 0,
121*37da2899SCharles.Forsyth 	MacRET	= 1,
122*37da2899SCharles.Forsyth 	MacCASE	= 2,
123*37da2899SCharles.Forsyth 	MacCOLR	= 3,
124*37da2899SCharles.Forsyth 	MacMCAL	= 4,
125*37da2899SCharles.Forsyth 	MacFRAM	= 5,
126*37da2899SCharles.Forsyth 	MacMFRA	= 6,
127*37da2899SCharles.Forsyth 	NMACRO
128*37da2899SCharles.Forsyth };
129*37da2899SCharles.Forsyth 
130*37da2899SCharles.Forsyth #define OP(n)			   (n<<30)
131*37da2899SCharles.Forsyth #define I13(i)			   ((i)&0x1fff)
132*37da2899SCharles.Forsyth #define D22(i)			   ((i)&0x3fffff)
133*37da2899SCharles.Forsyth #define PC30(pc)		   (((ulong)(pc) - (ulong)code)>>2)
134*37da2899SCharles.Forsyth 
135*37da2899SCharles.Forsyth #define CALL(addr)		   *code=OP(1)|PC30(addr); code++
136*37da2899SCharles.Forsyth #define FM2I(op2, i, rd)	   *code=OP(0)|(rd<<25)|(op2<<22)|D22(i); code++
137*37da2899SCharles.Forsyth #define BRA(cond, disp)		   *code=OP(0)|(cond<<25)|(2<<22)|D22((disp)); code++
138*37da2899SCharles.Forsyth #define BRAF(cond, disp)	   *code=OP(0)|(cond<<25)|(6<<22)|D22((disp)); code++
139*37da2899SCharles.Forsyth #define BRADIS(r, o)		   BRA(r, ((ulong)(base+patch[o])-(ulong)code)>>2)
140*37da2899SCharles.Forsyth #define BRAFDIS(r, o)		   BRAF(r, ((ulong)(base+patch[o])-(ulong)code)>>2)
141*37da2899SCharles.Forsyth #define BRAMAC(r, o)		   BRA(r, ((ulong)(base+macro[o])-(ulong)code)>>2);
142*37da2899SCharles.Forsyth #define FM3I(op, op3, i, rs1, rd)  *code++=OP(op)|(rd<<25)|(op3<<19)|(rs1<<14)|\
143*37da2899SCharles.Forsyth 					   (1<<13)|I13(i)
144*37da2899SCharles.Forsyth #define FM3(op, op3, rs2, rs1, rd) *code++=OP(op)|(rd<<25)|(op3<<19)|(rs1<<14)|rs2
145*37da2899SCharles.Forsyth #define FMF1(opf, rs2, rs1, rd)	   *code++=OP(2)|(rd<<25)|(52<<19)|(rs1<<14)|(opf<<5)|rs2
146*37da2899SCharles.Forsyth #define FMF2(opf, rs2, rs1, rd)	   *code++=OP(2)|(rd<<25)|(53<<19)|(rs1<<14)|(opf<<5)|rs2
147*37da2899SCharles.Forsyth #define NOOP			   *code++=(4<<22)
148*37da2899SCharles.Forsyth #define RETURN			   FM3I(2, Ojmpl, 8, RLINK, RZ);
149*37da2899SCharles.Forsyth #define MOV(s, d)		   FM3(2, Oor, s, RZ, d)
150*37da2899SCharles.Forsyth 
151*37da2899SCharles.Forsyth #define RELPC(pc)		   (ulong)(base+pc)
152*37da2899SCharles.Forsyth #define PATCH(ptr)		   *ptr |= (code-ptr) & 0x3fffff
153*37da2899SCharles.Forsyth 
154*37da2899SCharles.Forsyth static	ulong*	code;
155*37da2899SCharles.Forsyth static	ulong*	base;
156*37da2899SCharles.Forsyth static	ulong*	patch;
157*37da2899SCharles.Forsyth static	int	pass;
158*37da2899SCharles.Forsyth static	int	puntpc = 1;
159*37da2899SCharles.Forsyth static	Module*	mod;
160*37da2899SCharles.Forsyth static	uchar*	tinit;
161*37da2899SCharles.Forsyth static	ulong*	litpool;
162*37da2899SCharles.Forsyth static	int	nlit;
163*37da2899SCharles.Forsyth static	void	macfrp(void);
164*37da2899SCharles.Forsyth static	void	macret(void);
165*37da2899SCharles.Forsyth static	void	maccase(void);
166*37da2899SCharles.Forsyth static	void	maccolr(void);
167*37da2899SCharles.Forsyth static	void	macmcal(void);
168*37da2899SCharles.Forsyth static	void	macfram(void);
169*37da2899SCharles.Forsyth static	void	macmfra(void);
170*37da2899SCharles.Forsyth static	ulong	macro[NMACRO];
171*37da2899SCharles.Forsyth 	void	(*comvec)(void);
172*37da2899SCharles.Forsyth extern	void	das(ulong*, int);
173*37da2899SCharles.Forsyth 
174*37da2899SCharles.Forsyth #define T(r)	*((void**)(R.r))
175*37da2899SCharles.Forsyth 
176*37da2899SCharles.Forsyth struct
177*37da2899SCharles.Forsyth {
178*37da2899SCharles.Forsyth 	int	idx;
179*37da2899SCharles.Forsyth 	void	(*gen)(void);
180*37da2899SCharles.Forsyth 	char*	name;
181*37da2899SCharles.Forsyth } mactab[] =
182*37da2899SCharles.Forsyth {
183*37da2899SCharles.Forsyth 	MacFRP,		macfrp,		"FRP", 	/* decrement and free pointer */
184*37da2899SCharles.Forsyth 	MacRET,		macret,		"RET",	/* return instruction */
185*37da2899SCharles.Forsyth 	MacCASE,	maccase,	"CASE",	/* case instruction */
186*37da2899SCharles.Forsyth 	MacCOLR,	maccolr,	"COLR",	/* increment and color pointer */
187*37da2899SCharles.Forsyth 	MacMCAL,	macmcal,	"MCAL",	/* mcall bottom half */
188*37da2899SCharles.Forsyth 	MacFRAM,	macfram,	"FRAM",	/* frame instruction */
189*37da2899SCharles.Forsyth 	MacMFRA,	macmfra,	"MFRA",	/* punt mframe because t->initialize==0 */
190*37da2899SCharles.Forsyth };
191*37da2899SCharles.Forsyth 
192*37da2899SCharles.Forsyth static void
rdestroy(void)193*37da2899SCharles.Forsyth rdestroy(void)
194*37da2899SCharles.Forsyth {
195*37da2899SCharles.Forsyth 	destroy(R.s);
196*37da2899SCharles.Forsyth }
197*37da2899SCharles.Forsyth 
198*37da2899SCharles.Forsyth static void
rmcall(void)199*37da2899SCharles.Forsyth rmcall(void)
200*37da2899SCharles.Forsyth {
201*37da2899SCharles.Forsyth 	Prog *p;
202*37da2899SCharles.Forsyth 	Frame *f;
203*37da2899SCharles.Forsyth 
204*37da2899SCharles.Forsyth 	f = (Frame*)R.FP;
205*37da2899SCharles.Forsyth 	if(f == H)
206*37da2899SCharles.Forsyth 		error(exModule);
207*37da2899SCharles.Forsyth 
208*37da2899SCharles.Forsyth 	f->mr = nil;
209*37da2899SCharles.Forsyth 	((void(*)(Frame*))R.dt)(f);
210*37da2899SCharles.Forsyth 	R.SP = (uchar*)f;
211*37da2899SCharles.Forsyth 	R.FP = f->fp;
212*37da2899SCharles.Forsyth 	if(f->t == nil)
213*37da2899SCharles.Forsyth 		unextend(f);
214*37da2899SCharles.Forsyth 	else
215*37da2899SCharles.Forsyth 		freeptrs(f, f->t);
216*37da2899SCharles.Forsyth 	p = currun();
217*37da2899SCharles.Forsyth 	if(p->kill != nil)
218*37da2899SCharles.Forsyth 		error(p->kill);
219*37da2899SCharles.Forsyth }
220*37da2899SCharles.Forsyth 
221*37da2899SCharles.Forsyth static void
rmfram(void)222*37da2899SCharles.Forsyth rmfram(void)
223*37da2899SCharles.Forsyth {
224*37da2899SCharles.Forsyth 	Type *t;
225*37da2899SCharles.Forsyth 	Frame *f;
226*37da2899SCharles.Forsyth 	uchar *nsp;
227*37da2899SCharles.Forsyth 
228*37da2899SCharles.Forsyth 	if(R.d == H)
229*37da2899SCharles.Forsyth                 error(exModule);
230*37da2899SCharles.Forsyth         t = (Type*)R.s;
231*37da2899SCharles.Forsyth         if(t == H)
232*37da2899SCharles.Forsyth                 error(exModule);
233*37da2899SCharles.Forsyth 
234*37da2899SCharles.Forsyth 	nsp = R.SP + t->size;
235*37da2899SCharles.Forsyth 	if(nsp >= R.TS) {
236*37da2899SCharles.Forsyth 		R.s = t;
237*37da2899SCharles.Forsyth 		extend();
238*37da2899SCharles.Forsyth 		T(d) = R.s;
239*37da2899SCharles.Forsyth 		return;
240*37da2899SCharles.Forsyth 	}
241*37da2899SCharles.Forsyth 	f = (Frame*)R.SP;
242*37da2899SCharles.Forsyth 	R.SP = nsp;
243*37da2899SCharles.Forsyth 	f->t = t;
244*37da2899SCharles.Forsyth 	f->mr = nil;
245*37da2899SCharles.Forsyth 	initmem(t, f);
246*37da2899SCharles.Forsyth 	T(d) = f;
247*37da2899SCharles.Forsyth }
248*37da2899SCharles.Forsyth 
249*37da2899SCharles.Forsyth static void
urk(void)250*37da2899SCharles.Forsyth urk(void)
251*37da2899SCharles.Forsyth {
252*37da2899SCharles.Forsyth 	error(exCompile);
253*37da2899SCharles.Forsyth }
254*37da2899SCharles.Forsyth 
255*37da2899SCharles.Forsyth static int
bc(long c)256*37da2899SCharles.Forsyth bc(long c)
257*37da2899SCharles.Forsyth {
258*37da2899SCharles.Forsyth 	c &= ~0xfffL;
259*37da2899SCharles.Forsyth 	if (c == 0 || c == ~0xfffL)
260*37da2899SCharles.Forsyth 		return 1;
261*37da2899SCharles.Forsyth 
262*37da2899SCharles.Forsyth 	return 0;
263*37da2899SCharles.Forsyth }
264*37da2899SCharles.Forsyth 
265*37da2899SCharles.Forsyth static void
con(ulong o,int r,int opt)266*37da2899SCharles.Forsyth con(ulong o, int r, int opt)
267*37da2899SCharles.Forsyth {
268*37da2899SCharles.Forsyth 	if(opt != 0) {
269*37da2899SCharles.Forsyth 		if(bc(o)) {
270*37da2899SCharles.Forsyth 			FM3I(2, Oadd, o & 0x1fff, RZ, r);
271*37da2899SCharles.Forsyth 			return;
272*37da2899SCharles.Forsyth 		}
273*37da2899SCharles.Forsyth 		if((o & 0x3ff) == 0) {
274*37da2899SCharles.Forsyth 			FM2I(Osethi, o>>10, r);
275*37da2899SCharles.Forsyth 			return;
276*37da2899SCharles.Forsyth 		}
277*37da2899SCharles.Forsyth 	}
278*37da2899SCharles.Forsyth 	FM2I(Osethi, o>>10, r);
279*37da2899SCharles.Forsyth 	FM3I(2, Oadd, o & 0x3ff, r, r);
280*37da2899SCharles.Forsyth }
281*37da2899SCharles.Forsyth 
282*37da2899SCharles.Forsyth static void
mem(int inst,ulong disp,int rm,int r)283*37da2899SCharles.Forsyth mem(int inst, ulong disp, int rm, int r)
284*37da2899SCharles.Forsyth {
285*37da2899SCharles.Forsyth 	int op;
286*37da2899SCharles.Forsyth 
287*37da2899SCharles.Forsyth 	op = 3;
288*37da2899SCharles.Forsyth 	if(inst == Olea) {
289*37da2899SCharles.Forsyth 		op = 2;
290*37da2899SCharles.Forsyth 		inst = Oadd;
291*37da2899SCharles.Forsyth 	}
292*37da2899SCharles.Forsyth 	if(bc(disp)) {
293*37da2899SCharles.Forsyth 		FM3I(op, inst, disp, rm, r);
294*37da2899SCharles.Forsyth 		return;
295*37da2899SCharles.Forsyth 	}
296*37da2899SCharles.Forsyth 	con(disp, RCON, 1);
297*37da2899SCharles.Forsyth 	FM3(op, inst, RCON, rm, r);
298*37da2899SCharles.Forsyth }
299*37da2899SCharles.Forsyth 
300*37da2899SCharles.Forsyth static void
opwld(Inst * i,int mi,int r)301*37da2899SCharles.Forsyth opwld(Inst *i, int mi, int r)
302*37da2899SCharles.Forsyth {
303*37da2899SCharles.Forsyth 	int ir, rta;
304*37da2899SCharles.Forsyth 
305*37da2899SCharles.Forsyth 	switch(UXSRC(i->add)) {
306*37da2899SCharles.Forsyth 	default:
307*37da2899SCharles.Forsyth 		print("%D\n", i);
308*37da2899SCharles.Forsyth 		urk();
309*37da2899SCharles.Forsyth 	case SRC(AFP):
310*37da2899SCharles.Forsyth 		mem(mi, i->s.ind, RFP, r);
311*37da2899SCharles.Forsyth 		return;
312*37da2899SCharles.Forsyth 	case SRC(AMP):
313*37da2899SCharles.Forsyth 		mem(mi, i->s.ind, RMP, r);
314*37da2899SCharles.Forsyth 		return;
315*37da2899SCharles.Forsyth 	case SRC(AIMM):
316*37da2899SCharles.Forsyth 		con(i->s.imm, r, 1);
317*37da2899SCharles.Forsyth 		if(mi == Olea) {
318*37da2899SCharles.Forsyth 			mem(Ostw, O(REG, st), RREG, r);
319*37da2899SCharles.Forsyth 			con((ulong)&R.st, r, 1);
320*37da2899SCharles.Forsyth 		}
321*37da2899SCharles.Forsyth 		return;
322*37da2899SCharles.Forsyth 	case SRC(AIND|AFP):
323*37da2899SCharles.Forsyth 		ir = RFP;
324*37da2899SCharles.Forsyth 		break;
325*37da2899SCharles.Forsyth 	case SRC(AIND|AMP):
326*37da2899SCharles.Forsyth 		ir = RMP;
327*37da2899SCharles.Forsyth 		break;
328*37da2899SCharles.Forsyth 	}
329*37da2899SCharles.Forsyth 	rta = RTA;
330*37da2899SCharles.Forsyth 	if(mi == Olea)
331*37da2899SCharles.Forsyth 		rta = r;
332*37da2899SCharles.Forsyth 	mem(Oldw, i->s.i.f, ir, rta);
333*37da2899SCharles.Forsyth 	mem(mi, i->s.i.s, rta, r);
334*37da2899SCharles.Forsyth }
335*37da2899SCharles.Forsyth 
336*37da2899SCharles.Forsyth static void
opwst(Inst * i,int mi,int r)337*37da2899SCharles.Forsyth opwst(Inst *i, int mi, int r)
338*37da2899SCharles.Forsyth {
339*37da2899SCharles.Forsyth 	int ir, rta;
340*37da2899SCharles.Forsyth 
341*37da2899SCharles.Forsyth 	switch(UXDST(i->add)) {
342*37da2899SCharles.Forsyth 	default:
343*37da2899SCharles.Forsyth 		print("%D\n", i);
344*37da2899SCharles.Forsyth 		urk();
345*37da2899SCharles.Forsyth 	case DST(AIMM):
346*37da2899SCharles.Forsyth 		con(i->d.imm, r, 1);
347*37da2899SCharles.Forsyth 		return;
348*37da2899SCharles.Forsyth 	case DST(AFP):
349*37da2899SCharles.Forsyth 		mem(mi, i->d.ind, RFP, r);
350*37da2899SCharles.Forsyth 		return;
351*37da2899SCharles.Forsyth 	case DST(AMP):
352*37da2899SCharles.Forsyth 		mem(mi, i->d.ind, RMP, r);
353*37da2899SCharles.Forsyth 		return;
354*37da2899SCharles.Forsyth 	case DST(AIND|AFP):
355*37da2899SCharles.Forsyth 		ir = RFP;
356*37da2899SCharles.Forsyth 		break;
357*37da2899SCharles.Forsyth 	case DST(AIND|AMP):
358*37da2899SCharles.Forsyth 		ir = RMP;
359*37da2899SCharles.Forsyth 		break;
360*37da2899SCharles.Forsyth 	}
361*37da2899SCharles.Forsyth 	rta = RTA;
362*37da2899SCharles.Forsyth 	if(mi == Olea)
363*37da2899SCharles.Forsyth 		rta = r;
364*37da2899SCharles.Forsyth 	mem(Oldw, i->d.i.f, ir, rta);
365*37da2899SCharles.Forsyth 	mem(mi, i->d.i.s, rta, r);
366*37da2899SCharles.Forsyth }
367*37da2899SCharles.Forsyth 
368*37da2899SCharles.Forsyth static void
opfl(Adr * a,int am,int mi,int r)369*37da2899SCharles.Forsyth opfl(Adr *a, int am, int mi, int r)
370*37da2899SCharles.Forsyth {
371*37da2899SCharles.Forsyth 	int ir;
372*37da2899SCharles.Forsyth 
373*37da2899SCharles.Forsyth 	switch(am) {
374*37da2899SCharles.Forsyth 	default:
375*37da2899SCharles.Forsyth 		urk();
376*37da2899SCharles.Forsyth 	case AFP:
377*37da2899SCharles.Forsyth 		mem(mi, a->ind, RFP, r);
378*37da2899SCharles.Forsyth 		mem(mi, a->ind+4, RFP, r+1);
379*37da2899SCharles.Forsyth 		return;
380*37da2899SCharles.Forsyth 	case AMP:
381*37da2899SCharles.Forsyth 		mem(mi, a->ind, RMP, r);
382*37da2899SCharles.Forsyth 		mem(mi, a->ind+4, RMP, r+1);
383*37da2899SCharles.Forsyth 		return;
384*37da2899SCharles.Forsyth 	case AIND|AFP:
385*37da2899SCharles.Forsyth 		ir = RFP;
386*37da2899SCharles.Forsyth 		break;
387*37da2899SCharles.Forsyth 	case AIND|AMP:
388*37da2899SCharles.Forsyth 		ir = RMP;
389*37da2899SCharles.Forsyth 		break;
390*37da2899SCharles.Forsyth 	}
391*37da2899SCharles.Forsyth 	mem(Oldw, a->i.f, ir, RTA);
392*37da2899SCharles.Forsyth 	mem(mi, a->i.s, RTA, r);
393*37da2899SCharles.Forsyth 	mem(mi, a->i.s+4, RTA, r+1);
394*37da2899SCharles.Forsyth }
395*37da2899SCharles.Forsyth 
396*37da2899SCharles.Forsyth static void
opflld(Inst * i,int mi,int r)397*37da2899SCharles.Forsyth opflld(Inst *i, int mi, int r)
398*37da2899SCharles.Forsyth {
399*37da2899SCharles.Forsyth 	opfl(&i->s, USRC(i->add), mi, r);
400*37da2899SCharles.Forsyth }
401*37da2899SCharles.Forsyth 
402*37da2899SCharles.Forsyth static void
opflst(Inst * i,int mi,int r)403*37da2899SCharles.Forsyth opflst(Inst *i, int mi, int r)
404*37da2899SCharles.Forsyth {
405*37da2899SCharles.Forsyth 	opfl(&i->d, UDST(i->add), mi, r);
406*37da2899SCharles.Forsyth }
407*37da2899SCharles.Forsyth 
408*37da2899SCharles.Forsyth static void
literal(ulong imm,int roff)409*37da2899SCharles.Forsyth literal(ulong imm, int roff)
410*37da2899SCharles.Forsyth {
411*37da2899SCharles.Forsyth 	nlit++;
412*37da2899SCharles.Forsyth 
413*37da2899SCharles.Forsyth 	con((ulong)litpool, RTA, 0);
414*37da2899SCharles.Forsyth 	mem(Ostw, roff, RREG, RTA);
415*37da2899SCharles.Forsyth 
416*37da2899SCharles.Forsyth 	if(pass == 0)
417*37da2899SCharles.Forsyth 		return;
418*37da2899SCharles.Forsyth 
419*37da2899SCharles.Forsyth 	*litpool = imm;
420*37da2899SCharles.Forsyth 	litpool++;
421*37da2899SCharles.Forsyth }
422*37da2899SCharles.Forsyth 
423*37da2899SCharles.Forsyth static void
punt(Inst * i,int m,void (* fn)(void))424*37da2899SCharles.Forsyth punt(Inst *i, int m, void (*fn)(void))
425*37da2899SCharles.Forsyth {
426*37da2899SCharles.Forsyth 	ulong pc;
427*37da2899SCharles.Forsyth 
428*37da2899SCharles.Forsyth 	if(m & SRCOP) {
429*37da2899SCharles.Forsyth 		if(UXSRC(i->add) == SRC(AIMM))
430*37da2899SCharles.Forsyth 			literal(i->s.imm, O(REG, s));
431*37da2899SCharles.Forsyth 		else {
432*37da2899SCharles.Forsyth 			opwld(i, Olea, RA0);
433*37da2899SCharles.Forsyth 			mem(Ostw, O(REG, s), RREG, RA0);
434*37da2899SCharles.Forsyth 		}
435*37da2899SCharles.Forsyth 	}
436*37da2899SCharles.Forsyth 
437*37da2899SCharles.Forsyth 	if(m & DSTOP) {
438*37da2899SCharles.Forsyth 		opwst(i, Olea, RA0);
439*37da2899SCharles.Forsyth 		mem(Ostw, O(REG, d), RREG, RA0);
440*37da2899SCharles.Forsyth 	}
441*37da2899SCharles.Forsyth 	if(m & WRTPC) {
442*37da2899SCharles.Forsyth 		con(RELPC(patch[i-mod->prog+1]), RA0, 0);
443*37da2899SCharles.Forsyth 		mem(Ostw, O(REG, PC), RREG, RA0);
444*37da2899SCharles.Forsyth 	}
445*37da2899SCharles.Forsyth 	if(m & DBRAN) {
446*37da2899SCharles.Forsyth 		pc = patch[(Inst*)i->d.imm-mod->prog];
447*37da2899SCharles.Forsyth 		literal(RELPC(pc), O(REG, d));
448*37da2899SCharles.Forsyth 	}
449*37da2899SCharles.Forsyth 
450*37da2899SCharles.Forsyth 	switch(i->add&ARM) {
451*37da2899SCharles.Forsyth 	case AXNON:
452*37da2899SCharles.Forsyth 		if(m & THREOP) {
453*37da2899SCharles.Forsyth 			mem(Oldw, O(REG, d), RREG, RA0);
454*37da2899SCharles.Forsyth 			mem(Ostw, O(REG, m), RREG, RA0);
455*37da2899SCharles.Forsyth 		}
456*37da2899SCharles.Forsyth 		break;
457*37da2899SCharles.Forsyth 	case AXIMM:
458*37da2899SCharles.Forsyth 		literal((short)i->reg, O(REG, m));
459*37da2899SCharles.Forsyth 		break;
460*37da2899SCharles.Forsyth 	case AXINF:
461*37da2899SCharles.Forsyth 		mem(Olea, i->reg, RFP, RA0);
462*37da2899SCharles.Forsyth 		mem(Ostw, O(REG, m), RREG, RA0);
463*37da2899SCharles.Forsyth 		break;
464*37da2899SCharles.Forsyth 	case AXINM:
465*37da2899SCharles.Forsyth 		mem(Olea, i->reg, RMP, RA0);
466*37da2899SCharles.Forsyth 		mem(Ostw, O(REG, m), RREG, RA0);
467*37da2899SCharles.Forsyth 		break;
468*37da2899SCharles.Forsyth 	}
469*37da2899SCharles.Forsyth 
470*37da2899SCharles.Forsyth 	CALL(fn);
471*37da2899SCharles.Forsyth 	mem(Ostw, O(REG, FP), RREG, RFP);
472*37da2899SCharles.Forsyth 
473*37da2899SCharles.Forsyth 	con((ulong)&R, RREG, 1);
474*37da2899SCharles.Forsyth 	if(m & TCHECK) {
475*37da2899SCharles.Forsyth 		mem(Oldw, O(REG, t), RREG, RA0);
476*37da2899SCharles.Forsyth 		FM3I(2, Ocmp, 0, RA0, RZ);
477*37da2899SCharles.Forsyth 		BRA(Obe, 5);
478*37da2899SCharles.Forsyth 		NOOP;
479*37da2899SCharles.Forsyth 		mem(Oldw, O(REG, xpc), RREG, RLINK);
480*37da2899SCharles.Forsyth 		RETURN;
481*37da2899SCharles.Forsyth 		NOOP;
482*37da2899SCharles.Forsyth 	}
483*37da2899SCharles.Forsyth 
484*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, FP), RREG, RFP);
485*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, MP), RREG, RMP);
486*37da2899SCharles.Forsyth 
487*37da2899SCharles.Forsyth 	if(m & NEWPC) {
488*37da2899SCharles.Forsyth 		mem(Oldw, O(REG, PC), RREG, RA0);
489*37da2899SCharles.Forsyth 		FM3I(2, Ojmpl, 0, RA0, RZ);
490*37da2899SCharles.Forsyth 		NOOP;
491*37da2899SCharles.Forsyth 	}
492*37da2899SCharles.Forsyth }
493*37da2899SCharles.Forsyth 
494*37da2899SCharles.Forsyth static void
midfl(Inst * i,int mi,int r)495*37da2899SCharles.Forsyth midfl(Inst *i, int mi, int r)
496*37da2899SCharles.Forsyth {
497*37da2899SCharles.Forsyth 	int ir;
498*37da2899SCharles.Forsyth 
499*37da2899SCharles.Forsyth 	switch(i->add&ARM) {
500*37da2899SCharles.Forsyth 	default:
501*37da2899SCharles.Forsyth 		opflst(i, mi, r);
502*37da2899SCharles.Forsyth 		return;
503*37da2899SCharles.Forsyth 	case AXIMM:
504*37da2899SCharles.Forsyth 		con((short)i->reg, r, 1);
505*37da2899SCharles.Forsyth 		return;
506*37da2899SCharles.Forsyth 	case AXINF:
507*37da2899SCharles.Forsyth 		ir = RFP;
508*37da2899SCharles.Forsyth 		break;
509*37da2899SCharles.Forsyth 	case AXINM:
510*37da2899SCharles.Forsyth 		ir = RMP;
511*37da2899SCharles.Forsyth 		break;
512*37da2899SCharles.Forsyth 	}
513*37da2899SCharles.Forsyth 	mem(mi, i->reg, ir, r);
514*37da2899SCharles.Forsyth 	mem(mi, i->reg+4, ir, r+1);
515*37da2899SCharles.Forsyth }
516*37da2899SCharles.Forsyth 
517*37da2899SCharles.Forsyth static void
mid(Inst * i,int mi,int r)518*37da2899SCharles.Forsyth mid(Inst *i, int mi, int r)
519*37da2899SCharles.Forsyth {
520*37da2899SCharles.Forsyth 	int ir;
521*37da2899SCharles.Forsyth 
522*37da2899SCharles.Forsyth 	switch(i->add&ARM) {
523*37da2899SCharles.Forsyth 	default:
524*37da2899SCharles.Forsyth 		opwst(i, mi, r);
525*37da2899SCharles.Forsyth 		return;
526*37da2899SCharles.Forsyth 	case AXIMM:
527*37da2899SCharles.Forsyth 		con((short)i->reg, r, 1);
528*37da2899SCharles.Forsyth 		return;
529*37da2899SCharles.Forsyth 	case AXINF:
530*37da2899SCharles.Forsyth 		ir = RFP;
531*37da2899SCharles.Forsyth 		break;
532*37da2899SCharles.Forsyth 	case AXINM:
533*37da2899SCharles.Forsyth 		ir = RMP;
534*37da2899SCharles.Forsyth 		break;
535*37da2899SCharles.Forsyth 	}
536*37da2899SCharles.Forsyth 	mem(mi, i->reg, ir, r);
537*37da2899SCharles.Forsyth }
538*37da2899SCharles.Forsyth 
539*37da2899SCharles.Forsyth static void
cbral(Inst * i,int jmsw,int jlsw,int mode)540*37da2899SCharles.Forsyth cbral(Inst *i, int jmsw, int jlsw, int mode)
541*37da2899SCharles.Forsyth {
542*37da2899SCharles.Forsyth 	ulong dst, *label;
543*37da2899SCharles.Forsyth 
544*37da2899SCharles.Forsyth 	opwld(i, Olea, RA1);
545*37da2899SCharles.Forsyth 	mid(i, Olea, RA3);
546*37da2899SCharles.Forsyth 	mem(Oldw, 0, RA1, RA2);
547*37da2899SCharles.Forsyth 	mem(Oldw, 0, RA3, RA0);
548*37da2899SCharles.Forsyth 	FM3(2, Ocmp, RA0, RA2, RZ);
549*37da2899SCharles.Forsyth 	label = nil;
550*37da2899SCharles.Forsyth 	dst = i->d.ins-mod->prog;
551*37da2899SCharles.Forsyth 	switch(mode) {
552*37da2899SCharles.Forsyth 	case ANDAND:
553*37da2899SCharles.Forsyth 		label = code;
554*37da2899SCharles.Forsyth 		BRA(jmsw, 0);
555*37da2899SCharles.Forsyth 		break;
556*37da2899SCharles.Forsyth 	case OROR:
557*37da2899SCharles.Forsyth 		BRADIS(jmsw, dst);
558*37da2899SCharles.Forsyth 		break;
559*37da2899SCharles.Forsyth 	case EQAND:
560*37da2899SCharles.Forsyth 		BRADIS(jmsw, dst);
561*37da2899SCharles.Forsyth 		NOOP;
562*37da2899SCharles.Forsyth 		label = code;
563*37da2899SCharles.Forsyth 		BRA(Obne, 0);
564*37da2899SCharles.Forsyth 		break;
565*37da2899SCharles.Forsyth 	}
566*37da2899SCharles.Forsyth 	NOOP;
567*37da2899SCharles.Forsyth 	mem(Oldw, 4, RA3, RA0);
568*37da2899SCharles.Forsyth 	mem(Oldw, 4, RA1, RA2);
569*37da2899SCharles.Forsyth 	FM3(2, Ocmp, RA0, RA2, RZ);
570*37da2899SCharles.Forsyth 	BRADIS(jlsw, dst);
571*37da2899SCharles.Forsyth 	if(label != nil)
572*37da2899SCharles.Forsyth 		PATCH(label);
573*37da2899SCharles.Forsyth }
574*37da2899SCharles.Forsyth 
575*37da2899SCharles.Forsyth static void
comcase(Inst * i,int w)576*37da2899SCharles.Forsyth comcase(Inst *i, int w)
577*37da2899SCharles.Forsyth {
578*37da2899SCharles.Forsyth 	int l;
579*37da2899SCharles.Forsyth 	WORD *t, *e;
580*37da2899SCharles.Forsyth 
581*37da2899SCharles.Forsyth 	if(w != 0) {
582*37da2899SCharles.Forsyth 		opwld(i, Oldw, RA0);		// v
583*37da2899SCharles.Forsyth 		opwst(i, Olea, RCON);		// table
584*37da2899SCharles.Forsyth 		BRAMAC(Oba, MacCASE);
585*37da2899SCharles.Forsyth 		NOOP;
586*37da2899SCharles.Forsyth 	}
587*37da2899SCharles.Forsyth 
588*37da2899SCharles.Forsyth 	t = (WORD*)(mod->origmp+i->d.ind+4);
589*37da2899SCharles.Forsyth 	l = t[-1];
590*37da2899SCharles.Forsyth 
591*37da2899SCharles.Forsyth 	/* have to take care not to relocate the same table twice -
592*37da2899SCharles.Forsyth 	 * the limbo compiler can duplicate a case instruction
593*37da2899SCharles.Forsyth 	 * during its folding phase
594*37da2899SCharles.Forsyth 	 */
595*37da2899SCharles.Forsyth 
596*37da2899SCharles.Forsyth 	if(pass == 0) {
597*37da2899SCharles.Forsyth 		if(l >= 0)
598*37da2899SCharles.Forsyth 			t[-1] = -l-1;	/* Mark it not done */
599*37da2899SCharles.Forsyth 		return;
600*37da2899SCharles.Forsyth 	}
601*37da2899SCharles.Forsyth 	if(l >= 0)			/* Check pass 2 done */
602*37da2899SCharles.Forsyth 		return;
603*37da2899SCharles.Forsyth 	t[-1] = -l-1;			/* Set real count */
604*37da2899SCharles.Forsyth 	e = t + t[-1]*3;
605*37da2899SCharles.Forsyth 	while(t < e) {
606*37da2899SCharles.Forsyth 		t[2] = RELPC(patch[t[2]]);
607*37da2899SCharles.Forsyth 		t += 3;
608*37da2899SCharles.Forsyth 	}
609*37da2899SCharles.Forsyth 	t[0] = RELPC(patch[t[0]]);
610*37da2899SCharles.Forsyth }
611*37da2899SCharles.Forsyth 
612*37da2899SCharles.Forsyth static void
comcasel(Inst * i)613*37da2899SCharles.Forsyth comcasel(Inst *i)
614*37da2899SCharles.Forsyth {
615*37da2899SCharles.Forsyth 	int l;
616*37da2899SCharles.Forsyth 	WORD *t, *e;
617*37da2899SCharles.Forsyth 
618*37da2899SCharles.Forsyth 	t = (WORD*)(mod->origmp+i->d.ind+8);
619*37da2899SCharles.Forsyth 	l = t[-2];
620*37da2899SCharles.Forsyth 	if(pass == 0) {
621*37da2899SCharles.Forsyth 		if(l >= 0)
622*37da2899SCharles.Forsyth 			t[-2] = -l-1;	/* Mark it not done */
623*37da2899SCharles.Forsyth 		return;
624*37da2899SCharles.Forsyth 	}
625*37da2899SCharles.Forsyth 	if(l >= 0)			/* Check pass 2 done */
626*37da2899SCharles.Forsyth 		return;
627*37da2899SCharles.Forsyth 	t[-2] = -l-1;			/* Set real count */
628*37da2899SCharles.Forsyth 	e = t + t[-2]*6;
629*37da2899SCharles.Forsyth 	while(t < e) {
630*37da2899SCharles.Forsyth 		t[4] = RELPC(patch[t[4]]);
631*37da2899SCharles.Forsyth 		t += 6;
632*37da2899SCharles.Forsyth 	}
633*37da2899SCharles.Forsyth 	t[0] = RELPC(patch[t[0]]);
634*37da2899SCharles.Forsyth }
635*37da2899SCharles.Forsyth 
636*37da2899SCharles.Forsyth static void
commframe(Inst * i)637*37da2899SCharles.Forsyth commframe(Inst *i)
638*37da2899SCharles.Forsyth {
639*37da2899SCharles.Forsyth 	int o;
640*37da2899SCharles.Forsyth 	ulong *punt, *mlnil;
641*37da2899SCharles.Forsyth 
642*37da2899SCharles.Forsyth 	opwld(i, Oldw, RA0);
643*37da2899SCharles.Forsyth 	FM3I(2, Ocmp, -1, RA0, RZ);
644*37da2899SCharles.Forsyth 	mlnil = code;
645*37da2899SCharles.Forsyth 	BRA(Obe, 0);
646*37da2899SCharles.Forsyth 	NOOP;
647*37da2899SCharles.Forsyth 
648*37da2899SCharles.Forsyth 	if((i->add&ARM) == AXIMM) {
649*37da2899SCharles.Forsyth 		o = OA(Modlink, links)+i->reg*sizeof(Modl)+O(Modl, frame);
650*37da2899SCharles.Forsyth 		mem(Oldw, o, RA0, RA3);
651*37da2899SCharles.Forsyth 	} else {
652*37da2899SCharles.Forsyth 		mid(i, Oldw, RA1);
653*37da2899SCharles.Forsyth 		FM3I(2, Osll, 3, RA1, RA1);		// assumes sizeof(Modl) == 8
654*37da2899SCharles.Forsyth 		FM3(2, Oadd, RA0, RA1, RA1);
655*37da2899SCharles.Forsyth 		o = OA(Modlink, links)+O(Modl, frame);
656*37da2899SCharles.Forsyth 		mem(Oldw, o, RA1, RA3);
657*37da2899SCharles.Forsyth 	}
658*37da2899SCharles.Forsyth 	mem(Oldw, O(Type, initialize), RA3, RA1);
659*37da2899SCharles.Forsyth 	FM3I(2, Ocmp, 0, RA1, RZ);
660*37da2899SCharles.Forsyth 	punt = code;
661*37da2899SCharles.Forsyth 	BRA(Obne, 0);
662*37da2899SCharles.Forsyth 	NOOP;
663*37da2899SCharles.Forsyth 
664*37da2899SCharles.Forsyth 	opwst(i, Olea, RA0);
665*37da2899SCharles.Forsyth 
666*37da2899SCharles.Forsyth 	/* Type in RA3, destination in RA0 */
667*37da2899SCharles.Forsyth 	PATCH(mlnil);
668*37da2899SCharles.Forsyth 	con(RELPC(patch[i-mod->prog+1])-8, RLINK, 0);
669*37da2899SCharles.Forsyth 	BRAMAC(Oba, MacMFRA);
670*37da2899SCharles.Forsyth 	NOOP;
671*37da2899SCharles.Forsyth 
672*37da2899SCharles.Forsyth 	/* Type in RA3 */
673*37da2899SCharles.Forsyth 	PATCH(punt);
674*37da2899SCharles.Forsyth 	CALL(base+macro[MacFRAM]);
675*37da2899SCharles.Forsyth 	NOOP;
676*37da2899SCharles.Forsyth 	opwst(i, Ostw, RA2);
677*37da2899SCharles.Forsyth }
678*37da2899SCharles.Forsyth 
679*37da2899SCharles.Forsyth static void
commcall(Inst * i)680*37da2899SCharles.Forsyth commcall(Inst *i)
681*37da2899SCharles.Forsyth {
682*37da2899SCharles.Forsyth 	opwld(i, Oldw, RA2);
683*37da2899SCharles.Forsyth 	con(RELPC(patch[i-mod->prog+1]), RA0, 0);
684*37da2899SCharles.Forsyth 	mem(Ostw, O(Frame, lr), RA2, RA0);
685*37da2899SCharles.Forsyth 	mem(Ostw, O(Frame, fp), RA2, RFP);
686*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, M), RREG, RA3);
687*37da2899SCharles.Forsyth 	mem(Ostw, O(Frame, mr), RA2, RA3);
688*37da2899SCharles.Forsyth 	opwst(i, Oldw, RA3);
689*37da2899SCharles.Forsyth 	if((i->add&ARM) == AXIMM) {
690*37da2899SCharles.Forsyth 		CALL(base+macro[MacMCAL]);
691*37da2899SCharles.Forsyth 		mem(Oldw, OA(Modlink, links)+i->reg*sizeof(Modl)+O(Modl, u.pc), RA3, RA0);
692*37da2899SCharles.Forsyth 	} else {
693*37da2899SCharles.Forsyth 		mid(i, Oldw, RA1);
694*37da2899SCharles.Forsyth 		FM3I(2, Osll, 3, RA1, RA1);		// assumes sizeof(Modl) == 8
695*37da2899SCharles.Forsyth 		FM3(2, Oadd, RA1, RA3, RA0);
696*37da2899SCharles.Forsyth 		CALL(base+macro[MacMCAL]);
697*37da2899SCharles.Forsyth 		mem(Oldw, OA(Modlink, links)+O(Modl, u.pc), RA0, RA0);
698*37da2899SCharles.Forsyth 	}
699*37da2899SCharles.Forsyth }
700*37da2899SCharles.Forsyth 
701*37da2899SCharles.Forsyth static void
larith(Inst * i,int op,int opc)702*37da2899SCharles.Forsyth larith(Inst *i, int op, int opc)
703*37da2899SCharles.Forsyth {
704*37da2899SCharles.Forsyth 	opflld(i, Oldw, RA0);
705*37da2899SCharles.Forsyth 	midfl(i, Oldw, RA2);
706*37da2899SCharles.Forsyth 	FM3(2, op, RA1, RA3, RA1);
707*37da2899SCharles.Forsyth 	FM3(2, opc, RA0, RA2, RA0);
708*37da2899SCharles.Forsyth 	opflst(i, Ostw, RA0);
709*37da2899SCharles.Forsyth }
710*37da2899SCharles.Forsyth 
711*37da2899SCharles.Forsyth static void
movloop(Inst * i,int ld,int st)712*37da2899SCharles.Forsyth movloop(Inst *i, int ld, int st)
713*37da2899SCharles.Forsyth {
714*37da2899SCharles.Forsyth 	int s;
715*37da2899SCharles.Forsyth 
716*37da2899SCharles.Forsyth 	s = 1;
717*37da2899SCharles.Forsyth 	if(ld == Oldw)
718*37da2899SCharles.Forsyth 		s = 4;
719*37da2899SCharles.Forsyth 	opwld(i, Olea, RA1);
720*37da2899SCharles.Forsyth 	opwst(i, Olea, RA2);
721*37da2899SCharles.Forsyth 	mem(ld, 0, RA1, RA0);
722*37da2899SCharles.Forsyth 	mem(st, 0, RA2, RA0);
723*37da2899SCharles.Forsyth 	FM3I(2, Oadd, s, RA2, RA2);
724*37da2899SCharles.Forsyth 	FM3I(2, Oaddcc, -1, RA3, RA3);
725*37da2899SCharles.Forsyth 	BRA(Obne, -4);
726*37da2899SCharles.Forsyth 	FM3I(2, Oadd, s, RA1, RA1);
727*37da2899SCharles.Forsyth }
728*37da2899SCharles.Forsyth 
729*37da2899SCharles.Forsyth static
730*37da2899SCharles.Forsyth void
compdbg(void)731*37da2899SCharles.Forsyth compdbg(void)
732*37da2899SCharles.Forsyth {
733*37da2899SCharles.Forsyth 	print("%s:%d@%.8ux\n", R.M->m->name, R.t, R.st);
734*37da2899SCharles.Forsyth }
735*37da2899SCharles.Forsyth 
736*37da2899SCharles.Forsyth static void
shll(Inst * i)737*37da2899SCharles.Forsyth shll(Inst *i)
738*37da2899SCharles.Forsyth {
739*37da2899SCharles.Forsyth 	ulong *lab0, *lab1, *lab2;
740*37da2899SCharles.Forsyth 
741*37da2899SCharles.Forsyth 	opwld(i, Oldw, RA2);
742*37da2899SCharles.Forsyth 	midfl(i, Oldw, RA0);
743*37da2899SCharles.Forsyth 	FM3I(2, Ocmp, RZ, RA2, RZ);
744*37da2899SCharles.Forsyth 	lab0 = code;
745*37da2899SCharles.Forsyth 	BRA(Obe, 0);
746*37da2899SCharles.Forsyth 	FM3I(2, Ocmp, 32, RA2, RZ);
747*37da2899SCharles.Forsyth 	lab1 = code;
748*37da2899SCharles.Forsyth 	BRA(Obl, 0);
749*37da2899SCharles.Forsyth 	NOOP;
750*37da2899SCharles.Forsyth 	FM3I(2, Osub, 32, RA2, RA2);
751*37da2899SCharles.Forsyth 	FM3(2, Osll, RA2, RA1, RA0);
752*37da2899SCharles.Forsyth 	lab2 = code;
753*37da2899SCharles.Forsyth 	BRA(Oba, 0);
754*37da2899SCharles.Forsyth 	MOV(RZ, RA1);
755*37da2899SCharles.Forsyth 
756*37da2899SCharles.Forsyth 	PATCH(lab1);
757*37da2899SCharles.Forsyth 	FM3(2, Osll, RA2, RA0, RA0);
758*37da2899SCharles.Forsyth 	con(32, RA3, 1);
759*37da2899SCharles.Forsyth 	FM3(2, Osub, RA2, RA3, RA3);
760*37da2899SCharles.Forsyth 	FM3(2, Osrl, RA3, RA1, RA3);
761*37da2899SCharles.Forsyth 	FM3(2, Oor, RA0, RA3, RA0);
762*37da2899SCharles.Forsyth 	FM3(2, Osll, RA2, RA1, RA1);
763*37da2899SCharles.Forsyth 
764*37da2899SCharles.Forsyth 	PATCH(lab0);
765*37da2899SCharles.Forsyth 	PATCH(lab2);
766*37da2899SCharles.Forsyth 	opflst(i, Ostw, RA0);
767*37da2899SCharles.Forsyth }
768*37da2899SCharles.Forsyth 
769*37da2899SCharles.Forsyth static void
comp(Inst * i)770*37da2899SCharles.Forsyth comp(Inst *i)
771*37da2899SCharles.Forsyth {
772*37da2899SCharles.Forsyth 	int r;
773*37da2899SCharles.Forsyth 	WORD *t, *e;
774*37da2899SCharles.Forsyth 	char buf[64];
775*37da2899SCharles.Forsyth 
776*37da2899SCharles.Forsyth 	if(0) {
777*37da2899SCharles.Forsyth 		Inst xx;
778*37da2899SCharles.Forsyth 		xx.add = AXIMM|SRC(AIMM);
779*37da2899SCharles.Forsyth 		xx.s.imm = (ulong)code;
780*37da2899SCharles.Forsyth 		xx.reg = i-mod->prog;
781*37da2899SCharles.Forsyth 		puntpc = 0;
782*37da2899SCharles.Forsyth 		punt(&xx, SRCOP, compdbg);
783*37da2899SCharles.Forsyth 		puntpc = 1;
784*37da2899SCharles.Forsyth 	}
785*37da2899SCharles.Forsyth 
786*37da2899SCharles.Forsyth 	switch(i->op) {
787*37da2899SCharles.Forsyth 	default:
788*37da2899SCharles.Forsyth 		snprint(buf, sizeof buf, "%s compile, no '%D'", mod->name, i);
789*37da2899SCharles.Forsyth 		error(buf);
790*37da2899SCharles.Forsyth 		break;
791*37da2899SCharles.Forsyth 	case IMCALL:
792*37da2899SCharles.Forsyth 		if((i->add&ARM) == AXIMM)
793*37da2899SCharles.Forsyth 			commcall(i);
794*37da2899SCharles.Forsyth 		else
795*37da2899SCharles.Forsyth 			punt(i, SRCOP|DSTOP|THREOP|WRTPC|NEWPC, optab[i->op]);
796*37da2899SCharles.Forsyth 		break;
797*37da2899SCharles.Forsyth 	case ISEND:
798*37da2899SCharles.Forsyth 	case IRECV:
799*37da2899SCharles.Forsyth 	case IALT:
800*37da2899SCharles.Forsyth 		punt(i, SRCOP|DSTOP|TCHECK|WRTPC, optab[i->op]);
801*37da2899SCharles.Forsyth 		break;
802*37da2899SCharles.Forsyth 	case ISPAWN:
803*37da2899SCharles.Forsyth 		punt(i, SRCOP|DBRAN, optab[i->op]);
804*37da2899SCharles.Forsyth 		break;
805*37da2899SCharles.Forsyth 	case IBNEC:
806*37da2899SCharles.Forsyth 	case IBEQC:
807*37da2899SCharles.Forsyth 	case IBLTC:
808*37da2899SCharles.Forsyth 	case IBLEC:
809*37da2899SCharles.Forsyth 	case IBGTC:
810*37da2899SCharles.Forsyth 	case IBGEC:
811*37da2899SCharles.Forsyth 		punt(i, SRCOP|DBRAN|NEWPC|WRTPC, optab[i->op]);
812*37da2899SCharles.Forsyth 		break;
813*37da2899SCharles.Forsyth 	case ICASEC:
814*37da2899SCharles.Forsyth 		comcase(i, 0);
815*37da2899SCharles.Forsyth 		punt(i, SRCOP|DSTOP|NEWPC, optab[i->op]);
816*37da2899SCharles.Forsyth 		break;
817*37da2899SCharles.Forsyth 	case ICASEL:
818*37da2899SCharles.Forsyth 		comcasel(i);
819*37da2899SCharles.Forsyth 		punt(i, SRCOP|DSTOP|NEWPC, optab[i->op]);
820*37da2899SCharles.Forsyth 		break;
821*37da2899SCharles.Forsyth 	case IADDC:
822*37da2899SCharles.Forsyth 	case IMULL:
823*37da2899SCharles.Forsyth 	case IDIVL:
824*37da2899SCharles.Forsyth 	case IMODL:
825*37da2899SCharles.Forsyth 	case IMODW:
826*37da2899SCharles.Forsyth 	case IMODB:
827*37da2899SCharles.Forsyth 	case IMNEWZ:
828*37da2899SCharles.Forsyth 		punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
829*37da2899SCharles.Forsyth 		break;
830*37da2899SCharles.Forsyth 	case ILOAD:
831*37da2899SCharles.Forsyth 	case INEWA:
832*37da2899SCharles.Forsyth 	case INEWAZ:
833*37da2899SCharles.Forsyth 	case INEW:
834*37da2899SCharles.Forsyth 	case INEWZ:
835*37da2899SCharles.Forsyth 	case ISLICEA:
836*37da2899SCharles.Forsyth 	case ISLICELA:
837*37da2899SCharles.Forsyth 	case ICONSB:
838*37da2899SCharles.Forsyth 	case ICONSW:
839*37da2899SCharles.Forsyth 	case ICONSL:
840*37da2899SCharles.Forsyth 	case ICONSF:
841*37da2899SCharles.Forsyth 	case ICONSM:
842*37da2899SCharles.Forsyth 	case ICONSMP:
843*37da2899SCharles.Forsyth 	case ICONSP:
844*37da2899SCharles.Forsyth 	case IMOVMP:
845*37da2899SCharles.Forsyth 	case IHEADMP:
846*37da2899SCharles.Forsyth 	case IHEADM:
847*37da2899SCharles.Forsyth 	case IHEADB:
848*37da2899SCharles.Forsyth 	case IHEADW:
849*37da2899SCharles.Forsyth 	case IHEADL:
850*37da2899SCharles.Forsyth 	case IHEADF:
851*37da2899SCharles.Forsyth 	case IINDC:
852*37da2899SCharles.Forsyth 	case ILENC:
853*37da2899SCharles.Forsyth 	case IINSC:
854*37da2899SCharles.Forsyth 	case ICVTAC:
855*37da2899SCharles.Forsyth 	case ICVTCW:
856*37da2899SCharles.Forsyth 	case ICVTWC:
857*37da2899SCharles.Forsyth 	case ICVTLC:
858*37da2899SCharles.Forsyth 	case ICVTCL:
859*37da2899SCharles.Forsyth 	case ICVTFC:
860*37da2899SCharles.Forsyth 	case ICVTCF:
861*37da2899SCharles.Forsyth 	case ICVTRF:
862*37da2899SCharles.Forsyth 	case ICVTFR:
863*37da2899SCharles.Forsyth 	case IMSPAWN:
864*37da2899SCharles.Forsyth 	case ICVTCA:
865*37da2899SCharles.Forsyth 	case ISLICEC:
866*37da2899SCharles.Forsyth 	case INBALT:
867*37da2899SCharles.Forsyth 		punt(i, SRCOP|DSTOP, optab[i->op]);
868*37da2899SCharles.Forsyth 		break;
869*37da2899SCharles.Forsyth 	case INEWCM:
870*37da2899SCharles.Forsyth 	case INEWCMP:
871*37da2899SCharles.Forsyth 		punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
872*37da2899SCharles.Forsyth 		break;
873*37da2899SCharles.Forsyth 	case IMFRAME:
874*37da2899SCharles.Forsyth 		if((i->add&ARM) == AXIMM)
875*37da2899SCharles.Forsyth 			commframe(i);
876*37da2899SCharles.Forsyth 		else
877*37da2899SCharles.Forsyth 			punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
878*37da2899SCharles.Forsyth 		break;
879*37da2899SCharles.Forsyth 	case ICASE:
880*37da2899SCharles.Forsyth 		comcase(i, 1);
881*37da2899SCharles.Forsyth 		break;
882*37da2899SCharles.Forsyth 	case IGOTO:
883*37da2899SCharles.Forsyth 		opwld(i, Oldw, RA1);
884*37da2899SCharles.Forsyth 		opwst(i, Olea, RA0);
885*37da2899SCharles.Forsyth 		FM3I(2, Osll, 2, RA1, RA1);
886*37da2899SCharles.Forsyth 		FM3(3, Oldw, RA1, RA0, RA0);
887*37da2899SCharles.Forsyth 		FM3I(2, Ojmpl, 0, RA0, RZ);
888*37da2899SCharles.Forsyth 		NOOP;
889*37da2899SCharles.Forsyth 
890*37da2899SCharles.Forsyth 		if(pass == 0)
891*37da2899SCharles.Forsyth 			break;
892*37da2899SCharles.Forsyth 
893*37da2899SCharles.Forsyth 		t = (WORD*)(mod->origmp+i->d.ind);
894*37da2899SCharles.Forsyth 		e = t + t[-1];
895*37da2899SCharles.Forsyth 		t[-1] = 0;
896*37da2899SCharles.Forsyth 		while(t < e) {
897*37da2899SCharles.Forsyth 			t[0] = RELPC(patch[t[0]]);
898*37da2899SCharles.Forsyth 			t++;
899*37da2899SCharles.Forsyth 		}
900*37da2899SCharles.Forsyth 		break;
901*37da2899SCharles.Forsyth 	case IMOVL:
902*37da2899SCharles.Forsyth 	movl:
903*37da2899SCharles.Forsyth 		opflld(i, Oldw, RA0);
904*37da2899SCharles.Forsyth 		opflst(i, Ostw, RA0);
905*37da2899SCharles.Forsyth 		break;
906*37da2899SCharles.Forsyth 	case IMOVM:
907*37da2899SCharles.Forsyth 		if((i->add&ARM) == AXIMM) {
908*37da2899SCharles.Forsyth 			if(i->reg == 8)
909*37da2899SCharles.Forsyth 				goto movl;
910*37da2899SCharles.Forsyth 			if((i->reg&3) == 0) {
911*37da2899SCharles.Forsyth 				con(i->reg>>2, RA3, 1);
912*37da2899SCharles.Forsyth 				movloop(i, Oldw, Ostw);
913*37da2899SCharles.Forsyth 				break;
914*37da2899SCharles.Forsyth 			}
915*37da2899SCharles.Forsyth 		}
916*37da2899SCharles.Forsyth 		mid(i, Oldw, RA3);
917*37da2899SCharles.Forsyth 		movloop(i, Oldbu, Ostb);
918*37da2899SCharles.Forsyth 		break;
919*37da2899SCharles.Forsyth 	case IFRAME:
920*37da2899SCharles.Forsyth 		if(UXSRC(i->add) != SRC(AIMM)) {
921*37da2899SCharles.Forsyth 			punt(i, SRCOP|DSTOP, optab[i->op]);
922*37da2899SCharles.Forsyth 			break;
923*37da2899SCharles.Forsyth 		}
924*37da2899SCharles.Forsyth 		tinit[i->s.imm] = 1;
925*37da2899SCharles.Forsyth 		con((ulong)mod->type[i->s.imm], RA3, 1);
926*37da2899SCharles.Forsyth 		CALL(base+macro[MacFRAM]);
927*37da2899SCharles.Forsyth 		NOOP;
928*37da2899SCharles.Forsyth 		opwst(i, Ostw, RA2);
929*37da2899SCharles.Forsyth 		break;
930*37da2899SCharles.Forsyth 	case INEWCB:
931*37da2899SCharles.Forsyth 	case INEWCW:
932*37da2899SCharles.Forsyth 	case INEWCF:
933*37da2899SCharles.Forsyth 	case INEWCP:
934*37da2899SCharles.Forsyth 	case INEWCL:
935*37da2899SCharles.Forsyth 		punt(i, DSTOP|THREOP, optab[i->op]);
936*37da2899SCharles.Forsyth 		break;
937*37da2899SCharles.Forsyth 	case IEXIT:
938*37da2899SCharles.Forsyth 		punt(i, 0, optab[i->op]);
939*37da2899SCharles.Forsyth 		break;
940*37da2899SCharles.Forsyth 	case ICVTBW:
941*37da2899SCharles.Forsyth 		opwld(i, Oldbu, RA0);
942*37da2899SCharles.Forsyth 		opwst(i, Ostw, RA0);
943*37da2899SCharles.Forsyth 		break;
944*37da2899SCharles.Forsyth 	case ICVTWB:
945*37da2899SCharles.Forsyth 		opwld(i, Oldw, RA0);
946*37da2899SCharles.Forsyth 		opwst(i, Ostb, RA0);
947*37da2899SCharles.Forsyth 		break;
948*37da2899SCharles.Forsyth 	case ILEA:
949*37da2899SCharles.Forsyth 		opwld(i, Olea, RA0);
950*37da2899SCharles.Forsyth 		opwst(i, Ostw, RA0);
951*37da2899SCharles.Forsyth 		break;
952*37da2899SCharles.Forsyth 	case IMOVW:
953*37da2899SCharles.Forsyth 		opwld(i, Oldw, RA0);
954*37da2899SCharles.Forsyth 		opwst(i, Ostw, RA0);
955*37da2899SCharles.Forsyth 		break;
956*37da2899SCharles.Forsyth 	case IMOVB:
957*37da2899SCharles.Forsyth 		opwld(i, Oldbu, RA0);
958*37da2899SCharles.Forsyth 		opwst(i, Ostb, RA0);
959*37da2899SCharles.Forsyth 		break;
960*37da2899SCharles.Forsyth 	case ICVTSW:
961*37da2899SCharles.Forsyth 		opwld(i, Oldsh, RA0);
962*37da2899SCharles.Forsyth 		opwst(i, Ostw, RA0);
963*37da2899SCharles.Forsyth 		break;
964*37da2899SCharles.Forsyth 	case ICVTWS:
965*37da2899SCharles.Forsyth 		opwld(i, Oldw, RA0);
966*37da2899SCharles.Forsyth 		opwst(i, Osth, RA0);
967*37da2899SCharles.Forsyth 		break;
968*37da2899SCharles.Forsyth 	case ITAIL:
969*37da2899SCharles.Forsyth 		opwld(i, Oldw, RA0);
970*37da2899SCharles.Forsyth 		mem(Oldw, O(List, tail), RA0, RA1);
971*37da2899SCharles.Forsyth 		goto movp;
972*37da2899SCharles.Forsyth 	case IMOVP:
973*37da2899SCharles.Forsyth 	case IHEADP:
974*37da2899SCharles.Forsyth 		opwld(i, Oldw, RA1);
975*37da2899SCharles.Forsyth 		if(i->op == IHEADP)
976*37da2899SCharles.Forsyth 			mem(Oldw, OA(List, data), RA1, RA1);
977*37da2899SCharles.Forsyth 	movp:
978*37da2899SCharles.Forsyth 		FM3I(2, Ocmp, (ulong)H, RA1, RZ);
979*37da2899SCharles.Forsyth 		BRA(Obe, 5);
980*37da2899SCharles.Forsyth 		con((ulong)&mutator, RA2, 1);
981*37da2899SCharles.Forsyth 		CALL(base+macro[MacCOLR]);
982*37da2899SCharles.Forsyth 		mem(Oldw, O(Heap, ref)-sizeof(Heap), RA1, RA0);
983*37da2899SCharles.Forsyth 		opwst(i, Oldw, RA0);
984*37da2899SCharles.Forsyth 		opwst(i, Ostw, RA1);
985*37da2899SCharles.Forsyth 		CALL(base+macro[MacFRP]);
986*37da2899SCharles.Forsyth 		NOOP;
987*37da2899SCharles.Forsyth 		break;
988*37da2899SCharles.Forsyth 	case ILENA:
989*37da2899SCharles.Forsyth 		opwld(i, Oldw, RA1);
990*37da2899SCharles.Forsyth 		FM3I(2, Ocmp, (ulong)H, RA1, RZ);
991*37da2899SCharles.Forsyth 		BRA(Obe, 3);
992*37da2899SCharles.Forsyth 		con(0, RA0, 1);
993*37da2899SCharles.Forsyth 		mem(Oldw, O(Array, len), RA1, RA0);
994*37da2899SCharles.Forsyth 		opwst(i, Ostw, RA0);
995*37da2899SCharles.Forsyth 		break;
996*37da2899SCharles.Forsyth 	case ILENL:
997*37da2899SCharles.Forsyth 		con(0, RA0, 1);
998*37da2899SCharles.Forsyth 		opwld(i, Oldw, RA1);
999*37da2899SCharles.Forsyth 		FM3I(2, Ocmp, (ulong)H, RA1, RZ);
1000*37da2899SCharles.Forsyth 		BRA(Obe, 5);
1001*37da2899SCharles.Forsyth 		NOOP;
1002*37da2899SCharles.Forsyth 		mem(Oldw, O(List, tail), RA1, RA1);
1003*37da2899SCharles.Forsyth 		BRA(Oba, -4);
1004*37da2899SCharles.Forsyth 		FM3I(2, Oadd, 1, RA0, RA0);
1005*37da2899SCharles.Forsyth 		opwst(i, Ostw, RA0);
1006*37da2899SCharles.Forsyth 		break;
1007*37da2899SCharles.Forsyth 	case ICALL:
1008*37da2899SCharles.Forsyth 		opwld(i, Oldw, RA0);
1009*37da2899SCharles.Forsyth 		con(RELPC(patch[i-mod->prog+1]), RA1, 0);
1010*37da2899SCharles.Forsyth 		mem(Ostw, O(Frame, lr), RA0, RA1);
1011*37da2899SCharles.Forsyth 		mem(Ostw, O(Frame, fp), RA0, RFP);
1012*37da2899SCharles.Forsyth 		BRADIS(Oba, i->d.ins-mod->prog);
1013*37da2899SCharles.Forsyth 		MOV(RA0, RFP);
1014*37da2899SCharles.Forsyth 		break;
1015*37da2899SCharles.Forsyth 	case IJMP:
1016*37da2899SCharles.Forsyth 		BRADIS(Oba, i->d.ins-mod->prog);
1017*37da2899SCharles.Forsyth 		NOOP;
1018*37da2899SCharles.Forsyth 		break;
1019*37da2899SCharles.Forsyth 	case IBEQW:
1020*37da2899SCharles.Forsyth 		r = Obe;
1021*37da2899SCharles.Forsyth 	braw:
1022*37da2899SCharles.Forsyth 		opwld(i, Oldw, RA1);
1023*37da2899SCharles.Forsyth 		mid(i, Oldw, RA0);
1024*37da2899SCharles.Forsyth 		FM3(2, Ocmp, RA0, RA1, RZ);
1025*37da2899SCharles.Forsyth 		BRADIS(r, i->d.ins-mod->prog);
1026*37da2899SCharles.Forsyth 		NOOP;
1027*37da2899SCharles.Forsyth 		break;
1028*37da2899SCharles.Forsyth 	case IBNEW:
1029*37da2899SCharles.Forsyth 		r = Obne;
1030*37da2899SCharles.Forsyth 		goto braw;
1031*37da2899SCharles.Forsyth 	case IBLTW:
1032*37da2899SCharles.Forsyth 		r = Obl;
1033*37da2899SCharles.Forsyth 		goto braw;
1034*37da2899SCharles.Forsyth 	case IBLEW:
1035*37da2899SCharles.Forsyth 		r = Oble;
1036*37da2899SCharles.Forsyth 		goto braw;
1037*37da2899SCharles.Forsyth 	case IBGTW:
1038*37da2899SCharles.Forsyth 		r = Obg;
1039*37da2899SCharles.Forsyth 		goto braw;
1040*37da2899SCharles.Forsyth 	case IBGEW:
1041*37da2899SCharles.Forsyth 		r = Obge;
1042*37da2899SCharles.Forsyth 		goto braw;
1043*37da2899SCharles.Forsyth 	case IBEQB:
1044*37da2899SCharles.Forsyth 		r = Obe;
1045*37da2899SCharles.Forsyth 	brab:
1046*37da2899SCharles.Forsyth 		opwld(i, Oldbu, RA1);
1047*37da2899SCharles.Forsyth 		mid(i, Oldbu, RA0);
1048*37da2899SCharles.Forsyth 		FM3(2, Ocmp, RA0, RA1, RZ);
1049*37da2899SCharles.Forsyth 		BRADIS(r, i->d.ins-mod->prog);
1050*37da2899SCharles.Forsyth 		NOOP;
1051*37da2899SCharles.Forsyth 		break;
1052*37da2899SCharles.Forsyth 	case IBNEB:
1053*37da2899SCharles.Forsyth 		r = Obne;
1054*37da2899SCharles.Forsyth 		goto brab;
1055*37da2899SCharles.Forsyth 	case IBLTB:
1056*37da2899SCharles.Forsyth 		r = Obl;
1057*37da2899SCharles.Forsyth 		goto brab;
1058*37da2899SCharles.Forsyth 	case IBLEB:
1059*37da2899SCharles.Forsyth 		r = Oble;
1060*37da2899SCharles.Forsyth 		goto brab;
1061*37da2899SCharles.Forsyth 	case IBGTB:
1062*37da2899SCharles.Forsyth 		r = Obg;
1063*37da2899SCharles.Forsyth 		goto brab;
1064*37da2899SCharles.Forsyth 	case IBGEB:
1065*37da2899SCharles.Forsyth 		r = Obge;
1066*37da2899SCharles.Forsyth 		goto brab;
1067*37da2899SCharles.Forsyth 	case IBEQF:
1068*37da2899SCharles.Forsyth 		r = Ofbe;
1069*37da2899SCharles.Forsyth 	braf:
1070*37da2899SCharles.Forsyth 		opflld(i, Oldf, FA4);
1071*37da2899SCharles.Forsyth 		midfl(i, Oldf, FA2);
1072*37da2899SCharles.Forsyth 		FMF2(OfcmpD, FA2, FA4, 0);
1073*37da2899SCharles.Forsyth 		NOOP;
1074*37da2899SCharles.Forsyth 		BRAFDIS(r, i->d.ins-mod->prog);
1075*37da2899SCharles.Forsyth 		NOOP;
1076*37da2899SCharles.Forsyth 		break;
1077*37da2899SCharles.Forsyth 	case IBNEF:
1078*37da2899SCharles.Forsyth 		r = Ofbne;
1079*37da2899SCharles.Forsyth 		goto braf;
1080*37da2899SCharles.Forsyth 	case IBLTF:
1081*37da2899SCharles.Forsyth 		r = Ofbl;
1082*37da2899SCharles.Forsyth 		goto braf;
1083*37da2899SCharles.Forsyth 	case IBLEF:
1084*37da2899SCharles.Forsyth 		r = Ofble;
1085*37da2899SCharles.Forsyth 		goto braf;
1086*37da2899SCharles.Forsyth 	case IBGTF:
1087*37da2899SCharles.Forsyth 		r = Ofbg;
1088*37da2899SCharles.Forsyth 		goto braf;
1089*37da2899SCharles.Forsyth 	case IBGEF:
1090*37da2899SCharles.Forsyth 		r = Ofbge;
1091*37da2899SCharles.Forsyth 		goto braf;
1092*37da2899SCharles.Forsyth 	case IRET:
1093*37da2899SCharles.Forsyth 		BRAMAC(Oba, MacRET);
1094*37da2899SCharles.Forsyth 		mem(Oldw, O(Frame,t), RFP, RA1);
1095*37da2899SCharles.Forsyth 		break;
1096*37da2899SCharles.Forsyth 	case IORW:
1097*37da2899SCharles.Forsyth 		r = Oor;
1098*37da2899SCharles.Forsyth 		goto arithw;
1099*37da2899SCharles.Forsyth 	case IANDW:
1100*37da2899SCharles.Forsyth 		r = Oand;
1101*37da2899SCharles.Forsyth 		goto arithw;
1102*37da2899SCharles.Forsyth 	case IXORW:
1103*37da2899SCharles.Forsyth 		r = Oxor;
1104*37da2899SCharles.Forsyth 		goto arithw;
1105*37da2899SCharles.Forsyth 	case ISUBW:
1106*37da2899SCharles.Forsyth 		r = Osub;
1107*37da2899SCharles.Forsyth 		goto arithw;
1108*37da2899SCharles.Forsyth 	case ISHRW:
1109*37da2899SCharles.Forsyth 		r = Osra;
1110*37da2899SCharles.Forsyth 		goto arithw;
1111*37da2899SCharles.Forsyth 	case ISHLW:
1112*37da2899SCharles.Forsyth 		r = Osll;
1113*37da2899SCharles.Forsyth 		goto arithw;
1114*37da2899SCharles.Forsyth 	case ILSRW:
1115*37da2899SCharles.Forsyth 		r = Osrl;
1116*37da2899SCharles.Forsyth 		goto arithw;
1117*37da2899SCharles.Forsyth 	case IMULW:
1118*37da2899SCharles.Forsyth 		r = Omul;
1119*37da2899SCharles.Forsyth 		goto arithw;
1120*37da2899SCharles.Forsyth 	case IDIVW:
1121*37da2899SCharles.Forsyth 		r = Osdiv;
1122*37da2899SCharles.Forsyth 		goto arithw;
1123*37da2899SCharles.Forsyth 	case IADDW:
1124*37da2899SCharles.Forsyth 		r = Oadd;
1125*37da2899SCharles.Forsyth 	arithw:
1126*37da2899SCharles.Forsyth 		mid(i, Oldw, RA1);
1127*37da2899SCharles.Forsyth 		if(i->op == IDIVW) {
1128*37da2899SCharles.Forsyth 			FM3I(2, Osra, 31, RA1, RA0);
1129*37da2899SCharles.Forsyth 			FM3(2, Owry, RZ, RA0, 0);
1130*37da2899SCharles.Forsyth 		}
1131*37da2899SCharles.Forsyth 		if(UXSRC(i->add) == SRC(AIMM) && bc(i->s.imm))
1132*37da2899SCharles.Forsyth 			FM3I(2, r, i->s.imm, RA1, RA0);
1133*37da2899SCharles.Forsyth 		else {
1134*37da2899SCharles.Forsyth 			opwld(i, Oldw, RA0);
1135*37da2899SCharles.Forsyth 			FM3(2, r, RA0, RA1, RA0);
1136*37da2899SCharles.Forsyth 		}
1137*37da2899SCharles.Forsyth 		opwst(i, Ostw, RA0);
1138*37da2899SCharles.Forsyth 		break;
1139*37da2899SCharles.Forsyth 	case IORB:
1140*37da2899SCharles.Forsyth 		r = Oor;
1141*37da2899SCharles.Forsyth 		goto arithb;
1142*37da2899SCharles.Forsyth 	case IANDB:
1143*37da2899SCharles.Forsyth 		r = Oand;
1144*37da2899SCharles.Forsyth 		goto arithb;
1145*37da2899SCharles.Forsyth 	case IXORB:
1146*37da2899SCharles.Forsyth 		r = Oxor;
1147*37da2899SCharles.Forsyth 		goto arithb;
1148*37da2899SCharles.Forsyth 	case ISUBB:
1149*37da2899SCharles.Forsyth 		r = Osub;
1150*37da2899SCharles.Forsyth 		goto arithb;
1151*37da2899SCharles.Forsyth 	case IMULB:
1152*37da2899SCharles.Forsyth 		r = Omul;
1153*37da2899SCharles.Forsyth 		goto arithb;
1154*37da2899SCharles.Forsyth 	case IDIVB:
1155*37da2899SCharles.Forsyth 		FM3(2, Owry, RZ, RZ, 0);
1156*37da2899SCharles.Forsyth 		r = Osdiv;
1157*37da2899SCharles.Forsyth 		goto arithb;
1158*37da2899SCharles.Forsyth 	case IADDB:
1159*37da2899SCharles.Forsyth 		r = Oadd;
1160*37da2899SCharles.Forsyth 	arithb:
1161*37da2899SCharles.Forsyth 		mid(i, Oldbu, RA1);
1162*37da2899SCharles.Forsyth 		opwld(i, Oldbu, RA0);
1163*37da2899SCharles.Forsyth 		FM3(2, r, RA0, RA1, RA0);
1164*37da2899SCharles.Forsyth 		opwst(i, Ostb, RA0);
1165*37da2899SCharles.Forsyth 		break;
1166*37da2899SCharles.Forsyth 	case ISHRB:
1167*37da2899SCharles.Forsyth 		r = Osra;
1168*37da2899SCharles.Forsyth 		goto shiftb;
1169*37da2899SCharles.Forsyth 	case ISHLB:
1170*37da2899SCharles.Forsyth 		r = Osll;
1171*37da2899SCharles.Forsyth 	shiftb:
1172*37da2899SCharles.Forsyth 		mid(i, Oldbu, RA1);
1173*37da2899SCharles.Forsyth 		if(UXSRC(i->add) == SRC(AIMM) && bc(i->s.imm))
1174*37da2899SCharles.Forsyth 			FM3I(2, r, i->s.imm, RA1, RA0);
1175*37da2899SCharles.Forsyth 		else {
1176*37da2899SCharles.Forsyth 			opwld(i, Oldw, RA0);
1177*37da2899SCharles.Forsyth 			FM3(2, r, RA0, RA1, RA0);
1178*37da2899SCharles.Forsyth 		}
1179*37da2899SCharles.Forsyth 		opwst(i, Ostb, RA0);
1180*37da2899SCharles.Forsyth 		break;
1181*37da2899SCharles.Forsyth 	case IINDL:
1182*37da2899SCharles.Forsyth 	case IINDF:
1183*37da2899SCharles.Forsyth 	case IINDW:
1184*37da2899SCharles.Forsyth 	case IINDB:
1185*37da2899SCharles.Forsyth 		opwld(i, Oldw, RA0);			/* a */
1186*37da2899SCharles.Forsyth 		r = 0;
1187*37da2899SCharles.Forsyth 		switch(i->op) {
1188*37da2899SCharles.Forsyth 		case IINDL:
1189*37da2899SCharles.Forsyth 		case IINDF:
1190*37da2899SCharles.Forsyth 			r = 3;
1191*37da2899SCharles.Forsyth 			break;
1192*37da2899SCharles.Forsyth 		case IINDW:
1193*37da2899SCharles.Forsyth 			r = 2;
1194*37da2899SCharles.Forsyth 			break;
1195*37da2899SCharles.Forsyth 		}
1196*37da2899SCharles.Forsyth 		if(UXDST(i->add) == DST(AIMM) && bc(i->d.imm<<r)) {
1197*37da2899SCharles.Forsyth 			mem(Oldw, O(Array, data), RA0, RA0);
1198*37da2899SCharles.Forsyth 			FM3I(2, Oadd, (i->d.imm<<r), RA0, RA0);
1199*37da2899SCharles.Forsyth 		}
1200*37da2899SCharles.Forsyth 		else {
1201*37da2899SCharles.Forsyth 			opwst(i, Oldw, RA1);
1202*37da2899SCharles.Forsyth 			mem(Oldw, O(Array, data), RA0, RA0);
1203*37da2899SCharles.Forsyth 			if(r != 0)
1204*37da2899SCharles.Forsyth 				FM3I(2, Osll, r, RA1, RA1);
1205*37da2899SCharles.Forsyth 			FM3(2, Oadd, RA0, RA1, RA0);
1206*37da2899SCharles.Forsyth 		}
1207*37da2899SCharles.Forsyth 		r = RMP;
1208*37da2899SCharles.Forsyth 		if((i->add&ARM) == AXINF)
1209*37da2899SCharles.Forsyth 			r = RFP;
1210*37da2899SCharles.Forsyth 		mem(Ostw, i->reg, r, RA0);
1211*37da2899SCharles.Forsyth 		break;
1212*37da2899SCharles.Forsyth 	case IINDX:
1213*37da2899SCharles.Forsyth 		opwld(i, Oldw, RA0);			/* a */
1214*37da2899SCharles.Forsyth 		/*
1215*37da2899SCharles.Forsyth 		r = 0;
1216*37da2899SCharles.Forsyth 		if(UXDST(i->add) == DST(AIMM) && bc(i->d.imm<<r))
1217*37da2899SCharles.Forsyth 			r = i->d.imm<<r;
1218*37da2899SCharles.Forsyth 		else
1219*37da2899SCharles.Forsyth 		*/
1220*37da2899SCharles.Forsyth 			opwst(i, Oldw, RA1);		/* i */
1221*37da2899SCharles.Forsyth 		mem(Oldw, O(Array, t), RA0, RA2);
1222*37da2899SCharles.Forsyth 		mem(Oldw, O(Array, data), RA0, RA0);
1223*37da2899SCharles.Forsyth 		mem(Oldw, O(Type, size), RA2, RA2);
1224*37da2899SCharles.Forsyth 		/*
1225*37da2899SCharles.Forsyth 		if(r != 0)
1226*37da2899SCharles.Forsyth 			FM3I(2, Oumul, r, RA2, RA1);
1227*37da2899SCharles.Forsyth 		else
1228*37da2899SCharles.Forsyth 		*/
1229*37da2899SCharles.Forsyth 			FM3(2, Oumul, RA1, RA2, RA1);
1230*37da2899SCharles.Forsyth 		FM3(2, Oadd, RA0, RA1, RA0);
1231*37da2899SCharles.Forsyth 		r = RMP;
1232*37da2899SCharles.Forsyth 		if((i->add&ARM) == AXINF)
1233*37da2899SCharles.Forsyth 			r = RFP;
1234*37da2899SCharles.Forsyth 		mem(Ostw, i->reg, r, RA0);
1235*37da2899SCharles.Forsyth 		break;
1236*37da2899SCharles.Forsyth 	case IADDL:
1237*37da2899SCharles.Forsyth 		larith(i, Oaddcc, Oaddx);
1238*37da2899SCharles.Forsyth 		break;
1239*37da2899SCharles.Forsyth 	case ISUBL:
1240*37da2899SCharles.Forsyth 		larith(i, Osubcc, Osubx);
1241*37da2899SCharles.Forsyth 		break;
1242*37da2899SCharles.Forsyth 	case IORL:
1243*37da2899SCharles.Forsyth 		larith(i, Oor, Oor);
1244*37da2899SCharles.Forsyth 		break;
1245*37da2899SCharles.Forsyth 	case IANDL:
1246*37da2899SCharles.Forsyth 		larith(i, Oand, Oand);
1247*37da2899SCharles.Forsyth 		break;
1248*37da2899SCharles.Forsyth 	case IXORL:
1249*37da2899SCharles.Forsyth 		larith(i, Oxor, Oxor);
1250*37da2899SCharles.Forsyth 		break;
1251*37da2899SCharles.Forsyth 	case ICVTWL:
1252*37da2899SCharles.Forsyth 		opwld(i, Oldw, RA1);
1253*37da2899SCharles.Forsyth 		FM3I(2, Osra, 31, RA1, RA0);
1254*37da2899SCharles.Forsyth 		opflst(i, Ostw, RA0);
1255*37da2899SCharles.Forsyth 		break;
1256*37da2899SCharles.Forsyth 	case ICVTLW:
1257*37da2899SCharles.Forsyth 		opwld(i, Olea, RA0);
1258*37da2899SCharles.Forsyth 		mem(Oldw, 4, RA0, RA0);
1259*37da2899SCharles.Forsyth 		opwst(i, Ostw, RA0);
1260*37da2899SCharles.Forsyth 		break;
1261*37da2899SCharles.Forsyth 	case IBEQL:
1262*37da2899SCharles.Forsyth 		cbral(i, Obne, Obe, ANDAND);
1263*37da2899SCharles.Forsyth 		break;
1264*37da2899SCharles.Forsyth 	case IBNEL:
1265*37da2899SCharles.Forsyth 		cbral(i, Obne, Obne, OROR);
1266*37da2899SCharles.Forsyth 		break;
1267*37da2899SCharles.Forsyth 	case IBLEL:
1268*37da2899SCharles.Forsyth 		cbral(i, Obl, Obleu, EQAND);
1269*37da2899SCharles.Forsyth 		break;
1270*37da2899SCharles.Forsyth 	case IBGTL:
1271*37da2899SCharles.Forsyth 		cbral(i, Obg, Obgu, EQAND);
1272*37da2899SCharles.Forsyth 		break;
1273*37da2899SCharles.Forsyth 	case IBLTL:
1274*37da2899SCharles.Forsyth 		cbral(i, Obl, Obcs, EQAND);
1275*37da2899SCharles.Forsyth 		break;
1276*37da2899SCharles.Forsyth 	case IBGEL:
1277*37da2899SCharles.Forsyth 		cbral(i, Obg, Obcc, EQAND);
1278*37da2899SCharles.Forsyth 		break;
1279*37da2899SCharles.Forsyth 	case IMOVF:
1280*37da2899SCharles.Forsyth 		opflld(i, Oldf, FA2);
1281*37da2899SCharles.Forsyth 		opflst(i, Ostf, FA2);
1282*37da2899SCharles.Forsyth 		break;
1283*37da2899SCharles.Forsyth 	case IDIVF:
1284*37da2899SCharles.Forsyth 		r = OfdivD;
1285*37da2899SCharles.Forsyth 		goto arithf;
1286*37da2899SCharles.Forsyth 	case IMULF:
1287*37da2899SCharles.Forsyth 		r = OfmulD;
1288*37da2899SCharles.Forsyth 		goto arithf;
1289*37da2899SCharles.Forsyth 	case ISUBF:
1290*37da2899SCharles.Forsyth 		r = OfsubD;
1291*37da2899SCharles.Forsyth 		goto arithf;
1292*37da2899SCharles.Forsyth 	case IADDF:
1293*37da2899SCharles.Forsyth 		r = OfaddD;
1294*37da2899SCharles.Forsyth 	arithf:
1295*37da2899SCharles.Forsyth 		opflld(i, Oldf, FA2);
1296*37da2899SCharles.Forsyth 		midfl(i, Oldf, FA4);
1297*37da2899SCharles.Forsyth 		FMF1(r, FA2, FA4, FA4);
1298*37da2899SCharles.Forsyth 		opflst(i, Ostf, FA4);
1299*37da2899SCharles.Forsyth 		break;
1300*37da2899SCharles.Forsyth 	case INEGF:
1301*37da2899SCharles.Forsyth 		opflld(i, Oldf, FA2);
1302*37da2899SCharles.Forsyth 		FMF1(OfnegS, FA2, 0, FA2);
1303*37da2899SCharles.Forsyth 		opflst(i, Ostf, FA2);
1304*37da2899SCharles.Forsyth 		break;
1305*37da2899SCharles.Forsyth 	case ICVTFL:
1306*37da2899SCharles.Forsyth 		// >= Sparc 8
1307*37da2899SCharles.Forsyth 		// opflld(i, Oldf, FA2);
1308*37da2899SCharles.Forsyth 		// FMF1(OfDtoQ, FA2, 0, FA2);
1309*37da2899SCharles.Forsyth 		// opflst(i, Ostf, FA2);
1310*37da2899SCharles.Forsyth 		punt(i, SRCOP|DSTOP, optab[i->op]);
1311*37da2899SCharles.Forsyth 		break;
1312*37da2899SCharles.Forsyth 	case ICVTLF:
1313*37da2899SCharles.Forsyth 		// >= Sparc 8
1314*37da2899SCharles.Forsyth 		// opflld(i, Oldf, FA2);
1315*37da2899SCharles.Forsyth 		// FMF1(OfQtoD, FA2, 0, FA2);
1316*37da2899SCharles.Forsyth 		// opflst(i, Ostf, FA2);
1317*37da2899SCharles.Forsyth 		punt(i, SRCOP|DSTOP, optab[i->op]);
1318*37da2899SCharles.Forsyth 		break;
1319*37da2899SCharles.Forsyth 	case ICVTWF:
1320*37da2899SCharles.Forsyth 		opwld(i, Oldf, FA2);
1321*37da2899SCharles.Forsyth 		FMF1(OfWtoD, FA2, 0, FA2);
1322*37da2899SCharles.Forsyth 		opflst(i, Ostf, FA2);
1323*37da2899SCharles.Forsyth 		break;
1324*37da2899SCharles.Forsyth 	case ICVTFW:
1325*37da2899SCharles.Forsyth 		opflld(i, Oldf, FA2);
1326*37da2899SCharles.Forsyth 		FMF1(OfDtoW, FA2, 0, FA2);
1327*37da2899SCharles.Forsyth 		opwst(i, Ostf, FA2);
1328*37da2899SCharles.Forsyth 		break;
1329*37da2899SCharles.Forsyth 	case ISHLL:
1330*37da2899SCharles.Forsyth 		shll(i);
1331*37da2899SCharles.Forsyth 		break;
1332*37da2899SCharles.Forsyth 	case ISHRL:
1333*37da2899SCharles.Forsyth 	case ILSRL:
1334*37da2899SCharles.Forsyth 		punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
1335*37da2899SCharles.Forsyth 		break;
1336*37da2899SCharles.Forsyth 	case IRAISE:
1337*37da2899SCharles.Forsyth 		punt(i, SRCOP|WRTPC|NEWPC, optab[i->op]);
1338*37da2899SCharles.Forsyth 		break;
1339*37da2899SCharles.Forsyth 	case IMULX:
1340*37da2899SCharles.Forsyth 	case IDIVX:
1341*37da2899SCharles.Forsyth 	case ICVTXX:
1342*37da2899SCharles.Forsyth 	case IMULX0:
1343*37da2899SCharles.Forsyth 	case IDIVX0:
1344*37da2899SCharles.Forsyth 	case ICVTXX0:
1345*37da2899SCharles.Forsyth 	case IMULX1:
1346*37da2899SCharles.Forsyth 	case IDIVX1:
1347*37da2899SCharles.Forsyth 	case ICVTXX1:
1348*37da2899SCharles.Forsyth 	case ICVTFX:
1349*37da2899SCharles.Forsyth 	case ICVTXF:
1350*37da2899SCharles.Forsyth 	case IEXPW:
1351*37da2899SCharles.Forsyth 	case IEXPL:
1352*37da2899SCharles.Forsyth 	case IEXPF:
1353*37da2899SCharles.Forsyth 		punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
1354*37da2899SCharles.Forsyth 		break;
1355*37da2899SCharles.Forsyth 	case ISELF:
1356*37da2899SCharles.Forsyth 		punt(i, DSTOP, optab[i->op]);
1357*37da2899SCharles.Forsyth 		break;
1358*37da2899SCharles.Forsyth 	}
1359*37da2899SCharles.Forsyth }
1360*37da2899SCharles.Forsyth 
1361*37da2899SCharles.Forsyth static void
preamble(void)1362*37da2899SCharles.Forsyth preamble(void)
1363*37da2899SCharles.Forsyth {
1364*37da2899SCharles.Forsyth 	ulong *start;
1365*37da2899SCharles.Forsyth 
1366*37da2899SCharles.Forsyth 	if(comvec)
1367*37da2899SCharles.Forsyth 		return;
1368*37da2899SCharles.Forsyth 
1369*37da2899SCharles.Forsyth 	comvec = malloc(10 * sizeof(*code));
1370*37da2899SCharles.Forsyth 	if(comvec == nil)
1371*37da2899SCharles.Forsyth 		error(exNomem);
1372*37da2899SCharles.Forsyth 	code = (ulong*)comvec;
1373*37da2899SCharles.Forsyth 	start = code;
1374*37da2899SCharles.Forsyth 
1375*37da2899SCharles.Forsyth 	con((ulong)&R, RREG, 1);
1376*37da2899SCharles.Forsyth 	mem(Ostw, O(REG, xpc), RREG, RLINK);
1377*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, PC), RREG, RA0);
1378*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, FP), RREG, RFP);
1379*37da2899SCharles.Forsyth 	FM3I(2, Ojmpl, 0, RA0, RZ);
1380*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, MP), RREG, RMP);
1381*37da2899SCharles.Forsyth 
1382*37da2899SCharles.Forsyth 	segflush(comvec, 10 * sizeof(*code));
1383*37da2899SCharles.Forsyth 
1384*37da2899SCharles.Forsyth 	if(cflag > 4) {
1385*37da2899SCharles.Forsyth 		print("comvec:\n");
1386*37da2899SCharles.Forsyth 		das(start, code-start);
1387*37da2899SCharles.Forsyth 	}
1388*37da2899SCharles.Forsyth }
1389*37da2899SCharles.Forsyth 
1390*37da2899SCharles.Forsyth static void
maccase(void)1391*37da2899SCharles.Forsyth maccase(void)
1392*37da2899SCharles.Forsyth {
1393*37da2899SCharles.Forsyth 	ulong *loop, *def, *lab1;
1394*37da2899SCharles.Forsyth 
1395*37da2899SCharles.Forsyth 	mem(Oldw, 0, RCON, RA3);		// n = t[0]
1396*37da2899SCharles.Forsyth 	FM3I(2, Oadd, 4, RCON, RCON);
1397*37da2899SCharles.Forsyth 	MOV(RA3, RA1);
1398*37da2899SCharles.Forsyth 	FM3I(2, Osll, 1, RA1, RA1);
1399*37da2899SCharles.Forsyth 	FM3(2, Oadd, RA3, RA1, RA1);
1400*37da2899SCharles.Forsyth 	FM3I(2, Osll, 2, RA1, RA1);
1401*37da2899SCharles.Forsyth 	FM3(3, Oldw, RCON, RA1, RLINK);
1402*37da2899SCharles.Forsyth 
1403*37da2899SCharles.Forsyth 	loop = code;
1404*37da2899SCharles.Forsyth 	FM3(2, Ocmp, RZ, RA3, RZ);
1405*37da2899SCharles.Forsyth 	def = code;
1406*37da2899SCharles.Forsyth 	BRA(Oble, 0);
1407*37da2899SCharles.Forsyth 	NOOP;
1408*37da2899SCharles.Forsyth 
1409*37da2899SCharles.Forsyth 	MOV(RA3, RA2);				// MOVL	DX, CX	n2 = n
1410*37da2899SCharles.Forsyth 	FM3I(2, Osra, 1, RA2, RA2);		// SHR	CX,1	n2 = n2>>1
1411*37da2899SCharles.Forsyth 	MOV(RA2, RA1);
1412*37da2899SCharles.Forsyth 	FM3I(2, Osll, 1, RA1, RA1);
1413*37da2899SCharles.Forsyth 	FM3(2, Oadd, RA2, RA1, RA1);
1414*37da2899SCharles.Forsyth 	FM3I(2, Osll, 2, RA1, RA1);
1415*37da2899SCharles.Forsyth 
1416*37da2899SCharles.Forsyth 	FM3(3, Oldw, RA1, RCON, RTA);		// MOV	(RA1+RCON), RTA
1417*37da2899SCharles.Forsyth 	FM3(2, Ocmp, RTA, RA0, RZ);
1418*37da2899SCharles.Forsyth 	lab1 = code;
1419*37da2899SCharles.Forsyth 	BRA(Obge, 0);
1420*37da2899SCharles.Forsyth 	NOOP;
1421*37da2899SCharles.Forsyth 	MOV(RA2, RA3);				// n = n2
1422*37da2899SCharles.Forsyth 	BRA(Oba, loop-code);
1423*37da2899SCharles.Forsyth 	NOOP;
1424*37da2899SCharles.Forsyth 
1425*37da2899SCharles.Forsyth 	PATCH(lab1);
1426*37da2899SCharles.Forsyth 	FM3I(2, Oadd, 4, RA1, RTA);
1427*37da2899SCharles.Forsyth 	FM3(3, Oldw, RTA, RCON, RTA);		// MOV	(RA1+RCON), RTA
1428*37da2899SCharles.Forsyth 	FM3(2, Ocmp, RTA, RA0, RZ);
1429*37da2899SCharles.Forsyth 	lab1 = code;
1430*37da2899SCharles.Forsyth 	BRA(Obl, 0);
1431*37da2899SCharles.Forsyth 	NOOP;
1432*37da2899SCharles.Forsyth 
1433*37da2899SCharles.Forsyth 	FM3I(2, Oadd, 12, RA1, RTA);
1434*37da2899SCharles.Forsyth 	FM3(2, Oadd, RTA, RCON, RCON);
1435*37da2899SCharles.Forsyth 	FM3(2, Osub, RA2, RA3, RA3);		// SUBL	CX, DX		n -= n2
1436*37da2899SCharles.Forsyth 	FM3I(2, Oadd, -1, RA3, RA3);		// DECL	DX		n -= 1
1437*37da2899SCharles.Forsyth 	BRA(Oba, loop-code);
1438*37da2899SCharles.Forsyth 	NOOP;
1439*37da2899SCharles.Forsyth 
1440*37da2899SCharles.Forsyth 	PATCH(lab1);
1441*37da2899SCharles.Forsyth 	FM3I(2, Oadd, 8, RA1, RTA);
1442*37da2899SCharles.Forsyth 	FM3(3, Oldw, RTA, RCON, RLINK);
1443*37da2899SCharles.Forsyth 
1444*37da2899SCharles.Forsyth 	PATCH(def);
1445*37da2899SCharles.Forsyth 	FM3I(2, Ojmpl, 0, RLINK, RZ);
1446*37da2899SCharles.Forsyth 	NOOP;
1447*37da2899SCharles.Forsyth }
1448*37da2899SCharles.Forsyth 
1449*37da2899SCharles.Forsyth static void
macfrp(void)1450*37da2899SCharles.Forsyth macfrp(void)
1451*37da2899SCharles.Forsyth {
1452*37da2899SCharles.Forsyth 	ulong *lab1, *lab2;
1453*37da2899SCharles.Forsyth 
1454*37da2899SCharles.Forsyth 	/* destroy the pointer in RA0 */
1455*37da2899SCharles.Forsyth 	FM3I(2, Ocmp, -1, RA0, RZ);
1456*37da2899SCharles.Forsyth 	lab1 = code;
1457*37da2899SCharles.Forsyth 	BRA(Obe, 0);
1458*37da2899SCharles.Forsyth 	NOOP;
1459*37da2899SCharles.Forsyth 	mem(Oldw, O(Heap, ref)-sizeof(Heap), RA0, RA2);
1460*37da2899SCharles.Forsyth 	FM3I(2, Oadd, -1, RA2, RA2);
1461*37da2899SCharles.Forsyth 	FM3I(2, Ocmp, 0, RA2, RZ);
1462*37da2899SCharles.Forsyth 	lab2 = code;
1463*37da2899SCharles.Forsyth 	BRA(Obne, 0);
1464*37da2899SCharles.Forsyth 	NOOP;
1465*37da2899SCharles.Forsyth 	mem(Ostw, O(REG, FP), RREG, RFP);
1466*37da2899SCharles.Forsyth 	mem(Ostw, O(REG, st), RREG, RLINK);
1467*37da2899SCharles.Forsyth 	CALL(rdestroy);
1468*37da2899SCharles.Forsyth 	mem(Ostw, O(REG, s), RREG, RA0);
1469*37da2899SCharles.Forsyth 	con((ulong)&R, RREG, 1);
1470*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, st), RREG, RLINK);
1471*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, FP), RREG, RFP);
1472*37da2899SCharles.Forsyth 	RETURN;
1473*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, MP), RREG, RMP);
1474*37da2899SCharles.Forsyth 	PATCH(lab2);
1475*37da2899SCharles.Forsyth 	mem(Ostw, O(Heap, ref)-sizeof(Heap), RA0, RA2);
1476*37da2899SCharles.Forsyth 	PATCH(lab1);
1477*37da2899SCharles.Forsyth 	RETURN;
1478*37da2899SCharles.Forsyth 	NOOP;
1479*37da2899SCharles.Forsyth }
1480*37da2899SCharles.Forsyth 
1481*37da2899SCharles.Forsyth static void
macret(void)1482*37da2899SCharles.Forsyth macret(void)
1483*37da2899SCharles.Forsyth {
1484*37da2899SCharles.Forsyth 	Inst i;
1485*37da2899SCharles.Forsyth 	ulong *cp1, *cp2, *cp3, *cp4, *cp5, *cp6;
1486*37da2899SCharles.Forsyth 
1487*37da2899SCharles.Forsyth 	FM3I(2, Ocmp, 0, RA1, RZ);
1488*37da2899SCharles.Forsyth 	cp1 = code;
1489*37da2899SCharles.Forsyth 	BRA(Obe, 0);				// t(Rfp) == 0
1490*37da2899SCharles.Forsyth 	NOOP;
1491*37da2899SCharles.Forsyth 
1492*37da2899SCharles.Forsyth 	mem(Oldw, O(Type,destroy),RA1, RA0);
1493*37da2899SCharles.Forsyth 	FM3I(2, Ocmp, 0, RA0, RZ);
1494*37da2899SCharles.Forsyth 	cp2 = code;
1495*37da2899SCharles.Forsyth 	BRA(Obe, 0);				// destroy(t(fp)) == 0
1496*37da2899SCharles.Forsyth 	NOOP;
1497*37da2899SCharles.Forsyth 
1498*37da2899SCharles.Forsyth 	mem(Oldw, O(Frame,fp),RFP, RA2);
1499*37da2899SCharles.Forsyth 	FM3I(2, Ocmp, 0, RA2, RZ);
1500*37da2899SCharles.Forsyth 	cp3 = code;
1501*37da2899SCharles.Forsyth 	BRA(Obe, 0);				// fp(Rfp) == 0
1502*37da2899SCharles.Forsyth 	NOOP;
1503*37da2899SCharles.Forsyth 
1504*37da2899SCharles.Forsyth 	mem(Oldw, O(Frame,mr),RFP, RA3);
1505*37da2899SCharles.Forsyth 	FM3I(2, Ocmp, 0, RA3, RZ);
1506*37da2899SCharles.Forsyth 	cp4 = code;
1507*37da2899SCharles.Forsyth 	BRA(Obe, 0);				// mr(Rfp) == 0
1508*37da2899SCharles.Forsyth 	NOOP;
1509*37da2899SCharles.Forsyth 
1510*37da2899SCharles.Forsyth 	mem(Oldw, O(REG,M),RREG, RA2);
1511*37da2899SCharles.Forsyth 	mem(Oldw, O(Heap,ref)-sizeof(Heap),RA2, RA3);
1512*37da2899SCharles.Forsyth 	FM3I(2, Oaddcc, -1, RA3, RA3);
1513*37da2899SCharles.Forsyth 	cp5 = code;
1514*37da2899SCharles.Forsyth 	BRA(Obe, 0);				// --ref(arg) == 0
1515*37da2899SCharles.Forsyth 	NOOP;
1516*37da2899SCharles.Forsyth 	mem(Ostw, O(Heap,ref)-sizeof(Heap),RA2, RA3);
1517*37da2899SCharles.Forsyth 
1518*37da2899SCharles.Forsyth 	mem(Oldw, O(Frame,mr),RFP, RA1);
1519*37da2899SCharles.Forsyth 	mem(Ostw, O(REG,M),RREG, RA1);
1520*37da2899SCharles.Forsyth 	mem(Oldw, O(Modlink,compiled),RA1, RA2);	// check for uncompiled code
1521*37da2899SCharles.Forsyth 	mem(Oldw, O(Modlink,MP),RA1, RMP);
1522*37da2899SCharles.Forsyth 	FM3I(2, Ocmp, 0, RA2, RZ);
1523*37da2899SCharles.Forsyth 	cp6 = code;
1524*37da2899SCharles.Forsyth 	BRA(Obe, 0);
1525*37da2899SCharles.Forsyth 	NOOP;
1526*37da2899SCharles.Forsyth 	mem(Ostw, O(REG,MP),RREG, RMP);
1527*37da2899SCharles.Forsyth 
1528*37da2899SCharles.Forsyth 	PATCH(cp4);
1529*37da2899SCharles.Forsyth 	FM3I(2, Ojmpl, 0, RA0, RLINK);		// call destroy(t(fp))
1530*37da2899SCharles.Forsyth 	NOOP;
1531*37da2899SCharles.Forsyth 	mem(Ostw, O(REG,SP),RREG, RFP);
1532*37da2899SCharles.Forsyth 	mem(Oldw, O(Frame,lr),RFP, RA1);
1533*37da2899SCharles.Forsyth 	mem(Oldw, O(Frame,fp),RFP, RFP);
1534*37da2899SCharles.Forsyth 	mem(Ostw, O(REG,FP),RREG, RFP);
1535*37da2899SCharles.Forsyth 	FM3I(2, Ojmpl, 0, RA1, RZ);		// goto lr(Rfp)
1536*37da2899SCharles.Forsyth 	NOOP;
1537*37da2899SCharles.Forsyth 
1538*37da2899SCharles.Forsyth 	PATCH(cp6);
1539*37da2899SCharles.Forsyth 	FM3I(2, Ojmpl, 0, RA0, RLINK);		// call destroy(t(fp))
1540*37da2899SCharles.Forsyth 	NOOP;
1541*37da2899SCharles.Forsyth 	mem(Ostw, O(REG,SP),RREG, RFP);
1542*37da2899SCharles.Forsyth 	mem(Oldw, O(Frame,lr),RFP, RA1);
1543*37da2899SCharles.Forsyth 	mem(Oldw, O(Frame,fp),RFP, RFP);
1544*37da2899SCharles.Forsyth 	mem(Ostw, O(REG,FP),RREG, RFP);
1545*37da2899SCharles.Forsyth 	mem(Oldw, O(REG,xpc),RREG, RA2);
1546*37da2899SCharles.Forsyth 	FM3I(2, Oadd, 0x8, RA2, RA2);
1547*37da2899SCharles.Forsyth 	FM3I(2, Ojmpl, 0, RA2, RZ);		// return to uncompiled code
1548*37da2899SCharles.Forsyth 	mem(Ostw, O(REG,PC),RREG, RA1);
1549*37da2899SCharles.Forsyth 
1550*37da2899SCharles.Forsyth 	PATCH(cp1);
1551*37da2899SCharles.Forsyth 	PATCH(cp2);
1552*37da2899SCharles.Forsyth 	PATCH(cp3);
1553*37da2899SCharles.Forsyth 	PATCH(cp5);
1554*37da2899SCharles.Forsyth 	i.add = AXNON;
1555*37da2899SCharles.Forsyth 	punt(&i, TCHECK|NEWPC, optab[IRET]);
1556*37da2899SCharles.Forsyth }
1557*37da2899SCharles.Forsyth 
1558*37da2899SCharles.Forsyth static void
maccolr(void)1559*37da2899SCharles.Forsyth maccolr(void)
1560*37da2899SCharles.Forsyth {
1561*37da2899SCharles.Forsyth 	ulong *br;
1562*37da2899SCharles.Forsyth 
1563*37da2899SCharles.Forsyth 	/* color the pointer in RA1 */
1564*37da2899SCharles.Forsyth 	FM3I(2, Oadd, 1, RA0, RA0);
1565*37da2899SCharles.Forsyth 	mem(Ostw, O(Heap, ref)-sizeof(Heap), RA1, RA0);
1566*37da2899SCharles.Forsyth 	mem(Oldw, O(Heap, color)-sizeof(Heap), RA1, RA0);
1567*37da2899SCharles.Forsyth 	mem(Oldw, 0, RA2, RA2);
1568*37da2899SCharles.Forsyth 	FM3(2, Ocmp, RA0, RA2, RZ);
1569*37da2899SCharles.Forsyth 	br = code;
1570*37da2899SCharles.Forsyth 	BRA(Obe, 0);
1571*37da2899SCharles.Forsyth 	con(propagator, RA2, 1);
1572*37da2899SCharles.Forsyth 	mem(Ostw, O(Heap, color)-sizeof(Heap), RA1, RA2);
1573*37da2899SCharles.Forsyth 	con((ulong)&nprop, RA2, 1);
1574*37da2899SCharles.Forsyth 	RETURN;
1575*37da2899SCharles.Forsyth 	mem(Ostw, 0, RA2, RA2);
1576*37da2899SCharles.Forsyth 	PATCH(br);
1577*37da2899SCharles.Forsyth 	RETURN;
1578*37da2899SCharles.Forsyth 	NOOP;
1579*37da2899SCharles.Forsyth }
1580*37da2899SCharles.Forsyth 
1581*37da2899SCharles.Forsyth static void
macmcal(void)1582*37da2899SCharles.Forsyth macmcal(void)
1583*37da2899SCharles.Forsyth {
1584*37da2899SCharles.Forsyth 	ulong *lab1, *lab2;
1585*37da2899SCharles.Forsyth 
1586*37da2899SCharles.Forsyth 	mem(Oldw, O(Modlink, prog), RA3, RA1);
1587*37da2899SCharles.Forsyth 	FM3I(2, Ocmp, 0, RA1, RZ);
1588*37da2899SCharles.Forsyth 	lab1 = code;
1589*37da2899SCharles.Forsyth 	BRA(Obne, 0);
1590*37da2899SCharles.Forsyth 	NOOP;
1591*37da2899SCharles.Forsyth 
1592*37da2899SCharles.Forsyth 	mem(Ostw, O(REG, st), RREG, RLINK);
1593*37da2899SCharles.Forsyth 	mem(Ostw, O(REG, FP), RREG, RA2);
1594*37da2899SCharles.Forsyth 	CALL(rmcall);				// CALL rmcall
1595*37da2899SCharles.Forsyth 	mem(Ostw, O(REG, dt), RREG, RA0);
1596*37da2899SCharles.Forsyth 
1597*37da2899SCharles.Forsyth 	con((ulong)&R, RREG, 1);		// MOVL	$R, RREG
1598*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, st), RREG, RLINK);
1599*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, FP), RREG, RFP);
1600*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, MP), RREG, RMP);
1601*37da2899SCharles.Forsyth 	RETURN;
1602*37da2899SCharles.Forsyth 	NOOP;
1603*37da2899SCharles.Forsyth 
1604*37da2899SCharles.Forsyth 	PATCH(lab1);				// patch:
1605*37da2899SCharles.Forsyth 	FM3(2, Oor, RA2, RZ, RFP);
1606*37da2899SCharles.Forsyth 	mem(Ostw, O(REG, M), RREG, RA3);	// MOVL RA3, R.M
1607*37da2899SCharles.Forsyth 	mem(Oldw, O(Heap, ref)-sizeof(Heap), RA3, RA1);
1608*37da2899SCharles.Forsyth 	FM3I(2, Oadd, 1, RA1, RA1);
1609*37da2899SCharles.Forsyth 	mem(Ostw, O(Heap, ref)-sizeof(Heap), RA3, RA1);
1610*37da2899SCharles.Forsyth 	mem(Oldw, O(Modlink, compiled), RA3, RA1);
1611*37da2899SCharles.Forsyth 	mem(Oldw, O(Modlink, MP), RA3, RMP);	// MOVL R.M->MP, RMP
1612*37da2899SCharles.Forsyth 	FM3I(2, Ocmp, 0, RA1, RZ);
1613*37da2899SCharles.Forsyth 	lab2 = code;
1614*37da2899SCharles.Forsyth 	BRA(Obe, 0);
1615*37da2899SCharles.Forsyth 	mem(Ostw, O(REG, MP), RREG, RMP);	// MOVL RA3, R.MP	R.MP = ml->MP
1616*37da2899SCharles.Forsyth 
1617*37da2899SCharles.Forsyth 	FM3I(2, Ojmpl, 0, RA0, RZ);
1618*37da2899SCharles.Forsyth 	NOOP;
1619*37da2899SCharles.Forsyth 
1620*37da2899SCharles.Forsyth 	PATCH(lab2);
1621*37da2899SCharles.Forsyth 	mem(Ostw, O(REG,FP),RREG, RFP);
1622*37da2899SCharles.Forsyth 	mem(Oldw, O(REG,xpc),RREG, RA1);
1623*37da2899SCharles.Forsyth 	FM3I(2, Oadd, 0x8, RA1, RA1);
1624*37da2899SCharles.Forsyth 	FM3I(2, Ojmpl, 0, RA1, RZ);		// call to uncompiled code
1625*37da2899SCharles.Forsyth 	mem(Ostw, O(REG,PC),RREG, RA0);
1626*37da2899SCharles.Forsyth }
1627*37da2899SCharles.Forsyth 
1628*37da2899SCharles.Forsyth static void
macfram(void)1629*37da2899SCharles.Forsyth macfram(void)
1630*37da2899SCharles.Forsyth {
1631*37da2899SCharles.Forsyth 	ulong *lab1;
1632*37da2899SCharles.Forsyth 
1633*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, SP), RREG, RA0);	// MOVL	R.SP, RA0
1634*37da2899SCharles.Forsyth 	mem(Oldw, O(Type, size), RA3, RA1);
1635*37da2899SCharles.Forsyth 	FM3(2, Oadd, RA0, RA1, RA0);
1636*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, TS), RREG, RA1);
1637*37da2899SCharles.Forsyth 	FM3(2, Ocmp, RA1, RA0, RZ);
1638*37da2899SCharles.Forsyth 	lab1 = code;
1639*37da2899SCharles.Forsyth 	BRA(Obl, 0);
1640*37da2899SCharles.Forsyth 	NOOP;
1641*37da2899SCharles.Forsyth 
1642*37da2899SCharles.Forsyth 	mem(Ostw, O(REG, s), RREG, RA3);
1643*37da2899SCharles.Forsyth 	mem(Ostw, O(REG, st), RREG, RLINK);
1644*37da2899SCharles.Forsyth 	CALL(extend);				// CALL	extend
1645*37da2899SCharles.Forsyth 	mem(Ostw, O(REG, FP), RREG, RFP);	// MOVL	RFP, R.FP
1646*37da2899SCharles.Forsyth 
1647*37da2899SCharles.Forsyth 	con((ulong)&R, RREG, 1);
1648*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, st), RREG, RLINK);
1649*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, FP), RREG, RFP);	// MOVL	R.MP, RMP
1650*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, s), RREG, RA2);	// MOVL	R.s, *R.d
1651*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, MP), RREG, RMP);	// MOVL R.MP, RMP
1652*37da2899SCharles.Forsyth 	RETURN;					// RET
1653*37da2899SCharles.Forsyth 	NOOP;
1654*37da2899SCharles.Forsyth 
1655*37da2899SCharles.Forsyth 	PATCH(lab1);
1656*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, SP), RREG, RA2);	// MOVL	R.SP, RA2
1657*37da2899SCharles.Forsyth 	mem(Ostw, O(REG, SP), RREG, RA0);	// MOVL	RA0, R.SP
1658*37da2899SCharles.Forsyth 
1659*37da2899SCharles.Forsyth 	mem(Ostw, O(Frame, t), RA2, RA3);	// MOVL	RA3, t(RA2) f->t = t
1660*37da2899SCharles.Forsyth 	mem(Oldw, O(Type, initialize), RA3, RA3);
1661*37da2899SCharles.Forsyth 	FM3I(2, Ojmpl, 0, RA3, RZ);
1662*37da2899SCharles.Forsyth 	mem(Ostw, REGMOD*4, RA2, RZ);     	// MOVL $0, mr(RA2) f->mr
1663*37da2899SCharles.Forsyth }
1664*37da2899SCharles.Forsyth 
1665*37da2899SCharles.Forsyth static void
macmfra(void)1666*37da2899SCharles.Forsyth macmfra(void)
1667*37da2899SCharles.Forsyth {
1668*37da2899SCharles.Forsyth 	mem(Ostw, O(REG, st), RREG, RLINK);
1669*37da2899SCharles.Forsyth 	mem(Ostw, O(REG, s), RREG, RA3);	// Save type
1670*37da2899SCharles.Forsyth 	mem(Ostw, O(REG, d), RREG, RA0);	// Save destination
1671*37da2899SCharles.Forsyth 	CALL(rmfram);				// CALL rmfram
1672*37da2899SCharles.Forsyth 	mem(Ostw, O(REG, FP), RREG, RFP);
1673*37da2899SCharles.Forsyth 
1674*37da2899SCharles.Forsyth 	con((ulong)&R, RREG, 1);
1675*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, st), RREG, RLINK);
1676*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, FP), RREG, RFP);
1677*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, MP), RREG, RMP);
1678*37da2899SCharles.Forsyth 	RETURN;
1679*37da2899SCharles.Forsyth 	NOOP;
1680*37da2899SCharles.Forsyth }
1681*37da2899SCharles.Forsyth 
1682*37da2899SCharles.Forsyth void
comd(Type * t)1683*37da2899SCharles.Forsyth comd(Type *t)
1684*37da2899SCharles.Forsyth {
1685*37da2899SCharles.Forsyth 	int i, j, m, c;
1686*37da2899SCharles.Forsyth 
1687*37da2899SCharles.Forsyth 	mem(Ostw, O(REG, dt), RREG, RLINK);
1688*37da2899SCharles.Forsyth 	for(i = 0; i < t->np; i++) {
1689*37da2899SCharles.Forsyth 		c = t->map[i];
1690*37da2899SCharles.Forsyth 		j = i<<5;
1691*37da2899SCharles.Forsyth 		for(m = 0x80; m != 0; m >>= 1) {
1692*37da2899SCharles.Forsyth 			if(c & m) {
1693*37da2899SCharles.Forsyth 				CALL(base+macro[MacFRP]);
1694*37da2899SCharles.Forsyth 				mem(Oldw, j, RFP, RA0);
1695*37da2899SCharles.Forsyth 			}
1696*37da2899SCharles.Forsyth 			j += sizeof(WORD*);
1697*37da2899SCharles.Forsyth 		}
1698*37da2899SCharles.Forsyth 	}
1699*37da2899SCharles.Forsyth 	mem(Oldw, O(REG, dt), RREG, RLINK);
1700*37da2899SCharles.Forsyth 	RETURN;
1701*37da2899SCharles.Forsyth 	NOOP;
1702*37da2899SCharles.Forsyth }
1703*37da2899SCharles.Forsyth 
1704*37da2899SCharles.Forsyth void
comi(Type * t)1705*37da2899SCharles.Forsyth comi(Type *t)
1706*37da2899SCharles.Forsyth {
1707*37da2899SCharles.Forsyth 	int i, j, m, c;
1708*37da2899SCharles.Forsyth 
1709*37da2899SCharles.Forsyth 	con((ulong)H, RA0, 1);
1710*37da2899SCharles.Forsyth 	for(i = 0; i < t->np; i++) {
1711*37da2899SCharles.Forsyth 		c = t->map[i];
1712*37da2899SCharles.Forsyth 		j = i<<5;
1713*37da2899SCharles.Forsyth 		for(m = 0x80; m != 0; m >>= 1) {
1714*37da2899SCharles.Forsyth 			if(c & m)
1715*37da2899SCharles.Forsyth 				mem(Ostw, j, RA2, RA0);
1716*37da2899SCharles.Forsyth 			j += sizeof(WORD*);
1717*37da2899SCharles.Forsyth 		}
1718*37da2899SCharles.Forsyth 	}
1719*37da2899SCharles.Forsyth 	RETURN;
1720*37da2899SCharles.Forsyth 	NOOP;
1721*37da2899SCharles.Forsyth }
1722*37da2899SCharles.Forsyth 
1723*37da2899SCharles.Forsyth void
typecom(Type * t)1724*37da2899SCharles.Forsyth typecom(Type *t)
1725*37da2899SCharles.Forsyth {
1726*37da2899SCharles.Forsyth 	int n;
1727*37da2899SCharles.Forsyth 	ulong *tmp, *start;
1728*37da2899SCharles.Forsyth 
1729*37da2899SCharles.Forsyth 	if(t == nil || t->initialize != 0)
1730*37da2899SCharles.Forsyth 		return;
1731*37da2899SCharles.Forsyth 
1732*37da2899SCharles.Forsyth 	tmp = mallocz(4096*sizeof(ulong), 0);
1733*37da2899SCharles.Forsyth 	if(tmp == nil)
1734*37da2899SCharles.Forsyth 		error(exNomem);
1735*37da2899SCharles.Forsyth 
1736*37da2899SCharles.Forsyth 	code = tmp;
1737*37da2899SCharles.Forsyth 	comi(t);
1738*37da2899SCharles.Forsyth 	n = code - tmp;
1739*37da2899SCharles.Forsyth 	code = tmp;
1740*37da2899SCharles.Forsyth 	comd(t);
1741*37da2899SCharles.Forsyth 	n += code - tmp;
1742*37da2899SCharles.Forsyth 	free(tmp);
1743*37da2899SCharles.Forsyth 
1744*37da2899SCharles.Forsyth 	n *= sizeof(*code);
1745*37da2899SCharles.Forsyth 	code = mallocz(n, 0);
1746*37da2899SCharles.Forsyth 	if(code == nil)
1747*37da2899SCharles.Forsyth 		return;
1748*37da2899SCharles.Forsyth 
1749*37da2899SCharles.Forsyth 	start = code;
1750*37da2899SCharles.Forsyth 	t->initialize = code;
1751*37da2899SCharles.Forsyth 	comi(t);
1752*37da2899SCharles.Forsyth 	t->destroy = code;
1753*37da2899SCharles.Forsyth 	comd(t);
1754*37da2899SCharles.Forsyth 
1755*37da2899SCharles.Forsyth 	segflush(start, n);
1756*37da2899SCharles.Forsyth 
1757*37da2899SCharles.Forsyth 	if(cflag > 1)
1758*37da2899SCharles.Forsyth 		print("typ= %.8p %4d i %.8p d %.8p asm=%d\n",
1759*37da2899SCharles.Forsyth 			t, t->size, t->initialize, t->destroy, n);
1760*37da2899SCharles.Forsyth }
1761*37da2899SCharles.Forsyth 
1762*37da2899SCharles.Forsyth static void
patchex(Module * m,ulong * p)1763*37da2899SCharles.Forsyth patchex(Module *m, ulong *p)
1764*37da2899SCharles.Forsyth {
1765*37da2899SCharles.Forsyth 	Handler *h;
1766*37da2899SCharles.Forsyth 	Except *e;
1767*37da2899SCharles.Forsyth 
1768*37da2899SCharles.Forsyth 	if((h = m->htab) == nil)
1769*37da2899SCharles.Forsyth 		return;
1770*37da2899SCharles.Forsyth 	for( ; h->etab != nil; h++){
1771*37da2899SCharles.Forsyth 		h->pc1 = p[h->pc1];
1772*37da2899SCharles.Forsyth 		h->pc2 = p[h->pc2];
1773*37da2899SCharles.Forsyth 		for(e = h->etab; e->s != nil; e++)
1774*37da2899SCharles.Forsyth 			e->pc = p[e->pc];
1775*37da2899SCharles.Forsyth 		if(e->pc != -1)
1776*37da2899SCharles.Forsyth 			e->pc = p[e->pc];
1777*37da2899SCharles.Forsyth 	}
1778*37da2899SCharles.Forsyth }
1779*37da2899SCharles.Forsyth 
1780*37da2899SCharles.Forsyth int
compile(Module * m,int size,Modlink * ml)1781*37da2899SCharles.Forsyth compile(Module *m, int size, Modlink *ml)
1782*37da2899SCharles.Forsyth {
1783*37da2899SCharles.Forsyth 	Link *l;
1784*37da2899SCharles.Forsyth 	Modl *e;
1785*37da2899SCharles.Forsyth 	int i, n;
1786*37da2899SCharles.Forsyth 	ulong *s, *tmp;
1787*37da2899SCharles.Forsyth 
1788*37da2899SCharles.Forsyth 	base = nil;
1789*37da2899SCharles.Forsyth 	patch = mallocz(size*sizeof(*patch), 0);
1790*37da2899SCharles.Forsyth 	tinit = malloc(m->ntype*sizeof(*tinit));
1791*37da2899SCharles.Forsyth 	tmp = mallocz(1024*sizeof(ulong), 0);
1792*37da2899SCharles.Forsyth 	if(tinit == nil || patch == nil || tmp == nil)
1793*37da2899SCharles.Forsyth 		goto bad;
1794*37da2899SCharles.Forsyth 
1795*37da2899SCharles.Forsyth 	preamble();
1796*37da2899SCharles.Forsyth 
1797*37da2899SCharles.Forsyth 	mod = m;
1798*37da2899SCharles.Forsyth 	n = 0;
1799*37da2899SCharles.Forsyth 	pass = 0;
1800*37da2899SCharles.Forsyth 	nlit = 0;
1801*37da2899SCharles.Forsyth 
1802*37da2899SCharles.Forsyth 	for(i = 0; i < size; i++) {
1803*37da2899SCharles.Forsyth 		code = tmp;
1804*37da2899SCharles.Forsyth 		comp(&m->prog[i]);
1805*37da2899SCharles.Forsyth 		patch[i] = n;
1806*37da2899SCharles.Forsyth 		n += code - tmp;
1807*37da2899SCharles.Forsyth 	}
1808*37da2899SCharles.Forsyth 
1809*37da2899SCharles.Forsyth 	for(i = 0; i < nelem(mactab); i++) {
1810*37da2899SCharles.Forsyth 		code = tmp;
1811*37da2899SCharles.Forsyth 		mactab[i].gen();
1812*37da2899SCharles.Forsyth 		macro[mactab[i].idx] = n;
1813*37da2899SCharles.Forsyth 		n += code - tmp;
1814*37da2899SCharles.Forsyth 	}
1815*37da2899SCharles.Forsyth 
1816*37da2899SCharles.Forsyth 	base = mallocz((n+nlit)*sizeof(*code), 0);
1817*37da2899SCharles.Forsyth 	if(base == nil)
1818*37da2899SCharles.Forsyth 		goto bad;
1819*37da2899SCharles.Forsyth 
1820*37da2899SCharles.Forsyth 	if(cflag > 1)
1821*37da2899SCharles.Forsyth 		print("dis=%5d %5d sparc=%5d asm=%.8p lit=%d: %s\n",
1822*37da2899SCharles.Forsyth 			size, size*sizeof(Inst), n, base, nlit, m->name);
1823*37da2899SCharles.Forsyth 
1824*37da2899SCharles.Forsyth 	pass++;
1825*37da2899SCharles.Forsyth 	nlit = 0;
1826*37da2899SCharles.Forsyth 	litpool = base+n;
1827*37da2899SCharles.Forsyth 	code = base;
1828*37da2899SCharles.Forsyth 
1829*37da2899SCharles.Forsyth 	for(i = 0; i < size; i++) {
1830*37da2899SCharles.Forsyth 		s = code;
1831*37da2899SCharles.Forsyth 		comp(&m->prog[i]);
1832*37da2899SCharles.Forsyth 		if(cflag > 2) {
1833*37da2899SCharles.Forsyth 			print("%d %D\n", i, &m->prog[i]);
1834*37da2899SCharles.Forsyth 			das(s, code-s);
1835*37da2899SCharles.Forsyth 		}
1836*37da2899SCharles.Forsyth 	}
1837*37da2899SCharles.Forsyth 
1838*37da2899SCharles.Forsyth 	for(i = 0; i < nelem(mactab); i++) {
1839*37da2899SCharles.Forsyth 		s = code;
1840*37da2899SCharles.Forsyth 		mactab[i].gen();
1841*37da2899SCharles.Forsyth 		if(cflag > 2) {
1842*37da2899SCharles.Forsyth 			print("%s:\n", mactab[i].name);
1843*37da2899SCharles.Forsyth 			das(s, code-s);
1844*37da2899SCharles.Forsyth 		}
1845*37da2899SCharles.Forsyth 	}
1846*37da2899SCharles.Forsyth 
1847*37da2899SCharles.Forsyth 	if(n != (code - base))
1848*37da2899SCharles.Forsyth 		error(exCphase);
1849*37da2899SCharles.Forsyth 
1850*37da2899SCharles.Forsyth 	for(l = m->ext; l->name; l++) {
1851*37da2899SCharles.Forsyth 		l->u.pc = (Inst*)RELPC(patch[l->u.pc-m->prog]);
1852*37da2899SCharles.Forsyth 		typecom(l->frame);
1853*37da2899SCharles.Forsyth 	}
1854*37da2899SCharles.Forsyth 	if(ml != nil) {
1855*37da2899SCharles.Forsyth 		e = &ml->links[0];
1856*37da2899SCharles.Forsyth 		for(i = 0; i < ml->nlinks; i++) {
1857*37da2899SCharles.Forsyth 			e->u.pc = (Inst*)RELPC(patch[e->u.pc-m->prog]);
1858*37da2899SCharles.Forsyth 			typecom(e->frame);
1859*37da2899SCharles.Forsyth 			e++;
1860*37da2899SCharles.Forsyth 		}
1861*37da2899SCharles.Forsyth 	}
1862*37da2899SCharles.Forsyth 	for(i = 0; i < m->ntype; i++) {
1863*37da2899SCharles.Forsyth 		if(tinit[i] != 0)
1864*37da2899SCharles.Forsyth 			typecom(m->type[i]);
1865*37da2899SCharles.Forsyth 	}
1866*37da2899SCharles.Forsyth 	patchex(m, patch);
1867*37da2899SCharles.Forsyth 	m->entry = (Inst*)RELPC(patch[mod->entry-mod->prog]);
1868*37da2899SCharles.Forsyth 	free(patch);
1869*37da2899SCharles.Forsyth 	free(tinit);
1870*37da2899SCharles.Forsyth 	free(tmp);
1871*37da2899SCharles.Forsyth 	free(m->prog);
1872*37da2899SCharles.Forsyth 	m->prog = (Inst*)base;
1873*37da2899SCharles.Forsyth 	m->compiled = 1;
1874*37da2899SCharles.Forsyth 	segflush(base, n*sizeof(*base));
1875*37da2899SCharles.Forsyth 	return 1;
1876*37da2899SCharles.Forsyth bad:
1877*37da2899SCharles.Forsyth 	free(patch);
1878*37da2899SCharles.Forsyth 	free(tinit);
1879*37da2899SCharles.Forsyth 	free(tmp);
1880*37da2899SCharles.Forsyth 	free(base);
1881*37da2899SCharles.Forsyth 	return 0;
1882*37da2899SCharles.Forsyth }
1883