Charles.Forsyth20060303644188019 years agoHistory
1055 lines · 22.2 KB · C
RawDownload
#include <lib9.h>#include <bio.h>#include "mach.h" /* * Sparc-specific debugger interface */ static	char	*sparcexcep(Map*, Rgetter);static	int	sparcfoll(Map*, ulong, Rgetter, ulong*);static	int	sparcinst(Map*, ulong, char, char*, int);static	int	sparcdas(Map*, ulong, char*, int);static	int	sparcinstlen(Map*, ulong); Machdata sparcmach ={	{0x91, 0xd0, 0x20, 0x01},	/* breakpoint: TA $1 */	4,			/* break point size */ 	beswab,			/* convert short to local byte order */	beswal,			/* convert long to local byte order */	beswav,			/* convert vlong to local byte order */	risctrace,		/* C traceback */	riscframe,		/* frame finder */	sparcexcep,		/* print exception */	0,			/* breakpoint fixup */	beieeesftos,		/* single precision float printer */	beieeedftos,		/* double precision float printer */	sparcfoll,		/* following addresses */	sparcinst,		/* print instruction */	sparcdas,		/* dissembler */	sparcinstlen,		/* instruction size */}; static char *trapname[] ={	"reset",	"instruction access exception",	"illegal instruction",	"privileged instruction",	"fp disabled",	"window overflow",	"window underflow",	"unaligned address",	"fp exception",	"data access exception",	"tag overflow",}; static char*excname(ulong tbr){	static char buf[32]; 	if(tbr < sizeof trapname/sizeof(char*))		return trapname[tbr];	if(tbr >= 130)		sprint(buf, "trap instruction %ld", tbr-128);	else if(17<=tbr && tbr<=31)		sprint(buf, "interrupt level %ld", tbr-16);	else switch(tbr){	case 36:		return "cp disabled";	case 40:		return "cp exception";	case 128:		return "syscall";	case 129:		return "breakpoint";	default:		sprint(buf, "unknown trap %ld", tbr);	}	return buf;} static char*sparcexcep(Map *map, Rgetter rget){	long tbr; 	tbr = (*rget)(map, "TBR");	tbr = (tbr&0xFFF)>>4;	return excname(tbr);} 	/* Sparc disassembler and related functions */ typedef struct instr Instr; struct opcode {	char	*mnemonic;	void	(*f)(Instr*, char*);	int	flag;}; static	char FRAMENAME[] = ".frame"; struct instr {	uchar	op;		/* bits 31-30 */	uchar	rd;		/* bits 29-25 */	uchar	op2;		/* bits 24-22 */	uchar	a;		/* bit  29    */	uchar	cond;		/* bits 28-25 */	uchar	op3;		/* bits 24-19 */	uchar	rs1;		/* bits 18-14 */	uchar	i;		/* bit  13    */	uchar	asi;		/* bits 12-05 */	uchar	rs2;		/* bits 04-00 */	short	simm13;		/* bits 12-00, signed */	ushort	opf;		/* bits 13-05 */	ulong	immdisp22;	/* bits 21-00 */	ulong	simmdisp22;	/* bits 21-00, signed */	ulong	disp30;		/* bits 30-00 */	ulong	imm32;		/* SETHI+ADD constant */	int	target;		/* SETHI+ADD dest reg */	long	w0;	long	w1;	ulong	addr;		/* pc of instruction */	char	*curr;		/* current fill level in output buffer */	char	*end;		/* end of buffer */	int 	size;		/* number of longs in instr */	char	*err;		/* errmsg */}; static	Map	*mymap;		/* disassembler context */static	int	dascase; static int	mkinstr(ulong, Instr*);static void	bra1(Instr*, char*, char*[]);static void	bra(Instr*, char*);static void	fbra(Instr*, char*);static void	cbra(Instr*, char*);static void	unimp(Instr*, char*);static void	fpop(Instr*, char*);static void	shift(Instr*, char*);static void	sethi(Instr*, char*);static void	load(Instr*, char*);static void	loada(Instr*, char*);static void	store(Instr*, char*);static void	storea(Instr*, char*);static void	add(Instr*, char*);static void	cmp(Instr*, char*);static void	wr(Instr*, char*);static void	jmpl(Instr*, char*);static void	rd(Instr*, char*);static void	loadf(Instr*, char*);static void	storef(Instr*, char*);static void	loadc(Instr*, char*);static void	loadcsr(Instr*, char*);static void	trap(Instr*, char*); static struct opcode sparcop0[8] = {	"UNIMP",	unimp,	0,	/* page 137 */	/* 0 */		"",		0,	0,		/* 1 */	"B",		bra,	0,	/* page 119 */	/* 2 */		"",		0,	0,		/* 3 */	"SETHI",	sethi,	0,	/* page 104 */	/* 4 */		"",		0,	0,		/* 5 */	"FB",		fbra,	0,	/* page 121 */	/* 6 */	"CB",		cbra,	0,	/* page 123 */	/* 7 */}; static struct opcode sparcop2[64] = {		"ADD",		add,	0,	/* page 108 */	/* 0x00 */		"AND",		add,	0,	/* page 106 */	/* 0x01 */		"OR",		add,	0,			/* 0x02 */		"XOR",		add,	0,			/* 0x03 */		"SUB",		add,	0,	/* page 110 */	/* 0x04 */		"ANDN",		add,	0,			/* 0x05 */		"ORN",		add,	0,			/* 0x06 */		"XORN",		add,	0,			/* 0x07 */		"ADDX",		add,	0,			/* 0x08 */		"",		0,	0,			/* 0x09 */		"UMUL",		add,	0,	/* page 113 */	/* 0x0a */		"SMUL",		add,	0,			/* 0x0b */		"SUBX",		add,	0,			/* 0x0c */		"",		0,	0,			/* 0x0d */		"UDIV",		add,	0,	/* page 115 */	/* 0x0e */		"SDIV",		add,	0,			/* 0x0f */		"ADDCC",	add,	0,			/* 0x10 */		"ANDCC",	add,	0,			/* 0x11 */		"ORCC",		add,	0,			/* 0x12 */		"XORCC",	add,	0,			/* 0x13 */		"SUBCC",	cmp,	0,			/* 0x14 */		"ANDNCC",	add,	0,			/* 0x15 */		"ORNCC",	add,	0,			/* 0x16 */		"XORNCC",	add,	0,			/* 0x17 */		"ADDXCC",	add,	0,			/* 0x18 */		"",		0,	0,			/* 0x19 */		"UMULCC",	add,	0,			/* 0x1a */		"SMULCC",	add,	0,			/* 0x1b */		"SUBXCC",	add,	0,			/* 0x1c */		"",		0,	0,			/* 0x1d */		"UDIVCC",	add,	0,			/* 0x1e */		"SDIVCC",	add,	0,			/* 0x1f */		"TADD",		add,	0,	/* page 109 */	/* 0x20 */		"TSUB",		add,	0,	/* page 111 */	/* 0x21 */		"TADDCCTV",	add,	0,			/* 0x22 */		"TSUBCCTV",	add,	0,			/* 0x23 */		"MULSCC",	add,	0,	/* page 112 */	/* 0x24 */		"SLL",		shift,	0,	/* page 107 */	/* 0x25 */		"SRL",		shift,	0,			/* 0x26 */		"SRA",		shift,	0,			/* 0x27 */		"rdy",		rd,	0,	/* page 131 */	/* 0x28 */		"rdpsr",	rd,	0,			/* 0x29 */		"rdwim",	rd,	0,			/* 0x2a */		"rdtbr",	rd,	0,			/* 0x2b */		"",		0,	0,			/* 0x2c */		"",		0,	0,			/* 0x2d */		"",		0,	0,			/* 0x2e */		"",		0,	0,			/* 0x2f */		"wry",		wr,	0,	/* page 133 */	/* 0x30 */		"wrpsr",	wr,	0,			/* 0x31 */		"wrwim",	wr,	0,			/* 0x32 */		"wrtbr",	wr,	0,			/* 0x33 */		"FPOP",		fpop,	0,	/* page 140 */	/* 0x34 */		"FPOP",		fpop,	0,			/* 0x35 */		"",		0,	0,			/* 0x36 */		"",		0,	0,			/* 0x37 */		"JMPL",		jmpl,	0,	/* page 126 */	/* 0x38 */		"RETT",		add,	0,	/* page 127 */	/* 0x39 */		"T",		trap,	0,	/* page 129 */	/* 0x3a */		"flush",	add,	0,	/* page 138 */	/* 0x3b */		"SAVE",		add,	0,	/* page 117 */	/* 0x3c */		"RESTORE",	add,	0,			/* 0x3d */}; static struct opcode sparcop3[64]={		"ld",		load,	0,			/* 0x00 */		"ldub",		load,	0,			/* 0x01 */		"lduh",		load,	0,			/* 0x02 */		"ldd",		load,	0,			/* 0x03 */		"st",		store,	0,			/* 0x04 */		"stb",		store,	0,	/* page 95 */	/* 0x05 */		"sth",		store,	0,			/* 0x06 */		"std",		store,	0,			/* 0x07 */		"",		0,	0,			/* 0x08 */		"ldsb",		load,	0,	/* page 90 */	/* 0x09 */		"ldsh",		load,	0,			/* 0x0a */		"",		0,	0,			/* 0x0b */		"",		0,	0,			/* 0x0c */		"ldstub",	store,	0,	/* page 101 */	/* 0x0d */		"",		0,	0,			/* 0x0e */		"swap",		load,	0,	/* page 102 */	/* 0x0f */		"lda",		loada,	0,			/* 0x10 */		"lduba",	loada,	0,			/* 0x11 */		"lduha",	loada,	0,			/* 0x12 */		"ldda",		loada,	0,			/* 0x13 */		"sta",		storea,	0,			/* 0x14 */		"stba",		storea,	0,			/* 0x15 */		"stha",		storea,	0,			/* 0x16 */		"stda",		storea,	0,			/* 0x17 */		"",		0,	0,			/* 0x18 */		"ldsba",	loada,	0,			/* 0x19 */		"ldsha",	loada,	0,			/* 0x1a */		"",		0,	0,			/* 0x1b */		"",		0,	0,			/* 0x1c */		"ldstuba",	storea,	0,			/* 0x1d */		"",		0,	0,			/* 0x1e */		"swapa",	loada,	0,			/* 0x1f */		"ldf",		loadf,	0,	/* page 92 */	/* 0x20 */		"ldfsr",	loadf,0,			/* 0x21 */		"",		0,	0,			/* 0x22 */		"lddf",		loadf,	0,			/* 0x23 */		"stf",		storef,	0,	/* page 97 */	/* 0x24 */		"stfsr",	storef,0,			/* 0x25 */		"stdfq",	storef,0,			/* 0x26 */		"stdf",		storef,	0,			/* 0x27 */		"",		0,	0,			/* 0x28 */		"",		0,	0,			/* 0x29 */		"",		0,	0,			/* 0x2a */		"",		0,	0,			/* 0x2b */		"",		0,	0,			/* 0x2c */		"",		0,	0,			/* 0x2d */		"",		0,	0,			/* 0x2e */		"",		0,	0,			/* 0x2f */		"ldc",		loadc,	0,	/* page 94 */	/* 0x30 */		"ldcsr",	loadcsr,0,			/* 0x31 */		"",		0,	0,			/* 0x32 */		"lddc",		loadc,	0,			/* 0x33 */		"stc",		loadc,	0,	/* page 99 */	/* 0x34 */		"stcsr",	loadcsr,0,			/* 0x35 */		"stdcq",	loadcsr,0,			/* 0x36 */		"stdc",		loadc,	0,			/* 0x37 */}; static voidbprint(Instr *i, char *fmt, ...){	va_list arg; 	va_start(arg, fmt);	i->curr = vseprint(i->curr, i->end, fmt, arg);	va_end(arg);} static intdecode(ulong pc, Instr *i){	long w; 	if (get4(mymap, pc, &w) < 0) {		werrstr("can't read instruction: %r");		return -1;	}	i->op = (w >> 30) & 0x03;	i->rd = (w >> 25) & 0x1F;	i->op2 = (w >> 22) & 0x07;	i->a = (w >> 29) & 0x01;	i->cond = (w >> 25) & 0x0F;	i->op3 = (w >> 19) & 0x3F;	i->rs1 = (w >> 14) & 0x1F;	i->i = (w >> 13) & 0x01;	i->asi = (w >> 5) & 0xFF;	i->rs2 = (w >> 0) & 0x1F;	i->simm13 = (w >> 0) & 0x1FFF;	if(i->simm13 & (1<<12))		i->simm13 |= ~((1<<13)-1);	i->opf = (w >> 5) & 0x1FF;	i->immdisp22 = (w >> 0) & 0x3FFFFF;	i->simmdisp22 = i->immdisp22;	if(i->simmdisp22 & (1<<21))		i->simmdisp22 |= ~((1<<22)-1);	i->disp30 = (w >> 0) & 0x3FFFFFFF;	i->w0 = w;	i->target = -1;	i->addr = pc;	i->size = 1;	return 1;} static intmkinstr(ulong pc, Instr *i){	Instr xi; 	if (decode(pc, i) < 0)		return -1;	if(i->op==0 && i->op2==4 && !dascase){	/* SETHI */		if (decode(pc+4, &xi) < 0)			return -1;		if(xi.op==2 && xi.op3==0)		/* ADD */		if(xi.i == 1 && xi.rs1 == i->rd){	/* immediate to same reg */			i->imm32 = xi.simm13 + (i->immdisp22<<10);			i->target = xi.rd;			i->w1 = xi.w0;			i->size++;			return 1;		}	}	if(i->op==2 && i->opf==1 && !dascase){	/* FMOVS */		if (decode(pc+4, &xi) < 0)			return -1;		if(i->op==2 && i->opf==1)		/* FMOVS */		if(xi.rd==i->rd+1 && xi.rs2==i->rs2+1){	/* next pair */			i->w1 = xi.w0;			i->size++;		}	}	return 1;} static intprintins(Map *map, ulong pc, char *buf, int n){	Instr instr;	void (*f)(Instr*, char*); 	mymap = map;	memset(&instr, 0, sizeof(instr));	instr.curr = buf;	instr.end = buf+n-1;	if (mkinstr(pc, &instr) < 0)		return -1;	switch(instr.op){	case 0:		f = sparcop0[instr.op2].f;		if(f)			(*f)(&instr, sparcop0[instr.op2].mnemonic);		else			bprint(&instr, "unknown %lux", instr.w0);		break; 	case 1:		bprint(&instr, "%X", "CALL\t");		instr.curr += symoff(instr.curr, instr.end-instr.curr,					pc+instr.disp30*4, CTEXT);		if (!dascase)			bprint(&instr, "(SB)");		break; 	case 2:		f = sparcop2[instr.op3].f;		if(f)			(*f)(&instr, sparcop2[instr.op3].mnemonic);		else			bprint(&instr, "unknown %lux", instr.w0);		break; 	case 3:		f = sparcop3[instr.op3].f;		if(f)			(*f)(&instr, sparcop3[instr.op3].mnemonic);		else			bprint(&instr, "unknown %lux", instr.w0);		break;	}	if (instr.err) {		if (instr.curr != buf)			bprint(&instr, "\t\t;");		bprint(&instr, instr.err);	}	return instr.size*4;} /* convert to lower case from upper, according to dascase */static intXconv(Fmt *f){	char buf[128];	char *s, *t, *oa; 	oa = va_arg(f->args, char*);	if(dascase){		for(s=oa,t=buf; *t = *s; s++,t++)			if('A'<=*t && *t<='Z')				*t += 'a'-'A';		return fmtstrcpy(f, buf);	}	return fmtstrcpy(f, oa);} static intsparcinst(Map *map, ulong pc, char modifier, char *buf, int n){	static int fmtinstalled = 0; 		/* a modifier of 'I' toggles the dissassembler type */	if (!fmtinstalled) {		fmtinstalled = 1;		fmtinstall('X', Xconv);	}	if ((asstype == ASUNSPARC && modifier == 'i')		|| (asstype == ASPARC && modifier == 'I'))		dascase = 'a'-'A';	else		dascase = 0;	return printins(map, pc, buf, n);} static intsparcdas(Map *map, ulong pc, char *buf, int n){	Instr instr; 	mymap = map;	memset(&instr, 0, sizeof(instr));	instr.curr = buf;	instr.end = buf+n-1;	if (mkinstr(pc, &instr) < 0)		return -1;	if (instr.end-instr.curr > 8)		instr.curr = _hexify(instr.curr, instr.w0, 7);	if (instr.end-instr.curr > 9 && instr.size == 2) {		*instr.curr++ = ' ';		instr.curr = _hexify(instr.curr, instr.w1, 7);	}	*instr.curr = 0;	return instr.size*4;} static intsparcinstlen(Map *map, ulong pc){	Instr i; 	mymap = map;	if (mkinstr(pc, &i) < 0)		return -1;	return i.size*4;} static intplocal(Instr *i){	int offset;	Symbol s; 	if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))		return -1;	if (s.value > i->simm13) {		if(getauto(&s, s.value-i->simm13, CAUTO, &s)) {			bprint(i, "%s+%d(SP)", s.name, s.value);			return 1;		}	} else {		offset = i->simm13-s.value;		if (getauto(&s, offset-4, CPARAM, &s)) {			bprint(i, "%s+%d(FP)", s.name, offset);			return 1;

Lines 1–500 of 1055.