From e2a1ae696f954286cbc53c507f51aed938803446 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 30 Mar 2019 14:41:02 +0000 Subject: [PATCH] Added lazy flags for ROL and ROR. --- src/codegen_ops_branch.c | 12 +++---- src/x86_flags.h | 73 +++++++++++++++++++++++++++++++++++++++- src/x86_ops_shift.h | 26 ++++---------- 3 files changed, 85 insertions(+), 26 deletions(-) diff --git a/src/codegen_ops_branch.c b/src/codegen_ops_branch.c index d22093a..e41b9ee 100644 --- a/src/codegen_ops_branch.c +++ b/src/codegen_ops_branch.c @@ -189,7 +189,7 @@ static int ropJE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, u if (ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)) { - if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + if (!codegen_flags_changed || !flags_res_valid()) { uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); @@ -205,7 +205,7 @@ static int ropJE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, u } else { - if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + if (!codegen_flags_changed || !flags_res_valid()) { uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); @@ -226,7 +226,7 @@ int ropJNE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_ if (!ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)) { - if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + if (!codegen_flags_changed || !flags_res_valid()) { uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); @@ -242,7 +242,7 @@ int ropJNE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_ } else { - if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + if (!codegen_flags_changed || !flags_res_valid()) { uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); @@ -954,7 +954,7 @@ uint32_t ropLOOPE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); } - if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + if (!codegen_flags_changed || !flags_res_valid()) { uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); jump_uop2 = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); @@ -990,7 +990,7 @@ uint32_t ropLOOPNE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); } - if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + if (!codegen_flags_changed || !flags_res_valid()) { uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); diff --git a/src/x86_flags.h b/src/x86_flags.h index 4332fad..49170f3 100644 --- a/src/x86_flags.h +++ b/src/x86_flags.h @@ -28,6 +28,14 @@ enum FLAGS_SAR16, FLAGS_SAR32, + FLAGS_ROL8, + FLAGS_ROL16, + FLAGS_ROL32, + + FLAGS_ROR8, + FLAGS_ROR16, + FLAGS_ROR32, + FLAGS_INC8, FLAGS_INC16, FLAGS_INC32, @@ -81,6 +89,12 @@ static inline int ZF_SET() case FLAGS_SBC32: return !cpu_state.flags_res; + case FLAGS_ROL8: + case FLAGS_ROL16: + case FLAGS_ROL32: + case FLAGS_ROR8: + case FLAGS_ROR16: + case FLAGS_ROR32: case FLAGS_UNKNOWN: return cpu_state.flags & Z_FLAG; } @@ -127,6 +141,12 @@ static inline int NF_SET() case FLAGS_SBC32: return cpu_state.flags_res & 0x80000000; + case FLAGS_ROL8: + case FLAGS_ROL16: + case FLAGS_ROL32: + case FLAGS_ROR8: + case FLAGS_ROR16: + case FLAGS_ROR32: case FLAGS_UNKNOWN: return cpu_state.flags & N_FLAG; } @@ -169,6 +189,12 @@ static inline int PF_SET() case FLAGS_SBC32: return znptable8[cpu_state.flags_res & 0xff] & P_FLAG; + case FLAGS_ROL8: + case FLAGS_ROL16: + case FLAGS_ROL32: + case FLAGS_ROR8: + case FLAGS_ROR16: + case FLAGS_ROR32: case FLAGS_UNKNOWN: return cpu_state.flags & P_FLAG; } @@ -226,7 +252,21 @@ static inline int VF_SET() return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x8000)); case FLAGS_SHR32: return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x80000000)); - + + case FLAGS_ROL8: + return (cpu_state.flags_res ^ (cpu_state.flags_res >> 7)) & 1; + case FLAGS_ROL16: + return (cpu_state.flags_res ^ (cpu_state.flags_res >> 15)) & 1; + case FLAGS_ROL32: + return (cpu_state.flags_res ^ (cpu_state.flags_res >> 31)) & 1; + + case FLAGS_ROR8: + return (cpu_state.flags_res ^ (cpu_state.flags_res >> 1)) & 0x40; + case FLAGS_ROR16: + return (cpu_state.flags_res ^ (cpu_state.flags_res >> 1)) & 0x4000; + case FLAGS_ROR32: + return (cpu_state.flags_res ^ (cpu_state.flags_res >> 1)) & 0x40000000; + case FLAGS_UNKNOWN: return cpu_state.flags & V_FLAG; } @@ -283,6 +323,12 @@ static inline int AF_SET() return ((cpu_state.flags_op1 & 0xf) < (cpu_state.flags_op2 & 0xf)) || ((cpu_state.flags_op1 & 0xf) == (cpu_state.flags_op2 & 0xf) && (cpu_state.flags_res & 0xf) != 0); + case FLAGS_ROL8: + case FLAGS_ROL16: + case FLAGS_ROL32: + case FLAGS_ROR8: + case FLAGS_ROR16: + case FLAGS_ROR32: case FLAGS_UNKNOWN: return cpu_state.flags & A_FLAG; } @@ -344,6 +390,18 @@ static inline int CF_SET() case FLAGS_ZN16: case FLAGS_ZN32: return 0; + + case FLAGS_ROL8: + case FLAGS_ROL16: + case FLAGS_ROL32: + return cpu_state.flags_res & 1; + + case FLAGS_ROR8: + return (cpu_state.flags_res & 0x80) ? 1 : 0; + case FLAGS_ROR16: + return (cpu_state.flags_res & 0x8000) ? 1 :0; + case FLAGS_ROR32: + return (cpu_state.flags_res & 0x80000000) ? 1 : 0; case FLAGS_DEC8: case FLAGS_DEC16: @@ -396,6 +454,15 @@ static inline void flags_rebuild_c() } } +static inline int flags_res_valid() +{ + if (cpu_state.flags_op == FLAGS_UNKNOWN || + (cpu_state.flags_op >= FLAGS_ROL8 && cpu_state.flags_op <= FLAGS_ROR32)) + return 0; + + return 1; +} + static inline void setznp8(uint8_t val) { cpu_state.flags_op = FLAGS_ZN8; @@ -418,6 +485,10 @@ static inline void setznp32(uint32_t val) cpu_state.flags_op1 = orig; \ cpu_state.flags_op2 = shift; +#define set_flags_rotate(op, res) \ + cpu_state.flags_op = op; \ + cpu_state.flags_res = res; + static inline void setadd8(uint8_t a, uint8_t b) { cpu_state.flags_op1 = a; diff --git a/src/x86_ops_shift.h b/src/x86_ops_shift.h index c248593..0d6d193 100644 --- a/src/x86_ops_shift.h +++ b/src/x86_ops_shift.h @@ -8,18 +8,14 @@ case 0x00: /*ROL b, c*/ \ temp = (temp << (c & 7)) | (temp >> (8-(c & 7))); \ seteab(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp & 1) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 7)) & 1) cpu_state.flags |= V_FLAG; \ + set_flags_rotate(FLAGS_ROL8, temp); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x08: /*ROR b,CL*/ \ temp = (temp >> (c & 7)) | (temp << (8-(c & 7))); \ - seteab(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp & 0x80) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x40) cpu_state.flags |= V_FLAG; \ + seteab(temp); if (cpu_state.abrt) return 1; \ + set_flags_rotate(FLAGS_ROR8, temp); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ @@ -89,18 +85,14 @@ case 0x00: /*ROL w, c*/ \ temp = (temp << (c & 15)) | (temp >> (16-(c & 15))); \ seteaw(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp & 1) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 15)) & 1) cpu_state.flags |= V_FLAG; \ + set_flags_rotate(FLAGS_ROL16, temp); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x08: /*ROR w,CL*/ \ temp = (temp >> (c & 15)) | (temp << (16-(c & 15))); \ seteaw(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp & 0x8000) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x4000) cpu_state.flags |= V_FLAG; \ + set_flags_rotate(FLAGS_ROR16, temp); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ @@ -170,18 +162,14 @@ case 0x00: /*ROL l, c*/ \ temp = (temp << c) | (temp >> (32-c)); \ seteal(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp & 1) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 31)) & 1) cpu_state.flags |= V_FLAG; \ + set_flags_rotate(FLAGS_ROL32, temp); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x08: /*ROR l,CL*/ \ temp = (temp >> c) | (temp << (32-c)); \ seteal(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp & 0x80000000) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x40000000) cpu_state.flags |= V_FLAG; \ + set_flags_rotate(FLAGS_ROR32, temp); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \