xref: /plan9/sys/src/libmach/kdb.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
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);
11219b2ee8SDavid du Colombier static	int	sparcfoll(Map*, ulong, Rgetter, ulong*);
12219b2ee8SDavid du Colombier static	int	sparcinst(Map*, ulong, char, char*, int);
13219b2ee8SDavid du Colombier static	int	sparcdas(Map*, ulong, char*, int);
14219b2ee8SDavid du Colombier static	int	sparcinstlen(Map*, ulong);
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*
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*
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;
119219b2ee8SDavid du Colombier 	ulong	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 
129219b2ee8SDavid du Colombier static int	mkinstr(ulong, 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 
280219b2ee8SDavid du Colombier static void
281219b2ee8SDavid du Colombier bprint(Instr *i, char *fmt, ...)
282219b2ee8SDavid du Colombier {
2837dd7cddfSDavid du Colombier 	va_list arg;
2847dd7cddfSDavid du Colombier 
2857dd7cddfSDavid du Colombier 	va_start(arg, fmt);
286*9a747e4fSDavid du Colombier 	i->curr = vseprint(i->curr, i->end, fmt, arg);
2877dd7cddfSDavid du Colombier 	va_end(arg);
288219b2ee8SDavid du Colombier }
289219b2ee8SDavid du Colombier 
290219b2ee8SDavid du Colombier static int
291219b2ee8SDavid du Colombier decode(ulong pc, Instr *i)
292219b2ee8SDavid du Colombier {
293219b2ee8SDavid du Colombier 	long w;
294219b2ee8SDavid du Colombier 
295219b2ee8SDavid du Colombier 	if (get4(mymap, pc, &w) < 0) {
296219b2ee8SDavid du Colombier 		werrstr("can't read instruction: %r");
297219b2ee8SDavid du Colombier 		return -1;
298219b2ee8SDavid du Colombier 	}
299219b2ee8SDavid du Colombier 	i->op = (w >> 30) & 0x03;
300219b2ee8SDavid du Colombier 	i->rd = (w >> 25) & 0x1F;
301219b2ee8SDavid du Colombier 	i->op2 = (w >> 22) & 0x07;
302219b2ee8SDavid du Colombier 	i->a = (w >> 29) & 0x01;
303219b2ee8SDavid du Colombier 	i->cond = (w >> 25) & 0x0F;
304219b2ee8SDavid du Colombier 	i->op3 = (w >> 19) & 0x3F;
305219b2ee8SDavid du Colombier 	i->rs1 = (w >> 14) & 0x1F;
306219b2ee8SDavid du Colombier 	i->i = (w >> 13) & 0x01;
307219b2ee8SDavid du Colombier 	i->asi = (w >> 5) & 0xFF;
308219b2ee8SDavid du Colombier 	i->rs2 = (w >> 0) & 0x1F;
309219b2ee8SDavid du Colombier 	i->simm13 = (w >> 0) & 0x1FFF;
310219b2ee8SDavid du Colombier 	if(i->simm13 & (1<<12))
311219b2ee8SDavid du Colombier 		i->simm13 |= ~((1<<13)-1);
312219b2ee8SDavid du Colombier 	i->opf = (w >> 5) & 0x1FF;
313219b2ee8SDavid du Colombier 	i->immdisp22 = (w >> 0) & 0x3FFFFF;
314219b2ee8SDavid du Colombier 	i->simmdisp22 = i->immdisp22;
315219b2ee8SDavid du Colombier 	if(i->simmdisp22 & (1<<21))
316219b2ee8SDavid du Colombier 		i->simmdisp22 |= ~((1<<22)-1);
317219b2ee8SDavid du Colombier 	i->disp30 = (w >> 0) & 0x3FFFFFFF;
318219b2ee8SDavid du Colombier 	i->w0 = w;
319219b2ee8SDavid du Colombier 	i->target = -1;
320219b2ee8SDavid du Colombier 	i->addr = pc;
321219b2ee8SDavid du Colombier 	i->size = 1;
322219b2ee8SDavid du Colombier 	return 1;
323219b2ee8SDavid du Colombier }
324219b2ee8SDavid du Colombier 
325219b2ee8SDavid du Colombier static int
326219b2ee8SDavid du Colombier mkinstr(ulong pc, Instr *i)
327219b2ee8SDavid du Colombier {
328219b2ee8SDavid du Colombier 	Instr xi;
329219b2ee8SDavid du Colombier 
330219b2ee8SDavid du Colombier 	if (decode(pc, i) < 0)
331219b2ee8SDavid du Colombier 		return -1;
332219b2ee8SDavid du Colombier 	if(i->op==0 && i->op2==4 && !dascase){	/* SETHI */
333219b2ee8SDavid du Colombier 		if (decode(pc+4, &xi) < 0)
334219b2ee8SDavid du Colombier 			return -1;
335219b2ee8SDavid du Colombier 		if(xi.op==2 && xi.op3==0)		/* ADD */
336219b2ee8SDavid du Colombier 		if(xi.i == 1 && xi.rs1 == i->rd){	/* immediate to same reg */
337219b2ee8SDavid du Colombier 			i->imm32 = xi.simm13 + (i->immdisp22<<10);
338219b2ee8SDavid du Colombier 			i->target = xi.rd;
339219b2ee8SDavid du Colombier 			i->w1 = xi.w0;
340219b2ee8SDavid du Colombier 			i->size++;
341219b2ee8SDavid du Colombier 			return 1;
342219b2ee8SDavid du Colombier 		}
343219b2ee8SDavid du Colombier 	}
344219b2ee8SDavid du Colombier 	if(i->op==2 && i->opf==1 && !dascase){	/* FMOVS */
345219b2ee8SDavid du Colombier 		if (decode(pc+4, &xi) < 0)
346219b2ee8SDavid du Colombier 			return -1;
347219b2ee8SDavid du Colombier 		if(i->op==2 && i->opf==1)		/* FMOVS */
348219b2ee8SDavid du Colombier 		if(xi.rd==i->rd+1 && xi.rs2==i->rs2+1){	/* next pair */
349219b2ee8SDavid du Colombier 			i->w1 = xi.w0;
350219b2ee8SDavid du Colombier 			i->size++;
351219b2ee8SDavid du Colombier 		}
352219b2ee8SDavid du Colombier 	}
353219b2ee8SDavid du Colombier 	return 1;
354219b2ee8SDavid du Colombier }
355219b2ee8SDavid du Colombier 
356219b2ee8SDavid du Colombier static int
357219b2ee8SDavid du Colombier printins(Map *map, ulong pc, char *buf, int n)
358219b2ee8SDavid du Colombier {
359219b2ee8SDavid du Colombier 	Instr instr;
360219b2ee8SDavid du Colombier 	void (*f)(Instr*, char*);
361219b2ee8SDavid du Colombier 
362219b2ee8SDavid du Colombier 	mymap = map;
363219b2ee8SDavid du Colombier 	memset(&instr, 0, sizeof(instr));
364219b2ee8SDavid du Colombier 	instr.curr = buf;
365219b2ee8SDavid du Colombier 	instr.end = buf+n-1;
366219b2ee8SDavid du Colombier 	if (mkinstr(pc, &instr) < 0)
367219b2ee8SDavid du Colombier 		return -1;
368219b2ee8SDavid du Colombier 	switch(instr.op){
369219b2ee8SDavid du Colombier 	case 0:
370219b2ee8SDavid du Colombier 		f = sparcop0[instr.op2].f;
371219b2ee8SDavid du Colombier 		if(f)
372219b2ee8SDavid du Colombier 			(*f)(&instr, sparcop0[instr.op2].mnemonic);
373219b2ee8SDavid du Colombier 		else
374219b2ee8SDavid du Colombier 			bprint(&instr, "unknown %lux", instr.w0);
375219b2ee8SDavid du Colombier 		break;
376219b2ee8SDavid du Colombier 
377219b2ee8SDavid du Colombier 	case 1:
378219b2ee8SDavid du Colombier 		bprint(&instr, "%X", "CALL\t");
379219b2ee8SDavid du Colombier 		instr.curr += symoff(instr.curr, instr.end-instr.curr,
380219b2ee8SDavid du Colombier 					pc+instr.disp30*4, CTEXT);
381219b2ee8SDavid du Colombier 		if (!dascase)
382219b2ee8SDavid du Colombier 			bprint(&instr, "(SB)");
383219b2ee8SDavid du Colombier 		break;
384219b2ee8SDavid du Colombier 
385219b2ee8SDavid du Colombier 	case 2:
386219b2ee8SDavid du Colombier 		f = sparcop2[instr.op3].f;
387219b2ee8SDavid du Colombier 		if(f)
388219b2ee8SDavid du Colombier 			(*f)(&instr, sparcop2[instr.op3].mnemonic);
389219b2ee8SDavid du Colombier 		else
390219b2ee8SDavid du Colombier 			bprint(&instr, "unknown %lux", instr.w0);
391219b2ee8SDavid du Colombier 		break;
392219b2ee8SDavid du Colombier 
393219b2ee8SDavid du Colombier 	case 3:
394219b2ee8SDavid du Colombier 		f = sparcop3[instr.op3].f;
395219b2ee8SDavid du Colombier 		if(f)
396219b2ee8SDavid du Colombier 			(*f)(&instr, sparcop3[instr.op3].mnemonic);
397219b2ee8SDavid du Colombier 		else
398219b2ee8SDavid du Colombier 			bprint(&instr, "unknown %lux", instr.w0);
399219b2ee8SDavid du Colombier 		break;
400219b2ee8SDavid du Colombier 	}
401219b2ee8SDavid du Colombier 	if (instr.err) {
402219b2ee8SDavid du Colombier 		if (instr.curr != buf)
403219b2ee8SDavid du Colombier 			bprint(&instr, "\t\t;");
404219b2ee8SDavid du Colombier 		bprint(&instr, instr.err);
405219b2ee8SDavid du Colombier 	}
406219b2ee8SDavid du Colombier 	return instr.size*4;
407219b2ee8SDavid du Colombier }
408219b2ee8SDavid du Colombier 
409219b2ee8SDavid du Colombier /* convert to lower case from upper, according to dascase */
410219b2ee8SDavid du Colombier static int
411*9a747e4fSDavid du Colombier Xfmt(Fmt *f)
412219b2ee8SDavid du Colombier {
413219b2ee8SDavid du Colombier 	char buf[128];
4147dd7cddfSDavid du Colombier 	char *s, *t, *oa;
415219b2ee8SDavid du Colombier 
416*9a747e4fSDavid du Colombier 	oa = va_arg(f->args, char*);
417219b2ee8SDavid du Colombier 	if(dascase){
4187dd7cddfSDavid du Colombier 		for(s=oa,t=buf; *t = *s; s++,t++)
419219b2ee8SDavid du Colombier 			if('A'<=*t && *t<='Z')
420219b2ee8SDavid du Colombier 				*t += 'a'-'A';
421*9a747e4fSDavid du Colombier 		return fmtstrcpy(f, buf);
422*9a747e4fSDavid du Colombier 	}
423*9a747e4fSDavid du Colombier 	return fmtstrcpy(f, oa);
424219b2ee8SDavid du Colombier }
425219b2ee8SDavid du Colombier 
426219b2ee8SDavid du Colombier static int
427219b2ee8SDavid du Colombier sparcinst(Map *map, ulong pc, char modifier, char *buf, int n)
428219b2ee8SDavid du Colombier {
429219b2ee8SDavid du Colombier 	static int fmtinstalled = 0;
430219b2ee8SDavid du Colombier 
431219b2ee8SDavid du Colombier 		/* a modifier of 'I' toggles the dissassembler type */
432219b2ee8SDavid du Colombier 	if (!fmtinstalled) {
433219b2ee8SDavid du Colombier 		fmtinstalled = 1;
434*9a747e4fSDavid du Colombier 		fmtinstall('X', Xfmt);
435219b2ee8SDavid du Colombier 	}
436219b2ee8SDavid du Colombier 	if ((asstype == ASUNSPARC && modifier == 'i')
437219b2ee8SDavid du Colombier 		|| (asstype == ASPARC && modifier == 'I'))
438219b2ee8SDavid du Colombier 		dascase = 'a'-'A';
439219b2ee8SDavid du Colombier 	else
440219b2ee8SDavid du Colombier 		dascase = 0;
441219b2ee8SDavid du Colombier 	return printins(map, pc, buf, n);
442219b2ee8SDavid du Colombier }
443219b2ee8SDavid du Colombier 
444219b2ee8SDavid du Colombier static int
445219b2ee8SDavid du Colombier sparcdas(Map *map, ulong pc, char *buf, int n)
446219b2ee8SDavid du Colombier {
447219b2ee8SDavid du Colombier 	Instr instr;
448219b2ee8SDavid du Colombier 
449219b2ee8SDavid du Colombier 	mymap = map;
450219b2ee8SDavid du Colombier 	memset(&instr, 0, sizeof(instr));
451219b2ee8SDavid du Colombier 	instr.curr = buf;
452219b2ee8SDavid du Colombier 	instr.end = buf+n-1;
453219b2ee8SDavid du Colombier 	if (mkinstr(pc, &instr) < 0)
454219b2ee8SDavid du Colombier 		return -1;
455219b2ee8SDavid du Colombier 	if (instr.end-instr.curr > 8)
456219b2ee8SDavid du Colombier 		instr.curr = _hexify(instr.curr, instr.w0, 7);
457219b2ee8SDavid du Colombier 	if (instr.end-instr.curr > 9 && instr.size == 2) {
458219b2ee8SDavid du Colombier 		*instr.curr++ = ' ';
459219b2ee8SDavid du Colombier 		instr.curr = _hexify(instr.curr, instr.w1, 7);
460219b2ee8SDavid du Colombier 	}
461219b2ee8SDavid du Colombier 	*instr.curr = 0;
462219b2ee8SDavid du Colombier 	return instr.size*4;
463219b2ee8SDavid du Colombier }
464219b2ee8SDavid du Colombier 
465219b2ee8SDavid du Colombier static int
466219b2ee8SDavid du Colombier sparcinstlen(Map *map, ulong pc)
467219b2ee8SDavid du Colombier {
468219b2ee8SDavid du Colombier 	Instr i;
469219b2ee8SDavid du Colombier 
470219b2ee8SDavid du Colombier 	mymap = map;
471219b2ee8SDavid du Colombier 	if (mkinstr(pc, &i) < 0)
472219b2ee8SDavid du Colombier 		return -1;
473219b2ee8SDavid du Colombier 	return i.size*4;
474219b2ee8SDavid du Colombier }
475219b2ee8SDavid du Colombier 
476219b2ee8SDavid du Colombier static int
477219b2ee8SDavid du Colombier plocal(Instr *i)
478219b2ee8SDavid du Colombier {
479219b2ee8SDavid du Colombier 	int offset;
480219b2ee8SDavid du Colombier 	Symbol s;
481219b2ee8SDavid du Colombier 
482219b2ee8SDavid du Colombier 	if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
483219b2ee8SDavid du Colombier 		return -1;
484219b2ee8SDavid du Colombier 	if (s.value > i->simm13) {
485219b2ee8SDavid du Colombier 		if(getauto(&s, s.value-i->simm13, CAUTO, &s)) {
486219b2ee8SDavid du Colombier 			bprint(i, "%s+%d(SP)", s.name, s.value);
487219b2ee8SDavid du Colombier 			return 1;
488219b2ee8SDavid du Colombier 		}
489219b2ee8SDavid du Colombier 	} else {
490219b2ee8SDavid du Colombier 		offset = i->simm13-s.value;
491219b2ee8SDavid du Colombier 		if (getauto(&s, offset-4, CPARAM, &s)) {
492219b2ee8SDavid du Colombier 			bprint(i, "%s+%d(FP)", s.name, offset);
493219b2ee8SDavid du Colombier 			return 1;
494219b2ee8SDavid du Colombier 		}
495219b2ee8SDavid du Colombier 	}
496219b2ee8SDavid du Colombier 	return -1;
497219b2ee8SDavid du Colombier }
498219b2ee8SDavid du Colombier 
499219b2ee8SDavid du Colombier static void
500219b2ee8SDavid du Colombier address(Instr *i)
501219b2ee8SDavid du Colombier {
502219b2ee8SDavid du Colombier 	Symbol s, s2;
503219b2ee8SDavid du Colombier 	long off, off1;
504219b2ee8SDavid du Colombier 
505219b2ee8SDavid du Colombier 	if (i->rs1 == 1 && plocal(i) >= 0)
506219b2ee8SDavid du Colombier 		return;
507219b2ee8SDavid du Colombier 	off = mach->sb+i->simm13;
508219b2ee8SDavid du Colombier 	if(i->rs1 == 2	&& findsym(off, CANY, &s)
509219b2ee8SDavid du Colombier 			&& s.value-off < 4096
510219b2ee8SDavid du Colombier 			&& (s.class == CDATA || s.class == CTEXT)) {
511219b2ee8SDavid du Colombier 		if(off==s.value && s.name[0]=='$'){
512219b2ee8SDavid du Colombier 			off1 = 0;
513219b2ee8SDavid du Colombier 			get4(mymap, s.value, &off1);
514219b2ee8SDavid du Colombier 			if(off1 && findsym(off1, CANY, &s2) && s2.value == off1){
515219b2ee8SDavid du Colombier 				bprint(i, "$%s(SB)", s2.name);
516219b2ee8SDavid du Colombier 				return;
517219b2ee8SDavid du Colombier 			}
518219b2ee8SDavid du Colombier 		}
519219b2ee8SDavid du Colombier 		bprint(i, "%s", s.name);
520219b2ee8SDavid du Colombier 		if (s.value != off)
521219b2ee8SDavid du Colombier 			bprint(i, "+%lux", s.value-off);
522219b2ee8SDavid du Colombier 		bprint(i, "(SB)");
523219b2ee8SDavid du Colombier 		return;
524219b2ee8SDavid du Colombier 	}
525219b2ee8SDavid du Colombier 	bprint(i, "%lux(R%d)", i->simm13, i->rs1);
526219b2ee8SDavid du Colombier }
527219b2ee8SDavid du Colombier 
528219b2ee8SDavid du Colombier static void
529219b2ee8SDavid du Colombier unimp(Instr *i, char *m)
530219b2ee8SDavid du Colombier {
531219b2ee8SDavid du Colombier 	bprint(i, "%X", m);
532219b2ee8SDavid du Colombier }
533219b2ee8SDavid du Colombier 
534219b2ee8SDavid du Colombier static char	*bratab[16] = {	/* page 91 */
535219b2ee8SDavid du Colombier 	[0X8]	"A",
536219b2ee8SDavid du Colombier 	[0X0]	"N",
537219b2ee8SDavid du Colombier 	[0X9]	"NE",
538219b2ee8SDavid du Colombier 	[0X1]	"E",
539219b2ee8SDavid du Colombier 	[0XA]	"G",
540219b2ee8SDavid du Colombier 	[0X2]	"LE",
541219b2ee8SDavid du Colombier 	[0XB]	"GE",
542219b2ee8SDavid du Colombier 	[0X3]	"L",
543219b2ee8SDavid du Colombier 	[0XC]	"GU",
544219b2ee8SDavid du Colombier 	[0X4]	"LEU",
545219b2ee8SDavid du Colombier 	[0XD]	"CC",
546219b2ee8SDavid du Colombier 	[0X5]	"CS",
547219b2ee8SDavid du Colombier 	[0XE]	"POS",
548219b2ee8SDavid du Colombier 	[0X6]	"NEG",
549219b2ee8SDavid du Colombier 	[0XF]	"VC",
550219b2ee8SDavid du Colombier 	[0X7]	"VS",
551219b2ee8SDavid du Colombier };
552219b2ee8SDavid du Colombier 
553219b2ee8SDavid du Colombier static char	*fbratab[16] = {	/* page 91 */
554219b2ee8SDavid du Colombier 	[0X8]	"A",
555219b2ee8SDavid du Colombier 	[0X0]	"N",
556219b2ee8SDavid du Colombier 	[0X7]	"U",
557219b2ee8SDavid du Colombier 	[0X6]	"G",
558219b2ee8SDavid du Colombier 	[0X5]	"UG",
559219b2ee8SDavid du Colombier 	[0X4]	"L",
560219b2ee8SDavid du Colombier 	[0X3]	"UL",
561219b2ee8SDavid du Colombier 	[0X2]	"LG",
562219b2ee8SDavid du Colombier 	[0X1]	"NE",
563219b2ee8SDavid du Colombier 	[0X9]	"E",
564219b2ee8SDavid du Colombier 	[0XA]	"UE",
565219b2ee8SDavid du Colombier 	[0XB]	"GE",
566219b2ee8SDavid du Colombier 	[0XC]	"UGE",
567219b2ee8SDavid du Colombier 	[0XD]	"LE",
568219b2ee8SDavid du Colombier 	[0XE]	"ULE",
569219b2ee8SDavid du Colombier 	[0XF]	"O",
570219b2ee8SDavid du Colombier };
571219b2ee8SDavid du Colombier 
572219b2ee8SDavid du Colombier static char	*cbratab[16] = {	/* page 91 */
573219b2ee8SDavid du Colombier 	[0X8]	"A",
574219b2ee8SDavid du Colombier 	[0X0]	"N",
575219b2ee8SDavid du Colombier 	[0X7]	"3",
576219b2ee8SDavid du Colombier 	[0X6]	"2",
577219b2ee8SDavid du Colombier 	[0X5]	"23",
578219b2ee8SDavid du Colombier 	[0X4]	"1",
579219b2ee8SDavid du Colombier 	[0X3]	"13",
580219b2ee8SDavid du Colombier 	[0X2]	"12",
581219b2ee8SDavid du Colombier 	[0X1]	"123",
582219b2ee8SDavid du Colombier 	[0X9]	"0",
583219b2ee8SDavid du Colombier 	[0XA]	"03",
584219b2ee8SDavid du Colombier 	[0XB]	"02",
585219b2ee8SDavid du Colombier 	[0XC]	"023",
586219b2ee8SDavid du Colombier 	[0XD]	"01",
587219b2ee8SDavid du Colombier 	[0XE]	"013",
588219b2ee8SDavid du Colombier 	[0XF]	"012",
589219b2ee8SDavid du Colombier };
590219b2ee8SDavid du Colombier 
591219b2ee8SDavid du Colombier static void
592219b2ee8SDavid du Colombier bra1(Instr *i, char *m, char *tab[])
593219b2ee8SDavid du Colombier {
594219b2ee8SDavid du Colombier 	long imm;
595219b2ee8SDavid du Colombier 
596219b2ee8SDavid du Colombier 	imm = i->simmdisp22;
597219b2ee8SDavid du Colombier 	if(i->a)
598219b2ee8SDavid du Colombier 		bprint(i, "%X%X.%c\t", m, tab[i->cond], 'A'+dascase);
599219b2ee8SDavid du Colombier 	else
600219b2ee8SDavid du Colombier 		bprint(i, "%X%X\t", m, tab[i->cond]);
601219b2ee8SDavid du Colombier 	i->curr += symoff(i->curr, i->end-i->curr, i->addr+4*imm, CTEXT);
602219b2ee8SDavid du Colombier 	if (!dascase)
603219b2ee8SDavid du Colombier 		bprint(i, "(SB)");
604219b2ee8SDavid du Colombier }
605219b2ee8SDavid du Colombier 
606219b2ee8SDavid du Colombier static void
607219b2ee8SDavid du Colombier bra(Instr *i, char *m)			/* page 91 */
608219b2ee8SDavid du Colombier {
609219b2ee8SDavid du Colombier 	bra1(i, m, bratab);
610219b2ee8SDavid du Colombier }
611219b2ee8SDavid du Colombier 
612219b2ee8SDavid du Colombier static void
613219b2ee8SDavid du Colombier fbra(Instr *i, char *m)			/* page 93 */
614219b2ee8SDavid du Colombier {
615219b2ee8SDavid du Colombier 	bra1(i, m, fbratab);
616219b2ee8SDavid du Colombier }
617219b2ee8SDavid du Colombier 
618219b2ee8SDavid du Colombier static void
619219b2ee8SDavid du Colombier cbra(Instr *i, char *m)			/* page 95 */
620219b2ee8SDavid du Colombier {
621219b2ee8SDavid du Colombier 	bra1(i, m, cbratab);
622219b2ee8SDavid du Colombier }
623219b2ee8SDavid du Colombier 
624219b2ee8SDavid du Colombier static void
625219b2ee8SDavid du Colombier trap(Instr *i, char *m)			/* page 101 */
626219b2ee8SDavid du Colombier {
627219b2ee8SDavid du Colombier 	if(i->i == 0)
628219b2ee8SDavid du Colombier 		bprint(i, "%X%X\tR%d+R%d", m, bratab[i->cond], i->rs2, i->rs1);
629219b2ee8SDavid du Colombier 	else
630219b2ee8SDavid du Colombier 		bprint(i, "%X%X\t$%lux+R%d", m, bratab[i->cond], i->simm13, i->rs1);
631219b2ee8SDavid du Colombier }
632219b2ee8SDavid du Colombier 
633219b2ee8SDavid du Colombier static void
634219b2ee8SDavid du Colombier sethi(Instr *i, char *m)		/* page 89 */
635219b2ee8SDavid du Colombier {
636219b2ee8SDavid du Colombier 	ulong imm;
637219b2ee8SDavid du Colombier 
638219b2ee8SDavid du Colombier 	imm = i->immdisp22<<10;
639219b2ee8SDavid du Colombier 	if(dascase){
640219b2ee8SDavid du Colombier 		bprint(i, "%X\t%lux, R%d", m, imm, i->rd);
641219b2ee8SDavid du Colombier 		return;
642219b2ee8SDavid du Colombier 	}
643219b2ee8SDavid du Colombier 	if(imm==0 && i->rd==0){
644219b2ee8SDavid du Colombier 		bprint(i, "NOP");
645219b2ee8SDavid du Colombier 		return;
646219b2ee8SDavid du Colombier 	}
647219b2ee8SDavid du Colombier 	if(i->target < 0){
648219b2ee8SDavid du Colombier 		bprint(i, "MOVW\t$%lux, R%d", imm, i->rd);
649219b2ee8SDavid du Colombier 		return;
650219b2ee8SDavid du Colombier 	}
651219b2ee8SDavid du Colombier 	bprint(i, "MOVW\t$%lux, R%d", i->imm32, i->target);
652219b2ee8SDavid du Colombier }
653219b2ee8SDavid du Colombier 
654219b2ee8SDavid du Colombier static char ldtab[] = {
655219b2ee8SDavid du Colombier 	'W',
656219b2ee8SDavid du Colombier 	'B',
657219b2ee8SDavid du Colombier 	'H',
658219b2ee8SDavid du Colombier 	'D',
659219b2ee8SDavid du Colombier };
660219b2ee8SDavid du Colombier 
661219b2ee8SDavid du Colombier static char*
662219b2ee8SDavid du Colombier moveinstr(int op3, char *m)
663219b2ee8SDavid du Colombier {
664219b2ee8SDavid du Colombier 	char *s;
665219b2ee8SDavid du Colombier 	int c;
666219b2ee8SDavid du Colombier 	static char buf[8];
667219b2ee8SDavid du Colombier 
668219b2ee8SDavid du Colombier 	if(!dascase){
669219b2ee8SDavid du Colombier 		/* batshit cases */
670219b2ee8SDavid du Colombier 		if(op3 == 0xF || op3 == 0x1F)
671219b2ee8SDavid du Colombier 			return "SWAP";
672219b2ee8SDavid du Colombier 		if(op3 == 0xD || op3 == 0x1D)
673219b2ee8SDavid du Colombier 			return "TAS";	/* really LDSTUB */
674219b2ee8SDavid du Colombier 		c = ldtab[op3&3];
675219b2ee8SDavid du Colombier 		s = "";
676219b2ee8SDavid du Colombier 		if((op3&11)==1 || (op3&11)==2)
677219b2ee8SDavid du Colombier 			s="U";
678219b2ee8SDavid du Colombier 		sprint(buf, "MOV%c%s", c, s);
679219b2ee8SDavid du Colombier 		return buf;
680219b2ee8SDavid du Colombier 	}
681219b2ee8SDavid du Colombier 	return m;
682219b2ee8SDavid du Colombier }
683219b2ee8SDavid du Colombier 
684219b2ee8SDavid du Colombier static void
685219b2ee8SDavid du Colombier load(Instr *i, char *m)			/* page 68 */
686219b2ee8SDavid du Colombier {
687219b2ee8SDavid du Colombier 	m = moveinstr(i->op3, m);
688219b2ee8SDavid du Colombier 	if(i->i == 0)
689219b2ee8SDavid du Colombier 		bprint(i, "%s\t(R%d+R%d), R%d", m, i->rs1, i->rs2, i->rd);
690219b2ee8SDavid du Colombier 	else{
691219b2ee8SDavid du Colombier 		bprint(i, "%s\t", m);
692219b2ee8SDavid du Colombier 		address(i);
693219b2ee8SDavid du Colombier 		bprint(i, ", R%d", i->rd);
694219b2ee8SDavid du Colombier 	}
695219b2ee8SDavid du Colombier }
696219b2ee8SDavid du Colombier 
697219b2ee8SDavid du Colombier static void
698219b2ee8SDavid du Colombier loada(Instr *i, char *m)		/* page 68 */
699219b2ee8SDavid du Colombier {
700219b2ee8SDavid du Colombier 	m = moveinstr(i->op3, m);
701219b2ee8SDavid du Colombier 	if(i->i == 0)
702219b2ee8SDavid du Colombier 		bprint(i, "%s\t(R%d+R%d, %d), R%d", m, i->rs1, i->rs2, i->asi, i->rd);
703219b2ee8SDavid du Colombier 	else
704219b2ee8SDavid du Colombier 		bprint(i, "unknown ld asi %lux", i->w0);
705219b2ee8SDavid du Colombier }
706219b2ee8SDavid du Colombier 
707219b2ee8SDavid du Colombier static void
708219b2ee8SDavid du Colombier store(Instr *i, char *m)		/* page 74 */
709219b2ee8SDavid du Colombier {
710219b2ee8SDavid du Colombier 	m = moveinstr(i->op3, m);
711219b2ee8SDavid du Colombier 	if(i->i == 0)
712219b2ee8SDavid du Colombier 		bprint(i, "%s\tR%d, (R%d+R%d)",
713219b2ee8SDavid du Colombier 				m, i->rd, i->rs1, i->rs2);
714219b2ee8SDavid du Colombier 	else{
715219b2ee8SDavid du Colombier 		bprint(i, "%s\tR%d, ", m, i->rd);
716219b2ee8SDavid du Colombier 		address(i);
717219b2ee8SDavid du Colombier 	}
718219b2ee8SDavid du Colombier }
719219b2ee8SDavid du Colombier 
720219b2ee8SDavid du Colombier static void
721219b2ee8SDavid du Colombier storea(Instr *i, char *m)		/* page 74 */
722219b2ee8SDavid du Colombier {
723219b2ee8SDavid du Colombier 	m = moveinstr(i->op3, m);
724219b2ee8SDavid du Colombier 	if(i->i == 0)
725219b2ee8SDavid du Colombier 		bprint(i, "%s\tR%d, (R%d+R%d, %d)", m, i->rd, i->rs1, i->rs2, i->asi);
726219b2ee8SDavid du Colombier 	else
727219b2ee8SDavid du Colombier 		bprint(i, "%s\tR%d, %d(R%d, %d), ???", m, i->rd, i->simm13, i->rs1, i->asi);
728219b2ee8SDavid du Colombier }
729219b2ee8SDavid du Colombier 
7307dd7cddfSDavid du Colombier static void
731219b2ee8SDavid du Colombier shift(Instr *i, char *m)	/* page 88 */
732219b2ee8SDavid du Colombier {
733219b2ee8SDavid du Colombier 	if(i->i == 0){
734219b2ee8SDavid du Colombier 		if(i->rs1 == i->rd)
735219b2ee8SDavid du Colombier 			if(dascase)
736219b2ee8SDavid du Colombier 				bprint(i, "%X\tR%d, R%d", m, i->rs1, i->rs2);
737219b2ee8SDavid du Colombier 			else
738219b2ee8SDavid du Colombier 				bprint(i, "%X\tR%d, R%d", m, i->rs2, i->rs1);
739219b2ee8SDavid du Colombier 		else
740219b2ee8SDavid du Colombier 			if(dascase)
741219b2ee8SDavid du Colombier 				bprint(i, "%X\tR%d, R%d, R%d", m, i->rs1, i->rs2, i->rd);
742219b2ee8SDavid du Colombier 			else
743219b2ee8SDavid du Colombier 				bprint(i, "%X\tR%d, R%d, R%d", m, i->rs2, i->rs1, i->rd);
744219b2ee8SDavid du Colombier 	}else{
745219b2ee8SDavid du Colombier 		if(i->rs1 == i->rd)
746219b2ee8SDavid du Colombier 			if(dascase)
747219b2ee8SDavid du Colombier 				bprint(i, "%X\t$%d,R%d", m, i->simm13&0x1F, i->rs1);
748219b2ee8SDavid du Colombier 			else
749219b2ee8SDavid du Colombier 				bprint(i, "%X\tR%d, $%d", m,  i->rs1, i->simm13&0x1F);
750219b2ee8SDavid du Colombier 		else
751219b2ee8SDavid du Colombier 			if(dascase)
752219b2ee8SDavid du Colombier 				bprint(i, "%X\tR%d, $%d, R%d",m,i->rs1,i->simm13&0x1F,i->rd);
753219b2ee8SDavid du Colombier 			else
754219b2ee8SDavid du Colombier 				bprint(i, "%X\t$%d, R%d, R%d",m,i->simm13&0x1F,i->rs1,i->rd);
755219b2ee8SDavid du Colombier 	}
756219b2ee8SDavid du Colombier }
757219b2ee8SDavid du Colombier 
758219b2ee8SDavid du Colombier static void
759219b2ee8SDavid du Colombier add(Instr *i, char *m)	/* page 82 */
760219b2ee8SDavid du Colombier {
761219b2ee8SDavid du Colombier 	if(i->i == 0){
762219b2ee8SDavid du Colombier 		if(dascase)
763219b2ee8SDavid du Colombier 			bprint(i, "%X\tR%d, R%d", m, i->rs1, i->rs2);
764219b2ee8SDavid du Colombier 		else
765219b2ee8SDavid du Colombier 			if(i->op3==2 && i->rs1==0 && i->rd)  /* OR R2, R0, R1 */
766219b2ee8SDavid du Colombier 				bprint(i, "MOVW\tR%d", i->rs2);
767219b2ee8SDavid du Colombier 			else
768219b2ee8SDavid du Colombier 				bprint(i, "%X\tR%d, R%d", m, i->rs2, i->rs1);
769219b2ee8SDavid du Colombier 	}else{
770219b2ee8SDavid du Colombier 		if(dascase)
771219b2ee8SDavid du Colombier 			bprint(i, "%X\tR%d, $%lux", m, i->rs1, i->simm13);
772219b2ee8SDavid du Colombier 		else
773219b2ee8SDavid du Colombier 			if(i->op3==0 && i->rd && i->rs1==0)	/* ADD $x, R0, R1 */
774219b2ee8SDavid du Colombier 				bprint(i, "MOVW\t$%lux", i->simm13);
775219b2ee8SDavid du Colombier 			else if(i->op3==0 && i->rd && i->rs1==2){
776219b2ee8SDavid du Colombier 				/* ADD $x, R2, R1 -> MOVW $x(SB), R1 */
777219b2ee8SDavid du Colombier 				bprint(i, "MOVW\t$");
778219b2ee8SDavid du Colombier 				address(i);
779219b2ee8SDavid du Colombier 			} else
780219b2ee8SDavid du Colombier 				bprint(i, "%X\t$%lux, R%d", m, i->simm13, i->rs1);
781219b2ee8SDavid du Colombier 	}
782219b2ee8SDavid du Colombier 	if(i->rs1 != i->rd)
783219b2ee8SDavid du Colombier 		bprint(i, ", R%d", i->rd);
784219b2ee8SDavid du Colombier }
785219b2ee8SDavid du Colombier 
786219b2ee8SDavid du Colombier static void
787219b2ee8SDavid du Colombier cmp(Instr *i, char *m)
788219b2ee8SDavid du Colombier {
789219b2ee8SDavid du Colombier 	if(dascase || i->rd){
790219b2ee8SDavid du Colombier 		add(i, m);
791219b2ee8SDavid du Colombier 		return;
792219b2ee8SDavid du Colombier 	}
793219b2ee8SDavid du Colombier 	if(i->i == 0)
794219b2ee8SDavid du Colombier 		bprint(i, "CMP\tR%d, R%d", i->rs1, i->rs2);
795219b2ee8SDavid du Colombier 	else
796219b2ee8SDavid du Colombier 		bprint(i, "CMP\tR%d, $%lux", i->rs1, i->simm13);
797219b2ee8SDavid du Colombier }
798219b2ee8SDavid du Colombier 
799219b2ee8SDavid du Colombier static char *regtab[4] = {
800219b2ee8SDavid du Colombier 	"Y",
801219b2ee8SDavid du Colombier 	"PSR",
802219b2ee8SDavid du Colombier 	"WIM",
803219b2ee8SDavid du Colombier 	"TBR",
804219b2ee8SDavid du Colombier };
805219b2ee8SDavid du Colombier 
806219b2ee8SDavid du Colombier static void
807219b2ee8SDavid du Colombier wr(Instr *i, char *m)		/* page 82 */
808219b2ee8SDavid du Colombier {
809219b2ee8SDavid du Colombier 	if(dascase){
810219b2ee8SDavid du Colombier 		if(i->i == 0)
811219b2ee8SDavid du Colombier 			bprint(i, "%s\tR%d, R%d", m, i->rs1, i->rs2);
812219b2ee8SDavid du Colombier 		else
813219b2ee8SDavid du Colombier 			bprint(i, "%s\tR%d, $%lux", m, i->rs1, i->simm13);
814219b2ee8SDavid du Colombier 	}else{
815219b2ee8SDavid du Colombier 		if(i->i && i->simm13==0)
816219b2ee8SDavid du Colombier 			bprint(i, "MOVW\tR%d", i->rs1);
817219b2ee8SDavid du Colombier 		else if(i->i == 0)
818219b2ee8SDavid du Colombier 			bprint(i, "wr\tR%d, R%d", i->rs2, i->rs1);
819219b2ee8SDavid du Colombier 		else
820219b2ee8SDavid du Colombier 			bprint(i, "wr\t$%lux, R%d", i->simm13, i->rs1);
821219b2ee8SDavid du Colombier 	}
822219b2ee8SDavid du Colombier 	bprint(i, ", %s", regtab[i->op3&3]);
823219b2ee8SDavid du Colombier }
824219b2ee8SDavid du Colombier 
825219b2ee8SDavid du Colombier static void
826219b2ee8SDavid du Colombier rd(Instr *i, char *m)		/* page 103 */
827219b2ee8SDavid du Colombier {
828219b2ee8SDavid du Colombier 	if(i->rs1==15 && i->rd==0){
829219b2ee8SDavid du Colombier 		m = "stbar";
830219b2ee8SDavid du Colombier 		if(!dascase)
831219b2ee8SDavid du Colombier 			m = "STBAR";
832219b2ee8SDavid du Colombier 		bprint(i, "%s", m);
833219b2ee8SDavid du Colombier 	}else{
834219b2ee8SDavid du Colombier 		if(!dascase)
835219b2ee8SDavid du Colombier 			m = "MOVW";
836219b2ee8SDavid du Colombier 		bprint(i, "%s\t%s, R%d", m, regtab[i->op3&3], i->rd);
837219b2ee8SDavid du Colombier 	}
838219b2ee8SDavid du Colombier }
839219b2ee8SDavid du Colombier 
840219b2ee8SDavid du Colombier static void
841219b2ee8SDavid du Colombier jmpl(Instr *i, char *m)		/* page 82 */
842219b2ee8SDavid du Colombier {
843219b2ee8SDavid du Colombier 	if(i->i == 0){
844219b2ee8SDavid du Colombier 		if(i->rd == 15)
845219b2ee8SDavid du Colombier 			bprint(i, "%X\t(R%d+R%d)", "CALL", i->rs2, i->rs1);
846219b2ee8SDavid du Colombier 		else
847219b2ee8SDavid du Colombier 			bprint(i, "%X\t(R%d+R%d), R%d", m, i->rs2, i->rs1, i->rd);
848219b2ee8SDavid du Colombier 	}else{
849219b2ee8SDavid du Colombier 		if(!dascase && i->simm13==8 && i->rs1==15 && i->rd==0)
850219b2ee8SDavid du Colombier 			bprint(i, "RETURN");
851219b2ee8SDavid du Colombier 		else{
852219b2ee8SDavid du Colombier 			bprint(i, "%X\t", m);
853219b2ee8SDavid du Colombier 			address(i);
854219b2ee8SDavid du Colombier 			bprint(i, ", R%d", i->rd);
855219b2ee8SDavid du Colombier 		}
856219b2ee8SDavid du Colombier 	}
857219b2ee8SDavid du Colombier }
858219b2ee8SDavid du Colombier 
859219b2ee8SDavid du Colombier static void
860219b2ee8SDavid du Colombier loadf(Instr *i, char *m)		/* page 70 */
861219b2ee8SDavid du Colombier {
862219b2ee8SDavid du Colombier 	if(!dascase){
863219b2ee8SDavid du Colombier 		m = "FMOVD";
864219b2ee8SDavid du Colombier 		if(i->op3 == 0x20)
865219b2ee8SDavid du Colombier 			m = "FMOVF";
866219b2ee8SDavid du Colombier 		else if(i->op3 == 0x21)
867219b2ee8SDavid du Colombier 			m = "MOVW";
868219b2ee8SDavid du Colombier 	}
869219b2ee8SDavid du Colombier 	if(i->i == 0)
870219b2ee8SDavid du Colombier 		bprint(i, "%s\t(R%d+R%d)", m, i->rs1, i->rs2);
871219b2ee8SDavid du Colombier 	else{
872219b2ee8SDavid du Colombier 		bprint(i, "%s\t", m);
873219b2ee8SDavid du Colombier 		address(i);
874219b2ee8SDavid du Colombier 	}
875219b2ee8SDavid du Colombier 	if(i->op3 == 0x21)
876219b2ee8SDavid du Colombier 		bprint(i, ", FSR");
877219b2ee8SDavid du Colombier 	else
878219b2ee8SDavid du Colombier 		bprint(i, ", R%d", i->rd);
879219b2ee8SDavid du Colombier }
880219b2ee8SDavid du Colombier 
881219b2ee8SDavid du Colombier static
882219b2ee8SDavid du Colombier void storef(Instr *i, char *m)		/* page 70 */
883219b2ee8SDavid du Colombier {
884219b2ee8SDavid du Colombier 	if(!dascase){
885219b2ee8SDavid du Colombier 		m = "FMOVD";
886219b2ee8SDavid du Colombier 		if(i->op3 == 0x25 || i->op3 == 0x26)
887219b2ee8SDavid du Colombier 			m = "MOVW";
888219b2ee8SDavid du Colombier 		else if(i->op3 == 0x20)
889219b2ee8SDavid du Colombier 			m = "FMOVF";
890219b2ee8SDavid du Colombier 	}
891219b2ee8SDavid du Colombier 	bprint(i, "%s\t", m);
892219b2ee8SDavid du Colombier 	if(i->op3 == 0x25)
893219b2ee8SDavid du Colombier 		bprint(i, "FSR, ");
894219b2ee8SDavid du Colombier 	else if(i->op3 == 0x26)
895219b2ee8SDavid du Colombier 		bprint(i, "FQ, ");
896219b2ee8SDavid du Colombier 	else
897219b2ee8SDavid du Colombier 		bprint(i, "R%d, ", i->rd);
898219b2ee8SDavid du Colombier 	if(i->i == 0)
899219b2ee8SDavid du Colombier 		bprint(i, "(R%d+R%d)", i->rs1, i->rs2);
900219b2ee8SDavid du Colombier 	else
901219b2ee8SDavid du Colombier 		address(i);
902219b2ee8SDavid du Colombier }
903219b2ee8SDavid du Colombier 
904219b2ee8SDavid du Colombier static
905219b2ee8SDavid du Colombier void loadc(Instr *i, char *m)			/* page 72 */
906219b2ee8SDavid du Colombier {
907219b2ee8SDavid du Colombier 	if(i->i == 0)
908219b2ee8SDavid du Colombier 		bprint(i, "%s\t(R%d+R%d), C%d", m, i->rs1, i->rs2, i->rd);
909219b2ee8SDavid du Colombier 	else{
910219b2ee8SDavid du Colombier 		bprint(i, "%s\t", m);
911219b2ee8SDavid du Colombier 		address(i);
912219b2ee8SDavid du Colombier 		bprint(i, ", C%d", i->rd);
913219b2ee8SDavid du Colombier 	}
914219b2ee8SDavid du Colombier }
915219b2ee8SDavid du Colombier 
916219b2ee8SDavid du Colombier static
917219b2ee8SDavid du Colombier void loadcsr(Instr *i, char *m)			/* page 72 */
918219b2ee8SDavid du Colombier {
919219b2ee8SDavid du Colombier 	if(i->i == 0)
920219b2ee8SDavid du Colombier 		bprint(i, "%s\t(R%d+R%d), CSR", m, i->rs1, i->rs2);
921219b2ee8SDavid du Colombier 	else{
922219b2ee8SDavid du Colombier 		bprint(i, "%s\t", m);
923219b2ee8SDavid du Colombier 		address(i);
924219b2ee8SDavid du Colombier 		bprint(i, ", CSR");
925219b2ee8SDavid du Colombier 	}
926219b2ee8SDavid du Colombier }
927219b2ee8SDavid du Colombier 
928219b2ee8SDavid du Colombier static struct{
929219b2ee8SDavid du Colombier 	int	opf;
930219b2ee8SDavid du Colombier 	char	*name;
931219b2ee8SDavid du Colombier } fptab1[] = {			/* ignores rs1 */
932219b2ee8SDavid du Colombier 	0xC4,	"FITOS",	/* page 109 */
933219b2ee8SDavid du Colombier 	0xC8,	"FITOD",
934219b2ee8SDavid du Colombier 	0xCC,	"FITOX",
935219b2ee8SDavid du Colombier 
936219b2ee8SDavid du Colombier 	0xD1,	"FSTOI",	/* page 110 */
937219b2ee8SDavid du Colombier 	0xD2,	"FDTOI",
938219b2ee8SDavid du Colombier 	0xD3,	"FXTOI",
939219b2ee8SDavid du Colombier 
940219b2ee8SDavid du Colombier 	0xC9,	"FSTOD",	/* page 111 */
941219b2ee8SDavid du Colombier 	0xCD,	"FSTOX",
942219b2ee8SDavid du Colombier 	0xC6,	"FDTOS",
943219b2ee8SDavid du Colombier 	0xCE,	"FDTOX",
944219b2ee8SDavid du Colombier 	0xC7,	"FXTOS",
945219b2ee8SDavid du Colombier 	0xCB,	"FXTOD",
946219b2ee8SDavid du Colombier 
947219b2ee8SDavid du Colombier 	0x01,	"FMOVS",	/* page 112 */
948219b2ee8SDavid du Colombier 	0x05,	"FNEGS",
949219b2ee8SDavid du Colombier 	0x09,	"FABSS",
950219b2ee8SDavid du Colombier 
951219b2ee8SDavid du Colombier 	0x29,	"FSQRTS", 	/* page 113 */
952219b2ee8SDavid du Colombier 	0x2A,	"FSQRTD",
953219b2ee8SDavid du Colombier 	0x2B,	"FSQRTX",
954219b2ee8SDavid du Colombier 
955219b2ee8SDavid du Colombier 	0,	0,
956219b2ee8SDavid du Colombier };
957219b2ee8SDavid du Colombier 
958219b2ee8SDavid du Colombier static struct{
959219b2ee8SDavid du Colombier 	int	opf;
960219b2ee8SDavid du Colombier 	char	*name;
961219b2ee8SDavid du Colombier } fptab2[] = {			/* uses rs1 */
962219b2ee8SDavid du Colombier 
963219b2ee8SDavid du Colombier 	0x41,	"FADDS",	/* page 114 */
964219b2ee8SDavid du Colombier 	0x42,	"FADDD",
965219b2ee8SDavid du Colombier 	0x43,	"FADDX",
966219b2ee8SDavid du Colombier 	0x45,	"FSUBS",
967219b2ee8SDavid du Colombier 	0x46,	"FSUBD",
968219b2ee8SDavid du Colombier 	0x47,	"FSUBX",
969219b2ee8SDavid du Colombier 
970219b2ee8SDavid du Colombier 	0x49,	"FMULS",	/* page 115 */
971219b2ee8SDavid du Colombier 	0x4A,	"FMULD",
972219b2ee8SDavid du Colombier 	0x4B,	"FMULX",
973219b2ee8SDavid du Colombier 	0x4D,	"FDIVS",
974219b2ee8SDavid du Colombier 	0x4E,	"FDIVD",
975219b2ee8SDavid du Colombier 	0x4F,	"FDIVX",
976219b2ee8SDavid du Colombier 
977219b2ee8SDavid du Colombier 	0x51,	"FCMPS",	/* page 116 */
978219b2ee8SDavid du Colombier 	0x52,	"FCMPD",
979219b2ee8SDavid du Colombier 	0x53,	"FCMPX",
980219b2ee8SDavid du Colombier 	0x55,	"FCMPES",
981219b2ee8SDavid du Colombier 	0x56,	"FCMPED",
982219b2ee8SDavid du Colombier 	0x57,	"FCMPEX",
983219b2ee8SDavid du Colombier 
984219b2ee8SDavid du Colombier 	0, 0
985219b2ee8SDavid du Colombier };
986219b2ee8SDavid du Colombier 
987219b2ee8SDavid du Colombier static void
988219b2ee8SDavid du Colombier fpop(Instr *i, char *m)	/* page 108-116 */
989219b2ee8SDavid du Colombier {
990219b2ee8SDavid du Colombier 	int j;
991219b2ee8SDavid du Colombier 
992219b2ee8SDavid du Colombier 	if(dascase==0 && i->size==2){
993219b2ee8SDavid du Colombier 		bprint(i, "FMOVD\tF%d, F%d", i->rs2, i->rd);
994219b2ee8SDavid du Colombier 		return;
995219b2ee8SDavid du Colombier 	}
996219b2ee8SDavid du Colombier 	for(j=0; fptab1[j].name; j++)
997219b2ee8SDavid du Colombier 		if(fptab1[j].opf == i->opf){
998219b2ee8SDavid du Colombier 			bprint(i, "%X\tF%d, F%d", fptab1[j].name, i->rs2, i->rd);
999219b2ee8SDavid du Colombier 			return;
1000219b2ee8SDavid du Colombier 		}
1001219b2ee8SDavid du Colombier 	for(j=0; fptab2[j].name; j++)
1002219b2ee8SDavid du Colombier 		if(fptab2[j].opf == i->opf){
1003219b2ee8SDavid du Colombier 			bprint(i, "%X\tF%d, F%d, F%d", fptab2[j].name, i->rs1, i->rs2, i->rd);
1004219b2ee8SDavid du Colombier 			return;
1005219b2ee8SDavid du Colombier 		}
1006219b2ee8SDavid du Colombier 	bprint(i, "%X%ux\tF%d, F%d, F%d", m, i->opf, i->rs1, i->rs2, i->rd);
1007219b2ee8SDavid du Colombier }
1008219b2ee8SDavid du Colombier 
1009219b2ee8SDavid du Colombier static int
1010219b2ee8SDavid du Colombier sparcfoll(Map *map, ulong pc, Rgetter rget, ulong *foll)
1011219b2ee8SDavid du Colombier {
1012219b2ee8SDavid du Colombier 	ulong w, r1, r2;
1013219b2ee8SDavid du Colombier 	char buf[8];
1014219b2ee8SDavid du Colombier 	Instr i;
1015219b2ee8SDavid du Colombier 
1016219b2ee8SDavid du Colombier 	mymap = map;
1017219b2ee8SDavid du Colombier 	if (mkinstr(pc, &i) < 0)
1018219b2ee8SDavid du Colombier 		return -1;
1019219b2ee8SDavid du Colombier 	w = i.w0;
1020219b2ee8SDavid du Colombier 	switch(w & 0xC1C00000){
1021219b2ee8SDavid du Colombier 	case 0x00800000:		/* branch on int cond */
1022219b2ee8SDavid du Colombier 	case 0x01800000:		/* branch on fp cond */
1023219b2ee8SDavid du Colombier 	case 0x01C00000:		/* branch on copr cond */
1024219b2ee8SDavid du Colombier 		foll[0] = pc+8;
1025219b2ee8SDavid du Colombier 		foll[1] = pc + (i.simmdisp22<<2);
1026219b2ee8SDavid du Colombier 		return 2;
1027219b2ee8SDavid du Colombier 	}
1028219b2ee8SDavid du Colombier 
1029219b2ee8SDavid du Colombier 	if((w&0xC0000000) == 0x40000000){	/* CALL */
1030219b2ee8SDavid du Colombier 		foll[0] = pc + (i.disp30<<2);
1031219b2ee8SDavid du Colombier 		return 1;
1032219b2ee8SDavid du Colombier 	}
1033219b2ee8SDavid du Colombier 
1034219b2ee8SDavid du Colombier 	if((w&0xC1F80000) == 0x81C00000){	/* JMPL */
10357dd7cddfSDavid du Colombier 		sprint(buf, "R%ld", (w>>14)&0xF);
1036219b2ee8SDavid du Colombier 		r1 = (*rget)(map, buf);
1037219b2ee8SDavid du Colombier 		if(w & 0x2000)			/* JMPL R1+simm13 */
1038219b2ee8SDavid du Colombier 			r2 = i.simm13;
1039219b2ee8SDavid du Colombier 		else{				/* JMPL R1+R2 */
10407dd7cddfSDavid du Colombier 			sprint(buf, "R%ld", w&0xF);
1041219b2ee8SDavid du Colombier 			r2 = (*rget)(map, buf);
1042219b2ee8SDavid du Colombier 		}
1043219b2ee8SDavid du Colombier 		foll[0] = r1 + r2;
1044219b2ee8SDavid du Colombier 		return 1;
1045219b2ee8SDavid du Colombier 	}
1046219b2ee8SDavid du Colombier 	foll[0] = pc+i.size*4;
1047219b2ee8SDavid du Colombier 	return 1;
1048219b2ee8SDavid du Colombier }
1049