xref: /inferno-os/libinterp/das-arm.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth #include <lib9.h>
2*37da2899SCharles.Forsyth 
3*37da2899SCharles.Forsyth typedef struct	Instr	Instr;
4*37da2899SCharles.Forsyth struct	Instr
5*37da2899SCharles.Forsyth {
6*37da2899SCharles.Forsyth 	ulong	w;
7*37da2899SCharles.Forsyth 	ulong	addr;
8*37da2899SCharles.Forsyth 	uchar	op;			/* super opcode */
9*37da2899SCharles.Forsyth 
10*37da2899SCharles.Forsyth 	uchar	cond;			/* bits 28-31 */
11*37da2899SCharles.Forsyth 	uchar	store;			/* bit 20 */
12*37da2899SCharles.Forsyth 
13*37da2899SCharles.Forsyth 	uchar	rd;			/* bits 12-15 */
14*37da2899SCharles.Forsyth 	uchar	rn;			/* bits 16-19 */
15*37da2899SCharles.Forsyth 	uchar	rs;			/* bits 0-11 */
16*37da2899SCharles.Forsyth 
17*37da2899SCharles.Forsyth 	long	imm;			/* rotated imm */
18*37da2899SCharles.Forsyth 	char*	curr;			/* fill point in buffer */
19*37da2899SCharles.Forsyth 	char*	end;			/* end of buffer */
20*37da2899SCharles.Forsyth 	char*	err;			/* error message */
21*37da2899SCharles.Forsyth };
22*37da2899SCharles.Forsyth 
23*37da2899SCharles.Forsyth typedef struct Opcode Opcode;
24*37da2899SCharles.Forsyth struct Opcode
25*37da2899SCharles.Forsyth {
26*37da2899SCharles.Forsyth 	char*	o;
27*37da2899SCharles.Forsyth 	void	(*f)(Opcode*, Instr*);
28*37da2899SCharles.Forsyth 	char*	a;
29*37da2899SCharles.Forsyth };
30*37da2899SCharles.Forsyth 
31*37da2899SCharles.Forsyth static	void	format(char*, Instr*, char*);
32*37da2899SCharles.Forsyth static	int	arminst(ulong, char, char*, int);
33*37da2899SCharles.Forsyth static	int	armdas(ulong, char*, int);
34*37da2899SCharles.Forsyth 
35*37da2899SCharles.Forsyth static
36*37da2899SCharles.Forsyth char*	cond[16] =
37*37da2899SCharles.Forsyth {
38*37da2899SCharles.Forsyth 	"EQ",	"NE",	"CS",	"CC",
39*37da2899SCharles.Forsyth 	"MI",	"PL",	"VS",	"VC",
40*37da2899SCharles.Forsyth 	"HI",	"LS",	"GE",	"LT",
41*37da2899SCharles.Forsyth 	"GT",	"LE",	0,	"NV"
42*37da2899SCharles.Forsyth };
43*37da2899SCharles.Forsyth 
44*37da2899SCharles.Forsyth static
45*37da2899SCharles.Forsyth char*	shtype[4] =
46*37da2899SCharles.Forsyth {
47*37da2899SCharles.Forsyth 	"<<",	">>",	"->",	"@>"
48*37da2899SCharles.Forsyth };
49*37da2899SCharles.Forsyth 
50*37da2899SCharles.Forsyth static int
get4(ulong addr,long * v)51*37da2899SCharles.Forsyth get4(ulong addr, long *v)
52*37da2899SCharles.Forsyth {
53*37da2899SCharles.Forsyth 	*v = *(ulong*)addr;
54*37da2899SCharles.Forsyth 	return 1;
55*37da2899SCharles.Forsyth }
56*37da2899SCharles.Forsyth 
57*37da2899SCharles.Forsyth static char *
_hexify(char * buf,ulong p,int zeros)58*37da2899SCharles.Forsyth _hexify(char *buf, ulong p, int zeros)
59*37da2899SCharles.Forsyth {
60*37da2899SCharles.Forsyth 	ulong d;
61*37da2899SCharles.Forsyth 
62*37da2899SCharles.Forsyth 	d = p/16;
63*37da2899SCharles.Forsyth 	if(d)
64*37da2899SCharles.Forsyth 		buf = _hexify(buf, d, zeros-1);
65*37da2899SCharles.Forsyth 	else
66*37da2899SCharles.Forsyth 		while(zeros--)
67*37da2899SCharles.Forsyth 			*buf++ = '0';
68*37da2899SCharles.Forsyth 	*buf++ = "0123456789abcdef"[p&0x0f];
69*37da2899SCharles.Forsyth 	return buf;
70*37da2899SCharles.Forsyth }
71*37da2899SCharles.Forsyth 
72*37da2899SCharles.Forsyth int
armclass(long w)73*37da2899SCharles.Forsyth armclass(long w)
74*37da2899SCharles.Forsyth {
75*37da2899SCharles.Forsyth 	int op;
76*37da2899SCharles.Forsyth 
77*37da2899SCharles.Forsyth 	op = (w >> 25) & 0x7;
78*37da2899SCharles.Forsyth 	switch(op) {
79*37da2899SCharles.Forsyth 	case 0:	/* data processing r,r,r */
80*37da2899SCharles.Forsyth 		op = ((w >> 4) & 0xf);
81*37da2899SCharles.Forsyth 		if(op == 0x9) {
82*37da2899SCharles.Forsyth 			op = 48+16;		/* mul */
83*37da2899SCharles.Forsyth 			if(w & (1<<24)) {
84*37da2899SCharles.Forsyth 				op += 2;
85*37da2899SCharles.Forsyth 				if(w & (1<<22))
86*37da2899SCharles.Forsyth 					op++;	/* swap */
87*37da2899SCharles.Forsyth 				break;
88*37da2899SCharles.Forsyth 			}
89*37da2899SCharles.Forsyth 			if(w & (1<<21))
90*37da2899SCharles.Forsyth 				op++;		/* mla */
91*37da2899SCharles.Forsyth 			break;
92*37da2899SCharles.Forsyth 		}
93*37da2899SCharles.Forsyth 		op = (w >> 21) & 0xf;
94*37da2899SCharles.Forsyth 		if(w & (1<<4))
95*37da2899SCharles.Forsyth 			op += 32;
96*37da2899SCharles.Forsyth 		else
97*37da2899SCharles.Forsyth 		if(w & (31<<7))
98*37da2899SCharles.Forsyth 			op += 16;
99*37da2899SCharles.Forsyth 		break;
100*37da2899SCharles.Forsyth 	case 1:	/* data processing i,r,r */
101*37da2899SCharles.Forsyth 		op = (48) + ((w >> 21) & 0xf);
102*37da2899SCharles.Forsyth 		break;
103*37da2899SCharles.Forsyth 	case 2:	/* load/store byte/word i(r) */
104*37da2899SCharles.Forsyth 		op = (48+20) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
105*37da2899SCharles.Forsyth 		break;
106*37da2899SCharles.Forsyth 	case 3:	/* load/store byte/word (r)(r) */
107*37da2899SCharles.Forsyth 		op = (48+20+4) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
108*37da2899SCharles.Forsyth 		break;
109*37da2899SCharles.Forsyth 	case 4:	/* block data transfer (r)(r) */
110*37da2899SCharles.Forsyth 		op = (48+20+4+4) + ((w >> 20) & 0x1);
111*37da2899SCharles.Forsyth 		break;
112*37da2899SCharles.Forsyth 	case 5:	/* branch / branch link */
113*37da2899SCharles.Forsyth 		op = (48+20+4+4+2) + ((w >> 24) & 0x1);
114*37da2899SCharles.Forsyth 		break;
115*37da2899SCharles.Forsyth 	case 7:	/* coprocessor crap */
116*37da2899SCharles.Forsyth 		op = (48+20+4+4+2+2) + ((w >> 3) & 0x2) + ((w >> 20) & 0x1);
117*37da2899SCharles.Forsyth 		break;
118*37da2899SCharles.Forsyth 	default:
119*37da2899SCharles.Forsyth 		op = (48+20+4+4+2+2+4);
120*37da2899SCharles.Forsyth 		break;
121*37da2899SCharles.Forsyth 	}
122*37da2899SCharles.Forsyth 	return op;
123*37da2899SCharles.Forsyth }
124*37da2899SCharles.Forsyth 
125*37da2899SCharles.Forsyth static int
decode(ulong pc,Instr * i)126*37da2899SCharles.Forsyth decode(ulong pc, Instr *i)
127*37da2899SCharles.Forsyth {
128*37da2899SCharles.Forsyth 	long w;
129*37da2899SCharles.Forsyth 
130*37da2899SCharles.Forsyth 	get4(pc, &w);
131*37da2899SCharles.Forsyth 	i->w = w;
132*37da2899SCharles.Forsyth 	i->addr = pc;
133*37da2899SCharles.Forsyth 	i->cond = (w >> 28) & 0xF;
134*37da2899SCharles.Forsyth 	i->op = armclass(w);
135*37da2899SCharles.Forsyth 	return 1;
136*37da2899SCharles.Forsyth }
137*37da2899SCharles.Forsyth 
138*37da2899SCharles.Forsyth static void
bprint(Instr * i,char * fmt,...)139*37da2899SCharles.Forsyth bprint(Instr *i, char *fmt, ...)
140*37da2899SCharles.Forsyth {
141*37da2899SCharles.Forsyth 	va_list arg;
142*37da2899SCharles.Forsyth 
143*37da2899SCharles.Forsyth 	va_start(arg, fmt);
144*37da2899SCharles.Forsyth 	i->curr = vseprint(i->curr, i->end, fmt, arg);
145*37da2899SCharles.Forsyth 	va_end(arg);
146*37da2899SCharles.Forsyth }
147*37da2899SCharles.Forsyth 
148*37da2899SCharles.Forsyth static void
armdps(Opcode * o,Instr * i)149*37da2899SCharles.Forsyth armdps(Opcode *o, Instr *i)
150*37da2899SCharles.Forsyth {
151*37da2899SCharles.Forsyth 	i->store = (i->w >> 20) & 1;
152*37da2899SCharles.Forsyth 	i->rn = (i->w >> 16) & 0xf;
153*37da2899SCharles.Forsyth 	i->rd = (i->w >> 12) & 0xf;
154*37da2899SCharles.Forsyth 	i->rs = (i->w >> 0) & 0xf;
155*37da2899SCharles.Forsyth 	if(i->rn == 15 && i->rs == 0) {
156*37da2899SCharles.Forsyth 		if(i->op == 8) {
157*37da2899SCharles.Forsyth 			format("MOVW", i,"CPSR, R%d");
158*37da2899SCharles.Forsyth 			return;
159*37da2899SCharles.Forsyth 		} else
160*37da2899SCharles.Forsyth 		if(i->op == 10) {
161*37da2899SCharles.Forsyth 			format("MOVW", i,"SPSR, R%d");
162*37da2899SCharles.Forsyth 			return;
163*37da2899SCharles.Forsyth 		}
164*37da2899SCharles.Forsyth 	} else
165*37da2899SCharles.Forsyth 	if(i->rn == 9 && i->rd == 15) {
166*37da2899SCharles.Forsyth 		if(i->op == 9) {
167*37da2899SCharles.Forsyth 			format("MOVW", i, "R%s, CPSR");
168*37da2899SCharles.Forsyth 			return;
169*37da2899SCharles.Forsyth 		} else
170*37da2899SCharles.Forsyth 		if(i->op == 11) {
171*37da2899SCharles.Forsyth 			format("MOVW", i, "R%s, SPSR");
172*37da2899SCharles.Forsyth 			return;
173*37da2899SCharles.Forsyth 		}
174*37da2899SCharles.Forsyth 	}
175*37da2899SCharles.Forsyth 	format(o->o, i, o->a);
176*37da2899SCharles.Forsyth }
177*37da2899SCharles.Forsyth 
178*37da2899SCharles.Forsyth static void
armdpi(Opcode * o,Instr * i)179*37da2899SCharles.Forsyth armdpi(Opcode *o, Instr *i)
180*37da2899SCharles.Forsyth {
181*37da2899SCharles.Forsyth 	ulong v;
182*37da2899SCharles.Forsyth 	int c;
183*37da2899SCharles.Forsyth 
184*37da2899SCharles.Forsyth 	v = (i->w >> 0) & 0xff;
185*37da2899SCharles.Forsyth 	c = (i->w >> 8) & 0xf;
186*37da2899SCharles.Forsyth 	while(c) {
187*37da2899SCharles.Forsyth 		v = (v<<30) | (v>>2);
188*37da2899SCharles.Forsyth 		c--;
189*37da2899SCharles.Forsyth 	}
190*37da2899SCharles.Forsyth 	i->imm = v;
191*37da2899SCharles.Forsyth 	i->store = (i->w >> 20) & 1;
192*37da2899SCharles.Forsyth 	i->rn = (i->w >> 16) & 0xf;
193*37da2899SCharles.Forsyth 	i->rd = (i->w >> 12) & 0xf;
194*37da2899SCharles.Forsyth 	i->rs = i->w&0x0f;
195*37da2899SCharles.Forsyth 
196*37da2899SCharles.Forsyth 		/* RET is encoded as ADD #0,R14,R15 */
197*37da2899SCharles.Forsyth 	if(i->w == 0xe282f000){
198*37da2899SCharles.Forsyth 		format("RET", i, "");
199*37da2899SCharles.Forsyth 		return;
200*37da2899SCharles.Forsyth 	} else
201*37da2899SCharles.Forsyth 	format(o->o, i, o->a);
202*37da2899SCharles.Forsyth }
203*37da2899SCharles.Forsyth 
204*37da2899SCharles.Forsyth static void
armsdti(Opcode * o,Instr * i)205*37da2899SCharles.Forsyth armsdti(Opcode *o, Instr *i)
206*37da2899SCharles.Forsyth {
207*37da2899SCharles.Forsyth 	ulong v;
208*37da2899SCharles.Forsyth 
209*37da2899SCharles.Forsyth 	v = (i->w >> 0) & 0xfff;
210*37da2899SCharles.Forsyth 	if(!(i->w & (1<<23)))
211*37da2899SCharles.Forsyth 		v = -v;
212*37da2899SCharles.Forsyth 	i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
213*37da2899SCharles.Forsyth 	i->imm = v;
214*37da2899SCharles.Forsyth 	i->rn = (i->w >> 16) & 0xf;
215*37da2899SCharles.Forsyth 	i->rd = (i->w >> 12) & 0xf;
216*37da2899SCharles.Forsyth 		/* convert load of offset(PC) to a load immediate */
217*37da2899SCharles.Forsyth 	if(i->rn == 15 && (i->w & (1<<20)) && get4(i->addr+v+8, &i->imm) > 0)
218*37da2899SCharles.Forsyth 		format(o->o, i, "$#%i,R%d");
219*37da2899SCharles.Forsyth 	else
220*37da2899SCharles.Forsyth 		format(o->o, i, o->a);
221*37da2899SCharles.Forsyth }
222*37da2899SCharles.Forsyth 
223*37da2899SCharles.Forsyth static void
armsdts(Opcode * o,Instr * i)224*37da2899SCharles.Forsyth armsdts(Opcode *o, Instr *i)
225*37da2899SCharles.Forsyth {
226*37da2899SCharles.Forsyth 	i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
227*37da2899SCharles.Forsyth 	i->rs = (i->w >> 0) & 0xf;
228*37da2899SCharles.Forsyth 	i->rn = (i->w >> 16) & 0xf;
229*37da2899SCharles.Forsyth 	i->rd = (i->w >> 12) & 0xf;
230*37da2899SCharles.Forsyth 	format(o->o, i, o->a);
231*37da2899SCharles.Forsyth }
232*37da2899SCharles.Forsyth 
233*37da2899SCharles.Forsyth static void
armbdt(Opcode * o,Instr * i)234*37da2899SCharles.Forsyth armbdt(Opcode *o, Instr *i)
235*37da2899SCharles.Forsyth {
236*37da2899SCharles.Forsyth 	i->store = (i->w >> 21) & 0x3;		/* S & W bits */
237*37da2899SCharles.Forsyth 	i->rn = (i->w >> 16) & 0xf;
238*37da2899SCharles.Forsyth 	i->imm = i->w & 0xffff;
239*37da2899SCharles.Forsyth 	if(i->w == 0xe8fd8000)
240*37da2899SCharles.Forsyth 		format("RFE", i, "");
241*37da2899SCharles.Forsyth 	else
242*37da2899SCharles.Forsyth 		format(o->o, i, o->a);
243*37da2899SCharles.Forsyth }
244*37da2899SCharles.Forsyth 
245*37da2899SCharles.Forsyth static void
armund(Opcode * o,Instr * i)246*37da2899SCharles.Forsyth armund(Opcode *o, Instr *i)
247*37da2899SCharles.Forsyth {
248*37da2899SCharles.Forsyth 	format(o->o, i, o->a);
249*37da2899SCharles.Forsyth }
250*37da2899SCharles.Forsyth 
251*37da2899SCharles.Forsyth static void
armcdt(Opcode * o,Instr * i)252*37da2899SCharles.Forsyth armcdt(Opcode *o, Instr *i)
253*37da2899SCharles.Forsyth {
254*37da2899SCharles.Forsyth 	format(o->o, i, o->a);
255*37da2899SCharles.Forsyth }
256*37da2899SCharles.Forsyth 
257*37da2899SCharles.Forsyth static void
armunk(Opcode * o,Instr * i)258*37da2899SCharles.Forsyth armunk(Opcode *o, Instr *i)
259*37da2899SCharles.Forsyth {
260*37da2899SCharles.Forsyth 	format(o->o, i, o->a);
261*37da2899SCharles.Forsyth }
262*37da2899SCharles.Forsyth 
263*37da2899SCharles.Forsyth static void
armb(Opcode * o,Instr * i)264*37da2899SCharles.Forsyth armb(Opcode *o, Instr *i)
265*37da2899SCharles.Forsyth {
266*37da2899SCharles.Forsyth 	ulong v;
267*37da2899SCharles.Forsyth 
268*37da2899SCharles.Forsyth 	v = i->w & 0xffffff;
269*37da2899SCharles.Forsyth 	if(v & 0x800000)
270*37da2899SCharles.Forsyth 		v |= ~0xffffff;
271*37da2899SCharles.Forsyth 	i->imm = (v<<2) + i->addr + 8;
272*37da2899SCharles.Forsyth 	format(o->o, i, o->a);
273*37da2899SCharles.Forsyth }
274*37da2899SCharles.Forsyth 
275*37da2899SCharles.Forsyth static void
armco(Opcode * o,Instr * i)276*37da2899SCharles.Forsyth armco(Opcode *o, Instr *i)		/* coprocessor instructions */
277*37da2899SCharles.Forsyth {
278*37da2899SCharles.Forsyth 	int op, p, cp;
279*37da2899SCharles.Forsyth 
280*37da2899SCharles.Forsyth 	char buf[1024];
281*37da2899SCharles.Forsyth 
282*37da2899SCharles.Forsyth 	i->rn = (i->w >> 16) & 0xf;
283*37da2899SCharles.Forsyth 	i->rd = (i->w >> 12) & 0xf;
284*37da2899SCharles.Forsyth 	i->rs = i->w&0xf;
285*37da2899SCharles.Forsyth 	cp = (i->w >> 8) & 0xf;
286*37da2899SCharles.Forsyth 	p = (i->w >> 5) & 0x7;
287*37da2899SCharles.Forsyth 	if(i->w&0x10) {
288*37da2899SCharles.Forsyth 		op = (i->w >> 20) & 0x0f;
289*37da2899SCharles.Forsyth 		snprint(buf, sizeof(buf), "#%x, #%x, R%d, C(%d), C(%d), #%x\n", cp, op, i->rd, i->rn, i->rs, p);
290*37da2899SCharles.Forsyth 	} else {
291*37da2899SCharles.Forsyth 		op = (i->w >> 21) & 0x07;
292*37da2899SCharles.Forsyth 		snprint(buf, sizeof(buf), "#%x, #%x, C(%d), C(%d), C(%d), #%x\n", cp, op, i->rd, i->rn, i->rs, p);
293*37da2899SCharles.Forsyth 	}
294*37da2899SCharles.Forsyth 	format(o->o, i, buf);
295*37da2899SCharles.Forsyth }
296*37da2899SCharles.Forsyth 
297*37da2899SCharles.Forsyth static Opcode opcodes[] =
298*37da2899SCharles.Forsyth {
299*37da2899SCharles.Forsyth 	"AND%C%S",	armdps,	"R%s,R%n,R%d",
300*37da2899SCharles.Forsyth 	"EOR%C%S",	armdps,	"R%s,R%n,R%d",
301*37da2899SCharles.Forsyth 	"SUB%C%S",	armdps,	"R%s,R%n,R%d",
302*37da2899SCharles.Forsyth 	"RSB%C%S",	armdps,	"R%s,R%n,R%d",
303*37da2899SCharles.Forsyth 	"ADD%C%S",	armdps,	"R%s,R%n,R%d",
304*37da2899SCharles.Forsyth 	"ADC%C%S",	armdps,	"R%s,R%n,R%d",
305*37da2899SCharles.Forsyth 	"SBC%C%S",	armdps,	"R%s,R%n,R%d",
306*37da2899SCharles.Forsyth 	"RSC%C%S",	armdps,	"R%s,R%n,R%d",
307*37da2899SCharles.Forsyth 	"TST%C%S",	armdps,	"R%s,R%n,",
308*37da2899SCharles.Forsyth 	"TEQ%C%S",	armdps,	"R%s,R%n,",
309*37da2899SCharles.Forsyth 	"CMP%C%S",	armdps,	"R%s,R%n,",
310*37da2899SCharles.Forsyth 	"CMN%C%S",	armdps,	"R%s,R%n,",
311*37da2899SCharles.Forsyth 	"ORR%C%S",	armdps,	"R%s,R%n,R%d",
312*37da2899SCharles.Forsyth 	"MOVW%C%S",	armdps,	"R%s,R%d",
313*37da2899SCharles.Forsyth 	"BIC%C%S",	armdps,	"R%s,R%n,R%d",
314*37da2899SCharles.Forsyth 	"MVN%C%S",	armdps,	"R%s,R%d",
315*37da2899SCharles.Forsyth 
316*37da2899SCharles.Forsyth 	"AND%C%S",	armdps,	"(R%s%h#%m),R%n,R%d",
317*37da2899SCharles.Forsyth 	"EOR%C%S",	armdps,	"(R%s%h#%m),R%n,R%d",
318*37da2899SCharles.Forsyth 	"SUB%C%S",	armdps,	"(R%s%h#%m),R%n,R%d",
319*37da2899SCharles.Forsyth 	"RSB%C%S",	armdps,	"(R%s%h#%m),R%n,R%d",
320*37da2899SCharles.Forsyth 	"ADD%C%S",	armdps,	"(R%s%h#%m),R%n,R%d",
321*37da2899SCharles.Forsyth 	"ADC%C%S",	armdps,	"(R%s%h#%m),R%n,R%d",
322*37da2899SCharles.Forsyth 	"SBC%C%S",	armdps,	"(R%s%h#%m),R%n,R%d",
323*37da2899SCharles.Forsyth 	"RSC%C%S",	armdps,	"(R%s%h#%m),R%n,R%d",
324*37da2899SCharles.Forsyth 	"TST%C%S",	armdps,	"(R%s%h#%m),R%n,",
325*37da2899SCharles.Forsyth 	"TEQ%C%S",	armdps,	"(R%s%h#%m),R%n,",
326*37da2899SCharles.Forsyth 	"CMP%C%S",	armdps,	"(R%s%h#%m),R%n,",
327*37da2899SCharles.Forsyth 	"CMN%C%S",	armdps,	"(R%s%h#%m),R%n,",
328*37da2899SCharles.Forsyth 	"ORR%C%S",	armdps,	"(R%s%h#%m),R%n,R%d",
329*37da2899SCharles.Forsyth 	"MOVW%C%S",	armdps,	"(R%s%h#%m),R%d",
330*37da2899SCharles.Forsyth 	"BIC%C%S",	armdps,	"(R%s%h#%m),R%n,R%d",
331*37da2899SCharles.Forsyth 	"MVN%C%S",	armdps,	"(R%s%h#%m),R%d",
332*37da2899SCharles.Forsyth 
333*37da2899SCharles.Forsyth 	"AND%C%S",	armdps,	"(R%s%hR%m),R%n,R%d",
334*37da2899SCharles.Forsyth 	"EOR%C%S",	armdps,	"(R%s%hR%m),R%n,R%d",
335*37da2899SCharles.Forsyth 	"SUB%C%S",	armdps,	"(R%s%hR%m),R%n,R%d",
336*37da2899SCharles.Forsyth 	"RSB%C%S",	armdps,	"(R%s%hR%m),R%n,R%d",
337*37da2899SCharles.Forsyth 	"ADD%C%S",	armdps,	"(R%s%hR%m),R%n,R%d",
338*37da2899SCharles.Forsyth 	"ADC%C%S",	armdps,	"(R%s%hR%m),R%n,R%d",
339*37da2899SCharles.Forsyth 	"SBC%C%S",	armdps,	"(R%s%hR%m),R%n,R%d",
340*37da2899SCharles.Forsyth 	"RSC%C%S",	armdps,	"(R%s%hR%m),R%n,R%d",
341*37da2899SCharles.Forsyth 	"TST%C%S",	armdps,	"(R%s%hR%m),R%n,",
342*37da2899SCharles.Forsyth 	"TEQ%C%S",	armdps,	"(R%s%hR%m),R%n,",
343*37da2899SCharles.Forsyth 	"CMP%C%S",	armdps,	"(R%s%hR%m),R%n,",
344*37da2899SCharles.Forsyth 	"CMN%C%S",	armdps,	"(R%s%hR%m),R%n,",
345*37da2899SCharles.Forsyth 	"ORR%C%S",	armdps,	"(R%s%hR%m),R%n,R%d",
346*37da2899SCharles.Forsyth 	"MOVW%C%S",	armdps,	"(R%s%hR%m),R%d",
347*37da2899SCharles.Forsyth 	"BIC%C%S",	armdps,	"(R%s%hR%m),R%n,R%d",
348*37da2899SCharles.Forsyth 	"MVN%C%S",	armdps,	"(R%s%hR%m),R%d",
349*37da2899SCharles.Forsyth 
350*37da2899SCharles.Forsyth 	"AND%C%S",	armdpi,	"$#%i,R%n,R%d",
351*37da2899SCharles.Forsyth 	"EOR%C%S",	armdpi,	"$#%i,R%n,R%d",
352*37da2899SCharles.Forsyth 	"SUB%C%S",	armdpi,	"$#%i,R%n,R%d",
353*37da2899SCharles.Forsyth 	"RSB%C%S",	armdpi,	"$#%i,R%n,R%d",
354*37da2899SCharles.Forsyth 	"ADD%C%S",	armdpi,	"$#%i,R%n,R%d",
355*37da2899SCharles.Forsyth 	"ADC%C%S",	armdpi,	"$#%i,R%n,R%d",
356*37da2899SCharles.Forsyth 	"SBC%C%S",	armdpi,	"$#%i,R%n,R%d",
357*37da2899SCharles.Forsyth 	"RSC%C%S",	armdpi,	"$#%i,R%n,R%d",
358*37da2899SCharles.Forsyth 	"TST%C%S",	armdpi,	"$#%i,R%n,",
359*37da2899SCharles.Forsyth 	"TEQ%C%S",	armdpi,	"$#%i,R%n,",
360*37da2899SCharles.Forsyth 	"CMP%C%S",	armdpi,	"$#%i,R%n,",
361*37da2899SCharles.Forsyth 	"CMN%C%S",	armdpi,	"$#%i,R%n,",
362*37da2899SCharles.Forsyth 	"ORR%C%S",	armdpi,	"$#%i,R%n,R%d",
363*37da2899SCharles.Forsyth 	"MOVW%C%S",	armdpi,	"$#%i,,R%d",
364*37da2899SCharles.Forsyth 	"BIC%C%S",	armdpi,	"$#%i,R%n,R%d",
365*37da2899SCharles.Forsyth 	"MVN%C%S",	armdpi,	"$#%i,,R%d",
366*37da2899SCharles.Forsyth 
367*37da2899SCharles.Forsyth 	"MUL%C%S",	armdpi,	"R%s,R%m,R%n",
368*37da2899SCharles.Forsyth 	"MULA%C%S",	armdpi,	"R%s,R%m,R%n,R%d",
369*37da2899SCharles.Forsyth 	"SWPW",		armdpi,	"R%s,(R%n),R%d",
370*37da2899SCharles.Forsyth 	"SWPB",		armdpi,	"R%s,(R%n),R%d",
371*37da2899SCharles.Forsyth 
372*37da2899SCharles.Forsyth 	"MOVW%C%p",	armsdti,"R%d,#%i(R%n)",
373*37da2899SCharles.Forsyth 	"MOVB%C%p",	armsdti,"R%d,#%i(R%n)",
374*37da2899SCharles.Forsyth 	"MOVW%C%p",	armsdti,"#%i(R%n),R%d",
375*37da2899SCharles.Forsyth 	"MOVB%C%p",	armsdti,"#%i(R%n),R%d",
376*37da2899SCharles.Forsyth 
377*37da2899SCharles.Forsyth 	"MOVW%C%p",	armsdts,"R%d,%D(R%s%h#%m)(R%n)",
378*37da2899SCharles.Forsyth 	"MOVB%C%p",	armsdts,"R%d,%D(R%s%h#%m)(R%n)",
379*37da2899SCharles.Forsyth 	"MOVW%C%p",	armsdts,"%D(R%s%h#%m)(R%n),R%d",
380*37da2899SCharles.Forsyth 	"MOVB%C%p",	armsdts,"%D(R%s%h#%m)(R%n),R%d",
381*37da2899SCharles.Forsyth 
382*37da2899SCharles.Forsyth 	"MOVM%C%P%a",	armbdt,	"R%n,[%r]",
383*37da2899SCharles.Forsyth 	"MOVM%C%P%a",	armbdt,	"[%r],R%n",
384*37da2899SCharles.Forsyth 
385*37da2899SCharles.Forsyth 	"B%C",		armb,	"%b",
386*37da2899SCharles.Forsyth 	"BL%C",		armb,	"%b",
387*37da2899SCharles.Forsyth 
388*37da2899SCharles.Forsyth 	"CDP%C",	armco,	"",
389*37da2899SCharles.Forsyth 	"CDP%C",	armco,	"",
390*37da2899SCharles.Forsyth 	"MCR%C",	armco,	"",
391*37da2899SCharles.Forsyth 	"MRC%C",	armco,	"",
392*37da2899SCharles.Forsyth 
393*37da2899SCharles.Forsyth 	"UNK",		armunk,	"",
394*37da2899SCharles.Forsyth };
395*37da2899SCharles.Forsyth 
396*37da2899SCharles.Forsyth static	char *mode[] = { 0, "IA", "DB", "IB" };
397*37da2899SCharles.Forsyth static	char *pw[] = { "P", "PW", 0, "W" };
398*37da2899SCharles.Forsyth static	char *sw[] = { 0, "W", "S", "SW" };
399*37da2899SCharles.Forsyth 
400*37da2899SCharles.Forsyth static void
format(char * mnemonic,Instr * i,char * f)401*37da2899SCharles.Forsyth format(char *mnemonic, Instr *i, char *f)
402*37da2899SCharles.Forsyth {
403*37da2899SCharles.Forsyth 	int j, k, m, n;
404*37da2899SCharles.Forsyth 
405*37da2899SCharles.Forsyth 	if(mnemonic)
406*37da2899SCharles.Forsyth 		format(0, i, mnemonic);
407*37da2899SCharles.Forsyth 	if(f == 0)
408*37da2899SCharles.Forsyth 		return;
409*37da2899SCharles.Forsyth 	if(mnemonic)
410*37da2899SCharles.Forsyth 		if(i->curr < i->end)
411*37da2899SCharles.Forsyth 			*i->curr++ = '\t';
412*37da2899SCharles.Forsyth 	for ( ; *f && i->curr < i->end; f++) {
413*37da2899SCharles.Forsyth 		if(*f != '%') {
414*37da2899SCharles.Forsyth 			*i->curr++ = *f;
415*37da2899SCharles.Forsyth 			continue;
416*37da2899SCharles.Forsyth 		}
417*37da2899SCharles.Forsyth 		switch (*++f) {
418*37da2899SCharles.Forsyth 
419*37da2899SCharles.Forsyth 		case 'C':	/* .CONDITION */
420*37da2899SCharles.Forsyth 			if(cond[i->cond])
421*37da2899SCharles.Forsyth 				bprint(i, ".%s", cond[i->cond]);
422*37da2899SCharles.Forsyth 			break;
423*37da2899SCharles.Forsyth 
424*37da2899SCharles.Forsyth 		case 'S':	/* .STORE */
425*37da2899SCharles.Forsyth 			if(i->store)
426*37da2899SCharles.Forsyth 				bprint(i, ".S");
427*37da2899SCharles.Forsyth 			break;
428*37da2899SCharles.Forsyth 
429*37da2899SCharles.Forsyth 		case 'P':	/* P & U bits for block move */
430*37da2899SCharles.Forsyth 			n = (i->w >>23) & 0x3;
431*37da2899SCharles.Forsyth 			if (mode[n])
432*37da2899SCharles.Forsyth 				bprint(i, ".%s", mode[n]);
433*37da2899SCharles.Forsyth 			break;
434*37da2899SCharles.Forsyth 
435*37da2899SCharles.Forsyth 		case 'D':	/* ~U bit for single data xfer */
436*37da2899SCharles.Forsyth 			if((i->w & (1<<23)) == 0)
437*37da2899SCharles.Forsyth 				bprint(i, "-");
438*37da2899SCharles.Forsyth 			break;
439*37da2899SCharles.Forsyth 
440*37da2899SCharles.Forsyth 		case 'p':	/* P & W bits for single data xfer*/
441*37da2899SCharles.Forsyth 			if (pw[i->store])
442*37da2899SCharles.Forsyth 				bprint(i, ".%s", pw[i->store]);
443*37da2899SCharles.Forsyth 			break;
444*37da2899SCharles.Forsyth 
445*37da2899SCharles.Forsyth 		case 'a':	/* S & W bits for single data xfer*/
446*37da2899SCharles.Forsyth 			if (sw[i->store])
447*37da2899SCharles.Forsyth 				bprint(i, ".%s", sw[i->store]);
448*37da2899SCharles.Forsyth 			break;
449*37da2899SCharles.Forsyth 
450*37da2899SCharles.Forsyth 		case 's':
451*37da2899SCharles.Forsyth 			bprint(i, "%d", i->rs & 0xf);
452*37da2899SCharles.Forsyth 			break;
453*37da2899SCharles.Forsyth 
454*37da2899SCharles.Forsyth 		case 'm':
455*37da2899SCharles.Forsyth 			bprint(i, "%d", (i->w>>7) & 0x1f);
456*37da2899SCharles.Forsyth 			break;
457*37da2899SCharles.Forsyth 
458*37da2899SCharles.Forsyth 		case 'h':
459*37da2899SCharles.Forsyth 			bprint(i, "%s", shtype[(i->w>>5) & 0x3]);
460*37da2899SCharles.Forsyth 			break;
461*37da2899SCharles.Forsyth 
462*37da2899SCharles.Forsyth 		case 'n':
463*37da2899SCharles.Forsyth 			bprint(i, "%d", i->rn);
464*37da2899SCharles.Forsyth 			break;
465*37da2899SCharles.Forsyth 
466*37da2899SCharles.Forsyth 		case 'd':
467*37da2899SCharles.Forsyth 			bprint(i, "%d", i->rd);
468*37da2899SCharles.Forsyth 			break;
469*37da2899SCharles.Forsyth 
470*37da2899SCharles.Forsyth 		case 'i':
471*37da2899SCharles.Forsyth 			bprint(i, "%lux", i->imm);
472*37da2899SCharles.Forsyth 			break;
473*37da2899SCharles.Forsyth 
474*37da2899SCharles.Forsyth 		case 'b':
475*37da2899SCharles.Forsyth 			bprint(i, "%lux", i->imm);
476*37da2899SCharles.Forsyth 			break;
477*37da2899SCharles.Forsyth 
478*37da2899SCharles.Forsyth 		case 'r':
479*37da2899SCharles.Forsyth 			n = i->imm&0xffff;
480*37da2899SCharles.Forsyth 			j = 0;
481*37da2899SCharles.Forsyth 			k = 0;
482*37da2899SCharles.Forsyth 			while(n) {
483*37da2899SCharles.Forsyth 				m = j;
484*37da2899SCharles.Forsyth 				while(n&0x1) {
485*37da2899SCharles.Forsyth 					j++;
486*37da2899SCharles.Forsyth 					n >>= 1;
487*37da2899SCharles.Forsyth 				}
488*37da2899SCharles.Forsyth 				if(j != m) {
489*37da2899SCharles.Forsyth 					if(k)
490*37da2899SCharles.Forsyth 						bprint(i, ",");
491*37da2899SCharles.Forsyth 					if(j == m+1)
492*37da2899SCharles.Forsyth 						bprint(i, "R%d", m);
493*37da2899SCharles.Forsyth 					else
494*37da2899SCharles.Forsyth 						bprint(i, "R%d-R%d", m, j-1);
495*37da2899SCharles.Forsyth 					k = 1;
496*37da2899SCharles.Forsyth 				}
497*37da2899SCharles.Forsyth 				j++;
498*37da2899SCharles.Forsyth 				n >>= 1;
499*37da2899SCharles.Forsyth 			}
500*37da2899SCharles.Forsyth 			break;
501*37da2899SCharles.Forsyth 
502*37da2899SCharles.Forsyth 		case '\0':
503*37da2899SCharles.Forsyth 			*i->curr++ = '%';
504*37da2899SCharles.Forsyth 			return;
505*37da2899SCharles.Forsyth 
506*37da2899SCharles.Forsyth 		default:
507*37da2899SCharles.Forsyth 			bprint(i, "%%%c", *f);
508*37da2899SCharles.Forsyth 			break;
509*37da2899SCharles.Forsyth 		}
510*37da2899SCharles.Forsyth 	}
511*37da2899SCharles.Forsyth 	*i->curr = 0;
512*37da2899SCharles.Forsyth }
513*37da2899SCharles.Forsyth 
514*37da2899SCharles.Forsyth void
das(ulong * x,int n)515*37da2899SCharles.Forsyth das(ulong *x, int n)
516*37da2899SCharles.Forsyth {
517*37da2899SCharles.Forsyth 	ulong pc;
518*37da2899SCharles.Forsyth 	Instr i;
519*37da2899SCharles.Forsyth 	char buf[128];
520*37da2899SCharles.Forsyth 
521*37da2899SCharles.Forsyth 	pc = (ulong)x;
522*37da2899SCharles.Forsyth 	while(n > 0) {
523*37da2899SCharles.Forsyth 		i.curr = buf;
524*37da2899SCharles.Forsyth 		i.end = buf+sizeof(buf)-1;
525*37da2899SCharles.Forsyth 
526*37da2899SCharles.Forsyth 		if(decode(pc, &i) < 0)
527*37da2899SCharles.Forsyth 			sprint(buf, "???");
528*37da2899SCharles.Forsyth 		else
529*37da2899SCharles.Forsyth 			(*opcodes[i.op].f)(&opcodes[i.op], &i);
530*37da2899SCharles.Forsyth 
531*37da2899SCharles.Forsyth 		print("%.8lux %.8lux\t%s\n", pc, i.w, buf);
532*37da2899SCharles.Forsyth 		pc += 4;
533*37da2899SCharles.Forsyth 		n--;
534*37da2899SCharles.Forsyth 	}
535*37da2899SCharles.Forsyth }
536