#include #include #include #include #include #include "g.h" #define pr(x,y) fprintf(stderr, "G: %s %s\n", x, y ); void g_bomb(char* s) { fprintf( stderr, "G_BOMB: %s\n", s ); fflush(stdout); fflush(stderr); abort(); exit(1); } char* g_alloc(int n) { char* p= malloc(n); if (!p) g_bomb("cannot malloc"); memset( p, 0, n ); return p; } char* g_strdup(char* a) { int x= strlen(a); char* m= g_alloc(x+1); strcpy( m, a ); return m; } char* g_strdup2(char* a, char* b) { int x= strlen(a); int y= strlen(b); char* m= g_alloc(x+y+1); strcpy( m, a ); strcat( m, b ); return m; } char* g_strdup3(char* a, char* b, char* c) { int x= strlen(a); int y= strlen(b); int z= strlen(c); char* m= g_alloc(x+y+z+1); printf("SD3: %d %d %d %s %s %s\n", x, y, z, a, b, c); strcpy( m, a ); strcat( m, b ); strcat( m, c ); return m; } u4 g_stringhash(char* s) { u4 sum= 0; u1* p= (u1*)s; assert(p); for ( ; *p; ++p ) sum += *p; /* mix sum with first char */ return sum + ( *(u1*)s << 24 ); } /* from interned string, find hash */ #define IRN_hash(S) ( ((ghent*)S-1)->hash ) /* find internned string or intern it, return interned string */ char* g_intern(gvm* g, char* s) { u4 h= g_stringhash(s); ghent* p= g->itab.v[h&Htm]; u4 len; for ( ; p ; p=p->next ) { if ( h==p->hash && !strcmp(s,p->s) ) { return p->s; } } /* not found .. must intern it */ /* must alloc string right after new hent */ p= (ghent*) g_alloc( sizeof *p + strlen(s) + 1 ); p->hash= h; p->s= (char*)(p+1); /* fill in string at p+1 */ strcpy( p->s, s ); /* link into bucket chain */ p->next= g->itab.v[h&Htm]; g->itab.v[h&Htm]= p; return p->s; } /* find hash entry given internned string, or return null */ ghent* g_hashfind(ghtab* t, char* s) { u4 h= IRN_hash(s); ghent* p= t->v[h&Htm]; for ( ; p ; p=p->next ) { if ( s == p->s ) { return p; } } return (ghent*)NULL; } void g_hashadd(ghtab* t, char* s, ghent* e) { u4 h= IRN_hash(s); e->hash= h; e->s= s; e->next= t->v[h&Htm]; t->v[h&Htm]= e; } /* find gcls by interned name, create if required */ gcls* g_findcls( gvm* g, char* n, int creat ) { ghent* he= g_hashfind( &g->ctab, n ); if (he) return (gcls*) he; if (creat) { gcls* c= (gcls*)g_alloc( sizeof *c ); c->name= n; c->status= Gempty; c->gvm= g; g_hashadd( &g->ctab, n, &c->head ); return c; } else { return (gcls*)NULL; } } gcls* g_findarraycls( gvm* g, char* n, int atype ) { gcls* c= g_findcls( g, n, 1 ); if (c->status!=Gempty) return c; /* rather than concoct values, we cheat & call array */ c->status= Garr; c->atype= atype; return c; } gvm* g_gvmnew() { gvm* g= (gvm*) g_alloc( sizeof *g ); return g; } #define get4(X) { u4 _a, _b, _c, _d; \ _a=getc(f); _b=getc(f); _c=getc(f); _d=getc(f); \ (X)= (_a<<24)|(_b<<16)|(_c<<8)|_d; } #define get2(X) { u4 _a, _b; _a=getc(f); _b=getc(f); (X)= (_a<<8)|_b; } #define get1(X) { (X)=getc(f); } #define Gsmask 0x007f #define Gsend 0x0100 #define Gsnum 0x0200 #define Gsobj 0x0400 #define Gsarr 0x0800 #define Gsmeth 0x1000 #define Gsvoid 0x2000 #define Gseight 0x4000 #define Gsret 0x8000 u1* g_argtypes( char* p ) { char* s= p; char buf[299]; char* b= buf; int t; t= g_sgetnext(&s); if (t!=Gsmeth) return (u1*)NULL; while ( 1 ) { t= g_sgetnext(&s); if ( t & Gsend) g_bomb("Gsend"); if ( t & Gsret) break; if ( t & Gseight ) { *b++ = 'd'; } else if ( t & Gsnum ) { *b++ = 'i'; } else if ( t & Gsobj ) { *b++ = 'a'; } else { g_bomb("argtypes else"); } } *b++ = '\0'; return strdup(b); } char g_rettype( char* p ) { char* s= p; int t; t= g_sgetnext(&s); if (t!=Gsmeth) return (u1*)NULL; while ( 1 ) { t= g_sgetnext(&s); if ( t & Gsend) g_bomb("Gsend"); if ( t & Gsret) break; if ( t & Gseight ) { /*nothing*/ } else if ( t & Gsnum ) { /*nothing*/ } else if ( t & Gsobj ) { /*nothing*/ } else { g_bomb("argtypes else"); } } t= g_sgetnext(&s); if ( t & Gseight ) { return 'd'; } else if ( t & Gsnum ) { return 'i'; } else if ( t & Gsobj ) { return 'a'; } else if ( t & Gsvoid ) { return 'v'; } else { g_bomb("argtypes else"); } /*NOTREACHED*/ return 0; } int g_sgetnext( char** pp ) { char* p= *pp; int z= Gsend; int i; if (p[0]=='\0') return; switch (*p++) { case 'B': case 'C': case 'F': case 'I': case 'S': case 'Z': z= Gsnum | (Gsmask&p[-1]); break; case 'D': case 'J': z= Gsnum | Gseight | (Gsmask&p[-1]); break; case 'L': z= Gsobj; /* waste classname */ while ( p[0] && p[0]!=';' ) ++p; ++p; break; case '[': z= Gsobj | Gsarr; /* waste nested arrayness */ while ( p[0]=='[' || p[0]>='0' && p[9]<='9' ) ++p; /* waste element type */ g_sgetnext( &p ); break; case '(': z= Gsmeth; break; case ')': z= Gsret; break; case '\0': default: } end: *pp= p; return z; } int frob; int g_readclassfile( gvm* g, char* name, gcls** out ) { u4 magic; u4 version; u2 conc; gcon* cons; u4 i,j,k,l; gcls* c; u2 aflags; u2 this_c; u4 off= sizeof(gcls); u4 w; u4 x; u4 y; u4 z; char* cp; char* i_ConstantValue= g_intern(g,"ConstantValue"); char* i_Code= g_intern(g,"Code"); FILE* f= fopen( name, "r" ); if (!f) { pr("fopen fails", name); return GcannotOpenFile; } get4(magic); if ( magic != Cmagic ) return GbadClassFile; get4(version); if ( (0xFFFF&version) != Cversion ) return GbadClassFile; get2(conc); cons= (gcon*) g_alloc( conc * sizeof *cons ); for ( i=1; i %s\n", i, x, cp, cons[i].u.a.p ); free(cp); break; default: goto bad; } /* esac */ } /* next i */ for ( i=1; istatus == Gempty ); /* dont load twice */ c->conc= conc; c->cons= cons; c->aflags= aflags; get2(x); c->super_class= GCcls(x); get2(c->ifacec); c->iface= (gcls**) g_alloc( c->ifacec * sizeof *c->iface ); for ( i=0; iifacec; i++ ) { get2(x); c->iface[i]= GCcls(x); } get2(c->fldc); c->flds= (gfld*) g_alloc( c->fldc * sizeof *c->flds ); for ( i=0; ifldc; i++ ) { c->flds[i].cls= c; get2(c->flds[i].aflags); get2(x); c->flds[i].name= GCasc(x); get2(x); c->flds[i].sig= GCasc(x); get2(x); for ( j=0; jflds[i].conval= GCcon(w); } else { for ( k=0; kflds[i].sig[0] ) { case 'B': z= 0; break; case 'C': z= 0; break; case 'D': z= Gfeight; break; case 'F': z= 0; break; case 'I': z= 0; break; case 'J': z= Gfeight; break; case 'L': z= Gfobj; break; case 'S': z= 0; break; case 'Z': z= 0; break; case '[': z= Gfobj; break; default: g_bomb("default switch sig[0]"); } c->flds[i].gflags= z; if (z&Gfeight) off= (off+7)&~7; /* 8-align */ c->flds[i].off= off; off += (z&Gfeight) ? 8 : 4; } /* next i */ get2(c->methc); c->meths= (gmeth*) g_alloc( c->methc * sizeof *c->meths ); for ( i=0; imethc; i++ ) { c->meths[i].cls= c; get2(c->meths[i].aflags); get2(x); c->meths[i].name= GCasc(x); get2(x); c->meths[i].sig= GCasc(x); c->meths[i].argtypes= g_argtypes( c->meths[i].sig ); c->meths[i].rettype= g_rettype( c->meths[i].sig ); cp= g_strdup3( c->meths[i].name, "\t", c->meths[i].sig ); c->meths[i].ns= g_intern(g,cp); free(cp); get2(x); /* num attrs of methods info */ for ( j=0; jmeths[i].code= co; get1(co->maxstk); get1(co->maxloc); get2(co->codec); co->codes= (u1*) g_alloc( co->codec ); for ( k=0; kcodec; k++ ) get1(co->codes[i]); get2(co->exceptc); co->excepts= (gexc*) g_alloc( co->exceptc * sizeof co->excepts ); for ( k=0; kexceptc; k++ ) { get2( co->excepts[k].startpc ); get2( co->excepts[k].endpc ); get2( co->excepts[k].gopc ); get2( co->excepts[k].catchtype ); } get2(z); /* num attrs of code block */ for ( k=0; kstatus= Gfull; c->atype= 0; *out= c; return 0; bad: fclose(f); free(cons); return GbadClassFile; } char* g_name_and_sig(gvm* g, char* name, char* sig) { char* t= g_strdup3( name, "\t", sig ); char* ns= g_intern(g, t); free(t); } g_invoke_static_void(gvm* g, char* cls, char* mname) { char* t; char* ns= g_name_and_sig(g, mname, "()V" ); cls= g_intern(g, cls); } g_evalcode(gvm* g, gfram* prev, gmeth* m) { gfram f; gcod* e= m->code; u1* bc= e->codes; u4* loc; u4* stk; u1* mloc; /* loc holds obj ref */ u1* mstk; /* stk holds obj ref */ gcls* c= m->cls; u4 uv, uw, ux, uy, uz; s4 sv, sw, sx, sy, sz; if (!e) { /* invoke native? */ return 0; } f.vm= g; f.prev= prev; if (prev) prev->next= &f; f.next= (gfram*)NULL; f.cl= m->cls; f.me= m; f.co= e; f.bc= bc; f.loc= loc= (u4*) g_alloc( (e->maxloc + e->maxstk) * sizeof *loc + ( e->maxloc + e->maxstk) ); f.stk= stk= loc+e->maxloc; f.mloc= mloc= (u1*) stk+e->maxstk; f.mstk= mstk= mloc+e->maxloc; f.sp= 0; f.pc= 0; f.ex= (gobj*)NULL; while(1) switch ( f.bc[f.pc] ) { #define u1pc1 ( *(u1*)(f.bc+f.pc+1) ) #define u1pc2 ( *(u1*)(f.bc+f.pc+2) ) #define s1pc1 ( *(s1*)(f.bc+f.pc+1) ) #define s1pc2 ( *(s1*)(f.bc+f.pc+2) ) #define u2pc1 ( (u1pc1<<8) | u1pc2 ) #define s2pc1 ( (s1pc1<<8) | u1pc2 ) #define u2pc(n) ( ((*(u1*)(f.bc+f.pc+(n)))<<8) | (*(u1*)(f.bc+f.pc+(n+1))) ) #define s2pc(n) ( ((*(s1*)(f.bc+f.pc+(n)))<<8) | (*(u1*)(f.bc+f.pc+(n+1))) ) #define u4pc(n) ( ((*(u1*)(f.bc+f.pc+(n)))<<24) | ((*(u1*)(f.bc+f.pc+(n+1)))<<16) |\ ((*(u1*)(f.bc+f.pc+(n+2)))<<8) | (*(u1*)(f.bc+f.pc+(n+3))) ) #define spM (stk[f.sp+1]) #define sp0 (stk[f.sp-0]) #define sp1 (stk[f.sp-1]) #define sp2 (stk[f.sp-2]) #define sp3 (stk[f.sp-3]) #define sp4 (stk[f.sp-4]) #define sp5 (stk[f.sp-5]) #define sp6 (stk[f.sp-6]) #define mspM (mstk[f.sp+1]) #define msp0 (mstk[f.sp-0]) #define msp1 (mstk[f.sp-1]) #define msp2 (mstk[f.sp-2]) #define msp3 (mstk[f.sp-3]) #define msp4 (mstk[f.sp-4]) #define msp5 (mstk[f.sp-5]) #define msp6 (mstk[f.sp-6]) #define Ssp1(z) ( mstk[f.sp-1]? UL(stk[f.sp-1]): 0, stk[f.sp-1]=(z) ) #define Ssp2(z) ( mstk[f.sp-2]? UL(stk[f.sp-2]): 0, stk[f.sp-2]=(z) ) #define Ssp3(z) ( mstk[f.sp-3]? UL(stk[f.sp-3]): 0, stk[f.sp-3]=(z) ) #define Ssp4(z) ( mstk[f.sp-4]? UL(stk[f.sp-4]): 0, stk[f.sp-4]=(z) ) #define Ssp5(z) ( mstk[f.sp-5]? UL(stk[f.sp-5]): 0, stk[f.sp-5]=(z) ) #define Ssp1a(z) ( mstk[f.sp-1]? UL(stk[f.sp-1]): 0, stk[f.sp-1]=(u4)(z), LI(z) ) #define Ssp2a(z) ( mstk[f.sp-2]? UL(stk[f.sp-2]): 0, stk[f.sp-2]=(u4)(z), LI(z) ) #define Ssp3a(z) ( mstk[f.sp-3]? UL(stk[f.sp-3]): 0, stk[f.sp-3]=(u4)(z), LI(z) ) #define Ssp4a(z) ( mstk[f.sp-4]? UL(stk[f.sp-4]): 0, stk[f.sp-4]=(u4)(z), LI(z) ) #define Ssp5a(z) ( mstk[f.sp-5]? UL(stk[f.sp-5]): 0, stk[f.sp-5]=(u4)(z), LI(z) ) #define Sloc(n,z) ( mloc[n]? UL(loc[n]): 0, loc[n]=(z) ) #define Sloca(n,z) ( mloc[n]? UL(loc[n]): 0, loc[n]=(u4)(z), LI(z) ) #define N1 (f.pc+=1) #define N2 (f.pc+=2) #define N3 (f.pc+=3) #define N4 (f.pc+=4) #define I1 (f.sp+=1, mstk[f.sp-1]=0, stk[f.sp-1]= 0) #define I2 ( I1, I1 ) #define D1 (f.sp-=1, mstk[f.sp]? UL(stk[f.sp]): 0) #define D2 ( D1, D1 ) #define D3 ( D1, D1, D1 ) #define D4 ( D1, D1, D1, D1 ) case 16: /*bipush*/ I1; Ssp1( s1pc1 ); N2; break; case 17: /*sipush*/ I1; Ssp1( s2pc1 ); N3; break; case 18: /*ldc1*/ ux= u1pc1; I1; Ssp1( GCint(ux) ); N2; break; case 19: /*ldc2*/ ux= u2pc1; I1; Ssp1( GCint(ux) ); N3; break; case 20: /*ldc2w*/ ux= u2pc1; I2; Ssp2( GClo(ux) ); Ssp1( GChi(ux) ); N3; break; case 1: /*aconst_null*/ I1; Ssp1a(0 ); N1; break; case 2: /*iconst_m1*/ I1; Ssp1( -1 ); N1; break; case 3: I1; Ssp1( 0 ); N1; break; case 4: I1; Ssp1( 1 ); N1; break; case 5: I1; Ssp1( 2 ); N1; break; case 6: I1; Ssp1( 3 ); N1; break; case 7: I1; Ssp1( 4 ); N1; break; case 8: I1; Ssp1( 5 ); N1; break; case 9: case 10: case 11: case 12: case 13: case 14: case 15: g_bomb("op not imp"); break; case 21: /*iload*/ I1; Ssp1( loc[u1pc1] ); N2; break; case 26: I1; Ssp1( loc[0] ); N1; break; case 27: I1; Ssp1( loc[1] ); N1; break; case 28: I1; Ssp1( loc[2] ); N1; break; case 29: I1; Ssp1( loc[3] ); N1; break; case 22: /*lload*/ case 30: case 31: case 32: case 33: case 23: /*fload*/ case 34: case 35: case 36: case 37: case 24: /*dload*/ case 38: case 39: case 40: case 41: g_bomb("op not imp"); break; case 25: /*aload*/ I1; Ssp1a( loc[u1pc1] ); LI(sp1); N2; break; case 42: I1; Ssp1a( loc[0] ); LI(sp1); N1; break; case 43: I1; Ssp1a( loc[1] ); LI(sp1); N1; break; case 44: I1; Ssp1a( loc[2] ); LI(sp1); N1; break; case 45: I1; Ssp1a( loc[3] ); LI(sp1); N1; break; case 54: /*istore*/ Sloc(u1pc1, sp1); N2; break; case 59: Sloc(0, sp1); D1; N1; break; case 60: Sloc(1, sp1); D1; N1; break; case 61: Sloc(2, sp1); D1; N1; break; case 62: Sloc(3, sp1); D1; N1; break; case 55: /*lstore*/ case 63: case 64: case 65: case 66: case 56: /*fstore*/ case 67: case 68: case 69: case 70: case 57: /*dstore*/ case 71: case 72: case 73: case 74: g_bomb("op not imp"); break; case 58: /*astore*/ Sloca(u1pc1, sp1); LI(sp1); N2; break; case 75: Sloca(0, sp1); LI(sp1); D1; N1; break; case 76: Sloca(1, sp1); LI(sp1); D1; N1; break; case 77: Sloca(2, sp1); LI(sp1); D1; N1; break; case 78: Sloca(3, sp1); LI(sp1); D1; N1; break; case 132: /*iinc*/ loc[u1pc1] += s1pc2; N3; break; case 188: /*newarray*/ { garr* t; char* cp; gcls* cc; switch (u1pc1) { /* dont understand Gtarray, really */ case Gtarray: g_bomb("Gtarray"); ux= 4; cc=g_findarraycls( g, g_intern(g,"[Ljava.lang.Object;"), u1pc1 ); break; case Gtboolean: ux= 1; cc=g_findarraycls( g, g_intern(g,"[Z"), u1pc1 ); break; case Gtchar: ux= 1; cc=g_findarraycls( g, g_intern(g,"[C"), u1pc1 ); break; case Gtfloat: ux= 4; cc=g_findarraycls( g, g_intern(g,"[F"), u1pc1 ); break; case Gtdouble: ux= 8; cc=g_findarraycls( g, g_intern(g,"[D"), u1pc1 ); break; case Gtbyte: ux= 1; cc=g_findarraycls( g, g_intern(g,"[B"), u1pc1 ); break; case Gtshort: ux= 2; cc=g_findarraycls( g, g_intern(g,"[S"), u1pc1 ); break; case Gtint: ux= 4; cc=g_findarraycls( g, g_intern(g,"[I"), u1pc1 ); break; case Gtlong: ux= 8; cc=g_findarraycls( g, g_intern(g,"[J"), u1pc1 ); break; default: g_bomb("newarray switch"); } t= (garr*) g_alloc( sizeof *t + sp1*ux ); cc->atype= u1pc1; /*t->depth= 0;*/ t->length= sp1; Ssp1a( t ); /* replace length with result */ N2; } break; case 189: /*anewarray*/ { garr* t; gcls* ec= GCcls(u2pc1); char* tmp= g_strdup2( "[", ec->name ); char* n= g_intern(g,tmp); gcls* cc= g_findarraycls( g, n, 0 ); free(tmp); cc->atype= u1pc1; /* ? */ t= (garr*) g_alloc( sizeof *t + sp1*4 ); /*t->depth= 0;*/ t->length= sp1; Ssp1a( t ); /* replace length with result */ N3; } break; case 198: /*multianewarray*/ g_bomb( "multianewarray" ); break; case 190: /*arraylength*/ { garr* arr= (garr*)sp1; if (!arr) goto tnpx; Ssp1( arr->length ); N1; } break; case 46: /*iaload*/ { garr* arr= (garr*)sp2; if (!arr) goto tnpx; if ( sp1 >= arr->length ) goto tabx; Ssp2( ((u4*)( arr+1 ))[sp1] ); D1; N1; } break; case 47: case 48: case 49: g_bomb("47 48 49"); break; case 50: /*aaload*/ { garr* arr= (garr*)sp2; if (!arr) goto tnpx; if ( sp1 >= arr->length ) goto tabx; Ssp2a( ((u4*)( arr+1 ))[sp1] ); D1; N1; } break; case 51: { garr* arr= (garr*)sp2; if (!arr) goto tnpx; if ( sp1 >= arr->length ) goto tabx; Ssp2( ((s1*)( arr+1 ))[sp1] ); D1; N1; } break; case 52: { garr* arr= (garr*)sp2; if (!arr) goto tnpx; if ( sp1 >= arr->length ) goto tabx; Ssp2( ((u2*)( arr+1 ))[sp1] ); D1; N1; } break; case 53: { garr* arr= (garr*)sp2; if (!arr) goto tnpx; if ( sp1 >= arr->length ) goto tabx; Ssp2( ((s2*)( arr+1 ))[sp1] ); D1; N1; } break; case 79: /*iastore*/ { garr* arr= (garr*)sp3; if (!arr) goto tnpx; if ( sp2 >= arr->length ) goto tabx; ( ((u4*)( arr+1 ))[sp2] )= sp1; D3; N1; } break; case 80: /*lastore*/ case 81: /*fastore*/ case 82: /*dastore*/ g_bomb("(lfd)astore"); break; case 83: /*aastore*/ { garr* arr= (garr*)sp3; if (!arr) goto tnpx; if ( sp2 >= arr->length ) goto tabx; UL( ((u4*)( arr+1 ))[sp2] ); ( ((u4*)( arr+1 ))[sp2] )= sp1; D3; N1; } break; case 84: /*bastore*/ { garr* arr= (garr*)sp3; if (!arr) goto tnpx; if ( sp2 >= arr->length ) goto tabx; ( ((u4*)( arr+1 ))[sp2] )= sp1; D3; N1; } break; case 85: /*castore*/ { garr* arr= (garr*)sp3; if (!arr) goto tnpx; if ( sp2 >= arr->length ) goto tabx; ( ((u2*)( arr+1 ))[sp2] )= sp1; D3; N1; } break; case 86: /*sastore*/ { garr* arr= (garr*)sp3; if (!arr) goto tnpx; if ( sp2 >= arr->length ) goto tabx; ( ((s2*)( arr+1 ))[sp2] )= sp1; D3; N1; } break; case 0: /*nop*/ N1; break; case 87: /*pop*/ D1; N1; break; case 88: /*pop2*/ D2; N1; break; case 89: /*dup*/ if (msp1) LI(sp1); I1; sp1= sp2; N1; break; case 92: /*dup2*/ if (msp1) LI(sp1); if (msp2) LI(sp2); I2; sp1= sp3; sp2= sp4; N1; break; case 90: /*dup_x1*/ if (msp1) LI(sp1); I1; sp1= sp2; sp2= sp3; sp3= sp1; N1; break; case 93: /*dup2_x1*/ if (msp1) LI(sp1); if (msp2) LI(sp2); I2; sp1= sp3; sp2= sp4; sp3= sp1; sp4= sp1; sp5= sp2; N1; break; case 91: /*dup_x2*/ if (msp1) LI(sp1); I1; sp1= sp2; sp2= sp3; sp3= sp4; sp4= sp1; N1; break; case 94: /*dup2_x2*/ if (msp1) LI(sp1); if (msp2) LI(sp2); I2; sp1= sp3; sp2= sp4; sp3= sp5; sp4= sp6; sp5= sp1; sp6= sp2; N1; break; case 95: /*swap*/ ux= sp1; sp1= sp2; sp2= ux; N1; break; /* arithmetic */ case 96: /*iadd*/ sp2= sp2 + sp1; D1; N1; break; case 100: /*isub*/ sp2= sp2 - sp1; D1; N1; break; case 104: /*imul*/ sp2= sp2 * sp1; D1; N1; break; case 108: /*idiv*/ sp2= sp2 / sp1; D1; N1; break; case 112: /*imod*/ sp2= sp2 % sp1; D1; N1; break; case 116: /*ineg*/ sp1= 0-sp1; N1; break; case 120: /*ishl*/ sp2= sp2 >> (31&sp1); D1; N1; break; case 122: /*ishr*/ sp2= (s4)sp2 >> (s4)(31&sp1); D1; N1; break; case 124: /*iushr*/ sp2= sp2 >> (31&sp1); D1; N1; break; case 126: /*iand*/ sp2= sp2 & sp1; D1; N1; break; case 128: /*ior*/ sp2= sp2 | sp1; D1; N1; break; case 130: /*ixor*/ sp2= sp2 ^ sp1; D1; N1; break; /* conversions */ case 145: /*int2byte*/ sp1= (s1)sp1; N1; break; case 146: /*int2char*/ sp1= (u2)sp1; N1; break; case 147: /*int2short*/ sp1= (s2)sp1; N1; break; /* control */ case 153: /*ifeq*/ sx= sp1; D1; if (sx==0) f.pc+=s2pc1; else N3; break; case 154: /*ifne*/ sx= sp1; D1; if (sx!=0) f.pc+=s2pc1; else N3; break; case 155: /*iflt*/ sx= sp1; D1; if (sx<0) f.pc+=s2pc1; else N3; break; case 156: /*ifge*/ sx= sp1; D1; if (sx>=0) f.pc+=s2pc1; else N3; break; case 157: /*ifgt*/ sx= sp1; D1; if (sx>0) f.pc+=s2pc1; else N3; break; case 158: /*ifle*/ sx= sp1; D1; if (sx<=0) f.pc+=s2pc1; else N3; break; case 159: /*if_icmpeq*/ sx= sp2; sy= sp1; D2; if (sx==sy) f.pc+=s2pc1; else N3; break; case 160: /*if_icmpne*/ sx= sp2; sy= sp1; D2; if (sx!=sy) f.pc+=s2pc1; else N3; break; case 161: /*if_icmplt*/ sx= sp2; sy= sp1; D2; if (sx=sy) f.pc+=s2pc1; else N3; break; case 163: /*if_icmpgt*/ sx= sp2; sy= sp1; D2; if (sx>sy) f.pc+=s2pc1; else N3; break; case 164: /*if_icmple*/ sx= sp2; sy= sp1; D2; if (sx<=sy) f.pc+=s2pc1; else N3; break; case 165: /*if_acmpeq*/ ux= sp0; uy= sp1; D2; if (ux==uy) f.pc+=s2pc1; else N3; break; case 166: /*if_acmpne*/ ux= sp0; uy= sp1; D2; if (ux!=uy) f.pc+=s2pc1; else N3; break; case 167: /*goto*/ f.pc+=s2pc1; break; case 168: /*jsr*/ ux= f.pc+3; f.pc+=s2pc1; I1; Ssp1(ux); break; case 169: /*ret*/ f.pc= loc[u1pc1]; break; /* return */ case 172: /*ireturn*/ if (prev) { ++ prev->sp; prev->mstk[prev->sp-1]= 0; prev->stk[prev->sp-1]= sp1; } goto ret; case 176: /*areturn*/ if (prev) { ++ prev->sp; prev->mstk[prev->sp-1]= 1; prev->stk[prev->sp-1]= sp1; } goto ret; case 177: /*return*/ goto ret; case 170: /*tableswitch*/ ux= (3&f.pc) ? 4-(3&f.pc) : 0; /* find size of padding */ sx= u4pc(ux+0); /* default offset */ sy= u4pc(ux+4); /* low */ sz= u4pc(ux+8); /* high */ sw= sp1; I1; /* index */ if ( swsz ) f.pc += sx; else f.pc += u4pc(ux+12+4*(sw-sy)); break; case 171: /*lookupswitch*/ ux= (3&f.pc) ? 4-(3&f.pc) : 0; /* find size of padding */ uy= u4pc(ux+0); /* default offset */ uz= u4pc(ux+4); /* npairs */ uv= sp1; I1; /* key */ for ( uw=0; uwtag == ConFieldR ); cc= co->u.r.clsi; if (cc->gstatus==Gempty) g_loadclass(cc); if (fp= co->u.r.fld) goto doputfield; for ( i=0; ifldc; ++i ) { fp= cc->flds[i]; if ( fp->name == co->u.r.namei ) { co->u.r.fld= fp; goto doputfield; } } g_bomb("putfield: name not found"); doputfield: assert( ! (fp->gflags&Gfeight) ); obj= (gobj*)sp2; if (!obj) goto tnpx; datap= fp->off + (char*)obj; if (fp->gflags&Gfobj) { UL( (gobj*)datap ); } *(u4*)datap = sp1; if (fp->gflags&Gfobj) { LI( (gobj*)datap ); } endputfield: D2; /* TODO: eight */ N3; } break; case 181: /*getfield*/ { gcon* co= GCcon(u2pc1); gcls* cc; gfld* fp; gobj* obj; char* datap; assert ( co->tag == ConFieldR ); cc= co->u.r.clsi; if (cc->gstatus==Gempty) g_loadclass(cc); if (fp= co->u.r.fld) goto doputfield; for ( i=0; ifldc; ++i ) { fp= cc->flds[i]; if ( fp->name == co->u.r.namei ) { co->u.r.fld= fp; goto doputfield; } } g_bomb("putfield: name not found"); doputfield: assert( ! (fp->gflags&Gfeight) ); obj= (gobj*)sp2; if (!obj) goto tnpx; datap= fp->off + (char*)obj; *(u4*)datap = sp1; if (fp->gflags&Gfobj) { Ssp1a( *datap ); } else { Ssp1( *datap ); } endputfield: D2; /* TODO: eight */ N3; } break; case 179: /*putstatic*/ case 178: /*getstatic*/ g_bomb("static later"); break; case 182: /*invokevirtual*/ { gcon* co= GCcon(u2pc1); gcls* cc; gfld* fp; gobj* obj; char* datap; assert ( co->tag == ConFieldR ); cc= co->u.r.clsi; if (cc->gstatus==Gempty) g_loadclass(cc); /* cache??? */ for ( i=0; imethc; ++i ) { fp= cc->meths[i]; if ( fp->name == co->u.r.namei ) { /* set cache ??? */ goto doinvokevirtual; } } g_bomb("putfield: name not found");  doinvokevirtual: default: g_bomb("unknown opcode"); endwhile: } /* esac+endwhile */ tnpx: g_bomb("null ptr x"); tabx: g_bomb("array bound"); ret: for ( ux=0; uxnext= (gfram*)NULL; } out: return 0; } g_delete(gobj* obj) { printf( "free %d\n", (u4)obj ); } main( int argc, char* argv[] ) { int i; gvm* g= g_gvmnew(); for ( i=1; iname:"" ); } return 0; }