Commit 717fc2ad8dbedcb19ec939b752489d2d1a21647b
1 parent
c05bab77
more ring 0 instructions - full x86 MMU emulation based on mmap() syscall - fixed popl (%esp)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@258 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
249 additions
and
30 deletions
translate-i386.c
@@ -24,11 +24,14 @@ | @@ -24,11 +24,14 @@ | ||
24 | #include <inttypes.h> | 24 | #include <inttypes.h> |
25 | #include <signal.h> | 25 | #include <signal.h> |
26 | #include <assert.h> | 26 | #include <assert.h> |
27 | +#include <sys/mman.h> | ||
27 | 28 | ||
28 | #include "cpu-i386.h" | 29 | #include "cpu-i386.h" |
29 | #include "exec.h" | 30 | #include "exec.h" |
30 | #include "disas.h" | 31 | #include "disas.h" |
31 | 32 | ||
33 | +//#define DEBUG_MMU | ||
34 | + | ||
32 | /* XXX: move that elsewhere */ | 35 | /* XXX: move that elsewhere */ |
33 | static uint16_t *gen_opc_ptr; | 36 | static uint16_t *gen_opc_ptr; |
34 | static uint32_t *gen_opparam_ptr; | 37 | static uint32_t *gen_opparam_ptr; |
@@ -59,6 +62,7 @@ typedef struct DisasContext { | @@ -59,6 +62,7 @@ typedef struct DisasContext { | ||
59 | int iopl; | 62 | int iopl; |
60 | int tf; /* TF cpu flag */ | 63 | int tf; /* TF cpu flag */ |
61 | struct TranslationBlock *tb; | 64 | struct TranslationBlock *tb; |
65 | + int popl_esp_hack; /* for correct popl with esp base handling */ | ||
62 | } DisasContext; | 66 | } DisasContext; |
63 | 67 | ||
64 | /* i386 arith/logic operations */ | 68 | /* i386 arith/logic operations */ |
@@ -862,12 +866,16 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ | @@ -862,12 +866,16 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ | ||
862 | } | 866 | } |
863 | 867 | ||
864 | if (base >= 0) { | 868 | if (base >= 0) { |
869 | + /* for correct popl handling with esp */ | ||
870 | + if (base == 4 && s->popl_esp_hack) | ||
871 | + disp += 4; | ||
865 | gen_op_movl_A0_reg[base](); | 872 | gen_op_movl_A0_reg[base](); |
866 | if (disp != 0) | 873 | if (disp != 0) |
867 | gen_op_addl_A0_im(disp); | 874 | gen_op_addl_A0_im(disp); |
868 | } else { | 875 | } else { |
869 | gen_op_movl_A0_im(disp); | 876 | gen_op_movl_A0_im(disp); |
870 | } | 877 | } |
878 | + /* XXX: index == 4 is always invalid */ | ||
871 | if (havesib && (index != 4 || scale != 0)) { | 879 | if (havesib && (index != 4 || scale != 0)) { |
872 | gen_op_addl_A0_reg_sN[scale][index](); | 880 | gen_op_addl_A0_reg_sN[scale][index](); |
873 | } | 881 | } |
@@ -1894,7 +1902,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1894,7 +1902,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
1894 | ot = dflag ? OT_LONG : OT_WORD; | 1902 | ot = dflag ? OT_LONG : OT_WORD; |
1895 | modrm = ldub(s->pc++); | 1903 | modrm = ldub(s->pc++); |
1896 | gen_pop_T0(s); | 1904 | gen_pop_T0(s); |
1905 | + s->popl_esp_hack = 1; | ||
1897 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); | 1906 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
1907 | + s->popl_esp_hack = 0; | ||
1898 | gen_pop_update(s); | 1908 | gen_pop_update(s); |
1899 | break; | 1909 | break; |
1900 | case 0xc8: /* enter */ | 1910 | case 0xc8: /* enter */ |
@@ -2940,29 +2950,10 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2940,29 +2950,10 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2940 | if (s->vm86 && s->iopl != 3) { | 2950 | if (s->vm86 && s->iopl != 3) { |
2941 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 2951 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
2942 | } else { | 2952 | } else { |
2943 | - /* XXX: not restartable */ | ||
2944 | - gen_stack_A0(s); | ||
2945 | - /* pop offset */ | ||
2946 | - gen_op_ld_T0_A0[1 + s->dflag](); | ||
2947 | - if (s->dflag == 0) | ||
2948 | - gen_op_andl_T0_ffff(); | ||
2949 | - /* NOTE: keeping EIP updated is not a problem in case of | ||
2950 | - exception */ | ||
2951 | - gen_op_jmp_T0(); | ||
2952 | - /* pop selector */ | ||
2953 | - gen_op_addl_A0_im(2 << s->dflag); | ||
2954 | - gen_op_ld_T0_A0[1 + s->dflag](); | ||
2955 | - /* pop eflags */ | ||
2956 | - gen_op_addl_A0_im(2 << s->dflag); | ||
2957 | - gen_op_ld_T1_A0[1 + s->dflag](); | ||
2958 | - gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base); | ||
2959 | - gen_op_movl_T0_T1(); | ||
2960 | - if (s->dflag) { | ||
2961 | - gen_op_movl_eflags_T0(); | ||
2962 | - } else { | ||
2963 | - gen_op_movw_eflags_T0(); | ||
2964 | - } | ||
2965 | - gen_stack_update(s, (6 << s->dflag)); | 2953 | + if (s->cc_op != CC_OP_DYNAMIC) |
2954 | + gen_op_set_cc_op(s->cc_op); | ||
2955 | + gen_op_jmp_im(pc_start - s->cs_base); | ||
2956 | + gen_op_iret_protected(s->dflag); | ||
2966 | s->cc_op = CC_OP_EFLAGS; | 2957 | s->cc_op = CC_OP_EFLAGS; |
2967 | } | 2958 | } |
2968 | s->is_jmp = 1; | 2959 | s->is_jmp = 1; |
@@ -3096,10 +3087,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3096,10 +3087,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
3096 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 3087 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3097 | } else { | 3088 | } else { |
3098 | gen_pop_T0(s); | 3089 | gen_pop_T0(s); |
3099 | - if (s->dflag) { | ||
3100 | - gen_op_movl_eflags_T0(); | 3090 | + if (s->cpl == 0) { |
3091 | + if (s->dflag) { | ||
3092 | + gen_op_movl_eflags_T0_cpl0(); | ||
3093 | + } else { | ||
3094 | + gen_op_movw_eflags_T0_cpl0(); | ||
3095 | + } | ||
3101 | } else { | 3096 | } else { |
3102 | - gen_op_movw_eflags_T0(); | 3097 | + if (s->dflag) { |
3098 | + gen_op_movl_eflags_T0(); | ||
3099 | + } else { | ||
3100 | + gen_op_movw_eflags_T0(); | ||
3101 | + } | ||
3103 | } | 3102 | } |
3104 | gen_pop_update(s); | 3103 | gen_pop_update(s); |
3105 | s->cc_op = CC_OP_EFLAGS; | 3104 | s->cc_op = CC_OP_EFLAGS; |
@@ -3358,8 +3357,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3358,8 +3357,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
3358 | gen_op_cpuid(); | 3357 | gen_op_cpuid(); |
3359 | break; | 3358 | break; |
3360 | case 0xf4: /* hlt */ | 3359 | case 0xf4: /* hlt */ |
3361 | - /* XXX: if cpl == 0, then should do something else */ | ||
3362 | - gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 3360 | + if (s->cpl != 0) { |
3361 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | ||
3362 | + } else { | ||
3363 | + if (s->cc_op != CC_OP_DYNAMIC) | ||
3364 | + gen_op_set_cc_op(s->cc_op); | ||
3365 | + gen_op_jmp_im(s->pc - s->cs_base); | ||
3366 | + gen_op_hlt(); | ||
3367 | + s->is_jmp = 1; | ||
3368 | + } | ||
3363 | break; | 3369 | break; |
3364 | case 0x100: | 3370 | case 0x100: |
3365 | modrm = ldub(s->pc++); | 3371 | modrm = ldub(s->pc++); |
@@ -3462,6 +3468,16 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3462,6 +3468,16 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
3462 | gen_op_lmsw_T0(); | 3468 | gen_op_lmsw_T0(); |
3463 | } | 3469 | } |
3464 | break; | 3470 | break; |
3471 | + case 7: /* invlpg */ | ||
3472 | + if (s->cpl != 0) { | ||
3473 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | ||
3474 | + } else { | ||
3475 | + if (mod == 3) | ||
3476 | + goto illegal_op; | ||
3477 | + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | ||
3478 | + gen_op_invlpg_A0(); | ||
3479 | + } | ||
3480 | + break; | ||
3465 | default: | 3481 | default: |
3466 | goto illegal_op; | 3482 | goto illegal_op; |
3467 | } | 3483 | } |
@@ -3866,7 +3882,7 @@ static void optimize_flags(uint16_t *opc_buf, int opc_buf_len) | @@ -3866,7 +3882,7 @@ static void optimize_flags(uint16_t *opc_buf, int opc_buf_len) | ||
3866 | /* generate intermediate code in gen_opc_buf and gen_opparam_buf for | 3882 | /* generate intermediate code in gen_opc_buf and gen_opparam_buf for |
3867 | basic block 'tb'. If search_pc is TRUE, also generate PC | 3883 | basic block 'tb'. If search_pc is TRUE, also generate PC |
3868 | information for each intermediate instruction. */ | 3884 | information for each intermediate instruction. */ |
3869 | -int gen_intermediate_code(TranslationBlock *tb, int search_pc) | 3885 | +static inline int gen_intermediate_code_internal(TranslationBlock *tb, int search_pc) |
3870 | { | 3886 | { |
3871 | DisasContext dc1, *dc = &dc1; | 3887 | DisasContext dc1, *dc = &dc1; |
3872 | uint8_t *pc_ptr; | 3888 | uint8_t *pc_ptr; |
@@ -3892,7 +3908,8 @@ int gen_intermediate_code(TranslationBlock *tb, int search_pc) | @@ -3892,7 +3908,8 @@ int gen_intermediate_code(TranslationBlock *tb, int search_pc) | ||
3892 | dc->cc_op = CC_OP_DYNAMIC; | 3908 | dc->cc_op = CC_OP_DYNAMIC; |
3893 | dc->cs_base = cs_base; | 3909 | dc->cs_base = cs_base; |
3894 | dc->tb = tb; | 3910 | dc->tb = tb; |
3895 | - | 3911 | + dc->popl_esp_hack = 0; |
3912 | + | ||
3896 | gen_opc_ptr = gen_opc_buf; | 3913 | gen_opc_ptr = gen_opc_buf; |
3897 | gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; | 3914 | gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; |
3898 | gen_opparam_ptr = gen_opparam_buf; | 3915 | gen_opparam_ptr = gen_opparam_buf; |
@@ -3908,6 +3925,7 @@ int gen_intermediate_code(TranslationBlock *tb, int search_pc) | @@ -3908,6 +3925,7 @@ int gen_intermediate_code(TranslationBlock *tb, int search_pc) | ||
3908 | while (lj < j) | 3925 | while (lj < j) |
3909 | gen_opc_instr_start[lj++] = 0; | 3926 | gen_opc_instr_start[lj++] = 0; |
3910 | gen_opc_pc[lj] = (uint32_t)pc_ptr; | 3927 | gen_opc_pc[lj] = (uint32_t)pc_ptr; |
3928 | + gen_opc_cc_op[lj] = dc->cc_op; | ||
3911 | gen_opc_instr_start[lj] = 1; | 3929 | gen_opc_instr_start[lj] = 1; |
3912 | } | 3930 | } |
3913 | } | 3931 | } |
@@ -3974,6 +3992,16 @@ int gen_intermediate_code(TranslationBlock *tb, int search_pc) | @@ -3974,6 +3992,16 @@ int gen_intermediate_code(TranslationBlock *tb, int search_pc) | ||
3974 | return 0; | 3992 | return 0; |
3975 | } | 3993 | } |
3976 | 3994 | ||
3995 | +int gen_intermediate_code(TranslationBlock *tb) | ||
3996 | +{ | ||
3997 | + return gen_intermediate_code_internal(tb, 0); | ||
3998 | +} | ||
3999 | + | ||
4000 | +int gen_intermediate_code_pc(TranslationBlock *tb) | ||
4001 | +{ | ||
4002 | + return gen_intermediate_code_internal(tb, 1); | ||
4003 | +} | ||
4004 | + | ||
3977 | CPUX86State *cpu_x86_init(void) | 4005 | CPUX86State *cpu_x86_init(void) |
3978 | { | 4006 | { |
3979 | CPUX86State *env; | 4007 | CPUX86State *env; |
@@ -4006,6 +4034,197 @@ void cpu_x86_close(CPUX86State *env) | @@ -4006,6 +4034,197 @@ void cpu_x86_close(CPUX86State *env) | ||
4006 | free(env); | 4034 | free(env); |
4007 | } | 4035 | } |
4008 | 4036 | ||
4037 | +/***********************************************************/ | ||
4038 | +/* x86 mmu */ | ||
4039 | + | ||
4040 | +/* called when cr3 or PG bit are modified */ | ||
4041 | +static int last_pg_state = -1; | ||
4042 | +int phys_ram_size; | ||
4043 | +int phys_ram_fd; | ||
4044 | +uint8_t *phys_ram_base; | ||
4045 | + | ||
4046 | +void cpu_x86_update_cr0(CPUX86State *env) | ||
4047 | +{ | ||
4048 | + int pg_state; | ||
4049 | + void *map_addr; | ||
4050 | + | ||
4051 | +#ifdef DEBUG_MMU | ||
4052 | + printf("CR0 update: CR0=0x%08x\n", env->cr[0]); | ||
4053 | +#endif | ||
4054 | + pg_state = env->cr[0] & CR0_PG_MASK; | ||
4055 | + if (pg_state != last_pg_state) { | ||
4056 | + if (!pg_state) { | ||
4057 | + /* we map the physical memory at address 0 */ | ||
4058 | + | ||
4059 | + map_addr = mmap((void *)0, phys_ram_size, PROT_WRITE | PROT_READ, | ||
4060 | + MAP_SHARED | MAP_FIXED, phys_ram_fd, 0); | ||
4061 | + if (map_addr == MAP_FAILED) { | ||
4062 | + fprintf(stderr, | ||
4063 | + "Could not map physical memory at host address 0x%08x\n", | ||
4064 | + 0); | ||
4065 | + exit(1); | ||
4066 | + } | ||
4067 | + page_set_flags(0, phys_ram_size, | ||
4068 | + PAGE_VALID | PAGE_READ | PAGE_WRITE | PAGE_EXEC); | ||
4069 | + } else { | ||
4070 | + /* we unmap the physical memory */ | ||
4071 | + munmap((void *)0, phys_ram_size); | ||
4072 | + page_set_flags(0, phys_ram_size, 0); | ||
4073 | + } | ||
4074 | + last_pg_state = pg_state; | ||
4075 | + } | ||
4076 | +} | ||
4077 | + | ||
4078 | +void cpu_x86_update_cr3(CPUX86State *env) | ||
4079 | +{ | ||
4080 | + if (env->cr[0] & CR0_PG_MASK) { | ||
4081 | +#ifdef DEBUG_MMU | ||
4082 | + printf("CR3 update: CR3=%08x\n", env->cr[3]); | ||
4083 | +#endif | ||
4084 | + page_unmap(); | ||
4085 | + } | ||
4086 | +} | ||
4087 | + | ||
4088 | +void cpu_x86_init_mmu(CPUX86State *env) | ||
4089 | +{ | ||
4090 | + last_pg_state = -1; | ||
4091 | + cpu_x86_update_cr0(env); | ||
4092 | +} | ||
4093 | + | ||
4094 | +void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr) | ||
4095 | +{ | ||
4096 | +} | ||
4097 | + | ||
4098 | +/* return value: | ||
4099 | + -1 = cannot handle fault | ||
4100 | + 0 = nothing more to do | ||
4101 | + 1 = generate PF fault | ||
4102 | +*/ | ||
4103 | +int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write) | ||
4104 | +{ | ||
4105 | + uint8_t *pde_ptr, *pte_ptr; | ||
4106 | + uint32_t pde, pte, virt_addr; | ||
4107 | + int cpl, error_code, is_dirty, is_user, prot, page_size; | ||
4108 | + void *map_addr; | ||
4109 | + | ||
4110 | + cpl = env->segs[R_CS].selector & 3; | ||
4111 | + is_user = (cpl == 3); | ||
4112 | + | ||
4113 | +#ifdef DEBUG_MMU | ||
4114 | + printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n", | ||
4115 | + addr, is_write, is_user, env->eip); | ||
4116 | +#endif | ||
4117 | + | ||
4118 | + if (env->user_mode_only) { | ||
4119 | + /* user mode only emulation */ | ||
4120 | + error_code = 0; | ||
4121 | + goto do_fault; | ||
4122 | + } | ||
4123 | + | ||
4124 | + if (!(env->cr[0] & CR0_PG_MASK)) | ||
4125 | + return -1; | ||
4126 | + | ||
4127 | + /* page directory entry */ | ||
4128 | + pde_ptr = phys_ram_base + ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)); | ||
4129 | + pde = ldl(pde_ptr); | ||
4130 | + if (!(pde & PG_PRESENT_MASK)) { | ||
4131 | + error_code = 0; | ||
4132 | + goto do_fault; | ||
4133 | + } | ||
4134 | + if (is_user) { | ||
4135 | + if (!(pde & PG_USER_MASK)) | ||
4136 | + goto do_fault_protect; | ||
4137 | + if (is_write && !(pde & PG_RW_MASK)) | ||
4138 | + goto do_fault_protect; | ||
4139 | + } else { | ||
4140 | + if ((env->cr[0] & CR0_WP_MASK) && (pde & PG_USER_MASK) && | ||
4141 | + is_write && !(pde & PG_RW_MASK)) | ||
4142 | + goto do_fault_protect; | ||
4143 | + } | ||
4144 | + /* if PSE bit is set, then we use a 4MB page */ | ||
4145 | + if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) { | ||
4146 | + is_dirty = is_write && !(pde & PG_DIRTY_MASK); | ||
4147 | + if (!(pde & PG_ACCESSED_MASK)) { | ||
4148 | + pde |= PG_ACCESSED_MASK; | ||
4149 | + if (is_dirty) | ||
4150 | + pde |= PG_DIRTY_MASK; | ||
4151 | + stl(pde_ptr, pde); | ||
4152 | + } | ||
4153 | + | ||
4154 | + pte = pde & ~0x003ff000; /* align to 4MB */ | ||
4155 | + page_size = 4096 * 1024; | ||
4156 | + virt_addr = addr & ~0x003fffff; | ||
4157 | + } else { | ||
4158 | + if (!(pde & PG_ACCESSED_MASK)) { | ||
4159 | + pde |= PG_ACCESSED_MASK; | ||
4160 | + stl(pde_ptr, pde); | ||
4161 | + } | ||
4162 | + | ||
4163 | + /* page directory entry */ | ||
4164 | + pte_ptr = phys_ram_base + ((pde & ~0xfff) + ((addr >> 10) & 0xffc)); | ||
4165 | + pte = ldl(pte_ptr); | ||
4166 | + if (!(pte & PG_PRESENT_MASK)) { | ||
4167 | + error_code = 0; | ||
4168 | + goto do_fault; | ||
4169 | + } | ||
4170 | + if (is_user) { | ||
4171 | + if (!(pte & PG_USER_MASK)) | ||
4172 | + goto do_fault_protect; | ||
4173 | + if (is_write && !(pte & PG_RW_MASK)) | ||
4174 | + goto do_fault_protect; | ||
4175 | + } else { | ||
4176 | + if ((env->cr[0] & CR0_WP_MASK) && (pte & PG_USER_MASK) && | ||
4177 | + is_write && !(pte & PG_RW_MASK)) | ||
4178 | + goto do_fault_protect; | ||
4179 | + } | ||
4180 | + is_dirty = is_write && !(pte & PG_DIRTY_MASK); | ||
4181 | + if (!(pte & PG_ACCESSED_MASK) || is_dirty) { | ||
4182 | + pte |= PG_ACCESSED_MASK; | ||
4183 | + if (is_dirty) | ||
4184 | + pte |= PG_DIRTY_MASK; | ||
4185 | + stl(pte_ptr, pte); | ||
4186 | + } | ||
4187 | + page_size = 4096; | ||
4188 | + virt_addr = addr & ~0xfff; | ||
4189 | + } | ||
4190 | + /* the page can be put in the TLB */ | ||
4191 | + prot = PROT_READ; | ||
4192 | + if (is_user) { | ||
4193 | + if (pte & PG_RW_MASK) | ||
4194 | + prot |= PROT_WRITE; | ||
4195 | + } else { | ||
4196 | + if (!(env->cr[0] & CR0_WP_MASK) || !(pte & PG_USER_MASK) || | ||
4197 | + (pte & PG_RW_MASK)) | ||
4198 | + prot |= PROT_WRITE; | ||
4199 | + } | ||
4200 | + map_addr = mmap((void *)virt_addr, page_size, prot, | ||
4201 | + MAP_SHARED | MAP_FIXED, phys_ram_fd, pte & ~0xfff); | ||
4202 | + if (map_addr == MAP_FAILED) { | ||
4203 | + fprintf(stderr, | ||
4204 | + "mmap failed when mapped physical address 0x%08x to virtual address 0x%08x\n", | ||
4205 | + pte & ~0xfff, virt_addr); | ||
4206 | + exit(1); | ||
4207 | + } | ||
4208 | + page_set_flags(virt_addr, virt_addr + page_size, | ||
4209 | + PAGE_VALID | PAGE_EXEC | prot); | ||
4210 | +#ifdef DEBUG_MMU | ||
4211 | + printf("mmaping 0x%08x to virt 0x%08x pse=%d\n", | ||
4212 | + pte & ~0xfff, virt_addr, (page_size != 4096)); | ||
4213 | +#endif | ||
4214 | + return 0; | ||
4215 | + do_fault_protect: | ||
4216 | + error_code = PG_ERROR_P_MASK; | ||
4217 | + do_fault: | ||
4218 | + env->cr[2] = addr; | ||
4219 | + env->error_code = (is_write << PG_ERROR_W_BIT) | error_code; | ||
4220 | + if (is_user) | ||
4221 | + env->error_code |= PG_ERROR_U_MASK; | ||
4222 | + return 1; | ||
4223 | +} | ||
4224 | + | ||
4225 | +/***********************************************************/ | ||
4226 | +/* x86 debug */ | ||
4227 | + | ||
4009 | static const char *cc_op_str[] = { | 4228 | static const char *cc_op_str[] = { |
4010 | "DYNAMIC", | 4229 | "DYNAMIC", |
4011 | "EFLAGS", | 4230 | "EFLAGS", |