3094 lines · 55.7 KB · C
RawDownload
#include "java.h"#include "javaisa.h"#include "reloc.h" static	int	pcdis;static	int	callunrescue;static	Jinst	*J;static	Method	*M;	Code	*code;		/* method under translation */ static	int	trylevel(int);static	void	unrescue(int); /* * Allocate a Dis instruction. */ static Inst*newi(uchar op){	Inst *i; 	i = Mallocz(sizeof(Inst));	i->op = (uchar)op;	i->pc = pcdis;	pcdis += 1;	i->j = J;	i->next = nil;	if(J && J->dis == nil)		J->dis = i;	if(ihead == nil)		ihead = i;	if(itail)		itail->next = i;	itail = i;	return i;} /* * Allocate a Dis instruction and record for branch-address patching. */ static Inst*newibap(uchar op){	Inst *i; 	i = newi(op);	patchop(i);	return i;} /* * Turn single indirection off fp into double indirection. */ static voidsind2dind(Addr *a, int s){	if(a->mode == Afp) {		a->mode = Afpind;		/* check for overflow ??? */		a->u.b.fi = a->u.offset;		a->u.b.si = s;	} else if(a->mode == Amp && a->u.offset == 0)		;	/* verifyerror(J); *//* can't reject prior to runtime */	else		fatal("sind2dind: %d not Afp\n", a->mode);} /* * Middle operands that match destination operands are redundant. */ static voidmiddstcmp(Inst *i){	Addr *m, *d; 	m = &i->m;	d = &i->d;	if(m->mode == Afp && m->mode == d->mode && m->u.offset == d->u.offset) {		m->mode = Anone;		m->u.offset = 0;	}} /* * For instructions that may reference Module Data. */ static voiddatareloc(Inst *i){	if(i->op == IMOVP && i->s.mode == Amp && i->s.u.offset == 0)		return;		/* don't relocate reference to nil */	if(i->s.mode == Amp)		addDreloc(i, PSRC, PSIND);	if(i->m.mode == Amp)		addDreloc(i, PMID, PSIND);} static ucharmovinst(uchar jtype){	uchar movi; 	switch(jtype) {	case 'Z':	case 'B':		if(J->op == Jgetfield || J->op == Jgetstatic)			movi = ICVTBW;		else if(J->op == Jputfield || J->op == Jputstatic)			movi = ICVTWB;		else			movi = IMOVW;		break;	case 'C':	case 'S':	case 'I':		movi = IMOVW;		break;	case 'J':		movi = IMOVL;		break;	case 'F':	case 'D':		movi = IMOVF;		break;	case 'L':	case '[':		movi = IMOVP;		break;	default:		SET(movi);	/* not reached */	}	return movi;} typedef struct	FieldInfo	FieldInfo; struct FieldInfo {	char	*classname;	char	*fieldname;	char	*sig;	int	flags;}; static voidgetfldinfo(FieldInfo *fi){	Const *c, *n;	int i, ix;	Method *m; 	if(J->op == Jinvokeinterface)		ix = J->u.x2c0.ix;	else		ix = J->u.i;	c = &class->cps[ix];	fi->classname = CLASSNAME(c->fmiref.class_index);	n = &class->cps[c->fmiref.name_type_index];	fi->fieldname = STRING(n->nat.name_index);	fi->sig = STRING(n->nat.sig_index);	fi->flags = 0;	if(strcmp(fi->classname, THISCLASS) != 0)		return;	for(i = 0, m = class->methods; i < class->methods_count; i++, m++) {		if(strcmp(fi->fieldname, STRING(m->name_index)) == 0		&& strcmp(fi->sig, STRING(m->sig_index)) == 0) {			fi->flags = m->access_flags;			break;		}	}} /* * mframe instruction for a call to a Loader entry point. */ static Inst*loadermframe(Freloc *frm, Freloc *frf){	Inst *imframe; 	imframe = newi(IMFRAME);	addrsind(&imframe->s, Amp, 0);	addrimm(&imframe->m, 0);	addrsind(&imframe->d, Afp, getreg(DIS_W));	LTIpatch(frm, imframe, PSRC, PSIND);	LTIpatch(frf, imframe, PMID, PIMM); 	return imframe;} /* * mcall instruction for a call to a Loader entry point. */ static Inst*loadermcall(Inst *imframe, Freloc *frf, Freloc *frm){	Inst *imcall; 	imcall = newi(IMCALL);	imcall->s = imframe->d;	imcall->m = imframe->m;	imcall->d = imframe->s;	LTIpatch(frf, imcall, PMID, PIMM);	LTIpatch(frm, imcall, PDST, PSIND); 	return imcall;} /* * Call "rtload" for run-time resolution. */ static voidcallrtload(RTClass *rtc, char *classname){	Inst *imframe, *i;	Creloc *cr;	Freloc *frm, *frf;	RTReloc *rtr; 	USED(classname);	rtr = getRTReloc(rtc, RMP, nil, 0);	cr = getCreloc(RLOADER);	frm = getFreloc(cr, RMP, nil, 0);	frf = getFreloc(cr, "rtload", nil, 0); 	i = newi(IBNEW);	addrsind(&i->s, Amp, 0);	addrsind(&i->m, Amp, 0);	addrimm(&i->d, i->pc+4);	RTIpatch(rtr, i, PSRC, PSIND); 	imframe = loadermframe(frm, frf); 	i = newi(ILEA);	addrsind(&i->s, Amp, 0);	addrdind(&i->d, Afpind, imframe->d.u.offset, REGSIZE);	RTIpatch(rtr, i, PSRC, PSIND); 	loadermcall(imframe, frf, frm);	relreg(&imframe->d);} /* * Sign-extend an 8-bit unsigned char (Dis byte) to a 32-bit int. */ static voidsignextend(Addr *dst){	Inst *i; 	i = newi(ISHLW);	addrimm(&i->s, 24);	/*i->m = *dst;*/ /* redundant */	i->d = *dst; 	i = newi(ISHRW);	addrimm(&i->s, 24);	/*i->m = *dst;*/ /* redundant */	i->d = *dst;} /* * addw instruction for run-time relocated getstatic & putstatic. */ static Addr*rtstaticadd(FieldInfo *fi, RTClass *rtc){	Inst *i; 	i = newi(IADDW);	addrdind(&i->s, Ampind, 0, 0);	addrsind(&i->m, Amp, 0);	addrsind(&i->d, Afp, getreg(DIS_W)); 	RTIpatch(getRTReloc(rtc, RMP, nil, 0), i, PSRC, PDIND1);	RTIpatch(getRTReloc(rtc, fi->fieldname, fi->sig, Rgetputstatic),		i, PMID, PSIND); 	return &i->d;} /* * addw instruction for load-time relocated getstatic & putstatic. */ static Addr*ltstaticadd(FieldInfo *fi){	Inst *i;	Creloc *cr; 	i = newi(IADDW);	addrdind(&i->s, Ampind, 0, 0);	addrimm(&i->m, 0);	addrsind(&i->d, Afp, getreg(DIS_W)); 	cr = getCreloc(fi->classname);	LTIpatch(getFreloc(cr, RMP, nil, 0), i, PSRC, PDIND1);	LTIpatch(getFreloc(cr, fi->fieldname, fi->sig, Rgetputstatic),		i, PMID, PIMM); 	return &i->d;} /* * Java getstatic. */ static voidgetstatic(void){	int state;	Inst *i;	Addr *a;	FieldInfo fi;	RTClass *rtc; 	getfldinfo(&fi);	state = crefstate(fi.classname, J->bb, 0);	if(state & LTCODE) {		a = ltstaticadd(&fi);	} else {		rtc = getRTClass(fi.classname);		if(state & RTCALL)			callrtload(rtc, fi.classname);		a = rtstaticadd(&fi, rtc);	} 	i = newi(movinst(fi.sig[0]));	i->s = *a;	sind2dind(&i->s, 0);	relreg(a);	dstreg(&J->dst, j2dtype(J->jtype));	i->d = J->dst; 	if(fi.sig[0] == 'B')		signextend(&i->d);} /* * Java putstatic. */ static voidputstatic(void){	int state;	Inst *i;	Addr *a;	FieldInfo fi;	RTClass *rtc; 	getfldinfo(&fi);	state = crefstate(fi.classname, J->bb, 0);	if(state & LTCODE) {		a = ltstaticadd(&fi);	} else {		rtc = getRTClass(fi.classname);		if(state & RTCALL)			callrtload(rtc, fi.classname);		a = rtstaticadd(&fi, rtc);	} 	i = newi(movinst(fi.sig[0]));	i->s = code->j[J->src[0]].dst;	relreg(&code->j[J->src[0]].dst);	i->d = *a;	sind2dind(&i->d, 0);	relreg(a);	datareloc(i);} /* * addw instruction for run-time relocated getfield & putfield. */ static Addr*rtfieldadd(FieldInfo *fi, RTClass *rtc, Addr *a){	Inst *i; 	i = newi(IADDW);	i->s = *a;	addrsind(&i->m, Amp, 0);	addrsind(&i->d, Afp, getreg(DIS_W)); 	RTIpatch(getRTReloc(rtc, fi->fieldname, fi->sig, Rgetputfield),		i, PMID, PSIND); 	return &i->d;} /* * Java getfield. */ static voidgetfield(void){	int state;	Addr *a;	Inst *i;	FieldInfo fi;	Creloc *cr;	RTClass *rtc; 	getfldinfo(&fi);	state = crefstate(fi.classname, J->bb, 0);	if(state & LTCODE) {		i = newi(movinst(fi.sig[0]));		i->s = code->j[J->src[0]].dst;		sind2dind(&i->s, 0);		relreg(&code->j[J->src[0]].dst);		cr = getCreloc(fi.classname);		LTIpatch(getFreloc(cr, fi.fieldname, fi.sig, Rgetputfield),			i, PSRC, PDIND2);	} else {		rtc = getRTClass(fi.classname);		if(state & RTCALL)			callrtload(rtc, fi.classname);		a = rtfieldadd(&fi, rtc, &code->j[J->src[0]].dst);		relreg(&code->j[J->src[0]].dst);		i = newi(movinst(fi.sig[0]));		i->s = *a;		sind2dind(&i->s, 0);		relreg(a);	}	dstreg(&J->dst, j2dtype(J->jtype));	i->d = J->dst; 	if(fi.sig[0] == 'B')		signextend(&i->d); } /* * Java putfield. */ static voidputfield(void){	int state;	Addr *a;	Inst *i;	FieldInfo fi;	Creloc *cr;	RTClass *rtc; 	getfldinfo(&fi);	state = crefstate(fi.classname, J->bb, 0);	if(state & LTCODE) {		i = newi(movinst(fi.sig[0]));		i->s = code->j[J->src[1]].dst;		relreg(&code->j[J->src[1]].dst);		i->d = code->j[J->src[0]].dst;		relreg(&code->j[J->src[0]].dst); 		cr = getCreloc(fi.classname);		LTIpatch(getFreloc(cr, fi.fieldname, fi.sig, Rgetputfield),			i, PDST, PDIND2);	} else {		rtc = getRTClass(fi.classname);		if(state & RTCALL)			callrtload(rtc, fi.classname);		a = rtfieldadd(&fi, rtc, &code->j[J->src[0]].dst);		relreg(&code->j[J->src[0]].dst); 		i = newi(movinst(fi.sig[0]));		i->s = code->j[J->src[1]].dst;		relreg(&code->j[J->src[1]].dst);		i->d = *a;		relreg(a);	}	sind2dind(&i->d, 0);	datareloc(i);} /* * Push function arguments. */ static voidpushargs(int calltype, int calleeframe, char *sig){	Inst *i;	int frameoff;	int arg, size; 	frameoff = REGSIZE;	arg = 0;

Lines 1–500 of 3094.