diff mbox series

[RFC,1/3] target/mips: Introduce register access helper functions

Message ID 20220921124105.3824962-2-jiaxun.yang@flygoat.com (mailing list archive)
State New, archived
Headers show
Series MIPS decodetree conversion attempt | expand

Commit Message

Jiaxun Yang Sept. 21, 2022, 12:41 p.m. UTC
Introduce register access functions with value extend capability
to prepare for decodetree based translation implmentation.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 target/mips/tcg/translate.c | 143 +++++++++++++++++++++++++++++++++++-
 target/mips/tcg/translate.h |  54 ++++++++++++++
 2 files changed, 196 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index de1511baaf..b5d595ef34 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -1196,6 +1196,17 @@  enum {
     MMI_OPC_MADDU1     = 0x21 | MMI_OPC_CLASS_MMI,
 };
 
+/*
+ * If an operation is being performed on less than TARGET_LONG_BITS,
+ * it may require the inputs to be sign- or zero-extended; which will
+ * depend on the exact operation being performed.
+ */
+typedef enum {
+    EXT_NONE,
+    EXT_SIGN,
+    EXT_ZERO
+} DisasExtend;
+
 /* global register indices */
 TCGv cpu_gpr[32], cpu_PC;
 /*
@@ -1221,6 +1232,18 @@  static const char regnames_LO[][4] = {
     "LO0", "LO1", "LO2", "LO3",
 };
 
+static TCGv ctx_temp_new(DisasContext *ctx)
+{
+    assert(ctx->ntemp < ARRAY_SIZE(ctx->temp));
+    return ctx->temp[ctx->ntemp++] = tcg_temp_new();
+}
+
+static TCGv_i64 ctx_temp_new_i64(DisasContext *ctx)
+{
+    assert(ctx->ntemp64 < ARRAY_SIZE(ctx->temp64));
+    return ctx->temp64[ctx->ntemp64++] = tcg_temp_new_i64();
+}
+
 /* General purpose registers moves. */
 void gen_load_gpr(TCGv t, int reg)
 {
@@ -1238,6 +1261,106 @@  void gen_store_gpr(TCGv t, int reg)
     }
 }
 
+void gen_extend(TCGv dst, TCGv src, DisasExtend src_ext)
+{
+    switch (src_ext) {
+    case EXT_NONE:
+        tcg_gen_mov_tl(dst, src);
+        return;
+    case EXT_SIGN:
+        tcg_gen_ext32s_tl(dst, src);
+        return;
+    case EXT_ZERO:
+        tcg_gen_ext32u_tl(dst, src);
+        return;
+    }
+    g_assert_not_reached();
+}
+
+TCGv get_gpr(DisasContext *ctx, int reg_num, DisasExtend src_ext)
+{
+    TCGv t;
+
+    if (reg_num == 0) {
+        return ctx->zero;
+    }
+
+    switch (src_ext) {
+    case EXT_NONE:
+        return cpu_gpr[reg_num];
+    default:
+        t = ctx_temp_new(ctx);
+        gen_extend(t, cpu_gpr[reg_num], src_ext);
+        return t;
+    }
+}
+
+TCGv_i64 get_hilo(DisasContext *ctx, int acc)
+{
+    TCGv_i64 t = ctx_temp_new_i64(ctx);
+    /* acc must be 0 when DSP is not implemented */
+    g_assert(acc == 0 || ctx->insn_flags & ASE_DSP);
+    tcg_gen_concat_tl_i64(t, cpu_LO[acc], cpu_HI[acc]);
+
+    return t;
+}
+
+TCGv dest_gpr(DisasContext *ctx, int reg_num)
+{
+    if (reg_num == 0) {
+        return ctx_temp_new(ctx);
+    }
+    return cpu_gpr[reg_num];
+}
+
+TCGv dest_lo(DisasContext *ctx, int acc)
+{
+    /* acc must be 0 when DSP is not implemented */
+    g_assert(acc == 0 || ctx->insn_flags & ASE_DSP);
+
+    return cpu_LO[acc];
+}
+
+TCGv dest_hi(DisasContext *ctx, int acc)
+{
+    /* acc must be 0 when DSP is not implemented */
+    g_assert(acc == 0 || ctx->insn_flags & ASE_DSP);
+
+    return cpu_HI[acc];
+}
+
+/* For 32 bit hilo pair */
+TCGv_i64 dest_hilo(DisasContext *ctx, int acc)
+{
+    /* acc must be 0 when DSP is not implemented */
+    g_assert(acc == 0 || ctx->insn_flags & ASE_DSP);
+    return ctx_temp_new_i64(ctx);
+}
+
+void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext)
+{
+    if (reg_num != 0) {
+        gen_extend(cpu_gpr[reg_num], t, dst_ext);
+    }
+}
+
+void gen_set_lo(int acc, TCGv t, DisasExtend dst_ext)
+{
+    gen_extend(cpu_LO[acc], t, dst_ext);
+}
+
+void gen_set_hi(int acc, TCGv t, DisasExtend dst_ext)
+{
+    gen_extend(cpu_HI[acc], t, dst_ext);
+}
+
+/* For 32 bit hilo pair */
+void gen_set_hilo(int acc, TCGv_i64 t)
+{
+    gen_move_low32(cpu_LO[acc], t);
+    gen_move_high32(cpu_HI[acc], t);
+}
+
 #if defined(TARGET_MIPS64)
 void gen_load_gpr_hi(TCGv_i64 t, int reg)
 {
@@ -2615,7 +2738,6 @@  static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
     tcg_temp_free(t0);
 }
 
-/* Arithmetic */
 static void gen_arith(DisasContext *ctx, uint32_t opc,
                       int rd, int rs, int rt)
 {
@@ -16031,6 +16153,12 @@  static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
         ctx->base.max_insns = 2;
     }
 
+    ctx->ntemp = 0;
+    ctx->ntemp64 = 0;
+    memset(ctx->temp, 0, sizeof(ctx->temp));
+    memset(ctx->temp64, 0, sizeof(ctx->temp));
+    ctx->zero = tcg_constant_tl(0);
+
     LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
               ctx->hflags);
 }
@@ -16053,6 +16181,7 @@  static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
     DisasContext *ctx = container_of(dcbase, DisasContext, base);
     int insn_bytes;
     int is_slot;
+    int i;
 
     is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
     if (ctx->insn_flags & ISA_NANOMIPS32) {
@@ -16074,6 +16203,18 @@  static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
         return;
     }
 
+    for (i = ctx->ntemp - 1; i >= 0; --i) {
+        tcg_temp_free(ctx->temp[i]);
+        ctx->temp[i] = NULL;
+        ctx->ntemp--;
+    }
+
+    for (i = ctx->ntemp64 - 1; i >= 0; --i) {
+        tcg_temp_free_i64(ctx->temp64[i]);
+        ctx->temp64[i] = NULL;
+        ctx->ntemp64--;
+    }
+
     if (ctx->hflags & MIPS_HFLAG_BMASK) {
         if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
                              MIPS_HFLAG_FBNSLOT))) {
diff --git a/target/mips/tcg/translate.h b/target/mips/tcg/translate.h
index 69f85841d2..980aa8682d 100644
--- a/target/mips/tcg/translate.h
+++ b/target/mips/tcg/translate.h
@@ -49,6 +49,11 @@  typedef struct DisasContext {
     bool saar;
     bool mi;
     int gi;
+    TCGv zero;
+    TCGv temp[4];
+    uint8_t ntemp;
+    TCGv_i64 temp64[4];
+    uint8_t ntemp64;
 } DisasContext;
 
 #define DISAS_STOP       DISAS_TARGET_0
@@ -119,6 +124,17 @@  enum {
     OPC_BC1TANY4     = (0x01 << 16) | OPC_BC1ANY4,
 };
 
+/*
+ * If an operation is being performed on less than TARGET_LONG_BITS,
+ * it may require the inputs to be sign- or zero-extended; which will
+ * depend on the exact operation being performed.
+ */
+typedef enum {
+    EXT_NONE,
+    EXT_SIGN,
+    EXT_ZERO
+} DisasExtend;
+
 #define gen_helper_0e1i(name, arg1, arg2) do { \
     gen_helper_##name(cpu_env, arg1, tcg_constant_i32(arg2)); \
     } while (0)
@@ -150,6 +166,18 @@  void check_cp1_64bitmode(DisasContext *ctx);
 void check_cp1_registers(DisasContext *ctx, int regs);
 void check_cop1x(DisasContext *ctx);
 
+void gen_extend(TCGv dst, TCGv src, DisasExtend src_ext);
+TCGv get_gpr(DisasContext *ctx, int reg_num, DisasExtend src_ext);
+TCGv_i64 get_hilo(DisasContext *ctx, int acc);
+TCGv dest_gpr(DisasContext *ctx, int reg_num);
+TCGv dest_lo(DisasContext *ctx, int acc);
+TCGv dest_hi(DisasContext *ctx, int acc);
+TCGv_i64 dest_hilo(DisasContext *ctx, int acc);
+void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext);
+void gen_set_lo(int acc, TCGv t, DisasExtend dst_ext);
+void gen_set_hi(int acc, TCGv t, DisasExtend dst_ext);
+void gen_set_hilo(int acc, TCGv_i64 t);
+
 void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset);
 void gen_move_low32(TCGv ret, TCGv_i64 arg);
 void gen_move_high32(TCGv ret, TCGv_i64 arg);
@@ -231,6 +259,32 @@  bool decode_ext_vr54xx(DisasContext *ctx, uint32_t insn);
     static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
     { return FUNC(ctx, a, __VA_ARGS__); }
 
+/* Instructions removed in Release 6 */
+#define TRANS_6R(NAME, FUNC, ...) \
+    static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
+    { return !(ctx->insn_flags & ISA_MIPS_R6) & FUNC(ctx, a, __VA_ARGS__); }
+
+#if defined(TARGET_MIPS64)
+#define TRANS64(NAME, FUNC, ...) \
+    static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
+    { check_mips_64(ctx); return FUNC(ctx, a, __VA_ARGS__); }
+#define TRANS64_6R(NAME, FUNC, ...) \
+    static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
+    { if (ctx->insn_flags & ISA_MIPS_R6) return false; check_mips_64(ctx); \
+    return FUNC(ctx, a, __VA_ARGS__); }
+#else
+#define TRANS64(NAME, FUNC, ...) \
+    static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
+    { return false; }
+#define TRANS64_6R(NAME, FUNC, ...) \
+    static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
+    { return false; }
+#endif
+
+#define TRANS_FLAGS(NAME, FLAGS, ...) \
+    static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \
+    { return (ctx->insn_flags & FLAGS) && FUNC(s, __VA_ARGS__); }
+
 static inline bool cpu_is_bigendian(DisasContext *ctx)
 {
     return extract32(ctx->CP0_Config0, CP0C0_BE, 1);