336 lines · 5.5 KB · C
RawDownload
#include "java.h" Inst	*ihead;		/* first instruction generated for .class file */Inst	*itail;		/* last instruction (for appending to list) */ static	uchar	*cache;		/* module data cache */static	int	ncached;	/* number of bytes in cache */static	int	ndatum;		/* number of non-string basic datums in cache */static	int	startoff;	/* offset of first datum in cache */static	int	lastoff;	/* 1 past last byte offset in cache */static	int	lastkind = -1;	/* last kind of datum put in cache */static	int	lencache;	/* capacity of cache */ /* * Generate Dis object file (.dis). */ voiddiscon(int val){	if(val >= -64 && val <= 63) {		Bputc(bout, val & ~0x80);		return;	}	if(val >= -8192 && val <= 8191) {		Bputc(bout, ((val>>8) & ~0xC0) | 0x80);		Bputc(bout, val);		return;	}	if(notimmable(val))		fatal("discon: overflow 16r%ux\n", val);	Bputc(bout, (val>>24) | 0xC0);	Bputc(bout, val>>16);	Bputc(bout, val>>8);	Bputc(bout, val);} voiddisword(int w){	Bputc(bout, w >> 24);	Bputc(bout, w >> 16);	Bputc(bout, w >> 8);	Bputc(bout, w);} voiddisdata(int kind, int n){	if(n < DMAX && n != 0)		Bputc(bout, DBYTE(kind, n));	else{		Bputc(bout, DBYTE(kind, 0));		discon(n);	}} voiddisflush(int kind, int off, int size){	if(kind != lastkind || off != lastoff){		if(lastkind != -1 && ncached){			disdata(lastkind, ndatum);			discon(startoff);			Bwrite(bout, cache, ncached);		}		startoff = off;		lastkind = kind;		ncached = 0;		ndatum = 0;	}	lastoff = off + size;	while(kind >= 0 && ncached + size >= lencache){		lencache = ncached+1024;		cache = Realloc(cache, lencache);	}} voiddisbyte(int off, int v){	disflush(DEFB, off, 1);	cache[ncached++] = v;	ndatum++;} voiddisint(int off, int v){	disflush(DEFW, off, IBY2WD);	cache[ncached++] = v >> 24;	cache[ncached++] = v >> 16;	cache[ncached++] = v >> 8;	cache[ncached++] = v;	ndatum++;} voiddislong(int off, vlong v){	uint iv; 	disflush(DEFL, off, IBY2LG);	iv = v >> 32;	cache[ncached++] = iv >> 24;	cache[ncached++] = iv >> 16;	cache[ncached++] = iv >> 8;	cache[ncached++] = iv;	iv = v;	cache[ncached++] = iv >> 24;	cache[ncached++] = iv >> 16;	cache[ncached++] = iv >> 8;	cache[ncached++] = iv;	ndatum++;} static voiddtocanon(double f, uint v[]){	union { double d; uint ui[2]; } a; 	a.d = 1.;	if(a.ui[0]) {		a.d = f;		v[0] = a.ui[0];		v[1] = a.ui[1];	} else {		a.d = f;		v[0] = a.ui[1];		v[1] = a.ui[0];	}} voiddisreal(int off, double v){	uint bv[2];	uint iv; 	disflush(DEFF, off, IBY2LG);	dtocanon(v, bv);	iv = bv[0];	cache[ncached++] = iv >> 24;	cache[ncached++] = iv >> 16;	cache[ncached++] = iv >> 8;	cache[ncached++] = iv;	iv = bv[1];	cache[ncached++] = iv >> 24;	cache[ncached++] = iv >> 16;	cache[ncached++] = iv >> 8;	cache[ncached++] = iv;	ndatum++;} voiddisstring(int offset, char *s){	int n, src, dst;	char *a; 	/* null char represented as 0xC080 in String literals */	n = strlen(s);	a = Malloc(n);	src = 0;	dst = 0;	while(src < n) {		if(src+1 < n && (uchar)s[src] == 0xC0 && (uchar)s[src+1] == 0x80) {			a[dst] = '\0';			src++;		} else			a[dst] = s[src];		src++;		dst++;	}	disflush(-1, -1, 0);	disdata(DEFS, dst);	discon(offset);	Bwrite(bout, a, dst);	free(a);} /* * Begin an array initializer. */ voiddisarray(int off, int tid, int nelt){	disflush(-1, -1, 0);	disdata(DEFA, 1);	/* 1 is ignored */	discon(off);	disword(tid);	disword(nelt);	disdata(DIND, 1);	/* 1 is ignored */	discon(off);	disword(0);} /* * Terminate an array initializer. */ voiddisapop(void){	disflush(-1, -1, 0);	disdata(DAPOP, 1);	/* 1 is ignored */	discon(0);} /* * Put number of instructions into .dis Header. */ voiddisninst(void){	discon(itail ? itail->pc + 1 : 0);} static int dismode[Aend] = {	/* Anone */	AXXX,	/* Aimm */	AIMM,	/* Amp */	AMP,	/* Ampind */	AMP|AIND,	/* Afp */	AFP,	/* Afpind */	AFP|AIND}; static int disregmode[Aend] = {	/* Anone */	AXNON,	/* Aimm */	AXIMM,	/* Amp */	AXINM,	/* Ampind */	AXNON,	/* Afp */	AXINF,	/* Afpind */	AXNON}; enum{	MAXCON	= 4,	MAXADDR	= 2*MAXCON,	MAXINST	= 3*MAXCON+2,	NIBUF	= 1024}; static	uchar	*ibuf;static	int	nibuf; static voiddisbcon(int val){	if(val >= -64 && val <= 63){		ibuf[nibuf++] = val & ~0x80;		return;	}	if(val >= -8192 && val <= 8191){		ibuf[nibuf++] = val>>8 & ~0xC0 | 0x80;		ibuf[nibuf++] = val;		return;	}	if(notimmable(val))		fatal("disbcon: overflow 16r%x\n", val);	ibuf[nibuf++] = val>>24 | 0xC0;	ibuf[nibuf++] = val>>16;	ibuf[nibuf++] = val>>8;	ibuf[nibuf++] = val;} static voiddisaddr(Addr *a){	int val; 	val = 0;	switch(a->mode){	case Aimm:		val = a->u.ival;		break;	case Afp:	case Amp:		val = a->u.offset;		break;	case Afpind:	case Ampind:		disbcon(a->u.b.fi);		val = a->u.b.si;		break;	}	disbcon(val);} static voiddisinst(void){	Inst *i; 	ibuf = Malloc(NIBUF);	nibuf = 0;	for(i = ihead; i; i = i->next){		if(nibuf >= NIBUF-MAXINST){			Bwrite(bout, ibuf, nibuf);			nibuf = 0;		}		ibuf[nibuf++] = i->op;		ibuf[nibuf++] = SRC(dismode[i->s.mode])			| DST(dismode[i->d.mode]) | disregmode[i->m.mode];		if(i->m.mode != Anone)			disaddr(&i->m);		if(i->s.mode != Anone)			disaddr(&i->s);		if(i->d.mode != Anone)			disaddr(&i->d);	}	if(nibuf > 0)		Bwrite(bout, ibuf, nibuf);	free(ibuf);} voiddisout(void){	discon(XMAGIC);	discon(DONTCOMPILE);	/* runtime "hints" */	disstackext();		/* minimum stack extent size */	disninst();	disnvar();	disndesc();	disnlinks();	disentry();	disinst();	disdesc();	disvar();	dismod();	dislinks();}