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++) { | ... | ... |