qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 2/3] target-mips:Support for Cavium-Octeon specific


From: Khansa Butt
Subject: [Qemu-devel] [PATCH 2/3] target-mips:Support for Cavium-Octeon specific instructions
Date: Fri, 29 Apr 2011 11:19:31 +0500

From f699dbfdca62c5af92d764673b2300131d26263e Mon Sep 17 00:00:00 2001
From: Ehsan-ul-Haq, Abdul Qadeer, Abdul Waheed, Khansa Butt <address@hidden>
Date: Wed, 27 Apr 2011 16:08:16 +0500
Subject: [PATCH 2/3] target-mips:Support for Cavium-Octeon specific instructions


Signed-off-by: Khansa Butt <address@hidden>
---
 host-utils.c            |    1 +
 target-mips/cpu.h       |    7 +
 target-mips/helper.h    |    5 +
 target-mips/op_helper.c |   62 +++++++
 target-mips/translate.c |  445 +++++++++++++++++++++++++++++++++++++++++++++--
 5 files changed, 509 insertions(+), 11 deletions(-)

diff --git a/host-utils.c b/host-utils.c
index dc96123..1128698 100644
--- a/host-utils.c
+++ b/host-utils.c
@@ -102,4 +102,5 @@ void muls64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
            a, b, *phigh, *plow);
 #endif
 }
+
 #endif /* !defined(__x86_64__) */
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 0b98d10..47e6c1f 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -171,6 +171,13 @@ struct TCState {
     target_ulong CP0_TCSchedule;
     target_ulong CP0_TCScheFBack;
     int32_t CP0_Debug_tcstatus;
+    /* Multiplier registers for Octeon */
+    target_ulong MPL0;
+    target_ulong MPL1;
+    target_ulong MPL2;
+    target_ulong P0;
+    target_ulong P1;
+    target_ulong P2;
 };
 
 typedef struct CPUMIPSState CPUMIPSState;
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 297ab64..e892d39 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -8,7 +8,12 @@ DEF_HELPER_3(ldl, tl, tl, tl, int)
 DEF_HELPER_3(ldr, tl, tl, tl, int)
 DEF_HELPER_3(sdl, void, tl, tl, int)
 DEF_HELPER_3(sdr, void, tl, tl, int)
+DEF_HELPER_2(v3mulu, tl, tl, tl)
+DEF_HELPER_2(vmulu, tl, tl, tl)
+DEF_HELPER_1(dpop, tl, tl)
 #endif
+DEF_HELPER_1(pop, tl, tl);
+
 DEF_HELPER_3(lwl, tl, tl, tl, int)
 DEF_HELPER_3(lwr, tl, tl, tl, int)
 DEF_HELPER_3(swl, void, tl, tl, int)
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index b8e4991..96cfbe6 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -266,7 +266,69 @@ void helper_dmultu (target_ulong arg1, target_ulong arg2)
 {
     mulu64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2);
 }
+static void addc(uint64_t res[], uint64_t a, int i)
+{
+    uint64_t c = res[i];
+    for (; i < 4; i++) {
+        res[i] = c + a;
+        if (res[i] < a) {
+            c = 1;
+            a = res[i+1];
+        } else
+              break;
+    }
+}
+target_ulong helper_v3mulu(target_ulong arg1, target_ulong arg2)
+{
+    uint64_t hi, lo, res[4];
+    int i;
+    for (i = 0; i < 4; i++) {
+        res[i] = 0;
+    }
+    mulu64(&res[0], &res[1], env->active_tc.MPL0, arg1);
+    mulu64(&lo, &hi, env->active_tc.MPL1, arg1);
+    res[1] = res[1] + lo;
+    if (res[1] < lo)
+        res[2]++;
+    res[2] = res[2] + hi;
+    if (res[2] < hi)
+        res[3]++;
+    mulu64(&lo, &hi, env->active_tc.MPL2, arg1);
+    res[2] = res[2] + lo;
+    if (res[2] < lo)
+        res[3]++;
+    res[3] = res[3] + hi;
+    addc(res, arg2, 0);
+    addc(res, env->active_tc.P0, 0);
+    addc(res, env->active_tc.P1, 1);
+    addc(res, env->active_tc.P2, 2);
+    env->active_tc.P0 = res[1];
+    env->active_tc.P1 = res[2];
+    env->active_tc.P2 = res[3];
+    return res[0];
+}
+target_ulong helper_vmulu(target_ulong arg1, target_ulong arg2)
+{
+    uint64_t hi, lo;
+    mulu64(&lo, &hi, env->active_tc.MPL0, arg1);
+    lo = lo + arg2;
+    if (lo < arg2)
+        hi++;
+    lo = lo + env->active_tc.P0;
+    if (lo < env->active_tc.P0)
+        hi++;
+    env->active_tc.P0 = hi;
+    return lo;
+}
+target_ulong helper_dpop(target_ulong arg)
+{
+    return ctpop64(arg);
+}
 #endif
+target_ulong helper_pop(target_ulong arg)
+{
+    return ctpop32((uint32_t)arg);
+}
 
 #ifndef CONFIG_USER_ONLY
 
diff --git a/target-mips/translate.c b/target-mips/translate.c
index c88c3f9..cb431a8 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -70,6 +70,11 @@ enum {
     OPC_JAL      = (0x03 << 26),
     OPC_JALS     = OPC_JAL | 0x5,
     OPC_BEQ      = (0x04 << 26),  /* Unconditional if rs = rt = 0 (B) */
+    /* Cavium Specific */
+    OPC_BBIT1    = (0x3a << 26),  /* jump on bit set, cavium specific */
+    OPC_BBIT132  = (0x3e << 26),  /* jump on bit set(for upper 32 bits) */
+    OPC_BBIT0    = (0x32 << 26),  /* jump on bit clear, cavium specific */
+    OPC_BBIT032  = (0x36 << 26),  /* jump on bit clear(for upper 32 bits) */
     OPC_BEQL     = (0x14 << 26),
     OPC_BNE      = (0x05 << 26),
     OPC_BNEL     = (0x15 << 26),
@@ -265,6 +270,31 @@ enum {
     OPC_MADD     = 0x00 | OPC_SPECIAL2,
     OPC_MADDU    = 0x01 | OPC_SPECIAL2,
     OPC_MUL      = 0x02 | OPC_SPECIAL2,
+    /* Cavium Specific Instructions */
+    OPC_BADDU    = 0x28 | OPC_SPECIAL2,
+    OPC_DMUL     = 0x03 | OPC_SPECIAL2,
+    OPC_EXTS     = 0x3a | OPC_SPECIAL2,
+    OPC_EXTS32   = 0x3b | OPC_SPECIAL2,
+    OPC_CINS     = 0x32 | OPC_SPECIAL2,
+    OPC_CINS32   = 0x33 | OPC_SPECIAL2,
+    OPC_SEQI     = 0x2e | OPC_SPECIAL2,
+    OPC_SNEI     = 0x2f | OPC_SPECIAL2,
+    OPC_MTM0     = 0x08 | OPC_SPECIAL2,
+    OPC_MTM1     = 0x0c | OPC_SPECIAL2,
+    OPC_MTM2     = 0x0d | OPC_SPECIAL2,
+    OPC_MTP0     = 0x09 | OPC_SPECIAL2,
+    OPC_MTP1     = 0x0a | OPC_SPECIAL2,
+    OPC_MTP2     = 0x0b | OPC_SPECIAL2,
+    OPC_V3MULU   = 0x11 | OPC_SPECIAL2,
+    OPC_VMM0     = 0x10 | OPC_SPECIAL2,
+    OPC_VMULU    = 0x0f | OPC_SPECIAL2,
+    OPC_POP      = 0X2C | OPC_SPECIAL2,
+    OPC_DPOP     = 0X2D | OPC_SPECIAL2,
+    OPC_SEQ      = 0x2a | OPC_SPECIAL2,
+    OPC_SNE      = 0x2b | OPC_SPECIAL2,
+    OPC_SAA      = 0x18 | OPC_SPECIAL2,
+    OPC_SAAD     = 0x19 | OPC_SPECIAL2,
+/**************************************/
     OPC_MSUB     = 0x04 | OPC_SPECIAL2,
     OPC_MSUBU    = 0x05 | OPC_SPECIAL2,
     /* Loongson 2F */
@@ -483,7 +513,7 @@ enum {
 static TCGv_ptr cpu_env;
 static TCGv cpu_gpr[32], cpu_PC;
 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
-static TCGv cpu_dspctrl, btarget, bcond;
+static TCGv cpu_dspctrl, btarget, bcond, mpl0, mpl1, mpl2, p0, p1, p2;
 static TCGv_i32 hflags;
 static TCGv_i32 fpu_fcr0, fpu_fcr31;
 
@@ -1419,7 +1449,30 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
     (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
 }
-
+#if defined(TARGET_MIPS64)
+/* set on equal immidiate/set if not equal immidiate */
+static void gen_set_imm(CPUState *env, uint32_t opc,
+                        int rt, int rs, int16_t imm)
+{
+    TCGv t0;
+    const char *opn = "imm set";
+    t0 = tcg_temp_new();
+    gen_load_gpr(t0, rs);
+    switch (opc) {
+    case OPC_SEQI:
+        tcg_gen_xori_tl(t0, t0, imm);
+        tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, 1);
+        opn = "seqi";
+        break;
+    case OPC_SNEI:
+        tcg_gen_xori_tl(t0, t0, imm);
+        tcg_gen_setcondi_tl(TCG_COND_GT, cpu_gpr[rt], t0, 0);
+        opn = "snei";
+        break;
+    }
+    tcg_temp_free(t0);
+}
+#endif
 /* Logic with immediate operand */
 static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
 {
@@ -1583,6 +1636,78 @@ static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
     MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
     tcg_temp_free(t0);
 }
+#if defined(TARGET_MIPS64)
+static void gen_LMI (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
+                     int rs, int rt, int rd)
+{
+    const char *opn = "LMI";
+    TCGv t0, t1;
+    t0 = tcg_temp_new();
+    t1 = tcg_temp_new();
+    gen_load_gpr(t0, rs);
+    gen_load_gpr(t1, rt);
+    switch (opc) {
+    case OPC_MTM0:
+        tcg_gen_mov_tl(mpl0, t0);
+        tcg_gen_movi_tl(p0, 0);
+        tcg_gen_movi_tl(p1, 0);
+        tcg_gen_movi_tl(p2, 0);
+        opn = "mtm0";
+        break;
+    case OPC_MTM1:
+        tcg_gen_mov_tl(mpl1, t0);
+        tcg_gen_movi_tl(p0, 0);
+        tcg_gen_movi_tl(p1, 0);
+        tcg_gen_movi_tl(p2, 0);
+        opn = "mtm1";
+        break;
+    case OPC_MTM2:
+        tcg_gen_mov_tl(mpl2, t0);
+        tcg_gen_movi_tl(p0, 0);
+        tcg_gen_movi_tl(p1, 0);
+        tcg_gen_movi_tl(p2, 0);
+        opn = "mtm2";
+        break;
+    case OPC_MTP0:
+        tcg_gen_mov_tl(p0, t0);
+        opn = "mtp0";
+        break;
+    case OPC_MTP1:
+        tcg_gen_mov_tl(p1, t0);
+        opn = "mtp1";
+        break;
+    case OPC_MTP2:
+        tcg_gen_mov_tl(p2, t0);
+        opn = "mtp2";
+        break;
+    case OPC_VMM0:
+        tcg_gen_mul_i64(t0, t0, mpl0);
+        tcg_gen_add_tl(t1, t1, t0);
+        tcg_gen_add_tl(t1, t1, p0);
+        gen_store_gpr(t1, rd);
+        tcg_gen_mov_tl(mpl0, t1);
+        tcg_gen_movi_tl(p0, 0);
+        tcg_gen_movi_tl(p1, 0);
+        tcg_gen_movi_tl(p2, 0);
+        opn = "vmm0";
+        break;
+    case OPC_VMULU:
+        gen_helper_vmulu(t0, t0, t1);
+        gen_store_gpr(t0, rd);
+        opn = "vmulu";
+        break;
+    case OPC_V3MULU:
+        gen_load_gpr(t0, rs);
+        gen_load_gpr(t1, rt);
+        gen_helper_v3mulu(t0, t0, t1);
+        gen_store_gpr(t0, rd);
+        opn = "v3mulu";
+        break;
+    }
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+}
+#endif
 
 /* Arithmetic */
 static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
@@ -1637,6 +1762,30 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
         }
         opn = "addu";
         break;
+    case OPC_BADDU:
+        {
+            TCGv t0 = tcg_temp_new();
+            TCGv t1 = tcg_temp_new();
+            gen_load_gpr(t0, rs);
+            gen_load_gpr(t1, rt);
+            tcg_gen_add_tl(t0, t1, t0);
+            tcg_gen_ext8u_tl(t0, t0);
+            gen_store_gpr(t0, rd);
+            tcg_temp_free(t0);
+            tcg_temp_free(t1);
+        }
+       opn = "baddu";
+       break;
+    case OPC_DMUL:
+        {
+            TCGv t0 = tcg_temp_new();
+            TCGv t1 = tcg_temp_new();
+            gen_load_gpr(t0, rs);
+            gen_load_gpr(t1, rt);
+            tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
+        }
+            opn = "dmul";
+            break;
     case OPC_SUB:
         {
             TCGv t0 = tcg_temp_local_new();
@@ -2013,7 +2162,69 @@ static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
     (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s", opn, regnames[reg]);
 }
+#if defined(TARGET_MIPS64)
+static void gen_seqsne (DisasContext *ctx, uint32_t opc,
+                        int rd, int rs, int rt)
+{
+    const char *opn = "seq/sne";
+    TCGv t0, t1;
+    t0 = tcg_temp_new();
+    t1 = tcg_temp_new();
+    gen_load_gpr(t0, rs);
+    gen_load_gpr(t1, rt);
+    switch (opc) {
+    case OPC_SEQ:
+        tcg_gen_xor_tl(t0, t0, t1);
+        tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rd], t0, 1);
+        opn = "seq";
+        break;
+    case OPC_SNE:
+        tcg_gen_xor_tl(t0, t0, t1);
+        tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_gpr[rd], t0, 0);
+        opn = "sne";
+        break;
+    default:
+        MIPS_INVAL(opn);
+        generate_exception(ctx, EXCP_RI);
+        goto out;
+    }
+out:
+        tcg_temp_free(t0);
+        tcg_temp_free(t1);
+
+}
+/* FIXME: something else should be done for emulating SMP system. */
+static void gen_saa (CPUState *env, DisasContext *ctx, uint32_t opc,
+                     int rt, int base)
+{
+    const char *opn = "saa";
+    TCGv t0, t1, temp;
+    t0 = tcg_temp_new();
+    t1 = tcg_temp_new();
+    temp = tcg_temp_new();
+    gen_load_gpr(t1, rt);
+    gen_base_offset_addr(ctx, t0, base, 0);
+    switch (opc) {
+    case OPC_SAA:
+        save_cpu_state(ctx, 1);
+        op_ld_lw(temp, t0, ctx);
+        tcg_gen_add_tl(temp, temp, t1);
+        op_st_sw(temp, t0, ctx);
+        opn = "saa";
+        break;
+    case OPC_SAAD:
+        save_cpu_state(ctx, 0);
+        op_ld_ld(temp, t0, ctx);
+        tcg_gen_add_tl(temp, temp, t1);
+        op_st_sd(temp, t0, ctx);
+        opn = "saad";
+        break;
+    }
 
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+}
+#endif
 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
                         int rs, int rt)
 {
@@ -2368,7 +2579,28 @@ static void gen_cl (DisasContext *ctx, uint32_t opc,
     MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
     tcg_temp_free(t0);
 }
-
+#if defined(TARGET_MIPS64)
+static void gen_pop_count (DisasContext *ctx, uint32_t opc, int rd, int rs)
+{
+    const char *opn = "pop";
+        TCGv t0;
+        t0 = tcg_temp_new();
+        gen_load_gpr(t0, rs);
+        switch (opc) {
+        case OPC_DPOP:
+            gen_helper_dpop(t0, t0);
+            gen_store_gpr(t0, rd);
+            opn = "dpop";
+            break;
+        case OPC_POP:
+            gen_helper_pop(t0, t0);
+            gen_store_gpr(t0, rd);
+            opn = "pop";
+            break;
+        }
+        tcg_temp_free(t0);
+}
+#endif
 /* Godson integer instructions */
 static void gen_loongson_integer (DisasContext *ctx, uint32_t opc,
                                 int rd, int rs, int rt)
@@ -2705,6 +2937,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
     target_ulong btgt = -1;
     int blink = 0;
     int bcond_compute = 0;
+    target_ulong maskb; /* Used in BBIT0 and BBIT1 */
     TCGv t0 = tcg_temp_new();
     TCGv t1 = tcg_temp_new();
 
@@ -2730,6 +2963,22 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
         }
         btgt = ctx->pc + insn_bytes + offset;
         break;
+    case OPC_BBIT0:
+    case OPC_BBIT1:
+        gen_load_gpr(t0, rs);
+        maskb = 1ULL << rt;
+        tcg_gen_andi_tl(t0, t0, maskb);
+        bcond_compute = 1;
+        btgt = ctx->pc + insn_bytes + offset;
+        break;
+    case OPC_BBIT032:
+    case OPC_BBIT132:
+        gen_load_gpr(t0, rs);
+        maskb = 1ULL << (rt + 32);
+        tcg_gen_andi_tl(t0, t0, maskb);
+        bcond_compute = 1;
+        btgt = ctx->pc + insn_bytes + offset;
+        break;
     case OPC_BGEZ:
     case OPC_BGEZAL:
     case OPC_BGEZALS:
@@ -2888,6 +3137,14 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
             MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
                        regnames[rs], regnames[rt], btgt);
             goto not_likely;
+        case OPC_BBIT1:
+        case OPC_BBIT132:
+            tcg_gen_setcondi_tl(TCG_COND_NE, bcond, t0, 0);
+            goto not_likely;
+            case OPC_BBIT0:
+            case OPC_BBIT032:
+            tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, t0, 0);
+            goto not_likely;
         case OPC_BNEL:
             tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
             MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
@@ -2983,7 +3240,42 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
     tcg_temp_free(t0);
     tcg_temp_free(t1);
 }
+/* For cavium specific extract instructions */
+#if defined(TARGET_MIPS64)
+static void gen_exts (CPUState *env, DisasContext *ctx, uint32_t opc, int rt,
+                      int rs, int lsb, int msb)
+{
+    TCGv t0 = tcg_temp_new();
+    TCGv t1 = tcg_temp_new();
+    target_ulong mask;
+    gen_load_gpr(t1, rs);
+    switch (opc) {
+    case OPC_EXTS:
+        tcg_gen_shri_tl(t0, t1, lsb);
+        tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
+        /* To sign extened the remaining bits according to
+           the msb of the bit field */
+        mask = 1ULL << msb;
+        tcg_gen_andi_tl(t1, t0, mask);
+        tcg_gen_addi_tl(t1, t1, -1);
+        tcg_gen_orc_tl(t0, t0, t1);
+        gen_store_gpr(t0, rt);
+        break;
+    case OPC_EXTS32:
+        tcg_gen_shri_tl(t0, t1, lsb + 32);
+        tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
+        mask = 1ULL << msb;
+        tcg_gen_andi_tl(t1, t0, mask);
+        tcg_gen_addi_tl(t1, t1, -1);
+        tcg_gen_orc_tl(t0, t0, t1);
+        gen_store_gpr(t0, rt);
+        break;
 
+    }
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+}
+#endif
 /* special3 bitfield operations */
 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
                         int rs, int lsb, int msb)
@@ -3063,6 +3355,22 @@ static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
         tcg_gen_andi_tl(t1, t1, mask);
         tcg_gen_or_tl(t0, t0, t1);
         break;
+    case OPC_CINS:
+        mask =  (1ULL << (msb+1))-1;
+        gen_load_gpr(t0, rt);
+        tcg_gen_andi_tl(t0, t0, 0);
+        tcg_gen_andi_tl(t1, t1, mask);
+        tcg_gen_shli_tl(t1, t1, lsb);
+        tcg_gen_or_tl(t0, t0, t1);
+        break;
+    case OPC_CINS32:
+        mask =  (1ULL << (msb+1))-1;
+        gen_load_gpr(t0, rt);
+        tcg_gen_andi_tl(t0, t0, 0);
+        tcg_gen_andi_tl(t1, t1, mask);
+        tcg_gen_shli_tl(t1, t1, (lsb+32));
+        tcg_gen_or_tl(t0, t0, t1);
+        break;
 #endif
     default:
 fail:
@@ -11609,8 +11917,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
     int32_t offset;
     int rs, rt, rd, sa;
     uint32_t op, op1, op2;
-    int16_t imm;
-
+    int16_t imm, imm10;
     /* make sure instructions are on a word boundary */
     if (ctx->pc & 0x3) {
         env->CP0_BadVAddr = ctx->pc;
@@ -11638,6 +11945,9 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
     rd = (ctx->opcode >> 11) & 0x1f;
     sa = (ctx->opcode >> 6) & 0x1f;
     imm = (int16_t)ctx->opcode;
+    /* 10 bit Immediate value For SEQI,SNEI */
+    imm10 = (ctx->opcode >> 6) & 0x3ff;
+
     switch (op) {
     case OPC_SPECIAL:
         op1 = MASK_SPECIAL(ctx->opcode);
@@ -11863,6 +12173,58 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
         case OPC_MUL:
             gen_arith(env, ctx, op1, rd, rs, rt);
             break;
+#if defined(TARGET_MIPS64)
+
+        case OPC_DMUL:
+            check_mips_64(ctx);
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_arith(env, ctx, op1, rd, rs, rt);
+            break;
+        case OPC_CINS:
+            check_mips_64(ctx);
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_bitops(ctx, op1, rt, rs, sa, rd);
+            break;
+        case OPC_CINS32:
+            check_mips_64(ctx);
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_bitops(ctx, op1, rt, rs, sa, rd);
+            break;
+        case OPC_MTM0:
+        case OPC_MTM1:
+        case OPC_MTM2:
+        case OPC_MTP0:
+        case OPC_MTP1:
+        case OPC_MTP2:
+        case OPC_VMULU:
+            check_mips_64(ctx);
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_LMI(env, ctx, op1, rs, rt, rd);
+            break;
+        case OPC_BADDU:
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_arith(env, ctx, op1, rd, rs, rt);
+            break;
+        case OPC_EXTS:
+            check_mips_64(ctx);
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_exts(env, ctx, op1, rt, rs, sa, rd);
+            break;
+        case OPC_EXTS32:
+            check_mips_64(ctx);
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_exts(env, ctx, op1, rt, rs, sa, rd);
+            break;
+        case OPC_SAA:
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_saa(env, ctx, op1, rt, rs);
+            break;
+        case OPC_SAAD:
+            check_insn(env, ctx, INSN_OCTEON);
+            check_mips_64(ctx);
+            gen_saa(env, ctx, op1, rt, rs);
+            break;
+#endif
         case OPC_CLO:
         case OPC_CLZ:
             check_insn(env, ctx, ISA_MIPS32);
@@ -11882,13 +12244,24 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
             break;
         case OPC_DIV_G_2F:
         case OPC_DIVU_G_2F:
-        case OPC_MULT_G_2F:
         case OPC_MULTU_G_2F:
         case OPC_MOD_G_2F:
         case OPC_MODU_G_2F:
             check_insn(env, ctx, INSN_LOONGSON2F);
             gen_loongson_integer(ctx, op1, rd, rs, rt);
             break;
+        case OPC_MULT_G_2F:
+            if (!(env->insn_flags & CPU_OCTEON)) {
+                check_insn(env, ctx, INSN_LOONGSON2F);
+                gen_loongson_integer(ctx, op1, rd, rs, rt);
+            } else {
+#if defined(TARGET_MIPS64)
+                /* Cavium Specific vmm0 */
+                check_mips_64(ctx);
+                gen_LMI(env, ctx, op1, rs, rt, rd);
+#endif
+            }
+            break;
 #if defined(TARGET_MIPS64)
         case OPC_DCLO:
         case OPC_DCLZ:
@@ -11896,7 +12269,6 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
             check_mips_64(ctx);
             gen_cl(ctx, op1, rd, rs);
             break;
-        case OPC_DMULT_G_2F:
         case OPC_DMULTU_G_2F:
         case OPC_DDIV_G_2F:
         case OPC_DDIVU_G_2F:
@@ -11905,6 +12277,37 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
             check_insn(env, ctx, INSN_LOONGSON2F);
             gen_loongson_integer(ctx, op1, rd, rs, rt);
             break;
+        case OPC_DMULT_G_2F:
+            if (!(env->insn_flags & CPU_OCTEON)) {
+                check_insn(env, ctx, INSN_LOONGSON2F);
+                gen_loongson_integer(ctx, op1, rd, rs, rt);
+            } else {
+                /* Cavium Specific instruction v3mulu */
+                check_mips_64(ctx);
+                gen_LMI(env, ctx, op1, rs, rt, rd);
+            }
+            break;
+        case OPC_SEQ:
+        case OPC_SNE:
+            check_mips_64(ctx);
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_seqsne(ctx, op1, rd, rs, rt);
+            break;
+        case OPC_SEQI:
+        case OPC_SNEI:
+            check_mips_64(ctx);
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_set_imm(env, op1, rt, rs, imm10);
+            break;
+        case OPC_POP:
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_pop_count(ctx, op1, rd, rs);
+            break;
+        case OPC_DPOP:
+            check_mips_64(ctx);
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_pop_count(ctx, op1, rd, rs);
+            break;
 #endif
         default:            /* Invalid */
             MIPS_INVAL("special2");
@@ -12196,10 +12599,18 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
         break;
 
     /* COP2.  */
-    case OPC_LWC2:
-    case OPC_LDC2:
-    case OPC_SWC2:
-    case OPC_SDC2:
+    /* Conflicting opcodes with Cavium specific branch instructions
+       if cpu_model is set to Octeon these opcodes will
+       belong to Octeon processor */
+    case OPC_LWC2: /* BBIT0 */
+    case OPC_LDC2: /* BBIT032 */
+    case OPC_SWC2: /* BBIT1 */
+    case OPC_SDC2: /* BBIT132 */
+        if (env->insn_flags & CPU_OCTEON) {
+            gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
+            *is_branch = 1;
+            break;
+        }
     case OPC_CP2:
         /* COP2: Not implemented. */
         generate_exception_err(ctx, EXCP_CpU, 2);
@@ -12588,6 +12999,18 @@ static void mips_tcg_init(void)
     cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
                                      offsetof(CPUState, active_tc.DSPControl),
                                      "DSPControl");
+    mpl0 = tcg_global_mem_new(TCG_AREG0,
+                              offsetof(CPUState, active_tc.MPL0), "MPL0");
+    mpl1 = tcg_global_mem_new(TCG_AREG0,
+                              offsetof(CPUState, active_tc.MPL1), "MPL1");
+    mpl2 = tcg_global_mem_new(TCG_AREG0,
+                              offsetof(CPUState, active_tc.MPL2), "MPL2");
+    p0 = tcg_global_mem_new(TCG_AREG0,
+                            offsetof(CPUState, active_tc.P0), "P0");
+    p1 = tcg_global_mem_new(TCG_AREG0,
+                            offsetof(CPUState, active_tc.P1), "P1");
+    p2 = tcg_global_mem_new(TCG_AREG0,
+                            offsetof(CPUState, active_tc.P2), "P2");
     bcond = tcg_global_mem_new(TCG_AREG0,
                                offsetof(CPUState, bcond), "bcond");
     btarget = tcg_global_mem_new(TCG_AREG0,
-- 
1.7.3.4


reply via email to

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