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 | 1 | Correctness issues: |
| 2 | 2 | |
| 3 | +- some eflags manipulation incorrectly reset the bit 0x2. | |
| 3 | 4 | - rework eflags optimization (will be a consequence of TCG port) |
| 4 | 5 | - SVM: rework the implementation: simplify code, move most intercept |
| 5 | 6 | tests as dynamic, correct segment access, verify exception safety, | ... | ... |
target-i386/helper.c
| ... | ... | @@ -108,6 +108,20 @@ void helper_unlock(void) |
| 108 | 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 | 125 | /* return non zero if error */ |
| 112 | 126 | static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr, |
| 113 | 127 | int selector) | ... | ... |
target-i386/helper.h
| ... | ... | @@ -2,6 +2,8 @@ |
| 2 | 2 | |
| 3 | 3 | void helper_lock(void); |
| 4 | 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 | 7 | void helper_divb_AL(target_ulong t0); |
| 6 | 8 | void helper_idivb_AL(target_ulong t0); |
| 7 | 9 | void helper_divw_AX(target_ulong t0); | ... | ... |
target-i386/op.c
| ... | ... | @@ -255,138 +255,3 @@ void OPPROTO op_xor_T0_1(void) |
| 255 | 255 | { |
| 256 | 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 | 5733 | } else { |
| 5734 | 5734 | if (s->cc_op != CC_OP_DYNAMIC) |
| 5735 | 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 | 5737 | gen_push_T0(s); |
| 5738 | 5738 | } |
| 5739 | 5739 | break; |
| ... | ... | @@ -5746,22 +5746,28 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 5746 | 5746 | gen_pop_T0(s); |
| 5747 | 5747 | if (s->cpl == 0) { |
| 5748 | 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 | 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 | 5755 | } else { |
| 5754 | 5756 | if (s->cpl <= s->iopl) { |
| 5755 | 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 | 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 | 5764 | } else { |
| 5761 | 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 | 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 | 5784 | gen_op_mov_TN_reg(OT_BYTE, 0, R_AH); |
| 5779 | 5785 | if (s->cc_op != CC_OP_DYNAMIC) |
| 5780 | 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 | 5791 | s->cc_op = CC_OP_EFLAGS; |
| 5783 | 5792 | break; |
| 5784 | 5793 | case 0x9f: /* lahf */ |
| ... | ... | @@ -5786,25 +5795,30 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 5786 | 5795 | goto illegal_op; |
| 5787 | 5796 | if (s->cc_op != CC_OP_DYNAMIC) |
| 5788 | 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 | 5801 | gen_op_mov_reg_T0(OT_BYTE, R_AH); |
| 5791 | 5802 | break; |
| 5792 | 5803 | case 0xf5: /* cmc */ |
| 5793 | 5804 | if (s->cc_op != CC_OP_DYNAMIC) |
| 5794 | 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 | 5808 | s->cc_op = CC_OP_EFLAGS; |
| 5797 | 5809 | break; |
| 5798 | 5810 | case 0xf8: /* clc */ |
| 5799 | 5811 | if (s->cc_op != CC_OP_DYNAMIC) |
| 5800 | 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 | 5815 | s->cc_op = CC_OP_EFLAGS; |
| 5803 | 5816 | break; |
| 5804 | 5817 | case 0xf9: /* stc */ |
| 5805 | 5818 | if (s->cc_op != CC_OP_DYNAMIC) |
| 5806 | 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 | 5822 | s->cc_op = CC_OP_EFLAGS; |
| 5809 | 5823 | break; |
| 5810 | 5824 | case 0xfc: /* cld */ |
| ... | ... | @@ -6127,7 +6141,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 6127 | 6141 | goto illegal_op; |
| 6128 | 6142 | if (s->cc_op != CC_OP_DYNAMIC) |
| 6129 | 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 | 6147 | break; |
| 6132 | 6148 | case 0xe0: /* loopnz */ |
| 6133 | 6149 | case 0xe1: /* loopz */ | ... | ... |