From: Peter Maydell <peter.maydell@linaro.org>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 04/24] target-arm: Introduce DisasCompare
Date: Mon, 14 Sep 2015 14:52:51 +0100 [thread overview]
Message-ID: <1442238791-30255-5-git-send-email-peter.maydell@linaro.org> (raw)
In-Reply-To: <1442238791-30255-1-git-send-email-peter.maydell@linaro.org>
From: Richard Henderson <rth@twiddle.net>
Split arm_gen_test_cc into 3 functions, so that it can be reused
for non-branch TCG comparisons.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Message-id: 1441909103-24666-3-git-send-email-rth@twiddle.net
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target-arm/translate.c | 115 +++++++++++++++++++++++++++++--------------------
target-arm/translate.h | 9 ++++
2 files changed, 78 insertions(+), 46 deletions(-)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index f1b7c16..7d2e984 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -738,81 +738,104 @@ static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
#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(int cc, TCGLabel *label)
+void arm_test_cc(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_COND_EQ, cpu_ZF, 0, label);
- break;
case 1: /* ne: !Z */
- tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ZF, 0, label);
+ cond = TCG_COND_EQ;
+ value = cpu_ZF;
break;
+
case 2: /* cs: C */
- tcg_gen_brcondi_i32(TCG_COND_NE, cpu_CF, 0, label);
- break;
case 3: /* cc: !C */
- tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, label);
+ cond = TCG_COND_NE;
+ value = cpu_CF;
break;
+
case 4: /* mi: N */
- tcg_gen_brcondi_i32(TCG_COND_LT, cpu_NF, 0, label);
- break;
case 5: /* pl: !N */
- tcg_gen_brcondi_i32(TCG_COND_GE, cpu_NF, 0, label);
+ cond = TCG_COND_LT;
+ value = cpu_NF;
break;
+
case 6: /* vs: V */
- tcg_gen_brcondi_i32(TCG_COND_LT, cpu_VF, 0, label);
- break;
case 7: /* vc: !V */
- tcg_gen_brcondi_i32(TCG_COND_GE, cpu_VF, 0, label);
+ cond = TCG_COND_LT;
+ value = cpu_VF;
break;
+
case 8: /* hi: C && !Z */
- inv = gen_new_label();
- tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, inv);
- tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ZF, 0, label);
- gen_set_label(inv);
- break;
- case 9: /* ls: !C || Z */
- tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, label);
- tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
+ case 9: /* ls: !C || Z -> !(C && !Z) */
+ cond = TCG_COND_NE;
+ value = tcg_temp_new_i32();
+ 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(value, cpu_CF);
+ tcg_gen_and_i32(value, value, cpu_ZF);
break;
+
case 10: /* ge: N == V -> N ^ V == 0 */
- tmp = tcg_temp_new_i32();
- tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
- tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
- tcg_temp_free_i32(tmp);
- break;
case 11: /* lt: N != V -> N ^ V != 0 */
- tmp = tcg_temp_new_i32();
- tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
- tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
- tcg_temp_free_i32(tmp);
+ /* Since we're only interested in the sign bit, == 0 is >= 0. */
+ cond = TCG_COND_GE;
+ value = tcg_temp_new_i32();
+ global = false;
+ tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
break;
+
case 12: /* gt: !Z && N == V */
- inv = gen_new_label();
- tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, inv);
- tmp = tcg_temp_new_i32();
- tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
- tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
- tcg_temp_free_i32(tmp);
- gen_set_label(inv);
- break;
case 13: /* le: Z || N != V */
- tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
- tmp = tcg_temp_new_i32();
- tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
- tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
- tcg_temp_free_i32(tmp);
+ cond = TCG_COND_NE;
+ value = tcg_temp_new_i32();
+ 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(value, cpu_VF, cpu_NF);
+ tcg_gen_sari_i32(value, value, 31);
+ tcg_gen_andc_i32(value, 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(DisasCompare *cmp)
+{
+ if (!cmp->value_global) {
+ tcg_temp_free_i32(cmp->value);
+ }
+}
+
+void arm_jump_cc(DisasCompare *cmp, TCGLabel *label)
+{
+ tcg_gen_brcondi_i32(cmp->cond, cmp->value, 0, label);
+}
+
+void arm_gen_test_cc(int cc, TCGLabel *label)
+{
+ DisasCompare cmp;
+ arm_test_cc(&cmp, cc);
+ arm_jump_cc(&cmp, label);
+ arm_free_cc(&cmp);
}
static const uint8_t table_logic_cc[16] = {
diff --git a/target-arm/translate.h b/target-arm/translate.h
index a30a1db3..b8fe37a 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -63,6 +63,12 @@ typedef struct DisasContext {
TCGv_i64 tmp_a64[TMP_A64_MAX];
} DisasContext;
+typedef struct DisasCompare {
+ TCGCond cond;
+ TCGv_i32 value;
+ bool value_global;
+} DisasCompare;
+
/* Share the TCG temporaries common between 32 and 64 bit modes. */
extern TCGv_ptr cpu_env;
extern TCGv_i32 cpu_NF, cpu_ZF, cpu_CF, cpu_VF;
@@ -144,6 +150,9 @@ static inline void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
}
#endif
+void arm_test_cc(DisasCompare *cmp, int cc);
+void arm_free_cc(DisasCompare *cmp);
+void arm_jump_cc(DisasCompare *cmp, TCGLabel *label);
void arm_gen_test_cc(int cc, TCGLabel *label);
#endif /* TARGET_ARM_TRANSLATE_H */
--
1.9.1
next prev parent reply other threads:[~2015-09-14 13:53 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-09-14 13:52 [Qemu-devel] [PULL 00/24] target-arm queue Peter Maydell
2015-09-14 13:52 ` [Qemu-devel] [PULL 01/24] arm: xlnx-zynqmp: Fix up GIC region size Peter Maydell
2015-09-14 13:52 ` [Qemu-devel] [PULL 02/24] xlnx-zynqmp: Remove unnecessary brackets around error messages Peter Maydell
2015-09-14 13:52 ` [Qemu-devel] [PULL 03/24] target-arm: Share all common TCG temporaries Peter Maydell
2015-09-14 13:52 ` Peter Maydell [this message]
2015-09-14 13:52 ` [Qemu-devel] [PULL 05/24] target-arm: Handle always condition codes within arm_test_cc Peter Maydell
2015-09-14 13:52 ` [Qemu-devel] [PULL 06/24] target-arm: Use setcond and movcond for csel Peter Maydell
2015-09-14 13:52 ` [Qemu-devel] [PULL 07/24] target-arm: Implement ccmp branchless Peter Maydell
2015-09-14 13:52 ` [Qemu-devel] [PULL 08/24] target-arm: Implement fcsel with movcond Peter Maydell
2015-09-14 13:52 ` [Qemu-devel] [PULL 09/24] target-arm: Recognize SXTB, SXTH, SXTW, ASR Peter Maydell
2015-09-14 13:52 ` [Qemu-devel] [PULL 10/24] target-arm: Recognize UXTB, UXTH, LSR, LSL Peter Maydell
2015-09-14 13:52 ` [Qemu-devel] [PULL 11/24] target-arm: Eliminate unnecessary zero-extend in disas_bitfield Peter Maydell
2015-09-14 13:52 ` [Qemu-devel] [PULL 12/24] target-arm: Recognize ROR Peter Maydell
2015-09-14 13:53 ` [Qemu-devel] [PULL 13/24] target-arm: Use tcg_gen_extrh_i64_i32 Peter Maydell
2015-09-14 13:53 ` [Qemu-devel] [PULL 14/24] i.MX: Add GPIO device Peter Maydell
2015-09-14 13:53 ` [Qemu-devel] [PULL 15/24] i.MX: Add GPIO devices to i.MX31 SOC Peter Maydell
2015-09-14 13:53 ` [Qemu-devel] [PULL 16/24] i.MX: Add GPIO devices to i.MX25 SOC Peter Maydell
2015-09-14 13:53 ` [Qemu-devel] [PULL 17/24] hw/cpu/{a15mpcore, a9mpcore}: Handle missing has_el3 CPU props gracefully Peter Maydell
2015-09-14 13:53 ` [Qemu-devel] [PULL 18/24] target-arm: Add VTCR_EL2 Peter Maydell
2015-09-14 13:53 ` [Qemu-devel] [PULL 19/24] target-arm: Add VTTBR_EL2 Peter Maydell
2015-09-14 13:53 ` [Qemu-devel] [PULL 20/24] target-arm: Suppress TBI for S2 translations Peter Maydell
2015-09-14 13:53 ` [Qemu-devel] [PULL 21/24] target-arm: Suppress EPD for S2, EL2 and EL3 translations Peter Maydell
2015-09-14 13:53 ` [Qemu-devel] [PULL 22/24] target-arm: Add VPIDR_EL2 Peter Maydell
2015-09-14 13:53 ` [Qemu-devel] [PULL 23/24] target-arm: Break out mpidr_read_val() Peter Maydell
2015-09-14 13:53 ` [Qemu-devel] [PULL 24/24] target-arm: Add VMPIDR_EL2 Peter Maydell
2015-09-14 15:12 ` [Qemu-devel] [PULL 00/24] target-arm queue Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1442238791-30255-5-git-send-email-peter.maydell@linaro.org \
--to=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).