xref: /inferno-os/utils/libmach/kdb.c (revision 45a20ab721a513710138340faff3d59a31c3e01e)
174a4d8c2SCharles.Forsyth #include <lib9.h>
274a4d8c2SCharles.Forsyth #include <bio.h>
374a4d8c2SCharles.Forsyth #include "mach.h"
474a4d8c2SCharles.Forsyth 
574a4d8c2SCharles.Forsyth /*
674a4d8c2SCharles.Forsyth  * Sparc-specific debugger interface
774a4d8c2SCharles.Forsyth  */
874a4d8c2SCharles.Forsyth 
974a4d8c2SCharles.Forsyth static	char	*sparcexcep(Map*, Rgetter);
10d67b7dadSforsyth static	int	sparcfoll(Map*, uvlong, Rgetter, uvlong*);
11d67b7dadSforsyth static	int	sparcinst(Map*, uvlong, char, char*, int);
12d67b7dadSforsyth static	int	sparcdas(Map*, uvlong, char*, int);
13d67b7dadSforsyth static	int	sparcinstlen(Map*, uvlong);
1474a4d8c2SCharles.Forsyth 
1574a4d8c2SCharles.Forsyth Machdata sparcmach =
1674a4d8c2SCharles.Forsyth {
1774a4d8c2SCharles.Forsyth 	{0x91, 0xd0, 0x20, 0x01},	/* breakpoint: TA $1 */
1874a4d8c2SCharles.Forsyth 	4,			/* break point size */
1974a4d8c2SCharles.Forsyth 
2074a4d8c2SCharles.Forsyth 	beswab,			/* convert short to local byte order */
2174a4d8c2SCharles.Forsyth 	beswal,			/* convert long to local byte order */
2274a4d8c2SCharles.Forsyth 	beswav,			/* convert vlong to local byte order */
2374a4d8c2SCharles.Forsyth 	risctrace,		/* C traceback */
2474a4d8c2SCharles.Forsyth 	riscframe,		/* frame finder */
2574a4d8c2SCharles.Forsyth 	sparcexcep,		/* print exception */
2674a4d8c2SCharles.Forsyth 	0,			/* breakpoint fixup */
2774a4d8c2SCharles.Forsyth 	beieeesftos,		/* single precision float printer */
2874a4d8c2SCharles.Forsyth 	beieeedftos,		/* double precision float printer */
2974a4d8c2SCharles.Forsyth 	sparcfoll,		/* following addresses */
3074a4d8c2SCharles.Forsyth 	sparcinst,		/* print instruction */
3174a4d8c2SCharles.Forsyth 	sparcdas,		/* dissembler */
3274a4d8c2SCharles.Forsyth 	sparcinstlen,		/* instruction size */
3374a4d8c2SCharles.Forsyth };
3474a4d8c2SCharles.Forsyth 
3574a4d8c2SCharles.Forsyth static char *trapname[] =
3674a4d8c2SCharles.Forsyth {
3774a4d8c2SCharles.Forsyth 	"reset",
3874a4d8c2SCharles.Forsyth 	"instruction access exception",
3974a4d8c2SCharles.Forsyth 	"illegal instruction",
4074a4d8c2SCharles.Forsyth 	"privileged instruction",
4174a4d8c2SCharles.Forsyth 	"fp disabled",
4274a4d8c2SCharles.Forsyth 	"window overflow",
4374a4d8c2SCharles.Forsyth 	"window underflow",
4474a4d8c2SCharles.Forsyth 	"unaligned address",
4574a4d8c2SCharles.Forsyth 	"fp exception",
4674a4d8c2SCharles.Forsyth 	"data access exception",
4774a4d8c2SCharles.Forsyth 	"tag overflow",
4874a4d8c2SCharles.Forsyth };
4974a4d8c2SCharles.Forsyth 
5074a4d8c2SCharles.Forsyth static char*
excname(ulong tbr)5174a4d8c2SCharles.Forsyth excname(ulong tbr)
5274a4d8c2SCharles.Forsyth {
5374a4d8c2SCharles.Forsyth 	static char buf[32];
5474a4d8c2SCharles.Forsyth 
5574a4d8c2SCharles.Forsyth 	if(tbr < sizeof trapname/sizeof(char*))
5674a4d8c2SCharles.Forsyth 		return trapname[tbr];
5774a4d8c2SCharles.Forsyth 	if(tbr >= 130)
5874a4d8c2SCharles.Forsyth 		sprint(buf, "trap instruction %ld", tbr-128);
5974a4d8c2SCharles.Forsyth 	else if(17<=tbr && tbr<=31)
6074a4d8c2SCharles.Forsyth 		sprint(buf, "interrupt level %ld", tbr-16);
6174a4d8c2SCharles.Forsyth 	else switch(tbr){
6274a4d8c2SCharles.Forsyth 	case 36:
6374a4d8c2SCharles.Forsyth 		return "cp disabled";
6474a4d8c2SCharles.Forsyth 	case 40:
6574a4d8c2SCharles.Forsyth 		return "cp exception";
6674a4d8c2SCharles.Forsyth 	case 128:
6774a4d8c2SCharles.Forsyth 		return "syscall";
6874a4d8c2SCharles.Forsyth 	case 129:
6974a4d8c2SCharles.Forsyth 		return "breakpoint";
7074a4d8c2SCharles.Forsyth 	default:
7174a4d8c2SCharles.Forsyth 		sprint(buf, "unknown trap %ld", tbr);
7274a4d8c2SCharles.Forsyth 	}
7374a4d8c2SCharles.Forsyth 	return buf;
7474a4d8c2SCharles.Forsyth }
7574a4d8c2SCharles.Forsyth 
7674a4d8c2SCharles.Forsyth static char*
sparcexcep(Map * map,Rgetter rget)7774a4d8c2SCharles.Forsyth sparcexcep(Map *map, Rgetter rget)
7874a4d8c2SCharles.Forsyth {
7974a4d8c2SCharles.Forsyth 	long tbr;
8074a4d8c2SCharles.Forsyth 
8174a4d8c2SCharles.Forsyth 	tbr = (*rget)(map, "TBR");
8274a4d8c2SCharles.Forsyth 	tbr = (tbr&0xFFF)>>4;
8374a4d8c2SCharles.Forsyth 	return excname(tbr);
8474a4d8c2SCharles.Forsyth }
8574a4d8c2SCharles.Forsyth 
8674a4d8c2SCharles.Forsyth 	/* Sparc disassembler and related functions */
87fb27fba1Sforsyth typedef struct instr Instr;
8874a4d8c2SCharles.Forsyth 
8974a4d8c2SCharles.Forsyth struct opcode {
9074a4d8c2SCharles.Forsyth 	char	*mnemonic;
91fb27fba1Sforsyth 	void	(*f)(Instr*, char*);
9274a4d8c2SCharles.Forsyth 	int	flag;
9374a4d8c2SCharles.Forsyth };
9474a4d8c2SCharles.Forsyth 
9574a4d8c2SCharles.Forsyth static	char FRAMENAME[] = ".frame";
9674a4d8c2SCharles.Forsyth 
97d67b7dadSforsyth 
9874a4d8c2SCharles.Forsyth struct instr {
9974a4d8c2SCharles.Forsyth 	uchar	op;		/* bits 31-30 */
10074a4d8c2SCharles.Forsyth 	uchar	rd;		/* bits 29-25 */
10174a4d8c2SCharles.Forsyth 	uchar	op2;		/* bits 24-22 */
10274a4d8c2SCharles.Forsyth 	uchar	a;		/* bit  29    */
10374a4d8c2SCharles.Forsyth 	uchar	cond;		/* bits 28-25 */
10474a4d8c2SCharles.Forsyth 	uchar	op3;		/* bits 24-19 */
10574a4d8c2SCharles.Forsyth 	uchar	rs1;		/* bits 18-14 */
10674a4d8c2SCharles.Forsyth 	uchar	i;		/* bit  13    */
10774a4d8c2SCharles.Forsyth 	uchar	asi;		/* bits 12-05 */
10874a4d8c2SCharles.Forsyth 	uchar	rs2;		/* bits 04-00 */
10974a4d8c2SCharles.Forsyth 	short	simm13;		/* bits 12-00, signed */
11074a4d8c2SCharles.Forsyth 	ushort	opf;		/* bits 13-05 */
11174a4d8c2SCharles.Forsyth 	ulong	immdisp22;	/* bits 21-00 */
11274a4d8c2SCharles.Forsyth 	ulong	simmdisp22;	/* bits 21-00, signed */
11374a4d8c2SCharles.Forsyth 	ulong	disp30;		/* bits 30-00 */
11474a4d8c2SCharles.Forsyth 	ulong	imm32;		/* SETHI+ADD constant */
11574a4d8c2SCharles.Forsyth 	int	target;		/* SETHI+ADD dest reg */
11674a4d8c2SCharles.Forsyth 	long	w0;
11774a4d8c2SCharles.Forsyth 	long	w1;
118d67b7dadSforsyth 	uvlong	addr;		/* pc of instruction */
11974a4d8c2SCharles.Forsyth 	char	*curr;		/* current fill level in output buffer */
12074a4d8c2SCharles.Forsyth 	char	*end;		/* end of buffer */
12174a4d8c2SCharles.Forsyth 	int 	size;		/* number of longs in instr */
12274a4d8c2SCharles.Forsyth 	char	*err;		/* errmsg */
12374a4d8c2SCharles.Forsyth };
12474a4d8c2SCharles.Forsyth 
12574a4d8c2SCharles.Forsyth static	Map	*mymap;		/* disassembler context */
12674a4d8c2SCharles.Forsyth static	int	dascase;
12774a4d8c2SCharles.Forsyth 
128d67b7dadSforsyth static int	mkinstr(uvlong, Instr*);
12974a4d8c2SCharles.Forsyth static void	bra1(Instr*, char*, char*[]);
13074a4d8c2SCharles.Forsyth static void	bra(Instr*, char*);
13174a4d8c2SCharles.Forsyth static void	fbra(Instr*, char*);
13274a4d8c2SCharles.Forsyth static void	cbra(Instr*, char*);
13374a4d8c2SCharles.Forsyth static void	unimp(Instr*, char*);
13474a4d8c2SCharles.Forsyth static void	fpop(Instr*, char*);
13574a4d8c2SCharles.Forsyth static void	shift(Instr*, char*);
13674a4d8c2SCharles.Forsyth static void	sethi(Instr*, char*);
13774a4d8c2SCharles.Forsyth static void	load(Instr*, char*);
13874a4d8c2SCharles.Forsyth static void	loada(Instr*, char*);
13974a4d8c2SCharles.Forsyth static void	store(Instr*, char*);
14074a4d8c2SCharles.Forsyth static void	storea(Instr*, char*);
14174a4d8c2SCharles.Forsyth static void	add(Instr*, char*);
14274a4d8c2SCharles.Forsyth static void	cmp(Instr*, char*);
14374a4d8c2SCharles.Forsyth static void	wr(Instr*, char*);
14474a4d8c2SCharles.Forsyth static void	jmpl(Instr*, char*);
14574a4d8c2SCharles.Forsyth static void	rd(Instr*, char*);
14674a4d8c2SCharles.Forsyth static void	loadf(Instr*, char*);
14774a4d8c2SCharles.Forsyth static void	storef(Instr*, char*);
14874a4d8c2SCharles.Forsyth static void	loadc(Instr*, char*);
14974a4d8c2SCharles.Forsyth static void	loadcsr(Instr*, char*);
15074a4d8c2SCharles.Forsyth static void	trap(Instr*, char*);
15174a4d8c2SCharles.Forsyth 
15274a4d8c2SCharles.Forsyth static struct opcode sparcop0[8] = {
153773d7fd2Sforsyth 	"UNIMP",	unimp,	0,	/* page 137 */	/* 0 */
154773d7fd2Sforsyth 		"",		0,	0,		/* 1 */
155773d7fd2Sforsyth 	"B",		bra,	0,	/* page 119 */	/* 2 */
156773d7fd2Sforsyth 		"",		0,	0,		/* 3 */
157773d7fd2Sforsyth 	"SETHI",	sethi,	0,	/* page 104 */	/* 4 */
158773d7fd2Sforsyth 		"",		0,	0,		/* 5 */
159773d7fd2Sforsyth 	"FB",		fbra,	0,	/* page 121 */	/* 6 */
160773d7fd2Sforsyth 	"CB",		cbra,	0,	/* page 123 */	/* 7 */
16174a4d8c2SCharles.Forsyth };
16274a4d8c2SCharles.Forsyth 
16374a4d8c2SCharles.Forsyth static struct opcode sparcop2[64] = {
164773d7fd2Sforsyth 	"ADD",		add,	0,	/* page 108 */	/* 0x00 */
165773d7fd2Sforsyth 	"AND",		add,	0,	/* page 106 */	/* 0x01 */
166773d7fd2Sforsyth 	"OR",		add,	0,			/* 0x02 */
167773d7fd2Sforsyth 	"XOR",		add,	0,			/* 0x03 */
168773d7fd2Sforsyth 	"SUB",		add,	0,	/* page 110 */	/* 0x04 */
169773d7fd2Sforsyth 	"ANDN",		add,	0,			/* 0x05 */
170773d7fd2Sforsyth 	"ORN",		add,	0,			/* 0x06 */
171773d7fd2Sforsyth 	"XORN",		add,	0,			/* 0x07 */
172773d7fd2Sforsyth 	"ADDX",		add,	0,			/* 0x08 */
173773d7fd2Sforsyth 	"",		0,	0,			/* 0x09 */
174773d7fd2Sforsyth 	"UMUL",		add,	0,	/* page 113 */	/* 0x0a */
175773d7fd2Sforsyth 	"SMUL",		add,	0,			/* 0x0b */
176773d7fd2Sforsyth 	"SUBX",		add,	0,			/* 0x0c */
177773d7fd2Sforsyth 	"",		0,	0,			/* 0x0d */
178773d7fd2Sforsyth 	"UDIV",		add,	0,	/* page 115 */	/* 0x0e */
179773d7fd2Sforsyth 	"SDIV",		add,	0,			/* 0x0f */
180773d7fd2Sforsyth 	"ADDCC",	add,	0,			/* 0x10 */
181773d7fd2Sforsyth 	"ANDCC",	add,	0,			/* 0x11 */
182773d7fd2Sforsyth 	"ORCC",		add,	0,			/* 0x12 */
183773d7fd2Sforsyth 	"XORCC",	add,	0,			/* 0x13 */
184773d7fd2Sforsyth 	"SUBCC",	cmp,	0,			/* 0x14 */
185773d7fd2Sforsyth 	"ANDNCC",	add,	0,			/* 0x15 */
186773d7fd2Sforsyth 	"ORNCC",	add,	0,			/* 0x16 */
187773d7fd2Sforsyth 	"XORNCC",	add,	0,			/* 0x17 */
188773d7fd2Sforsyth 	"ADDXCC",	add,	0,			/* 0x18 */
189773d7fd2Sforsyth 	"",		0,	0,			/* 0x19 */
190773d7fd2Sforsyth 	"UMULCC",	add,	0,			/* 0x1a */
191773d7fd2Sforsyth 	"SMULCC",	add,	0,			/* 0x1b */
192773d7fd2Sforsyth 	"SUBXCC",	add,	0,			/* 0x1c */
193773d7fd2Sforsyth 	"",		0,	0,			/* 0x1d */
194773d7fd2Sforsyth 	"UDIVCC",	add,	0,			/* 0x1e */
195773d7fd2Sforsyth 	"SDIVCC",	add,	0,			/* 0x1f */
196773d7fd2Sforsyth 	"TADD",		add,	0,	/* page 109 */	/* 0x20 */
197773d7fd2Sforsyth 	"TSUB",		add,	0,	/* page 111 */	/* 0x21 */
198773d7fd2Sforsyth 	"TADDCCTV",	add,	0,			/* 0x22 */
199773d7fd2Sforsyth 	"TSUBCCTV",	add,	0,			/* 0x23 */
200773d7fd2Sforsyth 	"MULSCC",	add,	0,	/* page 112 */	/* 0x24 */
201773d7fd2Sforsyth 	"SLL",		shift,	0,	/* page 107 */	/* 0x25 */
202773d7fd2Sforsyth 	"SRL",		shift,	0,			/* 0x26 */
203773d7fd2Sforsyth 	"SRA",		shift,	0,			/* 0x27 */
204773d7fd2Sforsyth 	"rdy",		rd,	0,	/* page 131 */	/* 0x28 */
205773d7fd2Sforsyth 	"rdpsr",	rd,	0,			/* 0x29 */
206773d7fd2Sforsyth 	"rdwim",	rd,	0,			/* 0x2a */
207773d7fd2Sforsyth 	"rdtbr",	rd,	0,			/* 0x2b */
208773d7fd2Sforsyth 	"",		0,	0,			/* 0x2c */
209773d7fd2Sforsyth 	"",		0,	0,			/* 0x2d */
210773d7fd2Sforsyth 	"",		0,	0,			/* 0x2e */
211773d7fd2Sforsyth 	"",		0,	0,			/* 0x2f */
212773d7fd2Sforsyth 	"wry",		wr,	0,	/* page 133 */	/* 0x30 */
213773d7fd2Sforsyth 	"wrpsr",	wr,	0,			/* 0x31 */
214773d7fd2Sforsyth 	"wrwim",	wr,	0,			/* 0x32 */
215773d7fd2Sforsyth 	"wrtbr",	wr,	0,			/* 0x33 */
216773d7fd2Sforsyth 	"FPOP",		fpop,	0,	/* page 140 */	/* 0x34 */
217773d7fd2Sforsyth 	"FPOP",		fpop,	0,			/* 0x35 */
218773d7fd2Sforsyth 	"",		0,	0,			/* 0x36 */
219773d7fd2Sforsyth 	"",		0,	0,			/* 0x37 */
220773d7fd2Sforsyth 	"JMPL",		jmpl,	0,	/* page 126 */	/* 0x38 */
221773d7fd2Sforsyth 	"RETT",		add,	0,	/* page 127 */	/* 0x39 */
222773d7fd2Sforsyth 	"T",		trap,	0,	/* page 129 */	/* 0x3a */
223773d7fd2Sforsyth 	"flush",	add,	0,	/* page 138 */	/* 0x3b */
224773d7fd2Sforsyth 	"SAVE",		add,	0,	/* page 117 */	/* 0x3c */
225773d7fd2Sforsyth 	"RESTORE",	add,	0,			/* 0x3d */
22674a4d8c2SCharles.Forsyth };
22774a4d8c2SCharles.Forsyth 
22874a4d8c2SCharles.Forsyth static struct opcode sparcop3[64]={
229773d7fd2Sforsyth 	"ld",		load,	0,			/* 0x00 */
230773d7fd2Sforsyth 	"ldub",		load,	0,			/* 0x01 */
231773d7fd2Sforsyth 	"lduh",		load,	0,			/* 0x02 */
232773d7fd2Sforsyth 	"ldd",		load,	0,			/* 0x03 */
233773d7fd2Sforsyth 	"st",		store,	0,			/* 0x04 */
234773d7fd2Sforsyth 	"stb",		store,	0,	/* page 95 */	/* 0x05 */
235773d7fd2Sforsyth 	"sth",		store,	0,			/* 0x06 */
236773d7fd2Sforsyth 	"std",		store,	0,			/* 0x07 */
237773d7fd2Sforsyth 	"",		0,	0,			/* 0x08 */
238773d7fd2Sforsyth 	"ldsb",		load,	0,	/* page 90 */	/* 0x09 */
239773d7fd2Sforsyth 	"ldsh",		load,	0,			/* 0x0a */
240773d7fd2Sforsyth 	"",		0,	0,			/* 0x0b */
241773d7fd2Sforsyth 	"",		0,	0,			/* 0x0c */
242773d7fd2Sforsyth 	"ldstub",	store,	0,	/* page 101 */	/* 0x0d */
243773d7fd2Sforsyth 	"",		0,	0,			/* 0x0e */
244773d7fd2Sforsyth 	"swap",		load,	0,	/* page 102 */	/* 0x0f */
245773d7fd2Sforsyth 	"lda",		loada,	0,			/* 0x10 */
246773d7fd2Sforsyth 	"lduba",	loada,	0,			/* 0x11 */
247773d7fd2Sforsyth 	"lduha",	loada,	0,			/* 0x12 */
248773d7fd2Sforsyth 	"ldda",		loada,	0,			/* 0x13 */
249773d7fd2Sforsyth 	"sta",		storea,	0,			/* 0x14 */
250773d7fd2Sforsyth 	"stba",		storea,	0,			/* 0x15 */
251773d7fd2Sforsyth 	"stha",		storea,	0,			/* 0x16 */
252773d7fd2Sforsyth 	"stda",		storea,	0,			/* 0x17 */
253773d7fd2Sforsyth 	"",		0,	0,			/* 0x18 */
254773d7fd2Sforsyth 	"ldsba",	loada,	0,			/* 0x19 */
255773d7fd2Sforsyth 	"ldsha",	loada,	0,			/* 0x1a */
256773d7fd2Sforsyth 	"",		0,	0,			/* 0x1b */
257773d7fd2Sforsyth 	"",		0,	0,			/* 0x1c */
258773d7fd2Sforsyth 	"ldstuba",	storea,	0,			/* 0x1d */
259773d7fd2Sforsyth 	"",		0,	0,			/* 0x1e */
260773d7fd2Sforsyth 	"swapa",	loada,	0,			/* 0x1f */
261773d7fd2Sforsyth 	"ldf",		loadf,	0,	/* page 92 */	/* 0x20 */
262773d7fd2Sforsyth 	"ldfsr",	loadf,0,			/* 0x21 */
263773d7fd2Sforsyth 	"",		0,	0,			/* 0x22 */
264773d7fd2Sforsyth 	"lddf",		loadf,	0,			/* 0x23 */
265773d7fd2Sforsyth 	"stf",		storef,	0,	/* page 97 */	/* 0x24 */
266773d7fd2Sforsyth 	"stfsr",	storef,0,			/* 0x25 */
267773d7fd2Sforsyth 	"stdfq",	storef,0,			/* 0x26 */
268773d7fd2Sforsyth 	"stdf",		storef,	0,			/* 0x27 */
269773d7fd2Sforsyth 	"",		0,	0,			/* 0x28 */
270773d7fd2Sforsyth 	"",		0,	0,			/* 0x29 */
271773d7fd2Sforsyth 	"",		0,	0,			/* 0x2a */
272773d7fd2Sforsyth 	"",		0,	0,			/* 0x2b */
273773d7fd2Sforsyth 	"",		0,	0,			/* 0x2c */
274773d7fd2Sforsyth 	"",		0,	0,			/* 0x2d */
275773d7fd2Sforsyth 	"",		0,	0,			/* 0x2e */
276773d7fd2Sforsyth 	"",		0,	0,			/* 0x2f */
277773d7fd2Sforsyth 	"ldc",		loadc,	0,	/* page 94 */	/* 0x30 */
278773d7fd2Sforsyth 	"ldcsr",	loadcsr,0,			/* 0x31 */
279773d7fd2Sforsyth 	"",		0,	0,			/* 0x32 */
280773d7fd2Sforsyth 	"lddc",		loadc,	0,			/* 0x33 */
281773d7fd2Sforsyth 	"stc",		loadc,	0,	/* page 99 */	/* 0x34 */
282773d7fd2Sforsyth 	"stcsr",	loadcsr,0,			/* 0x35 */
283773d7fd2Sforsyth 	"stdcq",	loadcsr,0,			/* 0x36 */
284773d7fd2Sforsyth 	"stdc",		loadc,	0,			/* 0x37 */
28574a4d8c2SCharles.Forsyth };
28674a4d8c2SCharles.Forsyth 
287d67b7dadSforsyth #pragma	varargck	argpos	bprint	2
288d67b7dadSforsyth #pragma	varargck	type	"T"	char*
289d67b7dadSforsyth 
290d67b7dadSforsyth /* convert to lower case from upper, according to dascase */
291d67b7dadSforsyth static int
Tfmt(Fmt * f)292d67b7dadSforsyth Tfmt(Fmt *f)
293d67b7dadSforsyth {
294d67b7dadSforsyth 	char buf[128];
295d67b7dadSforsyth 	char *s, *t, *oa;
296d67b7dadSforsyth 
297d67b7dadSforsyth 	oa = va_arg(f->args, char*);
298d67b7dadSforsyth 	if(dascase){
299d67b7dadSforsyth 		for(s=oa,t=buf; *t = *s; s++,t++)
300d67b7dadSforsyth 			if('A'<=*t && *t<='Z')
301d67b7dadSforsyth 				*t += 'a'-'A';
302d67b7dadSforsyth 		return fmtstrcpy(f, buf);
303d67b7dadSforsyth 	}
304d67b7dadSforsyth 	return fmtstrcpy(f, oa);
305d67b7dadSforsyth }
306d67b7dadSforsyth 
30774a4d8c2SCharles.Forsyth static void
bprint(Instr * i,char * fmt,...)30874a4d8c2SCharles.Forsyth bprint(Instr *i, char *fmt, ...)
30974a4d8c2SCharles.Forsyth {
31074a4d8c2SCharles.Forsyth 	va_list arg;
31174a4d8c2SCharles.Forsyth 
31274a4d8c2SCharles.Forsyth 	va_start(arg, fmt);
31374a4d8c2SCharles.Forsyth 	i->curr = vseprint(i->curr, i->end, fmt, arg);
31474a4d8c2SCharles.Forsyth 	va_end(arg);
31574a4d8c2SCharles.Forsyth }
31674a4d8c2SCharles.Forsyth 
31774a4d8c2SCharles.Forsyth static int
decode(uvlong pc,Instr * i)318d67b7dadSforsyth decode(uvlong pc, Instr *i)
31974a4d8c2SCharles.Forsyth {
320d67b7dadSforsyth 	ulong w;
32174a4d8c2SCharles.Forsyth 
32274a4d8c2SCharles.Forsyth 	if (get4(mymap, pc, &w) < 0) {
32374a4d8c2SCharles.Forsyth 		werrstr("can't read instruction: %r");
32474a4d8c2SCharles.Forsyth 		return -1;
32574a4d8c2SCharles.Forsyth 	}
32674a4d8c2SCharles.Forsyth 	i->op = (w >> 30) & 0x03;
32774a4d8c2SCharles.Forsyth 	i->rd = (w >> 25) & 0x1F;
32874a4d8c2SCharles.Forsyth 	i->op2 = (w >> 22) & 0x07;
32974a4d8c2SCharles.Forsyth 	i->a = (w >> 29) & 0x01;
33074a4d8c2SCharles.Forsyth 	i->cond = (w >> 25) & 0x0F;
33174a4d8c2SCharles.Forsyth 	i->op3 = (w >> 19) & 0x3F;
33274a4d8c2SCharles.Forsyth 	i->rs1 = (w >> 14) & 0x1F;
33374a4d8c2SCharles.Forsyth 	i->i = (w >> 13) & 0x01;
33474a4d8c2SCharles.Forsyth 	i->asi = (w >> 5) & 0xFF;
33574a4d8c2SCharles.Forsyth 	i->rs2 = (w >> 0) & 0x1F;
33674a4d8c2SCharles.Forsyth 	i->simm13 = (w >> 0) & 0x1FFF;
33774a4d8c2SCharles.Forsyth 	if(i->simm13 & (1<<12))
33874a4d8c2SCharles.Forsyth 		i->simm13 |= ~((1<<13)-1);
33974a4d8c2SCharles.Forsyth 	i->opf = (w >> 5) & 0x1FF;
34074a4d8c2SCharles.Forsyth 	i->immdisp22 = (w >> 0) & 0x3FFFFF;
34174a4d8c2SCharles.Forsyth 	i->simmdisp22 = i->immdisp22;
34274a4d8c2SCharles.Forsyth 	if(i->simmdisp22 & (1<<21))
34374a4d8c2SCharles.Forsyth 		i->simmdisp22 |= ~((1<<22)-1);
34474a4d8c2SCharles.Forsyth 	i->disp30 = (w >> 0) & 0x3FFFFFFF;
34574a4d8c2SCharles.Forsyth 	i->w0 = w;
34674a4d8c2SCharles.Forsyth 	i->target = -1;
34774a4d8c2SCharles.Forsyth 	i->addr = pc;
34874a4d8c2SCharles.Forsyth 	i->size = 1;
34974a4d8c2SCharles.Forsyth 	return 1;
35074a4d8c2SCharles.Forsyth }
35174a4d8c2SCharles.Forsyth 
35274a4d8c2SCharles.Forsyth static int
mkinstr(uvlong pc,Instr * i)353d67b7dadSforsyth mkinstr(uvlong pc, Instr *i)
35474a4d8c2SCharles.Forsyth {
35574a4d8c2SCharles.Forsyth 	Instr xi;
35674a4d8c2SCharles.Forsyth 
35774a4d8c2SCharles.Forsyth 	if (decode(pc, i) < 0)
35874a4d8c2SCharles.Forsyth 		return -1;
35974a4d8c2SCharles.Forsyth 	if(i->op==0 && i->op2==4 && !dascase){	/* SETHI */
36074a4d8c2SCharles.Forsyth 		if (decode(pc+4, &xi) < 0)
36174a4d8c2SCharles.Forsyth 			return -1;
36274a4d8c2SCharles.Forsyth 		if(xi.op==2 && xi.op3==0)		/* ADD */
36374a4d8c2SCharles.Forsyth 		if(xi.i == 1 && xi.rs1 == i->rd){	/* immediate to same reg */
36474a4d8c2SCharles.Forsyth 			i->imm32 = xi.simm13 + (i->immdisp22<<10);
36574a4d8c2SCharles.Forsyth 			i->target = xi.rd;
36674a4d8c2SCharles.Forsyth 			i->w1 = xi.w0;
36774a4d8c2SCharles.Forsyth 			i->size++;
36874a4d8c2SCharles.Forsyth 			return 1;
36974a4d8c2SCharles.Forsyth 		}
37074a4d8c2SCharles.Forsyth 	}
37174a4d8c2SCharles.Forsyth 	if(i->op==2 && i->opf==1 && !dascase){	/* FMOVS */
37274a4d8c2SCharles.Forsyth 		if (decode(pc+4, &xi) < 0)
37374a4d8c2SCharles.Forsyth 			return -1;
37474a4d8c2SCharles.Forsyth 		if(i->op==2 && i->opf==1)		/* FMOVS */
37574a4d8c2SCharles.Forsyth 		if(xi.rd==i->rd+1 && xi.rs2==i->rs2+1){	/* next pair */
37674a4d8c2SCharles.Forsyth 			i->w1 = xi.w0;
37774a4d8c2SCharles.Forsyth 			i->size++;
37874a4d8c2SCharles.Forsyth 		}
37974a4d8c2SCharles.Forsyth 	}
38074a4d8c2SCharles.Forsyth 	return 1;
38174a4d8c2SCharles.Forsyth }
38274a4d8c2SCharles.Forsyth 
38374a4d8c2SCharles.Forsyth static int
printins(Map * map,uvlong pc,char * buf,int n)384d67b7dadSforsyth printins(Map *map, uvlong pc, char *buf, int n)
38574a4d8c2SCharles.Forsyth {
38674a4d8c2SCharles.Forsyth 	Instr instr;
38774a4d8c2SCharles.Forsyth 	void (*f)(Instr*, char*);
38874a4d8c2SCharles.Forsyth 
38974a4d8c2SCharles.Forsyth 	mymap = map;
39074a4d8c2SCharles.Forsyth 	memset(&instr, 0, sizeof(instr));
39174a4d8c2SCharles.Forsyth 	instr.curr = buf;
39274a4d8c2SCharles.Forsyth 	instr.end = buf+n-1;
39374a4d8c2SCharles.Forsyth 	if (mkinstr(pc, &instr) < 0)
39474a4d8c2SCharles.Forsyth 		return -1;
39574a4d8c2SCharles.Forsyth 	switch(instr.op){
39674a4d8c2SCharles.Forsyth 	case 0:
39774a4d8c2SCharles.Forsyth 		f = sparcop0[instr.op2].f;
39874a4d8c2SCharles.Forsyth 		if(f)
39974a4d8c2SCharles.Forsyth 			(*f)(&instr, sparcop0[instr.op2].mnemonic);
40074a4d8c2SCharles.Forsyth 		else
40174a4d8c2SCharles.Forsyth 			bprint(&instr, "unknown %lux", instr.w0);
40274a4d8c2SCharles.Forsyth 		break;
40374a4d8c2SCharles.Forsyth 
40474a4d8c2SCharles.Forsyth 	case 1:
405d67b7dadSforsyth 		bprint(&instr, "%T", "CALL\t");
40674a4d8c2SCharles.Forsyth 		instr.curr += symoff(instr.curr, instr.end-instr.curr,
40774a4d8c2SCharles.Forsyth 					pc+instr.disp30*4, CTEXT);
40874a4d8c2SCharles.Forsyth 		if (!dascase)
40974a4d8c2SCharles.Forsyth 			bprint(&instr, "(SB)");
41074a4d8c2SCharles.Forsyth 		break;
41174a4d8c2SCharles.Forsyth 
41274a4d8c2SCharles.Forsyth 	case 2:
41374a4d8c2SCharles.Forsyth 		f = sparcop2[instr.op3].f;
41474a4d8c2SCharles.Forsyth 		if(f)
41574a4d8c2SCharles.Forsyth 			(*f)(&instr, sparcop2[instr.op3].mnemonic);
41674a4d8c2SCharles.Forsyth 		else
41774a4d8c2SCharles.Forsyth 			bprint(&instr, "unknown %lux", instr.w0);
41874a4d8c2SCharles.Forsyth 		break;
41974a4d8c2SCharles.Forsyth 
42074a4d8c2SCharles.Forsyth 	case 3:
42174a4d8c2SCharles.Forsyth 		f = sparcop3[instr.op3].f;
42274a4d8c2SCharles.Forsyth 		if(f)
42374a4d8c2SCharles.Forsyth 			(*f)(&instr, sparcop3[instr.op3].mnemonic);
42474a4d8c2SCharles.Forsyth 		else
42574a4d8c2SCharles.Forsyth 			bprint(&instr, "unknown %lux", instr.w0);
42674a4d8c2SCharles.Forsyth 		break;
42774a4d8c2SCharles.Forsyth 	}
42874a4d8c2SCharles.Forsyth 	if (instr.err) {
42974a4d8c2SCharles.Forsyth 		if (instr.curr != buf)
43074a4d8c2SCharles.Forsyth 			bprint(&instr, "\t\t;");
43174a4d8c2SCharles.Forsyth 		bprint(&instr, instr.err);
43274a4d8c2SCharles.Forsyth 	}
43374a4d8c2SCharles.Forsyth 	return instr.size*4;
43474a4d8c2SCharles.Forsyth }
43574a4d8c2SCharles.Forsyth 
43674a4d8c2SCharles.Forsyth static int
sparcinst(Map * map,uvlong pc,char modifier,char * buf,int n)437d67b7dadSforsyth sparcinst(Map *map, uvlong pc, char modifier, char *buf, int n)
43874a4d8c2SCharles.Forsyth {
43974a4d8c2SCharles.Forsyth 	static int fmtinstalled = 0;
44074a4d8c2SCharles.Forsyth 
44174a4d8c2SCharles.Forsyth 		/* a modifier of 'I' toggles the dissassembler type */
44274a4d8c2SCharles.Forsyth 	if (!fmtinstalled) {
44374a4d8c2SCharles.Forsyth 		fmtinstalled = 1;
444d67b7dadSforsyth 		fmtinstall('T', Tfmt);
44574a4d8c2SCharles.Forsyth 	}
44674a4d8c2SCharles.Forsyth 	if ((asstype == ASUNSPARC && modifier == 'i')
44774a4d8c2SCharles.Forsyth 		|| (asstype == ASPARC && modifier == 'I'))
44874a4d8c2SCharles.Forsyth 		dascase = 'a'-'A';
44974a4d8c2SCharles.Forsyth 	else
45074a4d8c2SCharles.Forsyth 		dascase = 0;
45174a4d8c2SCharles.Forsyth 	return printins(map, pc, buf, n);
45274a4d8c2SCharles.Forsyth }
45374a4d8c2SCharles.Forsyth 
45474a4d8c2SCharles.Forsyth static int
sparcdas(Map * map,uvlong pc,char * buf,int n)455d67b7dadSforsyth sparcdas(Map *map, uvlong pc, char *buf, int n)
45674a4d8c2SCharles.Forsyth {
45774a4d8c2SCharles.Forsyth 	Instr instr;
45874a4d8c2SCharles.Forsyth 
45974a4d8c2SCharles.Forsyth 	mymap = map;
46074a4d8c2SCharles.Forsyth 	memset(&instr, 0, sizeof(instr));
46174a4d8c2SCharles.Forsyth 	instr.curr = buf;
46274a4d8c2SCharles.Forsyth 	instr.end = buf+n-1;
46374a4d8c2SCharles.Forsyth 	if (mkinstr(pc, &instr) < 0)
46474a4d8c2SCharles.Forsyth 		return -1;
46574a4d8c2SCharles.Forsyth 	if (instr.end-instr.curr > 8)
46674a4d8c2SCharles.Forsyth 		instr.curr = _hexify(instr.curr, instr.w0, 7);
46774a4d8c2SCharles.Forsyth 	if (instr.end-instr.curr > 9 && instr.size == 2) {
46874a4d8c2SCharles.Forsyth 		*instr.curr++ = ' ';
46974a4d8c2SCharles.Forsyth 		instr.curr = _hexify(instr.curr, instr.w1, 7);
47074a4d8c2SCharles.Forsyth 	}
47174a4d8c2SCharles.Forsyth 	*instr.curr = 0;
47274a4d8c2SCharles.Forsyth 	return instr.size*4;
47374a4d8c2SCharles.Forsyth }
47474a4d8c2SCharles.Forsyth 
47574a4d8c2SCharles.Forsyth static int
sparcinstlen(Map * map,uvlong pc)476d67b7dadSforsyth sparcinstlen(Map *map, uvlong pc)
47774a4d8c2SCharles.Forsyth {
47874a4d8c2SCharles.Forsyth 	Instr i;
47974a4d8c2SCharles.Forsyth 
48074a4d8c2SCharles.Forsyth 	mymap = map;
48174a4d8c2SCharles.Forsyth 	if (mkinstr(pc, &i) < 0)
48274a4d8c2SCharles.Forsyth 		return -1;
48374a4d8c2SCharles.Forsyth 	return i.size*4;
48474a4d8c2SCharles.Forsyth }
48574a4d8c2SCharles.Forsyth 
48674a4d8c2SCharles.Forsyth static int
plocal(Instr * i)48774a4d8c2SCharles.Forsyth plocal(Instr *i)
48874a4d8c2SCharles.Forsyth {
48974a4d8c2SCharles.Forsyth 	int offset;
49074a4d8c2SCharles.Forsyth 	Symbol s;
49174a4d8c2SCharles.Forsyth 
49274a4d8c2SCharles.Forsyth 	if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
49374a4d8c2SCharles.Forsyth 		return -1;
49474a4d8c2SCharles.Forsyth 	if (s.value > i->simm13) {
49574a4d8c2SCharles.Forsyth 		if(getauto(&s, s.value-i->simm13, CAUTO, &s)) {
496d67b7dadSforsyth 			bprint(i, "%s+%lld(SP)", s.name, s.value);
49774a4d8c2SCharles.Forsyth 			return 1;
49874a4d8c2SCharles.Forsyth 		}
49974a4d8c2SCharles.Forsyth 	} else {
50074a4d8c2SCharles.Forsyth 		offset = i->simm13-s.value;
50174a4d8c2SCharles.Forsyth 		if (getauto(&s, offset-4, CPARAM, &s)) {
50274a4d8c2SCharles.Forsyth 			bprint(i, "%s+%d(FP)", s.name, offset);
50374a4d8c2SCharles.Forsyth 			return 1;
50474a4d8c2SCharles.Forsyth 		}
50574a4d8c2SCharles.Forsyth 	}
50674a4d8c2SCharles.Forsyth 	return -1;
50774a4d8c2SCharles.Forsyth }
50874a4d8c2SCharles.Forsyth 
50974a4d8c2SCharles.Forsyth static void
address(Instr * i)51074a4d8c2SCharles.Forsyth address(Instr *i)
51174a4d8c2SCharles.Forsyth {
51274a4d8c2SCharles.Forsyth 	Symbol s, s2;
513d67b7dadSforsyth 	uvlong off, off1;
51474a4d8c2SCharles.Forsyth 
51574a4d8c2SCharles.Forsyth 	if (i->rs1 == 1 && plocal(i) >= 0)
51674a4d8c2SCharles.Forsyth 		return;
51774a4d8c2SCharles.Forsyth 	off = mach->sb+i->simm13;
51874a4d8c2SCharles.Forsyth 	if(i->rs1 == 2	&& findsym(off, CANY, &s)
51974a4d8c2SCharles.Forsyth 			&& s.value-off < 4096
52074a4d8c2SCharles.Forsyth 			&& (s.class == CDATA || s.class == CTEXT)) {
52174a4d8c2SCharles.Forsyth 		if(off==s.value && s.name[0]=='$'){
52274a4d8c2SCharles.Forsyth 			off1 = 0;
523d67b7dadSforsyth 			geta(mymap, s.value, &off1);
52474a4d8c2SCharles.Forsyth 			if(off1 && findsym(off1, CANY, &s2) && s2.value == off1){
52574a4d8c2SCharles.Forsyth 				bprint(i, "$%s(SB)", s2.name);
52674a4d8c2SCharles.Forsyth 				return;
52774a4d8c2SCharles.Forsyth 			}
52874a4d8c2SCharles.Forsyth 		}
52974a4d8c2SCharles.Forsyth 		bprint(i, "%s", s.name);
53074a4d8c2SCharles.Forsyth 		if (s.value != off)
531d67b7dadSforsyth 			bprint(i, "+%llux", s.value-off);
53274a4d8c2SCharles.Forsyth 		bprint(i, "(SB)");
53374a4d8c2SCharles.Forsyth 		return;
53474a4d8c2SCharles.Forsyth 	}
535d67b7dadSforsyth 	bprint(i, "%ux(R%d)", i->simm13, i->rs1);
53674a4d8c2SCharles.Forsyth }
53774a4d8c2SCharles.Forsyth 
53874a4d8c2SCharles.Forsyth static void
unimp(Instr * i,char * m)53974a4d8c2SCharles.Forsyth unimp(Instr *i, char *m)
54074a4d8c2SCharles.Forsyth {
541d67b7dadSforsyth 	bprint(i, "%T", m);
54274a4d8c2SCharles.Forsyth }
54374a4d8c2SCharles.Forsyth 
54474a4d8c2SCharles.Forsyth static char	*bratab[16] = {	/* page 91 */
545773d7fd2Sforsyth 	"N",		/* 0x0 */
546773d7fd2Sforsyth 	"E",		/* 0x1 */
547773d7fd2Sforsyth 	"LE",		/* 0x2 */
548773d7fd2Sforsyth 	"L",		/* 0x3 */
549773d7fd2Sforsyth 	"LEU",		/* 0x4 */
550773d7fd2Sforsyth 	"CS",		/* 0x5 */
551773d7fd2Sforsyth 	"NEG",		/* 0x6 */
552773d7fd2Sforsyth 	"VS",		/* 0x7 */
553773d7fd2Sforsyth 	"A",		/* 0x8 */
554773d7fd2Sforsyth 	"NE",		/* 0x9 */
555773d7fd2Sforsyth 	"G",		/* 0xa */
556773d7fd2Sforsyth 	"GE",		/* 0xb */
557773d7fd2Sforsyth 	"GU",		/* 0xc */
558773d7fd2Sforsyth 	"CC",		/* 0xd */
559773d7fd2Sforsyth 	"POS",		/* 0xe */
560773d7fd2Sforsyth 	"VC",		/* 0xf */
56174a4d8c2SCharles.Forsyth };
56274a4d8c2SCharles.Forsyth 
56374a4d8c2SCharles.Forsyth static char	*fbratab[16] = {	/* page 91 */
564773d7fd2Sforsyth 	"N",		/* 0x0 */
565773d7fd2Sforsyth 	"NE",		/* 0x1 */
566773d7fd2Sforsyth 	"LG",		/* 0x2 */
567773d7fd2Sforsyth 	"UL",		/* 0x3 */
568773d7fd2Sforsyth 	"L",		/* 0x4 */
569773d7fd2Sforsyth 	"UG",		/* 0x5 */
570773d7fd2Sforsyth 	"G",		/* 0x6 */
571773d7fd2Sforsyth 	"U",		/* 0x7 */
572773d7fd2Sforsyth 	"A",		/* 0x8 */
573773d7fd2Sforsyth 	"E",		/* 0x9 */
574773d7fd2Sforsyth 	"UE",		/* 0xa */
575773d7fd2Sforsyth 	"GE",		/* 0xb */
576773d7fd2Sforsyth 	"UGE",		/* 0xc */
577773d7fd2Sforsyth 	"LE",		/* 0xd */
578773d7fd2Sforsyth 	"ULE",		/* 0xe */
579773d7fd2Sforsyth 	"O",		/* 0xf */
58074a4d8c2SCharles.Forsyth };
58174a4d8c2SCharles.Forsyth 
58274a4d8c2SCharles.Forsyth static char	*cbratab[16] = {	/* page 91 */
583773d7fd2Sforsyth 	"N",		/* 0x0 */
584773d7fd2Sforsyth 	"123",		/* 0x1 */
585773d7fd2Sforsyth 	"12",		/* 0x2 */
586773d7fd2Sforsyth 	"13",		/* 0x3 */
587773d7fd2Sforsyth 	"1",		/* 0x4 */
588773d7fd2Sforsyth 	"23",		/* 0x5 */
589773d7fd2Sforsyth 	"2",		/* 0x6 */
590773d7fd2Sforsyth 	"3",		/* 0x7 */
591773d7fd2Sforsyth 	"A",		/* 0x8 */
592773d7fd2Sforsyth 	"0",		/* 0x9 */
593773d7fd2Sforsyth 	"03",		/* 0xa */
594773d7fd2Sforsyth 	"02",		/* 0xb */
595773d7fd2Sforsyth 	"023",		/* 0xc */
596773d7fd2Sforsyth 	"01",		/* 0xd */
597773d7fd2Sforsyth 	"013",		/* 0xe */
598773d7fd2Sforsyth 	"012",		/* 0xf */
59974a4d8c2SCharles.Forsyth };
60074a4d8c2SCharles.Forsyth 
60174a4d8c2SCharles.Forsyth static void
bra1(Instr * i,char * m,char * tab[])60274a4d8c2SCharles.Forsyth bra1(Instr *i, char *m, char *tab[])
60374a4d8c2SCharles.Forsyth {
60474a4d8c2SCharles.Forsyth 	long imm;
60574a4d8c2SCharles.Forsyth 
60674a4d8c2SCharles.Forsyth 	imm = i->simmdisp22;
60774a4d8c2SCharles.Forsyth 	if(i->a)
608d67b7dadSforsyth 		bprint(i, "%T%T.%c\t", m, tab[i->cond], 'A'+dascase);
60974a4d8c2SCharles.Forsyth 	else
610d67b7dadSforsyth 		bprint(i, "%T%T\t", m, tab[i->cond]);
61174a4d8c2SCharles.Forsyth 	i->curr += symoff(i->curr, i->end-i->curr, i->addr+4*imm, CTEXT);
61274a4d8c2SCharles.Forsyth 	if (!dascase)
61374a4d8c2SCharles.Forsyth 		bprint(i, "(SB)");
61474a4d8c2SCharles.Forsyth }
61574a4d8c2SCharles.Forsyth 
61674a4d8c2SCharles.Forsyth static void
bra(Instr * i,char * m)61774a4d8c2SCharles.Forsyth bra(Instr *i, char *m)			/* page 91 */
61874a4d8c2SCharles.Forsyth {
61974a4d8c2SCharles.Forsyth 	bra1(i, m, bratab);
62074a4d8c2SCharles.Forsyth }
62174a4d8c2SCharles.Forsyth 
62274a4d8c2SCharles.Forsyth static void
fbra(Instr * i,char * m)62374a4d8c2SCharles.Forsyth fbra(Instr *i, char *m)			/* page 93 */
62474a4d8c2SCharles.Forsyth {
62574a4d8c2SCharles.Forsyth 	bra1(i, m, fbratab);
62674a4d8c2SCharles.Forsyth }
62774a4d8c2SCharles.Forsyth 
62874a4d8c2SCharles.Forsyth static void
cbra(Instr * i,char * m)62974a4d8c2SCharles.Forsyth cbra(Instr *i, char *m)			/* page 95 */
63074a4d8c2SCharles.Forsyth {
63174a4d8c2SCharles.Forsyth 	bra1(i, m, cbratab);
63274a4d8c2SCharles.Forsyth }
63374a4d8c2SCharles.Forsyth 
63474a4d8c2SCharles.Forsyth static void
trap(Instr * i,char * m)63574a4d8c2SCharles.Forsyth trap(Instr *i, char *m)			/* page 101 */
63674a4d8c2SCharles.Forsyth {
63774a4d8c2SCharles.Forsyth 	if(i->i == 0)
638d67b7dadSforsyth 		bprint(i, "%T%T\tR%d+R%d", m, bratab[i->cond], i->rs2, i->rs1);
63974a4d8c2SCharles.Forsyth 	else
640d67b7dadSforsyth 		bprint(i, "%T%T\t$%ux+R%d", m, bratab[i->cond], i->simm13, i->rs1);
64174a4d8c2SCharles.Forsyth }
64274a4d8c2SCharles.Forsyth 
64374a4d8c2SCharles.Forsyth static void
sethi(Instr * i,char * m)64474a4d8c2SCharles.Forsyth sethi(Instr *i, char *m)		/* page 89 */
64574a4d8c2SCharles.Forsyth {
64674a4d8c2SCharles.Forsyth 	ulong imm;
64774a4d8c2SCharles.Forsyth 
64874a4d8c2SCharles.Forsyth 	imm = i->immdisp22<<10;
64974a4d8c2SCharles.Forsyth 	if(dascase){
650d67b7dadSforsyth 		bprint(i, "%T\t%lux, R%d", m, imm, i->rd);
65174a4d8c2SCharles.Forsyth 		return;
65274a4d8c2SCharles.Forsyth 	}
65374a4d8c2SCharles.Forsyth 	if(imm==0 && i->rd==0){
65474a4d8c2SCharles.Forsyth 		bprint(i, "NOP");
65574a4d8c2SCharles.Forsyth 		return;
65674a4d8c2SCharles.Forsyth 	}
65774a4d8c2SCharles.Forsyth 	if(i->target < 0){
65874a4d8c2SCharles.Forsyth 		bprint(i, "MOVW\t$%lux, R%d", imm, i->rd);
65974a4d8c2SCharles.Forsyth 		return;
66074a4d8c2SCharles.Forsyth 	}
66174a4d8c2SCharles.Forsyth 	bprint(i, "MOVW\t$%lux, R%d", i->imm32, i->target);
66274a4d8c2SCharles.Forsyth }
66374a4d8c2SCharles.Forsyth 
66474a4d8c2SCharles.Forsyth static char ldtab[] = {
66574a4d8c2SCharles.Forsyth 	'W',
66674a4d8c2SCharles.Forsyth 	'B',
66774a4d8c2SCharles.Forsyth 	'H',
66874a4d8c2SCharles.Forsyth 	'D',
66974a4d8c2SCharles.Forsyth };
67074a4d8c2SCharles.Forsyth 
67174a4d8c2SCharles.Forsyth static char*
moveinstr(int op3,char * m)67274a4d8c2SCharles.Forsyth moveinstr(int op3, char *m)
67374a4d8c2SCharles.Forsyth {
67474a4d8c2SCharles.Forsyth 	char *s;
67574a4d8c2SCharles.Forsyth 	int c;
67674a4d8c2SCharles.Forsyth 	static char buf[8];
67774a4d8c2SCharles.Forsyth 
67874a4d8c2SCharles.Forsyth 	if(!dascase){
67974a4d8c2SCharles.Forsyth 		/* batshit cases */
68074a4d8c2SCharles.Forsyth 		if(op3 == 0xF || op3 == 0x1F)
68174a4d8c2SCharles.Forsyth 			return "SWAP";
68274a4d8c2SCharles.Forsyth 		if(op3 == 0xD || op3 == 0x1D)
68374a4d8c2SCharles.Forsyth 			return "TAS";	/* really LDSTUB */
68474a4d8c2SCharles.Forsyth 		c = ldtab[op3&3];
68574a4d8c2SCharles.Forsyth 		s = "";
68674a4d8c2SCharles.Forsyth 		if((op3&11)==1 || (op3&11)==2)
68774a4d8c2SCharles.Forsyth 			s="U";
68874a4d8c2SCharles.Forsyth 		sprint(buf, "MOV%c%s", c, s);
68974a4d8c2SCharles.Forsyth 		return buf;
69074a4d8c2SCharles.Forsyth 	}
69174a4d8c2SCharles.Forsyth 	return m;
69274a4d8c2SCharles.Forsyth }
69374a4d8c2SCharles.Forsyth 
69474a4d8c2SCharles.Forsyth static void
load(Instr * i,char * m)69574a4d8c2SCharles.Forsyth load(Instr *i, char *m)			/* page 68 */
69674a4d8c2SCharles.Forsyth {
69774a4d8c2SCharles.Forsyth 	m = moveinstr(i->op3, m);
69874a4d8c2SCharles.Forsyth 	if(i->i == 0)
69974a4d8c2SCharles.Forsyth 		bprint(i, "%s\t(R%d+R%d), R%d", m, i->rs1, i->rs2, i->rd);
70074a4d8c2SCharles.Forsyth 	else{
70174a4d8c2SCharles.Forsyth 		bprint(i, "%s\t", m);
70274a4d8c2SCharles.Forsyth 		address(i);
70374a4d8c2SCharles.Forsyth 		bprint(i, ", R%d", i->rd);
70474a4d8c2SCharles.Forsyth 	}
70574a4d8c2SCharles.Forsyth }
70674a4d8c2SCharles.Forsyth 
70774a4d8c2SCharles.Forsyth static void
loada(Instr * i,char * m)70874a4d8c2SCharles.Forsyth loada(Instr *i, char *m)		/* page 68 */
70974a4d8c2SCharles.Forsyth {
71074a4d8c2SCharles.Forsyth 	m = moveinstr(i->op3, m);
71174a4d8c2SCharles.Forsyth 	if(i->i == 0)
71274a4d8c2SCharles.Forsyth 		bprint(i, "%s\t(R%d+R%d, %d), R%d", m, i->rs1, i->rs2, i->asi, i->rd);
71374a4d8c2SCharles.Forsyth 	else
71474a4d8c2SCharles.Forsyth 		bprint(i, "unknown ld asi %lux", i->w0);
71574a4d8c2SCharles.Forsyth }
71674a4d8c2SCharles.Forsyth 
71774a4d8c2SCharles.Forsyth static void
store(Instr * i,char * m)71874a4d8c2SCharles.Forsyth store(Instr *i, char *m)		/* page 74 */
71974a4d8c2SCharles.Forsyth {
72074a4d8c2SCharles.Forsyth 	m = moveinstr(i->op3, m);
72174a4d8c2SCharles.Forsyth 	if(i->i == 0)
72274a4d8c2SCharles.Forsyth 		bprint(i, "%s\tR%d, (R%d+R%d)",
72374a4d8c2SCharles.Forsyth 				m, i->rd, i->rs1, i->rs2);
72474a4d8c2SCharles.Forsyth 	else{
72574a4d8c2SCharles.Forsyth 		bprint(i, "%s\tR%d, ", m, i->rd);
72674a4d8c2SCharles.Forsyth 		address(i);
72774a4d8c2SCharles.Forsyth 	}
72874a4d8c2SCharles.Forsyth }
72974a4d8c2SCharles.Forsyth 
73074a4d8c2SCharles.Forsyth static void
storea(Instr * i,char * m)73174a4d8c2SCharles.Forsyth storea(Instr *i, char *m)		/* page 74 */
73274a4d8c2SCharles.Forsyth {
73374a4d8c2SCharles.Forsyth 	m = moveinstr(i->op3, m);
73474a4d8c2SCharles.Forsyth 	if(i->i == 0)
73574a4d8c2SCharles.Forsyth 		bprint(i, "%s\tR%d, (R%d+R%d, %d)", m, i->rd, i->rs1, i->rs2, i->asi);
73674a4d8c2SCharles.Forsyth 	else
737*45a20ab7Sforsyth 		bprint(i, "%s\tR%d, %d(R%d, %d), ?", m, i->rd, i->simm13, i->rs1, i->asi);
73874a4d8c2SCharles.Forsyth }
73974a4d8c2SCharles.Forsyth 
74074a4d8c2SCharles.Forsyth static void
shift(Instr * i,char * m)74174a4d8c2SCharles.Forsyth shift(Instr *i, char *m)	/* page 88 */
74274a4d8c2SCharles.Forsyth {
74374a4d8c2SCharles.Forsyth 	if(i->i == 0){
74474a4d8c2SCharles.Forsyth 		if(i->rs1 == i->rd)
74574a4d8c2SCharles.Forsyth 			if(dascase)
746d67b7dadSforsyth 				bprint(i, "%T\tR%d, R%d", m, i->rs1, i->rs2);
74774a4d8c2SCharles.Forsyth 			else
748d67b7dadSforsyth 				bprint(i, "%T\tR%d, R%d", m, i->rs2, i->rs1);
74974a4d8c2SCharles.Forsyth 		else
75074a4d8c2SCharles.Forsyth 			if(dascase)
751d67b7dadSforsyth 				bprint(i, "%T\tR%d, R%d, R%d", m, i->rs1, i->rs2, i->rd);
75274a4d8c2SCharles.Forsyth 			else
753d67b7dadSforsyth 				bprint(i, "%T\tR%d, R%d, R%d", m, i->rs2, i->rs1, i->rd);
75474a4d8c2SCharles.Forsyth 	}else{
75574a4d8c2SCharles.Forsyth 		if(i->rs1 == i->rd)
75674a4d8c2SCharles.Forsyth 			if(dascase)
757d67b7dadSforsyth 				bprint(i, "%T\t$%d,R%d", m, i->simm13&0x1F, i->rs1);
75874a4d8c2SCharles.Forsyth 			else
759d67b7dadSforsyth 				bprint(i, "%T\tR%d, $%d", m,  i->rs1, i->simm13&0x1F);
76074a4d8c2SCharles.Forsyth 		else
76174a4d8c2SCharles.Forsyth 			if(dascase)
762d67b7dadSforsyth 				bprint(i, "%T\tR%d, $%d, R%d",m,i->rs1,i->simm13&0x1F,i->rd);
76374a4d8c2SCharles.Forsyth 			else
764d67b7dadSforsyth 				bprint(i, "%T\t$%d, R%d, R%d",m,i->simm13&0x1F,i->rs1,i->rd);
76574a4d8c2SCharles.Forsyth 	}
76674a4d8c2SCharles.Forsyth }
76774a4d8c2SCharles.Forsyth 
76874a4d8c2SCharles.Forsyth static void
add(Instr * i,char * m)76974a4d8c2SCharles.Forsyth add(Instr *i, char *m)	/* page 82 */
77074a4d8c2SCharles.Forsyth {
77174a4d8c2SCharles.Forsyth 	if(i->i == 0){
77274a4d8c2SCharles.Forsyth 		if(dascase)
773d67b7dadSforsyth 			bprint(i, "%T\tR%d, R%d", m, i->rs1, i->rs2);
77474a4d8c2SCharles.Forsyth 		else
77574a4d8c2SCharles.Forsyth 			if(i->op3==2 && i->rs1==0 && i->rd)  /* OR R2, R0, R1 */
77674a4d8c2SCharles.Forsyth 				bprint(i, "MOVW\tR%d", i->rs2);
77774a4d8c2SCharles.Forsyth 			else
778d67b7dadSforsyth 				bprint(i, "%T\tR%d, R%d", m, i->rs2, i->rs1);
77974a4d8c2SCharles.Forsyth 	}else{
78074a4d8c2SCharles.Forsyth 		if(dascase)
781d67b7dadSforsyth 			bprint(i, "%T\tR%d, $%ux", m, i->rs1, i->simm13);
78274a4d8c2SCharles.Forsyth 		else
78374a4d8c2SCharles.Forsyth 			if(i->op3==0 && i->rd && i->rs1==0)	/* ADD $x, R0, R1 */
784d67b7dadSforsyth 				bprint(i, "MOVW\t$%ux", i->simm13);
78574a4d8c2SCharles.Forsyth 			else if(i->op3==0 && i->rd && i->rs1==2){
78674a4d8c2SCharles.Forsyth 				/* ADD $x, R2, R1 -> MOVW $x(SB), R1 */
78774a4d8c2SCharles.Forsyth 				bprint(i, "MOVW\t$");
78874a4d8c2SCharles.Forsyth 				address(i);
78974a4d8c2SCharles.Forsyth 			} else
790d67b7dadSforsyth 				bprint(i, "%T\t$%ux, R%d", m, i->simm13, i->rs1);
79174a4d8c2SCharles.Forsyth 	}
79274a4d8c2SCharles.Forsyth 	if(i->rs1 != i->rd)
79374a4d8c2SCharles.Forsyth 		bprint(i, ", R%d", i->rd);
79474a4d8c2SCharles.Forsyth }
79574a4d8c2SCharles.Forsyth 
79674a4d8c2SCharles.Forsyth static void
cmp(Instr * i,char * m)79774a4d8c2SCharles.Forsyth cmp(Instr *i, char *m)
79874a4d8c2SCharles.Forsyth {
79974a4d8c2SCharles.Forsyth 	if(dascase || i->rd){
80074a4d8c2SCharles.Forsyth 		add(i, m);
80174a4d8c2SCharles.Forsyth 		return;
80274a4d8c2SCharles.Forsyth 	}
80374a4d8c2SCharles.Forsyth 	if(i->i == 0)
80474a4d8c2SCharles.Forsyth 		bprint(i, "CMP\tR%d, R%d", i->rs1, i->rs2);
80574a4d8c2SCharles.Forsyth 	else
806d67b7dadSforsyth 		bprint(i, "CMP\tR%d, $%ux", i->rs1, i->simm13);
80774a4d8c2SCharles.Forsyth }
80874a4d8c2SCharles.Forsyth 
80974a4d8c2SCharles.Forsyth static char *regtab[4] = {
81074a4d8c2SCharles.Forsyth 	"Y",
81174a4d8c2SCharles.Forsyth 	"PSR",
81274a4d8c2SCharles.Forsyth 	"WIM",
81374a4d8c2SCharles.Forsyth 	"TBR",
81474a4d8c2SCharles.Forsyth };
81574a4d8c2SCharles.Forsyth 
81674a4d8c2SCharles.Forsyth static void
wr(Instr * i,char * m)81774a4d8c2SCharles.Forsyth wr(Instr *i, char *m)		/* page 82 */
81874a4d8c2SCharles.Forsyth {
81974a4d8c2SCharles.Forsyth 	if(dascase){
82074a4d8c2SCharles.Forsyth 		if(i->i == 0)
82174a4d8c2SCharles.Forsyth 			bprint(i, "%s\tR%d, R%d", m, i->rs1, i->rs2);
82274a4d8c2SCharles.Forsyth 		else
823d67b7dadSforsyth 			bprint(i, "%s\tR%d, $%ux", m, i->rs1, i->simm13);
82474a4d8c2SCharles.Forsyth 	}else{
82574a4d8c2SCharles.Forsyth 		if(i->i && i->simm13==0)
82674a4d8c2SCharles.Forsyth 			bprint(i, "MOVW\tR%d", i->rs1);
82774a4d8c2SCharles.Forsyth 		else if(i->i == 0)
82874a4d8c2SCharles.Forsyth 			bprint(i, "wr\tR%d, R%d", i->rs2, i->rs1);
82974a4d8c2SCharles.Forsyth 		else
830d67b7dadSforsyth 			bprint(i, "wr\t$%ux, R%d", i->simm13, i->rs1);
83174a4d8c2SCharles.Forsyth 	}
83274a4d8c2SCharles.Forsyth 	bprint(i, ", %s", regtab[i->op3&3]);
83374a4d8c2SCharles.Forsyth }
83474a4d8c2SCharles.Forsyth 
83574a4d8c2SCharles.Forsyth static void
rd(Instr * i,char * m)83674a4d8c2SCharles.Forsyth rd(Instr *i, char *m)		/* page 103 */
83774a4d8c2SCharles.Forsyth {
83874a4d8c2SCharles.Forsyth 	if(i->rs1==15 && i->rd==0){
83974a4d8c2SCharles.Forsyth 		m = "stbar";
84074a4d8c2SCharles.Forsyth 		if(!dascase)
84174a4d8c2SCharles.Forsyth 			m = "STBAR";
84274a4d8c2SCharles.Forsyth 		bprint(i, "%s", m);
84374a4d8c2SCharles.Forsyth 	}else{
84474a4d8c2SCharles.Forsyth 		if(!dascase)
84574a4d8c2SCharles.Forsyth 			m = "MOVW";
84674a4d8c2SCharles.Forsyth 		bprint(i, "%s\t%s, R%d", m, regtab[i->op3&3], i->rd);
84774a4d8c2SCharles.Forsyth 	}
84874a4d8c2SCharles.Forsyth }
84974a4d8c2SCharles.Forsyth 
85074a4d8c2SCharles.Forsyth static void
jmpl(Instr * i,char * m)85174a4d8c2SCharles.Forsyth jmpl(Instr *i, char *m)		/* page 82 */
85274a4d8c2SCharles.Forsyth {
85374a4d8c2SCharles.Forsyth 	if(i->i == 0){
85474a4d8c2SCharles.Forsyth 		if(i->rd == 15)
855d67b7dadSforsyth 			bprint(i, "%T\t(R%d+R%d)", "CALL", i->rs2, i->rs1);
85674a4d8c2SCharles.Forsyth 		else
857d67b7dadSforsyth 			bprint(i, "%T\t(R%d+R%d), R%d", m, i->rs2, i->rs1, i->rd);
85874a4d8c2SCharles.Forsyth 	}else{
85974a4d8c2SCharles.Forsyth 		if(!dascase && i->simm13==8 && i->rs1==15 && i->rd==0)
86074a4d8c2SCharles.Forsyth 			bprint(i, "RETURN");
86174a4d8c2SCharles.Forsyth 		else{
862d67b7dadSforsyth 			bprint(i, "%T\t", m);
86374a4d8c2SCharles.Forsyth 			address(i);
86474a4d8c2SCharles.Forsyth 			bprint(i, ", R%d", i->rd);
86574a4d8c2SCharles.Forsyth 		}
86674a4d8c2SCharles.Forsyth 	}
86774a4d8c2SCharles.Forsyth }
86874a4d8c2SCharles.Forsyth 
86974a4d8c2SCharles.Forsyth static void
loadf(Instr * i,char * m)87074a4d8c2SCharles.Forsyth loadf(Instr *i, char *m)		/* page 70 */
87174a4d8c2SCharles.Forsyth {
87274a4d8c2SCharles.Forsyth 	if(!dascase){
87374a4d8c2SCharles.Forsyth 		m = "FMOVD";
87474a4d8c2SCharles.Forsyth 		if(i->op3 == 0x20)
87574a4d8c2SCharles.Forsyth 			m = "FMOVF";
87674a4d8c2SCharles.Forsyth 		else if(i->op3 == 0x21)
87774a4d8c2SCharles.Forsyth 			m = "MOVW";
87874a4d8c2SCharles.Forsyth 	}
87974a4d8c2SCharles.Forsyth 	if(i->i == 0)
88074a4d8c2SCharles.Forsyth 		bprint(i, "%s\t(R%d+R%d)", m, i->rs1, i->rs2);
88174a4d8c2SCharles.Forsyth 	else{
88274a4d8c2SCharles.Forsyth 		bprint(i, "%s\t", m);
88374a4d8c2SCharles.Forsyth 		address(i);
88474a4d8c2SCharles.Forsyth 	}
88574a4d8c2SCharles.Forsyth 	if(i->op3 == 0x21)
88674a4d8c2SCharles.Forsyth 		bprint(i, ", FSR");
88774a4d8c2SCharles.Forsyth 	else
88874a4d8c2SCharles.Forsyth 		bprint(i, ", R%d", i->rd);
88974a4d8c2SCharles.Forsyth }
89074a4d8c2SCharles.Forsyth 
891d67b7dadSforsyth static void
storef(Instr * i,char * m)892d67b7dadSforsyth storef(Instr *i, char *m)		/* page 70 */
89374a4d8c2SCharles.Forsyth {
89474a4d8c2SCharles.Forsyth 	if(!dascase){
89574a4d8c2SCharles.Forsyth 		m = "FMOVD";
89674a4d8c2SCharles.Forsyth 		if(i->op3 == 0x25 || i->op3 == 0x26)
89774a4d8c2SCharles.Forsyth 			m = "MOVW";
89874a4d8c2SCharles.Forsyth 		else if(i->op3 == 0x20)
89974a4d8c2SCharles.Forsyth 			m = "FMOVF";
90074a4d8c2SCharles.Forsyth 	}
90174a4d8c2SCharles.Forsyth 	bprint(i, "%s\t", m);
90274a4d8c2SCharles.Forsyth 	if(i->op3 == 0x25)
90374a4d8c2SCharles.Forsyth 		bprint(i, "FSR, ");
90474a4d8c2SCharles.Forsyth 	else if(i->op3 == 0x26)
90574a4d8c2SCharles.Forsyth 		bprint(i, "FQ, ");
90674a4d8c2SCharles.Forsyth 	else
90774a4d8c2SCharles.Forsyth 		bprint(i, "R%d, ", i->rd);
90874a4d8c2SCharles.Forsyth 	if(i->i == 0)
90974a4d8c2SCharles.Forsyth 		bprint(i, "(R%d+R%d)", i->rs1, i->rs2);
91074a4d8c2SCharles.Forsyth 	else
91174a4d8c2SCharles.Forsyth 		address(i);
91274a4d8c2SCharles.Forsyth }
91374a4d8c2SCharles.Forsyth 
914d67b7dadSforsyth static void
loadc(Instr * i,char * m)915d67b7dadSforsyth loadc(Instr *i, char *m)			/* page 72 */
91674a4d8c2SCharles.Forsyth {
91774a4d8c2SCharles.Forsyth 	if(i->i == 0)
91874a4d8c2SCharles.Forsyth 		bprint(i, "%s\t(R%d+R%d), C%d", m, i->rs1, i->rs2, i->rd);
91974a4d8c2SCharles.Forsyth 	else{
92074a4d8c2SCharles.Forsyth 		bprint(i, "%s\t", m);
92174a4d8c2SCharles.Forsyth 		address(i);
92274a4d8c2SCharles.Forsyth 		bprint(i, ", C%d", i->rd);
92374a4d8c2SCharles.Forsyth 	}
92474a4d8c2SCharles.Forsyth }
92574a4d8c2SCharles.Forsyth 
926d67b7dadSforsyth static void
loadcsr(Instr * i,char * m)927d67b7dadSforsyth loadcsr(Instr *i, char *m)			/* page 72 */
92874a4d8c2SCharles.Forsyth {
92974a4d8c2SCharles.Forsyth 	if(i->i == 0)
93074a4d8c2SCharles.Forsyth 		bprint(i, "%s\t(R%d+R%d), CSR", m, i->rs1, i->rs2);
93174a4d8c2SCharles.Forsyth 	else{
93274a4d8c2SCharles.Forsyth 		bprint(i, "%s\t", m);
93374a4d8c2SCharles.Forsyth 		address(i);
93474a4d8c2SCharles.Forsyth 		bprint(i, ", CSR");
93574a4d8c2SCharles.Forsyth 	}
93674a4d8c2SCharles.Forsyth }
93774a4d8c2SCharles.Forsyth 
93874a4d8c2SCharles.Forsyth static struct{
93974a4d8c2SCharles.Forsyth 	int	opf;
94074a4d8c2SCharles.Forsyth 	char	*name;
94174a4d8c2SCharles.Forsyth } fptab1[] = {			/* ignores rs1 */
94274a4d8c2SCharles.Forsyth 	0xC4,	"FITOS",	/* page 109 */
94374a4d8c2SCharles.Forsyth 	0xC8,	"FITOD",
94474a4d8c2SCharles.Forsyth 	0xCC,	"FITOX",
94574a4d8c2SCharles.Forsyth 
94674a4d8c2SCharles.Forsyth 	0xD1,	"FSTOI",	/* page 110 */
94774a4d8c2SCharles.Forsyth 	0xD2,	"FDTOI",
94874a4d8c2SCharles.Forsyth 	0xD3,	"FXTOI",
94974a4d8c2SCharles.Forsyth 
95074a4d8c2SCharles.Forsyth 	0xC9,	"FSTOD",	/* page 111 */
95174a4d8c2SCharles.Forsyth 	0xCD,	"FSTOX",
95274a4d8c2SCharles.Forsyth 	0xC6,	"FDTOS",
95374a4d8c2SCharles.Forsyth 	0xCE,	"FDTOX",
95474a4d8c2SCharles.Forsyth 	0xC7,	"FXTOS",
95574a4d8c2SCharles.Forsyth 	0xCB,	"FXTOD",
95674a4d8c2SCharles.Forsyth 
95774a4d8c2SCharles.Forsyth 	0x01,	"FMOVS",	/* page 112 */
95874a4d8c2SCharles.Forsyth 	0x05,	"FNEGS",
95974a4d8c2SCharles.Forsyth 	0x09,	"FABSS",
96074a4d8c2SCharles.Forsyth 
96174a4d8c2SCharles.Forsyth 	0x29,	"FSQRTS", 	/* page 113 */
96274a4d8c2SCharles.Forsyth 	0x2A,	"FSQRTD",
96374a4d8c2SCharles.Forsyth 	0x2B,	"FSQRTX",
96474a4d8c2SCharles.Forsyth 
96574a4d8c2SCharles.Forsyth 	0,	0,
96674a4d8c2SCharles.Forsyth };
96774a4d8c2SCharles.Forsyth 
96874a4d8c2SCharles.Forsyth static struct{
96974a4d8c2SCharles.Forsyth 	int	opf;
97074a4d8c2SCharles.Forsyth 	char	*name;
97174a4d8c2SCharles.Forsyth } fptab2[] = {			/* uses rs1 */
97274a4d8c2SCharles.Forsyth 
97374a4d8c2SCharles.Forsyth 	0x41,	"FADDS",	/* page 114 */
97474a4d8c2SCharles.Forsyth 	0x42,	"FADDD",
97574a4d8c2SCharles.Forsyth 	0x43,	"FADDX",
97674a4d8c2SCharles.Forsyth 	0x45,	"FSUBS",
97774a4d8c2SCharles.Forsyth 	0x46,	"FSUBD",
97874a4d8c2SCharles.Forsyth 	0x47,	"FSUBX",
97974a4d8c2SCharles.Forsyth 
98074a4d8c2SCharles.Forsyth 	0x49,	"FMULS",	/* page 115 */
98174a4d8c2SCharles.Forsyth 	0x4A,	"FMULD",
98274a4d8c2SCharles.Forsyth 	0x4B,	"FMULX",
98374a4d8c2SCharles.Forsyth 	0x4D,	"FDIVS",
98474a4d8c2SCharles.Forsyth 	0x4E,	"FDIVD",
98574a4d8c2SCharles.Forsyth 	0x4F,	"FDIVX",
98674a4d8c2SCharles.Forsyth 
98774a4d8c2SCharles.Forsyth 	0x51,	"FCMPS",	/* page 116 */
98874a4d8c2SCharles.Forsyth 	0x52,	"FCMPD",
98974a4d8c2SCharles.Forsyth 	0x53,	"FCMPX",
99074a4d8c2SCharles.Forsyth 	0x55,	"FCMPES",
99174a4d8c2SCharles.Forsyth 	0x56,	"FCMPED",
99274a4d8c2SCharles.Forsyth 	0x57,	"FCMPEX",
99374a4d8c2SCharles.Forsyth 
99474a4d8c2SCharles.Forsyth 	0, 0
99574a4d8c2SCharles.Forsyth };
99674a4d8c2SCharles.Forsyth 
99774a4d8c2SCharles.Forsyth static void
fpop(Instr * i,char * m)99874a4d8c2SCharles.Forsyth fpop(Instr *i, char *m)	/* page 108-116 */
99974a4d8c2SCharles.Forsyth {
100074a4d8c2SCharles.Forsyth 	int j;
100174a4d8c2SCharles.Forsyth 
100274a4d8c2SCharles.Forsyth 	if(dascase==0 && i->size==2){
100374a4d8c2SCharles.Forsyth 		bprint(i, "FMOVD\tF%d, F%d", i->rs2, i->rd);
100474a4d8c2SCharles.Forsyth 		return;
100574a4d8c2SCharles.Forsyth 	}
100674a4d8c2SCharles.Forsyth 	for(j=0; fptab1[j].name; j++)
100774a4d8c2SCharles.Forsyth 		if(fptab1[j].opf == i->opf){
1008d67b7dadSforsyth 			bprint(i, "%T\tF%d, F%d", fptab1[j].name, i->rs2, i->rd);
100974a4d8c2SCharles.Forsyth 			return;
101074a4d8c2SCharles.Forsyth 		}
101174a4d8c2SCharles.Forsyth 	for(j=0; fptab2[j].name; j++)
101274a4d8c2SCharles.Forsyth 		if(fptab2[j].opf == i->opf){
1013d67b7dadSforsyth 			bprint(i, "%T\tF%d, F%d, F%d", fptab2[j].name, i->rs1, i->rs2, i->rd);
101474a4d8c2SCharles.Forsyth 			return;
101574a4d8c2SCharles.Forsyth 		}
1016d67b7dadSforsyth 	bprint(i, "%T%ux\tF%d, F%d, F%d", m, i->opf, i->rs1, i->rs2, i->rd);
101774a4d8c2SCharles.Forsyth }
101874a4d8c2SCharles.Forsyth 
101974a4d8c2SCharles.Forsyth static int
sparcfoll(Map * map,uvlong pc,Rgetter rget,uvlong * foll)1020d67b7dadSforsyth sparcfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
102174a4d8c2SCharles.Forsyth {
102274a4d8c2SCharles.Forsyth 	ulong w, r1, r2;
102374a4d8c2SCharles.Forsyth 	char buf[8];
102474a4d8c2SCharles.Forsyth 	Instr i;
102574a4d8c2SCharles.Forsyth 
102674a4d8c2SCharles.Forsyth 	mymap = map;
102774a4d8c2SCharles.Forsyth 	if (mkinstr(pc, &i) < 0)
102874a4d8c2SCharles.Forsyth 		return -1;
102974a4d8c2SCharles.Forsyth 	w = i.w0;
103074a4d8c2SCharles.Forsyth 	switch(w & 0xC1C00000){
103174a4d8c2SCharles.Forsyth 	case 0x00800000:		/* branch on int cond */
103274a4d8c2SCharles.Forsyth 	case 0x01800000:		/* branch on fp cond */
103374a4d8c2SCharles.Forsyth 	case 0x01C00000:		/* branch on copr cond */
103474a4d8c2SCharles.Forsyth 		foll[0] = pc+8;
103574a4d8c2SCharles.Forsyth 		foll[1] = pc + (i.simmdisp22<<2);
103674a4d8c2SCharles.Forsyth 		return 2;
103774a4d8c2SCharles.Forsyth 	}
103874a4d8c2SCharles.Forsyth 
103974a4d8c2SCharles.Forsyth 	if((w&0xC0000000) == 0x40000000){	/* CALL */
104074a4d8c2SCharles.Forsyth 		foll[0] = pc + (i.disp30<<2);
104174a4d8c2SCharles.Forsyth 		return 1;
104274a4d8c2SCharles.Forsyth 	}
104374a4d8c2SCharles.Forsyth 
104474a4d8c2SCharles.Forsyth 	if((w&0xC1F80000) == 0x81C00000){	/* JMPL */
104574a4d8c2SCharles.Forsyth 		sprint(buf, "R%ld", (w>>14)&0xF);
104674a4d8c2SCharles.Forsyth 		r1 = (*rget)(map, buf);
104774a4d8c2SCharles.Forsyth 		if(w & 0x2000)			/* JMPL R1+simm13 */
104874a4d8c2SCharles.Forsyth 			r2 = i.simm13;
104974a4d8c2SCharles.Forsyth 		else{				/* JMPL R1+R2 */
105074a4d8c2SCharles.Forsyth 			sprint(buf, "R%ld", w&0xF);
105174a4d8c2SCharles.Forsyth 			r2 = (*rget)(map, buf);
105274a4d8c2SCharles.Forsyth 		}
105374a4d8c2SCharles.Forsyth 		foll[0] = r1 + r2;
105474a4d8c2SCharles.Forsyth 		return 1;
105574a4d8c2SCharles.Forsyth 	}
105674a4d8c2SCharles.Forsyth 	foll[0] = pc+i.size*4;
105774a4d8c2SCharles.Forsyth 	return 1;
105874a4d8c2SCharles.Forsyth }
1059