diff mbox

[RFC,v1,17/29] target-arc: B, BL

Message ID 1473373930-31547-18-git-send-email-mrolnik@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Michael Rolnik Sept. 8, 2016, 10:31 p.m. UTC
Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-arc/translate-inst.c | 189 ++++++++++++++++++++++++++++++++++++++++++++
 target-arc/translate-inst.h |   4 +
 2 files changed, 193 insertions(+)

Comments

Richard Henderson Sept. 21, 2016, 12:28 a.m. UTC | #1
On 09/08/2016 03:31 PM, Michael Rolnik wrote:
> +        case    ARC_COND_HI: {
> +            ARC_COND_IF_1(C, label_skip);
> +            ARC_COND_IF_1(Z, label_skip);
> +        } break;

Why aren't you using AND / OR to combine these conditions?


r~
diff mbox

Patch

diff --git a/target-arc/translate-inst.c b/target-arc/translate-inst.c
index 8288edd..ed2ced0 100644
--- a/target-arc/translate-inst.c
+++ b/target-arc/translate-inst.c
@@ -140,6 +140,137 @@  static void arc_gen_kill_delayslot(DisasCtxt *ctx)
     /*  nothing to do   */
 }
 
+#define ARC_COND_IF_1(flag, label) \
+                    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_ ## flag ## f, 0, label)
+#define ARC_COND_IF_0(flag, label) \
+                    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_ ## flag ## f, 0, label)
+
+void arc_gen_jump_ifnot(DisasCtxt *ctx, ARC_COND cond, TCGLabel *label_skip)
+{
+    TCGLabel *label_cont = gen_new_label();
+
+    switch (cond) {
+        /*
+            Always
+        */
+        case    ARC_COND_AL: {
+        } break;
+
+        /*
+            Zero
+        */
+        case    ARC_COND_Z: {
+            ARC_COND_IF_0(Z, label_skip);
+        } break;
+
+        /*
+            Non-Zero
+        */
+        case    ARC_COND_NZ: {
+            ARC_COND_IF_1(Z, label_skip);
+        } break;
+
+        /*
+            Positive
+        */
+        case    ARC_COND_P: {
+            tcg_gen_brcondi_tl(TCG_COND_LT, cpu_Nf, 0, label_skip);
+        } break;
+
+        /*
+            Negative
+        */
+        case    ARC_COND_N: {
+            tcg_gen_brcondi_tl(TCG_COND_GE, cpu_Nf, 0, label_skip);
+        } break;
+
+        /*
+            Carry set, lower than (unsigned)
+        */
+        case    ARC_COND_C: {
+            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_Cf, 0, label_skip);
+        } break;
+
+        /*
+            Carry clear, higher or same (unsigned)
+        */
+        case    ARC_COND_CC: {
+            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_Cf, 0, label_skip);
+        } break;
+
+        /*
+            Over-flow set
+        */
+        case    ARC_COND_VS: {
+            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_Cf, 0, label_skip);
+        } break;
+
+        /*
+            Over-flow clear
+        */
+        case    ARC_COND_VC: {
+            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_Cf, 0, label_skip);
+        } break;
+
+        /*
+            Greater than (signed)
+        */
+        case    ARC_COND_GT: {
+            tcg_gen_brcondi_tl(TCG_COND_LE, cpu_Nf, 0, label_skip);
+        } break;
+
+        /*
+            Greater than or equal to (signed)
+        */
+        case    ARC_COND_GE: {
+            tcg_gen_brcondi_tl(TCG_COND_LT, cpu_Nf, 0, label_skip);
+        } break;
+
+        /*
+            Less than (signed)
+        */
+        case    ARC_COND_LT: {
+            tcg_gen_brcondi_tl(TCG_COND_GE, cpu_Nf, 0, label_skip);
+        } break;
+
+        /*
+            Less than or equal to (signed)
+        */
+        case    ARC_COND_LE: {
+            tcg_gen_brcondi_tl(TCG_COND_GT, cpu_Nf, 0, label_skip);
+        } break;
+
+        /*
+            Higher than (unsigned)
+            !C and !Z
+        */
+        case    ARC_COND_HI: {
+            ARC_COND_IF_1(C, label_skip);
+            ARC_COND_IF_1(Z, label_skip);
+        } break;
+
+        /*
+            Lower than
+            C or Z
+        */
+        case    ARC_COND_LS: {
+            ARC_COND_IF_1(C, label_cont);
+            ARC_COND_IF_0(Z, label_skip);
+        } break;
+
+        /*
+            Positive non-zero
+            !N and !Z
+        */
+        case    ARC_COND_PNZ: {
+            ARC_COND_IF_1(N, label_skip);
+            ARC_COND_IF_1(Z, label_skip);
+        } break;
+    }
+
+    gen_set_label(label_cont);
+}
+
 /*
     ADC
 */
@@ -1787,3 +1918,61 @@  gen_set_label(label_done);
     return  BS_BRANCH_DS;
 }
 
+/*
+    B
+*/
+int arc_gen_B(DisasCtxt *ctx, TCGv rd, ARC_COND cond)
+{
+    TCGLabel *label_done = gen_new_label();
+    TCGLabel *label_fall = gen_new_label();
+
+    arc_gen_jump_ifnot(ctx, cond, label_fall);
+
+    tcg_gen_shli_tl(cpu_pc, rd, 1);
+    tcg_gen_addi_tl(cpu_pc, cpu_pc, ctx->pcl);
+    if (ctx->opt.d == 0) {
+        arc_gen_kill_delayslot(ctx);
+    } else {
+        arc_gen_exec_delayslot(ctx);
+    }
+    tcg_gen_br(label_done);
+
+gen_set_label(label_fall);
+    tcg_gen_movi_tl(cpu_pc, ctx->dpc);
+    arc_gen_exec_delayslot(ctx);
+
+gen_set_label(label_done);
+
+    return  BS_BRANCH_DS;
+}
+
+/*
+    BL
+*/
+int arc_gen_BL(DisasCtxt *ctx, TCGv Rd, ARC_COND cond)
+{
+    TCGLabel *label_done = gen_new_label();
+    TCGLabel *label_fall = gen_new_label();
+
+    arc_gen_jump_ifnot(ctx, cond, label_fall);
+
+    tcg_gen_shli_tl(cpu_pc, Rd, 2);
+    tcg_gen_addi_tl(cpu_pc, cpu_pc, ctx->pcl);
+    if (ctx->opt.d == 0) {
+        tcg_gen_movi_tl(cpu_blink, ctx->npc);
+        arc_gen_kill_delayslot(ctx);
+    } else {
+        tcg_gen_movi_tl(cpu_blink, ctx->dpc);
+        arc_gen_exec_delayslot(ctx);
+    }
+    tcg_gen_br(label_done);
+
+gen_set_label(label_fall);
+    tcg_gen_movi_tl(cpu_pc, ctx->dpc);
+    arc_gen_exec_delayslot(ctx);
+
+gen_set_label(label_done);
+
+    return  BS_BRANCH_DS;
+}
+
diff --git a/target-arc/translate-inst.h b/target-arc/translate-inst.h
index c78ed24..065570e 100644
--- a/target-arc/translate-inst.h
+++ b/target-arc/translate-inst.h
@@ -134,3 +134,7 @@  int arc_gen_BBIT0(DisasCtxt *c, TCGv src1, TCGv src2, TCGv rd);
 int arc_gen_BBIT1(DisasCtxt *c, TCGv src1, TCGv src2, TCGv rd);
 int arc_gen_BR(DisasCtxt *c, TCGv src1, TCGv src2, TCGv Rd, TCGCond cond);
 
+void arc_gen_jump_ifnot(DisasCtxt *ctx, ARC_COND cond, TCGLabel *label_skip);
+int arc_gen_B(DisasCtxt *c, TCGv rd, ARC_COND cond);
+int arc_gen_BL(DisasCtxt *c, TCGv Rd, ARC_COND cond);
+