xref: /inferno-os/libinterp/das-386.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth #include <lib9.h>
2*37da2899SCharles.Forsyth #include <kernel.h>
3*37da2899SCharles.Forsyth 
4*37da2899SCharles.Forsyth int	i386inst(ulong, char, char*, int);
5*37da2899SCharles.Forsyth int	i386das(ulong, char*, int);
6*37da2899SCharles.Forsyth int	i386instlen(ulong);
7*37da2899SCharles.Forsyth 
8*37da2899SCharles.Forsyth static uchar *dasdata;
9*37da2899SCharles.Forsyth 
10*37da2899SCharles.Forsyth static char *
_hexify(char * buf,ulong p,int zeros)11*37da2899SCharles.Forsyth _hexify(char *buf, ulong p, int zeros)
12*37da2899SCharles.Forsyth {
13*37da2899SCharles.Forsyth 	ulong d;
14*37da2899SCharles.Forsyth 
15*37da2899SCharles.Forsyth 	d = p/16;
16*37da2899SCharles.Forsyth 	if(d)
17*37da2899SCharles.Forsyth 		buf = _hexify(buf, d, zeros-1);
18*37da2899SCharles.Forsyth 	else
19*37da2899SCharles.Forsyth 		while(zeros--)
20*37da2899SCharles.Forsyth 			*buf++ = '0';
21*37da2899SCharles.Forsyth 	*buf++ = "0123456789abcdef"[p&0x0f];
22*37da2899SCharles.Forsyth 	return buf;
23*37da2899SCharles.Forsyth }
24*37da2899SCharles.Forsyth 
25*37da2899SCharles.Forsyth /*
26*37da2899SCharles.Forsyth  *  an instruction
27*37da2899SCharles.Forsyth  */
28*37da2899SCharles.Forsyth typedef struct Instr Instr;
29*37da2899SCharles.Forsyth struct	Instr
30*37da2899SCharles.Forsyth {
31*37da2899SCharles.Forsyth 	uchar	mem[1+1+1+1+2+1+1+4+4];		/* raw instruction */
32*37da2899SCharles.Forsyth 	ulong	addr;		/* address of start of instruction */
33*37da2899SCharles.Forsyth 	int	n;		/* number of bytes in instruction */
34*37da2899SCharles.Forsyth 	char	*prefix;	/* instr prefix */
35*37da2899SCharles.Forsyth 	char	*segment;	/* segment override */
36*37da2899SCharles.Forsyth 	uchar	jumptype;	/* set to the operand type for jump/ret/call */
37*37da2899SCharles.Forsyth 	char	osize;		/* 'W' or 'L' */
38*37da2899SCharles.Forsyth 	char	asize;		/* address size 'W' or 'L' */
39*37da2899SCharles.Forsyth 	uchar	mod;		/* bits 6-7 of mod r/m field */
40*37da2899SCharles.Forsyth 	uchar	reg;		/* bits 3-5 of mod r/m field */
41*37da2899SCharles.Forsyth 	char	ss;		/* bits 6-7 of SIB */
42*37da2899SCharles.Forsyth 	char	index;		/* bits 3-5 of SIB */
43*37da2899SCharles.Forsyth 	char	base;		/* bits 0-2 of SIB */
44*37da2899SCharles.Forsyth 	short	seg;		/* segment of far address */
45*37da2899SCharles.Forsyth 	ulong	disp;		/* displacement */
46*37da2899SCharles.Forsyth 	ulong 	imm;		/* immediate */
47*37da2899SCharles.Forsyth 	ulong 	imm2;		/* second immediate operand */
48*37da2899SCharles.Forsyth 	char	*curr;		/* fill level in output buffer */
49*37da2899SCharles.Forsyth 	char	*end;		/* end of output buffer */
50*37da2899SCharles.Forsyth 	char	*err;		/* error message */
51*37da2899SCharles.Forsyth };
52*37da2899SCharles.Forsyth 
53*37da2899SCharles.Forsyth 	/* 386 register (ha!) set */
54*37da2899SCharles.Forsyth enum{
55*37da2899SCharles.Forsyth 	AX=0,
56*37da2899SCharles.Forsyth 	CX,
57*37da2899SCharles.Forsyth 	DX,
58*37da2899SCharles.Forsyth 	BX,
59*37da2899SCharles.Forsyth 	SP,
60*37da2899SCharles.Forsyth 	BP,
61*37da2899SCharles.Forsyth 	SI,
62*37da2899SCharles.Forsyth 	DI,
63*37da2899SCharles.Forsyth };
64*37da2899SCharles.Forsyth 	/* Operand Format codes */
65*37da2899SCharles.Forsyth /*
66*37da2899SCharles.Forsyth %A	-	address size register modifier (!asize -> 'E')
67*37da2899SCharles.Forsyth %C	-	Control register CR0/CR1/CR2
68*37da2899SCharles.Forsyth %D	-	Debug register DR0/DR1/DR2/DR3/DR6/DR7
69*37da2899SCharles.Forsyth %I	-	second immediate operand
70*37da2899SCharles.Forsyth %O	-	Operand size register modifier (!osize -> 'E')
71*37da2899SCharles.Forsyth %T	-	Test register TR6/TR7
72*37da2899SCharles.Forsyth %S	-	size code ('W' or 'L')
73*37da2899SCharles.Forsyth %X	-	Weird opcode: OSIZE == 'W' => "CBW"; else => "CWDE"
74*37da2899SCharles.Forsyth %d	-	displacement 16-32 bits
75*37da2899SCharles.Forsyth %e	-	effective address - Mod R/M value
76*37da2899SCharles.Forsyth %f	-	floating point register F0-F7 - from Mod R/M register
77*37da2899SCharles.Forsyth %g	-	segment register
78*37da2899SCharles.Forsyth %i	-	immediate operand 8-32 bits
79*37da2899SCharles.Forsyth %p	-	PC-relative - signed displacement in immediate field
80*37da2899SCharles.Forsyth %r	-	Reg from Mod R/M
81*37da2899SCharles.Forsyth %x	-	Weird opcode: OSIZE == 'W' => "CWD"; else => "CDQ"
82*37da2899SCharles.Forsyth */
83*37da2899SCharles.Forsyth 
84*37da2899SCharles.Forsyth typedef struct Optable Optable;
85*37da2899SCharles.Forsyth struct Optable
86*37da2899SCharles.Forsyth {
87*37da2899SCharles.Forsyth 	char	operand[2];
88*37da2899SCharles.Forsyth 	void	*proto;		/* actually either (char*) or (Optable*) */
89*37da2899SCharles.Forsyth };
90*37da2899SCharles.Forsyth 	/* Operand decoding codes */
91*37da2899SCharles.Forsyth enum {
92*37da2899SCharles.Forsyth 	Ib = 1,			/* 8-bit immediate - (no sign extension)*/
93*37da2899SCharles.Forsyth 	Ibs,			/* 8-bit immediate (sign extended) */
94*37da2899SCharles.Forsyth 	Jbs,			/* 8-bit sign-extended immediate in jump or call */
95*37da2899SCharles.Forsyth 	Iw,			/* 16-bit immediate -> imm */
96*37da2899SCharles.Forsyth 	Iw2,			/* 16-bit immediate -> imm2 */
97*37da2899SCharles.Forsyth 	Iwd,			/* Operand-sized immediate (no sign extension)*/
98*37da2899SCharles.Forsyth 	Awd,			/* Address offset */
99*37da2899SCharles.Forsyth 	Iwds,			/* Operand-sized immediate (sign extended) */
100*37da2899SCharles.Forsyth 	RM,			/* Word or long R/M field with register (/r) */
101*37da2899SCharles.Forsyth 	RMB,			/* Byte R/M field with register (/r) */
102*37da2899SCharles.Forsyth 	RMOP,			/* Word or long R/M field with op code (/digit) */
103*37da2899SCharles.Forsyth 	RMOPB,			/* Byte R/M field with op code (/digit) */
104*37da2899SCharles.Forsyth 	RMR,			/* R/M register only (mod = 11) */
105*37da2899SCharles.Forsyth 	RMM,			/* R/M memory only (mod = 0/1/2) */
106*37da2899SCharles.Forsyth 	R0,			/* Base reg of Mod R/M is literal 0x00 */
107*37da2899SCharles.Forsyth 	R1,			/* Base reg of Mod R/M is literal 0x01 */
108*37da2899SCharles.Forsyth 	FRMOP,			/* Floating point R/M field with opcode */
109*37da2899SCharles.Forsyth 	FRMEX,			/* Extended floating point R/M field with opcode */
110*37da2899SCharles.Forsyth 	JUMP,			/* Jump or Call flag - no operand */
111*37da2899SCharles.Forsyth 	RET,			/* Return flag - no operand */
112*37da2899SCharles.Forsyth 	OA,			/* literal 0x0a byte */
113*37da2899SCharles.Forsyth 	PTR,			/* Seg:Displacement addr (ptr16:16 or ptr16:32) */
114*37da2899SCharles.Forsyth 	AUX,			/* Multi-byte op code - Auxiliary table */
115*37da2899SCharles.Forsyth 	PRE,			/* Instr Prefix */
116*37da2899SCharles.Forsyth 	SEG,			/* Segment Prefix */
117*37da2899SCharles.Forsyth 	OPOVER,			/* Operand size override */
118*37da2899SCharles.Forsyth 	ADDOVER,		/* Address size override */
119*37da2899SCharles.Forsyth };
120*37da2899SCharles.Forsyth 
121*37da2899SCharles.Forsyth static Optable optab0F00[8]=
122*37da2899SCharles.Forsyth {
123*37da2899SCharles.Forsyth 	0,0,		"MOVW	LDT,%e",
124*37da2899SCharles.Forsyth 	0,0,		"MOVW	TR,%e",
125*37da2899SCharles.Forsyth 	0,0,		"MOVW	%e,LDT",
126*37da2899SCharles.Forsyth 	0,0,		"MOVW	%e,TR",
127*37da2899SCharles.Forsyth 	0,0,		"VERR	%e",
128*37da2899SCharles.Forsyth 	0,0,		"VERW	%e",
129*37da2899SCharles.Forsyth };
130*37da2899SCharles.Forsyth 
131*37da2899SCharles.Forsyth static Optable optab0F01[8]=
132*37da2899SCharles.Forsyth {
133*37da2899SCharles.Forsyth 	0,0,		"MOVL	GDTR,%e",
134*37da2899SCharles.Forsyth 	0,0,		"MOVL	IDTR,%e",
135*37da2899SCharles.Forsyth 	0,0,		"MOVL	%e,GDTR",
136*37da2899SCharles.Forsyth 	0,0,		"MOVL	%e,IDTR",
137*37da2899SCharles.Forsyth 	0,0,		"MOVW	MSW,%e",	/* word */
138*37da2899SCharles.Forsyth 	0,0,		nil,
139*37da2899SCharles.Forsyth 	0,0,		"MOVW	%e,MSW",	/* word */
140*37da2899SCharles.Forsyth };
141*37da2899SCharles.Forsyth 
142*37da2899SCharles.Forsyth static Optable optab0FBA[8]=
143*37da2899SCharles.Forsyth {
144*37da2899SCharles.Forsyth 	0,0,		nil,
145*37da2899SCharles.Forsyth 	0,0,		nil,
146*37da2899SCharles.Forsyth 	0,0,		nil,
147*37da2899SCharles.Forsyth 	0,0,		nil,
148*37da2899SCharles.Forsyth 	Ib,0,		"BT%S	%i,%e",
149*37da2899SCharles.Forsyth 	Ib,0,		"BTS%S	%i,%e",
150*37da2899SCharles.Forsyth 	Ib,0,		"BTR%S	%i,%e",
151*37da2899SCharles.Forsyth 	Ib,0,		"BTC%S	%i,%e",
152*37da2899SCharles.Forsyth };
153*37da2899SCharles.Forsyth 
154*37da2899SCharles.Forsyth static Optable optab0F[256]=
155*37da2899SCharles.Forsyth {
156*37da2899SCharles.Forsyth 	RMOP,0,		optab0F00,
157*37da2899SCharles.Forsyth 	RMOP,0,		optab0F01,
158*37da2899SCharles.Forsyth 	RM,0,		"LAR	%e,%r",
159*37da2899SCharles.Forsyth 	RM,0,		"LSL	%e,%r",
160*37da2899SCharles.Forsyth 	0,0,		nil,
161*37da2899SCharles.Forsyth 	0,0,		nil,
162*37da2899SCharles.Forsyth 	0,0,		"CLTS",
163*37da2899SCharles.Forsyth 	0,0,		nil,
164*37da2899SCharles.Forsyth 	0,0,		"INVD",
165*37da2899SCharles.Forsyth 	0,0,		"WBINVD",
166*37da2899SCharles.Forsyth 	0,0,		nil,
167*37da2899SCharles.Forsyth 	0,0,		nil,
168*37da2899SCharles.Forsyth 	0,0,		nil,
169*37da2899SCharles.Forsyth 	0,0,		nil,
170*37da2899SCharles.Forsyth 	0,0,		nil,
171*37da2899SCharles.Forsyth 	0,0,		nil,
172*37da2899SCharles.Forsyth 
173*37da2899SCharles.Forsyth 	0,0,		nil,
174*37da2899SCharles.Forsyth 	0,0,		nil,
175*37da2899SCharles.Forsyth 	0,0,		nil,
176*37da2899SCharles.Forsyth 	0,0,		nil,
177*37da2899SCharles.Forsyth 	0,0,		nil,
178*37da2899SCharles.Forsyth 	0,0,		nil,
179*37da2899SCharles.Forsyth 	0,0,		nil,
180*37da2899SCharles.Forsyth 	0,0,		nil,
181*37da2899SCharles.Forsyth 	0,0,		nil,
182*37da2899SCharles.Forsyth 	0,0,		nil,
183*37da2899SCharles.Forsyth 	0,0,		nil,
184*37da2899SCharles.Forsyth 	0,0,		nil,
185*37da2899SCharles.Forsyth 	0,0,		nil,
186*37da2899SCharles.Forsyth 	0,0,		nil,
187*37da2899SCharles.Forsyth 	0,0,		nil,
188*37da2899SCharles.Forsyth 	0,0,		nil,
189*37da2899SCharles.Forsyth 
190*37da2899SCharles.Forsyth 	RMR,0,		"MOVL	%C,%e",		/* [0x20] */
191*37da2899SCharles.Forsyth 	RMR,0,		"MOVL	%D,%e",
192*37da2899SCharles.Forsyth 	RMR,0,		"MOVL	%e,%C",
193*37da2899SCharles.Forsyth 	RMR,0,		"MOVL	%e,%D",
194*37da2899SCharles.Forsyth 	RMR,0,		"MOVL	%T,%e",
195*37da2899SCharles.Forsyth 	0,0,		nil,
196*37da2899SCharles.Forsyth 	RMR,0,		"MOVL	%e,%T",
197*37da2899SCharles.Forsyth 	0,0,		nil,
198*37da2899SCharles.Forsyth 	0,0,		nil,
199*37da2899SCharles.Forsyth 	0,0,		nil,
200*37da2899SCharles.Forsyth 	0,0,		nil,
201*37da2899SCharles.Forsyth 	0,0,		nil,
202*37da2899SCharles.Forsyth 	0,0,		nil,
203*37da2899SCharles.Forsyth 	0,0,		nil,
204*37da2899SCharles.Forsyth 	0,0,		nil,
205*37da2899SCharles.Forsyth 	0,0,		nil,
206*37da2899SCharles.Forsyth 
207*37da2899SCharles.Forsyth 	0,0,		"WRMSR",		/* [0x30] */
208*37da2899SCharles.Forsyth 	0,0,		"RDTSC",
209*37da2899SCharles.Forsyth 	0,0,		"RDMSR",
210*37da2899SCharles.Forsyth 	0,0,		nil,
211*37da2899SCharles.Forsyth 	0,0,		nil,
212*37da2899SCharles.Forsyth 	0,0,		nil,
213*37da2899SCharles.Forsyth 	0,0,		nil,
214*37da2899SCharles.Forsyth 	0,0,		nil,
215*37da2899SCharles.Forsyth 	0,0,		nil,
216*37da2899SCharles.Forsyth 	0,0,		nil,
217*37da2899SCharles.Forsyth 	0,0,		nil,
218*37da2899SCharles.Forsyth 	0,0,		nil,
219*37da2899SCharles.Forsyth 	0,0,		nil,
220*37da2899SCharles.Forsyth 	0,0,		nil,
221*37da2899SCharles.Forsyth 	0,0,		nil,
222*37da2899SCharles.Forsyth 	0,0,		nil,
223*37da2899SCharles.Forsyth 
224*37da2899SCharles.Forsyth 	0,0,		nil,
225*37da2899SCharles.Forsyth 	0,0,		nil,
226*37da2899SCharles.Forsyth 	0,0,		nil,
227*37da2899SCharles.Forsyth 	0,0,		nil,
228*37da2899SCharles.Forsyth 	0,0,		nil,
229*37da2899SCharles.Forsyth 	0,0,		nil,
230*37da2899SCharles.Forsyth 	0,0,		nil,
231*37da2899SCharles.Forsyth 	0,0,		nil,
232*37da2899SCharles.Forsyth 	0,0,		nil,
233*37da2899SCharles.Forsyth 	0,0,		nil,
234*37da2899SCharles.Forsyth 	0,0,		nil,
235*37da2899SCharles.Forsyth 	0,0,		nil,
236*37da2899SCharles.Forsyth 	0,0,		nil,
237*37da2899SCharles.Forsyth 	0,0,		nil,
238*37da2899SCharles.Forsyth 	0,0,		nil,
239*37da2899SCharles.Forsyth 	0,0,		nil,
240*37da2899SCharles.Forsyth 
241*37da2899SCharles.Forsyth 	0,0,		nil,
242*37da2899SCharles.Forsyth 	0,0,		nil,
243*37da2899SCharles.Forsyth 	0,0,		nil,
244*37da2899SCharles.Forsyth 	0,0,		nil,
245*37da2899SCharles.Forsyth 	0,0,		nil,
246*37da2899SCharles.Forsyth 	0,0,		nil,
247*37da2899SCharles.Forsyth 	0,0,		nil,
248*37da2899SCharles.Forsyth 	0,0,		nil,
249*37da2899SCharles.Forsyth 	0,0,		nil,
250*37da2899SCharles.Forsyth 	0,0,		nil,
251*37da2899SCharles.Forsyth 	0,0,		nil,
252*37da2899SCharles.Forsyth 	0,0,		nil,
253*37da2899SCharles.Forsyth 	0,0,		nil,
254*37da2899SCharles.Forsyth 	0,0,		nil,
255*37da2899SCharles.Forsyth 	0,0,		nil,
256*37da2899SCharles.Forsyth 	0,0,		nil,
257*37da2899SCharles.Forsyth 
258*37da2899SCharles.Forsyth 	0,0,		nil,
259*37da2899SCharles.Forsyth 	0,0,		nil,
260*37da2899SCharles.Forsyth 	0,0,		nil,
261*37da2899SCharles.Forsyth 	0,0,		nil,
262*37da2899SCharles.Forsyth 	0,0,		nil,
263*37da2899SCharles.Forsyth 	0,0,		nil,
264*37da2899SCharles.Forsyth 	0,0,		nil,
265*37da2899SCharles.Forsyth 	0,0,		nil,
266*37da2899SCharles.Forsyth 	0,0,		nil,
267*37da2899SCharles.Forsyth 	0,0,		nil,
268*37da2899SCharles.Forsyth 	0,0,		nil,
269*37da2899SCharles.Forsyth 	0,0,		nil,
270*37da2899SCharles.Forsyth 	0,0,		nil,
271*37da2899SCharles.Forsyth 	0,0,		nil,
272*37da2899SCharles.Forsyth 	0,0,		nil,
273*37da2899SCharles.Forsyth 	0,0,		nil,
274*37da2899SCharles.Forsyth 
275*37da2899SCharles.Forsyth 	0,0,		nil,
276*37da2899SCharles.Forsyth 	0,0,		nil,
277*37da2899SCharles.Forsyth 	0,0,		nil,
278*37da2899SCharles.Forsyth 	0,0,		nil,
279*37da2899SCharles.Forsyth 	0,0,		nil,
280*37da2899SCharles.Forsyth 	0,0,		nil,
281*37da2899SCharles.Forsyth 	0,0,		nil,
282*37da2899SCharles.Forsyth 	0,0,		nil,
283*37da2899SCharles.Forsyth 	0,0,		nil,
284*37da2899SCharles.Forsyth 	0,0,		nil,
285*37da2899SCharles.Forsyth 	0,0,		nil,
286*37da2899SCharles.Forsyth 	0,0,		nil,
287*37da2899SCharles.Forsyth 	0,0,		nil,
288*37da2899SCharles.Forsyth 	0,0,		nil,
289*37da2899SCharles.Forsyth 	0,0,		nil,
290*37da2899SCharles.Forsyth 	0,0,		nil,
291*37da2899SCharles.Forsyth 
292*37da2899SCharles.Forsyth 	Iwds,0,		"JOS	%p",	/* [0x80] */
293*37da2899SCharles.Forsyth 	Iwds,0,		"JOC	%p",
294*37da2899SCharles.Forsyth 	Iwds,0,		"JCS	%p",
295*37da2899SCharles.Forsyth 	Iwds,0,		"JCC	%p",
296*37da2899SCharles.Forsyth 	Iwds,0,		"JEQ	%p",
297*37da2899SCharles.Forsyth 	Iwds,0,		"JNE	%p",
298*37da2899SCharles.Forsyth 	Iwds,0,		"JLS	%p",
299*37da2899SCharles.Forsyth 	Iwds,0,		"JHI	%p",
300*37da2899SCharles.Forsyth 	Iwds,0,		"JMI	%p",
301*37da2899SCharles.Forsyth 	Iwds,0,		"JPL	%p",
302*37da2899SCharles.Forsyth 	Iwds,0,		"JPS	%p",
303*37da2899SCharles.Forsyth 	Iwds,0,		"JPC	%p",
304*37da2899SCharles.Forsyth 	Iwds,0,		"JLT	%p",
305*37da2899SCharles.Forsyth 	Iwds,0,		"JGE	%p",
306*37da2899SCharles.Forsyth 	Iwds,0,		"JLE	%p",
307*37da2899SCharles.Forsyth 	Iwds,0,		"JGT	%p",
308*37da2899SCharles.Forsyth 
309*37da2899SCharles.Forsyth 	RMB,0,		"SETOS	%e",	/* [0x90] */
310*37da2899SCharles.Forsyth 	RMB,0,		"SETOC	%e",
311*37da2899SCharles.Forsyth 	RMB,0,		"SETCS	%e",
312*37da2899SCharles.Forsyth 	RMB,0,		"SETCC	%e",
313*37da2899SCharles.Forsyth 	RMB,0,		"SETEQ	%e",
314*37da2899SCharles.Forsyth 	RMB,0,		"SETNE	%e",
315*37da2899SCharles.Forsyth 	RMB,0,		"SETLS	%e",
316*37da2899SCharles.Forsyth 	RMB,0,		"SETHI	%e",
317*37da2899SCharles.Forsyth 	RMB,0,		"SETMI	%e",
318*37da2899SCharles.Forsyth 	RMB,0,		"SETPL	%e",
319*37da2899SCharles.Forsyth 	RMB,0,		"SETPS	%e",
320*37da2899SCharles.Forsyth 	RMB,0,		"SETPC	%e",
321*37da2899SCharles.Forsyth 	RMB,0,		"SETLT	%e",
322*37da2899SCharles.Forsyth 	RMB,0,		"SETGE	%e",
323*37da2899SCharles.Forsyth 	RMB,0,		"SETLE	%e",
324*37da2899SCharles.Forsyth 	RMB,0,		"SETGT	%e",
325*37da2899SCharles.Forsyth 
326*37da2899SCharles.Forsyth 	0,0,		"PUSHL	FS",	/* [0xa0] */
327*37da2899SCharles.Forsyth 	0,0,		"POPL	FS",
328*37da2899SCharles.Forsyth 	0,0,		"CPUID",
329*37da2899SCharles.Forsyth 	RM,0,		"BT%S	%r,%e",
330*37da2899SCharles.Forsyth 	RM,Ib,		"SHLD%S	%r,%i,%e",
331*37da2899SCharles.Forsyth 	RM,0,		"SHLD%S	%r,CL,%e",
332*37da2899SCharles.Forsyth 	0,0,		nil,
333*37da2899SCharles.Forsyth 	0,0,		nil,
334*37da2899SCharles.Forsyth 	0,0,		"PUSHL	GS",
335*37da2899SCharles.Forsyth 	0,0,		"POPL	GS",
336*37da2899SCharles.Forsyth 	0,0,		nil,
337*37da2899SCharles.Forsyth 	RM,0,		"BTS%S	%r,%e",
338*37da2899SCharles.Forsyth 	RM,Ib,		"SHRD%S	%r,%i,%e",
339*37da2899SCharles.Forsyth 	RM,0,		"SHRD%S	%r,CL,%e",
340*37da2899SCharles.Forsyth 	0,0,		nil,
341*37da2899SCharles.Forsyth 	RM,0,		"IMUL%S	%e,%r",
342*37da2899SCharles.Forsyth 
343*37da2899SCharles.Forsyth 	0,0,		nil,
344*37da2899SCharles.Forsyth 	0,0,		nil,
345*37da2899SCharles.Forsyth 	RMM,0,		"LSS	%e,%r",	/* [0xb2] */
346*37da2899SCharles.Forsyth 	RM,0,		"BTR%S	%r,%e",
347*37da2899SCharles.Forsyth 	RMM,0,		"LFS	%e,%r",
348*37da2899SCharles.Forsyth 	RMM,0,		"LGS	%e,%r",
349*37da2899SCharles.Forsyth 	RMB,0,		"MOVBZX	%e,%R",
350*37da2899SCharles.Forsyth 	RM,0,		"MOVWZX	%e,%R",
351*37da2899SCharles.Forsyth 	0,0,		nil,
352*37da2899SCharles.Forsyth 	0,0,		nil,
353*37da2899SCharles.Forsyth 	RMOP,0,		optab0FBA,
354*37da2899SCharles.Forsyth 	RM,0,		"BTC%S	%e,%r",
355*37da2899SCharles.Forsyth 	RM,0,		"BSF%S	%e,%r",
356*37da2899SCharles.Forsyth 	RM,0,		"BSR%S	%e,%r",
357*37da2899SCharles.Forsyth 	RMB,0,		"MOVBSX	%e,%R",
358*37da2899SCharles.Forsyth 	RM,0,		"MOVWSX	%e,%R",
359*37da2899SCharles.Forsyth };
360*37da2899SCharles.Forsyth 
361*37da2899SCharles.Forsyth static Optable optab80[8]=
362*37da2899SCharles.Forsyth {
363*37da2899SCharles.Forsyth 	Ib,0,		"ADDB	%i,%e",
364*37da2899SCharles.Forsyth 	Ib,0,		"ORB	%i,%e",
365*37da2899SCharles.Forsyth 	Ib,0,		"ADCB	%i,%e",
366*37da2899SCharles.Forsyth 	Ib,0,		"SBBB	%i,%e",
367*37da2899SCharles.Forsyth 	Ib,0,		"ANDB	%i,%e",
368*37da2899SCharles.Forsyth 	Ib,0,		"SUBB	%i,%e",
369*37da2899SCharles.Forsyth 	Ib,0,		"XORB	%i,%e",
370*37da2899SCharles.Forsyth 	Ib,0,		"CMPB	%e,%i",
371*37da2899SCharles.Forsyth };
372*37da2899SCharles.Forsyth 
373*37da2899SCharles.Forsyth static Optable optab81[8]=
374*37da2899SCharles.Forsyth {
375*37da2899SCharles.Forsyth 	Iwd,0,		"ADD%S	%i,%e",
376*37da2899SCharles.Forsyth 	Iwd,0,		"OR%S	%i,%e",
377*37da2899SCharles.Forsyth 	Iwd,0,		"ADC%S	%i,%e",
378*37da2899SCharles.Forsyth 	Iwd,0,		"SBB%S	%i,%e",
379*37da2899SCharles.Forsyth 	Iwd,0,		"AND%S	%i,%e",
380*37da2899SCharles.Forsyth 	Iwd,0,		"SUB%S	%i,%e",
381*37da2899SCharles.Forsyth 	Iwd,0,		"XOR%S	%i,%e",
382*37da2899SCharles.Forsyth 	Iwd,0,		"CMP%S	%e,%i",
383*37da2899SCharles.Forsyth };
384*37da2899SCharles.Forsyth 
385*37da2899SCharles.Forsyth static Optable optab83[8]=
386*37da2899SCharles.Forsyth {
387*37da2899SCharles.Forsyth 	Ibs,0,		"ADD%S	%i,%e",
388*37da2899SCharles.Forsyth 	Ibs,0,		"OR%S	%i,%e",
389*37da2899SCharles.Forsyth 	Ibs,0,		"ADC%S	%i,%e",
390*37da2899SCharles.Forsyth 	Ibs,0,		"SBB%S	%i,%e",
391*37da2899SCharles.Forsyth 	Ibs,0,		"AND%S	%i,%e",
392*37da2899SCharles.Forsyth 	Ibs,0,		"SUB%S	%i,%e",
393*37da2899SCharles.Forsyth 	Ibs,0,		"XOR%S	%i,%e",
394*37da2899SCharles.Forsyth 	Ibs,0,		"CMP%S	%e,%i",
395*37da2899SCharles.Forsyth };
396*37da2899SCharles.Forsyth 
397*37da2899SCharles.Forsyth static Optable optabC0[8] =
398*37da2899SCharles.Forsyth {
399*37da2899SCharles.Forsyth 	Ib,0,		"ROLB	%i,%e",
400*37da2899SCharles.Forsyth 	Ib,0,		"RORB	%i,%e",
401*37da2899SCharles.Forsyth 	Ib,0,		"RCLB	%i,%e",
402*37da2899SCharles.Forsyth 	Ib,0,		"RCRB	%i,%e",
403*37da2899SCharles.Forsyth 	Ib,0,		"SHLB	%i,%e",
404*37da2899SCharles.Forsyth 	Ib,0,		"SHRB	%i,%e",
405*37da2899SCharles.Forsyth 	0,0,		nil,
406*37da2899SCharles.Forsyth 	Ib,0,		"SARB	%i,%e",
407*37da2899SCharles.Forsyth };
408*37da2899SCharles.Forsyth 
409*37da2899SCharles.Forsyth static Optable optabC1[8] =
410*37da2899SCharles.Forsyth {
411*37da2899SCharles.Forsyth 	Ib,0,		"ROL%S	%i,%e",
412*37da2899SCharles.Forsyth 	Ib,0,		"ROR%S	%i,%e",
413*37da2899SCharles.Forsyth 	Ib,0,		"RCL%S	%i,%e",
414*37da2899SCharles.Forsyth 	Ib,0,		"RCR%S	%i,%e",
415*37da2899SCharles.Forsyth 	Ib,0,		"SHL%S	%i,%e",
416*37da2899SCharles.Forsyth 	Ib,0,		"SHR%S	%i,%e",
417*37da2899SCharles.Forsyth 	0,0,		nil,
418*37da2899SCharles.Forsyth 	Ib,0,		"SAR%S	%i,%e",
419*37da2899SCharles.Forsyth };
420*37da2899SCharles.Forsyth 
421*37da2899SCharles.Forsyth static Optable optabD0[8] =
422*37da2899SCharles.Forsyth {
423*37da2899SCharles.Forsyth 	0,0,		"ROLB	%e",
424*37da2899SCharles.Forsyth 	0,0,		"RORB	%e",
425*37da2899SCharles.Forsyth 	0,0,		"RCLB	%e",
426*37da2899SCharles.Forsyth 	0,0,		"RCRB	%e",
427*37da2899SCharles.Forsyth 	0,0,		"SHLB	%e",
428*37da2899SCharles.Forsyth 	0,0,		"SHRB	%e",
429*37da2899SCharles.Forsyth 	0,0,		nil,
430*37da2899SCharles.Forsyth 	0,0,		"SARB	%e",
431*37da2899SCharles.Forsyth };
432*37da2899SCharles.Forsyth 
433*37da2899SCharles.Forsyth static Optable optabD1[8] =
434*37da2899SCharles.Forsyth {
435*37da2899SCharles.Forsyth 	0,0,		"ROL%S	%e",
436*37da2899SCharles.Forsyth 	0,0,		"ROR%S	%e",
437*37da2899SCharles.Forsyth 	0,0,		"RCL%S	%e",
438*37da2899SCharles.Forsyth 	0,0,		"RCR%S	%e",
439*37da2899SCharles.Forsyth 	0,0,		"SHL%S	%e",
440*37da2899SCharles.Forsyth 	0,0,		"SHR%S	%e",
441*37da2899SCharles.Forsyth 	0,0,		nil,
442*37da2899SCharles.Forsyth 	0,0,		"SAR%S	%e",
443*37da2899SCharles.Forsyth };
444*37da2899SCharles.Forsyth 
445*37da2899SCharles.Forsyth static Optable optabD2[8] =
446*37da2899SCharles.Forsyth {
447*37da2899SCharles.Forsyth 	0,0,		"ROLB	CL,%e",
448*37da2899SCharles.Forsyth 	0,0,		"RORB	CL,%e",
449*37da2899SCharles.Forsyth 	0,0,		"RCLB	CL,%e",
450*37da2899SCharles.Forsyth 	0,0,		"RCRB	CL,%e",
451*37da2899SCharles.Forsyth 	0,0,		"SHLB	CL,%e",
452*37da2899SCharles.Forsyth 	0,0,		"SHRB	CL,%e",
453*37da2899SCharles.Forsyth 	0,0,		nil,
454*37da2899SCharles.Forsyth 	0,0,		"SARB	CL,%e",
455*37da2899SCharles.Forsyth };
456*37da2899SCharles.Forsyth 
457*37da2899SCharles.Forsyth static Optable optabD3[8] =
458*37da2899SCharles.Forsyth {
459*37da2899SCharles.Forsyth 	0,0,		"ROL%S	CL,%e",
460*37da2899SCharles.Forsyth 	0,0,		"ROR%S	CL,%e",
461*37da2899SCharles.Forsyth 	0,0,		"RCL%S	CL,%e",
462*37da2899SCharles.Forsyth 	0,0,		"RCR%S	CL,%e",
463*37da2899SCharles.Forsyth 	0,0,		"SHL%S	CL,%e",
464*37da2899SCharles.Forsyth 	0,0,		"SHR%S	CL,%e",
465*37da2899SCharles.Forsyth 	0,0,		nil,
466*37da2899SCharles.Forsyth 	0,0,		"SAR%S	CL,%e",
467*37da2899SCharles.Forsyth };
468*37da2899SCharles.Forsyth 
469*37da2899SCharles.Forsyth static Optable optabD8[8+8] =
470*37da2899SCharles.Forsyth {
471*37da2899SCharles.Forsyth 	0,0,		"FADDF	%e,F0",
472*37da2899SCharles.Forsyth 	0,0,		"FMULF	%e,F0",
473*37da2899SCharles.Forsyth 	0,0,		"FCOMF	%e,F0",
474*37da2899SCharles.Forsyth 	0,0,		"FCOMFP	%e,F0",
475*37da2899SCharles.Forsyth 	0,0,		"FSUBF	%e,F0",
476*37da2899SCharles.Forsyth 	0,0,		"FSUBRF	%e,F0",
477*37da2899SCharles.Forsyth 	0,0,		"FDIVF	%e,F0",
478*37da2899SCharles.Forsyth 	0,0,		"FDIVRF	%e,F0",
479*37da2899SCharles.Forsyth 	0,0,		"FADDD	%f,F0",
480*37da2899SCharles.Forsyth 	0,0,		"FMULD	%f,F0",
481*37da2899SCharles.Forsyth 	0,0,		"FCOMD	%f,F0",
482*37da2899SCharles.Forsyth 	0,0,		"FCOMPD	%f,F0",
483*37da2899SCharles.Forsyth 	0,0,		"FSUBD	%f,F0",
484*37da2899SCharles.Forsyth 	0,0,		"FSUBRD	%f,F0",
485*37da2899SCharles.Forsyth 	0,0,		"FDIVD	%f,F0",
486*37da2899SCharles.Forsyth 	0,0,		"FDIVRD	%f,F0",
487*37da2899SCharles.Forsyth };
488*37da2899SCharles.Forsyth /*
489*37da2899SCharles.Forsyth  *	optabD9 and optabDB use the following encoding:
490*37da2899SCharles.Forsyth  *	if (0 <= modrm <= 2) instruction = optabDx[modrm&0x07];
491*37da2899SCharles.Forsyth  *	else instruction = optabDx[(modrm&0x3f)+8];
492*37da2899SCharles.Forsyth  *
493*37da2899SCharles.Forsyth  *	the instructions for MOD == 3, follow the 8 instructions
494*37da2899SCharles.Forsyth  *	for the other MOD values stored at the front of the table.
495*37da2899SCharles.Forsyth  */
496*37da2899SCharles.Forsyth static Optable optabD9[64+8] =
497*37da2899SCharles.Forsyth {
498*37da2899SCharles.Forsyth 	0,0,		"FMOVF	%e,F0",
499*37da2899SCharles.Forsyth 	0,0,		nil,
500*37da2899SCharles.Forsyth 	0,0,		"FMOVF	F0,%e",
501*37da2899SCharles.Forsyth 	0,0,		"FMOVFP	F0,%e",
502*37da2899SCharles.Forsyth 	0,0,		"FLDENV%S %e",
503*37da2899SCharles.Forsyth 	0,0,		"FLDCW	%e",
504*37da2899SCharles.Forsyth 	0,0,		"FSTENV%S %e",
505*37da2899SCharles.Forsyth 	0,0,		"FSTCW	%e",
506*37da2899SCharles.Forsyth 	0,0,		"FMOVD	F0,F0",		/* Mod R/M = 11xx xxxx*/
507*37da2899SCharles.Forsyth 	0,0,		"FMOVD	F1,F0",
508*37da2899SCharles.Forsyth 	0,0,		"FMOVD	F2,F0",
509*37da2899SCharles.Forsyth 	0,0,		"FMOVD	F3,F0",
510*37da2899SCharles.Forsyth 	0,0,		"FMOVD	F4,F0",
511*37da2899SCharles.Forsyth 	0,0,		"FMOVD	F5,F0",
512*37da2899SCharles.Forsyth 	0,0,		"FMOVD	F6,F0",
513*37da2899SCharles.Forsyth 	0,0,		"FMOVD	F7,F0",
514*37da2899SCharles.Forsyth 	0,0,		"FXCHD	F0,F0",
515*37da2899SCharles.Forsyth 	0,0,		"FXCHD	F1,F0",
516*37da2899SCharles.Forsyth 	0,0,		"FXCHD	F2,F0",
517*37da2899SCharles.Forsyth 	0,0,		"FXCHD	F3,F0",
518*37da2899SCharles.Forsyth 	0,0,		"FXCHD	F4,F0",
519*37da2899SCharles.Forsyth 	0,0,		"FXCHD	F5,F0",
520*37da2899SCharles.Forsyth 	0,0,		"FXCHD	F6,F0",
521*37da2899SCharles.Forsyth 	0,0,		"FXCHD	F7,F0",
522*37da2899SCharles.Forsyth 	0,0,		"FNOP",
523*37da2899SCharles.Forsyth 	0,0,		nil,
524*37da2899SCharles.Forsyth 	0,0,		nil,
525*37da2899SCharles.Forsyth 	0,0,		nil,
526*37da2899SCharles.Forsyth 	0,0,		nil,
527*37da2899SCharles.Forsyth 	0,0,		nil,
528*37da2899SCharles.Forsyth 	0,0,		nil,
529*37da2899SCharles.Forsyth 	0,0,		nil,
530*37da2899SCharles.Forsyth 	0,0,		nil,
531*37da2899SCharles.Forsyth 	0,0,		nil,
532*37da2899SCharles.Forsyth 	0,0,		nil,
533*37da2899SCharles.Forsyth 	0,0,		nil,
534*37da2899SCharles.Forsyth 	0,0,		nil,
535*37da2899SCharles.Forsyth 	0,0,		nil,
536*37da2899SCharles.Forsyth 	0,0,		nil,
537*37da2899SCharles.Forsyth 	0,0,		nil,
538*37da2899SCharles.Forsyth 	0,0,		"FCHS",		/* [0x28] */
539*37da2899SCharles.Forsyth 	0,0,		"FABS",
540*37da2899SCharles.Forsyth 	0,0,		nil,
541*37da2899SCharles.Forsyth 	0,0,		nil,
542*37da2899SCharles.Forsyth 	0,0,		"FTST",
543*37da2899SCharles.Forsyth 	0,0,		"FXAM",
544*37da2899SCharles.Forsyth 	0,0,		nil,
545*37da2899SCharles.Forsyth 	0,0,		nil,
546*37da2899SCharles.Forsyth 	0,0,		"FLD1",
547*37da2899SCharles.Forsyth 	0,0,		"FLDL2T",
548*37da2899SCharles.Forsyth 	0,0,		"FLDL2E",
549*37da2899SCharles.Forsyth 	0,0,		"FLDPI",
550*37da2899SCharles.Forsyth 	0,0,		"FLDLG2",
551*37da2899SCharles.Forsyth 	0,0,		"FLDLN2",
552*37da2899SCharles.Forsyth 	0,0,		"FLDZ",
553*37da2899SCharles.Forsyth 	0,0,		nil,
554*37da2899SCharles.Forsyth 	0,0,		"F2XM1",
555*37da2899SCharles.Forsyth 	0,0,		"FYL2X",
556*37da2899SCharles.Forsyth 	0,0,		"FPTAN",
557*37da2899SCharles.Forsyth 	0,0,		"FPATAN",
558*37da2899SCharles.Forsyth 	0,0,		"FXTRACT",
559*37da2899SCharles.Forsyth 	0,0,		"FPREM1",
560*37da2899SCharles.Forsyth 	0,0,		"FDECSTP",
561*37da2899SCharles.Forsyth 	0,0,		"FNCSTP",
562*37da2899SCharles.Forsyth 	0,0,		"FPREM",
563*37da2899SCharles.Forsyth 	0,0,		"FYL2XP1",
564*37da2899SCharles.Forsyth 	0,0,		"FSQRT",
565*37da2899SCharles.Forsyth 	0,0,		"FSINCOS",
566*37da2899SCharles.Forsyth 	0,0,		"FRNDINT",
567*37da2899SCharles.Forsyth 	0,0,		"FSCALE",
568*37da2899SCharles.Forsyth 	0,0,		"FSIN",
569*37da2899SCharles.Forsyth 	0,0,		"FCOS",
570*37da2899SCharles.Forsyth };
571*37da2899SCharles.Forsyth 
572*37da2899SCharles.Forsyth static Optable optabDA[8+8] =
573*37da2899SCharles.Forsyth {
574*37da2899SCharles.Forsyth 	0,0,		"FADDL	%e,F0",
575*37da2899SCharles.Forsyth 	0,0,		"FMULL	%e,F0",
576*37da2899SCharles.Forsyth 	0,0,		"FCOML	%e,F0",
577*37da2899SCharles.Forsyth 	0,0,		"FCOMLP	%e,F0",
578*37da2899SCharles.Forsyth 	0,0,		"FSUBL	%e,F0",
579*37da2899SCharles.Forsyth 	0,0,		"FSUBRL	%e,F0",
580*37da2899SCharles.Forsyth 	0,0,		"FDIVL	%e,F0",
581*37da2899SCharles.Forsyth 	0,0,		"FDIVRL	%e,F0",
582*37da2899SCharles.Forsyth 	0,0,		nil,
583*37da2899SCharles.Forsyth 	0,0,		nil,
584*37da2899SCharles.Forsyth 	0,0,		nil,
585*37da2899SCharles.Forsyth 	0,0,		nil,
586*37da2899SCharles.Forsyth 	0,0,		nil,
587*37da2899SCharles.Forsyth 	R1,0,		"FUCOMPP",	/* [0x0d] */
588*37da2899SCharles.Forsyth };
589*37da2899SCharles.Forsyth 
590*37da2899SCharles.Forsyth static Optable optabDB[8+64] =
591*37da2899SCharles.Forsyth {
592*37da2899SCharles.Forsyth 	0,0,		"FMOVL	%e,F0",
593*37da2899SCharles.Forsyth 	0,0,		nil,
594*37da2899SCharles.Forsyth 	0,0,		"FMOVL	F0,%e",
595*37da2899SCharles.Forsyth 	0,0,		"FMOVLP	F0,%e",
596*37da2899SCharles.Forsyth 	0,0,		nil,
597*37da2899SCharles.Forsyth 	0,0,		"FMOVX	%e,F0",
598*37da2899SCharles.Forsyth 	0,0,		nil,
599*37da2899SCharles.Forsyth 	0,0,		"FMOVXP	F0,%e",
600*37da2899SCharles.Forsyth 	0,0,		nil,
601*37da2899SCharles.Forsyth 	0,0,		nil,
602*37da2899SCharles.Forsyth 	0,0,		nil,
603*37da2899SCharles.Forsyth 	0,0,		nil,
604*37da2899SCharles.Forsyth 	0,0,		nil,
605*37da2899SCharles.Forsyth 	0,0,		nil,
606*37da2899SCharles.Forsyth 	0,0,		nil,
607*37da2899SCharles.Forsyth 	0,0,		nil,
608*37da2899SCharles.Forsyth 	0,0,		nil,
609*37da2899SCharles.Forsyth 	0,0,		nil,
610*37da2899SCharles.Forsyth 	0,0,		nil,
611*37da2899SCharles.Forsyth 	0,0,		nil,
612*37da2899SCharles.Forsyth 	0,0,		nil,
613*37da2899SCharles.Forsyth 	0,0,		nil,
614*37da2899SCharles.Forsyth 	0,0,		nil,
615*37da2899SCharles.Forsyth 	0,0,		nil,
616*37da2899SCharles.Forsyth 	0,0,		nil,
617*37da2899SCharles.Forsyth 	0,0,		nil,
618*37da2899SCharles.Forsyth 	0,0,		nil,
619*37da2899SCharles.Forsyth 	0,0,		nil,
620*37da2899SCharles.Forsyth 	0,0,		nil,
621*37da2899SCharles.Forsyth 	0,0,		nil,
622*37da2899SCharles.Forsyth 	0,0,		nil,
623*37da2899SCharles.Forsyth 	0,0,		nil,
624*37da2899SCharles.Forsyth 	0,0,		nil,
625*37da2899SCharles.Forsyth 	0,0,		nil,
626*37da2899SCharles.Forsyth 	0,0,		nil,
627*37da2899SCharles.Forsyth 	0,0,		nil,
628*37da2899SCharles.Forsyth 	0,0,		nil,
629*37da2899SCharles.Forsyth 	0,0,		nil,
630*37da2899SCharles.Forsyth 	0,0,		nil,
631*37da2899SCharles.Forsyth 	0,0,		nil,
632*37da2899SCharles.Forsyth 	0,0,		nil,
633*37da2899SCharles.Forsyth 	0,0,		nil,
634*37da2899SCharles.Forsyth 	0,0,		"FCLEX",	/* [0x2a] */
635*37da2899SCharles.Forsyth 	0,0,		"FINIT",
636*37da2899SCharles.Forsyth };
637*37da2899SCharles.Forsyth 
638*37da2899SCharles.Forsyth static Optable optabDC[8+8] =
639*37da2899SCharles.Forsyth {
640*37da2899SCharles.Forsyth 	0,0,		"FADDD	%e,F0",
641*37da2899SCharles.Forsyth 	0,0,		"FMULD	%e,F0",
642*37da2899SCharles.Forsyth 	0,0,		"FCOMD	%e,F0",
643*37da2899SCharles.Forsyth 	0,0,		"FCOMDP	%e,F0",
644*37da2899SCharles.Forsyth 	0,0,		"FSUBD	%e,F0",
645*37da2899SCharles.Forsyth 	0,0,		"FSUBRD	%e,F0",
646*37da2899SCharles.Forsyth 	0,0,		"FDIVD	%e,F0",
647*37da2899SCharles.Forsyth 	0,0,		"FDIVRD	%e,F0",
648*37da2899SCharles.Forsyth 	0,0,		"FADDD	F0,%f",
649*37da2899SCharles.Forsyth 	0,0,		"FMULD	F0,%f",
650*37da2899SCharles.Forsyth 	0,0,		nil,
651*37da2899SCharles.Forsyth 	0,0,		nil,
652*37da2899SCharles.Forsyth 	0,0,		"FSUBRD	F0,%f",
653*37da2899SCharles.Forsyth 	0,0,		"FSUBD	F0,%f",
654*37da2899SCharles.Forsyth 	0,0,		"FDIVRD	F0,%f",
655*37da2899SCharles.Forsyth 	0,0,		"FDIVD	F0,%f",
656*37da2899SCharles.Forsyth };
657*37da2899SCharles.Forsyth 
658*37da2899SCharles.Forsyth static Optable optabDD[8+8] =
659*37da2899SCharles.Forsyth {
660*37da2899SCharles.Forsyth 	0,0,		"FMOVD	%e,F0",
661*37da2899SCharles.Forsyth 	0,0,		nil,
662*37da2899SCharles.Forsyth 	0,0,		"FMOVD	F0,%e",
663*37da2899SCharles.Forsyth 	0,0,		"FMOVDP	F0,%e",
664*37da2899SCharles.Forsyth 	0,0,		"FRSTOR%S %e",
665*37da2899SCharles.Forsyth 	0,0,		nil,
666*37da2899SCharles.Forsyth 	0,0,		"FSAVE%S %e",
667*37da2899SCharles.Forsyth 	0,0,		"FSTSW	%e",
668*37da2899SCharles.Forsyth 	0,0,		"FFREED	%f",
669*37da2899SCharles.Forsyth 	0,0,		nil,
670*37da2899SCharles.Forsyth 	0,0,		"FMOVD	%f,F0",
671*37da2899SCharles.Forsyth 	0,0,		"FMOVDP	%f,F0",
672*37da2899SCharles.Forsyth 	0,0,		"FUCOMD	%f,F0",
673*37da2899SCharles.Forsyth 	0,0,		"FUCOMDP %f,F0",
674*37da2899SCharles.Forsyth };
675*37da2899SCharles.Forsyth 
676*37da2899SCharles.Forsyth static Optable optabDE[8+8] =
677*37da2899SCharles.Forsyth {
678*37da2899SCharles.Forsyth 	0,0,		"FADDW	%e,F0",
679*37da2899SCharles.Forsyth 	0,0,		"FMULW	%e,F0",
680*37da2899SCharles.Forsyth 	0,0,		"FCOMW	%e,F0",
681*37da2899SCharles.Forsyth 	0,0,		"FCOMWP	%e,F0",
682*37da2899SCharles.Forsyth 	0,0,		"FSUBW	%e,F0",
683*37da2899SCharles.Forsyth 	0,0,		"FSUBRW	%e,F0",
684*37da2899SCharles.Forsyth 	0,0,		"FDIVW	%e,F0",
685*37da2899SCharles.Forsyth 	0,0,		"FDIVRW	%e,F0",
686*37da2899SCharles.Forsyth 	0,0,		"FADDDP	F0,%f",
687*37da2899SCharles.Forsyth 	0,0,		"FMULDP	F0,%f",
688*37da2899SCharles.Forsyth 	0,0,		nil,
689*37da2899SCharles.Forsyth 	R1,0,		"FCOMPDP",
690*37da2899SCharles.Forsyth 	0,0,		"FSUBRDP F0,%f",
691*37da2899SCharles.Forsyth 	0,0,		"FSUBDP	F0,%f",
692*37da2899SCharles.Forsyth 	0,0,		"FDIVRDP F0,%f",
693*37da2899SCharles.Forsyth 	0,0,		"FDIVDP	F0,%f",
694*37da2899SCharles.Forsyth };
695*37da2899SCharles.Forsyth 
696*37da2899SCharles.Forsyth static Optable optabDF[8+8] =
697*37da2899SCharles.Forsyth {
698*37da2899SCharles.Forsyth 	0,0,		"FMOVW	%e,F0",
699*37da2899SCharles.Forsyth 	0,0,		nil,
700*37da2899SCharles.Forsyth 	0,0,		"FMOVW	F0,%e",
701*37da2899SCharles.Forsyth 	0,0,		"FMOVWP	F0,%e",
702*37da2899SCharles.Forsyth 	0,0,		"FBLD	%e",
703*37da2899SCharles.Forsyth 	0,0,		"FMOVL	%e,F0",
704*37da2899SCharles.Forsyth 	0,0,		"FBSTP	%e",
705*37da2899SCharles.Forsyth 	0,0,		"FMOVLP	F0,%e",
706*37da2899SCharles.Forsyth 	0,0,		nil,
707*37da2899SCharles.Forsyth 	0,0,		nil,
708*37da2899SCharles.Forsyth 	0,0,		nil,
709*37da2899SCharles.Forsyth 	0,0,		nil,
710*37da2899SCharles.Forsyth 	R0,0,		"FSTSW	%OAX",
711*37da2899SCharles.Forsyth };
712*37da2899SCharles.Forsyth 
713*37da2899SCharles.Forsyth static Optable optabF6[8] =
714*37da2899SCharles.Forsyth {
715*37da2899SCharles.Forsyth 	Ib,0,		"TESTB	%i,%e",
716*37da2899SCharles.Forsyth 	0,0,		nil,
717*37da2899SCharles.Forsyth 	0,0,		"NOTB	%e",
718*37da2899SCharles.Forsyth 	0,0,		"NEGB	%e",
719*37da2899SCharles.Forsyth 	0,0,		"MULB	AL,%e",
720*37da2899SCharles.Forsyth 	0,0,		"IMULB	AL,%e",
721*37da2899SCharles.Forsyth 	0,0,		"DIVB	AL,%e",
722*37da2899SCharles.Forsyth 	0,0,		"IDIVB	AL,%e",
723*37da2899SCharles.Forsyth };
724*37da2899SCharles.Forsyth 
725*37da2899SCharles.Forsyth static Optable optabF7[8] =
726*37da2899SCharles.Forsyth {
727*37da2899SCharles.Forsyth 	Iwd,0,		"TEST%S	%i,%e",
728*37da2899SCharles.Forsyth 	0,0,		nil,
729*37da2899SCharles.Forsyth 	0,0,		"NOT%S	%e",
730*37da2899SCharles.Forsyth 	0,0,		"NEG%S	%e",
731*37da2899SCharles.Forsyth 	0,0,		"MUL%S	%OAX,%e",
732*37da2899SCharles.Forsyth 	0,0,		"IMUL%S	%OAX,%e",
733*37da2899SCharles.Forsyth 	0,0,		"DIV%S	%OAX,%e",
734*37da2899SCharles.Forsyth 	0,0,		"IDIV%S	%OAX,%e",
735*37da2899SCharles.Forsyth };
736*37da2899SCharles.Forsyth 
737*37da2899SCharles.Forsyth static Optable optabFE[8] =
738*37da2899SCharles.Forsyth {
739*37da2899SCharles.Forsyth 	0,0,		"INCB	%e",
740*37da2899SCharles.Forsyth 	0,0,		"DECB	%e",
741*37da2899SCharles.Forsyth };
742*37da2899SCharles.Forsyth 
743*37da2899SCharles.Forsyth static Optable optabFF[8] =
744*37da2899SCharles.Forsyth {
745*37da2899SCharles.Forsyth 	0,0,		"INC%S	%e",
746*37da2899SCharles.Forsyth 	0,0,		"DEC%S	%e",
747*37da2899SCharles.Forsyth 	JUMP,0,		"CALL*%S %e",
748*37da2899SCharles.Forsyth 	JUMP,0,		"CALLF*%S %e",
749*37da2899SCharles.Forsyth 	JUMP,0,		"JMP*%S	%e",
750*37da2899SCharles.Forsyth 	JUMP,0,		"JMPF*%S %e",
751*37da2899SCharles.Forsyth 	0,0,		"PUSHL	%e",
752*37da2899SCharles.Forsyth };
753*37da2899SCharles.Forsyth 
754*37da2899SCharles.Forsyth static Optable optable[256] =
755*37da2899SCharles.Forsyth {
756*37da2899SCharles.Forsyth 	RMB,0,		"ADDB	%r,%e",
757*37da2899SCharles.Forsyth 	RM,0,		"ADD%S	%r,%e",
758*37da2899SCharles.Forsyth 	RMB,0,		"ADDB	%e,%r",
759*37da2899SCharles.Forsyth 	RM,0,		"ADD%S	%e,%r",
760*37da2899SCharles.Forsyth 	Ib,0,		"ADDB	%i,AL",
761*37da2899SCharles.Forsyth 	Iwd,0,		"ADD%S	%i,%OAX",
762*37da2899SCharles.Forsyth 	0,0,		"PUSHL	ES",
763*37da2899SCharles.Forsyth 	0,0,		"POPL	ES",
764*37da2899SCharles.Forsyth 	RMB,0,		"ORB	%r,%e",
765*37da2899SCharles.Forsyth 	RM,0,		"OR%S	%r,%e",
766*37da2899SCharles.Forsyth 	RMB,0,		"ORB	%e,%r",
767*37da2899SCharles.Forsyth 	RM,0,		"OR%S	%e,%r",
768*37da2899SCharles.Forsyth 	Ib,0,		"ORB	%i,AL",
769*37da2899SCharles.Forsyth 	Iwd,0,		"OR%S	%i,%OAX",
770*37da2899SCharles.Forsyth 	0,0,		"PUSHL	CS",
771*37da2899SCharles.Forsyth 	AUX,0,		optab0F,
772*37da2899SCharles.Forsyth 	RMB,0,		"ADCB	%r,%e",
773*37da2899SCharles.Forsyth 	RM,0,		"ADC%S	%r,%e",
774*37da2899SCharles.Forsyth 	RMB,0,		"ADCB	%e,%r",
775*37da2899SCharles.Forsyth 	RM,0,		"ADC%S	%e,%r",
776*37da2899SCharles.Forsyth 	Ib,0,		"ADCB	%i,AL",
777*37da2899SCharles.Forsyth 	Iwd,0,		"ADC%S	%i,%OAX",
778*37da2899SCharles.Forsyth 	0,0,		"PUSHL	SS",
779*37da2899SCharles.Forsyth 	0,0,		"POPL	SS",
780*37da2899SCharles.Forsyth 	RMB,0,		"SBBB	%r,%e",
781*37da2899SCharles.Forsyth 	RM,0,		"SBB%S	%r,%e",
782*37da2899SCharles.Forsyth 	RMB,0,		"SBBB	%e,%r",
783*37da2899SCharles.Forsyth 	RM,0,		"SBB%S	%e,%r",
784*37da2899SCharles.Forsyth 	Ib,0,		"SBBB	%i,AL",
785*37da2899SCharles.Forsyth 	Iwd,0,		"SBB%S	%i,%OAX",
786*37da2899SCharles.Forsyth 	0,0,		"PUSHL	DS",
787*37da2899SCharles.Forsyth 	0,0,		"POPL	DS",
788*37da2899SCharles.Forsyth 	RMB,0,		"ANDB	%r,%e",
789*37da2899SCharles.Forsyth 	RM,0,		"AND%S	%r,%e",
790*37da2899SCharles.Forsyth 	RMB,0,		"ANDB	%e,%r",
791*37da2899SCharles.Forsyth 	RM,0,		"AND%S	%e,%r",
792*37da2899SCharles.Forsyth 	Ib,0,		"ANDB	%i,AL",
793*37da2899SCharles.Forsyth 	Iwd,0,		"AND%S	%i,%OAX",
794*37da2899SCharles.Forsyth 	SEG,0,		"ES:",
795*37da2899SCharles.Forsyth 	0,0,		"DAA",
796*37da2899SCharles.Forsyth 	RMB,0,		"SUBB	%r,%e",
797*37da2899SCharles.Forsyth 	RM,0,		"SUB%S	%r,%e",
798*37da2899SCharles.Forsyth 	RMB,0,		"SUBB	%e,%r",
799*37da2899SCharles.Forsyth 	RM,0,		"SUB%S	%e,%r",
800*37da2899SCharles.Forsyth 	Ib,0,		"SUBB	%i,AL",
801*37da2899SCharles.Forsyth 	Iwd,0,		"SUB%S	%i,%OAX",
802*37da2899SCharles.Forsyth 	SEG,0,		"CS:",
803*37da2899SCharles.Forsyth 	0,0,		"DAS",
804*37da2899SCharles.Forsyth 	RMB,0,		"XORB	%r,%e",
805*37da2899SCharles.Forsyth 	RM,0,		"XOR%S	%r,%e",
806*37da2899SCharles.Forsyth 	RMB,0,		"XORB	%e,%r",
807*37da2899SCharles.Forsyth 	RM,0,		"XOR%S	%e,%r",
808*37da2899SCharles.Forsyth 	Ib,0,		"XORB	%i,AL",
809*37da2899SCharles.Forsyth 	Iwd,0,		"XOR%S	%i,%OAX",
810*37da2899SCharles.Forsyth 	SEG,0,		"SS:",
811*37da2899SCharles.Forsyth 	0,0,		"AAA",
812*37da2899SCharles.Forsyth 	RMB,0,		"CMPB	%r,%e",
813*37da2899SCharles.Forsyth 	RM,0,		"CMP%S	%r,%e",
814*37da2899SCharles.Forsyth 	RMB,0,		"CMPB	%e,%r",
815*37da2899SCharles.Forsyth 	RM,0,		"CMP%S	%e,%r",
816*37da2899SCharles.Forsyth 	Ib,0,		"CMPB	%i,AL",
817*37da2899SCharles.Forsyth 	Iwd,0,		"CMP%S	%i,%OAX",
818*37da2899SCharles.Forsyth 	SEG,0,		"DS:",
819*37da2899SCharles.Forsyth 	0,0,		"AAS",
820*37da2899SCharles.Forsyth 	0,0,		"INC%S	%OAX",
821*37da2899SCharles.Forsyth 	0,0,		"INC%S	%OCX",
822*37da2899SCharles.Forsyth 	0,0,		"INC%S	%ODX",
823*37da2899SCharles.Forsyth 	0,0,		"INC%S	%OBX",
824*37da2899SCharles.Forsyth 	0,0,		"INC%S	%OSP",
825*37da2899SCharles.Forsyth 	0,0,		"INC%S	%OBP",
826*37da2899SCharles.Forsyth 	0,0,		"INC%S	%OSI",
827*37da2899SCharles.Forsyth 	0,0,		"INC%S	%ODI",
828*37da2899SCharles.Forsyth 	0,0,		"DEC%S	%OAX",
829*37da2899SCharles.Forsyth 	0,0,		"DEC%S	%OCX",
830*37da2899SCharles.Forsyth 	0,0,		"DEC%S	%ODX",
831*37da2899SCharles.Forsyth 	0,0,		"DEC%S	%OBX",
832*37da2899SCharles.Forsyth 	0,0,		"DEC%S	%OSP",
833*37da2899SCharles.Forsyth 	0,0,		"DEC%S	%OBP",
834*37da2899SCharles.Forsyth 	0,0,		"DEC%S	%OSI",
835*37da2899SCharles.Forsyth 	0,0,		"DEC%S	%ODI",
836*37da2899SCharles.Forsyth 	0,0,		"PUSH%S	%OAX",
837*37da2899SCharles.Forsyth 	0,0,		"PUSH%S	%OCX",
838*37da2899SCharles.Forsyth 	0,0,		"PUSH%S	%ODX",
839*37da2899SCharles.Forsyth 	0,0,		"PUSH%S	%OBX",
840*37da2899SCharles.Forsyth 	0,0,		"PUSH%S	%OSP",
841*37da2899SCharles.Forsyth 	0,0,		"PUSH%S	%OBP",
842*37da2899SCharles.Forsyth 	0,0,		"PUSH%S	%OSI",
843*37da2899SCharles.Forsyth 	0,0,		"PUSH%S	%ODI",
844*37da2899SCharles.Forsyth 	0,0,		"POP%S	%OAX",
845*37da2899SCharles.Forsyth 	0,0,		"POP%S	%OCX",
846*37da2899SCharles.Forsyth 	0,0,		"POP%S	%ODX",
847*37da2899SCharles.Forsyth 	0,0,		"POP%S	%OBX",
848*37da2899SCharles.Forsyth 	0,0,		"POP%S	%OSP",
849*37da2899SCharles.Forsyth 	0,0,		"POP%S	%OBP",
850*37da2899SCharles.Forsyth 	0,0,		"POP%S	%OSI",
851*37da2899SCharles.Forsyth 	0,0,		"POP%S	%ODI",
852*37da2899SCharles.Forsyth 	0,0,		"PUSHA%S",
853*37da2899SCharles.Forsyth 	0,0,		"POPA%S",
854*37da2899SCharles.Forsyth 	RMM,0,		"BOUND	%e,%r",
855*37da2899SCharles.Forsyth 	RM,0,		"ARPL	%r,%e",
856*37da2899SCharles.Forsyth 	SEG,0,		"FS:",
857*37da2899SCharles.Forsyth 	SEG,0,		"GS:",
858*37da2899SCharles.Forsyth 	OPOVER,0,	"",
859*37da2899SCharles.Forsyth 	ADDOVER,0,	"",
860*37da2899SCharles.Forsyth 	Iwd,0,		"PUSH%S	%i",
861*37da2899SCharles.Forsyth 	RM,Iwd,		"IMUL%S	%e,%i,%r",
862*37da2899SCharles.Forsyth 	Ib,0,		"PUSH%S	%i",
863*37da2899SCharles.Forsyth 	RM,Ibs,		"IMUL%S	%e,%i,%r",
864*37da2899SCharles.Forsyth 	0,0,		"INSB	DX,(%ODI)",
865*37da2899SCharles.Forsyth 	0,0,		"INS%S	DX,(%ODI)",
866*37da2899SCharles.Forsyth 	0,0,		"OUTSB	(%ASI),DX",
867*37da2899SCharles.Forsyth 	0,0,		"OUTS%S	(%ASI),DX",
868*37da2899SCharles.Forsyth 	Jbs,0,		"JOS	%p",
869*37da2899SCharles.Forsyth 	Jbs,0,		"JOC	%p",
870*37da2899SCharles.Forsyth 	Jbs,0,		"JCS	%p",
871*37da2899SCharles.Forsyth 	Jbs,0,		"JCC	%p",
872*37da2899SCharles.Forsyth 	Jbs,0,		"JEQ	%p",
873*37da2899SCharles.Forsyth 	Jbs,0,		"JNE	%p",
874*37da2899SCharles.Forsyth 	Jbs,0,		"JLS	%p",
875*37da2899SCharles.Forsyth 	Jbs,0,		"JHI	%p",
876*37da2899SCharles.Forsyth 	Jbs,0,		"JMI	%p",
877*37da2899SCharles.Forsyth 	Jbs,0,		"JPL	%p",
878*37da2899SCharles.Forsyth 	Jbs,0,		"JPS	%p",
879*37da2899SCharles.Forsyth 	Jbs,0,		"JPC	%p",
880*37da2899SCharles.Forsyth 	Jbs,0,		"JLT	%p",
881*37da2899SCharles.Forsyth 	Jbs,0,		"JGE	%p",
882*37da2899SCharles.Forsyth 	Jbs,0,		"JLE	%p",
883*37da2899SCharles.Forsyth 	Jbs,0,		"JGT	%p",
884*37da2899SCharles.Forsyth 	RMOPB,0,	optab80,
885*37da2899SCharles.Forsyth 	RMOP,0,		optab81,
886*37da2899SCharles.Forsyth 	0,0,		nil,
887*37da2899SCharles.Forsyth 	RMOP,0,		optab83,
888*37da2899SCharles.Forsyth 	RMB,0,		"TESTB	%r,%e",
889*37da2899SCharles.Forsyth 	RM,0,		"TEST%S	%r,%e",
890*37da2899SCharles.Forsyth 	RMB,0,		"XCHGB	%r,%e",
891*37da2899SCharles.Forsyth 	RM,0,		"XCHG%S	%r,%e",
892*37da2899SCharles.Forsyth 	RMB,0,		"MOVB	%r,%e",
893*37da2899SCharles.Forsyth 	RM,0,		"MOV%S	%r,%e",
894*37da2899SCharles.Forsyth 	RMB,0,		"MOVB	%e,%r",
895*37da2899SCharles.Forsyth 	RM,0,		"MOV%S	%e,%r",
896*37da2899SCharles.Forsyth 	RM,0,		"MOVW	%g,%e",
897*37da2899SCharles.Forsyth 	RM,0,		"LEA	%e,%r",
898*37da2899SCharles.Forsyth 	RM,0,		"MOVW	%e,%g",
899*37da2899SCharles.Forsyth 	RM,0,		"POP%S	%e",
900*37da2899SCharles.Forsyth 	0,0,		"NOP",
901*37da2899SCharles.Forsyth 	0,0,		"XCHG	%OCX,%OAX",
902*37da2899SCharles.Forsyth 	0,0,		"XCHG	%ODX,%OAX",
903*37da2899SCharles.Forsyth 	0,0,		"XCHG	%OBX,%OAX",
904*37da2899SCharles.Forsyth 	0,0,		"XCHG	%OSP,%OAX",
905*37da2899SCharles.Forsyth 	0,0,		"XCHG	%OBP,%OAX",
906*37da2899SCharles.Forsyth 	0,0,		"XCHG	%OSI,%OAX",
907*37da2899SCharles.Forsyth 	0,0,		"XCHG	%ODI,%OAX",
908*37da2899SCharles.Forsyth 	0,0,		"%X",			/* miserable CBW or CWDE */
909*37da2899SCharles.Forsyth 	0,0,		"%x",			/* idiotic CWD or CDQ */
910*37da2899SCharles.Forsyth 	PTR,0,		"CALL%S	%d",
911*37da2899SCharles.Forsyth 	0,0,		"WAIT",
912*37da2899SCharles.Forsyth 	0,0,		"PUSH	FLAGS",
913*37da2899SCharles.Forsyth 	0,0,		"POP	FLAGS",
914*37da2899SCharles.Forsyth 	0,0,		"SAHF",
915*37da2899SCharles.Forsyth 	0,0,		"LAHF",
916*37da2899SCharles.Forsyth 	Awd,0,		"MOVB	%i,AL",
917*37da2899SCharles.Forsyth 	Awd,0,		"MOV%S	%i,%OAX",
918*37da2899SCharles.Forsyth 	Awd,0,		"MOVB	AL,%i",
919*37da2899SCharles.Forsyth 	Awd,0,		"MOV%S	%OAX,%i",
920*37da2899SCharles.Forsyth 	0,0,		"MOVSB	(%ASI),(%ADI)",
921*37da2899SCharles.Forsyth 	0,0,		"MOVS%S	(%ASI),(%ADI)",
922*37da2899SCharles.Forsyth 	0,0,		"CMPSB	(%ASI),(%ADI)",
923*37da2899SCharles.Forsyth 	0,0,		"CMPS%S	(%ASI),(%ADI)",
924*37da2899SCharles.Forsyth 	Ib,0,		"TESTB	%i,AL",
925*37da2899SCharles.Forsyth 	Iwd,0,		"TEST%S	%i,%OAX",
926*37da2899SCharles.Forsyth 	0,0,		"STOSB	AL,(%ADI)",
927*37da2899SCharles.Forsyth 	0,0,		"STOS%S	%OAX,(%ADI)",
928*37da2899SCharles.Forsyth 	0,0,		"LODSB	(%ASI),AL",
929*37da2899SCharles.Forsyth 	0,0,		"LODS%S	(%ASI),%OAX",
930*37da2899SCharles.Forsyth 	0,0,		"SCASB	(%ADI),AL",
931*37da2899SCharles.Forsyth 	0,0,		"SCAS%S	(%ADI),%OAX",
932*37da2899SCharles.Forsyth 	Ib,0,		"MOVB	%i,AL",
933*37da2899SCharles.Forsyth 	Ib,0,		"MOVB	%i,CL",
934*37da2899SCharles.Forsyth 	Ib,0,		"MOVB	%i,DL",
935*37da2899SCharles.Forsyth 	Ib,0,		"MOVB	%i,BL",
936*37da2899SCharles.Forsyth 	Ib,0,		"MOVB	%i,AH",
937*37da2899SCharles.Forsyth 	Ib,0,		"MOVB	%i,CH",
938*37da2899SCharles.Forsyth 	Ib,0,		"MOVB	%i,DH",
939*37da2899SCharles.Forsyth 	Ib,0,		"MOVB	%i,BH",
940*37da2899SCharles.Forsyth 	Iwd,0,		"MOV%S	%i,%OAX",
941*37da2899SCharles.Forsyth 	Iwd,0,		"MOV%S	%i,%OCX",
942*37da2899SCharles.Forsyth 	Iwd,0,		"MOV%S	%i,%ODX",
943*37da2899SCharles.Forsyth 	Iwd,0,		"MOV%S	%i,%OBX",
944*37da2899SCharles.Forsyth 	Iwd,0,		"MOV%S	%i,%OSP",
945*37da2899SCharles.Forsyth 	Iwd,0,		"MOV%S	%i,%OBP",
946*37da2899SCharles.Forsyth 	Iwd,0,		"MOV%S	%i,%OSI",
947*37da2899SCharles.Forsyth 	Iwd,0,		"MOV%S	%i,%ODI",
948*37da2899SCharles.Forsyth 	RMOPB,0,	optabC0,
949*37da2899SCharles.Forsyth 	RMOP,0,		optabC1,
950*37da2899SCharles.Forsyth 	Iw,0,		"RET	%i",
951*37da2899SCharles.Forsyth 	RET,0,		"RET",
952*37da2899SCharles.Forsyth 	RM,0,		"LES	%e,%r",
953*37da2899SCharles.Forsyth 	RM,0,		"LDS	%e,%r",
954*37da2899SCharles.Forsyth 	RMB,Ib,		"MOVB	%i,%e",
955*37da2899SCharles.Forsyth 	RM,Iwd,		"MOV%S	%i,%e",
956*37da2899SCharles.Forsyth 	Iw2,Ib,		"ENTER	%i,%I",		/* loony ENTER */
957*37da2899SCharles.Forsyth 	RET,0,		"LEAVE",		/* bizarre LEAVE */
958*37da2899SCharles.Forsyth 	Iw,0,		"RETF	%i",
959*37da2899SCharles.Forsyth 	RET,0,		"RETF",
960*37da2899SCharles.Forsyth 	0,0,		"INT	3",
961*37da2899SCharles.Forsyth 	Ib,0,		"INTB	%i",
962*37da2899SCharles.Forsyth 	0,0,		"INTO",
963*37da2899SCharles.Forsyth 	0,0,		"IRET",
964*37da2899SCharles.Forsyth 	RMOPB,0,	optabD0,
965*37da2899SCharles.Forsyth 	RMOP,0,		optabD1,
966*37da2899SCharles.Forsyth 	RMOPB,0,	optabD2,
967*37da2899SCharles.Forsyth 	RMOP,0,		optabD3,
968*37da2899SCharles.Forsyth 	OA,0,		"AAM",
969*37da2899SCharles.Forsyth 	OA,0,		"AAD",
970*37da2899SCharles.Forsyth 	0,0,		nil,
971*37da2899SCharles.Forsyth 	0,0,		"XLAT",
972*37da2899SCharles.Forsyth 	FRMOP,0,	optabD8,
973*37da2899SCharles.Forsyth 	FRMEX,0,	optabD9,
974*37da2899SCharles.Forsyth 	FRMOP,0,	optabDA,
975*37da2899SCharles.Forsyth 	FRMEX,0,	optabDB,
976*37da2899SCharles.Forsyth 	FRMOP,0,	optabDC,
977*37da2899SCharles.Forsyth 	FRMOP,0,	optabDD,
978*37da2899SCharles.Forsyth 	FRMOP,0,	optabDE,
979*37da2899SCharles.Forsyth 	FRMOP,0,	optabDF,
980*37da2899SCharles.Forsyth 	Jbs,0,		"LOOPNE	%p",
981*37da2899SCharles.Forsyth 	Jbs,0,		"LOOPE	%p",
982*37da2899SCharles.Forsyth 	Jbs,0,		"LOOP	%p",
983*37da2899SCharles.Forsyth 	Jbs,0,		"JCXZ	%p",
984*37da2899SCharles.Forsyth 	Ib,0,		"INB	%i,AL",
985*37da2899SCharles.Forsyth 	Ib,0,		"IN%S	%i,%OAX",
986*37da2899SCharles.Forsyth 	Ib,0,		"OUTB	AL,%i",
987*37da2899SCharles.Forsyth 	Ib,0,		"OUT%S	%OAX,%i",
988*37da2899SCharles.Forsyth 	Iwds,0,		"CALL	%p",
989*37da2899SCharles.Forsyth 	Iwds,0,		"JMP	%p",
990*37da2899SCharles.Forsyth 	PTR,0,		"JMP	%d",
991*37da2899SCharles.Forsyth 	Jbs,0,		"JMP	%p",
992*37da2899SCharles.Forsyth 	0,0,		"INB	DX,AL",
993*37da2899SCharles.Forsyth 	0,0,		"IN%S	DX,%OAX",
994*37da2899SCharles.Forsyth 	0,0,		"OUTB	AL,DX",
995*37da2899SCharles.Forsyth 	0,0,		"OUT%S	%OAX,DX",
996*37da2899SCharles.Forsyth 	PRE,0,		"LOCK",
997*37da2899SCharles.Forsyth 	0,0,		nil,
998*37da2899SCharles.Forsyth 	PRE,0,		"REPNE",
999*37da2899SCharles.Forsyth 	PRE,0,		"REP",
1000*37da2899SCharles.Forsyth 	0,0,		"HALT",
1001*37da2899SCharles.Forsyth 	0,0,		"CMC",
1002*37da2899SCharles.Forsyth 	RMOPB,0,	optabF6,
1003*37da2899SCharles.Forsyth 	RMOP,0,		optabF7,
1004*37da2899SCharles.Forsyth 	0,0,		"CLC",
1005*37da2899SCharles.Forsyth 	0,0,		"STC",
1006*37da2899SCharles.Forsyth 	0,0,		"CLI",
1007*37da2899SCharles.Forsyth 	0,0,		"STI",
1008*37da2899SCharles.Forsyth 	0,0,		"CLD",
1009*37da2899SCharles.Forsyth 	0,0,		"STD",
1010*37da2899SCharles.Forsyth 	RMOPB,0,	optabFE,
1011*37da2899SCharles.Forsyth 	RMOP,0,		optabFF,
1012*37da2899SCharles.Forsyth };
1013*37da2899SCharles.Forsyth 
1014*37da2899SCharles.Forsyth /*
1015*37da2899SCharles.Forsyth  *  get a byte of the instruction
1016*37da2899SCharles.Forsyth  */
1017*37da2899SCharles.Forsyth static int
igetc(Instr * ip,uchar * c)1018*37da2899SCharles.Forsyth igetc(Instr *ip, uchar *c)
1019*37da2899SCharles.Forsyth {
1020*37da2899SCharles.Forsyth 	if(ip->n+1 > sizeof(ip->mem)){
1021*37da2899SCharles.Forsyth 		kwerrstr("instruction too long");
1022*37da2899SCharles.Forsyth 		return -1;
1023*37da2899SCharles.Forsyth 	}
1024*37da2899SCharles.Forsyth 	*c = dasdata[ip->addr+ip->n];
1025*37da2899SCharles.Forsyth 	ip->mem[ip->n++] = *c;
1026*37da2899SCharles.Forsyth 	return 1;
1027*37da2899SCharles.Forsyth }
1028*37da2899SCharles.Forsyth 
1029*37da2899SCharles.Forsyth /*
1030*37da2899SCharles.Forsyth  *  get two bytes of the instruction
1031*37da2899SCharles.Forsyth  */
1032*37da2899SCharles.Forsyth static int
igets(Instr * ip,ushort * sp)1033*37da2899SCharles.Forsyth igets(Instr *ip, ushort *sp)
1034*37da2899SCharles.Forsyth {
1035*37da2899SCharles.Forsyth 	uchar	c;
1036*37da2899SCharles.Forsyth 	ushort s;
1037*37da2899SCharles.Forsyth 
1038*37da2899SCharles.Forsyth 	if (igetc(ip, &c) < 0)
1039*37da2899SCharles.Forsyth 		return -1;
1040*37da2899SCharles.Forsyth 	s = c;
1041*37da2899SCharles.Forsyth 	if (igetc(ip, &c) < 0)
1042*37da2899SCharles.Forsyth 		return -1;
1043*37da2899SCharles.Forsyth 	s |= (c<<8);
1044*37da2899SCharles.Forsyth 	*sp = s;
1045*37da2899SCharles.Forsyth 	return 1;
1046*37da2899SCharles.Forsyth }
1047*37da2899SCharles.Forsyth 
1048*37da2899SCharles.Forsyth /*
1049*37da2899SCharles.Forsyth  *  get 4 bytes of the instruction
1050*37da2899SCharles.Forsyth  */
1051*37da2899SCharles.Forsyth static int
igetl(Instr * ip,ulong * lp)1052*37da2899SCharles.Forsyth igetl(Instr *ip, ulong *lp)
1053*37da2899SCharles.Forsyth {
1054*37da2899SCharles.Forsyth 	ushort s;
1055*37da2899SCharles.Forsyth 	long	l;
1056*37da2899SCharles.Forsyth 
1057*37da2899SCharles.Forsyth 	if (igets(ip, &s) < 0)
1058*37da2899SCharles.Forsyth 		return -1;
1059*37da2899SCharles.Forsyth 	l = s;
1060*37da2899SCharles.Forsyth 	if (igets(ip, &s) < 0)
1061*37da2899SCharles.Forsyth 		return -1;
1062*37da2899SCharles.Forsyth 	l |= (s<<16);
1063*37da2899SCharles.Forsyth 	*lp = l;
1064*37da2899SCharles.Forsyth 	return 1;
1065*37da2899SCharles.Forsyth }
1066*37da2899SCharles.Forsyth 
1067*37da2899SCharles.Forsyth static int
getdisp(Instr * ip,int mod,int rm,int code)1068*37da2899SCharles.Forsyth getdisp(Instr *ip, int mod, int rm, int code)
1069*37da2899SCharles.Forsyth {
1070*37da2899SCharles.Forsyth 	uchar c;
1071*37da2899SCharles.Forsyth 	ushort s;
1072*37da2899SCharles.Forsyth 
1073*37da2899SCharles.Forsyth 	if (mod > 2)
1074*37da2899SCharles.Forsyth 		return 1;
1075*37da2899SCharles.Forsyth 	if (mod == 1) {
1076*37da2899SCharles.Forsyth 		if (igetc(ip, &c) < 0)
1077*37da2899SCharles.Forsyth 			return -1;
1078*37da2899SCharles.Forsyth 		if (c&0x80)
1079*37da2899SCharles.Forsyth 			ip->disp = c|0xffffff00;
1080*37da2899SCharles.Forsyth 		else
1081*37da2899SCharles.Forsyth 			ip->disp = c&0xff;
1082*37da2899SCharles.Forsyth 	} else if (mod == 2 || rm == code) {
1083*37da2899SCharles.Forsyth 		if (ip->asize == 'E') {
1084*37da2899SCharles.Forsyth 			if (igetl(ip, &ip->disp) < 0)
1085*37da2899SCharles.Forsyth 				return -1;
1086*37da2899SCharles.Forsyth 		} else {
1087*37da2899SCharles.Forsyth 			if (igets(ip, &s) < 0)
1088*37da2899SCharles.Forsyth 				return -1;
1089*37da2899SCharles.Forsyth 			if (s&0x8000)
1090*37da2899SCharles.Forsyth 				ip->disp = s|0xffff0000;
1091*37da2899SCharles.Forsyth 			else
1092*37da2899SCharles.Forsyth 				ip->disp = s;
1093*37da2899SCharles.Forsyth 		}
1094*37da2899SCharles.Forsyth 		if (mod == 0)
1095*37da2899SCharles.Forsyth 			ip->base = -1;
1096*37da2899SCharles.Forsyth 	}
1097*37da2899SCharles.Forsyth 	return 1;
1098*37da2899SCharles.Forsyth }
1099*37da2899SCharles.Forsyth 
1100*37da2899SCharles.Forsyth static int
modrm(Instr * ip,uchar c)1101*37da2899SCharles.Forsyth modrm(Instr *ip, uchar c)
1102*37da2899SCharles.Forsyth {
1103*37da2899SCharles.Forsyth 	uchar rm, mod;
1104*37da2899SCharles.Forsyth 
1105*37da2899SCharles.Forsyth 	mod = (c>>6)&3;
1106*37da2899SCharles.Forsyth 	rm = c&7;
1107*37da2899SCharles.Forsyth 	ip->mod = mod;
1108*37da2899SCharles.Forsyth 	ip->base = rm;
1109*37da2899SCharles.Forsyth 	ip->reg = (c>>3)&7;
1110*37da2899SCharles.Forsyth 	if (mod == 3)			/* register */
1111*37da2899SCharles.Forsyth 		return 1;
1112*37da2899SCharles.Forsyth 	if (ip->asize == 0) {		/* 16-bit mode */
1113*37da2899SCharles.Forsyth 		switch(rm)
1114*37da2899SCharles.Forsyth 		{
1115*37da2899SCharles.Forsyth 		case 0:
1116*37da2899SCharles.Forsyth 			ip->base = BX; ip->index = SI;
1117*37da2899SCharles.Forsyth 			break;
1118*37da2899SCharles.Forsyth 		case 1:
1119*37da2899SCharles.Forsyth 			ip->base = BX; ip->index = DI;
1120*37da2899SCharles.Forsyth 			break;
1121*37da2899SCharles.Forsyth 		case 2:
1122*37da2899SCharles.Forsyth 			ip->base = BP; ip->index = SI;
1123*37da2899SCharles.Forsyth 			break;
1124*37da2899SCharles.Forsyth 		case 3:
1125*37da2899SCharles.Forsyth 			ip->base = BP; ip->index = DI;
1126*37da2899SCharles.Forsyth 			break;
1127*37da2899SCharles.Forsyth 		case 4:
1128*37da2899SCharles.Forsyth 			ip->base = SI;
1129*37da2899SCharles.Forsyth 			break;
1130*37da2899SCharles.Forsyth 		case 5:
1131*37da2899SCharles.Forsyth 			ip->base = DI;
1132*37da2899SCharles.Forsyth 			break;
1133*37da2899SCharles.Forsyth 		case 6:
1134*37da2899SCharles.Forsyth 			ip->base = BP;
1135*37da2899SCharles.Forsyth 			break;
1136*37da2899SCharles.Forsyth 		case 7:
1137*37da2899SCharles.Forsyth 			ip->base = BX;
1138*37da2899SCharles.Forsyth 			break;
1139*37da2899SCharles.Forsyth 		default:
1140*37da2899SCharles.Forsyth 			break;
1141*37da2899SCharles.Forsyth 		}
1142*37da2899SCharles.Forsyth 		return getdisp(ip, mod, rm, 6);
1143*37da2899SCharles.Forsyth 	}
1144*37da2899SCharles.Forsyth 	if (rm == 4) {	/* scummy sib byte */
1145*37da2899SCharles.Forsyth 		if (igetc(ip, &c) < 0)
1146*37da2899SCharles.Forsyth 			return -1;
1147*37da2899SCharles.Forsyth 		ip->ss = (c>>6)&0x03;
1148*37da2899SCharles.Forsyth 		ip->index = (c>>3)&0x07;
1149*37da2899SCharles.Forsyth 		if (ip->index == 4)
1150*37da2899SCharles.Forsyth 			ip->index = -1;
1151*37da2899SCharles.Forsyth 		ip->base = c&0x07;
1152*37da2899SCharles.Forsyth 		return getdisp(ip, mod, ip->base, 5);
1153*37da2899SCharles.Forsyth 	}
1154*37da2899SCharles.Forsyth 	return getdisp(ip, mod, rm, 5);
1155*37da2899SCharles.Forsyth }
1156*37da2899SCharles.Forsyth 
1157*37da2899SCharles.Forsyth static Optable *
mkinstr(Instr * ip,ulong pc)1158*37da2899SCharles.Forsyth mkinstr(Instr *ip, ulong pc)
1159*37da2899SCharles.Forsyth {
1160*37da2899SCharles.Forsyth 	int i, n;
1161*37da2899SCharles.Forsyth 	uchar c;
1162*37da2899SCharles.Forsyth 	ushort s;
1163*37da2899SCharles.Forsyth 	Optable *op, *obase;
1164*37da2899SCharles.Forsyth 	char buf[128];
1165*37da2899SCharles.Forsyth 
1166*37da2899SCharles.Forsyth 	memset(ip, 0, sizeof(*ip));
1167*37da2899SCharles.Forsyth 	ip->base = -1;
1168*37da2899SCharles.Forsyth 	ip->index = -1;
1169*37da2899SCharles.Forsyth 	ip->osize = 'L';
1170*37da2899SCharles.Forsyth 	ip->asize = 'E';
1171*37da2899SCharles.Forsyth 	ip->addr = pc;
1172*37da2899SCharles.Forsyth 	if (igetc(ip, &c) < 0)
1173*37da2899SCharles.Forsyth 		return 0;
1174*37da2899SCharles.Forsyth 	obase = optable;
1175*37da2899SCharles.Forsyth newop:
1176*37da2899SCharles.Forsyth 	op = &obase[c];
1177*37da2899SCharles.Forsyth 	if (op->proto == 0) {
1178*37da2899SCharles.Forsyth badop:
1179*37da2899SCharles.Forsyth 		n = snprint(buf, sizeof(buf), "opcode: ??");
1180*37da2899SCharles.Forsyth 		for (i = 0; i < ip->n && n < sizeof(buf)-3; i++, n+=2)
1181*37da2899SCharles.Forsyth 			_hexify(buf+n, ip->mem[i], 1);
1182*37da2899SCharles.Forsyth 		strcpy(buf+n, "??");
1183*37da2899SCharles.Forsyth 		kwerrstr(buf);
1184*37da2899SCharles.Forsyth 		return 0;
1185*37da2899SCharles.Forsyth 	}
1186*37da2899SCharles.Forsyth 	for(i = 0; i < 2 && op->operand[i]; i++) {
1187*37da2899SCharles.Forsyth 		switch(op->operand[i])
1188*37da2899SCharles.Forsyth 		{
1189*37da2899SCharles.Forsyth 		case Ib:	/* 8-bit immediate - (no sign extension)*/
1190*37da2899SCharles.Forsyth 			if (igetc(ip, &c) < 0)
1191*37da2899SCharles.Forsyth 				return 0;
1192*37da2899SCharles.Forsyth 			ip->imm = c&0xff;
1193*37da2899SCharles.Forsyth 			break;
1194*37da2899SCharles.Forsyth 		case Jbs:	/* 8-bit jump immediate (sign extended) */
1195*37da2899SCharles.Forsyth 			if (igetc(ip, &c) < 0)
1196*37da2899SCharles.Forsyth 				return 0;
1197*37da2899SCharles.Forsyth 			if (c&0x80)
1198*37da2899SCharles.Forsyth 				ip->imm = c|0xffffff00;
1199*37da2899SCharles.Forsyth 			else
1200*37da2899SCharles.Forsyth 				ip->imm = c&0xff;
1201*37da2899SCharles.Forsyth 			ip->jumptype = Jbs;
1202*37da2899SCharles.Forsyth 			break;
1203*37da2899SCharles.Forsyth 		case Ibs:	/* 8-bit immediate (sign extended) */
1204*37da2899SCharles.Forsyth 			if (igetc(ip, &c) < 0)
1205*37da2899SCharles.Forsyth 				return 0;
1206*37da2899SCharles.Forsyth 			if (c&0x80)
1207*37da2899SCharles.Forsyth 				if (ip->osize == 'L')
1208*37da2899SCharles.Forsyth 					ip->imm = c|0xffffff00;
1209*37da2899SCharles.Forsyth 				else
1210*37da2899SCharles.Forsyth 					ip->imm = c|0xff00;
1211*37da2899SCharles.Forsyth 			else
1212*37da2899SCharles.Forsyth 				ip->imm = c&0xff;
1213*37da2899SCharles.Forsyth 			break;
1214*37da2899SCharles.Forsyth 		case Iw:	/* 16-bit immediate -> imm */
1215*37da2899SCharles.Forsyth 			if (igets(ip, &s) < 0)
1216*37da2899SCharles.Forsyth 				return 0;
1217*37da2899SCharles.Forsyth 			ip->imm = s&0xffff;
1218*37da2899SCharles.Forsyth 			ip->jumptype = Iw;
1219*37da2899SCharles.Forsyth 			break;
1220*37da2899SCharles.Forsyth 		case Iw2:	/* 16-bit immediate -> in imm2*/
1221*37da2899SCharles.Forsyth 			if (igets(ip, &s) < 0)
1222*37da2899SCharles.Forsyth 				return 0;
1223*37da2899SCharles.Forsyth 			ip->imm2 = s&0xffff;
1224*37da2899SCharles.Forsyth 			break;
1225*37da2899SCharles.Forsyth 		case Iwd:	/* Operand-sized immediate (no sign extension)*/
1226*37da2899SCharles.Forsyth 			if (ip->osize == 'L') {
1227*37da2899SCharles.Forsyth 				if (igetl(ip, &ip->imm) < 0)
1228*37da2899SCharles.Forsyth 					return 0;
1229*37da2899SCharles.Forsyth 			} else {
1230*37da2899SCharles.Forsyth 				if (igets(ip, &s)< 0)
1231*37da2899SCharles.Forsyth 					return 0;
1232*37da2899SCharles.Forsyth 				ip->imm = s&0xffff;
1233*37da2899SCharles.Forsyth 			}
1234*37da2899SCharles.Forsyth 			break;
1235*37da2899SCharles.Forsyth 		case Awd:	/* Address-sized immediate (no sign extension)*/
1236*37da2899SCharles.Forsyth 			if (ip->asize == 'E') {
1237*37da2899SCharles.Forsyth 				if (igetl(ip, &ip->imm) < 0)
1238*37da2899SCharles.Forsyth 					return 0;
1239*37da2899SCharles.Forsyth 			} else {
1240*37da2899SCharles.Forsyth 				if (igets(ip, &s)< 0)
1241*37da2899SCharles.Forsyth 					return 0;
1242*37da2899SCharles.Forsyth 				ip->imm = s&0xffff;
1243*37da2899SCharles.Forsyth 			}
1244*37da2899SCharles.Forsyth 			break;
1245*37da2899SCharles.Forsyth 		case Iwds:	/* Operand-sized immediate (sign extended) */
1246*37da2899SCharles.Forsyth 			if (ip->osize == 'L') {
1247*37da2899SCharles.Forsyth 				if (igetl(ip, &ip->imm) < 0)
1248*37da2899SCharles.Forsyth 					return 0;
1249*37da2899SCharles.Forsyth 			} else {
1250*37da2899SCharles.Forsyth 				if (igets(ip, &s)< 0)
1251*37da2899SCharles.Forsyth 					return 0;
1252*37da2899SCharles.Forsyth 				if (s&0x8000)
1253*37da2899SCharles.Forsyth 					ip->imm = s|0xffff0000;
1254*37da2899SCharles.Forsyth 				else
1255*37da2899SCharles.Forsyth 					ip->imm = s&0xffff;
1256*37da2899SCharles.Forsyth 			}
1257*37da2899SCharles.Forsyth 			ip->jumptype = Iwds;
1258*37da2899SCharles.Forsyth 			break;
1259*37da2899SCharles.Forsyth 		case OA:	/* literal 0x0a byte */
1260*37da2899SCharles.Forsyth 			if (igetc(ip, &c) < 0)
1261*37da2899SCharles.Forsyth 				return 0;
1262*37da2899SCharles.Forsyth 			if (c != 0x0a)
1263*37da2899SCharles.Forsyth 				goto badop;
1264*37da2899SCharles.Forsyth 			break;
1265*37da2899SCharles.Forsyth 		case R0:	/* base register must be R0 */
1266*37da2899SCharles.Forsyth 			if (ip->base != 0)
1267*37da2899SCharles.Forsyth 				goto badop;
1268*37da2899SCharles.Forsyth 			break;
1269*37da2899SCharles.Forsyth 		case R1:	/* base register must be R1 */
1270*37da2899SCharles.Forsyth 			if (ip->base != 1)
1271*37da2899SCharles.Forsyth 				goto badop;
1272*37da2899SCharles.Forsyth 			break;
1273*37da2899SCharles.Forsyth 		case RMB:	/* R/M field with byte register (/r)*/
1274*37da2899SCharles.Forsyth 			if (igetc(ip, &c) < 0)
1275*37da2899SCharles.Forsyth 				return 0;
1276*37da2899SCharles.Forsyth 			if (modrm(ip, c) < 0)
1277*37da2899SCharles.Forsyth 				return 0;
1278*37da2899SCharles.Forsyth 			ip->osize = 'B';
1279*37da2899SCharles.Forsyth 			break;
1280*37da2899SCharles.Forsyth 		case RM:	/* R/M field with register (/r) */
1281*37da2899SCharles.Forsyth 			if (igetc(ip, &c) < 0)
1282*37da2899SCharles.Forsyth 				return 0;
1283*37da2899SCharles.Forsyth 			if (modrm(ip, c) < 0)
1284*37da2899SCharles.Forsyth 				return 0;
1285*37da2899SCharles.Forsyth 			break;
1286*37da2899SCharles.Forsyth 		case RMOPB:	/* R/M field with op code (/digit) */
1287*37da2899SCharles.Forsyth 			if (igetc(ip, &c) < 0)
1288*37da2899SCharles.Forsyth 				return 0;
1289*37da2899SCharles.Forsyth 			if (modrm(ip, c) < 0)
1290*37da2899SCharles.Forsyth 				return 0;
1291*37da2899SCharles.Forsyth 			c = ip->reg;		/* secondary op code */
1292*37da2899SCharles.Forsyth 			obase = (Optable*)op->proto;
1293*37da2899SCharles.Forsyth 			ip->osize = 'B';
1294*37da2899SCharles.Forsyth 			goto newop;
1295*37da2899SCharles.Forsyth 		case RMOP:	/* R/M field with op code (/digit) */
1296*37da2899SCharles.Forsyth 			if (igetc(ip, &c) < 0)
1297*37da2899SCharles.Forsyth 				return 0;
1298*37da2899SCharles.Forsyth 			if (modrm(ip, c) < 0)
1299*37da2899SCharles.Forsyth 				return 0;
1300*37da2899SCharles.Forsyth 			c = ip->reg;
1301*37da2899SCharles.Forsyth 			obase = (Optable*)op->proto;
1302*37da2899SCharles.Forsyth 			goto newop;
1303*37da2899SCharles.Forsyth 		case FRMOP:	/* FP R/M field with op code (/digit) */
1304*37da2899SCharles.Forsyth 			if (igetc(ip, &c) < 0)
1305*37da2899SCharles.Forsyth 				return 0;
1306*37da2899SCharles.Forsyth 			if (modrm(ip, c) < 0)
1307*37da2899SCharles.Forsyth 				return 0;
1308*37da2899SCharles.Forsyth 			if ((c&0xc0) == 0xc0)
1309*37da2899SCharles.Forsyth 				c = ip->reg+8;		/* 16 entry table */
1310*37da2899SCharles.Forsyth 			else
1311*37da2899SCharles.Forsyth 				c = ip->reg;
1312*37da2899SCharles.Forsyth 			obase = (Optable*)op->proto;
1313*37da2899SCharles.Forsyth 			goto newop;
1314*37da2899SCharles.Forsyth 		case FRMEX:	/* Extended FP R/M field with op code (/digit) */
1315*37da2899SCharles.Forsyth 			if (igetc(ip, &c) < 0)
1316*37da2899SCharles.Forsyth 				return 0;
1317*37da2899SCharles.Forsyth 			if (modrm(ip, c) < 0)
1318*37da2899SCharles.Forsyth 				return 0;
1319*37da2899SCharles.Forsyth 			if ((c&0xc0) == 0xc0)
1320*37da2899SCharles.Forsyth 				c = (c&0x3f)+8;		/* 64-entry table */
1321*37da2899SCharles.Forsyth 			else
1322*37da2899SCharles.Forsyth 				c = ip->reg;
1323*37da2899SCharles.Forsyth 			obase = (Optable*)op->proto;
1324*37da2899SCharles.Forsyth 			goto newop;
1325*37da2899SCharles.Forsyth 		case RMR:	/* R/M register only (mod = 11) */
1326*37da2899SCharles.Forsyth 			if (igetc(ip, &c) < 0)
1327*37da2899SCharles.Forsyth 				return 0;
1328*37da2899SCharles.Forsyth 			if ((c&0xc0) != 0xc0) {
1329*37da2899SCharles.Forsyth 				kwerrstr("invalid R/M register: %x", c);
1330*37da2899SCharles.Forsyth 				return 0;
1331*37da2899SCharles.Forsyth 			}
1332*37da2899SCharles.Forsyth 			if (modrm(ip, c) < 0)
1333*37da2899SCharles.Forsyth 				return 0;
1334*37da2899SCharles.Forsyth 			break;
1335*37da2899SCharles.Forsyth 		case RMM:	/* R/M register only (mod = 11) */
1336*37da2899SCharles.Forsyth 			if (igetc(ip, &c) < 0)
1337*37da2899SCharles.Forsyth 				return 0;
1338*37da2899SCharles.Forsyth 			if ((c&0xc0) == 0xc0) {
1339*37da2899SCharles.Forsyth 				kwerrstr("invalid R/M memory mode: %x", c);
1340*37da2899SCharles.Forsyth 				return 0;
1341*37da2899SCharles.Forsyth 			}
1342*37da2899SCharles.Forsyth 			if (modrm(ip, c) < 0)
1343*37da2899SCharles.Forsyth 				return 0;
1344*37da2899SCharles.Forsyth 			break;
1345*37da2899SCharles.Forsyth 		case PTR:	/* Seg:Displacement addr (ptr16:16 or ptr16:32) */
1346*37da2899SCharles.Forsyth 			if (ip->osize == 'L') {
1347*37da2899SCharles.Forsyth 				if (igetl(ip, &ip->disp) < 0)
1348*37da2899SCharles.Forsyth 					return 0;
1349*37da2899SCharles.Forsyth 			} else {
1350*37da2899SCharles.Forsyth 				if (igets(ip, &s)< 0)
1351*37da2899SCharles.Forsyth 					return 0;
1352*37da2899SCharles.Forsyth 				ip->disp = s&0xffff;
1353*37da2899SCharles.Forsyth 			}
1354*37da2899SCharles.Forsyth 			if (igets(ip, (ushort*)&ip->seg) < 0)
1355*37da2899SCharles.Forsyth 				return 0;
1356*37da2899SCharles.Forsyth 			ip->jumptype = PTR;
1357*37da2899SCharles.Forsyth 			break;
1358*37da2899SCharles.Forsyth 		case AUX:	/* Multi-byte op code - Auxiliary table */
1359*37da2899SCharles.Forsyth 			obase = (Optable*)op->proto;
1360*37da2899SCharles.Forsyth 			if (igetc(ip, &c) < 0)
1361*37da2899SCharles.Forsyth 				return 0;
1362*37da2899SCharles.Forsyth 			goto newop;
1363*37da2899SCharles.Forsyth 		case PRE:	/* Instr Prefix */
1364*37da2899SCharles.Forsyth 			ip->prefix = (char*)op->proto;
1365*37da2899SCharles.Forsyth 			if (igetc(ip, &c) < 0)
1366*37da2899SCharles.Forsyth 				return 0;
1367*37da2899SCharles.Forsyth 			goto newop;
1368*37da2899SCharles.Forsyth 		case SEG:	/* Segment Prefix */
1369*37da2899SCharles.Forsyth 			ip->segment = (char*)op->proto;
1370*37da2899SCharles.Forsyth 			if (igetc(ip, &c) < 0)
1371*37da2899SCharles.Forsyth 				return 0;
1372*37da2899SCharles.Forsyth 			goto newop;
1373*37da2899SCharles.Forsyth 		case OPOVER:	/* Operand size override */
1374*37da2899SCharles.Forsyth 			ip->osize = 'W';
1375*37da2899SCharles.Forsyth 			if (igetc(ip, &c) < 0)
1376*37da2899SCharles.Forsyth 				return 0;
1377*37da2899SCharles.Forsyth 			goto newop;
1378*37da2899SCharles.Forsyth 		case ADDOVER:	/* Address size override */
1379*37da2899SCharles.Forsyth 			ip->asize = 0;
1380*37da2899SCharles.Forsyth 			if (igetc(ip, &c) < 0)
1381*37da2899SCharles.Forsyth 				return 0;
1382*37da2899SCharles.Forsyth 			goto newop;
1383*37da2899SCharles.Forsyth 		case JUMP:	/* mark instruction as JUMP or RET */
1384*37da2899SCharles.Forsyth 		case RET:
1385*37da2899SCharles.Forsyth 			ip->jumptype = op->operand[i];
1386*37da2899SCharles.Forsyth 			break;
1387*37da2899SCharles.Forsyth 		default:
1388*37da2899SCharles.Forsyth 			kwerrstr("bad operand type %d", op->operand[i]);
1389*37da2899SCharles.Forsyth 			return 0;
1390*37da2899SCharles.Forsyth 		}
1391*37da2899SCharles.Forsyth 	}
1392*37da2899SCharles.Forsyth 	return op;
1393*37da2899SCharles.Forsyth }
1394*37da2899SCharles.Forsyth 
1395*37da2899SCharles.Forsyth static void
bprint(Instr * ip,char * fmt,...)1396*37da2899SCharles.Forsyth bprint(Instr *ip, char *fmt, ...)
1397*37da2899SCharles.Forsyth {
1398*37da2899SCharles.Forsyth 	va_list arg;
1399*37da2899SCharles.Forsyth 
1400*37da2899SCharles.Forsyth 	va_start(arg, fmt);
1401*37da2899SCharles.Forsyth 	ip->curr = vseprint(ip->curr, ip->end, fmt, arg);
1402*37da2899SCharles.Forsyth 	va_end(arg);
1403*37da2899SCharles.Forsyth }
1404*37da2899SCharles.Forsyth 
1405*37da2899SCharles.Forsyth /*
1406*37da2899SCharles.Forsyth  *  if we want to call 16 bit regs AX,BX,CX,...
1407*37da2899SCharles.Forsyth  *  and 32 bit regs EAX,EBX,ECX,... then
1408*37da2899SCharles.Forsyth  *  change the defs of ANAME and ONAME to:
1409*37da2899SCharles.Forsyth  *  #define	ANAME(ip)	((ip->asize == 'E' ? "E" : "")
1410*37da2899SCharles.Forsyth  *  #define	ONAME(ip)	((ip)->osize == 'L' ? "E" : "")
1411*37da2899SCharles.Forsyth  */
1412*37da2899SCharles.Forsyth #define	ANAME(ip)	""
1413*37da2899SCharles.Forsyth #define	ONAME(ip)	""
1414*37da2899SCharles.Forsyth 
1415*37da2899SCharles.Forsyth static char *reg[] =  {
1416*37da2899SCharles.Forsyth 	"AX",
1417*37da2899SCharles.Forsyth 	"CX",
1418*37da2899SCharles.Forsyth 	"DX",
1419*37da2899SCharles.Forsyth 	"BX",
1420*37da2899SCharles.Forsyth 	"SP",
1421*37da2899SCharles.Forsyth 	"BP",
1422*37da2899SCharles.Forsyth 	"SI",
1423*37da2899SCharles.Forsyth 	"DI",
1424*37da2899SCharles.Forsyth };
1425*37da2899SCharles.Forsyth 
1426*37da2899SCharles.Forsyth static char *breg[] = { "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH" };
1427*37da2899SCharles.Forsyth static char *sreg[] = { "ES", "CS", "SS", "DS", "FS", "GS" };
1428*37da2899SCharles.Forsyth 
1429*37da2899SCharles.Forsyth static void
plocal(Instr * ip)1430*37da2899SCharles.Forsyth plocal(Instr *ip)
1431*37da2899SCharles.Forsyth {
1432*37da2899SCharles.Forsyth 	int offset;
1433*37da2899SCharles.Forsyth 
1434*37da2899SCharles.Forsyth 	offset = ip->disp;
1435*37da2899SCharles.Forsyth 
1436*37da2899SCharles.Forsyth 	bprint(ip, "%lux(SP)", offset);
1437*37da2899SCharles.Forsyth }
1438*37da2899SCharles.Forsyth 
1439*37da2899SCharles.Forsyth static void
pea(Instr * ip)1440*37da2899SCharles.Forsyth pea(Instr *ip)
1441*37da2899SCharles.Forsyth {
1442*37da2899SCharles.Forsyth 	if (ip->mod == 3) {
1443*37da2899SCharles.Forsyth 		if (ip->osize == 'B')
1444*37da2899SCharles.Forsyth 			bprint(ip, breg[ip->base]);
1445*37da2899SCharles.Forsyth 		else
1446*37da2899SCharles.Forsyth 			bprint(ip, "%s%s", ANAME(ip), reg[ip->base]);
1447*37da2899SCharles.Forsyth 		return;
1448*37da2899SCharles.Forsyth 	}
1449*37da2899SCharles.Forsyth 	if (ip->segment)
1450*37da2899SCharles.Forsyth 		bprint(ip, ip->segment);
1451*37da2899SCharles.Forsyth 	if (ip->asize == 'E' && ip->base == SP)
1452*37da2899SCharles.Forsyth 		plocal(ip);
1453*37da2899SCharles.Forsyth 	else {
1454*37da2899SCharles.Forsyth 		bprint(ip,"%lux", ip->disp);
1455*37da2899SCharles.Forsyth 		if (ip->base >= 0)
1456*37da2899SCharles.Forsyth 			bprint(ip,"(%s%s)", ANAME(ip), reg[ip->base]);
1457*37da2899SCharles.Forsyth 	}
1458*37da2899SCharles.Forsyth 	if (ip->index >= 0)
1459*37da2899SCharles.Forsyth 		bprint(ip,"(%s%s*%d)", ANAME(ip), reg[ip->index], 1<<ip->ss);
1460*37da2899SCharles.Forsyth }
1461*37da2899SCharles.Forsyth 
1462*37da2899SCharles.Forsyth static void
immediate(Instr * ip,long val)1463*37da2899SCharles.Forsyth immediate(Instr *ip, long val)
1464*37da2899SCharles.Forsyth {
1465*37da2899SCharles.Forsyth 	bprint(ip, "%lux", val);
1466*37da2899SCharles.Forsyth }
1467*37da2899SCharles.Forsyth 
1468*37da2899SCharles.Forsyth static void
prinstr(Instr * ip,char * fmt)1469*37da2899SCharles.Forsyth prinstr(Instr *ip, char *fmt)
1470*37da2899SCharles.Forsyth {
1471*37da2899SCharles.Forsyth 	if (ip->prefix)
1472*37da2899SCharles.Forsyth 		bprint(ip, "%s ", ip->prefix);
1473*37da2899SCharles.Forsyth 	for (; *fmt && ip->curr < ip->end; fmt++) {
1474*37da2899SCharles.Forsyth 		if (*fmt != '%')
1475*37da2899SCharles.Forsyth 			*ip->curr++ = *fmt;
1476*37da2899SCharles.Forsyth 		else switch(*++fmt)
1477*37da2899SCharles.Forsyth 		{
1478*37da2899SCharles.Forsyth 		case '%':
1479*37da2899SCharles.Forsyth 			*ip->curr++ = '%';
1480*37da2899SCharles.Forsyth 			break;
1481*37da2899SCharles.Forsyth 		case 'A':
1482*37da2899SCharles.Forsyth 			bprint(ip, "%s", ANAME(ip));
1483*37da2899SCharles.Forsyth 			break;
1484*37da2899SCharles.Forsyth 		case 'C':
1485*37da2899SCharles.Forsyth 			bprint(ip, "CR%d", ip->reg);
1486*37da2899SCharles.Forsyth 			break;
1487*37da2899SCharles.Forsyth 		case 'D':
1488*37da2899SCharles.Forsyth 			if (ip->reg < 4 || ip->reg == 6 || ip->reg == 7)
1489*37da2899SCharles.Forsyth 				bprint(ip, "DR%d",ip->reg);
1490*37da2899SCharles.Forsyth 			else
1491*37da2899SCharles.Forsyth 				bprint(ip, "???");
1492*37da2899SCharles.Forsyth 			break;
1493*37da2899SCharles.Forsyth 		case 'I':
1494*37da2899SCharles.Forsyth 			bprint(ip, "$");
1495*37da2899SCharles.Forsyth 			immediate(ip, ip->imm2);
1496*37da2899SCharles.Forsyth 			break;
1497*37da2899SCharles.Forsyth 		case 'O':
1498*37da2899SCharles.Forsyth 			bprint(ip,"%s", ONAME(ip));
1499*37da2899SCharles.Forsyth 			break;
1500*37da2899SCharles.Forsyth 		case 'i':
1501*37da2899SCharles.Forsyth 			bprint(ip, "$");
1502*37da2899SCharles.Forsyth 			immediate(ip,ip->imm);
1503*37da2899SCharles.Forsyth 			break;
1504*37da2899SCharles.Forsyth 		case 'R':
1505*37da2899SCharles.Forsyth 			bprint(ip, "%s%s", ONAME(ip), reg[ip->reg]);
1506*37da2899SCharles.Forsyth 			break;
1507*37da2899SCharles.Forsyth 		case 'S':
1508*37da2899SCharles.Forsyth 			bprint(ip, "%c", ip->osize);
1509*37da2899SCharles.Forsyth 			break;
1510*37da2899SCharles.Forsyth 		case 'T':
1511*37da2899SCharles.Forsyth 			if (ip->reg == 6 || ip->reg == 7)
1512*37da2899SCharles.Forsyth 				bprint(ip, "TR%d",ip->reg);
1513*37da2899SCharles.Forsyth 			else
1514*37da2899SCharles.Forsyth 				bprint(ip, "???");
1515*37da2899SCharles.Forsyth 			break;
1516*37da2899SCharles.Forsyth 		case 'X':
1517*37da2899SCharles.Forsyth 			if (ip->osize == 'L')
1518*37da2899SCharles.Forsyth 				bprint(ip,"CWDE");
1519*37da2899SCharles.Forsyth 			else
1520*37da2899SCharles.Forsyth 				bprint(ip, "CBW");
1521*37da2899SCharles.Forsyth 			break;
1522*37da2899SCharles.Forsyth 		case 'd':
1523*37da2899SCharles.Forsyth 			bprint(ip,"%lux:%lux",ip->seg,ip->disp);
1524*37da2899SCharles.Forsyth 			break;
1525*37da2899SCharles.Forsyth 		case 'e':
1526*37da2899SCharles.Forsyth 			pea(ip);
1527*37da2899SCharles.Forsyth 			break;
1528*37da2899SCharles.Forsyth 		case 'f':
1529*37da2899SCharles.Forsyth 			bprint(ip, "F%d", ip->base);
1530*37da2899SCharles.Forsyth 			break;
1531*37da2899SCharles.Forsyth 		case 'g':
1532*37da2899SCharles.Forsyth 			if (ip->reg < 6)
1533*37da2899SCharles.Forsyth 				bprint(ip,"%s",sreg[ip->reg]);
1534*37da2899SCharles.Forsyth 			else
1535*37da2899SCharles.Forsyth 				bprint(ip,"???");
1536*37da2899SCharles.Forsyth 			break;
1537*37da2899SCharles.Forsyth 		case 'p':
1538*37da2899SCharles.Forsyth 			immediate(ip, ip->imm+ip->addr+ip->n);
1539*37da2899SCharles.Forsyth 			break;
1540*37da2899SCharles.Forsyth 		case 'r':
1541*37da2899SCharles.Forsyth 			if (ip->osize == 'B')
1542*37da2899SCharles.Forsyth 				bprint(ip,"%s",breg[ip->reg]);
1543*37da2899SCharles.Forsyth 			else
1544*37da2899SCharles.Forsyth 				bprint(ip, reg[ip->reg]);
1545*37da2899SCharles.Forsyth 			break;
1546*37da2899SCharles.Forsyth 		case 'x':
1547*37da2899SCharles.Forsyth 			if (ip->osize == 'L')
1548*37da2899SCharles.Forsyth 				bprint(ip,"CDQ");
1549*37da2899SCharles.Forsyth 			else
1550*37da2899SCharles.Forsyth 				bprint(ip, "CWD");
1551*37da2899SCharles.Forsyth 			break;
1552*37da2899SCharles.Forsyth 		default:
1553*37da2899SCharles.Forsyth 			bprint(ip, "%%%c", *fmt);
1554*37da2899SCharles.Forsyth 			break;
1555*37da2899SCharles.Forsyth 		}
1556*37da2899SCharles.Forsyth 	}
1557*37da2899SCharles.Forsyth 	*ip->curr = 0;		/* there's always room for 1 byte */
1558*37da2899SCharles.Forsyth }
1559*37da2899SCharles.Forsyth 
1560*37da2899SCharles.Forsyth int
i386inst(ulong pc,char modifier,char * buf,int n)1561*37da2899SCharles.Forsyth i386inst(ulong pc, char modifier, char *buf, int n)
1562*37da2899SCharles.Forsyth {
1563*37da2899SCharles.Forsyth 	Instr	instr;
1564*37da2899SCharles.Forsyth 	Optable *op;
1565*37da2899SCharles.Forsyth 
1566*37da2899SCharles.Forsyth 	USED(modifier);
1567*37da2899SCharles.Forsyth 	op = mkinstr(&instr, pc);
1568*37da2899SCharles.Forsyth 	if (op == 0) {
1569*37da2899SCharles.Forsyth 		kgerrstr(buf, n);
1570*37da2899SCharles.Forsyth 		return -1;
1571*37da2899SCharles.Forsyth 	}
1572*37da2899SCharles.Forsyth 	instr.curr = buf;
1573*37da2899SCharles.Forsyth 	instr.end = buf+n-1;
1574*37da2899SCharles.Forsyth 	prinstr(&instr, op->proto);
1575*37da2899SCharles.Forsyth 	return instr.n;
1576*37da2899SCharles.Forsyth }
1577*37da2899SCharles.Forsyth 
1578*37da2899SCharles.Forsyth int
i386das(ulong pc,char * buf,int n)1579*37da2899SCharles.Forsyth i386das(ulong pc, char *buf, int n)
1580*37da2899SCharles.Forsyth {
1581*37da2899SCharles.Forsyth 	Instr	instr;
1582*37da2899SCharles.Forsyth 	int i;
1583*37da2899SCharles.Forsyth 
1584*37da2899SCharles.Forsyth 	if (mkinstr(&instr, pc) == 0) {
1585*37da2899SCharles.Forsyth 		kgerrstr(buf, n);
1586*37da2899SCharles.Forsyth 		return -1;
1587*37da2899SCharles.Forsyth 	}
1588*37da2899SCharles.Forsyth 	for(i = 0; i < instr.n && n > 2; i++) {
1589*37da2899SCharles.Forsyth 		_hexify(buf, instr.mem[i], 1);
1590*37da2899SCharles.Forsyth 		buf += 2;
1591*37da2899SCharles.Forsyth 		n -= 2;
1592*37da2899SCharles.Forsyth 	}
1593*37da2899SCharles.Forsyth 	*buf = 0;
1594*37da2899SCharles.Forsyth 	return instr.n;
1595*37da2899SCharles.Forsyth }
1596*37da2899SCharles.Forsyth 
1597*37da2899SCharles.Forsyth int
i386instlen(ulong pc)1598*37da2899SCharles.Forsyth i386instlen(ulong pc)
1599*37da2899SCharles.Forsyth {
1600*37da2899SCharles.Forsyth 	Instr i;
1601*37da2899SCharles.Forsyth 
1602*37da2899SCharles.Forsyth 	if (mkinstr(&i, pc))
1603*37da2899SCharles.Forsyth 		return i.n;
1604*37da2899SCharles.Forsyth 	return -1;
1605*37da2899SCharles.Forsyth }
1606*37da2899SCharles.Forsyth 
1607*37da2899SCharles.Forsyth void
das(uchar * x,int n)1608*37da2899SCharles.Forsyth das(uchar *x, int n)
1609*37da2899SCharles.Forsyth {
1610*37da2899SCharles.Forsyth 	int l, pc;
1611*37da2899SCharles.Forsyth 	char buf[128];
1612*37da2899SCharles.Forsyth /*
1613*37da2899SCharles.Forsyth 	int i;
1614*37da2899SCharles.Forsyth 	for(i = 0; i < n; i++)
1615*37da2899SCharles.Forsyth 		print("%.2ux", x[i]);
1616*37da2899SCharles.Forsyth 	print("\n");
1617*37da2899SCharles.Forsyth */
1618*37da2899SCharles.Forsyth 
1619*37da2899SCharles.Forsyth 	dasdata = x;
1620*37da2899SCharles.Forsyth 	pc = 0;
1621*37da2899SCharles.Forsyth 	while(n > 0) {
1622*37da2899SCharles.Forsyth 		i386das(pc, buf, sizeof(buf));
1623*37da2899SCharles.Forsyth 		print("%.8lux %2x %-20s ", (ulong)(dasdata+pc), pc, buf);
1624*37da2899SCharles.Forsyth 		l = i386inst(pc, 'i', buf, sizeof(buf));
1625*37da2899SCharles.Forsyth 		print("\t%s\n", buf);
1626*37da2899SCharles.Forsyth 
1627*37da2899SCharles.Forsyth 		pc += l;
1628*37da2899SCharles.Forsyth 		n -= l;
1629*37da2899SCharles.Forsyth 	}
1630*37da2899SCharles.Forsyth }
1631