x86dis.c - vx32 - Local 9vx git repository for patches.
(HTM) git clone git://r-36.net/vx32
(DIR) Log
(DIR) Files
(DIR) Refs
---
x86dis.c (37184B)
---
1 // X86 assembly library, adapted for use in VX32
2
3 #include "x86dis.h"
4 #include <string.h>
5 #include <stdio.h>
6
7 #define offsetof(S, x) (int)(&((S*)0)->x)
8 #define nelem(x) (sizeof(x)/sizeof((x)[0]))
9
10 typedef unsigned int uint;
11
12 enum
13 {
14 O_AAA = 1,
15 O_AAD,
16 O_AAM,
17 O_AAS,
18 O_ADC,
19 O_ADD,
20 O_ADDRSIZE,
21 O_AND,
22 O_ARPL,
23 O_BOUND,
24 O_BSF,
25 O_BSR,
26 O_BT,
27 O_BTC,
28 O_BTR,
29 O_BTS,
30 O_CBW,
31 O_CLC,
32 O_CLD,
33 O_CLI,
34 O_CLTS,
35 O_CMC,
36 O_CMP,
37 O_CMPS,
38 O_CMPXCHG,
39 O_CPUID,
40 O_CWD,
41 O_DAA,
42 O_DAS,
43 O_DATASIZE,
44 O_DEC,
45 O_DIV,
46 O_ENTER,
47 O_HALT,
48 O_IDIV,
49 O_IMUL,
50 O_IMUL2,
51 O_IMUL3,
52 O_IN,
53 O_INC,
54 O_INS,
55 O_INT,
56 O_IRET,
57 O_JA,
58 O_JC,
59 O_JCXZ,
60 O_JG,
61 O_JGE,
62 O_JL,
63 O_JLE,
64 O_JMP,
65 O_JMPF,
66 O_JNA,
67 O_JNC,
68 O_JNO,
69 O_JNP,
70 O_JNS,
71 O_JNZ,
72 O_JO,
73 O_JP,
74 O_JS,
75 O_JZ,
76 O_LAHF,
77 O_LAR,
78 O_LDS,
79 O_LEA,
80 O_LEAVE,
81 O_LES,
82 O_LFS,
83 O_LGDT,
84 O_LGS,
85 O_LIDT,
86 O_LLDT,
87 O_LMSW,
88 O_LOCK,
89 O_LODS,
90 O_LOOP,
91 O_LOOPNZ,
92 O_LOOPZ,
93 O_LSL,
94 O_LSS,
95 O_LTR,
96 O_MODRM,
97 O_MOV,
98 O_MOVS,
99 O_MOVSXB,
100 O_MOVSXW,
101 O_MOVZB,
102 O_MOVZW,
103 O_MUL,
104 O_NEG,
105 O_NEXTB,
106 O_NOP,
107 O_NOT,
108 O_OR,
109 O_OUT,
110 O_OUTS,
111 O_POP,
112 O_POPA,
113 O_POPF,
114 O_PUSH,
115 O_PUSHA,
116 O_PUSHF,
117 O_RCL,
118 O_RCR,
119 O_REP,
120 O_REPNE,
121 O_RET,
122 O_RETF,
123 O_ROL,
124 O_ROR,
125 O_SAHF,
126 O_SAR,
127 O_SBB,
128 O_SCAS,
129 O_SEGMENT,
130 O_SETA,
131 O_SETC,
132 O_SETG,
133 O_SETGE,
134 O_SETL,
135 O_SETLE,
136 O_SETNA,
137 O_SETNC,
138 O_SETNO,
139 O_SETNP,
140 O_SETNS,
141 O_SETNZ,
142 O_SETO,
143 O_SETP,
144 O_SETS,
145 O_SETZ,
146 O_SGDT,
147 O_SHL,
148 O_SHLD,
149 O_SHR,
150 O_SHRD,
151 O_SIDT,
152 O_SLDT,
153 O_SMSW,
154 O_STC,
155 O_STD,
156 O_STI,
157 O_STOS,
158 O_STR,
159 O_SUB,
160 O_TEST,
161 O_VERR,
162 O_VERW,
163 O_WAIT,
164 O_XCHG,
165 O_XOR,
166 O_CALL,
167 O_CALLF,
168 O_XLAT,
169
170 MAXO
171 };
172
173 enum
174 {
175 F_8 = 1,
176 F_16,
177 F_32,
178 F_1632,
179 F_0A,
180 F_X,
181 };
182
183 enum
184 {
185 A_0 = 5,
186 A_1 = 1,
187 A_3 = 3,
188 A_4 = 4,
189
190 A_AL = 8,
191 A_CL,
192 A_DL,
193 A_BL,
194 A_AH,
195 A_CH,
196 A_DH,
197 A_BH,
198
199 A_AX,
200 A_CX,
201 A_DX,
202 A_BX,
203 A_SP,
204 A_BP,
205 A_SI,
206 A_DI,
207
208 A_EAX,
209 A_ECX,
210 A_EDX,
211 A_EBX,
212 A_ESP,
213 A_EBP,
214 A_ESI,
215 A_EDI,
216
217 A_ES,
218 A_CS,
219 A_SS,
220 A_DS,
221 A_FS,
222 A_GS,
223
224 A_IMM8,
225 A_IMM16,
226 A_IMM32,
227
228 A_CR,
229 A_DR,
230 A_TR,
231 A_SR,
232
233 A_M,
234
235 A_MOFF8,
236 A_MOFF16,
237 A_MOFF32,
238
239 A_R8,
240 A_R16,
241 A_R32,
242
243 A_RM8,
244 A_RM16,
245 A_RM32,
246 A_RM32R,
247
248 A_REL8,
249 A_REL16,
250 A_REL32,
251 A_IMM1616,
252 A_IMM1632,
253
254 MAXA
255 };
256
257 enum
258 {
259 D_LOCK = 1<<0,
260 D_REP = 1<<1,
261 D_REPN = 1<<2,
262 D_ES = 1<<3,
263 D_CS = 1<<4,
264 D_SS = 1<<5,
265 D_DS = 1<<6,
266 D_FS = 1<<7,
267 D_GS = 1<<8,
268 D_ADDR32 = 1<<9,
269 D_DATA8 = 1<<10,
270 D_DATA16 = 1<<11,
271 D_DATA32 = 1<<12,
272 D_STACK32 = 1<<13,
273 };
274
275 enum
276 {
277 DA_NONE,
278 DA_REG8,
279 DA_REG16,
280 DA_REG32,
281 DA_IMM,
282 DA_MEM,
283 DA_SEGMEM,
284 DA_IND16,
285 DA_IND32,
286 DA_SIB,
287 DA_SIBX,
288 DA_SEG16,
289 DA_REL,
290 };
291
292 // String tables
293
294 static char *opnames[MAXO][3] =
295 {
296 { "xxx" },
297 [O_AAA] { "aaa" },
298 [O_AAD] { "aad" },
299 [O_AAM] { "aam" },
300 [O_AAS] { "aas" },
301 [O_ADC] { "adcb", "adcw", "adcl" },
302 [O_ADD] { "addb", "addw", "addl" },
303 [O_ADDRSIZE] { "addrsize" },
304 [O_AND] { "andb", "andw", "andl" },
305 [O_ARPL] { "arpl" },
306 [O_BOUND] { 0, "boundw", "boundl" },
307 [O_BSF] { 0, "bsfw", "bsfl" },
308 [O_BSR] { 0, "bsrw", "bsrl" },
309 [O_BT] { 0, "btw", "btl" },
310 [O_BTC] { 0, "btcw", "btcl" },
311 [O_BTR] { 0, "btrw", "btrl" },
312 [O_BTS] { 0, "btsw", "btsl" },
313 [O_CALL] { 0, "call", "call" },
314 [O_CBW] { 0, "cbw", "cwde" },
315 [O_CLC] { "clc" },
316 [O_CLD] { "cld" },
317 [O_CLI] { "cli" },
318 [O_CLTS] { "clts" },
319 [O_CMC] { "cmc" },
320 [O_CMP] { "cmpb", "cmpw", "cmpl" },
321 [O_CMPS] { "cmpsb", "cmpsw", "cmpsl" },
322 [O_CMPXCHG] { "cmpxchgb", "cmpxchgw", "cmpxchgl" },
323 [O_CPUID] { "cpuid" },
324 [O_CWD] { 0, "cwd", "cdq" },
325 [O_DAA] { "daa" },
326 [O_DAS] { "das" },
327 [O_DATASIZE] { "datasize" },
328 [O_DEC] { "decb", "decw", "decl" },
329 [O_DIV] { "divb", "divw", "divl" },
330 [O_ENTER] { "enter" },
331 [O_HALT] { "halt" },
332 [O_IDIV] { "idivb", "idivw", "idivl" },
333 [O_IMUL] { "imulb", "imulw", "imull" },
334 [O_IMUL2] { "imulb", "imulw", "imull" },
335 [O_IMUL3] { "imulb", "imulw", "imull" },
336 [O_IN] { "inb", "inw", "inl" },
337 [O_INC] { "incb", "incw", "incl" },
338 [O_INS] { "insb", "insw", "insl" },
339 [O_INT] { "int" },
340 [O_IRET] { 0, "iret", "iretd" },
341 [O_JA] { "ja", "ja", "ja" },
342 [O_JC] { "jc", "jc", "jc" },
343 [O_JCXZ] { "jcxz", "jcxz", "jcxz" },
344 [O_JG] { "jg", "jg", "jg" },
345 [O_JGE] { "jge", "jge", "jge" },
346 [O_JL] { "jl", "jl", "jl" },
347 [O_JLE] { "jle", "jle", "jle" },
348 [O_JMP] { "jmp", "jmp", "jmp" },
349 [O_JMPF] { "ljmp", "ljmp", "ljmp" },
350 [O_JNA] { "jna", "jna", "jna" },
351 [O_JNC] { "jnc", "jnc", "jnc" },
352 [O_JNO] { "jno", "jno", "jno" },
353 [O_JNP] { "jnp", "jnp", "jnp" },
354 [O_JNS] { "jns", "jns", "jns" },
355 [O_JNZ] { "jnz", "jnz", "jnz" },
356 [O_JO] { "jo", "jo", "jo" },
357 [O_JP] { "jp", "jp", "jp" },
358 [O_JS] { "js", "js", "js" },
359 [O_JZ] { "jz", "jz", "jz" },
360 [O_LAHF] { "lahf" },
361 [O_LAR] { 0, "larw", "larl" },
362 [O_LEA] { 0, "leaw", "leal" },
363 [O_LEAVE] { 0, "leavew", "leavel" },
364 [O_LGDT] { "lgdt", },
365 [O_LDS] { 0, "ldsw", "ldsl" },
366 [O_LES] { 0, "lesw", "lesl" },
367 [O_LFS] { 0, "lfsw", "lfsl" },
368 [O_LGS] { 0, "lgsw", "lgsl" },
369 [O_LSS] { 0, "lssw", "lssl" },
370 [O_LIDT] { "lidt" },
371 [O_LLDT] { "lldt" },
372 [O_LMSW] { 0, "lmsw" },
373 [O_LOCK] { "*LOCK*" },
374 [O_LODS] { "lodsb", "lodsw", "lodsl" },
375 [O_LOOP] { "loop" },
376 [O_LOOPNZ] { "loopnz" },
377 [O_LOOPZ] { "loopz" },
378 [O_LSL] { 0, "lslw", "lsll" },
379 [O_LTR] { 0, "ltr", 0 },
380 [O_MODRM] { "*MODRM*" },
381 [O_MOV] { "movb", "movw", "movl" },
382 [O_MOVS] { "movsb", "movsw", "movsl" },
383 [O_MOVSXB] { 0, "movsxb", "movsxb" },
384 [O_MOVSXW] { 0, 0, "movsxw" },
385 [O_MOVZB] { 0, "movzb", "movzb" },
386 [O_MOVZW] { 0, 0, "movzw" },
387 [O_MUL] { "mulb", "mulw", "mull" },
388 [O_NEG] { "negb", "negw", "negl" },
389 [O_NEXTB] { "*NEXTB*" },
390 [O_NOP] { "nop" },
391 [O_NOT] { "notb", "notw", "notl" },
392 [O_OR] { "orb", "orw", "orl" },
393 [O_OUT] { "outb", "outw", "outl" },
394 [O_OUTS] { "outsb", "outsw", "outsl" },
395 [O_POP] { 0, "popw", "popl" },
396 [O_POPA] { 0, "popaw", "popal" },
397 [O_POPF] { 0, "popfw", "popfl" },
398 [O_PUSH] { 0, "pushw", "pushl" },
399 [O_PUSHA] { 0, "pushaw", "pushal" },
400 [O_PUSHF] { 0, "pushfw", "pushfl" },
401 [O_RCL] { "rclb", "rclw", "rcll" },
402 [O_RCR] { "rcrb", "rcrw", "rcrl" },
403 [O_REP] { "rep" },
404 [O_REPNE] { "repne" },
405 [O_RET] { "ret", "ret", "ret" },
406 [O_RETF] { "retf", "retf", "retf" },
407 [O_ROL] { "rolb", "rolw", "roll" },
408 [O_ROR] { "rorb", "rorw", "rorl" },
409 [O_SAHF] { "sahf" },
410 [O_SAR] { "sarb", "sarw", "sarl" },
411 [O_SBB] { "sbbb", "sbbw", "sbbl" },
412 [O_SCAS] { "scasb", "scasw", "scasl" },
413 [O_SEGMENT] { "*SEGMENT*" },
414 [O_SETA] { "seta" },
415 [O_SETC] { "setc" },
416 [O_SETG] { "setg" },
417 [O_SETGE] { "setge" },
418 [O_SETL] { "setl" },
419 [O_SETLE] { "setle" },
420 [O_SETNA] { "setna" },
421 [O_SETNC] { "setnc" },
422 [O_SETNO] { "setno" },
423 [O_SETNP] { "setnp" },
424 [O_SETNS] { "setns" },
425 [O_SETNZ] { "setnz" },
426 [O_SETO] { "seto" },
427 [O_SETP] { "setp" },
428 [O_SETS] { "sets" },
429 [O_SETZ] { "setz" },
430 [O_SGDT] { "sgdt" },
431 [O_SHL] { "shlb", "shlw", "shll" },
432 [O_SHLD] { 0, "shldw", "shldl" },
433 [O_SHR] { "shrb", "shrw", "shrl" },
434 [O_SHRD] { 0, "shrdw", "shrdl" },
435 [O_SIDT] { "sidt" },
436 [O_SLDT] { "sldt" },
437 [O_SMSW] { 0, "smsw" },
438 [O_STC] { "stc" },
439 [O_STD] { "std" },
440 [O_STI] { "sti" },
441 [O_STOS] { "stosb", "stosw", "stosl" },
442 [O_STR] { 0, "str" },
443 [O_SUB] { "subb", "subw", "subl" },
444 [O_TEST] { "testb", "testw", "testl" },
445 [O_VERR] { 0, "verr" },
446 [O_VERW] { 0, "verw" },
447 [O_WAIT] { "wait" },
448 [O_XCHG] { "xchgb", "xchgw", "xchgl" },
449 [O_XOR] { "xorb", "xorw", "xorl" },
450 [O_XLAT] { "xlat" },
451 };
452
453 static struct {
454 int f;
455 char *s;
456 } prefixes[] = {
457 D_LOCK, "lock",
458 D_REP, "rep",
459 D_REPN, "repn",
460 D_CS, "cs:",
461 D_DS, "ds:",
462 D_ES, "es:",
463 D_FS, "fs:",
464 D_GS, "gs:",
465 D_SS, "ss:",
466 };
467
468 static char *reg8[] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" };
469 static char *reg16[] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" };
470 static char *reg32[] = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
471 "eip", "eflags",
472 "cr0", "cr2", "cr3",
473 "dr0", "dr1", "dr2", "dr3", "dr6", "dr7",
474 "tr6", "tr7" };
475 static char *seg[] = { "cs", "ds", "es", "fs", "gs", "ss" };
476
477 // Register Ids
478
479 #define EAX 0
480 #define ECX 4
481 #define EDX 8
482 #define EBX 12
483 #define ESP 16
484 #define EBP 20
485 #define ESI 24
486 #define EDI 28
487 #define EIP 32
488 #define EFLAGS 36
489 #define CR0 40
490 #define CR2 44
491 #define CR3 48
492 #define DR0 52
493 #define DR1 56
494 #define DR2 60
495 #define DR3 64
496 #define DR6 68
497 #define DR7 72
498 #define TR6 76
499 #define TR7 80
500
501 #define CS 100
502 #define DS 101
503 #define ES 102
504 #define FS 103
505 #define GS 104
506 #define SS 105
507 // Instruction decoding tables.
508
509 static xinst inst0F00[] =
510 {
511 /*/0*/ { O_SLDT, F_16, A_RM16, },
512 { O_STR, F_16, A_RM16, },
513 { O_LLDT, F_16, A_RM16, },
514 { O_LTR, F_16, A_RM16, },
515 { O_VERR, F_16, A_RM16, },
516 { O_VERW, F_16, A_RM16, },
517 { -1 },
518 { -1 },
519 };
520
521 static xinst inst0F01[] =
522 {
523 { O_SGDT, F_X, A_M, },
524 { O_SIDT, F_X, A_M, },
525 { O_LGDT, F_X, A_M, },
526 { O_LIDT, F_X, A_M, },
527 { O_SMSW, F_16, A_RM16, },
528 { -1 },
529 { O_LMSW, F_16, A_RM16, },
530 { -1 },
531 };
532
533 static xinst inst0FBA[] =
534 {
535 { -1 },
536 { -1 },
537 { -1 },
538 { -1 },
539 { O_BT, F_1632, A_RM16, A_IMM8 },
540 { O_BTS, F_1632, A_RM16, A_IMM8 },
541 { O_BTR, F_1632, A_RM16, A_IMM8 },
542 { O_BTC, F_1632, A_RM16, A_IMM8 },
543 };
544
545 static xinst inst0F[] =
546 {
547 /*00*/ { O_MODRM, 0, 0, 0, 0, inst0F00 },
548 { O_MODRM, 0, 0, 0, 0, inst0F01 },
549 { O_LAR, F_1632, A_R16, A_RM16, },
550 { O_LSL, F_1632, A_R16, A_RM16, },
551 { -1 },
552 { -1 },
553 { O_CLTS, F_X, 0, 0, },
554 { -1 },
555 /*08*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
556 /*10*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
557 /*18*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
558 /*20*/ { O_MOV, F_32, A_RM32R, A_CR },
559 { O_MOV, F_32, A_RM32R, A_DR },
560 { O_MOV, F_32, A_CR, A_RM32R },
561 { O_MOV, F_32, A_DR, A_RM32R },
562 { O_MOV, F_32, A_RM32R, A_TR },
563 { -1 },
564 { O_MOV, F_32, A_TR, A_RM32R },
565 { -1 },
566 /*28*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
567 /*30*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
568 /*38*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
569 /*40*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
570 /*48*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
571 /*50*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
572 /*58*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
573 /*60*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
574 /*68*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
575 /*70*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
576 /*78*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
577 /*80*/ { O_JO, F_1632, A_REL16, },
578 { O_JNO, F_1632, A_REL16, },
579 { O_JC, F_1632, A_REL16, },
580 { O_JNC, F_1632, A_REL16, },
581 { O_JZ, F_1632, A_REL16, },
582 { O_JNZ, F_1632, A_REL16, },
583 { O_JNA, F_1632, A_REL16, },
584 { O_JA, F_1632, A_REL16, },
585 /*88*/ { O_JS, F_1632, A_REL16, },
586 { O_JNS, F_1632, A_REL16, },
587 { O_JP, F_1632, A_REL16, },
588 { O_JNP, F_1632, A_REL16, },
589 { O_JL, F_1632, A_REL16, },
590 { O_JGE, F_1632, A_REL16, },
591 { O_JLE, F_1632, A_REL16, },
592 { O_JG, F_1632, A_REL16, },
593 /*90*/ { O_SETO, F_8, A_RM8, },
594 { O_SETNO, F_8, A_RM8, },
595 { O_SETC, F_8, A_RM8, },
596 { O_SETNC, F_8, A_RM8, },
597 { O_SETZ, F_8, A_RM8, },
598 { O_SETNZ, F_8, A_RM8, },
599 { O_SETNA, F_8, A_RM8, },
600 { O_SETA, F_8, A_RM8, },
601 /*98*/ { O_SETS, F_8, A_RM8, },
602 { O_SETNS, F_8, A_RM8, },
603 { O_SETP, F_8, A_RM8, },
604 { O_SETNP, F_8, A_RM8, },
605 { O_SETL, F_8, A_RM8, },
606 { O_SETGE, F_8, A_RM8, },
607 { O_SETLE, F_8, A_RM8, },
608 { O_SETG, F_8, A_RM8, },
609 /*A0*/ { O_PUSH, 0, A_FS, },
610 { O_POP, 0, A_FS, },
611 { O_CPUID, F_X, 0, 0 },
612 { O_BT, F_1632, A_RM16, A_R16 },
613 { O_SHLD, F_1632, A_RM16, A_R16, A_IMM8 },
614 { O_SHLD, F_1632, A_RM16, A_R16, A_CL },
615 { -1 },
616 { -1 },
617 /*A8*/ { O_PUSH, 0, A_GS, },
618 { O_POP, 0, A_GS, },
619 { -1 },
620 { O_BTS, F_1632, A_RM16, A_R16 },
621 { O_SHRD, F_1632, A_RM16, A_R16, A_IMM8 },
622 { O_SHRD, F_1632, A_RM16, A_R16, A_CL },
623 { -1 },
624 { O_IMUL2, F_1632, A_R16, A_RM16 },
625 /*B0*/ { O_CMPXCHG, F_8, A_AL, A_RM8, A_R8 },
626 { O_CMPXCHG, F_1632, A_AX, A_RM16, A_R16 },
627 { O_LSS, F_1632, A_R16, A_M },
628 { O_BTR, F_1632, A_RM16, A_R16 },
629 { O_LFS, F_1632, A_R16, A_M },
630 { O_LGS, F_1632, A_R16, A_M },
631 { O_MOVZB, F_1632, A_R16, A_RM8 },
632 { O_MOVZW, F_32, A_R32, A_RM16 },
633 /*B8*/ { -1 },
634 { -1 },
635 { O_MODRM, 0, 0, 0, 0, inst0FBA },
636 { O_BTC, F_1632, A_RM16, A_R16 },
637 { O_BSF, F_1632, A_R16, A_RM16 },
638 { O_BSR, F_1632, A_R16, A_RM16 },
639 { O_MOVSXB, F_1632, A_R16, A_RM8 },
640 { O_MOVSXW, F_32, A_R32, A_RM16 },
641 /*C0*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
642 /*C8*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
643 /*D0*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
644 /*D8*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
645 /*E0*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
646 /*E8*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
647 /*F0*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
648 /*F8*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
649 };
650
651 static xinst inst80[] =
652 {
653 { O_ADD, F_8, A_RM8, A_IMM8 },
654 { O_OR, F_8, A_RM8, A_IMM8 },
655 { O_ADC, F_8, A_RM8, A_IMM8 },
656 { O_SBB, F_8, A_RM8, A_IMM8 },
657 { O_AND, F_8, A_RM8, A_IMM8 },
658 { O_SUB, F_8, A_RM8, A_IMM8 },
659 { O_XOR, F_8, A_RM8, A_IMM8 },
660 { O_CMP, F_8, A_RM8, A_IMM8 },
661 };
662
663 static xinst inst81[] =
664 {
665 { O_ADD, F_1632, A_RM16, A_IMM16 },
666 { O_OR, F_1632, A_RM16, A_IMM16 },
667 { O_ADC, F_1632, A_RM16, A_IMM16 },
668 { O_SBB, F_1632, A_RM16, A_IMM16 },
669 { O_AND, F_1632, A_RM16, A_IMM16 },
670 { O_SUB, F_1632, A_RM16, A_IMM16 },
671 { O_XOR, F_1632, A_RM16, A_IMM16 },
672 { O_CMP, F_1632, A_RM16, A_IMM16 },
673 };
674
675 static xinst inst83[] =
676 {
677 { O_ADD, F_1632, A_RM16, A_IMM8 },
678 { O_OR, F_1632, A_RM16, A_IMM8 },
679 { O_ADC, F_1632, A_RM16, A_IMM8 },
680 { O_SBB, F_1632, A_RM16, A_IMM8 },
681 { O_AND, F_1632, A_RM16, A_IMM8 },
682 { O_SUB, F_1632, A_RM16, A_IMM8 },
683 { O_XOR, F_1632, A_RM16, A_IMM8 },
684 { O_CMP, F_1632, A_RM16, A_IMM8 },
685 };
686
687 static xinst inst8F[] =
688 {
689 { O_POP, F_1632, A_M, 0, },
690 { -1 },
691 { -1 },
692 { -1 },
693 { -1 },
694 { -1 },
695 { -1 },
696 { -1 },
697 };
698
699 static xinst instC0[] =
700 {
701 { O_ROL, F_8, A_RM8, A_IMM8, },
702 { O_ROR, F_8, A_RM8, A_IMM8, },
703 { O_RCL, F_8, A_RM8, A_IMM8, },
704 { O_RCR, F_8, A_RM8, A_IMM8, },
705 { O_SHL, F_8, A_RM8, A_IMM8, },
706 { O_SHR, F_8, A_RM8, A_IMM8, },
707 { -1, },
708 { O_SAR, F_8, A_RM8, A_IMM8, },
709 };
710
711 static xinst instC1[] =
712 {
713 { O_ROL, F_1632, A_RM16, A_IMM8, },
714 { O_ROR, F_1632, A_RM16, A_IMM8, },
715 { O_RCL, F_1632, A_RM16, A_IMM8, },
716 { O_RCR, F_1632, A_RM16, A_IMM8, },
717 { O_SHL, F_1632, A_RM16, A_IMM8, },
718 { O_SHR, F_1632, A_RM16, A_IMM8, },
719 { -1, },
720 { O_SAR, F_1632, A_RM16, A_IMM8, },
721 };
722
723 static xinst instD0[] =
724 {
725 { O_ROL, F_8, A_RM8, A_1, },
726 { O_ROR, F_8, A_RM8, A_1, },
727 { O_RCL, F_8, A_RM8, A_1, },
728 { O_RCR, F_8, A_RM8, A_1, },
729 { O_SHL, F_8, A_RM8, A_1, },
730 { O_SHR, F_8, A_RM8, A_1, },
731 { -1, },
732 { O_SAR, F_8, A_RM8, A_1, },
733 };
734
735 static xinst instD1[] =
736 {
737 { O_ROL, F_1632, A_RM16, A_1, },
738 { O_ROR, F_1632, A_RM16, A_1, },
739 { O_RCL, F_1632, A_RM16, A_1, },
740 { O_RCR, F_1632, A_RM16, A_1, },
741 { O_SHL, F_1632, A_RM16, A_1, },
742 { O_SHR, F_1632, A_RM16, A_1, },
743 { -1, },
744 { O_SAR, F_1632, A_RM16, A_1, },
745 };
746
747 static xinst instD2[] =
748 {
749 { O_ROL, F_8, A_RM8, A_CL, },
750 { O_ROR, F_8, A_RM8, A_CL, },
751 { O_RCL, F_8, A_RM8, A_CL, },
752 { O_RCR, F_8, A_RM8, A_CL, },
753 { O_SHL, F_8, A_RM8, A_CL, },
754 { O_SHR, F_8, A_RM8, A_CL, },
755 { -1, },
756 { O_SAR, F_8, A_RM8, A_CL, },
757 };
758
759 static xinst instD3[] =
760 {
761 { O_ROL, F_1632, A_RM16, A_CL, },
762 { O_ROR, F_1632, A_RM16, A_CL, },
763 { O_RCL, F_1632, A_RM16, A_CL, },
764 { O_RCR, F_1632, A_RM16, A_CL, },
765 { O_SHL, F_1632, A_RM16, A_CL, },
766 { O_SHR, F_1632, A_RM16, A_CL, },
767 { -1, },
768 { O_SAR, F_1632, A_RM16, A_CL, },
769 };
770
771 static xinst instF6[] =
772 {
773 { O_TEST, F_8, A_RM8, A_IMM8, },
774 { -1 },
775 { O_NOT, F_8, A_RM8, 0, },
776 { O_NEG, F_8, A_RM8, 0, },
777 { O_MUL, F_8, A_AL, A_RM8, },
778 { O_IMUL, F_8, A_RM8, },
779 { O_DIV, F_8, A_AX, A_RM8, },
780 { O_IDIV, F_8, A_AX, A_RM8, },
781 };
782 static xinst instF7[] =
783 {
784 { O_TEST, F_1632, A_RM16, A_IMM16, },
785 { -1 },
786 { O_NOT, F_1632, A_RM16, 0, },
787 { O_NEG, F_1632, A_RM16, 0, },
788 { O_MUL, F_1632, A_AX, A_RM16, },
789 { O_IMUL, F_1632, A_RM16, },
790 { O_DIV, F_1632, A_RM16, },
791 { O_IDIV, F_1632, A_RM16, },
792 };
793
794 static xinst instFE[] =
795 {
796 { O_INC, F_8, A_RM8, 0, },
797 { O_DEC, F_8, A_RM8, 0, },
798 { -1 },
799 { -1 },
800 { -1 },
801 { -1 },
802 { -1 },
803 { -1 },
804 { -1 },
805 { -1 },
806 };
807
808 static xinst instFF[] =
809 {
810 { O_INC, F_1632, A_RM16, 0, },
811 { O_DEC, F_1632, A_RM16, 0, },
812 { O_CALL, F_1632, A_RM16, 0, },
813 { O_CALLF, F_1632, A_M, 0, }, // INDIRECT
814 { O_JMP, F_1632, A_RM16, 0, },
815 { O_JMPF, F_1632, A_M, 0, }, // INDIRECT
816 { O_PUSH, F_1632, A_M, 0, },
817 { -1 },
818 };
819
820 xinst inst[] =
821 {
822 /*00*/ { O_ADD, F_8, A_RM8, A_R8 },
823 { O_ADD, F_1632, A_RM16, A_R16 },
824 { O_ADD, F_8, A_R8, A_RM8 },
825 { O_ADD, F_1632, A_R16, A_RM16 },
826 { O_ADD, F_8, A_AL, A_IMM8 },
827 { O_ADD, F_1632, A_AX, A_IMM16 },
828 { O_PUSH, 0, A_ES, },
829 { O_POP, 0, A_ES, },
830 /*08*/ { O_OR, F_8, A_RM8, A_R8 },
831 { O_OR, F_1632, A_RM16, A_R16 },
832 { O_OR, F_8, A_R8, A_RM8 },
833 { O_OR, F_1632, A_R16, A_RM16 },
834 { O_OR, F_8, A_AL, A_IMM8 },
835 { O_OR, F_1632, A_AX, A_IMM16 },
836 { O_PUSH, 0, A_CS, },
837 { O_NEXTB, 0, 0, 0, 0, inst0F },
838 /*10*/ { O_ADC, F_8, A_RM8, A_R8 },
839 { O_ADC, F_1632, A_RM16, A_R16 },
840 { O_ADC, F_8, A_R8, A_RM8 },
841 { O_ADC, F_1632, A_R16, A_RM16 },
842 { O_ADC, F_8, A_AL, A_IMM8 },
843 { O_ADC, F_1632, A_AX, A_IMM16 },
844 { O_PUSH, 0, A_SS, },
845 { O_POP, 0, A_SS, },
846 /*18*/ { O_SBB, F_8, A_RM8, A_R8 },
847 { O_SBB, F_1632, A_RM16, A_R16 },
848 { O_SBB, F_8, A_R8, A_RM8 },
849 { O_SBB, F_1632, A_R16, A_RM16 },
850 { O_SBB, F_8, A_AL, A_IMM8 },
851 { O_SBB, F_1632, A_AX, A_IMM16 },
852 { O_PUSH, F_1632, A_DS, 0, },
853 { O_POP, F_1632, A_DS, 0, },
854 /*20*/ { O_AND, F_8, A_RM8, A_R8 },
855 { O_AND, F_1632, A_RM16, A_R16 },
856 { O_AND, F_8, A_R8, A_RM8 },
857 { O_AND, F_1632, A_R16, A_RM16 },
858 { O_AND, F_8, A_AL, A_IMM8 },
859 { O_AND, F_1632, A_AX, A_IMM16 },
860 { O_SEGMENT, 0, A_ES, 0, },
861 { O_DAA, F_X, 0, 0, },
862 /*28*/ { O_SUB, F_8, A_RM8, A_R8 },
863 { O_SUB, F_1632, A_RM16, A_R16 },
864 { O_SUB, F_8, A_R8, A_RM8 },
865 { O_SUB, F_1632, A_R16, A_RM16 },
866 { O_SUB, F_8, A_AL, A_IMM8 },
867 { O_SUB, F_1632, A_AX, A_IMM16 },
868 { O_SEGMENT, 0, A_CS, 0, },
869 { O_DAS, F_X, 0, 0, },
870 /*30*/ { O_XOR, F_8, A_RM8, A_R8 },
871 { O_XOR, F_1632, A_RM16, A_R16 },
872 { O_XOR, F_8, A_R8, A_RM8 },
873 { O_XOR, F_1632, A_R16, A_RM16 },
874 { O_XOR, F_8, A_AL, A_IMM8 },
875 { O_XOR, F_1632, A_AX, A_IMM16 },
876 { O_SEGMENT, 0, A_SS, 0, },
877 { O_AAA, F_X, 0, 0, },
878 /*38*/ { O_CMP, F_8, A_RM8, A_R8 },
879 { O_CMP, F_1632, A_RM16, A_R16 },
880 { O_CMP, F_8, A_R8, A_RM8 },
881 { O_CMP, F_1632, A_R16, A_RM16 },
882 { O_CMP, F_8, A_AL, A_IMM8 },
883 { O_CMP, F_1632, A_AX, A_IMM16 },
884 { O_SEGMENT, 0, A_DS, 0, },
885 { O_AAS, F_X, 0, 0, },
886 /*40*/ { O_INC, F_1632, A_AX, 0, }, // +r
887 { O_INC, F_1632, A_CX, 0, },
888 { O_INC, F_1632, A_DX, 0, },
889 { O_INC, F_1632, A_BX, 0, },
890 { O_INC, F_1632, A_SP, 0, },
891 { O_INC, F_1632, A_BP, 0, },
892 { O_INC, F_1632, A_SI, 0, },
893 { O_INC, F_1632, A_DI, 0, },
894 /*48*/ { O_DEC, F_1632, A_AX, 0, }, // +r
895 { O_DEC, F_1632, A_CX, 0, },
896 { O_DEC, F_1632, A_DX, 0, },
897 { O_DEC, F_1632, A_BX, 0, },
898 { O_DEC, F_1632, A_SP, 0, },
899 { O_DEC, F_1632, A_BP, 0, },
900 { O_DEC, F_1632, A_SI, 0, },
901 { O_DEC, F_1632, A_DI, 0, },
902 /*50*/ { O_PUSH, F_1632, A_AX, 0, }, // +r
903 { O_PUSH, F_1632, A_CX, 0, },
904 { O_PUSH, F_1632, A_DX, 0, },
905 { O_PUSH, F_1632, A_BX, 0, },
906 { O_PUSH, F_1632, A_SP, 0, },
907 { O_PUSH, F_1632, A_BP, 0, },
908 { O_PUSH, F_1632, A_SI, 0, },
909 { O_PUSH, F_1632, A_DI, 0, },
910 /*58*/ { O_POP, F_1632, A_AX, 0, }, // +r
911 { O_POP, F_1632, A_CX, 0, },
912 { O_POP, F_1632, A_DX, 0, },
913 { O_POP, F_1632, A_BX, 0, },
914 { O_POP, F_1632, A_SP, 0, },
915 { O_POP, F_1632, A_BP, 0, },
916 { O_POP, F_1632, A_SI, 0, },
917 { O_POP, F_1632, A_DI, 0, },
918 /*60*/ { O_PUSHA, F_1632, 0, 0, },
919 { O_POPA, F_1632, 0, 0, },
920 { O_BOUND, F_1632, A_R16, A_M, },
921 { O_ARPL, F_X, A_RM16, A_R16, },
922 { O_SEGMENT, 0, A_FS, 0, },
923 { O_SEGMENT, 0, A_GS, 0, },
924 { O_DATASIZE, 0, 0, 0, },
925 { O_ADDRSIZE, 0, 0, 0, },
926 /*68*/ { O_PUSH, F_1632, A_IMM16, 0, },
927 { O_IMUL3, F_1632, A_R16, A_RM16, A_IMM16 },
928 { O_PUSH, F_1632, A_IMM8, 0, },
929 { O_IMUL3, F_1632, A_R16, A_RM16, A_IMM8 },
930 { O_INS, F_8, 0, 0 },
931 { O_INS, F_1632, 0, 0, },
932 { O_OUTS, F_8, 0, 0, },
933 { O_OUTS, F_1632, 0, 0, },
934 /*70*/ { O_JO, F_8, A_REL8, },
935 { O_JNO, F_8, A_REL8, },
936 { O_JC, F_8, A_REL8, },
937 { O_JNC, F_8, A_REL8, },
938 { O_JZ, F_8, A_REL8, },
939 { O_JNZ, F_8, A_REL8, },
940 { O_JNA, F_8, A_REL8, },
941 { O_JA, F_8, A_REL8, },
942 /*78*/ { O_JS, F_8, A_REL8, },
943 { O_JNS, F_8, A_REL8, },
944 { O_JP, F_8, A_REL8, },
945 { O_JNP, F_8, A_REL8, },
946 { O_JL, F_8, A_REL8, },
947 { O_JGE, F_8, A_REL8, },
948 { O_JLE, F_8, A_REL8, },
949 { O_JG, F_8, A_REL8, },
950 /*80*/ { O_MODRM, 0, 0, 0, 0, inst80 },
951 { O_MODRM, 0, 0, 0, 0, inst81 },
952 { -1 },
953 { O_MODRM, 0, 0, 0, 0, inst83 },
954 { O_TEST, F_8, A_RM8, A_R8, },
955 { O_TEST, F_1632, A_RM16, A_R16, },
956 { O_XCHG, F_8, A_R8, A_RM8, },
957 { O_XCHG, F_1632, A_R16, A_RM16, },
958 /*88*/ { O_MOV, F_8, A_RM8, A_R8, },
959 { O_MOV, F_1632, A_RM16, A_R16, },
960 { O_MOV, F_8, A_R8, A_RM8, },
961 { O_MOV, F_1632, A_R16, A_RM16, },
962 { O_MOV, F_16, A_RM16, A_SR },
963 { O_LEA, F_1632, A_R16, A_M },
964 { O_MOV, F_16, A_SR, A_RM16 },
965 { O_MODRM, 0, 0, 0, 0, inst8F },
966 /*90*/ { O_NOP, F_X, 0, 0, }, // really XCHG +r
967 { O_XCHG, F_1632, A_CX, A_R16 },
968 { O_XCHG, F_1632, A_DX, A_R16 },
969 { O_XCHG, F_1632, A_BX, A_R16 },
970 { O_XCHG, F_1632, A_SP, A_R16 },
971 { O_XCHG, F_1632, A_BP, A_R16 },
972 { O_XCHG, F_1632, A_SI, A_R16 },
973 { O_XCHG, F_1632, A_DI, A_R16 },
974 /*98*/ { O_CBW, F_1632, 0, 0 }, // or CWDE
975 { O_CWD, F_1632, 0, 0, }, // or CDQ
976 { O_CALLF, F_1632, A_IMM1616, 0, },
977 { O_WAIT, F_X, 0, 0, },
978 { O_PUSHF, F_1632, 0, 0, },
979 { O_POPF, F_1632, 0, 0, },
980 { O_SAHF, F_X, 0, 0, },
981 { O_LAHF, F_X, 0, 0, },
982 /*A0*/ { O_MOV, F_8, A_AL, A_MOFF8 },
983 { O_MOV, F_1632, A_AX, A_MOFF16},
984 { O_MOV, F_8, A_MOFF8,A_AL },
985 { O_MOV, F_1632, A_MOFF16, A_AX},
986 { O_MOVS, F_8, 0, 0 },
987 { O_MOVS, F_1632, 0, 0, },
988 { O_CMPS, F_8, 0, 0 },
989 { O_CMPS, F_1632, 0, 0, },
990 /*A8*/ { O_TEST, F_8, A_AL, A_IMM8 },
991 { O_TEST, F_1632, A_AX, A_IMM16 },
992 { O_STOS, F_8, 0, 0 },
993 { O_STOS, F_1632, 0, 0, },
994 { O_LODS, F_8, 0, 0 },
995 { O_LODS, F_1632, 0, 0, },
996 { O_SCAS, F_8, 0, 0 },
997 { O_SCAS, F_1632, 0, 0, },
998 /*B0*/ { O_MOV, F_8, A_AL, A_IMM8, }, // +r
999 { O_MOV, F_8, A_CL, A_IMM8, },
1000 { O_MOV, F_8, A_DL, A_IMM8, },
1001 { O_MOV, F_8, A_BL, A_IMM8, },
1002 { O_MOV, F_8, A_AH, A_IMM8, },
1003 { O_MOV, F_8, A_CH, A_IMM8, },
1004 { O_MOV, F_8, A_DH, A_IMM8, },
1005 { O_MOV, F_8, A_BH, A_IMM8, },
1006 /*B8*/ { O_MOV, F_1632, A_AX, A_IMM16, }, // +r
1007 { O_MOV, F_1632, A_CX, A_IMM16, },
1008 { O_MOV, F_1632, A_DX, A_IMM16, },
1009 { O_MOV, F_1632, A_BX, A_IMM16, },
1010 { O_MOV, F_1632, A_SP, A_IMM16, },
1011 { O_MOV, F_1632, A_BP, A_IMM16, },
1012 { O_MOV, F_1632, A_SI, A_IMM16, },
1013 { O_MOV, F_1632, A_DI, A_IMM16, },
1014 /*C0*/ { O_MODRM, 0, 0, 0, 0, instC0 },
1015 { O_MODRM, 0, 0, 0, 0, instC1 },
1016 { O_RET, 0, A_IMM16, 0, },
1017 { O_RET, 0, 0, 0, },
1018 { O_LES, F_1632, A_R16, A_M },
1019 { O_LDS, F_1632, A_R16, A_M },
1020 { O_MOV, F_8, A_RM8, A_IMM8 },
1021 { O_MOV, F_1632, A_RM16, A_IMM16 },
1022 /*C8*/ { O_ENTER, 0, A_IMM16, A_IMM8 },
1023 { O_LEAVE, F_1632, 0, 0, },
1024 { O_RETF, 0, A_IMM16, 0, },
1025 { O_RETF, 0, 0, 0, },
1026 { O_INT, F_X, A_3, 0, },
1027 { O_INT, F_X, A_IMM8, 0, },
1028 { O_INT, F_X, A_4, 0, },
1029 { O_IRET, F_1632, 0, 0, },
1030 /*D0*/ { O_MODRM, 0, 0, 0, 0, instD0 },
1031 { O_MODRM, 0, 0, 0, 0, instD1 },
1032 { O_MODRM, 0, 0, 0, 0, instD2 },
1033 { O_MODRM, 0, 0, 0, 0, instD3 },
1034 { O_AAM, F_0A, 0, 0, },
1035 { O_AAD, F_0A, 0, 0, },
1036 { -1 },
1037 { O_XLAT, F_8 },
1038 /*D8*/ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
1039 /*E0*/ { O_LOOPNZ, F_8, A_REL8, 0, },
1040 { O_LOOPZ, F_8, A_REL8, 0, },
1041 { O_LOOP, F_8, A_REL8, 0, },
1042 { O_JCXZ, F_8, A_REL8, 0, },
1043 { O_IN, F_8, A_AL, A_IMM8, },
1044 { O_IN, F_1632, A_AX, A_IMM8, },
1045 { O_OUT, F_8, A_IMM8, A_AL, },
1046 { O_OUT, F_1632, A_IMM8, A_AX, },
1047 /*E8*/ { O_CALL, F_1632, A_REL16, 0, },
1048 { O_JMP, F_1632, A_REL16, 0, },
1049 { O_JMPF, F_1632, A_IMM1616, 0, },
1050 { O_JMP, F_8, A_REL8, 0, },
1051 { O_IN, F_8, A_AL, A_DX, },
1052 { O_IN, F_1632, A_AX, A_DX, }, // DX not part of 16 -> 32
1053 { O_OUT, F_8, A_DX, A_AL, },
1054 { O_OUT, F_1632, A_DX, A_AX, },
1055 /*F0*/ { O_LOCK, 0, 0, 0, },
1056 { -1 },
1057 { O_REPNE, 0, 0, 0, },
1058 { O_REP, 0, 0, 0, }, // or O_REPE depending on next inst
1059 { O_HALT, F_X, 0, 0, },
1060 { O_CMC, F_X, 0, 0, },
1061 { O_MODRM, 0, 0, 0, 0, instF6 },
1062 { O_MODRM, 0, 0, 0, 0, instF7 },
1063 /*F8*/ { O_CLC, F_X, 0, 0, },
1064 { O_STC, F_X, 0, 0, },
1065 { O_CLI, F_X, 0, 0, },
1066 { O_STI, F_X, 0, 0, },
1067 { O_CLD, F_X, 0, 0, },
1068 { O_STD, F_X, 0, 0, },
1069 { O_MODRM, 0, 0, 0, 0, instFE },
1070 { O_MODRM, 0, 0, 0, 0, instFF },
1071 };
1072
1073 // Argument decoding tables.
1074
1075 static int needsmodrm[MAXA] =
1076 {
1077 [A_CR] 1,
1078 [A_DR] 1,
1079 [A_TR] 1,
1080 [A_SR] 1,
1081
1082 [A_R8] 1,
1083 [A_R16] 1,
1084 [A_R32] 1,
1085
1086 [A_M] 1,
1087
1088 [A_RM8] 1,
1089 [A_RM16] 1,
1090 [A_RM32] 1,
1091 };
1092
1093 static int cvt32[MAXA] =
1094 {
1095 [A_AX] A_EAX,
1096 [A_CX] A_ECX,
1097 [A_DX] A_EDX,
1098 [A_BX] A_EBX,
1099 [A_SP] A_ESP,
1100 [A_BP] A_EBP,
1101 [A_SI] A_ESI,
1102 [A_DI] A_EDI,
1103 [A_IMM16] A_IMM32,
1104 [A_R16] A_R32,
1105 [A_RM16] A_RM32,
1106 [A_REL16] A_REL32,
1107 [A_IMM1616] A_IMM1632,
1108 };
1109
1110 static int acvt32[MAXA] =
1111 {
1112 [A_MOFF16] A_MOFF32,
1113 };
1114
1115
1116 // Addressing mode tables.
1117
1118 static xdarg daimm = { DA_IMM };
1119 static xdarg darel = { DA_REL };
1120
1121 static xdarg daseg[] = {
1122 { DA_SEG16, ES },
1123 { DA_SEG16, CS },
1124 { DA_SEG16, SS },
1125 { DA_SEG16, DS },
1126 { DA_SEG16, FS },
1127 { DA_SEG16, GS },
1128 };
1129
1130 #define L 0 // offset of al in eax
1131 #define H 1 // offset of ah in eax
1132 #define X 0 // offset of ax in eax
1133
1134 static xdarg dareg[] = {
1135 { DA_REG8, EAX+L },
1136 { DA_REG8, ECX+L },
1137 { DA_REG8, EDX+L },
1138 { DA_REG8, EBX+L },
1139 { DA_REG8, EAX+H },
1140 { DA_REG8, ECX+H },
1141 { DA_REG8, EDX+H },
1142 { DA_REG8, EBX+H },
1143
1144 { DA_REG16, EAX+X },
1145 { DA_REG16, ECX+X },
1146 { DA_REG16, EDX+X },
1147 { DA_REG16, EBX+X },
1148 { DA_REG16, ESP+X },
1149 { DA_REG16, EBP+X },
1150 { DA_REG16, ESI+X },
1151 { DA_REG16, EDI+X },
1152
1153 { DA_REG32, EAX },
1154 { DA_REG32, ECX },
1155 { DA_REG32, EDX },
1156 { DA_REG32, EBX },
1157 { DA_REG32, ESP },
1158 { DA_REG32, EBP },
1159 { DA_REG32, ESI },
1160 { DA_REG32, EDI },
1161 };
1162
1163 static xdarg dacr[] = {
1164 { DA_REG32, CR0 },
1165 { DA_NONE },
1166 { DA_REG32, CR2 },
1167 { DA_REG32, CR3 },
1168 { DA_NONE },
1169 { DA_NONE },
1170 { DA_NONE },
1171 { DA_NONE },
1172 };
1173
1174 static xdarg dadr[] = {
1175 { DA_REG32, DR0 },
1176 { DA_REG32, DR1 },
1177 { DA_REG32, DR2 },
1178 { DA_REG32, DR3 },
1179 { DA_NONE },
1180 { DA_NONE },
1181 { DA_REG32, DR6 },
1182 { DA_REG32, DR7 },
1183 };
1184
1185 static xdarg datr[] = {
1186 { DA_NONE },
1187 { DA_NONE },
1188 { DA_NONE },
1189 { DA_NONE },
1190 { DA_NONE },
1191 { DA_NONE },
1192 { DA_REG32, TR6 },
1193 { DA_REG32, TR7 },
1194 };
1195
1196 static xdarg daind16[] = {
1197 { DA_IND16, EBX+X, ESI+X, 1, -DS },
1198 { DA_IND16, EBX+X, EDI+X, 1, -DS },
1199 { DA_IND16, EBP+X, ESI+X, 1, -SS },
1200 { DA_IND16, EBP+X, EDI+X, 1, -SS },
1201 { DA_IND16, ESI+X, 0, 0, -DS },
1202 { DA_IND16, EDI+X, 0, 0, -DS },
1203 { DA_IND16, EBP+X, 0, 0, -SS },
1204 { DA_IND16, EBX+X, 0, 0, -DS },
1205
1206 { DA_IND16, EBX+X, ESI+X, 1, -DS },
1207 { DA_IND16, EBX+X, EDI+X, 1, -DS },
1208 { DA_IND16, EBP+X, ESI+X, 1, -SS },
1209 { DA_IND16, EBP+X, EDI+X, 1, -DS },
1210 { DA_IND16, ESI+X, 0, 0, -DS },
1211 { DA_IND16, EDI+X, 0, 0, -DS },
1212 { DA_IND16, EBP+X, 0, 0, -SS },
1213 { DA_IND16, EBX+X, 0, 0, -DS },
1214
1215 { DA_IND16, EBX+X, ESI+X, 1, -DS },
1216 { DA_IND16, EBX+X, EDI+X, 1, -DS },
1217 { DA_IND16, EBP+X, ESI+X, 1, -SS },
1218 { DA_IND16, EBP+X, EDI+X, 1, -DS },
1219 { DA_IND16, ESI+X, 0, 0, -DS },
1220 { DA_IND16, EDI+X, 0, 0, -DS },
1221 { DA_IND16, EBP+X, 0, 0, -SS },
1222 { DA_IND16, EBX+X, 0, 0, -DS },
1223 };
1224
1225 static xdarg daind32[] = {
1226 { DA_IND32, EAX, 0, 0, -DS },
1227 { DA_IND32, ECX, 0, 0, -DS },
1228 { DA_IND32, EDX, 0, 0, -DS },
1229 { DA_IND32, EBX, 0, 0, -DS },
1230 { DA_NONE },
1231 { DA_IND32, EBP, 0, 0, -SS },
1232 { DA_IND32, ESI, 0, 0, -DS },
1233 { DA_IND32, EDI, 0, 0, -DS },
1234
1235 { DA_IND32, EAX, 0, 0, -DS },
1236 { DA_IND32, ECX, 0, 0, -DS },
1237 { DA_IND32, EDX, 0, 0, -DS },
1238 { DA_IND32, EBX, 0, 0, -DS },
1239 { DA_NONE },
1240 { DA_IND32, EBP, 0, 0, -SS },
1241 { DA_IND32, ESI, 0, 0, -DS },
1242 { DA_IND32, EDI, 0, 0, -DS },
1243
1244 { DA_IND32, EAX, 0, 0, -DS },
1245 { DA_IND32, ECX, 0, 0, -DS },
1246 { DA_IND32, EDX, 0, 0, -DS },
1247 { DA_IND32, EBX, 0, 0, -DS },
1248 { DA_NONE },
1249 { DA_IND32, EBP, 0, 0, -SS },
1250 { DA_IND32, ESI, 0, 0, -DS },
1251 { DA_IND32, EDI, 0, 0, -DS },
1252 };
1253
1254 static xdarg dasib[] = {
1255 { DA_SIB, 0, 0, 0, -DS },
1256 { DA_SIB, 0, 0, 0, -DS },
1257 { DA_SIB, 0, 0, 0, -DS },
1258 };
1259
1260 static xdarg dasibx[] = {
1261 { DA_SIBX, 0, 0, 0, -DS },
1262 { DA_SIBX, 0, 0, 0, -DS },
1263 { DA_SIBX, 0, 0, 0, -DS },
1264 };
1265
1266 static xdarg damem[] = {
1267 { DA_MEM, 0, 0, 0, -DS },
1268 { DA_MEM, 0, 0, 0, -DS },
1269 { DA_MEM, 0, 0, 0, -DS },
1270 };
1271
1272 static xdarg dasegmem[] = {
1273 { DA_SEGMEM },
1274 { DA_SEGMEM },
1275 { DA_SEGMEM },
1276 };
1277
1278 // Instruction decode.
1279
1280 static uint
1281 getimm8(uint8_t **pa)
1282 {
1283 return *(int8_t*)(*pa)++;
1284 }
1285
1286 static uint
1287 getimm16(uint8_t **pa)
1288 {
1289 uint8_t *a;
1290
1291 a = *pa;
1292 *pa += 2;
1293 return *(int16_t*)a;
1294 }
1295
1296 static uint
1297 getimm32(uint8_t **pa)
1298 {
1299 uint8_t *a;
1300
1301 a = *pa;
1302 *pa += 4;
1303 return *(int32_t*)a;
1304 }
1305
1306 static uint8_t*
1307 decodemodrm(uint8_t *a, uint flags, int sz, uint *reg, xdarg *ea)
1308 {
1309 int modrm, sib, s, i, b;
1310
1311 memset(ea, 0, sizeof *ea);
1312
1313 modrm = *a++;
1314 *reg = (modrm >> 3) & 7;
1315 if((modrm>>6) == 3){
1316 *ea = dareg[8*sz + (modrm&7)];
1317 return a;
1318 }
1319 if(!(flags&D_ADDR32)){
1320 if((modrm>>6) == 0 && (modrm&7) == 6){
1321 *ea = damem[sz];
1322 ea->disp = (uint16_t)getimm16(&a);
1323 return a;
1324 }
1325 *ea = daind16[sz*8 + (modrm&7)];
1326 switch(modrm>>6){
1327 case 1:
1328 ea->disp = getimm8(&a);
1329 break;
1330 case 2:
1331 ea->disp = (uint16_t)getimm16(&a);
1332 break;
1333 }
1334 }else{
1335 if((modrm>>6) == 0 && (modrm&7) == 5){
1336 *ea = damem[sz];
1337 ea->disp = getimm32(&a);
1338 return a;
1339 }
1340 switch(modrm&7){
1341 default:
1342 *ea = daind32[sz*8 + (modrm&7)];
1343 break;
1344 case 4:
1345 sib = *a++;
1346 s = (sib>>6);
1347 i = (sib>>3)&7;
1348 b = sib&7;
1349 *ea = dasib[sz];
1350 if((modrm>>6) == 0 && b == 5){
1351 *ea = dasibx[sz];
1352 ea->disp = getimm32(&a);
1353 }else{
1354 *ea = dasib[sz];
1355 ea->reg = 4*b;
1356 }
1357 if(ea->reg == 4*4 || ea->reg == 4*5)
1358 ea->seg = -SS;
1359 if(i != 4){
1360 ea->scale = 1<<s;
1361 ea->index = 4*i;
1362 }
1363 break;
1364 }
1365 switch(modrm>>6){
1366 case 1:
1367 ea->disp = getimm8(&a);
1368 break;
1369 case 2:
1370 ea->disp = getimm32(&a);
1371 break;
1372 }
1373 }
1374 return a;
1375 }
1376
1377 uint8_t*
1378 x86decode(uint8_t *addr0, uint8_t *a, xdinst *dec)
1379 {
1380 int i, arg, sz, didmodrm;
1381 uint reg;
1382 xdarg ea;
1383 xinst *ip;
1384 xdarg *da;
1385 uint8_t *astart;
1386 int flags;
1387
1388 flags = D_DATA32|D_ADDR32;
1389 reg = 0;
1390
1391 astart = a;
1392 dec->addr = a - addr0;
1393
1394 ip = &inst[*a++];
1395
1396 // xinstruction prefix.
1397 switch(ip->op){
1398 case O_LOCK:
1399 flags |= D_LOCK;
1400 goto next;
1401 case O_REPNE:
1402 flags |= D_REPN;
1403 goto next;
1404 case O_REP:
1405 flags |= D_REP;
1406 next:
1407 ip = &inst[*a++];
1408 break;
1409 }
1410
1411 // Address size prefix.
1412 switch(ip->op){
1413 case O_ADDRSIZE:
1414 flags ^= D_ADDR32;
1415 ip = &inst[*a++];
1416 break;
1417 }
1418
1419 // Operand size prefix.
1420 switch(ip->op){
1421 case O_DATASIZE:
1422 flags ^= D_DATA16|D_DATA32;
1423 ip = &inst[*a++];
1424 break;
1425 }
1426
1427 // Segment override.
1428 switch(ip->op){
1429 case O_SEGMENT:
1430 flags |= D_ES << (ip->arg1 - A_ES);
1431 ip = &inst[*a++];
1432 break;
1433 }
1434
1435 if(ip->op == O_NEXTB)
1436 ip = &ip->sub[*a++];
1437
1438 didmodrm = 0;
1439 if(ip->op == O_MODRM){
1440 ip = &ip->sub[(*a>>3)&7];
1441 didmodrm = 1;
1442 }
1443
1444 switch(ip->op){
1445 case O_ADDRSIZE:
1446 case O_DATASIZE:
1447 case O_SEGMENT:
1448 case O_LOCK:
1449 case O_REPNE:
1450 case O_REP:
1451 case -1:
1452 return NULL;
1453 }
1454
1455 switch(ip->flags){
1456 case F_X: // Don't care about operand size; pretend 8-bit for tables.
1457 case F_8: // Force 8-bit operands
1458 flags &= ~(D_DATA16|D_DATA32);
1459 flags |= D_DATA8;
1460 break;
1461 case F_16: // Force 16-bit operands
1462 flags &= ~D_DATA32;
1463 flags |= D_DATA16;
1464 break;
1465 case F_32: // Force 32-bit operands
1466 flags &= ~D_DATA16;
1467 flags |= D_DATA32;
1468 case F_1632: // Convert 16-bit operands to 32-bit if needed
1469 break;
1470 case F_0A: // Eat 0x0A byte.
1471 if(*a++ != 0x0A)
1472 return NULL;
1473 break;
1474 }
1475 if(flags&D_DATA8)
1476 sz = 0;
1477 else if(flags&D_DATA16)
1478 sz = 1;
1479 else
1480 sz = 2;
1481
1482 if(ip->op < 0 || ip->op >= MAXO)
1483 return NULL;
1484
1485 dec->name = opnames[ip->op][sz];
1486
1487 // Mod R/M byte if needed.
1488 if(didmodrm || needsmodrm[ip->arg1] || needsmodrm[ip->arg2])
1489 a = decodemodrm(a, flags, sz, ®, &ea);
1490
1491 // TO DO: Use override prefixes.
1492
1493 for(i=0; i<3; i++){
1494 arg = (&ip->arg1)[i];
1495 da = &dec->arg[i];
1496 if(arg == 0){
1497 da->op = DA_NONE;
1498 continue;
1499 }
1500 if((flags&D_DATA32) && ip->flags == F_1632 && cvt32[arg])
1501 arg = cvt32[arg];
1502 if((flags&D_ADDR32) && acvt32[arg])
1503 arg = acvt32[arg];
1504
1505 switch(arg){
1506 case A_0:
1507 *da = daimm;
1508 da->disp = 0;
1509 break;
1510 case A_1:
1511 case A_3:
1512 case A_4:
1513 *da = daimm;
1514 da->disp = arg;
1515 break;
1516 case A_AL:
1517 case A_CL:
1518 case A_DL:
1519 case A_BL:
1520 case A_AH:
1521 case A_CH:
1522 case A_DH:
1523 case A_BH:
1524 *da = dareg[arg - A_AL];
1525 break;
1526 case A_AX:
1527 case A_CX:
1528 case A_DX:
1529 case A_BX:
1530 case A_SP:
1531 case A_BP:
1532 case A_SI:
1533 case A_DI:
1534 *da = dareg[8 + arg - A_AX];
1535 break;
1536 case A_EAX:
1537 case A_ECX:
1538 case A_EDX:
1539 case A_EBX:
1540 case A_ESP:
1541 case A_EBP:
1542 case A_ESI:
1543 case A_EDI:
1544 *da = dareg[16 + arg - A_EAX];
1545 break;
1546 case A_ES:
1547 case A_CS:
1548 case A_SS:
1549 case A_DS:
1550 case A_FS:
1551 case A_GS:
1552 *da = daseg[arg - A_ES];
1553 break;
1554
1555 case A_IMM8:
1556 *da = daimm;
1557 da->disp = getimm8(&a);
1558 break;
1559 case A_IMM16:
1560 *da = daimm;
1561 da->disp = getimm16(&a);
1562 break;
1563 case A_IMM32:
1564 *da = daimm;
1565 da->disp = getimm32(&a);
1566 break;
1567
1568 case A_REL8:
1569 *da = darel;
1570 da->disp = getimm8(&a);
1571 break;
1572 case A_REL16:
1573 *da = darel;
1574 da->disp = getimm16(&a);
1575 break;
1576 case A_REL32:
1577 *da = darel;
1578 da->disp = getimm32(&a);
1579 break;
1580
1581 case A_R8:
1582 case A_R16:
1583 case A_R32:
1584 *da = dareg[sz*8 + reg];
1585 break;
1586
1587 case A_RM8:
1588 case A_RM16:
1589 case A_RM32:
1590 *da = ea;
1591 break;
1592
1593 case A_RM32R: // A_RM32 but needs to be register
1594 *da = ea;
1595 if(da->op > DA_REG32)
1596 return NULL;
1597 break;
1598
1599 case A_M: // A_RM but needs to be memory
1600 *da = ea;
1601 if(da->op <= DA_REG32)
1602 return NULL;
1603 break;
1604
1605 case A_MOFF8:
1606 *da = damem[sz];
1607 da->disp = getimm8(&a);
1608 break;
1609 case A_MOFF16:
1610 *da = damem[sz];
1611 da->disp = getimm16(&a);
1612 break;
1613 case A_MOFF32:
1614 *da = damem[sz];
1615 da->disp = getimm32(&a);
1616 break;
1617
1618 case A_SR:
1619 if(reg > 5)
1620 return NULL;
1621 *da = daseg[reg];
1622 break;
1623
1624 case A_CR:
1625 *da = dacr[reg];
1626 if(da->op == DA_NONE)
1627 return NULL;
1628 break;
1629 case A_DR:
1630 *da = dadr[reg];
1631 if(da->op == DA_NONE)
1632 return NULL;
1633 break;
1634 case A_TR:
1635 *da = dadr[reg];
1636 if(da->op == DA_NONE)
1637 return NULL;
1638 break;
1639
1640 case A_IMM1616:
1641 case A_IMM1632:
1642 *da = dasegmem[sz];
1643 if(arg == A_IMM1616)
1644 da->disp = getimm16(&a);
1645 else
1646 da->disp = getimm32(&a);
1647 da->seg = getimm16(&a);
1648 break;
1649
1650 }
1651 }
1652 dec->opsz = 8<<sz;
1653 dec->flags = flags;
1654 dec->len = a - astart;
1655 if(dec->name == NULL)
1656 dec->name = "???";
1657 return a;
1658 }
1659
1660
1661 // Instruction printing
1662
1663 static char*
1664 fmtseg(char *p, char *ep, xdarg *da)
1665 {
1666 if(da->seg < 0)
1667 p += snprintf(p, ep-p, "%s:", seg[-da->seg-CS]);
1668 else
1669 p += snprintf(p, ep-p, "%#x:", da->seg);
1670 return p;
1671 }
1672
1673 extern void vxrun_gentrap(void);
1674 extern void vxrun_lookup_backpatch(void);
1675 extern void vxrun_lookup_indirect(void);
1676
1677 static char*
1678 fmtarg(char *p, char *ep, xdarg *da, uint32_t npc)
1679 {
1680 uint32_t addr;
1681
1682 switch(da->op){
1683 default:
1684 p += snprintf(p, ep-p, "a%d", da->op);
1685 break;
1686 case DA_REG8:
1687 p += snprintf(p, ep-p, "%s", reg8[da->reg/4 + 4*(da->reg%2)]);
1688 break;
1689 case DA_REG16:
1690 p += snprintf(p, ep-p, "%s", reg16[da->reg/4]);
1691 break;
1692 case DA_REG32:
1693 p += snprintf(p, ep-p, "%s", reg32[da->reg/4]);
1694 break;
1695 case DA_SEG16:
1696 p += snprintf(p, ep-p, "%s", seg[da->reg-CS]);
1697 break;
1698 case DA_IMM:
1699 p += snprintf(p, ep-p, "$%#x", da->disp);
1700 break;
1701 case DA_REL:
1702 addr = da->disp + npc;
1703 if (addr == (uint32_t)(uintptr_t)vxrun_gentrap)
1704 p += snprintf(p, ep-p, "vxrun_gentrap");
1705 else if (addr == (uint32_t)(uintptr_t)vxrun_lookup_backpatch)
1706 p += snprintf(p, ep-p, "vxrun_lookup_backpatch");
1707 else if (addr == (uint32_t)(uintptr_t)vxrun_lookup_indirect)
1708 p += snprintf(p, ep-p, "vxrun_lookup_indirect");
1709 else
1710 p += snprintf(p, ep-p, "%#x", da->disp + npc);
1711 break;
1712 case DA_MEM:
1713 p = fmtseg(p, ep, da);
1714 p += snprintf(p, ep-p, "%#x", da->disp);
1715 break;
1716 case DA_SEGMEM:
1717 p += snprintf(p, ep-p, "%#x:%#x", da->seg, da->disp);
1718 break;
1719 case DA_IND16:
1720 p = fmtseg(p, ep, da);
1721 if(da->disp)
1722 p += snprintf(p, ep-p, "%#x", da->disp);
1723 p += snprintf(p, ep-p, "(");
1724 p += snprintf(p, ep-p, "%s", reg16[da->reg/4]);
1725 if(da->scale)
1726 p += snprintf(p, ep-p, "+%s", reg16[da->reg/4]);
1727 p += snprintf(p, ep-p, ")");
1728 break;
1729 case DA_IND32:
1730 p = fmtseg(p, ep, da);
1731 if(da->disp)
1732 p += snprintf(p, ep-p, "%#x", da->disp);
1733 p += snprintf(p, ep-p, "(%s)", reg32[da->reg/4]);
1734 break;
1735 case DA_SIB:
1736 case DA_SIBX:
1737 p = fmtseg(p, ep, da);
1738 if(da->disp)
1739 p += snprintf(p, ep-p, "%#x", da->disp);
1740 p += snprintf(p, ep-p, "(");
1741 if(da->op != DA_SIBX)
1742 p += snprintf(p, ep-p, "%s+", reg32[da->reg/4]);
1743 if(da->scale > 1)
1744 p += snprintf(p, ep-p, "%d*", da->scale);
1745 p += snprintf(p, ep-p, "%s", reg32[da->index/4]);
1746 p += snprintf(p, ep-p, ")");
1747 break;
1748 }
1749 return p;
1750 }
1751
1752 int
1753 x86print(char *buf, int nbuf, xdinst *dec)
1754 {
1755 int i;
1756 char *p, *ep;
1757
1758 p = buf;
1759 ep = buf + nbuf;
1760 for(i=0; i<nelem(prefixes); i++)
1761 if(dec->flags & prefixes[i].f)
1762 p += snprintf(p, ep-p, "%s ", prefixes[i].s);
1763 p += snprintf(p, ep-p, "%-6s", dec->name);
1764 for(i=0; i<nelem(dec->arg) && dec->arg[i].op != DA_NONE; i++){
1765 if(i > 0)
1766 p += snprintf(p, ep-p, ",");
1767 p += snprintf(p, ep-p, " ");
1768 p = fmtarg(p, ep, &dec->arg[i], dec->addr + dec->len);
1769 }
1770 return p - buf;
1771 }