#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. Load more
#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 void sind2dind(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 void middstcmp(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 void datareloc(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 uchar movinst(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 void getfldinfo(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 void callrtload(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 void signextend(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 void getstatic(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 void putstatic(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 void getfield(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 void putfield(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 void pushargs(int calltype, int calleeframe, char *sig) { Inst *i; int frameoff; int arg, size; frameoff = REGSIZE; arg = 0;