xref: /plan9/sys/src/libmach/kdb.c (revision 1bd2810994d48c5034925d24ca0b90739454b582)
1219b2ee8SDavid du Colombier #include <u.h>
2219b2ee8SDavid du Colombier #include <libc.h>
3219b2ee8SDavid du Colombier #include <bio.h>
4219b2ee8SDavid du Colombier #include <mach.h>
5219b2ee8SDavid du Colombier 
6219b2ee8SDavid du Colombier /*
7219b2ee8SDavid du Colombier  * Sparc-specific debugger interface
8219b2ee8SDavid du Colombier  */
9219b2ee8SDavid du Colombier 
10219b2ee8SDavid du Colombier static	char	*sparcexcep(Map*, Rgetter);
114de34a7eSDavid du Colombier static	int	sparcfoll(Map*, uvlong, Rgetter, uvlong*);
124de34a7eSDavid du Colombier static	int	sparcinst(Map*, uvlong, char, char*, int);
134de34a7eSDavid du Colombier static	int	sparcdas(Map*, uvlong, char*, int);
144de34a7eSDavid du Colombier static	int	sparcinstlen(Map*, uvlong);
15219b2ee8SDavid du Colombier 
16219b2ee8SDavid du Colombier Machdata sparcmach =
17219b2ee8SDavid du Colombier {
18219b2ee8SDavid du Colombier 	{0x91, 0xd0, 0x20, 0x01},	/* breakpoint: TA $1 */
19219b2ee8SDavid du Colombier 	4,			/* break point size */
20219b2ee8SDavid du Colombier 
21219b2ee8SDavid du Colombier 	beswab,			/* convert short to local byte order */
22219b2ee8SDavid du Colombier 	beswal,			/* convert long to local byte order */
237dd7cddfSDavid du Colombier 	beswav,			/* convert vlong to local byte order */
24219b2ee8SDavid du Colombier 	risctrace,		/* C traceback */
25219b2ee8SDavid du Colombier 	riscframe,		/* frame finder */
26219b2ee8SDavid du Colombier 	sparcexcep,		/* print exception */
27219b2ee8SDavid du Colombier 	0,			/* breakpoint fixup */
28219b2ee8SDavid du Colombier 	beieeesftos,		/* single precision float printer */
29219b2ee8SDavid du Colombier 	beieeedftos,		/* double precision float printer */
30219b2ee8SDavid du Colombier 	sparcfoll,		/* following addresses */
31219b2ee8SDavid du Colombier 	sparcinst,		/* print instruction */
32219b2ee8SDavid du Colombier 	sparcdas,		/* dissembler */
33219b2ee8SDavid du Colombier 	sparcinstlen,		/* instruction size */
34219b2ee8SDavid du Colombier };
35219b2ee8SDavid du Colombier 
36219b2ee8SDavid du Colombier static char *trapname[] =
37219b2ee8SDavid du Colombier {
38219b2ee8SDavid du Colombier 	"reset",
39219b2ee8SDavid du Colombier 	"instruction access exception",
40219b2ee8SDavid du Colombier 	"illegal instruction",
41219b2ee8SDavid du Colombier 	"privileged instruction",
42219b2ee8SDavid du Colombier 	"fp disabled",
43219b2ee8SDavid du Colombier 	"window overflow",
44219b2ee8SDavid du Colombier 	"window underflow",
45219b2ee8SDavid du Colombier 	"unaligned address",
46219b2ee8SDavid du Colombier 	"fp exception",
47219b2ee8SDavid du Colombier 	"data access exception",
48219b2ee8SDavid du Colombier 	"tag overflow",
49219b2ee8SDavid du Colombier };
50219b2ee8SDavid du Colombier 
51219b2ee8SDavid du Colombier static char*
excname(ulong tbr)52219b2ee8SDavid du Colombier excname(ulong tbr)
53219b2ee8SDavid du Colombier {
54219b2ee8SDavid du Colombier 	static char buf[32];
55219b2ee8SDavid du Colombier 
56219b2ee8SDavid du Colombier 	if(tbr < sizeof trapname/sizeof(char*))
57219b2ee8SDavid du Colombier 		return trapname[tbr];
58219b2ee8SDavid du Colombier 	if(tbr >= 130)
597dd7cddfSDavid du Colombier 		sprint(buf, "trap instruction %ld", tbr-128);
60219b2ee8SDavid du Colombier 	else if(17<=tbr && tbr<=31)
617dd7cddfSDavid du Colombier 		sprint(buf, "interrupt level %ld", tbr-16);
62219b2ee8SDavid du Colombier 	else switch(tbr){
63219b2ee8SDavid du Colombier 	case 36:
64219b2ee8SDavid du Colombier 		return "cp disabled";
65219b2ee8SDavid du Colombier 	case 40:
66219b2ee8SDavid du Colombier 		return "cp exception";
67219b2ee8SDavid du Colombier 	case 128:
68219b2ee8SDavid du Colombier 		return "syscall";
69219b2ee8SDavid du Colombier 	case 129:
70219b2ee8SDavid du Colombier 		return "breakpoint";
71219b2ee8SDavid du Colombier 	default:
727dd7cddfSDavid du Colombier 		sprint(buf, "unknown trap %ld", tbr);
73219b2ee8SDavid du Colombier 	}
74219b2ee8SDavid du Colombier 	return buf;
75219b2ee8SDavid du Colombier }
76219b2ee8SDavid du Colombier 
77219b2ee8SDavid du Colombier static char*
sparcexcep(Map * map,Rgetter rget)78219b2ee8SDavid du Colombier sparcexcep(Map *map, Rgetter rget)
79219b2ee8SDavid du Colombier {
80219b2ee8SDavid du Colombier 	long tbr;
81219b2ee8SDavid du Colombier 
82219b2ee8SDavid du Colombier 	tbr = (*rget)(map, "TBR");
83219b2ee8SDavid du Colombier 	tbr = (tbr&0xFFF)>>4;
84219b2ee8SDavid du Colombier 	return excname(tbr);
85219b2ee8SDavid du Colombier }
86219b2ee8SDavid du Colombier 
87219b2ee8SDavid du Colombier 	/* Sparc disassembler and related functions */
88219b2ee8SDavid du Colombier 
89219b2ee8SDavid du Colombier struct opcode {
90219b2ee8SDavid du Colombier 	char	*mnemonic;
91219b2ee8SDavid du Colombier 	void	(*f)(struct instr*, char*);
92219b2ee8SDavid du Colombier 	int	flag;
93219b2ee8SDavid du Colombier };
94219b2ee8SDavid du Colombier 
95219b2ee8SDavid du Colombier static	char FRAMENAME[] = ".frame";
96219b2ee8SDavid du Colombier 
97219b2ee8SDavid du Colombier typedef struct instr Instr;
98219b2ee8SDavid du Colombier 
99219b2ee8SDavid du Colombier struct instr {
100219b2ee8SDavid du Colombier 	uchar	op;		/* bits 31-30 */
101219b2ee8SDavid du Colombier 	uchar	rd;		/* bits 29-25 */
102219b2ee8SDavid du Colombier 	uchar	op2;		/* bits 24-22 */
103219b2ee8SDavid du Colombier 	uchar	a;		/* bit  29    */
104219b2ee8SDavid du Colombier 	uchar	cond;		/* bits 28-25 */
105219b2ee8SDavid du Colombier 	uchar	op3;		/* bits 24-19 */
106219b2ee8SDavid du Colombier 	uchar	rs1;		/* bits 18-14 */
107219b2ee8SDavid du Colombier 	uchar	i;		/* bit  13    */
108219b2ee8SDavid du Colombier 	uchar	asi;		/* bits 12-05 */
109219b2ee8SDavid du Colombier 	uchar	rs2;		/* bits 04-00 */
110219b2ee8SDavid du Colombier 	short	simm13;		/* bits 12-00, signed */
111219b2ee8SDavid du Colombier 	ushort	opf;		/* bits 13-05 */
112219b2ee8SDavid du Colombier 	ulong	immdisp22;	/* bits 21-00 */
113219b2ee8SDavid du Colombier 	ulong	simmdisp22;	/* bits 21-00, signed */
114219b2ee8SDavid du Colombier 	ulong	disp30;		/* bits 30-00 */
115219b2ee8SDavid du Colombier 	ulong	imm32;		/* SETHI+ADD constant */
116219b2ee8SDavid du Colombier 	int	target;		/* SETHI+ADD dest reg */
117219b2ee8SDavid du Colombier 	long	w0;
118219b2ee8SDavid du Colombier 	long	w1;
1194de34a7eSDavid du Colombier 	uvlong	addr;		/* pc of instruction */
120219b2ee8SDavid du Colombier 	char	*curr;		/* current fill level in output buffer */
121219b2ee8SDavid du Colombier 	char	*end;		/* end of buffer */
122219b2ee8SDavid du Colombier 	int 	size;		/* number of longs in instr */
123219b2ee8SDavid du Colombier 	char	*err;		/* errmsg */
124219b2ee8SDavid du Colombier };
125219b2ee8SDavid du Colombier 
126219b2ee8SDavid du Colombier static	Map	*mymap;		/* disassembler context */
127219b2ee8SDavid du Colombier static	int	dascase;
128219b2ee8SDavid du Colombier 
1294de34a7eSDavid du Colombier static int	mkinstr(uvlong, Instr*);
130219b2ee8SDavid du Colombier static void	bra1(Instr*, char*, char*[]);
131219b2ee8SDavid du Colombier static void	bra(Instr*, char*);
132219b2ee8SDavid du Colombier static void	fbra(Instr*, char*);
133219b2ee8SDavid du Colombier static void	cbra(Instr*, char*);
134219b2ee8SDavid du Colombier static void	unimp(Instr*, char*);
135219b2ee8SDavid du Colombier static void	fpop(Instr*, char*);
136219b2ee8SDavid du Colombier static void	shift(Instr*, char*);
137219b2ee8SDavid du Colombier static void	sethi(Instr*, char*);
138219b2ee8SDavid du Colombier static void	load(Instr*, char*);
139219b2ee8SDavid du Colombier static void	loada(Instr*, char*);
140219b2ee8SDavid du Colombier static void	store(Instr*, char*);
141219b2ee8SDavid du Colombier static void	storea(Instr*, char*);
142219b2ee8SDavid du Colombier static void	add(Instr*, char*);
143219b2ee8SDavid du Colombier static void	cmp(Instr*, char*);
144219b2ee8SDavid du Colombier static void	wr(Instr*, char*);
145219b2ee8SDavid du Colombier static void	jmpl(Instr*, char*);
146219b2ee8SDavid du Colombier static void	rd(Instr*, char*);
147219b2ee8SDavid du Colombier static void	loadf(Instr*, char*);
148219b2ee8SDavid du Colombier static void	storef(Instr*, char*);
149219b2ee8SDavid du Colombier static void	loadc(Instr*, char*);
150219b2ee8SDavid du Colombier static void	loadcsr(Instr*, char*);
151219b2ee8SDavid du Colombier static void	trap(Instr*, char*);
152219b2ee8SDavid du Colombier 
153219b2ee8SDavid du Colombier static struct opcode sparcop0[8] = {
154219b2ee8SDavid du Colombier 	[0]	"UNIMP",	unimp,	0,	/* page 137 */
155219b2ee8SDavid du Colombier 	[2]	"B",		bra,	0,	/* page 119 */
156219b2ee8SDavid du Colombier 	[4]	"SETHI",	sethi,	0,	/* page 104 */
157219b2ee8SDavid du Colombier 	[6]	"FB",		fbra,	0,	/* page 121 */
158219b2ee8SDavid du Colombier 	[7]	"CB",		cbra,	0,	/* page 123 */
159219b2ee8SDavid du Colombier };
160219b2ee8SDavid du Colombier 
161219b2ee8SDavid du Colombier static struct opcode sparcop2[64] = {
162219b2ee8SDavid du Colombier 	[0x00]	"ADD",		add,	0,	/* page 108 */
163219b2ee8SDavid du Colombier 	[0x10]	"ADDCC",	add,	0,
164219b2ee8SDavid du Colombier 	[0x08]	"ADDX",		add,	0,
165219b2ee8SDavid du Colombier 	[0x18]	"ADDXCC",	add,	0,
166219b2ee8SDavid du Colombier 
167219b2ee8SDavid du Colombier 	[0x20]	"TADD",		add,	0,	/* page 109 */
168219b2ee8SDavid du Colombier 	[0x22]	"TADDCCTV",	add,	0,
169219b2ee8SDavid du Colombier 
170219b2ee8SDavid du Colombier 	[0x04]	"SUB",		add,	0,	/* page 110 */
171219b2ee8SDavid du Colombier 	[0x14]	"SUBCC",	cmp,	0,
172219b2ee8SDavid du Colombier 	[0x0C]	"SUBX",		add,	0,
173219b2ee8SDavid du Colombier 	[0x1C]	"SUBXCC",	add,	0,
174219b2ee8SDavid du Colombier 
175219b2ee8SDavid du Colombier 	[0x21]	"TSUB",		add,	0,	/* page 111 */
176219b2ee8SDavid du Colombier 	[0x23]	"TSUBCCTV",	add,	0,
177219b2ee8SDavid du Colombier 
178219b2ee8SDavid du Colombier 	[0x24]	"MULSCC",	add,	0,	/* page 112 */
179219b2ee8SDavid du Colombier 
180219b2ee8SDavid du Colombier 	[0x0A]	"UMUL",		add,	0,	/* page 113 */
181219b2ee8SDavid du Colombier 	[0x0B]	"SMUL",		add,	0,
182219b2ee8SDavid du Colombier 	[0x1A]	"UMULCC",	add,	0,
183219b2ee8SDavid du Colombier 	[0x1B]	"SMULCC",	add,	0,
184219b2ee8SDavid du Colombier 
185219b2ee8SDavid du Colombier 	[0x0E]	"UDIV",		add,	0,	/* page 115 */
186219b2ee8SDavid du Colombier 	[0x0F]	"SDIV",		add,	0,
187219b2ee8SDavid du Colombier 	[0x1E]	"UDIVCC",	add,	0,
188219b2ee8SDavid du Colombier 	[0x1F]	"SDIVCC",	add,	0,
189219b2ee8SDavid du Colombier 
190219b2ee8SDavid du Colombier 	[0x01]	"AND",		add,	0,	/* page 106 */
191219b2ee8SDavid du Colombier 	[0x11]	"ANDCC",	add,	0,
192219b2ee8SDavid du Colombier 	[0x05]	"ANDN",		add,	0,
193219b2ee8SDavid du Colombier 	[0x15]	"ANDNCC",	add,	0,
194219b2ee8SDavid du Colombier 	[0x02]	"OR",		add,	0,
195219b2ee8SDavid du Colombier 	[0x12]	"ORCC",		add,	0,
196219b2ee8SDavid du Colombier 	[0x06]	"ORN",		add,	0,
197219b2ee8SDavid du Colombier 	[0x16]	"ORNCC",	add,	0,
198219b2ee8SDavid du Colombier 	[0x03]	"XOR",		add,	0,
199219b2ee8SDavid du Colombier 	[0x13]	"XORCC",	add,	0,
200219b2ee8SDavid du Colombier 	[0x07]	"XORN",		add,	0,
201219b2ee8SDavid du Colombier 	[0x17]	"XORNCC",	add,	0,
202219b2ee8SDavid du Colombier 
203219b2ee8SDavid du Colombier 	[0x25]	"SLL",		shift,	0,	/* page 107 */
204219b2ee8SDavid du Colombier 	[0x26]	"SRL",		shift,	0,
205219b2ee8SDavid du Colombier 	[0x27]	"SRA",		shift,	0,
206219b2ee8SDavid du Colombier 
207219b2ee8SDavid du Colombier 	[0x3C]	"SAVE",		add,	0,	/* page 117 */
208219b2ee8SDavid du Colombier 	[0x3D]	"RESTORE",	add,	0,
209219b2ee8SDavid du Colombier 
210219b2ee8SDavid du Colombier 	[0x38]	"JMPL",		jmpl,	0,	/* page 126 */
211219b2ee8SDavid du Colombier 
212219b2ee8SDavid du Colombier 	[0x39]	"RETT",		add,	0,	/* page 127 */
213219b2ee8SDavid du Colombier 
214219b2ee8SDavid du Colombier 	[0x3A]	"T",		trap,	0,	/* page 129 */
215219b2ee8SDavid du Colombier 
216219b2ee8SDavid du Colombier 	[0x28]	"rdy",		rd,	0,	/* page 131 */
217219b2ee8SDavid du Colombier 	[0x29]	"rdpsr",	rd,	0,
218219b2ee8SDavid du Colombier 	[0x2A]	"rdwim",	rd,	0,
219219b2ee8SDavid du Colombier 	[0x2B]	"rdtbr",	rd,	0,
220219b2ee8SDavid du Colombier 
221219b2ee8SDavid du Colombier 	[0x30]	"wry",		wr,	0,	/* page 133 */
222219b2ee8SDavid du Colombier 	[0x31]	"wrpsr",	wr,	0,
223219b2ee8SDavid du Colombier 	[0x32]	"wrwim",	wr,	0,
224219b2ee8SDavid du Colombier 	[0x33]	"wrtbr",	wr,	0,
225219b2ee8SDavid du Colombier 
226219b2ee8SDavid du Colombier 	[0x3B]	"flush",	add,	0,	/* page 138 */
227219b2ee8SDavid du Colombier 
228219b2ee8SDavid du Colombier 	[0x34]	"FPOP",		fpop,	0,	/* page 140 */
229219b2ee8SDavid du Colombier 	[0x35]	"FPOP",		fpop,	0,
230219b2ee8SDavid du Colombier };
231219b2ee8SDavid du Colombier 
232219b2ee8SDavid du Colombier static struct opcode sparcop3[64]={
233219b2ee8SDavid du Colombier 	[0x09]	"ldsb",		load,	0,	/* page 90 */
234219b2ee8SDavid du Colombier 	[0x19]	"ldsba",	loada,	0,
235219b2ee8SDavid du Colombier 	[0x0A]	"ldsh",		load,	0,
236219b2ee8SDavid du Colombier 	[0x1A]	"ldsha",	loada,	0,
237219b2ee8SDavid du Colombier 	[0x01]	"ldub",		load,	0,
238219b2ee8SDavid du Colombier 	[0x11]	"lduba",	loada,	0,
239219b2ee8SDavid du Colombier 	[0x02]	"lduh",		load,	0,
240219b2ee8SDavid du Colombier 	[0x12]	"lduha",	loada,	0,
241219b2ee8SDavid du Colombier 	[0x00]	"ld",		load,	0,
242219b2ee8SDavid du Colombier 	[0x10]	"lda",		loada,	0,
243219b2ee8SDavid du Colombier 	[0x03]	"ldd",		load,	0,
244219b2ee8SDavid du Colombier 	[0x13]	"ldda",		loada,	0,
245219b2ee8SDavid du Colombier 
246219b2ee8SDavid du Colombier 	[0x20]	"ldf",		loadf,	0,	/* page 92 */
247219b2ee8SDavid du Colombier 	[0x23]	"lddf",		loadf,	0,
248219b2ee8SDavid du Colombier 	[0x21]	"ldfsr",	loadf,0,
249219b2ee8SDavid du Colombier 
250219b2ee8SDavid du Colombier 	[0x30]	"ldc",		loadc,	0,	/* page 94 */
251219b2ee8SDavid du Colombier 	[0x33]	"lddc",		loadc,	0,
252219b2ee8SDavid du Colombier 	[0x31]	"ldcsr",	loadcsr,0,
253219b2ee8SDavid du Colombier 
254219b2ee8SDavid du Colombier 	[0x05]	"stb",		store,	0,	/* page 95 */
255219b2ee8SDavid du Colombier 	[0x15]	"stba",		storea,	0,
256219b2ee8SDavid du Colombier 	[0x06]	"sth",		store,	0,
257219b2ee8SDavid du Colombier 	[0x16]	"stha",		storea,	0,
258219b2ee8SDavid du Colombier 	[0x04]	"st",		store,	0,
259219b2ee8SDavid du Colombier 	[0x14]	"sta",		storea,	0,
260219b2ee8SDavid du Colombier 	[0x07]	"std",		store,	0,
261219b2ee8SDavid du Colombier 	[0x17]	"stda",		storea,	0,
262219b2ee8SDavid du Colombier 
263219b2ee8SDavid du Colombier 	[0x24]	"stf",		storef,	0,	/* page 97 */
264219b2ee8SDavid du Colombier 	[0x27]	"stdf",		storef,	0,
265219b2ee8SDavid du Colombier 	[0x25]	"stfsr",	storef,0,
266219b2ee8SDavid du Colombier 	[0x26]	"stdfq",	storef,0,
267219b2ee8SDavid du Colombier 
268219b2ee8SDavid du Colombier 	[0x34]	"stc",		loadc,	0,	/* page 99 */
269219b2ee8SDavid du Colombier 	[0x37]	"stdc",		loadc,	0,
270219b2ee8SDavid du Colombier 	[0x35]	"stcsr",	loadcsr,0,
271219b2ee8SDavid du Colombier 	[0x36]	"stdcq",	loadcsr,0,
272219b2ee8SDavid du Colombier 
273219b2ee8SDavid du Colombier 	[0x0D]	"ldstub",	store,	0,	/* page 101 */
274219b2ee8SDavid du Colombier 	[0x1D]	"ldstuba",	storea,	0,
275219b2ee8SDavid du Colombier 
276219b2ee8SDavid du Colombier 	[0x0F]	"swap",		load,	0,	/* page 102 */
277219b2ee8SDavid du Colombier 	[0x1F]	"swapa",	loada,	0,
278219b2ee8SDavid du Colombier };
279219b2ee8SDavid du Colombier 
280*1bd28109SDavid du Colombier #pragma	varargck	argpos	bprint	2
281*1bd28109SDavid du Colombier #pragma	varargck	type	"T"	char*
282*1bd28109SDavid du Colombier 
283*1bd28109SDavid du Colombier /* convert to lower case from upper, according to dascase */
284*1bd28109SDavid du Colombier static int
Tfmt(Fmt * f)285*1bd28109SDavid du Colombier Tfmt(Fmt *f)
286*1bd28109SDavid du Colombier {
287*1bd28109SDavid du Colombier 	char buf[128];
288*1bd28109SDavid du Colombier 	char *s, *t, *oa;
289*1bd28109SDavid du Colombier 
290*1bd28109SDavid du Colombier 	oa = va_arg(f->args, char*);
291*1bd28109SDavid du Colombier 	if(dascase){
292*1bd28109SDavid du Colombier 		for(s=oa,t=buf; *t = *s; s++,t++)
293*1bd28109SDavid du Colombier 			if('A'<=*t && *t<='Z')
294*1bd28109SDavid du Colombier 				*t += 'a'-'A';
295*1bd28109SDavid du Colombier 		return fmtstrcpy(f, buf);
296*1bd28109SDavid du Colombier 	}
297*1bd28109SDavid du Colombier 	return fmtstrcpy(f, oa);
298*1bd28109SDavid du Colombier }
299*1bd28109SDavid du Colombier 
300219b2ee8SDavid du Colombier static void
bprint(Instr * i,char * fmt,...)301219b2ee8SDavid du Colombier bprint(Instr *i, char *fmt, ...)
302219b2ee8SDavid du Colombier {
3037dd7cddfSDavid du Colombier 	va_list arg;
3047dd7cddfSDavid du Colombier 
3057dd7cddfSDavid du Colombier 	va_start(arg, fmt);
3069a747e4fSDavid du Colombier 	i->curr = vseprint(i->curr, i->end, fmt, arg);
3077dd7cddfSDavid du Colombier 	va_end(arg);
308219b2ee8SDavid du Colombier }
309219b2ee8SDavid du Colombier 
310219b2ee8SDavid du Colombier static int
decode(uvlong pc,Instr * i)3114de34a7eSDavid du Colombier decode(uvlong pc, Instr *i)
312219b2ee8SDavid du Colombier {
3134de34a7eSDavid du Colombier 	ulong w;
314219b2ee8SDavid du Colombier 
315219b2ee8SDavid du Colombier 	if (get4(mymap, pc, &w) < 0) {
316219b2ee8SDavid du Colombier 		werrstr("can't read instruction: %r");
317219b2ee8SDavid du Colombier 		return -1;
318219b2ee8SDavid du Colombier 	}
319219b2ee8SDavid du Colombier 	i->op = (w >> 30) & 0x03;
320219b2ee8SDavid du Colombier 	i->rd = (w >> 25) & 0x1F;
321219b2ee8SDavid du Colombier 	i->op2 = (w >> 22) & 0x07;
322219b2ee8SDavid du Colombier 	i->a = (w >> 29) & 0x01;
323219b2ee8SDavid du Colombier 	i->cond = (w >> 25) & 0x0F;
324219b2ee8SDavid du Colombier 	i->op3 = (w >> 19) & 0x3F;
325219b2ee8SDavid du Colombier 	i->rs1 = (w >> 14) & 0x1F;
326219b2ee8SDavid du Colombier 	i->i = (w >> 13) & 0x01;
327219b2ee8SDavid du Colombier 	i->asi = (w >> 5) & 0xFF;
328219b2ee8SDavid du Colombier 	i->rs2 = (w >> 0) & 0x1F;
329219b2ee8SDavid du Colombier 	i->simm13 = (w >> 0) & 0x1FFF;
330219b2ee8SDavid du Colombier 	if(i->simm13 & (1<<12))
331219b2ee8SDavid du Colombier 		i->simm13 |= ~((1<<13)-1);
332219b2ee8SDavid du Colombier 	i->opf = (w >> 5) & 0x1FF;
333219b2ee8SDavid du Colombier 	i->immdisp22 = (w >> 0) & 0x3FFFFF;
334219b2ee8SDavid du Colombier 	i->simmdisp22 = i->immdisp22;
335219b2ee8SDavid du Colombier 	if(i->simmdisp22 & (1<<21))
336219b2ee8SDavid du Colombier 		i->simmdisp22 |= ~((1<<22)-1);
337219b2ee8SDavid du Colombier 	i->disp30 = (w >> 0) & 0x3FFFFFFF;
338219b2ee8SDavid du Colombier 	i->w0 = w;
339219b2ee8SDavid du Colombier 	i->target = -1;
340219b2ee8SDavid du Colombier 	i->addr = pc;
341219b2ee8SDavid du Colombier 	i->size = 1;
342219b2ee8SDavid du Colombier 	return 1;
343219b2ee8SDavid du Colombier }
344219b2ee8SDavid du Colombier 
345219b2ee8SDavid du Colombier static int
mkinstr(uvlong pc,Instr * i)3464de34a7eSDavid du Colombier mkinstr(uvlong pc, Instr *i)
347219b2ee8SDavid du Colombier {
348219b2ee8SDavid du Colombier 	Instr xi;
349219b2ee8SDavid du Colombier 
350219b2ee8SDavid du Colombier 	if (decode(pc, i) < 0)
351219b2ee8SDavid du Colombier 		return -1;
352219b2ee8SDavid du Colombier 	if(i->op==0 && i->op2==4 && !dascase){	/* SETHI */
353219b2ee8SDavid du Colombier 		if (decode(pc+4, &xi) < 0)
354219b2ee8SDavid du Colombier 			return -1;
355219b2ee8SDavid du Colombier 		if(xi.op==2 && xi.op3==0)		/* ADD */
356219b2ee8SDavid du Colombier 		if(xi.i == 1 && xi.rs1 == i->rd){	/* immediate to same reg */
357219b2ee8SDavid du Colombier 			i->imm32 = xi.simm13 + (i->immdisp22<<10);
358219b2ee8SDavid du Colombier 			i->target = xi.rd;
359219b2ee8SDavid du Colombier 			i->w1 = xi.w0;
360219b2ee8SDavid du Colombier 			i->size++;
361219b2ee8SDavid du Colombier 			return 1;
362219b2ee8SDavid du Colombier 		}
363219b2ee8SDavid du Colombier 	}
364219b2ee8SDavid du Colombier 	if(i->op==2 && i->opf==1 && !dascase){	/* FMOVS */
365219b2ee8SDavid du Colombier 		if (decode(pc+4, &xi) < 0)
366219b2ee8SDavid du Colombier 			return -1;
367219b2ee8SDavid du Colombier 		if(i->op==2 && i->opf==1)		/* FMOVS */
368219b2ee8SDavid du Colombier 		if(xi.rd==i->rd+1 && xi.rs2==i->rs2+1){	/* next pair */
369219b2ee8SDavid du Colombier 			i->w1 = xi.w0;
370219b2ee8SDavid du Colombier 			i->size++;
371219b2ee8SDavid du Colombier 		}
372219b2ee8SDavid du Colombier 	}
373219b2ee8SDavid du Colombier 	return 1;
374219b2ee8SDavid du Colombier }
375219b2ee8SDavid du Colombier 
376219b2ee8SDavid du Colombier static int
printins(Map * map,uvlong pc,char * buf,int n)3774de34a7eSDavid du Colombier printins(Map *map, uvlong pc, char *buf, int n)
378219b2ee8SDavid du Colombier {
379219b2ee8SDavid du Colombier 	Instr instr;
380219b2ee8SDavid du Colombier 	void (*f)(Instr*, char*);
381219b2ee8SDavid du Colombier 
382219b2ee8SDavid du Colombier 	mymap = map;
383219b2ee8SDavid du Colombier 	memset(&instr, 0, sizeof(instr));
384219b2ee8SDavid du Colombier 	instr.curr = buf;
385219b2ee8SDavid du Colombier 	instr.end = buf+n-1;
386219b2ee8SDavid du Colombier 	if (mkinstr(pc, &instr) < 0)
387219b2ee8SDavid du Colombier 		return -1;
388219b2ee8SDavid du Colombier 	switch(instr.op){
389219b2ee8SDavid du Colombier 	case 0:
390219b2ee8SDavid du Colombier 		f = sparcop0[instr.op2].f;
391219b2ee8SDavid du Colombier 		if(f)
392219b2ee8SDavid du Colombier 			(*f)(&instr, sparcop0[instr.op2].mnemonic);
393219b2ee8SDavid du Colombier 		else
394219b2ee8SDavid du Colombier 			bprint(&instr, "unknown %lux", instr.w0);
395219b2ee8SDavid du Colombier 		break;
396219b2ee8SDavid du Colombier 
397219b2ee8SDavid du Colombier 	case 1:
398*1bd28109SDavid du Colombier 		bprint(&instr, "%T", "CALL\t");
399219b2ee8SDavid du Colombier 		instr.curr += symoff(instr.curr, instr.end-instr.curr,
400219b2ee8SDavid du Colombier 					pc+instr.disp30*4, CTEXT);
401219b2ee8SDavid du Colombier 		if (!dascase)
402219b2ee8SDavid du Colombier 			bprint(&instr, "(SB)");
403219b2ee8SDavid du Colombier 		break;
404219b2ee8SDavid du Colombier 
405219b2ee8SDavid du Colombier 	case 2:
406219b2ee8SDavid du Colombier 		f = sparcop2[instr.op3].f;
407219b2ee8SDavid du Colombier 		if(f)
408219b2ee8SDavid du Colombier 			(*f)(&instr, sparcop2[instr.op3].mnemonic);
409219b2ee8SDavid du Colombier 		else
410219b2ee8SDavid du Colombier 			bprint(&instr, "unknown %lux", instr.w0);
411219b2ee8SDavid du Colombier 		break;
412219b2ee8SDavid du Colombier 
413219b2ee8SDavid du Colombier 	case 3:
414219b2ee8SDavid du Colombier 		f = sparcop3[instr.op3].f;
415219b2ee8SDavid du Colombier 		if(f)
416219b2ee8SDavid du Colombier 			(*f)(&instr, sparcop3[instr.op3].mnemonic);
417219b2ee8SDavid du Colombier 		else
418219b2ee8SDavid du Colombier 			bprint(&instr, "unknown %lux", instr.w0);
419219b2ee8SDavid du Colombier 		break;
420219b2ee8SDavid du Colombier 	}
421219b2ee8SDavid du Colombier 	if (instr.err) {
422219b2ee8SDavid du Colombier 		if (instr.curr != buf)
423219b2ee8SDavid du Colombier 			bprint(&instr, "\t\t;");
424219b2ee8SDavid du Colombier 		bprint(&instr, instr.err);
425219b2ee8SDavid du Colombier 	}
426219b2ee8SDavid du Colombier 	return instr.size*4;
427219b2ee8SDavid du Colombier }
428219b2ee8SDavid du Colombier 
429219b2ee8SDavid du Colombier static int
sparcinst(Map * map,uvlong pc,char modifier,char * buf,int n)4304de34a7eSDavid du Colombier sparcinst(Map *map, uvlong pc, char modifier, char *buf, int n)
431219b2ee8SDavid du Colombier {
432219b2ee8SDavid du Colombier 	static int fmtinstalled = 0;
433219b2ee8SDavid du Colombier 
434219b2ee8SDavid du Colombier 		/* a modifier of 'I' toggles the dissassembler type */
435219b2ee8SDavid du Colombier 	if (!fmtinstalled) {
436219b2ee8SDavid du Colombier 		fmtinstalled = 1;
437*1bd28109SDavid du Colombier 		fmtinstall('T', Tfmt);
438219b2ee8SDavid du Colombier 	}
439219b2ee8SDavid du Colombier 	if ((asstype == ASUNSPARC && modifier == 'i')
440219b2ee8SDavid du Colombier 		|| (asstype == ASPARC && modifier == 'I'))
441219b2ee8SDavid du Colombier 		dascase = 'a'-'A';
442219b2ee8SDavid du Colombier 	else
443219b2ee8SDavid du Colombier 		dascase = 0;
444219b2ee8SDavid du Colombier 	return printins(map, pc, buf, n);
445219b2ee8SDavid du Colombier }
446219b2ee8SDavid du Colombier 
447219b2ee8SDavid du Colombier static int
sparcdas(Map * map,uvlong pc,char * buf,int n)4484de34a7eSDavid du Colombier sparcdas(Map *map, uvlong pc, char *buf, int n)
449219b2ee8SDavid du Colombier {
450219b2ee8SDavid du Colombier 	Instr instr;
451219b2ee8SDavid du Colombier 
452219b2ee8SDavid du Colombier 	mymap = map;
453219b2ee8SDavid du Colombier 	memset(&instr, 0, sizeof(instr));
454219b2ee8SDavid du Colombier 	instr.curr = buf;
455219b2ee8SDavid du Colombier 	instr.end = buf+n-1;
456219b2ee8SDavid du Colombier 	if (mkinstr(pc, &instr) < 0)
457219b2ee8SDavid du Colombier 		return -1;
458219b2ee8SDavid du Colombier 	if (instr.end-instr.curr > 8)
459219b2ee8SDavid du Colombier 		instr.curr = _hexify(instr.curr, instr.w0, 7);
460219b2ee8SDavid du Colombier 	if (instr.end-instr.curr > 9 && instr.size == 2) {
461219b2ee8SDavid du Colombier 		*instr.curr++ = ' ';
462219b2ee8SDavid du Colombier 		instr.curr = _hexify(instr.curr, instr.w1, 7);
463219b2ee8SDavid du Colombier 	}
464219b2ee8SDavid du Colombier 	*instr.curr = 0;
465219b2ee8SDavid du Colombier 	return instr.size*4;
466219b2ee8SDavid du Colombier }
467219b2ee8SDavid du Colombier 
468219b2ee8SDavid du Colombier static int
sparcinstlen(Map * map,uvlong pc)4694de34a7eSDavid du Colombier sparcinstlen(Map *map, uvlong pc)
470219b2ee8SDavid du Colombier {
471219b2ee8SDavid du Colombier 	Instr i;
472219b2ee8SDavid du Colombier 
473219b2ee8SDavid du Colombier 	mymap = map;
474219b2ee8SDavid du Colombier 	if (mkinstr(pc, &i) < 0)
475219b2ee8SDavid du Colombier 		return -1;
476219b2ee8SDavid du Colombier 	return i.size*4;
477219b2ee8SDavid du Colombier }
478219b2ee8SDavid du Colombier 
479219b2ee8SDavid du Colombier static int
plocal(Instr * i)480219b2ee8SDavid du Colombier plocal(Instr *i)
481219b2ee8SDavid du Colombier {
482219b2ee8SDavid du Colombier 	int offset;
483219b2ee8SDavid du Colombier 	Symbol s;
484219b2ee8SDavid du Colombier 
485219b2ee8SDavid du Colombier 	if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
486219b2ee8SDavid du Colombier 		return -1;
487219b2ee8SDavid du Colombier 	if (s.value > i->simm13) {
488219b2ee8SDavid du Colombier 		if(getauto(&s, s.value-i->simm13, CAUTO, &s)) {
489*1bd28109SDavid du Colombier 			bprint(i, "%s+%lld(SP)", s.name, s.value);
490219b2ee8SDavid du Colombier 			return 1;
491219b2ee8SDavid du Colombier 		}
492219b2ee8SDavid du Colombier 	} else {
493219b2ee8SDavid du Colombier 		offset = i->simm13-s.value;
494219b2ee8SDavid du Colombier 		if (getauto(&s, offset-4, CPARAM, &s)) {
495219b2ee8SDavid du Colombier 			bprint(i, "%s+%d(FP)", s.name, offset);
496219b2ee8SDavid du Colombier 			return 1;
497219b2ee8SDavid du Colombier 		}
498219b2ee8SDavid du Colombier 	}
499219b2ee8SDavid du Colombier 	return -1;
500219b2ee8SDavid du Colombier }
501219b2ee8SDavid du Colombier 
502219b2ee8SDavid du Colombier static void
address(Instr * i)503219b2ee8SDavid du Colombier address(Instr *i)
504219b2ee8SDavid du Colombier {
505219b2ee8SDavid du Colombier 	Symbol s, s2;
5064de34a7eSDavid du Colombier 	uvlong off, off1;
507219b2ee8SDavid du Colombier 
508219b2ee8SDavid du Colombier 	if (i->rs1 == 1 && plocal(i) >= 0)
509219b2ee8SDavid du Colombier 		return;
510219b2ee8SDavid du Colombier 	off = mach->sb+i->simm13;
511219b2ee8SDavid du Colombier 	if(i->rs1 == 2	&& findsym(off, CANY, &s)
512219b2ee8SDavid du Colombier 			&& s.value-off < 4096
513219b2ee8SDavid du Colombier 			&& (s.class == CDATA || s.class == CTEXT)) {
514219b2ee8SDavid du Colombier 		if(off==s.value && s.name[0]=='$'){
515219b2ee8SDavid du Colombier 			off1 = 0;
5164de34a7eSDavid du Colombier 			geta(mymap, s.value, &off1);
517219b2ee8SDavid du Colombier 			if(off1 && findsym(off1, CANY, &s2) && s2.value == off1){
518219b2ee8SDavid du Colombier 				bprint(i, "$%s(SB)", s2.name);
519219b2ee8SDavid du Colombier 				return;
520219b2ee8SDavid du Colombier 			}
521219b2ee8SDavid du Colombier 		}
522219b2ee8SDavid du Colombier 		bprint(i, "%s", s.name);
523219b2ee8SDavid du Colombier 		if (s.value != off)
524*1bd28109SDavid du Colombier 			bprint(i, "+%llux", s.value-off);
525219b2ee8SDavid du Colombier 		bprint(i, "(SB)");
526219b2ee8SDavid du Colombier 		return;
527219b2ee8SDavid du Colombier 	}
528*1bd28109SDavid du Colombier 	bprint(i, "%ux(R%d)", i->simm13, i->rs1);
529219b2ee8SDavid du Colombier }
530219b2ee8SDavid du Colombier 
531219b2ee8SDavid du Colombier static void
unimp(Instr * i,char * m)532219b2ee8SDavid du Colombier unimp(Instr *i, char *m)
533219b2ee8SDavid du Colombier {
534*1bd28109SDavid du Colombier 	bprint(i, "%T", m);
535219b2ee8SDavid du Colombier }
536219b2ee8SDavid du Colombier 
537219b2ee8SDavid du Colombier static char	*bratab[16] = {	/* page 91 */
538219b2ee8SDavid du Colombier 	[0X8]	"A",
539219b2ee8SDavid du Colombier 	[0X0]	"N",
540219b2ee8SDavid du Colombier 	[0X9]	"NE",
541219b2ee8SDavid du Colombier 	[0X1]	"E",
542219b2ee8SDavid du Colombier 	[0XA]	"G",
543219b2ee8SDavid du Colombier 	[0X2]	"LE",
544219b2ee8SDavid du Colombier 	[0XB]	"GE",
545219b2ee8SDavid du Colombier 	[0X3]	"L",
546219b2ee8SDavid du Colombier 	[0XC]	"GU",
547219b2ee8SDavid du Colombier 	[0X4]	"LEU",
548219b2ee8SDavid du Colombier 	[0XD]	"CC",
549219b2ee8SDavid du Colombier 	[0X5]	"CS",
550219b2ee8SDavid du Colombier 	[0XE]	"POS",
551219b2ee8SDavid du Colombier 	[0X6]	"NEG",
552219b2ee8SDavid du Colombier 	[0XF]	"VC",
553219b2ee8SDavid du Colombier 	[0X7]	"VS",
554219b2ee8SDavid du Colombier };
555219b2ee8SDavid du Colombier 
556219b2ee8SDavid du Colombier static char	*fbratab[16] = {	/* page 91 */
557219b2ee8SDavid du Colombier 	[0X8]	"A",
558219b2ee8SDavid du Colombier 	[0X0]	"N",
559219b2ee8SDavid du Colombier 	[0X7]	"U",
560219b2ee8SDavid du Colombier 	[0X6]	"G",
561219b2ee8SDavid du Colombier 	[0X5]	"UG",
562219b2ee8SDavid du Colombier 	[0X4]	"L",
563219b2ee8SDavid du Colombier 	[0X3]	"UL",
564219b2ee8SDavid du Colombier 	[0X2]	"LG",
565219b2ee8SDavid du Colombier 	[0X1]	"NE",
566219b2ee8SDavid du Colombier 	[0X9]	"E",
567219b2ee8SDavid du Colombier 	[0XA]	"UE",
568219b2ee8SDavid du Colombier 	[0XB]	"GE",
569219b2ee8SDavid du Colombier 	[0XC]	"UGE",
570219b2ee8SDavid du Colombier 	[0XD]	"LE",
571219b2ee8SDavid du Colombier 	[0XE]	"ULE",
572219b2ee8SDavid du Colombier 	[0XF]	"O",
573219b2ee8SDavid du Colombier };
574219b2ee8SDavid du Colombier 
575219b2ee8SDavid du Colombier static char	*cbratab[16] = {	/* page 91 */
576219b2ee8SDavid du Colombier 	[0X8]	"A",
577219b2ee8SDavid du Colombier 	[0X0]	"N",
578219b2ee8SDavid du Colombier 	[0X7]	"3",
579219b2ee8SDavid du Colombier 	[0X6]	"2",
580219b2ee8SDavid du Colombier 	[0X5]	"23",
581219b2ee8SDavid du Colombier 	[0X4]	"1",
582219b2ee8SDavid du Colombier 	[0X3]	"13",
583219b2ee8SDavid du Colombier 	[0X2]	"12",
584219b2ee8SDavid du Colombier 	[0X1]	"123",
585219b2ee8SDavid du Colombier 	[0X9]	"0",
586219b2ee8SDavid du Colombier 	[0XA]	"03",
587219b2ee8SDavid du Colombier 	[0XB]	"02",
588219b2ee8SDavid du Colombier 	[0XC]	"023",
589219b2ee8SDavid du Colombier 	[0XD]	"01",
590219b2ee8SDavid du Colombier 	[0XE]	"013",
591219b2ee8SDavid du Colombier 	[0XF]	"012",
592219b2ee8SDavid du Colombier };
593219b2ee8SDavid du Colombier 
594219b2ee8SDavid du Colombier static void
bra1(Instr * i,char * m,char * tab[])595219b2ee8SDavid du Colombier bra1(Instr *i, char *m, char *tab[])
596219b2ee8SDavid du Colombier {
597219b2ee8SDavid du Colombier 	long imm;
598219b2ee8SDavid du Colombier 
599219b2ee8SDavid du Colombier 	imm = i->simmdisp22;
600219b2ee8SDavid du Colombier 	if(i->a)
601*1bd28109SDavid du Colombier 		bprint(i, "%T%T.%c\t", m, tab[i->cond], 'A'+dascase);
602219b2ee8SDavid du Colombier 	else
603*1bd28109SDavid du Colombier 		bprint(i, "%T%T\t", m, tab[i->cond]);
604219b2ee8SDavid du Colombier 	i->curr += symoff(i->curr, i->end-i->curr, i->addr+4*imm, CTEXT);
605219b2ee8SDavid du Colombier 	if (!dascase)
606219b2ee8SDavid du Colombier 		bprint(i, "(SB)");
607219b2ee8SDavid du Colombier }
608219b2ee8SDavid du Colombier 
609219b2ee8SDavid du Colombier static void
bra(Instr * i,char * m)610219b2ee8SDavid du Colombier bra(Instr *i, char *m)			/* page 91 */
611219b2ee8SDavid du Colombier {
612219b2ee8SDavid du Colombier 	bra1(i, m, bratab);
613219b2ee8SDavid du Colombier }
614219b2ee8SDavid du Colombier 
615219b2ee8SDavid du Colombier static void
fbra(Instr * i,char * m)616219b2ee8SDavid du Colombier fbra(Instr *i, char *m)			/* page 93 */
617219b2ee8SDavid du Colombier {
618219b2ee8SDavid du Colombier 	bra1(i, m, fbratab);
619219b2ee8SDavid du Colombier }
620219b2ee8SDavid du Colombier 
621219b2ee8SDavid du Colombier static void
cbra(Instr * i,char * m)622219b2ee8SDavid du Colombier cbra(Instr *i, char *m)			/* page 95 */
623219b2ee8SDavid du Colombier {
624219b2ee8SDavid du Colombier 	bra1(i, m, cbratab);
625219b2ee8SDavid du Colombier }
626219b2ee8SDavid du Colombier 
627219b2ee8SDavid du Colombier static void
trap(Instr * i,char * m)628219b2ee8SDavid du Colombier trap(Instr *i, char *m)			/* page 101 */
629219b2ee8SDavid du Colombier {
630219b2ee8SDavid du Colombier 	if(i->i == 0)
631*1bd28109SDavid du Colombier 		bprint(i, "%T%T\tR%d+R%d", m, bratab[i->cond], i->rs2, i->rs1);
632219b2ee8SDavid du Colombier 	else
633*1bd28109SDavid du Colombier 		bprint(i, "%T%T\t$%ux+R%d", m, bratab[i->cond], i->simm13, i->rs1);
634219b2ee8SDavid du Colombier }
635219b2ee8SDavid du Colombier 
636219b2ee8SDavid du Colombier static void
sethi(Instr * i,char * m)637219b2ee8SDavid du Colombier sethi(Instr *i, char *m)		/* page 89 */
638219b2ee8SDavid du Colombier {
639219b2ee8SDavid du Colombier 	ulong imm;
640219b2ee8SDavid du Colombier 
641219b2ee8SDavid du Colombier 	imm = i->immdisp22<<10;
642219b2ee8SDavid du Colombier 	if(dascase){
643*1bd28109SDavid du Colombier 		bprint(i, "%T\t%lux, R%d", m, imm, i->rd);
644219b2ee8SDavid du Colombier 		return;
645219b2ee8SDavid du Colombier 	}
646219b2ee8SDavid du Colombier 	if(imm==0 && i->rd==0){
647219b2ee8SDavid du Colombier 		bprint(i, "NOP");
648219b2ee8SDavid du Colombier 		return;
649219b2ee8SDavid du Colombier 	}
650219b2ee8SDavid du Colombier 	if(i->target < 0){
651219b2ee8SDavid du Colombier 		bprint(i, "MOVW\t$%lux, R%d", imm, i->rd);
652219b2ee8SDavid du Colombier 		return;
653219b2ee8SDavid du Colombier 	}
654219b2ee8SDavid du Colombier 	bprint(i, "MOVW\t$%lux, R%d", i->imm32, i->target);
655219b2ee8SDavid du Colombier }
656219b2ee8SDavid du Colombier 
657219b2ee8SDavid du Colombier static char ldtab[] = {
658219b2ee8SDavid du Colombier 	'W',
659219b2ee8SDavid du Colombier 	'B',
660219b2ee8SDavid du Colombier 	'H',
661219b2ee8SDavid du Colombier 	'D',
662219b2ee8SDavid du Colombier };
663219b2ee8SDavid du Colombier 
664219b2ee8SDavid du Colombier static char*
moveinstr(int op3,char * m)665219b2ee8SDavid du Colombier moveinstr(int op3, char *m)
666219b2ee8SDavid du Colombier {
667219b2ee8SDavid du Colombier 	char *s;
668219b2ee8SDavid du Colombier 	int c;
669219b2ee8SDavid du Colombier 	static char buf[8];
670219b2ee8SDavid du Colombier 
671219b2ee8SDavid du Colombier 	if(!dascase){
672219b2ee8SDavid du Colombier 		/* batshit cases */
673219b2ee8SDavid du Colombier 		if(op3 == 0xF || op3 == 0x1F)
674219b2ee8SDavid du Colombier 			return "SWAP";
675219b2ee8SDavid du Colombier 		if(op3 == 0xD || op3 == 0x1D)
676219b2ee8SDavid du Colombier 			return "TAS";	/* really LDSTUB */
677219b2ee8SDavid du Colombier 		c = ldtab[op3&3];
678219b2ee8SDavid du Colombier 		s = "";
679219b2ee8SDavid du Colombier 		if((op3&11)==1 || (op3&11)==2)
680219b2ee8SDavid du Colombier 			s="U";
681219b2ee8SDavid du Colombier 		sprint(buf, "MOV%c%s", c, s);
682219b2ee8SDavid du Colombier 		return buf;
683219b2ee8SDavid du Colombier 	}
684219b2ee8SDavid du Colombier 	return m;
685219b2ee8SDavid du Colombier }
686219b2ee8SDavid du Colombier 
687219b2ee8SDavid du Colombier static void
load(Instr * i,char * m)688219b2ee8SDavid du Colombier load(Instr *i, char *m)			/* page 68 */
689219b2ee8SDavid du Colombier {
690219b2ee8SDavid du Colombier 	m = moveinstr(i->op3, m);
691219b2ee8SDavid du Colombier 	if(i->i == 0)
692219b2ee8SDavid du Colombier 		bprint(i, "%s\t(R%d+R%d), R%d", m, i->rs1, i->rs2, i->rd);
693219b2ee8SDavid du Colombier 	else{
694219b2ee8SDavid du Colombier 		bprint(i, "%s\t", m);
695219b2ee8SDavid du Colombier 		address(i);
696219b2ee8SDavid du Colombier 		bprint(i, ", R%d", i->rd);
697219b2ee8SDavid du Colombier 	}
698219b2ee8SDavid du Colombier }
699219b2ee8SDavid du Colombier 
700219b2ee8SDavid du Colombier static void
loada(Instr * i,char * m)701219b2ee8SDavid du Colombier loada(Instr *i, char *m)		/* page 68 */
702219b2ee8SDavid du Colombier {
703219b2ee8SDavid du Colombier 	m = moveinstr(i->op3, m);
704219b2ee8SDavid du Colombier 	if(i->i == 0)
705219b2ee8SDavid du Colombier 		bprint(i, "%s\t(R%d+R%d, %d), R%d", m, i->rs1, i->rs2, i->asi, i->rd);
706219b2ee8SDavid du Colombier 	else
707219b2ee8SDavid du Colombier 		bprint(i, "unknown ld asi %lux", i->w0);
708219b2ee8SDavid du Colombier }
709219b2ee8SDavid du Colombier 
710219b2ee8SDavid du Colombier static void
store(Instr * i,char * m)711219b2ee8SDavid du Colombier store(Instr *i, char *m)		/* page 74 */
712219b2ee8SDavid du Colombier {
713219b2ee8SDavid du Colombier 	m = moveinstr(i->op3, m);
714219b2ee8SDavid du Colombier 	if(i->i == 0)
715219b2ee8SDavid du Colombier 		bprint(i, "%s\tR%d, (R%d+R%d)",
716219b2ee8SDavid du Colombier 				m, i->rd, i->rs1, i->rs2);
717219b2ee8SDavid du Colombier 	else{
718219b2ee8SDavid du Colombier 		bprint(i, "%s\tR%d, ", m, i->rd);
719219b2ee8SDavid du Colombier 		address(i);
720219b2ee8SDavid du Colombier 	}
721219b2ee8SDavid du Colombier }
722219b2ee8SDavid du Colombier 
723219b2ee8SDavid du Colombier static void
storea(Instr * i,char * m)724219b2ee8SDavid du Colombier storea(Instr *i, char *m)		/* page 74 */
725219b2ee8SDavid du Colombier {
726219b2ee8SDavid du Colombier 	m = moveinstr(i->op3, m);
727219b2ee8SDavid du Colombier 	if(i->i == 0)
728219b2ee8SDavid du Colombier 		bprint(i, "%s\tR%d, (R%d+R%d, %d)", m, i->rd, i->rs1, i->rs2, i->asi);
729219b2ee8SDavid du Colombier 	else
730219b2ee8SDavid du Colombier 		bprint(i, "%s\tR%d, %d(R%d, %d), ???", m, i->rd, i->simm13, i->rs1, i->asi);
731219b2ee8SDavid du Colombier }
732219b2ee8SDavid du Colombier 
7337dd7cddfSDavid du Colombier static void
shift(Instr * i,char * m)734219b2ee8SDavid du Colombier shift(Instr *i, char *m)	/* page 88 */
735219b2ee8SDavid du Colombier {
736219b2ee8SDavid du Colombier 	if(i->i == 0){
737219b2ee8SDavid du Colombier 		if(i->rs1 == i->rd)
738219b2ee8SDavid du Colombier 			if(dascase)
739*1bd28109SDavid du Colombier 				bprint(i, "%T\tR%d, R%d", m, i->rs1, i->rs2);
740219b2ee8SDavid du Colombier 			else
741*1bd28109SDavid du Colombier 				bprint(i, "%T\tR%d, R%d", m, i->rs2, i->rs1);
742219b2ee8SDavid du Colombier 		else
743219b2ee8SDavid du Colombier 			if(dascase)
744*1bd28109SDavid du Colombier 				bprint(i, "%T\tR%d, R%d, R%d", m, i->rs1, i->rs2, i->rd);
745219b2ee8SDavid du Colombier 			else
746*1bd28109SDavid du Colombier 				bprint(i, "%T\tR%d, R%d, R%d", m, i->rs2, i->rs1, i->rd);
747219b2ee8SDavid du Colombier 	}else{
748219b2ee8SDavid du Colombier 		if(i->rs1 == i->rd)
749219b2ee8SDavid du Colombier 			if(dascase)
750*1bd28109SDavid du Colombier 				bprint(i, "%T\t$%d,R%d", m, i->simm13&0x1F, i->rs1);
751219b2ee8SDavid du Colombier 			else
752*1bd28109SDavid du Colombier 				bprint(i, "%T\tR%d, $%d", m,  i->rs1, i->simm13&0x1F);
753219b2ee8SDavid du Colombier 		else
754219b2ee8SDavid du Colombier 			if(dascase)
755*1bd28109SDavid du Colombier 				bprint(i, "%T\tR%d, $%d, R%d",m,i->rs1,i->simm13&0x1F,i->rd);
756219b2ee8SDavid du Colombier 			else
757*1bd28109SDavid du Colombier 				bprint(i, "%T\t$%d, R%d, R%d",m,i->simm13&0x1F,i->rs1,i->rd);
758219b2ee8SDavid du Colombier 	}
759219b2ee8SDavid du Colombier }
760219b2ee8SDavid du Colombier 
761219b2ee8SDavid du Colombier static void
add(Instr * i,char * m)762219b2ee8SDavid du Colombier add(Instr *i, char *m)	/* page 82 */
763219b2ee8SDavid du Colombier {
764219b2ee8SDavid du Colombier 	if(i->i == 0){
765219b2ee8SDavid du Colombier 		if(dascase)
766*1bd28109SDavid du Colombier 			bprint(i, "%T\tR%d, R%d", m, i->rs1, i->rs2);
767219b2ee8SDavid du Colombier 		else
768219b2ee8SDavid du Colombier 			if(i->op3==2 && i->rs1==0 && i->rd)  /* OR R2, R0, R1 */
769219b2ee8SDavid du Colombier 				bprint(i, "MOVW\tR%d", i->rs2);
770219b2ee8SDavid du Colombier 			else
771*1bd28109SDavid du Colombier 				bprint(i, "%T\tR%d, R%d", m, i->rs2, i->rs1);
772219b2ee8SDavid du Colombier 	}else{
773219b2ee8SDavid du Colombier 		if(dascase)
774*1bd28109SDavid du Colombier 			bprint(i, "%T\tR%d, $%ux", m, i->rs1, i->simm13);
775219b2ee8SDavid du Colombier 		else
776219b2ee8SDavid du Colombier 			if(i->op3==0 && i->rd && i->rs1==0)	/* ADD $x, R0, R1 */
777*1bd28109SDavid du Colombier 				bprint(i, "MOVW\t$%ux", i->simm13);
778219b2ee8SDavid du Colombier 			else if(i->op3==0 && i->rd && i->rs1==2){
779219b2ee8SDavid du Colombier 				/* ADD $x, R2, R1 -> MOVW $x(SB), R1 */
780219b2ee8SDavid du Colombier 				bprint(i, "MOVW\t$");
781219b2ee8SDavid du Colombier 				address(i);
782219b2ee8SDavid du Colombier 			} else
783*1bd28109SDavid du Colombier 				bprint(i, "%T\t$%ux, R%d", m, i->simm13, i->rs1);
784219b2ee8SDavid du Colombier 	}
785219b2ee8SDavid du Colombier 	if(i->rs1 != i->rd)
786219b2ee8SDavid du Colombier 		bprint(i, ", R%d", i->rd);
787219b2ee8SDavid du Colombier }
788219b2ee8SDavid du Colombier 
789219b2ee8SDavid du Colombier static void
cmp(Instr * i,char * m)790219b2ee8SDavid du Colombier cmp(Instr *i, char *m)
791219b2ee8SDavid du Colombier {
792219b2ee8SDavid du Colombier 	if(dascase || i->rd){
793219b2ee8SDavid du Colombier 		add(i, m);
794219b2ee8SDavid du Colombier 		return;
795219b2ee8SDavid du Colombier 	}
796219b2ee8SDavid du Colombier 	if(i->i == 0)
797219b2ee8SDavid du Colombier 		bprint(i, "CMP\tR%d, R%d", i->rs1, i->rs2);
798219b2ee8SDavid du Colombier 	else
799*1bd28109SDavid du Colombier 		bprint(i, "CMP\tR%d, $%ux", i->rs1, i->simm13);
800219b2ee8SDavid du Colombier }
801219b2ee8SDavid du Colombier 
802219b2ee8SDavid du Colombier static char *regtab[4] = {
803219b2ee8SDavid du Colombier 	"Y",
804219b2ee8SDavid du Colombier 	"PSR",
805219b2ee8SDavid du Colombier 	"WIM",
806219b2ee8SDavid du Colombier 	"TBR",
807219b2ee8SDavid du Colombier };
808219b2ee8SDavid du Colombier 
809219b2ee8SDavid du Colombier static void
wr(Instr * i,char * m)810219b2ee8SDavid du Colombier wr(Instr *i, char *m)		/* page 82 */
811219b2ee8SDavid du Colombier {
812219b2ee8SDavid du Colombier 	if(dascase){
813219b2ee8SDavid du Colombier 		if(i->i == 0)
814219b2ee8SDavid du Colombier 			bprint(i, "%s\tR%d, R%d", m, i->rs1, i->rs2);
815219b2ee8SDavid du Colombier 		else
816*1bd28109SDavid du Colombier 			bprint(i, "%s\tR%d, $%ux", m, i->rs1, i->simm13);
817219b2ee8SDavid du Colombier 	}else{
818219b2ee8SDavid du Colombier 		if(i->i && i->simm13==0)
819219b2ee8SDavid du Colombier 			bprint(i, "MOVW\tR%d", i->rs1);
820219b2ee8SDavid du Colombier 		else if(i->i == 0)
821219b2ee8SDavid du Colombier 			bprint(i, "wr\tR%d, R%d", i->rs2, i->rs1);
822219b2ee8SDavid du Colombier 		else
823*1bd28109SDavid du Colombier 			bprint(i, "wr\t$%ux, R%d", i->simm13, i->rs1);
824219b2ee8SDavid du Colombier 	}
825219b2ee8SDavid du Colombier 	bprint(i, ", %s", regtab[i->op3&3]);
826219b2ee8SDavid du Colombier }
827219b2ee8SDavid du Colombier 
828219b2ee8SDavid du Colombier static void
rd(Instr * i,char * m)829219b2ee8SDavid du Colombier rd(Instr *i, char *m)		/* page 103 */
830219b2ee8SDavid du Colombier {
831219b2ee8SDavid du Colombier 	if(i->rs1==15 && i->rd==0){
832219b2ee8SDavid du Colombier 		m = "stbar";
833219b2ee8SDavid du Colombier 		if(!dascase)
834219b2ee8SDavid du Colombier 			m = "STBAR";
835219b2ee8SDavid du Colombier 		bprint(i, "%s", m);
836219b2ee8SDavid du Colombier 	}else{
837219b2ee8SDavid du Colombier 		if(!dascase)
838219b2ee8SDavid du Colombier 			m = "MOVW";
839219b2ee8SDavid du Colombier 		bprint(i, "%s\t%s, R%d", m, regtab[i->op3&3], i->rd);
840219b2ee8SDavid du Colombier 	}
841219b2ee8SDavid du Colombier }
842219b2ee8SDavid du Colombier 
843219b2ee8SDavid du Colombier static void
jmpl(Instr * i,char * m)844219b2ee8SDavid du Colombier jmpl(Instr *i, char *m)		/* page 82 */
845219b2ee8SDavid du Colombier {
846219b2ee8SDavid du Colombier 	if(i->i == 0){
847219b2ee8SDavid du Colombier 		if(i->rd == 15)
848*1bd28109SDavid du Colombier 			bprint(i, "%T\t(R%d+R%d)", "CALL", i->rs2, i->rs1);
849219b2ee8SDavid du Colombier 		else
850*1bd28109SDavid du Colombier 			bprint(i, "%T\t(R%d+R%d), R%d", m, i->rs2, i->rs1, i->rd);
851219b2ee8SDavid du Colombier 	}else{
852219b2ee8SDavid du Colombier 		if(!dascase && i->simm13==8 && i->rs1==15 && i->rd==0)
853219b2ee8SDavid du Colombier 			bprint(i, "RETURN");
854219b2ee8SDavid du Colombier 		else{
855*1bd28109SDavid du Colombier 			bprint(i, "%T\t", m);
856219b2ee8SDavid du Colombier 			address(i);
857219b2ee8SDavid du Colombier 			bprint(i, ", R%d", i->rd);
858219b2ee8SDavid du Colombier 		}
859219b2ee8SDavid du Colombier 	}
860219b2ee8SDavid du Colombier }
861219b2ee8SDavid du Colombier 
862219b2ee8SDavid du Colombier static void
loadf(Instr * i,char * m)863219b2ee8SDavid du Colombier loadf(Instr *i, char *m)		/* page 70 */
864219b2ee8SDavid du Colombier {
865219b2ee8SDavid du Colombier 	if(!dascase){
866219b2ee8SDavid du Colombier 		m = "FMOVD";
867219b2ee8SDavid du Colombier 		if(i->op3 == 0x20)
868219b2ee8SDavid du Colombier 			m = "FMOVF";
869219b2ee8SDavid du Colombier 		else if(i->op3 == 0x21)
870219b2ee8SDavid du Colombier 			m = "MOVW";
871219b2ee8SDavid du Colombier 	}
872219b2ee8SDavid du Colombier 	if(i->i == 0)
873219b2ee8SDavid du Colombier 		bprint(i, "%s\t(R%d+R%d)", m, i->rs1, i->rs2);
874219b2ee8SDavid du Colombier 	else{
875219b2ee8SDavid du Colombier 		bprint(i, "%s\t", m);
876219b2ee8SDavid du Colombier 		address(i);
877219b2ee8SDavid du Colombier 	}
878219b2ee8SDavid du Colombier 	if(i->op3 == 0x21)
879219b2ee8SDavid du Colombier 		bprint(i, ", FSR");
880219b2ee8SDavid du Colombier 	else
881219b2ee8SDavid du Colombier 		bprint(i, ", R%d", i->rd);
882219b2ee8SDavid du Colombier }
883219b2ee8SDavid du Colombier 
8844de34a7eSDavid du Colombier static void
storef(Instr * i,char * m)8854de34a7eSDavid du Colombier storef(Instr *i, char *m)		/* page 70 */
886219b2ee8SDavid du Colombier {
887219b2ee8SDavid du Colombier 	if(!dascase){
888219b2ee8SDavid du Colombier 		m = "FMOVD";
889219b2ee8SDavid du Colombier 		if(i->op3 == 0x25 || i->op3 == 0x26)
890219b2ee8SDavid du Colombier 			m = "MOVW";
891219b2ee8SDavid du Colombier 		else if(i->op3 == 0x20)
892219b2ee8SDavid du Colombier 			m = "FMOVF";
893219b2ee8SDavid du Colombier 	}
894219b2ee8SDavid du Colombier 	bprint(i, "%s\t", m);
895219b2ee8SDavid du Colombier 	if(i->op3 == 0x25)
896219b2ee8SDavid du Colombier 		bprint(i, "FSR, ");
897219b2ee8SDavid du Colombier 	else if(i->op3 == 0x26)
898219b2ee8SDavid du Colombier 		bprint(i, "FQ, ");
899219b2ee8SDavid du Colombier 	else
900219b2ee8SDavid du Colombier 		bprint(i, "R%d, ", i->rd);
901219b2ee8SDavid du Colombier 	if(i->i == 0)
902219b2ee8SDavid du Colombier 		bprint(i, "(R%d+R%d)", i->rs1, i->rs2);
903219b2ee8SDavid du Colombier 	else
904219b2ee8SDavid du Colombier 		address(i);
905219b2ee8SDavid du Colombier }
906219b2ee8SDavid du Colombier 
9074de34a7eSDavid du Colombier static void
loadc(Instr * i,char * m)9084de34a7eSDavid du Colombier loadc(Instr *i, char *m)			/* page 72 */
909219b2ee8SDavid du Colombier {
910219b2ee8SDavid du Colombier 	if(i->i == 0)
911219b2ee8SDavid du Colombier 		bprint(i, "%s\t(R%d+R%d), C%d", m, i->rs1, i->rs2, i->rd);
912219b2ee8SDavid du Colombier 	else{
913219b2ee8SDavid du Colombier 		bprint(i, "%s\t", m);
914219b2ee8SDavid du Colombier 		address(i);
915219b2ee8SDavid du Colombier 		bprint(i, ", C%d", i->rd);
916219b2ee8SDavid du Colombier 	}
917219b2ee8SDavid du Colombier }
918219b2ee8SDavid du Colombier 
9194de34a7eSDavid du Colombier static void
loadcsr(Instr * i,char * m)9204de34a7eSDavid du Colombier loadcsr(Instr *i, char *m)			/* page 72 */
921219b2ee8SDavid du Colombier {
922219b2ee8SDavid du Colombier 	if(i->i == 0)
923219b2ee8SDavid du Colombier 		bprint(i, "%s\t(R%d+R%d), CSR", m, i->rs1, i->rs2);
924219b2ee8SDavid du Colombier 	else{
925219b2ee8SDavid du Colombier 		bprint(i, "%s\t", m);
926219b2ee8SDavid du Colombier 		address(i);
927219b2ee8SDavid du Colombier 		bprint(i, ", CSR");
928219b2ee8SDavid du Colombier 	}
929219b2ee8SDavid du Colombier }
930219b2ee8SDavid du Colombier 
931219b2ee8SDavid du Colombier static struct{
932219b2ee8SDavid du Colombier 	int	opf;
933219b2ee8SDavid du Colombier 	char	*name;
934219b2ee8SDavid du Colombier } fptab1[] = {			/* ignores rs1 */
935219b2ee8SDavid du Colombier 	0xC4,	"FITOS",	/* page 109 */
936219b2ee8SDavid du Colombier 	0xC8,	"FITOD",
937219b2ee8SDavid du Colombier 	0xCC,	"FITOX",
938219b2ee8SDavid du Colombier 
939219b2ee8SDavid du Colombier 	0xD1,	"FSTOI",	/* page 110 */
940219b2ee8SDavid du Colombier 	0xD2,	"FDTOI",
941219b2ee8SDavid du Colombier 	0xD3,	"FXTOI",
942219b2ee8SDavid du Colombier 
943219b2ee8SDavid du Colombier 	0xC9,	"FSTOD",	/* page 111 */
944219b2ee8SDavid du Colombier 	0xCD,	"FSTOX",
945219b2ee8SDavid du Colombier 	0xC6,	"FDTOS",
946219b2ee8SDavid du Colombier 	0xCE,	"FDTOX",
947219b2ee8SDavid du Colombier 	0xC7,	"FXTOS",
948219b2ee8SDavid du Colombier 	0xCB,	"FXTOD",
949219b2ee8SDavid du Colombier 
950219b2ee8SDavid du Colombier 	0x01,	"FMOVS",	/* page 112 */
951219b2ee8SDavid du Colombier 	0x05,	"FNEGS",
952219b2ee8SDavid du Colombier 	0x09,	"FABSS",
953219b2ee8SDavid du Colombier 
954219b2ee8SDavid du Colombier 	0x29,	"FSQRTS", 	/* page 113 */
955219b2ee8SDavid du Colombier 	0x2A,	"FSQRTD",
956219b2ee8SDavid du Colombier 	0x2B,	"FSQRTX",
957219b2ee8SDavid du Colombier 
958219b2ee8SDavid du Colombier 	0,	0,
959219b2ee8SDavid du Colombier };
960219b2ee8SDavid du Colombier 
961219b2ee8SDavid du Colombier static struct{
962219b2ee8SDavid du Colombier 	int	opf;
963219b2ee8SDavid du Colombier 	char	*name;
964219b2ee8SDavid du Colombier } fptab2[] = {			/* uses rs1 */
965219b2ee8SDavid du Colombier 
966219b2ee8SDavid du Colombier 	0x41,	"FADDS",	/* page 114 */
967219b2ee8SDavid du Colombier 	0x42,	"FADDD",
968219b2ee8SDavid du Colombier 	0x43,	"FADDX",
969219b2ee8SDavid du Colombier 	0x45,	"FSUBS",
970219b2ee8SDavid du Colombier 	0x46,	"FSUBD",
971219b2ee8SDavid du Colombier 	0x47,	"FSUBX",
972219b2ee8SDavid du Colombier 
973219b2ee8SDavid du Colombier 	0x49,	"FMULS",	/* page 115 */
974219b2ee8SDavid du Colombier 	0x4A,	"FMULD",
975219b2ee8SDavid du Colombier 	0x4B,	"FMULX",
976219b2ee8SDavid du Colombier 	0x4D,	"FDIVS",
977219b2ee8SDavid du Colombier 	0x4E,	"FDIVD",
978219b2ee8SDavid du Colombier 	0x4F,	"FDIVX",
979219b2ee8SDavid du Colombier 
980219b2ee8SDavid du Colombier 	0x51,	"FCMPS",	/* page 116 */
981219b2ee8SDavid du Colombier 	0x52,	"FCMPD",
982219b2ee8SDavid du Colombier 	0x53,	"FCMPX",
983219b2ee8SDavid du Colombier 	0x55,	"FCMPES",
984219b2ee8SDavid du Colombier 	0x56,	"FCMPED",
985219b2ee8SDavid du Colombier 	0x57,	"FCMPEX",
986219b2ee8SDavid du Colombier 
987219b2ee8SDavid du Colombier 	0, 0
988219b2ee8SDavid du Colombier };
989219b2ee8SDavid du Colombier 
990219b2ee8SDavid du Colombier static void
fpop(Instr * i,char * m)991219b2ee8SDavid du Colombier fpop(Instr *i, char *m)	/* page 108-116 */
992219b2ee8SDavid du Colombier {
993219b2ee8SDavid du Colombier 	int j;
994219b2ee8SDavid du Colombier 
995219b2ee8SDavid du Colombier 	if(dascase==0 && i->size==2){
996219b2ee8SDavid du Colombier 		bprint(i, "FMOVD\tF%d, F%d", i->rs2, i->rd);
997219b2ee8SDavid du Colombier 		return;
998219b2ee8SDavid du Colombier 	}
999219b2ee8SDavid du Colombier 	for(j=0; fptab1[j].name; j++)
1000219b2ee8SDavid du Colombier 		if(fptab1[j].opf == i->opf){
1001*1bd28109SDavid du Colombier 			bprint(i, "%T\tF%d, F%d", fptab1[j].name, i->rs2, i->rd);
1002219b2ee8SDavid du Colombier 			return;
1003219b2ee8SDavid du Colombier 		}
1004219b2ee8SDavid du Colombier 	for(j=0; fptab2[j].name; j++)
1005219b2ee8SDavid du Colombier 		if(fptab2[j].opf == i->opf){
1006*1bd28109SDavid du Colombier 			bprint(i, "%T\tF%d, F%d, F%d", fptab2[j].name, i->rs1, i->rs2, i->rd);
1007219b2ee8SDavid du Colombier 			return;
1008219b2ee8SDavid du Colombier 		}
1009*1bd28109SDavid du Colombier 	bprint(i, "%T%ux\tF%d, F%d, F%d", m, i->opf, i->rs1, i->rs2, i->rd);
1010219b2ee8SDavid du Colombier }
1011219b2ee8SDavid du Colombier 
1012219b2ee8SDavid du Colombier static int
sparcfoll(Map * map,uvlong pc,Rgetter rget,uvlong * foll)10134de34a7eSDavid du Colombier sparcfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
1014219b2ee8SDavid du Colombier {
1015219b2ee8SDavid du Colombier 	ulong w, r1, r2;
1016219b2ee8SDavid du Colombier 	char buf[8];
1017219b2ee8SDavid du Colombier 	Instr i;
1018219b2ee8SDavid du Colombier 
1019219b2ee8SDavid du Colombier 	mymap = map;
1020219b2ee8SDavid du Colombier 	if (mkinstr(pc, &i) < 0)
1021219b2ee8SDavid du Colombier 		return -1;
1022219b2ee8SDavid du Colombier 	w = i.w0;
1023219b2ee8SDavid du Colombier 	switch(w & 0xC1C00000){
1024219b2ee8SDavid du Colombier 	case 0x00800000:		/* branch on int cond */
1025219b2ee8SDavid du Colombier 	case 0x01800000:		/* branch on fp cond */
1026219b2ee8SDavid du Colombier 	case 0x01C00000:		/* branch on copr cond */
1027219b2ee8SDavid du Colombier 		foll[0] = pc+8;
1028219b2ee8SDavid du Colombier 		foll[1] = pc + (i.simmdisp22<<2);
1029219b2ee8SDavid du Colombier 		return 2;
1030219b2ee8SDavid du Colombier 	}
1031219b2ee8SDavid du Colombier 
1032219b2ee8SDavid du Colombier 	if((w&0xC0000000) == 0x40000000){	/* CALL */
1033219b2ee8SDavid du Colombier 		foll[0] = pc + (i.disp30<<2);
1034219b2ee8SDavid du Colombier 		return 1;
1035219b2ee8SDavid du Colombier 	}
1036219b2ee8SDavid du Colombier 
1037219b2ee8SDavid du Colombier 	if((w&0xC1F80000) == 0x81C00000){	/* JMPL */
10387dd7cddfSDavid du Colombier 		sprint(buf, "R%ld", (w>>14)&0xF);
1039219b2ee8SDavid du Colombier 		r1 = (*rget)(map, buf);
1040219b2ee8SDavid du Colombier 		if(w & 0x2000)			/* JMPL R1+simm13 */
1041219b2ee8SDavid du Colombier 			r2 = i.simm13;
1042219b2ee8SDavid du Colombier 		else{				/* JMPL R1+R2 */
10437dd7cddfSDavid du Colombier 			sprint(buf, "R%ld", w&0xF);
1044219b2ee8SDavid du Colombier 			r2 = (*rget)(map, buf);
1045219b2ee8SDavid du Colombier 		}
1046219b2ee8SDavid du Colombier 		foll[0] = r1 + r2;
1047219b2ee8SDavid du Colombier 		return 1;
1048219b2ee8SDavid du Colombier 	}
1049219b2ee8SDavid du Colombier 	foll[0] = pc+i.size*4;
1050219b2ee8SDavid du Colombier 	return 1;
1051219b2ee8SDavid du Colombier }
1052