Commit bd7a7b33df84cb053f9d2ac774d77372e4065d5f
1 parent
3bd7da9e
convert eflags manipulation insns to TCG
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4515 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
5 changed files
with
46 additions
and
148 deletions
target-i386/TODO
| 1 | Correctness issues: | 1 | Correctness issues: |
| 2 | 2 | ||
| 3 | +- some eflags manipulation incorrectly reset the bit 0x2. | ||
| 3 | - rework eflags optimization (will be a consequence of TCG port) | 4 | - rework eflags optimization (will be a consequence of TCG port) |
| 4 | - SVM: rework the implementation: simplify code, move most intercept | 5 | - SVM: rework the implementation: simplify code, move most intercept |
| 5 | tests as dynamic, correct segment access, verify exception safety, | 6 | tests as dynamic, correct segment access, verify exception safety, |
target-i386/helper.c
| @@ -108,6 +108,20 @@ void helper_unlock(void) | @@ -108,6 +108,20 @@ void helper_unlock(void) | ||
| 108 | spin_unlock(&global_cpu_lock); | 108 | spin_unlock(&global_cpu_lock); |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | +void helper_write_eflags(target_ulong t0, uint32_t update_mask) | ||
| 112 | +{ | ||
| 113 | + load_eflags(t0, update_mask); | ||
| 114 | +} | ||
| 115 | + | ||
| 116 | +target_ulong helper_read_eflags(void) | ||
| 117 | +{ | ||
| 118 | + uint32_t eflags; | ||
| 119 | + eflags = cc_table[CC_OP].compute_all(); | ||
| 120 | + eflags |= (DF & DF_MASK); | ||
| 121 | + eflags |= env->eflags & ~(VM_MASK | RF_MASK); | ||
| 122 | + return eflags; | ||
| 123 | +} | ||
| 124 | + | ||
| 111 | /* return non zero if error */ | 125 | /* return non zero if error */ |
| 112 | static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr, | 126 | static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr, |
| 113 | int selector) | 127 | int selector) |
target-i386/helper.h
| @@ -2,6 +2,8 @@ | @@ -2,6 +2,8 @@ | ||
| 2 | 2 | ||
| 3 | void helper_lock(void); | 3 | void helper_lock(void); |
| 4 | void helper_unlock(void); | 4 | void helper_unlock(void); |
| 5 | +void helper_write_eflags(target_ulong t0, uint32_t update_mask); | ||
| 6 | +target_ulong helper_read_eflags(void); | ||
| 5 | void helper_divb_AL(target_ulong t0); | 7 | void helper_divb_AL(target_ulong t0); |
| 6 | void helper_idivb_AL(target_ulong t0); | 8 | void helper_idivb_AL(target_ulong t0); |
| 7 | void helper_divw_AX(target_ulong t0); | 9 | void helper_divw_AX(target_ulong t0); |
target-i386/op.c
| @@ -255,138 +255,3 @@ void OPPROTO op_xor_T0_1(void) | @@ -255,138 +255,3 @@ void OPPROTO op_xor_T0_1(void) | ||
| 255 | { | 255 | { |
| 256 | T0 ^= 1; | 256 | T0 ^= 1; |
| 257 | } | 257 | } |
| 258 | - | ||
| 259 | -/* XXX: clear VIF/VIP in all ops ? */ | ||
| 260 | - | ||
| 261 | -void OPPROTO op_movl_eflags_T0(void) | ||
| 262 | -{ | ||
| 263 | - load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK)); | ||
| 264 | -} | ||
| 265 | - | ||
| 266 | -void OPPROTO op_movw_eflags_T0(void) | ||
| 267 | -{ | ||
| 268 | - load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff); | ||
| 269 | -} | ||
| 270 | - | ||
| 271 | -void OPPROTO op_movl_eflags_T0_io(void) | ||
| 272 | -{ | ||
| 273 | - load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK)); | ||
| 274 | -} | ||
| 275 | - | ||
| 276 | -void OPPROTO op_movw_eflags_T0_io(void) | ||
| 277 | -{ | ||
| 278 | - load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff); | ||
| 279 | -} | ||
| 280 | - | ||
| 281 | -void OPPROTO op_movl_eflags_T0_cpl0(void) | ||
| 282 | -{ | ||
| 283 | - load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK)); | ||
| 284 | -} | ||
| 285 | - | ||
| 286 | -void OPPROTO op_movw_eflags_T0_cpl0(void) | ||
| 287 | -{ | ||
| 288 | - load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff); | ||
| 289 | -} | ||
| 290 | - | ||
| 291 | -#if 0 | ||
| 292 | -/* vm86plus version */ | ||
| 293 | -void OPPROTO op_movw_eflags_T0_vm(void) | ||
| 294 | -{ | ||
| 295 | - int eflags; | ||
| 296 | - eflags = T0; | ||
| 297 | - CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); | ||
| 298 | - DF = 1 - (2 * ((eflags >> 10) & 1)); | ||
| 299 | - /* we also update some system flags as in user mode */ | ||
| 300 | - env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) | | ||
| 301 | - (eflags & FL_UPDATE_MASK16); | ||
| 302 | - if (eflags & IF_MASK) { | ||
| 303 | - env->eflags |= VIF_MASK; | ||
| 304 | - if (env->eflags & VIP_MASK) { | ||
| 305 | - EIP = PARAM1; | ||
| 306 | - raise_exception(EXCP0D_GPF); | ||
| 307 | - } | ||
| 308 | - } | ||
| 309 | - FORCE_RET(); | ||
| 310 | -} | ||
| 311 | - | ||
| 312 | -void OPPROTO op_movl_eflags_T0_vm(void) | ||
| 313 | -{ | ||
| 314 | - int eflags; | ||
| 315 | - eflags = T0; | ||
| 316 | - CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); | ||
| 317 | - DF = 1 - (2 * ((eflags >> 10) & 1)); | ||
| 318 | - /* we also update some system flags as in user mode */ | ||
| 319 | - env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) | | ||
| 320 | - (eflags & FL_UPDATE_MASK32); | ||
| 321 | - if (eflags & IF_MASK) { | ||
| 322 | - env->eflags |= VIF_MASK; | ||
| 323 | - if (env->eflags & VIP_MASK) { | ||
| 324 | - EIP = PARAM1; | ||
| 325 | - raise_exception(EXCP0D_GPF); | ||
| 326 | - } | ||
| 327 | - } | ||
| 328 | - FORCE_RET(); | ||
| 329 | -} | ||
| 330 | -#endif | ||
| 331 | - | ||
| 332 | -/* XXX: compute only O flag */ | ||
| 333 | -void OPPROTO op_movb_eflags_T0(void) | ||
| 334 | -{ | ||
| 335 | - int of; | ||
| 336 | - of = cc_table[CC_OP].compute_all() & CC_O; | ||
| 337 | - CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of; | ||
| 338 | -} | ||
| 339 | - | ||
| 340 | -void OPPROTO op_movl_T0_eflags(void) | ||
| 341 | -{ | ||
| 342 | - int eflags; | ||
| 343 | - eflags = cc_table[CC_OP].compute_all(); | ||
| 344 | - eflags |= (DF & DF_MASK); | ||
| 345 | - eflags |= env->eflags & ~(VM_MASK | RF_MASK); | ||
| 346 | - T0 = eflags; | ||
| 347 | -} | ||
| 348 | - | ||
| 349 | -/* vm86plus version */ | ||
| 350 | -#if 0 | ||
| 351 | -void OPPROTO op_movl_T0_eflags_vm(void) | ||
| 352 | -{ | ||
| 353 | - int eflags; | ||
| 354 | - eflags = cc_table[CC_OP].compute_all(); | ||
| 355 | - eflags |= (DF & DF_MASK); | ||
| 356 | - eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK); | ||
| 357 | - if (env->eflags & VIF_MASK) | ||
| 358 | - eflags |= IF_MASK; | ||
| 359 | - T0 = eflags; | ||
| 360 | -} | ||
| 361 | -#endif | ||
| 362 | - | ||
| 363 | -void OPPROTO op_clc(void) | ||
| 364 | -{ | ||
| 365 | - int eflags; | ||
| 366 | - eflags = cc_table[CC_OP].compute_all(); | ||
| 367 | - eflags &= ~CC_C; | ||
| 368 | - CC_SRC = eflags; | ||
| 369 | -} | ||
| 370 | - | ||
| 371 | -void OPPROTO op_stc(void) | ||
| 372 | -{ | ||
| 373 | - int eflags; | ||
| 374 | - eflags = cc_table[CC_OP].compute_all(); | ||
| 375 | - eflags |= CC_C; | ||
| 376 | - CC_SRC = eflags; | ||
| 377 | -} | ||
| 378 | - | ||
| 379 | -void OPPROTO op_cmc(void) | ||
| 380 | -{ | ||
| 381 | - int eflags; | ||
| 382 | - eflags = cc_table[CC_OP].compute_all(); | ||
| 383 | - eflags ^= CC_C; | ||
| 384 | - CC_SRC = eflags; | ||
| 385 | -} | ||
| 386 | - | ||
| 387 | -void OPPROTO op_salc(void) | ||
| 388 | -{ | ||
| 389 | - int cf; | ||
| 390 | - cf = cc_table[CC_OP].compute_c(); | ||
| 391 | - EAX = (EAX & ~0xff) | ((-cf) & 0xff); | ||
| 392 | -} |
target-i386/translate.c
| @@ -5733,7 +5733,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -5733,7 +5733,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 5733 | } else { | 5733 | } else { |
| 5734 | if (s->cc_op != CC_OP_DYNAMIC) | 5734 | if (s->cc_op != CC_OP_DYNAMIC) |
| 5735 | gen_op_set_cc_op(s->cc_op); | 5735 | gen_op_set_cc_op(s->cc_op); |
| 5736 | - gen_op_movl_T0_eflags(); | 5736 | + tcg_gen_helper_1_0(helper_read_eflags, cpu_T[0]); |
| 5737 | gen_push_T0(s); | 5737 | gen_push_T0(s); |
| 5738 | } | 5738 | } |
| 5739 | break; | 5739 | break; |
| @@ -5746,22 +5746,28 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -5746,22 +5746,28 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 5746 | gen_pop_T0(s); | 5746 | gen_pop_T0(s); |
| 5747 | if (s->cpl == 0) { | 5747 | if (s->cpl == 0) { |
| 5748 | if (s->dflag) { | 5748 | if (s->dflag) { |
| 5749 | - gen_op_movl_eflags_T0_cpl0(); | 5749 | + tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0], |
| 5750 | + tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK))); | ||
| 5750 | } else { | 5751 | } else { |
| 5751 | - gen_op_movw_eflags_T0_cpl0(); | 5752 | + tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0], |
| 5753 | + tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff)); | ||
| 5752 | } | 5754 | } |
| 5753 | } else { | 5755 | } else { |
| 5754 | if (s->cpl <= s->iopl) { | 5756 | if (s->cpl <= s->iopl) { |
| 5755 | if (s->dflag) { | 5757 | if (s->dflag) { |
| 5756 | - gen_op_movl_eflags_T0_io(); | 5758 | + tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0], |
| 5759 | + tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK))); | ||
| 5757 | } else { | 5760 | } else { |
| 5758 | - gen_op_movw_eflags_T0_io(); | 5761 | + tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0], |
| 5762 | + tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff)); | ||
| 5759 | } | 5763 | } |
| 5760 | } else { | 5764 | } else { |
| 5761 | if (s->dflag) { | 5765 | if (s->dflag) { |
| 5762 | - gen_op_movl_eflags_T0(); | 5766 | + tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0], |
| 5767 | + tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK))); | ||
| 5763 | } else { | 5768 | } else { |
| 5764 | - gen_op_movw_eflags_T0(); | 5769 | + tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0], |
| 5770 | + tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff)); | ||
| 5765 | } | 5771 | } |
| 5766 | } | 5772 | } |
| 5767 | } | 5773 | } |
| @@ -5778,7 +5784,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -5778,7 +5784,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 5778 | gen_op_mov_TN_reg(OT_BYTE, 0, R_AH); | 5784 | gen_op_mov_TN_reg(OT_BYTE, 0, R_AH); |
| 5779 | if (s->cc_op != CC_OP_DYNAMIC) | 5785 | if (s->cc_op != CC_OP_DYNAMIC) |
| 5780 | gen_op_set_cc_op(s->cc_op); | 5786 | gen_op_set_cc_op(s->cc_op); |
| 5781 | - gen_op_movb_eflags_T0(); | 5787 | + gen_compute_eflags(cpu_cc_src); |
| 5788 | + tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O); | ||
| 5789 | + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], CC_S | CC_Z | CC_A | CC_P | CC_C); | ||
| 5790 | + tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T[0]); | ||
| 5782 | s->cc_op = CC_OP_EFLAGS; | 5791 | s->cc_op = CC_OP_EFLAGS; |
| 5783 | break; | 5792 | break; |
| 5784 | case 0x9f: /* lahf */ | 5793 | case 0x9f: /* lahf */ |
| @@ -5786,25 +5795,30 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -5786,25 +5795,30 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 5786 | goto illegal_op; | 5795 | goto illegal_op; |
| 5787 | if (s->cc_op != CC_OP_DYNAMIC) | 5796 | if (s->cc_op != CC_OP_DYNAMIC) |
| 5788 | gen_op_set_cc_op(s->cc_op); | 5797 | gen_op_set_cc_op(s->cc_op); |
| 5789 | - gen_op_movl_T0_eflags(); | 5798 | + gen_compute_eflags(cpu_T[0]); |
| 5799 | + /* Note: gen_compute_eflags() only gives the condition codes */ | ||
| 5800 | + tcg_gen_ori_tl(cpu_T[0], cpu_T[0], 0x02); | ||
| 5790 | gen_op_mov_reg_T0(OT_BYTE, R_AH); | 5801 | gen_op_mov_reg_T0(OT_BYTE, R_AH); |
| 5791 | break; | 5802 | break; |
| 5792 | case 0xf5: /* cmc */ | 5803 | case 0xf5: /* cmc */ |
| 5793 | if (s->cc_op != CC_OP_DYNAMIC) | 5804 | if (s->cc_op != CC_OP_DYNAMIC) |
| 5794 | gen_op_set_cc_op(s->cc_op); | 5805 | gen_op_set_cc_op(s->cc_op); |
| 5795 | - gen_op_cmc(); | 5806 | + gen_compute_eflags(cpu_cc_src); |
| 5807 | + tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C); | ||
| 5796 | s->cc_op = CC_OP_EFLAGS; | 5808 | s->cc_op = CC_OP_EFLAGS; |
| 5797 | break; | 5809 | break; |
| 5798 | case 0xf8: /* clc */ | 5810 | case 0xf8: /* clc */ |
| 5799 | if (s->cc_op != CC_OP_DYNAMIC) | 5811 | if (s->cc_op != CC_OP_DYNAMIC) |
| 5800 | gen_op_set_cc_op(s->cc_op); | 5812 | gen_op_set_cc_op(s->cc_op); |
| 5801 | - gen_op_clc(); | 5813 | + gen_compute_eflags(cpu_cc_src); |
| 5814 | + tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C); | ||
| 5802 | s->cc_op = CC_OP_EFLAGS; | 5815 | s->cc_op = CC_OP_EFLAGS; |
| 5803 | break; | 5816 | break; |
| 5804 | case 0xf9: /* stc */ | 5817 | case 0xf9: /* stc */ |
| 5805 | if (s->cc_op != CC_OP_DYNAMIC) | 5818 | if (s->cc_op != CC_OP_DYNAMIC) |
| 5806 | gen_op_set_cc_op(s->cc_op); | 5819 | gen_op_set_cc_op(s->cc_op); |
| 5807 | - gen_op_stc(); | 5820 | + gen_compute_eflags(cpu_cc_src); |
| 5821 | + tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C); | ||
| 5808 | s->cc_op = CC_OP_EFLAGS; | 5822 | s->cc_op = CC_OP_EFLAGS; |
| 5809 | break; | 5823 | break; |
| 5810 | case 0xfc: /* cld */ | 5824 | case 0xfc: /* cld */ |
| @@ -6127,7 +6141,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6127,7 +6141,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6127 | goto illegal_op; | 6141 | goto illegal_op; |
| 6128 | if (s->cc_op != CC_OP_DYNAMIC) | 6142 | if (s->cc_op != CC_OP_DYNAMIC) |
| 6129 | gen_op_set_cc_op(s->cc_op); | 6143 | gen_op_set_cc_op(s->cc_op); |
| 6130 | - gen_op_salc(); | 6144 | + gen_compute_eflags_c(cpu_T[0]); |
| 6145 | + tcg_gen_neg_tl(cpu_T[0], cpu_T[0]); | ||
| 6146 | + gen_op_mov_reg_T0(OT_BYTE, R_EAX); | ||
| 6131 | break; | 6147 | break; |
| 6132 | case 0xe0: /* loopnz */ | 6148 | case 0xe0: /* loopnz */ |
| 6133 | case 0xe1: /* loopz */ | 6149 | case 0xe1: /* loopz */ |