forsyth20121205-174063a80cc13 years agoHistory
2074 lines · 39.4 KB · C
RawDownload
#include "lib9.h"#include "isa.h"#include "interp.h"#include "raise.h" enum{	RAX	= 0,	RCX	= 1,			/* Be careful with RCX, smashed in bra() */	RTA	= 2,	RTMP	= 3,	RFP	= 4,	RMP	= 5,	R7	= 7, 	DTMP	= 0,	DTMP1	= 1,	DTMP2	= 2,	DTMP3	= 3, 	Oadd	= 0xD000,	OaddaR	= 0xD1E8,		/* ADDA (d16,Rr), Rr */	Oaddi	= 0x0600,	OaddRD	= 0xD0A8,	OaslbD	= 0xE120,	OaslwD	= 0xE1A0,	OasrbD	= 0xE020,	OasrwD	= 0xE0A0,	Oand	= 0xC000,	Oandi	= 0x0200,	Obra	= 0x6000,	Obsr	= 0x6100,	OclrwD	= 0x4280,	OcmpiwR	= 0x0CA8,		/* cmpi.l offset(Rrm), imm.long */	OcmpwR	= 0xB1E8,		/* cmpa $offset(Rrm), Rr */	OcmpbD	= 0xB028,		/* cmp.b $offset(Rrm), Dr */	OcmpwD	= 0xB0A8,		/* cmp.l $offset(Rx), Dr */	OcmpwDD	= 0xB080,		/* cmp.l Dr, Dx */	Odbeq	= 0x57C8,	OdecrwRind = 0x53A8,		/* SUBQ.L $0x1, offset(Rr) */	Odivs	= 0x81C0,	Oeor	= 0xB000,	Oeori	= 0x0A00,	OexgRR	= 0xC148,		/* exg Rx, Ry */	Oextw	= 0x4880,		/* EXT.W Dx extend byte to 16-bit */	Oextbw	= 0x49C0,		/* EXTB.L Dx extend byte to 32-bit */	OincrwR	= 0x5288,		/* ADDQ.L $0x1, Rr */	OincrwRind = 0x52A8,		/* ADDQ.L $0x1, offset(Rr) */	Ojhi	= 0x6200,		/* BHI */	Ojhs	= 0x6400,		/* BCC(HS) */	Ojlo	= 0x6500,		/* BCS(LO) */	Ojls	= 0x6300,		/* BLS */	Ojeq	= 0x6700,		/* BEQ */	Ojge	= 0x6C00,		/* BGE */	Ojgt	= 0x6E00,		/* BGT */	Ojle	= 0x6F00,		/* BLE */	Ojlt	= 0x6D00,		/* BLT */	Ojne	= 0x6600,		/* BNE */	OjmpRind= 0x4ED0,		/* jmp (Rn) */	OjmpRindoffs= 0x4EE8,		/* jmp $offs(Rn) */	OjsrRind= 0x4E90,	OldbD	= 0x1028,		/* $offset(Rrm).b -> Dr */	OldbR	= 0x1058,		/* $offset(Rrm).b -> Rr */	OldwD	= 0x2028,		/* $offset(Rrm) -> Dr */	OldwR	= 0x2068,		/* $offset(Rrm) -> Rr */	OleaR	= 0x41E8,		/* addr($offset(Rrm) -> Rr */	OlslD	= 0xE388,	Olsl2D	= 0xE588,	OlsrD	= 0xE288,	OlslbD	= 0xE128,	OlslwD	= 0xE1A8,	OlsrbD	= 0xE028,	OlsrwD	= 0xE0A8,	OmovelitwR= 0x207C,		/* move $xx, Rr */	OmovelitwD= 0x203C,		/* move $xx, Dr */	Omoveal	= 0x2040,	OmovwR	= 0x217C,		/* imm.long -> $offset(Rrm) */	OmovwRR	= 0x2048,		/* movea.l Rr, Rx */	OmovwRD	= 0x2008,		/* move.l Rr, Dx */	Omuls	= 0xC1C0,	OnegwD	= 0x4480,	Oor	= 0x8000,	Oori	= 0x0000,	OpopwR	= 0x205F,		/* MOVEA.L (A7)+, Rr */	OpushwR	= 0x2F08,		/* MOVE.L Rr, -(A7) */	Opushil	= 0x2F3C,		/* MOVE.L imm., -(A7) */	OroxlD	= 0xE390,	OroxrD	= 0xE290,	Orts	= 0x4E75,	OstbD	= 0x1140,		/* Dr.b -> $offset(Rrm) !!!!! ostbR does NOT exist */	OstwD	= 0x2140,		/* Dr -> $offset(Rrm) */	OstwR	= 0x2148,		/* Rr -> $offset(Rrm) */	Osub	= 0x9000,	Osubi	= 0x0400,	OaddqwR	= 0x5088,	Oswap	= 0x4840,	OtstbD	= 0x4A00,		/* tst.b Dr */	OtstwR	= 0x4AA8,		/* tst.l $offset(Rx) */	Oill	= 0x4afc,		/* illegal instruction trap */	Onop	= 0x4E71,	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}; static	uchar*	code;static	uchar*	base;static	ulong*	patch;static	int	pass;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(uchar*, int); extern void _mull(void);extern void _divsl(void); #define T(r)	*((void**)(R.r)) struct{	int	idx;	void	(*gen)(void);} mactab[] ={	MacFRP,		macfrp,		/* decrement and free pointer */	MacRET,		macret,		/* return instruction */	MacCASE,	maccase,	/* case instruction */	MacCOLR,	maccolr,	/* increment and color pointer */	MacMCAL,	macmcal,	/* mcall bottom half */	MacFRAM,	macfram,	/* frame instruction */	MacMFRA,	macmfra,	/* 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; 	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;} static intbc(int o){	if(o < 127 && o > -128)		return 1;	return 0;} static intwc(int o){	if(o < 65535 && o > -65536)		return 1;	return 0;} static voidurk(void){	error(exCompile);} static voidgen2(uchar o1, uchar o2){	code[0] = o1;	code[1] = o2;	code += 2;} static voidgenw(ulong o){	code[0] = (o>>8)&0xFF;	code[1] = o&0xFF;	code += 2;} static voidgenl(ulong o){	*(ulong*)code = o;	code += 4;} static voidmodrm(int inst, ulong disp, int rm, int r){	switch (inst) {		case OstwD:		case OstwR:		case OstbD:			if (!disp) {				inst&=0xfe3f;				inst|=0x0080;			}			genw(inst | (rm<<9) | r);			if (disp)				genw(disp);			break;		case Oadd|0x28|(0x6<<6):		case Oadd|0x28|(0x4<<6):		case Osub|0x28|(0x6<<6):		case Osub|0x28|(0x4<<6):		case Oor|0x28|(0x6<<6):		case Oor|0x28|(0x4<<6):		case Oand|0x28|(0x6<<6):		case Oand|0x28|(0x4<<6):		case Oeor|0x28|(0x6<<6):		case Oeor|0x28|(0x4<<6):		case Oaddi|0x28|(0x2<<6):		case Oori|0x28|(0x2<<6):		case Oandi|0x28|(0x2<<6):		case Oeori|0x28|(0x2<<6):		case Osubi|0x28|(0x2<<6):		case Oaddi|0x28:		case Oori|0x28:		case Oandi|0x28:		case Oeori|0x28:		case Osubi|0x28:		case OldbD:		case OldwD:		case OldwR:		case OldbR:		case OleaR:		case OaddRD:		case OcmpwR:		case OcmpwD:		case OcmpbD:		case OdecrwRind:		case OincrwRind:		case OtstwR:			if (!disp) {				inst&=0xffc7;				inst|=0x0010;			}			genw(inst | (r<<9) | rm);				if (disp)				genw(disp);			break;		default:			print("modrm: urk on opcode 0x%ux\n",inst);			urk();	}} static voidconR(ulong o, int r){	if(o == 0) {		genw(0x91C8|(r<<9)|r); /* SUBA Rr, Rr */		return;	}	genw(Omoveal|(r<<9)|0x7C); /* MOVEA.L $o,Rr */	genl(o);} static voidconD(ulong o, int r){	if(o == 0) {		genw(OclrwD|r); /* CLR.L Dr */		return;	}	genw(OmovelitwD|(r<<9)); /* MOVEA.L $o,Dr */	genl(o);} static voidopwld(Inst *i, int mi, int r){	int ir, rta;	switch(UXSRC(i->add)) {	default:		print("%D\n", i);		urk();	case SRC(AFP):		modrm(mi, i->s.ind, RFP, r);		return;	case SRC(AMP):		modrm(mi, i->s.ind, RMP, r);		return;	case SRC(AIMM):		conR(i->s.imm, r);		return;	case SRC(AIND|AFP):		ir = RFP;		break;	case SRC(AIND|AMP):		ir = RMP;		break;	}	rta = RTA;	if(mi == OleaR)		rta = r;	modrm(OldwR, i->s.i.f, ir, rta);	modrm(mi, i->s.i.s, rta, r);} static voidopwldD(Inst *i, int mi, int r){	int ir, rta;	switch(UXSRC(i->add)) {	default:		print("%D\n", i);		urk();	case SRC(AFP):		modrm(mi, i->s.ind, RFP, r);		return;	case SRC(AMP):		modrm(mi, i->s.ind, RMP, r);		return;	case SRC(AIMM):		conD(i->s.imm, r);		return;	case SRC(AIND|AFP):		ir = RFP;		break;	case SRC(AIND|AMP):		ir = RMP;		break;	}	rta = RTA;	modrm(OldwR, i->s.i.f, ir, rta);	modrm(mi, i->s.i.s, rta, r);} static intopwst(Inst *i, int mi, int r){	int ir, rta; 	switch(UXDST(i->add)) {	default:		print("%D\n", i);		urk();	case DST(AIMM):		conR(i->d.imm, r);		return 0;	case DST(AFP):		modrm(mi, i->d.ind, RFP, r);		return i->d.ind;	case DST(AMP):		modrm(mi, i->d.ind, RMP, r);		return i->d.ind;	case DST(AIND|AFP):		ir = RFP;		break;	case DST(AIND|AMP):		ir = RMP;		break;	}	rta = RTA;	if(mi == OleaR)		rta = r;	modrm(OldwR, i->d.i.f, ir, rta);	modrm(mi, i->d.i.s, rta, r);	return i->d.i.s;} static voidopwstD(Inst *i, int mi, int r){	int ir, rta; 	switch(UXDST(i->add)) {	default:		print("%D\n", i);		urk();	case DST(AIMM):		conD(i->d.imm, r);		return;	case DST(AFP):		modrm(mi, i->d.ind, RFP, r);		return;	case DST(AMP):		modrm(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 == OleaR)		rta = r;	modrm(OldwR, i->d.i.f, ir, rta);	modrm(mi, i->d.i.s, rta, r);} static intswapbraop(int b){	switch(b) {	case Ojge:		return Ojlt;	case Ojle:		return Ojgt;	case Ojgt:		return Ojle;	case Ojlt:		return Ojge;	case Ojhi:		return Ojls;	case Ojlo:		return Ojhs;	case Ojhs:		return Ojlo;	case Ojls:		return Ojhi;	case Ojeq:		return Ojne;	case Ojne:		return Ojeq;	}	return b;} static voidbra(ulong dst, int op){	ulong ddst;	switch (op) {		case Obsr:

Lines 1–500 of 2074.