qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH v1 5/6] target-mips: Support for Cavium specific ins


From: khansa
Subject: [Qemu-devel] [PATCH v1 5/6] target-mips: Support for Cavium specific instructions
Date: Sat, 1 Oct 2011 14:26:40 +0500

From: Khansa Butt <address@hidden>


Signed-off-by: Khansa Butt <address@hidden>
Signed-off-by: Ehsan Ul Haq <address@hidden>
Signed-off-by: Abdul Qadeer <address@hidden>
Signed-off-by: Abdul Waheed <address@hidden>
---
 target-mips/cpu.h       |    7 +
 target-mips/helper.h    |    5 +
 target-mips/machine.c   |   12 ++
 target-mips/op_helper.c |   73 ++++++++
 target-mips/translate.c |  429 ++++++++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 521 insertions(+), 5 deletions(-)

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 79e2558..9180ee9 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -173,6 +173,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 442f684..7ba5d9f 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/machine.c b/target-mips/machine.c
index be72b36..a274ce2 100644
--- a/target-mips/machine.c
+++ b/target-mips/machine.c
@@ -25,6 +25,12 @@ static void save_tc(QEMUFile *f, TCState *tc)
     qemu_put_betls(f, &tc->CP0_TCSchedule);
     qemu_put_betls(f, &tc->CP0_TCScheFBack);
     qemu_put_sbe32s(f, &tc->CP0_Debug_tcstatus);
+    qemu_put_betls(f, &tc->MPL0);
+    qemu_put_betls(f, &tc->MPL1);
+    qemu_put_betls(f, &tc->P0);
+    qemu_put_betls(f, &tc->P1);
+    qemu_put_betls(f, &tc->P2);
+
 }
 
 static void save_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
@@ -173,6 +179,12 @@ static void load_tc(QEMUFile *f, TCState *tc)
     qemu_get_betls(f, &tc->CP0_TCSchedule);
     qemu_get_betls(f, &tc->CP0_TCScheFBack);
     qemu_get_sbe32s(f, &tc->CP0_Debug_tcstatus);
+    qemu_get_betls(f, &tc->MPL0);
+    qemu_get_betls(f, &tc->MPL1);
+    qemu_get_betls(f, &tc->MPL2);
+    qemu_get_betls(f, &tc->P0);
+    qemu_get_betls(f, &tc->P1);
+    qemu_get_betls(f, &tc->P2);
 }
 
 static void load_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 96e40c6..4565d17 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -320,8 +320,81 @@ 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
 
 static inline target_phys_addr_t do_translate_address(target_ulong address, 
int rw)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 0550333..86776a8 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -78,6 +78,11 @@ enum {
     OPC_BGTZL    = (0x17 << 26),
     OPC_JALX     = (0x1D << 26),  /* MIPS 16 only */
     OPC_JALXS    = OPC_JALX | 0x5,
+    /* Cavium Specific branches */
+    OPC_BBIT1    = (0x3a << 26),  /* jump on bit set */
+    OPC_BBIT132  = (0x3e << 26),  /* jump on bit set (for upper 32 bits) */
+    OPC_BBIT0    = (0x32 << 26),  /* jump on bit clear */
+    OPC_BBIT032  = (0x36 << 26),  /* jump on bit clear (for upper 32 bits) */
     /* Load and stores */
     OPC_LDL      = (0x1A << 26),
     OPC_LDR      = (0x1B << 26),
@@ -286,6 +291,30 @@ enum {
     OPC_DCLO     = 0x25 | OPC_SPECIAL2,
     /* Special */
     OPC_SDBBP    = 0x3F | 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,
 };
 
 /* Special3 opcodes */
@@ -1419,6 +1448,225 @@ static void gen_arith_imm (CPUState *env, DisasContext 
*ctx, uint32_t opc,
     MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], 
uimm);
 }
 
+#if defined(TARGET_MIPS64)
+/* set on equal/not equal immediate */
+static void gen_set_imm(CPUState *env, uint32_t opc,
+                        int rt, int rs, int16_t imm)
+{
+    target_ulong uimm = (target_long)imm;
+    TCGv t0;
+    const char *opn = "imm set";
+    if (rt == 0) {
+        /* If no destination, treat it as a NOP. */
+        MIPS_DEBUG("NOP");
+        return;
+    }
+    t0 = tcg_temp_new();
+    gen_load_gpr(t0, rs);
+    switch (opc) {
+    case OPC_SEQI:
+        tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_gpr[rt], t0, uimm);
+        opn = "seqi";
+        break;
+    case OPC_SNEI:
+        tcg_gen_setcondi_tl(TCG_COND_NE, cpu_gpr[rt], t0, uimm);
+        opn = "snei";
+        break;
+    }
+    tcg_temp_free(t0);
+}
+
+/* Cavium specific Large Multiply Instructions */
+static void gen_LMI(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_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.MPL0));
+        tcg_gen_movi_tl(t0, 0);
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P0));
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P1));
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P2));
+        opn = "mtm0";
+        break;
+    case OPC_MTM1:
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.MPL1));
+        tcg_gen_movi_tl(t0, 0);
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P0));
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P1));
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P2));
+        opn = "mtm1";
+        break;
+    case OPC_MTM2:
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.MPL2));
+        tcg_gen_movi_tl(t0, 0);
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P0));
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P1));
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P2));
+        break;
+    case OPC_MTP0:
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P0));
+        opn = "mtp0";
+        break;
+    case OPC_MTP1:
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P1));
+        opn = "mtp1";
+        break;
+    case OPC_MTP2:
+        tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P2));
+        opn = "mtp2";
+        break;
+    case OPC_VMM0:
+        {
+            TCGv t2, t3;
+            t2 = tcg_temp_new();
+            t3 = tcg_temp_new();
+            tcg_gen_ld_tl(t2, cpu_env, offsetof(CPUState, active_tc.MPL0));
+            tcg_gen_ld_tl(t3, cpu_env, offsetof(CPUState, active_tc.P0));
+            tcg_gen_mul_i64(t0, t0, t2);
+            tcg_gen_add_tl(t1, t1, t0);
+            tcg_gen_add_tl(t1, t1, t3);
+            gen_store_gpr(t1, rd);
+            tcg_gen_movi_tl(t0, 0);
+            tcg_gen_st_tl(t1, cpu_env, offsetof(CPUState, active_tc.MPL0));
+            tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P0));
+            tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P1));
+            tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, active_tc.P2));
+            tcg_temp_free(t2);
+            tcg_temp_free(t3);
+            opn = "vmm0";
+            break;
+        }
+    case OPC_VMULU:
+        gen_helper_vmulu(t0, t0, t1);
+        gen_store_gpr(t0, rd);
+        opn = "vmulu";
+        break;
+    case OPC_V3MULU:
+        gen_helper_v3mulu(t0, t0, t1);
+        gen_store_gpr(t0, rd);
+        opn = "v3mulu";
+        break;
+    }
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+}
+
+/* set if equal/not equal */
+static void gen_set(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);
+    tcg_gen_xor_tl(t0, t0, t1);
+    switch (opc) {
+    case OPC_SEQ:
+        tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rd], t0, 1);
+        opn = "seq";
+        break;
+    case OPC_SNE:
+        tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_gpr[rd], t0, 0);
+        opn = "sne";
+        break;
+    default:
+        MIPS_INVAL(opn);
+        generate_exception(ctx, EXCP_RI);
+    }
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+
+}
+
+/* Store atomic add */
+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_ll(temp, t0, ctx);
+        tcg_gen_add_tl(temp, temp, t1);
+        op_st_sc(temp, t0, rt, ctx);
+        opn = "saa";
+        break;
+    case OPC_SAAD:
+        save_cpu_state(ctx, 0);
+        op_ld_lld(temp, t0, ctx);
+        tcg_gen_add_tl(temp, temp, t1);
+        op_st_scd(temp, t0, rt, ctx);
+        opn = "saad";
+        break;
+    }
+
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+}
+
+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);
+}
+
+/* Cavium specific extract instructions */
+static void gen_exts(CPUState *env, DisasContext *ctx, uint32_t opc, int rt,
+                      int rs, int lsb, int msb)
+{
+    TCGv t0 = tcg_temp_new();
+    uint32_t lshft, rshft;
+    gen_load_gpr(t0, rs);
+    switch (opc) {
+    case OPC_EXTS:
+        lshft = 64 - msb - 1 - lsb;
+        rshft = lshft + lsb;
+        tcg_gen_shli_tl(t0, t0, lshft);
+        tcg_gen_sari_tl(t0, t0, rshft);
+        gen_store_gpr(t0, rt);
+        break;
+    case OPC_EXTS32:
+        lshft = 32 - msb - 1 - lsb;
+        rshft = 64 - msb - 1;
+        tcg_gen_shli_tl(t0, t0, lshft);
+        tcg_gen_sari_tl(t0, t0, rshft);
+        gen_store_gpr(t0, rt);
+        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)
 {
@@ -1636,6 +1884,32 @@ 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);
+            tcg_temp_free(t0);
+            tcg_temp_free(t1);
+            opn = "dmul";
+            break;
+        }
     case OPC_SUB:
         {
             TCGv t0 = tcg_temp_local_new();
@@ -2729,6 +3003,28 @@ static void gen_compute_branch (DisasContext *ctx, 
uint32_t opc,
         }
         btgt = ctx->pc + insn_bytes + offset;
         break;
+    case OPC_BBIT0:
+    case OPC_BBIT1:
+        {
+            target_ulong maskb;
+            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:
+        {
+            target_ulong maskb;
+            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:
@@ -2887,6 +3183,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,
@@ -3062,6 +3366,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:
@@ -11948,6 +12268,57 @@ 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(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);
@@ -11965,9 +12336,18 @@ static void decode_opc (CPUState *env, DisasContext 
*ctx, int *is_branch)
             }
             /* Treat as NOP. */
             break;
+        case OPC_MULT_G_2F:
+#if defined(TARGET_MIPS64)
+             /* Is Cavium Specific vmm0? */
+             if ((env->insn_flags & CPU_OCTEON)) {
+                check_mips_64(ctx);
+                gen_LMI(ctx, op1, rs, rt, rd);
+                break;
+             }
+#endif
+        /* Otherwise fall through */
         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:
@@ -11982,6 +12362,12 @@ static void decode_opc (CPUState *env, DisasContext 
*ctx, int *is_branch)
             gen_cl(ctx, op1, rd, rs);
             break;
         case OPC_DMULT_G_2F:
+            /* Is Cavium Specific instruction v3mulu? */
+            if ((env->insn_flags & CPU_OCTEON)) {
+                check_mips_64(ctx);
+                gen_LMI(ctx, op1, rs, rt, rd);
+                break;
+            }
         case OPC_DMULTU_G_2F:
         case OPC_DDIV_G_2F:
         case OPC_DDIVU_G_2F:
@@ -11990,6 +12376,31 @@ 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_SEQ:
+        case OPC_SNE:
+            check_mips_64(ctx);
+            check_insn(env, ctx, INSN_OCTEON);
+            gen_set(ctx, op1, rd, rs, rt);
+            break;
+        case OPC_SEQI:
+        case OPC_SNEI:
+            {
+                int16_t imm10;
+                imm10 = (ctx->opcode >> 6) & 0x3ff;
+                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");
@@ -12281,10 +12692,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 INSN_OCTEON */
+    case OPC_LWC2: /* BBIT0 */
+    case OPC_LDC2: /* BBIT032 */
+    case OPC_SWC2: /* BBIT1 */
+    case OPC_SDC2: /* BBIT132 */
+        if (env->insn_flags & INSN_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);
-- 
1.7.3.4




reply via email to

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