Charles.Forsyth20090401-2350ad63c6b17 years agoHistory
1962 lines · 34.5 KB · C
RawDownload
#include "lib9.h"#include "isa.h"#include "interp.h"#include "raise.h" #define T(r)	*((void**)(R.r)) #define	SRR(op,c,r1,r2)		gen((op)|((c)<<6)|((r1)<<16)|((r2)<<11))#define	RRR(op,r1,r2,r3)	gen((op)|((r1)<<16)|((r2)<<21)|((r3)<<11))#define	FRRR(op,r1,r2,r3)	gen((op)|((r1)<<16)|((r2)<<11)|((r3)<<6))#define	FI(op,c)		gen((op)|((c)&0xffff))#define	IRR(op,c,r1,r2)		gen((op)|((c)&0xffff)|((r1)<<21)|((r2)<<16))#define	BRRI(op,r1,r2,c)	gen((op)|((r1)<<21)|((r2)<<16)|((c)&0xffff))#define	BRI(op,r,c)		gen((op)|((r)<<21)|((c)&0xffff))#define	JR(op,r)		gen((op)|((r)<<21))#define	J(op,c)			gen((op)|(((ulong)(c)>>2)&0x3FFFFFFUL)) #ifndef HIOFFSET#define	HIOFFSET	0	/* big endian */#endif enum{	Rzero	= 0, 	Ro1	= 8,	Ro2	= 9,	Ro3	= 10,	Ri	= 11,	Rj	= 12, 	Rmp	= 13,	Rfp	= 14,	Rreg	= 15, 	Rpic	= 25,	Rlink	= 31, 	Rf1	= 4,	Rf2	= 6, 	Olw	= 0x23<<26,	Olbu	= 0x24<<26,	Olhu	= 0x25<<26,	Osw	= 0x2b<<26,	Osb	= 0x28<<26,	Oaddui	= 0x09<<26,	Olui	= 0x0f<<26,	Oori	= 0x0d<<26,	Odiv	= (0x00<<26) | 0x1a,	Omul	= (0x00<<26) | 0x18,	Omfhi	= (0x00<<26) | 0x10,	Omflo	= (0x00<<26) | 0x12,	Osubu	= (0x00<<26) | 0x23,	Oaddu	= (0x00<<26) | 0x21,	Oand	= (0x00<<26) | 0x24,	Oor	= (0x00<<26) | 0x25,	Oxor	= (0x00<<26) | 0x26,	Odelay	= (0x00<<26) | 0x27,	Osll	= (0x00<<26) | 0x00,	Osrl	= (0x00<<26) | 0x02,	Osra	= (0x00<<26) | 0x03,	Osllv	= (0x00<<26) | 0x04,	Osrlv	= (0x00<<26) | 0x06,	Osrav	= (0x00<<26) | 0x07,	Oslt	= (0x00<<26) | 0x2a,	Osltu	= (0x00<<26) | 0x2b,	Obeq	= 0x04<<26,	Obne	= 0x05<<26,	Obltz	= (0x01<<26) | (0x0<<16),	Obgtz	= (0x07<<26) | (0x0<<16),	Oblez	= (0x06<<26) | (0x0<<16),	Obgez	= (0x01<<26) | (0x1<<16),	Ojr	= (0x00<<26) | 0x08,	Ojalr	= (0x00<<26) | 0x09 | (Rlink<<11),	Oj	= (0x02<<26),	Ojal	= (0x03<<26),	Olea	= Oaddui,		// pseudo op 	Olf	= 0x31<<26,	Osf	= 0x39<<26,	Oaddf	= (0x11<<26) | (17<<21) | 0,	Osubf	= (0x11<<26) | (17<<21) | 1,	Omulf	= (0x11<<26) | (17<<21) | 2,	Odivf	= (0x11<<26) | (17<<21) | 3,	Onegf	= (0x11<<26) | (17<<21) | 7, 	Ocvtwf	= (0x11<<26) | (20<<21) | 33,	Ocvtfw	= (0x11<<26) | (17<<21) | 36, 	Ofeq	= (0x11<<26) | (17<<21) | (3<<4) | 2,	Oflt	= (0x11<<26) | (17<<21) | (3<<4) | 12, 	Obrf	= (0x11<<26) | (0x100<<16),	Obrt	= (0x11<<26) | (0x101<<16), 	SRCOP	= (1<<0),	DSTOP	= (1<<1),	WRTPC	= (1<<2),	TCHECK	= (1<<3),	NEWPC	= (1<<4),	DBRAN	= (1<<5),	THREOP	= (1<<6), 	ANDAND	= 1,	OROR,	EQAND, 	XOR,	IOR,	AND,	ADD,	SUB, 	OMASK	= (1<<4) - 1,	REV1	= 1<<4,	REV2	= 1<<5, 	Bhi		= HIOFFSET,	Blo		= Bhi ^ 4, 	MacRET	= 0,	MacFRP,	MacINDX,	MacCASE,	MacLENA,	MacFRAM,	MacMOVM,	MacCOLR,	MacMCAL,	MacMFRA,	MacEND,	NMACRO}; extern	char	Tmodule[];	void	(*comvec)(void);extern	void	das(ulong*);static	ulong*	code;static	ulong*	base;static	ulong*	patch;static	int	pass;static	int	regdelay;static	Module*	mod;static	ulong*	tinit;static	ulong*	litpool;static	int	nlit;static	ulong	macro[NMACRO];static	void	rdestroy(void);static	void	macret(void);static	void	macfrp(void);static	void	macindx(void);static	void	maccase(void);static	void	maclena(void);static	void	macfram(void);static	void	macmovm(void);static	void	maccvtfw(void);static	void	maccolr(void);static	void	macend(void);static	void	macmcal(void);static	void	macmfra(void); 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 */	MacMOVM,	macmovm,	MacLENA,	maclena,	MacINDX,	macindx,	MacEND,		macend,	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; 	t = (Type*)R.s;	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("urk: %s\n", s);	exits(0);} voidgen(ulong o){	*code++ = o;} voiddelay(void){	gen(Odelay);} intbigc(long c){	c >>= 15;	if(c == 0 || c == -1)		return 0;	return 1;} voidldbigc(ulong c, int reg){	IRR(Olui, c>>16,Rzero,reg);	IRR(Oori, c,reg,reg);} voidldc(ulong c, int reg){ 	if(bigc(c))		ldbigc(c, reg);	else		IRR(Oaddui, c,Rzero, reg);} voidxchg(void){	ulong t; 	t = code[-1];	code[-1] = code[-2];	code[-2] = t;} voidopx(int mode, Adr *a, int op, int reg, int del){	ulong c;	int r, rx; 	switch(mode) {	case AFP:		c = a->ind;		if(bigc(c))			urk("bigc op1b 1");		if(regdelay == Rfp)			delay();		IRR(op, c,Rfp, reg);		break;	case AMP:		c = a->ind;		if(bigc(c))			urk("bigc op1b 2");		if(regdelay == Rmp)			delay();		IRR(op, c,Rmp, reg);		break;	case AIMM:		if(op == Olea) {			if(a->imm != 0) {				ldc(a->imm, reg);				IRR(Osw, O(REG,st),Rreg, reg);			} else				IRR(Osw, O(REG,st),Rreg, Rzero);			IRR(Oaddui, O(REG,st),Rreg, reg);		} else			ldc(a->imm, reg);		return;	case AIND|AFP:		r = Rfp;		goto offset;	case AIND|AMP:		r = Rmp;	offset:		if(regdelay == r)			delay();		c = a->i.s;		rx = Ri;		if(op == Olea || op == Olw)			rx = reg;		IRR(Olw, a->i.f,r, rx);		if(c != 0 || op != Oaddui) {			delay();			IRR(op, c,rx, reg);		}		break;	}	if(op != Olea && del)		delay();	regdelay = 0;} voidop1(Inst *i, int op, int reg, int del){	opx(USRC(i->add), &i->s, op, reg, del);} voidop3(Inst *i, int op, int reg, int del){	opx(UDST(i->add), &i->d, op, reg, del);} voidop2(Inst *i, int op, int reg, int del){	switch(i->add & ARM) {	case AXNON:		op3(i, op, reg, del);		return;	case AXIMM:		if(op == Olea) {			if((short)i->reg != 0) {				ldc((short)i->reg, reg);				IRR(Osw, O(REG,t),Rreg, reg);			} else				IRR(Osw, O(REG,t),Rreg, Rzero);			IRR(Oaddui, O(REG,t),Rreg, reg);		} else			ldc((short)i->reg, reg);		return;	case AXINF:		IRR(op, i->reg,Rfp, reg);		break;	case AXINM:		IRR(op, i->reg,Rmp, reg);		break;	}	if(op != Olea && del)		delay();} ulongbranch(Inst *i){	ulong rel; 	if(base == 0)		return 0;	rel = patch[(Inst*)i->d.imm - mod->prog];	rel += (base - code) - 1;	return rel & 0xffff;} static voidliteral(ulong imm, int roff){	nlit++; 	ldbigc((ulong)litpool, Ro1);	IRR(Osw, roff, Rreg, Ro1); 	if(pass == 0)		return; 	*litpool = imm;	litpool++;	} voidpunt(Inst *i, int m, void (*fn)(void)){	ulong *cp, pc; 	if(m & SRCOP) {		op1(i, Olea, Ro1, 1);		IRR(Osw, O(REG,s),Rreg, Ro1);	}	if(m & DSTOP) {		op3(i, Olea, Ro3, 1);		IRR(Osw, O(REG,d),Rreg, Ro3);	}	if(m & WRTPC) {		pc = patch[i-mod->prog+1];		ldbigc((ulong)(base+pc), Ro1);		IRR(Osw, O(REG,PC),Rreg, Ro1);	}	if(m & DBRAN) {		pc = patch[(Inst*)i->d.imm-mod->prog];		literal((ulong)(base+pc), O(REG, d));	} 	if((i->add&ARM) == AXNON) {		if(m & THREOP) {			delay();			IRR(Olw, O(REG,d),Rreg, Ro2);			delay();			IRR(Osw, O(REG,m),Rreg, Ro2);		}	} else {		op2(i, Olea, Ro2, 1);		IRR(Osw, O(REG,m),Rreg, Ro2);	} 	ldc((ulong)fn, Rpic);	JR(Ojalr, Rpic);	IRR(Osw, O(REG,FP),Rreg, Rfp); 	ldc((ulong)&R, Rreg);	IRR(Olw, O(REG,FP),Rreg, Rfp);	IRR(Olw, O(REG,MP),Rreg, Rmp);	regdelay = Rmp; 	if(m & TCHECK) {		IRR(Olw, O(REG,t),Rreg, Ro1);		xchg();		cp = code;		BRRI(Obeq,Ro1,Rzero,0);		IRR(Olw, O(REG,xpc),Rreg, Ro2);		delay();		JR(Ojr, Ro2);		delay();		*cp |= (code - cp) - 1;		regdelay = 0;	} 	if(m & NEWPC) {		IRR(Olw, O(REG,PC),Rreg, Ro1);		if(m & TCHECK)			delay();		else			xchg();		JR(Ojr, Ro1);		delay();		regdelay = 0;	}}				static voidcomgoto(Inst *i){	WORD *t, *e; 	op1(i, Olw, Ro2, 0);	op3(i, Olea, Ro3, 0);	SRR(Osll, 2, Ro2, Ro2);	RRR(Oaddu, Ro2, Ro3, Ro3);	IRR(Olw, 0,Ro3, Ro1);	delay();	JR(Ojr, Ro1);	delay(); 	if(pass == 0)		return;

Lines 1–500 of 1962.