diff mbox series

[RFC,v2,11/24] riscv: tcg-target: Add the mov and movi instruction

Message ID 51221791beb40b25309805b1c76db0004f26f64e.1543352682.git.alistair.francis@wdc.com
State New
Headers show
Series Add RISC-V TCG backend support | expand

Commit Message

Alistair Francis Nov. 27, 2018, 9:08 p.m. UTC
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
 tcg/riscv/tcg-target.inc.c | 78 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

Comments

Richard Henderson Nov. 28, 2018, 7:48 p.m. UTC | #1
On 11/27/18 1:08 PM, Alistair Francis wrote:
> +static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
> +                         tcg_target_long val)
> +{
> +#if TCG_TARGET_REG_BITS == 64
> +    tcg_target_long lo = sextract64(val, 0, 12);
> +#else
> +    tcg_target_long lo = sextract32(val, 0, 12);
> +#endif

I really think this ifdef should be moved into a helper function.  There are
quite a number of copies of it throughout.

> +    tcg_target_long hi = val - lo;
> +    int shift;
> +    tcg_target_long tmp;
> +
> +    RISCVInsn add32_op = TCG_TARGET_REG_BITS == 64 ? OPC_ADDIW : OPC_ADDI;
> +
> +#if TCG_TARGET_REG_BITS == 64
> +    ptrdiff_t offset = tcg_pcrel_diff(s, (void *)val);
> +#endif
> +
> +    if (TCG_TARGET_REG_BITS == 32 || val == (int32_t)val) {
> +        tcg_out_opc_upper(s, OPC_LUI, rd, hi);
> +        if (lo != 0) {
> +            tcg_out_opc_imm(s, add32_op, rd, rd, lo);
> +        }
> +
> +        return;
> +    }

Your reorg has failed to keep the single insn ADDI(W) case.

> +    /* We can only be here if TCG_TARGET_REG_BITS != 32 */
> +    if (offset == sextract64(offset, 1, 31) << 1) {

The ifdef above won't compile for rv32, because offset is used unconditionally
here.  Remove the ifdef and allow that to be removed as dead code by the compiler.

> +        tcg_out_opc_upper(s, OPC_AUIPC, rd, 0);
> +        tcg_out_opc_imm(s, OPC_ADDI, rd, rd, 0);
> +        reloc_call(s->code_ptr - 2, (tcg_insn_unit *)val);
> +        return;
> +    }
> +
> +    shift = ctz64(val);
> +    tmp = val >> shift;
> +
> +    if (tmp == sextract64(tmp, 0, 12)) {
> +        tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, 1);

s/1/tmp/

> +        tcg_out_opc_imm(s, OPC_SLLI, rd, rd, ctz64(val));
> +    } else if (!(val >> 31 == 0 || val >> 31 == -1)) {
> +        shift = ctz64(hi);
> +        hi >>= shift;
> +        tcg_out_movi(s, type, rd, hi);
> +        tcg_out_opc_imm(s, OPC_SLLI, rd, rd, shift);
> +        if (lo != 0) {
> +            tcg_out_opc_imm(s, OPC_ADDI, rd, rd, lo);
> +        }
> +    } else {
> +        if (hi != 0) {
> +            tcg_out_opc_upper(s, OPC_LUI, rd, hi);
> +        }
> +        if (lo != 0) {
> +            tcg_out_opc_imm(s, add32_op, rd, hi == 0 ? TCG_REG_ZERO : rd, lo);
> +        }
> +    }

The final else case is identical with the first if.


r~
diff mbox series

Patch

diff --git a/tcg/riscv/tcg-target.inc.c b/tcg/riscv/tcg-target.inc.c
index 9c48679f11..e5a07b146f 100644
--- a/tcg/riscv/tcg-target.inc.c
+++ b/tcg/riscv/tcg-target.inc.c
@@ -434,6 +434,84 @@  static void patch_reloc(tcg_insn_unit *code_ptr, int type,
     }
 }
 
+/*
+ * TCG intrinsics
+ */
+
+static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
+{
+    if (ret == arg) {
+        return;
+    }
+    switch (type) {
+    case TCG_TYPE_I32:
+    case TCG_TYPE_I64:
+        tcg_out_opc_imm(s, OPC_ADDI, ret, arg, 0);
+        break;
+    default:
+        g_assert_not_reached();
+    }
+}
+
+static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
+                         tcg_target_long val)
+{
+#if TCG_TARGET_REG_BITS == 64
+    tcg_target_long lo = sextract64(val, 0, 12);
+#else
+    tcg_target_long lo = sextract32(val, 0, 12);
+#endif
+    tcg_target_long hi = val - lo;
+    int shift;
+    tcg_target_long tmp;
+
+    RISCVInsn add32_op = TCG_TARGET_REG_BITS == 64 ? OPC_ADDIW : OPC_ADDI;
+
+#if TCG_TARGET_REG_BITS == 64
+    ptrdiff_t offset = tcg_pcrel_diff(s, (void *)val);
+#endif
+
+    if (TCG_TARGET_REG_BITS == 32 || val == (int32_t)val) {
+        tcg_out_opc_upper(s, OPC_LUI, rd, hi);
+        if (lo != 0) {
+            tcg_out_opc_imm(s, add32_op, rd, rd, lo);
+        }
+
+        return;
+    }
+
+    /* We can only be here if TCG_TARGET_REG_BITS != 32 */
+    if (offset == sextract64(offset, 1, 31) << 1) {
+        tcg_out_opc_upper(s, OPC_AUIPC, rd, 0);
+        tcg_out_opc_imm(s, OPC_ADDI, rd, rd, 0);
+        reloc_call(s->code_ptr - 2, (tcg_insn_unit *)val);
+        return;
+    }
+
+    shift = ctz64(val);
+    tmp = val >> shift;
+
+    if (tmp == sextract64(tmp, 0, 12)) {
+        tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, 1);
+        tcg_out_opc_imm(s, OPC_SLLI, rd, rd, ctz64(val));
+    } else if (!(val >> 31 == 0 || val >> 31 == -1)) {
+        shift = ctz64(hi);
+        hi >>= shift;
+        tcg_out_movi(s, type, rd, hi);
+        tcg_out_opc_imm(s, OPC_SLLI, rd, rd, shift);
+        if (lo != 0) {
+            tcg_out_opc_imm(s, OPC_ADDI, rd, rd, lo);
+        }
+    } else {
+        if (hi != 0) {
+            tcg_out_opc_upper(s, OPC_LUI, rd, hi);
+        }
+        if (lo != 0) {
+            tcg_out_opc_imm(s, add32_op, rd, hi == 0 ? TCG_REG_ZERO : rd, lo);
+        }
+    }
+}
+
 void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr,
                               uintptr_t addr)
 {