Charles.Forsyth20060303a828770d19 years agoHistory
1882 lines · 33.0 KB · C
RawDownload
#include "lib9.h"#include "isa.h"#include "interp.h"#include "raise.h" enum{	R8	= 8,		/* SUN calls these %o0 - %o7 */	R9	= 9,	R10	= 10,	R11	= 11,	R12	= 12,	R13	= 13,	R14	= 14,		/* SUN %sp */	R15	= 15,		/* R15/%o7 is the default link register */ 	R16	= 16,		/* SUN calls these %l0 - %l7 */	R17	= 17,	R18	= 18,	R19	= 19,	R20	= 20,	R21	= 21,	R22	= 22,	R23	= 23,	RLINK	= 15, 	RZ	= 0,		/* Always 0 */	RFP	= R23,		/* Frame Pointer */	RMP	= R22,		/* Module Pointer */	RTA	= R21,		/* Intermediate address for double indirect */	RREG	= R20,		/* Pointer to REG */	RA3	= R19,		/* gpr 3 */	RA2	= R18,		/* gpr 2 2+3 = L */	RA1	= R17,		/* gpr 1 */	RA0	= R16,		/* gpr 0 0+1 = L */ 	RCON	= R8,		/* Constant builder */ 	FA2	= 2,		/* Floating */	FA3	= 3,	FA4	= 4,	FA5	= 5, 	Olea	= (1<<20),	/* Pseudo op */	Owry	= 48,	Omul	= 11,	Oumul	= 10,	Osdiv	= 15,	Osll	= 37,	Osra	= 39,	Osrl	= 38,	Osethi	= 4,	Oadd	= 0,	Oaddcc	= 16,	Oaddx	= 8,	Osub	= 4,	Osubcc	= 20,	Osubx	= 12,	Oor	= 2,	Oand	= 1,	Oxor	= 3,	Oldw	= 0,	Oldsh	= 10,	Ostw	= 4,	Osth	= 6,	Ojmpl	= 56,	Ocall	= 1,	Ocmp	= 20,		/* subcc */	Oldbu	= 1,	Ostb	= 5,	Oba	= 8,	Obn	= 0,	Obne	= 9,	Obe	= 1,	Obg	= 10,	Oble	= 2,	Obge	= 11,	Obl	= 3,	Obgu	= 12,	Obleu	= 4,	Obcc	= 13,	Obcs	= 5,	Obpos	= 14,	Obneg	= 6,	Obvc	= 15,	Obvs	= 7,	OfaddD	= 66,	OfsubD	= 70,	OfdivD	= 78,	OfmulD	= 74,	Oldf	= 32,	Ostf	= 36,	OfDtoQ	= 206,	OfnegS	= 5,	OfcmpD	= 82,	Ofba	= 8,	Ofbe	= 9,	Ofbg	= 6,	Ofbge	= 11,	Ofbl	= 4,	Ofble	= 13,	Ofbne	= 1,	OfWtoD	= 200,	OfDtoW	= 210,	Osave	= 60,	Orestore= 61, 	SRCOP	= (1<<0),	DSTOP	= (1<<1),	WRTPC	= (1<<2),	TCHECK	= (1<<3),	NEWPC	= (1<<4),	DBRAN	= (1<<5),	THREOP	= (1<<6), 	ANDAND	= 1,	OROR	= 2,	EQAND	= 3, 	MacFRP	= 0,	MacRET	= 1,	MacCASE	= 2,	MacCOLR	= 3,	MacMCAL	= 4,	MacFRAM	= 5,	MacMFRA	= 6,	NMACRO}; #define OP(n)			   (n<<30)#define I13(i)			   ((i)&0x1fff)#define D22(i)			   ((i)&0x3fffff)#define PC30(pc)		   (((ulong)(pc) - (ulong)code)>>2) #define CALL(addr)		   *code=OP(1)|PC30(addr); code++#define FM2I(op2, i, rd)	   *code=OP(0)|(rd<<25)|(op2<<22)|D22(i); code++#define BRA(cond, disp)		   *code=OP(0)|(cond<<25)|(2<<22)|D22((disp)); code++#define BRAF(cond, disp)	   *code=OP(0)|(cond<<25)|(6<<22)|D22((disp)); code++#define BRADIS(r, o)		   BRA(r, ((ulong)(base+patch[o])-(ulong)code)>>2)#define BRAFDIS(r, o)		   BRAF(r, ((ulong)(base+patch[o])-(ulong)code)>>2)#define BRAMAC(r, o)		   BRA(r, ((ulong)(base+macro[o])-(ulong)code)>>2);#define FM3I(op, op3, i, rs1, rd)  *code++=OP(op)|(rd<<25)|(op3<<19)|(rs1<<14)|\					   (1<<13)|I13(i)#define FM3(op, op3, rs2, rs1, rd) *code++=OP(op)|(rd<<25)|(op3<<19)|(rs1<<14)|rs2#define FMF1(opf, rs2, rs1, rd)	   *code++=OP(2)|(rd<<25)|(52<<19)|(rs1<<14)|(opf<<5)|rs2#define FMF2(opf, rs2, rs1, rd)	   *code++=OP(2)|(rd<<25)|(53<<19)|(rs1<<14)|(opf<<5)|rs2#define NOOP			   *code++=(4<<22)#define RETURN			   FM3I(2, Ojmpl, 8, RLINK, RZ);#define MOV(s, d)		   FM3(2, Oor, s, RZ, d) #define RELPC(pc)		   (ulong)(base+pc)#define PATCH(ptr)		   *ptr |= (code-ptr) & 0x3fffff static	ulong*	code;static	ulong*	base;static	ulong*	patch;static	int	pass;static	int	puntpc = 1;static	Module*	mod;static	uchar*	tinit;static	ulong*	litpool;static	int	nlit;static	void	macfrp(void);static	void	macret(void);static	void	maccase(void);static	void	maccolr(void);static	void	macmcal(void);static	void	macfram(void);static	void	macmfra(void);static	ulong	macro[NMACRO];	void	(*comvec)(void);extern	void	das(ulong*, int); #define T(r)	*((void**)(R.r)) struct{	int	idx;	void	(*gen)(void);	char*	name;} mactab[] ={	MacFRP,		macfrp,		"FRP", 	/* decrement and free pointer */	MacRET,		macret,		"RET",	/* return instruction */	MacCASE,	maccase,	"CASE",	/* case instruction */	MacCOLR,	maccolr,	"COLR",	/* increment and color pointer */	MacMCAL,	macmcal,	"MCAL",	/* mcall bottom half */	MacFRAM,	macfram,	"FRAM",	/* frame instruction */	MacMFRA,	macmfra,	"MFRA",	/* punt mframe because t->initialize==0 */}; static voidrdestroy(void){	destroy(R.s);} static voidrmcall(void){	Prog *p;	Frame *f; 	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; 	if(R.d == H)                error(exModule);        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;} static voidurk(void){	error(exCompile);} static intbc(long c){	c &= ~0xfffL;	if (c == 0 || c == ~0xfffL)		return 1; 	return 0;} static voidcon(ulong o, int r, int opt){	if(opt != 0) {		if(bc(o)) {				FM3I(2, Oadd, o & 0x1fff, RZ, r);			return;		}		if((o & 0x3ff) == 0) {			FM2I(Osethi, o>>10, r);			return;		}	}	FM2I(Osethi, o>>10, r);	FM3I(2, Oadd, o & 0x3ff, r, r);} static voidmem(int inst, ulong disp, int rm, int r){	int op; 	op = 3;	if(inst == Olea) {		op = 2;		inst = Oadd;	}	if(bc(disp)) {		FM3I(op, inst, disp, rm, r);		return;	}	con(disp, RCON, 1);	FM3(op, inst, RCON, rm, r);} static voidopwld(Inst *i, int mi, int r){	int ir, rta; 	switch(UXSRC(i->add)) {	default:		print("%D\n", i);		urk();	case SRC(AFP):		mem(mi, i->s.ind, RFP, r);		return;	case SRC(AMP):		mem(mi, i->s.ind, RMP, r);		return;	case SRC(AIMM):		con(i->s.imm, r, 1);		if(mi == Olea) {			mem(Ostw, O(REG, st), RREG, r);			con((ulong)&R.st, r, 1);		}		return;	case SRC(AIND|AFP):		ir = RFP;		break;	case SRC(AIND|AMP):		ir = RMP;		break;	}	rta = RTA;	if(mi == Olea)		rta = r;	mem(Oldw, i->s.i.f, ir, rta);	mem(mi, i->s.i.s, rta, r);} static voidopwst(Inst *i, int mi, int r){	int ir, rta; 	switch(UXDST(i->add)) {	default:		print("%D\n", i);		urk();	case DST(AIMM):		con(i->d.imm, r, 1);		return;	case DST(AFP):		mem(mi, i->d.ind, RFP, r);		return;	case DST(AMP):		mem(mi, i->d.ind, RMP, r);		return;	case DST(AIND|AFP):		ir = RFP;		break;	case DST(AIND|AMP):		ir = RMP;		break;	}	rta = RTA;	if(mi == Olea)		rta = r;	mem(Oldw, i->d.i.f, ir, rta);	mem(mi, i->d.i.s, rta, r);} static voidopfl(Adr *a, int am, int mi, int r){	int ir; 	switch(am) {	default:		urk();	case AFP:		mem(mi, a->ind, RFP, r);		mem(mi, a->ind+4, RFP, r+1);		return;	case AMP:		mem(mi, a->ind, RMP, r);		mem(mi, a->ind+4, RMP, r+1);		return;	case AIND|AFP:		ir = RFP;		break;	case AIND|AMP:		ir = RMP;		break;	}	mem(Oldw, a->i.f, ir, RTA);	mem(mi, a->i.s, RTA, r);	mem(mi, a->i.s+4, RTA, r+1);} static voidopflld(Inst *i, int mi, int r){	opfl(&i->s, USRC(i->add), mi, r);} static voidopflst(Inst *i, int mi, int r){	opfl(&i->d, UDST(i->add), mi, r);} static voidliteral(ulong imm, int roff){	nlit++; 	con((ulong)litpool, RTA, 0);	mem(Ostw, roff, RREG, RTA); 	if(pass == 0)		return; 	*litpool = imm;	litpool++;	} static voidpunt(Inst *i, int m, void (*fn)(void)){	ulong pc; 	if(m & SRCOP) {		if(UXSRC(i->add) == SRC(AIMM))			literal(i->s.imm, O(REG, s));		else {			opwld(i, Olea, RA0);			mem(Ostw, O(REG, s), RREG, RA0);		}	} 	if(m & DSTOP) {		opwst(i, Olea, RA0);		mem(Ostw, O(REG, d), RREG, RA0);	}	if(m & WRTPC) {		con(RELPC(patch[i-mod->prog+1]), RA0, 0);		mem(Ostw, O(REG, PC), RREG, RA0);	}	if(m & DBRAN) {		pc = patch[(Inst*)i->d.imm-mod->prog];		literal(RELPC(pc), O(REG, d));	} 	switch(i->add&ARM) {	case AXNON:		if(m & THREOP) {			mem(Oldw, O(REG, d), RREG, RA0);			mem(Ostw, O(REG, m), RREG, RA0);		}		break;	case AXIMM:		literal((short)i->reg, O(REG, m));		break;	case AXINF:		mem(Olea, i->reg, RFP, RA0);		mem(Ostw, O(REG, m), RREG, RA0);		break;	case AXINM:		mem(Olea, i->reg, RMP, RA0);		mem(Ostw, O(REG, m), RREG, RA0);		break;	} 	CALL(fn);	mem(Ostw, O(REG, FP), RREG, RFP); 	con((ulong)&R, RREG, 1);	if(m & TCHECK) {		mem(Oldw, O(REG, t), RREG, RA0);		FM3I(2, Ocmp, 0, RA0, RZ);		BRA(Obe, 5);		NOOP;						mem(Oldw, O(REG, xpc), RREG, RLINK);		RETURN;		NOOP;	} 	mem(Oldw, O(REG, FP), RREG, RFP);	mem(Oldw, O(REG, MP), RREG, RMP); 	if(m & NEWPC) {		mem(Oldw, O(REG, PC), RREG, RA0);		FM3I(2, Ojmpl, 0, RA0, RZ);		NOOP;	}} static voidmidfl(Inst *i, int mi, int r){	int ir; 	switch(i->add&ARM) {	default:

Lines 1–500 of 1882.