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