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