vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | 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, &reg, &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 }