Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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 *
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
}