xref: /plan9/sys/src/libmach/sparc64db.c (revision 473d4f4b3fed09ca133e03643ec71c9150b33bcc)
1*473d4f4bSDavid du Colombier #include <u.h>
2*473d4f4bSDavid du Colombier #include <libc.h>
3*473d4f4bSDavid du Colombier #include <bio.h>
4*473d4f4bSDavid du Colombier #include <mach.h>
5*473d4f4bSDavid du Colombier 
6*473d4f4bSDavid du Colombier /*
7*473d4f4bSDavid du Colombier  * Sparc64-specific debugger interface
8*473d4f4bSDavid du Colombier  */
9*473d4f4bSDavid du Colombier 
10*473d4f4bSDavid du Colombier static	char	*sparc64excep(Map*, Rgetter);
11*473d4f4bSDavid du Colombier static	int	sparc64foll(Map*, uvlong, Rgetter, uvlong*);
12*473d4f4bSDavid du Colombier static	int	sparc64inst(Map*, uvlong, char, char*, int);
13*473d4f4bSDavid du Colombier static	int	sparc64das(Map*, uvlong, char*, int);
14*473d4f4bSDavid du Colombier static	int	sparc64instlen(Map*, uvlong);
15*473d4f4bSDavid du Colombier 
16*473d4f4bSDavid du Colombier Machdata sparc64mach =
17*473d4f4bSDavid du Colombier {
18*473d4f4bSDavid du Colombier 	{0x91, 0xd0, 0x20, 0x01},	/* breakpoint: TA $1 */
19*473d4f4bSDavid du Colombier 	4,			/* break point size */
20*473d4f4bSDavid du Colombier 
21*473d4f4bSDavid du Colombier 	beswab,			/* convert short to local byte order */
22*473d4f4bSDavid du Colombier 	beswal,			/* convert long to local byte order */
23*473d4f4bSDavid du Colombier 	beswav,			/* convert vlong to local byte order */
24*473d4f4bSDavid du Colombier 	risctrace,		/* C traceback */
25*473d4f4bSDavid du Colombier 	riscframe,		/* frame finder */
26*473d4f4bSDavid du Colombier 	sparc64excep,		/* print exception */
27*473d4f4bSDavid du Colombier 	0,			/* breakpoint fixup */
28*473d4f4bSDavid du Colombier 	beieeesftos,		/* single precision float printer */
29*473d4f4bSDavid du Colombier 	beieeedftos,		/* double precision float printer */
30*473d4f4bSDavid du Colombier 	sparc64foll,		/* following addresses */
31*473d4f4bSDavid du Colombier 	sparc64inst,		/* print instruction */
32*473d4f4bSDavid du Colombier 	sparc64das,		/* dissembler */
33*473d4f4bSDavid du Colombier 	sparc64instlen,		/* instruction size */
34*473d4f4bSDavid du Colombier };
35*473d4f4bSDavid du Colombier 
36*473d4f4bSDavid du Colombier static char *trapname[] =
37*473d4f4bSDavid du Colombier {
38*473d4f4bSDavid du Colombier 	0,
39*473d4f4bSDavid du Colombier 	"power on reset",
40*473d4f4bSDavid du Colombier 	"watchdog reset",
41*473d4f4bSDavid du Colombier 	"external reset",
42*473d4f4bSDavid du Colombier 	"software reset",
43*473d4f4bSDavid du Colombier 	"RED",
44*473d4f4bSDavid du Colombier 	0, 0,
45*473d4f4bSDavid du Colombier 	"instruction access exception",
46*473d4f4bSDavid du Colombier 	"instruction access MMU miss",
47*473d4f4bSDavid du Colombier 	"instruction access error",
48*473d4f4bSDavid du Colombier 	0, 0, 0, 0, 0,
49*473d4f4bSDavid du Colombier 	"illegal instruction",
50*473d4f4bSDavid du Colombier 	"privileged opcode",
51*473d4f4bSDavid du Colombier 	"unimplemented LDD",
52*473d4f4bSDavid du Colombier 	"unimplemented STD",
53*473d4f4bSDavid du Colombier 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
54*473d4f4bSDavid du Colombier 	"fp disabled",
55*473d4f4bSDavid du Colombier 	"fp exception ieee 754",
56*473d4f4bSDavid du Colombier 	"fp exception other",
57*473d4f4bSDavid du Colombier 	0, 0, 0, 0,
58*473d4f4bSDavid du Colombier 	"division by zero",
59*473d4f4bSDavid du Colombier 	"internal processor error",
60*473d4f4bSDavid du Colombier 	0, 0, 0, 0, 0, 0,
61*473d4f4bSDavid du Colombier 	"data access exception",
62*473d4f4bSDavid du Colombier 	"data access MMU miss",
63*473d4f4bSDavid du Colombier 	"data access error",
64*473d4f4bSDavid du Colombier 	"data access protection",
65*473d4f4bSDavid du Colombier 	"mem address not aligned",
66*473d4f4bSDavid du Colombier 	"LDDF mem address not aligned",
67*473d4f4bSDavid du Colombier 	"STDF mem address not aligned",
68*473d4f4bSDavid du Colombier 	"privileged action",
69*473d4f4bSDavid du Colombier 	"LDQF mem address nto aligned",
70*473d4f4bSDavid du Colombier 	"STQF mem address not aligned",
71*473d4f4bSDavid du Colombier };
72*473d4f4bSDavid du Colombier 
73*473d4f4bSDavid du Colombier static char*
excname(ulong tt)74*473d4f4bSDavid du Colombier excname(ulong tt)
75*473d4f4bSDavid du Colombier {
76*473d4f4bSDavid du Colombier 	static char buf[32];
77*473d4f4bSDavid du Colombier 
78*473d4f4bSDavid du Colombier 	if(tt < sizeof trapname/sizeof(char*) && trapname[tt])
79*473d4f4bSDavid du Colombier 		return trapname[tt];
80*473d4f4bSDavid du Colombier 	if(tt >= 258)
81*473d4f4bSDavid du Colombier 		sprint(buf, "trap instruction %ld", tt-128);
82*473d4f4bSDavid du Colombier 	else if(65<=tt && tt<=79)
83*473d4f4bSDavid du Colombier 		sprint(buf, "interrupt level %ld", tt-64);
84*473d4f4bSDavid du Colombier 	else switch(tt){
85*473d4f4bSDavid du Colombier 	case 64:
86*473d4f4bSDavid du Colombier 		return "async data error";
87*473d4f4bSDavid du Colombier 	case 96:
88*473d4f4bSDavid du Colombier 		return "mondo interrupt";
89*473d4f4bSDavid du Colombier 	case 100:
90*473d4f4bSDavid du Colombier 		return "instruction access MMU miss";
91*473d4f4bSDavid du Colombier 	case 104:
92*473d4f4bSDavid du Colombier 		return "data access MMU miss";
93*473d4f4bSDavid du Colombier 	case 108:
94*473d4f4bSDavid du Colombier 		return "data access protection";
95*473d4f4bSDavid du Colombier 	case 256:
96*473d4f4bSDavid du Colombier 		return "syscall";
97*473d4f4bSDavid du Colombier 	case 257:
98*473d4f4bSDavid du Colombier 		return "breakpoint";
99*473d4f4bSDavid du Colombier 	default:
100*473d4f4bSDavid du Colombier 		sprint(buf, "unknown trap %ld", tt);
101*473d4f4bSDavid du Colombier 	}
102*473d4f4bSDavid du Colombier 	return buf;
103*473d4f4bSDavid du Colombier }
104*473d4f4bSDavid du Colombier 
105*473d4f4bSDavid du Colombier static char*
sparc64excep(Map * map,Rgetter rget)106*473d4f4bSDavid du Colombier sparc64excep(Map *map, Rgetter rget)
107*473d4f4bSDavid du Colombier {
108*473d4f4bSDavid du Colombier 	long tt;
109*473d4f4bSDavid du Colombier 
110*473d4f4bSDavid du Colombier 	tt = (*rget)(map, "TT");
111*473d4f4bSDavid du Colombier 	return excname(tt);
112*473d4f4bSDavid du Colombier }
113*473d4f4bSDavid du Colombier 
114*473d4f4bSDavid du Colombier 	/* Sparc disassembler and related functions */
115*473d4f4bSDavid du Colombier 
116*473d4f4bSDavid du Colombier struct opcode {
117*473d4f4bSDavid du Colombier 	char	*mnemonic;
118*473d4f4bSDavid du Colombier 	void	(*f)(struct instr*, char*);
119*473d4f4bSDavid du Colombier 	int	flag;
120*473d4f4bSDavid du Colombier };
121*473d4f4bSDavid du Colombier 
122*473d4f4bSDavid du Colombier static	char FRAMENAME[] = ".frame";
123*473d4f4bSDavid du Colombier 
124*473d4f4bSDavid du Colombier typedef struct instr Instr;
125*473d4f4bSDavid du Colombier 
126*473d4f4bSDavid du Colombier struct instr {
127*473d4f4bSDavid du Colombier 	uchar	op;		/* bits 31-30 */
128*473d4f4bSDavid du Colombier 	uchar	rd;		/* bits 29-25 */
129*473d4f4bSDavid du Colombier 	uchar	op2;		/* bits 24-22 */
130*473d4f4bSDavid du Colombier 	uchar	a;		/* bit  29    */
131*473d4f4bSDavid du Colombier 	uchar	cond;		/* bits 28-25 */
132*473d4f4bSDavid du Colombier 	uchar	op3;		/* bits 24-19 */
133*473d4f4bSDavid du Colombier 	uchar	rs1;		/* bits 18-14 */
134*473d4f4bSDavid du Colombier 	uchar	i;		/* bit  13    */
135*473d4f4bSDavid du Colombier 	uchar	asi;		/* bits 12-05 */
136*473d4f4bSDavid du Colombier 	uchar	rs2;		/* bits 04-00 */
137*473d4f4bSDavid du Colombier 	short	simm13;		/* bits 12-00, signed */
138*473d4f4bSDavid du Colombier 	ushort	opf;		/* bits 13-05 */
139*473d4f4bSDavid du Colombier 	ulong	immdisp22;	/* bits 21-00 */
140*473d4f4bSDavid du Colombier 	ulong	simmdisp22;	/* bits 21-00, signed */
141*473d4f4bSDavid du Colombier 	ulong	disp30;		/* bits 30-00 */
142*473d4f4bSDavid du Colombier 	ulong	imm32;		/* SETHI+ADD constant */
143*473d4f4bSDavid du Colombier 	int	target;		/* SETHI+ADD dest reg */
144*473d4f4bSDavid du Colombier 	long	w0;
145*473d4f4bSDavid du Colombier 	long	w1;
146*473d4f4bSDavid du Colombier 	uvlong	addr;		/* pc of instruction */
147*473d4f4bSDavid du Colombier 	char	*curr;		/* current fill level in output buffer */
148*473d4f4bSDavid du Colombier 	char	*end;		/* end of buffer */
149*473d4f4bSDavid du Colombier 	int 	size;		/* number of longs in instr */
150*473d4f4bSDavid du Colombier 	char	*err;		/* errmsg */
151*473d4f4bSDavid du Colombier };
152*473d4f4bSDavid du Colombier 
153*473d4f4bSDavid du Colombier static	Map	*mymap;		/* disassembler context */
154*473d4f4bSDavid du Colombier static	int	dascase;
155*473d4f4bSDavid du Colombier 
156*473d4f4bSDavid du Colombier static int	mkinstr(uvlong, Instr*);
157*473d4f4bSDavid du Colombier static void	bra1(Instr*, char*, char*[]);
158*473d4f4bSDavid du Colombier static void	bra(Instr*, char*);
159*473d4f4bSDavid du Colombier static void	fbra(Instr*, char*);
160*473d4f4bSDavid du Colombier static void	cbra(Instr*, char*);
161*473d4f4bSDavid du Colombier static void	unimp(Instr*, char*);
162*473d4f4bSDavid du Colombier static void	fpop(Instr*, char*);
163*473d4f4bSDavid du Colombier static void	shift(Instr*, char*);
164*473d4f4bSDavid du Colombier static void	sethi(Instr*, char*);
165*473d4f4bSDavid du Colombier static void	load(Instr*, char*);
166*473d4f4bSDavid du Colombier static void	loada(Instr*, char*);
167*473d4f4bSDavid du Colombier static void	store(Instr*, char*);
168*473d4f4bSDavid du Colombier static void	storea(Instr*, char*);
169*473d4f4bSDavid du Colombier static void	add(Instr*, char*);
170*473d4f4bSDavid du Colombier static void	cmp(Instr*, char*);
171*473d4f4bSDavid du Colombier static void	wr(Instr*, char*);
172*473d4f4bSDavid du Colombier static void	jmpl(Instr*, char*);
173*473d4f4bSDavid du Colombier static void	rd(Instr*, char*);
174*473d4f4bSDavid du Colombier static void	loadf(Instr*, char*);
175*473d4f4bSDavid du Colombier static void	storef(Instr*, char*);
176*473d4f4bSDavid du Colombier static void	loadc(Instr*, char*);
177*473d4f4bSDavid du Colombier static void	loadcsr(Instr*, char*);
178*473d4f4bSDavid du Colombier static void	trap(Instr*, char*);
179*473d4f4bSDavid du Colombier 
180*473d4f4bSDavid du Colombier static struct opcode sparc64op0[8] = {
181*473d4f4bSDavid du Colombier 	[0]	"UNIMP",	unimp,	0,	/* page 137 */
182*473d4f4bSDavid du Colombier 	[2]	"B",		bra,	0,	/* page 119 */
183*473d4f4bSDavid du Colombier 	[4]	"SETHI",	sethi,	0,	/* page 104 */
184*473d4f4bSDavid du Colombier 	[6]	"FB",		fbra,	0,	/* page 121 */
185*473d4f4bSDavid du Colombier 	[7]	"CB",		cbra,	0,	/* page 123 */
186*473d4f4bSDavid du Colombier };
187*473d4f4bSDavid du Colombier 
188*473d4f4bSDavid du Colombier static struct opcode sparc64op2[64] = {
189*473d4f4bSDavid du Colombier 	[0x00]	"ADD",		add,	0,	/* page 108 */
190*473d4f4bSDavid du Colombier 	[0x10]	"ADDCC",	add,	0,
191*473d4f4bSDavid du Colombier 	[0x08]	"ADDX",		add,	0,
192*473d4f4bSDavid du Colombier 	[0x18]	"ADDXCC",	add,	0,
193*473d4f4bSDavid du Colombier 
194*473d4f4bSDavid du Colombier 	[0x20]	"TADD",		add,	0,	/* page 109 */
195*473d4f4bSDavid du Colombier 	[0x22]	"TADDCCTV",	add,	0,
196*473d4f4bSDavid du Colombier 
197*473d4f4bSDavid du Colombier 	[0x04]	"SUB",		add,	0,	/* page 110 */
198*473d4f4bSDavid du Colombier 	[0x14]	"SUBCC",	cmp,	0,
199*473d4f4bSDavid du Colombier 	[0x0C]	"SUBX",		add,	0,
200*473d4f4bSDavid du Colombier 	[0x1C]	"SUBXCC",	add,	0,
201*473d4f4bSDavid du Colombier 
202*473d4f4bSDavid du Colombier 	[0x21]	"TSUB",		add,	0,	/* page 111 */
203*473d4f4bSDavid du Colombier 	[0x23]	"TSUBCCTV",	add,	0,
204*473d4f4bSDavid du Colombier 
205*473d4f4bSDavid du Colombier 	[0x24]	"MULSCC",	add,	0,	/* page 112 */
206*473d4f4bSDavid du Colombier 
207*473d4f4bSDavid du Colombier 	[0x0A]	"UMUL",		add,	0,	/* page 113 */
208*473d4f4bSDavid du Colombier 	[0x0B]	"SMUL",		add,	0,
209*473d4f4bSDavid du Colombier 	[0x1A]	"UMULCC",	add,	0,
210*473d4f4bSDavid du Colombier 	[0x1B]	"SMULCC",	add,	0,
211*473d4f4bSDavid du Colombier 
212*473d4f4bSDavid du Colombier 	[0x0E]	"UDIV",		add,	0,	/* page 115 */
213*473d4f4bSDavid du Colombier 	[0x0F]	"SDIV",		add,	0,
214*473d4f4bSDavid du Colombier 	[0x1E]	"UDIVCC",	add,	0,
215*473d4f4bSDavid du Colombier 	[0x1F]	"SDIVCC",	add,	0,
216*473d4f4bSDavid du Colombier 
217*473d4f4bSDavid du Colombier 	[0x01]	"AND",		add,	0,	/* page 106 */
218*473d4f4bSDavid du Colombier 	[0x11]	"ANDCC",	add,	0,
219*473d4f4bSDavid du Colombier 	[0x05]	"ANDN",		add,	0,
220*473d4f4bSDavid du Colombier 	[0x15]	"ANDNCC",	add,	0,
221*473d4f4bSDavid du Colombier 	[0x02]	"OR",		add,	0,
222*473d4f4bSDavid du Colombier 	[0x12]	"ORCC",		add,	0,
223*473d4f4bSDavid du Colombier 	[0x06]	"ORN",		add,	0,
224*473d4f4bSDavid du Colombier 	[0x16]	"ORNCC",	add,	0,
225*473d4f4bSDavid du Colombier 	[0x03]	"XOR",		add,	0,
226*473d4f4bSDavid du Colombier 	[0x13]	"XORCC",	add,	0,
227*473d4f4bSDavid du Colombier 	[0x07]	"XORN",		add,	0,
228*473d4f4bSDavid du Colombier 	[0x17]	"XORNCC",	add,	0,
229*473d4f4bSDavid du Colombier 
230*473d4f4bSDavid du Colombier 	[0x25]	"SLL",		shift,	0,	/* page 107 */
231*473d4f4bSDavid du Colombier 	[0x26]	"SRL",		shift,	0,
232*473d4f4bSDavid du Colombier 	[0x27]	"SRA",		shift,	0,
233*473d4f4bSDavid du Colombier 
234*473d4f4bSDavid du Colombier 	[0x3C]	"SAVE",		add,	0,	/* page 117 */
235*473d4f4bSDavid du Colombier 	[0x3D]	"RESTORE",	add,	0,
236*473d4f4bSDavid du Colombier 
237*473d4f4bSDavid du Colombier 	[0x38]	"JMPL",		jmpl,	0,	/* page 126 */
238*473d4f4bSDavid du Colombier 
239*473d4f4bSDavid du Colombier 	[0x39]	"RETT",		add,	0,	/* page 127 */
240*473d4f4bSDavid du Colombier 
241*473d4f4bSDavid du Colombier 	[0x3A]	"T",		trap,	0,	/* page 129 */
242*473d4f4bSDavid du Colombier 
243*473d4f4bSDavid du Colombier 	[0x28]	"rdy",		rd,	0,	/* page 131 */
244*473d4f4bSDavid du Colombier 	[0x29]	"rdpsr",	rd,	0,
245*473d4f4bSDavid du Colombier 	[0x2A]	"rdwim",	rd,	0,
246*473d4f4bSDavid du Colombier 	[0x2B]	"rdtbr",	rd,	0,
247*473d4f4bSDavid du Colombier 
248*473d4f4bSDavid du Colombier 	[0x30]	"wry",		wr,	0,	/* page 133 */
249*473d4f4bSDavid du Colombier 	[0x31]	"wrpsr",	wr,	0,
250*473d4f4bSDavid du Colombier 	[0x32]	"wrwim",	wr,	0,
251*473d4f4bSDavid du Colombier 	[0x33]	"wrtbr",	wr,	0,
252*473d4f4bSDavid du Colombier 
253*473d4f4bSDavid du Colombier 	[0x3B]	"flush",	add,	0,	/* page 138 */
254*473d4f4bSDavid du Colombier 
255*473d4f4bSDavid du Colombier 	[0x34]	"FPOP",		fpop,	0,	/* page 140 */
256*473d4f4bSDavid du Colombier 	[0x35]	"FPOP",		fpop,	0,
257*473d4f4bSDavid du Colombier };
258*473d4f4bSDavid du Colombier 
259*473d4f4bSDavid du Colombier static struct opcode sparc64op3[64]={
260*473d4f4bSDavid du Colombier 	[0x09]	"ldsb",		load,	0,	/* page 90 */
261*473d4f4bSDavid du Colombier 	[0x19]	"ldsba",	loada,	0,
262*473d4f4bSDavid du Colombier 	[0x0A]	"ldsh",		load,	0,
263*473d4f4bSDavid du Colombier 	[0x1A]	"ldsha",	loada,	0,
264*473d4f4bSDavid du Colombier 	[0x01]	"ldub",		load,	0,
265*473d4f4bSDavid du Colombier 	[0x11]	"lduba",	loada,	0,
266*473d4f4bSDavid du Colombier 	[0x02]	"lduh",		load,	0,
267*473d4f4bSDavid du Colombier 	[0x12]	"lduha",	loada,	0,
268*473d4f4bSDavid du Colombier 	[0x00]	"ld",		load,	0,
269*473d4f4bSDavid du Colombier 	[0x10]	"lda",		loada,	0,
270*473d4f4bSDavid du Colombier 	[0x03]	"ldd",		load,	0,
271*473d4f4bSDavid du Colombier 	[0x13]	"ldda",		loada,	0,
272*473d4f4bSDavid du Colombier 
273*473d4f4bSDavid du Colombier 	[0x20]	"ldf",		loadf,	0,	/* page 92 */
274*473d4f4bSDavid du Colombier 	[0x23]	"lddf",		loadf,	0,
275*473d4f4bSDavid du Colombier 	[0x21]	"ldfsr",	loadf,0,
276*473d4f4bSDavid du Colombier 
277*473d4f4bSDavid du Colombier 	[0x30]	"ldc",		loadc,	0,	/* page 94 */
278*473d4f4bSDavid du Colombier 	[0x33]	"lddc",		loadc,	0,
279*473d4f4bSDavid du Colombier 	[0x31]	"ldcsr",	loadcsr,0,
280*473d4f4bSDavid du Colombier 
281*473d4f4bSDavid du Colombier 	[0x05]	"stb",		store,	0,	/* page 95 */
282*473d4f4bSDavid du Colombier 	[0x15]	"stba",		storea,	0,
283*473d4f4bSDavid du Colombier 	[0x06]	"sth",		store,	0,
284*473d4f4bSDavid du Colombier 	[0x16]	"stha",		storea,	0,
285*473d4f4bSDavid du Colombier 	[0x04]	"st",		store,	0,
286*473d4f4bSDavid du Colombier 	[0x14]	"sta",		storea,	0,
287*473d4f4bSDavid du Colombier 	[0x07]	"std",		store,	0,
288*473d4f4bSDavid du Colombier 	[0x17]	"stda",		storea,	0,
289*473d4f4bSDavid du Colombier 
290*473d4f4bSDavid du Colombier 	[0x24]	"stf",		storef,	0,	/* page 97 */
291*473d4f4bSDavid du Colombier 	[0x27]	"stdf",		storef,	0,
292*473d4f4bSDavid du Colombier 	[0x25]	"stfsr",	storef,0,
293*473d4f4bSDavid du Colombier 	[0x26]	"stdfq",	storef,0,
294*473d4f4bSDavid du Colombier 
295*473d4f4bSDavid du Colombier 	[0x34]	"stc",		loadc,	0,	/* page 99 */
296*473d4f4bSDavid du Colombier 	[0x37]	"stdc",		loadc,	0,
297*473d4f4bSDavid du Colombier 	[0x35]	"stcsr",	loadcsr,0,
298*473d4f4bSDavid du Colombier 	[0x36]	"stdcq",	loadcsr,0,
299*473d4f4bSDavid du Colombier 
300*473d4f4bSDavid du Colombier 	[0x0D]	"ldstub",	store,	0,	/* page 101 */
301*473d4f4bSDavid du Colombier 	[0x1D]	"ldstuba",	storea,	0,
302*473d4f4bSDavid du Colombier 
303*473d4f4bSDavid du Colombier 	[0x0F]	"swap",		load,	0,	/* page 102 */
304*473d4f4bSDavid du Colombier 	[0x1F]	"swapa",	loada,	0,
305*473d4f4bSDavid du Colombier };
306*473d4f4bSDavid du Colombier 
307*473d4f4bSDavid du Colombier #pragma	varargck	argpos	bprint	2
308*473d4f4bSDavid du Colombier #pragma	varargck	type	"T"	char*
309*473d4f4bSDavid du Colombier 
310*473d4f4bSDavid du Colombier /* convert to lower case from upper, according to dascase */
311*473d4f4bSDavid du Colombier static int
Tfmt(Fmt * f)312*473d4f4bSDavid du Colombier Tfmt(Fmt *f)
313*473d4f4bSDavid du Colombier {
314*473d4f4bSDavid du Colombier 	char buf[128];
315*473d4f4bSDavid du Colombier 	char *s, *t, *oa;
316*473d4f4bSDavid du Colombier 
317*473d4f4bSDavid du Colombier 	oa = va_arg(f->args, char*);
318*473d4f4bSDavid du Colombier 	if(dascase){
319*473d4f4bSDavid du Colombier 		for(s=oa,t=buf; *t = *s; s++,t++)
320*473d4f4bSDavid du Colombier 			if('A'<=*t && *t<='Z')
321*473d4f4bSDavid du Colombier 				*t += 'a'-'A';
322*473d4f4bSDavid du Colombier 		return fmtstrcpy(f, buf);
323*473d4f4bSDavid du Colombier 	}
324*473d4f4bSDavid du Colombier 	return fmtstrcpy(f, oa);
325*473d4f4bSDavid du Colombier }
326*473d4f4bSDavid du Colombier 
327*473d4f4bSDavid du Colombier static void
bprint(Instr * i,char * fmt,...)328*473d4f4bSDavid du Colombier bprint(Instr *i, char *fmt, ...)
329*473d4f4bSDavid du Colombier {
330*473d4f4bSDavid du Colombier 	va_list arg;
331*473d4f4bSDavid du Colombier 
332*473d4f4bSDavid du Colombier 	va_start(arg, fmt);
333*473d4f4bSDavid du Colombier 	i->curr = vseprint(i->curr, i->end, fmt, arg);
334*473d4f4bSDavid du Colombier 	va_end(arg);
335*473d4f4bSDavid du Colombier }
336*473d4f4bSDavid du Colombier 
337*473d4f4bSDavid du Colombier static int
decode(ulong pc,Instr * i)338*473d4f4bSDavid du Colombier decode(ulong pc, Instr *i)
339*473d4f4bSDavid du Colombier {
340*473d4f4bSDavid du Colombier 	ulong w;
341*473d4f4bSDavid du Colombier 
342*473d4f4bSDavid du Colombier 	if (get4(mymap, pc, &w) < 0) {
343*473d4f4bSDavid du Colombier 		werrstr("can't read instruction: %r");
344*473d4f4bSDavid du Colombier 		return -1;
345*473d4f4bSDavid du Colombier 	}
346*473d4f4bSDavid du Colombier 	i->op = (w >> 30) & 0x03;
347*473d4f4bSDavid du Colombier 	i->rd = (w >> 25) & 0x1F;
348*473d4f4bSDavid du Colombier 	i->op2 = (w >> 22) & 0x07;
349*473d4f4bSDavid du Colombier 	i->a = (w >> 29) & 0x01;
350*473d4f4bSDavid du Colombier 	i->cond = (w >> 25) & 0x0F;
351*473d4f4bSDavid du Colombier 	i->op3 = (w >> 19) & 0x3F;
352*473d4f4bSDavid du Colombier 	i->rs1 = (w >> 14) & 0x1F;
353*473d4f4bSDavid du Colombier 	i->i = (w >> 13) & 0x01;
354*473d4f4bSDavid du Colombier 	i->asi = (w >> 5) & 0xFF;
355*473d4f4bSDavid du Colombier 	i->rs2 = (w >> 0) & 0x1F;
356*473d4f4bSDavid du Colombier 	i->simm13 = (w >> 0) & 0x1FFF;
357*473d4f4bSDavid du Colombier 	if(i->simm13 & (1<<12))
358*473d4f4bSDavid du Colombier 		i->simm13 |= ~((1<<13)-1);
359*473d4f4bSDavid du Colombier 	i->opf = (w >> 5) & 0x1FF;
360*473d4f4bSDavid du Colombier 	i->immdisp22 = (w >> 0) & 0x3FFFFF;
361*473d4f4bSDavid du Colombier 	i->simmdisp22 = i->immdisp22;
362*473d4f4bSDavid du Colombier 	if(i->simmdisp22 & (1<<21))
363*473d4f4bSDavid du Colombier 		i->simmdisp22 |= ~((1<<22)-1);
364*473d4f4bSDavid du Colombier 	i->disp30 = (w >> 0) & 0x3FFFFFFF;
365*473d4f4bSDavid du Colombier 	i->w0 = w;
366*473d4f4bSDavid du Colombier 	i->target = -1;
367*473d4f4bSDavid du Colombier 	i->addr = pc;
368*473d4f4bSDavid du Colombier 	i->size = 1;
369*473d4f4bSDavid du Colombier 	return 1;
370*473d4f4bSDavid du Colombier }
371*473d4f4bSDavid du Colombier 
372*473d4f4bSDavid du Colombier static int
mkinstr(uvlong pc,Instr * i)373*473d4f4bSDavid du Colombier mkinstr(uvlong pc, Instr *i)
374*473d4f4bSDavid du Colombier {
375*473d4f4bSDavid du Colombier 	Instr xi;
376*473d4f4bSDavid du Colombier 
377*473d4f4bSDavid du Colombier 	if (decode(pc, i) < 0)
378*473d4f4bSDavid du Colombier 		return -1;
379*473d4f4bSDavid du Colombier 	if(i->op==0 && i->op2==4 && !dascase){	/* SETHI */
380*473d4f4bSDavid du Colombier 		if (decode(pc+4, &xi) < 0)
381*473d4f4bSDavid du Colombier 			return -1;
382*473d4f4bSDavid du Colombier 		if(xi.op==2 && xi.op3==0)		/* ADD */
383*473d4f4bSDavid du Colombier 		if(xi.i == 1 && xi.rs1 == i->rd){	/* immediate to same reg */
384*473d4f4bSDavid du Colombier 			i->imm32 = xi.simm13 + (i->immdisp22<<10);
385*473d4f4bSDavid du Colombier 			i->target = xi.rd;
386*473d4f4bSDavid du Colombier 			i->w1 = xi.w0;
387*473d4f4bSDavid du Colombier 			i->size++;
388*473d4f4bSDavid du Colombier 			return 1;
389*473d4f4bSDavid du Colombier 		}
390*473d4f4bSDavid du Colombier 	}
391*473d4f4bSDavid du Colombier 	if(i->op==2 && i->opf==1 && !dascase){	/* FMOVS */
392*473d4f4bSDavid du Colombier 		if (decode(pc+4, &xi) < 0)
393*473d4f4bSDavid du Colombier 			return -1;
394*473d4f4bSDavid du Colombier 		if(i->op==2 && i->opf==1)		/* FMOVS */
395*473d4f4bSDavid du Colombier 		if(xi.rd==i->rd+1 && xi.rs2==i->rs2+1){	/* next pair */
396*473d4f4bSDavid du Colombier 			i->w1 = xi.w0;
397*473d4f4bSDavid du Colombier 			i->size++;
398*473d4f4bSDavid du Colombier 		}
399*473d4f4bSDavid du Colombier 	}
400*473d4f4bSDavid du Colombier 	return 1;
401*473d4f4bSDavid du Colombier }
402*473d4f4bSDavid du Colombier 
403*473d4f4bSDavid du Colombier static int
printins(Map * map,uvlong pc,char * buf,int n)404*473d4f4bSDavid du Colombier printins(Map *map, uvlong pc, char *buf, int n)
405*473d4f4bSDavid du Colombier {
406*473d4f4bSDavid du Colombier 	Instr instr;
407*473d4f4bSDavid du Colombier 	void (*f)(Instr*, char*);
408*473d4f4bSDavid du Colombier 
409*473d4f4bSDavid du Colombier 	mymap = map;
410*473d4f4bSDavid du Colombier 	memset(&instr, 0, sizeof(instr));
411*473d4f4bSDavid du Colombier 	instr.curr = buf;
412*473d4f4bSDavid du Colombier 	instr.end = buf+n-1;
413*473d4f4bSDavid du Colombier 	if (mkinstr(pc, &instr) < 0)
414*473d4f4bSDavid du Colombier 		return -1;
415*473d4f4bSDavid du Colombier 	switch(instr.op){
416*473d4f4bSDavid du Colombier 	case 0:
417*473d4f4bSDavid du Colombier 		f = sparc64op0[instr.op2].f;
418*473d4f4bSDavid du Colombier 		if(f)
419*473d4f4bSDavid du Colombier 			(*f)(&instr, sparc64op0[instr.op2].mnemonic);
420*473d4f4bSDavid du Colombier 		else
421*473d4f4bSDavid du Colombier 			bprint(&instr, "unknown %lux", instr.w0);
422*473d4f4bSDavid du Colombier 		break;
423*473d4f4bSDavid du Colombier 
424*473d4f4bSDavid du Colombier 	case 1:
425*473d4f4bSDavid du Colombier 		bprint(&instr, "CALL\t");
426*473d4f4bSDavid du Colombier 		instr.curr += symoff(instr.curr, instr.end-instr.curr,
427*473d4f4bSDavid du Colombier 					pc+instr.disp30*4, CTEXT);
428*473d4f4bSDavid du Colombier 		if (!dascase)
429*473d4f4bSDavid du Colombier 			bprint(&instr, "(SB)");
430*473d4f4bSDavid du Colombier 		break;
431*473d4f4bSDavid du Colombier 
432*473d4f4bSDavid du Colombier 	case 2:
433*473d4f4bSDavid du Colombier 		f = sparc64op2[instr.op3].f;
434*473d4f4bSDavid du Colombier 		if(f)
435*473d4f4bSDavid du Colombier 			(*f)(&instr, sparc64op2[instr.op3].mnemonic);
436*473d4f4bSDavid du Colombier 		else
437*473d4f4bSDavid du Colombier 			bprint(&instr, "unknown %lux", instr.w0);
438*473d4f4bSDavid du Colombier 		break;
439*473d4f4bSDavid du Colombier 
440*473d4f4bSDavid du Colombier 	case 3:
441*473d4f4bSDavid du Colombier 		f = sparc64op3[instr.op3].f;
442*473d4f4bSDavid du Colombier 		if(f)
443*473d4f4bSDavid du Colombier 			(*f)(&instr, sparc64op3[instr.op3].mnemonic);
444*473d4f4bSDavid du Colombier 		else
445*473d4f4bSDavid du Colombier 			bprint(&instr, "unknown %lux", instr.w0);
446*473d4f4bSDavid du Colombier 		break;
447*473d4f4bSDavid du Colombier 	}
448*473d4f4bSDavid du Colombier 	if (instr.err) {
449*473d4f4bSDavid du Colombier 		if (instr.curr != buf)
450*473d4f4bSDavid du Colombier 			bprint(&instr, "\t\t;");
451*473d4f4bSDavid du Colombier 		bprint(&instr, instr.err);
452*473d4f4bSDavid du Colombier 	}
453*473d4f4bSDavid du Colombier 	return instr.size*4;
454*473d4f4bSDavid du Colombier }
455*473d4f4bSDavid du Colombier 
456*473d4f4bSDavid du Colombier static int
sparc64inst(Map * map,uvlong pc,char modifier,char * buf,int n)457*473d4f4bSDavid du Colombier sparc64inst(Map *map, uvlong pc, char modifier, char *buf, int n)
458*473d4f4bSDavid du Colombier {
459*473d4f4bSDavid du Colombier 	static int fmtinstalled = 0;
460*473d4f4bSDavid du Colombier 
461*473d4f4bSDavid du Colombier 		/* a modifier of 'I' toggles the dissassembler type */
462*473d4f4bSDavid du Colombier 	if (!fmtinstalled) {
463*473d4f4bSDavid du Colombier 		fmtinstalled = 1;
464*473d4f4bSDavid du Colombier 		fmtinstall('T', Tfmt);
465*473d4f4bSDavid du Colombier 	}
466*473d4f4bSDavid du Colombier 	if ((asstype == ASUNSPARC && modifier == 'i')
467*473d4f4bSDavid du Colombier 		|| (asstype == ASPARC && modifier == 'I'))
468*473d4f4bSDavid du Colombier 		dascase = 'a'-'A';
469*473d4f4bSDavid du Colombier 	else
470*473d4f4bSDavid du Colombier 		dascase = 0;
471*473d4f4bSDavid du Colombier 	return printins(map, pc, buf, n);
472*473d4f4bSDavid du Colombier }
473*473d4f4bSDavid du Colombier 
474*473d4f4bSDavid du Colombier static int
sparc64das(Map * map,uvlong pc,char * buf,int n)475*473d4f4bSDavid du Colombier sparc64das(Map *map, uvlong pc, char *buf, int n)
476*473d4f4bSDavid du Colombier {
477*473d4f4bSDavid du Colombier 	Instr instr;
478*473d4f4bSDavid du Colombier 
479*473d4f4bSDavid du Colombier 	mymap = map;
480*473d4f4bSDavid du Colombier 	memset(&instr, 0, sizeof(instr));
481*473d4f4bSDavid du Colombier 	instr.curr = buf;
482*473d4f4bSDavid du Colombier 	instr.end = buf+n-1;
483*473d4f4bSDavid du Colombier 	if (mkinstr(pc, &instr) < 0)
484*473d4f4bSDavid du Colombier 		return -1;
485*473d4f4bSDavid du Colombier 	if (instr.end-instr.curr > 8)
486*473d4f4bSDavid du Colombier 		instr.curr = _hexify(instr.curr, instr.w0, 7);
487*473d4f4bSDavid du Colombier 	if (instr.end-instr.curr > 9 && instr.size == 2) {
488*473d4f4bSDavid du Colombier 		*instr.curr++ = ' ';
489*473d4f4bSDavid du Colombier 		instr.curr = _hexify(instr.curr, instr.w1, 7);
490*473d4f4bSDavid du Colombier 	}
491*473d4f4bSDavid du Colombier 	*instr.curr = 0;
492*473d4f4bSDavid du Colombier 	return instr.size*4;
493*473d4f4bSDavid du Colombier }
494*473d4f4bSDavid du Colombier 
495*473d4f4bSDavid du Colombier static int
sparc64instlen(Map * map,uvlong pc)496*473d4f4bSDavid du Colombier sparc64instlen(Map *map, uvlong pc)
497*473d4f4bSDavid du Colombier {
498*473d4f4bSDavid du Colombier 	Instr i;
499*473d4f4bSDavid du Colombier 
500*473d4f4bSDavid du Colombier 	mymap = map;
501*473d4f4bSDavid du Colombier 	if (mkinstr(pc, &i) < 0)
502*473d4f4bSDavid du Colombier 		return -1;
503*473d4f4bSDavid du Colombier 	return i.size*4;
504*473d4f4bSDavid du Colombier }
505*473d4f4bSDavid du Colombier 
506*473d4f4bSDavid du Colombier static int
plocal(Instr * i)507*473d4f4bSDavid du Colombier plocal(Instr *i)
508*473d4f4bSDavid du Colombier {
509*473d4f4bSDavid du Colombier 	long offset;
510*473d4f4bSDavid du Colombier 	Symbol s;
511*473d4f4bSDavid du Colombier 
512*473d4f4bSDavid du Colombier 	if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
513*473d4f4bSDavid du Colombier 		return -1;
514*473d4f4bSDavid du Colombier 	if (s.value > i->simm13) {
515*473d4f4bSDavid du Colombier 		if(getauto(&s, s.value-i->simm13, CAUTO, &s)) {
516*473d4f4bSDavid du Colombier 			bprint(i, "%s+%lld(SP)", s.name, s.value);
517*473d4f4bSDavid du Colombier 			return 1;
518*473d4f4bSDavid du Colombier 		}
519*473d4f4bSDavid du Colombier 	} else {
520*473d4f4bSDavid du Colombier 		offset = i->simm13-s.value;
521*473d4f4bSDavid du Colombier 		if (getauto(&s, offset-4, CPARAM, &s)) {
522*473d4f4bSDavid du Colombier 			bprint(i, "%s+%ld(FP)", s.name, offset);
523*473d4f4bSDavid du Colombier 			return 1;
524*473d4f4bSDavid du Colombier 		}
525*473d4f4bSDavid du Colombier 	}
526*473d4f4bSDavid du Colombier 	return -1;
527*473d4f4bSDavid du Colombier }
528*473d4f4bSDavid du Colombier 
529*473d4f4bSDavid du Colombier static void
address(Instr * i)530*473d4f4bSDavid du Colombier address(Instr *i)
531*473d4f4bSDavid du Colombier {
532*473d4f4bSDavid du Colombier 	Symbol s, s2;
533*473d4f4bSDavid du Colombier 	uvlong off, off1;
534*473d4f4bSDavid du Colombier 
535*473d4f4bSDavid du Colombier 	if (i->rs1 == 1 && plocal(i) >= 0)
536*473d4f4bSDavid du Colombier 		return;
537*473d4f4bSDavid du Colombier 	off = mach->sb+i->simm13;
538*473d4f4bSDavid du Colombier 	if(i->rs1 == 2	&& findsym(off, CANY, &s)
539*473d4f4bSDavid du Colombier 			&& s.value-off < 4096
540*473d4f4bSDavid du Colombier 			&& (s.class == CDATA || s.class == CTEXT)) {
541*473d4f4bSDavid du Colombier 		if(off==s.value && s.name[0]=='$'){
542*473d4f4bSDavid du Colombier 			off1 = 0;
543*473d4f4bSDavid du Colombier 			geta(mymap, s.value, &off1);
544*473d4f4bSDavid du Colombier 			if(off1 && findsym(off1, CANY, &s2) && s2.value == off1){
545*473d4f4bSDavid du Colombier 				bprint(i, "$%s(SB)", s2.name);
546*473d4f4bSDavid du Colombier 				return;
547*473d4f4bSDavid du Colombier 			}
548*473d4f4bSDavid du Colombier 		}
549*473d4f4bSDavid du Colombier 		bprint(i, "%s", s.name);
550*473d4f4bSDavid du Colombier 		if (s.value != off)
551*473d4f4bSDavid du Colombier 			bprint(i, "+%llux", s.value-off);
552*473d4f4bSDavid du Colombier 		bprint(i, "(SB)");
553*473d4f4bSDavid du Colombier 		return;
554*473d4f4bSDavid du Colombier 	}
555*473d4f4bSDavid du Colombier 	bprint(i, "%ux(R%d)", i->simm13, i->rs1);
556*473d4f4bSDavid du Colombier }
557*473d4f4bSDavid du Colombier 
558*473d4f4bSDavid du Colombier static void
unimp(Instr * i,char * m)559*473d4f4bSDavid du Colombier unimp(Instr *i, char *m)
560*473d4f4bSDavid du Colombier {
561*473d4f4bSDavid du Colombier 	bprint(i, "%T", m);
562*473d4f4bSDavid du Colombier }
563*473d4f4bSDavid du Colombier 
564*473d4f4bSDavid du Colombier static char	*bratab[16] = {		/* page 91 */
565*473d4f4bSDavid du Colombier 	[0X8]	"A",
566*473d4f4bSDavid du Colombier 	[0X0]	"N",
567*473d4f4bSDavid du Colombier 	[0X9]	"NE",
568*473d4f4bSDavid du Colombier 	[0X1]	"E",
569*473d4f4bSDavid du Colombier 	[0XA]	"G",
570*473d4f4bSDavid du Colombier 	[0X2]	"LE",
571*473d4f4bSDavid du Colombier 	[0XB]	"GE",
572*473d4f4bSDavid du Colombier 	[0X3]	"L",
573*473d4f4bSDavid du Colombier 	[0XC]	"GU",
574*473d4f4bSDavid du Colombier 	[0X4]	"LEU",
575*473d4f4bSDavid du Colombier 	[0XD]	"CC",
576*473d4f4bSDavid du Colombier 	[0X5]	"CS",
577*473d4f4bSDavid du Colombier 	[0XE]	"POS",
578*473d4f4bSDavid du Colombier 	[0X6]	"NEG",
579*473d4f4bSDavid du Colombier 	[0XF]	"VC",
580*473d4f4bSDavid du Colombier 	[0X7]	"VS",
581*473d4f4bSDavid du Colombier };
582*473d4f4bSDavid du Colombier 
583*473d4f4bSDavid du Colombier static char	*fbratab[16] = {	/* page 91 */
584*473d4f4bSDavid du Colombier 	[0X8]	"A",
585*473d4f4bSDavid du Colombier 	[0X0]	"N",
586*473d4f4bSDavid du Colombier 	[0X7]	"U",
587*473d4f4bSDavid du Colombier 	[0X6]	"G",
588*473d4f4bSDavid du Colombier 	[0X5]	"UG",
589*473d4f4bSDavid du Colombier 	[0X4]	"L",
590*473d4f4bSDavid du Colombier 	[0X3]	"UL",
591*473d4f4bSDavid du Colombier 	[0X2]	"LG",
592*473d4f4bSDavid du Colombier 	[0X1]	"NE",
593*473d4f4bSDavid du Colombier 	[0X9]	"E",
594*473d4f4bSDavid du Colombier 	[0XA]	"UE",
595*473d4f4bSDavid du Colombier 	[0XB]	"GE",
596*473d4f4bSDavid du Colombier 	[0XC]	"UGE",
597*473d4f4bSDavid du Colombier 	[0XD]	"LE",
598*473d4f4bSDavid du Colombier 	[0XE]	"ULE",
599*473d4f4bSDavid du Colombier 	[0XF]	"O",
600*473d4f4bSDavid du Colombier };
601*473d4f4bSDavid du Colombier 
602*473d4f4bSDavid du Colombier static char	*cbratab[16] = {	/* page 91 */
603*473d4f4bSDavid du Colombier 	[0X8]	"A",
604*473d4f4bSDavid du Colombier 	[0X0]	"N",
605*473d4f4bSDavid du Colombier 	[0X7]	"3",
606*473d4f4bSDavid du Colombier 	[0X6]	"2",
607*473d4f4bSDavid du Colombier 	[0X5]	"23",
608*473d4f4bSDavid du Colombier 	[0X4]	"1",
609*473d4f4bSDavid du Colombier 	[0X3]	"13",
610*473d4f4bSDavid du Colombier 	[0X2]	"12",
611*473d4f4bSDavid du Colombier 	[0X1]	"123",
612*473d4f4bSDavid du Colombier 	[0X9]	"0",
613*473d4f4bSDavid du Colombier 	[0XA]	"03",
614*473d4f4bSDavid du Colombier 	[0XB]	"02",
615*473d4f4bSDavid du Colombier 	[0XC]	"023",
616*473d4f4bSDavid du Colombier 	[0XD]	"01",
617*473d4f4bSDavid du Colombier 	[0XE]	"013",
618*473d4f4bSDavid du Colombier 	[0XF]	"012",
619*473d4f4bSDavid du Colombier };
620*473d4f4bSDavid du Colombier 
621*473d4f4bSDavid du Colombier static void
bra1(Instr * i,char * m,char * tab[])622*473d4f4bSDavid du Colombier bra1(Instr *i, char *m, char *tab[])
623*473d4f4bSDavid du Colombier {
624*473d4f4bSDavid du Colombier 	long imm;
625*473d4f4bSDavid du Colombier 
626*473d4f4bSDavid du Colombier 	imm = i->simmdisp22;
627*473d4f4bSDavid du Colombier 	if(i->a)
628*473d4f4bSDavid du Colombier 		bprint(i, "%T%T.%c\t", m, tab[i->cond], 'A'+dascase);
629*473d4f4bSDavid du Colombier 	else
630*473d4f4bSDavid du Colombier 		bprint(i, "%T%T\t", m, tab[i->cond]);
631*473d4f4bSDavid du Colombier 	i->curr += symoff(i->curr, i->end-i->curr, i->addr+4*imm, CTEXT);
632*473d4f4bSDavid du Colombier 	if (!dascase)
633*473d4f4bSDavid du Colombier 		bprint(i, "(SB)");
634*473d4f4bSDavid du Colombier }
635*473d4f4bSDavid du Colombier 
636*473d4f4bSDavid du Colombier static void
bra(Instr * i,char * m)637*473d4f4bSDavid du Colombier bra(Instr *i, char *m)			/* page 91 */
638*473d4f4bSDavid du Colombier {
639*473d4f4bSDavid du Colombier 	bra1(i, m, bratab);
640*473d4f4bSDavid du Colombier }
641*473d4f4bSDavid du Colombier 
642*473d4f4bSDavid du Colombier static void
fbra(Instr * i,char * m)643*473d4f4bSDavid du Colombier fbra(Instr *i, char *m)			/* page 93 */
644*473d4f4bSDavid du Colombier {
645*473d4f4bSDavid du Colombier 	bra1(i, m, fbratab);
646*473d4f4bSDavid du Colombier }
647*473d4f4bSDavid du Colombier 
648*473d4f4bSDavid du Colombier static void
cbra(Instr * i,char * m)649*473d4f4bSDavid du Colombier cbra(Instr *i, char *m)			/* page 95 */
650*473d4f4bSDavid du Colombier {
651*473d4f4bSDavid du Colombier 	bra1(i, m, cbratab);
652*473d4f4bSDavid du Colombier }
653*473d4f4bSDavid du Colombier 
654*473d4f4bSDavid du Colombier static void
trap(Instr * i,char * m)655*473d4f4bSDavid du Colombier trap(Instr *i, char *m)			/* page 101 */
656*473d4f4bSDavid du Colombier {
657*473d4f4bSDavid du Colombier 	if(i->i == 0)
658*473d4f4bSDavid du Colombier 		bprint(i, "%T%T\tR%d+R%d", m, bratab[i->cond], i->rs2, i->rs1);
659*473d4f4bSDavid du Colombier 	else
660*473d4f4bSDavid du Colombier 		bprint(i, "%T%T\t$%ux+R%d", m, bratab[i->cond], i->simm13, i->rs1);
661*473d4f4bSDavid du Colombier }
662*473d4f4bSDavid du Colombier 
663*473d4f4bSDavid du Colombier static void
sethi(Instr * i,char * m)664*473d4f4bSDavid du Colombier sethi(Instr *i, char *m)		/* page 89 */
665*473d4f4bSDavid du Colombier {
666*473d4f4bSDavid du Colombier 	ulong imm;
667*473d4f4bSDavid du Colombier 
668*473d4f4bSDavid du Colombier 	imm = i->immdisp22<<10;
669*473d4f4bSDavid du Colombier 	if(dascase){
670*473d4f4bSDavid du Colombier 		bprint(i, "%T\t%lux, R%d", m, imm, i->rd);
671*473d4f4bSDavid du Colombier 		return;
672*473d4f4bSDavid du Colombier 	}
673*473d4f4bSDavid du Colombier 	if(imm==0 && i->rd==0){
674*473d4f4bSDavid du Colombier 		bprint(i, "NOP");
675*473d4f4bSDavid du Colombier 		return;
676*473d4f4bSDavid du Colombier 	}
677*473d4f4bSDavid du Colombier 	if(i->target < 0){
678*473d4f4bSDavid du Colombier 		bprint(i, "MOVW\t$%lux, R%d", imm, i->rd);
679*473d4f4bSDavid du Colombier 		return;
680*473d4f4bSDavid du Colombier 	}
681*473d4f4bSDavid du Colombier 	bprint(i, "MOVW\t$%lux, R%d", i->imm32, i->target);
682*473d4f4bSDavid du Colombier }
683*473d4f4bSDavid du Colombier 
684*473d4f4bSDavid du Colombier static char ldtab[] = {
685*473d4f4bSDavid du Colombier 	'W',
686*473d4f4bSDavid du Colombier 	'B',
687*473d4f4bSDavid du Colombier 	'H',
688*473d4f4bSDavid du Colombier 	'D',
689*473d4f4bSDavid du Colombier };
690*473d4f4bSDavid du Colombier 
691*473d4f4bSDavid du Colombier static char*
moveinstr(int op3,char * m)692*473d4f4bSDavid du Colombier moveinstr(int op3, char *m)
693*473d4f4bSDavid du Colombier {
694*473d4f4bSDavid du Colombier 	char *s;
695*473d4f4bSDavid du Colombier 	int c;
696*473d4f4bSDavid du Colombier 	static char buf[8];
697*473d4f4bSDavid du Colombier 
698*473d4f4bSDavid du Colombier 	if(!dascase){
699*473d4f4bSDavid du Colombier 		/* batshit cases */
700*473d4f4bSDavid du Colombier 		if(op3 == 0xF || op3 == 0x1F)
701*473d4f4bSDavid du Colombier 			return "SWAP";
702*473d4f4bSDavid du Colombier 		if(op3 == 0xD || op3 == 0x1D)
703*473d4f4bSDavid du Colombier 			return "TAS";	/* really LDSTUB */
704*473d4f4bSDavid du Colombier 		c = ldtab[op3&3];
705*473d4f4bSDavid du Colombier 		s = "";
706*473d4f4bSDavid du Colombier 		if((op3&11)==1 || (op3&11)==2)
707*473d4f4bSDavid du Colombier 			s="U";
708*473d4f4bSDavid du Colombier 		sprint(buf, "MOV%c%s", c, s);
709*473d4f4bSDavid du Colombier 		return buf;
710*473d4f4bSDavid du Colombier 	}
711*473d4f4bSDavid du Colombier 	return m;
712*473d4f4bSDavid du Colombier }
713*473d4f4bSDavid du Colombier 
714*473d4f4bSDavid du Colombier static void
load(Instr * i,char * m)715*473d4f4bSDavid du Colombier load(Instr *i, char *m)			/* page 68 */
716*473d4f4bSDavid du Colombier {
717*473d4f4bSDavid du Colombier 	m = moveinstr(i->op3, m);
718*473d4f4bSDavid du Colombier 	if(i->i == 0)
719*473d4f4bSDavid du Colombier 		bprint(i, "%s\t(R%d+R%d), R%d", m, i->rs1, i->rs2, i->rd);
720*473d4f4bSDavid du Colombier 	else{
721*473d4f4bSDavid du Colombier 		bprint(i, "%s\t", m);
722*473d4f4bSDavid du Colombier 		address(i);
723*473d4f4bSDavid du Colombier 		bprint(i, ", R%d", i->rd);
724*473d4f4bSDavid du Colombier 	}
725*473d4f4bSDavid du Colombier }
726*473d4f4bSDavid du Colombier 
727*473d4f4bSDavid du Colombier static void
loada(Instr * i,char * m)728*473d4f4bSDavid du Colombier loada(Instr *i, char *m)		/* page 68 */
729*473d4f4bSDavid du Colombier {
730*473d4f4bSDavid du Colombier 	m = moveinstr(i->op3, m);
731*473d4f4bSDavid du Colombier 	if(i->i == 0)
732*473d4f4bSDavid du Colombier 		bprint(i, "%s\t(R%d+R%d, %d), R%d", m, i->rs1, i->rs2, i->asi, i->rd);
733*473d4f4bSDavid du Colombier 	else
734*473d4f4bSDavid du Colombier 		bprint(i, "unknown ld asi %lux", i->w0);
735*473d4f4bSDavid du Colombier }
736*473d4f4bSDavid du Colombier 
737*473d4f4bSDavid du Colombier static void
store(Instr * i,char * m)738*473d4f4bSDavid du Colombier store(Instr *i, char *m)		/* page 74 */
739*473d4f4bSDavid du Colombier {
740*473d4f4bSDavid du Colombier 	m = moveinstr(i->op3, m);
741*473d4f4bSDavid du Colombier 	if(i->i == 0)
742*473d4f4bSDavid du Colombier 		bprint(i, "%s\tR%d, (R%d+R%d)",
743*473d4f4bSDavid du Colombier 				m, i->rd, i->rs1, i->rs2);
744*473d4f4bSDavid du Colombier 	else{
745*473d4f4bSDavid du Colombier 		bprint(i, "%s\tR%d, ", m, i->rd);
746*473d4f4bSDavid du Colombier 		address(i);
747*473d4f4bSDavid du Colombier 	}
748*473d4f4bSDavid du Colombier }
749*473d4f4bSDavid du Colombier 
750*473d4f4bSDavid du Colombier static void
storea(Instr * i,char * m)751*473d4f4bSDavid du Colombier storea(Instr *i, char *m)		/* page 74 */
752*473d4f4bSDavid du Colombier {
753*473d4f4bSDavid du Colombier 	m = moveinstr(i->op3, m);
754*473d4f4bSDavid du Colombier 	if(i->i == 0)
755*473d4f4bSDavid du Colombier 		bprint(i, "%s\tR%d, (R%d+R%d, %d)", m, i->rd, i->rs1, i->rs2, i->asi);
756*473d4f4bSDavid du Colombier 	else
757*473d4f4bSDavid du Colombier 		bprint(i, "%s\tR%d, %d(R%d, %d), ???", m, i->rd, i->simm13, i->rs1, i->asi);
758*473d4f4bSDavid du Colombier }
759*473d4f4bSDavid du Colombier 
760*473d4f4bSDavid du Colombier static void
shift(Instr * i,char * m)761*473d4f4bSDavid du Colombier shift(Instr *i, char *m)		/* page 88 */
762*473d4f4bSDavid du Colombier {
763*473d4f4bSDavid du Colombier 	if(i->i == 0){
764*473d4f4bSDavid du Colombier 		if(i->rs1 == i->rd)
765*473d4f4bSDavid du Colombier 			if(dascase)
766*473d4f4bSDavid du Colombier 				bprint(i, "%T\tR%d, R%d", m, i->rs1, i->rs2);
767*473d4f4bSDavid du Colombier 			else
768*473d4f4bSDavid du Colombier 				bprint(i, "%T\tR%d, R%d", m, i->rs2, i->rs1);
769*473d4f4bSDavid du Colombier 		else
770*473d4f4bSDavid du Colombier 			if(dascase)
771*473d4f4bSDavid du Colombier 				bprint(i, "%T\tR%d, R%d, R%d", m, i->rs1, i->rs2, i->rd);
772*473d4f4bSDavid du Colombier 			else
773*473d4f4bSDavid du Colombier 				bprint(i, "%T\tR%d, R%d, R%d", m, i->rs2, i->rs1, i->rd);
774*473d4f4bSDavid du Colombier 	}else{
775*473d4f4bSDavid du Colombier 		if(i->rs1 == i->rd)
776*473d4f4bSDavid du Colombier 			if(dascase)
777*473d4f4bSDavid du Colombier 				bprint(i, "%T\t$%d,R%d", m, i->simm13&0x1F, i->rs1);
778*473d4f4bSDavid du Colombier 			else
779*473d4f4bSDavid du Colombier 				bprint(i, "%T\tR%d, $%d", m,  i->rs1, i->simm13&0x1F);
780*473d4f4bSDavid du Colombier 		else
781*473d4f4bSDavid du Colombier 			if(dascase)
782*473d4f4bSDavid du Colombier 				bprint(i, "%T\tR%d, $%d, R%d",m,i->rs1,i->simm13&0x1F,i->rd);
783*473d4f4bSDavid du Colombier 			else
784*473d4f4bSDavid du Colombier 				bprint(i, "%T\t$%d, R%d, R%d",m,i->simm13&0x1F,i->rs1,i->rd);
785*473d4f4bSDavid du Colombier 	}
786*473d4f4bSDavid du Colombier }
787*473d4f4bSDavid du Colombier 
788*473d4f4bSDavid du Colombier static void
add(Instr * i,char * m)789*473d4f4bSDavid du Colombier add(Instr *i, char *m)			/* page 82 */
790*473d4f4bSDavid du Colombier {
791*473d4f4bSDavid du Colombier 	if(i->i == 0){
792*473d4f4bSDavid du Colombier 		if(dascase)
793*473d4f4bSDavid du Colombier 			bprint(i, "%T\tR%d, R%d", m, i->rs1, i->rs2);
794*473d4f4bSDavid du Colombier 		else
795*473d4f4bSDavid du Colombier 			if(i->op3==2 && i->rs1==0 && i->rd)  /* OR R2, R0, R1 */
796*473d4f4bSDavid du Colombier 				bprint(i, "MOVW\tR%d", i->rs2);
797*473d4f4bSDavid du Colombier 			else
798*473d4f4bSDavid du Colombier 				bprint(i, "%T\tR%d, R%d", m, i->rs2, i->rs1);
799*473d4f4bSDavid du Colombier 	}else{
800*473d4f4bSDavid du Colombier 		if(dascase)
801*473d4f4bSDavid du Colombier 			bprint(i, "%T\tR%d, $%ux", m, i->rs1, i->simm13);
802*473d4f4bSDavid du Colombier 		else
803*473d4f4bSDavid du Colombier 			if(i->op3==0 && i->rd && i->rs1==0)	/* ADD $x, R0, R1 */
804*473d4f4bSDavid du Colombier 				bprint(i, "MOVW\t$%ux", i->simm13);
805*473d4f4bSDavid du Colombier 			else if(i->op3==0 && i->rd && i->rs1==2){
806*473d4f4bSDavid du Colombier 				/* ADD $x, R2, R1 -> MOVW $x(SB), R1 */
807*473d4f4bSDavid du Colombier 				bprint(i, "MOVW\t$");
808*473d4f4bSDavid du Colombier 				address(i);
809*473d4f4bSDavid du Colombier 			} else
810*473d4f4bSDavid du Colombier 				bprint(i, "%T\t$%ux, R%d", m, i->simm13, i->rs1);
811*473d4f4bSDavid du Colombier 	}
812*473d4f4bSDavid du Colombier 	if(i->rs1 != i->rd)
813*473d4f4bSDavid du Colombier 		bprint(i, ", R%d", i->rd);
814*473d4f4bSDavid du Colombier }
815*473d4f4bSDavid du Colombier 
816*473d4f4bSDavid du Colombier static void
cmp(Instr * i,char * m)817*473d4f4bSDavid du Colombier cmp(Instr *i, char *m)
818*473d4f4bSDavid du Colombier {
819*473d4f4bSDavid du Colombier 	if(dascase || i->rd){
820*473d4f4bSDavid du Colombier 		add(i, m);
821*473d4f4bSDavid du Colombier 		return;
822*473d4f4bSDavid du Colombier 	}
823*473d4f4bSDavid du Colombier 	if(i->i == 0)
824*473d4f4bSDavid du Colombier 		bprint(i, "CMP\tR%d, R%d", i->rs1, i->rs2);
825*473d4f4bSDavid du Colombier 	else
826*473d4f4bSDavid du Colombier 		bprint(i, "CMP\tR%d, $%ux", i->rs1, i->simm13);
827*473d4f4bSDavid du Colombier }
828*473d4f4bSDavid du Colombier 
829*473d4f4bSDavid du Colombier static char *regtab[4] = {
830*473d4f4bSDavid du Colombier 	"Y",
831*473d4f4bSDavid du Colombier 	"PSTATE",
832*473d4f4bSDavid du Colombier 	"WIM",	/* XXX not any more */
833*473d4f4bSDavid du Colombier 	"TT",
834*473d4f4bSDavid du Colombier };
835*473d4f4bSDavid du Colombier 
836*473d4f4bSDavid du Colombier static void
wr(Instr * i,char * m)837*473d4f4bSDavid du Colombier wr(Instr *i, char *m)			/* page 82 */
838*473d4f4bSDavid du Colombier {
839*473d4f4bSDavid du Colombier 	if(dascase){
840*473d4f4bSDavid du Colombier 		if(i->i == 0)
841*473d4f4bSDavid du Colombier 			bprint(i, "%s\tR%d, R%d", m, i->rs1, i->rs2);
842*473d4f4bSDavid du Colombier 		else
843*473d4f4bSDavid du Colombier 			bprint(i, "%s\tR%d, $%ux", m, i->rs1, i->simm13);
844*473d4f4bSDavid du Colombier 	}else{
845*473d4f4bSDavid du Colombier 		if(i->i && i->simm13==0)
846*473d4f4bSDavid du Colombier 			bprint(i, "MOVW\tR%d", i->rs1);
847*473d4f4bSDavid du Colombier 		else if(i->i == 0)
848*473d4f4bSDavid du Colombier 			bprint(i, "wr\tR%d, R%d", i->rs2, i->rs1);
849*473d4f4bSDavid du Colombier 		else
850*473d4f4bSDavid du Colombier 			bprint(i, "wr\t$%ux, R%d", i->simm13, i->rs1);
851*473d4f4bSDavid du Colombier 	}
852*473d4f4bSDavid du Colombier 	bprint(i, ", %s", regtab[i->op3&3]);
853*473d4f4bSDavid du Colombier }
854*473d4f4bSDavid du Colombier 
855*473d4f4bSDavid du Colombier static void
rd(Instr * i,char * m)856*473d4f4bSDavid du Colombier rd(Instr *i, char *m)			/* page 103 */
857*473d4f4bSDavid du Colombier {
858*473d4f4bSDavid du Colombier 	if(i->rs1==15 && i->rd==0){
859*473d4f4bSDavid du Colombier 		m = "stbar";
860*473d4f4bSDavid du Colombier 		if(!dascase)
861*473d4f4bSDavid du Colombier 			m = "STBAR";
862*473d4f4bSDavid du Colombier 		bprint(i, "%s", m);
863*473d4f4bSDavid du Colombier 	}else{
864*473d4f4bSDavid du Colombier 		if(!dascase)
865*473d4f4bSDavid du Colombier 			m = "MOVW";
866*473d4f4bSDavid du Colombier 		bprint(i, "%s\t%s, R%d", m, regtab[i->op3&3], i->rd);
867*473d4f4bSDavid du Colombier 	}
868*473d4f4bSDavid du Colombier }
869*473d4f4bSDavid du Colombier 
870*473d4f4bSDavid du Colombier static void
jmpl(Instr * i,char * m)871*473d4f4bSDavid du Colombier jmpl(Instr *i, char *m)			/* page 82 */
872*473d4f4bSDavid du Colombier {
873*473d4f4bSDavid du Colombier 	if(i->i == 0){
874*473d4f4bSDavid du Colombier 		if(i->rd == 15)
875*473d4f4bSDavid du Colombier 			bprint(i, "%T\t(R%d+R%d)", "CALL", i->rs2, i->rs1);
876*473d4f4bSDavid du Colombier 		else
877*473d4f4bSDavid du Colombier 			bprint(i, "%T\t(R%d+R%d), R%d", m, i->rs2, i->rs1, i->rd);
878*473d4f4bSDavid du Colombier 	}else{
879*473d4f4bSDavid du Colombier 		if(!dascase && i->simm13==8 && i->rs1==15 && i->rd==0)
880*473d4f4bSDavid du Colombier 			bprint(i, "RETURN");
881*473d4f4bSDavid du Colombier 		else{
882*473d4f4bSDavid du Colombier 			bprint(i, "%T\t", m);
883*473d4f4bSDavid du Colombier 			address(i);
884*473d4f4bSDavid du Colombier 			bprint(i, ", R%d", i->rd);
885*473d4f4bSDavid du Colombier 		}
886*473d4f4bSDavid du Colombier 	}
887*473d4f4bSDavid du Colombier }
888*473d4f4bSDavid du Colombier 
889*473d4f4bSDavid du Colombier static void
loadf(Instr * i,char * m)890*473d4f4bSDavid du Colombier loadf(Instr *i, char *m)		/* page 70 */
891*473d4f4bSDavid du Colombier {
892*473d4f4bSDavid du Colombier 	if(!dascase){
893*473d4f4bSDavid du Colombier 		m = "FMOVD";
894*473d4f4bSDavid du Colombier 		if(i->op3 == 0x20)
895*473d4f4bSDavid du Colombier 			m = "FMOVF";
896*473d4f4bSDavid du Colombier 		else if(i->op3 == 0x21)
897*473d4f4bSDavid du Colombier 			m = "MOVW";
898*473d4f4bSDavid du Colombier 	}
899*473d4f4bSDavid du Colombier 	if(i->i == 0)
900*473d4f4bSDavid du Colombier 		bprint(i, "%s\t(R%d+R%d)", m, i->rs1, i->rs2);
901*473d4f4bSDavid du Colombier 	else{
902*473d4f4bSDavid du Colombier 		bprint(i, "%s\t", m);
903*473d4f4bSDavid du Colombier 		address(i);
904*473d4f4bSDavid du Colombier 	}
905*473d4f4bSDavid du Colombier 	if(i->op3 == 0x21)
906*473d4f4bSDavid du Colombier 		bprint(i, ", FSR");
907*473d4f4bSDavid du Colombier 	else
908*473d4f4bSDavid du Colombier 		bprint(i, ", R%d", i->rd);
909*473d4f4bSDavid du Colombier }
910*473d4f4bSDavid du Colombier 
911*473d4f4bSDavid du Colombier static
storef(Instr * i,char * m)912*473d4f4bSDavid du Colombier void storef(Instr *i, char *m)		/* page 70 */
913*473d4f4bSDavid du Colombier {
914*473d4f4bSDavid du Colombier 	if(!dascase){
915*473d4f4bSDavid du Colombier 		m = "FMOVD";
916*473d4f4bSDavid du Colombier 		if(i->op3 == 0x25 || i->op3 == 0x26)
917*473d4f4bSDavid du Colombier 			m = "MOVW";
918*473d4f4bSDavid du Colombier 		else if(i->op3 == 0x20)
919*473d4f4bSDavid du Colombier 			m = "FMOVF";
920*473d4f4bSDavid du Colombier 	}
921*473d4f4bSDavid du Colombier 	bprint(i, "%s\t", m);
922*473d4f4bSDavid du Colombier 	if(i->op3 == 0x25)
923*473d4f4bSDavid du Colombier 		bprint(i, "FSR, ");
924*473d4f4bSDavid du Colombier 	else if(i->op3 == 0x26)
925*473d4f4bSDavid du Colombier 		bprint(i, "FQ, ");
926*473d4f4bSDavid du Colombier 	else
927*473d4f4bSDavid du Colombier 		bprint(i, "R%d, ", i->rd);
928*473d4f4bSDavid du Colombier 	if(i->i == 0)
929*473d4f4bSDavid du Colombier 		bprint(i, "(R%d+R%d)", i->rs1, i->rs2);
930*473d4f4bSDavid du Colombier 	else
931*473d4f4bSDavid du Colombier 		address(i);
932*473d4f4bSDavid du Colombier }
933*473d4f4bSDavid du Colombier 
934*473d4f4bSDavid du Colombier static
loadc(Instr * i,char * m)935*473d4f4bSDavid du Colombier void loadc(Instr *i, char *m)		/* page 72 */
936*473d4f4bSDavid du Colombier {
937*473d4f4bSDavid du Colombier 	if(i->i == 0)
938*473d4f4bSDavid du Colombier 		bprint(i, "%s\t(R%d+R%d), C%d", m, i->rs1, i->rs2, i->rd);
939*473d4f4bSDavid du Colombier 	else{
940*473d4f4bSDavid du Colombier 		bprint(i, "%s\t", m);
941*473d4f4bSDavid du Colombier 		address(i);
942*473d4f4bSDavid du Colombier 		bprint(i, ", C%d", i->rd);
943*473d4f4bSDavid du Colombier 	}
944*473d4f4bSDavid du Colombier }
945*473d4f4bSDavid du Colombier 
946*473d4f4bSDavid du Colombier static
loadcsr(Instr * i,char * m)947*473d4f4bSDavid du Colombier void loadcsr(Instr *i, char *m)		/* page 72 */
948*473d4f4bSDavid du Colombier {
949*473d4f4bSDavid du Colombier 	if(i->i == 0)
950*473d4f4bSDavid du Colombier 		bprint(i, "%s\t(R%d+R%d), CSR", m, i->rs1, i->rs2);
951*473d4f4bSDavid du Colombier 	else{
952*473d4f4bSDavid du Colombier 		bprint(i, "%s\t", m);
953*473d4f4bSDavid du Colombier 		address(i);
954*473d4f4bSDavid du Colombier 		bprint(i, ", CSR");
955*473d4f4bSDavid du Colombier 	}
956*473d4f4bSDavid du Colombier }
957*473d4f4bSDavid du Colombier 
958*473d4f4bSDavid du Colombier static struct{
959*473d4f4bSDavid du Colombier 	int	opf;
960*473d4f4bSDavid du Colombier 	char	*name;
961*473d4f4bSDavid du Colombier } fptab1[] = {				/* ignores rs1 */
962*473d4f4bSDavid du Colombier 	0xC4,	"FITOS",		/* page 109 */
963*473d4f4bSDavid du Colombier 	0xC8,	"FITOD",
964*473d4f4bSDavid du Colombier 	0xCC,	"FITOX",
965*473d4f4bSDavid du Colombier 
966*473d4f4bSDavid du Colombier 	0xD1,	"FSTOI",		/* page 110 */
967*473d4f4bSDavid du Colombier 	0xD2,	"FDTOI",
968*473d4f4bSDavid du Colombier 	0xD3,	"FXTOI",
969*473d4f4bSDavid du Colombier 
970*473d4f4bSDavid du Colombier 	0xC9,	"FSTOD",		/* page 111 */
971*473d4f4bSDavid du Colombier 	0xCD,	"FSTOX",
972*473d4f4bSDavid du Colombier 	0xC6,	"FDTOS",
973*473d4f4bSDavid du Colombier 	0xCE,	"FDTOX",
974*473d4f4bSDavid du Colombier 	0xC7,	"FXTOS",
975*473d4f4bSDavid du Colombier 	0xCB,	"FXTOD",
976*473d4f4bSDavid du Colombier 
977*473d4f4bSDavid du Colombier 	0x01,	"FMOVS",		/* page 112 */
978*473d4f4bSDavid du Colombier 	0x05,	"FNEGS",
979*473d4f4bSDavid du Colombier 	0x09,	"FABSS",
980*473d4f4bSDavid du Colombier 
981*473d4f4bSDavid du Colombier 	0x29,	"FSQRTS", 		/* page 113 */
982*473d4f4bSDavid du Colombier 	0x2A,	"FSQRTD",
983*473d4f4bSDavid du Colombier 	0x2B,	"FSQRTX",
984*473d4f4bSDavid du Colombier 
985*473d4f4bSDavid du Colombier 	0,	0,
986*473d4f4bSDavid du Colombier };
987*473d4f4bSDavid du Colombier 
988*473d4f4bSDavid du Colombier static struct{
989*473d4f4bSDavid du Colombier 	int	opf;
990*473d4f4bSDavid du Colombier 	char	*name;
991*473d4f4bSDavid du Colombier } fptab2[] = {				/* uses rs1 */
992*473d4f4bSDavid du Colombier 
993*473d4f4bSDavid du Colombier 	0x41,	"FADDS",		/* page 114 */
994*473d4f4bSDavid du Colombier 	0x42,	"FADDD",
995*473d4f4bSDavid du Colombier 	0x43,	"FADDX",
996*473d4f4bSDavid du Colombier 	0x45,	"FSUBS",
997*473d4f4bSDavid du Colombier 	0x46,	"FSUBD",
998*473d4f4bSDavid du Colombier 	0x47,	"FSUBX",
999*473d4f4bSDavid du Colombier 
1000*473d4f4bSDavid du Colombier 	0x49,	"FMULS",		/* page 115 */
1001*473d4f4bSDavid du Colombier 	0x4A,	"FMULD",
1002*473d4f4bSDavid du Colombier 	0x4B,	"FMULX",
1003*473d4f4bSDavid du Colombier 	0x4D,	"FDIVS",
1004*473d4f4bSDavid du Colombier 	0x4E,	"FDIVD",
1005*473d4f4bSDavid du Colombier 	0x4F,	"FDIVX",
1006*473d4f4bSDavid du Colombier 
1007*473d4f4bSDavid du Colombier 	0x51,	"FCMPS",		/* page 116 */
1008*473d4f4bSDavid du Colombier 	0x52,	"FCMPD",
1009*473d4f4bSDavid du Colombier 	0x53,	"FCMPX",
1010*473d4f4bSDavid du Colombier 	0x55,	"FCMPES",
1011*473d4f4bSDavid du Colombier 	0x56,	"FCMPED",
1012*473d4f4bSDavid du Colombier 	0x57,	"FCMPEX",
1013*473d4f4bSDavid du Colombier 
1014*473d4f4bSDavid du Colombier 	0, 0
1015*473d4f4bSDavid du Colombier };
1016*473d4f4bSDavid du Colombier 
1017*473d4f4bSDavid du Colombier static void
fpop(Instr * i,char * m)1018*473d4f4bSDavid du Colombier fpop(Instr *i, char *m)			/* page 108-116 */
1019*473d4f4bSDavid du Colombier {
1020*473d4f4bSDavid du Colombier 	int j;
1021*473d4f4bSDavid du Colombier 
1022*473d4f4bSDavid du Colombier 	if(dascase==0 && i->size==2){
1023*473d4f4bSDavid du Colombier 		bprint(i, "FMOVD\tF%d, F%d", i->rs2, i->rd);
1024*473d4f4bSDavid du Colombier 		return;
1025*473d4f4bSDavid du Colombier 	}
1026*473d4f4bSDavid du Colombier 	for(j=0; fptab1[j].name; j++)
1027*473d4f4bSDavid du Colombier 		if(fptab1[j].opf == i->opf){
1028*473d4f4bSDavid du Colombier 			bprint(i, "%T\tF%d, F%d", fptab1[j].name, i->rs2, i->rd);
1029*473d4f4bSDavid du Colombier 			return;
1030*473d4f4bSDavid du Colombier 		}
1031*473d4f4bSDavid du Colombier 	for(j=0; fptab2[j].name; j++)
1032*473d4f4bSDavid du Colombier 		if(fptab2[j].opf == i->opf){
1033*473d4f4bSDavid du Colombier 			bprint(i, "%T\tF%d, F%d, F%d", fptab2[j].name, i->rs1, i->rs2, i->rd);
1034*473d4f4bSDavid du Colombier 			return;
1035*473d4f4bSDavid du Colombier 		}
1036*473d4f4bSDavid du Colombier 	bprint(i, "%T%ux\tF%d, F%d, F%d", m, i->opf, i->rs1, i->rs2, i->rd);
1037*473d4f4bSDavid du Colombier }
1038*473d4f4bSDavid du Colombier 
1039*473d4f4bSDavid du Colombier static int
sparc64foll(Map * map,uvlong pc,Rgetter rget,uvlong * foll)1040*473d4f4bSDavid du Colombier sparc64foll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
1041*473d4f4bSDavid du Colombier {
1042*473d4f4bSDavid du Colombier 	ulong w, r1, r2;
1043*473d4f4bSDavid du Colombier 	char buf[8];
1044*473d4f4bSDavid du Colombier 	Instr i;
1045*473d4f4bSDavid du Colombier 
1046*473d4f4bSDavid du Colombier 	mymap = map;
1047*473d4f4bSDavid du Colombier 	if (mkinstr(pc, &i) < 0)
1048*473d4f4bSDavid du Colombier 		return -1;
1049*473d4f4bSDavid du Colombier 	w = i.w0;
1050*473d4f4bSDavid du Colombier 	switch(w & 0xC1C00000){
1051*473d4f4bSDavid du Colombier 	case 0x00800000:		/* branch on int cond */
1052*473d4f4bSDavid du Colombier 	case 0x01800000:		/* branch on fp cond */
1053*473d4f4bSDavid du Colombier 	case 0x01C00000:		/* branch on copr cond */
1054*473d4f4bSDavid du Colombier 		foll[0] = pc+8;
1055*473d4f4bSDavid du Colombier 		foll[1] = pc + (i.simmdisp22<<2);
1056*473d4f4bSDavid du Colombier 		return 2;
1057*473d4f4bSDavid du Colombier 	}
1058*473d4f4bSDavid du Colombier 
1059*473d4f4bSDavid du Colombier 	if((w&0xC0000000) == 0x40000000){	/* CALL */
1060*473d4f4bSDavid du Colombier 		foll[0] = pc + (i.disp30<<2);
1061*473d4f4bSDavid du Colombier 		return 1;
1062*473d4f4bSDavid du Colombier 	}
1063*473d4f4bSDavid du Colombier 
1064*473d4f4bSDavid du Colombier 	if((w&0xC1F80000) == 0x81C00000){	/* JMPL */
1065*473d4f4bSDavid du Colombier 		sprint(buf, "R%ld", (w>>14)&0xF);
1066*473d4f4bSDavid du Colombier 		r1 = (*rget)(map, buf);
1067*473d4f4bSDavid du Colombier 		if(w & 0x2000)			/* JMPL R1+simm13 */
1068*473d4f4bSDavid du Colombier 			r2 = i.simm13;
1069*473d4f4bSDavid du Colombier 		else{				/* JMPL R1+R2 */
1070*473d4f4bSDavid du Colombier 			sprint(buf, "R%ld", w&0xF);
1071*473d4f4bSDavid du Colombier 			r2 = (*rget)(map, buf);
1072*473d4f4bSDavid du Colombier 		}
1073*473d4f4bSDavid du Colombier 		foll[0] = r1 + r2;
1074*473d4f4bSDavid du Colombier 		return 1;
1075*473d4f4bSDavid du Colombier 	}
1076*473d4f4bSDavid du Colombier 	foll[0] = pc+i.size*4;
1077*473d4f4bSDavid du Colombier 	return 1;
1078*473d4f4bSDavid du Colombier }
1079