| version 1.5, 2004/01/15 15:50:33 | version 1.23, 2005/03/03 06:59:41 | 
| Line 28 | Line 28 | 
 | */ | */ | 
 |  |  | 
 | #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(IA32_PROFILE_INSTRUCTION) | #if defined(ENABLE_TRAP) | 
| UINT32  inst_1byte_count[2][256]; | #include "steptrap.h" | 
| UINT32  inst_2byte_count[2][256]; |  | 
| UINT32  ea16_count[24]; |  | 
| UINT32  ea32_count[24]; |  | 
| UINT32  sib0_count[256]; |  | 
| UINT32  sib1_count[256]; |  | 
| UINT32  sib2_count[256]; |  | 
|  |  | 
| static const char *ea16_str[24] = { |  | 
| "BX + SI", "BX + SI + DISP8", "BX + SI + DISP16", |  | 
| "BX + DI", "BX + DI + DISP8", "BX + DI + DISP16", |  | 
| "BP + SI", "BP + SI + DISP8", "BP + SI + DISP16", |  | 
| "BP + DI", "BP + DI + DISP8", "BP + DI + DISP16", |  | 
| "SI",      "SI + DISP8",      "SI + DISP16", |  | 
| "DI",      "DI + DISP8",      "DI + DISP16", |  | 
| "DISP16",  "BP + DISP8",      "BP + DISP16", |  | 
| "BX",      "BX + DISP8",      "BX + DISP16", |  | 
| }; |  | 
|  |  | 
| static const char *ea32_str[24] = { |  | 
| "EAX", "ECX", "EDX", "EBX", "SIB", "DISP32", "ESI", "EDI", |  | 
| "EAX + DISP8",  "ECX + DISP8",  "EDX + DISP8",  "EBX + DISP8", |  | 
| "SIB + DISP8",  "EBP + DISP8",  "ESI + DISP8",  "EDI + DISP8", |  | 
| "EAX + DISP32", "ECX + DISP32", "EDX + DISP32", "EBX + DISP32", |  | 
| "SIB + DISP32", "EBP + DISP32", "ESI + DISP32", "EDI + DISP32", |  | 
| }; |  | 
|  |  | 
| static const char *sib0_base_str[8] = { |  | 
| "EAX", "ECX", "EDX", "EBX", "ESP", "DISP32", "ESI", "EDI", |  | 
| }; |  | 
|  |  | 
| static const char *sib1_base_str[8] = { |  | 
| "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI", |  | 
| }; |  | 
|  |  | 
| static const char *sib_index_str[8] = { |  | 
| "EAX", "ECX", "EDX", "EBX", "", "EBP", "ESI", "EDI", |  | 
| }; |  | 
|  |  | 
| static const char *sib_scale_str[4] = { |  | 
| "", "2", "4", "8", |  | 
| }; |  | 
|  |  | 
| void |  | 
| clear_profile_inst(void) |  | 
| { |  | 
|  |  | 
| memset(inst_1byte_count, 0, sizeof(inst_1byte_count)); |  | 
| memset(inst_2byte_count, 0, sizeof(inst_2byte_count)); |  | 
| memset(ea16_count, 0, sizeof(ea16_count)); |  | 
| memset(ea32_count, 0, sizeof(ea32_count)); |  | 
| memset(sib0_count, 0, sizeof(sib0_count)); |  | 
| memset(sib1_count, 0, sizeof(sib1_count)); |  | 
| memset(sib2_count, 0, sizeof(sib2_count)); |  | 
| } |  | 
|  |  | 
| void |  | 
| show_profile_inst(void) |  | 
| { |  | 
| int i; |  | 
|  |  | 
| printf("instruction (16bit)\n"); |  | 
| for (i = 0; i < 256; i++) { |  | 
| if (inst_1byte_count[0][i] != 0) { |  | 
| printf("0x%02x: %d\n", i, inst_1byte_count[0][i]); |  | 
| } |  | 
| } |  | 
| for (i = 0; i < 256; i++) { |  | 
| if (inst_2byte_count[0][i] != 0) { |  | 
| printf("0x0f%02x: %d\n", i, inst_2byte_count[0][i]); |  | 
| } |  | 
| } |  | 
|  |  | 
| printf("instruction (32bit)\n"); |  | 
| for (i = 0; i < 256; i++) { |  | 
| if (inst_1byte_count[1][i] != 0) { |  | 
| printf("0x%02x: %d\n", i, inst_1byte_count[1][i]); |  | 
| } |  | 
| } |  | 
| for (i = 0; i < 256; i++) { |  | 
| if (inst_2byte_count[1][i] != 0) { |  | 
| printf("0x0f%02x: %d\n", i, inst_2byte_count[1][i]); |  | 
| } |  | 
| } |  | 
| } |  | 
|  |  | 
| void |  | 
| show_profile_ea(void) |  | 
| { |  | 
| char buf[80]; |  | 
| char tmp[80]; |  | 
| int i; |  | 
| int t; |  | 
|  |  | 
| printf("EA16\n"); |  | 
| for (i = 0; i < NELEMENTS(ea16_count); i++) { |  | 
| if (ea16_count[i] != 0) { |  | 
| printf("%s: %d\n", ea16_str[i], ea16_count[i]); |  | 
| } |  | 
| } |  | 
| printf("EA32\n"); |  | 
| for (i = 0; i < NELEMENTS(ea32_count); i++) { |  | 
| if (ea32_count[i] != 0) { |  | 
| printf("%s: %d\n", ea32_str[i], ea32_count[i]); |  | 
| } |  | 
| } |  | 
| printf("SIB0\n"); |  | 
| for (i = 0; i < NELEMENTS(sib0_count); i++) { |  | 
| if (sib0_count[i] != 0) { |  | 
| sprintf(tmp, "%s", sib0_base_str[i & 7]); |  | 
| strcpy(buf, tmp); |  | 
| t = (i >> 3) & 7; |  | 
| if (t != 4) { |  | 
| sprintf(tmp, " + %s", sib_index_str[t]); |  | 
| strcat(buf, tmp); |  | 
| } |  | 
| t = (i >> 6) & 3; |  | 
| if (t != 0) { |  | 
| sprintf(tmp, " * %s", sib_scale_str[t]); |  | 
| strcat(buf, tmp); |  | 
| } |  | 
| printf("%s: %d\n", buf, sib0_count[i]); |  | 
| } |  | 
| } |  | 
| printf("SIB1\n"); |  | 
| for (i = 0; i < NELEMENTS(sib1_count); i++) { |  | 
| if (sib1_count[i] != 0) { |  | 
| sprintf(tmp, "%s", sib1_base_str[i & 7]); |  | 
| strcpy(buf, tmp); |  | 
| t = (i >> 3) & 7; |  | 
| if (t != 4) { |  | 
| sprintf(tmp, " + %s", sib_index_str[t]); |  | 
| strcat(buf, tmp); |  | 
| } |  | 
| t = (i >> 6) & 3; |  | 
| if (t != 0) { |  | 
| sprintf(tmp, " * %s", sib_scale_str[t]); |  | 
| strcat(buf, tmp); |  | 
| } |  | 
| printf("%s + DISP8: %d\n", buf, sib1_count[i]); |  | 
| } |  | 
| } |  | 
| printf("SIB2\n"); |  | 
| for (i = 0; i < NELEMENTS(sib2_count); i++) { |  | 
| if (sib2_count[i] != 0) { |  | 
| sprintf(tmp, "%s", sib1_base_str[i & 7]); |  | 
| strcpy(buf, tmp); |  | 
| t = (i >> 3) & 7; |  | 
| if (t != 4) { |  | 
| sprintf(tmp, " + %s", sib_index_str[t]); |  | 
| strcat(buf, tmp); |  | 
| } |  | 
| t = (i >> 6) & 3; |  | 
| if (t != 0) { |  | 
| sprintf(tmp, " * %s", sib_scale_str[t]); |  | 
| strcat(buf, tmp); |  | 
| } |  | 
| printf("%s + DISP32: %d\n", buf, sib2_count[i]); |  | 
| } |  | 
| } |  | 
| } |  | 
 | #endif | #endif | 
 |  |  | 
 | #ifdef  IA32_INSTRUCTION_TRACE |  | 
 | static FILE *fp = NULL; |  | 
 | BOOL cpu_inst_trace = FALSE; |  | 
 |  |  | 
| static const char *opcode_1byte[2][256] = { | sigjmp_buf exec_1step_jmpbuf; | 
| /* 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*/  "pushal","popal", "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",  "iret", |  | 
| /*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] = { | #if defined(IA32_INSTRUCTION_TRACE) | 
| /* 16bit */ | typedef struct { | 
| { | CPU_REGS                regs; | 
| /*00*/  NULL,      NULL,      "lar",     "lsl", | disasm_context_t        disasm; | 
| 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] = { | BYTE                    op[MAX_PREFIX + 2]; | 
| /* 16bit */ | int                     opbytes; | 
| { | } ia32_context_t; | 
| { "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] = { | #define NCTX    1024 | 
| /* 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] = { | ia32_context_t ctx[NCTX]; | 
| /* 16bit */ | int ctx_index = 0; | 
| { |  | 
| { "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" } |  | 
| }, |  | 
| }; |  | 
 |  |  | 
| static const char *opcode_0xfe[2][2][8] = { | int cpu_inst_trace = 0; | 
| /* 16bit */ | #endif | 
| { |  | 
| { "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] = { |  | 
 | "sldt", "str", "lldt", "ltr", "verr", "verw", NULL, NULL |  | 
 | }; |  | 
 |  |  | 
 | static const char *opcode2_g7[8] = { |  | 
 | "sgdt", "sidt", "lgdt", "lidt", "smsw", NULL, "lmsw", "invlpg" |  | 
 | }; |  | 
 |  |  | 
 | static const char *opcode2_g8[8] = { |  | 
 | NULL, NULL, NULL, NULL, "bt", "bts", "btr", "btc" |  | 
 | }; |  | 
 |  |  | 
 | static const char *opcode2_g9[8] = { |  | 
 | NULL, "cmpxchg8b", NULL, NULL, NULL, NULL, NULL, NULL |  | 
 | }; |  | 
 |  |  | 
 | static const char *reg8[8] = { |  | 
 | "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" |  | 
 | }; |  | 
 |  |  | 
 | static const char *reg16[8] = { |  | 
 | "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" |  | 
 | }; |  | 
 |  |  | 
 | static const char *reg32[8] = { |  | 
 | "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" |  | 
 | }; |  | 
 |  |  | 
| 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) { |  | 
| if (mod == 0) { |  | 
| 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)); | CPU_PREV_EIP = CPU_EIP; | 
|  | CPU_STATSAVE.cpu_inst = CPU_STATSAVE.cpu_inst_default; | 
 |  |  | 
| if (rm == 5) { | #if defined(ENABLE_TRAP) | 
| DWORD sib; | steptrap(CPU_CS, CPU_EIP); | 
| DWORD scale; | #endif | 
| DWORD idx; |  | 
| DWORD base; |  | 
|  |  | 
| sib = cpu_codefetch(eip); |  | 
| eip++; |  | 
|  |  | 
| scale = (sib >> 6) & 3; |  | 
| idx = (sib >> 3) & 7; |  | 
| base = sib & 7; |  | 
|  |  | 
| if (base == 5 && mod == 0) { |  | 
| val = cpu_codefetch_d(eip); |  | 
| eip += 4; |  | 
| count[8] += val; |  | 
| } else { |  | 
| count[base]++; |  | 
| } |  | 
| if (idx != 4) { |  | 
| count[idx] += 1 << scale; |  | 
| } |  | 
| } |  | 
 |  |  | 
| if (rm == 6 && mod == 0) { | #if defined(IA32_INSTRUCTION_TRACE) | 
| /* disp32 */ | ctx[ctx_index].regs = CPU_STATSAVE.cpu_regs; | 
| val = cpu_codefetch_d(eip); | if (cpu_inst_trace) { | 
| eip += 4; | disasm_context_t *d = &ctx[ctx_index].disasm; | 
| count[8] += val; | UINT32 eip = CPU_EIP; | 
| } else { | int rv; | 
| if (mod == 1) { |  | 
| /* disp8 */ | rv = disasm(&eip, d); | 
| val = cpu_codefetch(eip); | if (rv == 0) { | 
| eip++; | char buf[256]; | 
| if (val & 0x80) { | char tmp[32]; | 
| val |= 0xffffff00; | int len = d->nopbytes > 8 ? 8 : d->nopbytes; | 
| } | int i; | 
| count[8] += val; |  | 
| } else if (mod == 2) { | buf[0] = '\0'; | 
| /* disp32 */ | for (i = 0; i < len; i++) { | 
| val = cpu_codefetch_d(eip); | snprintf(tmp, sizeof(tmp), "%02x ", d->opcode[i]); | 
| eip += 4; | milstr_ncat(buf, tmp, sizeof(buf)); | 
| count[8] += val; |  | 
 | } | } | 
| if (rm != 5) { | for (; i < 8; i++) { | 
| count[rm]++; | milstr_ncat(buf, "   ", sizeof(buf)); | 
 | } | } | 
| } | VERBOSE(("%04x:%08x: %s%s", CPU_CS, CPU_EIP, buf, d->str)); | 
 |  |  | 
| n = 0; | buf[0] = '\0'; | 
| for (i = 0; i < 8; i++) { | for (; i < d->nopbytes; i++) { | 
| if (count[i] != 0) { | snprintf(tmp, sizeof(tmp), "%02x ", d->opcode[i]); | 
| if (n > 0) { |  | 
| milstr_ncat(buf, " + ", sizeof(buf)); |  | 
| } |  | 
| if (count[i] > 1) { |  | 
| SPRINTF(tmp, "%s * %d", |  | 
| reg32[i], count[i]); |  | 
| } else { |  | 
| milstr_ncpy(tmp, reg32[i], sizeof(tmp)); |  | 
| } |  | 
 | milstr_ncat(buf, tmp, sizeof(buf)); | milstr_ncat(buf, tmp, sizeof(buf)); | 
| n++; | if ((i % 8) == 7) { | 
|  | VERBOSE(("             : %s", buf)); | 
|  | buf[0] = '\0'; | 
|  | } | 
 | } | } | 
| } | if ((i % 8) != 0) { | 
| if (count[8] != 0) { | VERBOSE(("             : %s", buf)); | 
| if (n > 0) { |  | 
| milstr_ncat(buf, " + ", sizeof(buf)); |  | 
 | } | } | 
 | SPRINTF(tmp, "0x%08x", count[8]); |  | 
 | milstr_ncat(buf, tmp, sizeof(buf)); |  | 
 | } | } | 
 | } | } | 
| fprintf(fp, "[%s]", buf); | ctx[ctx_index].opbytes = 0; | 
|  |  | 
| return eip; |  | 
| } |  | 
|  |  | 
| void |  | 
| close_instruction_trace(void) |  | 
| { |  | 
|  |  | 
| if (fp) { |  | 
| fclose(fp); |  | 
| fp = NULL; |  | 
| } |  | 
| } |  | 
 | #endif | #endif | 
 |  |  | 
| #define MAX_PREFIX      8 | #if defined(IA32_SUPPORT_DEBUG_REGISTER) | 
|  | if (CPU_STAT_BP && !(CPU_EFLAG & RF_FLAG)) { | 
| jmp_buf exec_1step_jmpbuf; | int i; | 
|  | for (i = 0; i < CPU_DEBUG_REG_INDEX_NUM; i++) { | 
| void | if ((CPU_STAT_BP & (1 << i)) | 
| exec_1step(void) | && (CPU_DR7_GET_RW(i) == CPU_DR7_RW_CODE) | 
| { | && (CPU_DR(i) == CPU_EIP) | 
| int prefix; | && (CPU_DR7_GET_LEN(i) == 0)) { | 
| BYTE op; | CPU_DR6 |= CPU_DR6_B(i); | 
|  | EXCEPTION(DB_EXCEPTION, 0); | 
| 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 ((CPU_CS == 0x0018) && (eip >= 0x0000b42c) && (eip <= 0x0000b435)) { |  | 
| t = FALSE; |  | 
| } |  | 
|  |  | 
| if ((fp == NULL) && t) { |  | 
| fp = fopen("ia32trace.txt", "a"); |  | 
| } |  | 
| if (fp && t) { |  | 
| fprintf(fp, "%04x:%08x:", CPU_CS, eip); |  | 
 | } | } | 
| #endif | #endif  /* IA32_SUPPORT_DEBUG_REGISTER */ | 
 |  |  | 
 | 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 */ | 
 | if (insttable_info[op] & INST_PREFIX) { | if (insttable_info[op] & INST_PREFIX) { | 
 | PROFILE_INC_INST_1BYTE(op); |  | 
 | (*insttable_1byte[0][op])(); | (*insttable_1byte[0][op])(); | 
 | continue; | continue; | 
 | } | } | 
| Line 687  exec_1step(void) | Line 145  exec_1step(void) | 
 | if (prefix == MAX_PREFIX) { | if (prefix == MAX_PREFIX) { | 
 | EXCEPTION(UD_EXCEPTION, 0); | EXCEPTION(UD_EXCEPTION, 0); | 
 | } | } | 
 | PROFILE_INC_INST_1BYTE(op); |  | 
 |  |  | 
 | #ifdef  IA32_INSTRUCTION_TRACE |  | 
 | if (fp && t) { |  | 
 | BYTE op2 = 0; |  | 
 | if ((op == 0x0f) |  | 
 | || (op >= 0x80 && op <= 0x83) |  | 
 | || (op >= 0xc0 && op <= 0xc1) |  | 
 | || (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) { | #if defined(IA32_INSTRUCTION_TRACE) | 
| case 0x80: case 0x81: case 0x82: case 0x83: | if (op == 0x0f) { | 
| p = opcode_0x8x[CPU_INST_OP32][c&1][t]; | BYTE op2; | 
| break; | op2 = cpu_codefetch(CPU_EIP); | 
|  | ctx[ctx_index].op[prefix + 1] = op2; | 
| case 0xc0: case 0xc1: | ctx[ctx_index].opbytes++; | 
| 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); |  | 
| } |  | 
| } |  | 
| } |  | 
| fprintf(fp, "\n"); |  | 
| } |  | 
| #if 0 |  | 
| if (fp) { |  | 
| fclose(fp); |  | 
| fp = NULL; |  | 
 | } | } | 
| #endif | 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) { | 
 | (*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 */ | 
| Line 794  exec_1step(void) | Line 172  exec_1step(void) | 
 | 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) | 
|  | 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) | 
|  | 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) | 
|  | 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) | 
|  | 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) | 
|  | 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) | 
|  | 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, TRUE, FALSE, 0); | 
 |  | } | 
 |  | 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 */ | 
 | } | } |