xref: /inferno-os/libinterp/das-sparc.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1 #include <lib9.h>
2 
3 	/* Sparc disassembler and related functions */
4 
5 typedef struct instr Instr;
6 
7 struct opcode
8 {
9 	char	*mnemonic;
10 	void	(*f)(Instr*, char*);
11 	int	flag;
12 };
13 
14 static	char FRAMENAME[] = ".frame";
15 
16 
17 struct instr
18 {
19 	uchar	op;		/* bits 31-30 */
20 	uchar	rd;		/* bits 29-25 */
21 	uchar	op2;		/* bits 24-22 */
22 	uchar	a;		/* bit  29    */
23 	uchar	cond;		/* bits 28-25 */
24 	uchar	op3;		/* bits 24-19 */
25 	uchar	rs1;		/* bits 18-14 */
26 	uchar	i;		/* bit  13    */
27 	uchar	asi;		/* bits 12-05 */
28 	uchar	rs2;		/* bits 04-00 */
29 	short	simm13;		/* bits 12-00, signed */
30 	ushort	opf;		/* bits 13-05 */
31 	ulong	immdisp22;	/* bits 21-00 */
32 	ulong	simmdisp22;	/* bits 21-00, signed */
33 	ulong	disp30;		/* bits 30-00 */
34 	ulong	imm32;		/* SETHI+ADD constant */
35 	int	target;		/* SETHI+ADD dest reg */
36 	long	w0;
37 	long	w1;
38 	ulong	addr;		/* pc of instruction */
39 	char*	curr;		/* current fill level in output buffer */
40 	char*	end;		/* end of buffer */
41 	int 	size;		/* number of longs in instr */
42 	char*	err;		/* errmsg */
43 };
44 
45 static	int	dascase;
46 
47 static int	mkinstr(ulong*, Instr*);
48 static void	bra1(Instr*, char*, char*[]);
49 static void	bra(Instr*, char*);
50 static void	fbra(Instr*, char*);
51 static void	cbra(Instr*, char*);
52 static void	unimp(Instr*, char*);
53 static void	fpop(Instr*, char*);
54 static void	shift(Instr*, char*);
55 static void	sethi(Instr*, char*);
56 static void	load(Instr*, char*);
57 static void	loada(Instr*, char*);
58 static void	store(Instr*, char*);
59 static void	storea(Instr*, char*);
60 static void	add(Instr*, char*);
61 static void	cmp(Instr*, char*);
62 static void	wr(Instr*, char*);
63 static void	jmpl(Instr*, char*);
64 static void	rd(Instr*, char*);
65 static void	loadf(Instr*, char*);
66 static void	storef(Instr*, char*);
67 static void	loadc(Instr*, char*);
68 static void	loadcsr(Instr*, char*);
69 static void	trap(Instr*, char*);
70 
71 static struct opcode sparcop0[8] = {
72 	/* [0] */	"UNIMP",	unimp,	0,	/* page 137 */
73 		0,		0,	0,
74 	/* [2] */	"B",		bra,	0,	/* page 119 */
75 		0,		0,	0,
76 	/* [4] */	"SETHI",	sethi,	0,	/* page 104 */
77 		0,		0,	0,
78 	/* [6] */	"FB",		fbra,	0,	/* page 121 */
79 	/* [7] */	"CB",		cbra,	0,	/* page 123 */
80 };
81 
82 static struct opcode sparcop2[64] = {
83 	/* [0x00] */	"ADD",		add,	0,	/* page 108 */
84 	/* [0x01] */	"AND",		add,	0,	/* page 106 */
85 	/* [0x02] */	"OR",		add,	0,
86 	/* [0x03] */	"XOR",		add,	0,
87 	/* [0x04] */	"SUB",		add,	0,	/* page 110 */
88 	/* [0x05] */	"ANDN",		add,	0,
89 	/* [0x06] */	"ORN",		add,	0,
90 	/* [0x07] */	"XORN",		add,	0,
91 	/* [0x08] */	"ADDX",		add,	0,
92 			0,		0,	0,
93 	/* [0x0A] */	"UMUL",		add,	0,	/* page 113 */
94 	/* [0x0B] */	"SMUL",		add,	0,
95 	/* [0x0C] */	"SUBX",		add,	0,
96 			0,		0,	0,
97 	/* [0x0E] */	"UDIV",		add,	0,	/* page 115 */
98 	/* [0x0F] */	"SDIV",		add,	0,
99 	/* [0x10] */	"ADDCC",	add,	0,
100 	/* [0x11] */	"ANDCC",	add,	0,
101 	/* [0x12] */	"ORCC",		add,	0,
102 	/* [0x13] */	"XORCC",	add,	0,
103 	/* [0x14] */	"SUBCC",	cmp,	0,
104 	/* [0x15] */	"ANDNCC",	add,	0,
105 	/* [0x16] */	"ORNCC",	add,	0,
106 	/* [0x17] */	"XORNCC",	add,	0,
107 	/* [0x18] */	"ADDXCC",	add,	0,
108 			0,		0,	0,
109 	/* [0x1A] */	"UMULCC",	add,	0,
110 	/* [0x1B] */	"SMULCC",	add,	0,
111 	/* [0x1C] */	"SUBXCC",	add,	0,
112 			0,		0,	0,
113 	/* [0x1E] */	"UDIVCC",	add,	0,
114 	/* [0x1F] */	"SDIVCC",	add,	0,
115 	/* [0x20] */	"TADD",		add,	0,	/* page 109 */
116 	/* [0x21] */	"TSUB",		add,	0,	/* page 111 */
117 	/* [0x22] */	"TADDCCTV",	add,	0,
118 	/* [0x23] */	"TSUBCCTV",	add,	0,
119 	/* [0x24] */	"MULSCC",	add,	0,	/* page 112 */
120 	/* [0x25] */	"SLL",		shift,	0,	/* page 107 */
121 	/* [0x26] */	"SRL",		shift,	0,
122 	/* [0x27] */	"SRA",		shift,	0,
123 	/* [0x28] */	"rdy",		rd,	0,	/* page 131 */
124 	/* [0x29] */	"rdpsr",	rd,	0,
125 	/* [0x2A] */	"rdwim",	rd,	0,
126 	/* [0x2B] */	"rdtbr",	rd,	0,
127 			0,		0,	0,
128 			0,		0,	0,
129 			0,		0,	0,
130 			0,		0,	0,
131 	/* [0x30] */	"wry",		wr,	0,	/* page 133 */
132 	/* [0x31] */	"wrpsr",	wr,	0,
133 	/* [0x32] */	"wrwim",	wr,	0,
134 	/* [0x33] */	"wrtbr",	wr,	0,
135 	/* [0x34] */	"FPOP",		fpop,	0,	/* page 140 */
136 	/* [0x35] */	"FPOP",		fpop,	0,
137 			0,		0,	0,
138 			0,		0,	0,
139 	/* [0x38] */	"JMPL",		jmpl,	0,	/* page 126 */
140 	/* [0x39] */	"RETT",		add,	0,	/* page 127 */
141 	/* [0x3A] */	"T",		trap,	0,	/* page 129 */
142 	/* [0x3B] */	"flush",	add,	0,	/* page 138 */
143 	/* [0x3C] */	"SAVE",		add,	0,	/* page 117 */
144 	/* [0x3D] */	"RESTORE",	add,	0,
145 };
146 
147 static struct opcode sparcop3[64]={
148 	/* [0x00] */	"ld",		load,	0,
149 	/* [0x01] */	"ldub",		load,	0,
150 	/* [0x02] */	"lduh",		load,	0,
151 	/* [0x03] */	"ldd",		load,	0,
152 	/* [0x04] */	"st",		store,	0,
153 	/* [0x05] */	"stb",		store,	0,	/* page 95 */
154 	/* [0x06] */	"sth",		store,	0,
155 	/* [0x07] */	"std",		store,	0,
156 			0,		0,	0,
157 	/* [0x09] */	"ldsb",		load,	0,	/* page 90 */
158 	/* [0x0A] */	"ldsh",		load,	0,
159 			0,		0,	0,
160 			0,		0,	0,
161 	/* [0x0D] */	"ldstub",	store,	0,	/* page 101 */
162 			0,		0,	0,
163 	/* [0x0F] */	"swap",		load,	0,	/* page 102 */
164 	/* [0x10] */	"lda",		loada,	0,
165 	/* [0x11] */	"lduba",	loada,	0,
166 	/* [0x12] */	"lduha",	loada,	0,
167 	/* [0x13] */	"ldda",		loada,	0,
168 	/* [0x14] */	"sta",		storea,	0,
169 	/* [0x15] */	"stba",		storea,	0,
170 	/* [0x16] */	"stha",		storea,	0,
171 	/* [0x17] */	"stda",		storea,	0,
172 			0,		0,	0,
173 	/* [0x19] */	"ldsba",	loada,	0,
174 	/* [0x1A] */	"ldsha",	loada,	0,
175 			0,		0,	0,
176 			0,		0,	0,
177 	/* [0x1D] */	"ldstuba",	storea,	0,
178 			0,		0,	0,
179 	/* [0x1F] */	"swapa",	loada,	0,
180 	/* [0x20] */	"ldf",		loadf,	0,	/* page 92 */
181 	/* [0x21] */	"ldfsr",	loadf,	0,
182 			0,		0,	0,
183 	/* [0x23] */	"lddf",		loadf,	0,
184 	/* [0x24] */	"stf",		storef,	0,	/* page 97 */
185 	/* [0x25] */	"stfsr",	storef,	0,
186 	/* [0x26] */	"stdfq",	storef,	0,
187 	/* [0x27] */	"stdf",		storef,	0,
188 			0,		0,	0,
189 			0,		0,	0,
190 			0,		0,	0,
191 			0,		0,	0,
192 			0,		0,	0,
193 			0,		0,	0,
194 			0,		0,	0,
195 			0,		0,	0,
196 	/* [0x30] */	"ldc",		loadc,	0,	/* page 94 */
197 	/* [0x31] */	"ldcsr",	loadcsr,0,
198 			0,		0,	0,
199 	/* [0x33] */	"lddc",		loadc,	0,
200 	/* [0x34] */	"stc",		loadc,	0,	/* page 99 */
201 	/* [0x35] */	"stcsr",	loadcsr,0,
202 	/* [0x36] */	"stdcq",	loadcsr,0,
203 	/* [0x37] */	"stdc",		loadc,	0,
204 };
205 
206 static void
bprint(Instr * i,char * fmt,...)207 bprint(Instr *i, char *fmt, ...)
208 {
209 	va_list arg;
210 
211 	va_start(arg, fmt);
212 	i->curr = vseprint(i->curr, i->end, fmt, arg);
213 	va_end(arg);
214 }
215 
216 static int
decode(ulong * pc,Instr * i)217 decode(ulong *pc, Instr *i)
218 {
219 	ulong w;
220 
221 	w = *pc;
222 
223 	i->op = (w >> 30) & 0x03;
224 	i->rd = (w >> 25) & 0x1F;
225 	i->op2 = (w >> 22) & 0x07;
226 	i->a = (w >> 29) & 0x01;
227 	i->cond = (w >> 25) & 0x0F;
228 	i->op3 = (w >> 19) & 0x3F;
229 	i->rs1 = (w >> 14) & 0x1F;
230 	i->i = (w >> 13) & 0x01;
231 	i->asi = (w >> 5) & 0xFF;
232 	i->rs2 = (w >> 0) & 0x1F;
233 	i->simm13 = (w >> 0) & 0x1FFF;
234 	if(i->simm13 & (1<<12))
235 		i->simm13 |= ~((1<<13)-1);
236 	i->opf = (w >> 5) & 0x1FF;
237 	i->immdisp22 = (w >> 0) & 0x3FFFFF;
238 	i->simmdisp22 = i->immdisp22;
239 	if(i->simmdisp22 & (1<<21))
240 		i->simmdisp22 |= ~((1<<22)-1);
241 	i->disp30 = (w >> 0) & 0x3FFFFFFF;
242 	i->w0 = w;
243 	i->target = -1;
244 	i->addr = (ulong)pc;
245 	i->size = 1;
246 	return 1;
247 }
248 
249 static int
mkinstr(ulong * pc,Instr * i)250 mkinstr(ulong *pc, Instr *i)
251 {
252 	Instr xi;
253 
254 	if (decode(pc, i) < 0)
255 		return -1;
256 	if(i->op==0 && i->op2==4 && !dascase){		/* SETHI */
257 		if(decode(pc+1, &xi) < 0)
258 			return -1;
259 		if(xi.op == 2 && xi.op3 == 0)		/* ADD */
260 		if(xi.i == 1 && xi.rs1 == i->rd){	/* immediate to same reg */
261 			i->imm32 = xi.simm13 + (i->immdisp22<<10);
262 			i->target = xi.rd;
263 			i->w1 = xi.w0;
264 			i->size++;
265 			return 1;
266 		}
267 	}
268 	if(i->op==2 && i->opf==1 && !dascase){		/* FMOVS */
269 		if (decode(pc+1, &xi) < 0)
270 			return -1;
271 		if(i->op==2 && i->opf==1)		/* FMOVS */
272 		if(xi.rd==i->rd+1 && xi.rs2==i->rs2+1){	/* next pair */
273 			i->w1 = xi.w0;
274 			i->size++;
275 		}
276 	}
277 	return 1;
278 }
279 
280 static int
inst(ulong * pc)281 inst(ulong *pc)
282 {
283 	long disp;
284 	Instr instr;
285 	static char buf[128];
286 	void (*f)(Instr*, char*);
287 
288 	memset(&instr, 0, sizeof(instr));
289 	instr.curr = buf;
290 	instr.end = buf+sizeof(buf)-1;
291 	if(mkinstr(pc, &instr) < 0)
292 		return 4;
293 	switch(instr.op){
294 	case 0:
295 		f = sparcop0[instr.op2].f;
296 		if(f)
297 			(*f)(&instr, sparcop0[instr.op2].mnemonic);
298 		else
299 			bprint(&instr, "unknown 0x%lux", instr.w0);
300 		break;
301 
302 	case 1:
303 		disp = instr.disp30;
304 		disp = (disp<<2)>>2;
305 		bprint(&instr, "CALL\t0x%lux", pc+disp);
306 		if (!dascase)
307 			bprint(&instr, "(SB)");
308 		break;
309 
310 	case 2:
311 		f = sparcop2[instr.op3].f;
312 		if(f)
313 			(*f)(&instr, sparcop2[instr.op3].mnemonic);
314 		else
315 			bprint(&instr, "unknown 0x%lux", instr.w0);
316 		break;
317 
318 	case 3:
319 		f = sparcop3[instr.op3].f;
320 		if(f)
321 			(*f)(&instr, sparcop3[instr.op3].mnemonic);
322 		else
323 			bprint(&instr, "unknown 0x%lux", instr.w0);
324 		break;
325 	}
326 	if (instr.err) {
327 		if (instr.curr != buf)
328 			bprint(&instr, "\t\t;");
329 		bprint(&instr, instr.err);
330 	}
331 	print("\t%.8lux %s\n", (ulong)pc, buf);
332 
333 	return instr.size;
334 }
335 
336 void
das(ulong * pc,int n)337 das(ulong *pc, int n)
338 {
339 	ulong *e;
340 
341 	e = pc + n;
342 	while(pc < e)
343 		pc += inst(pc);
344 }
345 
346 static void
address(Instr * i)347 address(Instr *i)
348 {
349 	bprint(i, "0x%lux(R%d)", i->simm13, i->rs1);
350 }
351 
352 static void
unimp(Instr * i,char * m)353 unimp(Instr *i, char *m)
354 {
355 	bprint(i, "%s", m);
356 }
357 
358 static char	*bratab[16] = {	/* page 91 */
359 	/* [0x0] */	"N",
360 	/* [0x1] */	"E",
361 	/* [0x2] */	"LE",
362 	/* [0x3] */	"L",
363 	/* [0x4] */	"LEU",
364 	/* [0x5] */	"CS",
365 	/* [0x6] */	"NEG",
366 	/* [0x7] */	"VS",
367 	/* [0x8] */	"A",
368 	/* [0x9] */	"NE",
369 	/* [0xA] */	"G",
370 	/* [0xB] */	"GE",
371 	/* [0xC] */	"GU",
372 	/* [0xD] */	"CC",
373 	/* [0xE] */	"POS",
374 	/* [0xF] */	"VC",
375 };
376 
377 static char	*fbratab[16] = {	/* page 91 */
378 	/* [0x0] */	"N",
379 	/* [0x1] */	"NE",
380 	/* [0x2] */	"LG",
381 	/* [0x3] */	"UL",
382 	/* [0x4] */	"L",
383 	/* [0x5] */	"UG",
384 	/* [0x6] */	"G",
385 	/* [0x7] */	"U",
386 	/* [0x8] */	"A",
387 	/* [0x9] */	"E",
388 	/* [0xA] */	"UE",
389 	/* [0xB] */	"GE",
390 	/* [0xC] */	"UGE",
391 	/* [0xD] */	"LE",
392 	/* [0xE] */	"ULE",
393 	/* [0xF] */	"O",
394 };
395 
396 static char	*cbratab[16] = {	/* page 91 */
397 	/* [0x0] */	"N",
398 	/* [0x1] */	"123",
399 	/* [0x2] */	"12",
400 	/* [0x3] */	"13",
401 	/* [0x4] */	"1",
402 	/* [0x5] */	"23",
403 	/* [0x6] */	"2",
404 	/* [0x7] */	"3",
405 	/* [0x8] */	"A",
406 	/* [0x9] */	"0",
407 	/* [0xA] */	"03",
408 	/* [0xB] */	"02",
409 	/* [0xC] */	"023",
410 	/* [0xD] */	"01",
411 	/* [0xE] */	"013",
412 	/* [0xF] */	"012",
413 };
414 
415 static void
bra1(Instr * i,char * m,char * tab[])416 bra1(Instr *i, char *m, char *tab[])
417 {
418 	long imm;
419 
420 	imm = i->simmdisp22;
421 	if(i->a)
422 		bprint(i, "%s%s.%c\t", m, tab[i->cond], 'A'+dascase);
423 	else
424 		bprint(i, "%s%s\t", m, tab[i->cond]);
425 	bprint(i, "0x%lux", i->addr+4*imm);
426 	if (!dascase)
427 		bprint(i, "(SB)");
428 }
429 
430 static void
bra(Instr * i,char * m)431 bra(Instr *i, char *m)			/* page 91 */
432 {
433 	bra1(i, m, bratab);
434 }
435 
436 static void
fbra(Instr * i,char * m)437 fbra(Instr *i, char *m)			/* page 93 */
438 {
439 	bra1(i, m, fbratab);
440 }
441 
442 static void
cbra(Instr * i,char * m)443 cbra(Instr *i, char *m)			/* page 95 */
444 {
445 	bra1(i, m, cbratab);
446 }
447 
448 static void
trap(Instr * i,char * m)449 trap(Instr *i, char *m)			/* page 101 */
450 {
451 	if(i->i == 0)
452 		bprint(i, "%s%s\tR%d+R%d", m, bratab[i->cond], i->rs2, i->rs1);
453 	else
454 		bprint(i, "%s%s\t$0x%lux+R%d", m, bratab[i->cond], i->simm13, i->rs1);
455 }
456 
457 static void
sethi(Instr * i,char * m)458 sethi(Instr *i, char *m)		/* page 89 */
459 {
460 	ulong imm;
461 
462 	imm = i->immdisp22<<10;
463 	if(dascase){
464 		bprint(i, "%s\t0x%lux, R%d", m, imm, i->rd);
465 		return;
466 	}
467 	if(imm==0 && i->rd==0){
468 		bprint(i, "NOP");
469 		return;
470 	}
471 	if(i->target < 0){
472 		bprint(i, "MOVW\t$0x%lux, R%d", imm, i->rd);
473 		return;
474 	}
475 	bprint(i, "MOVW\t$0x%lux, R%d", i->imm32, i->target);
476 }
477 
478 static char ldtab[] = {
479 	'W',
480 	'B',
481 	'H',
482 	'D',
483 };
484 
485 static char*
moveinstr(int op3,char * m)486 moveinstr(int op3, char *m)
487 {
488 	char *s;
489 	int c;
490 	static char buf[8];
491 
492 	if(!dascase){
493 		/* batshit cases */
494 		if(op3 == 0xF || op3 == 0x1F)
495 			return "SWAP";
496 		if(op3 == 0xD || op3 == 0x1D)
497 			return "TAS";	/* really LDSTUB */
498 		c = ldtab[op3&3];
499 		s = "";
500 		if((op3&11)==1 || (op3&11)==2)
501 			s="U";
502 		sprint(buf, "MOV%c%s", c, s);
503 		return buf;
504 	}
505 	return m;
506 }
507 
508 static void
load(Instr * i,char * m)509 load(Instr *i, char *m)			/* page 68 */
510 {
511 	m = moveinstr(i->op3, m);
512 	if(i->i == 0)
513 		bprint(i, "%s\t(R%d+R%d), R%d", m, i->rs1, i->rs2, i->rd);
514 	else{
515 		bprint(i, "%s\t", m);
516 		address(i);
517 		bprint(i, ", R%d", i->rd);
518 	}
519 }
520 
521 static void
loada(Instr * i,char * m)522 loada(Instr *i, char *m)		/* page 68 */
523 {
524 	m = moveinstr(i->op3, m);
525 	if(i->i == 0)
526 		bprint(i, "%s\t(R%d+R%d, %d), R%d", m, i->rs1, i->rs2, i->asi, i->rd);
527 	else
528 		bprint(i, "unknown ld asi 0x%lux", i->w0);
529 }
530 
531 static void
store(Instr * i,char * m)532 store(Instr *i, char *m)		/* page 74 */
533 {
534 	m = moveinstr(i->op3, m);
535 	if(i->i == 0)
536 		bprint(i, "%s\tR%d, (R%d+R%d)",
537 				m, i->rd, i->rs1, i->rs2);
538 	else{
539 		bprint(i, "%s\tR%d, ", m, i->rd);
540 		address(i);
541 	}
542 }
543 
544 static void
storea(Instr * i,char * m)545 storea(Instr *i, char *m)		/* page 74 */
546 {
547 	m = moveinstr(i->op3, m);
548 	if(i->i == 0)
549 		bprint(i, "%s\tR%d, (R%d+R%d, %d)", m, i->rd, i->rs1, i->rs2, i->asi);
550 	else
551 		bprint(i, "%s\tR%d, %d(R%d, %d), ???", m, i->rd, i->simm13, i->rs1, i->asi);
552 }
553 
554 static void
shift(Instr * i,char * m)555 shift(Instr *i, char *m)	/* page 88 */
556 {
557 	if(i->i == 0){
558 		if(i->rs1 == i->rd)
559 			if(dascase)
560 				bprint(i, "%s\tR%d, R%d", m, i->rs1, i->rs2);
561 			else
562 				bprint(i, "%s\tR%d, R%d", m, i->rs2, i->rs1);
563 		else
564 			if(dascase)
565 				bprint(i, "%s\tR%d, R%d, R%d", m, i->rs1, i->rs2, i->rd);
566 			else
567 				bprint(i, "%s\tR%d, R%d, R%d", m, i->rs2, i->rs1, i->rd);
568 	}else{
569 		if(i->rs1 == i->rd)
570 			if(dascase)
571 				bprint(i, "%s\t$%d,R%d", m, i->simm13&0x1F, i->rs1);
572 			else
573 				bprint(i, "%s\tR%d, $%d", m,  i->rs1, i->simm13&0x1F);
574 		else
575 			if(dascase)
576 				bprint(i, "%s\tR%d, $%d, R%d",m,i->rs1,i->simm13&0x1F,i->rd);
577 			else
578 				bprint(i, "%s\t$%d, R%d, R%d",m,i->simm13&0x1F,i->rs1,i->rd);
579 	}
580 }
581 
582 static void
add(Instr * i,char * m)583 add(Instr *i, char *m)	/* page 82 */
584 {
585 	if(i->i == 0){
586 		if(dascase)
587 			bprint(i, "%s\tR%d, R%d", m, i->rs1, i->rs2);
588 		else
589 			if(i->op3==2 && i->rs1==0 && i->rd)  /* OR R2, R0, R1 */
590 				bprint(i, "MOVW\tR%d", i->rs2);
591 			else
592 				bprint(i, "%s\tR%d, R%d", m, i->rs2, i->rs1);
593 	}else{
594 		if(dascase)
595 			bprint(i, "%s\tR%d, $0x%lux", m, i->rs1, i->simm13);
596 		else
597 			if(i->op3==0 && i->rd && i->rs1==0)	/* ADD $x, R0, R1 */
598 				bprint(i, "MOVW\t$0x%lux", i->simm13);
599 			else if(i->op3==0 && i->rd && i->rs1==2){
600 				/* ADD $x, R2, R1 -> MOVW $x(SB), R1 */
601 				bprint(i, "MOVW\t$");
602 				address(i);
603 			} else
604 				bprint(i, "%s\t$0x%lux, R%d", m, i->simm13, i->rs1);
605 	}
606 	if(i->rs1 != i->rd)
607 		bprint(i, ", R%d", i->rd);
608 }
609 
610 static void
cmp(Instr * i,char * m)611 cmp(Instr *i, char *m)
612 {
613 	if(dascase || i->rd){
614 		add(i, m);
615 		return;
616 	}
617 	if(i->i == 0)
618 		bprint(i, "CMP\tR%d, R%d", i->rs1, i->rs2);
619 	else
620 		bprint(i, "CMP\tR%d, $0x%lux", i->rs1, i->simm13);
621 }
622 
623 static char *regtab[4] =
624 {
625 	"Y",
626 	"PSR",
627 	"WIM",
628 	"TBR",
629 };
630 
631 static void
wr(Instr * i,char * m)632 wr(Instr *i, char *m)		/* page 82 */
633 {
634 	if(dascase){
635 		if(i->i == 0)
636 			bprint(i, "%s\tR%d, R%d", m, i->rs1, i->rs2);
637 		else
638 			bprint(i, "%s\tR%d, $0x%lux", m, i->rs1, i->simm13);
639 	}else{
640 		if(i->i && i->simm13==0)
641 			bprint(i, "MOVW\tR%d", i->rs1);
642 		else if(i->i == 0)
643 			bprint(i, "wr\tR%d, R%d", i->rs2, i->rs1);
644 		else
645 			bprint(i, "wr\t$0x%lux, R%d", i->simm13, i->rs1);
646 	}
647 	bprint(i, ", %s", regtab[i->op3&3]);
648 }
649 
650 static void
rd(Instr * i,char * m)651 rd(Instr *i, char *m)		/* page 103 */
652 {
653 	if(i->rs1==15 && i->rd==0){
654 		m = "stbar";
655 		if(!dascase)
656 			m = "STBAR";
657 		bprint(i, "%s", m);
658 	}else{
659 		if(!dascase)
660 			m = "MOVW";
661 		bprint(i, "%s\t%s, R%d", m, regtab[i->op3&3], i->rd);
662 	}
663 }
664 
665 static void
jmpl(Instr * i,char * m)666 jmpl(Instr *i, char *m)		/* page 82 */
667 {
668 	if(i->i == 0){
669 		if(i->rd == 15)
670 			bprint(i, "CALL\t(R%d+R%d)", i->rs2, i->rs1);
671 		else
672 			bprint(i, "%s\t(R%d+R%d), R%d", m, i->rs2, i->rs1, i->rd);
673 	}else{
674 		if(!dascase && i->simm13==8 && i->rs1==15 && i->rd==0)
675 			bprint(i, "RETURN");
676 		else{
677 			bprint(i, "%s\t", m);
678 			address(i);
679 			bprint(i, ", R%d", i->rd);
680 		}
681 	}
682 }
683 
684 static void
loadf(Instr * i,char * m)685 loadf(Instr *i, char *m)		/* page 70 */
686 {
687 	if(!dascase){
688 		m = "FMOVD";
689 		if(i->op3 == 0x20)
690 			m = "FMOVF";
691 		else if(i->op3 == 0x21)
692 			m = "MOVW";
693 	}
694 	if(i->i == 0)
695 		bprint(i, "%s\t(R%d+R%d)", m, i->rs1, i->rs2);
696 	else{
697 		bprint(i, "%s\t", m);
698 		address(i);
699 	}
700 	if(i->op3 == 0x21)
701 		bprint(i, ", FSR");
702 	else
703 		bprint(i, ", R%d", i->rd);
704 }
705 
706 static
storef(Instr * i,char * m)707 void storef(Instr *i, char *m)		/* page 70 */
708 {
709 	if(!dascase){
710 		m = "FMOVD";
711 		if(i->op3 == 0x25 || i->op3 == 0x26)
712 			m = "MOVW";
713 		else if(i->op3 == 0x24)
714 			m = "FMOVF";
715 	}
716 	bprint(i, "%s\t", m);
717 	if(i->op3 == 0x25)
718 		bprint(i, "FSR, ");
719 	else if(i->op3 == 0x26)
720 		bprint(i, "FQ, ");
721 	else
722 		bprint(i, "R%d, ", i->rd);
723 	if(i->i == 0)
724 		bprint(i, "(R%d+R%d)", i->rs1, i->rs2);
725 	else
726 		address(i);
727 }
728 
729 static
loadc(Instr * i,char * m)730 void loadc(Instr *i, char *m)			/* page 72 */
731 {
732 	if(i->i == 0)
733 		bprint(i, "%s\t(R%d+R%d), C%d", m, i->rs1, i->rs2, i->rd);
734 	else{
735 		bprint(i, "%s\t", m);
736 		address(i);
737 		bprint(i, ", C%d", i->rd);
738 	}
739 }
740 
741 static
loadcsr(Instr * i,char * m)742 void loadcsr(Instr *i, char *m)			/* page 72 */
743 {
744 	if(i->i == 0)
745 		bprint(i, "%s\t(R%d+R%d), CSR", m, i->rs1, i->rs2);
746 	else{
747 		bprint(i, "%s\t", m);
748 		address(i);
749 		bprint(i, ", CSR");
750 	}
751 }
752 
753 static struct
754 {
755 	int	opf;
756 	char	*name;
757 } fptab1[] = {			/* ignores rs1 */
758 	0xC4,	"FITOS",	/* page 109 */
759 	0xC8,	"FITOD",
760 	0xCC,	"FITOX",
761 
762 	0xD1,	"FSTOI",	/* page 110 */
763 	0xD2,	"FDTOI",
764 	0xD3,	"FXTOI",
765 
766 	0xC9,	"FSTOD",	/* page 111 */
767 	0xCD,	"FSTOX",
768 	0xC6,	"FDTOS",
769 	0xCE,	"FDTOX",
770 	0xC7,	"FXTOS",
771 	0xCB,	"FXTOD",
772 
773 	0x01,	"FMOVS",	/* page 112 */
774 	0x05,	"FNEGS",
775 	0x09,	"FABSS",
776 
777 	0x29,	"FSQRTS", 	/* page 113 */
778 	0x2A,	"FSQRTD",
779 	0x2B,	"FSQRTX",
780 
781 	0,	0,
782 };
783 
784 static struct{
785 	int	opf;
786 	char	*name;
787 } fptab2[] = {			/* uses rs1 */
788 
789 	0x41,	"FADDS",	/* page 114 */
790 	0x42,	"FADDD",
791 	0x43,	"FADDX",
792 	0x45,	"FSUBS",
793 	0x46,	"FSUBD",
794 	0x47,	"FSUBX",
795 
796 	0x49,	"FMULS",	/* page 115 */
797 	0x4A,	"FMULD",
798 	0x4B,	"FMULX",
799 	0x4D,	"FDIVS",
800 	0x4E,	"FDIVD",
801 	0x4F,	"FDIVX",
802 
803 	0x51,	"FCMPS",	/* page 116 */
804 	0x52,	"FCMPD",
805 	0x53,	"FCMPX",
806 	0x55,	"FCMPES",
807 	0x56,	"FCMPED",
808 	0x57,	"FCMPEX",
809 
810 	0, 0
811 };
812 
813 static void
fpop(Instr * i,char * m)814 fpop(Instr *i, char *m)	/* page 108-116 */
815 {
816 	int j;
817 
818 	if(dascase==0 && i->size==2){
819 		bprint(i, "FMOVD\tF%d, F%d", i->rs2, i->rd);
820 		return;
821 	}
822 	for(j=0; fptab1[j].name; j++)
823 		if(fptab1[j].opf == i->opf){
824 			bprint(i, "%s\tF%d, F%d", fptab1[j].name, i->rs2, i->rd);
825 			return;
826 		}
827 	for(j=0; fptab2[j].name; j++)
828 		if(fptab2[j].opf == i->opf){
829 			bprint(i, "%s\tF%d, F%d, F%d", fptab2[j].name, i->rs1, i->rs2, i->rd);
830 			return;
831 		}
832 	bprint(i, "%s%ux\tF%d, F%d, F%d", m, i->opf, i->rs1, i->rs2, i->rd);
833 }
834