Support for VR5432, and some of its special instructions. Original patch
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Tue, 25 Dec 2007 20:46:56 +0000 (20:46 +0000)
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Tue, 25 Dec 2007 20:46:56 +0000 (20:46 +0000)
by Dirk Behme.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3859 c046a42c-6fe2-441c-8c8c-71466251a162

target-mips/exec.h
target-mips/mips-defs.h
target-mips/op.c
target-mips/op_helper.c
target-mips/translate.c
target-mips/translate_init.c

index 307049e..7b2c468 100644 (file)
@@ -79,6 +79,20 @@ void do_madd (void);
 void do_maddu (void);
 void do_msub (void);
 void do_msubu (void);
+void do_muls (void);
+void do_mulsu (void);
+void do_macc (void);
+void do_macchi (void);
+void do_maccu (void);
+void do_macchiu (void);
+void do_msac (void);
+void do_msachi (void);
+void do_msacu (void);
+void do_msachiu (void);
+void do_mulhi (void);
+void do_mulhiu (void);
+void do_mulshi (void);
+void do_mulshiu (void);
 #endif
 #if defined(TARGET_MIPS64)
 void do_ddiv (void);
index 76ea8d0..2d0c138 100644 (file)
@@ -4,7 +4,7 @@
 /* If we want to use host float regs... */
 //#define USE_HOST_FLOAT_REGS
 
-/* real pages are variable size... */
+/* Real pages are variable size... */
 #define TARGET_PAGE_BITS 12
 #define MIPS_TLB_MAX 128
 
@@ -29,7 +29,7 @@
 #define                ISA_MIPS64      0x00000080
 #define                ISA_MIPS64R2    0x00000100
 
-/* MIPS ASE */
+/* MIPS ASEs. */
 #define                ASE_MIPS16      0x00001000
 #define                ASE_MIPS3D      0x00002000
 #define                ASE_MDMX        0x00004000
 #define                ASE_MT          0x00020000
 #define                ASE_SMARTMIPS   0x00040000
 
-/* Chip specific instructions.   */
-/* Currently void */
+/* Chip specific instructions. */
+#define                INSN_VR54XX     0x80000000
 
-/* MIPS CPU defines.  */
+/* MIPS CPU defines. */
 #define                CPU_MIPS1       (ISA_MIPS1)
 #define                CPU_MIPS2       (CPU_MIPS1 | ISA_MIPS2)
 #define                CPU_MIPS3       (CPU_MIPS2 | ISA_MIPS3)
 #define                CPU_MIPS4       (CPU_MIPS3 | ISA_MIPS4)
+#define                CPU_VR54XX      (CPU_MIPS4 | INSN_VR54XX)
+
 #define                CPU_MIPS5       (CPU_MIPS4 | ISA_MIPS5)
 
+/* MIPS Technologies "Release 1" */
 #define                CPU_MIPS32      (CPU_MIPS2 | ISA_MIPS32)
 #define                CPU_MIPS64      (CPU_MIPS5 | CPU_MIPS32 | ISA_MIPS64)
 
+/* MIPS Technologies "Release 2" */
 #define                CPU_MIPS32R2    (CPU_MIPS32 | ISA_MIPS32R2)
 #define                CPU_MIPS64R2    (CPU_MIPS64 | CPU_MIPS32R2 | ISA_MIPS64R2)
 
index b5c24b2..cf965fa 100644 (file)
@@ -781,6 +781,90 @@ void op_msubu (void)
     FORCE_RET();
 }
 
+/* Multiplication variants of the vr54xx. */
+void op_muls (void)
+{
+    CALL_FROM_TB0(do_muls);
+    FORCE_RET();
+}
+
+void op_mulsu (void)
+{
+    CALL_FROM_TB0(do_mulsu);
+    FORCE_RET();
+}
+
+void op_macc (void)
+{
+    CALL_FROM_TB0(do_macc);
+    FORCE_RET();
+}
+
+void op_macchi (void)
+{
+    CALL_FROM_TB0(do_macchi);
+    FORCE_RET();
+}
+
+void op_maccu (void)
+{
+    CALL_FROM_TB0(do_maccu);
+    FORCE_RET();
+}
+void op_macchiu (void)
+{
+    CALL_FROM_TB0(do_macchiu);
+    FORCE_RET();
+}
+
+void op_msac (void)
+{
+    CALL_FROM_TB0(do_msac);
+    FORCE_RET();
+}
+
+void op_msachi (void)
+{
+    CALL_FROM_TB0(do_msachi);
+    FORCE_RET();
+}
+
+void op_msacu (void)
+{
+    CALL_FROM_TB0(do_msacu);
+    FORCE_RET();
+}
+
+void op_msachiu (void)
+{
+    CALL_FROM_TB0(do_msachiu);
+    FORCE_RET();
+}
+
+void op_mulhi (void)
+{
+    CALL_FROM_TB0(do_mulhi);
+    FORCE_RET();
+}
+
+void op_mulhiu (void)
+{
+    CALL_FROM_TB0(do_mulhiu);
+    FORCE_RET();
+}
+
+void op_mulshi (void)
+{
+    CALL_FROM_TB0(do_mulshi);
+    FORCE_RET();
+}
+
+void op_mulshiu (void)
+{
+    CALL_FROM_TB0(do_mulshiu);
+    FORCE_RET();
+}
+
 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
 
 static always_inline uint64_t get_HILO (void)
@@ -795,6 +879,18 @@ static always_inline void set_HILO (uint64_t HILO)
     env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
 }
 
+static always_inline void set_HIT0_LO (uint64_t HILO)
+{
+    env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
+    T0 = env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
+}
+
+static always_inline void set_HI_LOT0 (uint64_t HILO)
+{
+    T0 = env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
+    env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
+}
+
 void op_mult (void)
 {
     set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
@@ -842,6 +938,92 @@ void op_msubu (void)
     set_HILO(get_HILO() - tmp);
     FORCE_RET();
 }
+
+/* Multiplication variants of the vr54xx. */
+void op_muls (void)
+{
+    set_HI_LOT0(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+    FORCE_RET();
+}
+
+void op_mulsu (void)
+{
+    set_HI_LOT0(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+    FORCE_RET();
+}
+
+void op_macc (void)
+{
+    set_HI_LOT0(get_HILO() + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+    FORCE_RET();
+}
+
+void op_macchi (void)
+{
+    set_HIT0_LO(get_HILO() + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+    FORCE_RET();
+}
+
+void op_maccu (void)
+{
+    set_HI_LOT0(get_HILO() + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+    FORCE_RET();
+}
+
+void op_macchiu (void)
+{
+    set_HIT0_LO(get_HILO() + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+    FORCE_RET();
+}
+
+void op_msac (void)
+{
+    set_HI_LOT0(get_HILO() - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+    FORCE_RET();
+}
+
+void op_msachi (void)
+{
+    set_HIT0_LO(get_HILO() - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+    FORCE_RET();
+}
+
+void op_msacu (void)
+{
+    set_HI_LOT0(get_HILO() - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+    FORCE_RET();
+}
+
+void op_msachiu (void)
+{
+    set_HIT0_LO(get_HILO() - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+    FORCE_RET();
+}
+
+void op_mulhi (void)
+{
+    set_HIT0_LO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+    FORCE_RET();
+}
+
+void op_mulhiu (void)
+{
+    set_HIT0_LO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+    FORCE_RET();
+}
+
+void op_mulshi (void)
+{
+    set_HIT0_LO(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+    FORCE_RET();
+}
+
+void op_mulshiu (void)
+{
+    set_HIT0_LO(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+    FORCE_RET();
+}
+
 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
 
 #if defined(TARGET_MIPS64)
index 36c4b73..93ba79c 100644 (file)
@@ -172,6 +172,18 @@ static always_inline void set_HILO (uint64_t HILO)
     env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
 }
 
+static always_inline void set_HIT0_LO (uint64_t HILO)
+{
+    env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
+    T0 = env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
+}
+
+static always_inline void set_HI_LOT0 (uint64_t HILO)
+{
+    T0 = env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
+    env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
+}
+
 void do_mult (void)
 {
     set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
@@ -213,7 +225,78 @@ void do_msubu (void)
     tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
     set_HILO(get_HILO() - tmp);
 }
-#endif
+
+/* Multiplication variants of the vr54xx. */
+void do_muls (void)
+{
+    set_HI_LOT0(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+}
+
+void do_mulsu (void)
+{
+    set_HI_LOT0(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+}
+
+void do_macc (void)
+{
+    set_HI_LOT0(((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+}
+
+void do_macchi (void)
+{
+    set_HIT0_LO(((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+}
+
+void do_maccu (void)
+{
+    set_HI_LOT0(((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+}
+
+void do_macchiu (void)
+{
+    set_HIT0_LO(((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+}
+
+void do_msac (void)
+{
+    set_HI_LOT0(((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+}
+
+void do_msachi (void)
+{
+    set_HIT0_LO(((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+}
+
+void do_msacu (void)
+{
+    set_HI_LOT0(((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+}
+
+void do_msachiu (void)
+{
+    set_HIT0_LO(((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+}
+
+void do_mulhi (void)
+{
+    set_HIT0_LO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+}
+
+void do_mulhiu (void)
+{
+    set_HIT0_LO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+}
+
+void do_mulshi (void)
+{
+    set_HIT0_LO(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+}
+
+void do_mulshiu (void)
+{
+    set_HIT0_LO(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+}
+#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
 
 #if HOST_LONG_BITS < 64
 void do_div (void)
index be29357..1d8aea1 100644 (file)
@@ -214,6 +214,26 @@ enum {
     OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
 };
 
+/* Multiplication variants of the vr54xx. */
+#define MASK_MUL_VR54XX(op)   MASK_SPECIAL(op) | (op & (0x1F << 6))
+
+enum {
+    OPC_VR54XX_MULS    = (0x03 << 6) | OPC_MULT,
+    OPC_VR54XX_MULSU   = (0x03 << 6) | OPC_MULTU,
+    OPC_VR54XX_MACC    = (0x05 << 6) | OPC_MULT,
+    OPC_VR54XX_MACCU   = (0x05 << 6) | OPC_MULTU,
+    OPC_VR54XX_MSAC    = (0x07 << 6) | OPC_MULT,
+    OPC_VR54XX_MSACU   = (0x07 << 6) | OPC_MULTU,
+    OPC_VR54XX_MULHI   = (0x09 << 6) | OPC_MULT,
+    OPC_VR54XX_MULHIU  = (0x09 << 6) | OPC_MULTU,
+    OPC_VR54XX_MULSHI  = (0x0B << 6) | OPC_MULT,
+    OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
+    OPC_VR54XX_MACCHI  = (0x0D << 6) | OPC_MULT,
+    OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
+    OPC_VR54XX_MSACHI  = (0x0F << 6) | OPC_MULT,
+    OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
+};
+
 /* REGIMM (rt field) opcodes */
 #define MASK_REGIMM(op)    MASK_OP_MAJOR(op) | (op & (0x1F << 16))
 
@@ -1530,6 +1550,80 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
     MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
 }
 
+static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
+                            int rd, int rs, int rt)
+{
+    const char *opn = "mul vr54xx";
+
+    GEN_LOAD_REG_T0(rs);
+    GEN_LOAD_REG_T1(rt);
+
+    switch (opc) {
+    case OPC_VR54XX_MULS:
+        gen_op_muls();
+        opn = "muls";
+       break;
+    case OPC_VR54XX_MULSU:
+        gen_op_mulsu();
+        opn = "mulsu";
+       break;
+    case OPC_VR54XX_MACC:
+        gen_op_macc();
+        opn = "macc";
+       break;
+    case OPC_VR54XX_MACCU:
+        gen_op_maccu();
+        opn = "maccu";
+       break;
+    case OPC_VR54XX_MSAC:
+        gen_op_msac();
+        opn = "msac";
+       break;
+    case OPC_VR54XX_MSACU:
+        gen_op_msacu();
+        opn = "msacu";
+       break;
+    case OPC_VR54XX_MULHI:
+        gen_op_mulhi();
+        opn = "mulhi";
+       break;
+    case OPC_VR54XX_MULHIU:
+        gen_op_mulhiu();
+        opn = "mulhiu";
+       break;
+    case OPC_VR54XX_MULSHI:
+        gen_op_mulshi();
+        opn = "mulshi";
+       break;
+    case OPC_VR54XX_MULSHIU:
+        gen_op_mulshiu();
+        opn = "mulshiu";
+       break;
+    case OPC_VR54XX_MACCHI:
+        gen_op_macchi();
+        opn = "macchi";
+       break;
+    case OPC_VR54XX_MACCHIU:
+        gen_op_macchiu();
+        opn = "macchiu";
+       break;
+    case OPC_VR54XX_MSACHI:
+        gen_op_msachi();
+        opn = "msachi";
+       break;
+    case OPC_VR54XX_MSACHIU:
+        gen_op_msachiu();
+        opn = "msachiu";
+       break;
+    default:
+        MIPS_INVAL("mul vr54xx");
+        generate_exception(ctx, EXCP_RI);
+        return;
+    }
+    GEN_STORE_T0_REG(rd);
+    MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
+}
+
 static void gen_cl (DisasContext *ctx, uint32_t opc,
                     int rd, int rs)
 {
@@ -5973,7 +6067,12 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
             gen_arith(env, ctx, op1, rd, rs, rt);
             break;
         case OPC_MULT ... OPC_DIVU:
-            gen_muldiv(ctx, op1, rs, rt);
+            if (sa) {
+                check_insn(env, ctx, INSN_VR54XX);
+                op1 = MASK_MUL_VR54XX(ctx->opcode);
+                gen_mul_vr54xx(ctx, op1, rd, rs, rt);
+            } else
+                gen_muldiv(ctx, op1, rs, rt);
             break;
         case OPC_JR ... OPC_JALR:
             gen_compute_branch(ctx, op1, rs, rd, sa);
index a2dec0a..57666d4 100644 (file)
@@ -306,6 +306,22 @@ static mips_def_t mips_defs[] =
         .mmu_type = MMU_TYPE_R4000,
     },
     {
+        .name = "VR5432",
+        .CP0_PRid = 0x00005400,
+        /* No L2 cache, icache size 8k, dcache size 8k, uncached coherency. */
+        .CP0_Config0 = (1 << 17) | (0x1 << 9) | (0x1 << 6) | (0x2 << CP0C0_K0),
+        .CP0_Config1 = (1 << CP0C1_FP) | (47 << CP0C1_MMU),
+        .SYNCI_Step = 16,
+        .CCRes = 2,
+        .CP0_Status_rw_bitmask = 0x3678FFFF,
+        /* The VR5432 has a full 64bit FPU but doesn't use the fcr0 bits. */
+        .CP1_fcr0 = (0x54 << FCR0_PRID) | (0x0 << FCR0_REV),
+        .SEGBITS = 40,
+        .PABITS = 32,
+        .insn_flags = CPU_VR54XX,
+        .mmu_type = MMU_TYPE_R4000,
+    },
+    {
         .name = "5Kc",
         .CP0_PRid = 0x00018100,
         .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT) |