All of lore.kernel.org
 help / color / mirror / Atom feed
From: Leon Alrae <leon.alrae@imgtec.com>
To: qemu-devel@nongnu.org
Cc: yongbok.kim@imgtec.com, cristian.cuna@imgtec.com,
	leon.alrae@imgtec.com, aurelien@aurel32.net, rth@twiddle.net
Subject: [Qemu-devel] [PATCH v3 14/21] target-mips: add AUI, LSA and PCREL instruction families
Date: Fri, 27 Jun 2014 16:22:03 +0100	[thread overview]
Message-ID: <1403882530-47821-15-git-send-email-leon.alrae@imgtec.com> (raw)
In-Reply-To: <1403882530-47821-1-git-send-email-leon.alrae@imgtec.com>

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
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 |  196 ++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 225 insertions(+), 13 deletions(-)

diff --git a/disas/mips.c b/disas/mips.c
index bee39d8..e041858 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},
+{"ldpc",    "s,+o1",    0xec180000, 0xfc1a0000, WR_d,                 0, I32R6},
+{"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, 0xfc0007ff, WR_d|RD_s,            0, I32R6},
 {"clo",     "U,s",      0x00000051, 0xfc0007ff, WR_d|RD_s,            0, I32R6},
 {"dclz",    "U,s",      0x00000052, 0xfc0007ff, 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 8a6adac..188caf7 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -71,6 +71,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),
@@ -137,8 +138,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)))
+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 */
@@ -264,6 +282,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. */
@@ -307,6 +328,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 */
@@ -2160,8 +2184,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:
@@ -2765,6 +2796,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";
@@ -15095,6 +15197,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) {
@@ -15132,6 +15248,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) {
@@ -15317,13 +15447,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 */
 #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);
@@ -16292,6 +16427,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);
@@ -16404,7 +16557,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);
@@ -16702,14 +16855,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);
-- 
1.7.5.4

  parent reply	other threads:[~2014-06-27 15:23 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-27 15:21 [Qemu-devel] [PATCH v3 00/21] target-mips: add MIPS64R6 Instruction Set support Leon Alrae
2014-06-27 15:21 ` [Qemu-devel] [PATCH v3 01/21] target-mips: define ISA_MIPS64R6 Leon Alrae
2014-06-27 15:21 ` [Qemu-devel] [PATCH v3 02/21] target-mips: signal RI Exception on instructions removed in R6 Leon Alrae
2014-06-27 15:21 ` [Qemu-devel] [PATCH v3 03/21] target-mips: add SELEQZ and SELNEZ instructions Leon Alrae
2014-09-26 12:03   ` James Hogan
2014-09-26 12:45     ` Leon Alrae
2014-09-26 12:54       ` James Hogan
2014-09-26 12:23   ` James Hogan
2014-06-27 15:21 ` [Qemu-devel] [PATCH v3 04/21] target-mips: move LL and SC instructions Leon Alrae
2014-09-26 12:44   ` James Hogan
2014-09-26 14:12     ` Leon Alrae
2014-06-27 15:21 ` [Qemu-devel] [PATCH v3 05/21] target-mips: extract decode_opc_special* from decode_opc Leon Alrae
2014-06-27 15:21 ` [Qemu-devel] [PATCH v3 06/21] target-mips: split decode_opc_special* into *_r6 and *_legacy Leon Alrae
2014-06-27 15:21 ` [Qemu-devel] [PATCH v3 07/21] target-mips: signal RI Exception on DSP and Loongson instructions Leon Alrae
2014-06-27 15:21 ` [Qemu-devel] [PATCH v3 08/21] target-mips: move PREF, CACHE, LLD and SCD instructions Leon Alrae
2014-06-27 15:21 ` [Qemu-devel] [PATCH v3 09/21] target-mips: redefine Integer Multiply and Divide instructions Leon Alrae
2014-06-27 15:21 ` [Qemu-devel] [PATCH v3 10/21] target-mips: move CLO, DCLO, CLZ, DCLZ, SDBBP and free special2 in R6 Leon Alrae
2014-06-27 15:22 ` [Qemu-devel] [PATCH v3 11/21] target-mips: Status.UX/SX/KX enable 32-bit address wrapping Leon Alrae
2014-06-27 15:22 ` [Qemu-devel] [PATCH v3 12/21] target-mips: add ALIGN, DALIGN, BITSWAP and DBITSWAP instructions Leon Alrae
2014-06-27 15:22 ` [Qemu-devel] [PATCH v3 13/21] target-mips: add compact and CP1 branches Leon Alrae
2014-06-27 15:22 ` Leon Alrae [this message]
2014-06-27 15:22 ` [Qemu-devel] [PATCH v3 15/21] softfloat: add functions corresponding to IEEE-2008 min/maxNumMag Leon Alrae
2014-06-27 15:22 ` [Qemu-devel] [PATCH v3 16/21] target-mips: add new Floating Point instructions Leon Alrae
2014-10-02 16:10   ` Yongbok Kim
2014-10-03  8:59     ` Leon Alrae
2014-06-27 15:22 ` [Qemu-devel] [PATCH v3 17/21] target-mips: add new Floating Point Comparison instructions Leon Alrae
2014-06-27 15:22 ` [Qemu-devel] [PATCH v3 18/21] target-mips: do not allow Status.FR=0 mode in 64-bit FPU Leon Alrae
2014-10-02 10:21   ` Yongbok Kim
2014-10-02 10:28     ` Yongbok Kim
2014-06-27 15:22 ` [Qemu-devel] [PATCH v3 19/21] target-mips: remove JR, BLTZAL, BGEZAL and add NAL, BAL instructions Leon Alrae
2014-06-27 15:22 ` [Qemu-devel] [PATCH v3 20/21] mips_malta: update malta's pseudo-bootloader - replace JR with JALR Leon Alrae
2014-06-27 15:22 ` [Qemu-devel] [PATCH v3 21/21] target-mips: define a new generic CPU supporting MIPS64 Release 6 ISA Leon Alrae
2014-08-05  9:26 ` [Qemu-devel] [PATCH v3 00/21] target-mips: add MIPS64R6 Instruction Set support Leon Alrae
2014-08-12 11:36   ` Leon Alrae
2014-08-22 11:26     ` Leon Alrae
2014-09-24 11:01       ` Leon Alrae

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1403882530-47821-15-git-send-email-leon.alrae@imgtec.com \
    --to=leon.alrae@imgtec.com \
    --cc=aurelien@aurel32.net \
    --cc=cristian.cuna@imgtec.com \
    --cc=qemu-devel@nongnu.org \
    --cc=rth@twiddle.net \
    --cc=yongbok.kim@imgtec.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.