From 94f1227f7a9fb416c29f3d90ae505aa73365fbc2 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 10 Feb 2018 23:42:08 -0500 Subject: [PATCH] target-arm: Introduce DisasCompare Split arm_gen_test_cc into 3 functions, so that it can be reused for non-branch TCG comparisons. Backports commit 6c2c63d3a02c79e9035ca0370cc549d0f938a4dd from qemu --- qemu/aarch64.h | 3 + qemu/aarch64eb.h | 3 + qemu/arm.h | 3 + qemu/armeb.h | 3 + qemu/header_gen.py | 3 + qemu/m68k.h | 3 + qemu/mips.h | 3 + qemu/mips64.h | 3 + qemu/mips64el.h | 3 + qemu/mipsel.h | 3 + qemu/powerpc.h | 3 + qemu/sparc.h | 3 + qemu/sparc64.h | 3 + qemu/target-arm/translate.c | 115 +++++++++++++++++++++--------------- qemu/target-arm/translate.h | 8 +++ qemu/x86_64.h | 3 + 16 files changed, 119 insertions(+), 46 deletions(-) diff --git a/qemu/aarch64.h b/qemu/aarch64.h index fb6945f0..8bf79e93 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -120,6 +120,7 @@ #define arm_excp_target_el arm_excp_target_el_aarch64 #define arm_excp_unmasked arm_excp_unmasked_aarch64 #define arm_feature arm_feature_aarch64 +#define arm_free_cc arm_free_cc_aarch64 #define arm_generate_debug_exceptions arm_generate_debug_exceptions_aarch64 #define gen_intermediate_code gen_intermediate_code_aarch64 #define gen_intermediate_code_pc gen_intermediate_code_pc_aarch64 @@ -130,6 +131,7 @@ #define arm_is_psci_call arm_is_psci_call_aarch64 #define arm_is_secure arm_is_secure_aarch64 #define arm_is_secure_below_el3 arm_is_secure_below_el3_aarch64 +#define arm_jump_cc arm_jump_cc_aarch64 #define arm_ldl_code arm_ldl_code_aarch64 #define arm_lduw_code arm_lduw_code_aarch64 #define arm_log_exception arm_log_exception_aarch64 @@ -139,6 +141,7 @@ #define restore_state_to_opc restore_state_to_opc_aarch64 #define arm_rmode_to_sf arm_rmode_to_sf_aarch64 #define arm_singlestep_active arm_singlestep_active_aarch64 +#define arm_test_cc arm_test_cc_aarch64 #define tlb_fill tlb_fill_aarch64 #define tlb_flush tlb_flush_aarch64 #define tlb_flush_page tlb_flush_page_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index 46add07c..b196c53d 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -120,6 +120,7 @@ #define arm_excp_target_el arm_excp_target_el_aarch64eb #define arm_excp_unmasked arm_excp_unmasked_aarch64eb #define arm_feature arm_feature_aarch64eb +#define arm_free_cc arm_free_cc_aarch64eb #define arm_generate_debug_exceptions arm_generate_debug_exceptions_aarch64eb #define gen_intermediate_code gen_intermediate_code_aarch64eb #define gen_intermediate_code_pc gen_intermediate_code_pc_aarch64eb @@ -130,6 +131,7 @@ #define arm_is_psci_call arm_is_psci_call_aarch64eb #define arm_is_secure arm_is_secure_aarch64eb #define arm_is_secure_below_el3 arm_is_secure_below_el3_aarch64eb +#define arm_jump_cc arm_jump_cc_aarch64eb #define arm_ldl_code arm_ldl_code_aarch64eb #define arm_lduw_code arm_lduw_code_aarch64eb #define arm_log_exception arm_log_exception_aarch64eb @@ -139,6 +141,7 @@ #define restore_state_to_opc restore_state_to_opc_aarch64eb #define arm_rmode_to_sf arm_rmode_to_sf_aarch64eb #define arm_singlestep_active arm_singlestep_active_aarch64eb +#define arm_test_cc arm_test_cc_aarch64eb #define tlb_fill tlb_fill_aarch64eb #define tlb_flush tlb_flush_aarch64eb #define tlb_flush_page tlb_flush_page_aarch64eb diff --git a/qemu/arm.h b/qemu/arm.h index ee1938bf..80bd144b 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -120,6 +120,7 @@ #define arm_excp_target_el arm_excp_target_el_arm #define arm_excp_unmasked arm_excp_unmasked_arm #define arm_feature arm_feature_arm +#define arm_free_cc arm_free_cc_arm #define arm_generate_debug_exceptions arm_generate_debug_exceptions_arm #define gen_intermediate_code gen_intermediate_code_arm #define gen_intermediate_code_pc gen_intermediate_code_pc_arm @@ -130,6 +131,7 @@ #define arm_is_psci_call arm_is_psci_call_arm #define arm_is_secure arm_is_secure_arm #define arm_is_secure_below_el3 arm_is_secure_below_el3_arm +#define arm_jump_cc arm_jump_cc_arm #define arm_ldl_code arm_ldl_code_arm #define arm_lduw_code arm_lduw_code_arm #define arm_log_exception arm_log_exception_arm @@ -139,6 +141,7 @@ #define restore_state_to_opc restore_state_to_opc_arm #define arm_rmode_to_sf arm_rmode_to_sf_arm #define arm_singlestep_active arm_singlestep_active_arm +#define arm_test_cc arm_test_cc_arm #define tlb_fill tlb_fill_arm #define tlb_flush tlb_flush_arm #define tlb_flush_page tlb_flush_page_arm diff --git a/qemu/armeb.h b/qemu/armeb.h index 85ad2594..110e235e 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -120,6 +120,7 @@ #define arm_excp_target_el arm_excp_target_el_armeb #define arm_excp_unmasked arm_excp_unmasked_armeb #define arm_feature arm_feature_armeb +#define arm_free_cc arm_free_cc_armeb #define arm_generate_debug_exceptions arm_generate_debug_exceptions_armeb #define gen_intermediate_code gen_intermediate_code_armeb #define gen_intermediate_code_pc gen_intermediate_code_pc_armeb @@ -130,6 +131,7 @@ #define arm_is_psci_call arm_is_psci_call_armeb #define arm_is_secure arm_is_secure_armeb #define arm_is_secure_below_el3 arm_is_secure_below_el3_armeb +#define arm_jump_cc arm_jump_cc_armeb #define arm_ldl_code arm_ldl_code_armeb #define arm_lduw_code arm_lduw_code_armeb #define arm_log_exception arm_log_exception_armeb @@ -139,6 +141,7 @@ #define restore_state_to_opc restore_state_to_opc_armeb #define arm_rmode_to_sf arm_rmode_to_sf_armeb #define arm_singlestep_active arm_singlestep_active_armeb +#define arm_test_cc arm_test_cc_armeb #define tlb_fill tlb_fill_armeb #define tlb_flush tlb_flush_armeb #define tlb_flush_page tlb_flush_page_armeb diff --git a/qemu/header_gen.py b/qemu/header_gen.py index e763bff6..d02a7c04 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -126,6 +126,7 @@ symbols = ( 'arm_excp_target_el', 'arm_excp_unmasked', 'arm_feature', + 'arm_free_cc', 'arm_generate_debug_exceptions', 'gen_intermediate_code', 'gen_intermediate_code_pc', @@ -136,6 +137,7 @@ symbols = ( 'arm_is_psci_call', 'arm_is_secure', 'arm_is_secure_below_el3', + 'arm_jump_cc', 'arm_ldl_code', 'arm_lduw_code', 'arm_log_exception', @@ -145,6 +147,7 @@ symbols = ( 'restore_state_to_opc', 'arm_rmode_to_sf', 'arm_singlestep_active', + 'arm_test_cc', 'tlb_fill', 'tlb_flush', 'tlb_flush_page', diff --git a/qemu/m68k.h b/qemu/m68k.h index c5aecf5d..e6ee76e1 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -120,6 +120,7 @@ #define arm_excp_target_el arm_excp_target_el_m68k #define arm_excp_unmasked arm_excp_unmasked_m68k #define arm_feature arm_feature_m68k +#define arm_free_cc arm_free_cc_m68k #define arm_generate_debug_exceptions arm_generate_debug_exceptions_m68k #define gen_intermediate_code gen_intermediate_code_m68k #define gen_intermediate_code_pc gen_intermediate_code_pc_m68k @@ -130,6 +131,7 @@ #define arm_is_psci_call arm_is_psci_call_m68k #define arm_is_secure arm_is_secure_m68k #define arm_is_secure_below_el3 arm_is_secure_below_el3_m68k +#define arm_jump_cc arm_jump_cc_m68k #define arm_ldl_code arm_ldl_code_m68k #define arm_lduw_code arm_lduw_code_m68k #define arm_log_exception arm_log_exception_m68k @@ -139,6 +141,7 @@ #define restore_state_to_opc restore_state_to_opc_m68k #define arm_rmode_to_sf arm_rmode_to_sf_m68k #define arm_singlestep_active arm_singlestep_active_m68k +#define arm_test_cc arm_test_cc_m68k #define tlb_fill tlb_fill_m68k #define tlb_flush tlb_flush_m68k #define tlb_flush_page tlb_flush_page_m68k diff --git a/qemu/mips.h b/qemu/mips.h index 90d69f28..24ed5c98 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -120,6 +120,7 @@ #define arm_excp_target_el arm_excp_target_el_mips #define arm_excp_unmasked arm_excp_unmasked_mips #define arm_feature arm_feature_mips +#define arm_free_cc arm_free_cc_mips #define arm_generate_debug_exceptions arm_generate_debug_exceptions_mips #define gen_intermediate_code gen_intermediate_code_mips #define gen_intermediate_code_pc gen_intermediate_code_pc_mips @@ -130,6 +131,7 @@ #define arm_is_psci_call arm_is_psci_call_mips #define arm_is_secure arm_is_secure_mips #define arm_is_secure_below_el3 arm_is_secure_below_el3_mips +#define arm_jump_cc arm_jump_cc_mips #define arm_ldl_code arm_ldl_code_mips #define arm_lduw_code arm_lduw_code_mips #define arm_log_exception arm_log_exception_mips @@ -139,6 +141,7 @@ #define restore_state_to_opc restore_state_to_opc_mips #define arm_rmode_to_sf arm_rmode_to_sf_mips #define arm_singlestep_active arm_singlestep_active_mips +#define arm_test_cc arm_test_cc_mips #define tlb_fill tlb_fill_mips #define tlb_flush tlb_flush_mips #define tlb_flush_page tlb_flush_page_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 9042c657..c56eae7a 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -120,6 +120,7 @@ #define arm_excp_target_el arm_excp_target_el_mips64 #define arm_excp_unmasked arm_excp_unmasked_mips64 #define arm_feature arm_feature_mips64 +#define arm_free_cc arm_free_cc_mips64 #define arm_generate_debug_exceptions arm_generate_debug_exceptions_mips64 #define gen_intermediate_code gen_intermediate_code_mips64 #define gen_intermediate_code_pc gen_intermediate_code_pc_mips64 @@ -130,6 +131,7 @@ #define arm_is_psci_call arm_is_psci_call_mips64 #define arm_is_secure arm_is_secure_mips64 #define arm_is_secure_below_el3 arm_is_secure_below_el3_mips64 +#define arm_jump_cc arm_jump_cc_mips64 #define arm_ldl_code arm_ldl_code_mips64 #define arm_lduw_code arm_lduw_code_mips64 #define arm_log_exception arm_log_exception_mips64 @@ -139,6 +141,7 @@ #define restore_state_to_opc restore_state_to_opc_mips64 #define arm_rmode_to_sf arm_rmode_to_sf_mips64 #define arm_singlestep_active arm_singlestep_active_mips64 +#define arm_test_cc arm_test_cc_mips64 #define tlb_fill tlb_fill_mips64 #define tlb_flush tlb_flush_mips64 #define tlb_flush_page tlb_flush_page_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 4bcd3785..9ca6afab 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -120,6 +120,7 @@ #define arm_excp_target_el arm_excp_target_el_mips64el #define arm_excp_unmasked arm_excp_unmasked_mips64el #define arm_feature arm_feature_mips64el +#define arm_free_cc arm_free_cc_mips64el #define arm_generate_debug_exceptions arm_generate_debug_exceptions_mips64el #define gen_intermediate_code gen_intermediate_code_mips64el #define gen_intermediate_code_pc gen_intermediate_code_pc_mips64el @@ -130,6 +131,7 @@ #define arm_is_psci_call arm_is_psci_call_mips64el #define arm_is_secure arm_is_secure_mips64el #define arm_is_secure_below_el3 arm_is_secure_below_el3_mips64el +#define arm_jump_cc arm_jump_cc_mips64el #define arm_ldl_code arm_ldl_code_mips64el #define arm_lduw_code arm_lduw_code_mips64el #define arm_log_exception arm_log_exception_mips64el @@ -139,6 +141,7 @@ #define restore_state_to_opc restore_state_to_opc_mips64el #define arm_rmode_to_sf arm_rmode_to_sf_mips64el #define arm_singlestep_active arm_singlestep_active_mips64el +#define arm_test_cc arm_test_cc_mips64el #define tlb_fill tlb_fill_mips64el #define tlb_flush tlb_flush_mips64el #define tlb_flush_page tlb_flush_page_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index f62ba292..bd832097 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -120,6 +120,7 @@ #define arm_excp_target_el arm_excp_target_el_mipsel #define arm_excp_unmasked arm_excp_unmasked_mipsel #define arm_feature arm_feature_mipsel +#define arm_free_cc arm_free_cc_mipsel #define arm_generate_debug_exceptions arm_generate_debug_exceptions_mipsel #define gen_intermediate_code gen_intermediate_code_mipsel #define gen_intermediate_code_pc gen_intermediate_code_pc_mipsel @@ -130,6 +131,7 @@ #define arm_is_psci_call arm_is_psci_call_mipsel #define arm_is_secure arm_is_secure_mipsel #define arm_is_secure_below_el3 arm_is_secure_below_el3_mipsel +#define arm_jump_cc arm_jump_cc_mipsel #define arm_ldl_code arm_ldl_code_mipsel #define arm_lduw_code arm_lduw_code_mipsel #define arm_log_exception arm_log_exception_mipsel @@ -139,6 +141,7 @@ #define restore_state_to_opc restore_state_to_opc_mipsel #define arm_rmode_to_sf arm_rmode_to_sf_mipsel #define arm_singlestep_active arm_singlestep_active_mipsel +#define arm_test_cc arm_test_cc_mipsel #define tlb_fill tlb_fill_mipsel #define tlb_flush tlb_flush_mipsel #define tlb_flush_page tlb_flush_page_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index 32313a71..5dc36403 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -120,6 +120,7 @@ #define arm_excp_target_el arm_excp_target_el_powerpc #define arm_excp_unmasked arm_excp_unmasked_powerpc #define arm_feature arm_feature_powerpc +#define arm_free_cc arm_free_cc_powerpc #define arm_generate_debug_exceptions arm_generate_debug_exceptions_powerpc #define gen_intermediate_code gen_intermediate_code_powerpc #define gen_intermediate_code_pc gen_intermediate_code_pc_powerpc @@ -130,6 +131,7 @@ #define arm_is_psci_call arm_is_psci_call_powerpc #define arm_is_secure arm_is_secure_powerpc #define arm_is_secure_below_el3 arm_is_secure_below_el3_powerpc +#define arm_jump_cc arm_jump_cc_powerpc #define arm_ldl_code arm_ldl_code_powerpc #define arm_lduw_code arm_lduw_code_powerpc #define arm_log_exception arm_log_exception_powerpc @@ -139,6 +141,7 @@ #define restore_state_to_opc restore_state_to_opc_powerpc #define arm_rmode_to_sf arm_rmode_to_sf_powerpc #define arm_singlestep_active arm_singlestep_active_powerpc +#define arm_test_cc arm_test_cc_powerpc #define tlb_fill tlb_fill_powerpc #define tlb_flush tlb_flush_powerpc #define tlb_flush_page tlb_flush_page_powerpc diff --git a/qemu/sparc.h b/qemu/sparc.h index 232154a4..fbff34d6 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -120,6 +120,7 @@ #define arm_excp_target_el arm_excp_target_el_sparc #define arm_excp_unmasked arm_excp_unmasked_sparc #define arm_feature arm_feature_sparc +#define arm_free_cc arm_free_cc_sparc #define arm_generate_debug_exceptions arm_generate_debug_exceptions_sparc #define gen_intermediate_code gen_intermediate_code_sparc #define gen_intermediate_code_pc gen_intermediate_code_pc_sparc @@ -130,6 +131,7 @@ #define arm_is_psci_call arm_is_psci_call_sparc #define arm_is_secure arm_is_secure_sparc #define arm_is_secure_below_el3 arm_is_secure_below_el3_sparc +#define arm_jump_cc arm_jump_cc_sparc #define arm_ldl_code arm_ldl_code_sparc #define arm_lduw_code arm_lduw_code_sparc #define arm_log_exception arm_log_exception_sparc @@ -139,6 +141,7 @@ #define restore_state_to_opc restore_state_to_opc_sparc #define arm_rmode_to_sf arm_rmode_to_sf_sparc #define arm_singlestep_active arm_singlestep_active_sparc +#define arm_test_cc arm_test_cc_sparc #define tlb_fill tlb_fill_sparc #define tlb_flush tlb_flush_sparc #define tlb_flush_page tlb_flush_page_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index 8d012e71..4b581b79 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -120,6 +120,7 @@ #define arm_excp_target_el arm_excp_target_el_sparc64 #define arm_excp_unmasked arm_excp_unmasked_sparc64 #define arm_feature arm_feature_sparc64 +#define arm_free_cc arm_free_cc_sparc64 #define arm_generate_debug_exceptions arm_generate_debug_exceptions_sparc64 #define gen_intermediate_code gen_intermediate_code_sparc64 #define gen_intermediate_code_pc gen_intermediate_code_pc_sparc64 @@ -130,6 +131,7 @@ #define arm_is_psci_call arm_is_psci_call_sparc64 #define arm_is_secure arm_is_secure_sparc64 #define arm_is_secure_below_el3 arm_is_secure_below_el3_sparc64 +#define arm_jump_cc arm_jump_cc_sparc64 #define arm_ldl_code arm_ldl_code_sparc64 #define arm_lduw_code arm_lduw_code_sparc64 #define arm_log_exception arm_log_exception_sparc64 @@ -139,6 +141,7 @@ #define restore_state_to_opc restore_state_to_opc_sparc64 #define arm_rmode_to_sf arm_rmode_to_sf_sparc64 #define arm_singlestep_active arm_singlestep_active_sparc64 +#define arm_test_cc arm_test_cc_sparc64 #define tlb_fill tlb_fill_sparc64 #define tlb_flush tlb_flush_sparc64 #define tlb_flush_page tlb_flush_page_sparc64 diff --git a/qemu/target-arm/translate.c b/qemu/target-arm/translate.c index 14123e10..d07305e2 100644 --- a/qemu/target-arm/translate.c +++ b/qemu/target-arm/translate.c @@ -736,81 +736,104 @@ static void gen_thumb2_parallel_addsub(DisasContext *s, int op1, int op2, TCGv_i #undef PAS_OP /* - * generate a conditional branch based on ARM condition code cc. + * Generate a conditional based on ARM condition code cc. * This is common between ARM and Aarch64 targets. */ -void arm_gen_test_cc(TCGContext *tcg_ctx, int cc, TCGLabel *label) +void arm_test_cc(TCGContext *tcg_ctx, DisasCompare *cmp, int cc) { - TCGv_i32 tmp; - TCGLabel *inv; + TCGv_i32 value; + TCGCond cond; + bool global = true; switch (cc) { case 0: /* eq: Z */ - tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_EQ, tcg_ctx->cpu_ZF, 0, label); - break; case 1: /* ne: !Z */ - tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_NE, tcg_ctx->cpu_ZF, 0, label); + cond = TCG_COND_EQ; + value = tcg_ctx->cpu_ZF; break; + case 2: /* cs: C */ - tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_NE, tcg_ctx->cpu_CF, 0, label); - break; case 3: /* cc: !C */ - tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_EQ, tcg_ctx->cpu_CF, 0, label); + cond = TCG_COND_NE; + value = tcg_ctx->cpu_CF; break; + case 4: /* mi: N */ - tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_LT, tcg_ctx->cpu_NF, 0, label); - break; case 5: /* pl: !N */ - tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_GE, tcg_ctx->cpu_NF, 0, label); + cond = TCG_COND_LT; + value = tcg_ctx->cpu_NF; break; + case 6: /* vs: V */ - tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_LT, tcg_ctx->cpu_VF, 0, label); - break; case 7: /* vc: !V */ - tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_GE, tcg_ctx->cpu_VF, 0, label); + cond = TCG_COND_LT; + value = tcg_ctx->cpu_VF; break; + case 8: /* hi: C && !Z */ - inv = gen_new_label(tcg_ctx); - tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_EQ, tcg_ctx->cpu_CF, 0, inv); - tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_NE, tcg_ctx->cpu_ZF, 0, label); - gen_set_label(tcg_ctx, inv); - break; - case 9: /* ls: !C || Z */ - tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_EQ, tcg_ctx->cpu_CF, 0, label); - tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_EQ, tcg_ctx->cpu_ZF, 0, label); + case 9: /* ls: !C || Z -> !(C && !Z) */ + cond = TCG_COND_NE; + value = tcg_temp_new_i32(tcg_ctx); + global = false; + /* CF is 1 for C, so -CF is an all-bits-set mask for C; + ZF is non-zero for !Z; so AND the two subexpressions. */ + tcg_gen_neg_i32(tcg_ctx, value, tcg_ctx->cpu_CF); + tcg_gen_and_i32(tcg_ctx, value, value, tcg_ctx->cpu_ZF); break; + case 10: /* ge: N == V -> N ^ V == 0 */ - tmp = tcg_temp_new_i32(tcg_ctx); - tcg_gen_xor_i32(tcg_ctx, tmp, tcg_ctx->cpu_VF, tcg_ctx->cpu_NF); - tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_GE, tmp, 0, label); - tcg_temp_free_i32(tcg_ctx, tmp); - break; case 11: /* lt: N != V -> N ^ V != 0 */ - tmp = tcg_temp_new_i32(tcg_ctx); - tcg_gen_xor_i32(tcg_ctx, tmp, tcg_ctx->cpu_VF, tcg_ctx->cpu_NF); - tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_LT, tmp, 0, label); - tcg_temp_free_i32(tcg_ctx, tmp); + /* Since we're only interested in the sign bit, == 0 is >= 0. */ + cond = TCG_COND_GE; + value = tcg_temp_new_i32(tcg_ctx); + global = false; + tcg_gen_xor_i32(tcg_ctx, value, tcg_ctx->cpu_VF, tcg_ctx->cpu_NF); break; + case 12: /* gt: !Z && N == V */ - inv = gen_new_label(tcg_ctx); - tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_EQ, tcg_ctx->cpu_ZF, 0, inv); - tmp = tcg_temp_new_i32(tcg_ctx); - tcg_gen_xor_i32(tcg_ctx, tmp, tcg_ctx->cpu_VF, tcg_ctx->cpu_NF); - tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_GE, tmp, 0, label); - tcg_temp_free_i32(tcg_ctx, tmp); - gen_set_label(tcg_ctx, inv); - break; case 13: /* le: Z || N != V */ - tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_EQ, tcg_ctx->cpu_ZF, 0, label); - tmp = tcg_temp_new_i32(tcg_ctx); - tcg_gen_xor_i32(tcg_ctx, tmp, tcg_ctx->cpu_VF, tcg_ctx->cpu_NF); - tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_LT, tmp, 0, label); - tcg_temp_free_i32(tcg_ctx, tmp); + cond = TCG_COND_NE; + value = tcg_temp_new_i32(tcg_ctx); + global = false; + /* (N == V) is equal to the sign bit of ~(NF ^ VF). Propagate + * the sign bit then AND with ZF to yield the result. */ + tcg_gen_xor_i32(tcg_ctx, value, tcg_ctx->cpu_VF, tcg_ctx->cpu_NF); + tcg_gen_sari_i32(tcg_ctx, value, value, 31); + tcg_gen_andc_i32(tcg_ctx, value, tcg_ctx->cpu_ZF, value); break; + default: fprintf(stderr, "Bad condition code 0x%x\n", cc); abort(); } + + if (cc & 1) { + cond = tcg_invert_cond(cond); + } + + cmp->cond = cond; + cmp->value = value; + cmp->value_global = global; +} + +void arm_free_cc(TCGContext *tcg_ctx, DisasCompare *cmp) +{ + if (!cmp->value_global) { + tcg_temp_free_i32(tcg_ctx, cmp->value); + } +} + +void arm_jump_cc(TCGContext *tcg_ctx, DisasCompare *cmp, TCGLabel *label) +{ + tcg_gen_brcondi_i32(tcg_ctx, cmp->cond, cmp->value, 0, label); +} + +void arm_gen_test_cc(TCGContext *tcg_ctx, int cc, TCGLabel *label) +{ + DisasCompare cmp; + arm_test_cc(tcg_ctx, &cmp, cc); + arm_jump_cc(tcg_ctx, &cmp, label); + arm_free_cc(tcg_ctx, &cmp); } static const uint8_t table_logic_cc[16] = { diff --git a/qemu/target-arm/translate.h b/qemu/target-arm/translate.h index e0c9ddf0..92a84a7d 100644 --- a/qemu/target-arm/translate.h +++ b/qemu/target-arm/translate.h @@ -62,6 +62,11 @@ typedef struct DisasContext { struct uc_struct *uc; } DisasContext; +typedef struct DisasCompare { + TCGCond cond; + TCGv_i32 value; + bool value_global; +} DisasCompare; static inline int arm_dc_feature(DisasContext *dc, int feature) { @@ -111,6 +116,9 @@ static inline void gen_a64_set_pc_im(uint64_t val) } #endif +void arm_test_cc(TCGContext *tcg_ctx, DisasCompare *cmp, int cc); +void arm_free_cc(TCGContext *tcg_ctx, DisasCompare *cmp); +void arm_jump_cc(TCGContext *tcg_ctx, DisasCompare *cmp, TCGLabel *label); void arm_gen_test_cc(TCGContext *tcg_ctx, int cc, TCGLabel *label); #endif /* TARGET_ARM_TRANSLATE_H */ diff --git a/qemu/x86_64.h b/qemu/x86_64.h index 8c84e419..94c6e3a3 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -120,6 +120,7 @@ #define arm_excp_target_el arm_excp_target_el_x86_64 #define arm_excp_unmasked arm_excp_unmasked_x86_64 #define arm_feature arm_feature_x86_64 +#define arm_free_cc arm_free_cc_x86_64 #define arm_generate_debug_exceptions arm_generate_debug_exceptions_x86_64 #define gen_intermediate_code gen_intermediate_code_x86_64 #define gen_intermediate_code_pc gen_intermediate_code_pc_x86_64 @@ -130,6 +131,7 @@ #define arm_is_psci_call arm_is_psci_call_x86_64 #define arm_is_secure arm_is_secure_x86_64 #define arm_is_secure_below_el3 arm_is_secure_below_el3_x86_64 +#define arm_jump_cc arm_jump_cc_x86_64 #define arm_ldl_code arm_ldl_code_x86_64 #define arm_lduw_code arm_lduw_code_x86_64 #define arm_log_exception arm_log_exception_x86_64 @@ -139,6 +141,7 @@ #define restore_state_to_opc restore_state_to_opc_x86_64 #define arm_rmode_to_sf arm_rmode_to_sf_x86_64 #define arm_singlestep_active arm_singlestep_active_x86_64 +#define arm_test_cc arm_test_cc_x86_64 #define tlb_fill tlb_fill_x86_64 #define tlb_flush tlb_flush_x86_64 #define tlb_flush_page tlb_flush_page_x86_64