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