Charles.Forsyth20060303a828770d19 years agoHistory
1975 lines · 37.1 KB · C
RawDownload
#include "lib9.h"#include "isa.h"#include "interp.h"#include "raise.h" #define DOT			((ulong)code) #define	RESCHED 1	/* check for interpreter reschedule */ enum{	RAX	= 0,	RAH	= 4,	RCX	= 1,	RDX	= 2,	RBX	= 3,	RSP	= 4,	RBP	= 5,	RSI	= 6,	RDI	= 7, 	RFP	= RSI,	RMP	= RDI,	RTA	= RDX,	RTMP	= RBX, 	Omovzxb	= 0xb6,	Omovzxw	= 0xb7,	Osal	= 0xd1,	Oaddf	= 0xdc,	Ocall	= 0xe8,	Ocallrm	= 0xff,	Ocdq	= 0x99,	Ocld	= 0xfc,	Ocmpb	= 0x38,	Ocmpw	= 0x39,	Ocmpi	= 0x83,	Odecrm	= 0xff,	Oincr	= 0x40,	Oincrm	= 0xff,	Ojccl	= 0x83,	Ojcsl	= 0x82,	Ojeqb	= 0x74,	Ojeql	= 0x84,	Ojgel	= 0x8d,	Ojgtl	= 0x8f,	Ojhil	= 0x87,	Ojlel	= 0x8e,	Ojlsl	= 0x86,	Ojltl	= 0x8c,	Ojol	= 0x80,	Ojnol	= 0x81,	Ojbl	= 0x82,	Ojael	= 0x83,	Ojal	= 0x87,	Ojnel	= 0x85,	Ojbel	= 0x86,	Ojneb	= 0x75,	Ojgtb	= 0x7f,	Ojgeb	= 0x7d,	Ojleb	= 0x7e,	Ojltb	= 0x7c,	Ojmp	= 0xe9,	Ojmpb	= 0xeb,	Ojmprm	= 0xff,	Oldb	= 0x8a,	Olds	= 0x89,	Oldw	= 0x8b,	Olea	= 0x8d,	Otestib	= 0xf6,	Oshld	= 0xa5,	Oshrd	= 0xad,	Osar	= 0xd3,	Osarimm = 0xc1,	Omov	= 0xc7,	Omovf	= 0xdd,	Omovimm	= 0xb8,	Omovsb	= 0xa4,	Orep	= 0xf3,	Oret	= 0xc3,	Oshl	= 0xd3,	Oshr	= 0xd1,	Ostb	= 0x88,	Ostw	= 0x89,	Osubf	= 0xdc,	Oxchg	= 0x87,	OxchgAX	= 0x90,	Oxor	= 0x31,	Opopl	= 0x58,	Opushl	= 0x50,	Opushrm	= 0xff,	Oneg	= 0xf7, 	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,	MacRELQ = 7,	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	void	macrelq(void);static	ulong	macro[NMACRO];	void	(*comvec)(void);extern	void	das(uchar*, int); #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 */	MacRELQ,		macrelq,	/* reschedule */}; static voidbounds(void){	error(exBounds);} static voidrdestroy(void){	destroy(R.s);} static voidrmcall(void){	Prog *p;	Frame *f; 	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;} static intbc(int o){	if(o < 127 && o > -128)		return 1;	return 0;} static voidurk(void){	error(exCompile);} static voidgenb(uchar o){	*code++ = o;} static voidgen2(uchar o1, uchar o2){	code[0] = o1;	code[1] = o2;	code += 2;} static voidgenw(ulong o){	*(ulong*)code = o;	code += 4;} static voidmodrm(int inst, ulong disp, int rm, int r){	*code++ = inst;	if(disp == 0) {		*code++ = (0<<6)|(r<<3)|rm;		return;	}	if(bc(disp)) {		code[0] = (1<<6)|(r<<3)|rm;		code[1] = disp;		code += 2;		return;	}	*code++ = (2<<6)|(r<<3)|rm;	*(ulong*)code = disp;	code += 4;} static voidcon(ulong o, int r){	if(o == 0) {		gen2(Oxor, (3<<6)|(r<<3)|r);		return;	}	genb(Omovimm+r);	genw(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):		con(i->s.imm, r);		return;	case SRC(AIND|AFP):		ir = RFP;		break;	case SRC(AIND|AMP):		ir = RMP;		break;	}	rta = RTA;	if(mi == Olea)		rta = r;	modrm(Oldw, i->s.i.f, ir, rta);	modrm(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);		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 == Olea)		rta = r;	modrm(Oldw, i->d.i.f, ir, rta);	modrm(mi, i->d.i.s, rta, r);} static voidbra(ulong dst, int op){	dst -= (DOT+5);	genb(op);	genw(dst);} static voidrbra(ulong dst, int op){	dst += (ulong)base;	dst -= DOT+5;	genb(op);	genw(dst);} static voidliteral(ulong imm, int roff){	nlit++; 	genb(Omovimm+RAX);	genw((ulong)litpool);	modrm(Ostw, roff, RTMP, RAX); 	if(pass == 0)		return; 	*litpool = imm;	litpool++;	} static voidpunt(Inst *i, int m, void (*fn)(void)){	ulong pc; 	con((ulong)&R, RTMP); 	if(m & SRCOP) {		if(UXSRC(i->add) == SRC(AIMM))			literal(i->s.imm, O(REG, s));		else {			opwld(i, Olea, RAX);			modrm(Ostw, O(REG, s), RTMP, RAX);		}	} 	if(m & DSTOP) {		opwst(i, Olea, 0);		modrm(Ostw, O(REG, d), RTMP, RAX);	}	if(m & WRTPC) {		modrm(Omov, O(REG, PC), RTMP, 0);		pc = patch[i-mod->prog+1];		genw((ulong)base + pc);	}	if(m & DBRAN) {		pc = patch[(Inst*)i->d.imm-mod->prog];		literal((ulong)base+pc, O(REG, d));	} 	switch(i->add&ARM) {	case AXNON:		if(m & THREOP) {			modrm(Oldw, O(REG, d), RTMP, RAX);			modrm(Ostw, O(REG, m), RTMP, RAX);		}		break;	case AXIMM:		literal((short)i->reg, O(REG, m));		break;	case AXINF:		modrm(Olea, i->reg, RFP, RAX);		modrm(Ostw, O(REG, m), RTMP, RAX);		break;	case AXINM:		modrm(Olea, i->reg, RMP, RAX);		modrm(Ostw, O(REG, m), RTMP, RAX);		break;	}	modrm(Ostw, O(REG, FP), RTMP, RFP); 	bra((ulong)fn, Ocall); 	con((ulong)&R, RTMP);	if(m & TCHECK) {		modrm(Ocmpi, O(REG, t), RTMP, 7);// CMPL $0, R.t		genb(0x00);		gen2(Ojeqb, 0x06);		// JEQ	.+6		genb(Opopl+RDI);		genb(Opopl+RSI);		genb(Opopl+RDX);		genb(Opopl+RCX);		genb(Opopl+RBX);		genb(Oret);	} 	modrm(Oldw, O(REG, FP), RTMP, RFP);	modrm(Oldw, O(REG, MP), RTMP, RMP); 	if(m & NEWPC) {		modrm(Oldw, O(REG, PC), RTMP, RAX);		gen2(Ojmprm, (3<<6)|(4<<3)|RAX);	}} static voidmid(Inst *i, uchar mi, int r){	int ir; 	switch(i->add&ARM) {	default:		opwst(i, mi, r);		return;	case AXIMM:		con((short)i->reg, r);		return;	case AXINF:		ir = RFP;		break;	case AXINM:		ir = RMP;		break;	}	modrm(mi, i->reg, ir, r);} static voidarith(Inst *i, int op2, int rm){	if(UXSRC(i->add) != SRC(AIMM)) {		if(i->add&ARM) {			mid(i, Oldw, RAX);			opwld(i, op2|2, 0);			opwst(i, Ostw, 0);			return;		}		opwld(i, Oldw, RAX);		opwst(i, op2, 0);		return;	}	if(i->add&ARM) {		mid(i, Oldw, RAX);		if(bc(i->s.imm)) {			gen2(0x83, (3<<6)|(rm<<3)|RAX);			genb(i->s.imm);		}		else {			gen2(0x81, (3<<6)|(rm<<3)|RAX);			genw(i->s.imm);

Lines 1–500 of 1975.