qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v4 14/21] target-mips: add AUI, LSA and PCREL in


From: Yongbok Kim
Subject: Re: [Qemu-devel] [PATCH v4 14/21] target-mips: add AUI, LSA and PCREL instruction families
Date: Mon, 13 Oct 2014 14:37:48 +0100
User-agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Thunderbird/31.1.2

I have just few minor comments.

Reviewed-by: Yongbok Kim <address@hidden>

regards,
Yongbok

On 08/10/2014 11:55, Leon Alrae wrote:
Signed-off-by: Leon Alrae <address@hidden>
---
v3:
* use sextract32 instead of open coding the bit field extraction
* replace _i64 with _tl in DAHI, DATI and DAUI
* fix misleading LDPC comment
---
  disas/mips.c            |  42 ++++++++++-
  target-mips/translate.c | 197 +++++++++++++++++++++++++++++++++++++++++++++---
  2 files changed, 225 insertions(+), 14 deletions(-)

diff --git a/disas/mips.c b/disas/mips.c
index 8234369..091f4e2 100644
--- a/disas/mips.c
+++ b/disas/mips.c
@@ -407,6 +407,12 @@ struct mips_opcode
     "+3" UDI immediate bits 6-20
     "+4" UDI immediate bits 6-25
+ R6 immediates/displacements :
+   (adding suffix to 'o' to avoid adding new characters)
+   "+o"  9 bits immediate/displacement (shift = 7)
+   "+o1" 18 bits immediate/displacement (shift = 0)
+   "+o2" 19 bits immediate/displacement (shift = 0)
+
     Other:
     "()" parens surrounding optional value
     ","  separates operands
@@ -1217,6 +1223,17 @@ const struct mips_opcode mips_builtin_opcodes[] =
     them first.  The assemblers uses a hash table based on the
     instruction name anyhow.  */
  /* name,    args,     match,      mask,       pinfo,                  
membership */
+{"lwpc",    "s,+o2",    0xec080000, 0xfc180000, WR_d,                 0, 
I32R6},
+{"lwupc",   "s,+o2",    0xec100000, 0xfc180000, WR_d,                 0, 
I32R6},

I64R6

+{"ldpc",    "s,+o1",    0xec180000, 0xfc1c0000, WR_d,                 0, 
I64R6},
+{"addiupc", "s,+o2",    0xec000000, 0xfc180000, WR_d,                 0, 
I32R6},
+{"auipc",   "s,u",      0xec1e0000, 0xfc1f0000, WR_d,                 0, 
I32R6},
+{"aluipc",  "s,u",      0xec1f0000, 0xfc1f0000, WR_d,                 0, 
I32R6},
+{"daui",    "s,t,u",    0x74000000, 0xfc000000, RD_s|WR_t,            0, 
I64R6},
+{"dahi",    "s,u",      0x04060000, 0xfc1f0000, RD_s,                 0, 
I64R6},
+{"dati",    "s,u",      0x041e0000, 0xfc1f0000, RD_s,                 0, 
I64R6},
+{"lsa",     "d,s,t",    0x00000005, 0xfc00073f, WR_d|RD_s|RD_t,       0, 
I32R6},
+{"dlsa",    "d,s,t",    0x00000015, 0xfc00073f, WR_d|RD_s|RD_t,       0, 
I64R6},
  {"clz",     "U,s",      0x00000050, 0xfc1f07ff, WR_d|RD_s,            0, 
I32R6},
  {"clo",     "U,s",      0x00000051, 0xfc1f07ff, WR_d|RD_s,            0, 
I32R6},
  {"dclz",    "U,s",      0x00000052, 0xfc1f07ff, WR_d|RD_s,            0, 
I64R6},
@@ -1822,6 +1839,7 @@ const struct mips_opcode mips_builtin_opcodes[] =
  {"lld",         "t,o(b)", 0xd0000000, 0xfc000000, LDD|RD_b|WR_t,          0,  
            I3      },
  {"lld",     "t,A(b)",     0,    (int) M_LLD_AB,   INSN_MACRO,             0,  
            I3      },
  {"lui",     "t,u",        0x3c000000, 0xffe00000, WR_t,                   0,  
            I1      },
+{"aui",     "s,t,u",    0x3c000000, 0xfc000000, RD_s|WR_t,            0, 
I32R6},
  {"luxc1",   "D,t(b)",     0x4c000005, 0xfc00f83f, LDD|WR_D|RD_t|RD_b|FP_D, 0, 
            I5|I33|N55},
  {"lw",      "t,o(b)",     0x8c000000, 0xfc000000, LDD|RD_b|WR_t,          0,  
            I1      },
  {"lw",      "t,A(b)",     0,    (int) M_LW_AB,    INSN_MACRO,             0,  
            I1      },
@@ -3645,10 +3663,28 @@ print_insn_args (const char *d,
              break;
case 'o':
-                delta = (l >> OP_SH_DELTA_R6) & OP_MASK_DELTA_R6;
-                if (delta & 0x8000) {
-                    delta |= ~0xffff;
+                switch (*(d+1)) {
+                case '1':
+                    d++;
+                    delta = l & ((1 << 18) - 1);
+                    if (delta & 0x20000) {
+                        delta |= ~0x1ffff;
+                    }
+                    break;
+                case '2':
+                    d++;
+                    delta = l & ((1 << 19) - 1);
+                    if (delta & 0x40000) {
+                        delta |= ~0x3ffff;
+                    }
+                    break;
+                default:
+                    delta = (l >> OP_SH_DELTA_R6) & OP_MASK_DELTA_R6;
+                    if (delta & 0x8000) {
+                        delta |= ~0xffff;
+                    }
                  }
+
                  (*info->fprintf_func) (info->stream, "%d", delta);
                  break;
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 06ececb..6f64c47 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -75,6 +75,7 @@ enum {
      OPC_BGTZ     = (0x07 << 26),
      OPC_BGTZL    = (0x17 << 26),
      OPC_JALX     = (0x1D << 26),  /* MIPS 16 only */
+    OPC_DAUI     = (0x1D << 26),
      OPC_JALXS    = OPC_JALX | 0x5,
      /* Load and stores */
      OPC_LDL      = (0x1A << 26),
@@ -141,8 +142,25 @@ enum {
      /* Cache and prefetch */
      OPC_CACHE    = (0x2F << 26),
      OPC_PREF     = (0x33 << 26),
-    /* Reserved major opcode */
-    OPC_MAJOR3B_RESERVED = (0x3B << 26),
+    /* PC-relative address computation / loads */
+    OPC_PCREL    = (0x3B << 26),
+};
+
+/* PC-relative address computation / loads  */
+#define MASK_OPC_PCREL_TOP2BITS(op)  (MASK_OP_MAJOR(op) | (op & (3 << 19)))
+#define MASK_OPC_PCREL_TOP5BITS(op)  (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))

There must be better name for this macro.
It confused me that was looking like 31 and 30 bits.
Just naming though...

+enum {
+    /* Instructions determined by bits 19 and 20 */
+    OPC_ADDIUPC = OPC_PCREL | (0 << 19),
+    R6_OPC_LWPC = OPC_PCREL | (1 << 19),
+    OPC_LWUPC   = OPC_PCREL | (2 << 19),
+
+    /* Instructions determined by bits 16 ... 20 */
+    OPC_AUIPC   = OPC_PCREL | (0x1e << 16),
+    OPC_ALUIPC  = OPC_PCREL | (0x1f << 16),
+
+    /* Other */
+    R6_OPC_LDPC = OPC_PCREL | (6 << 18),
  };
/* MIPS special opcodes */
@@ -231,7 +249,6 @@ enum {
      OPC_SPIM     = 0x0E | OPC_SPECIAL, /* unofficial */
      OPC_SYNC     = 0x0F | OPC_SPECIAL,
- OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
      OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
      OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
      OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
@@ -266,6 +283,9 @@ enum {
      R6_OPC_DCLZ     = 0x12 | OPC_SPECIAL,
      R6_OPC_DCLO     = 0x13 | OPC_SPECIAL,
      R6_OPC_SDBBP    = 0x0e | OPC_SPECIAL,
+
+    OPC_LSA  = 0x05 | OPC_SPECIAL,
+    OPC_DLSA = 0x15 | OPC_SPECIAL,
  };
/* Multiplication variants of the vr54xx. */
@@ -309,6 +329,9 @@ enum {
      OPC_TEQI     = (0x0C << 16) | OPC_REGIMM,
      OPC_TNEI     = (0x0E << 16) | OPC_REGIMM,
      OPC_SYNCI    = (0x1F << 16) | OPC_REGIMM,
+
+    OPC_DAHI     = (0x06 << 16) | OPC_REGIMM,
+    OPC_DATI     = (0x1e << 16) | OPC_REGIMM,
  };
/* Special2 opcodes */
@@ -2162,8 +2185,15 @@ static void gen_logic_imm(DisasContext *ctx, uint32_t 
opc,
                     regnames[rs], uimm);
          break;
      case OPC_LUI:
-        tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
-        MIPS_DEBUG("lui %s, " TARGET_FMT_lx, regnames[rt], uimm);
+        if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
+            /* OPC_AUI */
+            tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
+            tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
+            MIPS_DEBUG("aui %s, %s, %04x", regnames[rt], regnames[rs], imm);
+        } else {
+            tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
+            MIPS_DEBUG("lui %s, " TARGET_FMT_lx, regnames[rt], uimm);
+        }
          break;
default:
@@ -2767,6 +2797,77 @@ static void gen_HILO(DisasContext *ctx, uint32_t opc, 
int acc, int reg)
      MIPS_DEBUG("%s %s", opn, regnames[reg]);
  }
+static inline void gen_r6_ld(target_long addr, int reg, int memidx,
+                             TCGMemOp memop)
+{
+    TCGv t0 = tcg_const_tl(addr);
+    tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
+    gen_store_gpr(t0, reg);
+    tcg_temp_free(t0);
+}
+
+static inline void gen_pcrel(DisasContext *ctx, int rs, int16_t imm)
+{
+    target_long offset;
+    target_long addr;
+
+    switch (MASK_OPC_PCREL_TOP2BITS(ctx->opcode)) {
+    case OPC_ADDIUPC:
+        if (rs != 0) {
+            offset = sextract32(ctx->opcode << 2, 0, 21);
+            addr = addr_add(ctx, ctx->pc, offset);
+            tcg_gen_movi_tl(cpu_gpr[rs], addr);
+        }
+        break;
+    case R6_OPC_LWPC:
+        offset = sextract32(ctx->opcode << 2, 0, 21);
+        addr = addr_add(ctx, ctx->pc, offset);
+        gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
+        break;
+#if defined(TARGET_MIPS64)
+    case OPC_LWUPC:
+        check_mips_64(ctx);
+        offset = sextract32(ctx->opcode << 2, 0, 21);
+        addr = addr_add(ctx, ctx->pc, offset);
+        gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
+        break;
+#endif
+    default:
+        switch (MASK_OPC_PCREL_TOP5BITS(ctx->opcode)) {
+        case OPC_AUIPC:
+            if (rs != 0) {
+                offset = imm << 16;
+                addr = addr_add(ctx, ctx->pc, offset);
+                tcg_gen_movi_tl(cpu_gpr[rs], addr);
+            }
+            break;
+        case OPC_ALUIPC:
+            if (rs != 0) {
+                offset = imm << 16;
+                addr = ~0xFFFF & addr_add(ctx, ctx->pc, offset);
+                tcg_gen_movi_tl(cpu_gpr[rs], addr);
+            }
+            break;
+#if defined(TARGET_MIPS64)
+        case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
+        case R6_OPC_LDPC + (1 << 16):
+        case R6_OPC_LDPC + (2 << 16):
+        case R6_OPC_LDPC + (3 << 16):
+            check_mips_64(ctx);
+            offset = sextract32(ctx->opcode << 3, 0, 21);
+            addr = addr_add(ctx, (ctx->pc & ~0x7), offset);
+            gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
+            break;
+#endif
+        default:
+            MIPS_INVAL("OPC_PCREL");
+            generate_exception(ctx, EXCP_RI);
+            break;
+        }
+        break;
+    }
+}
+
  static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
  {
      const char *opn = "r6 mul/div";
@@ -15097,6 +15198,20 @@ static void decode_opc_special_r6(CPUMIPSState *env, 
DisasContext *ctx)
op1 = MASK_SPECIAL(ctx->opcode);
      switch (op1) {
+    case OPC_LSA:
+        if (rd != 0) {
+            int imm2 = extract32(ctx->opcode, 6, 3);
+            TCGv t0 = tcg_temp_new();
+            TCGv t1 = tcg_temp_new();
+            gen_load_gpr(t0, rs);
+            gen_load_gpr(t1, rt);
+            tcg_gen_shli_tl(t0, t0, imm2 + 1);
+            tcg_gen_add_tl(t0, t0, t1);
+            tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
+            tcg_temp_free(t1);
+            tcg_temp_free(t0);
+        }
+        break;
      case OPC_MULT ... OPC_DIVU:
          op2 = MASK_R6_MULDIV(ctx->opcode);
          switch (op2) {
@@ -15134,6 +15249,20 @@ static void decode_opc_special_r6(CPUMIPSState *env, 
DisasContext *ctx)
          generate_exception(ctx, EXCP_DBp);
          break;
  #if defined(TARGET_MIPS64)
+    case OPC_DLSA:
+        check_mips_64(ctx);
+        if (rd != 0) {
+            int imm2 = extract32(ctx->opcode, 6, 3);
+            TCGv t0 = tcg_temp_new();
+            TCGv t1 = tcg_temp_new();
+            gen_load_gpr(t0, rs);
+            gen_load_gpr(t1, rt);
+            tcg_gen_shli_tl(t0, t0, imm2 + 1);
+            tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
+            tcg_temp_free(t1);
+            tcg_temp_free(t0);
+        }
+        break;
      case R6_OPC_DCLO:
      case R6_OPC_DCLZ:
          if (rt == 0 && sa == 1) {
@@ -15319,13 +15448,18 @@ static void decode_opc_special(CPUMIPSState *env, 
DisasContext *ctx)
      case OPC_TNE:
          gen_trap(ctx, op1, rs, rt, -1);
          break;
-    case OPC_PMON:          /* Pmon entry point, also R4010 selsl */
+    case OPC_LSA: /* OPC_PMON */
+        if (ctx->insn_flags & ISA_MIPS32R6) {
+            decode_opc_special_r6(env, ctx);
+        } else {
+            /* Pmon entry point, also R4010 selsl */

indentation :)

  #ifdef MIPS_STRICT_STANDARD
          MIPS_INVAL("PMON / selsl");
          generate_exception(ctx, EXCP_RI);
  #else
          gen_helper_0e0i(pmon, sa);
  #endif
+        }
          break;
      case OPC_SYSCALL:
          generate_exception(ctx, EXCP_SYSCALL);
@@ -16297,6 +16431,24 @@ static void decode_opc (CPUMIPSState *env, 
DisasContext *ctx)
              check_dsp(ctx);
              gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2);
              break;
+#if defined(TARGET_MIPS64)
+        case OPC_DAHI:
+            check_insn(ctx, ISA_MIPS32R6);
+            check_mips_64(ctx);
+            if (rs != 0) {
+                tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
+            }
+            MIPS_DEBUG("dahi %s, %04x", regnames[rs], imm);
+            break;
+        case OPC_DATI:
+            check_insn(ctx, ISA_MIPS32R6);
+            check_mips_64(ctx);
+            if (rs != 0) {
+                tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
+            }
+            MIPS_DEBUG("dati %s, %04x", regnames[rs], imm);
+            break;
+#endif
          default:            /* Invalid */
              MIPS_INVAL("regimm");
              generate_exception(ctx, EXCP_RI);
@@ -16409,7 +16561,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext 
*ctx)
           gen_slt_imm(ctx, op, rt, rs, imm);
           break;
      case OPC_ANDI: /* Arithmetic with immediate opcode */
-    case OPC_LUI:
+    case OPC_LUI: /* OPC_AUI */
      case OPC_ORI:
      case OPC_XORI:
           gen_logic_imm(ctx, op, rt, rs, imm);
@@ -16707,14 +16859,37 @@ static void decode_opc (CPUMIPSState *env, 
DisasContext *ctx)
          }
          break;
  #endif
-    case OPC_JALX:
-        check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
-        offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
-        gen_compute_branch(ctx, op, 4, rs, rt, offset);
+    case OPC_DAUI: /* OPC_JALX */
+        if (ctx->insn_flags & ISA_MIPS32R6) {
+#if defined(TARGET_MIPS64)
+            /* OPC_DAUI */
+            check_mips_64(ctx);
+            if (rt != 0) {
+                TCGv t0 = tcg_temp_new();
+                gen_load_gpr(t0, rs);
+                tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
+                tcg_temp_free(t0);
+            }
+            MIPS_DEBUG("daui %s, %s, %04x", regnames[rt], regnames[rs], imm);
+#else
+            generate_exception(ctx, EXCP_RI);
+            MIPS_INVAL("major opcode");
+#endif
+        } else {
+            /* OPC_JALX */
+            check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
+            offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
+            gen_compute_branch(ctx, op, 4, rs, rt, offset);
+        }
          break;
      case OPC_MDMX:
          check_insn(ctx, ASE_MDMX);
          /* MDMX: Not implemented. */
+        break;
+    case OPC_PCREL:
+        check_insn(ctx, ISA_MIPS32R6);
+        gen_pcrel(ctx, rs, imm);
+        break;
      default:            /* Invalid */
          MIPS_INVAL("major opcode");
          generate_exception(ctx, EXCP_RI);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]