xref: /plan9/sys/src/libmach/5db.c (revision f1b2ee28c1dcb21e637a95dfec1fecc82992b275)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier #include <mach.h>
57dd7cddfSDavid du Colombier 
659cc4ca5SDavid du Colombier static int debug = 0;
759cc4ca5SDavid du Colombier 
859cc4ca5SDavid du Colombier #define	BITS(a, b)	((1<<(b+1))-(1<<a))
959cc4ca5SDavid du Colombier 
1059cc4ca5SDavid du Colombier #define LSR(v, s)	((ulong)(v) >> (s))
1159cc4ca5SDavid du Colombier #define ASR(v, s)	((long)(v) >> (s))
1259cc4ca5SDavid du Colombier #define ROR(v, s)	(LSR((v), (s)) | (((v) & ((1 << (s))-1)) << (32 - (s))))
1359cc4ca5SDavid du Colombier 
1459cc4ca5SDavid du Colombier 
157dd7cddfSDavid du Colombier 
167dd7cddfSDavid du Colombier typedef struct	Instr	Instr;
177dd7cddfSDavid du Colombier struct	Instr
187dd7cddfSDavid du Colombier {
197dd7cddfSDavid du Colombier 	Map	*map;
207dd7cddfSDavid du Colombier 	ulong	w;
214de34a7eSDavid du Colombier 	uvlong	addr;
227dd7cddfSDavid du Colombier 	uchar	op;			/* super opcode */
237dd7cddfSDavid du Colombier 
247dd7cddfSDavid du Colombier 	uchar	cond;			/* bits 28-31 */
2559cc4ca5SDavid du Colombier 	uchar	store;			/* bit 20 */
267dd7cddfSDavid du Colombier 
277dd7cddfSDavid du Colombier 	uchar	rd;			/* bits 12-15 */
287dd7cddfSDavid du Colombier 	uchar	rn;			/* bits 16-19 */
2959cc4ca5SDavid du Colombier 	uchar	rs;			/* bits 0-11 (shifter operand) */
307dd7cddfSDavid du Colombier 
317dd7cddfSDavid du Colombier 	long	imm;			/* rotated imm */
327dd7cddfSDavid du Colombier 	char*	curr;			/* fill point in buffer */
337dd7cddfSDavid du Colombier 	char*	end;			/* end of buffer */
347dd7cddfSDavid du Colombier 	char*	err;			/* error message */
357dd7cddfSDavid du Colombier };
367dd7cddfSDavid du Colombier 
377dd7cddfSDavid du Colombier typedef struct Opcode Opcode;
387dd7cddfSDavid du Colombier struct Opcode
397dd7cddfSDavid du Colombier {
407dd7cddfSDavid du Colombier 	char*	o;
4159cc4ca5SDavid du Colombier 	void	(*fmt)(Opcode*, Instr*);
424de34a7eSDavid du Colombier 	uvlong	(*foll)(Map*, Rgetter, Instr*, uvlong);
437dd7cddfSDavid du Colombier 	char*	a;
447dd7cddfSDavid du Colombier };
457dd7cddfSDavid du Colombier 
467dd7cddfSDavid du Colombier static	void	format(char*, Instr*, char*);
477dd7cddfSDavid du Colombier static	char	FRAMENAME[] = ".frame";
487dd7cddfSDavid du Colombier 
497dd7cddfSDavid du Colombier /*
507dd7cddfSDavid du Colombier  * Arm-specific debugger interface
517dd7cddfSDavid du Colombier  */
527dd7cddfSDavid du Colombier 
5359cc4ca5SDavid du Colombier static	char	*armexcep(Map*, Rgetter);
544de34a7eSDavid du Colombier static	int	armfoll(Map*, uvlong, Rgetter, uvlong*);
554de34a7eSDavid du Colombier static	int	arminst(Map*, uvlong, char, char*, int);
564de34a7eSDavid du Colombier static	int	armdas(Map*, uvlong, char*, int);
574de34a7eSDavid du Colombier static	int	arminstlen(Map*, uvlong);
587dd7cddfSDavid du Colombier 
597dd7cddfSDavid du Colombier /*
607dd7cddfSDavid du Colombier  *	Debugger interface
617dd7cddfSDavid du Colombier  */
627dd7cddfSDavid du Colombier Machdata armmach =
637dd7cddfSDavid du Colombier {
646bbfed0dSDavid du Colombier 	{0x70, 0x00, 0x20, 0xE1},		/* break point */	/* E1200070 */
657dd7cddfSDavid du Colombier 	4,			/* break point size */
667dd7cddfSDavid du Colombier 
677dd7cddfSDavid du Colombier 	leswab,			/* short to local byte order */
687dd7cddfSDavid du Colombier 	leswal,			/* long to local byte order */
697dd7cddfSDavid du Colombier 	leswav,			/* long to local byte order */
707dd7cddfSDavid du Colombier 	risctrace,		/* C traceback */
717dd7cddfSDavid du Colombier 	riscframe,		/* Frame finder */
7259cc4ca5SDavid du Colombier 	armexcep,			/* print exception */
737dd7cddfSDavid du Colombier 	0,			/* breakpoint fixup */
747dd7cddfSDavid du Colombier 	0,			/* single precision float printer */
757dd7cddfSDavid du Colombier 	0,			/* double precision float printer */
767dd7cddfSDavid du Colombier 	armfoll,		/* following addresses */
777dd7cddfSDavid du Colombier 	arminst,		/* print instruction */
787dd7cddfSDavid du Colombier 	armdas,			/* dissembler */
797dd7cddfSDavid du Colombier 	arminstlen,		/* instruction size */
807dd7cddfSDavid du Colombier };
817dd7cddfSDavid du Colombier 
8259cc4ca5SDavid du Colombier static char*
armexcep(Map * map,Rgetter rget)8359cc4ca5SDavid du Colombier armexcep(Map *map, Rgetter rget)
8459cc4ca5SDavid du Colombier {
854de34a7eSDavid du Colombier 	uvlong c;
8659cc4ca5SDavid du Colombier 
8759cc4ca5SDavid du Colombier 	c = (*rget)(map, "TYPE");
884de34a7eSDavid du Colombier 	switch ((int)c&0x1f) {
8959cc4ca5SDavid du Colombier 	case 0x11:
9059cc4ca5SDavid du Colombier 		return "Fiq interrupt";
9159cc4ca5SDavid du Colombier 	case 0x12:
9259cc4ca5SDavid du Colombier 		return "Mirq interrupt";
9359cc4ca5SDavid du Colombier 	case 0x13:
9459cc4ca5SDavid du Colombier 		return "SVC/SWI Exception";
9559cc4ca5SDavid du Colombier 	case 0x17:
96*f1b2ee28SDavid du Colombier 		return "Prefetch Abort/Breakpoint";
9759cc4ca5SDavid du Colombier 	case 0x18:
9859cc4ca5SDavid du Colombier 		return "Data Abort";
9959cc4ca5SDavid du Colombier 	case 0x1b:
10059cc4ca5SDavid du Colombier 		return "Undefined instruction/Breakpoint";
10159cc4ca5SDavid du Colombier 	case 0x1f:
10259cc4ca5SDavid du Colombier 		return "Sys trap";
10359cc4ca5SDavid du Colombier 	default:
10459cc4ca5SDavid du Colombier 		return "Undefined trap";
10559cc4ca5SDavid du Colombier 	}
10659cc4ca5SDavid du Colombier }
10759cc4ca5SDavid du Colombier 
1087dd7cddfSDavid du Colombier static
1097dd7cddfSDavid du Colombier char*	cond[16] =
1107dd7cddfSDavid du Colombier {
1117dd7cddfSDavid du Colombier 	"EQ",	"NE",	"CS",	"CC",
1127dd7cddfSDavid du Colombier 	"MI",	"PL",	"VS",	"VC",
1137dd7cddfSDavid du Colombier 	"HI",	"LS",	"GE",	"LT",
1147dd7cddfSDavid du Colombier 	"GT",	"LE",	0,	"NV"
1157dd7cddfSDavid du Colombier };
1167dd7cddfSDavid du Colombier 
1177dd7cddfSDavid du Colombier static
1187dd7cddfSDavid du Colombier char*	shtype[4] =
1197dd7cddfSDavid du Colombier {
1207dd7cddfSDavid du Colombier 	"<<",	">>",	"->",	"@>"
1217dd7cddfSDavid du Colombier };
1227dd7cddfSDavid du Colombier 
12359cc4ca5SDavid du Colombier static
12459cc4ca5SDavid du Colombier char *hb[4] =
1257dd7cddfSDavid du Colombier {
12659cc4ca5SDavid du Colombier 	"???",	"HU", "B", "H"
12759cc4ca5SDavid du Colombier };
12859cc4ca5SDavid du Colombier 
12959cc4ca5SDavid du Colombier static
13059cc4ca5SDavid du Colombier char*	addsub[2] =
13159cc4ca5SDavid du Colombier {
13259cc4ca5SDavid du Colombier 	"-",	"+",
13359cc4ca5SDavid du Colombier };
13459cc4ca5SDavid du Colombier 
13559cc4ca5SDavid du Colombier int
armclass(long w)13659cc4ca5SDavid du Colombier armclass(long w)
13759cc4ca5SDavid du Colombier {
1389b7bf7dfSDavid du Colombier 	int op, done, cp;
13959cc4ca5SDavid du Colombier 
14059cc4ca5SDavid du Colombier 	op = (w >> 25) & 0x7;
1417dd7cddfSDavid du Colombier 	switch(op) {
1427dd7cddfSDavid du Colombier 	case 0:	/* data processing r,r,r */
143*f1b2ee28SDavid du Colombier 		if((w & 0x0ff00080) == 0x01200000) {
144*f1b2ee28SDavid du Colombier 			op = (w >> 4) & 0x7;
145*f1b2ee28SDavid du Colombier 			if(op == 7)
146*f1b2ee28SDavid du Colombier 				op = 124;	/* bkpt */
147*f1b2ee28SDavid du Colombier 			else if (op > 0 && op < 4)
148*f1b2ee28SDavid du Colombier 				op += 124;	/* bx, blx */
149*f1b2ee28SDavid du Colombier 			else
150*f1b2ee28SDavid du Colombier 				op = 92;	/* unk */
151*f1b2ee28SDavid du Colombier 			break;
152*f1b2ee28SDavid du Colombier 		}
1537dd7cddfSDavid du Colombier 		op = ((w >> 4) & 0xf);
1547dd7cddfSDavid du Colombier 		if(op == 0x9) {
1554f4ac6b1SDavid du Colombier 			op = 48+16;		/* mul, swp or *rex */
1564f4ac6b1SDavid du Colombier 			if((w & 0x0ff00fff) == 0x01900f9f) {
1574f4ac6b1SDavid du Colombier 				op = 93;	/* ldrex */
1584f4ac6b1SDavid du Colombier 				break;
1594f4ac6b1SDavid du Colombier 			}
1604f4ac6b1SDavid du Colombier 			if((w & 0x0ff00ff0) == 0x01800f90) {
1614f4ac6b1SDavid du Colombier 				op = 94;	/* strex */
1624f4ac6b1SDavid du Colombier 				break;
1634f4ac6b1SDavid du Colombier 			}
1647dd7cddfSDavid du Colombier 			if(w & (1<<24)) {
1657dd7cddfSDavid du Colombier 				op += 2;
1667dd7cddfSDavid du Colombier 				if(w & (1<<22))
1674f4ac6b1SDavid du Colombier 					op++;	/* swpb */
1687dd7cddfSDavid du Colombier 				break;
1697dd7cddfSDavid du Colombier 			}
17080ee5cbfSDavid du Colombier 			if(w & (1<<23)) {	/* mullu */
17180ee5cbfSDavid du Colombier 				op = (48+24+4+4+2+2+4);
17280ee5cbfSDavid du Colombier 				if(w & (1<<22))	/* mull */
17380ee5cbfSDavid du Colombier 					op += 2;
17480ee5cbfSDavid du Colombier 			}
1757dd7cddfSDavid du Colombier 			if(w & (1<<21))
1767dd7cddfSDavid du Colombier 				op++;		/* mla */
1777dd7cddfSDavid du Colombier 			break;
1787dd7cddfSDavid du Colombier 		}
17959cc4ca5SDavid du Colombier 		if((op & 0x9) == 0x9)		/* ld/st byte/half s/u */
18059cc4ca5SDavid du Colombier 		{
18159cc4ca5SDavid du Colombier 			op = (48+16+4) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
18259cc4ca5SDavid du Colombier 			break;
18359cc4ca5SDavid du Colombier 		}
1847dd7cddfSDavid du Colombier 		op = (w >> 21) & 0xf;
1857dd7cddfSDavid du Colombier 		if(w & (1<<4))
1867dd7cddfSDavid du Colombier 			op += 32;
1877dd7cddfSDavid du Colombier 		else
1889a747e4fSDavid du Colombier 		if((w & (31<<7)) || (w & (1<<5)))
1897dd7cddfSDavid du Colombier 			op += 16;
1907dd7cddfSDavid du Colombier 		break;
1917dd7cddfSDavid du Colombier 	case 1:	/* data processing i,r,r */
1927dd7cddfSDavid du Colombier 		op = (48) + ((w >> 21) & 0xf);
1937dd7cddfSDavid du Colombier 		break;
1947dd7cddfSDavid du Colombier 	case 2:	/* load/store byte/word i(r) */
1954f4ac6b1SDavid du Colombier 		if ((w & 0xffffff8f) == 0xf57ff00f) {	/* barriers, clrex */
1964f4ac6b1SDavid du Colombier 			done = 1;
1974f4ac6b1SDavid du Colombier 			switch ((w >> 4) & 7) {
1984f4ac6b1SDavid du Colombier 			case 1:
1994f4ac6b1SDavid du Colombier 				op = 95;	/* clrex */
2004f4ac6b1SDavid du Colombier 				break;
2014f4ac6b1SDavid du Colombier 			case 4:
2024f4ac6b1SDavid du Colombier 				op = 96;	/* dsb */
2034f4ac6b1SDavid du Colombier 				break;
2044f4ac6b1SDavid du Colombier 			case 5:
2054f4ac6b1SDavid du Colombier 				op = 97;	/* dmb */
2064f4ac6b1SDavid du Colombier 				break;
2074f4ac6b1SDavid du Colombier 			case 6:
2084f4ac6b1SDavid du Colombier 				op = 98;	/* isb */
2094f4ac6b1SDavid du Colombier 				break;
2104f4ac6b1SDavid du Colombier 			default:
2114f4ac6b1SDavid du Colombier 				done = 0;
2124f4ac6b1SDavid du Colombier 				break;
2134f4ac6b1SDavid du Colombier 			}
2144f4ac6b1SDavid du Colombier 			if (done)
2154f4ac6b1SDavid du Colombier 				break;
2164f4ac6b1SDavid du Colombier 		}
21759cc4ca5SDavid du Colombier 		op = (48+24) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
2187dd7cddfSDavid du Colombier 		break;
2197dd7cddfSDavid du Colombier 	case 3:	/* load/store byte/word (r)(r) */
22059cc4ca5SDavid du Colombier 		op = (48+24+4) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
2217dd7cddfSDavid du Colombier 		break;
2227dd7cddfSDavid du Colombier 	case 4:	/* block data transfer (r)(r) */
2236ca8a7e3SDavid du Colombier 		if ((w & 0xfe50ffff) == 0xf8100a00) {	/* v7 RFE */
2246ca8a7e3SDavid du Colombier 			op = 99;
2256ca8a7e3SDavid du Colombier 			break;
2266ca8a7e3SDavid du Colombier 		}
22759cc4ca5SDavid du Colombier 		op = (48+24+4+4) + ((w >> 20) & 0x1);
2287dd7cddfSDavid du Colombier 		break;
2297dd7cddfSDavid du Colombier 	case 5:	/* branch / branch link */
23059cc4ca5SDavid du Colombier 		op = (48+24+4+4+2) + ((w >> 24) & 0x1);
2317dd7cddfSDavid du Colombier 		break;
2327dd7cddfSDavid du Colombier 	case 7:	/* coprocessor crap */
2339b7bf7dfSDavid du Colombier 		cp = (w >> 8) & 0xF;
2349b7bf7dfSDavid du Colombier 		if(cp == 10 || cp == 11){	/* vfp */
2359b7bf7dfSDavid du Colombier 			if((w >> 4) & 0x1){
2369b7bf7dfSDavid du Colombier 				/* vfp register transfer */
2379b7bf7dfSDavid du Colombier 				switch((w >> 21) & 0x7){
2389b7bf7dfSDavid du Colombier 				case 0:
2399b7bf7dfSDavid du Colombier 					op = 118 + ((w >> 20) & 0x1);
2409b7bf7dfSDavid du Colombier 					break;
2419b7bf7dfSDavid du Colombier 				case 7:
2429b7bf7dfSDavid du Colombier 					op = 118+2 + ((w >> 20) & 0x1);
2439b7bf7dfSDavid du Colombier 					break;
2449b7bf7dfSDavid du Colombier 				default:
2459b7bf7dfSDavid du Colombier 					op = (48+24+4+4+2+2+4+4);
2469b7bf7dfSDavid du Colombier 					break;
2479b7bf7dfSDavid du Colombier 				}
2489b7bf7dfSDavid du Colombier 				break;
2499b7bf7dfSDavid du Colombier 			}
2509b7bf7dfSDavid du Colombier 			/* vfp data processing */
2519b7bf7dfSDavid du Colombier 			if(((w >> 23) & 0x1) == 0){
2529b7bf7dfSDavid du Colombier 				op = 100 + ((w >> 19) & 0x6) + ((w >> 6) & 0x1);
2539b7bf7dfSDavid du Colombier 				break;
2549b7bf7dfSDavid du Colombier 			}
2559b7bf7dfSDavid du Colombier 			switch(((w >> 19) & 0x6) + ((w >> 6) & 0x1)){
2569b7bf7dfSDavid du Colombier 			case 0:
2579b7bf7dfSDavid du Colombier 				op = 108;
2589b7bf7dfSDavid du Colombier 				break;
2599b7bf7dfSDavid du Colombier 			case 7:
2606bbfed0dSDavid du Colombier 				if(((w >> 19) & 0x1) == 0){
2619b7bf7dfSDavid du Colombier 					if(((w >> 17) & 0x1) == 0)
2629b7bf7dfSDavid du Colombier 						op = 109 + ((w >> 16) & 0x4) +
2639b7bf7dfSDavid du Colombier 							((w >> 15) & 0x2) +
2649b7bf7dfSDavid du Colombier 							((w >> 7) & 0x1);
2659b7bf7dfSDavid du Colombier 					else if(((w >> 16) & 0x7) == 0x7)
2669b7bf7dfSDavid du Colombier 						op = 117;
2676bbfed0dSDavid du Colombier 				}else
2689b7bf7dfSDavid du Colombier 					switch((w >> 16) & 0x7){
2699b7bf7dfSDavid du Colombier 					case 0:
2709b7bf7dfSDavid du Colombier 					case 4:
2719b7bf7dfSDavid du Colombier 					case 5:
2729b7bf7dfSDavid du Colombier 						op = 117;
2739b7bf7dfSDavid du Colombier 						break;
2749b7bf7dfSDavid du Colombier 					}
2759b7bf7dfSDavid du Colombier 				break;
2769b7bf7dfSDavid du Colombier 			}
2779b7bf7dfSDavid du Colombier 			if(op == 7)
2789b7bf7dfSDavid du Colombier 				op = (48+24+4+4+2+2+4+4);
2799b7bf7dfSDavid du Colombier 			break;
2809b7bf7dfSDavid du Colombier 		}
28159cc4ca5SDavid du Colombier 		op = (48+24+4+4+2+2) + ((w >> 3) & 0x2) + ((w >> 20) & 0x1);
2827dd7cddfSDavid du Colombier 		break;
2839b7bf7dfSDavid du Colombier 	case 6:	/* vfp load / store */
2849b7bf7dfSDavid du Colombier 		if(((w >> 21) &0x9) == 0x8){
2859b7bf7dfSDavid du Colombier 			op = 122 + ((w >> 20) & 0x1);
2869b7bf7dfSDavid du Colombier 			break;
2879b7bf7dfSDavid du Colombier 		}
2889b7bf7dfSDavid du Colombier 		/* fall through */
2897dd7cddfSDavid du Colombier 	default:
29080ee5cbfSDavid du Colombier 		op = (48+24+4+4+2+2+4+4);
2917dd7cddfSDavid du Colombier 		break;
2927dd7cddfSDavid du Colombier 	}
2937dd7cddfSDavid du Colombier 	return op;
2947dd7cddfSDavid du Colombier }
2957dd7cddfSDavid du Colombier 
2967dd7cddfSDavid du Colombier static int
decode(Map * map,uvlong pc,Instr * i)2974de34a7eSDavid du Colombier decode(Map *map, uvlong pc, Instr *i)
2987dd7cddfSDavid du Colombier {
2994de34a7eSDavid du Colombier 	ulong w;
3007dd7cddfSDavid du Colombier 
3017dd7cddfSDavid du Colombier 	if(get4(map, pc, &w) < 0) {
3027dd7cddfSDavid du Colombier 		werrstr("can't read instruction: %r");
3037dd7cddfSDavid du Colombier 		return -1;
3047dd7cddfSDavid du Colombier 	}
3057dd7cddfSDavid du Colombier 	i->w = w;
3067dd7cddfSDavid du Colombier 	i->addr = pc;
30759cc4ca5SDavid du Colombier 	i->cond = (w >> 28) & 0xF;
30859cc4ca5SDavid du Colombier 	i->op = armclass(w);
3097dd7cddfSDavid du Colombier 	i->map = map;
3107dd7cddfSDavid du Colombier 	return 1;
3117dd7cddfSDavid du Colombier }
3127dd7cddfSDavid du Colombier 
3131bd28109SDavid du Colombier #pragma	varargck	argpos	bprint		2
3141bd28109SDavid du Colombier 
3157dd7cddfSDavid du Colombier static void
bprint(Instr * i,char * fmt,...)3167dd7cddfSDavid du Colombier bprint(Instr *i, char *fmt, ...)
3177dd7cddfSDavid du Colombier {
3187dd7cddfSDavid du Colombier 	va_list arg;
3197dd7cddfSDavid du Colombier 
3207dd7cddfSDavid du Colombier 	va_start(arg, fmt);
3219a747e4fSDavid du Colombier 	i->curr = vseprint(i->curr, i->end, fmt, arg);
3227dd7cddfSDavid du Colombier 	va_end(arg);
3237dd7cddfSDavid du Colombier }
3247dd7cddfSDavid du Colombier 
3257dd7cddfSDavid du Colombier static int
plocal(Instr * i)32659cc4ca5SDavid du Colombier plocal(Instr *i)
3277dd7cddfSDavid du Colombier {
3287dd7cddfSDavid du Colombier 	char *reg;
3297dd7cddfSDavid du Colombier 	Symbol s;
33059cc4ca5SDavid du Colombier 	char *fn;
33159cc4ca5SDavid du Colombier 	int class;
33259cc4ca5SDavid du Colombier 	int offset;
3337dd7cddfSDavid du Colombier 
33459cc4ca5SDavid du Colombier 	if(!findsym(i->addr, CTEXT, &s)) {
3354de34a7eSDavid du Colombier 		if(debug)fprint(2,"fn not found @%llux: %r\n", i->addr);
3367dd7cddfSDavid du Colombier 		return 0;
33759cc4ca5SDavid du Colombier 	}
33859cc4ca5SDavid du Colombier 	fn = s.name;
33959cc4ca5SDavid du Colombier 	if (!findlocal(&s, FRAMENAME, &s)) {
34059cc4ca5SDavid du Colombier 		if(debug)fprint(2,"%s.%s not found @%s: %r\n", fn, FRAMENAME, s.name);
34159cc4ca5SDavid du Colombier 			return 0;
34259cc4ca5SDavid du Colombier 	}
3437dd7cddfSDavid du Colombier 	if(s.value > i->imm) {
34459cc4ca5SDavid du Colombier 		class = CAUTO;
34559cc4ca5SDavid du Colombier 		offset = s.value-i->imm;
3467dd7cddfSDavid du Colombier 		reg = "(SP)";
3477dd7cddfSDavid du Colombier 	} else {
34859cc4ca5SDavid du Colombier 		class = CPARAM;
34959cc4ca5SDavid du Colombier 		offset = i->imm-s.value-4;
3507dd7cddfSDavid du Colombier 		reg = "(FP)";
3517dd7cddfSDavid du Colombier 	}
35259cc4ca5SDavid du Colombier 	if(!getauto(&s, offset, class, &s)) {
35359cc4ca5SDavid du Colombier 		if(debug)fprint(2,"%s %s not found @%ux: %r\n", fn,
35459cc4ca5SDavid du Colombier 			class == CAUTO ? " auto" : "param", offset);
35559cc4ca5SDavid du Colombier 		return 0;
35659cc4ca5SDavid du Colombier 	}
3571bd28109SDavid du Colombier 	bprint(i, "%s%c%lld%s", s.name, class == CPARAM ? '+' : '-', s.value, reg);
3587dd7cddfSDavid du Colombier 	return 1;
3597dd7cddfSDavid du Colombier }
3607dd7cddfSDavid du Colombier 
36159cc4ca5SDavid du Colombier /*
36259cc4ca5SDavid du Colombier  * Print value v as name[+offset]
36359cc4ca5SDavid du Colombier  */
36459cc4ca5SDavid du Colombier static int
gsymoff(char * buf,int n,ulong v,int space)36548207d97SDavid du Colombier gsymoff(char *buf, int n, ulong v, int space)
36659cc4ca5SDavid du Colombier {
36759cc4ca5SDavid du Colombier 	Symbol s;
36859cc4ca5SDavid du Colombier 	int r;
36959cc4ca5SDavid du Colombier 	long delta;
37059cc4ca5SDavid du Colombier 
37159cc4ca5SDavid du Colombier 	r = delta = 0;		/* to shut compiler up */
37259cc4ca5SDavid du Colombier 	if (v) {
37359cc4ca5SDavid du Colombier 		r = findsym(v, space, &s);
37459cc4ca5SDavid du Colombier 		if (r)
37559cc4ca5SDavid du Colombier 			delta = v-s.value;
37659cc4ca5SDavid du Colombier 		if (delta < 0)
37759cc4ca5SDavid du Colombier 			delta = -delta;
37859cc4ca5SDavid du Colombier 	}
37959cc4ca5SDavid du Colombier 	if (v == 0 || r == 0 || delta >= 4096)
38059cc4ca5SDavid du Colombier 		return snprint(buf, n, "#%lux", v);
38159cc4ca5SDavid du Colombier 	if (strcmp(s.name, ".string") == 0)
38259cc4ca5SDavid du Colombier 		return snprint(buf, n, "#%lux", v);
38359cc4ca5SDavid du Colombier 	if (!delta)
38459cc4ca5SDavid du Colombier 		return snprint(buf, n, "%s", s.name);
38559cc4ca5SDavid du Colombier 	if (s.type != 't' && s.type != 'T')
3863806af99SDavid du Colombier 		return snprint(buf, n, "%s+%llux", s.name, v-s.value);
38759cc4ca5SDavid du Colombier 	else
38859cc4ca5SDavid du Colombier 		return snprint(buf, n, "#%lux", v);
38959cc4ca5SDavid du Colombier }
39059cc4ca5SDavid du Colombier 
3917dd7cddfSDavid du Colombier static void
armdps(Opcode * o,Instr * i)3927dd7cddfSDavid du Colombier armdps(Opcode *o, Instr *i)
3937dd7cddfSDavid du Colombier {
3947dd7cddfSDavid du Colombier 	i->store = (i->w >> 20) & 1;
39559cc4ca5SDavid du Colombier 	i->rn = (i->w >> 16) & 0xf;
39659cc4ca5SDavid du Colombier 	i->rd = (i->w >> 12) & 0xf;
39759cc4ca5SDavid du Colombier 	i->rs = (i->w >> 0) & 0xf;
3987dd7cddfSDavid du Colombier 	if(i->rn == 15 && i->rs == 0) {
3997dd7cddfSDavid du Colombier 		if(i->op == 8) {
4007dd7cddfSDavid du Colombier 			format("MOVW", i,"CPSR, R%d");
4017dd7cddfSDavid du Colombier 			return;
4027dd7cddfSDavid du Colombier 		} else
4037dd7cddfSDavid du Colombier 		if(i->op == 10) {
4047dd7cddfSDavid du Colombier 			format("MOVW", i,"SPSR, R%d");
4057dd7cddfSDavid du Colombier 			return;
4067dd7cddfSDavid du Colombier 		}
4077dd7cddfSDavid du Colombier 	} else
4087dd7cddfSDavid du Colombier 	if(i->rn == 9 && i->rd == 15) {
4097dd7cddfSDavid du Colombier 		if(i->op == 9) {
4107dd7cddfSDavid du Colombier 			format("MOVW", i, "R%s, CPSR");
4117dd7cddfSDavid du Colombier 			return;
4127dd7cddfSDavid du Colombier 		} else
4137dd7cddfSDavid du Colombier 		if(i->op == 11) {
4147dd7cddfSDavid du Colombier 			format("MOVW", i, "R%s, SPSR");
4157dd7cddfSDavid du Colombier 			return;
4167dd7cddfSDavid du Colombier 		}
4177dd7cddfSDavid du Colombier 	}
4186bbfed0dSDavid du Colombier 	if(i->rd == 15) {
4196bbfed0dSDavid du Colombier 		if(i->op == 120) {
4206bbfed0dSDavid du Colombier 			format("MOVW", i, "PSR, %x");
4216bbfed0dSDavid du Colombier 			return;
4226bbfed0dSDavid du Colombier 		} else
4236bbfed0dSDavid du Colombier 		if(i->op == 121) {
4246bbfed0dSDavid du Colombier 			format("MOVW", i, "%x, PSR");
4256bbfed0dSDavid du Colombier 			return;
4266bbfed0dSDavid du Colombier 		}
4276bbfed0dSDavid du Colombier 	}
4287dd7cddfSDavid du Colombier 	format(o->o, i, o->a);
4297dd7cddfSDavid du Colombier }
4307dd7cddfSDavid du Colombier 
4317dd7cddfSDavid du Colombier static void
armdpi(Opcode * o,Instr * i)4327dd7cddfSDavid du Colombier armdpi(Opcode *o, Instr *i)
4337dd7cddfSDavid du Colombier {
4347dd7cddfSDavid du Colombier 	ulong v;
4357dd7cddfSDavid du Colombier 	int c;
4367dd7cddfSDavid du Colombier 
43759cc4ca5SDavid du Colombier 	v = (i->w >> 0) & 0xff;
4387dd7cddfSDavid du Colombier 	c = (i->w >> 8) & 0xf;
4397dd7cddfSDavid du Colombier 	while(c) {
4407dd7cddfSDavid du Colombier 		v = (v<<30) | (v>>2);
4417dd7cddfSDavid du Colombier 		c--;
4427dd7cddfSDavid du Colombier 	}
4437dd7cddfSDavid du Colombier 	i->imm = v;
4447dd7cddfSDavid du Colombier 	i->store = (i->w >> 20) & 1;
44559cc4ca5SDavid du Colombier 	i->rn = (i->w >> 16) & 0xf;
44659cc4ca5SDavid du Colombier 	i->rd = (i->w >> 12) & 0xf;
44759cc4ca5SDavid du Colombier 	i->rs = i->w&0x0f;
4487dd7cddfSDavid du Colombier 
4497dd7cddfSDavid du Colombier 		/* RET is encoded as ADD #0,R14,R15 */
45059cc4ca5SDavid du Colombier 	if((i->w & 0x0fffffff) == 0x028ef000){
45159cc4ca5SDavid du Colombier 		format("RET%C", i, "");
4527dd7cddfSDavid du Colombier 		return;
45359cc4ca5SDavid du Colombier 	}
45459cc4ca5SDavid du Colombier 	if((i->w & 0x0ff0ffff) == 0x0280f000){
45559cc4ca5SDavid du Colombier 		format("B%C", i, "0(R%n)");
45659cc4ca5SDavid du Colombier 		return;
45759cc4ca5SDavid du Colombier 	}
4587dd7cddfSDavid du Colombier 	format(o->o, i, o->a);
4597dd7cddfSDavid du Colombier }
4607dd7cddfSDavid du Colombier 
4617dd7cddfSDavid du Colombier static void
armsdti(Opcode * o,Instr * i)4627dd7cddfSDavid du Colombier armsdti(Opcode *o, Instr *i)
4637dd7cddfSDavid du Colombier {
4647dd7cddfSDavid du Colombier 	ulong v;
4657dd7cddfSDavid du Colombier 
46659cc4ca5SDavid du Colombier 	v = i->w & 0xfff;
4677dd7cddfSDavid du Colombier 	if(!(i->w & (1<<23)))
4687dd7cddfSDavid du Colombier 		v = -v;
4697dd7cddfSDavid du Colombier 	i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
4707dd7cddfSDavid du Colombier 	i->imm = v;
47159cc4ca5SDavid du Colombier 	i->rn = (i->w >> 16) & 0xf;
47259cc4ca5SDavid du Colombier 	i->rd = (i->w >> 12) & 0xf;
47359cc4ca5SDavid du Colombier 		/* RET is encoded as LW.P x,R13,R15 */
47459cc4ca5SDavid du Colombier 	if ((i->w & 0x0ffff000) == 0x049df000)
47559cc4ca5SDavid du Colombier 	{
47659cc4ca5SDavid du Colombier 		format("RET%C%p", i, "%I");
47759cc4ca5SDavid du Colombier 		return;
47859cc4ca5SDavid du Colombier 	}
47959cc4ca5SDavid du Colombier 	format(o->o, i, o->a);
48059cc4ca5SDavid du Colombier }
48159cc4ca5SDavid du Colombier 
4829b7bf7dfSDavid du Colombier static void
armvstdi(Opcode * o,Instr * i)4839b7bf7dfSDavid du Colombier armvstdi(Opcode *o, Instr *i)
4849b7bf7dfSDavid du Colombier {
4859b7bf7dfSDavid du Colombier 	ulong v;
4869b7bf7dfSDavid du Colombier 
4879b7bf7dfSDavid du Colombier 	v = (i->w & 0xff) << 2;
4889b7bf7dfSDavid du Colombier 	if(!(i->w & (1<<23)))
4899b7bf7dfSDavid du Colombier 		v = -v;
4909b7bf7dfSDavid du Colombier 	i->imm = v;
4919b7bf7dfSDavid du Colombier 	i->rn = (i->w >> 16) & 0xf;
4929b7bf7dfSDavid du Colombier 	i->rd = (i->w >> 12) & 0xf;
4939b7bf7dfSDavid du Colombier 	format(o->o, i, o->a);
4949b7bf7dfSDavid du Colombier }
4959b7bf7dfSDavid du Colombier 
49659cc4ca5SDavid du Colombier /* arm V4 ld/st halfword, signed byte */
49759cc4ca5SDavid du Colombier static void
armhwby(Opcode * o,Instr * i)49859cc4ca5SDavid du Colombier armhwby(Opcode *o, Instr *i)
49959cc4ca5SDavid du Colombier {
50059cc4ca5SDavid du Colombier 	i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
50159cc4ca5SDavid du Colombier 	i->imm = (i->w & 0xf) | ((i->w >> 8) & 0xf);
50259cc4ca5SDavid du Colombier 	if (!(i->w & (1 << 23)))
50359cc4ca5SDavid du Colombier 		i->imm = - i->imm;
50459cc4ca5SDavid du Colombier 	i->rn = (i->w >> 16) & 0xf;
50559cc4ca5SDavid du Colombier 	i->rd = (i->w >> 12) & 0xf;
50659cc4ca5SDavid du Colombier 	i->rs = (i->w >> 0) & 0xf;
5077dd7cddfSDavid du Colombier 	format(o->o, i, o->a);
5087dd7cddfSDavid du Colombier }
5097dd7cddfSDavid du Colombier 
5107dd7cddfSDavid du Colombier static void
armsdts(Opcode * o,Instr * i)5117dd7cddfSDavid du Colombier armsdts(Opcode *o, Instr *i)
5127dd7cddfSDavid du Colombier {
5137dd7cddfSDavid du Colombier 	i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
51459cc4ca5SDavid du Colombier 	i->rs = (i->w >> 0) & 0xf;
51559cc4ca5SDavid du Colombier 	i->rn = (i->w >> 16) & 0xf;
51659cc4ca5SDavid du Colombier 	i->rd = (i->w >> 12) & 0xf;
5177dd7cddfSDavid du Colombier 	format(o->o, i, o->a);
5187dd7cddfSDavid du Colombier }
5197dd7cddfSDavid du Colombier 
5207dd7cddfSDavid du Colombier static void
armbdt(Opcode * o,Instr * i)5217dd7cddfSDavid du Colombier armbdt(Opcode *o, Instr *i)
5227dd7cddfSDavid du Colombier {
5237dd7cddfSDavid du Colombier 	i->store = (i->w >> 21) & 0x3;		/* S & W bits */
52459cc4ca5SDavid du Colombier 	i->rn = (i->w >> 16) & 0xf;
5257dd7cddfSDavid du Colombier 	i->imm = i->w & 0xffff;
5267dd7cddfSDavid du Colombier 	if(i->w == 0xe8fd8000)
5277dd7cddfSDavid du Colombier 		format("RFE", i, "");
5287dd7cddfSDavid du Colombier 	else
5297dd7cddfSDavid du Colombier 		format(o->o, i, o->a);
5307dd7cddfSDavid du Colombier }
5317dd7cddfSDavid du Colombier 
5327dd7cddfSDavid du Colombier static void
armund(Opcode * o,Instr * i)5337dd7cddfSDavid du Colombier armund(Opcode *o, Instr *i)
5347dd7cddfSDavid du Colombier {
5357dd7cddfSDavid du Colombier 	format(o->o, i, o->a);
5367dd7cddfSDavid du Colombier }
5377dd7cddfSDavid du Colombier 
5387dd7cddfSDavid du Colombier static void
armcdt(Opcode * o,Instr * i)5397dd7cddfSDavid du Colombier armcdt(Opcode *o, Instr *i)
5407dd7cddfSDavid du Colombier {
5417dd7cddfSDavid du Colombier 	format(o->o, i, o->a);
5427dd7cddfSDavid du Colombier }
5437dd7cddfSDavid du Colombier 
5447dd7cddfSDavid du Colombier static void
armunk(Opcode * o,Instr * i)5457dd7cddfSDavid du Colombier armunk(Opcode *o, Instr *i)
5467dd7cddfSDavid du Colombier {
5477dd7cddfSDavid du Colombier 	format(o->o, i, o->a);
5487dd7cddfSDavid du Colombier }
5497dd7cddfSDavid du Colombier 
5507dd7cddfSDavid du Colombier static void
armb(Opcode * o,Instr * i)5517dd7cddfSDavid du Colombier armb(Opcode *o, Instr *i)
5527dd7cddfSDavid du Colombier {
5537dd7cddfSDavid du Colombier 	ulong v;
5547dd7cddfSDavid du Colombier 
5557dd7cddfSDavid du Colombier 	v = i->w & 0xffffff;
55659cc4ca5SDavid du Colombier 	if(v & 0x800000)
5577dd7cddfSDavid du Colombier 		v |= ~0xffffff;
5587dd7cddfSDavid du Colombier 	i->imm = (v<<2) + i->addr + 8;
5597dd7cddfSDavid du Colombier 	format(o->o, i, o->a);
5607dd7cddfSDavid du Colombier }
5617dd7cddfSDavid du Colombier 
5627dd7cddfSDavid du Colombier static void
armbpt(Opcode * o,Instr * i)563*f1b2ee28SDavid du Colombier armbpt(Opcode *o, Instr *i)
564*f1b2ee28SDavid du Colombier {
565*f1b2ee28SDavid du Colombier 	i->imm = ((i->w >> 4) & 0xfff0) | (i->w &0xf);
566*f1b2ee28SDavid du Colombier 	format(o->o, i, o->a);
567*f1b2ee28SDavid du Colombier }
568*f1b2ee28SDavid du Colombier 
569*f1b2ee28SDavid du Colombier static void
armco(Opcode * o,Instr * i)5707dd7cddfSDavid du Colombier armco(Opcode *o, Instr *i)		/* coprocessor instructions */
5717dd7cddfSDavid du Colombier {
5727dd7cddfSDavid du Colombier 	int op, p, cp;
5737dd7cddfSDavid du Colombier 
5747dd7cddfSDavid du Colombier 	char buf[1024];
5757dd7cddfSDavid du Colombier 
57659cc4ca5SDavid du Colombier 	i->rn = (i->w >> 16) & 0xf;
57759cc4ca5SDavid du Colombier 	i->rd = (i->w >> 12) & 0xf;
57859cc4ca5SDavid du Colombier 	i->rs = i->w&0xf;
5797dd7cddfSDavid du Colombier 	cp = (i->w >> 8) & 0xf;
5807dd7cddfSDavid du Colombier 	p = (i->w >> 5) & 0x7;
58159cc4ca5SDavid du Colombier 	if(i->w&(1<<4)) {
58259cc4ca5SDavid du Colombier 		op = (i->w >> 21) & 0x07;
5833468a491SDavid du Colombier 		snprint(buf, sizeof(buf), "#%x, #%x, R%d, C(%d), C(%d), #%x", cp, op, i->rd, i->rn, i->rs, p);
5847dd7cddfSDavid du Colombier 	} else {
58559cc4ca5SDavid du Colombier 		op = (i->w >> 20) & 0x0f;
5863468a491SDavid du Colombier 		snprint(buf, sizeof(buf), "#%x, #%x, C(%d), C(%d), C(%d), #%x", cp, op, i->rd, i->rn, i->rs, p);
5877dd7cddfSDavid du Colombier 	}
5887dd7cddfSDavid du Colombier 	format(o->o, i, buf);
5897dd7cddfSDavid du Colombier }
5907dd7cddfSDavid du Colombier 
59159cc4ca5SDavid du Colombier static int
armcondpass(Map * map,Rgetter rget,uchar cond)59259cc4ca5SDavid du Colombier armcondpass(Map *map, Rgetter rget, uchar cond)
5937dd7cddfSDavid du Colombier {
5944de34a7eSDavid du Colombier 	uvlong psr;
59559cc4ca5SDavid du Colombier 	uchar n;
59659cc4ca5SDavid du Colombier 	uchar z;
59759cc4ca5SDavid du Colombier 	uchar c;
59859cc4ca5SDavid du Colombier 	uchar v;
59959cc4ca5SDavid du Colombier 
60059cc4ca5SDavid du Colombier 	psr = rget(map, "PSR");
60159cc4ca5SDavid du Colombier 	n = (psr >> 31) & 1;
60259cc4ca5SDavid du Colombier 	z = (psr >> 30) & 1;
60359cc4ca5SDavid du Colombier 	c = (psr >> 29) & 1;
60459cc4ca5SDavid du Colombier 	v = (psr >> 28) & 1;
60559cc4ca5SDavid du Colombier 
60659cc4ca5SDavid du Colombier 	switch(cond) {
607ec46fab0SDavid du Colombier 	default:
60859cc4ca5SDavid du Colombier 	case 0:		return z;
60959cc4ca5SDavid du Colombier 	case 1:		return !z;
61059cc4ca5SDavid du Colombier 	case 2:		return c;
61159cc4ca5SDavid du Colombier 	case 3:		return !c;
61259cc4ca5SDavid du Colombier 	case 4:		return n;
61359cc4ca5SDavid du Colombier 	case 5:		return !n;
61459cc4ca5SDavid du Colombier 	case 6:		return v;
61559cc4ca5SDavid du Colombier 	case 7:		return !v;
61659cc4ca5SDavid du Colombier 	case 8:		return c && !z;
61759cc4ca5SDavid du Colombier 	case 9:		return !c || z;
61859cc4ca5SDavid du Colombier 	case 10:	return n == v;
61959cc4ca5SDavid du Colombier 	case 11:	return n != v;
62059cc4ca5SDavid du Colombier 	case 12:	return !z && (n == v);
6216bbfed0dSDavid du Colombier 	case 13:	return z || (n != v);
62259cc4ca5SDavid du Colombier 	case 14:	return 1;
62359cc4ca5SDavid du Colombier 	case 15:	return 0;
62459cc4ca5SDavid du Colombier 	}
62559cc4ca5SDavid du Colombier }
62659cc4ca5SDavid du Colombier 
62759cc4ca5SDavid du Colombier static ulong
armshiftval(Map * map,Rgetter rget,Instr * i)62859cc4ca5SDavid du Colombier armshiftval(Map *map, Rgetter rget, Instr *i)
62959cc4ca5SDavid du Colombier {
63059cc4ca5SDavid du Colombier 	if(i->w & (1 << 25)) {				/* immediate */
63159cc4ca5SDavid du Colombier 		ulong imm = i->w & BITS(0, 7);
63259cc4ca5SDavid du Colombier 		ulong s = (i->w & BITS(8, 11)) >> 7; /* this contains the *2 */
63359cc4ca5SDavid du Colombier 		return ROR(imm, s);
63459cc4ca5SDavid du Colombier 	} else {
6357dd7cddfSDavid du Colombier 		char buf[8];
63659cc4ca5SDavid du Colombier 		ulong v;
63759cc4ca5SDavid du Colombier 		ulong s = (i->w & BITS(7,11)) >> 7;
6387dd7cddfSDavid du Colombier 
63959cc4ca5SDavid du Colombier 		sprint(buf, "R%ld", i->w & 0xf);
64059cc4ca5SDavid du Colombier 		v = rget(map, buf);
6417dd7cddfSDavid du Colombier 
64259cc4ca5SDavid du Colombier 		switch((i->w & BITS(4, 6)) >> 4) {
643ec46fab0SDavid du Colombier 		default:
6447dd7cddfSDavid du Colombier 		case 0:					/* LSLIMM */
6457dd7cddfSDavid du Colombier 			return v << s;
6467dd7cddfSDavid du Colombier 		case 1:					/* LSLREG */
64759cc4ca5SDavid du Colombier 			sprint(buf, "R%lud", s >> 1);
64859cc4ca5SDavid du Colombier 			s = rget(map, buf) & 0xFF;
64959cc4ca5SDavid du Colombier 			if(s >= 32) return 0;
6507dd7cddfSDavid du Colombier 			return v << s;
6517dd7cddfSDavid du Colombier 		case 2:					/* LSRIMM */
65259cc4ca5SDavid du Colombier 			return LSR(v, s);
6537dd7cddfSDavid du Colombier 		case 3:					/* LSRREG */
6547dd7cddfSDavid du Colombier 			sprint(buf, "R%ld", s >> 1);
65559cc4ca5SDavid du Colombier 			s = rget(map, buf) & 0xFF;
65659cc4ca5SDavid du Colombier 			if(s >= 32) return 0;
65759cc4ca5SDavid du Colombier 			return LSR(v, s);
6587dd7cddfSDavid du Colombier 		case 4:					/* ASRIMM */
6597dd7cddfSDavid du Colombier 			if(s == 0) {
66059cc4ca5SDavid du Colombier 				if((v & (1U<<31)) == 0)
6617dd7cddfSDavid du Colombier 					return 0;
66259cc4ca5SDavid du Colombier 				return 0xFFFFFFFF;
6637dd7cddfSDavid du Colombier 			}
66459cc4ca5SDavid du Colombier 			return ASR(v, s);
6657dd7cddfSDavid du Colombier 		case 5:					/* ASRREG */
6667dd7cddfSDavid du Colombier 			sprint(buf, "R%ld", s >> 1);
66759cc4ca5SDavid du Colombier 			s = rget(map, buf) & 0xFF;
6687dd7cddfSDavid du Colombier 			if(s >= 32) {
66959cc4ca5SDavid du Colombier 				if((v & (1U<<31)) == 0)
6707dd7cddfSDavid du Colombier 					return 0;
67159cc4ca5SDavid du Colombier 				return 0xFFFFFFFF;
6727dd7cddfSDavid du Colombier 			}
67359cc4ca5SDavid du Colombier 			return ASR(v, s);
6747dd7cddfSDavid du Colombier 		case 6:					/* RORIMM */
67559cc4ca5SDavid du Colombier 			if(s == 0) {
67659cc4ca5SDavid du Colombier 				ulong c = (rget(map, "PSR") >> 29) & 1;
67759cc4ca5SDavid du Colombier 
67859cc4ca5SDavid du Colombier 				return (c << 31) | LSR(v, 1);
67959cc4ca5SDavid du Colombier 			}
6807dd7cddfSDavid du Colombier 			return ROR(v, s);
6817dd7cddfSDavid du Colombier 		case 7:					/* RORREG */
68259cc4ca5SDavid du Colombier 			sprint(buf, "R%ld", (s>>1)&0xF);
68359cc4ca5SDavid du Colombier 			s = rget(map, buf);
68459cc4ca5SDavid du Colombier 			if(s == 0 || (s & 0xF) == 0)
6857dd7cddfSDavid du Colombier 				return v;
68659cc4ca5SDavid du Colombier 			return ROR(v, s & 0xF);
6877dd7cddfSDavid du Colombier 		}
68859cc4ca5SDavid du Colombier 	}
68959cc4ca5SDavid du Colombier }
69059cc4ca5SDavid du Colombier 
69159cc4ca5SDavid du Colombier static int
nbits(ulong v)69259cc4ca5SDavid du Colombier nbits(ulong v)
69359cc4ca5SDavid du Colombier {
69459cc4ca5SDavid du Colombier 	int n = 0;
69559cc4ca5SDavid du Colombier 	int i;
69659cc4ca5SDavid du Colombier 
69759cc4ca5SDavid du Colombier 	for(i=0; i < 32 ; i++) {
69859cc4ca5SDavid du Colombier 		if(v & 1) ++n;
69959cc4ca5SDavid du Colombier 		v >>= 1;
70059cc4ca5SDavid du Colombier 	}
70159cc4ca5SDavid du Colombier 
70259cc4ca5SDavid du Colombier 	return n;
7037dd7cddfSDavid du Colombier }
7047dd7cddfSDavid du Colombier 
7057dd7cddfSDavid du Colombier static ulong
armmaddr(Map * map,Rgetter rget,Instr * i)70659cc4ca5SDavid du Colombier armmaddr(Map *map, Rgetter rget, Instr *i)
70759cc4ca5SDavid du Colombier {
70859cc4ca5SDavid du Colombier 	ulong v;
70959cc4ca5SDavid du Colombier 	ulong nb;
71059cc4ca5SDavid du Colombier 	char buf[8];
71159cc4ca5SDavid du Colombier 	ulong rn;
71259cc4ca5SDavid du Colombier 
71359cc4ca5SDavid du Colombier 	rn = (i->w >> 16) & 0xf;
71459cc4ca5SDavid du Colombier 	sprint(buf,"R%ld", rn);
71559cc4ca5SDavid du Colombier 
71659cc4ca5SDavid du Colombier 	v = rget(map, buf);
71759cc4ca5SDavid du Colombier 	nb = nbits(i->w & ((1 << 15) - 1));
71859cc4ca5SDavid du Colombier 
71959cc4ca5SDavid du Colombier 	switch((i->w >> 23) & 3) {
720ec46fab0SDavid du Colombier 	default:
72159cc4ca5SDavid du Colombier 	case 0: return (v - (nb*4)) + 4;
72259cc4ca5SDavid du Colombier 	case 1: return v;
72359cc4ca5SDavid du Colombier 	case 2: return v - (nb*4);
72459cc4ca5SDavid du Colombier 	case 3: return v + 4;
72559cc4ca5SDavid du Colombier 	}
72659cc4ca5SDavid du Colombier }
72759cc4ca5SDavid du Colombier 
7284de34a7eSDavid du Colombier static uvlong
armaddr(Map * map,Rgetter rget,Instr * i)72959cc4ca5SDavid du Colombier armaddr(Map *map, Rgetter rget, Instr *i)
7307dd7cddfSDavid du Colombier {
7317dd7cddfSDavid du Colombier 	char buf[8];
73259cc4ca5SDavid du Colombier 	ulong rn;
7337dd7cddfSDavid du Colombier 
7346ca8a7e3SDavid du Colombier 	snprint(buf, sizeof(buf), "R%ld", (i->w >> 16) & 0xf);
73559cc4ca5SDavid du Colombier 	rn = rget(map, buf);
7367dd7cddfSDavid du Colombier 
7376ca8a7e3SDavid du Colombier 	if((i->w & (1<<24)) == 0)			/* POSTIDX */
7386ca8a7e3SDavid du Colombier 		return rn;
7397dd7cddfSDavid du Colombier 
74059cc4ca5SDavid du Colombier 	if((i->w & (1<<25)) == 0) {			/* OFFSET */
74159cc4ca5SDavid du Colombier 		if(i->w & (1U<<23))
7426ca8a7e3SDavid du Colombier 			return rn + (i->w & BITS(0,11));
7436ca8a7e3SDavid du Colombier 		return rn - (i->w & BITS(0,11));
74459cc4ca5SDavid du Colombier 	} else {					/* REGOFF */
74559cc4ca5SDavid du Colombier 		ulong index = 0;
74659cc4ca5SDavid du Colombier 		uchar c;
74759cc4ca5SDavid du Colombier 		uchar rm;
7487dd7cddfSDavid du Colombier 
74959cc4ca5SDavid du Colombier 		sprint(buf, "R%ld", i->w & 0xf);
75059cc4ca5SDavid du Colombier 		rm = rget(map, buf);
75159cc4ca5SDavid du Colombier 
75259cc4ca5SDavid du Colombier 		switch((i->w & BITS(5,6)) >> 5) {
75359cc4ca5SDavid du Colombier 		case 0: index = rm << ((i->w & BITS(7,11)) >> 7);	break;
75459cc4ca5SDavid du Colombier 		case 1: index = LSR(rm, ((i->w & BITS(7,11)) >> 7));	break;
75559cc4ca5SDavid du Colombier 		case 2: index = ASR(rm, ((i->w & BITS(7,11)) >> 7));	break;
7567dd7cddfSDavid du Colombier 		case 3:
75759cc4ca5SDavid du Colombier 			if((i->w & BITS(7,11)) == 0) {
75859cc4ca5SDavid du Colombier 				c = (rget(map, "PSR") >> 29) & 1;
75959cc4ca5SDavid du Colombier 				index = c << 31 | LSR(rm, 1);
76059cc4ca5SDavid du Colombier 			} else {
76159cc4ca5SDavid du Colombier 				index = ROR(rm, ((i->w & BITS(7,11)) >> 7));
76259cc4ca5SDavid du Colombier 			}
7637dd7cddfSDavid du Colombier 			break;
7647dd7cddfSDavid du Colombier 		}
76559cc4ca5SDavid du Colombier 		if(i->w & (1<<23))
76659cc4ca5SDavid du Colombier 			return rn + index;
76759cc4ca5SDavid du Colombier 		return rn - index;
7687dd7cddfSDavid du Colombier 	}
7697dd7cddfSDavid du Colombier }
7707dd7cddfSDavid du Colombier 
7714de34a7eSDavid du Colombier static uvlong
armfadd(Map * map,Rgetter rget,Instr * i,uvlong pc)7724de34a7eSDavid du Colombier armfadd(Map *map, Rgetter rget, Instr *i, uvlong pc)
7737dd7cddfSDavid du Colombier {
7747dd7cddfSDavid du Colombier 	char buf[8];
77559cc4ca5SDavid du Colombier 	int r;
7767dd7cddfSDavid du Colombier 
77759cc4ca5SDavid du Colombier 	r = (i->w >> 12) & 0xf;
77859cc4ca5SDavid du Colombier 	if(r != 15 || !armcondpass(map, rget, (i->w >> 28) & 0xf))
77959cc4ca5SDavid du Colombier 		return pc+4;
7807dd7cddfSDavid du Colombier 
78159cc4ca5SDavid du Colombier 	r = (i->w >> 16) & 0xf;
78259cc4ca5SDavid du Colombier 	sprint(buf, "R%d", r);
7837dd7cddfSDavid du Colombier 
78459cc4ca5SDavid du Colombier 	return rget(map, buf) + armshiftval(map, rget, i);
7857dd7cddfSDavid du Colombier }
78659cc4ca5SDavid du Colombier 
7874de34a7eSDavid du Colombier static uvlong
armfbx(Map * map,Rgetter rget,Instr * i,uvlong pc)788*f1b2ee28SDavid du Colombier armfbx(Map *map, Rgetter rget, Instr *i, uvlong pc)
789*f1b2ee28SDavid du Colombier {
790*f1b2ee28SDavid du Colombier 	char buf[8];
791*f1b2ee28SDavid du Colombier 	int r;
792*f1b2ee28SDavid du Colombier 
793*f1b2ee28SDavid du Colombier 	if(!armcondpass(map, rget, (i->w>>28)&0xf))
794*f1b2ee28SDavid du Colombier 		return pc+4;
795*f1b2ee28SDavid du Colombier 	r = (i->w >> 0) & 0xf;
796*f1b2ee28SDavid du Colombier 	sprint(buf, "R%d", r);
797*f1b2ee28SDavid du Colombier 	return rget(map, buf);
798*f1b2ee28SDavid du Colombier }
799*f1b2ee28SDavid du Colombier 
800*f1b2ee28SDavid du Colombier static uvlong
armfmovm(Map * map,Rgetter rget,Instr * i,uvlong pc)8014de34a7eSDavid du Colombier armfmovm(Map *map, Rgetter rget, Instr *i, uvlong pc)
80259cc4ca5SDavid du Colombier {
80359cc4ca5SDavid du Colombier 	ulong v;
80459cc4ca5SDavid du Colombier 	ulong addr;
80559cc4ca5SDavid du Colombier 
80659cc4ca5SDavid du Colombier 	v = i->w & 1<<15;
80759cc4ca5SDavid du Colombier 	if(!v || !armcondpass(map, rget, (i->w>>28)&0xf))
80859cc4ca5SDavid du Colombier 		return pc+4;
80959cc4ca5SDavid du Colombier 
81059cc4ca5SDavid du Colombier 	addr = armmaddr(map, rget, i) + nbits(i->w & BITS(0,15));
8114de34a7eSDavid du Colombier 	if(get4(map, addr, &v) < 0) {
81259cc4ca5SDavid du Colombier 		werrstr("can't read addr: %r");
81359cc4ca5SDavid du Colombier 		return -1;
81459cc4ca5SDavid du Colombier 	}
81559cc4ca5SDavid du Colombier 	return v;
81659cc4ca5SDavid du Colombier }
81759cc4ca5SDavid du Colombier 
8184de34a7eSDavid du Colombier static uvlong
armfbranch(Map * map,Rgetter rget,Instr * i,uvlong pc)8194de34a7eSDavid du Colombier armfbranch(Map *map, Rgetter rget, Instr *i, uvlong pc)
82059cc4ca5SDavid du Colombier {
82159cc4ca5SDavid du Colombier 	if(!armcondpass(map, rget, (i->w >> 28) & 0xf))
82259cc4ca5SDavid du Colombier 		return pc+4;
82359cc4ca5SDavid du Colombier 
82459cc4ca5SDavid du Colombier 	return pc + (((signed long)i->w << 8) >> 6) + 8;
82559cc4ca5SDavid du Colombier }
82659cc4ca5SDavid du Colombier 
8274de34a7eSDavid du Colombier static uvlong
armfmov(Map * map,Rgetter rget,Instr * i,uvlong pc)8284de34a7eSDavid du Colombier armfmov(Map *map, Rgetter rget, Instr *i, uvlong pc)
82959cc4ca5SDavid du Colombier {
8304de34a7eSDavid du Colombier 	ulong rd, v;
83159cc4ca5SDavid du Colombier 
83259cc4ca5SDavid du Colombier 	rd = (i->w >> 12) & 0xf;
83359cc4ca5SDavid du Colombier 	if(rd != 15 || !armcondpass(map, rget, (i->w>>28)&0xf))
83459cc4ca5SDavid du Colombier 		return pc+4;
83559cc4ca5SDavid du Colombier 
83659cc4ca5SDavid du Colombier 	 /* LDR */
83759cc4ca5SDavid du Colombier 	/* BUG: Needs LDH/B, too */
838b85a8364SDavid du Colombier 	if(((i->w>>26)&0x3) == 1) {
8394de34a7eSDavid du Colombier 		if(get4(map, armaddr(map, rget, i), &v) < 0) {
84059cc4ca5SDavid du Colombier 			werrstr("can't read instruction: %r");
84159cc4ca5SDavid du Colombier 			return pc+4;
84259cc4ca5SDavid du Colombier 		}
84359cc4ca5SDavid du Colombier 		return v;
84459cc4ca5SDavid du Colombier 	}
84559cc4ca5SDavid du Colombier 
84659cc4ca5SDavid du Colombier 	 /* MOV */
84759cc4ca5SDavid du Colombier 	v = armshiftval(map, rget, i);
84859cc4ca5SDavid du Colombier 
84959cc4ca5SDavid du Colombier 	return v;
8507dd7cddfSDavid du Colombier }
8517dd7cddfSDavid du Colombier 
8527dd7cddfSDavid du Colombier static Opcode opcodes[] =
8537dd7cddfSDavid du Colombier {
85459cc4ca5SDavid du Colombier 	"AND%C%S",	armdps, 0,	"R%s,R%n,R%d",
85559cc4ca5SDavid du Colombier 	"EOR%C%S",	armdps, 0,	"R%s,R%n,R%d",
85659cc4ca5SDavid du Colombier 	"SUB%C%S",	armdps, 0,	"R%s,R%n,R%d",
85759cc4ca5SDavid du Colombier 	"RSB%C%S",	armdps, 0,	"R%s,R%n,R%d",
85859cc4ca5SDavid du Colombier 	"ADD%C%S",	armdps, armfadd,	"R%s,R%n,R%d",
85959cc4ca5SDavid du Colombier 	"ADC%C%S",	armdps, 0,	"R%s,R%n,R%d",
86059cc4ca5SDavid du Colombier 	"SBC%C%S",	armdps, 0,	"R%s,R%n,R%d",
86159cc4ca5SDavid du Colombier 	"RSC%C%S",	armdps, 0,	"R%s,R%n,R%d",
86259cc4ca5SDavid du Colombier 	"TST%C%S",	armdps, 0,	"R%s,R%n",
86359cc4ca5SDavid du Colombier 	"TEQ%C%S",	armdps, 0,	"R%s,R%n",
86459cc4ca5SDavid du Colombier 	"CMP%C%S",	armdps, 0,	"R%s,R%n",
86559cc4ca5SDavid du Colombier 	"CMN%C%S",	armdps, 0,	"R%s,R%n",
86659cc4ca5SDavid du Colombier 	"ORR%C%S",	armdps, 0,	"R%s,R%n,R%d",
86759cc4ca5SDavid du Colombier 	"MOVW%C%S",	armdps, armfmov,	"R%s,R%d",
86859cc4ca5SDavid du Colombier 	"BIC%C%S",	armdps, 0,	"R%s,R%n,R%d",
86959cc4ca5SDavid du Colombier 	"MVN%C%S",	armdps, 0,	"R%s,R%d",
8707dd7cddfSDavid du Colombier 
87159cc4ca5SDavid du Colombier /* 16 */
87259cc4ca5SDavid du Colombier 	"AND%C%S",	armdps, 0,	"(R%s%h%m),R%n,R%d",
87359cc4ca5SDavid du Colombier 	"EOR%C%S",	armdps, 0,	"(R%s%h%m),R%n,R%d",
87459cc4ca5SDavid du Colombier 	"SUB%C%S",	armdps, 0,	"(R%s%h%m),R%n,R%d",
87559cc4ca5SDavid du Colombier 	"RSB%C%S",	armdps, 0,	"(R%s%h%m),R%n,R%d",
87659cc4ca5SDavid du Colombier 	"ADD%C%S",	armdps, armfadd,	"(R%s%h%m),R%n,R%d",
87759cc4ca5SDavid du Colombier 	"ADC%C%S",	armdps, 0,	"(R%s%h%m),R%n,R%d",
87859cc4ca5SDavid du Colombier 	"SBC%C%S",	armdps, 0,	"(R%s%h%m),R%n,R%d",
87959cc4ca5SDavid du Colombier 	"RSC%C%S",	armdps, 0,	"(R%s%h%m),R%n,R%d",
88059cc4ca5SDavid du Colombier 	"TST%C%S",	armdps, 0,	"(R%s%h%m),R%n",
88159cc4ca5SDavid du Colombier 	"TEQ%C%S",	armdps, 0,	"(R%s%h%m),R%n",
88259cc4ca5SDavid du Colombier 	"CMP%C%S",	armdps, 0,	"(R%s%h%m),R%n",
88359cc4ca5SDavid du Colombier 	"CMN%C%S",	armdps, 0,	"(R%s%h%m),R%n",
88459cc4ca5SDavid du Colombier 	"ORR%C%S",	armdps, 0,	"(R%s%h%m),R%n,R%d",
88559cc4ca5SDavid du Colombier 	"MOVW%C%S",	armdps, armfmov,	"(R%s%h%m),R%d",
88659cc4ca5SDavid du Colombier 	"BIC%C%S",	armdps, 0,	"(R%s%h%m),R%n,R%d",
88759cc4ca5SDavid du Colombier 	"MVN%C%S",	armdps, 0,	"(R%s%h%m),R%d",
8887dd7cddfSDavid du Colombier 
88959cc4ca5SDavid du Colombier /* 32 */
89059cc4ca5SDavid du Colombier 	"AND%C%S",	armdps, 0,	"(R%s%hR%M),R%n,R%d",
89159cc4ca5SDavid du Colombier 	"EOR%C%S",	armdps, 0,	"(R%s%hR%M),R%n,R%d",
89259cc4ca5SDavid du Colombier 	"SUB%C%S",	armdps, 0,	"(R%s%hR%M),R%n,R%d",
89359cc4ca5SDavid du Colombier 	"RSB%C%S",	armdps, 0,	"(R%s%hR%M),R%n,R%d",
89459cc4ca5SDavid du Colombier 	"ADD%C%S",	armdps, armfadd,	"(R%s%hR%M),R%n,R%d",
89559cc4ca5SDavid du Colombier 	"ADC%C%S",	armdps, 0,	"(R%s%hR%M),R%n,R%d",
89659cc4ca5SDavid du Colombier 	"SBC%C%S",	armdps, 0,	"(R%s%hR%M),R%n,R%d",
89759cc4ca5SDavid du Colombier 	"RSC%C%S",	armdps, 0,	"(R%s%hR%M),R%n,R%d",
89859cc4ca5SDavid du Colombier 	"TST%C%S",	armdps, 0,	"(R%s%hR%M),R%n",
89959cc4ca5SDavid du Colombier 	"TEQ%C%S",	armdps, 0,	"(R%s%hR%M),R%n",
90059cc4ca5SDavid du Colombier 	"CMP%C%S",	armdps, 0,	"(R%s%hR%M),R%n",
90159cc4ca5SDavid du Colombier 	"CMN%C%S",	armdps, 0,	"(R%s%hR%M),R%n",
90259cc4ca5SDavid du Colombier 	"ORR%C%S",	armdps, 0,	"(R%s%hR%M),R%n,R%d",
90359cc4ca5SDavid du Colombier 	"MOVW%C%S",	armdps, armfmov,	"(R%s%hR%M),R%d",
90459cc4ca5SDavid du Colombier 	"BIC%C%S",	armdps, 0,	"(R%s%hR%M),R%n,R%d",
90559cc4ca5SDavid du Colombier 	"MVN%C%S",	armdps, 0,	"(R%s%hR%M),R%d",
9067dd7cddfSDavid du Colombier 
90759cc4ca5SDavid du Colombier /* 48 */
90859cc4ca5SDavid du Colombier 	"AND%C%S",	armdpi, 0,	"$#%i,R%n,R%d",
90959cc4ca5SDavid du Colombier 	"EOR%C%S",	armdpi, 0,	"$#%i,R%n,R%d",
91059cc4ca5SDavid du Colombier 	"SUB%C%S",	armdpi, 0,	"$#%i,R%n,R%d",
91159cc4ca5SDavid du Colombier 	"RSB%C%S",	armdpi, 0,	"$#%i,R%n,R%d",
91259cc4ca5SDavid du Colombier 	"ADD%C%S",	armdpi, armfadd,	"$#%i,R%n,R%d",
91359cc4ca5SDavid du Colombier 	"ADC%C%S",	armdpi, 0,	"$#%i,R%n,R%d",
91459cc4ca5SDavid du Colombier 	"SBC%C%S",	armdpi, 0,	"$#%i,R%n,R%d",
91559cc4ca5SDavid du Colombier 	"RSC%C%S",	armdpi, 0,	"$#%i,R%n,R%d",
91659cc4ca5SDavid du Colombier 	"TST%C%S",	armdpi, 0,	"$#%i,R%n",
91759cc4ca5SDavid du Colombier 	"TEQ%C%S",	armdpi, 0,	"$#%i,R%n",
91859cc4ca5SDavid du Colombier 	"CMP%C%S",	armdpi, 0,	"$#%i,R%n",
91959cc4ca5SDavid du Colombier 	"CMN%C%S",	armdpi, 0,	"$#%i,R%n",
92059cc4ca5SDavid du Colombier 	"ORR%C%S",	armdpi, 0,	"$#%i,R%n,R%d",
92159cc4ca5SDavid du Colombier 	"MOVW%C%S",	armdpi, armfmov,	"$#%i,R%d",
92259cc4ca5SDavid du Colombier 	"BIC%C%S",	armdpi, 0,	"$#%i,R%n,R%d",
92359cc4ca5SDavid du Colombier 	"MVN%C%S",	armdpi, 0,	"$#%i,R%d",
9247dd7cddfSDavid du Colombier 
92559cc4ca5SDavid du Colombier /* 48+16 */
92680ee5cbfSDavid du Colombier 	"MUL%C%S",	armdpi, 0,	"R%M,R%s,R%n",
92780ee5cbfSDavid du Colombier 	"MULA%C%S",	armdpi, 0,	"R%M,R%s,R%n,R%d",
92859cc4ca5SDavid du Colombier 	"SWPW",		armdpi, 0,	"R%s,(R%n),R%d",
92959cc4ca5SDavid du Colombier 	"SWPB",		armdpi, 0,	"R%s,(R%n),R%d",
9307dd7cddfSDavid du Colombier 
93159cc4ca5SDavid du Colombier /* 48+16+4 */
93259cc4ca5SDavid du Colombier 	"MOV%u%C%p",	armhwby, 0,	"R%d,(R%n%UR%M)",
93359cc4ca5SDavid du Colombier 	"MOV%u%C%p",	armhwby, 0,	"R%d,%I",
93459cc4ca5SDavid du Colombier 	"MOV%u%C%p",	armhwby, armfmov,	"(R%n%UR%M),R%d",
93559cc4ca5SDavid du Colombier 	"MOV%u%C%p",	armhwby, armfmov,	"%I,R%d",
9367dd7cddfSDavid du Colombier 
93759cc4ca5SDavid du Colombier /* 48+24 */
93859cc4ca5SDavid du Colombier 	"MOVW%C%p",	armsdti, 0,	"R%d,%I",
93959cc4ca5SDavid du Colombier 	"MOVB%C%p",	armsdti, 0,	"R%d,%I",
94059cc4ca5SDavid du Colombier 	"MOVW%C%p",	armsdti, armfmov,	"%I,R%d",
94159cc4ca5SDavid du Colombier 	"MOVBU%C%p",	armsdti, armfmov,	"%I,R%d",
9427dd7cddfSDavid du Colombier 
94359cc4ca5SDavid du Colombier 	"MOVW%C%p",	armsdts, 0,	"R%d,(R%s%h%m)(R%n)",
94459cc4ca5SDavid du Colombier 	"MOVB%C%p",	armsdts, 0,	"R%d,(R%s%h%m)(R%n)",
94559cc4ca5SDavid du Colombier 	"MOVW%C%p",	armsdts, armfmov,	"(R%s%h%m)(R%n),R%d",
94659cc4ca5SDavid du Colombier 	"MOVBU%C%p",	armsdts, armfmov,	"(R%s%h%m)(R%n),R%d",
9477dd7cddfSDavid du Colombier 
94859cc4ca5SDavid du Colombier 	"MOVM%C%P%a",	armbdt, armfmovm,		"[%r],(R%n)",
94959cc4ca5SDavid du Colombier 	"MOVM%C%P%a",	armbdt, armfmovm,		"(R%n),[%r]",
9507dd7cddfSDavid du Colombier 
95159cc4ca5SDavid du Colombier 	"B%C",		armb, armfbranch,		"%b",
95259cc4ca5SDavid du Colombier 	"BL%C",		armb, armfbranch,		"%b",
9537dd7cddfSDavid du Colombier 
95459cc4ca5SDavid du Colombier 	"CDP%C",	armco, 0,		"",
95559cc4ca5SDavid du Colombier 	"CDP%C",	armco, 0,		"",
95659cc4ca5SDavid du Colombier 	"MCR%C",	armco, 0,		"",
95759cc4ca5SDavid du Colombier 	"MRC%C",	armco, 0,		"",
95859cc4ca5SDavid du Colombier 
95980ee5cbfSDavid du Colombier /* 48+24+4+4+2+2+4 */
96080ee5cbfSDavid du Colombier 	"MULLU%C%S",	armdpi, 0,	"R%M,R%s,(R%n,R%d)",
96180ee5cbfSDavid du Colombier 	"MULALU%C%S",	armdpi, 0,	"R%M,R%s,(R%n,R%d)",
96280ee5cbfSDavid du Colombier 	"MULL%C%S",	armdpi, 0,	"R%M,R%s,(R%n,R%d)",
96380ee5cbfSDavid du Colombier 	"MULAL%C%S",	armdpi, 0,	"R%M,R%s,(R%n,R%d)",
96480ee5cbfSDavid du Colombier 
9654f4ac6b1SDavid du Colombier /* 48+24+4+4+2+2+4+4 = 92 */
96659cc4ca5SDavid du Colombier 	"UNK",		armunk, 0,	"",
9674f4ac6b1SDavid du Colombier 
9686ca8a7e3SDavid du Colombier 	/* new v7 arch instructions */
9694f4ac6b1SDavid du Colombier /* 93 */
9704f4ac6b1SDavid du Colombier 	"LDREX",	armdpi, 0,	"(R%n),R%d",
9714f4ac6b1SDavid du Colombier 	"STREX",	armdpi, 0,	"R%s,(R%n),R%d",
9724f4ac6b1SDavid du Colombier 	"CLREX",	armunk, 0,	"",
9734f4ac6b1SDavid du Colombier 
9744f4ac6b1SDavid du Colombier /* 96 */
9754f4ac6b1SDavid du Colombier 	"DSB",		armunk, 0,	"",
9764f4ac6b1SDavid du Colombier 	"DMB",		armunk, 0,	"",
9774f4ac6b1SDavid du Colombier 	"ISB",		armunk, 0,	"",
9786ca8a7e3SDavid du Colombier 
9796ca8a7e3SDavid du Colombier /* 99 */
9806ca8a7e3SDavid du Colombier 	"RFEV7%P%a",	armbdt, 0,	"(R%n)",
9819b7bf7dfSDavid du Colombier 
9829b7bf7dfSDavid du Colombier /* 100 */
9839b7bf7dfSDavid du Colombier 	"MLA%f%C",	armdps,	0,	"F%s,F%n,F%d",
9849b7bf7dfSDavid du Colombier 	"MLS%f%C",	armdps,	0,	"F%s,F%n,F%d",
9859b7bf7dfSDavid du Colombier 	"NMLS%f%C",	armdps,	0,	"F%s,F%n,F%d",
9869b7bf7dfSDavid du Colombier 	"NMLA%f%C",	armdps,	0,	"F%s,F%n,F%d",
9879b7bf7dfSDavid du Colombier 	"MUL%f%C",	armdps,	0,	"F%s,F%n,F%d",
9889b7bf7dfSDavid du Colombier 	"NMUL%f%C",	armdps,	0,	"F%s,F%n,F%d",
9899b7bf7dfSDavid du Colombier 	"ADD%f%C",	armdps,	0,	"F%s,F%n,F%d",
9909b7bf7dfSDavid du Colombier 	"SUB%f%C",	armdps,	0,	"F%s,F%n,F%d",
9919b7bf7dfSDavid du Colombier 	"DIV%f%C",	armdps,	0,	"F%s,F%n,F%d",
9929b7bf7dfSDavid du Colombier 
9939b7bf7dfSDavid du Colombier /* 109 */
9949b7bf7dfSDavid du Colombier 	"MOV%f%C",	armdps,	0,	"F%s,F%d",
9959b7bf7dfSDavid du Colombier 	"ABS%f%C",	armdps,	0,	"F%s,F%d",
9969b7bf7dfSDavid du Colombier 	"NEG%f%C",	armdps,	0,	"F%s,F%d",
9979b7bf7dfSDavid du Colombier 	"SQRT%f%C",	armdps,	0,	"F%s,F%d",
9989b7bf7dfSDavid du Colombier 	"CMP%f%C",	armdps,	0,	"F%s,F%d",
9999b7bf7dfSDavid du Colombier 	"CMPE%f%C",	armdps,	0,	"F%s,F%d",
10009b7bf7dfSDavid du Colombier 	"CMP%f%C",	armdps,	0,	"$0.0,F%d",
10019b7bf7dfSDavid du Colombier 	"CMPE%f%C",	armdps,	0,	"$0.0,F%d",
10029b7bf7dfSDavid du Colombier 
10039b7bf7dfSDavid du Colombier /* 117 */
10049b7bf7dfSDavid du Colombier 	"MOV%F%R%C",	armdps, 0,	"F%s,F%d",
10059b7bf7dfSDavid du Colombier 
10069b7bf7dfSDavid du Colombier /* 118 */
10079b7bf7dfSDavid du Colombier 	"MOVW%C",	armdps, 0,	"R%d,F%n",
10089b7bf7dfSDavid du Colombier 	"MOVW%C",	armdps, 0,	"F%n,R%d",
10099b7bf7dfSDavid du Colombier 	"MOVW%C",	armdps, 0,	"R%d,%x",
10109b7bf7dfSDavid du Colombier 	"MOVW%C",	armdps, 0,	"%x,R%d",
10119b7bf7dfSDavid du Colombier 
10129b7bf7dfSDavid du Colombier /* 122 */
10139b7bf7dfSDavid du Colombier 	"MOV%f%C",	armvstdi,	0,	"F%d,%I",
10149b7bf7dfSDavid du Colombier 	"MOV%f%C",	armvstdi,	0,	"%I,F%d",
1015*f1b2ee28SDavid du Colombier 
1016*f1b2ee28SDavid du Colombier /* 124 */
1017*f1b2ee28SDavid du Colombier 	"BKPT%C",	armbpt,	0,		"$#%i",
1018*f1b2ee28SDavid du Colombier 	"BX%C",		armdps,	armfbx,	"(R%s)",
1019*f1b2ee28SDavid du Colombier 	"BXJ%C",	armdps,	armfbx,	"(R%s)",
1020*f1b2ee28SDavid du Colombier 	"BLX%C",	armdps,	armfbx,	"(R%s)",
10217dd7cddfSDavid du Colombier };
10227dd7cddfSDavid du Colombier 
102359cc4ca5SDavid du Colombier static void
gaddr(Instr * i)102459cc4ca5SDavid du Colombier gaddr(Instr *i)
102559cc4ca5SDavid du Colombier {
102659cc4ca5SDavid du Colombier 	*i->curr++ = '$';
102759cc4ca5SDavid du Colombier 	i->curr += gsymoff(i->curr, i->end-i->curr, i->imm, CANY);
102859cc4ca5SDavid du Colombier }
102959cc4ca5SDavid du Colombier 
10307dd7cddfSDavid du Colombier static	char *mode[] = { 0, "IA", "DB", "IB" };
10317dd7cddfSDavid du Colombier static	char *pw[] = { "P", "PW", 0, "W" };
10327dd7cddfSDavid du Colombier static	char *sw[] = { 0, "W", "S", "SW" };
10337dd7cddfSDavid du Colombier 
10347dd7cddfSDavid du Colombier static void
format(char * mnemonic,Instr * i,char * f)10357dd7cddfSDavid du Colombier format(char *mnemonic, Instr *i, char *f)
10367dd7cddfSDavid du Colombier {
10377dd7cddfSDavid du Colombier 	int j, k, m, n;
103859cc4ca5SDavid du Colombier 	int g;
103959cc4ca5SDavid du Colombier 	char *fmt;
10407dd7cddfSDavid du Colombier 
10417dd7cddfSDavid du Colombier 	if(mnemonic)
10427dd7cddfSDavid du Colombier 		format(0, i, mnemonic);
10437dd7cddfSDavid du Colombier 	if(f == 0)
10447dd7cddfSDavid du Colombier 		return;
10457dd7cddfSDavid du Colombier 	if(mnemonic)
10467dd7cddfSDavid du Colombier 		if(i->curr < i->end)
10477dd7cddfSDavid du Colombier 			*i->curr++ = '\t';
10487dd7cddfSDavid du Colombier 	for ( ; *f && i->curr < i->end; f++) {
10497dd7cddfSDavid du Colombier 		if(*f != '%') {
10507dd7cddfSDavid du Colombier 			*i->curr++ = *f;
10517dd7cddfSDavid du Colombier 			continue;
10527dd7cddfSDavid du Colombier 		}
10537dd7cddfSDavid du Colombier 		switch (*++f) {
10547dd7cddfSDavid du Colombier 
10557dd7cddfSDavid du Colombier 		case 'C':	/* .CONDITION */
10567dd7cddfSDavid du Colombier 			if(cond[i->cond])
10577dd7cddfSDavid du Colombier 				bprint(i, ".%s", cond[i->cond]);
10587dd7cddfSDavid du Colombier 			break;
10597dd7cddfSDavid du Colombier 
10607dd7cddfSDavid du Colombier 		case 'S':	/* .STORE */
10617dd7cddfSDavid du Colombier 			if(i->store)
10627dd7cddfSDavid du Colombier 				bprint(i, ".S");
10637dd7cddfSDavid du Colombier 			break;
10647dd7cddfSDavid du Colombier 
10657dd7cddfSDavid du Colombier 		case 'P':	/* P & U bits for block move */
10667dd7cddfSDavid du Colombier 			n = (i->w >>23) & 0x3;
10677dd7cddfSDavid du Colombier 			if (mode[n])
10687dd7cddfSDavid du Colombier 				bprint(i, ".%s", mode[n]);
10697dd7cddfSDavid du Colombier 			break;
10707dd7cddfSDavid du Colombier 
10717dd7cddfSDavid du Colombier 		case 'p':	/* P & W bits for single data xfer*/
10727dd7cddfSDavid du Colombier 			if (pw[i->store])
10737dd7cddfSDavid du Colombier 				bprint(i, ".%s", pw[i->store]);
10747dd7cddfSDavid du Colombier 			break;
10757dd7cddfSDavid du Colombier 
10767dd7cddfSDavid du Colombier 		case 'a':	/* S & W bits for single data xfer*/
10777dd7cddfSDavid du Colombier 			if (sw[i->store])
10787dd7cddfSDavid du Colombier 				bprint(i, ".%s", sw[i->store]);
10797dd7cddfSDavid du Colombier 			break;
10807dd7cddfSDavid du Colombier 
10817dd7cddfSDavid du Colombier 		case 's':
10827dd7cddfSDavid du Colombier 			bprint(i, "%d", i->rs & 0xf);
10837dd7cddfSDavid du Colombier 			break;
10847dd7cddfSDavid du Colombier 
108559cc4ca5SDavid du Colombier 		case 'M':
10861bd28109SDavid du Colombier 			bprint(i, "%lud", (i->w>>8) & 0xf);
108759cc4ca5SDavid du Colombier 			break;
108859cc4ca5SDavid du Colombier 
10897dd7cddfSDavid du Colombier 		case 'm':
10901bd28109SDavid du Colombier 			bprint(i, "%lud", (i->w>>7) & 0x1f);
10917dd7cddfSDavid du Colombier 			break;
10927dd7cddfSDavid du Colombier 
10937dd7cddfSDavid du Colombier 		case 'h':
109459cc4ca5SDavid du Colombier 			bprint(i, shtype[(i->w>>5) & 0x3]);
109559cc4ca5SDavid du Colombier 			break;
109659cc4ca5SDavid du Colombier 
109759cc4ca5SDavid du Colombier 		case 'u':		/* Signed/unsigned Byte/Halfword */
109859cc4ca5SDavid du Colombier 			bprint(i, hb[(i->w>>5) & 0x3]);
109959cc4ca5SDavid du Colombier 			break;
110059cc4ca5SDavid du Colombier 
110159cc4ca5SDavid du Colombier 		case 'I':
110259cc4ca5SDavid du Colombier 			if (i->rn == 13) {
110359cc4ca5SDavid du Colombier 				if (plocal(i))
110459cc4ca5SDavid du Colombier 					break;
110559cc4ca5SDavid du Colombier 			}
110659cc4ca5SDavid du Colombier 			g = 0;
110759cc4ca5SDavid du Colombier 			fmt = "#%lx(R%d)";
110859cc4ca5SDavid du Colombier 			if (i->rn == 15) {
110959cc4ca5SDavid du Colombier 				/* convert load of offset(PC) to a load immediate */
11104de34a7eSDavid du Colombier 				if (get4(i->map, i->addr+i->imm+8, (ulong*)&i->imm) > 0)
111159cc4ca5SDavid du Colombier 				{
111259cc4ca5SDavid du Colombier 					g = 1;
111359cc4ca5SDavid du Colombier 					fmt = "";
111459cc4ca5SDavid du Colombier 				}
111559cc4ca5SDavid du Colombier 			}
111659cc4ca5SDavid du Colombier 			if (mach->sb)
111759cc4ca5SDavid du Colombier 			{
111859cc4ca5SDavid du Colombier 				if (i->rd == 11) {
111959cc4ca5SDavid du Colombier 					ulong nxti;
112059cc4ca5SDavid du Colombier 
11214de34a7eSDavid du Colombier 					if (get4(i->map, i->addr+4, &nxti) > 0) {
112259cc4ca5SDavid du Colombier 						if ((nxti & 0x0e0f0fff) == 0x060c000b) {
112359cc4ca5SDavid du Colombier 							i->imm += mach->sb;
112459cc4ca5SDavid du Colombier 							g = 1;
112559cc4ca5SDavid du Colombier 							fmt = "-SB";
112659cc4ca5SDavid du Colombier 						}
112759cc4ca5SDavid du Colombier 					}
112859cc4ca5SDavid du Colombier 				}
112959cc4ca5SDavid du Colombier 				if (i->rn == 12)
113059cc4ca5SDavid du Colombier 				{
113159cc4ca5SDavid du Colombier 					i->imm += mach->sb;
113259cc4ca5SDavid du Colombier 					g = 1;
113359cc4ca5SDavid du Colombier 					fmt = "-SB(SB)";
113459cc4ca5SDavid du Colombier 				}
113559cc4ca5SDavid du Colombier 			}
113659cc4ca5SDavid du Colombier 			if (g)
113759cc4ca5SDavid du Colombier 			{
113859cc4ca5SDavid du Colombier 				gaddr(i);
113959cc4ca5SDavid du Colombier 				bprint(i, fmt, i->rn);
114059cc4ca5SDavid du Colombier 			}
114159cc4ca5SDavid du Colombier 			else
114259cc4ca5SDavid du Colombier 				bprint(i, fmt, i->imm, i->rn);
114359cc4ca5SDavid du Colombier 			break;
114459cc4ca5SDavid du Colombier 		case 'U':		/* Add/subtract from base */
114559cc4ca5SDavid du Colombier 			bprint(i, addsub[(i->w >> 23) & 1]);
11467dd7cddfSDavid du Colombier 			break;
11477dd7cddfSDavid du Colombier 
11487dd7cddfSDavid du Colombier 		case 'n':
11497dd7cddfSDavid du Colombier 			bprint(i, "%d", i->rn);
11507dd7cddfSDavid du Colombier 			break;
11517dd7cddfSDavid du Colombier 
11527dd7cddfSDavid du Colombier 		case 'd':
11537dd7cddfSDavid du Colombier 			bprint(i, "%d", i->rd);
11547dd7cddfSDavid du Colombier 			break;
11557dd7cddfSDavid du Colombier 
11567dd7cddfSDavid du Colombier 		case 'i':
11577dd7cddfSDavid du Colombier 			bprint(i, "%lux", i->imm);
11587dd7cddfSDavid du Colombier 			break;
11597dd7cddfSDavid du Colombier 
11607dd7cddfSDavid du Colombier 		case 'b':
11617dd7cddfSDavid du Colombier 			i->curr += symoff(i->curr, i->end-i->curr,
116248207d97SDavid du Colombier 				(ulong)i->imm, CTEXT);
116359cc4ca5SDavid du Colombier 			break;
116459cc4ca5SDavid du Colombier 
116559cc4ca5SDavid du Colombier 		case 'g':
116659cc4ca5SDavid du Colombier 			i->curr += gsymoff(i->curr, i->end-i->curr,
11677dd7cddfSDavid du Colombier 				i->imm, CANY);
11687dd7cddfSDavid du Colombier 			break;
11697dd7cddfSDavid du Colombier 
11709b7bf7dfSDavid du Colombier 		case 'f':
11719b7bf7dfSDavid du Colombier 			switch((i->w >> 8) & 0xF){
11729b7bf7dfSDavid du Colombier 			case 10:
11739b7bf7dfSDavid du Colombier 				bprint(i, "F");
11749b7bf7dfSDavid du Colombier 				break;
11759b7bf7dfSDavid du Colombier 			case 11:
11769b7bf7dfSDavid du Colombier 				bprint(i, "D");
11779b7bf7dfSDavid du Colombier 				break;
11789b7bf7dfSDavid du Colombier 			}
11799b7bf7dfSDavid du Colombier 			break;
11809b7bf7dfSDavid du Colombier 
11819b7bf7dfSDavid du Colombier 		case 'F':
11829b7bf7dfSDavid du Colombier 			switch(((i->w >> 15) & 0xE) + ((i->w >> 8) & 0x1)){
11839b7bf7dfSDavid du Colombier 			case 0x0:
11849b7bf7dfSDavid du Colombier 				bprint(i, ((i->w >> 7) & 0x1)? "WF" : "WF.U");
11859b7bf7dfSDavid du Colombier 				break;
11869b7bf7dfSDavid du Colombier 			case 0x1:
11879b7bf7dfSDavid du Colombier 				bprint(i, ((i->w >> 7) & 0x1)? "WD" : "WD.U");
11889b7bf7dfSDavid du Colombier 				break;
11899b7bf7dfSDavid du Colombier 			case 0x8:
11909b7bf7dfSDavid du Colombier 				bprint(i, "FW.U");
11919b7bf7dfSDavid du Colombier 				break;
11929b7bf7dfSDavid du Colombier 			case 0x9:
11939b7bf7dfSDavid du Colombier 				bprint(i, "DW.U");
11949b7bf7dfSDavid du Colombier 				break;
11959b7bf7dfSDavid du Colombier 			case 0xA:
11969b7bf7dfSDavid du Colombier 				bprint(i, "FW");
11979b7bf7dfSDavid du Colombier 				break;
11989b7bf7dfSDavid du Colombier 			case 0xB:
11999b7bf7dfSDavid du Colombier 				bprint(i, "DW");
12009b7bf7dfSDavid du Colombier 				break;
12019b7bf7dfSDavid du Colombier 			case 0xE:
12029b7bf7dfSDavid du Colombier 				bprint(i, "FD");
12039b7bf7dfSDavid du Colombier 				break;
12049b7bf7dfSDavid du Colombier 			case 0xF:
12059b7bf7dfSDavid du Colombier 				bprint(i, "DF");
12069b7bf7dfSDavid du Colombier 				break;
12079b7bf7dfSDavid du Colombier 			}
12089b7bf7dfSDavid du Colombier 			break;
12099b7bf7dfSDavid du Colombier 
12109b7bf7dfSDavid du Colombier 		case 'R':
12119b7bf7dfSDavid du Colombier 			if(((i->w >> 7) & 0x1) == 0)
12129b7bf7dfSDavid du Colombier 				bprint(i, "R");
12139b7bf7dfSDavid du Colombier 			break;
12149b7bf7dfSDavid du Colombier 
12159b7bf7dfSDavid du Colombier 		case 'x':
12169b7bf7dfSDavid du Colombier 			switch(i->rn){
12179b7bf7dfSDavid du Colombier 			case 0:
12189b7bf7dfSDavid du Colombier 				bprint(i, "FPSID");
12199b7bf7dfSDavid du Colombier 				break;
12209b7bf7dfSDavid du Colombier 			case 1:
12219b7bf7dfSDavid du Colombier 				bprint(i, "FPSCR");
12229b7bf7dfSDavid du Colombier 				break;
12239b7bf7dfSDavid du Colombier 			case 2:
12249b7bf7dfSDavid du Colombier 				bprint(i, "FPEXC");
12259b7bf7dfSDavid du Colombier 				break;
12269b7bf7dfSDavid du Colombier 			default:
12279b7bf7dfSDavid du Colombier 				bprint(i, "FPS(%d)", i->rn);
12289b7bf7dfSDavid du Colombier 				break;
12299b7bf7dfSDavid du Colombier 			}
12309b7bf7dfSDavid du Colombier 			break;
12319b7bf7dfSDavid du Colombier 
12327dd7cddfSDavid du Colombier 		case 'r':
12337dd7cddfSDavid du Colombier 			n = i->imm&0xffff;
12347dd7cddfSDavid du Colombier 			j = 0;
12357dd7cddfSDavid du Colombier 			k = 0;
12367dd7cddfSDavid du Colombier 			while(n) {
12377dd7cddfSDavid du Colombier 				m = j;
12387dd7cddfSDavid du Colombier 				while(n&0x1) {
12397dd7cddfSDavid du Colombier 					j++;
12407dd7cddfSDavid du Colombier 					n >>= 1;
12417dd7cddfSDavid du Colombier 				}
12427dd7cddfSDavid du Colombier 				if(j != m) {
12437dd7cddfSDavid du Colombier 					if(k)
12447dd7cddfSDavid du Colombier 						bprint(i, ",");
12457dd7cddfSDavid du Colombier 					if(j == m+1)
12467dd7cddfSDavid du Colombier 						bprint(i, "R%d", m);
12477dd7cddfSDavid du Colombier 					else
12487dd7cddfSDavid du Colombier 						bprint(i, "R%d-R%d", m, j-1);
12497dd7cddfSDavid du Colombier 					k = 1;
12507dd7cddfSDavid du Colombier 				}
12517dd7cddfSDavid du Colombier 				j++;
12527dd7cddfSDavid du Colombier 				n >>= 1;
12537dd7cddfSDavid du Colombier 			}
12547dd7cddfSDavid du Colombier 			break;
12557dd7cddfSDavid du Colombier 
12567dd7cddfSDavid du Colombier 		case '\0':
12577dd7cddfSDavid du Colombier 			*i->curr++ = '%';
12587dd7cddfSDavid du Colombier 			return;
12597dd7cddfSDavid du Colombier 
12607dd7cddfSDavid du Colombier 		default:
12617dd7cddfSDavid du Colombier 			bprint(i, "%%%c", *f);
12627dd7cddfSDavid du Colombier 			break;
12637dd7cddfSDavid du Colombier 		}
12647dd7cddfSDavid du Colombier 	}
12657dd7cddfSDavid du Colombier 	*i->curr = 0;
12667dd7cddfSDavid du Colombier }
12677dd7cddfSDavid du Colombier 
12687dd7cddfSDavid du Colombier static int
printins(Map * map,uvlong pc,char * buf,int n)12694de34a7eSDavid du Colombier printins(Map *map, uvlong pc, char *buf, int n)
12707dd7cddfSDavid du Colombier {
12717dd7cddfSDavid du Colombier 	Instr i;
12727dd7cddfSDavid du Colombier 
12737dd7cddfSDavid du Colombier 	i.curr = buf;
12747dd7cddfSDavid du Colombier 	i.end = buf+n-1;
12757dd7cddfSDavid du Colombier 	if(decode(map, pc, &i) < 0)
12767dd7cddfSDavid du Colombier 		return -1;
12777dd7cddfSDavid du Colombier 
127859cc4ca5SDavid du Colombier 	(*opcodes[i.op].fmt)(&opcodes[i.op], &i);
12797dd7cddfSDavid du Colombier 	return 4;
12807dd7cddfSDavid du Colombier }
12817dd7cddfSDavid du Colombier 
12827dd7cddfSDavid du Colombier static int
arminst(Map * map,uvlong pc,char modifier,char * buf,int n)12834de34a7eSDavid du Colombier arminst(Map *map, uvlong pc, char modifier, char *buf, int n)
12847dd7cddfSDavid du Colombier {
128559cc4ca5SDavid du Colombier 	USED(modifier);
12867dd7cddfSDavid du Colombier 	return printins(map, pc, buf, n);
12877dd7cddfSDavid du Colombier }
12887dd7cddfSDavid du Colombier 
12897dd7cddfSDavid du Colombier static int
armdas(Map * map,uvlong pc,char * buf,int n)12904de34a7eSDavid du Colombier armdas(Map *map, uvlong pc, char *buf, int n)
12917dd7cddfSDavid du Colombier {
12927dd7cddfSDavid du Colombier 	Instr i;
12937dd7cddfSDavid du Colombier 
12947dd7cddfSDavid du Colombier 	i.curr = buf;
12957dd7cddfSDavid du Colombier 	i.end = buf+n;
12967dd7cddfSDavid du Colombier 	if(decode(map, pc, &i) < 0)
12977dd7cddfSDavid du Colombier 		return -1;
12987dd7cddfSDavid du Colombier 	if(i.end-i.curr > 8)
12997dd7cddfSDavid du Colombier 		i.curr = _hexify(buf, i.w, 7);
13007dd7cddfSDavid du Colombier 	*i.curr = 0;
13017dd7cddfSDavid du Colombier 	return 4;
13027dd7cddfSDavid du Colombier }
13037dd7cddfSDavid du Colombier 
13047dd7cddfSDavid du Colombier static int
arminstlen(Map * map,uvlong pc)13054de34a7eSDavid du Colombier arminstlen(Map *map, uvlong pc)
13067dd7cddfSDavid du Colombier {
13077dd7cddfSDavid du Colombier 	Instr i;
13087dd7cddfSDavid du Colombier 
13097dd7cddfSDavid du Colombier 	if(decode(map, pc, &i) < 0)
13107dd7cddfSDavid du Colombier 		return -1;
13117dd7cddfSDavid du Colombier 	return 4;
13127dd7cddfSDavid du Colombier }
13137dd7cddfSDavid du Colombier 
13147dd7cddfSDavid du Colombier static int
armfoll(Map * map,uvlong pc,Rgetter rget,uvlong * foll)13154de34a7eSDavid du Colombier armfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
13167dd7cddfSDavid du Colombier {
13174de34a7eSDavid du Colombier 	uvlong d;
13187dd7cddfSDavid du Colombier 	Instr i;
13197dd7cddfSDavid du Colombier 
13207dd7cddfSDavid du Colombier 	if(decode(map, pc, &i) < 0)
13217dd7cddfSDavid du Colombier 		return -1;
13227dd7cddfSDavid du Colombier 
132359cc4ca5SDavid du Colombier 	if(opcodes[i.op].foll) {
132459cc4ca5SDavid du Colombier 		d = (*opcodes[i.op].foll)(map, rget, &i, pc);
132559cc4ca5SDavid du Colombier 		if(d == -1)
132659cc4ca5SDavid du Colombier 			return -1;
13277dd7cddfSDavid du Colombier 	} else
132859cc4ca5SDavid du Colombier 		d = pc+4;
132959cc4ca5SDavid du Colombier 
133059cc4ca5SDavid du Colombier 	foll[0] = d;
13317dd7cddfSDavid du Colombier 	return 1;
13327dd7cddfSDavid du Colombier }
1333