| version 1.7, 2004/01/23 14:33:26 | version 1.27, 2012/01/08 11:32:16 | 
| Line 1 | Line 1 | 
 | /*      $Id$    */ |  | 
 |  |  | 
 | /* | /* | 
 | * Copyright (c) 2002-2003 NONAKA Kimihiro | * Copyright (c) 2002-2003 NONAKA Kimihiro | 
 | * All rights reserved. | * All rights reserved. | 
| Line 12 | Line 10 | 
 | * 2. Redistributions in binary form must reproduce the above copyright | * 2. Redistributions in binary form must reproduce the above copyright | 
 | *    notice, this list of conditions and the following disclaimer in the | *    notice, this list of conditions and the following disclaimer in the | 
 | *    documentation and/or other materials provided with the distribution. | *    documentation and/or other materials provided with the distribution. | 
 | * 3. The name of the author may not be used to endorse or promote products |  | 
 | *    derived from this software without specific prior written permission. |  | 
 | * | * | 
 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 
 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 
| Line 28 | Line 24 | 
 | */ | */ | 
 |  |  | 
 | #include "compiler.h" | #include "compiler.h" | 
 |  | #include "dosio.h" | 
 | #include "cpu.h" | #include "cpu.h" | 
 | #include "ia32.mcr" | #include "ia32.mcr" | 
 |  |  | 
 | #include "inst_table.h" | #include "inst_table.h" | 
 |  |  | 
 |  | #if defined(ENABLE_TRAP) | 
 |  | #include "steptrap.h" | 
 |  | #endif | 
 |  |  | 
 | #if defined(IA32_INSTRUCTION_TRACE) |  | 
 | static FILE *fp = NULL; |  | 
 | BOOL cpu_inst_trace = FALSE; |  | 
 |  |  | 
 | static const char *opcode_1byte[2][256] = { |  | 
 | /* 16bit */ |  | 
 | { |  | 
 | /*00*/  "addb",  "addw",  "addb",  "addw",  "addb",  "addw",  "push",  "pop", |  | 
 | "orb",   "orw",   "orb",   "orw",   "orb",   "orw",   "push",  NULL, |  | 
 | /*10*/  "adcb",  "adcw",  "adcb",  "adcw",  "adcb",  "adcw",  "push",  "pop", |  | 
 | "sbbb",  "sbbw",  "sbbb",  "sbbw",  "sbbb",  "sbbw",  "push",  "pop", |  | 
 | /*20*/  "andb",  "andw",  "andb",  "andw",  "andb",  "andw",  "es:",   "daa", |  | 
 | "subb",  "subw",  "subb",  "subw",  "subb",  "subw",  "cs:",   "das", |  | 
 | /*30*/  "xorb",  "xorw",  "xorb",  "xorw",  "xorb",  "xorw",  "ss:",   "aaa", |  | 
 | "cmpb",  "cmpw",  "cmpb",  "cmpw",  "cmpb",  "cmpw",  "ds:",   "aas", |  | 
 | /*40*/  "incw",  "incw",  "incw",  "incw",  "incw",  "incw",  "incw",  "incw", |  | 
 | "decw",  "decw",  "decw",  "decw",  "decw",  "decw",  "decw",  "decw", |  | 
 | /*50*/  "push",  "push",  "push",  "push",  "push",  "push",  "push",  "push", |  | 
 | "pop",   "pop",   "pop",   "pop",   "pop",   "pop",   "pop",   "pop", |  | 
 | /*60*/  "pusha", "popa",  "bound", "arpl",  "fs:",   "gs:",   NULL,    NULL, |  | 
 | "push",  "imul",  "push",  "imul",  "insb",  "insw",  "outsb", "outsw", |  | 
 | /*70*/  "jo",    "jno",   "jc",    "jnc",   "jz",    "jnz",   "jna",   "ja", |  | 
 | "js",    "jns",   "jp",    "jnp",   "jl",    "jnl",   "jle",   "jnle", |  | 
 | /*80*/  NULL,    NULL,    NULL,    NULL,    "testb", "testw", "xchgb", "xchgw", |  | 
 | "movb",  "movw",  "movb",  "movw",  "movw",  "lea",   "movw",  "pop", |  | 
 | /*90*/  "nop",   "xchgw", "xchgw", "xchgw", "xchgw", "xchgw", "xchgw", "xchgw", |  | 
 | "cbw",   "cwd",   "callf", "fwait", "pushf", "popf",  "sahf",  "lahf", |  | 
 | /*a0*/  "movb",  "movw",  "movb",  "movw",  "movsb", "movsw", "cmpsb", "cmpsw", |  | 
 | "testb", "testw", "stosb", "stosw", "lodsb", "lodsw", "scasb", "scasw", |  | 
 | /*b0*/  "movb",  "movb",  "movb",  "movb",  "movb",  "movb",  "movb",  "movb", |  | 
 | "movw",  "movw",  "movw",  "movw",  "movw",  "movw",  "movw",  "movw", |  | 
 | /*c0*/  NULL,    NULL,    "ret",   "ret",   "les",   "lds",   "movb",  "movw", |  | 
 | "enter", "leave", "retf",  "retf",  "int3",  "int",   "into",  "iret", |  | 
 | /*d0*/  NULL,    NULL,    NULL,    NULL,    "aam",   "aad",   "salc",  "xlat", |  | 
 | "esc0",  "esc1",  "esc2",  "esc3",  "esc4",  "esc5",  "esc6",  "esc7", |  | 
 | /*e0*/  "loopne","loope", "loop",  "jcxz",  "inb",   "inw",   "outb",  "outw", |  | 
 | "call",  "jmp",   "jmpf",  "jmp",   "inb",   "inw",   "outb",  "outw", |  | 
 | /*f0*/  "lock:", "int1",  "repne", "repe",  "hlt",   "cmc",   NULL,    NULL, |  | 
 | "clc",   "stc",   "cli",   "sti",   "cld",   "std",   NULL,    NULL, |  | 
 | }, |  | 
 | /* 32bit */ |  | 
 | { |  | 
 | /*00*/  "addb",  "addl",  "addb",  "addl",  "addb",  "addl",  "pushl", "popl", |  | 
 | "orb",   "orl",   "orb",   "orl",   "orb",   "orl",   "pushl", NULL, |  | 
 | /*10*/  "adcb",  "adcl",  "adcb",  "adcl",  "adcb",  "adcl",  "pushl", "popl", |  | 
 | "sbbb",  "sbbl",  "sbbb",  "sbbl",  "sbbb",  "sbbl",  "pushl", "popl", |  | 
 | /*20*/  "andb",  "andl",  "andb",  "andl",  "andb",  "andl",  "es:",   "daa", |  | 
 | "subb",  "subl",  "subb",  "subl",  "subb",  "subl",  "cs:",   "das", |  | 
 | /*30*/  "xorb",  "xorl",  "xorb",  "xorl",  "xorb",  "xorl",  "ss:",   "aaa", |  | 
 | "cmpb",  "cmpl",  "cmpb",  "cmpl",  "cmpb",  "cmpl",  "ds:",   "aas", |  | 
 | /*40*/  "incl",  "incl",  "incl",  "incl",  "incl",  "incl",  "incl",  "incl", |  | 
 | "decl",  "decl",  "decl",  "decl",  "decl",  "decl",  "decl",  "decl", |  | 
 | /*50*/  "pushl", "pushl", "pushl", "pushl", "pushl", "pushl", "pushl", "pushl", |  | 
 | "popl",  "popl",  "popl",  "popl",  "popl",  "popl",  "popl",  "pop", |  | 
 | /*60*/  "pushad","popad", "bound", "arpl",  "fs:",   "gs:",   NULL,    NULL, |  | 
 | "pushl", "imul",  "pushl", "imul",  "insb",  "insl",  "outsb", "outsl", |  | 
 | /*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", |  | 
 | "movb",  "movl",  "movb",  "movl",  "movl",  "lea",   "movl",  "popl", |  | 
 | /*90*/  "nop",   "xchgl", "xchgl", "xchgl", "xchgl", "xchgl", "xchgl", "xchgl", |  | 
 | "cwde",  "cdq",   "callfl","fwait", "pushfd","popfd", "sahf",  "lahf", |  | 
 | /*a0*/  "movb",  "movl",  "movb",  "movl",  "movsb", "movsd", "cmpsb", "cmpsd", |  | 
 | "testb", "testl", "stosb", "stosd", "lodsb", "lodsd", "scasb", "scasd", |  | 
 | /*b0*/  "movb",  "movb",  "movb",  "movb",  "movb",  "movb",  "movb",  "movb", |  | 
 | "movl",  "movl",  "movl",  "movl",  "movl",  "movl",  "movl",  "movl", |  | 
 | /*c0*/  NULL,    NULL,    "ret",   "ret",   "les",   "lds",   "movb",  "movl", |  | 
 | "enter", "leave", "retfd", "retfd", "int3",  "int",   "into",  "iretd", |  | 
 | /*d0*/  NULL,    NULL,    NULL,    NULL,    "aam",   "aad",   "salc",  "xlat", |  | 
 | "esc0",  "esc1",  "esc2",  "esc3",  "esc4",  "esc5",  "esc6",  "esc7", |  | 
 | /*e0*/  "loopne","loope", "loop",  "jecxz", "inb",   "inl",   "outb",  "outl", |  | 
 | "call",  "jmp",   "jmpf",  "jmp",   "inb",   "inl",   "outb",  "outl", |  | 
 | /*f0*/  "lock:", "int1",  "repne", "repe",  "hlt",   "cmc",   NULL,    NULL, |  | 
 | "clc",   "stc",   "cli",   "sti",   "cld",   "std",   NULL,    NULL, |  | 
 | } |  | 
 | }; |  | 
 |  |  | 
 | static const char *opcode_2byte[2][256] = { |  | 
 | /* 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, |  | 
 | } |  | 
 | }; |  | 
 |  |  | 
 | static const char *opcode_0x8x[2][2][8] = { |  | 
 | /* 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" } |  | 
 | } |  | 
 | }; |  | 
 |  |  | 
| static const char *opcode_shift[2][2][8] = { | sigjmp_buf exec_1step_jmpbuf; | 
| /* 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" } |  | 
| }, |  | 
| }; |  | 
 |  |  | 
| static const char *opcode_0xf6[2][2][8] = { | #if defined(IA32_INSTRUCTION_TRACE) | 
| /* 16bit */ | typedef struct { | 
| { | CPU_REGS                regs; | 
| { "testb", "testb", "notb", "negb", "mul", "imul", "div", "idiv" }, | disasm_context_t        disasm; | 
| { "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" } |  | 
| }, |  | 
| }; |  | 
 |  |  | 
| static const char *opcode_0xfe[2][2][8] = { | BYTE                    op[MAX_PREFIX + 2]; | 
| /* 16bit */ | int                     opbytes; | 
| { | } ia32_context_t; | 
| { "incb", "decb", NULL, NULL, NULL, NULL, NULL, NULL }, |  | 
| { "incw", "decw", "call", "callf", "jmp", "jmpf", "push", NULL } |  | 
| }, |  | 
| /* 32bit */ |  | 
| { |  | 
| { "incb", "decb", NULL, NULL, NULL, NULL, NULL, NULL }, |  | 
| { "incl", "decl", "call", "callf", "jmp", "jmpf", "pushl", NULL } |  | 
| } |  | 
| }; |  | 
 |  |  | 
| static const char *opcode2_g6[8] = { | #define NCTX    1024 | 
| "sldt", "str", "lldt", "ltr", "verr", "verw", NULL, NULL |  | 
| }; |  | 
 |  |  | 
| static const char *opcode2_g7[8] = { | ia32_context_t ctx[NCTX]; | 
| "sgdt", "sidt", "lgdt", "lidt", "smsw", NULL, "lmsw", "invlpg" | int ctx_index = 0; | 
| }; |  | 
 |  |  | 
| static const char *opcode2_g8[8] = { | int cpu_inst_trace = 0; | 
| NULL, NULL, NULL, NULL, "bt", "bts", "btr", "btc" | #endif | 
| }; |  | 
 |  |  | 
| static const char *opcode2_g9[8] = { | #if defined(DEBUG) | 
| NULL, "cmpxchg8b", NULL, NULL, NULL, NULL, NULL, NULL | int cpu_debug_rep_cont = 0; | 
| }; | CPU_REGS cpu_debug_rep_regs; | 
|  | #endif | 
 |  |  | 
 |  |  | 
| static DWORD | void | 
| ea(DWORD eip, DWORD op) | exec_1step(void) | 
 | { | { | 
| static const char *ea16[8] = { | int prefix; | 
| "bx + si", "bx + di", "bp + si", "bp + di", | UINT32 op; | 
| "si", "di", "bp", "bx" |  | 
| }; |  | 
|  |  | 
| char buf[256]; |  | 
| DWORD mod = (op >> 6) & 3; |  | 
| DWORD rm = op & 7; |  | 
| DWORD val; |  | 
|  |  | 
| __ASSERT(mod != 3); |  | 
|  |  | 
| buf[0] = '\0'; |  | 
 |  |  | 
| if (!CPU_INST_AS32) { | CPU_PREV_EIP = CPU_EIP; | 
| if (mod == 0) { | CPU_STATSAVE.cpu_inst = CPU_STATSAVE.cpu_inst_default; | 
| if (rm == 6) { |  | 
| /* disp16 */ |  | 
| val = cpu_codefetch_w(eip); |  | 
| eip += 2; |  | 
| SPRINTF(buf, "0x%04x", val); |  | 
| } else { |  | 
| SPRINTF(buf, "%s", ea16[rm]); |  | 
| } |  | 
| } else { |  | 
| if (mod == 1) { |  | 
| /* disp8 */ |  | 
| val = cpu_codefetch(eip); |  | 
| if (val & 0x80) { |  | 
| val |= 0xff00; |  | 
| } |  | 
| eip++; |  | 
| } else { |  | 
| /* disp16 */ |  | 
| val = cpu_codefetch_w(eip); |  | 
| eip += 2; |  | 
| } |  | 
| SPRINTF(buf, "%s + 0x%04x", ea16[rm], val); |  | 
| } |  | 
| } else { |  | 
| char tmp[32]; |  | 
| BYTE count[9]; |  | 
| int n; |  | 
| int i; |  | 
 |  |  | 
| ZeroMemory(count, sizeof(count)); | #if defined(ENABLE_TRAP) | 
|  | steptrap(CPU_CS, CPU_EIP); | 
|  | #endif | 
 |  |  | 
| if (rm == 5) { | #if defined(IA32_INSTRUCTION_TRACE) | 
| DWORD sib; | ctx[ctx_index].regs = CPU_STATSAVE.cpu_regs; | 
| DWORD scale; | if (cpu_inst_trace) { | 
| DWORD idx; | disasm_context_t *d = &ctx[ctx_index].disasm; | 
| DWORD base; | UINT32 eip = CPU_EIP; | 
|  | int rv; | 
| sib = cpu_codefetch(eip); |  | 
| eip++; | rv = disasm(&eip, d); | 
|  | if (rv == 0) { | 
| scale = (sib >> 6) & 3; | char buf[256]; | 
| idx = (sib >> 3) & 7; | char tmp[32]; | 
| base = sib & 7; | int len = d->nopbytes > 8 ? 8 : d->nopbytes; | 
|  | int i; | 
| if (base == 5 && mod == 0) { |  | 
| val = cpu_codefetch_d(eip); | buf[0] = '\0'; | 
| eip += 4; | for (i = 0; i < len; i++) { | 
| count[8] += val; | snprintf(tmp, sizeof(tmp), "%02x ", d->opbyte[i]); | 
| } else { | milstr_ncat(buf, tmp, sizeof(buf)); | 
| count[base]++; |  | 
 | } | } | 
| if (idx != 4) { | for (; i < 8; i++) { | 
| count[idx] += 1 << scale; | milstr_ncat(buf, "   ", sizeof(buf)); | 
 | } | } | 
| } | VERBOSE(("%04x:%08x: %s%s", CPU_CS, CPU_EIP, buf, d->str)); | 
 |  |  | 
| if (rm == 6 && mod == 0) { | buf[0] = '\0'; | 
| /* disp32 */ | for (; i < d->nopbytes; i++) { | 
| val = cpu_codefetch_d(eip); | snprintf(tmp, sizeof(tmp), "%02x ", d->opbyte[i]); | 
| eip += 4; | milstr_ncat(buf, tmp, sizeof(buf)); | 
| count[8] += val; | if ((i % 8) == 7) { | 
| } else { | VERBOSE(("             : %s", buf)); | 
| if (mod == 1) { | buf[0] = '\0'; | 
| /* disp8 */ |  | 
| val = cpu_codefetch(eip); |  | 
| eip++; |  | 
| if (val & 0x80) { |  | 
| val |= 0xffffff00; |  | 
 | } | } | 
 | count[8] += val; |  | 
 | } else if (mod == 2) { |  | 
 | /* disp32 */ |  | 
 | val = cpu_codefetch_d(eip); |  | 
 | eip += 4; |  | 
 | count[8] += val; |  | 
 | } | } | 
| if (rm != 5) { | if ((i % 8) != 0) { | 
| count[rm]++; | VERBOSE(("             : %s", buf)); | 
 | } | } | 
 | } | } | 
 |  | } | 
 |  | ctx[ctx_index].opbytes = 0; | 
 |  | #endif | 
 |  |  | 
| n = 0; | #if defined(IA32_SUPPORT_DEBUG_REGISTER) | 
| for (i = 0; i < 8; i++) { | if (CPU_STAT_BP && !(CPU_EFLAG & RF_FLAG)) { | 
| if (count[i] != 0) { | int i; | 
| if (n > 0) { | for (i = 0; i < CPU_DEBUG_REG_INDEX_NUM; i++) { | 
| milstr_ncat(buf, " + ", sizeof(buf)); | if ((CPU_STAT_BP & (1 << i)) | 
| } | && (CPU_DR7_GET_RW(i) == CPU_DR7_RW_CODE) | 
| if (count[i] > 1) { | && (CPU_DR(i) == CPU_EIP) | 
| SPRINTF(tmp, "%s * %d", | && (CPU_DR7_GET_LEN(i) == 0)) { | 
| reg32_str[i], count[i]); | CPU_DR6 |= CPU_DR6_B(i); | 
| } else { | EXCEPTION(DB_EXCEPTION, 0); | 
| milstr_ncpy(tmp, reg32_str[i], sizeof(tmp)); |  | 
| } |  | 
| milstr_ncat(buf, tmp, sizeof(buf)); |  | 
| n++; |  | 
| } |  | 
| } |  | 
| if (count[8] != 0) { |  | 
| if (n > 0) { |  | 
| milstr_ncat(buf, " + ", sizeof(buf)); |  | 
 | } | } | 
 | SPRINTF(tmp, "0x%08x", count[8]); |  | 
 | milstr_ncat(buf, tmp, sizeof(buf)); |  | 
 | } | } | 
 | } | } | 
| fprintf(fp, "[%s]", buf); | #endif  /* IA32_SUPPORT_DEBUG_REGISTER */ | 
|  |  | 
| return eip; |  | 
| } |  | 
|  |  | 
| void |  | 
| close_instruction_trace(void) |  | 
| { |  | 
|  |  | 
| if (fp) { |  | 
| fclose(fp); |  | 
| fp = NULL; |  | 
| } |  | 
| } |  | 
| #endif  /* IA32_INSTRUCTION_TRACE */ |  | 
|  |  | 
|  |  | 
| jmp_buf exec_1step_jmpbuf; |  | 
|  |  | 
| void |  | 
| exec_1step(void) |  | 
| { |  | 
| int prefix; |  | 
| BYTE op; |  | 
|  |  | 
| CPU_PREV_EIP = CPU_EIP; |  | 
|  |  | 
| CPU_STATSAVE.cpu_inst = CPU_STATSAVE.cpu_inst_default; |  | 
|  |  | 
| #ifdef  IA32_INSTRUCTION_TRACE |  | 
| { |  | 
| BYTE opcode[MAX_PREFIX + 1]; |  | 
| DWORD eip = CPU_EIP; |  | 
| int num = 0; |  | 
| int i; |  | 
| BOOL t = cpu_inst_trace; |  | 
|  |  | 
| if ((fp == NULL) && t) { |  | 
| fp = fopen("ia32trace.txt", "a"); |  | 
| } |  | 
| if (fp && t) { |  | 
| fprintf(fp, "%04x:%08x:", CPU_CS, eip); |  | 
| } |  | 
| #endif |  | 
 |  |  | 
 | for (prefix = 0; prefix < MAX_PREFIX; prefix++) { | for (prefix = 0; prefix < MAX_PREFIX; prefix++) { | 
 | GET_PCBYTE(op); | GET_PCBYTE(op); | 
|  | #if defined(IA32_INSTRUCTION_TRACE) | 
| #ifdef  IA32_INSTRUCTION_TRACE | ctx[ctx_index].op[prefix] = op; | 
| eip++; | ctx[ctx_index].opbytes++; | 
| if (fp && t) { |  | 
| opcode[num++] = op; |  | 
| fprintf(fp, " %02x", op); |  | 
| } |  | 
 | #endif | #endif | 
 |  |  | 
 | /* prefix */ | /* prefix */ | 
| Line 508  exec_1step(void) | Line 147  exec_1step(void) | 
 | EXCEPTION(UD_EXCEPTION, 0); | EXCEPTION(UD_EXCEPTION, 0); | 
 | } | } | 
 |  |  | 
| #ifdef  IA32_INSTRUCTION_TRACE | #if defined(IA32_INSTRUCTION_TRACE) | 
| if (fp && t) { | if (op == 0x0f) { | 
| BYTE op2 = 0; | BYTE op2; | 
| if ((op == 0x0f) | op2 = cpu_codefetch(CPU_EIP); | 
| || (op >= 0x80 && op <= 0x83) | ctx[ctx_index].op[prefix + 1] = op2; | 
| || (op >= 0xc0 && op <= 0xc1) | ctx[ctx_index].opbytes++; | 
| || (op >= 0xd0 && op <= 0xd3) |  | 
| || (op >= 0xf6 && op <= 0xf7) |  | 
| || (op >= 0xfe /* && op <= 0xff */) |  | 
| ) { |  | 
| op2 = cpu_codefetch(eip); |  | 
| eip++; |  | 
| fprintf(fp, " %02x", op2); |  | 
| } |  | 
|  |  | 
| fprintf(fp, "\t\t"); |  | 
| for (i = 0; i < num; i++) { |  | 
| BYTE c = opcode[i]; |  | 
| const char *p = opcode_1byte[CPU_INST_OP32][c]; |  | 
| if (p) { |  | 
| fprintf(fp, "%s ", p); |  | 
| } else { |  | 
| BYTE t = (op2 >> 3) & 7; |  | 
|  |  | 
| switch (c) { |  | 
| case 0x80: case 0x81: case 0x82: case 0x83: |  | 
| p = opcode_0x8x[CPU_INST_OP32][c&1][t]; |  | 
| break; |  | 
|  |  | 
| case 0xc0: case 0xc1: |  | 
| case 0xd0: case 0xd1: case 0xd2: case 0xd3: |  | 
| p = opcode_shift[CPU_INST_OP32][c&1][t]; |  | 
| break; |  | 
|  |  | 
| case 0xf6: |  | 
| case 0xf7: |  | 
| p = opcode_0xf6[CPU_INST_OP32][c&1][t]; |  | 
| break; |  | 
|  |  | 
| case 0xfe: |  | 
| case 0xff: |  | 
| p = opcode_0xfe[CPU_INST_OP32][c&1][t]; |  | 
| break; |  | 
| } |  | 
| if (p) { |  | 
| fprintf(fp, "%s ", p); |  | 
| } |  | 
| } |  | 
| } |  | 
| if (op == 0x0f) { |  | 
| const char *p = opcode_2byte[CPU_INST_OP32][op2]; |  | 
| if (p) { |  | 
| fprintf(fp, "%s ", p); |  | 
| } else { |  | 
| BYTE t; |  | 
|  |  | 
| t = cpu_codefetch(eip); |  | 
| eip++; |  | 
| t = (t >> 3) & 7; |  | 
|  |  | 
| switch (op2) { |  | 
| case 0x00: |  | 
| p = opcode2_g6[t]; |  | 
| break; |  | 
|  |  | 
| case 0x01: |  | 
| p = opcode2_g7[t]; |  | 
| break; |  | 
|  |  | 
| case 0xba: |  | 
| p = opcode2_g8[t]; |  | 
| break; |  | 
|  |  | 
| case 0xc7: |  | 
| p = opcode2_g9[t]; |  | 
| break; |  | 
| } |  | 
| if (p) { |  | 
| fprintf(fp, "%s ", p); |  | 
| } |  | 
| } |  | 
| } |  | 
|  |  | 
| /* arg */ |  | 
| switch (op) { |  | 
| case 0xcd: |  | 
| op2 = cpu_codefetch(eip); |  | 
| eip++; |  | 
| fprintf(fp, "%02xh", op2); |  | 
| break; |  | 
| } |  | 
| fprintf(fp, "\n"); |  | 
 | } | } | 
| } | ctx_index = (ctx_index + 1) % NELEMENTS(ctx); | 
 | #endif | #endif | 
 |  |  | 
 | /* normal / rep, but not use */ | /* normal / rep, but not use */ | 
 | if (!(insttable_info[op] & INST_STRING) || !CPU_INST_REPUSE) { | if (!(insttable_info[op] & INST_STRING) || !CPU_INST_REPUSE) { | 
 |  | #if defined(DEBUG) | 
 |  | cpu_debug_rep_cont = 0; | 
 |  | #endif | 
 | (*insttable_1byte[CPU_INST_OP32][op])(); | (*insttable_1byte[CPU_INST_OP32][op])(); | 
 |  | #if defined(IA32_SUPPORT_DEBUG_REGISTER) | 
 |  | goto check_break_point; | 
 |  | #else | 
 | return; | return; | 
 |  | #endif | 
 | } | } | 
 |  |  | 
 | /* rep */ | /* rep */ | 
 | CPU_WORKCLOCK(5); | CPU_WORKCLOCK(5); | 
 |  | #if defined(DEBUG) | 
 |  | if (!cpu_debug_rep_cont) { | 
 |  | cpu_debug_rep_cont = 1; | 
 |  | cpu_debug_rep_regs = CPU_STATSAVE.cpu_regs; | 
 |  | } | 
 |  | #endif | 
 | if (!CPU_INST_AS32) { | if (!CPU_INST_AS32) { | 
 | if (CPU_CX != 0) { | if (CPU_CX != 0) { | 
 | if (!(insttable_info[op] & REP_CHECKZF)) { | if (!(insttable_info[op] & REP_CHECKZF)) { | 
 | /* rep */ | /* rep */ | 
| do { | for (;;) { | 
 | (*insttable_1byte[CPU_INST_OP32][op])(); | (*insttable_1byte[CPU_INST_OP32][op])(); | 
| } while (--CPU_CX); | if (--CPU_CX == 0) { | 
|  | #if defined(DEBUG) | 
|  | cpu_debug_rep_cont = 0; | 
|  | #endif | 
|  | break; | 
|  | } | 
|  | if (CPU_REMCLOCK <= 0) { | 
|  | CPU_EIP = CPU_PREV_EIP; | 
|  | break; | 
|  | } | 
|  | } | 
 | } else if (CPU_INST_REPUSE != 0xf2) { | } else if (CPU_INST_REPUSE != 0xf2) { | 
 | /* repe */ | /* repe */ | 
| do { | for (;;) { | 
 | (*insttable_1byte[CPU_INST_OP32][op])(); | (*insttable_1byte[CPU_INST_OP32][op])(); | 
| } while (--CPU_CX && (CPU_FLAGL & Z_FLAG)); | if (--CPU_CX == 0 || CC_NZ) { | 
|  | #if defined(DEBUG) | 
|  | cpu_debug_rep_cont = 0; | 
|  | #endif | 
|  | break; | 
|  | } | 
|  | if (CPU_REMCLOCK <= 0) { | 
|  | CPU_EIP = CPU_PREV_EIP; | 
|  | break; | 
|  | } | 
|  | } | 
 | } else { | } else { | 
 | /* repne */ | /* repne */ | 
| do { | for (;;) { | 
 | (*insttable_1byte[CPU_INST_OP32][op])(); | (*insttable_1byte[CPU_INST_OP32][op])(); | 
| } while (--CPU_CX && !(CPU_FLAGL & Z_FLAG)); | if (--CPU_CX == 0 || CC_Z) { | 
|  | #if defined(DEBUG) | 
|  | cpu_debug_rep_cont = 0; | 
|  | #endif | 
|  | break; | 
|  | } | 
|  | if (CPU_REMCLOCK <= 0) { | 
|  | CPU_EIP = CPU_PREV_EIP; | 
|  | break; | 
|  | } | 
|  | } | 
 | } | } | 
 | } | } | 
 | } else { | } else { | 
 | if (CPU_ECX != 0) { | if (CPU_ECX != 0) { | 
 | if (!(insttable_info[op] & REP_CHECKZF)) { | if (!(insttable_info[op] & REP_CHECKZF)) { | 
 | /* rep */ | /* rep */ | 
| do { | for (;;) { | 
 | (*insttable_1byte[CPU_INST_OP32][op])(); | (*insttable_1byte[CPU_INST_OP32][op])(); | 
| } while (--CPU_ECX); | if (--CPU_ECX == 0) { | 
|  | #if defined(DEBUG) | 
|  | cpu_debug_rep_cont = 0; | 
|  | #endif | 
|  | break; | 
|  | } | 
|  | if (CPU_REMCLOCK <= 0) { | 
|  | CPU_EIP = CPU_PREV_EIP; | 
|  | break; | 
|  | } | 
|  | } | 
 | } else if (CPU_INST_REPUSE != 0xf2) { | } else if (CPU_INST_REPUSE != 0xf2) { | 
 | /* repe */ | /* repe */ | 
| do { | for (;;) { | 
 | (*insttable_1byte[CPU_INST_OP32][op])(); | (*insttable_1byte[CPU_INST_OP32][op])(); | 
| } while (--CPU_ECX && (CPU_FLAGL & Z_FLAG)); | if (--CPU_ECX == 0 || CC_NZ) { | 
|  | #if defined(DEBUG) | 
|  | cpu_debug_rep_cont = 0; | 
|  | #endif | 
|  | break; | 
|  | } | 
|  | if (CPU_REMCLOCK <= 0) { | 
|  | CPU_EIP = CPU_PREV_EIP; | 
|  | break; | 
|  | } | 
|  | } | 
 | } else { | } else { | 
 | /* repne */ | /* repne */ | 
| do { | for (;;) { | 
 | (*insttable_1byte[CPU_INST_OP32][op])(); | (*insttable_1byte[CPU_INST_OP32][op])(); | 
| } while (--CPU_ECX && !(CPU_FLAGL & Z_FLAG)); | if (--CPU_ECX == 0 || CC_Z) { | 
|  | #if defined(DEBUG) | 
|  | cpu_debug_rep_cont = 0; | 
|  | #endif | 
|  | break; | 
|  | } | 
|  | if (CPU_REMCLOCK <= 0) { | 
|  | CPU_EIP = CPU_PREV_EIP; | 
|  | break; | 
|  | } | 
|  | } | 
 | } | } | 
 | } | } | 
 | } | } | 
 |  |  | 
 |  | #if defined(IA32_SUPPORT_DEBUG_REGISTER) | 
 |  | check_break_point: | 
 |  | if (CPU_TRAP || (CPU_STAT_BP_EVENT & ~CPU_STAT_BP_EVENT_RF)) { | 
 |  | UINT8 orig = CPU_STAT_BP_EVENT & ~CPU_STAT_BP_EVENT_RF; | 
 |  |  | 
 |  | CPU_STAT_BP_EVENT &= CPU_STAT_BP_EVENT_RF; | 
 |  |  | 
 |  | CPU_DR6 |= (orig & 0xf); | 
 |  | if (orig & CPU_STAT_BP_EVENT_TASK) { | 
 |  | CPU_DR6 |= CPU_DR6_BT; | 
 |  | } | 
 |  | if (CPU_TRAP) { | 
 |  | CPU_DR6 |= CPU_DR6_BS; | 
 |  | } | 
 |  | INTERRUPT(DB_EXCEPTION, INTR_TYPE_EXCEPTION); | 
 |  | } | 
 |  | if (CPU_EFLAG & RF_FLAG) { | 
 |  | if (CPU_STAT_BP_EVENT & CPU_STAT_BP_EVENT_RF) { | 
 |  | /* after IRETD or task switch */ | 
 |  | CPU_STAT_BP_EVENT &= ~CPU_STAT_BP_EVENT_RF; | 
 |  | } else { | 
 |  | CPU_EFLAG &= ~RF_FLAG; | 
 |  | } | 
 |  | } | 
 |  | #endif  /* IA32_SUPPORT_DEBUG_REGISTER */ | 
 | } | } |