Charles.Forsyth20060303a828770d19 years agoHistory
2257 lines · 41.5 KB · C
RawDownload
#include "lib9.h"#include "isa.h"#include "interp.h"#include "raise.h" /* * Copyright © 1997 C H Forsyth (forsyth@terzarima.net) */ #define	ROMABLE	0	/* costs something to zero patch vectors */#define	RESCHED 1	/* check for interpreter reschedule */ #define PATCH(ptr)		   *ptr |= ((ulong)code-(ulong)ptr) & 0xfffc #define T(r)	*((void**)(R.r)) #define	XO(o,xo)	(((o)<<26)|((xo)<<1)) /* botch: ARRR, AIRR, LRRR, etc have dest first (will fix soon) */ #define	OPARRR(o,d,a,b)	((o)|((d)<<21)|((a)<<16)|((b)<<11))#define	ARRR(o,d,a,b)		gen((o)|((d)<<21)|((a)<<16)|((b)<<11))#define	AIRR(o,d,a,v)		gen((o)|((d)<<21)|((a)<<16)|((v)&0xFFFF))#define	IRR(o,v,a,d)	AIRR((o),(d),(a),(v))#define	RRR(o,b,a,d)	ARRR((o),(d),(a),(b))#define	LRRR(o,a,s,b)		ARRR((o),(s),(a),(b))#define	LIRR(o,a,s,v)		AIRR((o),(s),(a),(v))#define	Bx(li,aa)		gen((18<<26)|((li)&0x3FFFFFC)|((aa)<<1))#define	RLW(op,a,s,sh,mb,me) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((sh)&31L)<<11)|\					(((mb)&31L)<<6)|(((me)&31L)<<1))#define	MFSPR(s, d)	gen(XO(31,339) | ((d)<<21) | ((s)<<11))#define	MTSPR(s, d)	gen(XO(31,467) | ((s)<<21) | ((d)<<11)); #define	SLWI(d,a,n)	gen(slw((d),(a),(n),0))#define	LRET()	gen(Oblr) #define	SETR0()	if(macjit){	AIRR(Oaddi, Rzero, 0, 0); }		/* set R0 to 0 */ /* assumes H can be formed from signed halfword */#define	CMPH(r)		AIRR(Ocmpi, Rcrf0, (r), (ulong)H);#define NOTNIL(r)	(CMPH((r)), CCALL(EQ, bounds)) enum{	Rzero	= 0,	/* zero by design, not definition (P9/Inferno) */ 	Rsp = 1,	Rsb = 2,	Rarg	= 3, 	Ro1	= 8,	Ro2	= 9,	Ro3	= 10,	Ri	= 11,	Rj	= 12, 	Rmp	= 13,	Rfp	= 14,	Rreg	= 15,	Rta	= 16,		/* unused */	Rpic	= 17,		/* address for computed goto, for move to CTR or LR */ 	Rcon = 26,	/* constant builder; temporary */	/* 27, 28, 29, 30 are potentially external registers (P9/Inferno) */	Rlink = 31,	/* holds copies of LR; linker temp */ 	Rfret	= 0,	Rf1	= 4,	Rf2	= 6,	Rfcvi	= 27,	/* floating conversion constant (P9/Inferno) */	Rfzero = 28,	/* 0.0 (P9/Inferno) */	Rfhalf = 29,	/* 0.5 (P9/Inferno) */ 	Rlr = 8<<5,	/* SPR(LR) */	Rctr = 9<<5,	/* SPR(CTR) */ 	Rcrf0 = 0,		/* condition code field 0 */	Rcrf1 = 1<<2,	/* condition code field 1 */ 	Rcrbrel = 31,	/* condition code bit set to force relinquish */ 	Olwz	= XO(32, 0),	Olwzu = XO(33, 0),	Olwzx = XO(31, 23),	Olbz	= XO(34, 0),	Olbzu = XO(35, 0),	Olbzx = XO(31, 87),	Olfd	= XO(50, 0),	Olhz	= XO(40, 0),	Olhzx = XO(31, 279),	Ostw	= XO(36, 0),	Ostwu = XO(37, 0),	Ostwx = XO(31, 151),	Ostb	= XO(38, 0),	Ostbu = XO(39, 0),	Ostbx = XO(31, 215),	Osth	= XO(44,0),	Osthx = XO(31, 407),	Ostfd	= XO(54, 0),	Ostfdu	= XO(55, 0), 	Oaddc	= XO(31,10),	Oadde	= XO(31, 138),	Oaddi	= XO(14, 0),	/* simm */	Oaddic_	= XO(13, 0),	Oaddis	= XO(15, 0),	Ocrxor	= XO(19, 193),	Ofadd	= XO(63, 21),	Ofcmpo	= XO(63, 32),	Ofctiwz	= XO(63, 15),	Ofsub	= XO(63, 20),	Ofmr	= XO(63, 72),	Ofmul	= XO(63, 25),	Ofdiv	= XO(63, 18),	Ofneg	= XO(63, 40),	Oori		= XO(24,0),	/* uimm */	Ooris	= XO(25,0),	/* uimm */	Odivw	= XO(31, 491),	Odivwu	= XO(31, 459),	Omulhw	= XO(31, 75),	Omulhwu	= XO(31, 11),	Omulli	= XO(7, 0),	Omullw	= XO(31, 235),	Osubf	= XO(31, 40),	Osubfc	= XO(31,8),	Osubfe	= XO(31,136),	Osubfic	= XO(8, 0),	Oadd	= XO(31, 266),	Oand	= XO(31, 28),	Oneg	= XO(31, 104),	Oor		= XO(31, 444),	Oxor		= XO(31, 316), 	Ocmpi = XO(11, 0),	Ocmp = XO(31, 0),	Ocmpl = XO(31, 32),	Ocmpli = XO(10,0), 	Orlwinm = XO(21, 0),	Oslw	= XO(31, 24),	Osraw = XO(31,792),	Osrawi =	XO(31,824),	Osrw = XO(31,536), 	Cnone	= OPARRR(0,20,0,0),	/* unconditional */	Ceq		= OPARRR(0,12,2,0),	Cle		= OPARRR(0,4,1,0),	Clt		= OPARRR(0,12,0,0),	Cdnz	= OPARRR(0,16,0,0),	Cgt		= OPARRR(0,12,1,0),	Cne		= OPARRR(0,4,2,0),	Cge		= OPARRR(0,4,0,0),	Cle1		= OPARRR(0,4,5,0),	/* Cle on CR1 */	Crelq	= OPARRR(0,12,Rcrbrel,0),	/* relinquish */	Cnrelq	= OPARRR(0,4,Rcrbrel,0),	/* not relinquish */	Cpredict	= OPARRR(0,1,0,0),	/* reverse prediction */	Lk		= 1,	Aa		= 2, 	Obeq	= OPARRR(16<<26,12,2,0),	Obge	= OPARRR(16<<26,4,0,0),	Obgt		= OPARRR(16<<26,12,1,0),	Oble		= OPARRR(16<<26,4,1,0),	Oblt		= OPARRR(16<<26,12,0,0),	Obne	= OPARRR(16<<26,4,2,0), 	Ob		= XO(18, 0),	Obc		= XO(16, 0),	Obcctr	= XO(19,528),	Obcctrl	= Obcctr | Lk,	Obctr	= Obcctr | Cnone,	Obctrl	= Obctr | Lk,	Obclr	= XO(19, 16),	Oblr		= Obclr | Cnone,	Oblrl		= Oblr | Lk, 	Olea	= 100,		// pseudo op 	SRCOP	= (1<<0),	DSTOP	= (1<<1),	WRTPC	= (1<<2),	/* update R.PC */	TCHECK	= (1<<3),	/* check R.t for continue/ret */	NEWPC	= (1<<4),	/* goto R.PC */	DBRAN	= (1<<5),	/* dest is branch */	THREOP	= (1<<6), 	ANDAND	= 1,	OROR,	EQAND, 	MacRET	= 0,	MacFRP,	MacCASE,	MacFRAM,	MacCOLR,	MacMCAL,	MacMFRA,	MacCVTFW,	MacRELQ,	MacEND,	NMACRO}; 	void	(*comvec)(void);	int	macjit;extern	long	das(ulong*);static	ulong*	code;static	ulong*	base;static	ulong*	patch;static	int	pass;static	Module*	mod;static	ulong*	tinit;static	ulong*	litpool;static	int	nlit;static	ulong	macro[NMACRO];static	void	ldbigc(long, int);static	void	rdestroy(void);static	void	macret(void);static	void	macfrp(void);static	void	maccase(void);static	void	maccvtfw(void);static	void	macfram(void);static	void	maccolr(void);static	void	macend(void);static	void	macmcal(void);static	void	macmfra(void);static	void	macrelq(void);static	void	movmem(Inst*); struct{	int	o;	void	(*f)(void);} macinit[] ={	MacFRP,		macfrp,		/* decrement and free pointer */	MacRET,		macret,		/* return instruction */	MacCASE,	maccase,	/* case instruction */	MacCOLR,	maccolr,	/* increment and color pointer */	MacFRAM,	macfram,	/* frame instruction */	MacMCAL,	macmcal,	/* mcall bottom half */	MacMFRA,	macmfra,	/* punt mframe because t->initialize==0 */	MacCVTFW,	maccvtfw,	MacRELQ,		macrelq,	/* reschedule */	MacEND,		macend,	0}; static voidrdestroy(void){	destroy(R.s);} static voidrmcall(void){	Frame *f;	Prog *p; 	if((void*)R.dt == H)		error(exModule); 	f = (Frame*)R.FP;	if(f == H)		error(exModule); 	f->mr = nil;	((void(*)(Frame*))R.dt)(f);	R.SP = (uchar*)f;	R.FP = f->fp;	if(f->t == nil)		unextend(f);	else		freeptrs(f, f->t);	p = currun();	if(p->kill != nil)		error(p->kill);} static voidrmfram(void){	Type *t;	Frame *f;	uchar *nsp; 	t = (Type*)R.s;	if(t == H)		error(exModule);	nsp = R.SP + t->size;	if(nsp >= R.TS) {		R.s = t;		extend();		T(d) = R.s;		return;	}	f = (Frame*)R.SP;	R.SP = nsp;	f->t = t;	f->mr = nil;	initmem(t, f);	T(d) = f;} voidurk(char *s){	print("compile failed: %s\n", s);	// debugging	error(exCompile);	// production} static voidgen(ulong o){	*code++ = o;} static voidbr(ulong op, ulong disp){	*code++ = op | (disp & 0xfffc);} static voidmfspr(int d, int s){	MFSPR(s, d);} static voidmtspr(int d, int s){	MTSPR(s, d);} static ulongslw(int d, int s, int v, int rshift){	int m0, m1; 	if(v < 0 || v > 32)		urk("slw v");	if(v < 0)		v = 0;	else if(v > 32)		v = 32;	if(rshift) {	/* shift right */		m0 = v;		m1 = 31;		v = 32-v;	} else {		m0 = 0;		m1 = 31-v;	}	return RLW(Orlwinm, d, s, v, m0, m1);} static voidjr(int reg){	mtspr(Rctr, reg);	/* code would be faster if this were loaded well before branch */	gen(Obctr);} static voidjrl(int reg){	mtspr(Rctr, reg);	gen(Obctrl);} static voidjrc(int op, int reg){	mtspr(Rctr, reg);	gen(Obcctr | op);} static longbrdisp(ulong *dest){	ulong d, top; 	d = (ulong)dest - (ulong)code;	if(!ROMABLE)		return d & 0x3fffffc;	top = d>>25;	if(top == 0 || top == 0x7F){		/* fits in 26-bit signed displacement */		return d & 0x3fffffc;	}	return -1;} static voidjmp(ulong *dest){	long d; 	if((d = brdisp(dest)) < 0){		ldbigc((ulong)dest, Rpic);	/* Rpic & Rctr must be free */		jr(Rpic);	} else		gen(Ob | d);} static voidjmpl(ulong *dest){	long d; 	if((d = brdisp(dest)) < 0){		ldbigc((ulong)dest, Rpic);	/* Rpic must be free */		jrl(Rpic);	} else		gen(Ob | d | Lk);} static voidjmpc(int op, ulong *dest){	ldbigc((ulong)dest, Rpic);	jrc(op, Rpic);} static intbigc(long c){	if(c >= -0x8000 && c <= 0x7FFF)		return 0;	return 1;} static voidldbigc(long c, int reg){	AIRR(Oaddis, reg,Rzero,c>>16);	LIRR(Oori, reg,reg,c);} static voidldc(long c, int reg){	if(!bigc(c))		AIRR(Oaddi, reg, Rzero, c);	else if((ulong)c <= 0xFFFF)		LIRR(Oori, reg, Rzero, c);	else if((c&0xFFFF) == 0)		LIRR(Ooris, reg, Rzero, c>>16);	else {		AIRR(Oaddis, reg,Rzero,c>>16);		LIRR(Oori, reg,reg,c);	}} static voidmem(int inst, long disp, int rm, int r){	if(bigc(disp)) {		ldc(disp, Rcon);		switch(inst){		default: 		urk("mem op"); break;		case Olea:		inst = Oadd; break;		case Olwz:	inst = Olwzx; break;		case Olbz:		inst = Olbzx; break;		case Olhz:		inst = Olhzx; break;		case Ostw:	inst = Ostwx; break;		case Ostb:		inst = Ostbx; break;		case Osth:		inst = Osthx; break;		}		ARRR(inst, r, Rcon, rm);	} else {		if(inst == Olea)			inst = Oaddi;		AIRR(inst, r, rm,disp);	}} static voidopx(int mode, Adr *a, int op, int reg){	ulong c;	int r, rx, lea; 	lea = 0;	if(op == Olea){		lea = 1;		op = Oaddi;	}	switch(mode) {	case AFP:		c = a->ind;		if(bigc(c))			urk("bigc op1b 1");		AIRR(op, reg, Rfp,c);		break;	case AMP:		c = a->ind;		if(bigc(c))

Lines 1–500 of 2257.