xref: /plan9/sys/src/libmach/68020db.c (revision 473d4f4b3fed09ca133e03643ec71c9150b33bcc)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5 
6 /*
7  * 68020-specific debugger interface
8  */
9 
10 static	char	*m68020excep(Map*, Rgetter);
11 
12 static	int	m68020foll(Map*, uvlong, Rgetter, uvlong*);
13 static	int	m68020inst(Map*, uvlong, char, char*, int);
14 static	int	m68020das(Map*, uvlong, char*, int);
15 static	int	m68020instlen(Map*, uvlong);
16 
17 Machdata m68020mach =
18 {
19 	{0x48,0x48,0,0},	/* break point #0 instr. */
20 	2,			/* size of break point instr. */
21 
22 	beswab,			/* convert short to local byte order */
23 	beswal,			/* convert long to local byte order */
24 	beswav,			/* convert vlong to local byte order */
25 	cisctrace,		/* C traceback */
26 	ciscframe,		/* frame finder */
27 	m68020excep,		/* print exception */
28 	0,			/* breakpoint fixup */
29 	beieeesftos,
30 	beieeedftos,
31 	m68020foll,		/* follow-set calculation */
32 	m68020inst,		/* print instruction */
33 	m68020das,		/* dissembler */
34 	m68020instlen,		/* instruction size */
35 };
36 
37 /*
38  * 68020 exception frames
39  */
40 
41 #define BPTTRAP	4		/* breakpoint gives illegal inst */
42 
43 static char * excep[] = {
44 	[2]	"bus error",
45 	[3]	"address error",
46 	[4]	"illegal instruction",
47 	[5]	"zero divide",
48 	[6]	"CHK",
49 	[7]	"TRAP",
50 	[8]	"privilege violation",
51 	[9]	"Trace",
52 	[10]	"line 1010",
53 	[11]	"line 1011",
54 	[13]	"coprocessor protocol violation",
55 	[24]	"spurious",
56 	[25]	"incon",
57 	[26]	"tac",
58 	[27]	"auto 3",
59 	[28]	"clock",
60 	[29]	"auto 5",
61 	[30]	"parity",
62 	[31]	"mouse",
63 	[32]	"system call",
64 	[33]	"system call 1",
65 	[48]	"FPCP branch",
66 	[49]	"FPCP inexact",
67 	[50]	"FPCP zero div",
68 	[51]	"FPCP underflow",
69 	[52]	"FPCP operand err",
70 	[53]	"FPCP overflow",
71 	[54]	"FPCP signal NAN",
72 };
73 
74 static int m68020vec;
75 static
76 struct ftype{
77 	short	fmt;
78 	short	len;
79 	char	*name;
80 } ftype[] = {		/* section 6.5.7 page 6-24 */
81 	{  0,  4*2, "Short Format" },
82 	{  1,  4*2, "Throwaway" },
83 	{  2,  6*2, "Instruction Exception" },
84 	{  3,  6*2, "MC68040 Floating Point Exception" },
85 	{  8, 29*2, "MC68010 Bus Fault" },
86 	{  7, 30*2, "MC68040 Bus Fault" },
87 	{  9, 10*2, "Coprocessor mid-Instruction" },
88 	{ 10, 16*2, "MC68020 Short Bus Fault" },
89 	{ 11, 46*2, "MC68020 Long Bus Fault" },
90 	{  0,    0, 0 }
91 };
92 
93 static int
m68020ufix(Map * map)94 m68020ufix(Map *map)
95 {
96 	struct ftype *ft;
97 	int i, size, vec;
98 	ulong efl[2];
99 	uchar *ef=(uchar*)efl;
100 	ulong l;
101 	uvlong stktop;
102 	short fvo;
103 
104 		/* The kernel proc pointer on a 68020 is always
105 		 * at #8xxxxxxx; on the 68040 NeXT, the address
106 		 * is always #04xxxxxx.  the sun3 port at sydney
107 		 * uses 0xf8xxxxxx to 0xffxxxxxx.
108 		 */
109 	m68020vec = 0;
110 
111 	if (get4(map, mach->kbase, (&l)) < 0)
112 		return -1;
113 	if ((l&0xfc000000) == 0x04000000)	/* if NeXT */
114 		size = 30*2;
115 	else
116 		size = 46*2;			/* 68020 */
117 	USED(size);
118 
119 	stktop = mach->kbase+mach->pgsize;
120 	for(i=3; i<100; i++){
121 		if (get1(map, stktop-i*4, (uchar*)&l, 4)< 0)
122 			return -1;
123 
124 		if(machdata->swal(l) == 0xBADC0C0A){
125 			if (get1(map, stktop-(i-1)*4, (uchar *)&efl[0], 4) < 0)
126 				return -1;
127 			if (get1(map, stktop-(i-2)*4, (uchar *)&efl[1], 4) < 0)
128 				return -1;
129 			fvo = (ef[6]<<8)|ef[7];
130 			vec = fvo & 0xfff;
131 			vec >>= 2;
132 			if(vec >= 256)
133 				continue;
134 
135 			for(ft=ftype; ft->name; ft++) {
136 				if(ft->fmt == ((fvo>>12) & 0xF)){
137 					m68020vec = vec;
138 					return 1;
139 				}
140 			}
141 			break;
142 		}
143 	}
144 	return -1;
145 }
146 
147 static char *
m68020excep(Map * map,Rgetter rget)148 m68020excep(Map *map, Rgetter rget)
149 {
150 	uvlong pc;
151 	uchar buf[4];
152 
153 	if (m68020ufix(map) < 0)
154 		return "bad exception frame";
155 
156 	if(excep[m68020vec] == 0)
157 		return "bad exeception type";
158 
159 	if(m68020vec == BPTTRAP) {
160 		pc = (*rget)(map, "PC");
161 		if (get1(map, pc, buf, machdata->bpsize) > 0)
162 		if(memcmp(buf, machdata->bpinst, machdata->bpsize) == 0)
163 			return "breakpoint";
164 	}
165 	return excep[m68020vec];
166 }
167 	/* 68020 Disassembler and related functions */
168 /*
169 not supported: cpBcc, cpDBcc, cpGEN, cpScc, cpTRAPcc, cpRESTORE, cpSAVE
170 
171 opcode:					1 1 1 1 1 1
172 					5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
173 %y - register number						  x x x
174 %f - trap vector						  x x x
175 %e - destination eff addr				    x x x x x x
176 %p - conditional predicate				    x x x x x x
177 %s - size code						x x
178 %C - cache code						x x
179 %E - source eff addr.				x x x x x x
180 %d - direction bit				      x
181 %c - condition code				x x x x
182 %x - register number				x x x
183 %b - shift count				x x x
184 %q - daffy 3-bit quick operand or shift count	x x x
185 %i - immediate operand <varies>
186 %t - offset(PC) <varies>
187 
188 word 1:					1 1 1 1 1 1
189 					5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
190 %a - register number						  x x x
191 %w - bit field width					      x x x x x
192 %L - MMU function code (SFC/DFC/D%a/#[0-3])		      x x x x x
193 %P - conditional predicate				    x x x x x x
194 %k - k factor						  x x x x x x x
195 %m - register mask					x x x x x x x x
196 %N - control register id			x x x x x x x x x x x x
197 %j - (Dq != Dr) ? Dq:Dr : Dr		  x x x			  x x x
198 %K - dynamic k register					  x x x
199 %h - register number					x x x
200 %I - MMU function code mask			      x x x x
201 %o - bit field offset				  x x x x x
202 %u - register number				      x x x
203 %D - float dest reg				    x x x
204 %F - (fdr==fsr) ? "F%D" :"F%B,F%D" 	   x x x x x x
205 %S - float source type			      x x x
206 %B - float source register		      x x x
207 %Z - ATC level number			      x x x
208 %H - MMU register			    x x x x
209 %r - register type/number		x x x x
210 
211 word 2:					1 1 1 1 1 1
212 					5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
213 %A - register number						  x x x
214 %U - register number				      x x x
215 %R - register type,number		x x x x
216 
217 -----------------------------------------------------------------------------
218 
219 %a	-	register [word 1: 0-2]
220 %c	-	condition code [opcode: 8-11]
221 %d	-	direction [opcode: 8]
222 %e	-	destination effective address [opcode: 0-5]
223 %f	-	trap vector [opcode: 0-3]
224 %h	-	register [word 1: 5-7]
225 %i	-	immediate operand (1, 2, or 4 bytes)
226 %j	-	Dq:Dr if Dq != Dr; else Dr => Dr [word 1: 0-2] Dq [word 1: 12-14]
227 %k	-	k factor [word 1: 0-6]
228 %m	-	register mask [word 1: 0-7]
229 %o	-	bit field offset [word 1: 6-10]
230 %p	-	conditional predicate [opcode: 0-5]
231 %q	-	daffy 3-bit quick operand [opcode: 9-11]
232 %r	-	register type, [word 1: 15], register [word 1: 12-14]
233 %s	-	size [opcode: 6-7]
234 %t	-	offset beyond pc (text address) (2 or 4 bytes)
235 %u	-	register [word 1: 6-8]
236 %w	-	bit field width [word 1: 0-4]
237 %x	-	register [opcode: 9-11]
238 %y	-	register [opcode: 0-2]
239 %A	-	register [word 2: 0-2]
240 %B	-	float source register [word 1: 10-12]
241 %C	-	cache identifier [opcode: 6-7] (IC, DC, or BC)
242 %D	-	float dest reg [word 1: 7-9]
243 %E	-	dest effective address [opcode: 6-11]
244 %F	-	float dest reg == float src reg => "F%D"; else "F%B,F%D"
245 %H	-	MMU reg [word 1: 10-13] (see above & p 4-53/54)
246 %I	-	MMU function code mask [word 1: 5-8]
247 %K	-	dynamic k factor register [word 1: 4-6]
248 %L	-	MMU function code [word 1: 0-4] (SFC, DFC, D%a, or #[0-3])
249 %N	-	control register [word 1: 0-11]
250 %P	-	conditional predicate [word 1: 0-5]
251 %R	-	register type, [word 2: 15], register [word 2: 12-14]
252 %S	-	float source type code [word 1: 10-12]
253 %U	-	register [word 2: 6-8]
254 %Z	-	ATC level number [word 1: 10-12]
255 %1	-	Special case: EA as second operand
256 */
257 	/* Operand classes */
258 enum {
259 	EAPI = 1,	/* extended address: pre decrement only */
260 	EACA,		/* extended address: control alterable */
261 	EACAD,		/* extended address: control alterable or Dreg */
262 	EACAPI,		/* extended address: control alterable or post-incr */
263 	EACAPD,		/* extended address: control alterable or pre-decr */
264 	EAMA,		/* extended address: memory alterable */
265 	EADA,		/* extended address: data alterable */
266 	EAA,		/* extended address: alterable */
267 	EAC,		/* extended address: control addressing */
268 	EACPI,		/* extended address: control addressing or post-incr */
269 	EACD,		/* extended address: control addressing or Dreg */
270 	EAD,		/* extended address: data addressing */
271 	EAM,		/* extended address: memory addressing */
272 	EAM_B,		/* EAM with byte immediate data */
273 	EADI,		/* extended address: data addressing or immediate */
274 	EADI_L,		/* EADI with long immediate data */
275 	EADI_W,		/* EADI with word immediate data */
276 	EAALL,		/* extended address: all modes */
277 	EAALL_L,	/* EAALL with long immediate data */
278 	EAALL_W,	/* EAALL with word immediate data */
279 	EAALL_B,	/* EAALL with byte immediate date */
280 		/* special codes not directly used for validation */
281 	EAFLT,		/* extended address: EADI for B, W, L, or S; else EAM */
282 	EADDA,		/* destination extended address: EADA */
283 	BREAC,		/* EAC operand for JMP or CALL */
284 	OP8,		/* low 8 bits of op word */
285 	I8,		/* low 8-bits of first extension word */
286 	I16,		/* 16 bits in first extension word */
287 	I32,		/* 32 bits in first and second extension words */
288 	IV,		/* 8, 16 or 32 bit data in first & 2nd extension words */
289 	C16,		/* CAS2 16 bit immediate with bits 9-11 & 3-5 zero */
290 	BR8,		/* 8 bits in op word or 16 or 32 bits in extension words
291 				branch instruction format (p. 2-25) */
292 	BR16,		/* 16-bit branch displacement */
293 	BR32,		/* 32-bit branch displacement */
294 	STACK,		/* return PC on stack - follow set only */
295 };
296 		/* validation bit masks for various EA classes */
297 enum {
298 	Dn	= 0x0001,	/* Data register */
299 	An	= 0x0002,	/* Address register */
300 	Ind	= 0x0004,	/* Address register indirect */
301 	Pinc	= 0x0008,	/* Address register indirect post-increment */
302 	Pdec	= 0x0010,	/* Address register indirect pre-decrement */
303 	Bdisp	= 0x0020,	/* Base/Displacement in all its forms */
304 	PCrel	= 0x0040,	/* PC relative addressing in all its forms */
305 	Imm	= 0x0080,	/* Immediate data */
306 	Abs	= 0x0100,	/* Absolute */
307 };
308 	/* EA validation table indexed by operand class number */
309 
310 static	short	validea[] =
311 {
312 	0,						/* none */
313 	Pdec,						/* EAPI */
314 	Abs|Bdisp|Ind,					/* EACA */
315 	Abs|Bdisp|Ind|Dn,				/* EACAD */
316 	Abs|Bdisp|Pinc|Ind,				/* EACAPI */
317 	Abs|Bdisp|Pdec|Ind,				/* EACAPD */
318 	Abs|Bdisp|Pdec|Pinc|Ind,			/* EAMA */
319 	Abs|Bdisp|Pdec|Pinc|Ind|Dn,			/* EADA */
320 	Abs|Bdisp|Pdec|Pinc|Ind|An|Dn,			/* EAA */
321 	Abs|PCrel|Bdisp|Ind,				/* EAC */
322 	Abs|PCrel|Bdisp|Pinc|Ind,			/* EACPI */
323 	Abs|PCrel|Bdisp|Ind|Dn,				/* EACD */
324 	Abs|PCrel|Bdisp|Pdec|Pinc|Ind|Dn,		/* EAD */
325 	Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind,		/* EAM */
326 	Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind,		/* EAM_B */
327 	Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|Dn,		/* EADI */
328 	Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|Dn,		/* EADI_L */
329 	Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|Dn,		/* EADI_W */
330 	Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|An|Dn,	/* EAALL */
331 	Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|An|Dn,	/* EAALL_L */
332 	Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|An|Dn,	/* EAALL_W */
333 	Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|An|Dn,	/* EAALL_B */
334 };
335 	/* EA types */
336 enum
337 {
338 	Dreg,		/* Dn */
339 	Areg,		/* An */
340 	AInd,		/* (An) */
341 	APdec,		/* -(An) */
342 	APinc,		/* (An)+ */
343 	ADisp,		/* Displacement beyond (An) */
344 	BXD,		/* Base, Index, Displacement */
345 	PDisp,		/* Displacement beyond PC */
346 	PXD,		/* PC, Index, Displacement */
347 	ABS,		/* absolute */
348 	IMM,		/* immediate */
349 	IREAL,		/* single precision real immediate */
350 	IEXT,		/* extended precision real immediate */
351 	IPACK,		/* packed real immediate */
352 	IDBL,		/* double precision real immediate */
353 };
354 
355 typedef	struct optable	Optable;
356 typedef	struct operand	Operand;
357 typedef	struct inst	Inst;
358 
359 struct optable
360 {
361 	ushort	opcode;
362 	ushort	mask0;
363 	ushort	op2;
364 	ushort	mask1;
365 	char	opdata[2];
366 	char	*format;
367 };
368 
369 struct	operand
370 {
371 	int	eatype;
372 	short	ext;
373 	union {
374 		long	immediate;	/* sign-extended integer byte/word/long */
375 		struct	{		/* index mode displacements */
376 			long	disp;
377 			long	outer;
378 		};
379 		char	floater[24];	/* floating point immediates */
380 	};
381 };
382 
383 struct	inst
384 {
385 	int	n;		/* # bytes in instruction */
386 	uvlong	addr;		/* addr of start of instruction */
387 	ushort	raw[4+12];	/* longest instruction: 24 byte packed immediate */
388 	Operand	and[2];
389 	char	*end;		/* end of print buffer */
390 	char	*curr;		/* current fill point in buffer */
391 	char	*errmsg;
392 };
393 	/* class 0: bit field, MOVEP & immediate instructions */
394 static Optable t0[] = {
395 { 0x003c, 0xffff, 0x0000, 0xff00, {I8},		"ORB	%i,CCR" },
396 { 0x007c, 0xffff, 0x0000, 0x0000, {I16},	"ORW	%i,SR" },
397 { 0x023c, 0xffff, 0x0000, 0xff00, {I8},		"ANDB	%i,CCR" },
398 { 0x027c, 0xffff, 0x0000, 0x0000, {I16},	"ANDW	%i,SR" },
399 { 0x0a3c, 0xffff, 0x0000, 0xff00, {I8},		"EORB	%i,CCR" },
400 { 0x0a7c, 0xffff, 0x0000, 0x0000, {I16},	"EORW	%i,SR" },
401 { 0x0cfc, 0xffff, 0x0000, 0x0000, {C16,C16},	"CAS2W	R%a:R%A,R%u:R%U,(%r):(%R)"} ,
402 { 0x0efc, 0xffff, 0x0000, 0x0000, {C16,C16},	"CAS2L	R%a:R%A,R%u:R%U,(%r):(%R)"} ,
403 
404 { 0x06c0, 0xfff8, 0x0000, 0x0000, {0},		"RTM	R%y" },
405 { 0x06c8, 0xfff8, 0x0000, 0x0000, {0},		"RTM	A%y" },
406 { 0x0800, 0xfff8, 0x0000, 0x0000, {I16},	"BTSTL	%i,R%y" },
407 { 0x0840, 0xfff8, 0x0000, 0x0000, {I16},	"BCHGL	%i,R%y" },
408 { 0x0880, 0xfff8, 0x0000, 0x0000, {I16},	"BCLRL	%i,R%y" },
409 
410 { 0x00c0, 0xffc0, 0x0000, 0x0fff, {EAC},	"CMP2B	%e,%r" },
411 { 0x00c0, 0xffc0, 0x0800, 0x0fff, {EAC},	"CHK2B	%e,%r" },
412 { 0x02c0, 0xffc0, 0x0000, 0x0fff, {EAC},	"CMP2W	%e,%r" },
413 { 0x02c0, 0xffc0, 0x0800, 0x0fff, {EAC},	"CHK2W	%e,%r" },
414 { 0x04c0, 0xffc0, 0x0000, 0x0fff, {EAC},	"CMP2L	%e,%r" },
415 { 0x04c0, 0xffc0, 0x0800, 0x0fff, {EAC},	"CHK2L	%e,%r" },
416 { 0x06c0, 0xffc0, 0x0000, 0x0000, {I16, BREAC},	"CALLM	%i,%e" },
417 { 0x0800, 0xffc0, 0x0000, 0x0000, {I16, EAD},	"BTSTB	%i,%e" },
418 { 0x0840, 0xffc0, 0x0000, 0x0000, {I16, EADA},	"BCHG	%i,%e" },
419 { 0x0880, 0xffc0, 0x0000, 0x0000, {I16, EADA},	"BCLR	%i,%e" },
420 { 0x08c0, 0xffc0, 0x0000, 0x0000, {I16, EADA},	"BSET	%i,%e" },
421 { 0x0ac0, 0xffc0, 0x0000, 0xfe38, {EAMA},	"CASB	R%a,R%u,%e" },
422 { 0x0cc0, 0xffc0, 0x0000, 0xfe38, {EAMA},	"CASW	R%a,R%u,%e" },
423 { 0x0ec0, 0xffc0, 0x0000, 0xfe38, {EAMA},	"CASL	R%a,R%u,%e" },
424 
425 { 0x0000, 0xff00, 0x0000, 0x0000, {IV, EADA},	"OR%s	%i,%e" },
426 { 0x0200, 0xff00, 0x0000, 0x0000, {IV, EADA},	"AND%s	%i,%e" },
427 { 0x0400, 0xff00, 0x0000, 0x0000, {IV, EADA},	"SUB%s	%i,%e" },
428 { 0x0600, 0xff00, 0x0000, 0x0000, {IV, EADA},	"ADD%s	%i,%e" },
429 { 0x0a00, 0xff00, 0x0000, 0x0000, {IV, EADA},	"EOR%s	%i,%e" },
430 { 0x0c00, 0xff00, 0x0000, 0x0000, {IV, EAD},	"CMP%s	%i,%e" },
431 { 0x0e00, 0xff00, 0x0000, 0x0800, {EAMA},	"MOVES%s	%e,%r" },
432 { 0x0e00, 0xff00, 0x0800, 0x0800, {EAMA},	"MOVES%s	%r,%e" },
433 
434 { 0x0108, 0xf1f8, 0x0000, 0x0000, {I16},	"MOVEPW	(%i,A%y),R%x" },
435 { 0x0148, 0xf1f8, 0x0000, 0x0000, {I16},	"MOVEPL	(%i,A%y),R%x" },
436 { 0x0188, 0xf1f8, 0x0000, 0x0000, {I16},	"MOVEPW	R%x,(%i,A%y)" },
437 { 0x01c8, 0xf1f8, 0x0000, 0x0000, {I16},	"MOVEPL	R%x,(%i,A%y)" },
438 { 0x0100, 0xf1f8, 0x0000, 0x0000, {0},		"BTSTL	R%x,R%y" },
439 { 0x0140, 0xf1f8, 0x0000, 0x0000, {0},		"BCHGL	R%x,R%y" },
440 { 0x0180, 0xf1f8, 0x0000, 0x0000, {0},		"BCLRL	R%x,R%y" },
441 { 0x01c0, 0xf1f8, 0x0000, 0x0000, {0},		"BSET	R%x,R%y" },
442 
443 { 0x0100, 0xf1c0, 0x0000, 0x0000, {EAM_B},	"BTSTB	R%x,%e" },
444 { 0x0140, 0xf1c0, 0x0000, 0x0000, {EAMA},	"BCHG	R%x,%e" },
445 { 0x0180, 0xf1c0, 0x0000, 0x0000, {EAMA},	"BCLR	R%x,%e" },
446 { 0x01c0, 0xf1c0, 0x0000, 0x0000, {EAMA},	"BSET	R%x,%e" },
447 { 0,0,0,0,{0},0 },
448 };
449 	/* class 1: move byte */
450 static Optable t1[] = {
451 { 0x1000, 0xf000, 0x0000, 0x0000, {EAALL_B,EADDA},"MOVB	%e,%E" },
452 { 0,0,0,0,{0},0 },
453 };
454 	/* class 2: move long */
455 static Optable t2[] = {
456 { 0x2040, 0xf1c0, 0x0000, 0x0000, {EAALL_L},	  "MOVL	%e,A%x" },
457 
458 { 0x2000, 0xf000, 0x0000, 0x0000, {EAALL_L,EADDA},"MOVL	%e,%E" },
459 { 0,0,0,0,{0},0 },
460 };
461 	/* class 3: move word */
462 static Optable t3[] = {
463 { 0x3040, 0xf1c0, 0x0000, 0x0000, {EAALL_W},	  "MOVW	%e,A%x" },
464 
465 { 0x3000, 0xf000, 0x0000, 0x0000, {EAALL_W,EADDA},"MOVW	%e,%E" },
466 { 0,0,0,0,{0},0 },
467 };
468 	/* class 4: miscellaneous */
469 static Optable t4[] = {
470 { 0x4e75, 0xffff, 0x0000, 0x0000, {STACK},	"RTS" },
471 { 0x4e77, 0xffff, 0x0000, 0x0000, {STACK},	"RTR" },
472 { 0x4afc, 0xffff, 0x0000, 0x0000, {0},		"ILLEGAL" },
473 { 0x4e71, 0xffff, 0x0000, 0x0000, {0},		"NOP" },
474 { 0x4e74, 0xffff, 0x0000, 0x0000, {I16, STACK},	"RTD	%i" },
475 { 0x4e76, 0xffff, 0x0000, 0x0000, {0},		"TRAPV" },
476 { 0x4e70, 0xffff, 0x0000, 0x0000, {0},		"RESET" },
477 { 0x4e72, 0xffff, 0x0000, 0x0000, {I16},	"STOP	%i" },
478 { 0x4e73, 0xffff, 0x0000, 0x0000, {0},		"RTE" },
479 { 0x4e7a, 0xffff, 0x0000, 0x0000, {I16},	"MOVEL	%N,%r" },
480 { 0x4e7b, 0xffff, 0x0000, 0x0000, {I16},	"MOVEL	%r,%N" },
481 
482 { 0x4808, 0xfff8, 0x0000, 0x0000, {I32},	"LINKL	A%y,%i" },
483 { 0x4840, 0xfff8, 0x0000, 0x0000, {0},		"SWAPW	R%y" },
484 { 0x4848, 0xfff8, 0x0000, 0x0000, {0},		"BKPT	#%y" },
485 { 0x4880, 0xfff8, 0x0000, 0x0000, {0},		"EXTW	R%y" },
486 { 0x48C0, 0xfff8, 0x0000, 0x0000, {0},		"EXTL	R%y" },
487 { 0x49C0, 0xfff8, 0x0000, 0x0000, {0},		"EXTBL	R%y" },
488 { 0x4e50, 0xfff8, 0x0000, 0x0000, {I16},	"LINKW	A%y,%i" },
489 { 0x4e58, 0xfff8, 0x0000, 0x0000, {0},		"UNLK	A%y" },
490 { 0x4e60, 0xfff8, 0x0000, 0x0000, {0},		"MOVEL	(A%y),USP" },
491 { 0x4e68, 0xfff8, 0x0000, 0x0000, {0},		"MOVEL	USP,(A%y)" },
492 
493 { 0x4e40, 0xfff0, 0x0000, 0x0000, {0},		"SYS	%f" },
494 
495 { 0x40c0, 0xffc0, 0x0000, 0x0000, {EADA},	"MOVW	SR,%e" },
496 { 0x42c0, 0xffc0, 0x0000, 0x0000, {EADA},	"MOVW	CCR,%e" },
497 { 0x44c0, 0xffc0, 0x0000, 0x0000, {EADI_W},	"MOVW	%e,CCR" },
498 { 0x46c0, 0xffc0, 0x0000, 0x0000, {EADI_W},	"MOVW	%e,SR" },
499 { 0x4800, 0xffc0, 0x0000, 0x0000, {EADA},	"NBCDB	%e" },
500 { 0x4840, 0xffc0, 0x0000, 0x0000, {EAC},	"PEA	%e" },
501 { 0x4880, 0xffc0, 0x0000, 0x0000, {I16, EACAPD},"MOVEMW	%i,%e" },
502 { 0x48c0, 0xffc0, 0x0000, 0x0000, {I16, EACAPD},"MOVEML	%i,%e" },
503 { 0x4ac0, 0xffc0, 0x0000, 0x0000, {EADA},	"TAS	%e" },
504 { 0x4a00, 0xffc0, 0x0000, 0x0000, {EAD},	"TSTB	%e" },
505 { 0x4c00, 0xffc0, 0x0000, 0x8ff8, {EADI_L},	"MULUL	%e,%r" },
506 { 0x4c00, 0xffc0, 0x0400, 0x8ff8, {EADI_L},	"MULUL	%e,R%a:%r" },
507 { 0x4c00, 0xffc0, 0x0800, 0x8ff8, {EADI_L},	"MULSL	%e,%r" },
508 { 0x4c00, 0xffc0, 0x0c00, 0x8ff8, {EADI_L},	"MULSL	%e,R%a:%r" },
509 { 0x4c40, 0xffc0, 0x0000, 0x8ff8, {EADI_L},	"DIVUL	%e,%j" },
510 { 0x4c40, 0xffc0, 0x0400, 0x8ff8, {EADI_L},	"DIVUD	%e,%r:R%a" },
511 { 0x4c40, 0xffc0, 0x0800, 0x8ff8, {EADI_L},	"DIVSL	%e,%j" },
512 { 0x4c40, 0xffc0, 0x0c00, 0x8ff8, {EADI_L},	"DIVSD	%e,%r:R%a" },
513 { 0x4c80, 0xffc0, 0x0000, 0x0000, {I16, EACPI}, "MOVEMW	%1,%i" },
514 { 0x4cc0, 0xffc0, 0x0000, 0x0000, {I16, EACPI}, "MOVEML	%1,%i" },
515 { 0x4e80, 0xffc0, 0x0000, 0x0000, {BREAC},	"JSR	%e" },
516 { 0x4ec0, 0xffc0, 0x0000, 0x0000, {BREAC},	"JMP	%e" },
517 
518 { 0x4000, 0xff00, 0x0000, 0x0000, {EADA},	"NEGX%s	%e" },
519 { 0x4200, 0xff00, 0x0000, 0x0000, {EADA},	"CLR%s	%e" },
520 { 0x4400, 0xff00, 0x0000, 0x0000, {EADA},	"NEG%s	%e" },
521 { 0x4600, 0xff00, 0x0000, 0x0000, {EADA},	"NOT%s	%e" },
522 { 0x4a00, 0xff00, 0x0000, 0x0000, {EAALL},	"TST%s	%e" },
523 
524 { 0x4180, 0xf1c0, 0x0000, 0x0000, {EADI_W},	"CHKW	%e,R%x" },
525 { 0x41c0, 0xf1c0, 0x0000, 0x0000, {EAC},	"LEA	%e,A%x" },
526 { 0x4100, 0xf1c0, 0x0000, 0x0000, {EADI_L},	"CHKL	%e,R%x" },
527 { 0,0,0,0,{0},0 },
528 };
529 	/* class 5:  miscellaneous quick, branch & trap instructions */
530 static Optable t5[] = {
531 { 0x5000, 0xf1c0, 0x0000, 0x0000, {EADA},	"ADDB	$Q#%q,%e" },
532 { 0x5100, 0xf1c0, 0x0000, 0x0000, {EADA},	"SUBB	$Q#%q,%e" },
533 
534 { 0x50c8, 0xf1f8, 0x0000, 0x0000, {BR16},	"DB%c	R%y,%t" },
535 { 0x51c8, 0xf1f8, 0x0000, 0x0000, {BR16},	"DB%c	R%y,%t" },
536 
537 { 0x5000, 0xf1c0, 0x0000, 0x0000, {EAA},	"ADDB	$Q#%q,%e" },
538 { 0x5040, 0xf1c0, 0x0000, 0x0000, {EAA},	"ADDW	$Q#%q,%e" },
539 { 0x5080, 0xf1c0, 0x0000, 0x0000, {EAA},	"ADDL	$Q#%q,%e" },
540 { 0x5100, 0xf1c0, 0x0000, 0x0000, {EAA},	"SUBB	$Q#%q,%e" },
541 { 0x5140, 0xf1c0, 0x0000, 0x0000, {EAA},	"SUBW	$Q#%q,%e" },
542 { 0x5180, 0xf1c0, 0x0000, 0x0000, {EAA},	"SUBL	$Q#%q,%e" },
543 
544 { 0x50fa, 0xf0ff, 0x0000, 0x0000, {I16},	"TRAP%cW	%i" },
545 { 0x50fb, 0xf0ff, 0x0000, 0x0000, {I32},	"TRAP%cL	%i" },
546 { 0x50fc, 0xf0ff, 0x0000, 0x0000, {0},		"TRAP%c" },
547 
548 { 0x50c0, 0xf0c0, 0x0000, 0x0000, {EADA},	"S%c	%e" },
549 { 0,0,0,0,{0},0 },
550 };
551 	/* class 6: branch instructions */
552 static Optable t6[] = {
553 { 0x6000, 0xff00, 0x0000, 0x0000, {BR8},	"BRA	%t" },
554 { 0x6100, 0xff00, 0x0000, 0x0000, {BR8},	"BSR	%t" },
555 { 0x6000, 0xf000, 0x0000, 0x0000, {BR8},	"B%c	%t" },
556 { 0,0,0,0,{0},0 },
557 };
558 	/* class 7: move quick */
559 static Optable t7[] = {
560 { 0x7000, 0xf100, 0x0000, 0x0000, {OP8},	"MOVL	$Q%i,R%x" },
561 { 0,0,0,0,{0},0 },
562 };
563 	/* class 8: BCD operations, DIV, and OR instructions */
564 static Optable t8[] = {
565 { 0x8100, 0xf1f8, 0x0000, 0x0000, {0},		"SBCDB	R%y,R%x" },
566 { 0x8108, 0xf1f8, 0x0000, 0x0000, {0},		"SBCDB	-(A%y),-(A%x)" },
567 { 0x8140, 0xf1f8, 0x0000, 0x0000, {I16},	"PACK	R%y,R%x,%i" },
568 { 0x8148, 0xf1f8, 0x0000, 0x0000, {I16},	"PACK	-(A%y),-(A%x),%i" },
569 { 0x8180, 0xf1f8, 0x0000, 0x0000, {I16},	"UNPK	R%y,R%x,%i" },
570 { 0x8188, 0xf1f8, 0x0000, 0x0000, {I16},	"UNPK	-(A%y),-(A%x),%i" },
571 
572 { 0x80c0, 0xf1c0, 0x0000, 0x0000, {EADI_W},	"DIVUW	%e,R%x" },
573 { 0x81c0, 0xf1c0, 0x0000, 0x0000, {EADI_W},	"DIVSW	%e,R%x" },
574 
575 { 0x8000, 0xf100, 0x0000, 0x0000, {EADI},	"OR%s	%e,R%x" },
576 { 0x8100, 0xf100, 0x0000, 0x0000, {EAMA},	"OR%s	R%x,%e" },
577 { 0,0,0,0,{0},0 },
578 };
579 	/* class 9: subtract instruction */
580 static Optable t9[] = {
581 { 0x90c0, 0xf1c0, 0x0000, 0x0000, {EAALL_W},	"SUBW	%e,A%x" },
582 { 0x91c0, 0xf1c0, 0x0000, 0x0000, {EAALL_L},	"SUBL	%e,A%x" },
583 
584 { 0x9100, 0xf138, 0x0000, 0x0000, {0},		"SUBX%s	R%y,R%x" },
585 { 0x9108, 0xf138, 0x0000, 0x0000, {0},		"SUBX%s	-(A%y),-(A%x)" },
586 
587 { 0x9000, 0xf100, 0x0000, 0x0000, {EAALL},	"SUB%s	%e,R%x" },
588 { 0x9100, 0xf100, 0x0000, 0x0000, {EAMA},	"SUB%s	R%x,%e" },
589 { 0,0,0,0,{0},0 },
590 };
591 	/* class b: CMP & EOR */
592 static Optable tb[] = {
593 { 0xb000, 0xf1c0, 0x0000, 0x0000, {EADI},	"CMPB	R%x,%e" },
594 { 0xb040, 0xf1c0, 0x0000, 0x0000, {EAALL_W},	"CMPW	R%x,%e" },
595 { 0xb080, 0xf1c0, 0x0000, 0x0000, {EAALL_L},	"CMPL	R%x,%e" },
596 { 0xb0c0, 0xf1c0, 0x0000, 0x0000, {EAALL_W},	"CMPW	A%x,%e" },
597 { 0xb1c0, 0xf1c0, 0x0000, 0x0000, {EAALL_L},	"CMPL	A%x,%e" },
598 
599 { 0xb108, 0xf138, 0x0000, 0x0000, {0},		"CMP%s	(A%y)+,(A%x)+" },
600 
601 { 0xb100, 0xf100, 0x0000, 0x0000, {EADA},	"EOR%s	%e,R%x" },
602 { 0,0,0,0,{0},0 },
603 };
604 	/* class c: AND, MUL, BCD & Exchange */
605 static Optable tc[] = {
606 { 0xc100, 0xf1f8, 0x0000, 0x0000, {0},		"ABCDB	R%y,R%x" },
607 { 0xc108, 0xf1f8, 0x0000, 0x0000, {0},		"ABCDB	-(A%y),-(A%x)" },
608 { 0xc140, 0xf1f8, 0x0000, 0x0000, {0},		"EXG	R%x,R%y" },
609 { 0xc148, 0xf1f8, 0x0000, 0x0000, {0},		"EXG	A%x,A%y" },
610 { 0xc188, 0xf1f8, 0x0000, 0x0000, {0},		"EXG	R%x,A%y" },
611 
612 { 0xc0c0, 0xf1c0, 0x0000, 0x0000, {EADI_W},	"MULUW	%e,R%x" },
613 { 0xc1c0, 0xf1c0, 0x0000, 0x0000, {EADI_W},	"MULSW	%e,R%x" },
614 
615 { 0xc000, 0xf100, 0x0000, 0x0000, {EADI},	"AND%s	%e,R%x" },
616 { 0xc100, 0xf100, 0x0000, 0x0000, {EAMA},	"AND%s	R%x,%e" },
617 { 0,0,0,0,{0},0 },
618 };
619 	/* class d: addition  */
620 static Optable td[] = {
621 { 0xd000, 0xf1c0, 0x0000, 0x0000, {EADI},	"ADDB	%e,R%x" },
622 { 0xd0c0, 0xf1c0, 0x0000, 0x0000, {EAALL_W},	"ADDW	%e,A%x" },
623 { 0xd1c0, 0xf1c0, 0x0000, 0x0000, {EAALL_L},	"ADDL	%e,A%x" },
624 
625 { 0xd100, 0xf138, 0x0000, 0x0000, {0},		"ADDX%s	R%y,R%x" },
626 { 0xd108, 0xf138, 0x0000, 0x0000, {0},		"ADDX%s	-(A%y),-(A%x)" },
627 
628 { 0xd000, 0xf100, 0x0000, 0x0000, {EAALL},	"ADD%s	%e,R%x" },
629 { 0xd100, 0xf100, 0x0000, 0x0000, {EAMA},	"ADD%s	R%x,%e" },
630 { 0,0,0,0,{0},0 },
631 };
632 	/* class e: shift, rotate, bit field operations */
633 static Optable te[] = {
634 { 0xe8c0, 0xffc0, 0x0820, 0xfe38, {EACD},	"BFTST	%e{R%u:R%a}" },
635 { 0xe8c0, 0xffc0, 0x0800, 0xfe20, {EACD},	"BFTST	%e{R%u:%w}" },
636 { 0xe8c0, 0xffc0, 0x0020, 0xf838, {EACD},	"BFTST	%e{%o:R%a}" },
637 { 0xe8c0, 0xffc0, 0x0000, 0xf820, {EACD},	"BFTST	%e{%o:%w}" },
638 
639 { 0xe9c0, 0xffc0, 0x0820, 0x8e38, {EACD},	"BFEXTU	%e{R%u:R%a},%r" },
640 { 0xe9c0, 0xffc0, 0x0800, 0x8e20, {EACD},	"BFEXTU	%e{R%u:%w},%r" },
641 { 0xe9c0, 0xffc0, 0x0020, 0x8838, {EACD},	"BFEXTU	%e{%o:R%a},%r" },
642 { 0xe9c0, 0xffc0, 0x0000, 0x8820, {EACD},	"BFEXTU	%e{%o:%w},%r" },
643 
644 { 0xeac0, 0xffc0, 0x0820, 0xfe38, {EACAD},	"BFCHG	%e{R%u:R%a}" },
645 { 0xeac0, 0xffc0, 0x0800, 0xfe20, {EACAD},	"BFCHG	%e{R%u:%w}" },
646 { 0xeac0, 0xffc0, 0x0020, 0xf838, {EACAD},	"BFCHG	%e{%o:R%a}" },
647 { 0xeac0, 0xffc0, 0x0000, 0xf820, {EACAD},	"BFCHG	%e{%o:%w}" },
648 
649 { 0xebc0, 0xffc0, 0x0820, 0x8e38, {EACD},	"BFEXTS	%e{R%u:R%a},%r" },
650 { 0xebc0, 0xffc0, 0x0800, 0x8e20, {EACD},	"BFEXTS	%e{R%u:%w},%r" },
651 { 0xebc0, 0xffc0, 0x0020, 0x8838, {EACD},	"BFEXTS	%e{%o:R%a},%r" },
652 { 0xebc0, 0xffc0, 0x0000, 0x8820, {EACD},	"BFEXTS	%e{%o:%w},%r" },
653 
654 { 0xecc0, 0xffc0, 0x0820, 0xfe38, {EACAD},	"BFCLR	%e{R%u:R%a}" },
655 { 0xecc0, 0xffc0, 0x0800, 0xfe20, {EACAD},	"BFCLR	%e{R%u:%w}" },
656 { 0xecc0, 0xffc0, 0x0020, 0xf838, {EACAD},	"BFCLR	%e{%o:R%a}" },
657 { 0xecc0, 0xffc0, 0x0000, 0xf820, {EACAD},	"BFCLR	%e{%o:%w}" },
658 
659 { 0xedc0, 0xffc0, 0x0820, 0x8e38, {EACAD},	"BFFFO	%e{R%u:R%a},%r" },
660 { 0xedc0, 0xffc0, 0x0800, 0x8e20, {EACAD},	"BFFFO	%e{R%u:%w},%r" },
661 { 0xedc0, 0xffc0, 0x0020, 0x8838, {EACAD},	"BFFFO	%e{%o:R%a},%r" },
662 { 0xedc0, 0xffc0, 0x0000, 0x8820, {EACAD},	"BFFFO	%e{%o:%w},%r" },
663 
664 { 0xeec0, 0xffc0, 0x0820, 0xfe38, {EACAD},	"BFSET	%e{R%u:R%a}" },
665 { 0xeec0, 0xffc0, 0x0800, 0xfe20, {EACAD},	"BFSET	%e{R%u:%w}" },
666 { 0xeec0, 0xffc0, 0x0020, 0xf838, {EACAD},	"BFSET	%e{%o:R%a}" },
667 { 0xeec0, 0xffc0, 0x0000, 0xf820, {EACAD},	"BFSET	%e{%o:%w}" },
668 
669 { 0xefc0, 0xffc0, 0x0820, 0x8e38, {EACAD},	"BFINS	%r,%e{R%u:R%a}" },
670 { 0xefc0, 0xffc0, 0x0800, 0x8e20, {EACAD},	"BFINS	%r,%e{R%u:%w}" },
671 { 0xefc0, 0xffc0, 0x0020, 0x8838, {EACAD},	"BFINS	%r,%e{%o:R%a}" },
672 { 0xefc0, 0xffc0, 0x0000, 0x8820, {EACAD},	"BFINS	%r,%e{%o:%w}" },
673 
674 { 0xe0c0, 0xfec0, 0x0000, 0x0000, {EAMA},	"AS%dW	%e" },
675 { 0xe2c0, 0xfec0, 0x0000, 0x0000, {EAMA},	"LS%dW	%e" },
676 { 0xe4c0, 0xfec0, 0x0000, 0x0000, {EAMA},	"ROX%dW	%e" },
677 { 0xe6c0, 0xfec0, 0x0000, 0x0000, {EAMA},	"RO%dW	%e" },
678 
679 { 0xe000, 0xf038, 0x0000, 0x0000, {0},		"AS%d%s	#%q,R%y" },
680 { 0xe008, 0xf038, 0x0000, 0x0000, {0},		"LS%d%s	#%q,R%y" },
681 { 0xe010, 0xf038, 0x0000, 0x0000, {0},		"ROX%d%s	#%q,R%y" },
682 { 0xe018, 0xf038, 0x0000, 0x0000, {0},		"RO%d%s	#%q,R%y" },
683 { 0xe020, 0xf038, 0x0000, 0x0000, {0},		"AS%d%s	R%x,R%y" },
684 { 0xe028, 0xf038, 0x0000, 0x0000, {0},		"LS%d%s	R%x,R%y" },
685 { 0xe030, 0xf038, 0x0000, 0x0000, {0},		"ROX%d%s	R%x,R%y" },
686 { 0xe038, 0xf038, 0x0000, 0x0000, {0},		"RO%d%s	R%x,R%y" },
687 { 0,0,0,0,{0},0 },
688 };
689 	/* class f: coprocessor and mmu instructions */
690 static Optable tf[] = {
691 { 0xf280, 0xffff, 0x0000, 0xffff, {0},		"FNOP" },
692 { 0xf200, 0xffff, 0x5c00, 0xfc00, {0},		"FMOVECRX	%k,F%D" },
693 { 0xf27a, 0xffff, 0x0000, 0xffc0, {I16},	"FTRAP%P	%i" },
694 { 0xf27b, 0xffff, 0x0000, 0xffc0, {I32},	"FTRAP%P	%i" },
695 { 0xf27c, 0xffff, 0x0000, 0xffc0, {0},		"FTRAP%P" },
696 
697 { 0xf248, 0xfff8, 0x0000, 0xffc0, {BR16},	"FDB%P	R%y,%t" },
698 { 0xf620, 0xfff8, 0x8000, 0x8fff, {0},		"MOVE16	(A%y)+,(%r)+" },
699 { 0xf500, 0xfff8, 0x0000, 0x0000, {0},		"PFLUSHN	(A%y)" },
700 { 0xf508, 0xfff8, 0x0000, 0x0000, {0},		"PFLUSH	(A%y)" },
701 { 0xf510, 0xfff8, 0x0000, 0x0000, {0},		"PFLUSHAN" },
702 { 0xf518, 0xfff8, 0x0000, 0x0000, {0},		"PFLUSHA" },
703 { 0xf548, 0xfff8, 0x0000, 0x0000, {0},		"PTESTW	(A%y)" },
704 { 0xf568, 0xfff8, 0x0000, 0x0000, {0},		"PTESTR	(A%y)" },
705 { 0xf600, 0xfff8, 0x0000, 0x0000, {I32},	"MOVE16	(A%y)+,$%i" },
706 { 0xf608, 0xfff8, 0x0000, 0x0000, {I32},	"MOVE16	$%i,(A%y)-" },
707 { 0xf610, 0xfff8, 0x0000, 0x0000, {I32},	"MOVE16	(A%y),$%i" },
708 { 0xf618, 0xfff8, 0x0000, 0x0000, {I32},	"MOVE16	$%i,(A%y)" },
709 
710 { 0xf000, 0xffc0, 0x0800, 0xffff, {EACA},	"PMOVE	%e,TT0" },
711 { 0xf000, 0xffc0, 0x0900, 0xffff, {EACA},	"PMOVEFD	%e,TT0" },
712 { 0xf000, 0xffc0, 0x0a00, 0xffff, {EACA},	"PMOVE	TT0,%e" },
713 { 0xf000, 0xffc0, 0x0b00, 0xffff, {EACA},	"PMOVEFD	TT0,%e" },
714 { 0xf000, 0xffc0, 0x0c00, 0xffff, {EACA},	"PMOVE	%e,TT1" },
715 { 0xf000, 0xffc0, 0x0d00, 0xffff, {EACA},	"PMOVEFD	%e,TT1" },
716 { 0xf000, 0xffc0, 0x0e00, 0xffff, {EACA},	"PMOVE	TT1,%e" },
717 { 0xf000, 0xffc0, 0x0f00, 0xffff, {EACA},	"PMOVEFD	TT1,%e" },
718 { 0xf000, 0xffc0, 0x2400, 0xffff, {0},		"PFLUSHA" },
719 { 0xf000, 0xffc0, 0x2800, 0xffff, {EACA},	"PVALID	VAL,%e" },
720 { 0xf000, 0xffc0, 0x6000, 0xffff, {EACA},	"PMOVE	%e,MMUSR" },
721 { 0xf000, 0xffc0, 0x6200, 0xffff, {EACA},	"PMOVE	MMUSR,%e" },
722 { 0xf000, 0xffc0, 0x2800, 0xfff8, {EACA},	"PVALID	A%a,%e" },
723 { 0xf000, 0xffc0, 0x2000, 0xffe0, {EACA},	"PLOADW	%L,%e" },
724 { 0xf000, 0xffc0, 0x2200, 0xffe0, {EACA},	"PLOADR	%L,%e" },
725 { 0xf000, 0xffc0, 0x8000, 0xffe0, {EACA},	"PTESTW	%L,%e,#0" },
726 { 0xf000, 0xffc0, 0x8200, 0xffe0, {EACA},	"PTESTR	%L,%e,#0" },
727 { 0xf000, 0xffc0, 0x3000, 0xfe00, {0},		"PFLUSH	%L,#%I" },
728 { 0xf000, 0xffc0, 0x3800, 0xfe00, {EACA},	"PFLUSH	%L,#%I,%e" },
729 { 0xf000, 0xffc0, 0x8000, 0xe300, {EACA},	"PTESTW	%L,%e,#%Z" },
730 { 0xf000, 0xffc0, 0x8100, 0xe300, {EACA},	"PTESTW	%L,%e,#%Z,A%h" },
731 { 0xf000, 0xffc0, 0x8200, 0xe300, {EACA},	"PTESTR	%L,%e,#%Z" },
732 { 0xf000, 0xffc0, 0x8300, 0xe300, {EACA},	"PTESTR	%L,%e,#%Z,A%h" },
733 { 0xf000, 0xffc0, 0x4000, 0xc3ff, {EACA},	"PMOVE	%e,%H" },
734 { 0xf000, 0xffc0, 0x4100, 0xc3ff, {EACA},	"PMOVEFD	%e,%H" },
735 { 0xf000, 0xffc0, 0x4200, 0xc3ff, {EACA},	"PMOVE	%H,%e" },
736 
737 	/* floating point (coprocessor 1)*/
738 
739 { 0xf200, 0xffc0, 0x8400, 0xffff, {EAALL_L},	"FMOVEL	%e,FPIAR" },
740 { 0xf200, 0xffc0, 0x8800, 0xffff, {EADI_L},	"FMOVEL	%e,FPSR" },
741 { 0xf200, 0xffc0, 0x9000, 0xffff, {EADI_L},	"FMOVEL	%e,FPCR" },
742 { 0xf200, 0xffc0, 0xa400, 0xffff, {EAA},	"FMOVEL	FPIAR,%e" },
743 { 0xf200, 0xffc0, 0xa800, 0xffff, {EADA},	"FMOVEL	FPSR,%e" },
744 { 0xf200, 0xffc0, 0xb000, 0xffff, {EADA},	"FMOVEL	FPCR,%e" },
745 
746 { 0xf240, 0xffc0, 0x0000, 0xffc0, {EADA},	"FS%P	%e" },
747 
748 { 0xf200, 0xffc0, 0xd000, 0xff00, {EACPI},	"FMOVEMX	%e,%m" },
749 { 0xf200, 0xffc0, 0xd800, 0xff00, {EACPI},	"FMOVEMX	%e,R%K" },
750 { 0xf200, 0xffc0, 0xe000, 0xff00, {EAPI},	"FMOVEMX	%m,-(A%y)" },
751 { 0xf200, 0xffc0, 0xe800, 0xff00, {EAPI},	"FMOVEMX	R%K,-(A%y)" },
752 { 0xf200, 0xffc0, 0xf000, 0xff00, {EACAPD},	"FMOVEMX	%m,%e" },
753 { 0xf200, 0xffc0, 0xf800, 0xff00, {EACAPD},	"FMOVEMX	R%K,%e" },
754 
755 { 0xf200, 0xffc0, 0x6800, 0xfc00, {EAMA},	"FMOVEX	F%D,%e" },
756 { 0xf200, 0xffc0, 0x6c00, 0xfc00, {EAMA},	"FMOVEP	F%D,%e,{%k}" },
757 { 0xf200, 0xffc0, 0x7400, 0xfc00, {EAMA},	"FMOVED	F%D,%e" },
758 { 0xf200, 0xffc0, 0x7c00, 0xfc00, {EAMA},	"FMOVEP	F%D,%e,{R%K}" },
759 
760 { 0xf200, 0xffc0, 0x8000, 0xe3ff, {EAM},	"FMOVEML	#%B,%e" },
761 { 0xf200, 0xffc0, 0xa000, 0xe3ff, {EAMA},	"FMOVEML	%e,#%B" },
762 
763 { 0xf200, 0xffc0, 0x0000, 0xe07f, {0},		"FMOVE	F%B,F%D" },
764 { 0xf200, 0xffc0, 0x0001, 0xe07f, {0},		"FINTX	%F" },
765 { 0xf200, 0xffc0, 0x0002, 0xe07f, {0},		"FSINHX	%F" },
766 { 0xf200, 0xffc0, 0x0003, 0xe07f, {0},		"FINTRZ	%F" },
767 { 0xf200, 0xffc0, 0x0004, 0xe07f, {0},		"FSQRTX	%F" },
768 { 0xf200, 0xffc0, 0x0006, 0xe07f, {0},		"FLOGNP1X	%F" },
769 { 0xf200, 0xffc0, 0x0009, 0xe07f, {0},		"FTANHX	%F" },
770 { 0xf200, 0xffc0, 0x000a, 0xe07f, {0},		"FATANX	%F" },
771 { 0xf200, 0xffc0, 0x000c, 0xe07f, {0},		"FASINX	%F" },
772 { 0xf200, 0xffc0, 0x000d, 0xe07f, {0},		"FATANHX	%F" },
773 { 0xf200, 0xffc0, 0x000e, 0xe07f, {0},		"FSINX	%F" },
774 { 0xf200, 0xffc0, 0x000f, 0xe07f, {0},		"FTANX	%F" },
775 { 0xf200, 0xffc0, 0x0010, 0xe07f, {0},		"FETOXX	%F" },
776 { 0xf200, 0xffc0, 0x0011, 0xe07f, {0},		"FTWOTOXX	%F" },
777 { 0xf200, 0xffc0, 0x0012, 0xe07f, {0},		"FTENTOXX	%F" },
778 { 0xf200, 0xffc0, 0x0014, 0xe07f, {0},		"FLOGNX	%F" },
779 { 0xf200, 0xffc0, 0x0015, 0xe07f, {0},		"FLOG10X	%F" },
780 { 0xf200, 0xffc0, 0x0016, 0xe07f, {0},		"FLOG2X	%F" },
781 { 0xf200, 0xffc0, 0x0018, 0xe07f, {0},		"FABSX	%F" },
782 { 0xf200, 0xffc0, 0x0019, 0xe07f, {0},		"FCOSHX	%F" },
783 { 0xf200, 0xffc0, 0x001a, 0xe07f, {0},		"FNEGX	%F" },
784 { 0xf200, 0xffc0, 0x001c, 0xe07f, {0},		"FACOSX	%F" },
785 { 0xf200, 0xffc0, 0x001d, 0xe07f, {0},		"FCOSX	%F" },
786 { 0xf200, 0xffc0, 0x001e, 0xe07f, {0},		"FGETEXPX	%F" },
787 { 0xf200, 0xffc0, 0x001f, 0xe07f, {0},		"FGETMANX	%F" },
788 { 0xf200, 0xffc0, 0x0020, 0xe07f, {0},		"FDIVX	F%B,F%D" },
789 { 0xf200, 0xffc0, 0x0021, 0xe07f, {0},		"FMODX	F%B,F%D" },
790 { 0xf200, 0xffc0, 0x0022, 0xe07f, {0},		"FADDX	F%B,F%D" },
791 { 0xf200, 0xffc0, 0x0023, 0xe07f, {0},		"FMULX	F%B,F%D" },
792 { 0xf200, 0xffc0, 0x0024, 0xe07f, {0},		"FSGLDIVX	F%B,F%D" },
793 { 0xf200, 0xffc0, 0x0025, 0xe07f, {0},		"FREMX	F%B,F%D" },
794 { 0xf200, 0xffc0, 0x0026, 0xe07f, {0},		"FSCALEX	F%B,F%D" },
795 { 0xf200, 0xffc0, 0x0027, 0xe07f, {0},		"FSGLMULX	F%B,F%D" },
796 { 0xf200, 0xffc0, 0x0028, 0xe07f, {0},		"FSUBX	F%B,F%D" },
797 { 0xf200, 0xffc0, 0x0038, 0xe07f, {0},		"FCMPX	F%B,F%D" },
798 { 0xf200, 0xffc0, 0x003a, 0xe07f, {0},		"FTSTX	F%B" },
799 { 0xf200, 0xffc0, 0x0040, 0xe07f, {0},		"FSMOVE	F%B,F%D" },
800 { 0xf200, 0xffc0, 0x0041, 0xe07f, {0},		"FSSQRTX	%F"},
801 { 0xf200, 0xffc0, 0x0044, 0xe07f, {0},		"FDMOVE	F%B,F%D" },
802 { 0xf200, 0xffc0, 0x0045, 0xe07f, {0},		"FDSQRTX	%F" },
803 { 0xf200, 0xffc0, 0x0058, 0xe07f, {0},		"FSABSX	%F" },
804 { 0xf200, 0xffc0, 0x005a, 0xe07f, {0},		"FSNEGX	%F" },
805 { 0xf200, 0xffc0, 0x005c, 0xe07f, {0},		"FDABSX	%F" },
806 { 0xf200, 0xffc0, 0x005e, 0xe07f, {0},		"FDNEGX	%F" },
807 { 0xf200, 0xffc0, 0x0060, 0xe07f, {0},		"FSDIVX	F%B,F%D" },
808 { 0xf200, 0xffc0, 0x0062, 0xe07f, {0},		"FSADDX	F%B,F%D" },
809 { 0xf200, 0xffc0, 0x0063, 0xe07f, {0},		"FSMULX	F%B,F%D" },
810 { 0xf200, 0xffc0, 0x0064, 0xe07f, {0},		"FDDIVX	F%B,F%D" },
811 { 0xf200, 0xffc0, 0x0066, 0xe07f, {0},		"FDADDX	F%B,F%D" },
812 { 0xf200, 0xffc0, 0x0067, 0xe07f, {0},		"FDMULX	F%B,F%D" },
813 { 0xf200, 0xffc0, 0x0068, 0xe07f, {0},		"FSSUBX	F%B,F%D" },
814 { 0xf200, 0xffc0, 0x006c, 0xe07f, {0},		"FDSUBX	F%B,F%D" },
815 { 0xf200, 0xffc0, 0x4000, 0xe07f, {EAFLT},	"FMOVE%S	%e,F%D" },
816 { 0xf200, 0xffc0, 0x4001, 0xe07f, {EAFLT},	"FINT%S	%e,F%D" },
817 { 0xf200, 0xffc0, 0x4002, 0xe07f, {EAFLT},	"FSINH%S	%e,F%D" },
818 { 0xf200, 0xffc0, 0x4003, 0xe07f, {EAFLT},	"FINTRZ%S	%e,F%D" },
819 { 0xf200, 0xffc0, 0x4004, 0xe07f, {EAFLT},	"FSQRT%S	%e,F%D" },
820 { 0xf200, 0xffc0, 0x4006, 0xe07f, {EAFLT},	"FLOGNP1%S	%e,F%D" },
821 { 0xf200, 0xffc0, 0x4009, 0xe07f, {EAFLT},	"FTANH%S	%e,F%D" },
822 { 0xf200, 0xffc0, 0x400a, 0xe07f, {EAFLT},	"FATAN%S	%e,F%D" },
823 { 0xf200, 0xffc0, 0x400c, 0xe07f, {EAFLT},	"FASIN%S	%e,F%D" },
824 { 0xf200, 0xffc0, 0x400d, 0xe07f, {EAFLT},	"FATANH%S	%e,F%D" },
825 { 0xf200, 0xffc0, 0x400e, 0xe07f, {EAFLT},	"FSIN%S	%e,F%D" },
826 { 0xf200, 0xffc0, 0x400f, 0xe07f, {EAFLT},	"FTAN%S	%e,F%D" },
827 { 0xf200, 0xffc0, 0x4010, 0xe07f, {EAFLT},	"FETOX%S	%e,F%D" },
828 { 0xf200, 0xffc0, 0x4011, 0xe07f, {EAFLT},	"FTWOTOX%S	%e,F%D" },
829 { 0xf200, 0xffc0, 0x4012, 0xe07f, {EAFLT},	"FTENTOX%S	%e,F%D" },
830 { 0xf200, 0xffc0, 0x4014, 0xe07f, {EAFLT},	"FLOGN%S	%e,F%D" },
831 { 0xf200, 0xffc0, 0x4015, 0xe07f, {EAFLT},	"FLOG10%S	%e,F%D" },
832 { 0xf200, 0xffc0, 0x4016, 0xe07f, {EAFLT},	"FLOG2%S	%e,F%D" },
833 { 0xf200, 0xffc0, 0x4018, 0xe07f, {EAFLT},	"FABS%S	%e,F%D" },
834 { 0xf200, 0xffc0, 0x4019, 0xe07f, {EAFLT},	"FCOSH%S	%e,F%D" },
835 { 0xf200, 0xffc0, 0x401a, 0xe07f, {EAFLT},	"FNEG%S	%e,F%D" },
836 { 0xf200, 0xffc0, 0x401c, 0xe07f, {EAFLT},	"FACOS%S	%e,F%D" },
837 { 0xf200, 0xffc0, 0x401d, 0xe07f, {EAFLT},	"FCOS%S	%e,F%D" },
838 { 0xf200, 0xffc0, 0x401e, 0xe07f, {EAFLT},	"FGETEXP%S	%e,F%D" },
839 { 0xf200, 0xffc0, 0x401f, 0xe07f, {EAFLT},	"FGETMAN%S	%e,F%D" },
840 { 0xf200, 0xffc0, 0x4020, 0xe07f, {EAFLT},	"FDIV%S	%e,F%D" },
841 { 0xf200, 0xffc0, 0x4021, 0xe07f, {EAFLT},	"FMOD%S	%e,F%D" },
842 { 0xf200, 0xffc0, 0x4022, 0xe07f, {EAFLT},	"FADD%S	%e,F%D" },
843 { 0xf200, 0xffc0, 0x4023, 0xe07f, {EAFLT},	"FMUL%S	%e,F%D" },
844 { 0xf200, 0xffc0, 0x4024, 0xe07f, {EAFLT},	"FSGLDIV%S	%e,F%D" },
845 { 0xf200, 0xffc0, 0x4025, 0xe07f, {EAFLT},	"FREM%S	%e,F%D" },
846 { 0xf200, 0xffc0, 0x4026, 0xe07f, {EAFLT},	"FSCALE%S	%e,F%D" },
847 { 0xf200, 0xffc0, 0x4027, 0xe07f, {EAFLT},	"FSGLMUL%S	%e,F%D" },
848 { 0xf200, 0xffc0, 0x4028, 0xe07f, {EAFLT},	"FSUB%S	%e,F%D" },
849 { 0xf200, 0xffc0, 0x4038, 0xe07f, {EAFLT},	"FCMP%S	%e,F%D" },
850 { 0xf200, 0xffc0, 0x403a, 0xe07f, {EAFLT},	"FTST%S	%e" },
851 { 0xf200, 0xffc0, 0x4040, 0xe07f, {EAFLT},	"FSMOVE%S	%e,F%D" },
852 { 0xf200, 0xffc0, 0x4041, 0xe07f, {EAFLT},	"FSSQRT%S	%e,F%D" },
853 { 0xf200, 0xffc0, 0x4044, 0xe07f, {EAFLT},	"FDMOVE%S	%e,F%D" },
854 { 0xf200, 0xffc0, 0x4045, 0xe07f, {EAFLT},	"FDSQRT%S	%e,F%D" },
855 { 0xf200, 0xffc0, 0x4058, 0xe07f, {EAFLT},	"FSABS%S	%e,F%D" },
856 { 0xf200, 0xffc0, 0x405a, 0xe07f, {EAFLT},	"FSNEG%S	%e,F%D" },
857 { 0xf200, 0xffc0, 0x405c, 0xe07f, {EAFLT},	"FDABS%S	%e,F%D" },
858 { 0xf200, 0xffc0, 0x405e, 0xe07f, {EAFLT},	"FDNEG%S	%e,F%D" },
859 { 0xf200, 0xffc0, 0x4060, 0xe07f, {EAFLT},	"FSDIV%S	%e,F%D" },
860 { 0xf200, 0xffc0, 0x4062, 0xe07f, {EAFLT},	"FSADD%S	%e,F%D" },
861 { 0xf200, 0xffc0, 0x4063, 0xe07f, {EAFLT},	"FSMUL%S	%e,F%D" },
862 { 0xf200, 0xffc0, 0x4064, 0xe07f, {EAFLT},	"FDDIV%S	%e,F%D" },
863 { 0xf200, 0xffc0, 0x4066, 0xe07f, {EAFLT},	"FDADD%S	%e,F%D" },
864 { 0xf200, 0xffc0, 0x4067, 0xe07f, {EAFLT},	"FDMUL%S	%e,F%D" },
865 { 0xf200, 0xffc0, 0x4068, 0xe07f, {EAFLT},	"FSSUB%S	%e,F%D" },
866 { 0xf200, 0xffc0, 0x406c, 0xe07f, {EAFLT},	"FDSUB%S	%e,F%D" },
867 
868 { 0xf200, 0xffc0, 0x0030, 0xe078, {0},		"FSINCOSX	F%B,F%a:F%D" },
869 { 0xf200, 0xffc0, 0x4030, 0xe078, {EAFLT},	"FSINCOS%S	%e,F%a:F%D" },
870 
871 { 0xf200, 0xffc0, 0x6000, 0xe000, {EADA},	"FMOVE%S	F%D,%e" },
872 
873 { 0xf300, 0xffc0, 0x0000, 0x0000, {EACAPD},	"FSAVE	%e" },
874 { 0xf340, 0xffc0, 0x0000, 0x0000, {EACAPI},	"FRESTORE	%e" },
875 
876 { 0xf280, 0xffc0, 0x0000, 0x0000, {BR16},	"FB%p	%t" },
877 { 0xf2c0, 0xffc0, 0x0000, 0x0000, {BR32},	"FB%p	%t" },
878 
879 { 0xf408, 0xff38, 0x0000, 0x0000, {0},		"CINVL	%C,(A%y)" },
880 { 0xf410, 0xff38, 0x0000, 0x0000, {0},		"CINVP	%C,(A%y)" },
881 { 0xf418, 0xff38, 0x0000, 0x0000, {0},		"CINVA	%C" },
882 { 0xf428, 0xff38, 0x0000, 0x0000, {0},		"CPUSHL	%C,(A%y)" },
883 { 0xf430, 0xff38, 0x0000, 0x0000, {0},		"CPUSHP	%C,(A%y)" },
884 { 0xf438, 0xff38, 0x0000, 0x0000, {0},		"CPUSHA	%C" },
885 { 0,0,0,0,{0},0 },
886 };
887 
888 static Optable	*optables[] =
889 {
890 	t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, 0, tb, tc, td, te, tf,
891 };
892 
893 static	Map	*mymap;
894 
895 static int
dumpinst(Inst * ip,char * buf,int n)896 dumpinst(Inst *ip, char *buf, int n)
897 {
898 	int i;
899 
900 	if (n <= 0)
901 		return 0;
902 
903 	*buf++ = '#';
904 	for (i = 0; i < ip->n && i*4+1 < n-4; i++, buf += 4)
905 		_hexify(buf, ip->raw[i], 3);
906 	*buf = 0;
907 	return i*4+1;
908 }
909 
910 static int
getword(Inst * ip,uvlong offset)911 getword(Inst *ip, uvlong offset)
912 {
913 	if (ip->n < nelem(ip->raw)) {
914 		if (get2(mymap, offset, &ip->raw[ip->n++]) > 0)
915 			return 1;
916 		werrstr("can't read instruction: %r");
917 	} else
918 		werrstr("instruction too big: %r");
919 	return -1;
920 }
921 
922 static int
getshorts(Inst * ip,void * where,int n)923 getshorts(Inst *ip, void *where, int n)
924 {
925 	if (ip->n+n < nelem(ip->raw)) {
926 		if (get1(mymap, ip->addr+ip->n*2, (uchar*)&ip->raw[ip->n], n*2) < 0) {
927 			werrstr("can't read instruction: %r");
928 			return 0;
929 		}
930 		memmove(where, &ip->raw[ip->n], n*2);
931 		ip->n += n;
932 		return 1;
933 	}
934 	werrstr("instruction too big: %r");
935 	return 0;
936 }
937 
938 static int
i8(Inst * ip,long * l)939 i8(Inst *ip, long *l)
940 {
941 	if (getword(ip, ip->addr+ip->n*2) < 0)
942 		return -1;
943 	*l = ip->raw[ip->n-1]&0xff;
944 	if (*l&0x80)
945 		*l |= ~0xff;
946 	return 1;
947 }
948 
949 static int
i16(Inst * ip,long * l)950 i16(Inst *ip, long *l)
951 {
952 	if (getword(ip, ip->addr+ip->n*2) < 0)
953 		return -1;
954 	*l = ip->raw[ip->n-1];
955 	if (*l&0x8000)
956 		*l |= ~0xffff;
957 	return 1;
958 }
959 static int
i32(Inst * ip,long * l)960 i32(Inst *ip, long *l)
961 {
962 	if (getword(ip, ip->addr+ip->n*2) < 0)
963 		return -1;
964 	if (getword(ip, ip->addr+ip->n*2) < 0)
965 		return -1;
966 	*l = (ip->raw[ip->n-2]<<16)|ip->raw[ip->n-1];
967 	return 1;
968 }
969 
970 static int
getimm(Inst * ip,Operand * ap,int mode)971 getimm(Inst *ip, Operand *ap, int mode)
972 {
973 	ap->eatype = IMM;
974 	switch(mode)
975 	{
976 	case EAM_B:	/* byte */
977 	case EAALL_B:
978 		return i8(ip, &ap->immediate);
979 	case EADI_W:	/* word */
980 	case EAALL_W:
981 		return i16(ip, &ap->immediate);
982 	case EADI_L:	/* long */
983 	case EAALL_L:
984 		return i32(ip, &ap->immediate);
985 	case EAFLT:	/* floating point - size in bits 10-12 or word 1 */
986 		switch((ip->raw[1]>>10)&0x07)
987 		{
988 		case 0:	/* long integer */
989 			return i32(ip, &ap->immediate);
990 		case 1:	/* single precision real */
991 			ap->eatype = IREAL;
992 			return getshorts(ip, ap->floater, 2);
993 		case 2:	/* extended precision real - not supported */
994 			ap->eatype = IEXT;
995 			return getshorts(ip, ap->floater, 6);
996 		case 3: /* packed decimal real - not supported */
997 			ap->eatype = IPACK;
998 			return getshorts(ip, ap->floater, 12);
999 		case 4:	/* integer word */
1000 			return i16(ip, &ap->immediate);
1001 		case 5:	/* double precision real */
1002 			ap->eatype = IDBL;
1003 			return getshorts(ip, ap->floater, 4);
1004 		case 6:	/* integer byte */
1005 			return i8(ip, &ap->immediate);
1006 		default:
1007 			ip->errmsg = "bad immediate float data";
1008 			return -1;
1009 		}
1010 		/* not reached */
1011 	case IV:	/* size encoded in bits 6&7 of opcode word */
1012 	default:
1013 		switch((ip->raw[0]>>6)&0x03)
1014 		{
1015 		case 0x00:	/* integer byte */
1016 			return i8(ip, &ap->immediate);
1017 		case 0x01:	/* integer word */
1018 			return i16(ip, &ap->immediate);
1019 		case 0x02:	/* integer long */
1020 			return i32(ip, &ap->immediate);
1021 		default:
1022 			ip->errmsg = "bad immediate size";
1023 			return -1;
1024 		}
1025 		/* not reached */
1026 	}
1027 }
1028 
1029 static int
getdisp(Inst * ip,Operand * ap)1030 getdisp(Inst *ip, Operand *ap)
1031 {
1032 	short ext;
1033 
1034 	if (getword(ip, ip->addr+ip->n*2) < 0)
1035 		return -1;
1036 	ext = ip->raw[ip->n-1];
1037 	ap->ext = ext;
1038 	if ((ext&0x100) == 0) {		/* indexed with 7-bit displacement */
1039 		ap->disp = ext&0x7f;
1040 		if (ap->disp&0x40)
1041 			ap->disp |= ~0x7f;
1042 		return 1;
1043 	}
1044 	switch(ext&0x30)	/* first (inner) displacement  */
1045 	{
1046 	case 0x10:
1047 		break;
1048 	case 0x20:
1049 		if (i16(ip, &ap->disp) < 0)
1050 			return -1;
1051 		break;
1052 	case 0x30:
1053 		if (i32(ip, &ap->disp) < 0)
1054 			return -1;
1055 		break;
1056 	default:
1057 		ip->errmsg = "bad EA displacement";
1058 		return -1;
1059 	}
1060 	switch (ext&0x03)	/* outer displacement */
1061 	{
1062 	case 0x02:		/* 16 bit displacement */
1063 		return i16(ip, &ap->outer);
1064 	case 0x03:		/* 32 bit displacement */
1065 		return i32(ip, &ap->outer);
1066 	default:
1067 		break;
1068 	}
1069 	return 1;
1070 }
1071 
1072 static int
ea(Inst * ip,int ea,Operand * ap,int mode)1073 ea(Inst *ip, int ea, Operand *ap, int mode)
1074 {
1075 	int type, size;
1076 
1077 	type = 0;
1078 	ap->ext = 0;
1079 	switch((ea>>3)&0x07)
1080 	{
1081 	case 0x00:
1082 		ap->eatype = Dreg;
1083 		type = Dn;
1084 		break;
1085 	case 0x01:
1086 		ap->eatype = Areg;
1087 		type = An;
1088 		break;
1089 	case 0x02:
1090 		ap->eatype = AInd;
1091 		type = Ind;
1092 		break;
1093 	case 0x03:
1094 		ap->eatype = APinc;
1095 		type = Pinc;
1096 		break;
1097 	case 0x04:
1098 		ap->eatype = APdec;
1099 		type = Pdec;
1100 		break;
1101 	case 0x05:
1102 		ap->eatype = ADisp;
1103 		type = Bdisp;
1104 		if (i16(ip, &ap->disp) < 0)
1105 			return -1;
1106 		break;
1107 	case 0x06:
1108 		ap->eatype = BXD;
1109 		type = Bdisp;
1110 		if (getdisp(ip, ap) < 0)
1111 			return -1;
1112 		break;
1113 	case 0x07:
1114 		switch(ea&0x07)
1115 		{
1116 		case 0x00:
1117 			type = Abs;
1118 			ap->eatype = ABS;
1119 			if (i16(ip, &ap->immediate) < 0)
1120 				return -1;
1121 			break;
1122 		case 0x01:
1123 			type = Abs;
1124 			ap->eatype = ABS;
1125 			if (i32(ip, &ap->immediate) < 0)
1126 				return -1;
1127 			break;
1128 		case 0x02:
1129 			type = PCrel;
1130 			ap->eatype = PDisp;
1131 			if (i16(ip, &ap->disp) < 0)
1132 				return -1;
1133 			break;
1134 		case 0x03:
1135 			type = PCrel;
1136 			ap->eatype = PXD;
1137 			if (getdisp(ip, ap) < 0)
1138 				return -1;
1139 			break;
1140 		case 0x04:
1141 			type = Imm;
1142 			if (getimm(ip, ap, mode) < 0)
1143 				return -1;
1144 			break;
1145 		default:
1146 			ip->errmsg = "bad EA mode";
1147 			return -1;
1148 		}
1149 	}
1150 		/* Allowable floating point EAs are restricted for packed,
1151 		 * extended, and double precision operands
1152 		 */
1153 	if (mode == EAFLT) {
1154 		size = (ip->raw[1]>>10)&0x07;
1155 		if (size == 2 || size == 3 || size == 5)
1156 			mode = EAM;
1157 		else
1158 			mode = EADI;
1159 	}
1160 	if (!(validea[mode]&type)) {
1161 		ip->errmsg = "invalid EA";
1162 		return -1;
1163 	}
1164 	return 1;
1165 }
1166 
1167 static int
decode(Inst * ip,Optable * op)1168 decode(Inst *ip, Optable *op)
1169 {
1170 	int i, t, mode;
1171 	Operand *ap;
1172 	short opcode;
1173 
1174 	opcode = ip->raw[0];
1175 	for (i = 0; i < nelem(op->opdata) && op->opdata[i]; i++) {
1176 		ap = &ip->and[i];
1177 		mode = op->opdata[i];
1178 		switch(mode)
1179 		{
1180 		case EAPI:		/* normal EA modes */
1181 		case EACA:
1182 		case EACAD:
1183 		case EACAPI:
1184 		case EACAPD:
1185 		case EAMA:
1186 		case EADA:
1187 		case EAA:
1188 		case EAC:
1189 		case EACPI:
1190 		case EACD:
1191 		case EAD:
1192 		case EAM:
1193 		case EAM_B:
1194 		case EADI:
1195 		case EADI_L:
1196 		case EADI_W:
1197 		case EAALL:
1198 		case EAALL_L:
1199 		case EAALL_W:
1200 		case EAALL_B:
1201 		case EAFLT:
1202 			if (ea(ip, opcode&0x3f, ap, mode) < 0)
1203 				return -1;
1204 			break;
1205 		case EADDA:	/* stupid bit flop required */
1206 			t = ((opcode>>9)&0x07)|((opcode>>3)&0x38);
1207 			if (ea(ip, t, ap, EADA)< 0)
1208 					return -1;
1209 			break;
1210 		case BREAC:	/* EAC JMP or CALL operand */
1211 			if (ea(ip, opcode&0x3f, ap, EAC) < 0)
1212 				return -1;
1213 			break;
1214 		case OP8:	/* weird movq instruction */
1215 			ap->eatype = IMM;
1216 			ap->immediate = opcode&0xff;
1217 			if (opcode&0x80)
1218 				ap->immediate |= ~0xff;
1219 			break;
1220 		case I8:	/* must be two-word opcode */
1221 			ap->eatype = IMM;
1222 			ap->immediate = ip->raw[1]&0xff;
1223 			if (ap->immediate&0x80)
1224 				ap->immediate |= ~0xff;
1225 			break;
1226 		case I16:	/* 16 bit immediate */
1227 		case BR16:
1228 			ap->eatype = IMM;
1229 			if (i16(ip, &ap->immediate) < 0)
1230 				return -1;
1231 			break;
1232 		case C16:	/* CAS2 16 bit immediate */
1233 			ap->eatype = IMM;
1234 			if (i16(ip, &ap->immediate) < 0)
1235 				return -1;
1236 			if (ap->immediate & 0x0e38) {
1237 				ip->errmsg = "bad CAS2W operand";
1238 				return 0;
1239 			}
1240 			break;
1241 		case I32:	/* 32 bit immediate */
1242 		case BR32:
1243 			ap->eatype = IMM;
1244 			if (i32(ip, &ap->immediate) < 0)
1245 				return -1;
1246 			break;
1247 		case IV:	/* immediate data depends on size field */
1248 			if (getimm(ip, ap, IV) < 0)
1249 				return -1;
1250 			break;
1251 		case BR8:	/* branch displacement format */
1252 			ap->eatype = IMM;
1253 			ap->immediate = opcode&0xff;
1254 			if (ap->immediate == 0) {
1255 				if (i16(ip, &ap->immediate) < 0)
1256 					return -1;
1257 			} else if (ap->immediate == 0xff) {
1258 				if (i32(ip, &ap->immediate) < 0)
1259 					return -1;
1260 			} else if (ap->immediate & 0x80)
1261 				ap->immediate |= ~0xff;
1262 			break;
1263 		case STACK:	/* Dummy operand type for Return instructions */
1264 		default:
1265 			break;
1266 		}
1267 	}
1268 	return 1;
1269 }
1270 
1271 static Optable *
instruction(Inst * ip)1272 instruction(Inst *ip)
1273 {
1274 	ushort opcode, op2;
1275 	Optable *op;
1276 	int class;
1277 
1278 	ip->n = 0;
1279 	if (getword(ip, ip->addr) < 0)
1280 		return 0;
1281 	opcode = ip->raw[0];
1282 	if (get2(mymap, ip->addr+2, &op2) < 0)
1283 		op2 = 0;
1284 	class = (opcode>>12)&0x0f;
1285 	for (op = optables[class]; op && op->format; op++) {
1286 		if (op->opcode != (opcode&op->mask0))
1287 			continue;
1288 		if (op->op2 != (op2&op->mask1))
1289 			continue;
1290 		if (op->mask1)
1291 			ip->raw[ip->n++] = op2;
1292 		return op;
1293 	}
1294 	ip->errmsg = "Invalid opcode";
1295 	return 0;
1296 }
1297 
1298 #pragma	varargck	argpos	bprint		2
1299 
1300 static void
bprint(Inst * i,char * fmt,...)1301 bprint(Inst *i, char *fmt, ...)
1302 {
1303 	va_list arg;
1304 
1305 	va_start(arg, fmt);
1306 	i->curr = vseprint(i->curr, i->end, fmt, arg);
1307 	va_end(arg);
1308 }
1309 
1310 static	char	*regname[] =
1311 {
1312 	"R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "A0",
1313 	"A1", "A2", "A3", "A4", "A5", "A6", "A7", "PC", "SB"
1314 };
1315 
1316 static void
plocal(Inst * ip,Operand * ap)1317 plocal(Inst *ip, Operand *ap)
1318 {
1319 	int ret;
1320 	long offset;
1321 	uvlong moved;
1322 	Symbol s;
1323 
1324 	offset = ap->disp;
1325 	if (!findsym(ip->addr, CTEXT, &s))
1326 		goto none;
1327 
1328 	moved = pc2sp(ip->addr);
1329 	if (moved == -1)
1330 		goto none;
1331 
1332 	if (offset > moved) {		/* above frame - must be argument */
1333 		offset -= moved;
1334 		ret = getauto(&s, offset-mach->szaddr, CPARAM, &s);
1335 	} else				/* below frame - must be automatic */
1336 		ret = getauto(&s, moved-offset, CPARAM, &s);
1337 	if (ret)
1338 		bprint(ip, "%s+%lux", s.name, offset);
1339 	else
1340 none:		bprint(ip, "%lux", ap->disp);
1341 }
1342 
1343 /*
1344  *	this guy does all the work of printing the base and index component
1345  *	of an EA.
1346  */
1347 static int
pidx(Inst * ip,int ext,int reg,char * bfmt,char * ifmt,char * nobase)1348 pidx(Inst *ip, int ext, int reg, char *bfmt, char *ifmt, char *nobase)
1349 {
1350 	char *s;
1351 	int printed;
1352 	char buf[512];
1353 
1354 	printed = 1;
1355 	if (ext&0x80) {				/* Base suppressed */
1356 		if (reg == 16)
1357 			bprint(ip, bfmt, "(ZPC)");
1358 		else if (nobase)
1359 			bprint(ip, nobase);
1360 		else
1361 			printed = 0;
1362 	} else					/* format base reg */
1363 		bprint(ip, bfmt, regname[reg]);
1364 	if (ext & 0x40)				/* index suppressed */
1365 		return printed;
1366 	switch ((ext>>9)&0x03)
1367 	{
1368 	case 0x01:
1369 		s = "*2";
1370 		break;
1371 	case 0x02:
1372 		s = "*4";
1373 		break;
1374 	case 0x03:
1375 		s = "*8";
1376 		break;
1377 	default:
1378 		if (ext&0x80)
1379 			s = "*1";
1380 		else
1381 			s = "";
1382 		break;
1383 	}
1384 	sprint(buf, "%s.%c%s", regname[(ext>>12)&0x0f], (ext&0x800) ? 'L' : 'W', s);
1385 	if (!printed)
1386 		bprint(ip, ifmt, buf);
1387 	else
1388 		bprint(ip, "(%s)", buf);
1389 	return 1;
1390 }
1391 
1392 static void
prindex(Inst * ip,int reg,Operand * ap)1393 prindex(Inst *ip, int reg, Operand *ap)
1394 {
1395 	short ext;
1396 	int left;
1397 	int disp;
1398 
1399 	left = ip->end-ip->curr;
1400 	if (left <= 0)
1401 		return;
1402 	ext = ap->ext;
1403 	disp = ap->disp;
1404 		/* look for static base register references */
1405 	if ((ext&0xa0) == 0x20 && reg == 14 && mach->sb && disp) {
1406 		reg = 17;		/* "A6" -> "SB" */
1407 		disp += mach->sb;
1408 	}
1409 	if ((ext&0x100) == 0) {		/* brief form */
1410 		if (reg == 15)
1411 			plocal(ip, ap);
1412 		else if (disp)
1413 			ip->curr += symoff(ip->curr, left, disp, CANY);
1414 		pidx(ip, ext&0xff00, reg, "(%s)", "(%s)", 0);
1415 		return;
1416 	}
1417 	switch(ext&0x3f)	/* bd size, && i/is */
1418 	{
1419 	case 0x10:
1420 		if (!pidx(ip, ext, reg, "(%s)", "(%s)", 0))
1421 			bprint(ip, "#0");
1422 		break;
1423 	case 0x11:
1424 		if (pidx(ip, ext, reg, "((%s)", "((%s)", 0))
1425 			bprint(ip, ")");
1426 		else
1427 			bprint(ip, "#0");
1428 		break;
1429 	case 0x12:
1430 	case 0x13:
1431 		ip->curr += symoff(ip->curr, left, ap->outer, CANY);
1432 		if (pidx(ip, ext, reg, "((%s)", "((%s)", 0))
1433 			bprint(ip, ")");
1434 		break;
1435 	case 0x15:
1436 		if (!pidx(ip, ext, reg, "((%s))", "(%s)", 0))
1437 			bprint(ip, "#0");
1438 		break;
1439 	case 0x16:
1440 	case 0x17:
1441 		ip->curr += symoff(ip->curr, left, ap->outer, CANY);
1442 		pidx(ip, ext, reg, "((%s))", "(%s)", 0);
1443 		break;
1444 	case 0x20:
1445 	case 0x30:
1446 		if (reg == 15)
1447 			plocal(ip, ap);
1448 		else
1449 			ip->curr += symoff(ip->curr, left, disp, CANY);
1450 		pidx(ip, ext, reg, "(%s)", "(%s)", 0);
1451 		break;
1452 	case 0x21:
1453 	case 0x31:
1454 		*ip->curr++ = '(';
1455 		if (reg == 15)
1456 			plocal(ip, ap);
1457 		else
1458 			ip->curr += symoff(ip->curr, left-1, disp, CANY);
1459 		pidx(ip, ext, reg, "(%s)", "(%s)", 0);
1460 		bprint(ip, ")");
1461 		break;
1462 	case 0x22:
1463 	case 0x23:
1464 	case 0x32:
1465 	case 0x33:
1466 		ip->curr += symoff(ip->curr, left, ap->outer, CANY);
1467 		bprint(ip, "(");
1468 		if (reg == 15)
1469 			plocal(ip, ap);
1470 		else
1471 			ip->curr += symoff(ip->curr, ip->end-ip->curr, disp, CANY);
1472 		pidx(ip, ext, reg, "(%s)", "(%s)", 0);
1473 		bprint(ip, ")");
1474 		break;
1475 	case 0x25:
1476 	case 0x35:
1477 		*ip->curr++ = '(';
1478 		if (reg == 15)
1479 			plocal(ip, ap);
1480 		else
1481 			ip->curr += symoff(ip->curr, left-1, disp, CANY);
1482 		if (!pidx(ip, ext, reg, "(%s))", "(%s)", "())"))
1483 			bprint(ip, ")");
1484 		break;
1485 	case 0x26:
1486 	case 0x27:
1487 	case 0x36:
1488 	case 0x37:
1489 		ip->curr += symoff(ip->curr, left, ap->outer, CANY);
1490 		bprint(ip, "(");
1491 		if (reg == 15)
1492 			plocal(ip, ap);
1493 		else
1494 			ip->curr += symoff(ip->curr, ip->end-ip->curr, disp, CANY);
1495 		pidx(ip, ext, reg, "(%s))", "(%s)", "())");
1496 		break;
1497 	default:
1498 		bprint(ip, "??%x??", ext);
1499 		ip->errmsg = "bad EA";
1500 		break;
1501 	}
1502 }
1503 
1504 static	void
pea(int reg,Inst * ip,Operand * ap)1505 pea(int reg, Inst *ip, Operand *ap)
1506 {
1507 	int i, left;
1508 
1509 	left = ip->end-ip->curr;
1510 	if (left < 0)
1511 		return;
1512 	switch(ap->eatype)
1513 	{
1514 	case Dreg:
1515 		bprint(ip, "R%d", reg);
1516 		break;
1517 	case Areg:
1518 		bprint(ip, "A%d", reg);
1519 		break;
1520 	case AInd:
1521 		bprint(ip, "(A%d)", reg);
1522 		break;
1523 	case APinc:
1524 		bprint(ip, "(A%d)+", reg);
1525 		break;
1526 	case APdec:
1527 		bprint(ip, "-(A%d)", reg);
1528 		break;
1529 	case PDisp:
1530 		ip->curr += symoff(ip->curr, left, ip->addr+2+ap->disp, CANY);
1531 		break;
1532 	case PXD:
1533 		prindex(ip, 16, ap);
1534 		break;
1535 	case ADisp:	/* references off the static base */
1536 		if (reg == 6 && mach->sb && ap->disp) {
1537 			ip->curr += symoff(ip->curr, left, ap->disp+mach->sb, CANY);
1538 			bprint(ip, "(SB)");
1539 			break;
1540 		}
1541 			/* reference autos and parameters off the stack */
1542 		if (reg == 7)
1543 			plocal(ip, ap);
1544 		else
1545 			ip->curr += symoff(ip->curr, left, ap->disp, CANY);
1546 		bprint(ip, "(A%d)", reg);
1547 		break;
1548 	case BXD:
1549 		prindex(ip, reg+8, ap);
1550 		break;
1551 	case ABS:
1552 		ip->curr += symoff(ip->curr, left, ap->immediate, CANY);
1553 		bprint(ip, "($0)");
1554 		break;
1555 	case IMM:
1556 		*ip->curr++ = '$';
1557 		ip->curr += symoff(ip->curr, left-1, ap->immediate, CANY);
1558 		break;
1559 	case IREAL:
1560 		*ip->curr++ = '$';
1561 		ip->curr += beieeesftos(ip->curr, left-1, (void*) ap->floater);
1562 		break;
1563 	case IDBL:
1564 		*ip->curr++ = '$';
1565 		ip->curr += beieeedftos(ip->curr, left-1, (void*) ap->floater);
1566 		break;
1567 	case IPACK:
1568 		bprint(ip, "$#");
1569 		for (i = 0; i < 24 && ip->curr < ip->end-1; i++) {
1570 			_hexify(ip->curr, ap->floater[i], 1);
1571 			ip->curr += 2;
1572 		}
1573 		break;
1574 	case IEXT:
1575 		bprint(ip, "$#");
1576 		ip->curr += beieee80ftos(ip->curr, left-2, (void*)ap->floater);
1577 		break;
1578 	default:
1579 		bprint(ip, "??%x??", ap->eatype);
1580 		ip->errmsg = "bad EA type";
1581 		break;
1582 	}
1583 }
1584 
1585 static char *cctab[]  = { "F", "T", "HI", "LS", "CC", "CS", "NE", "EQ",
1586 			  "VC", "VS", "PL", "MI", "GE", "LT", "GT", "LE" };
1587 static	char *fcond[] =
1588 {
1589 	"F",	"EQ",	"OGT",	"OGE",	"OLT",	"OLE",	"OGL", "OR",
1590 	"UN",	"UEQ",	"UGT",	"UGE",	"ULT",	"ULE",	"NE",	"T",
1591 	"SF",	"SEQ",	"GT",	"GE",	"LT",	"LE",	"GL",	"GLE",
1592 	"NGLE",	"NGL",	"NLE",	"NLT",	"NGE",	"NGT",	"SNE",	"ST"
1593 };
1594 static	char *cachetab[] =	{ "NC", "DC", "IC", "BC" };
1595 static	char *mmutab[] =	{ "TC", "??", "SRP", "CRP" };
1596 static	char *crtab0[] =
1597 {
1598 	"SFC", "DFC", "CACR", "TC", "ITT0", "ITT1", "DTT0", "DTT1",
1599 };
1600 static	char *crtab1[] =
1601 {
1602 	"USP", "VBR", "CAAR", "MSP", "ISP", "MMUSR", "URP", "SRP",
1603 };
1604 static	char typetab[] =	{ 'L', 'S', 'X', 'P', 'W', 'D', 'B', '?', };
1605 static	char sztab[] =		{'?', 'B', 'W', 'L', '?' };
1606 
1607 static	void
formatins(char * fmt,Inst * ip)1608 formatins(char *fmt, Inst *ip)
1609 {
1610 	short op, w1;
1611 	int r1, r2;
1612 	int currand;
1613 
1614 	op = ip->raw[0];
1615 	w1 = ip->raw[1];
1616 	currand = 0;
1617 	for (; *fmt && ip->curr < ip->end; fmt++) {
1618 		if (*fmt != '%')
1619 			*ip->curr++ = *fmt;
1620 		else switch(*++fmt)
1621 		{
1622 		case '%':
1623 			*ip->curr++ = '%';
1624 			break;
1625 		case 'a':	/* register number; word 1:[0-2] */
1626 			*ip->curr++ = (w1&0x07)+'0';
1627 			break;
1628 		case 'c':	/* condition code; opcode: [8-11] */
1629 			bprint(ip, cctab[(op>>8)&0x0f]);
1630 			break;
1631 		case 'd':	/* shift direction; opcode: [8] */
1632 			if (op&0x100)
1633 				*ip->curr++ = 'L';
1634 			else
1635 				*ip->curr++ = 'R';
1636 			break;
1637 		case 'e':	/* source effective address */
1638 			pea(op&0x07, ip, &ip->and[currand++]);
1639 			break;
1640 		case 'f':	/* trap vector; op code: [0-3] */
1641 			bprint(ip, "%x", op&0x0f);
1642 			break;
1643 		case 'h':	/* register number; word 1: [5-7] */
1644 			*ip->curr++ = (w1>>5)&0x07+'0';
1645 			break;
1646 		case 'i':	/* immediate operand */
1647 			ip->curr += symoff(ip->curr, ip->end-ip->curr,
1648 					ip->and[currand++].immediate, CANY);
1649 			break;
1650 		case 'j':	/* data registers; word 1: [0-2] & [12-14] */
1651 			r1 = w1&0x07;
1652 			r2 = (w1>>12)&0x07;
1653 			if (r1 == r2)
1654 				bprint(ip, "R%d", r1);
1655 			else
1656 				bprint(ip, "R%d:R%d", r2, r1);
1657 			break;
1658 		case 'k':	/* k factor; word 1 [0-6] */
1659 			bprint(ip, "%x", w1&0x7f);
1660 			break;
1661 		case 'm':	/* register mask; word 1 [0-7] */
1662 			bprint(ip, "%x", w1&0xff);
1663 			break;
1664 		case 'o':	/* bit field offset; word1: [6-10] */
1665 			bprint(ip, "%d", (w1>>6)&0x3f);
1666 			break;
1667 		case 'p':	/* conditional predicate; opcode: [0-5]
1668 				   only bits 0-4 are defined  */
1669 			bprint(ip, fcond[op&0x1f]);
1670 			break;
1671 		case 'q':	/* 3-bit immediate value; opcode[9-11] */
1672 			r1 = (op>>9)&0x07;
1673 			if (r1 == 0)
1674 				*ip->curr++ = '8';
1675 			else
1676 				*ip->curr++ = r1+'0';
1677 			break;
1678 		case 'r':	/* register type & number; word 1: [12-15] */
1679 			bprint(ip, regname[(w1>>12)&0x0f]);
1680 			break;
1681 		case 's':	/* size; opcode [6-7] */
1682 			*ip->curr = sztab[((op>>6)&0x03)+1];
1683 			if (*ip->curr++ == '?')
1684 				ip->errmsg = "bad size code";
1685 			break;
1686 		case 't':	/* text offset */
1687 			ip->curr += symoff(ip->curr, ip->end-ip->curr,
1688 				ip->and[currand++].immediate+ip->addr+2, CTEXT);
1689 			break;
1690 		case 'u':	/* register number; word 1: [6-8] */
1691 			*ip->curr++ = ((w1>>6)&0x07)+'0';
1692 			break;
1693 		case 'w':	/* bit field width; word 1: [0-4] */
1694 			bprint(ip, "%d", w1&0x0f);
1695 			break;
1696 		case 'x':	/* register number; opcode: [9-11] */
1697 			*ip->curr++ = ((op>>9)&0x07)+'0';
1698 			break;
1699 		case 'y':	/* register number; opcode: [0-2] */
1700 			*ip->curr++ = (op&0x07)+'0';
1701 			break;
1702 		case 'z':	/* shift count; opcode: [9-11] */
1703 			*ip->curr++ = ((op>>9)&0x07)+'0';
1704 			break;
1705 		case 'A':	/* register number; word 2: [0-2] */
1706 			*ip->curr++ = (ip->raw[2]&0x07)+'0';
1707 			break;
1708 		case 'B':	/* float source reg; word 1: [10-12] */
1709 			*ip->curr++ = ((w1>>10)&0x07)+'0';
1710 			break;
1711 		case 'C':	/* cache identifier; opcode: [6-7] */
1712 			bprint(ip, cachetab[(op>>6)&0x03]);
1713 			break;
1714 		case 'D':	/* float dest reg; word 1: [7-9] */
1715 			*ip->curr++ = ((w1>>7)&0x07)+'0';
1716 			break;
1717 		case 'E':	/* destination EA; opcode: [6-11] */
1718 			pea((op>>9)&0x07, ip, &ip->and[currand++]);
1719 			break;
1720 		case 'F':	/* float dest register(s); word 1: [7-9] & [10-12] */
1721 			r1 = (w1>>7)&0x07;
1722 			r2 = (w1>>10)&0x07;
1723 			if (r1 == r2)
1724 				bprint(ip, "F%d", r1);
1725 			else
1726 				bprint(ip, "F%d,F%d", r2, r1);
1727 			break;
1728 		case 'H':	/* MMU register; word 1 [10-13] */
1729 			bprint(ip, mmutab[(w1>>10)&0x03]);
1730 			if (ip->curr[-1] == '?')
1731 				ip->errmsg = "bad mmu register";
1732 			break;
1733 		case 'I':	/* MMU function code mask; word 1: [5-8] */
1734 			bprint(ip, "%x", (w1>>4)&0x0f);
1735 			break;
1736 		case 'K':	/* dynamic k-factor register; word 1: [5-8] */
1737 			bprint(ip, "%d",  (w1>>4)&0x0f);
1738 			break;
1739 		case 'L':	/* MMU function code; word 1: [0-6] */
1740 			if (w1&0x10)
1741 				bprint(ip, "%x", w1&0x0f);
1742 			else if (w1&0x08)
1743 				bprint(ip, "R%d",w1&0x07);
1744 			else if (w1&0x01)
1745 				bprint(ip, "DFC");
1746 			else
1747 				bprint(ip, "SFC");
1748 			break;
1749 		case 'N':	/* control register; word 1: [0-11] */
1750 			r1 = w1&0xfff;
1751 			if (r1&0x800)
1752 				bprint(ip, crtab1[r1&0x07]);
1753 			else
1754 				bprint(ip, crtab0[r1&0x07]);
1755 			break;
1756 		case 'P':	/* conditional predicate; word 1: [0-5] */
1757 			bprint(ip, fcond[w1&0x1f]);
1758 			break;
1759 		case 'R':	/* register type & number; word 2 [12-15] */
1760 			bprint(ip, regname[(ip->raw[2]>>12)&0x0f]);
1761 			break;
1762 		case 'S':	/* float source type code; word 1: [10-12] */
1763 			*ip->curr = typetab[(w1>>10)&0x07];
1764 			if (*ip->curr++ == '?')
1765 				ip->errmsg = "bad float type";
1766 			break;
1767 		case 'U':	/* register number; word 2: [6-8] */
1768 			*ip->curr++ = ((ip->raw[2]>>6)&0x07)+'0';
1769 			break;
1770 		case 'Z':	/* ATC level number; word 1: [10-12] */
1771 			bprint(ip, "%x", (w1>>10)&0x07);
1772 			break;
1773 		case '1':	/* effective address in second operand*/
1774 			pea(op&0x07, ip, &ip->and[1]);
1775 			break;
1776 		default:
1777 			bprint(ip, "%%%c", *fmt);
1778 			break;
1779 		}
1780 	}
1781 	*ip->curr = 0;		/* there's always room for 1 byte */
1782 }
1783 
1784 static int
dispsize(Inst * ip)1785 dispsize(Inst *ip)
1786 {
1787 	ushort ext;
1788 	static int dsize[] = {0, 0, 1, 2};	/* in words */
1789 
1790 	if (get2(mymap, ip->addr+ip->n*2, &ext) < 0)
1791 		return -1;
1792 	if ((ext&0x100) == 0)
1793 		return 1;
1794 	return dsize[(ext>>4)&0x03]+dsize[ext&0x03]+1;
1795 }
1796 
1797 static int
immsize(Inst * ip,int mode)1798 immsize(Inst *ip, int mode)
1799 {
1800 	static int fsize[] = { 2, 2, 6, 12, 1, 4, 1, -1 };
1801 	static int isize[] = { 1, 1, 2, -1 };
1802 
1803 	switch(mode)
1804 	{
1805 	case EAM_B:			/* byte */
1806 	case EAALL_B:
1807 	case EADI_W:			/* word */
1808 	case EAALL_W:
1809 		return 1;
1810 	case EADI_L:			/* long */
1811 	case EAALL_L:
1812 		return 2;
1813 	case EAFLT:	/* floating point - size in bits 10-12 or word 1 */
1814 		return fsize[(ip->raw[1]>>10)&0x07];
1815 	case IV:	/* size encoded in bits 6&7 of opcode word */
1816 	default:
1817 		return isize[(ip->raw[0]>>6)&0x03];
1818 	}
1819 }
1820 
1821 static int
easize(Inst * ip,int ea,int mode)1822 easize(Inst *ip, int ea, int mode)
1823 {
1824 	switch((ea>>3)&0x07)
1825 	{
1826 	case 0x00:
1827 	case 0x01:
1828 	case 0x02:
1829 	case 0x03:
1830 	case 0x04:
1831 		return 0;
1832 	case 0x05:
1833 		return 1;
1834 	case 0x06:
1835 		return dispsize(ip);
1836 	case 0x07:
1837 		switch(ea&0x07)
1838 		{
1839 		case 0x00:
1840 		case 0x02:
1841 			return 1;
1842 		case 0x01:
1843 			return 2;
1844 		case 0x03:
1845 			return dispsize(ip);
1846 		case 0x04:
1847 			return immsize(ip, mode);
1848 		default:
1849 			return -1;
1850 		}
1851 	}
1852 	return -1;
1853 }
1854 
1855 static int
instrsize(Inst * ip,Optable * op)1856 instrsize(Inst *ip, Optable *op)
1857 {
1858 	int i, t, mode;
1859 	short opcode;
1860 
1861 	opcode = ip->raw[0];
1862 	for (i = 0; i < nelem(op->opdata) && op->opdata[i]; i++) {
1863 		mode = op->opdata[i];
1864 		switch(mode)
1865 		{
1866 		case EAPI:		/* normal EA modes */
1867 		case EACA:
1868 		case EACAD:
1869 		case EACAPI:
1870 		case EACAPD:
1871 		case EAMA:
1872 		case EADA:
1873 		case EAA:
1874 		case EAC:
1875 		case EACPI:
1876 		case EACD:
1877 		case EAD:
1878 		case EAM:
1879 		case EAM_B:
1880 		case EADI:
1881 		case EADI_L:
1882 		case EADI_W:
1883 		case EAALL:
1884 		case EAALL_L:
1885 		case EAALL_W:
1886 		case EAALL_B:
1887 		case EAFLT:
1888 			t = easize(ip, opcode&0x3f, mode);
1889 			if (t < 0)
1890 				return -1;
1891 			ip->n += t;
1892 			break;
1893 		case EADDA:	/* stupid bit flop required */
1894 			t = ((opcode>>9)&0x07)|((opcode>>3)&0x38);
1895 			t = easize(ip, t, mode);
1896 			if (t < 0)
1897 				return -1;
1898 			ip->n += t;
1899 			break;
1900 		case BREAC:	/* EAC JMP or CALL operand */
1901 				/* easy displacements for follow set */
1902 			if ((opcode&0x038) == 0x28 || (opcode&0x3f) == 0x3a) {
1903 				if (i16(ip, &ip->and[i].immediate) < 0)
1904 					return -1;
1905 			} else {
1906 				t = easize(ip, opcode&0x3f, mode);
1907 				if (t < 0)
1908 					return -1;
1909 				ip->n += t;
1910 			}
1911 			break;
1912 		case I16:	/* 16 bit immediate */
1913 		case C16:	/* CAS2 16 bit immediate */
1914 			ip->n++;
1915 			break;
1916 		case BR16:	/* 16 bit branch displacement */
1917 			if (i16(ip, &ip->and[i].immediate) < 0)
1918 				return -1;
1919 			break;
1920 		case BR32:	/* 32 bit branch displacement */
1921 			if (i32(ip, &ip->and[i].immediate) < 0)
1922 				return -1;
1923 			break;
1924 		case I32:	/* 32 bit immediate */
1925 			ip->n += 2;
1926 			break;
1927 		case IV:	/* immediate data depends on size field */
1928 			t = (ip->raw[0]>>6)&0x03;
1929 			if (t < 2)
1930 				ip->n++;
1931 			else if (t == 2)
1932 				ip->n += 2;
1933 			else
1934 				return -1;
1935 			break;
1936 		case BR8:	/* loony branch displacement format */
1937 			t = opcode&0xff;
1938 			if (t == 0) {
1939 				if (i16(ip, &ip->and[i].immediate) < 0)
1940 					return -1;
1941 			} else if (t == 0xff) {
1942 				if (i32(ip, &ip->and[i].immediate) < 0)
1943 					return -1;
1944 			} else {
1945 				ip->and[i].immediate = t;
1946 				if (t & 0x80)
1947 					ip->and[i].immediate |= ~0xff;
1948 			}
1949 			break;
1950 		case STACK:	/* Dummy operand for Return instructions */
1951 		case OP8:	/* weird movq instruction */
1952 		case I8:	/* must be two-word opcode */
1953 		default:
1954 			break;
1955 		}
1956 	}
1957 	return 1;
1958 }
1959 
1960 static int
eaval(Inst * ip,Operand * ap,Rgetter rget)1961 eaval(Inst *ip, Operand *ap, Rgetter rget)
1962 {
1963 	int reg;
1964 	char buf[8];
1965 
1966 	reg = ip->raw[0]&0x07;
1967 	switch(ap->eatype)
1968 	{
1969 	case AInd:
1970 		sprint(buf, "A%d", reg);
1971 		return (*rget)(mymap, buf);
1972 	case PDisp:
1973 		return ip->addr+2+ap->disp;
1974 	case ADisp:
1975 		sprint(buf, "A%d", reg);
1976 		return ap->disp+(*rget)(mymap, buf);
1977 	case ABS:
1978 		return ap->immediate;
1979 	default:
1980 		return 0;
1981 	}
1982 }
1983 
1984 static int
m68020instlen(Map * map,uvlong pc)1985 m68020instlen(Map *map, uvlong pc)
1986 {
1987 	Inst i;
1988 	Optable *op;
1989 
1990 	mymap = map;
1991 	i.addr = pc;
1992 	i.errmsg = 0;
1993 	op = instruction(&i);
1994 	if (op && instrsize(&i, op) > 0)
1995 			return i.n*2;
1996 	return -1;
1997 }
1998 
1999 static int
m68020foll(Map * map,uvlong pc,Rgetter rget,uvlong * foll)2000 m68020foll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
2001 {
2002 	int j;
2003 	Inst i;
2004 	ulong l;
2005 	Optable *op;
2006 
2007 	mymap = map;
2008 	i.addr = pc;
2009 	i.errmsg = 0;
2010 	op = instruction(&i);
2011 	if (op == 0  || instrsize(&i, op) < 0)
2012 		return -1;
2013 	for (j = 0; j < nelem(op->opdata) && op->opdata[j]; j++) {
2014 		switch(op->opdata[j])
2015 		{
2016 		case BREAC:	/* CALL, JMP, JSR */
2017 			foll[0] = pc+2+eaval(&i, &i.and[j], rget);
2018 			return 1;
2019 		case BR8:	/* Bcc, BSR, & BRA */
2020 		case BR16:	/* FBcc, FDBcc, DBcc */
2021 		case BR32:	/* FBcc */
2022 			foll[0] = pc+i.n*2;
2023 			foll[1] = pc+2+i.and[j].immediate;
2024 			return 2;
2025 		case STACK:	/* RTR, RTS, RTD */
2026 			if (get4(map, (*rget)(map, mach->sp), &l) < 0)
2027 				return -1;
2028 			*foll = l;
2029 			return 1;
2030 		default:
2031 			break;
2032 		}
2033 	}
2034 	foll[0] = pc+i.n*2;
2035 	return 1;
2036 }
2037 
2038 static int
m68020inst(Map * map,uvlong pc,char modifier,char * buf,int n)2039 m68020inst(Map *map, uvlong pc, char modifier, char *buf, int n)
2040 {
2041 	Inst i;
2042 	Optable *op;
2043 
2044 	USED(modifier);
2045 	mymap = map;
2046 	i.addr = pc;
2047 	i.curr = buf;
2048 	i.end = buf+n-1;
2049 	i.errmsg = 0;
2050 	op = instruction(&i);
2051 	if (!op)
2052 		return -1;
2053 	if (decode(&i, op) > 0)
2054 		formatins(op->format, &i);
2055 	if (i.errmsg) {
2056 		if (i.curr != buf)
2057 			bprint(&i, "\t\t;");
2058 		bprint(&i, "%s: ", i.errmsg);
2059 		dumpinst(&i, i.curr, i.end-i.curr);
2060 	}
2061 	return i.n*2;
2062 }
2063 
2064 static int
m68020das(Map * map,uvlong pc,char * buf,int n)2065 m68020das(Map *map, uvlong pc, char *buf, int n)
2066 {
2067 	Inst i;
2068 	Optable *op;
2069 
2070 	mymap = map;
2071 	i.addr = pc;
2072 	i.curr = buf;
2073 	i.end = buf+n-1;
2074 	i.errmsg = 0;
2075 
2076 	op = instruction(&i);
2077 	if (!op)
2078 		return -1;
2079 	decode(&i, op);
2080 	if (i.errmsg)
2081 		bprint(&i, "%s: ", i.errmsg);
2082 	dumpinst(&i, i.curr, i.end-i.curr);
2083 	return i.n*2;
2084 }
2085