From patchwork Sat Oct 22 10:11:12 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Khansa Butt X-Patchwork-Id: 121178 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 30DC9B6FAF for ; Sat, 22 Oct 2011 21:34:25 +1100 (EST) Received: from localhost ([::1]:38835 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RHYNN-000163-SJ for incoming@patchwork.ozlabs.org; Sat, 22 Oct 2011 06:00:25 -0400 Received: from eggs.gnu.org ([140.186.70.92]:47228) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RHYN5-0000q1-TG for qemu-devel@nongnu.org; Sat, 22 Oct 2011 06:00:11 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RHYMy-0006i7-Si for qemu-devel@nongnu.org; Sat, 22 Oct 2011 06:00:07 -0400 Received: from mail-wy0-f173.google.com ([74.125.82.173]:39457) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RHYMy-0006Q2-52 for qemu-devel@nongnu.org; Sat, 22 Oct 2011 06:00:00 -0400 Received: by mail-wy0-f173.google.com with SMTP id 15so5354962wyh.4 for ; Sat, 22 Oct 2011 02:59:59 -0700 (PDT) Received: by 10.216.72.65 with SMTP id s43mr6610743wed.40.1319277599421; Sat, 22 Oct 2011 02:59:59 -0700 (PDT) Received: from localhost.localdomain ([111.68.102.16]) by mx.google.com with ESMTPS id e7sm26686750wbh.12.2011.10.22.02.59.56 (version=TLSv1/SSLv3 cipher=OTHER); Sat, 22 Oct 2011 02:59:59 -0700 (PDT) From: khansa@kics.edu.pk To: qemu-devel@nongnu.org Date: Sat, 22 Oct 2011 15:11:12 +0500 Message-Id: <1319278273-32437-6-git-send-email-khansa@kics.edu.pk> X-Mailer: git-send-email 1.7.3.4 In-Reply-To: <1319278273-32437-1-git-send-email-khansa@kics.edu.pk> References: <1319278273-32437-1-git-send-email-khansa@kics.edu.pk> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 74.125.82.173 Cc: peter.maydell@linaro.org, riku.voipio@iki.fi, Khansa Butt , aurelien@aurel32.net Subject: [Qemu-devel] [PATCH v3 5/6] target-mips: Adding support for Cavium specific instructions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Khansa Butt Signed-off-by: Khansa Butt Signed-off-by: Ehsan Ul Haq Signed-off-by: Abdul Qadeer Signed-off-by: Abdul Waheed --- 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 | 428 ++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 520 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..e57f3fe 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,224 @@ 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); + switch (opc) { + case OPC_SEQ: + tcg_gen_setcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1); + opn = "seq"; + break; + case OPC_SNE: + tcg_gen_setcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1); + 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 +1883,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 +3002,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 +3182,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 +3365,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 +12267,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 +12335,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 +12361,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 +12375,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 +12691,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);