Commit 3f3373166227b13e762e20d2fb51eadfa6a2d653
1 parent
d05e66d2
pop ss, mov ss, x and sti disable irqs for the next instruction - began dispatch…
… optimization by adding new x86 cpu 'hidden' flags git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@372 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
8 changed files
with
109 additions
and
58 deletions
cpu-exec.c
| ... | ... | @@ -186,7 +186,8 @@ int cpu_exec(CPUState *env1) |
| 186 | 186 | #if defined(TARGET_I386) |
| 187 | 187 | /* if hardware interrupt pending, we execute it */ |
| 188 | 188 | if ((interrupt_request & CPU_INTERRUPT_HARD) && |
| 189 | - (env->eflags & IF_MASK)) { | |
| 189 | + (env->eflags & IF_MASK) && | |
| 190 | + !(env->hflags & HF_INHIBIT_IRQ_MASK)) { | |
| 190 | 191 | int intno; |
| 191 | 192 | intno = cpu_x86_get_pic_interrupt(env); |
| 192 | 193 | if (loglevel) { |
| ... | ... | @@ -233,21 +234,20 @@ int cpu_exec(CPUState *env1) |
| 233 | 234 | #endif |
| 234 | 235 | } |
| 235 | 236 | #endif |
| 236 | - /* we compute the CPU state. We assume it will not | |
| 237 | - change during the whole generated block. */ | |
| 237 | + /* we record a subset of the CPU state. It will | |
| 238 | + always be the same before a given translated block | |
| 239 | + is executed. */ | |
| 238 | 240 | #if defined(TARGET_I386) |
| 239 | 241 | flags = (env->segs[R_CS].flags & DESC_B_MASK) |
| 240 | - >> (DESC_B_SHIFT - GEN_FLAG_CODE32_SHIFT); | |
| 242 | + >> (DESC_B_SHIFT - HF_CS32_SHIFT); | |
| 241 | 243 | flags |= (env->segs[R_SS].flags & DESC_B_MASK) |
| 242 | - >> (DESC_B_SHIFT - GEN_FLAG_SS32_SHIFT); | |
| 244 | + >> (DESC_B_SHIFT - HF_SS32_SHIFT); | |
| 243 | 245 | flags |= (((unsigned long)env->segs[R_DS].base | |
| 244 | 246 | (unsigned long)env->segs[R_ES].base | |
| 245 | 247 | (unsigned long)env->segs[R_SS].base) != 0) << |
| 246 | - GEN_FLAG_ADDSEG_SHIFT; | |
| 247 | - flags |= env->cpl << GEN_FLAG_CPL_SHIFT; | |
| 248 | - flags |= env->soft_mmu << GEN_FLAG_SOFT_MMU_SHIFT; | |
| 249 | - flags |= (env->eflags & VM_MASK) >> (17 - GEN_FLAG_VM_SHIFT); | |
| 250 | - flags |= (env->eflags & (IOPL_MASK | TF_MASK)); | |
| 248 | + HF_ADDSEG_SHIFT; | |
| 249 | + flags |= env->hflags; | |
| 250 | + flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK)); | |
| 251 | 251 | cs_base = env->segs[R_CS].base; |
| 252 | 252 | pc = cs_base + env->eip; |
| 253 | 253 | #elif defined(TARGET_ARM) |
| ... | ... | @@ -337,8 +337,8 @@ int cpu_exec(CPUState *env1) |
| 337 | 337 | /* reset soft MMU for next block (it can currently |
| 338 | 338 | only be set by a memory fault) */ |
| 339 | 339 | #if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU) |
| 340 | - if (env->soft_mmu) { | |
| 341 | - env->soft_mmu = 0; | |
| 340 | + if (env->hflags & HF_SOFTMMU_MASK) { | |
| 341 | + env->hflags &= ~HF_SOFTMMU_MASK; | |
| 342 | 342 | /* do not allow linking to another block */ |
| 343 | 343 | T0 = 0; |
| 344 | 344 | } |
| ... | ... | @@ -499,7 +499,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
| 499 | 499 | raise_exception_err(EXCP0E_PAGE, env->error_code); |
| 500 | 500 | } else { |
| 501 | 501 | /* activate soft MMU for this block */ |
| 502 | - env->soft_mmu = 1; | |
| 502 | + env->hflags |= HF_SOFTMMU_MASK; | |
| 503 | 503 | sigprocmask(SIG_SETMASK, old_set, NULL); |
| 504 | 504 | cpu_loop_exit(); |
| 505 | 505 | } | ... | ... |
cpu-i386.h
| ... | ... | @@ -73,6 +73,10 @@ |
| 73 | 73 | #define CC_S 0x0080 |
| 74 | 74 | #define CC_O 0x0800 |
| 75 | 75 | |
| 76 | +#define TF_SHIFT 8 | |
| 77 | +#define IOPL_SHIFT 12 | |
| 78 | +#define VM_SHIFT 17 | |
| 79 | + | |
| 76 | 80 | #define TF_MASK 0x00000100 |
| 77 | 81 | #define IF_MASK 0x00000200 |
| 78 | 82 | #define DF_MASK 0x00000400 |
| ... | ... | @@ -85,6 +89,29 @@ |
| 85 | 89 | #define VIP_MASK 0x00100000 |
| 86 | 90 | #define ID_MASK 0x00200000 |
| 87 | 91 | |
| 92 | +/* hidden flags - used internally by qemu to represent additionnal cpu | |
| 93 | + states. Only the CPL and INHIBIT_IRQ are not redundant. We avoid | |
| 94 | + using the IOPL_MASK, TF_MASK and VM_MASK bit position to ease oring | |
| 95 | + with eflags. */ | |
| 96 | +/* current cpl */ | |
| 97 | +#define HF_CPL_SHIFT 0 | |
| 98 | +/* true if soft mmu is being used */ | |
| 99 | +#define HF_SOFTMMU_SHIFT 2 | |
| 100 | +/* true if hardware interrupts must be disabled for next instruction */ | |
| 101 | +#define HF_INHIBIT_IRQ_SHIFT 3 | |
| 102 | +/* 16 or 32 segments */ | |
| 103 | +#define HF_CS32_SHIFT 4 | |
| 104 | +#define HF_SS32_SHIFT 5 | |
| 105 | +/* zero base for DS, ES and SS */ | |
| 106 | +#define HF_ADDSEG_SHIFT 6 | |
| 107 | + | |
| 108 | +#define HF_CPL_MASK (3 << HF_CPL_SHIFT) | |
| 109 | +#define HF_SOFTMMU_MASK (1 << HF_SOFTMMU_SHIFT) | |
| 110 | +#define HF_INHIBIT_IRQ_MASK (1 << HF_INHIBIT_IRQ_SHIFT) | |
| 111 | +#define HF_CS32_MASK (1 << HF_CS32_SHIFT) | |
| 112 | +#define HF_SS32_MASK (1 << HF_CS32_SHIFT) | |
| 113 | +#define HF_ADDSEG_MASK (1 << HF_ADDSEG_SHIFT) | |
| 114 | + | |
| 88 | 115 | #define CR0_PE_MASK (1 << 0) |
| 89 | 116 | #define CR0_TS_MASK (1 << 3) |
| 90 | 117 | #define CR0_WP_MASK (1 << 16) |
| ... | ... | @@ -226,6 +253,7 @@ typedef struct CPUX86State { |
| 226 | 253 | uint32_t cc_dst; |
| 227 | 254 | uint32_t cc_op; |
| 228 | 255 | int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */ |
| 256 | + uint32_t hflags; /* hidden flags, see HF_xxx constants */ | |
| 229 | 257 | |
| 230 | 258 | /* FPU state */ |
| 231 | 259 | unsigned int fpstt; /* top of stack index */ |
| ... | ... | @@ -249,8 +277,6 @@ typedef struct CPUX86State { |
| 249 | 277 | SegmentCache tr; |
| 250 | 278 | SegmentCache gdt; /* only base and limit are used */ |
| 251 | 279 | SegmentCache idt; /* only base and limit are used */ |
| 252 | - int cpl; /* current cpl */ | |
| 253 | - int soft_mmu; /* TRUE if soft mmu is being used */ | |
| 254 | 280 | |
| 255 | 281 | /* sysenter registers */ |
| 256 | 282 | uint32_t sysenter_cs; |
| ... | ... | @@ -303,7 +329,11 @@ void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector); |
| 303 | 329 | /* wrapper, just in case memory mappings must be changed */ |
| 304 | 330 | static inline void cpu_x86_set_cpl(CPUX86State *s, int cpl) |
| 305 | 331 | { |
| 306 | - s->cpl = cpl; | |
| 332 | +#if HF_CPL_MASK == 3 | |
| 333 | + s->hflags = (s->hflags & ~HF_CPL_MASK) | cpl; | |
| 334 | +#else | |
| 335 | +#error HF_CPL_MASK is hardcoded | |
| 336 | +#endif | |
| 307 | 337 | } |
| 308 | 338 | |
| 309 | 339 | /* simulate fsave/frstor */ | ... | ... |
exec.h
| ... | ... | @@ -61,16 +61,6 @@ extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; |
| 61 | 61 | |
| 62 | 62 | #if defined(TARGET_I386) |
| 63 | 63 | |
| 64 | -#define GEN_FLAG_CODE32_SHIFT 0 | |
| 65 | -#define GEN_FLAG_ADDSEG_SHIFT 1 | |
| 66 | -#define GEN_FLAG_SS32_SHIFT 2 | |
| 67 | -#define GEN_FLAG_VM_SHIFT 3 | |
| 68 | -#define GEN_FLAG_ST_SHIFT 4 | |
| 69 | -#define GEN_FLAG_TF_SHIFT 8 /* same position as eflags */ | |
| 70 | -#define GEN_FLAG_CPL_SHIFT 9 | |
| 71 | -#define GEN_FLAG_SOFT_MMU_SHIFT 11 | |
| 72 | -#define GEN_FLAG_IOPL_SHIFT 12 /* same position as eflags */ | |
| 73 | - | |
| 74 | 64 | void optimize_flags_init(void); |
| 75 | 65 | |
| 76 | 66 | #endif | ... | ... |
helper-i386.c
| ... | ... | @@ -189,7 +189,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, |
| 189 | 189 | { |
| 190 | 190 | SegmentCache *dt; |
| 191 | 191 | uint8_t *ptr, *ssp; |
| 192 | - int type, dpl, selector, ss_dpl; | |
| 192 | + int type, dpl, selector, ss_dpl, cpl; | |
| 193 | 193 | int has_error_code, new_stack, shift; |
| 194 | 194 | uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2, push_size; |
| 195 | 195 | uint32_t old_cs, old_ss, old_esp, old_eip; |
| ... | ... | @@ -216,8 +216,9 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, |
| 216 | 216 | break; |
| 217 | 217 | } |
| 218 | 218 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
| 219 | + cpl = env->hflags & HF_CPL_MASK; | |
| 219 | 220 | /* check privledge if software int */ |
| 220 | - if (is_int && dpl < env->cpl) | |
| 221 | + if (is_int && dpl < cpl) | |
| 221 | 222 | raise_exception_err(EXCP0D_GPF, intno * 8 + 2); |
| 222 | 223 | /* check valid bit */ |
| 223 | 224 | if (!(e2 & DESC_P_MASK)) |
| ... | ... | @@ -232,11 +233,11 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, |
| 232 | 233 | if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) |
| 233 | 234 | raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
| 234 | 235 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
| 235 | - if (dpl > env->cpl) | |
| 236 | + if (dpl > cpl) | |
| 236 | 237 | raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
| 237 | 238 | if (!(e2 & DESC_P_MASK)) |
| 238 | 239 | raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); |
| 239 | - if (!(e2 & DESC_C_MASK) && dpl < env->cpl) { | |
| 240 | + if (!(e2 & DESC_C_MASK) && dpl < cpl) { | |
| 240 | 241 | /* to inner priviledge */ |
| 241 | 242 | get_ss_esp_from_tss(&ss, &esp, dpl); |
| 242 | 243 | if ((ss & 0xfffc) == 0) |
| ... | ... | @@ -255,7 +256,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, |
| 255 | 256 | if (!(ss_e2 & DESC_P_MASK)) |
| 256 | 257 | raise_exception_err(EXCP0A_TSS, ss & 0xfffc); |
| 257 | 258 | new_stack = 1; |
| 258 | - } else if ((e2 & DESC_C_MASK) || dpl == env->cpl) { | |
| 259 | + } else if ((e2 & DESC_C_MASK) || dpl == cpl) { | |
| 259 | 260 | /* to same priviledge */ |
| 260 | 261 | new_stack = 0; |
| 261 | 262 | } else { |
| ... | ... | @@ -402,7 +403,7 @@ void do_interrupt_user(int intno, int is_int, int error_code, |
| 402 | 403 | { |
| 403 | 404 | SegmentCache *dt; |
| 404 | 405 | uint8_t *ptr; |
| 405 | - int dpl; | |
| 406 | + int dpl, cpl; | |
| 406 | 407 | uint32_t e2; |
| 407 | 408 | |
| 408 | 409 | dt = &env->idt; |
| ... | ... | @@ -410,8 +411,9 @@ void do_interrupt_user(int intno, int is_int, int error_code, |
| 410 | 411 | e2 = ldl(ptr + 4); |
| 411 | 412 | |
| 412 | 413 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
| 414 | + cpl = env->hflags & HF_CPL_MASK; | |
| 413 | 415 | /* check privledge if software int */ |
| 414 | - if (is_int && dpl < env->cpl) | |
| 416 | + if (is_int && dpl < cpl) | |
| 415 | 417 | raise_exception_err(EXCP0D_GPF, intno * 8 + 2); |
| 416 | 418 | |
| 417 | 419 | /* Since we emulate only user space, we cannot do more than |
| ... | ... | @@ -742,7 +744,7 @@ void helper_ljmp_protected_T0_T1(void) |
| 742 | 744 | raise_exception_err(EXCP0D_GPF, 0); |
| 743 | 745 | if (load_segment(&e1, &e2, new_cs) != 0) |
| 744 | 746 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
| 745 | - cpl = env->cpl; | |
| 747 | + cpl = env->hflags & HF_CPL_MASK; | |
| 746 | 748 | if (e2 & DESC_S_MASK) { |
| 747 | 749 | if (!(e2 & DESC_CS_MASK)) |
| 748 | 750 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
| ... | ... | @@ -826,7 +828,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) |
| 826 | 828 | raise_exception_err(EXCP0D_GPF, 0); |
| 827 | 829 | if (load_segment(&e1, &e2, new_cs) != 0) |
| 828 | 830 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
| 829 | - cpl = env->cpl; | |
| 831 | + cpl = env->hflags & HF_CPL_MASK; | |
| 830 | 832 | if (e2 & DESC_S_MASK) { |
| 831 | 833 | if (!(e2 & DESC_CS_MASK)) |
| 832 | 834 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
| ... | ... | @@ -1079,7 +1081,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) |
| 1079 | 1081 | if (!(e2 & DESC_S_MASK) || |
| 1080 | 1082 | !(e2 & DESC_CS_MASK)) |
| 1081 | 1083 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
| 1082 | - cpl = env->cpl; | |
| 1084 | + cpl = env->hflags & HF_CPL_MASK; | |
| 1083 | 1085 | rpl = new_cs & 3; |
| 1084 | 1086 | if (rpl < cpl) |
| 1085 | 1087 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ... | ... |
helper2-i386.c
| ... | ... | @@ -52,7 +52,7 @@ CPUX86State *cpu_x86_init(void) |
| 52 | 52 | |
| 53 | 53 | tlb_flush(env); |
| 54 | 54 | #ifdef CONFIG_SOFTMMU |
| 55 | - env->soft_mmu = 1; | |
| 55 | + env->hflags |= HF_SOFTMMU_MASK; | |
| 56 | 56 | #endif |
| 57 | 57 | /* init various static tables */ |
| 58 | 58 | if (!inited) { |
| ... | ... | @@ -228,7 +228,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write) |
| 228 | 228 | int cpl, error_code, is_dirty, is_user, prot, page_size, ret; |
| 229 | 229 | unsigned long pd; |
| 230 | 230 | |
| 231 | - cpl = env->cpl; | |
| 231 | + cpl = env->hflags & HF_CPL_MASK; | |
| 232 | 232 | is_user = (cpl == 3); |
| 233 | 233 | |
| 234 | 234 | #ifdef DEBUG_MMU |
| ... | ... | @@ -325,7 +325,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write) |
| 325 | 325 | } |
| 326 | 326 | |
| 327 | 327 | do_mapping: |
| 328 | - if (env->soft_mmu) { | |
| 328 | + if (env->hflags & HF_SOFTMMU_MASK) { | |
| 329 | 329 | unsigned long paddr, vaddr, address, addend, page_offset; |
| 330 | 330 | int index; |
| 331 | 331 | |
| ... | ... | @@ -359,7 +359,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write) |
| 359 | 359 | if ((pd & 0xfff) != 0) { |
| 360 | 360 | /* IO access: no mapping is done as it will be handled by the |
| 361 | 361 | soft MMU */ |
| 362 | - if (!env->soft_mmu) | |
| 362 | + if (!(env->hflags & HF_SOFTMMU_MASK)) | |
| 363 | 363 | ret = 2; |
| 364 | 364 | } else { |
| 365 | 365 | void *map_addr; | ... | ... |
op-i386.c
| ... | ... | @@ -457,6 +457,16 @@ void OPPROTO op_sti(void) |
| 457 | 457 | env->eflags |= IF_MASK; |
| 458 | 458 | } |
| 459 | 459 | |
| 460 | +void OPPROTO op_set_inhibit_irq(void) | |
| 461 | +{ | |
| 462 | + env->hflags |= HF_INHIBIT_IRQ_MASK; | |
| 463 | +} | |
| 464 | + | |
| 465 | +void OPPROTO op_reset_inhibit_irq(void) | |
| 466 | +{ | |
| 467 | + env->hflags &= ~HF_INHIBIT_IRQ_MASK; | |
| 468 | +} | |
| 469 | + | |
| 460 | 470 | #if 0 |
| 461 | 471 | /* vm86plus instructions */ |
| 462 | 472 | void OPPROTO op_cli_vm(void) | ... | ... |
softmmu_template.h
| ... | ... | @@ -90,7 +90,7 @@ DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), _mmu)(unsigned long addr) |
| 90 | 90 | |
| 91 | 91 | /* test if there is match for unaligned or IO access */ |
| 92 | 92 | /* XXX: could done more in memory macro in a non portable way */ |
| 93 | - is_user = (env->cpl == 3); | |
| 93 | + is_user = ((env->hflags & HF_CPL_MASK) == 3); | |
| 94 | 94 | index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
| 95 | 95 | redo: |
| 96 | 96 | tlb_addr = env->tlb_read[is_user][index].address; |
| ... | ... | @@ -126,7 +126,7 @@ static DATA_TYPE glue(slow_ld, SUFFIX)(unsigned long addr, void *retaddr) |
| 126 | 126 | int is_user, index, shift; |
| 127 | 127 | unsigned long physaddr, tlb_addr, addr1, addr2; |
| 128 | 128 | |
| 129 | - is_user = (env->cpl == 3); | |
| 129 | + is_user = ((env->hflags & HF_CPL_MASK) == 3); | |
| 130 | 130 | index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
| 131 | 131 | redo: |
| 132 | 132 | tlb_addr = env->tlb_read[is_user][index].address; |
| ... | ... | @@ -169,7 +169,7 @@ void REGPARM(2) glue(glue(__st, SUFFIX), _mmu)(unsigned long addr, DATA_TYPE val |
| 169 | 169 | void *retaddr; |
| 170 | 170 | int is_user, index; |
| 171 | 171 | |
| 172 | - is_user = (env->cpl == 3); | |
| 172 | + is_user = ((env->hflags & HF_CPL_MASK) == 3); | |
| 173 | 173 | index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
| 174 | 174 | redo: |
| 175 | 175 | tlb_addr = env->tlb_write[is_user][index].address; |
| ... | ... | @@ -203,7 +203,7 @@ static void glue(slow_st, SUFFIX)(unsigned long addr, DATA_TYPE val, |
| 203 | 203 | unsigned long physaddr, tlb_addr; |
| 204 | 204 | int is_user, index, i; |
| 205 | 205 | |
| 206 | - is_user = (env->cpl == 3); | |
| 206 | + is_user = ((env->hflags & HF_CPL_MASK) == 3); | |
| 207 | 207 | index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
| 208 | 208 | redo: |
| 209 | 209 | tlb_addr = env->tlb_write[is_user][index].address; | ... | ... |
translate-i386.c
| ... | ... | @@ -1552,7 +1552,9 @@ static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip) |
| 1552 | 1552 | else |
| 1553 | 1553 | gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg])); |
| 1554 | 1554 | /* abort translation because the register may have a non zero base |
| 1555 | - or because ss32 may change */ | |
| 1555 | + or because ss32 may change. For R_SS, translation must always | |
| 1556 | + stop as a special handling must be done to disable hardware | |
| 1557 | + interrupts for the next instruction */ | |
| 1556 | 1558 | if (seg_reg == R_SS || (!s->addseg && seg_reg < R_FS)) |
| 1557 | 1559 | s->is_jmp = 2; |
| 1558 | 1560 | } |
| ... | ... | @@ -2356,10 +2358,14 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2356 | 2358 | case 0x07: /* pop es */ |
| 2357 | 2359 | case 0x17: /* pop ss */ |
| 2358 | 2360 | case 0x1f: /* pop ds */ |
| 2361 | + reg = b >> 3; | |
| 2359 | 2362 | gen_pop_T0(s); |
| 2360 | - gen_movl_seg_T0(s, b >> 3, pc_start - s->cs_base); | |
| 2363 | + gen_movl_seg_T0(s, reg, pc_start - s->cs_base); | |
| 2361 | 2364 | gen_pop_update(s); |
| 2362 | - /* XXX: if reg == SS, inhibit interrupts/trace */ | |
| 2365 | + if (reg == R_SS) { | |
| 2366 | + /* if reg == SS, inhibit interrupts/trace */ | |
| 2367 | + gen_op_set_inhibit_irq(); | |
| 2368 | + } | |
| 2363 | 2369 | break; |
| 2364 | 2370 | case 0x1a1: /* pop fs */ |
| 2365 | 2371 | case 0x1a9: /* pop gs */ |
| ... | ... | @@ -2418,7 +2424,10 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2418 | 2424 | goto illegal_op; |
| 2419 | 2425 | gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
| 2420 | 2426 | gen_movl_seg_T0(s, reg, pc_start - s->cs_base); |
| 2421 | - /* XXX: if reg == SS, inhibit interrupts/trace */ | |
| 2427 | + if (reg == R_SS) { | |
| 2428 | + /* if reg == SS, inhibit interrupts/trace */ | |
| 2429 | + gen_op_set_inhibit_irq(); | |
| 2430 | + } | |
| 2422 | 2431 | break; |
| 2423 | 2432 | case 0x8c: /* mov Gv, seg */ |
| 2424 | 2433 | modrm = ldub(s->pc++); |
| ... | ... | @@ -3704,6 +3713,8 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3704 | 3713 | if (!s->vm86) { |
| 3705 | 3714 | if (s->cpl <= s->iopl) { |
| 3706 | 3715 | gen_op_sti(); |
| 3716 | + /* interruptions are enabled only the first insn after sti */ | |
| 3717 | + gen_op_set_inhibit_irq(); | |
| 3707 | 3718 | s->is_jmp = 2; /* give a chance to handle pending irqs */ |
| 3708 | 3719 | } else { |
| 3709 | 3720 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| ... | ... | @@ -3711,12 +3722,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3711 | 3722 | } else { |
| 3712 | 3723 | if (s->iopl == 3) { |
| 3713 | 3724 | gen_op_sti(); |
| 3725 | + /* interruptions are enabled only the first insn after sti */ | |
| 3726 | + gen_op_set_inhibit_irq(); | |
| 3714 | 3727 | s->is_jmp = 2; /* give a chance to handle pending irqs */ |
| 3715 | 3728 | } else { |
| 3716 | 3729 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 3717 | 3730 | } |
| 3718 | 3731 | } |
| 3719 | - /* XXX: interruptions are enabled only the first insn after sti */ | |
| 3720 | 3732 | break; |
| 3721 | 3733 | case 0x62: /* bound */ |
| 3722 | 3734 | ot = dflag ? OT_LONG : OT_WORD; |
| ... | ... | @@ -4380,21 +4392,21 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
| 4380 | 4392 | flags = tb->flags; |
| 4381 | 4393 | |
| 4382 | 4394 | dc->pe = env->cr[0] & CR0_PE_MASK; |
| 4383 | - dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1; | |
| 4384 | - dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1; | |
| 4385 | - dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1; | |
| 4386 | - dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7; | |
| 4387 | - dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1; | |
| 4388 | - dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3; | |
| 4389 | - dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3; | |
| 4390 | - dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1; | |
| 4395 | + dc->code32 = (flags >> HF_CS32_SHIFT) & 1; | |
| 4396 | + dc->ss32 = (flags >> HF_SS32_SHIFT) & 1; | |
| 4397 | + dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1; | |
| 4398 | + dc->f_st = 0; | |
| 4399 | + dc->vm86 = (flags >> VM_SHIFT) & 1; | |
| 4400 | + dc->cpl = (flags >> HF_CPL_SHIFT) & 3; | |
| 4401 | + dc->iopl = (flags >> IOPL_SHIFT) & 3; | |
| 4402 | + dc->tf = (flags >> TF_SHIFT) & 1; | |
| 4391 | 4403 | dc->cc_op = CC_OP_DYNAMIC; |
| 4392 | 4404 | dc->cs_base = cs_base; |
| 4393 | 4405 | dc->tb = tb; |
| 4394 | 4406 | dc->popl_esp_hack = 0; |
| 4395 | 4407 | /* select memory access functions */ |
| 4396 | 4408 | dc->mem_index = 0; |
| 4397 | - if ((flags >> GEN_FLAG_SOFT_MMU_SHIFT) & 1) { | |
| 4409 | + if (flags & HF_SOFTMMU_MASK) { | |
| 4398 | 4410 | if (dc->cpl == 3) |
| 4399 | 4411 | dc->mem_index = 6; |
| 4400 | 4412 | else |
| ... | ... | @@ -4408,6 +4420,13 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
| 4408 | 4420 | dc->is_jmp = DISAS_NEXT; |
| 4409 | 4421 | pc_ptr = pc_start; |
| 4410 | 4422 | lj = -1; |
| 4423 | + | |
| 4424 | + /* if irq were inhibited for the next instruction, we can disable | |
| 4425 | + them here as it is simpler (otherwise jumps would have to | |
| 4426 | + handled as special case) */ | |
| 4427 | + if (flags & HF_INHIBIT_IRQ_MASK) { | |
| 4428 | + gen_op_reset_inhibit_irq(); | |
| 4429 | + } | |
| 4411 | 4430 | do { |
| 4412 | 4431 | if (env->nb_breakpoints > 0) { |
| 4413 | 4432 | for(j = 0; j < env->nb_breakpoints; j++) { | ... | ... |