xref: /plan9/sys/src/libmach/8db.c (revision 3b86f2f88bade1f00206c7aa750b7add255f5724)
1219b2ee8SDavid du Colombier #include <u.h>
2219b2ee8SDavid du Colombier #include <libc.h>
3219b2ee8SDavid du Colombier #include <bio.h>
4219b2ee8SDavid du Colombier #include <mach.h>
5219b2ee8SDavid du Colombier 
6219b2ee8SDavid du Colombier /*
7219b2ee8SDavid du Colombier  * i386-specific debugger interface
8b0dcc5a8SDavid du Colombier  * also amd64 extensions
9219b2ee8SDavid du Colombier  */
10219b2ee8SDavid du Colombier 
11219b2ee8SDavid du Colombier static	char	*i386excep(Map*, Rgetter);
12219b2ee8SDavid du Colombier 
134de34a7eSDavid du Colombier static	int	i386trace(Map*, uvlong, uvlong, uvlong, Tracer);
144de34a7eSDavid du Colombier static	uvlong	i386frame(Map*, uvlong, uvlong, uvlong, uvlong);
154de34a7eSDavid du Colombier static	int	i386foll(Map*, uvlong, Rgetter, uvlong*);
164de34a7eSDavid du Colombier static	int	i386inst(Map*, uvlong, char, char*, int);
174de34a7eSDavid du Colombier static	int	i386das(Map*, uvlong, char*, int);
184de34a7eSDavid du Colombier static	int	i386instlen(Map*, uvlong);
19219b2ee8SDavid du Colombier 
20219b2ee8SDavid du Colombier static	char	STARTSYM[] =	"_main";
21219b2ee8SDavid du Colombier static	char	PROFSYM[] =	"_mainp";
22219b2ee8SDavid du Colombier static	char	FRAMENAME[] =	".frame";
23219b2ee8SDavid du Colombier static char *excname[] =
24219b2ee8SDavid du Colombier {
25219b2ee8SDavid du Colombier [0]	"divide error",
26219b2ee8SDavid du Colombier [1]	"debug exception",
27219b2ee8SDavid du Colombier [4]	"overflow",
28219b2ee8SDavid du Colombier [5]	"bounds check",
29219b2ee8SDavid du Colombier [6]	"invalid opcode",
30219b2ee8SDavid du Colombier [7]	"math coprocessor emulation",
31219b2ee8SDavid du Colombier [8]	"double fault",
32219b2ee8SDavid du Colombier [9]	"math coprocessor overrun",
33219b2ee8SDavid du Colombier [10]	"invalid TSS",
34219b2ee8SDavid du Colombier [11]	"segment not present",
35219b2ee8SDavid du Colombier [12]	"stack exception",
36219b2ee8SDavid du Colombier [13]	"general protection violation",
37219b2ee8SDavid du Colombier [14]	"page fault",
38219b2ee8SDavid du Colombier [16]	"math coprocessor error",
39b0dcc5a8SDavid du Colombier [17]	"alignment check",
40b0dcc5a8SDavid du Colombier [18]	"machine check",
41b0dcc5a8SDavid du Colombier [19]	"floating-point exception",
42219b2ee8SDavid du Colombier [24]	"clock",
43219b2ee8SDavid du Colombier [25]	"keyboard",
44219b2ee8SDavid du Colombier [27]	"modem status",
45219b2ee8SDavid du Colombier [28]	"serial line status",
46219b2ee8SDavid du Colombier [30]	"floppy disk",
47219b2ee8SDavid du Colombier [36]	"mouse",
48219b2ee8SDavid du Colombier [37]	"math coprocessor",
49219b2ee8SDavid du Colombier [38]	"hard disk",
50219b2ee8SDavid du Colombier [64]	"system call",
51219b2ee8SDavid du Colombier };
52219b2ee8SDavid du Colombier 
53219b2ee8SDavid du Colombier Machdata i386mach =
54219b2ee8SDavid du Colombier {
55219b2ee8SDavid du Colombier 	{0xCC, 0, 0, 0},	/* break point: INT 3 */
56219b2ee8SDavid du Colombier 	1,			/* break point size */
57219b2ee8SDavid du Colombier 
58219b2ee8SDavid du Colombier 	leswab,			/* convert short to local byte order */
59219b2ee8SDavid du Colombier 	leswal,			/* convert long to local byte order */
607dd7cddfSDavid du Colombier 	leswav,			/* convert vlong to local byte order */
61219b2ee8SDavid du Colombier 	i386trace,		/* C traceback */
62219b2ee8SDavid du Colombier 	i386frame,		/* frame finder */
63219b2ee8SDavid du Colombier 	i386excep,		/* print exception */
64219b2ee8SDavid du Colombier 	0,			/* breakpoint fixup */
65219b2ee8SDavid du Colombier 	leieeesftos,		/* single precision float printer */
66219b2ee8SDavid du Colombier 	leieeedftos,		/* double precision float printer */
67219b2ee8SDavid du Colombier 	i386foll,		/* following addresses */
68219b2ee8SDavid du Colombier 	i386inst,		/* print instruction */
69219b2ee8SDavid du Colombier 	i386das,		/* dissembler */
70219b2ee8SDavid du Colombier 	i386instlen,		/* instruction size calculation */
71219b2ee8SDavid du Colombier };
72219b2ee8SDavid du Colombier 
73219b2ee8SDavid du Colombier static char*
i386excep(Map * map,Rgetter rget)74219b2ee8SDavid du Colombier i386excep(Map *map, Rgetter rget)
75219b2ee8SDavid du Colombier {
76219b2ee8SDavid du Colombier 	ulong c;
774de34a7eSDavid du Colombier 	uvlong pc;
78219b2ee8SDavid du Colombier 	static char buf[16];
79219b2ee8SDavid du Colombier 
80219b2ee8SDavid du Colombier 	c = (*rget)(map, "TRAP");
81219b2ee8SDavid du Colombier 	if(c > 64 || excname[c] == 0) {
82219b2ee8SDavid du Colombier 		if (c == 3) {
83219b2ee8SDavid du Colombier 			pc = (*rget)(map, "PC");
84219b2ee8SDavid du Colombier 			if (get1(map, pc, (uchar*)buf, machdata->bpsize) > 0)
85219b2ee8SDavid du Colombier 			if (memcmp(buf, machdata->bpinst, machdata->bpsize) == 0)
86219b2ee8SDavid du Colombier 				return "breakpoint";
87219b2ee8SDavid du Colombier 		}
884de34a7eSDavid du Colombier 		snprint(buf, sizeof(buf), "exception %ld", c);
89219b2ee8SDavid du Colombier 		return buf;
90219b2ee8SDavid du Colombier 	} else
91219b2ee8SDavid du Colombier 		return excname[c];
92219b2ee8SDavid du Colombier }
93219b2ee8SDavid du Colombier 
94219b2ee8SDavid du Colombier static int
i386trace(Map * map,uvlong pc,uvlong sp,uvlong link,Tracer trace)954de34a7eSDavid du Colombier i386trace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace)
96219b2ee8SDavid du Colombier {
97219b2ee8SDavid du Colombier 	int i;
984de34a7eSDavid du Colombier 	uvlong osp;
997dd7cddfSDavid du Colombier 	Symbol s, f;
100219b2ee8SDavid du Colombier 
101219b2ee8SDavid du Colombier 	USED(link);
102219b2ee8SDavid du Colombier 	i = 0;
103219b2ee8SDavid du Colombier 	osp = 0;
104219b2ee8SDavid du Colombier 	while(findsym(pc, CTEXT, &s)) {
105219b2ee8SDavid du Colombier 		if (osp == sp)
106219b2ee8SDavid du Colombier 			break;
107219b2ee8SDavid du Colombier 		osp = sp;
1087dd7cddfSDavid du Colombier 
109219b2ee8SDavid du Colombier 		if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
110219b2ee8SDavid du Colombier 			break;
111219b2ee8SDavid du Colombier 
112219b2ee8SDavid du Colombier 		if(pc != s.value) {	/* not at first instruction */
113219b2ee8SDavid du Colombier 			if(findlocal(&s, FRAMENAME, &f) == 0)
114219b2ee8SDavid du Colombier 				break;
115219b2ee8SDavid du Colombier 			sp += f.value-mach->szaddr;
116219b2ee8SDavid du Colombier 		}
117219b2ee8SDavid du Colombier 
1184de34a7eSDavid du Colombier 		if (geta(map, sp, &pc) < 0)
119219b2ee8SDavid du Colombier 			break;
120219b2ee8SDavid du Colombier 
121219b2ee8SDavid du Colombier 		if(pc == 0)
122219b2ee8SDavid du Colombier 			break;
123219b2ee8SDavid du Colombier 
124219b2ee8SDavid du Colombier 		(*trace)(map, pc, sp, &s);
125219b2ee8SDavid du Colombier 		sp += mach->szaddr;
126219b2ee8SDavid du Colombier 
1277dd7cddfSDavid du Colombier 		if(++i > 1000)
128219b2ee8SDavid du Colombier 			break;
129219b2ee8SDavid du Colombier 	}
130219b2ee8SDavid du Colombier 	return i;
131219b2ee8SDavid du Colombier }
132219b2ee8SDavid du Colombier 
1334de34a7eSDavid du Colombier static uvlong
i386frame(Map * map,uvlong addr,uvlong pc,uvlong sp,uvlong link)1344de34a7eSDavid du Colombier i386frame(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong link)
135219b2ee8SDavid du Colombier {
136219b2ee8SDavid du Colombier 	Symbol s, f;
137219b2ee8SDavid du Colombier 
138219b2ee8SDavid du Colombier 	USED(link);
139219b2ee8SDavid du Colombier 	while (findsym(pc, CTEXT, &s)) {
140219b2ee8SDavid du Colombier 		if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
141219b2ee8SDavid du Colombier 			break;
142219b2ee8SDavid du Colombier 
143219b2ee8SDavid du Colombier 		if(pc != s.value) {	/* not first instruction */
144219b2ee8SDavid du Colombier 			if(findlocal(&s, FRAMENAME, &f) == 0)
145219b2ee8SDavid du Colombier 				break;
146219b2ee8SDavid du Colombier 			sp += f.value-mach->szaddr;
147219b2ee8SDavid du Colombier 		}
148219b2ee8SDavid du Colombier 
149219b2ee8SDavid du Colombier 		if (s.value == addr)
150219b2ee8SDavid du Colombier 			return sp;
151219b2ee8SDavid du Colombier 
1524de34a7eSDavid du Colombier 		if (geta(map, sp, &pc) < 0)
153219b2ee8SDavid du Colombier 			break;
154219b2ee8SDavid du Colombier 		sp += mach->szaddr;
155219b2ee8SDavid du Colombier 	}
156219b2ee8SDavid du Colombier 	return 0;
157219b2ee8SDavid du Colombier }
158219b2ee8SDavid du Colombier 
159219b2ee8SDavid du Colombier 	/* I386/486 - Disassembler and related functions */
160219b2ee8SDavid du Colombier 
161219b2ee8SDavid du Colombier /*
162219b2ee8SDavid du Colombier  *  an instruction
163219b2ee8SDavid du Colombier  */
164219b2ee8SDavid du Colombier typedef struct Instr Instr;
165219b2ee8SDavid du Colombier struct	Instr
166219b2ee8SDavid du Colombier {
167219b2ee8SDavid du Colombier 	uchar	mem[1+1+1+1+2+1+1+4+4];		/* raw instruction */
1684de34a7eSDavid du Colombier 	uvlong	addr;		/* address of start of instruction */
169219b2ee8SDavid du Colombier 	int	n;		/* number of bytes in instruction */
170219b2ee8SDavid du Colombier 	char	*prefix;	/* instr prefix */
171219b2ee8SDavid du Colombier 	char	*segment;	/* segment override */
172219b2ee8SDavid du Colombier 	uchar	jumptype;	/* set to the operand type for jump/ret/call */
173b0dcc5a8SDavid du Colombier 	uchar	amd64;
174b0dcc5a8SDavid du Colombier 	uchar	rex;		/* REX prefix (or zero) */
175b0dcc5a8SDavid du Colombier 	char	osize;		/* 'W' or 'L' (or 'Q' on amd64) */
176b0dcc5a8SDavid du Colombier 	char	asize;		/* address size 'W' or 'L' (or 'Q' or amd64) */
177219b2ee8SDavid du Colombier 	uchar	mod;		/* bits 6-7 of mod r/m field */
178219b2ee8SDavid du Colombier 	uchar	reg;		/* bits 3-5 of mod r/m field */
179219b2ee8SDavid du Colombier 	char	ss;		/* bits 6-7 of SIB */
180219b2ee8SDavid du Colombier 	char	index;		/* bits 3-5 of SIB */
181219b2ee8SDavid du Colombier 	char	base;		/* bits 0-2 of SIB */
182b0dcc5a8SDavid du Colombier 	char	rip;		/* RIP-relative in amd64 mode */
183b0dcc5a8SDavid du Colombier 	uchar	opre;		/* f2/f3 could introduce media */
184219b2ee8SDavid du Colombier 	short	seg;		/* segment of far address */
185219b2ee8SDavid du Colombier 	ulong	disp;		/* displacement */
186219b2ee8SDavid du Colombier 	ulong 	imm;		/* immediate */
187219b2ee8SDavid du Colombier 	ulong 	imm2;		/* second immediate operand */
188b0dcc5a8SDavid du Colombier 	uvlong	imm64;		/* big immediate */
189219b2ee8SDavid du Colombier 	char	*curr;		/* fill level in output buffer */
190219b2ee8SDavid du Colombier 	char	*end;		/* end of output buffer */
191219b2ee8SDavid du Colombier 	char	*err;		/* error message */
192219b2ee8SDavid du Colombier };
193219b2ee8SDavid du Colombier 
194219b2ee8SDavid du Colombier 	/* 386 register (ha!) set */
195219b2ee8SDavid du Colombier enum{
196219b2ee8SDavid du Colombier 	AX=0,
197219b2ee8SDavid du Colombier 	CX,
198219b2ee8SDavid du Colombier 	DX,
199219b2ee8SDavid du Colombier 	BX,
200219b2ee8SDavid du Colombier 	SP,
201219b2ee8SDavid du Colombier 	BP,
202219b2ee8SDavid du Colombier 	SI,
203219b2ee8SDavid du Colombier 	DI,
204b0dcc5a8SDavid du Colombier 
205b0dcc5a8SDavid du Colombier 	/* amd64 */
206b0dcc5a8SDavid du Colombier 	R8,
207b0dcc5a8SDavid du Colombier 	R9,
208b0dcc5a8SDavid du Colombier 	R10,
209b0dcc5a8SDavid du Colombier 	R11,
210b0dcc5a8SDavid du Colombier 	R12,
211b0dcc5a8SDavid du Colombier 	R13,
212b0dcc5a8SDavid du Colombier 	R14,
213b0dcc5a8SDavid du Colombier 	R15
214219b2ee8SDavid du Colombier };
215b0dcc5a8SDavid du Colombier 
216b0dcc5a8SDavid du Colombier 	/* amd64 rex extension byte */
217b0dcc5a8SDavid du Colombier enum{
218b0dcc5a8SDavid du Colombier 	REXW		= 1<<3,	/* =1, 64-bit operand size */
219b0dcc5a8SDavid du Colombier 	REXR		= 1<<2,	/* extend modrm reg */
220b0dcc5a8SDavid du Colombier 	REXX		= 1<<1,	/* extend sib index */
221b0dcc5a8SDavid du Colombier 	REXB		= 1<<0	/* extend modrm r/m, sib base, or opcode reg */
222b0dcc5a8SDavid du Colombier };
223b0dcc5a8SDavid du Colombier 
224219b2ee8SDavid du Colombier 	/* Operand Format codes */
225219b2ee8SDavid du Colombier /*
226219b2ee8SDavid du Colombier %A	-	address size register modifier (!asize -> 'E')
227219b2ee8SDavid du Colombier %C	-	Control register CR0/CR1/CR2
228219b2ee8SDavid du Colombier %D	-	Debug register DR0/DR1/DR2/DR3/DR6/DR7
229219b2ee8SDavid du Colombier %I	-	second immediate operand
230219b2ee8SDavid du Colombier %O	-	Operand size register modifier (!osize -> 'E')
231219b2ee8SDavid du Colombier %T	-	Test register TR6/TR7
232219b2ee8SDavid du Colombier %S	-	size code ('W' or 'L')
233b0dcc5a8SDavid du Colombier %W	-	Weird opcode: OSIZE == 'W' => "CBW"; else => "CWDE"
234219b2ee8SDavid du Colombier %d	-	displacement 16-32 bits
235219b2ee8SDavid du Colombier %e	-	effective address - Mod R/M value
236219b2ee8SDavid du Colombier %f	-	floating point register F0-F7 - from Mod R/M register
237219b2ee8SDavid du Colombier %g	-	segment register
238219b2ee8SDavid du Colombier %i	-	immediate operand 8-32 bits
239219b2ee8SDavid du Colombier %p	-	PC-relative - signed displacement in immediate field
240219b2ee8SDavid du Colombier %r	-	Reg from Mod R/M
241b0dcc5a8SDavid du Colombier %w	-	Weird opcode: OSIZE == 'W' => "CWD"; else => "CDQ"
242219b2ee8SDavid du Colombier */
243219b2ee8SDavid du Colombier 
244219b2ee8SDavid du Colombier typedef struct Optable Optable;
245219b2ee8SDavid du Colombier struct Optable
246219b2ee8SDavid du Colombier {
247219b2ee8SDavid du Colombier 	char	operand[2];
248219b2ee8SDavid du Colombier 	void	*proto;		/* actually either (char*) or (Optable*) */
249219b2ee8SDavid du Colombier };
250219b2ee8SDavid du Colombier 	/* Operand decoding codes */
251219b2ee8SDavid du Colombier enum {
252219b2ee8SDavid du Colombier 	Ib = 1,			/* 8-bit immediate - (no sign extension)*/
253219b2ee8SDavid du Colombier 	Ibs,			/* 8-bit immediate (sign extended) */
254219b2ee8SDavid du Colombier 	Jbs,			/* 8-bit sign-extended immediate in jump or call */
255219b2ee8SDavid du Colombier 	Iw,			/* 16-bit immediate -> imm */
256219b2ee8SDavid du Colombier 	Iw2,			/* 16-bit immediate -> imm2 */
257219b2ee8SDavid du Colombier 	Iwd,			/* Operand-sized immediate (no sign extension)*/
258b0dcc5a8SDavid du Colombier 	Iwdq,			/* Operand-sized immediate, possibly 64 bits */
259219b2ee8SDavid du Colombier 	Awd,			/* Address offset */
260219b2ee8SDavid du Colombier 	Iwds,			/* Operand-sized immediate (sign extended) */
261219b2ee8SDavid du Colombier 	RM,			/* Word or long R/M field with register (/r) */
262219b2ee8SDavid du Colombier 	RMB,			/* Byte R/M field with register (/r) */
263219b2ee8SDavid du Colombier 	RMOP,			/* Word or long R/M field with op code (/digit) */
264219b2ee8SDavid du Colombier 	RMOPB,			/* Byte R/M field with op code (/digit) */
265219b2ee8SDavid du Colombier 	RMR,			/* R/M register only (mod = 11) */
266219b2ee8SDavid du Colombier 	RMM,			/* R/M memory only (mod = 0/1/2) */
267219b2ee8SDavid du Colombier 	R0,			/* Base reg of Mod R/M is literal 0x00 */
268219b2ee8SDavid du Colombier 	R1,			/* Base reg of Mod R/M is literal 0x01 */
269219b2ee8SDavid du Colombier 	FRMOP,			/* Floating point R/M field with opcode */
270219b2ee8SDavid du Colombier 	FRMEX,			/* Extended floating point R/M field with opcode */
271219b2ee8SDavid du Colombier 	JUMP,			/* Jump or Call flag - no operand */
272219b2ee8SDavid du Colombier 	RET,			/* Return flag - no operand */
273219b2ee8SDavid du Colombier 	OA,			/* literal 0x0a byte */
274219b2ee8SDavid du Colombier 	PTR,			/* Seg:Displacement addr (ptr16:16 or ptr16:32) */
275219b2ee8SDavid du Colombier 	AUX,			/* Multi-byte op code - Auxiliary table */
276b0dcc5a8SDavid du Colombier 	AUXMM,			/* multi-byte op code - auxiliary table chosen by prefix */
277219b2ee8SDavid du Colombier 	PRE,			/* Instr Prefix */
278b0dcc5a8SDavid du Colombier 	OPRE,			/* Instr Prefix or media op extension */
279219b2ee8SDavid du Colombier 	SEG,			/* Segment Prefix */
280219b2ee8SDavid du Colombier 	OPOVER,			/* Operand size override */
281219b2ee8SDavid du Colombier 	ADDOVER,		/* Address size override */
282219b2ee8SDavid du Colombier };
283219b2ee8SDavid du Colombier 
284219b2ee8SDavid du Colombier static Optable optab0F00[8]=
285219b2ee8SDavid du Colombier {
286219b2ee8SDavid du Colombier [0x00]	0,0,		"MOVW	LDT,%e",
287219b2ee8SDavid du Colombier [0x01]	0,0,		"MOVW	TR,%e",
288219b2ee8SDavid du Colombier [0x02]	0,0,		"MOVW	%e,LDT",
289219b2ee8SDavid du Colombier [0x03]	0,0,		"MOVW	%e,TR",
290219b2ee8SDavid du Colombier [0x04]	0,0,		"VERR	%e",
291219b2ee8SDavid du Colombier [0x05]	0,0,		"VERW	%e",
292219b2ee8SDavid du Colombier };
293219b2ee8SDavid du Colombier 
294219b2ee8SDavid du Colombier static Optable optab0F01[8]=
295219b2ee8SDavid du Colombier {
296219b2ee8SDavid du Colombier [0x00]	0,0,		"MOVL	GDTR,%e",
297219b2ee8SDavid du Colombier [0x01]	0,0,		"MOVL	IDTR,%e",
298219b2ee8SDavid du Colombier [0x02]	0,0,		"MOVL	%e,GDTR",
299219b2ee8SDavid du Colombier [0x03]	0,0,		"MOVL	%e,IDTR",
300219b2ee8SDavid du Colombier [0x04]	0,0,		"MOVW	MSW,%e",	/* word */
301219b2ee8SDavid du Colombier [0x06]	0,0,		"MOVW	%e,MSW",	/* word */
302d5d7c35bSDavid du Colombier [0x07]	0,0,		"INVLPG	%e",		/* or SWAPGS */
303d5d7c35bSDavid du Colombier };
304d5d7c35bSDavid du Colombier 
305d5d7c35bSDavid du Colombier static Optable optab0F01F8[1]=
306d5d7c35bSDavid du Colombier {
307d5d7c35bSDavid du Colombier [0x00]	0,0,		"SWAPGS",
308219b2ee8SDavid du Colombier };
309219b2ee8SDavid du Colombier 
310b0dcc5a8SDavid du Colombier /* 0F71 */
311b0dcc5a8SDavid du Colombier /* 0F72 */
312b0dcc5a8SDavid du Colombier /* 0F73 */
313b0dcc5a8SDavid du Colombier 
314b0dcc5a8SDavid du Colombier static Optable optab0FAE[8]=
315b0dcc5a8SDavid du Colombier {
316b0dcc5a8SDavid du Colombier [0x00]	0,0,		"FXSAVE	%e",
317b0dcc5a8SDavid du Colombier [0x01]	0,0,		"FXRSTOR	%e",
318b0dcc5a8SDavid du Colombier [0x02]	0,0,		"LDMXCSR	%e",
319b0dcc5a8SDavid du Colombier [0x03]	0,0,		"STMXCSR	%e",
320b0dcc5a8SDavid du Colombier [0x05]	0,0,		"LFENCE",
321b0dcc5a8SDavid du Colombier [0x06]	0,0,		"MFENCE",
322b0dcc5a8SDavid du Colombier [0x07]	0,0,		"SFENCE",
323b0dcc5a8SDavid du Colombier };
324b0dcc5a8SDavid du Colombier 
325b0dcc5a8SDavid du Colombier /* 0F18 */
326b0dcc5a8SDavid du Colombier /* 0F0D */
327b0dcc5a8SDavid du Colombier 
328219b2ee8SDavid du Colombier static Optable optab0FBA[8]=
329219b2ee8SDavid du Colombier {
330219b2ee8SDavid du Colombier [0x04]	Ib,0,		"BT%S	%i,%e",
331219b2ee8SDavid du Colombier [0x05]	Ib,0,		"BTS%S	%i,%e",
332219b2ee8SDavid du Colombier [0x06]	Ib,0,		"BTR%S	%i,%e",
333219b2ee8SDavid du Colombier [0x07]	Ib,0,		"BTC%S	%i,%e",
334219b2ee8SDavid du Colombier };
335219b2ee8SDavid du Colombier 
336b0dcc5a8SDavid du Colombier static Optable optab0F0F[256]=
337b0dcc5a8SDavid du Colombier {
338b0dcc5a8SDavid du Colombier [0x0c]	0,0,		"PI2FW	%m,%M",
339b0dcc5a8SDavid du Colombier [0x0d]	0,0,		"PI2L	%m,%M",
340b0dcc5a8SDavid du Colombier [0x1c]	0,0,		"PF2IW	%m,%M",
341b0dcc5a8SDavid du Colombier [0x1d]	0,0,		"PF2IL	%m,%M",
342b0dcc5a8SDavid du Colombier [0x8a]	0,0,		"PFNACC	%m,%M",
343b0dcc5a8SDavid du Colombier [0x8e]	0,0,		"PFPNACC	%m,%M",
344b0dcc5a8SDavid du Colombier [0x90]	0,0,		"PFCMPGE	%m,%M",
345b0dcc5a8SDavid du Colombier [0x94]	0,0,		"PFMIN	%m,%M",
346b0dcc5a8SDavid du Colombier [0x96]	0,0,		"PFRCP	%m,%M",
347b0dcc5a8SDavid du Colombier [0x97]	0,0,		"PFRSQRT	%m,%M",
348b0dcc5a8SDavid du Colombier [0x9a]	0,0,		"PFSUB	%m,%M",
349b0dcc5a8SDavid du Colombier [0x9e]	0,0,		"PFADD	%m,%M",
350b0dcc5a8SDavid du Colombier [0xa0]	0,0,		"PFCMPGT	%m,%M",
351b0dcc5a8SDavid du Colombier [0xa4]	0,0,		"PFMAX	%m,%M",
352b0dcc5a8SDavid du Colombier [0xa6]	0,0,		"PFRCPIT1	%m,%M",
353b0dcc5a8SDavid du Colombier [0xa7]	0,0,		"PFRSQIT1	%m,%M",
354b0dcc5a8SDavid du Colombier [0xaa]	0,0,		"PFSUBR	%m,%M",
355b0dcc5a8SDavid du Colombier [0xae]	0,0,		"PFACC	%m,%M",
356b0dcc5a8SDavid du Colombier [0xb0]	0,0,		"PFCMPEQ	%m,%M",
357b0dcc5a8SDavid du Colombier [0xb4]	0,0,		"PFMUL	%m,%M",
358b0dcc5a8SDavid du Colombier [0xb6]	0,0,		"PFRCPI2T	%m,%M",
359b0dcc5a8SDavid du Colombier [0xb7]	0,0,		"PMULHRW	%m,%M",
360b0dcc5a8SDavid du Colombier [0xbb]	0,0,		"PSWAPL	%m,%M",
361b0dcc5a8SDavid du Colombier };
362b0dcc5a8SDavid du Colombier 
363b0dcc5a8SDavid du Colombier static Optable optab0FC7[8]=
364b0dcc5a8SDavid du Colombier {
365b0dcc5a8SDavid du Colombier [0x01]	0,0,		"CMPXCHG8B	%e",
366b0dcc5a8SDavid du Colombier };
367b0dcc5a8SDavid du Colombier 
368b0dcc5a8SDavid du Colombier static Optable optab660F71[8]=
369b0dcc5a8SDavid du Colombier {
370b0dcc5a8SDavid du Colombier [0x02]	Ib,0,		"PSRLW	%i,%X",
371b0dcc5a8SDavid du Colombier [0x04]	Ib,0,		"PSRAW	%i,%X",
372b0dcc5a8SDavid du Colombier [0x06]	Ib,0,		"PSLLW	%i,%X",
373b0dcc5a8SDavid du Colombier };
374b0dcc5a8SDavid du Colombier 
375b0dcc5a8SDavid du Colombier static Optable optab660F72[8]=
376b0dcc5a8SDavid du Colombier {
377b0dcc5a8SDavid du Colombier [0x02]	Ib,0,		"PSRLL	%i,%X",
378b0dcc5a8SDavid du Colombier [0x04]	Ib,0,		"PSRAL	%i,%X",
379b0dcc5a8SDavid du Colombier [0x06]	Ib,0,		"PSLLL	%i,%X",
380b0dcc5a8SDavid du Colombier };
381b0dcc5a8SDavid du Colombier 
382b0dcc5a8SDavid du Colombier static Optable optab660F73[8]=
383b0dcc5a8SDavid du Colombier {
384b0dcc5a8SDavid du Colombier [0x02]	Ib,0,		"PSRLQ	%i,%X",
385b0dcc5a8SDavid du Colombier [0x03]	Ib,0,		"PSRLO	%i,%X",
386b0dcc5a8SDavid du Colombier [0x06]	Ib,0,		"PSLLQ	%i,%X",
387b0dcc5a8SDavid du Colombier [0x07]	Ib,0,		"PSLLO	%i,%X",
388b0dcc5a8SDavid du Colombier };
389b0dcc5a8SDavid du Colombier 
390b0dcc5a8SDavid du Colombier static Optable optab660F[256]=
391b0dcc5a8SDavid du Colombier {
392b0dcc5a8SDavid du Colombier [0x2B]	RM,0,		"MOVNTPD	%x,%e",
393b0dcc5a8SDavid du Colombier [0x2E]	RM,0,		"UCOMISD	%x,%X",
394b0dcc5a8SDavid du Colombier [0x2F]	RM,0,		"COMISD	%x,%X",
395b0dcc5a8SDavid du Colombier [0x5A]	RM,0,		"CVTPD2PS	%x,%X",
396b0dcc5a8SDavid du Colombier [0x5B]	RM,0,		"CVTPS2PL	%x,%X",
397b0dcc5a8SDavid du Colombier [0x6A]	RM,0,		"PUNPCKHLQ %x,%X",
398b0dcc5a8SDavid du Colombier [0x6B]	RM,0,		"PACKSSLW %x,%X",
399b0dcc5a8SDavid du Colombier [0x6C]	RM,0,		"PUNPCKLQDQ %x,%X",
400b0dcc5a8SDavid du Colombier [0x6D]	RM,0,		"PUNPCKHQDQ %x,%X",
401b0dcc5a8SDavid du Colombier [0x6E]	RM,0,		"MOV%S	%e,%X",
402b0dcc5a8SDavid du Colombier [0x6F]	RM,0,		"MOVO	%x,%X",		/* MOVDQA */
403b0dcc5a8SDavid du Colombier [0x70]	RM,Ib,		"PSHUFL	%i,%x,%X",
404b0dcc5a8SDavid du Colombier [0x71]	RMOP,0,		optab660F71,
405b0dcc5a8SDavid du Colombier [0x72]	RMOP,0,		optab660F72,
406b0dcc5a8SDavid du Colombier [0x73]	RMOP,0,		optab660F73,
407b0dcc5a8SDavid du Colombier [0x7E]	RM,0,		"MOV%S	%X,%e",
408b0dcc5a8SDavid du Colombier [0x7F]	RM,0,		"MOVO	%X,%x",
409b0dcc5a8SDavid du Colombier [0xC4]	RM,Ib,		"PINSRW	%i,%e,%X",
410b0dcc5a8SDavid du Colombier [0xC5]	RMR,Ib,		"PEXTRW	%i,%X,%e",
411b0dcc5a8SDavid du Colombier [0xD4]	RM,0,		"PADDQ	%x,%X",
412b0dcc5a8SDavid du Colombier [0xD5]	RM,0,		"PMULLW	%x,%X",
413b0dcc5a8SDavid du Colombier [0xD6]	RM,0,		"MOVQ	%X,%x",
414b0dcc5a8SDavid du Colombier [0xE6]	RM,0,		"CVTTPD2PL	%x,%X",
415b0dcc5a8SDavid du Colombier [0xE7]	RM,0,		"MOVNTO	%X,%e",
416b0dcc5a8SDavid du Colombier [0xF7]	RM,0,		"MASKMOVOU	%x,%X",
417b0dcc5a8SDavid du Colombier };
418b0dcc5a8SDavid du Colombier 
419b0dcc5a8SDavid du Colombier static Optable optabF20F[256]=
420b0dcc5a8SDavid du Colombier {
421b0dcc5a8SDavid du Colombier [0x10]	RM,0,		"MOVSD	%x,%X",
422b0dcc5a8SDavid du Colombier [0x11]	RM,0,		"MOVSD	%X,%x",
423b0dcc5a8SDavid du Colombier [0x2A]	RM,0,		"CVTS%S2SD	%e,%X",
424b0dcc5a8SDavid du Colombier [0x2C]	RM,0,		"CVTTSD2S%S	%x,%r",
425b0dcc5a8SDavid du Colombier [0x2D]	RM,0,		"CVTSD2S%S	%x,%r",
426b0dcc5a8SDavid du Colombier [0x5A]	RM,0,		"CVTSD2SS	%x,%X",
427b0dcc5a8SDavid du Colombier [0x6F]	RM,0,		"MOVOU	%x,%X",
428b0dcc5a8SDavid du Colombier [0x70]	RM,Ib,		"PSHUFLW	%i,%x,%X",
429b0dcc5a8SDavid du Colombier [0x7F]	RM,0,		"MOVOU	%X,%x",
430b0dcc5a8SDavid du Colombier [0xD6]	RM,0,		"MOVQOZX	%M,%X",
431b0dcc5a8SDavid du Colombier [0xE6]	RM,0,		"CVTPD2PL	%x,%X",
432b0dcc5a8SDavid du Colombier };
433b0dcc5a8SDavid du Colombier 
434b0dcc5a8SDavid du Colombier static Optable optabF30F[256]=
435b0dcc5a8SDavid du Colombier {
436b0dcc5a8SDavid du Colombier [0x10]	RM,0,		"MOVSS	%x,%X",
437b0dcc5a8SDavid du Colombier [0x11]	RM,0,		"MOVSS	%X,%x",
438b0dcc5a8SDavid du Colombier [0x2A]	RM,0,		"CVTS%S2SS	%e,%X",
439b0dcc5a8SDavid du Colombier [0x2C]	RM,0,		"CVTTSS2S%S	%x,%r",
440b0dcc5a8SDavid du Colombier [0x2D]	RM,0,		"CVTSS2S%S	%x,%r",
441b0dcc5a8SDavid du Colombier [0x5A]	RM,0,		"CVTSS2SD	%x,%X",
442b0dcc5a8SDavid du Colombier [0x5B]	RM,0,		"CVTTPS2PL	%x,%X",
443b0dcc5a8SDavid du Colombier [0x6F]	RM,0,		"MOVOU	%x,%X",
444b0dcc5a8SDavid du Colombier [0x70]	RM,Ib,		"PSHUFHW	%i,%x,%X",
445b0dcc5a8SDavid du Colombier [0x7E]	RM,0,		"MOVQOZX	%x,%X",
446b0dcc5a8SDavid du Colombier [0x7F]	RM,0,		"MOVOU	%X,%x",
447b0dcc5a8SDavid du Colombier [0xD6]	RM,0,		"MOVQOZX	%m*,%X",
448b0dcc5a8SDavid du Colombier [0xE6]	RM,0,		"CVTPL2PD	%x,%X",
449b0dcc5a8SDavid du Colombier };
450b0dcc5a8SDavid du Colombier 
451219b2ee8SDavid du Colombier static Optable optab0F[256]=
452219b2ee8SDavid du Colombier {
453219b2ee8SDavid du Colombier [0x00]	RMOP,0,		optab0F00,
454219b2ee8SDavid du Colombier [0x01]	RMOP,0,		optab0F01,
455219b2ee8SDavid du Colombier [0x02]	RM,0,		"LAR	%e,%r",
456219b2ee8SDavid du Colombier [0x03]	RM,0,		"LSL	%e,%r",
4574de34a7eSDavid du Colombier [0x05]	0,0,		"SYSCALL",
458219b2ee8SDavid du Colombier [0x06]	0,0,		"CLTS",
459b0dcc5a8SDavid du Colombier [0x07]	0,0,		"SYSRET",
460219b2ee8SDavid du Colombier [0x08]	0,0,		"INVD",
461219b2ee8SDavid du Colombier [0x09]	0,0,		"WBINVD",
4624de34a7eSDavid du Colombier [0x0B]	0,0,		"UD2",
463b0dcc5a8SDavid du Colombier [0x0F]	RM,AUX,		optab0F0F,		/* 3DNow! */
464b0dcc5a8SDavid du Colombier [0x10]	RM,0,		"MOVU%s	%x,%X",
465b0dcc5a8SDavid du Colombier [0x11]	RM,0,		"MOVU%s	%X,%x",
466b0dcc5a8SDavid du Colombier [0x12]	RM,0,		"MOV[H]L%s	%x,%X",	/* TO DO: H if source is XMM */
467b0dcc5a8SDavid du Colombier [0x13]	RM,0,		"MOVL%s	%X,%e",
468b0dcc5a8SDavid du Colombier [0x14]	RM,0,		"UNPCKL%s	%x,%X",
469b0dcc5a8SDavid du Colombier [0x15]	RM,0,		"UNPCKH%s	%x,%X",
470b0dcc5a8SDavid du Colombier [0x16]	RM,0,		"MOV[L]H%s	%x,%X",	/* TO DO: L if source is XMM */
471b0dcc5a8SDavid du Colombier [0x17]	RM,0,		"MOVH%s	%X,%x",
472219b2ee8SDavid du Colombier [0x20]	RMR,0,		"MOVL	%C,%e",
473219b2ee8SDavid du Colombier [0x21]	RMR,0,		"MOVL	%D,%e",
474219b2ee8SDavid du Colombier [0x22]	RMR,0,		"MOVL	%e,%C",
475219b2ee8SDavid du Colombier [0x23]	RMR,0,		"MOVL	%e,%D",
476219b2ee8SDavid du Colombier [0x24]	RMR,0,		"MOVL	%T,%e",
477219b2ee8SDavid du Colombier [0x26]	RMR,0,		"MOVL	%e,%T",
478b0dcc5a8SDavid du Colombier [0x28]	RM,0,		"MOVA%s	%x,%X",
479b0dcc5a8SDavid du Colombier [0x29]	RM,0,		"MOVA%s	%X,%x",
480b0dcc5a8SDavid du Colombier [0x2A]	RM,0,		"CVTPL2%s	%m*,%X",
481b0dcc5a8SDavid du Colombier [0x2B]	RM,0,		"MOVNT%s	%X,%e",
482b0dcc5a8SDavid du Colombier [0x2C]	RM,0,		"CVTT%s2PL	%x,%M",
483b0dcc5a8SDavid du Colombier [0x2D]	RM,0,		"CVT%s2PL	%x,%M",
484b0dcc5a8SDavid du Colombier [0x2E]	RM,0,		"UCOMISS	%x,%X",
485b0dcc5a8SDavid du Colombier [0x2F]	RM,0,		"COMISS	%x,%X",
486219b2ee8SDavid du Colombier [0x30]	0,0,		"WRMSR",
487219b2ee8SDavid du Colombier [0x31]	0,0,		"RDTSC",
488219b2ee8SDavid du Colombier [0x32]	0,0,		"RDMSR",
489b0dcc5a8SDavid du Colombier [0x33]	0,0,		"RDPMC",
4907dd7cddfSDavid du Colombier [0x42]	RM,0,		"CMOVC	%e,%r",		/* CF */
4917dd7cddfSDavid du Colombier [0x43]	RM,0,		"CMOVNC	%e,%r",		/* ¬ CF */
4927dd7cddfSDavid du Colombier [0x44]	RM,0,		"CMOVZ	%e,%r",		/* ZF */
4937dd7cddfSDavid du Colombier [0x45]	RM,0,		"CMOVNZ	%e,%r",		/* ¬ ZF */
4947dd7cddfSDavid du Colombier [0x46]	RM,0,		"CMOVBE	%e,%r",		/* CF ∨ ZF */
4957dd7cddfSDavid du Colombier [0x47]	RM,0,		"CMOVA	%e,%r",		/* ¬CF ∧ ¬ZF */
4967dd7cddfSDavid du Colombier [0x48]	RM,0,		"CMOVS	%e,%r",		/* SF */
4977dd7cddfSDavid du Colombier [0x49]	RM,0,		"CMOVNS	%e,%r",		/* ¬ SF */
4987dd7cddfSDavid du Colombier [0x4A]	RM,0,		"CMOVP	%e,%r",		/* PF */
4997dd7cddfSDavid du Colombier [0x4B]	RM,0,		"CMOVNP	%e,%r",		/* ¬ PF */
5007dd7cddfSDavid du Colombier [0x4C]	RM,0,		"CMOVLT	%e,%r",		/* LT ≡ OF ≠ SF */
5017dd7cddfSDavid du Colombier [0x4D]	RM,0,		"CMOVGE	%e,%r",		/* GE ≡ ZF ∨ SF */
5027dd7cddfSDavid du Colombier [0x4E]	RM,0,		"CMOVLE	%e,%r",		/* LE ≡ ZF ∨ LT */
5037dd7cddfSDavid du Colombier [0x4F]	RM,0,		"CMOVGT	%e,%r",		/* GT ≡ ¬ZF ∧ GE */
504b0dcc5a8SDavid du Colombier [0x50]	RM,0,		"MOVMSK%s	%X,%r",	/* TO DO: check */
505b0dcc5a8SDavid du Colombier [0x51]	RM,0,		"SQRT%s	%x,%X",
506b0dcc5a8SDavid du Colombier [0x52]	RM,0,		"RSQRT%s	%x,%X",
507b0dcc5a8SDavid du Colombier [0x53]	RM,0,		"RCP%s	%x,%X",
508b0dcc5a8SDavid du Colombier [0x54]	RM,0,		"AND%s	%x,%X",
509b0dcc5a8SDavid du Colombier [0x55]	RM,0,		"ANDN%s	%x,%X",
510b0dcc5a8SDavid du Colombier [0x56]	RM,0,		"OR%s	%x,%X",		/* TO DO: S/D */
511b0dcc5a8SDavid du Colombier [0x57]	RM,0,		"XOR%s	%x,%X",		/* S/D */
512b0dcc5a8SDavid du Colombier [0x58]	RM,0,		"ADD%s	%x,%X",		/* S/P S/D */
513b0dcc5a8SDavid du Colombier [0x59]	RM,0,		"MUL%s	%x,%X",
514b0dcc5a8SDavid du Colombier [0x5A]	RM,0,		"CVTPS2PD	%x,%X",
515b0dcc5a8SDavid du Colombier [0x5B]	RM,0,		"CVTPL2PS	%x,%X",
516b0dcc5a8SDavid du Colombier [0x5C]	RM,0,		"SUB%s	%x,%X",
517b0dcc5a8SDavid du Colombier [0x5D]	RM,0,		"MIN%s	%x,%X",
518b0dcc5a8SDavid du Colombier [0x5E]	RM,0,		"DIV%s	%x,%X",		/* TO DO: S/P S/D */
519b0dcc5a8SDavid du Colombier [0x5F]	RM,0,		"MAX%s	%x,%X",
520b0dcc5a8SDavid du Colombier [0x60]	RM,0,		"PUNPCKLBW %m,%M",
521b0dcc5a8SDavid du Colombier [0x61]	RM,0,		"PUNPCKLWL %m,%M",
522b0dcc5a8SDavid du Colombier [0x62]	RM,0,		"PUNPCKLLQ %m,%M",
523b0dcc5a8SDavid du Colombier [0x63]	RM,0,		"PACKSSWB %m,%M",
524b0dcc5a8SDavid du Colombier [0x64]	RM,0,		"PCMPGTB %m,%M",
525b0dcc5a8SDavid du Colombier [0x65]	RM,0,		"PCMPGTW %m,%M",
526b0dcc5a8SDavid du Colombier [0x66]	RM,0,		"PCMPGTL %m,%M",
527b0dcc5a8SDavid du Colombier [0x67]	RM,0,		"PACKUSWB %m,%M",
528b0dcc5a8SDavid du Colombier [0x68]	RM,0,		"PUNPCKHBW %m,%M",
529b0dcc5a8SDavid du Colombier [0x69]	RM,0,		"PUNPCKHWL %m,%M",
530b0dcc5a8SDavid du Colombier [0x6A]	RM,0,		"PUNPCKHLQ %m,%M",
531b0dcc5a8SDavid du Colombier [0x6B]	RM,0,		"PACKSSLW %m,%M",
532b0dcc5a8SDavid du Colombier [0x6E]	RM,0,		"MOV%S %e,%M",
533b0dcc5a8SDavid du Colombier [0x6F]	RM,0,		"MOVQ %m,%M",
534b0dcc5a8SDavid du Colombier [0x70]	RM,Ib,		"PSHUFW	%i,%m,%M",
535b0dcc5a8SDavid du Colombier [0x74]	RM,0,		"PCMPEQB %m,%M",
536b0dcc5a8SDavid du Colombier [0x75]	RM,0,		"PCMPEQW %m,%M",
537b0dcc5a8SDavid du Colombier [0x76]	RM,0,		"PCMPEQL %m,%M",
538b0dcc5a8SDavid du Colombier [0x7E]	RM,0,		"MOV%S %M,%e",
539b0dcc5a8SDavid du Colombier [0x7F]	RM,0,		"MOVQ %M,%m",
540b0dcc5a8SDavid du Colombier [0xAE]	RMOP,0,		optab0FAE,
541b0dcc5a8SDavid du Colombier [0xAA]	0,0,		"RSM",
542b0dcc5a8SDavid du Colombier [0xB0]	RM,0,		"CMPXCHGB	%r,%e",
543b0dcc5a8SDavid du Colombier [0xB1]	RM,0,		"CMPXCHG%S	%r,%e",
544b0dcc5a8SDavid du Colombier [0xC0]	RMB,0,		"XADDB	%r,%e",
545b0dcc5a8SDavid du Colombier [0xC1]	RM,0,		"XADD%S	%r,%e",
546b0dcc5a8SDavid du Colombier [0xC2]	RM,Ib,		"CMP%s	%i,%x,%X",
547b0dcc5a8SDavid du Colombier [0xC3]	RM,0,		"MOVNTI%S	%r,%e",
548b0dcc5a8SDavid du Colombier [0xC6]	RM,Ib,		"SHUF%s	%i,%x,%X",
5494de34a7eSDavid du Colombier [0xC8]	0,0,		"BSWAP	AX",
5504de34a7eSDavid du Colombier [0xC9]	0,0,		"BSWAP	CX",
5514de34a7eSDavid du Colombier [0xCA]	0,0,		"BSWAP	DX",
5524de34a7eSDavid du Colombier [0xCB]	0,0,		"BSWAP	BX",
5534de34a7eSDavid du Colombier [0xCC]	0,0,		"BSWAP	SP",
5544de34a7eSDavid du Colombier [0xCD]	0,0,		"BSWAP	BP",
5554de34a7eSDavid du Colombier [0xCE]	0,0,		"BSWAP	SI",
5564de34a7eSDavid du Colombier [0xCF]	0,0,		"BSWAP	DI",
557b0dcc5a8SDavid du Colombier [0xD1]	RM,0,		"PSRLW %m,%M",
558b0dcc5a8SDavid du Colombier [0xD2]	RM,0,		"PSRLL %m,%M",
559b0dcc5a8SDavid du Colombier [0xD3]	RM,0,		"PSRLQ %m,%M",
560b0dcc5a8SDavid du Colombier [0xD5]	RM,0,		"PMULLW %m,%M",
561b0dcc5a8SDavid du Colombier [0xD6]	RM,0,		"MOVQOZX	%m*,%X",
562b0dcc5a8SDavid du Colombier [0xD7]	RM,0,		"PMOVMSKB %m,%r",
563b0dcc5a8SDavid du Colombier [0xD8]	RM,0,		"PSUBUSB %m,%M",
564b0dcc5a8SDavid du Colombier [0xD9]	RM,0,		"PSUBUSW %m,%M",
565b0dcc5a8SDavid du Colombier [0xDA]	RM,0,		"PMINUB %m,%M",
566b0dcc5a8SDavid du Colombier [0xDB]	RM,0,		"PAND %m,%M",
567b0dcc5a8SDavid du Colombier [0xDC]	RM,0,		"PADDUSB %m,%M",
568b0dcc5a8SDavid du Colombier [0xDD]	RM,0,		"PADDUSW %m,%M",
569b0dcc5a8SDavid du Colombier [0xDE]	RM,0,		"PMAXUB %m,%M",
570b0dcc5a8SDavid du Colombier [0xDF]	RM,0,		"PANDN %m,%M",
571b0dcc5a8SDavid du Colombier [0xE0]	RM,0,		"PAVGB %m,%M",
572b0dcc5a8SDavid du Colombier [0xE1]	RM,0,		"PSRAW %m,%M",
573b0dcc5a8SDavid du Colombier [0xE2]	RM,0,		"PSRAL %m,%M",
574b0dcc5a8SDavid du Colombier [0xE3]	RM,0,		"PAVGW %m,%M",
575b0dcc5a8SDavid du Colombier [0xE4]	RM,0,		"PMULHUW %m,%M",
576b0dcc5a8SDavid du Colombier [0xE5]	RM,0,		"PMULHW %m,%M",
577b0dcc5a8SDavid du Colombier [0xE7]	RM,0,		"MOVNTQ	%M,%e",
578b0dcc5a8SDavid du Colombier [0xE8]	RM,0,		"PSUBSB %m,%M",
579b0dcc5a8SDavid du Colombier [0xE9]	RM,0,		"PSUBSW %m,%M",
580b0dcc5a8SDavid du Colombier [0xEA]	RM,0,		"PMINSW %m,%M",
581b0dcc5a8SDavid du Colombier [0xEB]	RM,0,		"POR %m,%M",
582b0dcc5a8SDavid du Colombier [0xEC]	RM,0,		"PADDSB %m,%M",
583b0dcc5a8SDavid du Colombier [0xED]	RM,0,		"PADDSW %m,%M",
584b0dcc5a8SDavid du Colombier [0xEE]	RM,0,		"PMAXSW %m,%M",
585b0dcc5a8SDavid du Colombier [0xEF]	RM,0,		"PXOR %m,%M",
586b0dcc5a8SDavid du Colombier [0xF1]	RM,0,		"PSLLW %m,%M",
587b0dcc5a8SDavid du Colombier [0xF2]	RM,0,		"PSLLL %m,%M",
588b0dcc5a8SDavid du Colombier [0xF3]	RM,0,		"PSLLQ %m,%M",
589b0dcc5a8SDavid du Colombier [0xF4]	RM,0,		"PMULULQ	%m,%M",
590b0dcc5a8SDavid du Colombier [0xF5]	RM,0,		"PMADDWL %m,%M",
591b0dcc5a8SDavid du Colombier [0xF6]	RM,0,		"PSADBW %m,%M",
592b0dcc5a8SDavid du Colombier [0xF7]	RMR,0,		"MASKMOVQ	%m,%M",
593b0dcc5a8SDavid du Colombier [0xF8]	RM,0,		"PSUBB %m,%M",
594b0dcc5a8SDavid du Colombier [0xF9]	RM,0,		"PSUBW %m,%M",
595b0dcc5a8SDavid du Colombier [0xFA]	RM,0,		"PSUBL %m,%M",
596b0dcc5a8SDavid du Colombier [0xFC]	RM,0,		"PADDB %m,%M",
597b0dcc5a8SDavid du Colombier [0xFD]	RM,0,		"PADDW %m,%M",
598b0dcc5a8SDavid du Colombier [0xFE]	RM,0,		"PADDL %m,%M",
599b0dcc5a8SDavid du Colombier 
600219b2ee8SDavid du Colombier [0x80]	Iwds,0,		"JOS	%p",
601219b2ee8SDavid du Colombier [0x81]	Iwds,0,		"JOC	%p",
602219b2ee8SDavid du Colombier [0x82]	Iwds,0,		"JCS	%p",
603219b2ee8SDavid du Colombier [0x83]	Iwds,0,		"JCC	%p",
604219b2ee8SDavid du Colombier [0x84]	Iwds,0,		"JEQ	%p",
605219b2ee8SDavid du Colombier [0x85]	Iwds,0,		"JNE	%p",
606219b2ee8SDavid du Colombier [0x86]	Iwds,0,		"JLS	%p",
607219b2ee8SDavid du Colombier [0x87]	Iwds,0,		"JHI	%p",
608219b2ee8SDavid du Colombier [0x88]	Iwds,0,		"JMI	%p",
609219b2ee8SDavid du Colombier [0x89]	Iwds,0,		"JPL	%p",
610219b2ee8SDavid du Colombier [0x8a]	Iwds,0,		"JPS	%p",
611219b2ee8SDavid du Colombier [0x8b]	Iwds,0,		"JPC	%p",
612219b2ee8SDavid du Colombier [0x8c]	Iwds,0,		"JLT	%p",
613219b2ee8SDavid du Colombier [0x8d]	Iwds,0,		"JGE	%p",
614219b2ee8SDavid du Colombier [0x8e]	Iwds,0,		"JLE	%p",
615219b2ee8SDavid du Colombier [0x8f]	Iwds,0,		"JGT	%p",
616219b2ee8SDavid du Colombier [0x90]	RMB,0,		"SETOS	%e",
617219b2ee8SDavid du Colombier [0x91]	RMB,0,		"SETOC	%e",
618219b2ee8SDavid du Colombier [0x92]	RMB,0,		"SETCS	%e",
619219b2ee8SDavid du Colombier [0x93]	RMB,0,		"SETCC	%e",
620219b2ee8SDavid du Colombier [0x94]	RMB,0,		"SETEQ	%e",
621219b2ee8SDavid du Colombier [0x95]	RMB,0,		"SETNE	%e",
622219b2ee8SDavid du Colombier [0x96]	RMB,0,		"SETLS	%e",
623219b2ee8SDavid du Colombier [0x97]	RMB,0,		"SETHI	%e",
624219b2ee8SDavid du Colombier [0x98]	RMB,0,		"SETMI	%e",
625219b2ee8SDavid du Colombier [0x99]	RMB,0,		"SETPL	%e",
626219b2ee8SDavid du Colombier [0x9a]	RMB,0,		"SETPS	%e",
627219b2ee8SDavid du Colombier [0x9b]	RMB,0,		"SETPC	%e",
628219b2ee8SDavid du Colombier [0x9c]	RMB,0,		"SETLT	%e",
629219b2ee8SDavid du Colombier [0x9d]	RMB,0,		"SETGE	%e",
630219b2ee8SDavid du Colombier [0x9e]	RMB,0,		"SETLE	%e",
631219b2ee8SDavid du Colombier [0x9f]	RMB,0,		"SETGT	%e",
632219b2ee8SDavid du Colombier [0xa0]	0,0,		"PUSHL	FS",
633219b2ee8SDavid du Colombier [0xa1]	0,0,		"POPL	FS",
634219b2ee8SDavid du Colombier [0xa2]	0,0,		"CPUID",
635219b2ee8SDavid du Colombier [0xa3]	RM,0,		"BT%S	%r,%e",
636219b2ee8SDavid du Colombier [0xa4]	RM,Ib,		"SHLD%S	%r,%i,%e",
637219b2ee8SDavid du Colombier [0xa5]	RM,0,		"SHLD%S	%r,CL,%e",
638219b2ee8SDavid du Colombier [0xa8]	0,0,		"PUSHL	GS",
639219b2ee8SDavid du Colombier [0xa9]	0,0,		"POPL	GS",
640219b2ee8SDavid du Colombier [0xab]	RM,0,		"BTS%S	%r,%e",
641219b2ee8SDavid du Colombier [0xac]	RM,Ib,		"SHRD%S	%r,%i,%e",
642219b2ee8SDavid du Colombier [0xad]	RM,0,		"SHRD%S	%r,CL,%e",
643219b2ee8SDavid du Colombier [0xaf]	RM,0,		"IMUL%S	%e,%r",
644219b2ee8SDavid du Colombier [0xb2]	RMM,0,		"LSS	%e,%r",
645219b2ee8SDavid du Colombier [0xb3]	RM,0,		"BTR%S	%r,%e",
646219b2ee8SDavid du Colombier [0xb4]	RMM,0,		"LFS	%e,%r",
647219b2ee8SDavid du Colombier [0xb5]	RMM,0,		"LGS	%e,%r",
648219b2ee8SDavid du Colombier [0xb6]	RMB,0,		"MOVBZX	%e,%R",
649219b2ee8SDavid du Colombier [0xb7]	RM,0,		"MOVWZX	%e,%R",
650219b2ee8SDavid du Colombier [0xba]	RMOP,0,		optab0FBA,
651219b2ee8SDavid du Colombier [0xbb]	RM,0,		"BTC%S	%e,%r",
652219b2ee8SDavid du Colombier [0xbc]	RM,0,		"BSF%S	%e,%r",
653219b2ee8SDavid du Colombier [0xbd]	RM,0,		"BSR%S	%e,%r",
654219b2ee8SDavid du Colombier [0xbe]	RMB,0,		"MOVBSX	%e,%R",
655219b2ee8SDavid du Colombier [0xbf]	RM,0,		"MOVWSX	%e,%R",
656b0dcc5a8SDavid du Colombier [0xc7]	RMOP,0,		optab0FC7,
657219b2ee8SDavid du Colombier };
658219b2ee8SDavid du Colombier 
659219b2ee8SDavid du Colombier static Optable optab80[8]=
660219b2ee8SDavid du Colombier {
661219b2ee8SDavid du Colombier [0x00]	Ib,0,		"ADDB	%i,%e",
662219b2ee8SDavid du Colombier [0x01]	Ib,0,		"ORB	%i,%e",
663219b2ee8SDavid du Colombier [0x02]	Ib,0,		"ADCB	%i,%e",
664219b2ee8SDavid du Colombier [0x03]	Ib,0,		"SBBB	%i,%e",
665219b2ee8SDavid du Colombier [0x04]	Ib,0,		"ANDB	%i,%e",
666219b2ee8SDavid du Colombier [0x05]	Ib,0,		"SUBB	%i,%e",
667219b2ee8SDavid du Colombier [0x06]	Ib,0,		"XORB	%i,%e",
668219b2ee8SDavid du Colombier [0x07]	Ib,0,		"CMPB	%e,%i",
669219b2ee8SDavid du Colombier };
670219b2ee8SDavid du Colombier 
671219b2ee8SDavid du Colombier static Optable optab81[8]=
672219b2ee8SDavid du Colombier {
673219b2ee8SDavid du Colombier [0x00]	Iwd,0,		"ADD%S	%i,%e",
674219b2ee8SDavid du Colombier [0x01]	Iwd,0,		"OR%S	%i,%e",
675219b2ee8SDavid du Colombier [0x02]	Iwd,0,		"ADC%S	%i,%e",
676219b2ee8SDavid du Colombier [0x03]	Iwd,0,		"SBB%S	%i,%e",
677219b2ee8SDavid du Colombier [0x04]	Iwd,0,		"AND%S	%i,%e",
678219b2ee8SDavid du Colombier [0x05]	Iwd,0,		"SUB%S	%i,%e",
679219b2ee8SDavid du Colombier [0x06]	Iwd,0,		"XOR%S	%i,%e",
680219b2ee8SDavid du Colombier [0x07]	Iwd,0,		"CMP%S	%e,%i",
681219b2ee8SDavid du Colombier };
682219b2ee8SDavid du Colombier 
683219b2ee8SDavid du Colombier static Optable optab83[8]=
684219b2ee8SDavid du Colombier {
685219b2ee8SDavid du Colombier [0x00]	Ibs,0,		"ADD%S	%i,%e",
686219b2ee8SDavid du Colombier [0x01]	Ibs,0,		"OR%S	%i,%e",
687219b2ee8SDavid du Colombier [0x02]	Ibs,0,		"ADC%S	%i,%e",
688219b2ee8SDavid du Colombier [0x03]	Ibs,0,		"SBB%S	%i,%e",
689219b2ee8SDavid du Colombier [0x04]	Ibs,0,		"AND%S	%i,%e",
690219b2ee8SDavid du Colombier [0x05]	Ibs,0,		"SUB%S	%i,%e",
691219b2ee8SDavid du Colombier [0x06]	Ibs,0,		"XOR%S	%i,%e",
692219b2ee8SDavid du Colombier [0x07]	Ibs,0,		"CMP%S	%e,%i",
693219b2ee8SDavid du Colombier };
694219b2ee8SDavid du Colombier 
695219b2ee8SDavid du Colombier static Optable optabC0[8] =
696219b2ee8SDavid du Colombier {
697219b2ee8SDavid du Colombier [0x00]	Ib,0,		"ROLB	%i,%e",
698219b2ee8SDavid du Colombier [0x01]	Ib,0,		"RORB	%i,%e",
699219b2ee8SDavid du Colombier [0x02]	Ib,0,		"RCLB	%i,%e",
700219b2ee8SDavid du Colombier [0x03]	Ib,0,		"RCRB	%i,%e",
701219b2ee8SDavid du Colombier [0x04]	Ib,0,		"SHLB	%i,%e",
702219b2ee8SDavid du Colombier [0x05]	Ib,0,		"SHRB	%i,%e",
703219b2ee8SDavid du Colombier [0x07]	Ib,0,		"SARB	%i,%e",
704219b2ee8SDavid du Colombier };
705219b2ee8SDavid du Colombier 
706219b2ee8SDavid du Colombier static Optable optabC1[8] =
707219b2ee8SDavid du Colombier {
708219b2ee8SDavid du Colombier [0x00]	Ib,0,		"ROL%S	%i,%e",
709219b2ee8SDavid du Colombier [0x01]	Ib,0,		"ROR%S	%i,%e",
710219b2ee8SDavid du Colombier [0x02]	Ib,0,		"RCL%S	%i,%e",
711219b2ee8SDavid du Colombier [0x03]	Ib,0,		"RCR%S	%i,%e",
712219b2ee8SDavid du Colombier [0x04]	Ib,0,		"SHL%S	%i,%e",
713219b2ee8SDavid du Colombier [0x05]	Ib,0,		"SHR%S	%i,%e",
714219b2ee8SDavid du Colombier [0x07]	Ib,0,		"SAR%S	%i,%e",
715219b2ee8SDavid du Colombier };
716219b2ee8SDavid du Colombier 
717219b2ee8SDavid du Colombier static Optable optabD0[8] =
718219b2ee8SDavid du Colombier {
719219b2ee8SDavid du Colombier [0x00]	0,0,		"ROLB	%e",
720219b2ee8SDavid du Colombier [0x01]	0,0,		"RORB	%e",
721219b2ee8SDavid du Colombier [0x02]	0,0,		"RCLB	%e",
722219b2ee8SDavid du Colombier [0x03]	0,0,		"RCRB	%e",
723219b2ee8SDavid du Colombier [0x04]	0,0,		"SHLB	%e",
724219b2ee8SDavid du Colombier [0x05]	0,0,		"SHRB	%e",
725219b2ee8SDavid du Colombier [0x07]	0,0,		"SARB	%e",
726219b2ee8SDavid du Colombier };
727219b2ee8SDavid du Colombier 
728219b2ee8SDavid du Colombier static Optable optabD1[8] =
729219b2ee8SDavid du Colombier {
730219b2ee8SDavid du Colombier [0x00]	0,0,		"ROL%S	%e",
731219b2ee8SDavid du Colombier [0x01]	0,0,		"ROR%S	%e",
732219b2ee8SDavid du Colombier [0x02]	0,0,		"RCL%S	%e",
733219b2ee8SDavid du Colombier [0x03]	0,0,		"RCR%S	%e",
734219b2ee8SDavid du Colombier [0x04]	0,0,		"SHL%S	%e",
735219b2ee8SDavid du Colombier [0x05]	0,0,		"SHR%S	%e",
736219b2ee8SDavid du Colombier [0x07]	0,0,		"SAR%S	%e",
737219b2ee8SDavid du Colombier };
738219b2ee8SDavid du Colombier 
739219b2ee8SDavid du Colombier static Optable optabD2[8] =
740219b2ee8SDavid du Colombier {
741219b2ee8SDavid du Colombier [0x00]	0,0,		"ROLB	CL,%e",
742219b2ee8SDavid du Colombier [0x01]	0,0,		"RORB	CL,%e",
743219b2ee8SDavid du Colombier [0x02]	0,0,		"RCLB	CL,%e",
744219b2ee8SDavid du Colombier [0x03]	0,0,		"RCRB	CL,%e",
745219b2ee8SDavid du Colombier [0x04]	0,0,		"SHLB	CL,%e",
746219b2ee8SDavid du Colombier [0x05]	0,0,		"SHRB	CL,%e",
747219b2ee8SDavid du Colombier [0x07]	0,0,		"SARB	CL,%e",
748219b2ee8SDavid du Colombier };
749219b2ee8SDavid du Colombier 
750219b2ee8SDavid du Colombier static Optable optabD3[8] =
751219b2ee8SDavid du Colombier {
752219b2ee8SDavid du Colombier [0x00]	0,0,		"ROL%S	CL,%e",
753219b2ee8SDavid du Colombier [0x01]	0,0,		"ROR%S	CL,%e",
754219b2ee8SDavid du Colombier [0x02]	0,0,		"RCL%S	CL,%e",
755219b2ee8SDavid du Colombier [0x03]	0,0,		"RCR%S	CL,%e",
756219b2ee8SDavid du Colombier [0x04]	0,0,		"SHL%S	CL,%e",
757219b2ee8SDavid du Colombier [0x05]	0,0,		"SHR%S	CL,%e",
758219b2ee8SDavid du Colombier [0x07]	0,0,		"SAR%S	CL,%e",
759219b2ee8SDavid du Colombier };
760219b2ee8SDavid du Colombier 
761219b2ee8SDavid du Colombier static Optable optabD8[8+8] =
762219b2ee8SDavid du Colombier {
763219b2ee8SDavid du Colombier [0x00]	0,0,		"FADDF	%e,F0",
764219b2ee8SDavid du Colombier [0x01]	0,0,		"FMULF	%e,F0",
765219b2ee8SDavid du Colombier [0x02]	0,0,		"FCOMF	%e,F0",
766219b2ee8SDavid du Colombier [0x03]	0,0,		"FCOMFP	%e,F0",
767219b2ee8SDavid du Colombier [0x04]	0,0,		"FSUBF	%e,F0",
768219b2ee8SDavid du Colombier [0x05]	0,0,		"FSUBRF	%e,F0",
769219b2ee8SDavid du Colombier [0x06]	0,0,		"FDIVF	%e,F0",
770219b2ee8SDavid du Colombier [0x07]	0,0,		"FDIVRF	%e,F0",
771219b2ee8SDavid du Colombier [0x08]	0,0,		"FADDD	%f,F0",
772219b2ee8SDavid du Colombier [0x09]	0,0,		"FMULD	%f,F0",
773219b2ee8SDavid du Colombier [0x0a]	0,0,		"FCOMD	%f,F0",
774219b2ee8SDavid du Colombier [0x0b]	0,0,		"FCOMPD	%f,F0",
775219b2ee8SDavid du Colombier [0x0c]	0,0,		"FSUBD	%f,F0",
776219b2ee8SDavid du Colombier [0x0d]	0,0,		"FSUBRD	%f,F0",
777219b2ee8SDavid du Colombier [0x0e]	0,0,		"FDIVD	%f,F0",
778219b2ee8SDavid du Colombier [0x0f]	0,0,		"FDIVRD	%f,F0",
779219b2ee8SDavid du Colombier };
780219b2ee8SDavid du Colombier /*
781219b2ee8SDavid du Colombier  *	optabD9 and optabDB use the following encoding:
782219b2ee8SDavid du Colombier  *	if (0 <= modrm <= 2) instruction = optabDx[modrm&0x07];
783219b2ee8SDavid du Colombier  *	else instruction = optabDx[(modrm&0x3f)+8];
784219b2ee8SDavid du Colombier  *
785219b2ee8SDavid du Colombier  *	the instructions for MOD == 3, follow the 8 instructions
786219b2ee8SDavid du Colombier  *	for the other MOD values stored at the front of the table.
787219b2ee8SDavid du Colombier  */
788219b2ee8SDavid du Colombier static Optable optabD9[64+8] =
789219b2ee8SDavid du Colombier {
790219b2ee8SDavid du Colombier [0x00]	0,0,		"FMOVF	%e,F0",
791219b2ee8SDavid du Colombier [0x02]	0,0,		"FMOVF	F0,%e",
792219b2ee8SDavid du Colombier [0x03]	0,0,		"FMOVFP	F0,%e",
793219b2ee8SDavid du Colombier [0x04]	0,0,		"FLDENV%S %e",
794219b2ee8SDavid du Colombier [0x05]	0,0,		"FLDCW	%e",
795219b2ee8SDavid du Colombier [0x06]	0,0,		"FSTENV%S %e",
796219b2ee8SDavid du Colombier [0x07]	0,0,		"FSTCW	%e",
797219b2ee8SDavid du Colombier [0x08]	0,0,		"FMOVD	F0,F0",		/* Mod R/M = 11xx xxxx*/
798219b2ee8SDavid du Colombier [0x09]	0,0,		"FMOVD	F1,F0",
799219b2ee8SDavid du Colombier [0x0a]	0,0,		"FMOVD	F2,F0",
800219b2ee8SDavid du Colombier [0x0b]	0,0,		"FMOVD	F3,F0",
801219b2ee8SDavid du Colombier [0x0c]	0,0,		"FMOVD	F4,F0",
802219b2ee8SDavid du Colombier [0x0d]	0,0,		"FMOVD	F5,F0",
803219b2ee8SDavid du Colombier [0x0e]	0,0,		"FMOVD	F6,F0",
804219b2ee8SDavid du Colombier [0x0f]	0,0,		"FMOVD	F7,F0",
805219b2ee8SDavid du Colombier [0x10]	0,0,		"FXCHD	F0,F0",
806219b2ee8SDavid du Colombier [0x11]	0,0,		"FXCHD	F1,F0",
807219b2ee8SDavid du Colombier [0x12]	0,0,		"FXCHD	F2,F0",
808219b2ee8SDavid du Colombier [0x13]	0,0,		"FXCHD	F3,F0",
809219b2ee8SDavid du Colombier [0x14]	0,0,		"FXCHD	F4,F0",
810219b2ee8SDavid du Colombier [0x15]	0,0,		"FXCHD	F5,F0",
811219b2ee8SDavid du Colombier [0x16]	0,0,		"FXCHD	F6,F0",
812219b2ee8SDavid du Colombier [0x17]	0,0,		"FXCHD	F7,F0",
813219b2ee8SDavid du Colombier [0x18]	0,0,		"FNOP",
814219b2ee8SDavid du Colombier [0x28]	0,0,		"FCHS",
815219b2ee8SDavid du Colombier [0x29]	0,0,		"FABS",
816219b2ee8SDavid du Colombier [0x2c]	0,0,		"FTST",
817219b2ee8SDavid du Colombier [0x2d]	0,0,		"FXAM",
818219b2ee8SDavid du Colombier [0x30]	0,0,		"FLD1",
819219b2ee8SDavid du Colombier [0x31]	0,0,		"FLDL2T",
820219b2ee8SDavid du Colombier [0x32]	0,0,		"FLDL2E",
821219b2ee8SDavid du Colombier [0x33]	0,0,		"FLDPI",
822219b2ee8SDavid du Colombier [0x34]	0,0,		"FLDLG2",
823219b2ee8SDavid du Colombier [0x35]	0,0,		"FLDLN2",
824219b2ee8SDavid du Colombier [0x36]	0,0,		"FLDZ",
825219b2ee8SDavid du Colombier [0x38]	0,0,		"F2XM1",
826219b2ee8SDavid du Colombier [0x39]	0,0,		"FYL2X",
827219b2ee8SDavid du Colombier [0x3a]	0,0,		"FPTAN",
828219b2ee8SDavid du Colombier [0x3b]	0,0,		"FPATAN",
829219b2ee8SDavid du Colombier [0x3c]	0,0,		"FXTRACT",
830219b2ee8SDavid du Colombier [0x3d]	0,0,		"FPREM1",
831219b2ee8SDavid du Colombier [0x3e]	0,0,		"FDECSTP",
832219b2ee8SDavid du Colombier [0x3f]	0,0,		"FNCSTP",
833219b2ee8SDavid du Colombier [0x40]	0,0,		"FPREM",
834219b2ee8SDavid du Colombier [0x41]	0,0,		"FYL2XP1",
835219b2ee8SDavid du Colombier [0x42]	0,0,		"FSQRT",
836219b2ee8SDavid du Colombier [0x43]	0,0,		"FSINCOS",
837219b2ee8SDavid du Colombier [0x44]	0,0,		"FRNDINT",
838219b2ee8SDavid du Colombier [0x45]	0,0,		"FSCALE",
839219b2ee8SDavid du Colombier [0x46]	0,0,		"FSIN",
840219b2ee8SDavid du Colombier [0x47]	0,0,		"FCOS",
841219b2ee8SDavid du Colombier };
842219b2ee8SDavid du Colombier 
843219b2ee8SDavid du Colombier static Optable optabDA[8+8] =
844219b2ee8SDavid du Colombier {
845219b2ee8SDavid du Colombier [0x00]	0,0,		"FADDL	%e,F0",
846219b2ee8SDavid du Colombier [0x01]	0,0,		"FMULL	%e,F0",
847219b2ee8SDavid du Colombier [0x02]	0,0,		"FCOML	%e,F0",
848219b2ee8SDavid du Colombier [0x03]	0,0,		"FCOMLP	%e,F0",
849219b2ee8SDavid du Colombier [0x04]	0,0,		"FSUBL	%e,F0",
850219b2ee8SDavid du Colombier [0x05]	0,0,		"FSUBRL	%e,F0",
851219b2ee8SDavid du Colombier [0x06]	0,0,		"FDIVL	%e,F0",
852219b2ee8SDavid du Colombier [0x07]	0,0,		"FDIVRL	%e,F0",
853219b2ee8SDavid du Colombier [0x0d]	R1,0,		"FUCOMPP",
854219b2ee8SDavid du Colombier };
855219b2ee8SDavid du Colombier 
856219b2ee8SDavid du Colombier static Optable optabDB[8+64] =
857219b2ee8SDavid du Colombier {
858219b2ee8SDavid du Colombier [0x00]	0,0,		"FMOVL	%e,F0",
859219b2ee8SDavid du Colombier [0x02]	0,0,		"FMOVL	F0,%e",
860219b2ee8SDavid du Colombier [0x03]	0,0,		"FMOVLP	F0,%e",
861219b2ee8SDavid du Colombier [0x05]	0,0,		"FMOVX	%e,F0",
862219b2ee8SDavid du Colombier [0x07]	0,0,		"FMOVXP	F0,%e",
863219b2ee8SDavid du Colombier [0x2a]	0,0,		"FCLEX",
864219b2ee8SDavid du Colombier [0x2b]	0,0,		"FINIT",
865219b2ee8SDavid du Colombier };
866219b2ee8SDavid du Colombier 
867219b2ee8SDavid du Colombier static Optable optabDC[8+8] =
868219b2ee8SDavid du Colombier {
869219b2ee8SDavid du Colombier [0x00]	0,0,		"FADDD	%e,F0",
870219b2ee8SDavid du Colombier [0x01]	0,0,		"FMULD	%e,F0",
871219b2ee8SDavid du Colombier [0x02]	0,0,		"FCOMD	%e,F0",
872219b2ee8SDavid du Colombier [0x03]	0,0,		"FCOMDP	%e,F0",
873219b2ee8SDavid du Colombier [0x04]	0,0,		"FSUBD	%e,F0",
874219b2ee8SDavid du Colombier [0x05]	0,0,		"FSUBRD	%e,F0",
875219b2ee8SDavid du Colombier [0x06]	0,0,		"FDIVD	%e,F0",
876219b2ee8SDavid du Colombier [0x07]	0,0,		"FDIVRD	%e,F0",
877219b2ee8SDavid du Colombier [0x08]	0,0,		"FADDD	F0,%f",
878219b2ee8SDavid du Colombier [0x09]	0,0,		"FMULD	F0,%f",
879219b2ee8SDavid du Colombier [0x0c]	0,0,		"FSUBRD	F0,%f",
880219b2ee8SDavid du Colombier [0x0d]	0,0,		"FSUBD	F0,%f",
881219b2ee8SDavid du Colombier [0x0e]	0,0,		"FDIVRD	F0,%f",
882219b2ee8SDavid du Colombier [0x0f]	0,0,		"FDIVD	F0,%f",
883219b2ee8SDavid du Colombier };
884219b2ee8SDavid du Colombier 
885219b2ee8SDavid du Colombier static Optable optabDD[8+8] =
886219b2ee8SDavid du Colombier {
887219b2ee8SDavid du Colombier [0x00]	0,0,		"FMOVD	%e,F0",
888219b2ee8SDavid du Colombier [0x02]	0,0,		"FMOVD	F0,%e",
889219b2ee8SDavid du Colombier [0x03]	0,0,		"FMOVDP	F0,%e",
890219b2ee8SDavid du Colombier [0x04]	0,0,		"FRSTOR%S %e",
891219b2ee8SDavid du Colombier [0x06]	0,0,		"FSAVE%S %e",
892219b2ee8SDavid du Colombier [0x07]	0,0,		"FSTSW	%e",
893219b2ee8SDavid du Colombier [0x08]	0,0,		"FFREED	%f",
894219b2ee8SDavid du Colombier [0x0a]	0,0,		"FMOVD	%f,F0",
895219b2ee8SDavid du Colombier [0x0b]	0,0,		"FMOVDP	%f,F0",
896219b2ee8SDavid du Colombier [0x0c]	0,0,		"FUCOMD	%f,F0",
897219b2ee8SDavid du Colombier [0x0d]	0,0,		"FUCOMDP %f,F0",
898219b2ee8SDavid du Colombier };
899219b2ee8SDavid du Colombier 
900219b2ee8SDavid du Colombier static Optable optabDE[8+8] =
901219b2ee8SDavid du Colombier {
902219b2ee8SDavid du Colombier [0x00]	0,0,		"FADDW	%e,F0",
903219b2ee8SDavid du Colombier [0x01]	0,0,		"FMULW	%e,F0",
904219b2ee8SDavid du Colombier [0x02]	0,0,		"FCOMW	%e,F0",
905219b2ee8SDavid du Colombier [0x03]	0,0,		"FCOMWP	%e,F0",
906219b2ee8SDavid du Colombier [0x04]	0,0,		"FSUBW	%e,F0",
907219b2ee8SDavid du Colombier [0x05]	0,0,		"FSUBRW	%e,F0",
908219b2ee8SDavid du Colombier [0x06]	0,0,		"FDIVW	%e,F0",
909219b2ee8SDavid du Colombier [0x07]	0,0,		"FDIVRW	%e,F0",
910219b2ee8SDavid du Colombier [0x08]	0,0,		"FADDDP	F0,%f",
911219b2ee8SDavid du Colombier [0x09]	0,0,		"FMULDP	F0,%f",
912219b2ee8SDavid du Colombier [0x0b]	R1,0,		"FCOMPDP",
913219b2ee8SDavid du Colombier [0x0c]	0,0,		"FSUBRDP F0,%f",
914219b2ee8SDavid du Colombier [0x0d]	0,0,		"FSUBDP	F0,%f",
915219b2ee8SDavid du Colombier [0x0e]	0,0,		"FDIVRDP F0,%f",
916219b2ee8SDavid du Colombier [0x0f]	0,0,		"FDIVDP	F0,%f",
917219b2ee8SDavid du Colombier };
918219b2ee8SDavid du Colombier 
919219b2ee8SDavid du Colombier static Optable optabDF[8+8] =
920219b2ee8SDavid du Colombier {
921219b2ee8SDavid du Colombier [0x00]	0,0,		"FMOVW	%e,F0",
922219b2ee8SDavid du Colombier [0x02]	0,0,		"FMOVW	F0,%e",
923219b2ee8SDavid du Colombier [0x03]	0,0,		"FMOVWP	F0,%e",
924219b2ee8SDavid du Colombier [0x04]	0,0,		"FBLD	%e",
925219b2ee8SDavid du Colombier [0x05]	0,0,		"FMOVL	%e,F0",
926219b2ee8SDavid du Colombier [0x06]	0,0,		"FBSTP	%e",
927219b2ee8SDavid du Colombier [0x07]	0,0,		"FMOVLP	F0,%e",
928219b2ee8SDavid du Colombier [0x0c]	R0,0,		"FSTSW	%OAX",
929219b2ee8SDavid du Colombier };
930219b2ee8SDavid du Colombier 
931219b2ee8SDavid du Colombier static Optable optabF6[8] =
932219b2ee8SDavid du Colombier {
933219b2ee8SDavid du Colombier [0x00]	Ib,0,		"TESTB	%i,%e",
934219b2ee8SDavid du Colombier [0x02]	0,0,		"NOTB	%e",
935219b2ee8SDavid du Colombier [0x03]	0,0,		"NEGB	%e",
936219b2ee8SDavid du Colombier [0x04]	0,0,		"MULB	AL,%e",
937219b2ee8SDavid du Colombier [0x05]	0,0,		"IMULB	AL,%e",
938219b2ee8SDavid du Colombier [0x06]	0,0,		"DIVB	AL,%e",
939219b2ee8SDavid du Colombier [0x07]	0,0,		"IDIVB	AL,%e",
940219b2ee8SDavid du Colombier };
941219b2ee8SDavid du Colombier 
942219b2ee8SDavid du Colombier static Optable optabF7[8] =
943219b2ee8SDavid du Colombier {
944219b2ee8SDavid du Colombier [0x00]	Iwd,0,		"TEST%S	%i,%e",
945219b2ee8SDavid du Colombier [0x02]	0,0,		"NOT%S	%e",
946219b2ee8SDavid du Colombier [0x03]	0,0,		"NEG%S	%e",
947219b2ee8SDavid du Colombier [0x04]	0,0,		"MUL%S	%OAX,%e",
948219b2ee8SDavid du Colombier [0x05]	0,0,		"IMUL%S	%OAX,%e",
949219b2ee8SDavid du Colombier [0x06]	0,0,		"DIV%S	%OAX,%e",
950219b2ee8SDavid du Colombier [0x07]	0,0,		"IDIV%S	%OAX,%e",
951219b2ee8SDavid du Colombier };
952219b2ee8SDavid du Colombier 
953219b2ee8SDavid du Colombier static Optable optabFE[8] =
954219b2ee8SDavid du Colombier {
955219b2ee8SDavid du Colombier [0x00]	0,0,		"INCB	%e",
956219b2ee8SDavid du Colombier [0x01]	0,0,		"DECB	%e",
957219b2ee8SDavid du Colombier };
958219b2ee8SDavid du Colombier 
959219b2ee8SDavid du Colombier static Optable optabFF[8] =
960219b2ee8SDavid du Colombier {
961219b2ee8SDavid du Colombier [0x00]	0,0,		"INC%S	%e",
962219b2ee8SDavid du Colombier [0x01]	0,0,		"DEC%S	%e",
9637dd7cddfSDavid du Colombier [0x02]	JUMP,0,		"CALL*	%e",
9647dd7cddfSDavid du Colombier [0x03]	JUMP,0,		"CALLF*	%e",
9657dd7cddfSDavid du Colombier [0x04]	JUMP,0,		"JMP*	%e",
9667dd7cddfSDavid du Colombier [0x05]	JUMP,0,		"JMPF*	%e",
967219b2ee8SDavid du Colombier [0x06]	0,0,		"PUSHL	%e",
968219b2ee8SDavid du Colombier };
969219b2ee8SDavid du Colombier 
970b0dcc5a8SDavid du Colombier static Optable optable[256+1] =
971219b2ee8SDavid du Colombier {
972219b2ee8SDavid du Colombier [0x00]	RMB,0,		"ADDB	%r,%e",
973219b2ee8SDavid du Colombier [0x01]	RM,0,		"ADD%S	%r,%e",
974219b2ee8SDavid du Colombier [0x02]	RMB,0,		"ADDB	%e,%r",
975219b2ee8SDavid du Colombier [0x03]	RM,0,		"ADD%S	%e,%r",
976219b2ee8SDavid du Colombier [0x04]	Ib,0,		"ADDB	%i,AL",
977219b2ee8SDavid du Colombier [0x05]	Iwd,0,		"ADD%S	%i,%OAX",
978219b2ee8SDavid du Colombier [0x06]	0,0,		"PUSHL	ES",
979219b2ee8SDavid du Colombier [0x07]	0,0,		"POPL	ES",
980219b2ee8SDavid du Colombier [0x08]	RMB,0,		"ORB	%r,%e",
981219b2ee8SDavid du Colombier [0x09]	RM,0,		"OR%S	%r,%e",
982219b2ee8SDavid du Colombier [0x0a]	RMB,0,		"ORB	%e,%r",
983219b2ee8SDavid du Colombier [0x0b]	RM,0,		"OR%S	%e,%r",
984219b2ee8SDavid du Colombier [0x0c]	Ib,0,		"ORB	%i,AL",
985219b2ee8SDavid du Colombier [0x0d]	Iwd,0,		"OR%S	%i,%OAX",
986219b2ee8SDavid du Colombier [0x0e]	0,0,		"PUSHL	CS",
987b0dcc5a8SDavid du Colombier [0x0f]	AUXMM,0,	optab0F,
988219b2ee8SDavid du Colombier [0x10]	RMB,0,		"ADCB	%r,%e",
989219b2ee8SDavid du Colombier [0x11]	RM,0,		"ADC%S	%r,%e",
990219b2ee8SDavid du Colombier [0x12]	RMB,0,		"ADCB	%e,%r",
991219b2ee8SDavid du Colombier [0x13]	RM,0,		"ADC%S	%e,%r",
992219b2ee8SDavid du Colombier [0x14]	Ib,0,		"ADCB	%i,AL",
993219b2ee8SDavid du Colombier [0x15]	Iwd,0,		"ADC%S	%i,%OAX",
994219b2ee8SDavid du Colombier [0x16]	0,0,		"PUSHL	SS",
995219b2ee8SDavid du Colombier [0x17]	0,0,		"POPL	SS",
996219b2ee8SDavid du Colombier [0x18]	RMB,0,		"SBBB	%r,%e",
997219b2ee8SDavid du Colombier [0x19]	RM,0,		"SBB%S	%r,%e",
998219b2ee8SDavid du Colombier [0x1a]	RMB,0,		"SBBB	%e,%r",
999219b2ee8SDavid du Colombier [0x1b]	RM,0,		"SBB%S	%e,%r",
1000219b2ee8SDavid du Colombier [0x1c]	Ib,0,		"SBBB	%i,AL",
1001219b2ee8SDavid du Colombier [0x1d]	Iwd,0,		"SBB%S	%i,%OAX",
1002219b2ee8SDavid du Colombier [0x1e]	0,0,		"PUSHL	DS",
1003219b2ee8SDavid du Colombier [0x1f]	0,0,		"POPL	DS",
1004219b2ee8SDavid du Colombier [0x20]	RMB,0,		"ANDB	%r,%e",
1005219b2ee8SDavid du Colombier [0x21]	RM,0,		"AND%S	%r,%e",
1006219b2ee8SDavid du Colombier [0x22]	RMB,0,		"ANDB	%e,%r",
1007219b2ee8SDavid du Colombier [0x23]	RM,0,		"AND%S	%e,%r",
1008219b2ee8SDavid du Colombier [0x24]	Ib,0,		"ANDB	%i,AL",
1009219b2ee8SDavid du Colombier [0x25]	Iwd,0,		"AND%S	%i,%OAX",
1010219b2ee8SDavid du Colombier [0x26]	SEG,0,		"ES:",
1011219b2ee8SDavid du Colombier [0x27]	0,0,		"DAA",
1012219b2ee8SDavid du Colombier [0x28]	RMB,0,		"SUBB	%r,%e",
1013219b2ee8SDavid du Colombier [0x29]	RM,0,		"SUB%S	%r,%e",
1014219b2ee8SDavid du Colombier [0x2a]	RMB,0,		"SUBB	%e,%r",
1015219b2ee8SDavid du Colombier [0x2b]	RM,0,		"SUB%S	%e,%r",
1016219b2ee8SDavid du Colombier [0x2c]	Ib,0,		"SUBB	%i,AL",
1017219b2ee8SDavid du Colombier [0x2d]	Iwd,0,		"SUB%S	%i,%OAX",
1018219b2ee8SDavid du Colombier [0x2e]	SEG,0,		"CS:",
1019219b2ee8SDavid du Colombier [0x2f]	0,0,		"DAS",
1020219b2ee8SDavid du Colombier [0x30]	RMB,0,		"XORB	%r,%e",
1021219b2ee8SDavid du Colombier [0x31]	RM,0,		"XOR%S	%r,%e",
1022219b2ee8SDavid du Colombier [0x32]	RMB,0,		"XORB	%e,%r",
1023219b2ee8SDavid du Colombier [0x33]	RM,0,		"XOR%S	%e,%r",
1024219b2ee8SDavid du Colombier [0x34]	Ib,0,		"XORB	%i,AL",
1025219b2ee8SDavid du Colombier [0x35]	Iwd,0,		"XOR%S	%i,%OAX",
1026219b2ee8SDavid du Colombier [0x36]	SEG,0,		"SS:",
1027219b2ee8SDavid du Colombier [0x37]	0,0,		"AAA",
1028219b2ee8SDavid du Colombier [0x38]	RMB,0,		"CMPB	%r,%e",
1029219b2ee8SDavid du Colombier [0x39]	RM,0,		"CMP%S	%r,%e",
1030219b2ee8SDavid du Colombier [0x3a]	RMB,0,		"CMPB	%e,%r",
1031219b2ee8SDavid du Colombier [0x3b]	RM,0,		"CMP%S	%e,%r",
1032219b2ee8SDavid du Colombier [0x3c]	Ib,0,		"CMPB	%i,AL",
1033219b2ee8SDavid du Colombier [0x3d]	Iwd,0,		"CMP%S	%i,%OAX",
1034219b2ee8SDavid du Colombier [0x3e]	SEG,0,		"DS:",
1035219b2ee8SDavid du Colombier [0x3f]	0,0,		"AAS",
1036219b2ee8SDavid du Colombier [0x40]	0,0,		"INC%S	%OAX",
1037219b2ee8SDavid du Colombier [0x41]	0,0,		"INC%S	%OCX",
1038219b2ee8SDavid du Colombier [0x42]	0,0,		"INC%S	%ODX",
1039219b2ee8SDavid du Colombier [0x43]	0,0,		"INC%S	%OBX",
1040219b2ee8SDavid du Colombier [0x44]	0,0,		"INC%S	%OSP",
1041219b2ee8SDavid du Colombier [0x45]	0,0,		"INC%S	%OBP",
1042219b2ee8SDavid du Colombier [0x46]	0,0,		"INC%S	%OSI",
1043219b2ee8SDavid du Colombier [0x47]	0,0,		"INC%S	%ODI",
1044219b2ee8SDavid du Colombier [0x48]	0,0,		"DEC%S	%OAX",
1045219b2ee8SDavid du Colombier [0x49]	0,0,		"DEC%S	%OCX",
1046219b2ee8SDavid du Colombier [0x4a]	0,0,		"DEC%S	%ODX",
1047219b2ee8SDavid du Colombier [0x4b]	0,0,		"DEC%S	%OBX",
1048219b2ee8SDavid du Colombier [0x4c]	0,0,		"DEC%S	%OSP",
1049219b2ee8SDavid du Colombier [0x4d]	0,0,		"DEC%S	%OBP",
1050219b2ee8SDavid du Colombier [0x4e]	0,0,		"DEC%S	%OSI",
1051219b2ee8SDavid du Colombier [0x4f]	0,0,		"DEC%S	%ODI",
1052219b2ee8SDavid du Colombier [0x50]	0,0,		"PUSH%S	%OAX",
1053219b2ee8SDavid du Colombier [0x51]	0,0,		"PUSH%S	%OCX",
1054219b2ee8SDavid du Colombier [0x52]	0,0,		"PUSH%S	%ODX",
1055219b2ee8SDavid du Colombier [0x53]	0,0,		"PUSH%S	%OBX",
1056219b2ee8SDavid du Colombier [0x54]	0,0,		"PUSH%S	%OSP",
1057219b2ee8SDavid du Colombier [0x55]	0,0,		"PUSH%S	%OBP",
1058219b2ee8SDavid du Colombier [0x56]	0,0,		"PUSH%S	%OSI",
1059219b2ee8SDavid du Colombier [0x57]	0,0,		"PUSH%S	%ODI",
1060219b2ee8SDavid du Colombier [0x58]	0,0,		"POP%S	%OAX",
1061219b2ee8SDavid du Colombier [0x59]	0,0,		"POP%S	%OCX",
1062219b2ee8SDavid du Colombier [0x5a]	0,0,		"POP%S	%ODX",
1063219b2ee8SDavid du Colombier [0x5b]	0,0,		"POP%S	%OBX",
1064219b2ee8SDavid du Colombier [0x5c]	0,0,		"POP%S	%OSP",
1065219b2ee8SDavid du Colombier [0x5d]	0,0,		"POP%S	%OBP",
1066219b2ee8SDavid du Colombier [0x5e]	0,0,		"POP%S	%OSI",
1067219b2ee8SDavid du Colombier [0x5f]	0,0,		"POP%S	%ODI",
1068219b2ee8SDavid du Colombier [0x60]	0,0,		"PUSHA%S",
1069219b2ee8SDavid du Colombier [0x61]	0,0,		"POPA%S",
1070219b2ee8SDavid du Colombier [0x62]	RMM,0,		"BOUND	%e,%r",
1071219b2ee8SDavid du Colombier [0x63]	RM,0,		"ARPL	%r,%e",
1072219b2ee8SDavid du Colombier [0x64]	SEG,0,		"FS:",
1073219b2ee8SDavid du Colombier [0x65]	SEG,0,		"GS:",
1074219b2ee8SDavid du Colombier [0x66]	OPOVER,0,	"",
1075219b2ee8SDavid du Colombier [0x67]	ADDOVER,0,	"",
1076219b2ee8SDavid du Colombier [0x68]	Iwd,0,		"PUSH%S	%i",
1077219b2ee8SDavid du Colombier [0x69]	RM,Iwd,		"IMUL%S	%e,%i,%r",
1078219b2ee8SDavid du Colombier [0x6a]	Ib,0,		"PUSH%S	%i",
1079219b2ee8SDavid du Colombier [0x6b]	RM,Ibs,		"IMUL%S	%e,%i,%r",
1080219b2ee8SDavid du Colombier [0x6c]	0,0,		"INSB	DX,(%ODI)",
1081219b2ee8SDavid du Colombier [0x6d]	0,0,		"INS%S	DX,(%ODI)",
1082219b2ee8SDavid du Colombier [0x6e]	0,0,		"OUTSB	(%ASI),DX",
1083219b2ee8SDavid du Colombier [0x6f]	0,0,		"OUTS%S	(%ASI),DX",
1084219b2ee8SDavid du Colombier [0x70]	Jbs,0,		"JOS	%p",
1085219b2ee8SDavid du Colombier [0x71]	Jbs,0,		"JOC	%p",
1086219b2ee8SDavid du Colombier [0x72]	Jbs,0,		"JCS	%p",
1087219b2ee8SDavid du Colombier [0x73]	Jbs,0,		"JCC	%p",
1088219b2ee8SDavid du Colombier [0x74]	Jbs,0,		"JEQ	%p",
1089219b2ee8SDavid du Colombier [0x75]	Jbs,0,		"JNE	%p",
1090219b2ee8SDavid du Colombier [0x76]	Jbs,0,		"JLS	%p",
1091219b2ee8SDavid du Colombier [0x77]	Jbs,0,		"JHI	%p",
1092219b2ee8SDavid du Colombier [0x78]	Jbs,0,		"JMI	%p",
1093219b2ee8SDavid du Colombier [0x79]	Jbs,0,		"JPL	%p",
1094219b2ee8SDavid du Colombier [0x7a]	Jbs,0,		"JPS	%p",
1095219b2ee8SDavid du Colombier [0x7b]	Jbs,0,		"JPC	%p",
1096219b2ee8SDavid du Colombier [0x7c]	Jbs,0,		"JLT	%p",
1097219b2ee8SDavid du Colombier [0x7d]	Jbs,0,		"JGE	%p",
1098219b2ee8SDavid du Colombier [0x7e]	Jbs,0,		"JLE	%p",
1099219b2ee8SDavid du Colombier [0x7f]	Jbs,0,		"JGT	%p",
1100219b2ee8SDavid du Colombier [0x80]	RMOPB,0,	optab80,
1101219b2ee8SDavid du Colombier [0x81]	RMOP,0,		optab81,
1102219b2ee8SDavid du Colombier [0x83]	RMOP,0,		optab83,
1103219b2ee8SDavid du Colombier [0x84]	RMB,0,		"TESTB	%r,%e",
1104219b2ee8SDavid du Colombier [0x85]	RM,0,		"TEST%S	%r,%e",
1105219b2ee8SDavid du Colombier [0x86]	RMB,0,		"XCHGB	%r,%e",
1106219b2ee8SDavid du Colombier [0x87]	RM,0,		"XCHG%S	%r,%e",
1107219b2ee8SDavid du Colombier [0x88]	RMB,0,		"MOVB	%r,%e",
1108219b2ee8SDavid du Colombier [0x89]	RM,0,		"MOV%S	%r,%e",
1109219b2ee8SDavid du Colombier [0x8a]	RMB,0,		"MOVB	%e,%r",
1110219b2ee8SDavid du Colombier [0x8b]	RM,0,		"MOV%S	%e,%r",
1111219b2ee8SDavid du Colombier [0x8c]	RM,0,		"MOVW	%g,%e",
11124de34a7eSDavid du Colombier [0x8d]	RM,0,		"LEA%S	%e,%r",
1113219b2ee8SDavid du Colombier [0x8e]	RM,0,		"MOVW	%e,%g",
1114219b2ee8SDavid du Colombier [0x8f]	RM,0,		"POP%S	%e",
1115219b2ee8SDavid du Colombier [0x90]	0,0,		"NOP",
1116219b2ee8SDavid du Colombier [0x91]	0,0,		"XCHG	%OCX,%OAX",
11177dd7cddfSDavid du Colombier [0x92]	0,0,		"XCHG	%ODX,%OAX",
11187dd7cddfSDavid du Colombier [0x93]	0,0,		"XCHG	%OBX,%OAX",
1119219b2ee8SDavid du Colombier [0x94]	0,0,		"XCHG	%OSP,%OAX",
1120219b2ee8SDavid du Colombier [0x95]	0,0,		"XCHG	%OBP,%OAX",
1121219b2ee8SDavid du Colombier [0x96]	0,0,		"XCHG	%OSI,%OAX",
1122219b2ee8SDavid du Colombier [0x97]	0,0,		"XCHG	%ODI,%OAX",
1123b0dcc5a8SDavid du Colombier [0x98]	0,0,		"%W",			/* miserable CBW or CWDE */
1124b0dcc5a8SDavid du Colombier [0x99]	0,0,		"%w",			/* idiotic CWD or CDQ */
1125219b2ee8SDavid du Colombier [0x9a]	PTR,0,		"CALL%S	%d",
1126219b2ee8SDavid du Colombier [0x9b]	0,0,		"WAIT",
11277dd7cddfSDavid du Colombier [0x9c]	0,0,		"PUSHF",
11287dd7cddfSDavid du Colombier [0x9d]	0,0,		"POPF",
11297dd7cddfSDavid du Colombier [0x9e]	0,0,		"SAHF",
1130219b2ee8SDavid du Colombier [0x9f]	0,0,		"LAHF",
1131219b2ee8SDavid du Colombier [0xa0]	Awd,0,		"MOVB	%i,AL",
1132219b2ee8SDavid du Colombier [0xa1]	Awd,0,		"MOV%S	%i,%OAX",
1133219b2ee8SDavid du Colombier [0xa2]	Awd,0,		"MOVB	AL,%i",
1134219b2ee8SDavid du Colombier [0xa3]	Awd,0,		"MOV%S	%OAX,%i",
1135219b2ee8SDavid du Colombier [0xa4]	0,0,		"MOVSB	(%ASI),(%ADI)",
1136219b2ee8SDavid du Colombier [0xa5]	0,0,		"MOVS%S	(%ASI),(%ADI)",
1137219b2ee8SDavid du Colombier [0xa6]	0,0,		"CMPSB	(%ASI),(%ADI)",
1138219b2ee8SDavid du Colombier [0xa7]	0,0,		"CMPS%S	(%ASI),(%ADI)",
1139219b2ee8SDavid du Colombier [0xa8]	Ib,0,		"TESTB	%i,AL",
1140219b2ee8SDavid du Colombier [0xa9]	Iwd,0,		"TEST%S	%i,%OAX",
1141219b2ee8SDavid du Colombier [0xaa]	0,0,		"STOSB	AL,(%ADI)",
1142219b2ee8SDavid du Colombier [0xab]	0,0,		"STOS%S	%OAX,(%ADI)",
1143219b2ee8SDavid du Colombier [0xac]	0,0,		"LODSB	(%ASI),AL",
1144219b2ee8SDavid du Colombier [0xad]	0,0,		"LODS%S	(%ASI),%OAX",
1145219b2ee8SDavid du Colombier [0xae]	0,0,		"SCASB	(%ADI),AL",
1146219b2ee8SDavid du Colombier [0xaf]	0,0,		"SCAS%S	(%ADI),%OAX",
1147219b2ee8SDavid du Colombier [0xb0]	Ib,0,		"MOVB	%i,AL",
1148219b2ee8SDavid du Colombier [0xb1]	Ib,0,		"MOVB	%i,CL",
1149219b2ee8SDavid du Colombier [0xb2]	Ib,0,		"MOVB	%i,DL",
1150219b2ee8SDavid du Colombier [0xb3]	Ib,0,		"MOVB	%i,BL",
1151219b2ee8SDavid du Colombier [0xb4]	Ib,0,		"MOVB	%i,AH",
1152219b2ee8SDavid du Colombier [0xb5]	Ib,0,		"MOVB	%i,CH",
1153219b2ee8SDavid du Colombier [0xb6]	Ib,0,		"MOVB	%i,DH",
1154219b2ee8SDavid du Colombier [0xb7]	Ib,0,		"MOVB	%i,BH",
1155b0dcc5a8SDavid du Colombier [0xb8]	Iwdq,0,		"MOV%S	%i,%OAX",
1156b0dcc5a8SDavid du Colombier [0xb9]	Iwdq,0,		"MOV%S	%i,%OCX",
1157b0dcc5a8SDavid du Colombier [0xba]	Iwdq,0,		"MOV%S	%i,%ODX",
1158b0dcc5a8SDavid du Colombier [0xbb]	Iwdq,0,		"MOV%S	%i,%OBX",
1159b0dcc5a8SDavid du Colombier [0xbc]	Iwdq,0,		"MOV%S	%i,%OSP",
1160b0dcc5a8SDavid du Colombier [0xbd]	Iwdq,0,		"MOV%S	%i,%OBP",
1161b0dcc5a8SDavid du Colombier [0xbe]	Iwdq,0,		"MOV%S	%i,%OSI",
1162b0dcc5a8SDavid du Colombier [0xbf]	Iwdq,0,		"MOV%S	%i,%ODI",
1163219b2ee8SDavid du Colombier [0xc0]	RMOPB,0,	optabC0,
1164219b2ee8SDavid du Colombier [0xc1]	RMOP,0,		optabC1,
1165219b2ee8SDavid du Colombier [0xc2]	Iw,0,		"RET	%i",
1166219b2ee8SDavid du Colombier [0xc3]	RET,0,		"RET",
1167219b2ee8SDavid du Colombier [0xc4]	RM,0,		"LES	%e,%r",
1168219b2ee8SDavid du Colombier [0xc5]	RM,0,		"LDS	%e,%r",
1169219b2ee8SDavid du Colombier [0xc6]	RMB,Ib,		"MOVB	%i,%e",
1170219b2ee8SDavid du Colombier [0xc7]	RM,Iwd,		"MOV%S	%i,%e",
1171219b2ee8SDavid du Colombier [0xc8]	Iw2,Ib,		"ENTER	%i,%I",		/* loony ENTER */
1172219b2ee8SDavid du Colombier [0xc9]	RET,0,		"LEAVE",		/* bizarre LEAVE */
1173219b2ee8SDavid du Colombier [0xca]	Iw,0,		"RETF	%i",
1174219b2ee8SDavid du Colombier [0xcb]	RET,0,		"RETF",
1175219b2ee8SDavid du Colombier [0xcc]	0,0,		"INT	3",
1176219b2ee8SDavid du Colombier [0xcd]	Ib,0,		"INTB	%i",
1177219b2ee8SDavid du Colombier [0xce]	0,0,		"INTO",
1178219b2ee8SDavid du Colombier [0xcf]	0,0,		"IRET",
1179219b2ee8SDavid du Colombier [0xd0]	RMOPB,0,	optabD0,
1180219b2ee8SDavid du Colombier [0xd1]	RMOP,0,		optabD1,
1181219b2ee8SDavid du Colombier [0xd2]	RMOPB,0,	optabD2,
1182219b2ee8SDavid du Colombier [0xd3]	RMOP,0,		optabD3,
1183219b2ee8SDavid du Colombier [0xd4]	OA,0,		"AAM",
1184219b2ee8SDavid du Colombier [0xd5]	OA,0,		"AAD",
1185219b2ee8SDavid du Colombier [0xd7]	0,0,		"XLAT",
1186219b2ee8SDavid du Colombier [0xd8]	FRMOP,0,	optabD8,
1187219b2ee8SDavid du Colombier [0xd9]	FRMEX,0,	optabD9,
1188219b2ee8SDavid du Colombier [0xda]	FRMOP,0,	optabDA,
1189219b2ee8SDavid du Colombier [0xdb]	FRMEX,0,	optabDB,
1190219b2ee8SDavid du Colombier [0xdc]	FRMOP,0,	optabDC,
1191219b2ee8SDavid du Colombier [0xdd]	FRMOP,0,	optabDD,
1192219b2ee8SDavid du Colombier [0xde]	FRMOP,0,	optabDE,
1193219b2ee8SDavid du Colombier [0xdf]	FRMOP,0,	optabDF,
1194219b2ee8SDavid du Colombier [0xe0]	Jbs,0,		"LOOPNE	%p",
1195219b2ee8SDavid du Colombier [0xe1]	Jbs,0,		"LOOPE	%p",
1196219b2ee8SDavid du Colombier [0xe2]	Jbs,0,		"LOOP	%p",
1197219b2ee8SDavid du Colombier [0xe3]	Jbs,0,		"JCXZ	%p",
1198219b2ee8SDavid du Colombier [0xe4]	Ib,0,		"INB	%i,AL",
1199219b2ee8SDavid du Colombier [0xe5]	Ib,0,		"IN%S	%i,%OAX",
1200219b2ee8SDavid du Colombier [0xe6]	Ib,0,		"OUTB	AL,%i",
1201219b2ee8SDavid du Colombier [0xe7]	Ib,0,		"OUT%S	%OAX,%i",
1202219b2ee8SDavid du Colombier [0xe8]	Iwds,0,		"CALL	%p",
1203219b2ee8SDavid du Colombier [0xe9]	Iwds,0,		"JMP	%p",
1204219b2ee8SDavid du Colombier [0xea]	PTR,0,		"JMP	%d",
1205219b2ee8SDavid du Colombier [0xeb]	Jbs,0,		"JMP	%p",
1206219b2ee8SDavid du Colombier [0xec]	0,0,		"INB	DX,AL",
1207219b2ee8SDavid du Colombier [0xed]	0,0,		"IN%S	DX,%OAX",
1208219b2ee8SDavid du Colombier [0xee]	0,0,		"OUTB	AL,DX",
1209219b2ee8SDavid du Colombier [0xef]	0,0,		"OUT%S	%OAX,DX",
1210219b2ee8SDavid du Colombier [0xf0]	PRE,0,		"LOCK",
1211b0dcc5a8SDavid du Colombier [0xf2]	OPRE,0,		"REPNE",
1212b0dcc5a8SDavid du Colombier [0xf3]	OPRE,0,		"REP",
1213*3b86f2f8SDavid du Colombier [0xf4]	0,0,		"HLT",
1214219b2ee8SDavid du Colombier [0xf5]	0,0,		"CMC",
1215219b2ee8SDavid du Colombier [0xf6]	RMOPB,0,	optabF6,
1216219b2ee8SDavid du Colombier [0xf7]	RMOP,0,		optabF7,
1217219b2ee8SDavid du Colombier [0xf8]	0,0,		"CLC",
1218219b2ee8SDavid du Colombier [0xf9]	0,0,		"STC",
1219219b2ee8SDavid du Colombier [0xfa]	0,0,		"CLI",
1220219b2ee8SDavid du Colombier [0xfb]	0,0,		"STI",
1221219b2ee8SDavid du Colombier [0xfc]	0,0,		"CLD",
1222219b2ee8SDavid du Colombier [0xfd]	0,0,		"STD",
1223219b2ee8SDavid du Colombier [0xfe]	RMOPB,0,	optabFE,
1224219b2ee8SDavid du Colombier [0xff]	RMOP,0,		optabFF,
1225b0dcc5a8SDavid du Colombier [0x100]	RM,0,		"MOVLQSX	%r,%e",
1226219b2ee8SDavid du Colombier };
1227219b2ee8SDavid du Colombier 
1228219b2ee8SDavid du Colombier /*
1229219b2ee8SDavid du Colombier  *  get a byte of the instruction
1230219b2ee8SDavid du Colombier  */
1231219b2ee8SDavid du Colombier static int
igetc(Map * map,Instr * ip,uchar * c)1232219b2ee8SDavid du Colombier igetc(Map *map, Instr *ip, uchar *c)
1233219b2ee8SDavid du Colombier {
1234219b2ee8SDavid du Colombier 	if(ip->n+1 > sizeof(ip->mem)){
1235219b2ee8SDavid du Colombier 		werrstr("instruction too long");
1236219b2ee8SDavid du Colombier 		return -1;
1237219b2ee8SDavid du Colombier 	}
1238219b2ee8SDavid du Colombier 	if (get1(map, ip->addr+ip->n, c, 1) < 0) {
1239219b2ee8SDavid du Colombier 		werrstr("can't read instruction: %r");
1240219b2ee8SDavid du Colombier 		return -1;
1241219b2ee8SDavid du Colombier 	}
1242219b2ee8SDavid du Colombier 	ip->mem[ip->n++] = *c;
1243219b2ee8SDavid du Colombier 	return 1;
1244219b2ee8SDavid du Colombier }
1245219b2ee8SDavid du Colombier 
1246219b2ee8SDavid du Colombier /*
1247219b2ee8SDavid du Colombier  *  get two bytes of the instruction
1248219b2ee8SDavid du Colombier  */
1249219b2ee8SDavid du Colombier static int
igets(Map * map,Instr * ip,ushort * sp)1250219b2ee8SDavid du Colombier igets(Map *map, Instr *ip, ushort *sp)
1251219b2ee8SDavid du Colombier {
1252219b2ee8SDavid du Colombier 	uchar c;
1253219b2ee8SDavid du Colombier 	ushort s;
1254219b2ee8SDavid du Colombier 
1255219b2ee8SDavid du Colombier 	if (igetc(map, ip, &c) < 0)
1256219b2ee8SDavid du Colombier 		return -1;
1257219b2ee8SDavid du Colombier 	s = c;
1258219b2ee8SDavid du Colombier 	if (igetc(map, ip, &c) < 0)
1259219b2ee8SDavid du Colombier 		return -1;
1260219b2ee8SDavid du Colombier 	s |= (c<<8);
1261219b2ee8SDavid du Colombier 	*sp = s;
1262219b2ee8SDavid du Colombier 	return 1;
1263219b2ee8SDavid du Colombier }
1264219b2ee8SDavid du Colombier 
1265219b2ee8SDavid du Colombier /*
1266219b2ee8SDavid du Colombier  *  get 4 bytes of the instruction
1267219b2ee8SDavid du Colombier  */
1268219b2ee8SDavid du Colombier static int
igetl(Map * map,Instr * ip,ulong * lp)1269219b2ee8SDavid du Colombier igetl(Map *map, Instr *ip, ulong *lp)
1270219b2ee8SDavid du Colombier {
1271219b2ee8SDavid du Colombier 	ushort s;
1272219b2ee8SDavid du Colombier 	long	l;
1273219b2ee8SDavid du Colombier 
1274219b2ee8SDavid du Colombier 	if (igets(map, ip, &s) < 0)
1275219b2ee8SDavid du Colombier 		return -1;
1276219b2ee8SDavid du Colombier 	l = s;
1277219b2ee8SDavid du Colombier 	if (igets(map, ip, &s) < 0)
1278219b2ee8SDavid du Colombier 		return -1;
1279219b2ee8SDavid du Colombier 	l |= (s<<16);
1280219b2ee8SDavid du Colombier 	*lp = l;
1281219b2ee8SDavid du Colombier 	return 1;
1282219b2ee8SDavid du Colombier }
1283219b2ee8SDavid du Colombier 
1284b0dcc5a8SDavid du Colombier /*
1285b0dcc5a8SDavid du Colombier  *  get 8 bytes of the instruction
1286b0dcc5a8SDavid du Colombier  */
1287219b2ee8SDavid du Colombier static int
igetq(Map * map,Instr * ip,vlong * qp)1288b0dcc5a8SDavid du Colombier igetq(Map *map, Instr *ip, vlong *qp)
1289b0dcc5a8SDavid du Colombier {
1290b0dcc5a8SDavid du Colombier 	ulong	l;
1291b0dcc5a8SDavid du Colombier 	uvlong q;
1292b0dcc5a8SDavid du Colombier 
1293b0dcc5a8SDavid du Colombier 	if (igetl(map, ip, &l) < 0)
1294b0dcc5a8SDavid du Colombier 		return -1;
1295b0dcc5a8SDavid du Colombier 	q = l;
1296b0dcc5a8SDavid du Colombier 	if (igetl(map, ip, &l) < 0)
1297b0dcc5a8SDavid du Colombier 		return -1;
1298b0dcc5a8SDavid du Colombier 	q |= ((uvlong)l<<32);
1299b0dcc5a8SDavid du Colombier 	*qp = q;
1300b0dcc5a8SDavid du Colombier 	return 1;
1301b0dcc5a8SDavid du Colombier }
1302b0dcc5a8SDavid du Colombier 
1303b0dcc5a8SDavid du Colombier static int
getdisp(Map * map,Instr * ip,int mod,int rm,int code,int pcrel)1304b0dcc5a8SDavid du Colombier getdisp(Map *map, Instr *ip, int mod, int rm, int code, int pcrel)
1305219b2ee8SDavid du Colombier {
1306219b2ee8SDavid du Colombier 	uchar c;
1307219b2ee8SDavid du Colombier 	ushort s;
1308219b2ee8SDavid du Colombier 
1309219b2ee8SDavid du Colombier 	if (mod > 2)
1310219b2ee8SDavid du Colombier 		return 1;
1311219b2ee8SDavid du Colombier 	if (mod == 1) {
1312219b2ee8SDavid du Colombier 		if (igetc(map, ip, &c) < 0)
1313219b2ee8SDavid du Colombier 			return -1;
1314219b2ee8SDavid du Colombier 		if (c&0x80)
1315219b2ee8SDavid du Colombier 			ip->disp = c|0xffffff00;
1316219b2ee8SDavid du Colombier 		else
1317219b2ee8SDavid du Colombier 			ip->disp = c&0xff;
1318219b2ee8SDavid du Colombier 	} else if (mod == 2 || rm == code) {
1319219b2ee8SDavid du Colombier 		if (ip->asize == 'E') {
1320219b2ee8SDavid du Colombier 			if (igetl(map, ip, &ip->disp) < 0)
1321219b2ee8SDavid du Colombier 				return -1;
1322b0dcc5a8SDavid du Colombier 			if (mod == 0)
1323b0dcc5a8SDavid du Colombier 				ip->rip = pcrel;
1324219b2ee8SDavid du Colombier 		} else {
1325219b2ee8SDavid du Colombier 			if (igets(map, ip, &s) < 0)
1326219b2ee8SDavid du Colombier 				return -1;
1327219b2ee8SDavid du Colombier 			if (s&0x8000)
1328219b2ee8SDavid du Colombier 				ip->disp = s|0xffff0000;
1329219b2ee8SDavid du Colombier 			else
1330219b2ee8SDavid du Colombier 				ip->disp = s;
1331219b2ee8SDavid du Colombier 		}
1332219b2ee8SDavid du Colombier 		if (mod == 0)
1333219b2ee8SDavid du Colombier 			ip->base = -1;
1334219b2ee8SDavid du Colombier 	}
1335219b2ee8SDavid du Colombier 	return 1;
1336219b2ee8SDavid du Colombier }
1337219b2ee8SDavid du Colombier 
1338219b2ee8SDavid du Colombier static int
modrm(Map * map,Instr * ip,uchar c)1339219b2ee8SDavid du Colombier modrm(Map *map, Instr *ip, uchar c)
1340219b2ee8SDavid du Colombier {
1341219b2ee8SDavid du Colombier 	uchar rm, mod;
1342219b2ee8SDavid du Colombier 
1343219b2ee8SDavid du Colombier 	mod = (c>>6)&3;
1344219b2ee8SDavid du Colombier 	rm = c&7;
1345219b2ee8SDavid du Colombier 	ip->mod = mod;
1346219b2ee8SDavid du Colombier 	ip->base = rm;
1347219b2ee8SDavid du Colombier 	ip->reg = (c>>3)&7;
1348b0dcc5a8SDavid du Colombier 	ip->rip = 0;
1349219b2ee8SDavid du Colombier 	if (mod == 3)			/* register */
1350219b2ee8SDavid du Colombier 		return 1;
1351219b2ee8SDavid du Colombier 	if (ip->asize == 0) {		/* 16-bit mode */
1352b0dcc5a8SDavid du Colombier 		switch(rm) {
1353219b2ee8SDavid du Colombier 		case 0:
1354219b2ee8SDavid du Colombier 			ip->base = BX; ip->index = SI;
1355219b2ee8SDavid du Colombier 			break;
1356219b2ee8SDavid du Colombier 		case 1:
1357219b2ee8SDavid du Colombier 			ip->base = BX; ip->index = DI;
1358219b2ee8SDavid du Colombier 			break;
1359219b2ee8SDavid du Colombier 		case 2:
1360219b2ee8SDavid du Colombier 			ip->base = BP; ip->index = SI;
1361219b2ee8SDavid du Colombier 			break;
1362219b2ee8SDavid du Colombier 		case 3:
1363219b2ee8SDavid du Colombier 			ip->base = BP; ip->index = DI;
1364219b2ee8SDavid du Colombier 			break;
1365219b2ee8SDavid du Colombier 		case 4:
1366219b2ee8SDavid du Colombier 			ip->base = SI;
1367219b2ee8SDavid du Colombier 			break;
1368219b2ee8SDavid du Colombier 		case 5:
1369219b2ee8SDavid du Colombier 			ip->base = DI;
1370219b2ee8SDavid du Colombier 			break;
1371219b2ee8SDavid du Colombier 		case 6:
1372219b2ee8SDavid du Colombier 			ip->base = BP;
1373219b2ee8SDavid du Colombier 			break;
1374219b2ee8SDavid du Colombier 		case 7:
1375219b2ee8SDavid du Colombier 			ip->base = BX;
1376219b2ee8SDavid du Colombier 			break;
1377219b2ee8SDavid du Colombier 		default:
1378219b2ee8SDavid du Colombier 			break;
1379219b2ee8SDavid du Colombier 		}
1380b0dcc5a8SDavid du Colombier 		return getdisp(map, ip, mod, rm, 6, 0);
1381219b2ee8SDavid du Colombier 	}
1382219b2ee8SDavid du Colombier 	if (rm == 4) {	/* scummy sib byte */
1383219b2ee8SDavid du Colombier 		if (igetc(map, ip, &c) < 0)
1384219b2ee8SDavid du Colombier 			return -1;
1385219b2ee8SDavid du Colombier 		ip->ss = (c>>6)&0x03;
1386219b2ee8SDavid du Colombier 		ip->index = (c>>3)&0x07;
1387219b2ee8SDavid du Colombier 		if (ip->index == 4)
1388219b2ee8SDavid du Colombier 			ip->index = -1;
1389219b2ee8SDavid du Colombier 		ip->base = c&0x07;
1390b0dcc5a8SDavid du Colombier 		return getdisp(map, ip, mod, ip->base, 5, 0);
1391219b2ee8SDavid du Colombier 	}
1392b0dcc5a8SDavid du Colombier 	return getdisp(map, ip, mod, rm, 5, ip->amd64);
1393219b2ee8SDavid du Colombier }
1394219b2ee8SDavid du Colombier 
1395219b2ee8SDavid du Colombier static Optable *
mkinstr(Map * map,Instr * ip,uvlong pc)13964de34a7eSDavid du Colombier mkinstr(Map *map, Instr *ip, uvlong pc)
1397219b2ee8SDavid du Colombier {
1398b0dcc5a8SDavid du Colombier 	int i, n, norex;
1399219b2ee8SDavid du Colombier 	uchar c;
1400219b2ee8SDavid du Colombier 	ushort s;
1401219b2ee8SDavid du Colombier 	Optable *op, *obase;
1402219b2ee8SDavid du Colombier 	char buf[128];
1403219b2ee8SDavid du Colombier 
1404219b2ee8SDavid du Colombier 	memset(ip, 0, sizeof(*ip));
1405b0dcc5a8SDavid du Colombier 	norex = 1;
1406219b2ee8SDavid du Colombier 	ip->base = -1;
1407219b2ee8SDavid du Colombier 	ip->index = -1;
1408219b2ee8SDavid du Colombier 	if(asstype == AI8086)
1409219b2ee8SDavid du Colombier 		ip->osize = 'W';
1410219b2ee8SDavid du Colombier 	else {
1411219b2ee8SDavid du Colombier 		ip->osize = 'L';
1412219b2ee8SDavid du Colombier 		ip->asize = 'E';
1413b0dcc5a8SDavid du Colombier 		ip->amd64 = asstype != AI386;
1414b0dcc5a8SDavid du Colombier 		norex = 0;
1415219b2ee8SDavid du Colombier 	}
1416219b2ee8SDavid du Colombier 	ip->addr = pc;
1417219b2ee8SDavid du Colombier 	if (igetc(map, ip, &c) < 0)
1418219b2ee8SDavid du Colombier 		return 0;
1419219b2ee8SDavid du Colombier 	obase = optable;
1420219b2ee8SDavid du Colombier newop:
1421b0dcc5a8SDavid du Colombier 	if(ip->amd64 && !norex){
1422b0dcc5a8SDavid du Colombier 		if(c >= 0x40 && c <= 0x4f) {
1423b0dcc5a8SDavid du Colombier 			ip->rex = c;
1424b0dcc5a8SDavid du Colombier 			if(igetc(map, ip, &c) < 0)
1425b0dcc5a8SDavid du Colombier 				return 0;
1426b0dcc5a8SDavid du Colombier 		}
1427b0dcc5a8SDavid du Colombier 		if(c == 0x63){
1428b0dcc5a8SDavid du Colombier 			op = &obase[0x100];	/* MOVLQSX */
1429b0dcc5a8SDavid du Colombier 			goto hack;
1430b0dcc5a8SDavid du Colombier 		}
1431b0dcc5a8SDavid du Colombier 	}
1432219b2ee8SDavid du Colombier 	op = &obase[c];
1433b0dcc5a8SDavid du Colombier hack:
1434219b2ee8SDavid du Colombier 	if (op->proto == 0) {
1435219b2ee8SDavid du Colombier badop:
1436219b2ee8SDavid du Colombier 		n = snprint(buf, sizeof(buf), "opcode: ??");
1437219b2ee8SDavid du Colombier 		for (i = 0; i < ip->n && n < sizeof(buf)-3; i++, n+=2)
1438219b2ee8SDavid du Colombier 			_hexify(buf+n, ip->mem[i], 1);
1439219b2ee8SDavid du Colombier 		strcpy(buf+n, "??");
1440219b2ee8SDavid du Colombier 		werrstr(buf);
1441219b2ee8SDavid du Colombier 		return 0;
1442219b2ee8SDavid du Colombier 	}
1443219b2ee8SDavid du Colombier 	for(i = 0; i < 2 && op->operand[i]; i++) {
1444b0dcc5a8SDavid du Colombier 		switch(op->operand[i]) {
1445219b2ee8SDavid du Colombier 		case Ib:	/* 8-bit immediate - (no sign extension)*/
1446219b2ee8SDavid du Colombier 			if (igetc(map, ip, &c) < 0)
1447219b2ee8SDavid du Colombier 				return 0;
1448219b2ee8SDavid du Colombier 			ip->imm = c&0xff;
1449373b2ef6SDavid du Colombier 			ip->imm64 = ip->imm;
1450219b2ee8SDavid du Colombier 			break;
1451219b2ee8SDavid du Colombier 		case Jbs:	/* 8-bit jump immediate (sign extended) */
1452219b2ee8SDavid du Colombier 			if (igetc(map, ip, &c) < 0)
1453219b2ee8SDavid du Colombier 				return 0;
1454219b2ee8SDavid du Colombier 			if (c&0x80)
1455219b2ee8SDavid du Colombier 				ip->imm = c|0xffffff00;
1456219b2ee8SDavid du Colombier 			else
1457219b2ee8SDavid du Colombier 				ip->imm = c&0xff;
1458373b2ef6SDavid du Colombier 			ip->imm64 = (long)ip->imm;
1459219b2ee8SDavid du Colombier 			ip->jumptype = Jbs;
1460219b2ee8SDavid du Colombier 			break;
1461219b2ee8SDavid du Colombier 		case Ibs:	/* 8-bit immediate (sign extended) */
1462219b2ee8SDavid du Colombier 			if (igetc(map, ip, &c) < 0)
1463219b2ee8SDavid du Colombier 				return 0;
1464219b2ee8SDavid du Colombier 			if (c&0x80)
1465219b2ee8SDavid du Colombier 				if (ip->osize == 'L')
1466219b2ee8SDavid du Colombier 					ip->imm = c|0xffffff00;
1467219b2ee8SDavid du Colombier 				else
1468219b2ee8SDavid du Colombier 					ip->imm = c|0xff00;
1469219b2ee8SDavid du Colombier 			else
1470219b2ee8SDavid du Colombier 				ip->imm = c&0xff;
14714de34a7eSDavid du Colombier 			ip->imm64 = (long)ip->imm;
1472219b2ee8SDavid du Colombier 			break;
1473219b2ee8SDavid du Colombier 		case Iw:	/* 16-bit immediate -> imm */
1474219b2ee8SDavid du Colombier 			if (igets(map, ip, &s) < 0)
1475219b2ee8SDavid du Colombier 				return 0;
1476219b2ee8SDavid du Colombier 			ip->imm = s&0xffff;
1477373b2ef6SDavid du Colombier 			ip->imm64 = ip->imm;
1478219b2ee8SDavid du Colombier 			ip->jumptype = Iw;
1479219b2ee8SDavid du Colombier 			break;
1480219b2ee8SDavid du Colombier 		case Iw2:	/* 16-bit immediate -> in imm2*/
1481219b2ee8SDavid du Colombier 			if (igets(map, ip, &s) < 0)
1482219b2ee8SDavid du Colombier 				return 0;
1483219b2ee8SDavid du Colombier 			ip->imm2 = s&0xffff;
1484219b2ee8SDavid du Colombier 			break;
1485b0dcc5a8SDavid du Colombier 		case Iwd:	/* Operand-sized immediate (no sign extension unless 64 bits)*/
1486219b2ee8SDavid du Colombier 			if (ip->osize == 'L') {
1487219b2ee8SDavid du Colombier 				if (igetl(map, ip, &ip->imm) < 0)
1488219b2ee8SDavid du Colombier 					return 0;
1489b0dcc5a8SDavid du Colombier 				ip->imm64 = ip->imm;
1490b0dcc5a8SDavid du Colombier 				if(ip->rex&REXW && (ip->imm & (1<<31)) != 0)
1491b0dcc5a8SDavid du Colombier 					ip->imm64 |= (vlong)~0 << 32;
1492b0dcc5a8SDavid du Colombier 			} else {
1493b0dcc5a8SDavid du Colombier 				if (igets(map, ip, &s)< 0)
1494b0dcc5a8SDavid du Colombier 					return 0;
1495b0dcc5a8SDavid du Colombier 				ip->imm = s&0xffff;
1496b0dcc5a8SDavid du Colombier 				ip->imm64 = ip->imm;
1497b0dcc5a8SDavid du Colombier 			}
1498b0dcc5a8SDavid du Colombier 			break;
1499b0dcc5a8SDavid du Colombier 		case Iwdq:	/* Operand-sized immediate, possibly big */
1500b0dcc5a8SDavid du Colombier 			if (ip->osize == 'L') {
1501b0dcc5a8SDavid du Colombier 				if (igetl(map, ip, &ip->imm) < 0)
1502b0dcc5a8SDavid du Colombier 					return 0;
1503b0dcc5a8SDavid du Colombier 				ip->imm64 = ip->imm;
1504b0dcc5a8SDavid du Colombier 				if (ip->rex & REXW) {
1505b0dcc5a8SDavid du Colombier 					ulong l;
1506b0dcc5a8SDavid du Colombier 					if (igetl(map, ip, &l) < 0)
1507b0dcc5a8SDavid du Colombier 						return 0;
1508b0dcc5a8SDavid du Colombier 					ip->imm64 |= (uvlong)l << 32;
1509b0dcc5a8SDavid du Colombier 				}
1510219b2ee8SDavid du Colombier 			} else {
1511219b2ee8SDavid du Colombier 				if (igets(map, ip, &s)< 0)
1512219b2ee8SDavid du Colombier 					return 0;
1513219b2ee8SDavid du Colombier 				ip->imm = s&0xffff;
1514219b2ee8SDavid du Colombier 			}
1515219b2ee8SDavid du Colombier 			break;
1516219b2ee8SDavid du Colombier 		case Awd:	/* Address-sized immediate (no sign extension)*/
1517219b2ee8SDavid du Colombier 			if (ip->asize == 'E') {
1518219b2ee8SDavid du Colombier 				if (igetl(map, ip, &ip->imm) < 0)
1519219b2ee8SDavid du Colombier 					return 0;
1520b0dcc5a8SDavid du Colombier 				/* TO DO: REX */
1521219b2ee8SDavid du Colombier 			} else {
1522219b2ee8SDavid du Colombier 				if (igets(map, ip, &s)< 0)
1523219b2ee8SDavid du Colombier 					return 0;
1524219b2ee8SDavid du Colombier 				ip->imm = s&0xffff;
1525219b2ee8SDavid du Colombier 			}
1526219b2ee8SDavid du Colombier 			break;
1527219b2ee8SDavid du Colombier 		case Iwds:	/* Operand-sized immediate (sign extended) */
1528219b2ee8SDavid du Colombier 			if (ip->osize == 'L') {
1529219b2ee8SDavid du Colombier 				if (igetl(map, ip, &ip->imm) < 0)
1530219b2ee8SDavid du Colombier 					return 0;
1531219b2ee8SDavid du Colombier 			} else {
1532219b2ee8SDavid du Colombier 				if (igets(map, ip, &s)< 0)
1533219b2ee8SDavid du Colombier 					return 0;
1534219b2ee8SDavid du Colombier 				if (s&0x8000)
1535219b2ee8SDavid du Colombier 					ip->imm = s|0xffff0000;
1536219b2ee8SDavid du Colombier 				else
1537219b2ee8SDavid du Colombier 					ip->imm = s&0xffff;
1538219b2ee8SDavid du Colombier 			}
1539219b2ee8SDavid du Colombier 			ip->jumptype = Iwds;
1540219b2ee8SDavid du Colombier 			break;
1541219b2ee8SDavid du Colombier 		case OA:	/* literal 0x0a byte */
1542219b2ee8SDavid du Colombier 			if (igetc(map, ip, &c) < 0)
1543219b2ee8SDavid du Colombier 				return 0;
1544219b2ee8SDavid du Colombier 			if (c != 0x0a)
1545219b2ee8SDavid du Colombier 				goto badop;
1546219b2ee8SDavid du Colombier 			break;
1547219b2ee8SDavid du Colombier 		case R0:	/* base register must be R0 */
1548219b2ee8SDavid du Colombier 			if (ip->base != 0)
1549219b2ee8SDavid du Colombier 				goto badop;
1550219b2ee8SDavid du Colombier 			break;
1551219b2ee8SDavid du Colombier 		case R1:	/* base register must be R1 */
1552219b2ee8SDavid du Colombier 			if (ip->base != 1)
1553219b2ee8SDavid du Colombier 				goto badop;
1554219b2ee8SDavid du Colombier 			break;
1555219b2ee8SDavid du Colombier 		case RMB:	/* R/M field with byte register (/r)*/
1556219b2ee8SDavid du Colombier 			if (igetc(map, ip, &c) < 0)
1557219b2ee8SDavid du Colombier 				return 0;
1558219b2ee8SDavid du Colombier 			if (modrm(map, ip, c) < 0)
1559219b2ee8SDavid du Colombier 				return 0;
1560219b2ee8SDavid du Colombier 			ip->osize = 'B';
1561219b2ee8SDavid du Colombier 			break;
1562219b2ee8SDavid du Colombier 		case RM:	/* R/M field with register (/r) */
1563219b2ee8SDavid du Colombier 			if (igetc(map, ip, &c) < 0)
1564219b2ee8SDavid du Colombier 				return 0;
1565219b2ee8SDavid du Colombier 			if (modrm(map, ip, c) < 0)
1566219b2ee8SDavid du Colombier 				return 0;
1567219b2ee8SDavid du Colombier 			break;
1568219b2ee8SDavid du Colombier 		case RMOPB:	/* R/M field with op code (/digit) */
1569219b2ee8SDavid du Colombier 			if (igetc(map, ip, &c) < 0)
1570219b2ee8SDavid du Colombier 				return 0;
1571219b2ee8SDavid du Colombier 			if (modrm(map, ip, c) < 0)
1572219b2ee8SDavid du Colombier 				return 0;
1573219b2ee8SDavid du Colombier 			c = ip->reg;		/* secondary op code */
1574219b2ee8SDavid du Colombier 			obase = (Optable*)op->proto;
1575219b2ee8SDavid du Colombier 			ip->osize = 'B';
1576219b2ee8SDavid du Colombier 			goto newop;
1577219b2ee8SDavid du Colombier 		case RMOP:	/* R/M field with op code (/digit) */
1578219b2ee8SDavid du Colombier 			if (igetc(map, ip, &c) < 0)
1579219b2ee8SDavid du Colombier 				return 0;
1580219b2ee8SDavid du Colombier 			if (modrm(map, ip, c) < 0)
1581219b2ee8SDavid du Colombier 				return 0;
1582219b2ee8SDavid du Colombier 			obase = (Optable*)op->proto;
1583d5d7c35bSDavid du Colombier 			if(ip->amd64 && obase == optab0F01 && c == 0xF8)
1584d5d7c35bSDavid du Colombier 				return optab0F01F8;
1585d5d7c35bSDavid du Colombier 			c = ip->reg;
1586219b2ee8SDavid du Colombier 			goto newop;
1587219b2ee8SDavid du Colombier 		case FRMOP:	/* FP R/M field with op code (/digit) */
1588219b2ee8SDavid du Colombier 			if (igetc(map, ip, &c) < 0)
1589219b2ee8SDavid du Colombier 				return 0;
1590219b2ee8SDavid du Colombier 			if (modrm(map, ip, c) < 0)
1591219b2ee8SDavid du Colombier 				return 0;
1592219b2ee8SDavid du Colombier 			if ((c&0xc0) == 0xc0)
1593219b2ee8SDavid du Colombier 				c = ip->reg+8;		/* 16 entry table */
1594219b2ee8SDavid du Colombier 			else
1595219b2ee8SDavid du Colombier 				c = ip->reg;
1596219b2ee8SDavid du Colombier 			obase = (Optable*)op->proto;
1597219b2ee8SDavid du Colombier 			goto newop;
1598219b2ee8SDavid du Colombier 		case FRMEX:	/* Extended FP R/M field with op code (/digit) */
1599219b2ee8SDavid du Colombier 			if (igetc(map, ip, &c) < 0)
1600219b2ee8SDavid du Colombier 				return 0;
1601219b2ee8SDavid du Colombier 			if (modrm(map, ip, c) < 0)
1602219b2ee8SDavid du Colombier 				return 0;
1603219b2ee8SDavid du Colombier 			if ((c&0xc0) == 0xc0)
1604219b2ee8SDavid du Colombier 				c = (c&0x3f)+8;		/* 64-entry table */
1605219b2ee8SDavid du Colombier 			else
1606219b2ee8SDavid du Colombier 				c = ip->reg;
1607219b2ee8SDavid du Colombier 			obase = (Optable*)op->proto;
1608219b2ee8SDavid du Colombier 			goto newop;
1609219b2ee8SDavid du Colombier 		case RMR:	/* R/M register only (mod = 11) */
1610219b2ee8SDavid du Colombier 			if (igetc(map, ip, &c) < 0)
1611219b2ee8SDavid du Colombier 				return 0;
1612219b2ee8SDavid du Colombier 			if ((c&0xc0) != 0xc0) {
1613219b2ee8SDavid du Colombier 				werrstr("invalid R/M register: %x", c);
1614219b2ee8SDavid du Colombier 				return 0;
1615219b2ee8SDavid du Colombier 			}
1616219b2ee8SDavid du Colombier 			if (modrm(map, ip, c) < 0)
1617219b2ee8SDavid du Colombier 				return 0;
1618219b2ee8SDavid du Colombier 			break;
1619219b2ee8SDavid du Colombier 		case RMM:	/* R/M register only (mod = 11) */
1620219b2ee8SDavid du Colombier 			if (igetc(map, ip, &c) < 0)
1621219b2ee8SDavid du Colombier 				return 0;
1622219b2ee8SDavid du Colombier 			if ((c&0xc0) == 0xc0) {
1623219b2ee8SDavid du Colombier 				werrstr("invalid R/M memory mode: %x", c);
1624219b2ee8SDavid du Colombier 				return 0;
1625219b2ee8SDavid du Colombier 			}
1626219b2ee8SDavid du Colombier 			if (modrm(map, ip, c) < 0)
1627219b2ee8SDavid du Colombier 				return 0;
1628219b2ee8SDavid du Colombier 			break;
1629219b2ee8SDavid du Colombier 		case PTR:	/* Seg:Displacement addr (ptr16:16 or ptr16:32) */
1630219b2ee8SDavid du Colombier 			if (ip->osize == 'L') {
1631219b2ee8SDavid du Colombier 				if (igetl(map, ip, &ip->disp) < 0)
1632219b2ee8SDavid du Colombier 					return 0;
1633219b2ee8SDavid du Colombier 			} else {
1634219b2ee8SDavid du Colombier 				if (igets(map, ip, &s)< 0)
1635219b2ee8SDavid du Colombier 					return 0;
1636219b2ee8SDavid du Colombier 				ip->disp = s&0xffff;
1637219b2ee8SDavid du Colombier 			}
16387dd7cddfSDavid du Colombier 			if (igets(map, ip, (ushort*)&ip->seg) < 0)
16397dd7cddfSDavid du Colombier 				return 0;
1640219b2ee8SDavid du Colombier 			ip->jumptype = PTR;
1641219b2ee8SDavid du Colombier 			break;
1642b0dcc5a8SDavid du Colombier 		case AUXMM:	/* Multi-byte op code; prefix determines table selection */
1643b0dcc5a8SDavid du Colombier 			if (igetc(map, ip, &c) < 0)
1644b0dcc5a8SDavid du Colombier 				return 0;
1645b0dcc5a8SDavid du Colombier 			obase = (Optable*)op->proto;
1646b0dcc5a8SDavid du Colombier 			switch (ip->opre) {
1647b0dcc5a8SDavid du Colombier 			case 0x66:	op = optab660F; break;
1648b0dcc5a8SDavid du Colombier 			case 0xF2:	op = optabF20F; break;
1649b0dcc5a8SDavid du Colombier 			case 0xF3:	op = optabF30F; break;
1650b0dcc5a8SDavid du Colombier 			default:	op = nil; break;
1651b0dcc5a8SDavid du Colombier 			}
1652b0dcc5a8SDavid du Colombier 			if(op != nil && op[c].proto != nil)
1653b0dcc5a8SDavid du Colombier 				obase = op;
1654b0dcc5a8SDavid du Colombier 			norex = 1;	/* no more rex prefixes */
1655b0dcc5a8SDavid du Colombier 			/* otherwise the optab entry captures it */
1656b0dcc5a8SDavid du Colombier 			goto newop;
1657219b2ee8SDavid du Colombier 		case AUX:	/* Multi-byte op code - Auxiliary table */
1658219b2ee8SDavid du Colombier 			obase = (Optable*)op->proto;
1659219b2ee8SDavid du Colombier 			if (igetc(map, ip, &c) < 0)
1660219b2ee8SDavid du Colombier 				return 0;
1661219b2ee8SDavid du Colombier 			goto newop;
1662b0dcc5a8SDavid du Colombier 		case OPRE:	/* Instr Prefix or media op */
1663b0dcc5a8SDavid du Colombier 			ip->opre = c;
1664b0dcc5a8SDavid du Colombier 			/* fall through */
1665219b2ee8SDavid du Colombier 		case PRE:	/* Instr Prefix */
1666219b2ee8SDavid du Colombier 			ip->prefix = (char*)op->proto;
1667219b2ee8SDavid du Colombier 			if (igetc(map, ip, &c) < 0)
1668219b2ee8SDavid du Colombier 				return 0;
1669b0dcc5a8SDavid du Colombier 			if (ip->opre && c == 0x0F)
1670b0dcc5a8SDavid du Colombier 				ip->prefix = 0;
1671219b2ee8SDavid du Colombier 			goto newop;
1672219b2ee8SDavid du Colombier 		case SEG:	/* Segment Prefix */
1673219b2ee8SDavid du Colombier 			ip->segment = (char*)op->proto;
1674219b2ee8SDavid du Colombier 			if (igetc(map, ip, &c) < 0)
1675219b2ee8SDavid du Colombier 				return 0;
1676219b2ee8SDavid du Colombier 			goto newop;
1677219b2ee8SDavid du Colombier 		case OPOVER:	/* Operand size override */
1678b0dcc5a8SDavid du Colombier 			ip->opre = c;
1679219b2ee8SDavid du Colombier 			ip->osize = 'W';
1680219b2ee8SDavid du Colombier 			if (igetc(map, ip, &c) < 0)
1681219b2ee8SDavid du Colombier 				return 0;
1682b0dcc5a8SDavid du Colombier 			if (c == 0x0F)
1683b0dcc5a8SDavid du Colombier 				ip->osize = 'L';
1684b0dcc5a8SDavid du Colombier 			else if (ip->amd64 && (c&0xF0) == 0x40)
1685b0dcc5a8SDavid du Colombier 				ip->osize = 'Q';
1686219b2ee8SDavid du Colombier 			goto newop;
1687219b2ee8SDavid du Colombier 		case ADDOVER:	/* Address size override */
1688219b2ee8SDavid du Colombier 			ip->asize = 0;
1689219b2ee8SDavid du Colombier 			if (igetc(map, ip, &c) < 0)
1690219b2ee8SDavid du Colombier 				return 0;
1691219b2ee8SDavid du Colombier 			goto newop;
1692219b2ee8SDavid du Colombier 		case JUMP:	/* mark instruction as JUMP or RET */
1693219b2ee8SDavid du Colombier 		case RET:
1694219b2ee8SDavid du Colombier 			ip->jumptype = op->operand[i];
1695219b2ee8SDavid du Colombier 			break;
1696219b2ee8SDavid du Colombier 		default:
1697219b2ee8SDavid du Colombier 			werrstr("bad operand type %d", op->operand[i]);
1698219b2ee8SDavid du Colombier 			return 0;
1699219b2ee8SDavid du Colombier 		}
1700219b2ee8SDavid du Colombier 	}
1701219b2ee8SDavid du Colombier 	return op;
1702219b2ee8SDavid du Colombier }
1703219b2ee8SDavid du Colombier 
17041bd28109SDavid du Colombier #pragma	varargck	argpos	bprint		2
17051bd28109SDavid du Colombier 
1706219b2ee8SDavid du Colombier static void
bprint(Instr * ip,char * fmt,...)1707219b2ee8SDavid du Colombier bprint(Instr *ip, char *fmt, ...)
1708219b2ee8SDavid du Colombier {
17097dd7cddfSDavid du Colombier 	va_list arg;
17107dd7cddfSDavid du Colombier 
17117dd7cddfSDavid du Colombier 	va_start(arg, fmt);
17129a747e4fSDavid du Colombier 	ip->curr = vseprint(ip->curr, ip->end, fmt, arg);
17137dd7cddfSDavid du Colombier 	va_end(arg);
1714219b2ee8SDavid du Colombier }
1715219b2ee8SDavid du Colombier 
1716219b2ee8SDavid du Colombier /*
17179a747e4fSDavid du Colombier  *  if we want to call 16 bit regs AX,BX,CX,...
17189a747e4fSDavid du Colombier  *  and 32 bit regs EAX,EBX,ECX,... then
17199a747e4fSDavid du Colombier  *  change the defs of ANAME and ONAME to:
17209a747e4fSDavid du Colombier  *  #define	ANAME(ip)	((ip->asize == 'E' ? "E" : "")
17219a747e4fSDavid du Colombier  *  #define	ONAME(ip)	((ip)->osize == 'L' ? "E" : "")
1722219b2ee8SDavid du Colombier  */
17239a747e4fSDavid du Colombier #define	ANAME(ip)	""
17249a747e4fSDavid du Colombier #define	ONAME(ip)	""
1725219b2ee8SDavid du Colombier 
1726219b2ee8SDavid du Colombier static char *reg[] =  {
1727219b2ee8SDavid du Colombier [AX]	"AX",
1728219b2ee8SDavid du Colombier [CX]	"CX",
1729219b2ee8SDavid du Colombier [DX]	"DX",
1730219b2ee8SDavid du Colombier [BX]	"BX",
1731219b2ee8SDavid du Colombier [SP]	"SP",
1732219b2ee8SDavid du Colombier [BP]	"BP",
1733219b2ee8SDavid du Colombier [SI]	"SI",
1734219b2ee8SDavid du Colombier [DI]	"DI",
1735b0dcc5a8SDavid du Colombier 
1736b0dcc5a8SDavid du Colombier 	/* amd64 */
1737b0dcc5a8SDavid du Colombier [R8]	"R8",
1738b0dcc5a8SDavid du Colombier [R9]	"R9",
1739b0dcc5a8SDavid du Colombier [R10]	"R10",
1740b0dcc5a8SDavid du Colombier [R11]	"R11",
1741b0dcc5a8SDavid du Colombier [R12]	"R12",
1742b0dcc5a8SDavid du Colombier [R13]	"R13",
1743b0dcc5a8SDavid du Colombier [R14]	"R14",
1744b0dcc5a8SDavid du Colombier [R15]	"R15",
1745219b2ee8SDavid du Colombier };
1746219b2ee8SDavid du Colombier 
1747219b2ee8SDavid du Colombier static char *breg[] = { "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH" };
1748b0dcc5a8SDavid du Colombier static char *breg64[] = { "AL", "CL", "DL", "BL", "SPB", "BPB", "SIB", "DIB",
1749b0dcc5a8SDavid du Colombier 	"R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B" };
1750219b2ee8SDavid du Colombier static char *sreg[] = { "ES", "CS", "SS", "DS", "FS", "GS" };
1751219b2ee8SDavid du Colombier 
1752219b2ee8SDavid du Colombier static void
plocal(Instr * ip)1753219b2ee8SDavid du Colombier plocal(Instr *ip)
1754219b2ee8SDavid du Colombier {
17551bd28109SDavid du Colombier 	int ret;
17561bd28109SDavid du Colombier 	long offset;
1757219b2ee8SDavid du Colombier 	Symbol s;
1758219b2ee8SDavid du Colombier 	char *reg;
1759219b2ee8SDavid du Colombier 
1760219b2ee8SDavid du Colombier 	offset = ip->disp;
1761219b2ee8SDavid du Colombier 	if (!findsym(ip->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s)) {
1762219b2ee8SDavid du Colombier 		bprint(ip, "%lux(SP)", offset);
1763219b2ee8SDavid du Colombier 		return;
1764219b2ee8SDavid du Colombier 	}
1765219b2ee8SDavid du Colombier 
1766219b2ee8SDavid du Colombier 	if (s.value > ip->disp) {
1767219b2ee8SDavid du Colombier 		ret = getauto(&s, s.value-ip->disp-mach->szaddr, CAUTO, &s);
1768219b2ee8SDavid du Colombier 		reg = "(SP)";
1769219b2ee8SDavid du Colombier 	} else {
1770219b2ee8SDavid du Colombier 		offset -= s.value;
1771219b2ee8SDavid du Colombier 		ret = getauto(&s, offset, CPARAM, &s);
1772219b2ee8SDavid du Colombier 		reg = "(FP)";
1773219b2ee8SDavid du Colombier 	}
1774219b2ee8SDavid du Colombier 	if (ret)
1775219b2ee8SDavid du Colombier 		bprint(ip, "%s+", s.name);
1776219b2ee8SDavid du Colombier 	else
1777219b2ee8SDavid du Colombier 		offset = ip->disp;
1778219b2ee8SDavid du Colombier 	bprint(ip, "%lux%s", offset, reg);
1779219b2ee8SDavid du Colombier }
1780219b2ee8SDavid du Colombier 
1781867bfcc6SDavid du Colombier static int
isjmp(Instr * ip)1782867bfcc6SDavid du Colombier isjmp(Instr *ip)
1783867bfcc6SDavid du Colombier {
1784867bfcc6SDavid du Colombier 	switch(ip->jumptype){
1785867bfcc6SDavid du Colombier 	case Iwds:
1786867bfcc6SDavid du Colombier 	case Jbs:
1787867bfcc6SDavid du Colombier 	case JUMP:
1788867bfcc6SDavid du Colombier 		return 1;
1789867bfcc6SDavid du Colombier 	default:
1790867bfcc6SDavid du Colombier 		return 0;
1791867bfcc6SDavid du Colombier 	}
1792867bfcc6SDavid du Colombier }
1793867bfcc6SDavid du Colombier 
1794867bfcc6SDavid du Colombier /*
1795867bfcc6SDavid du Colombier  * This is too smart for its own good, but it really is nice
1796867bfcc6SDavid du Colombier  * to have accurate translations when debugging, and it
1797867bfcc6SDavid du Colombier  * helps us identify which code is different in binaries that
1798867bfcc6SDavid du Colombier  * are changed on sources.
1799867bfcc6SDavid du Colombier  */
1800867bfcc6SDavid du Colombier static int
issymref(Instr * ip,Symbol * s,long w,long val)1801867bfcc6SDavid du Colombier issymref(Instr *ip, Symbol *s, long w, long val)
1802867bfcc6SDavid du Colombier {
1803867bfcc6SDavid du Colombier 	Symbol next, tmp;
1804867bfcc6SDavid du Colombier 	long isstring, size;
1805867bfcc6SDavid du Colombier 
1806867bfcc6SDavid du Colombier 	if (isjmp(ip))
1807867bfcc6SDavid du Colombier 		return 1;
1808867bfcc6SDavid du Colombier 	if (s->class==CTEXT && w==0)
1809867bfcc6SDavid du Colombier 		return 1;
1810867bfcc6SDavid du Colombier 	if (s->class==CDATA) {
1811867bfcc6SDavid du Colombier 		/* use first bss symbol (or "end") rather than edata */
1812867bfcc6SDavid du Colombier 		if (s->name[0]=='e' && strcmp(s->name, "edata") == 0){
18137f061a25SDavid du Colombier 			if((s ->index >= 0 && globalsym(&tmp, s->index+1) && tmp.value==s->value)
18147f061a25SDavid du Colombier 			|| (s->index > 0 && globalsym(&tmp, s->index-1) && tmp.value==s->value))
1815867bfcc6SDavid du Colombier 				*s = tmp;
1816867bfcc6SDavid du Colombier 		}
1817867bfcc6SDavid du Colombier 		if (w == 0)
1818867bfcc6SDavid du Colombier 			return 1;
1819867bfcc6SDavid du Colombier 		for (next=*s; next.value==s->value; next=tmp)
1820867bfcc6SDavid du Colombier 			if (!globalsym(&tmp, next.index+1))
1821867bfcc6SDavid du Colombier 				break;
1822867bfcc6SDavid du Colombier 		size = next.value - s->value;
1823867bfcc6SDavid du Colombier 		if (w >= size)
1824867bfcc6SDavid du Colombier 			return 0;
1825867bfcc6SDavid du Colombier 		if (w > size-w)
1826867bfcc6SDavid du Colombier 			w = size-w;
1827867bfcc6SDavid du Colombier 		/* huge distances are usually wrong except in .string */
1828867bfcc6SDavid du Colombier 		isstring = (s->name[0]=='.' && strcmp(s->name, ".string") == 0);
1829867bfcc6SDavid du Colombier 		if (w > 8192 && !isstring)
1830867bfcc6SDavid du Colombier 			return 0;
1831867bfcc6SDavid du Colombier 		/* medium distances are tricky - look for constants */
1832867bfcc6SDavid du Colombier 		/* near powers of two */
1833867bfcc6SDavid du Colombier 		if ((val&(val-1)) == 0 || (val&(val+1)) == 0)
1834867bfcc6SDavid du Colombier 			return 0;
1835867bfcc6SDavid du Colombier 		return 1;
1836867bfcc6SDavid du Colombier 	}
1837867bfcc6SDavid du Colombier 	return 0;
1838867bfcc6SDavid du Colombier }
1839867bfcc6SDavid du Colombier 
1840867bfcc6SDavid du Colombier static void
immediate(Instr * ip,vlong val)1841b0dcc5a8SDavid du Colombier immediate(Instr *ip, vlong val)
1842867bfcc6SDavid du Colombier {
1843867bfcc6SDavid du Colombier 	Symbol s;
1844867bfcc6SDavid du Colombier 	long w;
1845867bfcc6SDavid du Colombier 
18464de34a7eSDavid du Colombier 	if (findsym(val, CANY, &s)) {		/* TO DO */
1847867bfcc6SDavid du Colombier 		w = val - s.value;
1848867bfcc6SDavid du Colombier 		if (w < 0)
1849867bfcc6SDavid du Colombier 			w = -w;
1850867bfcc6SDavid du Colombier 		if (issymref(ip, &s, w, val)) {
1851867bfcc6SDavid du Colombier 			if (w)
1852867bfcc6SDavid du Colombier 				bprint(ip, "%s+%lux(SB)", s.name, w);
1853867bfcc6SDavid du Colombier 			else
1854867bfcc6SDavid du Colombier 				bprint(ip, "%s(SB)", s.name);
1855867bfcc6SDavid du Colombier 			return;
1856867bfcc6SDavid du Colombier 		}
1857867bfcc6SDavid du Colombier /*
1858867bfcc6SDavid du Colombier 		if (s.class==CDATA && globalsym(&s, s.index+1)) {
1859867bfcc6SDavid du Colombier 			w = s.value - val;
1860867bfcc6SDavid du Colombier 			if (w < 0)
1861867bfcc6SDavid du Colombier 				w = -w;
1862867bfcc6SDavid du Colombier 			if (w < 4096) {
1863867bfcc6SDavid du Colombier 				bprint(ip, "%s-%lux(SB)", s.name, w);
1864867bfcc6SDavid du Colombier 				return;
1865867bfcc6SDavid du Colombier 			}
1866867bfcc6SDavid du Colombier 		}
1867867bfcc6SDavid du Colombier */
1868867bfcc6SDavid du Colombier 	}
1869b0dcc5a8SDavid du Colombier 	if((ip->rex & REXW) == 0)
1870b0dcc5a8SDavid du Colombier 		bprint(ip, "%lux", (long)val);
1871b0dcc5a8SDavid du Colombier 	else
1872b0dcc5a8SDavid du Colombier 		bprint(ip, "%llux", val);
1873867bfcc6SDavid du Colombier }
1874867bfcc6SDavid du Colombier 
1875219b2ee8SDavid du Colombier static void
pea(Instr * ip)1876219b2ee8SDavid du Colombier pea(Instr *ip)
1877219b2ee8SDavid du Colombier {
1878219b2ee8SDavid du Colombier 	if (ip->mod == 3) {
1879219b2ee8SDavid du Colombier 		if (ip->osize == 'B')
1880b0dcc5a8SDavid du Colombier 			bprint(ip, (ip->rex & REXB? breg64: breg)[ip->base]);
1881b0dcc5a8SDavid du Colombier 		else if(ip->rex & REXB)
1882b0dcc5a8SDavid du Colombier 			bprint(ip, "%s%s", ANAME(ip), reg[ip->base+8]);
1883219b2ee8SDavid du Colombier 		else
18849a747e4fSDavid du Colombier 			bprint(ip, "%s%s", ANAME(ip), reg[ip->base]);
1885219b2ee8SDavid du Colombier 		return;
1886219b2ee8SDavid du Colombier 	}
1887219b2ee8SDavid du Colombier 	if (ip->segment)
1888219b2ee8SDavid du Colombier 		bprint(ip, ip->segment);
1889219b2ee8SDavid du Colombier 	if (ip->asize == 'E' && ip->base == SP)
1890219b2ee8SDavid du Colombier 		plocal(ip);
1891219b2ee8SDavid du Colombier 	else {
1892867bfcc6SDavid du Colombier 		if (ip->base < 0)
1893867bfcc6SDavid du Colombier 			immediate(ip, ip->disp);
1894da51d93aSDavid du Colombier 		else {
1895da51d93aSDavid du Colombier 			bprint(ip, "%lux", ip->disp);
1896373b2ef6SDavid du Colombier 			if(ip->rip)
1897373b2ef6SDavid du Colombier 				bprint(ip, "(RIP)");
1898b0dcc5a8SDavid du Colombier 			bprint(ip,"(%s%s)", ANAME(ip), reg[ip->rex&REXB? ip->base+8: ip->base]);
1899219b2ee8SDavid du Colombier 		}
1900da51d93aSDavid du Colombier 	}
1901219b2ee8SDavid du Colombier 	if (ip->index >= 0)
1902b0dcc5a8SDavid du Colombier 		bprint(ip,"(%s%s*%d)", ANAME(ip), reg[ip->rex&REXX? ip->index+8: ip->index], 1<<ip->ss);
1903219b2ee8SDavid du Colombier }
1904219b2ee8SDavid du Colombier 
1905219b2ee8SDavid du Colombier static void
prinstr(Instr * ip,char * fmt)1906219b2ee8SDavid du Colombier prinstr(Instr *ip, char *fmt)
1907219b2ee8SDavid du Colombier {
1908b0dcc5a8SDavid du Colombier 	vlong v;
1909b0dcc5a8SDavid du Colombier 
1910219b2ee8SDavid du Colombier 	if (ip->prefix)
1911219b2ee8SDavid du Colombier 		bprint(ip, "%s ", ip->prefix);
1912219b2ee8SDavid du Colombier 	for (; *fmt && ip->curr < ip->end; fmt++) {
1913b0dcc5a8SDavid du Colombier 		if (*fmt != '%'){
1914219b2ee8SDavid du Colombier 			*ip->curr++ = *fmt;
1915b0dcc5a8SDavid du Colombier 			continue;
1916b0dcc5a8SDavid du Colombier 		}
1917b0dcc5a8SDavid du Colombier 		switch(*++fmt){
1918219b2ee8SDavid du Colombier 		case '%':
1919219b2ee8SDavid du Colombier 			*ip->curr++ = '%';
1920219b2ee8SDavid du Colombier 			break;
1921219b2ee8SDavid du Colombier 		case 'A':
19229a747e4fSDavid du Colombier 			bprint(ip, "%s", ANAME(ip));
1923219b2ee8SDavid du Colombier 			break;
1924219b2ee8SDavid du Colombier 		case 'C':
1925219b2ee8SDavid du Colombier 			bprint(ip, "CR%d", ip->reg);
1926219b2ee8SDavid du Colombier 			break;
1927219b2ee8SDavid du Colombier 		case 'D':
1928219b2ee8SDavid du Colombier 			if (ip->reg < 4 || ip->reg == 6 || ip->reg == 7)
1929219b2ee8SDavid du Colombier 				bprint(ip, "DR%d",ip->reg);
1930219b2ee8SDavid du Colombier 			else
1931219b2ee8SDavid du Colombier 				bprint(ip, "???");
1932219b2ee8SDavid du Colombier 			break;
1933219b2ee8SDavid du Colombier 		case 'I':
1934219b2ee8SDavid du Colombier 			bprint(ip, "$");
1935219b2ee8SDavid du Colombier 			immediate(ip, ip->imm2);
1936219b2ee8SDavid du Colombier 			break;
1937219b2ee8SDavid du Colombier 		case 'O':
19389a747e4fSDavid du Colombier 			bprint(ip,"%s", ONAME(ip));
1939219b2ee8SDavid du Colombier 			break;
1940219b2ee8SDavid du Colombier 		case 'i':
1941219b2ee8SDavid du Colombier 			bprint(ip, "$");
1942b0dcc5a8SDavid du Colombier 			v = ip->imm;
1943b0dcc5a8SDavid du Colombier 			if(ip->rex & REXW)
1944b0dcc5a8SDavid du Colombier 				v = ip->imm64;
1945b0dcc5a8SDavid du Colombier 			immediate(ip, v);
1946219b2ee8SDavid du Colombier 			break;
1947219b2ee8SDavid du Colombier 		case 'R':
1948b0dcc5a8SDavid du Colombier 			bprint(ip, "%s%s", ONAME(ip), reg[ip->rex&REXR? ip->reg+8: ip->reg]);
1949219b2ee8SDavid du Colombier 			break;
1950219b2ee8SDavid du Colombier 		case 'S':
1951b0dcc5a8SDavid du Colombier 			if(ip->osize == 'Q' || ip->osize == 'L' && ip->rex & REXW)
1952b0dcc5a8SDavid du Colombier 				bprint(ip, "Q");
1953b0dcc5a8SDavid du Colombier 			else
1954219b2ee8SDavid du Colombier 				bprint(ip, "%c", ip->osize);
1955219b2ee8SDavid du Colombier 			break;
1956b0dcc5a8SDavid du Colombier 		case 's':
1957b0dcc5a8SDavid du Colombier 			if(ip->opre == 0 || ip->opre == 0x66)
1958b0dcc5a8SDavid du Colombier 				bprint(ip, "P");
1959b0dcc5a8SDavid du Colombier 			else
1960b0dcc5a8SDavid du Colombier 				bprint(ip, "S");
1961b0dcc5a8SDavid du Colombier 			if(ip->opre == 0xf2 || ip->opre == 0x66)
1962b0dcc5a8SDavid du Colombier 				bprint(ip, "D");
1963b0dcc5a8SDavid du Colombier 			else
1964b0dcc5a8SDavid du Colombier 				bprint(ip, "S");
1965b0dcc5a8SDavid du Colombier 			break;
1966219b2ee8SDavid du Colombier 		case 'T':
1967219b2ee8SDavid du Colombier 			if (ip->reg == 6 || ip->reg == 7)
1968219b2ee8SDavid du Colombier 				bprint(ip, "TR%d",ip->reg);
1969219b2ee8SDavid du Colombier 			else
1970219b2ee8SDavid du Colombier 				bprint(ip, "???");
1971219b2ee8SDavid du Colombier 			break;
1972b0dcc5a8SDavid du Colombier 		case 'W':
1973b0dcc5a8SDavid du Colombier 			if (ip->osize == 'Q' || ip->osize == 'L' && ip->rex & REXW)
1974b0dcc5a8SDavid du Colombier 				bprint(ip, "CDQE");
1975b0dcc5a8SDavid du Colombier 			else if (ip->osize == 'L')
1976219b2ee8SDavid du Colombier 				bprint(ip,"CWDE");
1977219b2ee8SDavid du Colombier 			else
1978219b2ee8SDavid du Colombier 				bprint(ip, "CBW");
1979219b2ee8SDavid du Colombier 			break;
1980219b2ee8SDavid du Colombier 		case 'd':
19811bd28109SDavid du Colombier 			bprint(ip,"%ux:%lux",ip->seg,ip->disp);
1982219b2ee8SDavid du Colombier 			break;
1983b0dcc5a8SDavid du Colombier 		case 'm':
1984b0dcc5a8SDavid du Colombier 			if (ip->mod == 3 && ip->osize != 'B') {
1985b0dcc5a8SDavid du Colombier 				if(fmt[1] != '*'){
1986b0dcc5a8SDavid du Colombier 					if(ip->opre != 0) {
1987b0dcc5a8SDavid du Colombier 						bprint(ip, "X%d", ip->rex&REXB? ip->base+8: ip->base);
1988b0dcc5a8SDavid du Colombier 						break;
1989b0dcc5a8SDavid du Colombier 					}
1990b0dcc5a8SDavid du Colombier 				} else
1991b0dcc5a8SDavid du Colombier 					fmt++;
1992b0dcc5a8SDavid du Colombier 				bprint(ip, "M%d", ip->base);
1993b0dcc5a8SDavid du Colombier 				break;
1994b0dcc5a8SDavid du Colombier 			}
1995b0dcc5a8SDavid du Colombier 			pea(ip);
1996b0dcc5a8SDavid du Colombier 			break;
1997219b2ee8SDavid du Colombier 		case 'e':
1998219b2ee8SDavid du Colombier 			pea(ip);
1999219b2ee8SDavid du Colombier 			break;
2000219b2ee8SDavid du Colombier 		case 'f':
2001219b2ee8SDavid du Colombier 			bprint(ip, "F%d", ip->base);
2002219b2ee8SDavid du Colombier 			break;
2003219b2ee8SDavid du Colombier 		case 'g':
2004219b2ee8SDavid du Colombier 			if (ip->reg < 6)
2005219b2ee8SDavid du Colombier 				bprint(ip,"%s",sreg[ip->reg]);
2006219b2ee8SDavid du Colombier 			else
2007219b2ee8SDavid du Colombier 				bprint(ip,"???");
2008219b2ee8SDavid du Colombier 			break;
2009219b2ee8SDavid du Colombier 		case 'p':
20104de34a7eSDavid du Colombier 			/*
20114de34a7eSDavid du Colombier 			 * signed immediate in the ulong ip->imm.
20124de34a7eSDavid du Colombier 			 */
20134de34a7eSDavid du Colombier 			v = (long)ip->imm;
20144de34a7eSDavid du Colombier 			immediate(ip, v+ip->addr+ip->n);
2015219b2ee8SDavid du Colombier 			break;
2016219b2ee8SDavid du Colombier 		case 'r':
2017219b2ee8SDavid du Colombier 			if (ip->osize == 'B')
2018b0dcc5a8SDavid du Colombier 				bprint(ip,"%s", (ip->rex? breg64: breg)[ip->rex&REXR? ip->reg+8: ip->reg]);
2019219b2ee8SDavid du Colombier 			else
2020b0dcc5a8SDavid du Colombier 				bprint(ip, reg[ip->rex&REXR? ip->reg+8: ip->reg]);
2021219b2ee8SDavid du Colombier 			break;
2022b0dcc5a8SDavid du Colombier 		case 'w':
2023b0dcc5a8SDavid du Colombier 			if (ip->osize == 'Q' || ip->rex & REXW)
2024b0dcc5a8SDavid du Colombier 				bprint(ip, "CQO");
2025b0dcc5a8SDavid du Colombier 			else if (ip->osize == 'L')
2026219b2ee8SDavid du Colombier 				bprint(ip,"CDQ");
2027219b2ee8SDavid du Colombier 			else
2028219b2ee8SDavid du Colombier 				bprint(ip, "CWD");
2029219b2ee8SDavid du Colombier 			break;
2030b0dcc5a8SDavid du Colombier 		case 'M':
2031b0dcc5a8SDavid du Colombier 			if(ip->opre != 0)
2032b0dcc5a8SDavid du Colombier 				bprint(ip, "X%d", ip->rex&REXR? ip->reg+8: ip->reg);
2033b0dcc5a8SDavid du Colombier 			else
2034b0dcc5a8SDavid du Colombier 				bprint(ip, "M%d", ip->reg);
2035b0dcc5a8SDavid du Colombier 			break;
2036b0dcc5a8SDavid du Colombier 		case 'x':
2037b0dcc5a8SDavid du Colombier 			if (ip->mod == 3 && ip->osize != 'B') {
2038b0dcc5a8SDavid du Colombier 				bprint(ip, "X%d", ip->rex&REXB? ip->base+8: ip->base);
2039b0dcc5a8SDavid du Colombier 				break;
2040b0dcc5a8SDavid du Colombier 			}
2041b0dcc5a8SDavid du Colombier 			pea(ip);
2042b0dcc5a8SDavid du Colombier 			break;
2043b0dcc5a8SDavid du Colombier 		case 'X':
2044b0dcc5a8SDavid du Colombier 			bprint(ip, "X%d", ip->rex&REXR? ip->reg+8: ip->reg);
2045b0dcc5a8SDavid du Colombier 			break;
2046219b2ee8SDavid du Colombier 		default:
2047219b2ee8SDavid du Colombier 			bprint(ip, "%%%c", *fmt);
2048219b2ee8SDavid du Colombier 			break;
2049219b2ee8SDavid du Colombier 		}
2050219b2ee8SDavid du Colombier 	}
2051219b2ee8SDavid du Colombier 	*ip->curr = 0;		/* there's always room for 1 byte */
2052219b2ee8SDavid du Colombier }
2053219b2ee8SDavid du Colombier 
2054219b2ee8SDavid du Colombier static int
i386inst(Map * map,uvlong pc,char modifier,char * buf,int n)20554de34a7eSDavid du Colombier i386inst(Map *map, uvlong pc, char modifier, char *buf, int n)
2056219b2ee8SDavid du Colombier {
2057219b2ee8SDavid du Colombier 	Instr instr;
2058219b2ee8SDavid du Colombier 	Optable *op;
2059219b2ee8SDavid du Colombier 
2060219b2ee8SDavid du Colombier 	USED(modifier);
2061219b2ee8SDavid du Colombier 	op = mkinstr(map, &instr, pc);
2062219b2ee8SDavid du Colombier 	if (op == 0) {
20639a747e4fSDavid du Colombier 		errstr(buf, n);
2064219b2ee8SDavid du Colombier 		return -1;
2065219b2ee8SDavid du Colombier 	}
2066219b2ee8SDavid du Colombier 	instr.curr = buf;
2067219b2ee8SDavid du Colombier 	instr.end = buf+n-1;
2068219b2ee8SDavid du Colombier 	prinstr(&instr, op->proto);
2069219b2ee8SDavid du Colombier 	return instr.n;
2070219b2ee8SDavid du Colombier }
2071219b2ee8SDavid du Colombier 
2072219b2ee8SDavid du Colombier static int
i386das(Map * map,uvlong pc,char * buf,int n)20734de34a7eSDavid du Colombier i386das(Map *map, uvlong pc, char *buf, int n)
2074219b2ee8SDavid du Colombier {
2075219b2ee8SDavid du Colombier 	Instr instr;
2076219b2ee8SDavid du Colombier 	int i;
2077219b2ee8SDavid du Colombier 
2078219b2ee8SDavid du Colombier 	if (mkinstr(map, &instr, pc) == 0) {
20799a747e4fSDavid du Colombier 		errstr(buf, n);
2080219b2ee8SDavid du Colombier 		return -1;
2081219b2ee8SDavid du Colombier 	}
2082219b2ee8SDavid du Colombier 	for(i = 0; i < instr.n && n > 2; i++) {
2083219b2ee8SDavid du Colombier 		_hexify(buf, instr.mem[i], 1);
2084219b2ee8SDavid du Colombier 		buf += 2;
2085219b2ee8SDavid du Colombier 		n -= 2;
2086219b2ee8SDavid du Colombier 	}
2087219b2ee8SDavid du Colombier 	*buf = 0;
2088219b2ee8SDavid du Colombier 	return instr.n;
2089219b2ee8SDavid du Colombier }
2090219b2ee8SDavid du Colombier 
2091219b2ee8SDavid du Colombier static int
i386instlen(Map * map,uvlong pc)20924de34a7eSDavid du Colombier i386instlen(Map *map, uvlong pc)
2093219b2ee8SDavid du Colombier {
2094219b2ee8SDavid du Colombier 	Instr i;
2095219b2ee8SDavid du Colombier 
2096219b2ee8SDavid du Colombier 	if (mkinstr(map, &i, pc))
2097219b2ee8SDavid du Colombier 		return i.n;
2098219b2ee8SDavid du Colombier 	return -1;
2099219b2ee8SDavid du Colombier }
2100219b2ee8SDavid du Colombier 
2101219b2ee8SDavid du Colombier static int
i386foll(Map * map,uvlong pc,Rgetter rget,uvlong * foll)21024de34a7eSDavid du Colombier i386foll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
2103219b2ee8SDavid du Colombier {
2104219b2ee8SDavid du Colombier 	Instr i;
2105219b2ee8SDavid du Colombier 	Optable *op;
2106219b2ee8SDavid du Colombier 	ushort s;
21074de34a7eSDavid du Colombier 	uvlong l, addr;
21084de34a7eSDavid du Colombier 	vlong v;
2109219b2ee8SDavid du Colombier 	int n;
2110219b2ee8SDavid du Colombier 
2111219b2ee8SDavid du Colombier 	op = mkinstr(map, &i, pc);
2112219b2ee8SDavid du Colombier 	if (!op)
2113219b2ee8SDavid du Colombier 		return -1;
2114219b2ee8SDavid du Colombier 
2115219b2ee8SDavid du Colombier 	n = 0;
21167dd7cddfSDavid du Colombier 
21177dd7cddfSDavid du Colombier 	switch(i.jumptype) {
2118219b2ee8SDavid du Colombier 	case RET:		/* RETURN or LEAVE */
2119219b2ee8SDavid du Colombier 	case Iw:		/* RETURN */
2120219b2ee8SDavid du Colombier 		if (strcmp(op->proto, "LEAVE") == 0) {
21214de34a7eSDavid du Colombier 			if (geta(map, (*rget)(map, "BP"), &l) < 0)
2122219b2ee8SDavid du Colombier 				return -1;
21234de34a7eSDavid du Colombier 		} else if (geta(map, (*rget)(map, mach->sp), &l) < 0)
2124219b2ee8SDavid du Colombier 			return -1;
2125219b2ee8SDavid du Colombier 		foll[0] = l;
2126219b2ee8SDavid du Colombier 		return 1;
2127219b2ee8SDavid du Colombier 	case Iwds:		/* pc relative JUMP or CALL*/
2128219b2ee8SDavid du Colombier 	case Jbs:		/* pc relative JUMP or CALL */
21294de34a7eSDavid du Colombier 		v = (long)i.imm;
21304de34a7eSDavid du Colombier 		foll[0] = pc+v+i.n;
2131219b2ee8SDavid du Colombier 		n = 1;
2132219b2ee8SDavid du Colombier 		break;
2133219b2ee8SDavid du Colombier 	case PTR:		/* seg:displacement JUMP or CALL */
2134219b2ee8SDavid du Colombier 		foll[0] = (i.seg<<4)+i.disp;
2135219b2ee8SDavid du Colombier 		return 1;
2136219b2ee8SDavid du Colombier 	case JUMP:		/* JUMP or CALL EA */
21377dd7cddfSDavid du Colombier 
21387dd7cddfSDavid du Colombier 		if(i.mod == 3) {
2139b0dcc5a8SDavid du Colombier 			foll[0] = (*rget)(map, reg[i.rex&REXB? i.base+8: i.base]);
21407dd7cddfSDavid du Colombier 			return 1;
21417dd7cddfSDavid du Colombier 		}
2142219b2ee8SDavid du Colombier 			/* calculate the effective address */
2143219b2ee8SDavid du Colombier 		addr = i.disp;
2144219b2ee8SDavid du Colombier 		if (i.base >= 0) {
21454de34a7eSDavid du Colombier 			if (geta(map, (*rget)(map, reg[i.rex&REXB? i.base+8: i.base]), &l) < 0)
2146219b2ee8SDavid du Colombier 				return -1;
2147219b2ee8SDavid du Colombier 			addr += l;
2148219b2ee8SDavid du Colombier 		}
2149219b2ee8SDavid du Colombier 		if (i.index >= 0) {
21504de34a7eSDavid du Colombier 			if (geta(map, (*rget)(map, reg[i.rex&REXX? i.index+8: i.index]), &l) < 0)
2151219b2ee8SDavid du Colombier 				return -1;
2152219b2ee8SDavid du Colombier 			addr += l*(1<<i.ss);
2153219b2ee8SDavid du Colombier 		}
2154219b2ee8SDavid du Colombier 			/* now retrieve a seg:disp value at that address */
2155219b2ee8SDavid du Colombier 		if (get2(map, addr, &s) < 0)			/* seg */
2156219b2ee8SDavid du Colombier 			return -1;
2157219b2ee8SDavid du Colombier 		foll[0] = s<<4;
2158219b2ee8SDavid du Colombier 		addr += 2;
2159219b2ee8SDavid du Colombier 		if (i.asize == 'L') {
21604de34a7eSDavid du Colombier 			if (geta(map, addr, &l) < 0)		/* disp32 */
2161219b2ee8SDavid du Colombier 				return -1;
2162219b2ee8SDavid du Colombier 			foll[0] += l;
2163219b2ee8SDavid du Colombier 		} else {					/* disp16 */
2164219b2ee8SDavid du Colombier 			if (get2(map, addr, &s) < 0)
2165219b2ee8SDavid du Colombier 				return -1;
2166219b2ee8SDavid du Colombier 			foll[0] += s;
2167219b2ee8SDavid du Colombier 		}
2168219b2ee8SDavid du Colombier 		return 1;
2169219b2ee8SDavid du Colombier 	default:
2170219b2ee8SDavid du Colombier 		break;
2171219b2ee8SDavid du Colombier 	}
2172219b2ee8SDavid du Colombier 	if (strncmp(op->proto,"JMP", 3) == 0 || strncmp(op->proto,"CALL", 4) == 0)
2173219b2ee8SDavid du Colombier 		return 1;
2174219b2ee8SDavid du Colombier 	foll[n++] = pc+i.n;
2175219b2ee8SDavid du Colombier 	return n;
2176219b2ee8SDavid du Colombier }
2177