| version 1.1, 2003/12/08 00:55:31 | version 1.13, 2012/02/07 09:11:10 | 
| Line 1 | Line 1 | 
 | /*      $Id$    */ |  | 
 | /*      $NetBSD: db_disasm.c,v 1.28 2002/10/01 12:56:49 fvdl Exp $      */ |  | 
 |  |  | 
 | /* |  | 
 | * Mach Operating System |  | 
 | * Copyright (c) 1991,1990 Carnegie Mellon University |  | 
 | * All Rights Reserved. |  | 
 | * |  | 
 | * Permission to use, copy, modify and distribute this software and its |  | 
 | * documentation is hereby granted, provided that both the copyright |  | 
 | * notice and this permission notice appear in all copies of the |  | 
 | * software, derivative works or modified versions, and any portions |  | 
 | * thereof, and that both notices appear in supporting documentation. |  | 
 | * |  | 
 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" |  | 
 | * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR |  | 
 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. |  | 
 | * |  | 
 | * Carnegie Mellon requests users of this software to return to |  | 
 | * |  | 
 | *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU |  | 
 | *  School of Computer Science |  | 
 | *  Carnegie Mellon University |  | 
 | *  Pittsburgh PA 15213-3890 |  | 
 | * |  | 
 | * any improvements or extensions that they make and grant Carnegie the |  | 
 | * rights to redistribute these changes. |  | 
 | * |  | 
 | *      Id: db_disasm.c,v 2.3 91/02/05 17:11:03 mrt (CMU) |  | 
 | */ |  | 
 |  |  | 
 | /* | /* | 
| * Instruction disassembler. | * Copyright (c) 2004 NONAKA Kimihiro | 
|  | * All rights reserved. | 
|  | * | 
|  | * Redistribution and use in source and binary forms, with or without | 
|  | * modification, are permitted provided that the following conditions | 
|  | * are met: | 
|  | * 1. Redistributions of source code must retain the above copyright | 
|  | *    notice, this list of conditions and the following disclaimer. | 
|  | * 2. Redistributions in binary form must reproduce the above copyright | 
|  | *    notice, this list of conditions and the following disclaimer in the | 
|  | *    documentation and/or other materials provided with the distribution. | 
|  | * | 
|  | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 
|  | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 
|  | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 
|  | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 
|  | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 
|  | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
|  | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
|  | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
|  | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 
|  | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
 | */ | */ | 
 |  |  | 
 |  | #include "compiler.h" | 
 | #include "cpu.h" | #include "cpu.h" | 
 |  | #include "inst_table.h" | 
 |  |  | 
 | typedef BOOL    boolean_t; |  | 
 | typedef DWORD   db_addr_t; |  | 
 | typedef long    db_expr_t; |  | 
 |  |  | 
 | #define db_radix                                16 |  | 
 | #define db_printf                               ia32_printf |  | 
 | #define db_printsym(off, strategy, funcp)       db_printf(db_num_to_str(off)) |  | 
 | #define db_get_value(cs,loc,size,is_signed) \ |  | 
 | (db_expr_t)((size == 4) ? cpu_vmemoryread_d(cs,loc) \ |  | 
 | : ((size == 2) ? cpu_vmemoryread_w(cs,loc) \ |  | 
 | : ((size == 1) ? cpu_vmemoryread(cs,loc) : 0))) |  | 
 |  |  | 
 | static char * |  | 
 | db_num_to_str(db_expr_t val) |  | 
 | { |  | 
 | static char buf[25]; |  | 
 |  |  | 
 | if (db_radix == 16) { |  | 
 | snprintf(buf, sizeof(buf), "%lx", val); |  | 
 | } else if (db_radix == 8) { |  | 
 | snprintf(buf, sizeof(buf), "%lo", val); |  | 
 | } else { |  | 
 | snprintf(buf, sizeof(buf), "%lu", val); |  | 
 | } |  | 
 | return buf; |  | 
 | } |  | 
 |  |  | 
 | static void |  | 
 | db_format_radix(char *buf, size_t bufsiz, SQWORD val, int altflag) |  | 
 | { |  | 
 | const char *fmt; |  | 
 |  |  | 
 | UNUSED(altflag); |  | 
 |  |  | 
 | if (db_radix == 16) { |  | 
 | fmt = "-%llx"; |  | 
 | } else if (db_radix == 8) { |  | 
 | fmt = "-%llo"; |  | 
 | } else { |  | 
 | fmt = "-%llu"; |  | 
 | } |  | 
 | if (val < 0) |  | 
 | val = -val; |  | 
 | else |  | 
 | ++fmt; |  | 
 |  |  | 
 | snprintf(buf, bufsiz, fmt, val); |  | 
 | } |  | 
 |  |  | 
 | /* |  | 
 | * Size attributes |  | 
 | */ |  | 
 | #define DISASM_BYTE     0 |  | 
 | #define DISASM_WORD     1 |  | 
 | #define DISASM_LONG     2 |  | 
 | #define DISASM_QUAD     3 |  | 
 | #define DISASM_SNGL     4 |  | 
 | #define DISASM_DBLR     5 |  | 
 | #define DISASM_EXTR     6 |  | 
 | #define DISASM_SDEP     7 |  | 
 | #define DISASM_NONE     8 |  | 
 |  |  | 
 | /* | /* | 
| * Addressing modes | * opcode strings | 
 | */ | */ | 
| #define E       1                       /* general effective address */ | static const char *opcode_1byte[2][256] = { | 
| #define Eind    2                       /* indirect address (jump, call) */ | /* 16bit */ | 
| #define Ew      3                       /* address, word size */ | { | 
| #define Eb      4                       /* address, byte size */ | /*00*/  "addb",  "addw",  "addb",  "addw",  "addb",  "addw",  "push",  "pop", | 
| #define R       5                       /* register, in 'reg' field */ | "orb",   "orw",   "orb",   "orw",   "orb",   "orw",   "push",  NULL, | 
| #define Rw      6                       /* word register, in 'reg' field */ | /*10*/  "adcb",  "adcw",  "adcb",  "adcw",  "adcb",  "adcw",  "push",  "pop", | 
| #define Ri      7                       /* register in instruction */ | "sbbb",  "sbbw",  "sbbb",  "sbbw",  "sbbb",  "sbbw",  "push",  "pop", | 
| #define S       8                       /* segment reg, in 'reg' field */ | /*20*/  "andb",  "andw",  "andb",  "andw",  "andb",  "andw",  NULL,    "daa", | 
| #define Si      9                       /* segment reg, in instruction */ | "subb",  "subw",  "subb",  "subw",  "subb",  "subw",  NULL,    "das", | 
| #define A       10                      /* accumulator */ | /*30*/  "xorb",  "xorw",  "xorb",  "xorw",  "xorb",  "xorw",  NULL,    "aaa", | 
| #define BX      11                      /* (bx) */ | "cmpb",  "cmpw",  "cmpb",  "cmpw",  "cmpb",  "cmpw",  NULL,    "aas", | 
| #define CL      12                      /* cl, for shifts */ | /*40*/  "incw",  "incw",  "incw",  "incw",  "incw",  "incw",  "incw",  "incw", | 
| #define DX      13                      /* dx, for IO */ | "decw",  "decw",  "decw",  "decw",  "decw",  "decw",  "decw",  "decw", | 
| #define SI      14                      /* si */ | /*50*/  "push",  "push",  "push",  "push",  "push",  "push",  "push",  "push", | 
| #define DI      15                      /* di */ | "pop",   "pop",   "pop",   "pop",   "pop",   "pop",   "pop",   "pop", | 
| #define CR      16                      /* control register */ | /*60*/  "pusha", "popa",  "bound", "arpl",  NULL,    NULL,    NULL,    NULL, | 
| #define DR      17                      /* debug register */ | "push",  "imul",  "push",  "imul",  "insb",  "insw",  "outsb", "outsw", | 
| #define TR      18                      /* test register */ | /*70*/  "jo",    "jno",   "jc",    "jnc",   "jz",    "jnz",   "jna",   "ja", | 
| #define I       19                      /* immediate, unsigned */ | "js",    "jns",   "jp",    "jnp",   "jl",    "jnl",   "jle",   "jnle", | 
| #define Is      20                      /* immediate, signed */ | /*80*/  NULL,    NULL,    NULL,    NULL,    "testb", "testw", "xchgb", "xchgw", | 
| #define Ib      21                      /* byte immediate, unsigned */ | "movb",  "movw",  "movb",  "movw",  "movw",  "lea",   "movw",  "pop", | 
| #define Ibs     22                      /* byte immediate, signed */ | /*90*/  "nop",   "xchgw", "xchgw", "xchgw", "xchgw", "xchgw", "xchgw", "xchgw", | 
| #define Iw      23                      /* word immediate, unsigned */ | "cbw",   "cwd",   "callf", "fwait", "pushf", "popf",  "sahf",  "lahf", | 
| #define Il      24                      /* long immediate */ | /*a0*/  "movb",  "movw",  "movb",  "movw",  "movsb", "movsw", "cmpsb", "cmpsw", | 
| #define O       25                      /* direct address */ | "testb", "testw", "stosb", "stosw", "lodsb", "lodsw", "scasb", "scasw", | 
| #define Db      26                      /* byte displacement from EIP */ | /*b0*/  "movb",  "movb",  "movb",  "movb",  "movb",  "movb",  "movb",  "movb", | 
| #define Dl      27                      /* long displacement from EIP */ | "movw",  "movw",  "movw",  "movw",  "movw",  "movw",  "movw",  "movw", | 
| #define o1      28                      /* constant 1 */ | /*c0*/  NULL,    NULL,    "ret",   "ret",   "les",   "lds",   "movb",  "movw", | 
| #define o3      29                      /* constant 3 */ | "enter", "leave", "retf",  "retf",  "int3",  "int",   "into",  "iret", | 
| #define OS      30                      /* immediate offset/segment */ | /*d0*/  NULL,    NULL,    NULL,    NULL,    "aam",   "aad",   "salc",  "xlat", | 
| #define ST      31                      /* FP stack top */ | "esc0",  "esc1",  "esc2",  "esc3",  "esc4",  "esc5",  "esc6",  "esc7", | 
| #define STI     32                      /* FP stack */ | /*e0*/  "loopne","loope", "loop",  "jcxz",  "inb",   "inw",   "outb",  "outw", | 
| #define X       33                      /* extended FP op */ | "call",  "jmp",   "jmpf",  "jmp",   "inb",   "inw",   "outb",  "outw", | 
| #define XA      34                      /* for 'fstcw %ax' */ | /*f0*/  "lock:", "int1",  "repne", "repe",  "hlt",   "cmc",   NULL,    NULL, | 
|  | "clc",   "stc",   "cli",   "sti",   "cld",   "std",   NULL,    NULL, | 
| struct inst { | }, | 
| char *  i_name;                 /* name */ | /* 32bit */ | 
| short   i_has_modrm;            /* has regmodrm byte */ | { | 
| short   i_size;                 /* operand size */ | /*00*/  "addb",  "addl",  "addb",  "addl",  "addb",  "addl",  "pushl", "popl", | 
| int     i_mode;                 /* addressing modes */ | "orb",   "orl",   "orb",   "orl",   "orb",   "orl",   "pushl", NULL, | 
| char *  i_extra;                /* pointer to extra opcode table */ | /*10*/  "adcb",  "adcl",  "adcb",  "adcl",  "adcb",  "adcl",  "pushl", "popl", | 
| }; | "sbbb",  "sbbl",  "sbbb",  "sbbl",  "sbbb",  "sbbl",  "pushl", "popl", | 
|  | /*20*/  "andb",  "andl",  "andb",  "andl",  "andb",  "andl",  NULL,    "daa", | 
| #define op1(x)          (x) | "subb",  "subl",  "subb",  "subl",  "subb",  "subl",  NULL,    "das", | 
| #define op2(x,y)        ((x)|((y)<<8)) | /*30*/  "xorb",  "xorl",  "xorb",  "xorl",  "xorb",  "xorl",  NULL,    "aaa", | 
| #define op3(x,y,z)      ((x)|((y)<<8)|((z)<<16)) | "cmpb",  "cmpl",  "cmpb",  "cmpl",  "cmpb",  "cmpl",  NULL,    "aas", | 
|  | /*40*/  "incl",  "incl",  "incl",  "incl",  "incl",  "incl",  "incl",  "incl", | 
| struct finst { | "decl",  "decl",  "decl",  "decl",  "decl",  "decl",  "decl",  "decl", | 
| char *  f_name;                 /* name for memory instruction */ | /*50*/  "pushl", "pushl", "pushl", "pushl", "pushl", "pushl", "pushl", "pushl", | 
| int     f_size;                 /* size for memory instruction */ | "popl",  "popl",  "popl",  "popl",  "popl",  "popl",  "popl",  "pop", | 
| int     f_rrmode;               /* mode for rr instruction */ | /*60*/  "pushad","popad", "bound", "arpl",  NULL,    NULL,    NULL,    NULL, | 
| char *  f_rrname;               /* name for rr instruction | "pushl", "imul",  "pushl", "imul",  "insb",  "insl",  "outsb", "outsl", | 
| (or pointer to table) */ | /*70*/  "jo",    "jno",   "jc",    "jnc",   "jz",    "jnz",   "jna",   "ja", | 
| }; | "js",    "jns",   "jp",    "jnp",   "jl",    "jnl",   "jle",   "jnle", | 
|  | /*80*/  NULL,    NULL,    NULL,    NULL,    "testb", "testl", "xchgb", "xchgl", | 
| const char * const db_Grp6[] = { | "movb",  "movl",  "movb",  "movl",  "movl",  "lea",   "movl",  "popl", | 
| "sldt", | /*90*/  "nop",   "xchgl", "xchgl", "xchgl", "xchgl", "xchgl", "xchgl", "xchgl", | 
| "str", | "cwde",  "cdq",   "callfl","fwait", "pushfd","popfd", "sahf",  "lahf", | 
| "lldt", | /*a0*/  "movb",  "movl",  "movb",  "movl",  "movsb", "movsd", "cmpsb", "cmpsd", | 
| "ltr", | "testb", "testl", "stosb", "stosd", "lodsb", "lodsd", "scasb", "scasd", | 
| "verr", | /*b0*/  "movb",  "movb",  "movb",  "movb",  "movb",  "movb",  "movb",  "movb", | 
| "verw", | "movl",  "movl",  "movl",  "movl",  "movl",  "movl",  "movl",  "movl", | 
| "", | /*c0*/  NULL,    NULL,    "ret",   "ret",   "les",   "lds",   "movb",  "movl", | 
| "" | "enter", "leave", "retf",  "retf",  "int3",  "int",   "into",  "iretd", | 
| }; | /*d0*/  NULL,    NULL,    NULL,    NULL,    "aam",   "aad",   "salc",  "xlat", | 
|  | "esc0",  "esc1",  "esc2",  "esc3",  "esc4",  "esc5",  "esc6",  "esc7", | 
| const char * const db_Grp7[] = { | /*e0*/  "loopne","loope", "loop",  "jecxz", "inb",   "inl",   "outb",  "outl", | 
| "sgdt", | "call",  "jmp",   "jmpf",  "jmp",   "inb",   "inl",   "outb",  "outl", | 
| "sidt", | /*f0*/  "lock:", "int1",  "repne", "repe",  "hlt",   "cmc",   NULL,    NULL, | 
| "lgdt", | "clc",   "stc",   "cli",   "sti",   "cld",   "std",   NULL,    NULL, | 
| "lidt", | } | 
| "smsw", |  | 
| "", |  | 
| "lmsw", |  | 
| "invlpg" |  | 
| }; |  | 
|  |  | 
| const char * const db_Grp8[] = { |  | 
| "", |  | 
| "", |  | 
| "", |  | 
| "", |  | 
| "bt", |  | 
| "bts", |  | 
| "btr", |  | 
| "btc" |  | 
| }; |  | 
|  |  | 
| const char * const db_Grp9[] = { |  | 
| "", |  | 
| "cmpxchg8b", |  | 
| "", |  | 
| "", |  | 
| "", |  | 
| "", |  | 
| "", |  | 
| "", |  | 
| }; |  | 
|  |  | 
| const struct inst db_inst_0f0x[] = { |  | 
| /*00*/  { "",      TRUE,  DISASM_NONE,  op1(Ew),     (char *)db_Grp6 }, |  | 
| /*01*/  { "",      TRUE,  DISASM_NONE,  op1(Ew),     (char *)db_Grp7 }, |  | 
| /*02*/  { "lar",   TRUE,  DISASM_LONG,  op2(E,R),    0 }, |  | 
| /*03*/  { "lsl",   TRUE,  DISASM_LONG,  op2(E,R),    0 }, |  | 
| /*04*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*05*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*06*/  { "clts",  FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*07*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
|  |  | 
| /*08*/  { "invd",  FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*09*/  { "wbinvd",FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*0a*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*0b*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*0c*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*0d*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*0e*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*0f*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| }; |  | 
|  |  | 
| const struct inst       db_inst_0f2x[] = { |  | 
| /*20*/  { "mov",   TRUE,  DISASM_LONG,  op2(CR,E),   0 }, /* use E for reg */ |  | 
| /*21*/  { "mov",   TRUE,  DISASM_LONG,  op2(DR,E),   0 }, /* since mod == 11 */ |  | 
| /*22*/  { "mov",   TRUE,  DISASM_LONG,  op2(E,CR),   0 }, |  | 
| /*23*/  { "mov",   TRUE,  DISASM_LONG,  op2(E,DR),   0 }, |  | 
| /*24*/  { "mov",   TRUE,  DISASM_LONG,  op2(TR,E),   0 }, |  | 
| /*25*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*26*/  { "mov",   TRUE,  DISASM_LONG,  op2(E,TR),   0 }, |  | 
| /*27*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
|  |  | 
| /*28*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*29*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*2a*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*2b*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*2c*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*2d*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*2e*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*2f*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| }; |  | 
|  |  | 
| const struct inst       db_inst_0f3x[] = { |  | 
| /*30*/  { "wrmsr", FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*31*/  { "rdtsc", FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*32*/  { "rdmsr", FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*33*/  { "rdpmc", FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*34*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*35*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*36*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*37*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
|  |  | 
| /*38*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*39*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*3a*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*3v*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*3c*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*3d*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*3e*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*3f*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| }; |  | 
|  |  | 
| const struct inst       db_inst_0f8x[] = { |  | 
| /*80*/  { "jo",    FALSE, DISASM_NONE,  op1(Dl),     0 }, |  | 
| /*81*/  { "jno",   FALSE, DISASM_NONE,  op1(Dl),     0 }, |  | 
| /*82*/  { "jb",    FALSE, DISASM_NONE,  op1(Dl),     0 }, |  | 
| /*83*/  { "jnb",   FALSE, DISASM_NONE,  op1(Dl),     0 }, |  | 
| /*84*/  { "jz",    FALSE, DISASM_NONE,  op1(Dl),     0 }, |  | 
| /*85*/  { "jnz",   FALSE, DISASM_NONE,  op1(Dl),     0 }, |  | 
| /*86*/  { "jbe",   FALSE, DISASM_NONE,  op1(Dl),     0 }, |  | 
| /*87*/  { "jnbe",  FALSE, DISASM_NONE,  op1(Dl),     0 }, |  | 
|  |  | 
| /*88*/  { "js",    FALSE, DISASM_NONE,  op1(Dl),     0 }, |  | 
| /*89*/  { "jns",   FALSE, DISASM_NONE,  op1(Dl),     0 }, |  | 
| /*8a*/  { "jp",    FALSE, DISASM_NONE,  op1(Dl),     0 }, |  | 
| /*8b*/  { "jnp",   FALSE, DISASM_NONE,  op1(Dl),     0 }, |  | 
| /*8c*/  { "jl",    FALSE, DISASM_NONE,  op1(Dl),     0 }, |  | 
| /*8d*/  { "jnl",   FALSE, DISASM_NONE,  op1(Dl),     0 }, |  | 
| /*8e*/  { "jle",   FALSE, DISASM_NONE,  op1(Dl),     0 }, |  | 
| /*8f*/  { "jnle",  FALSE, DISASM_NONE,  op1(Dl),     0 }, |  | 
| }; |  | 
|  |  | 
| const struct inst       db_inst_0f9x[] = { |  | 
| /*90*/  { "seto",  TRUE,  DISASM_NONE,  op1(Eb),     0 }, |  | 
| /*91*/  { "setno", TRUE,  DISASM_NONE,  op1(Eb),     0 }, |  | 
| /*92*/  { "setb",  TRUE,  DISASM_NONE,  op1(Eb),     0 }, |  | 
| /*93*/  { "setnb", TRUE,  DISASM_NONE,  op1(Eb),     0 }, |  | 
| /*94*/  { "setz",  TRUE,  DISASM_NONE,  op1(Eb),     0 }, |  | 
| /*95*/  { "setnz", TRUE,  DISASM_NONE,  op1(Eb),     0 }, |  | 
| /*96*/  { "setbe", TRUE,  DISASM_NONE,  op1(Eb),     0 }, |  | 
| /*97*/  { "setnbe",TRUE,  DISASM_NONE,  op1(Eb),     0 }, |  | 
|  |  | 
| /*98*/  { "sets",  TRUE,  DISASM_NONE,  op1(Eb),     0 }, |  | 
| /*99*/  { "setns", TRUE,  DISASM_NONE,  op1(Eb),     0 }, |  | 
| /*9a*/  { "setp",  TRUE,  DISASM_NONE,  op1(Eb),     0 }, |  | 
| /*9b*/  { "setnp", TRUE,  DISASM_NONE,  op1(Eb),     0 }, |  | 
| /*9c*/  { "setl",  TRUE,  DISASM_NONE,  op1(Eb),     0 }, |  | 
| /*9d*/  { "setnl", TRUE,  DISASM_NONE,  op1(Eb),     0 }, |  | 
| /*9e*/  { "setle", TRUE,  DISASM_NONE,  op1(Eb),     0 }, |  | 
| /*9f*/  { "setnle",TRUE,  DISASM_NONE,  op1(Eb),     0 }, |  | 
| }; |  | 
|  |  | 
| const struct inst       db_inst_0fax[] = { |  | 
| /*a0*/  { "push",  FALSE, DISASM_NONE,  op1(Si),     0 }, |  | 
| /*a1*/  { "pop",   FALSE, DISASM_NONE,  op1(Si),     0 }, |  | 
| /*a2*/  { "cpuid", FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*a3*/  { "bt",    TRUE,  DISASM_LONG,  op2(R,E),    0 }, |  | 
| /*a4*/  { "shld",  TRUE,  DISASM_LONG,  op3(Ib,E,R), 0 }, |  | 
| /*a5*/  { "shld",  TRUE,  DISASM_LONG,  op3(CL,E,R), 0 }, |  | 
| /*a6*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*a7*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
|  |  | 
| /*a8*/  { "push",  FALSE, DISASM_NONE,  op1(Si),     0 }, |  | 
| /*a9*/  { "pop",   FALSE, DISASM_NONE,  op1(Si),     0 }, |  | 
| /*aa*/  { "rsm",   FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*ab*/  { "bts",   TRUE,  DISASM_LONG,  op2(R,E),    0 }, |  | 
| /*ac*/  { "shrd",  TRUE,  DISASM_LONG,  op3(Ib,E,R), 0 }, |  | 
| /*ad*/  { "shrd",  TRUE,  DISASM_LONG,  op3(CL,E,R), 0 }, |  | 
| /*ae*/  { "fxsave",TRUE,  DISASM_LONG,  0,            0 }, |  | 
| /*af*/  { "imul",  TRUE,  DISASM_LONG,  op2(E,R),    0 }, |  | 
| }; |  | 
|  |  | 
| const struct inst       db_inst_0fbx[] = { |  | 
| /*b0*/  { "cmpxchg",TRUE, DISASM_BYTE,   op2(R, E),   0 }, |  | 
| /*b1*/  { "cmpxchg",TRUE, DISASM_LONG,   op2(R, E),   0 }, |  | 
| /*b2*/  { "lss",   TRUE,  DISASM_LONG,  op2(E, R),   0 }, |  | 
| /*b3*/  { "btr",   TRUE,  DISASM_LONG,  op2(R, E),   0 }, |  | 
| /*b4*/  { "lfs",   TRUE,  DISASM_LONG,  op2(E, R),   0 }, |  | 
| /*b5*/  { "lgs",   TRUE,  DISASM_LONG,  op2(E, R),   0 }, |  | 
| /*b6*/  { "movzb", TRUE,  DISASM_LONG,  op2(E, R),   0 }, |  | 
| /*b7*/  { "movzw", TRUE,  DISASM_LONG,  op2(E, R),   0 }, |  | 
|  |  | 
| /*b8*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*b9*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*ba*/  { "",      TRUE,  DISASM_LONG,  op2(Ib, E),  (char *)db_Grp8 }, |  | 
| /*bb*/  { "btc",   TRUE,  DISASM_LONG,  op2(R, E),   0 }, |  | 
| /*bc*/  { "bsf",   TRUE,  DISASM_LONG,  op2(E, R),   0 }, |  | 
| /*bd*/  { "bsr",   TRUE,  DISASM_LONG,  op2(E, R),   0 }, |  | 
| /*be*/  { "movsb", TRUE,  DISASM_LONG,  op2(E, R),   0 }, |  | 
| /*bf*/  { "movsw", TRUE,  DISASM_LONG,  op2(E, R),   0 }, |  | 
| }; |  | 
|  |  | 
| const struct inst       db_inst_0fcx[] = { |  | 
| /*c0*/  { "xadd",  TRUE,  DISASM_BYTE,   op2(R, E),   0 }, |  | 
| /*c1*/  { "xadd",  TRUE,  DISASM_LONG,   op2(R, E),   0 }, |  | 
| /*c2*/  { "",      FALSE, DISASM_NONE,   0,           0 }, |  | 
| /*c3*/  { "",      FALSE, DISASM_NONE,   0,           0 }, |  | 
| /*c4*/  { "",      FALSE, DISASM_NONE,   0,           0 }, |  | 
| /*c5*/  { "",      FALSE, DISASM_NONE,   0,           0 }, |  | 
| /*c6*/  { "",      FALSE, DISASM_NONE,   0,           0 }, |  | 
| /*c7*/  { "",      TRUE,  DISASM_NONE,   op1(E),      (char *)db_Grp9 }, |  | 
| /*c8*/  { "bswap", FALSE, DISASM_LONG,  op1(Ri),     0 }, |  | 
| /*c9*/  { "bswap", FALSE, DISASM_LONG,  op1(Ri),     0 }, |  | 
| /*ca*/  { "bswap", FALSE, DISASM_LONG,  op1(Ri),     0 }, |  | 
| /*cb*/  { "bswap", FALSE, DISASM_LONG,  op1(Ri),     0 }, |  | 
| /*cc*/  { "bswap", FALSE, DISASM_LONG,  op1(Ri),     0 }, |  | 
| /*cd*/  { "bswap", FALSE, DISASM_LONG,  op1(Ri),     0 }, |  | 
| /*ce*/  { "bswap", FALSE, DISASM_LONG,  op1(Ri),     0 }, |  | 
| /*cf*/  { "bswap", FALSE, DISASM_LONG,  op1(Ri),     0 }, |  | 
| }; |  | 
|  |  | 
| const struct inst * const db_inst_0f[] = { |  | 
| db_inst_0f0x, |  | 
| 0, |  | 
| db_inst_0f2x, |  | 
| db_inst_0f3x, |  | 
| 0, |  | 
| 0, |  | 
| 0, |  | 
| 0, |  | 
| db_inst_0f8x, |  | 
| db_inst_0f9x, |  | 
| db_inst_0fax, |  | 
| db_inst_0fbx, |  | 
| db_inst_0fcx, |  | 
| 0, |  | 
| 0, |  | 
| 0 |  | 
| }; |  | 
|  |  | 
| const char * const db_Esc92[] = { |  | 
| "fnop", "",     "",     "",     "",     "",     "",     "" |  | 
| }; |  | 
| const char * const db_Esc93[] = { |  | 
| "",     "",     "",     "",     "",     "",     "",     "" |  | 
| }; |  | 
| const char * const db_Esc94[] = { |  | 
| "fchs", "fabs", "",     "",     "ftst", "fxam", "",     "" |  | 
| }; |  | 
| const char * const db_Esc95[] = { |  | 
| "fld1", "fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","" |  | 
| }; |  | 
| const char * const db_Esc96[] = { |  | 
| "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp", |  | 
| "fincstp" |  | 
| }; |  | 
| const char * const db_Esc97[] = { |  | 
| "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos" |  | 
 | }; | }; | 
 |  |  | 
| const char * const db_Esca4[] = { | static const char *opcode_2byte[2][256] = { | 
| "",     "fucompp","",   "",     "",     "",     "",     "" | /* 16bit */ | 
|  | { | 
|  | /*00*/  NULL,      NULL,      "lar",     "lsl", | 
|  | NULL,      "loadall", "clts",    NULL, | 
|  | "invd",    "wbinvd",  NULL,      "UD2", | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | /*10*/  NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | /*20*/  "movl",    "movl",    "movl",    "movl", | 
|  | "movl",    NULL,      "movl",    NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | /*30*/  "wrmsr",   "rdtsc",   "rdmsr",   NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | /*40*/  "cmovo",   "cmovno",  "cmovc",   "cmovnc", | 
|  | "cmovz",   "cmovnz",  "cmovna",  "cmova", | 
|  | "cmovs",   "cmovns",  "cmovp",   "cmovnp", | 
|  | "cmovl",   "cmovnl",  "cmovle",  "cmovnle", | 
|  | /*50*/  NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | /*60*/  NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | /*70*/  NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | /*80*/  "jo",      "jno",     "jc",      "jnc", | 
|  | "jz",      "jnz",     "jna",     "ja", | 
|  | "js",      "jns",     "jp",      "jnp", | 
|  | "jl",      "jnl",     "jle",     "jnle", | 
|  | /*90*/  "seto",    "setno",   "setc",    "setnc", | 
|  | "setz",    "setnz",   "setna",   "seta", | 
|  | "sets",    "setns",   "setp",    "setnp", | 
|  | "setl",    "setnl",   "setle",   "setnle", | 
|  | /*a0*/  "push",    "pop",     "cpuid",   "bt", | 
|  | "shldb",   "shldw",   "cmpxchgb","cmpxchgw", | 
|  | "push",    "pop",     "rsm",     "bts", | 
|  | "shrdb",   "shrdw",   NULL,      "imul", | 
|  | /*b0*/  "cmpxchgb","cmpxchgw","lss",     "btr", | 
|  | "lfs",     "lgs",     "movzb",   "movzw", | 
|  | NULL,      "UD2",     NULL,      "btc", | 
|  | "bsf",     "bsr",     "movsb",   "movsw", | 
|  | /*c0*/  "xaddb",   "xaddw",   NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | "bswap",   "bswap",   "bswap",   "bswap", | 
|  | "bswap",   "bswap",   "bswap",   "bswap", | 
|  | /*d0*/  NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | /*e0*/  NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | /*f0*/  NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | }, | 
|  | /* 32bit */ | 
|  | { | 
|  | /*00*/  NULL,      NULL,      "lar",     "lsl", | 
|  | NULL,      "loadall", "clts",    NULL, | 
|  | "invd",    "wbinvd",  NULL,      "UD2", | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | /*10*/  NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | /*20*/  "movl",    "movl",    "movl",    "movl", | 
|  | "movl",    NULL,      "movl",    NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | /*30*/  "wrmsr",   "rdtsc",   "rdmsr",   NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | /*40*/  "cmovo",   "cmovno",  "cmovc",   "cmovnc", | 
|  | "cmovz",   "cmovnz",  "cmovna",  "cmova", | 
|  | "cmovs",   "cmovns",  "cmovp",   "cmovnp", | 
|  | "cmovl",   "cmovnl",  "cmovle",  "cmovnle", | 
|  | /*50*/  NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | /*60*/  NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | /*70*/  NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | /*80*/  "jo",      "jno",     "jc",      "jnc", | 
|  | "jz",      "jnz",     "jna",     "ja", | 
|  | "js",      "jns",     "jp",      "jnp", | 
|  | "jl",      "jnl",     "jle",     "jnle", | 
|  | /*90*/  "seto",    "setno",   "setc",    "setnc", | 
|  | "setz",    "setnz",   "setna",   "seta", | 
|  | "sets",    "setns",   "setp",    "setnp", | 
|  | "setl",    "setnl",   "setle",   "setnle", | 
|  | /*a0*/  "push",    "pop",     "cpuid",   "bt", | 
|  | "shldb",   "shldl",   "cmpxchgb","cmpxchgl", | 
|  | "push",    "pop",     "rsm",     "bts", | 
|  | "shrdb",   "shrdl",   NULL,      "imul", | 
|  | /*b0*/  "cmpxchgb","cmpxchgd","lss",     "btr", | 
|  | "lfs",     "lgs",     "movzbl",  "movzwl", | 
|  | NULL,      "UD2",     NULL,      "btc", | 
|  | "bsf",     "bsr",     "movsbl",  "movswl", | 
|  | /*c0*/  "xaddb",   "xaddl",   NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | "bswapl",  "bswapl",  "bswapl",  "bswapl", | 
|  | "bswapl",  "bswapl",  "bswapl",  "bswapl", | 
|  | /*d0*/  NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | /*e0*/  NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | /*f0*/  NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | NULL,      NULL,      NULL,      NULL, | 
|  | } | 
 | }; | }; | 
 |  |  | 
| const char * const db_Escb4[] = { | static const char *opcode_0x8x[2][2][8] = { | 
| "",     "",     "fnclex","fninit","",   "",     "",     "" | /* 16bit */ | 
|  | { | 
|  | { "addb", "orb", "adcb", "sbbb", "andb", "subb", "xorb", "cmpb" }, | 
|  | { "addw", "orw", "adcw", "sbbw", "andw", "subw", "xorw", "cmpw" } | 
|  | }, | 
|  | /* 32bit */ | 
|  | { | 
|  | { "addb", "orb", "adcb", "sbbb", "andb", "subb", "xorb", "cmpb" }, | 
|  | { "addl", "orl", "adcl", "sbbl", "andl", "subl", "xorl", "cmpl" } | 
|  | } | 
 | }; | }; | 
 |  |  | 
| const char * const db_Esce3[] = { | static const char *opcode_shift[2][2][8] = { | 
| "",     "fcompp","",    "",     "",     "",     "",     "" | /* 16bit */ | 
|  | { | 
|  | { "rolb", "rorb", "rclb", "rcrb", "shlb", "shrb", "shlb", "sarb" }, | 
|  | { "rolw", "rorw", "rclw", "rcrw", "shlw", "shrw", "shlw", "sarw" } | 
|  | }, | 
|  | /* 32bit */ | 
|  | { | 
|  | { "rolb", "rorb", "rclb", "rcrb", "shlb", "shrb", "shlb", "sarb" }, | 
|  | { "roll", "rorl", "rcll", "rcrl", "shll", "shrl", "shll", "sarl" } | 
|  | }, | 
 | }; | }; | 
 |  |  | 
| const char * const db_Escf4[] = { | static const char *opcode_0xf6[2][2][8] = { | 
| "fnstsw","",    "",     "",     "",     "",     "",     "" | /* 16bit */ | 
|  | { | 
|  | { "testb", "testb", "notb", "negb", "mul", "imul", "div", "idiv" }, | 
|  | { "testw", "testw", "notw", "negw", "mulw", "imulw", "divw", "idivw" } | 
|  | }, | 
|  | /* 32bit */ | 
|  | { | 
|  | { "testb", "testb", "notb", "negb", "mul", "imul", "div", "idiv" }, | 
|  | { "testl", "testl", "notl", "negl", "mull", "imull", "divl", "idivl" } | 
|  | }, | 
 | }; | }; | 
 |  |  | 
| const struct finst db_Esc8[] = { | static const char *opcode_0xfe[2][2][8] = { | 
| /*0*/   { "fadd",   DISASM_SNGL,  op2(STI,ST),  0 }, | /* 16bit */ | 
| /*1*/   { "fmul",   DISASM_SNGL,  op2(STI,ST),  0 }, | { | 
| /*2*/   { "fcom",   DISASM_SNGL,  op2(STI,ST),  0 }, | { "incb", "decb", NULL, NULL, NULL, NULL, NULL, NULL }, | 
| /*3*/   { "fcomp",  DISASM_SNGL,  op2(STI,ST),  0 }, | { "incw", "decw", "call", "callf", "jmp", "jmpf", "push", NULL } | 
| /*4*/   { "fsub",   DISASM_SNGL,  op2(STI,ST),  0 }, | }, | 
| /*5*/   { "fsubr",  DISASM_SNGL,  op2(STI,ST),  0 }, | /* 32bit */ | 
| /*6*/   { "fdiv",   DISASM_SNGL,  op2(STI,ST),  0 }, | { | 
| /*7*/   { "fdivr",  DISASM_SNGL,  op2(STI,ST),  0 }, | { "incb", "decb", NULL, NULL, NULL, NULL, NULL, NULL }, | 
|  | { "incl", "decl", "call", "callf", "jmp", "jmpf", "pushl", NULL } | 
|  | } | 
 | }; | }; | 
 |  |  | 
| const struct finst db_Esc9[] = { | static const char *opcode2_g6[8] = { | 
| /*0*/   { "fld",    DISASM_SNGL,  op1(STI),     0 }, | "sldt", "str", "lldt", "ltr", "verr", "verw", NULL, NULL | 
| /*1*/   { "",       DISASM_NONE,  op1(STI),     "fxch" }, |  | 
| /*2*/   { "fst",    DISASM_SNGL,  op1(X),       (char *)db_Esc92 }, |  | 
| /*3*/   { "fstp",   DISASM_SNGL,  op1(X),       (char *)db_Esc93 }, |  | 
| /*4*/   { "fldenv", DISASM_NONE,  op1(X),       (char *)db_Esc94 }, |  | 
| /*5*/   { "fldcw",  DISASM_NONE,  op1(X),       (char *)db_Esc95 }, |  | 
| /*6*/   { "fnstenv",DISASM_NONE,  op1(X),       (char *)db_Esc96 }, |  | 
| /*7*/   { "fnstcw", DISASM_NONE,  op1(X),       (char *)db_Esc97 }, |  | 
 | }; | }; | 
 |  |  | 
| const struct finst db_Esca[] = { | static const char *opcode2_g7[8] = { | 
| /*0*/   { "fiadd",  DISASM_WORD,  0,            0 }, | "sgdt", "sidt", "lgdt", "lidt", "smsw", NULL, "lmsw", "invlpg" | 
| /*1*/   { "fimul",  DISASM_WORD,  0,            0 }, |  | 
| /*2*/   { "ficom",  DISASM_WORD,  0,            0 }, |  | 
| /*3*/   { "ficomp", DISASM_WORD,  0,            0 }, |  | 
| /*4*/   { "fisub",  DISASM_WORD,  op1(X),       (char *)db_Esca4 }, |  | 
| /*5*/   { "fisubr", DISASM_WORD,  0,            0 }, |  | 
| /*6*/   { "fidiv",  DISASM_WORD,  0,            0 }, |  | 
| /*7*/   { "fidivr", DISASM_WORD,  0,            0 } |  | 
 | }; | }; | 
 |  |  | 
| const struct finst db_Escb[] = { | static const char *opcode2_g8[8] = { | 
| /*0*/   { "fild",   DISASM_WORD,  0,            0 }, | NULL, NULL, NULL, NULL, "bt", "bts", "btr", "btc" | 
| /*1*/   { "",       DISASM_NONE,  0,            0 }, |  | 
| /*2*/   { "fist",   DISASM_WORD,  0,            0 }, |  | 
| /*3*/   { "fistp",  DISASM_WORD,  0,            0 }, |  | 
| /*4*/   { "",       DISASM_WORD,  op1(X),       (char *)db_Escb4 }, |  | 
| /*5*/   { "fld",    DISASM_EXTR,  0,            0 }, |  | 
| /*6*/   { "",       DISASM_WORD,  0,            0 }, |  | 
| /*7*/   { "fstp",   DISASM_EXTR,  0,            0 }, |  | 
 | }; | }; | 
 |  |  | 
| const struct finst db_Escc[] = { | static const char *opcode2_g9[8] = { | 
| /*0*/   { "fadd",   DISASM_DBLR,  op2(ST,STI),  0 }, | NULL, "cmpxchg8b", NULL, NULL, NULL, NULL, NULL, NULL | 
| /*1*/   { "fmul",   DISASM_DBLR,  op2(ST,STI),  0 }, |  | 
| /*2*/   { "fcom",   DISASM_DBLR,  op2(ST,STI),  0 }, |  | 
| /*3*/   { "fcomp",  DISASM_DBLR,  op2(ST,STI),  0 }, |  | 
| /*4*/   { "fsub",   DISASM_DBLR,  op2(ST,STI),  "fsubr" }, |  | 
| /*5*/   { "fsubr",  DISASM_DBLR,  op2(ST,STI),  "fsub" }, |  | 
| /*6*/   { "fdiv",   DISASM_DBLR,  op2(ST,STI),  "fdivr" }, |  | 
| /*7*/   { "fdivr",  DISASM_DBLR,  op2(ST,STI),  "fdiv" }, |  | 
 | }; | }; | 
 |  |  | 
| const struct finst db_Escd[] = { | #if 0 | 
| /*0*/   { "fld",    DISASM_DBLR,  op1(STI),     "ffree" }, | static const char *sep[2] = { " ", ", " }; | 
| /*1*/   { "",       DISASM_NONE,  0,            0 }, | #endif | 
| /*2*/   { "fst",    DISASM_DBLR,  op1(STI),     0 }, |  | 
| /*3*/   { "fstp",   DISASM_DBLR,  op1(STI),     0 }, |  | 
| /*4*/   { "frstor", DISASM_NONE,  op1(STI),     "fucom" }, |  | 
| /*5*/   { "",       DISASM_NONE,  op1(STI),     "fucomp" }, |  | 
| /*6*/   { "fnsave", DISASM_NONE,  0,            0 }, |  | 
| /*7*/   { "fnstsw", DISASM_NONE,  0,            0 }, |  | 
| }; |  | 
 |  |  | 
 | const struct finst db_Esce[] = { |  | 
 | /*0*/   { "fiadd",  DISASM_LONG,  op2(ST,STI),  "faddp" }, |  | 
 | /*1*/   { "fimul",  DISASM_LONG,  op2(ST,STI),  "fmulp" }, |  | 
 | /*2*/   { "ficom",  DISASM_LONG,  0,            0 }, |  | 
 | /*3*/   { "ficomp", DISASM_LONG,  op1(X),       (char *)db_Esce3 }, |  | 
 | /*4*/   { "fisub",  DISASM_LONG,  op2(ST,STI),  "fsubrp" }, |  | 
 | /*5*/   { "fisubr", DISASM_LONG,  op2(ST,STI),  "fsubp" }, |  | 
 | /*6*/   { "fidiv",  DISASM_LONG,  op2(ST,STI),  "fdivrp" }, |  | 
 | /*7*/   { "fidivr", DISASM_LONG,  op2(ST,STI),  "fdivp" }, |  | 
 | }; |  | 
 |  |  | 
| const struct finst db_Escf[] = { | /* | 
| /*0*/   { "fild",   DISASM_LONG,  0,            0 }, | * fetch memory | 
| /*1*/   { "",       DISASM_LONG,  0,            0 }, | */ | 
| /*2*/   { "fist",   DISASM_LONG,  0,            0 }, | static int | 
| /*3*/   { "fistp",  DISASM_LONG,  0,            0 }, | convert_address(disasm_context_t *ctx) | 
| /*4*/   { "fbld",   DISASM_NONE,  op1(XA),      (char *)db_Escf4 }, | { | 
| /*5*/   { "fld",    DISASM_QUAD,  0,            0 }, | UINT32 pde_addr;        /* page directory entry address */ | 
| /*6*/   { "fbstp",  DISASM_NONE,  0,            0 }, | UINT32 pde;             /* page directory entry */ | 
| /*7*/   { "fstp",   DISASM_QUAD,  0,            0 }, | UINT32 pte_addr;        /* page table entry address */ | 
| }; | UINT32 pte;             /* page table entry */ | 
|  | UINT32 addr; | 
|  |  | 
|  | if (CPU_STAT_SREG(CPU_CS_INDEX).valid) { | 
|  | addr = CPU_STAT_SREGBASE(CPU_CS_INDEX) + ctx->eip; | 
|  | if (CPU_STAT_PAGING) { | 
|  | pde_addr = CPU_STAT_PDE_BASE + ((addr >> 20) & 0xffc); | 
|  | pde = cpu_memoryread_d(pde_addr); | 
|  | /* XXX: check */ | 
|  | pte_addr = (pde & CPU_PDE_BASEADDR_MASK) + ((addr >> 10) & 0xffc); | 
|  | pte = cpu_memoryread_d(pte_addr); | 
|  | /* XXX: check */ | 
|  | addr = (pte & CPU_PTE_BASEADDR_MASK) + (addr & 0x00000fff); | 
|  | } | 
|  | ctx->val = addr; | 
|  | return 0; | 
|  | } | 
|  | return 1; | 
|  | } | 
 |  |  | 
| const struct finst * const db_Esc_inst[] = { | static int | 
| db_Esc8, db_Esc9, db_Esca, db_Escb, | disasm_codefetch_1(disasm_context_t *ctx) | 
| db_Escc, db_Escd, db_Esce, db_Escf | { | 
| }; | UINT8 val; | 
|  | int rv; | 
 |  |  | 
| const char * const db_Grp1[] = { | rv = convert_address(ctx); | 
| "add", | if (rv) | 
| "or", | return rv; | 
| "adc", |  | 
| "sbb", |  | 
| "and", |  | 
| "sub", |  | 
| "xor", |  | 
| "cmp" |  | 
| }; |  | 
 |  |  | 
| const char * const db_Grp2[] = { | val = cpu_memoryread(ctx->val); | 
| "rol", | ctx->val = val; | 
| "ror", |  | 
| "rcl", |  | 
| "rcr", |  | 
| "shl", |  | 
| "shr", |  | 
| "shl", |  | 
| "sar" |  | 
| }; |  | 
 |  |  | 
| const struct inst db_Grp3[] = { | ctx->opbyte[ctx->nopbytes++] = (UINT8)ctx->val; | 
| { "test",  TRUE, DISASM_NONE, op2(I,E), 0 }, | ctx->eip++; | 
| { "test",  TRUE, DISASM_NONE, op2(I,E), 0 }, |  | 
| { "not",   TRUE, DISASM_NONE, op1(E),   0 }, |  | 
| { "neg",   TRUE, DISASM_NONE, op1(E),   0 }, |  | 
| { "mul",   TRUE, DISASM_NONE, op2(E,A), 0 }, |  | 
| { "imul",  TRUE, DISASM_NONE, op2(E,A), 0 }, |  | 
| { "div",   TRUE, DISASM_NONE, op2(E,A), 0 }, |  | 
| { "idiv",  TRUE, DISASM_NONE, op2(E,A), 0 }, |  | 
| }; |  | 
 |  |  | 
| const struct inst       db_Grp4[] = { | return 0; | 
| { "inc",   TRUE, DISASM_BYTE, op1(E),   0 }, | } | 
| { "dec",   TRUE, DISASM_BYTE, op1(E),   0 }, |  | 
| { "",      TRUE, DISASM_NONE, 0,         0 }, |  | 
| { "",      TRUE, DISASM_NONE, 0,         0 }, |  | 
| { "",      TRUE, DISASM_NONE, 0,         0 }, |  | 
| { "",      TRUE, DISASM_NONE, 0,         0 }, |  | 
| { "",      TRUE, DISASM_NONE, 0,         0 }, |  | 
| { "",      TRUE, DISASM_NONE, 0,         0 } |  | 
| }; |  | 
 |  |  | 
| const struct inst       db_Grp5[] = { | #if 0 | 
| { "inc",   TRUE, DISASM_LONG, op1(E),   0 }, | static int | 
| { "dec",   TRUE, DISASM_LONG, op1(E),   0 }, | disasm_codefetch_2(disasm_context_t *ctx) | 
| { "call",  TRUE, DISASM_NONE, op1(Eind),0 }, | { | 
| { "lcall", TRUE, DISASM_NONE, op1(Eind),0 }, | UINT16 val; | 
| { "jmp",   TRUE, DISASM_NONE, op1(Eind),0 }, | int rv; | 
| { "ljmp",  TRUE, DISASM_NONE, op1(Eind),0 }, |  | 
| { "push",  TRUE, DISASM_LONG, op1(E),   0 }, |  | 
| { "",      TRUE, DISASM_NONE, 0,         0 } |  | 
| }; |  | 
 |  |  | 
| const struct inst db_inst_table[256] = { | rv = disasm_codefetch_1(ctx); | 
| /*00*/  { "add",   TRUE,  DISASM_BYTE,  op2(R, E),  0 }, | if (rv) | 
| /*01*/  { "add",   TRUE,  DISASM_LONG,  op2(R, E),  0 }, | return rv; | 
| /*02*/  { "add",   TRUE,  DISASM_BYTE,  op2(E, R),  0 }, | val = (UINT16)(ctx->val & 0xff); | 
| /*03*/  { "add",   TRUE,  DISASM_LONG,  op2(E, R),  0 }, | rv = disasm_codefetch_1(ctx); | 
| /*04*/  { "add",   FALSE, DISASM_BYTE,  op2(Is, A), 0 }, | if (rv) | 
| /*05*/  { "add",   FALSE, DISASM_LONG,  op2(Is, A), 0 }, | return rv; | 
| /*06*/  { "push",  FALSE, DISASM_NONE,  op1(Si),    0 }, | val |= (UINT16)(ctx->val & 0xff) << 8; | 
| /*07*/  { "pop",   FALSE, DISASM_NONE,  op1(Si),    0 }, |  | 
|  |  | 
| /*08*/  { "or",    TRUE,  DISASM_BYTE,  op2(R, E),  0 }, |  | 
| /*09*/  { "or",    TRUE,  DISASM_LONG,  op2(R, E),  0 }, |  | 
| /*0a*/  { "or",    TRUE,  DISASM_BYTE,  op2(E, R),  0 }, |  | 
| /*0b*/  { "or",    TRUE,  DISASM_LONG,  op2(E, R),  0 }, |  | 
| /*0c*/  { "or",    FALSE, DISASM_BYTE,  op2(I, A),  0 }, |  | 
| /*0d*/  { "or",    FALSE, DISASM_LONG,  op2(I, A),  0 }, |  | 
| /*0e*/  { "push",  FALSE, DISASM_NONE,  op1(Si),    0 }, |  | 
| /*0f*/  { "",      FALSE, DISASM_NONE,  0,           0 }, |  | 
|  |  | 
| /*10*/  { "adc",   TRUE,  DISASM_BYTE,  op2(R, E),  0 }, |  | 
| /*11*/  { "adc",   TRUE,  DISASM_LONG,  op2(R, E),  0 }, |  | 
| /*12*/  { "adc",   TRUE,  DISASM_BYTE,  op2(E, R),  0 }, |  | 
| /*13*/  { "adc",   TRUE,  DISASM_LONG,  op2(E, R),  0 }, |  | 
| /*14*/  { "adc",   FALSE, DISASM_BYTE,  op2(Is, A), 0 }, |  | 
| /*15*/  { "adc",   FALSE, DISASM_LONG,  op2(Is, A), 0 }, |  | 
| /*16*/  { "push",  FALSE, DISASM_NONE,  op1(Si),    0 }, |  | 
| /*17*/  { "pop",   FALSE, DISASM_NONE,  op1(Si),    0 }, |  | 
|  |  | 
| /*18*/  { "sbb",   TRUE,  DISASM_BYTE,  op2(R, E),  0 }, |  | 
| /*19*/  { "sbb",   TRUE,  DISASM_LONG,  op2(R, E),  0 }, |  | 
| /*1a*/  { "sbb",   TRUE,  DISASM_BYTE,  op2(E, R),  0 }, |  | 
| /*1b*/  { "sbb",   TRUE,  DISASM_LONG,  op2(E, R),  0 }, |  | 
| /*1c*/  { "sbb",   FALSE, DISASM_BYTE,  op2(Is, A), 0 }, |  | 
| /*1d*/  { "sbb",   FALSE, DISASM_LONG,  op2(Is, A), 0 }, |  | 
| /*1e*/  { "push",  FALSE, DISASM_NONE,  op1(Si),    0 }, |  | 
| /*1f*/  { "pop",   FALSE, DISASM_NONE,  op1(Si),    0 }, |  | 
|  |  | 
| /*20*/  { "and",   TRUE,  DISASM_BYTE,  op2(R, E),  0 }, |  | 
| /*21*/  { "and",   TRUE,  DISASM_LONG,  op2(R, E),  0 }, |  | 
| /*22*/  { "and",   TRUE,  DISASM_BYTE,  op2(E, R),  0 }, |  | 
| /*23*/  { "and",   TRUE,  DISASM_LONG,  op2(E, R),  0 }, |  | 
| /*24*/  { "and",   FALSE, DISASM_BYTE,  op2(I, A),  0 }, |  | 
| /*25*/  { "and",   FALSE, DISASM_LONG,  op2(I, A),  0 }, |  | 
| /*26*/  { "",      FALSE, DISASM_NONE,  0,           0 }, |  | 
| /*27*/  { "aaa",   FALSE, DISASM_NONE,  0,           0 }, |  | 
|  |  | 
| /*28*/  { "sub",   TRUE,  DISASM_BYTE,  op2(R, E),  0 }, |  | 
| /*29*/  { "sub",   TRUE,  DISASM_LONG,  op2(R, E),  0 }, |  | 
| /*2a*/  { "sub",   TRUE,  DISASM_BYTE,  op2(E, R),  0 }, |  | 
| /*2b*/  { "sub",   TRUE,  DISASM_LONG,  op2(E, R),  0 }, |  | 
| /*2c*/  { "sub",   FALSE, DISASM_BYTE,  op2(Is, A), 0 }, |  | 
| /*2d*/  { "sub",   FALSE, DISASM_LONG,  op2(Is, A), 0 }, |  | 
| /*2e*/  { "",      FALSE, DISASM_NONE,  0,           0 }, |  | 
| /*2f*/  { "das",   FALSE, DISASM_NONE,  0,           0 }, |  | 
|  |  | 
| /*30*/  { "xor",   TRUE,  DISASM_BYTE,  op2(R, E),  0 }, |  | 
| /*31*/  { "xor",   TRUE,  DISASM_LONG,  op2(R, E),  0 }, |  | 
| /*32*/  { "xor",   TRUE,  DISASM_BYTE,  op2(E, R),  0 }, |  | 
| /*33*/  { "xor",   TRUE,  DISASM_LONG,  op2(E, R),  0 }, |  | 
| /*34*/  { "xor",   FALSE, DISASM_BYTE,  op2(I, A),  0 }, |  | 
| /*35*/  { "xor",   FALSE, DISASM_LONG,  op2(I, A),  0 }, |  | 
| /*36*/  { "",      FALSE, DISASM_NONE,  0,           0 }, |  | 
| /*37*/  { "daa",   FALSE, DISASM_NONE,  0,           0 }, |  | 
|  |  | 
| /*38*/  { "cmp",   TRUE,  DISASM_BYTE,  op2(R, E),  0 }, |  | 
| /*39*/  { "cmp",   TRUE,  DISASM_LONG,  op2(R, E),  0 }, |  | 
| /*3a*/  { "cmp",   TRUE,  DISASM_BYTE,  op2(E, R),  0 }, |  | 
| /*3b*/  { "cmp",   TRUE,  DISASM_LONG,  op2(E, R),  0 }, |  | 
| /*3c*/  { "cmp",   FALSE, DISASM_BYTE,  op2(Is, A), 0 }, |  | 
| /*3d*/  { "cmp",   FALSE, DISASM_LONG,  op2(Is, A), 0 }, |  | 
| /*3e*/  { "",      FALSE, DISASM_NONE,  0,           0 }, |  | 
| /*3f*/  { "aas",   FALSE, DISASM_NONE,  0,           0 }, |  | 
|  |  | 
| /*40*/  { "inc",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*41*/  { "inc",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*42*/  { "inc",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*43*/  { "inc",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*44*/  { "inc",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*45*/  { "inc",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*46*/  { "inc",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*47*/  { "inc",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
|  |  | 
| /*48*/  { "dec",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*49*/  { "dec",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*4a*/  { "dec",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*4b*/  { "dec",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*4c*/  { "dec",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*4d*/  { "dec",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*4e*/  { "dec",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*4f*/  { "dec",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
|  |  | 
| /*50*/  { "push",  FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*51*/  { "push",  FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*52*/  { "push",  FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*53*/  { "push",  FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*54*/  { "push",  FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*55*/  { "push",  FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*56*/  { "push",  FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*57*/  { "push",  FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
|  |  | 
| /*58*/  { "pop",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*59*/  { "pop",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*5a*/  { "pop",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*5b*/  { "pop",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*5c*/  { "pop",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*5d*/  { "pop",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*5e*/  { "pop",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
| /*5f*/  { "pop",   FALSE, DISASM_LONG,  op1(Ri),    0 }, |  | 
|  |  | 
| /*60*/  { "pusha", FALSE, DISASM_LONG,  0,           0 }, |  | 
| /*61*/  { "popa",  FALSE, DISASM_LONG,  0,           0 }, |  | 
| /*62*/  { "bound", TRUE,  DISASM_LONG,  op2(E, R),  0 }, |  | 
| /*63*/  { "arpl",  TRUE,  DISASM_NONE,  op2(Ew,Rw), 0 }, |  | 
|  |  | 
| /*64*/  { "",      FALSE, DISASM_NONE,  0,           0 }, |  | 
| /*65*/  { "",      FALSE, DISASM_NONE,  0,           0 }, |  | 
| /*66*/  { "",      FALSE, DISASM_NONE,  0,           0 }, |  | 
| /*67*/  { "",      FALSE, DISASM_NONE,  0,           0 }, |  | 
|  |  | 
| /*68*/  { "push",  FALSE, DISASM_LONG,  op1(I),     0 }, |  | 
| /*69*/  { "imul",  TRUE,  DISASM_LONG,  op3(I,E,R), 0 }, |  | 
| /*6a*/  { "push",  FALSE, DISASM_LONG,  op1(Ib),    0 }, |  | 
| /*6b*/  { "imul",  TRUE,  DISASM_LONG,  op3(Ibs,E,R),0 }, |  | 
| /*6c*/  { "ins",   FALSE, DISASM_BYTE,  op2(DX, DI), 0 }, |  | 
| /*6d*/  { "ins",   FALSE, DISASM_LONG,  op2(DX, DI), 0 }, |  | 
| /*6e*/  { "outs",  FALSE, DISASM_BYTE,  op2(SI, DX), 0 }, |  | 
| /*6f*/  { "outs",  FALSE, DISASM_LONG,  op2(SI, DX), 0 }, |  | 
|  |  | 
| /*70*/  { "jo",    FALSE, DISASM_NONE,  op1(Db),     0 }, |  | 
| /*71*/  { "jno",   FALSE, DISASM_NONE,  op1(Db),     0 }, |  | 
| /*72*/  { "jb",    FALSE, DISASM_NONE,  op1(Db),     0 }, |  | 
| /*73*/  { "jnb",   FALSE, DISASM_NONE,  op1(Db),     0 }, |  | 
| /*74*/  { "jz",    FALSE, DISASM_NONE,  op1(Db),     0 }, |  | 
| /*75*/  { "jnz",   FALSE, DISASM_NONE,  op1(Db),     0 }, |  | 
| /*76*/  { "jbe",   FALSE, DISASM_NONE,  op1(Db),     0 }, |  | 
| /*77*/  { "jnbe",  FALSE, DISASM_NONE,  op1(Db),     0 }, |  | 
|  |  | 
| /*78*/  { "js",    FALSE, DISASM_NONE,  op1(Db),     0 }, |  | 
| /*79*/  { "jns",   FALSE, DISASM_NONE,  op1(Db),     0 }, |  | 
| /*7a*/  { "jp",    FALSE, DISASM_NONE,  op1(Db),     0 }, |  | 
| /*7b*/  { "jnp",   FALSE, DISASM_NONE,  op1(Db),     0 }, |  | 
| /*7c*/  { "jl",    FALSE, DISASM_NONE,  op1(Db),     0 }, |  | 
| /*7d*/  { "jnl",   FALSE, DISASM_NONE,  op1(Db),     0 }, |  | 
| /*7e*/  { "jle",   FALSE, DISASM_NONE,  op1(Db),     0 }, |  | 
| /*7f*/  { "jnle",  FALSE, DISASM_NONE,  op1(Db),     0 }, |  | 
|  |  | 
| /*80*/  { "",      TRUE,  DISASM_BYTE,  op2(I, E),   (char *)db_Grp1 }, |  | 
| /*81*/  { "",      TRUE,  DISASM_LONG,  op2(I, E),   (char *)db_Grp1 }, |  | 
| /*82*/  { "",      TRUE,  DISASM_BYTE,  op2(Is,E),   (char *)db_Grp1 }, |  | 
| /*83*/  { "",      TRUE,  DISASM_LONG,  op2(Ibs,E),  (char *)db_Grp1 }, |  | 
| /*84*/  { "test",  TRUE,  DISASM_BYTE,  op2(R, E),   0 }, |  | 
| /*85*/  { "test",  TRUE,  DISASM_LONG,  op2(R, E),   0 }, |  | 
| /*86*/  { "xchg",  TRUE,  DISASM_BYTE,  op2(R, E),   0 }, |  | 
| /*87*/  { "xchg",  TRUE,  DISASM_LONG,  op2(R, E),   0 }, |  | 
|  |  | 
| /*88*/  { "mov",   TRUE,  DISASM_BYTE,  op2(R, E),   0 }, |  | 
| /*89*/  { "mov",   TRUE,  DISASM_LONG,  op2(R, E),   0 }, |  | 
| /*8a*/  { "mov",   TRUE,  DISASM_BYTE,  op2(E, R),   0 }, |  | 
| /*8b*/  { "mov",   TRUE,  DISASM_LONG,  op2(E, R),   0 }, |  | 
| /*8c*/  { "mov",   TRUE,  DISASM_NONE,  op2(S, Ew),  0 }, |  | 
| /*8d*/  { "lea",   TRUE,  DISASM_LONG,  op2(E, R),   0 }, |  | 
| /*8e*/  { "mov",   TRUE,  DISASM_NONE,  op2(Ew, S),  0 }, |  | 
| /*8f*/  { "pop",   TRUE,  DISASM_LONG,  op1(E),      0 }, |  | 
|  |  | 
| /*90*/  { "nop",   FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*91*/  { "xchg",  FALSE, DISASM_LONG,  op2(A, Ri),  0 }, |  | 
| /*92*/  { "xchg",  FALSE, DISASM_LONG,  op2(A, Ri),  0 }, |  | 
| /*93*/  { "xchg",  FALSE, DISASM_LONG,  op2(A, Ri),  0 }, |  | 
| /*94*/  { "xchg",  FALSE, DISASM_LONG,  op2(A, Ri),  0 }, |  | 
| /*95*/  { "xchg",  FALSE, DISASM_LONG,  op2(A, Ri),  0 }, |  | 
| /*96*/  { "xchg",  FALSE, DISASM_LONG,  op2(A, Ri),  0 }, |  | 
| /*97*/  { "xchg",  FALSE, DISASM_LONG,  op2(A, Ri),  0 }, |  | 
|  |  | 
| /*98*/  { "cbw",   FALSE, DISASM_SDEP,  0,            "cwde" }, /* cbw/cwde */ |  | 
| /*99*/  { "cwd",   FALSE, DISASM_SDEP,  0,            "cdq"  }, /* cwd/cdq */ |  | 
| /*9a*/  { "lcall", FALSE, DISASM_NONE,  op1(OS),     0 }, |  | 
| /*9b*/  { "wait",  FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*9c*/  { "pushf", FALSE, DISASM_LONG,  0,            0 }, |  | 
| /*9d*/  { "popf",  FALSE, DISASM_LONG,  0,            0 }, |  | 
| /*9e*/  { "sahf",  FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*9f*/  { "lahf",  FALSE, DISASM_NONE,  0,            0 }, |  | 
|  |  | 
| /*a0*/  { "mov",   FALSE, DISASM_BYTE,  op2(O, A),   0 }, |  | 
| /*a1*/  { "mov",   FALSE, DISASM_LONG,  op2(O, A),   0 }, |  | 
| /*a2*/  { "mov",   FALSE, DISASM_BYTE,  op2(A, O),   0 }, |  | 
| /*a3*/  { "mov",   FALSE, DISASM_LONG,  op2(A, O),   0 }, |  | 
| /*a4*/  { "movs",  FALSE, DISASM_BYTE,  op2(SI,DI),  0 }, |  | 
| /*a5*/  { "movs",  FALSE, DISASM_LONG,  op2(SI,DI),  0 }, |  | 
| /*a6*/  { "cmps",  FALSE, DISASM_BYTE,  op2(SI,DI),  0 }, |  | 
| /*a7*/  { "cmps",  FALSE, DISASM_LONG,  op2(SI,DI),  0 }, |  | 
|  |  | 
| /*a8*/  { "test",  FALSE, DISASM_BYTE,  op2(I, A),   0 }, |  | 
| /*a9*/  { "test",  FALSE, DISASM_LONG,  op2(I, A),   0 }, |  | 
| /*aa*/  { "stos",  FALSE, DISASM_BYTE,  op1(DI),     0 }, |  | 
| /*ab*/  { "stos",  FALSE, DISASM_LONG,  op1(DI),     0 }, |  | 
| /*ac*/  { "lods",  FALSE, DISASM_BYTE,  op1(SI),     0 }, |  | 
| /*ad*/  { "lods",  FALSE, DISASM_LONG,  op1(SI),     0 }, |  | 
| /*ae*/  { "scas",  FALSE, DISASM_BYTE,  op1(SI),     0 }, |  | 
| /*af*/  { "scas",  FALSE, DISASM_LONG,  op1(SI),     0 }, |  | 
|  |  | 
| /*b0*/  { "mov",   FALSE, DISASM_BYTE,  op2(I, Ri),  0 }, |  | 
| /*b1*/  { "mov",   FALSE, DISASM_BYTE,  op2(I, Ri),  0 }, |  | 
| /*b2*/  { "mov",   FALSE, DISASM_BYTE,  op2(I, Ri),  0 }, |  | 
| /*b3*/  { "mov",   FALSE, DISASM_BYTE,  op2(I, Ri),  0 }, |  | 
| /*b4*/  { "mov",   FALSE, DISASM_BYTE,  op2(I, Ri),  0 }, |  | 
| /*b5*/  { "mov",   FALSE, DISASM_BYTE,  op2(I, Ri),  0 }, |  | 
| /*b6*/  { "mov",   FALSE, DISASM_BYTE,  op2(I, Ri),  0 }, |  | 
| /*b7*/  { "mov",   FALSE, DISASM_BYTE,  op2(I, Ri),  0 }, |  | 
|  |  | 
| /*b8*/  { "mov",   FALSE, DISASM_LONG,  op2(I, Ri),  0 }, |  | 
| /*b9*/  { "mov",   FALSE, DISASM_LONG,  op2(I, Ri),  0 }, |  | 
| /*ba*/  { "mov",   FALSE, DISASM_LONG,  op2(I, Ri),  0 }, |  | 
| /*bb*/  { "mov",   FALSE, DISASM_LONG,  op2(I, Ri),  0 }, |  | 
| /*bc*/  { "mov",   FALSE, DISASM_LONG,  op2(I, Ri),  0 }, |  | 
| /*bd*/  { "mov",   FALSE, DISASM_LONG,  op2(I, Ri),  0 }, |  | 
| /*be*/  { "mov",   FALSE, DISASM_LONG,  op2(I, Ri),  0 }, |  | 
| /*bf*/  { "mov",   FALSE, DISASM_LONG,  op2(I, Ri),  0 }, |  | 
|  |  | 
| /*c0*/  { "",      TRUE,  DISASM_BYTE,  op2(Ib, E),  (char *)db_Grp2 }, |  | 
| /*c1*/  { "",      TRUE,  DISASM_LONG,  op2(Ib, E),  (char *)db_Grp2 }, |  | 
| /*c2*/  { "ret",   FALSE, DISASM_NONE,  op1(Iw),     0 }, |  | 
| /*c3*/  { "ret",   FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*c4*/  { "les",   TRUE,  DISASM_LONG,  op2(E, R),   0 }, |  | 
| /*c5*/  { "lds",   TRUE,  DISASM_LONG,  op2(E, R),   0 }, |  | 
| /*c6*/  { "mov",   TRUE,  DISASM_BYTE,  op2(I, E),   0 }, |  | 
| /*c7*/  { "mov",   TRUE,  DISASM_LONG,  op2(I, E),   0 }, |  | 
|  |  | 
| /*c8*/  { "enter", FALSE, DISASM_NONE,  op2(Ib, Iw), 0 }, |  | 
| /*c9*/  { "leave", FALSE, DISASM_NONE,  0,           0 }, |  | 
| /*ca*/  { "lret",  FALSE, DISASM_NONE,  op1(Iw),     0 }, |  | 
| /*cb*/  { "lret",  FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*cc*/  { "int",   FALSE, DISASM_NONE,  op1(o3),     0 }, |  | 
| /*cd*/  { "int",   FALSE, DISASM_NONE,  op1(Ib),     0 }, |  | 
| /*ce*/  { "into",  FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*cf*/  { "iret",  FALSE, DISASM_NONE,  0,            0 }, |  | 
|  |  | 
| /*d0*/  { "",      TRUE,  DISASM_BYTE,  op2(o1, E),  (char *)db_Grp2 }, |  | 
| /*d1*/  { "",      TRUE,  DISASM_LONG,  op2(o1, E),  (char *)db_Grp2 }, |  | 
| /*d2*/  { "",      TRUE,  DISASM_BYTE,  op2(CL, E),  (char *)db_Grp2 }, |  | 
| /*d3*/  { "",      TRUE,  DISASM_LONG,  op2(CL, E),  (char *)db_Grp2 }, |  | 
| /*d4*/  { "aam",   TRUE,  DISASM_NONE,  0,            0 }, |  | 
| /*d5*/  { "aad",   TRUE,  DISASM_NONE,  0,            0 }, |  | 
| /*d6*/  { "",      FALSE, DISASM_NONE,  0,            0 }, |  | 
| /*d7*/  { "xlat",  FALSE, DISASM_BYTE,  op1(BX),     0 }, |  | 
|  |  | 
| /*d8*/  { "",      TRUE,  DISASM_NONE,  0,            (char *)db_Esc8 }, |  | 
| /*d9*/  { "",      TRUE,  DISASM_NONE,  0,            (char *)db_Esc9 }, |  | 
| /*da*/  { "",      TRUE,  DISASM_NONE,  0,            (char *)db_Esca }, |  | 
| /*db*/  { "",      TRUE,  DISASM_NONE,  0,            (char *)db_Escb }, |  | 
| /*dc*/  { "",      TRUE,  DISASM_NONE,  0,            (char *)db_Escc }, |  | 
| /*dd*/  { "",      TRUE,  DISASM_NONE,  0,            (char *)db_Escd }, |  | 
| /*de*/  { "",      TRUE,  DISASM_NONE,  0,            (char *)db_Esce }, |  | 
| /*df*/  { "",      TRUE,  DISASM_NONE,  0,            (char *)db_Escf }, |  | 
|  |  | 
| /*e0*/  { "loopne",FALSE, DISASM_NONE,  op1(Db),     0 }, |  | 
| /*e1*/  { "loope", FALSE, DISASM_NONE,  op1(Db),     0 }, |  | 
| /*e2*/  { "loop",  FALSE, DISASM_NONE,  op1(Db),     0 }, |  | 
| /*e3*/  { "jcxz",  FALSE, DISASM_SDEP,  op1(Db),     "jecxz" }, |  | 
| /*e4*/  { "in",    FALSE, DISASM_BYTE,  op2(Ib, A),  0 }, |  | 
| /*e5*/  { "in",    FALSE, DISASM_LONG,  op2(Ib, A) , 0 }, |  | 
| /*e6*/  { "out",   FALSE, DISASM_BYTE,  op2(A, Ib),  0 }, |  | 
| /*e7*/  { "out",   FALSE, DISASM_LONG,  op2(A, Ib) , 0 }, |  | 
|  |  | 
| /*e8*/  { "call",  FALSE, DISASM_NONE,  op1(Dl),     0 }, |  | 
| /*e9*/  { "jmp",   FALSE, DISASM_NONE,  op1(Dl),     0 }, |  | 
| /*ea*/  { "ljmp",  FALSE, DISASM_NONE,  op1(OS),     0 }, |  | 
| /*eb*/  { "jmp",   FALSE, DISASM_NONE,  op1(Db),     0 }, |  | 
| /*ec*/  { "in",    FALSE, DISASM_BYTE,  op2(DX, A),  0 }, |  | 
| /*ed*/  { "in",    FALSE, DISASM_LONG,  op2(DX, A) , 0 }, |  | 
| /*ee*/  { "out",   FALSE, DISASM_BYTE,  op2(A, DX),  0 }, |  | 
| /*ef*/  { "out",   FALSE, DISASM_LONG,  op2(A, DX) , 0 }, |  | 
|  |  | 
| /*f0*/  { "",      FALSE, DISASM_NONE,  0,           0 }, |  | 
| /*f1*/  { "",      FALSE, DISASM_NONE,  0,           0 }, |  | 
| /*f2*/  { "",      FALSE, DISASM_NONE,  0,           0 }, |  | 
| /*f3*/  { "",      FALSE, DISASM_NONE,  0,           0 }, |  | 
| /*f4*/  { "hlt",   FALSE, DISASM_NONE,  0,           0 }, |  | 
| /*f5*/  { "cmc",   FALSE, DISASM_NONE,  0,           0 }, |  | 
| /*f6*/  { "",      TRUE,  DISASM_BYTE,  0,           (char *)db_Grp3 }, |  | 
| /*f7*/  { "",      TRUE,  DISASM_LONG,  0,           (char *)db_Grp3 }, |  | 
|  |  | 
| /*f8*/  { "clc",   FALSE, DISASM_NONE,  0,           0 }, |  | 
| /*f9*/  { "stc",   FALSE, DISASM_NONE,  0,           0 }, |  | 
| /*fa*/  { "cli",   FALSE, DISASM_NONE,  0,           0 }, |  | 
| /*fb*/  { "sti",   FALSE, DISASM_NONE,  0,           0 }, |  | 
| /*fc*/  { "cld",   FALSE, DISASM_NONE,  0,           0 }, |  | 
| /*fd*/  { "std",   FALSE, DISASM_NONE,  0,           0 }, |  | 
| /*fe*/  { "",      TRUE,  DISASM_NONE,  0,           (char *)db_Grp4 }, |  | 
| /*ff*/  { "",      TRUE,  DISASM_NONE,  0,           (char *)db_Grp5 }, |  | 
| }; |  | 
 |  |  | 
| const struct inst       db_bad_inst = | ctx->val = val; | 
| { "???",   FALSE, DISASM_NONE,  0,            0 } | return 0; | 
| ; | } | 
|  |  | 
| #define f_mod(byte)     ((byte)>>6) |  | 
| #define f_reg(byte)     (((byte)>>3)&0x7) |  | 
| #define f_rm(byte)      ((byte)&0x7) |  | 
|  |  | 
| #define sib_ss(byte)    ((byte)>>6) |  | 
| #define sib_index(byte) (((byte)>>3)&0x7) |  | 
| #define sib_base(byte)  ((byte)&0x7) |  | 
|  |  | 
| struct i_addr { |  | 
| int             is_reg; /* if reg, reg number is in 'disp' */ |  | 
| int             disp; |  | 
| const char *    base; |  | 
| const char *    index; |  | 
| int             ss; |  | 
| }; |  | 
 |  |  | 
| const char * const db_index_reg_16[8] = { | static int | 
| "%bx,%si", | disasm_codefetch_4(disasm_context_t *ctx) | 
| "%bx,%di", | { | 
| "%bp,%si", | UINT32 val; | 
| "%bp,%di", | int rv; | 
| "%si", |  | 
| "%di", |  | 
| "%bp", |  | 
| "%bx" |  | 
| }; |  | 
 |  |  | 
| const char * const db_reg[3][8] = { | rv = disasm_codefetch_1(ctx); | 
| { "%al",  "%cl",  "%dl",  "%bl",  "%ah",  "%ch",  "%dh",  "%bh" }, | if (rv) | 
| { "%ax",  "%cx",  "%dx",  "%bx",  "%sp",  "%bp",  "%si",  "%di" }, | return rv; | 
| { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi" } | val = ctx->val & 0xff; | 
| }; | rv = disasm_codefetch_1(ctx); | 
|  | if (rv) | 
|  | return rv; | 
|  | val |= (UINT32)(ctx->val & 0xff) << 8; | 
|  | rv = disasm_codefetch_1(ctx); | 
|  | if (rv) | 
|  | return rv; | 
|  | val |= (UINT32)(ctx->val & 0xff) << 16; | 
|  | rv = disasm_codefetch_1(ctx); | 
|  | if (rv) | 
|  | return rv; | 
|  | val |= (UINT32)(ctx->val & 0xff) << 24; | 
 |  |  | 
| const char * const db_seg_reg[8] = { | ctx->val = val; | 
| "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "", "" | return 0; | 
| }; | } | 
 |  |  | 
 | /* | /* | 
| * lengths for size attributes | * get effective address. | 
 | */ | */ | 
 | const int db_lengths[] = { |  | 
 | 1,      /* DISASM_BYTE */ |  | 
 | 2,      /* DISASM_WORD */ |  | 
 | 4,      /* DISASM_LONG */ |  | 
 | 8,      /* DISASM_QUAD */ |  | 
 | 4,      /* DISASM_SNGL */ |  | 
 | 8,      /* DISASM_DBLR */ |  | 
 | 10,     /* DISASM_EXTR */ |  | 
 | }; |  | 
 |  |  | 
| #define get_value_inc(result, cs, loc, size, is_signed) \ | static int | 
| do { \ | ea16(disasm_context_t *ctx, char *buf, size_t size) | 
| result = db_get_value((cs), (loc), (size), (is_signed)); \ | { | 
| (loc) += (size); \ | static const char *ea16_str[8] = { | 
| } while (0) | "bx + si", "bx + di", "bp + si", "bp + di", | 
|  | "si", "di", "bp", "bx" | 
|  | }; | 
|  | UINT32 val; | 
|  | UINT mod, rm; | 
|  | int rv; | 
|  |  | 
|  | mod = (ctx->modrm >> 6) & 3; | 
|  | rm = ctx->modrm & 7; | 
|  |  | 
|  | if (mod == 0) { | 
|  | if (rm == 6) { | 
|  | /* disp16 */ | 
|  | rv = disasm_codefetch_2(ctx); | 
|  | if (rv) | 
|  | return rv; | 
|  |  | 
|  | snprintf(buf, size, "[0x%04x]", ctx->val); | 
|  | } else { | 
|  | snprintf(buf, size, "[%s]", ea16_str[rm]); | 
|  | } | 
|  | } else { | 
|  | if (mod == 1) { | 
|  | /* disp8 */ | 
|  | rv = disasm_codefetch_1(ctx); | 
|  | if (rv) | 
|  | return rv; | 
|  |  | 
|  | val = ctx->val; | 
|  | if (val & 0x80) { | 
|  | val |= 0xff00; | 
|  | } | 
|  | } else { | 
|  | /* disp16 */ | 
|  | rv = disasm_codefetch_2(ctx); | 
|  | if (rv) | 
|  | return rv; | 
 |  |  | 
 |  | val = ctx->val; | 
 |  | } | 
 |  | snprintf(buf, size, "[%s + 0x%04x]", ea16_str[rm], val); | 
 |  | } | 
 |  |  | 
| static db_addr_t db_read_address(WORD, db_addr_t, int, int, struct i_addr *); | return 0; | 
| static void db_print_address(char *, int, struct i_addr *); | } | 
| static db_addr_t db_disasm_esc(WORD cs, db_addr_t, int, int, int, char *); |  | 
 |  |  | 
| /* | static int | 
| * Read address at location and return updated location. | ea32(disasm_context_t *ctx, char *buf, size_t size) | 
| */ | { | 
| static db_addr_t | char tmp[32]; | 
| db_read_address(cs, loc, short_addr, regmodrm, addrp) | UINT count[9]; | 
| WORD            cs; | UINT32 val; | 
| db_addr_t       loc; | UINT mod, rm; | 
| int             short_addr; | UINT sib; | 
| int             regmodrm; | UINT scale; | 
| struct i_addr   *addrp;         /* out */ | UINT idx; | 
| { | UINT base; | 
| int             mod, rm, sib, index, disp; | int rv; | 
|  | int i, n; | 
| mod = f_mod(regmodrm); |  | 
| rm  = f_rm(regmodrm); | memset(count, 0, sizeof(count)); | 
|  |  | 
| if (mod == 3) { | mod = (ctx->modrm >> 6) & 3; | 
| addrp->is_reg = TRUE; | rm = ctx->modrm & 7; | 
| addrp->disp = rm; |  | 
| return (loc); | /* SIB */ | 
|  | if (rm == 4) { | 
|  | rv = disasm_codefetch_1(ctx); | 
|  | if (rv) | 
|  | return rv; | 
|  |  | 
|  | sib = ctx->val; | 
|  | scale = (sib >> 6) & 3; | 
|  | idx = (sib >> 3) & 7; | 
|  | base = sib & 7; | 
|  |  | 
|  | /* base */ | 
|  | if (mod == 0 && base == 5) { | 
|  | /* disp32 */ | 
|  | rv = disasm_codefetch_4(ctx); | 
|  | if (rv) | 
|  | return rv; | 
|  | count[8] += ctx->val; | 
|  | } else { | 
|  | count[base]++; | 
|  | } | 
|  |  | 
|  | /* index & scale */ | 
|  | if (idx != 4) { | 
|  | count[idx] += 1 << scale; | 
|  | } | 
 | } | } | 
 | addrp->is_reg = FALSE; |  | 
 | addrp->index = 0; |  | 
 |  |  | 
| if (short_addr) { | /* MOD/RM */ | 
| addrp->index = 0; | if (mod == 0 && rm == 5) { | 
| addrp->ss = 0; | /* disp32 */ | 
| switch (mod) { | rv = disasm_codefetch_4(ctx); | 
| case 0: | if (rv) | 
| if (rm == 6) { | return rv; | 
| get_value_inc(disp, cs, loc, 2, TRUE); | count[8] += ctx->val; | 
| addrp->disp = disp; | } else { | 
| addrp->base = 0; | /* mod */ | 
| } else { | if (mod == 1) { | 
| addrp->disp = 0; | /* disp8 */ | 
| addrp->base = db_index_reg_16[rm]; | rv = disasm_codefetch_1(ctx); | 
|  | if (rv) | 
|  | return rv; | 
|  |  | 
|  | val = ctx->val; | 
|  | if (val & 0x80) { | 
|  | val |= 0xffffff00; | 
 | } | } | 
| break; | count[8] += val; | 
| case 1: | } else if (mod == 2) { | 
| get_value_inc(disp, cs, loc, 1, TRUE); | /* disp32 */ | 
| addrp->disp = disp; | rv = disasm_codefetch_4(ctx); | 
| addrp->base = db_index_reg_16[rm]; | if (rv) | 
| break; | return rv; | 
| case 2: | count[8] += ctx->val; | 
| get_value_inc(disp, cs, loc, 2, TRUE); |  | 
| addrp->disp = disp; |  | 
| addrp->base = db_index_reg_16[rm]; |  | 
| break; |  | 
 | } | } | 
| } else { |  | 
| if (mod != 3 && rm == 4) { | /* rm */ | 
| get_value_inc(sib, cs, loc, 1, FALSE); | if (rm != 4) { | 
| rm = sib_base(sib); | count[rm]++; | 
| index = sib_index(sib); |  | 
| if (index != 4) |  | 
| addrp->index = db_reg[DISASM_LONG][index]; |  | 
| addrp->ss = sib_ss(sib); |  | 
 | } | } | 
 |  | } | 
 |  |  | 
| switch (mod) { | milstr_ncpy(buf, "[", size); | 
| case 0: | for (n = 0, i = 0; i < 8; i++) { | 
| if (rm == 5) { | if (count[i] != 0) { | 
| get_value_inc(addrp->disp, cs, loc, 4, FALSE); | if (n > 0) { | 
| addrp->base = 0; | milstr_ncat(buf, " + ", size); | 
|  | } | 
|  | if (count[i] > 1) { | 
|  | snprintf(tmp, size, "%s * %d", | 
|  | reg32_str[i], count[i]); | 
 | } else { | } else { | 
| addrp->disp = 0; | milstr_ncpy(tmp, reg32_str[i], sizeof(tmp)); | 
| addrp->base = db_reg[DISASM_LONG][rm]; |  | 
 | } | } | 
| break; | milstr_ncat(buf, tmp, size); | 
| case 1: | n++; | 
| get_value_inc(disp, cs, loc, 1, TRUE); | } | 
| addrp->disp = disp; | } | 
| addrp->base = db_reg[DISASM_LONG][rm]; | if (count[8] != 0) { | 
| break; | if (n > 0) { | 
| case 2: | milstr_ncat(buf, " + ", size); | 
| get_value_inc(disp, cs, loc, 4, FALSE); |  | 
| addrp->disp = disp; |  | 
| addrp->base = db_reg[DISASM_LONG][rm]; |  | 
| break; |  | 
 | } | } | 
 |  | snprintf(tmp, sizeof(tmp), "0x%08x", count[8]); | 
 |  | milstr_ncat(buf, tmp, size); | 
 | } | } | 
| return (loc); | milstr_ncat(buf, "]", size); | 
|  |  | 
|  | return 0; | 
 | } | } | 
 |  |  | 
| static void | static int | 
| db_print_address(seg, size, addrp) | ea(disasm_context_t *ctx) | 
| char *          seg; | { | 
| int             size; | char buf[256]; | 
| struct i_addr   *addrp; | char tmp[8]; | 
| { | size_t len; | 
| if (addrp->is_reg) { | int rv; | 
| db_printf("%s", db_reg[size][addrp->disp]); |  | 
| return; |  | 
| } |  | 
 |  |  | 
| if (seg) | memset(buf, 0, sizeof(buf)); | 
| db_printf("%s:", seg); |  | 
 |  |  | 
| db_printsym((db_addr_t)addrp->disp, DB_STGY_ANY, db_printf); | if (!ctx->as32) | 
| if (addrp->base != 0 || addrp->index != 0) { | rv = ea16(ctx, buf, sizeof(buf)); | 
| db_printf("("); | else | 
| if (addrp->base) | rv = ea32(ctx, buf, sizeof(buf)); | 
| db_printf("%s", addrp->base); | if (rv) | 
| if (addrp->index) | return rv; | 
| db_printf(", %s, %d", addrp->index, 1<<addrp->ss); |  | 
| db_printf(")"); | if (ctx->narg == 0) { | 
|  | milstr_ncat(ctx->next, sep[0], ctx->remain); | 
|  | } else { | 
|  | milstr_ncat(ctx->next, sep[1], ctx->remain); | 
 | } | } | 
 |  | len = strlen(ctx->next); | 
 |  | len = (len < ctx->remain) ? len : ctx->remain; | 
 |  | ctx->next += len; | 
 |  | ctx->remain -= len; | 
 |  |  | 
 |  | ctx->arg[ctx->narg++] = ctx->next; | 
 |  | if (ctx->useseg) { | 
 |  | snprintf(tmp, sizeof(tmp), "%s:", sreg_str[ctx->seg]); | 
 |  | milstr_ncat(ctx->next, tmp, ctx->remain); | 
 |  | } | 
 |  | milstr_ncat(ctx->next, buf, ctx->remain); | 
 |  | len = strlen(ctx->next); | 
 |  | len = (len < ctx->remain) ? len : ctx->remain; | 
 |  | ctx->next += len; | 
 |  | ctx->remain -= len; | 
 |  |  | 
 |  | return 0; | 
 | } | } | 
 |  | #endif | 
 |  |  | 
 | /* | /* | 
| * Disassemble floating-point ("escape") instruction | * get opcode | 
| * and return updated location. |  | 
 | */ | */ | 
| static db_addr_t | static int | 
| db_disasm_esc(cs, loc, inst, short_addr, size, seg) | get_opcode(disasm_context_t *ctx) | 
| WORD            cs; | { | 
| db_addr_t       loc; | const char *opcode; | 
| int             inst; | UINT8 op[3]; | 
| int             short_addr; | int prefix; | 
| int             size; | size_t len; | 
| char *          seg; | int rv; | 
| { | int i; | 
| int             regmodrm; |  | 
| const struct finst      *fp; | for (prefix = 0; prefix < MAX_PREFIX; prefix++) { | 
| int             mod; | rv = disasm_codefetch_1(ctx); | 
| struct i_addr   address; | if (rv) | 
| char *          name; | return rv; | 
|  |  | 
| UNUSED(size); | op[0] = (UINT8)(ctx->val & 0xff); | 
|  | if (!(insttable_info[op[0]] & INST_PREFIX)) | 
| get_value_inc(regmodrm, cs, loc, 1, FALSE); |  | 
| fp = &db_Esc_inst[inst - 0xd8][f_reg(regmodrm)]; |  | 
| mod = f_mod(regmodrm); |  | 
| if (mod != 3) { |  | 
| /* |  | 
| * Normal address modes. |  | 
| */ |  | 
| loc = db_read_address(cs, loc, short_addr, regmodrm, &address); |  | 
| db_printf("%s", fp->f_name); |  | 
| switch(fp->f_size) { |  | 
| case DISASM_SNGL: |  | 
| db_printf("s"); |  | 
| break; |  | 
| case DISASM_DBLR: |  | 
| db_printf("l"); |  | 
| break; |  | 
| case DISASM_EXTR: |  | 
| db_printf("t"); |  | 
 | break; | break; | 
| case DISASM_WORD: |  | 
| db_printf("s"); | if (ctx->prefix == 0) | 
|  | ctx->prefix = ctx->next; | 
|  |  | 
|  | switch (op[0]) { | 
|  | case 0x26:      /* ES: */ | 
|  | case 0x2e:      /* CS: */ | 
|  | case 0x36:      /* SS: */ | 
|  | case 0x3e:      /* DS: */ | 
|  | ctx->useseg = TRUE; | 
|  | ctx->seg = (op[0] >> 3) & 3; | 
 | break; | break; | 
| case DISASM_LONG: |  | 
| db_printf("l"); | case 0x64:      /* FS: */ | 
|  | case 0x65:      /* GS: */ | 
|  | ctx->useseg = TRUE; | 
|  | ctx->seg = (op[0] - 0x64) + 4; | 
 | break; | break; | 
| case DISASM_QUAD: |  | 
| db_printf("q"); | case 0x66:      /* OPSize: */ | 
|  | ctx->op32 = !CPU_STATSAVE.cpu_inst_default.op_32; | 
 | break; | break; | 
| default: |  | 
|  | case 0x67:      /* AddrSize: */ | 
|  | ctx->as32 = !CPU_STATSAVE.cpu_inst_default.as_32; | 
 | break; | break; | 
 | } | } | 
| db_printf("\t"); | } | 
| db_print_address(seg, DISASM_BYTE, &address); | if (prefix == MAX_PREFIX) | 
| } else { | return 1; | 
| /* |  | 
| * 'reg-reg' - special formats | if (ctx->prefix) { | 
| */ | for (i = 0; i < prefix - 1; i++) { | 
| switch (fp->f_rrmode) { | opcode = opcode_1byte[ctx->op32][ctx->opbyte[i]]; | 
| case op2(ST,STI): | if (opcode) { | 
| name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; | milstr_ncat(ctx->next, opcode, ctx->remain); | 
| db_printf("%s\t%%st, %%st(%d)",name,f_rm(regmodrm)); | milstr_ncat(ctx->next, " ", ctx->remain); | 
| break; | } | 
| case op2(STI,ST): | } | 
| name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; | len = strlen(ctx->next); | 
| db_printf("%s\t%%st(%d), %%st",name, f_rm(regmodrm)); | len = (len < ctx->remain) ? len : ctx->remain; | 
|  | ctx->next += len; | 
|  | ctx->remain -= len; | 
|  | } | 
|  |  | 
|  | ctx->opcode[0] = op[0]; | 
|  | opcode = opcode_1byte[ctx->op32][op[0]]; | 
|  | if (opcode == NULL) { | 
|  | rv = disasm_codefetch_1(ctx); | 
|  | if (rv) | 
|  | return rv; | 
|  |  | 
|  | op[1] = (UINT8)(ctx->val & 0xff); | 
|  | ctx->opcode[1] = op[1]; | 
|  |  | 
|  | switch (op[0]) { | 
|  | case 0x0f: | 
|  | opcode = opcode_2byte[ctx->op32][op[1]]; | 
|  | if (opcode == NULL) { | 
|  | rv = disasm_codefetch_1(ctx); | 
|  | if (rv) | 
|  | return rv; | 
|  |  | 
|  | op[2] = (UINT8)(ctx->val & 0xff); | 
|  | ctx->opcode[2] = op[2]; | 
|  |  | 
|  | switch (op[1]) { | 
|  | case 0x00: | 
|  | opcode = opcode2_g6[(op[2]>>3)&7]; | 
|  | ctx->modrm = op[2]; | 
|  | break; | 
|  |  | 
|  | case 0x01: | 
|  | opcode = opcode2_g7[(op[2]>>3)&7]; | 
|  | ctx->modrm = op[2]; | 
|  | break; | 
|  |  | 
|  | case 0xba: | 
|  | opcode = opcode2_g8[(op[2]>>3)&7]; | 
|  | ctx->modrm = op[2]; | 
|  | break; | 
|  |  | 
|  | case 0xc7: | 
|  | opcode = opcode2_g9[(op[2]>>3)&7]; | 
|  | ctx->modrm = op[2]; | 
|  | break; | 
|  | } | 
|  | } | 
 | break; | break; | 
| case op1(STI): |  | 
| name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; | case 0x80: case 0x81: case 0x82: case 0x83: | 
| db_printf("%s\t%%st(%d)",name, f_rm(regmodrm)); | opcode = opcode_0x8x[ctx->op32][op[0]&1][(op[1]>>3)&7]; | 
|  | ctx->modrm = op[1]; | 
 | break; | break; | 
| case op1(X): |  | 
| db_printf("%s", ((char **)fp->f_rrname)[f_rm(regmodrm)]); | case 0xc0: case 0xc1: | 
|  | case 0xd0: case 0xd1: case 0xd2: case 0xd3: | 
|  | opcode = opcode_shift[ctx->op32][op[0]&1][(op[1]>>3)&7]; | 
|  | ctx->modrm = op[1]; | 
 | break; | break; | 
| case op1(XA): |  | 
| db_printf("%s\t%%ax", | case 0xf6: case 0xf7: | 
| ((char **)fp->f_rrname)[f_rm(regmodrm)]); | opcode = opcode_0xf6[ctx->op32][op[0]&1][(op[1]>>3)&7]; | 
|  | ctx->modrm = op[1]; | 
 | break; | break; | 
| default: |  | 
| db_printf("<bad instruction>"); | case 0xfe: case 0xff: | 
|  | opcode = opcode_0xfe[ctx->op32][op[0]&1][(op[1]>>3)&7]; | 
|  | ctx->modrm = op[1]; | 
 | break; | break; | 
 | } | } | 
 | } | } | 
 |  | if (opcode == NULL) | 
 |  | return 1; | 
 |  |  | 
| return (loc); | milstr_ncat(ctx->next, opcode, ctx->remain); | 
|  |  | 
|  | return 0; | 
 | } | } | 
 |  |  | 
 | /* | /* | 
| * Disassemble instruction at 'loc'.  'altfmt' specifies an | * interface | 
| * (optional) alternate format.  Return address of start of |  | 
| * next instruction. |  | 
 | */ | */ | 
| static db_addr_t | int | 
| db_disasm(cs, loc, altfmt) | disasm(UINT32 *eip, disasm_context_t *ctx) | 
| WORD            cs; | { | 
| db_addr_t       loc; | int rv; | 
| boolean_t       altfmt; |  | 
| { |  | 
| int     inst; |  | 
| int     size; |  | 
| int     short_addr; |  | 
| char *  seg; |  | 
| const struct inst *     ip; |  | 
| char *  i_name; |  | 
| int     i_size; |  | 
| int     i_mode; |  | 
| int     regmodrm = 0; |  | 
| boolean_t       first; |  | 
| int     displ; |  | 
| int     prefix; |  | 
| int     imm; |  | 
| int     imm2; |  | 
| int     len; |  | 
| struct i_addr   address; |  | 
|  |  | 
| UNUSED(altfmt); |  | 
|  |  | 
| get_value_inc(inst, cs, loc, 1, FALSE); |  | 
| short_addr = CPU_INST_OP32 ? FALSE : TRUE; |  | 
| size = short_addr ? DISASM_WORD : DISASM_LONG; |  | 
| seg = 0; |  | 
|  |  | 
| /* |  | 
| * Get prefixes |  | 
| */ |  | 
| prefix = TRUE; |  | 
| do { |  | 
| switch (inst) { |  | 
| case 0x66:          /* data16 */ |  | 
| size = short_addr ? DISASM_LONG : DISASM_WORD; |  | 
| break; |  | 
| case 0x67: |  | 
| short_addr = CPU_INST_OP32 ? TRUE : FALSE; |  | 
| break; |  | 
| case 0x26: |  | 
| seg = "%es"; |  | 
| break; |  | 
| case 0x36: |  | 
| seg = "%ss"; |  | 
| break; |  | 
| case 0x2e: |  | 
| seg = "%cs"; |  | 
| break; |  | 
| case 0x3e: |  | 
| seg = "%ds"; |  | 
| break; |  | 
| case 0x64: |  | 
| seg = "%fs"; |  | 
| break; |  | 
| case 0x65: |  | 
| seg = "%gs"; |  | 
| break; |  | 
| case 0xf0: |  | 
| db_printf("lock "); |  | 
| break; |  | 
| case 0xf2: |  | 
| db_printf("repne "); |  | 
| break; |  | 
| case 0xf3: |  | 
| db_printf("repe ");     /* XXX repe VS rep */ |  | 
| break; |  | 
| default: |  | 
| prefix = FALSE; |  | 
| break; |  | 
| } |  | 
| if (prefix) |  | 
| get_value_inc(inst, cs, loc, 1, FALSE); |  | 
| } while (prefix); |  | 
|  |  | 
| if (inst >= 0xd8 && inst <= 0xdf) { |  | 
| loc = db_disasm_esc(cs, loc, inst, short_addr, size, seg); |  | 
| db_printf("\n"); |  | 
| return (loc); |  | 
| } |  | 
 |  |  | 
| if (inst == 0x0f) { | memset(ctx, 0, sizeof(disasm_context_t)); | 
| get_value_inc(inst, cs, loc, 1, FALSE); | ctx->remain = sizeof(ctx->str) - 1; | 
| ip = db_inst_0f[inst>>4]; | ctx->next = ctx->str; | 
| if (ip == 0) | ctx->prefix = 0; | 
| ip = &db_bad_inst; | ctx->op = 0; | 
| else | ctx->arg[0] = 0; | 
| ip = &ip[inst&0xf]; | ctx->arg[1] = 0; | 
| } else { | ctx->arg[2] = 0; | 
| ip = &db_inst_table[inst]; |  | 
|  | ctx->eip = *eip; | 
|  | ctx->op32 = CPU_STATSAVE.cpu_inst_default.op_32; | 
|  | ctx->as32 = CPU_STATSAVE.cpu_inst_default.as_32; | 
|  | ctx->seg = -1; | 
|  |  | 
|  | ctx->baseaddr = ctx->eip; | 
|  | ctx->pad = ' '; | 
|  |  | 
|  | rv = get_opcode(ctx); | 
|  | if (rv) { | 
|  | memset(ctx, 0, sizeof(disasm_context_t)); | 
|  | return rv; | 
 | } | } | 
 |  | *eip = ctx->eip; | 
 |  |  | 
| if (ip->i_has_modrm) { | return 0; | 
| get_value_inc(regmodrm, cs, loc, 1, FALSE); | } | 
| loc = db_read_address(cs, loc, short_addr, regmodrm, &address); |  | 
| } |  | 
 |  |  | 
| i_name = ip->i_name; | char * | 
| i_size = ip->i_size; | cpu_disasm2str(UINT32 eip) | 
| i_mode = ip->i_mode; | { | 
|  | static char output[2048]; | 
| if (ip->i_extra == (char *)db_Grp1 || | disasm_context_t d; | 
| ip->i_extra == (char *)db_Grp2 || | UINT32 eip2 = eip; | 
| ip->i_extra == (char *)db_Grp6 || | int rv; | 
| ip->i_extra == (char *)db_Grp7 || |  | 
| ip->i_extra == (char *)db_Grp8) { | output[0] = '\0'; | 
| i_name = ((char **)ip->i_extra)[f_reg(regmodrm)]; | rv = disasm(&eip2, &d); | 
| } else if (ip->i_extra == (char *)db_Grp3) { | if (rv == 0) { | 
| ip = (struct inst *)ip->i_extra; | char buf[256]; | 
| ip = &ip[f_reg(regmodrm)]; | char tmp[32]; | 
| i_name = ip->i_name; | int len = d.nopbytes > 8 ? 8 : d.nopbytes; | 
| i_mode = ip->i_mode; | int i; | 
| } else if (ip->i_extra == (char *)db_Grp4 || |  | 
| ip->i_extra == (char *)db_Grp5) { | buf[0] = '\0'; | 
| ip = (struct inst *)ip->i_extra; | for (i = 0; i < len; i++) { | 
| ip = &ip[f_reg(regmodrm)]; | snprintf(tmp, sizeof(tmp), "%02x ", d.opbyte[i]); | 
| i_name = ip->i_name; | milstr_ncat(buf, tmp, sizeof(buf)); | 
| i_mode = ip->i_mode; | } | 
| i_size = ip->i_size; | for (; i < 8; i++) { | 
| } | milstr_ncat(buf, "   ", sizeof(buf)); | 
|  | } | 
|  | snprintf(output, sizeof(output), "%04x:%08x: %s%s", | 
|  | CPU_CS, eip, buf, d.str); | 
 |  |  | 
| if (i_size == DISASM_SDEP) { | if (i < d.nopbytes) { | 
| if (size == DISASM_WORD) | char t[256]; | 
| db_printf("%s", i_name); | buf[0] = '\0'; | 
| else | for (; i < d.nopbytes; i++) { | 
| db_printf("%s", ip->i_extra); | snprintf(tmp, sizeof(tmp), "%02x ", | 
| } else { | d.opbyte[i]); | 
| db_printf("%s", i_name); | milstr_ncat(buf, tmp, sizeof(buf)); | 
| if (i_size != DISASM_NONE) { | if ((i % 8) == 7) { | 
| if (i_size == DISASM_BYTE) { | snprintf(t, sizeof(t), | 
| db_printf("b"); | "\n             : %s", buf); | 
| size = DISASM_BYTE; | milstr_ncat(output, t, sizeof(output)); | 
| } else if (i_size == DISASM_WORD) { | buf[0] = '\0'; | 
| db_printf("w"); | } | 
| size = DISASM_WORD; | } | 
| } else if (size == DISASM_WORD) { | if ((i % 8) != 0) { | 
| db_printf("w"); | snprintf(t, sizeof(t), | 
| } else { | "\n             : %s", buf); | 
| db_printf("l"); | milstr_ncat(output, t, sizeof(output)); | 
 | } | } | 
 | } | } | 
 | } | } | 
| db_printf("\t"); | return output; | 
| for (first = TRUE; |  | 
| i_mode != 0; |  | 
| i_mode >>= 8, first = FALSE) { |  | 
| char tbuf[24]; |  | 
|  |  | 
| if (!first) |  | 
| db_printf(", "); |  | 
|  |  | 
| switch (i_mode & 0xFF) { |  | 
| case E: |  | 
| db_print_address(seg, size, &address); |  | 
| break; |  | 
| case Eind: |  | 
| db_printf("*"); |  | 
| db_print_address(seg, size, &address); |  | 
| break; |  | 
| case Ew: |  | 
| db_print_address(seg, DISASM_WORD, &address); |  | 
| break; |  | 
| case Eb: |  | 
| db_print_address(seg, DISASM_BYTE, &address); |  | 
| break; |  | 
| case R: |  | 
| db_printf("%s", db_reg[size][f_reg(regmodrm)]); |  | 
| break; |  | 
| case Rw: |  | 
| db_printf("%s", db_reg[DISASM_WORD][f_reg(regmodrm)]); |  | 
| break; |  | 
| case Ri: |  | 
| db_printf("%s", db_reg[size][f_rm(inst)]); |  | 
| break; |  | 
| case S: |  | 
| db_printf("%s", db_seg_reg[f_reg(regmodrm)]); |  | 
| break; |  | 
| case Si: |  | 
| db_printf("%s", db_seg_reg[f_reg(inst)]); |  | 
| break; |  | 
| case A: |  | 
| db_printf("%s", db_reg[size][0]);       /* acc */ |  | 
| break; |  | 
| case BX: |  | 
| if (seg) |  | 
| db_printf("%s:", seg); |  | 
| db_printf("(%s)", short_addr ? "%bx" : "%ebx"); |  | 
| break; |  | 
| case CL: |  | 
| db_printf("%%cl"); |  | 
| break; |  | 
| case DX: |  | 
| db_printf("%%dx"); |  | 
| break; |  | 
| case SI: |  | 
| if (seg) |  | 
| db_printf("%s:", seg); |  | 
| db_printf("(%s)", short_addr ? "%si" : "%esi"); |  | 
| break; |  | 
| case DI: |  | 
| db_printf("%%es:(%s)", short_addr ? "%di" : "%edi"); |  | 
| break; |  | 
| case CR: |  | 
| db_printf("%%cr%d", f_reg(regmodrm)); |  | 
| break; |  | 
| case DR: |  | 
| db_printf("%%dr%d", f_reg(regmodrm)); |  | 
| break; |  | 
| case TR: |  | 
| db_printf("%%tr%d", f_reg(regmodrm)); |  | 
| break; |  | 
| case I: |  | 
| len = db_lengths[size]; |  | 
| get_value_inc(imm, cs, loc, len, FALSE);/* unsigned */ |  | 
| db_format_radix(tbuf, 24, (unsigned int)imm, TRUE); |  | 
| db_printf("$%s", tbuf); |  | 
| break; |  | 
| case Is: |  | 
| len = db_lengths[size]; |  | 
| get_value_inc(imm, cs, loc, len, TRUE); /* signed */ |  | 
| db_format_radix(tbuf, 24, imm, TRUE); |  | 
| db_printf("$%s", tbuf); |  | 
| break; |  | 
| case Ib: |  | 
| get_value_inc(imm, cs, loc, 1, FALSE);  /* unsigned */ |  | 
| db_format_radix(tbuf, 24, (unsigned int)imm, TRUE); |  | 
| db_printf("$%s", tbuf); |  | 
| break; |  | 
| case Ibs: |  | 
| get_value_inc(imm, cs, loc, 1, TRUE);   /* signed */ |  | 
| db_format_radix(tbuf, 24, imm, TRUE); |  | 
| db_printf("$%s", tbuf); |  | 
| break; |  | 
| case Iw: |  | 
| get_value_inc(imm, cs, loc, 2, FALSE);  /* unsigned */ |  | 
| db_format_radix(tbuf, 24, (unsigned int)imm, TRUE); |  | 
| db_printf("$%s", tbuf); |  | 
| break; |  | 
| case Il: |  | 
| get_value_inc(imm, cs, loc, 4, FALSE); |  | 
| db_format_radix(tbuf, 24, (unsigned int)imm, TRUE); |  | 
| db_printf("$%s", tbuf); |  | 
| break; |  | 
| case O: |  | 
| if (short_addr) |  | 
| get_value_inc(displ, cs, loc, 2, TRUE); |  | 
| else |  | 
| get_value_inc(displ, cs, loc, 4, TRUE); |  | 
| if (seg) { |  | 
| db_format_radix(tbuf, 24, displ, TRUE); |  | 
| db_printf("%s:%s", seg, tbuf); |  | 
| } else |  | 
| db_printsym((db_addr_t)displ, DB_STGY_ANY, |  | 
| db_printf); |  | 
| break; |  | 
| case Db: |  | 
| get_value_inc(displ, cs, loc, 1, TRUE); |  | 
| db_printsym((db_addr_t)(displ + loc), DB_STGY_XTRN, |  | 
| db_printf); |  | 
| break; |  | 
| case Dl: |  | 
| get_value_inc(displ, cs, loc, 4, TRUE); |  | 
| db_printsym((db_addr_t)(displ + loc), DB_STGY_XTRN, |  | 
| db_printf); |  | 
| break; |  | 
| case o1: |  | 
| db_printf("$1"); |  | 
| break; |  | 
| case o3: |  | 
| db_printf("$3"); |  | 
| break; |  | 
| case OS: |  | 
| get_value_inc(imm, cs, loc, 4, FALSE);  /* offset */ |  | 
| db_format_radix(tbuf, 24, (unsigned int)imm, TRUE); |  | 
| db_printf("$%s", tbuf); |  | 
| get_value_inc(imm2, cs, loc, 2, FALSE); /* segment */ |  | 
| db_format_radix(tbuf, 24, (unsigned int)imm2, TRUE); |  | 
| db_printf(",%s", tbuf); |  | 
| break; |  | 
| } |  | 
| } |  | 
|  |  | 
| db_printf("\n"); |  | 
| return (loc); |  | 
| } |  | 
|  |  | 
| void |  | 
| disasm(WORD cs, DWORD loc) |  | 
| { |  | 
|  |  | 
| db_disasm(cs, loc, FALSE); |  | 
 | } | } |