diff mbox

[v2,01/13] target-arm: A64: add support for conditional select

Message ID 1386335953-28876-2-git-send-email-peter.maydell@linaro.org
State Superseded
Headers show

Commit Message

Peter Maydell Dec. 6, 2013, 1:19 p.m. UTC
From: Claudio Fontana <claudio.fontana@linaro.org>

This patch adds support for the instruction group "C3.5.6
Conditional select": CSEL, CSINC, CSINV, CSNEG.

Signed-off-by: Claudio Fontana <claudio.fontana@linaro.org>
[PMM: Improved code generated in the nomatch case as per RTH suggestions]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/translate-a64.c |   59 ++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 57 insertions(+), 2 deletions(-)

Comments

Richard Henderson Dec. 6, 2013, 4:59 p.m. UTC | #1
On 12/07/2013 02:19 AM, Peter Maydell wrote:
> +    tcg_rd = cpu_reg(s, rd);
> +
> +    if (cond >= 0x0e) { /* condition "always" */
> +        tcg_src = read_cpu_reg(s, rn, sf);
> +        tcg_gen_mov_i64(tcg_rd, tcg_src);
> +    } else {
> +        /* OPTME: we could use movcond here, at the cost of duplicating
> +         * a lot of the arm_gen_test_cc() logic.
> +         */
> +        int label_match = gen_new_label();
> +        int label_continue = gen_new_label();
> +
> +        arm_gen_test_cc(cond, label_match);
> +        /* nomatch: */
> +        tcg_src = cpu_reg(s, rm);

Sorry for missing this in the first round: For the silly corner case of Rd ==
XZR, tcg_rd is dead after the branch.

We could either move the tcg_rd assignment down into each basic block with the
assignment to tcg_src, or simply add

    if (rd == 31) {
        /* silly no-op write; until we use movcond we must special-case
           this to avoid a dead temporary across basic blocks.  */
        return;
    }

Either solution is ok by me.


r~
Peter Maydell Dec. 6, 2013, 5:24 p.m. UTC | #2
On 6 December 2013 16:59, Richard Henderson <rth@twiddle.net> wrote:
> Sorry for missing this in the first round: For the silly corner case of Rd ==
> XZR, tcg_rd is dead after the branch.
>
> We could either move the tcg_rd assignment down into each basic block with the
> assignment to tcg_src, or simply add
>
>     if (rd == 31) {
>         /* silly no-op write; until we use movcond we must special-case
>            this to avoid a dead temporary across basic blocks.  */
>         return;
>     }
>
> Either solution is ok by me.

That specialcase looks simplest to me.

thanks
-- PMM
diff mbox

Patch

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index fdc3ed8..977c4c2 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -724,10 +724,65 @@  static void disas_cc_reg(DisasContext *s, uint32_t insn)
     unsupported_encoding(s, insn);
 }
 
-/* Conditional select */
+/* C3.5.6 Conditional select
+ *   31   30  29  28             21 20  16 15  12 11 10 9    5 4    0
+ * +----+----+---+-----------------+------+------+-----+------+------+
+ * | sf | op | S | 1 1 0 1 0 1 0 0 |  Rm  | cond | op2 |  Rn  |  Rd  |
+ * +----+----+---+-----------------+------+------+-----+------+------+
+ */
 static void disas_cond_select(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    unsigned int sf, else_inv, rm, cond, else_inc, rn, rd;
+    TCGv_i64 tcg_rd, tcg_src;
+
+    if (extract32(insn, 29, 1) || extract32(insn, 11, 1)) {
+        /* S == 1 or op2<1> == 1 */
+        unallocated_encoding(s);
+        return;
+    }
+    sf = extract32(insn, 31, 1);
+    else_inv = extract32(insn, 30, 1);
+    rm = extract32(insn, 16, 5);
+    cond = extract32(insn, 12, 4);
+    else_inc = extract32(insn, 10, 1);
+    rn = extract32(insn, 5, 5);
+    rd = extract32(insn, 0, 5);
+    tcg_rd = cpu_reg(s, rd);
+
+    if (cond >= 0x0e) { /* condition "always" */
+        tcg_src = read_cpu_reg(s, rn, sf);
+        tcg_gen_mov_i64(tcg_rd, tcg_src);
+    } else {
+        /* OPTME: we could use movcond here, at the cost of duplicating
+         * a lot of the arm_gen_test_cc() logic.
+         */
+        int label_match = gen_new_label();
+        int label_continue = gen_new_label();
+
+        arm_gen_test_cc(cond, label_match);
+        /* nomatch: */
+        tcg_src = cpu_reg(s, rm);
+
+        if (else_inv && else_inc) {
+            tcg_gen_neg_i64(tcg_rd, tcg_src);
+        } else if (else_inv) {
+            tcg_gen_not_i64(tcg_rd, tcg_src);
+        } else if (else_inc) {
+            tcg_gen_addi_i64(tcg_rd, tcg_src, 1);
+        } else {
+            tcg_gen_mov_i64(tcg_rd, tcg_src);
+        }
+        if (!sf) {
+            tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
+        }
+        tcg_gen_br(label_continue);
+        /* match: */
+        gen_set_label(label_match);
+        tcg_src = read_cpu_reg(s, rn, sf);
+        tcg_gen_mov_i64(tcg_rd, tcg_src);
+        /* continue: */
+        gen_set_label(label_continue);
+    }
 }
 
 /* Data-processing (1 source) */