From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=45936 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Q8VzD-00021N-9c for qemu-devel@nongnu.org; Sat, 09 Apr 2011 07:05:55 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Q8Vz9-0005K6-1I for qemu-devel@nongnu.org; Sat, 09 Apr 2011 07:05:51 -0400 Received: from mail-qw0-f45.google.com ([209.85.216.45]:50156) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Q8Vz8-0005Jz-Lt for qemu-devel@nongnu.org; Sat, 09 Apr 2011 07:05:46 -0400 Received: by qwj8 with SMTP id 8so2981904qwj.4 for ; Sat, 09 Apr 2011 04:05:46 -0700 (PDT) MIME-Version: 1.0 Date: Sat, 9 Apr 2011 16:05:45 +0500 Message-ID: From: Khansa Butt Content-Type: multipart/alternative; boundary=00235433362e03106904a07a5388 Subject: [Qemu-devel] [PATCH 2/2] Support for Cavium-Octeon specific instruction List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Aurelien Jarno , Nathan Froyd --00235433362e03106904a07a5388 Content-Type: text/plain; charset=ISO-8859-1 >>From 7fd3ef1360b78ad85848e54e36d97ab50d77e6a6 Mon Sep 17 00:00:00 2001 From: Ehsan-ul-Haq & Khansa Butt Date: Sat, 9 Apr 2011 11:09:18 +0500 Subject: [PATCH 2/2] Support for Cavium-Octeon specific instruction Signed-off-by: Ehsan-ul-Haq, Abdul Qadeer, Abdul Waheed, Khansa Butt < khansa@kics.edu.pk> --- host-utils.c | 14 ++ host-utils.h | 1 + linux-user/elfload.c | 5 + linux-user/main.c | 5 + linux-user/qemu.h | 1 + linux-user/syscall.c | 5 + target-mips/cpu.h | 15 ++ target-mips/helper.h | 5 + target-mips/op_helper.c | 70 ++++++ target-mips/translate.c | 556 ++++++++++++++++++++++++++++++++++++++++++++++- 10 files changed, 666 insertions(+), 11 deletions(-) diff --git a/host-utils.c b/host-utils.c index dc96123..3073ef8 100644 --- a/host-utils.c +++ b/host-utils.c @@ -102,4 +102,18 @@ void muls64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b) a, b, *phigh, *plow); #endif } + #endif /* !defined(__x86_64__) */ +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; + } +} diff --git a/host-utils.h b/host-utils.h index 0ddc176..172c4fd 100644 --- a/host-utils.h +++ b/host-utils.h @@ -46,6 +46,7 @@ static inline void muls64(uint64_t *plow, uint64_t *phigh, void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b); void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b); #endif +void addc(uint64_t res [], uint64_t a, int i); /* Binary search for leading zeros. */ diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 2832a33..9399e44 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1662,6 +1662,11 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, when we load the interpreter. */ elf_ex = *(struct elfhdr *)bprm->buf; +#if defined(TARGET_MIPS64) + if ((elf_ex.e_flags & EF_MIPS_MARCH) == E_MIPS_MACH_OCTEON) { + info->elf_arch = 1; + } +#endif bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p); bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p); bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p); diff --git a/linux-user/main.c b/linux-user/main.c index a7f4955..acf9cac 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -3348,6 +3348,11 @@ int main(int argc, char **argv, char **envp) if (regs->cp0_epc & 1) { env->hflags |= MIPS_HFLAG_M16; } +#if defined(TARGET_MIPS64) + if (info->elf_arch) { + env->TARGET_OCTEON = 1; + } +#endif } #elif defined(TARGET_SH4) { diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 250814d..adef428 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -51,6 +51,7 @@ struct image_info { abi_ulong arg_start; abi_ulong arg_end; int personality; + int elf_arch; #ifdef CONFIG_USE_FDPIC abi_ulong loadmap_addr; uint16_t nsegs; diff --git a/linux-user/syscall.c b/linux-user/syscall.c index bb0999d..d5da0ee 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -7320,6 +7320,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_set_thread_area: #if defined(TARGET_MIPS) ((CPUMIPSState *) cpu_env)->tls_value = arg1; + if (((CPUMIPSState *) cpu_env)->TARGET_OCTEON) { + /* tls entry is moved to k0 so that this can be used later + * currently this thing is tested only for Octeon */ + ((CPUMIPSState *) cpu_env)->active_tc.gpr[26] = arg1; + } ret = 0; break; #elif defined(TARGET_CRIS) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 0b98d10..8ef8afb 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -5,6 +5,11 @@ #define ELF_MACHINE EM_MIPS +/* These flags are used to check whether given + * user mode binary is octeon specific or not */ +#define EF_MIPS_MARCH 0xFF0000 +#define E_MIPS_MACH_OCTEON 0x8B0000 + #define CPUState struct CPUMIPSState #include "config.h" @@ -171,6 +176,15 @@ 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; + /* Octeon specific Coprocessor 0 register */ + target_ulong cvmctl; }; typedef struct CPUMIPSState CPUMIPSState; @@ -178,6 +192,7 @@ struct CPUMIPSState { TCState active_tc; CPUMIPSFPUContext active_fpu; + int TARGET_OCTEON; uint32_t current_tc; uint32_t current_fpu; diff --git a/target-mips/helper.h b/target-mips/helper.h index 297ab64..409c08d 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_3(v3mulu, void, tl, tl, int) +DEF_HELPER_3(vmulu, void, tl, tl, int) +DEF_HELPER_2(dpop, void, tl, i32) #endif +DEF_HELPER_2(pop, void, tl, i32) + 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 bd16ce3..de793ba 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -266,7 +266,77 @@ void helper_dmultu (target_ulong arg1, target_ulong arg2) { mulu64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2); } +void helper_v3mulu (target_ulong arg1, target_ulong arg2, int rd) +{ + 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.gpr[rd] = res[0]; + env->active_tc.P0 = res[1]; + env->active_tc.P1 = res[2]; + env->active_tc.P2 = res[3]; +} +void helper_vmulu (target_ulong arg1, target_ulong arg2, int rd) +{ + 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.gpr[rd] = lo; + env->active_tc.P0 = hi; +} +void helper_dpop (target_ulong arg, uint32_t rd) +{ + uint32_t rem, ones = 0; + while (arg >= 1) { + arg = arg/2; + rem = arg % 2; + if(rem == 1) + ones++; + if(arg == 1) + ones++; + } + env->active_tc.gpr[rd] = ones; +} #endif +void helper_pop (target_ulong arg, uint32_t rd) +{ + uint32_t rem, i, ones = 0; + i = 0; + while(i <= 31) { + arg = arg/2; + rem = arg % 2; + if(rem == 1) + ones++; + if(arg == 1) + ones++; + i++; + } + env->active_tc.gpr[rd] = ones; +} #ifndef CONFIG_USER_ONLY diff --git a/target-mips/translate.c b/target-mips/translate.c index 63c2563..1394e18 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -36,6 +36,14 @@ #define GEN_HELPER 1 #include "helper.h" +#if defined(TARGET_MIPS64) +/* Macros for setting values of cvmctl registers */ +#define FUSE_START_BIT(cvmctl) (cvmctl | 0x80000000) +#define KASUMI(cvmctl) (cvmctl | 0x20000000) +#define IPPCI(cvmctl) (cvmctl | 0x380) +#define IPTI(cvmctl) (cvmctl | 0x70) +#endif + //#define MIPS_DEBUG_DISAS //#define MIPS_DEBUG_SIGN_EXTENSIONS @@ -70,6 +78,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 +278,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 +521,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; @@ -847,6 +885,13 @@ static inline void check_mips_64(DisasContext *ctx) if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) generate_exception(ctx, EXCP_RI); } +/* This code generates a "reserved instruction" exception if Octeon + instructions are not enabled. */ +static inline void check_octeon(DisasContext *ctx, CPUState *env) +{ + if (!env->TARGET_OCTEON) + generate_exception(ctx, EXCP_RI); +} /* Define small wrappers for gen_load_fpr* so that we have a uniform calling interface for 32 and 64-bit FPRs. No sense in changing @@ -1419,7 +1464,33 @@ 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/seton not equal immidiate */ +static void gen_set_imm(CPUState *env, uint32_t opc, int rt, int rs, int16_t imm) +{ + target_ulong uimm; + TCGv t0, t1; + const char *opn = "imm set"; + uimm = (uint16_t)imm; + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + switch (opc) { + case OPC_SEQI: + tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm); + gen_load_gpr(t0, rt); + tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, 1); + opn = "seqi"; + break; + case OPC_SNEI: + tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm); + gen_load_gpr(t0, rt); + gen_load_gpr(t1, 0); + tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rt], t1, t0); + opn = "snei"; + break; + } +} +#endif /* Logic with immediate operand */ static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm) { @@ -1583,7 +1654,86 @@ 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(); + int nomul = env->active_tc.cvmctl & 0x8000000; + if (!nomul) { + switch (opc) { + case OPC_MTM0: + tcg_gen_mov_tl(mpl0, cpu_gpr[rs]); + 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, cpu_gpr[rs]); + 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, cpu_gpr[rs]); + 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, cpu_gpr[rs]); + opn = "mtp0"; + break; + case OPC_MTP1: + tcg_gen_mov_tl(p1, cpu_gpr[rs]); + opn = "mtp1"; + break; + case OPC_MTP2: + tcg_gen_mov_tl(p2, cpu_gpr[rs]); + opn = "mtp2"; + break; + case OPC_VMM0: + gen_load_gpr(t1, rs); + gen_helper_dmultu(t1, mpl0); + gen_load_gpr(t0, rt); + tcg_gen_add_tl(t0, t0, cpu_LO[0]); + tcg_gen_add_tl(t0, t0, p0); + gen_store_gpr(t0, rd); + tcg_gen_mov_tl(mpl0, cpu_gpr[rd]); + 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_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + gen_helper_2i(vmulu, t0, t1, rd); + opn = "vmulu"; + break; + case OPC_V3MULU: + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + gen_helper_2i(v3mulu, t0, t1, rd); + opn = "v3mulu"; + break; + } + + } else { + generate_exception(ctx, EXCP_RI); + } + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +#endif /* Arithmetic */ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, int rd, int rs, int rt) @@ -1637,6 +1787,25 @@ 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(); + TCGv t2 = tcg_temp_new(); + gen_load_gpr(t1, rs); + gen_load_gpr(t2, rt); + tcg_gen_andi_tl(t1, t1, 0xff); + tcg_gen_andi_tl(t2, t2, 0xff); + tcg_gen_add_tl(t0, t1, t2); + tcg_gen_andi_tl(t0, t0, 0xff); + gen_store_gpr(t0, rd); + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); + } + + opn = "baddu"; + break; case OPC_SUB: { TCGv t0 = tcg_temp_local_new(); @@ -2013,7 +2182,70 @@ 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(); + switch (opc) { + case OPC_SEQ: + tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); + gen_load_gpr(t0, rd); + tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rd], t0, 1); + opn = "seq"; + break; + case OPC_SNE: + tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); + gen_load_gpr(t0, rd); + gen_load_gpr(t1, 0); + tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t1, t0); + opn = "sne"; + break; + default: + MIPS_INVAL(opn); + generate_exception(ctx, EXCP_RI); + goto out; + } +out: + tcg_temp_free(t0); + tcg_temp_free(t1); + +} + +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) { @@ -2149,6 +2381,10 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, gen_helper_dmult(t0, t1); opn = "dmult"; break; + case OPC_DMUL: + gen_helper_dmult(t0, t1); + opn = "dmul"; + break; case OPC_DMULTU: gen_helper_dmultu(t0, t1); opn = "dmultu"; @@ -2368,7 +2604,26 @@ 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_1i(dpop, t0, rd); + opn = "dpop"; + break; + case OPC_POP: + gen_helper_1i(pop, 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 +2960,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 +2986,39 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, } btgt = ctx->pc + insn_bytes + offset; break; + case OPC_BBIT1: + gen_load_gpr(t0, rs); + gen_load_gpr(t1, 0); + maskb = 1ULL << rt; + tcg_gen_andi_tl(t0, t0, maskb); + bcond_compute = 1; + btgt = ctx->pc + insn_bytes + offset; + break; + case OPC_BBIT132: + gen_load_gpr(t0, rs); + gen_load_gpr(t1, 0); + maskb = 1ULL << (rt + 32); + tcg_gen_andi_tl(t0, t0, maskb); + bcond_compute = 1; + btgt = ctx->pc + insn_bytes + offset; + break; + case OPC_BBIT0: + gen_load_gpr(t0, rs); + gen_load_gpr(t1, 0); + maskb = 1ULL << rt; + tcg_gen_andi_tl(t0, t0, maskb); + bcond_compute = 1; + btgt = ctx->pc + insn_bytes + offset; + break; + case OPC_BBIT032: + gen_load_gpr(t0, rs); + gen_load_gpr(t1, 0); + 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 +3177,18 @@ 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: + tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1); + goto not_likely; + case OPC_BBIT132: + tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1); + goto not_likely; + case OPC_BBIT0: + tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1); + goto not_likely; + case OPC_BBIT032: + tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1); + 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 +3284,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 +3399,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 +11961,8 @@ 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; + int TARGET_OCTEON = env->TARGET_OCTEON; /* make sure instructions are on a word boundary */ if (ctx->pc & 0x3) { env->CP0_BadVAddr = ctx->pc; @@ -11638,6 +11990,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 +12218,84 @@ 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_insn(env, ctx, ISA_MIPS3); + check_mips_64(ctx); + check_octeon(ctx, env); + gen_muldiv(ctx, op1, rs, rt); + tcg_gen_mov_tl(cpu_gpr[rd], cpu_LO[0]); + break; + case OPC_CINS: + check_insn(env, ctx, ISA_MIPS64R2); + check_mips_64(ctx); + check_octeon(ctx, env); + gen_bitops(ctx, op1, rt, rs, sa, rd); + break; + case OPC_CINS32: + check_mips_64(ctx); + check_octeon(ctx, env); + gen_bitops(ctx, op1, rt, rs, sa, rd); + break; + case OPC_MTM0: + check_mips_64(ctx); + check_octeon(ctx, env); + gen_LMI(env, ctx, op1, rs, rt, rd); + break; + case OPC_MTM1: + check_mips_64(ctx); + check_octeon(ctx, env); + gen_LMI(env, ctx, op1, rs, rt, rd); + break; + case OPC_MTM2: + check_mips_64(ctx); + check_octeon(ctx, env); + gen_LMI(env, ctx, op1, rs, rt, rd); + break; + case OPC_MTP0: + check_mips_64(ctx); + check_octeon(ctx, env); + gen_LMI(env, ctx, op1, rs, rt, rd); + break; + case OPC_MTP1: + check_mips_64(ctx); + check_octeon(ctx, env); + gen_LMI(env, ctx, op1, rs, rt, rd); + break; + case OPC_MTP2: + check_mips_64(ctx); + check_octeon(ctx, env); + gen_LMI(env, ctx, op1, rs, rt, rd); + break; + case OPC_VMULU: + check_mips_64(ctx); + gen_LMI(env, ctx, op1, rs, rt, rd); + break; + case OPC_BADDU: + check_octeon(ctx, env); + gen_arith(env, ctx, op1, rd, rs, rt); + break; + case OPC_EXTS: + check_mips_64(ctx); + check_octeon(ctx, env); + gen_exts(env, ctx, op1, rt, rs, sa, rd); + break; + case OPC_EXTS32: + check_mips_64(ctx); + check_octeon(ctx, env); + gen_exts(env, ctx, op1, rt, rs, sa, rd); + break; + case OPC_SAA: + check_octeon(ctx, env); + gen_saa(env, ctx, op1, rt, rs); + break; + case OPC_SAAD: + check_octeon(ctx, env); + 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 +12315,25 @@ 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 (!TARGET_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); + check_octeon(ctx, env); + gen_LMI(env, ctx, op1, rs, rt, rd); +#endif + } + break; #if defined(TARGET_MIPS64) case OPC_DCLO: case OPC_DCLZ: @@ -11896,7 +12341,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 +12349,46 @@ 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 (!TARGET_OCTEON) { + check_insn(env, ctx, INSN_LOONGSON2F); + gen_loongson_integer(ctx, op1, rd, rs, rt); + } else { + /* Cavium Specific instruction v3mulu */ + check_mips_64(ctx); + check_octeon(ctx, env); + gen_LMI(env, ctx, op1, rs, rt, rd); + } + break; + case OPC_SEQ: + check_mips_64(ctx); + check_octeon(ctx, env); + gen_seqsne(ctx, op1, rd, rs, rt); + break; + case OPC_SNE: + check_mips_64(ctx); + check_octeon(ctx, env); + gen_seqsne(ctx, op1, rd, rs, rt); + break; + case OPC_SEQI: + check_mips_64(ctx); + check_octeon(ctx, env); + gen_set_imm(env, op1, rt, rs, imm10); + break; + case OPC_SNEI: + check_mips_64(ctx); + check_octeon(ctx, env); + gen_set_imm(env, op1, rt, rs, imm10); + break; + case OPC_POP: + check_octeon(ctx, env); + gen_pop_count(ctx, op1, rd, rs); + break; + case OPC_DPOP: + check_mips_64(ctx); + check_octeon(ctx, env); + gen_pop_count(ctx, op1, rd, rs); + break; #endif default: /* Invalid */ MIPS_INVAL("special2"); @@ -12196,10 +12680,32 @@ 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 TARGET_OCTEON is set these opcodes will belong to Cavium */ + case OPC_LWC2: /* BBIT0 */ + if (TARGET_OCTEON) { + gen_compute_branch(ctx, op, 4, rs, rt, imm << 2); + *is_branch = 1; + break; + } + case OPC_LDC2: /* BBIT032 */ + if (TARGET_OCTEON) { + gen_compute_branch(ctx, op, 4, rs, rt, imm << 2); + *is_branch = 1; + break; + } + case OPC_SWC2: /* BBIT1 */ + if (TARGET_OCTEON) { + gen_compute_branch(ctx, op, 4, rs, rt, imm << 2); + *is_branch = 1; + break; + } + case OPC_SDC2: /* BBIT132 */ + if (TARGET_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 +13094,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, @@ -12611,6 +13129,18 @@ static void mips_tcg_init(void) #include "translate_init.c" +#if defined(TARGET_MIPS64) + +static void set_cvmctl_register(CPUMIPSState *env) +{ + env->active_tc.cvmctl = env->active_tc.cvmctl + ^ env->active_tc.cvmctl; + env->active_tc.cvmctl = FUSE_START_BIT(env->active_tc.cvmctl); + env->active_tc.cvmctl = KASUMI(env->active_tc.cvmctl); + env->active_tc.cvmctl = IPPCI(env->active_tc.cvmctl); + env->active_tc.cvmctl = IPTI(env->active_tc.cvmctl); +} +#endif CPUMIPSState *cpu_mips_init (const char *cpu_model) { CPUMIPSState *env; @@ -12623,6 +13153,10 @@ CPUMIPSState *cpu_mips_init (const char *cpu_model) env->cpu_model = def; env->cpu_model_str = cpu_model; +#if defined(TARGET_MIPS64) + /* Function for setting cvmctl register */ + set_cvmctl_register(env); +#endif cpu_exec_init(env); #ifndef CONFIG_USER_ONLY mmu_init(env, def); -- 1.7.3.4 --00235433362e03106904a07a5388 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable
From 7fd3ef1360b78ad85848e54e36d97ab50d77e6a6 Mon Sep 17 00:00:00 2001=
From: Ehsan-ul-Haq & Khansa Butt <khansa@kics.edu.pk>
Date: Sat, 9 Apr 2011 1= 1:09:18 +0500
Subject: [PATCH 2/2] Support for Cavium-Octeon specific instruction


Signed-off-by: Ehsan-ul-Haq, Abdul Qa= deer, Abdul Waheed, Khansa Butt <k= hansa@kics.edu.pk>
---
=A0host-utils.c =A0 =A0 =A0 =A0 =A0 =A0| =A0 14 ++
=
=A0host-utils.h =A0 =A0 =A0 =A0 =A0 =A0| =A0 =A01 +
=A0linux= -user/elfload.c =A0 =A0| =A0 =A05 +
=A0linux-user/main.c =A0 =A0 = =A0 | =A0 =A05 +
=A0linux-user/qemu.h =A0 =A0 =A0 | =A0 =A01 +
=A0linux-user/syscall.c =A0 =A0| =A0 =A05 +
=A0target-mips/c= pu.h =A0 =A0 =A0 | =A0 15 ++
=A0target-mips/helper.h =A0 =A0| =A0= =A05 +
=A0target-mips/op_helper.c | =A0 70 ++++++
=A0t= arget-mips/translate.c | =A0556 +++++++++++++++++++++++++++++++++++++++++++= +++-
=A010 files changed, 666 insertions(+), 11 deletions(-)

=
diff --git a/host-utils.c b/host-utils.c
index dc96123= ..3073ef8 100644
--- a/host-utils.c
+++ b/host-utils.c<= /div>
@@ -102,4 +102,18 @@ void muls64 (uint64_t *plow, uint64_t *phigh, int= 64_t a, int64_t b)
=A0=A0 =A0 =A0 =A0 =A0 =A0a, b, *phigh, *plow)= ;
=A0#endif
=A0}
+
=A0#endif /* !de= fined(__x86_64__) */
+void addc(uint64_t res [], uint64_t a, int i)
+{
= + =A0 =A0uint64_t c =3D res[i];
+ =A0 =A0for (;i < 4;i++) {
+ =A0 =A0 =A0 =A0res[i] =3D c + a;
+ =A0 =A0 =A0 =A0if (r= es[i] < a) {
+ =A0 =A0 =A0 =A0 =A0 =A0c =3D 1;
+ =A0 =A0 =A0 =A0 =A0 =A0a =3D = res[i+1];
+ =A0 =A0 =A0 =A0}
+ =A0 =A0 =A0 =A0else
+ =A0 =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0}
+}
diff --git a/host-utils.h b/host-utils.h
index 0ddc176..172c4fd 100644
--- a/host-utils.h
+++ b/= host-utils.h
@@ -46,6 +46,7 @@ static inline void muls64(uint64_t= *plow, uint64_t *phigh,
=A0void muls64(uint64_t *phigh, uint64_t= *plow, int64_t a, int64_t b);
=A0void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b= );
=A0#endif
+void addc(uint64_t res [], uint64_t a, in= t i);
=A0
=A0/* Binary search for leading zeros. =A0*/<= /div>
=A0
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 2832a33..9399e44 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1662,6 +1662,11 @@ int loa= d_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
=A0=A0 =A0 =A0 =A0when we load the interpreter. =A0*/
=A0=A0= =A0 elf_ex =3D *(struct elfhdr *)bprm->buf;
=A0
+#i= f defined(TARGET_MIPS64)
+ =A0 =A0if ((elf_ex.e_flags & EF_MI= PS_MARCH) =3D=3D E_MIPS_MACH_OCTEON) {
+ =A0 =A0 =A0 =A0info->elf_arch =3D 1;
+ =A0 =A0}
+#endif
=A0=A0 =A0 bprm->p =3D copy_elf_strings(1, &bpr= m->filename, bprm->page, bprm->p);
=A0=A0 =A0 bprm->p= =3D copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p)= ;
=A0=A0 =A0 bprm->p =3D copy_elf_strings(bprm->argc,bprm->argv= ,bprm->page,bprm->p);
diff --git a/linux-user/main.c b/linu= x-user/main.c
index a7f4955..acf9cac 100644
--- a/linux= -user/main.c
+++ b/linux-user/main.c
@@ -3348,6 +3348,11 @@ int main(int = argc, char **argv, char **envp)
=A0=A0 =A0 =A0 =A0 if (regs->c= p0_epc & 1) {
=A0=A0 =A0 =A0 =A0 =A0 =A0 env->hflags |=3D = MIPS_HFLAG_M16;
=A0=A0 =A0 =A0 =A0 }
+#if defined(TARGET_MIPS64)
+ =A0 = =A0 =A0 =A0if (info->elf_arch) {
+ =A0 =A0 =A0 =A0 =A0 =A0env-= >TARGET_OCTEON =3D 1;
+ =A0 =A0 =A0 =A0}
+#endif
=A0=A0 =A0 }
=A0#elif defined(TARGET_SH4)
=A0=A0 =A0 {
diff --git a/linux-user/qemu.h b/linux-user/qem= u.h
index 250814d..adef428 100644
--- a/linux-user/qemu= .h
+++ b/linux-user/qemu.h
@@ -51,6 +51,7 @@ struct ima= ge_info {
=A0=A0 =A0 =A0 =A0 abi_ulong =A0 =A0 =A0 arg_start;
=A0=A0 = =A0 =A0 =A0 abi_ulong =A0 =A0 =A0 arg_end;
=A0 int personality;
+ int<= span class=3D"Apple-tab-span" style=3D"white-space:pre"> elf_arch;<= /div>
=A0#ifdef CONFIG_USE_FDPIC
=A0=A0 =A0 =A0 =A0 abi_ulong= =A0 =A0 =A0 loadmap_addr;
=A0=A0 =A0 =A0 =A0 uint16_t =A0 =A0 =A0 =A0nsegs;
diff --git= a/linux-user/syscall.c b/linux-user/syscall.c
index bb0999d..d5d= a0ee 100644
--- a/linux-user/syscall.c
+++ b/linux-user= /syscall.c
@@ -7320,6 +7320,11 @@ abi_long do_syscall(void *cpu_env, int num, abi= _long arg1,
=A0=A0 =A0 case TARGET_NR_set_thread_area:
= =A0#if defined(TARGET_MIPS)
=A0=A0 =A0 =A0 ((CPUMIPSState *) cpu_= env)->tls_value =3D arg1;
+ =A0 =A0 =A0if (((CPUMIPSState *) cpu_env)->TARGET_OCTEON) {
=
+ =A0 =A0 =A0 =A0 =A0/* tls entry is moved to k0 so that this can be u= sed later
+ =A0 =A0 =A0 =A0 =A0 * currently this thing is tested = only for Octeon */
+ =A0 =A0 =A0 =A0 =A0((CPUMIPSState *) cpu_env)->active_tc.gpr[26] = =3D arg1;
+ =A0 =A0 =A0}
=A0=A0 =A0 =A0 ret =3D 0;
=A0=A0 =A0 =A0 break;
=A0#elif defined(TARGET_CRIS)
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 0b98d10..8ef8afb 100644
--- a/target-mips/cpu.h
<= div>+++ b/target-mips/cpu.h
@@ -5,6 +5,11 @@
=A0
<= div>=A0#define ELF_MACHINE EM_MIPS
=A0
+/* These flags are used to check whether given
+ * user mode binary is octeon specific or not */
+#define EF_M= IPS_MARCH 0xFF0000
+#define E_MIPS_MACH_OCTEON 0x8B0000
+
=A0#define CPUState struct CPUMIPSState
=A0
=A0#include "config.h"
@@ -171,6 +176,15 @@ struct TCS= tate {
=A0=A0 =A0 target_ulong CP0_TCSchedule;
=A0=A0 = =A0 target_ulong CP0_TCScheFBack;
=A0=A0 =A0 int32_t CP0_Debug_tcstatus;
+ =A0 =A0/* Multiplie= r registers for Octeon */
+ =A0 =A0target_ulong MPL0;
+= =A0 =A0target_ulong MPL1;
+ =A0 =A0target_ulong MPL2;
= + =A0 =A0target_ulong P0;
+ =A0 =A0target_ulong P1;
+ =A0 =A0target_ulong P2;
+ =A0 =A0/* Octeon specific Coprocessor 0 register */
+ =A0 =A0= target_ulong cvmctl;
=A0};
=A0
=A0typedef str= uct CPUMIPSState CPUMIPSState;
@@ -178,6 +192,7 @@ struct CPUMIPSState {
=A0=A0 =A0 TCState= active_tc;
=A0=A0 =A0 CPUMIPSFPUContext active_fpu;
= =A0
+ =A0 =A0int TARGET_OCTEON;
=A0=A0 =A0 uint32_t cur= rent_tc;
=A0=A0 =A0 uint32_t current_fpu;
=A0
diff --git a/target-mips/helper.h b/target-mips/helper.h=
index 297ab64..409c08d 100644
--- a/target-mips/helper= .h
+++ b/target-mips/helper.h
@@ -8,7 +8,12 @@ DEF_HELP= ER_3(ldl, tl, tl, tl, int)
=A0DEF_HELPER_3(ldr, tl, tl, tl, int)
=A0DEF_HELPER_3(sdl, v= oid, tl, tl, int)
=A0DEF_HELPER_3(sdr, void, tl, tl, int)
+DEF_HELPER_3(v3mulu, void, tl, tl, int)
+DEF_HELPER_3(vmulu, = void, tl, tl, int)
+DEF_HELPER_2(dpop, void, tl, i32)
=A0#endif
+DEF_= HELPER_2(pop, void, tl, i32)
+
=A0DEF_HELPER_3(lwl, tl,= tl, tl, int)
=A0DEF_HELPER_3(lwr, tl, tl, tl, int)
=A0= DEF_HELPER_3(swl, void, tl, tl, int)
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index bd16ce3..de793ba 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -266,7 +266,77 @@ void h= elper_dmultu (target_ulong arg1, target_ulong arg2)
=A0{
=A0=A0 =A0 mulu64(&(env->active_tc.LO[0]), &= (env->active_tc.HI[0]), arg1, arg2);
=A0}
+void help= er_v3mulu (target_ulong arg1, target_ulong arg2, int rd)
+{
=
+ =A0 =A0uint64_t hi, lo, res[4];
+ =A0 =A0int i;
+ =A0 =A0for (i =3D 0;i < 4; i++) {
=
+ =A0 =A0 =A0 =A0res[i] =3D 0;
+ =A0 =A0}
+ =A0 = =A0mulu64(&res[0], &res[1], env->active_tc.MPL0, arg1);
+ =A0 =A0mulu64(&lo, &hi, env->active_tc.MPL1, arg1);
+ =A0 =A0res[1] =3D res[1] + lo;
+ =A0 =A0if (res[1] < lo= )
+ =A0 =A0 =A0 =A0res[2]++;
+ =A0 =A0res[2] =3D res[2]= + hi;
+ =A0 =A0if (res[2] < hi)
+ =A0 =A0 =A0 =A0re= s[3]++;
+ =A0 =A0mulu64(&lo, &hi, env->active_tc.MPL2,= arg1);
+ =A0 =A0res[2] =3D res[2] + lo;
+ =A0 =A0if (res[2] < lo= )
+ =A0 =A0 =A0 =A0res[3]++;
+ =A0 =A0res[3] =3D res[3]= + hi;
+ =A0 =A0addc(res, arg2, 0);
+ =A0 =A0addc(res, = env->active_tc.P0, 0);
+ =A0 =A0addc(res, env->active_tc.P1, 1);
+ =A0 =A0addc(r= es, env->active_tc.P2, 2);
+ =A0 =A0env->active_tc.gpr[rd] = =3D res[0];
+ =A0 =A0env->active_tc.P0 =3D res[1];
+= =A0 =A0env->active_tc.P1 =3D res[2];
+ =A0 =A0env->active_tc.P2 =3D res[3];
+}
+void= helper_vmulu (target_ulong arg1, target_ulong arg2, int rd)
+{
+ = uint64_t hi, lo;
+ mulu= 64(&lo, &hi, env->active_tc.MPL0, arg1);
+ lo =3D lo + arg2;
+ if (lo &l= t; arg2)
+ hi++;
+ lo =3D lo + env->active_tc.P0;
+ if (= lo < env->active_tc.P0)
+ hi++;
+ env->active_tc.gpr[rd] =3D lo;
+ env-= >active_tc.P0 =3D hi;
+}
+void helper_dpop (target_u= long arg, uint32_t rd)
+{
+ =A0 =A0uint32_t rem, ones = =3D 0;
+ =A0 =A0while (arg >=3D 1) {
+ =A0 =A0 =A0 =A0arg =3D ar= g/2;
+ =A0 =A0 =A0 =A0rem =3D arg % 2;
+ =A0 =A0 =A0 = =A0if(rem =3D=3D 1)
+ =A0 =A0 =A0 =A0 =A0 =A0ones++;
+ = =A0 =A0 =A0 =A0if(arg =3D=3D 1)
+ =A0 =A0 =A0 =A0 =A0 =A0ones++;<= /div>
+ =A0 =A0}
+ =A0 =A0env->active_tc.gpr[rd] =3D ones;
+}
=A0#endif
+void helper_pop (target_ulong arg, = uint32_t rd)
+{
+ =A0 =A0uint32_t rem, i, ones =3D 0;
+ =A0 =A0i =3D 0;
+ =A0 =A0while(i <=3D 31) {
+ =A0 =A0 =A0 =A0arg =3D arg/= 2;
+ =A0 =A0 =A0 =A0rem =3D arg % 2;
+ =A0 =A0 =A0 =A0i= f(rem =3D=3D 1)
+ =A0 =A0 =A0 =A0 =A0 =A0ones++;
+ =A0 = =A0 =A0 =A0if(arg =3D=3D 1)
+ =A0 =A0 =A0 =A0 =A0 =A0ones++;
+ =A0 =A0 =A0 =A0i++;
+ =A0 =A0}
+ =A0 =A0env->= active_tc.gpr[rd] =3D ones;
+}
=A0
=A0#ifndef= CONFIG_USER_ONLY
=A0
diff --git a/target-mips/translat= e.c b/target-mips/translate.c
index 63c2563..1394e18 100644
--- a/target-mips/translate.c<= /div>
+++ b/target-mips/translate.c
@@ -36,6 +36,14 @@
<= div>=A0#define GEN_HELPER 1
=A0#include "helper.h"
=A0
+#if defined(TARGET_MIPS64)
+/* Macros for set= ting values of cvmctl registers */
+#define FUSE_START_BIT(cvmctl= ) =A0(cvmctl | 0x80000000)
+#define KASUMI(cvmctl) =A0(cvmctl | 0= x20000000)
+#define IPPCI(cvmctl) =A0(cvmctl | 0x380)
+#define IPTI(cvm= ctl) =A0(cvmctl | 0x70)
+#endif
+
=A0//#defin= e MIPS_DEBUG_DISAS
=A0//#define MIPS_DEBUG_SIGN_EXTENSIONS
<= div> =A0
@@ -70,6 +78,11 @@ enum {
=A0=A0 =A0 OPC_JAL =A0 = =A0 =A0=3D (0x03 << 26),
=A0=A0 =A0 OPC_JALS =A0 =A0 =3D OP= C_JAL | 0x5,
=A0=A0 =A0 OPC_BEQ =A0 =A0 =A0=3D (0x04 << 26)= , =A0/* Unconditional if rs =3D rt =3D 0 (B) */
+ =A0 =A0/* Cavium Specific */
+ =A0 =A0OPC_BBIT1 =A0 =A0=3D= (0x3a << 26), =A0/* jump on bit set, cavium specific */
+ = =A0 =A0OPC_BBIT132 =A0=3D (0x3e << 26), =A0/* jump on bit set(for upp= er 32 bits) */
+ =A0 =A0OPC_BBIT0 =A0 =A0=3D (0x32 << 26), =A0/* jump on bit clear, = cavium specific */
+ =A0 =A0OPC_BBIT032 =A0=3D (0x36 << 26)= , =A0/* jump on bit clear(for upper 32 bits) */
=A0=A0 =A0 OPC_BE= QL =A0 =A0 =3D (0x14 << 26),
=A0=A0 =A0 OPC_BNE =A0 =A0 =A0=3D (0x05 << 26),
=A0=A0= =A0 OPC_BNEL =A0 =A0 =3D (0x15 << 26),
@@ -265,6 +278,31 @= @ enum {
=A0=A0 =A0 OPC_MADD =A0 =A0 =3D 0x00 | OPC_SPECIAL2,
=A0=A0 =A0 OPC_MADDU =A0 =A0=3D 0x01 | OPC_SPECIAL2,
=A0=A0 =A0 OPC_MUL =A0 =A0 =A0=3D 0x02 | OPC_SPECIAL2,
+ =A0= =A0/* Cavium Specific Instructions */
+ =A0 =A0OPC_BADDU =A0 =A0= =3D 0x28 | OPC_SPECIAL2,
+ =A0 =A0OPC_DMUL =A0 =A0 =3D 0x03 | OPC= _SPECIAL2,
+ =A0 =A0OPC_EXTS =A0 =A0 =3D 0x3a | OPC_SPECIAL2,
+ =A0 =A0OPC_EXTS32 =A0 =3D 0x3b | OPC_SPECIAL2,
+ =A0 =A0OP= C_CINS =A0 =A0 =3D 0x32 | OPC_SPECIAL2,
+ =A0 =A0OPC_CINS32 =A0 = =3D 0x33 | OPC_SPECIAL2,
+ =A0 =A0OPC_SEQI =A0 =A0 =3D 0x2e | OPC= _SPECIAL2,
+ =A0 =A0OPC_SNEI =A0 =A0 =3D 0x2f | OPC_SPECIAL2,
+ =A0 =A0OPC_MTM0 =A0 =A0 =3D 0x08 | OPC_SPECIAL2,
+ =A0 =A0= OPC_MTM1 =A0 =A0 =3D 0x0c | OPC_SPECIAL2,
+ =A0 =A0OPC_MTM2 =A0 = =A0 =3D 0x0d | OPC_SPECIAL2,
+ =A0 =A0OPC_MTP0 =A0 =A0 =3D 0x09 |= OPC_SPECIAL2,
+ =A0 =A0OPC_MTP1 =A0 =A0 =3D 0x0a | OPC_SPECIAL2,=
+ =A0 =A0OPC_MTP2 =A0 =A0 =3D 0x0b | OPC_SPECIAL2,
+ =A0 =A0= OPC_V3MULU =A0 =3D 0x11 | OPC_SPECIAL2,
+ =A0 =A0OPC_VMM0 =A0 =A0= =3D 0x10 | OPC_SPECIAL2,
+ =A0 =A0OPC_VMULU =A0 =A0=3D 0x0f | OP= C_SPECIAL2,
+ =A0 =A0OPC_POP =A0 =A0 =A0=3D 0X2C | OPC_SPECIAL2,<= /div>
+ =A0 =A0OPC_DPOP =A0 =A0 =3D 0X2D | OPC_SPECIAL2,
+ =A0 =A0= OPC_SEQ =A0 =A0 =A0=3D 0x2a | OPC_SPECIAL2,
+ =A0 =A0OPC_SNE =A0 = =A0 =A0=3D 0x2b | OPC_SPECIAL2,
+ =A0 =A0OPC_SAA =A0 =A0 =A0=3D 0= x18 | OPC_SPECIAL2,
+ =A0 =A0OPC_SAAD =A0 =A0 =3D 0x19 | OPC_SPEC= IAL2,
+/**************************************/
=A0=A0 =A0 OPC_MSU= B =A0 =A0 =3D 0x04 | OPC_SPECIAL2,
=A0=A0 =A0 OPC_MSUBU =A0 =A0= =3D 0x05 | OPC_SPECIAL2,
=A0=A0 =A0 /* Loongson 2F */
@= @ -483,7 +521,7 @@ enum {
=A0static TCGv_ptr cpu_env;
=A0static TCGv cpu_gpr[32], cpu_= PC;
=A0static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cp= u_ACX[MIPS_DSP_ACC];
-static TCGv cpu_dspctrl, btarget, bcond;
+static TCGv cpu_dspctrl, btarget, bcond, mpl0, mpl1, mpl2, p0, p1, p2= ;
=A0static TCGv_i32 hflags;
=A0static TCGv_i32 fpu_fcr= 0, fpu_fcr31;
=A0
@@ -847,6 +885,13 @@ static inline vo= id check_mips_64(DisasContext *ctx)
=A0=A0 =A0 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
<= div>=A0=A0 =A0 =A0 =A0 generate_exception(ctx, EXCP_RI);
=A0}
+/* This code generates a "reserved instruction" exception= if Octeon
+ =A0 instructions are not enabled. */
+static inline void c= heck_octeon(DisasContext *ctx, CPUState *env)
+{
+ =A0 = =A0if (!env->TARGET_OCTEON)
+ =A0 =A0 =A0 =A0generate_exceptio= n(ctx, EXCP_RI);
+}
=A0
=A0/* Define small wrappers for gen_load_fp= r* so that we have a uniform
=A0=A0 =A0calling interface for 32 a= nd 64-bit FPRs. =A0No sense in changing
@@ -1419,7 +1464,33 @@ st= atic void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
=A0=A0 =A0 (void)opn; /* avoid a compiler warning */
=A0=A0 = =A0 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], re= gnames[rs], uimm);
=A0}
-
+#if defined(TARGET= _MIPS64)
+/* set on equal immidiate/seton not equal immidiate */
+sta= tic void gen_set_imm(CPUState *env, uint32_t opc, int rt, int rs, int16_t i= mm)
+{
+ =A0 =A0target_ulong uimm;
+ =A0 =A0T= CGv t0, t1;
+ =A0 =A0const char *opn =3D "imm set";
+ =A0 =A0u= imm =3D (uint16_t)imm;
+ =A0 =A0t0 =3D tcg_temp_new();
= + =A0 =A0t1 =3D tcg_temp_new();
+ =A0 =A0switch (opc) {
+ =A0 =A0case OPC_SEQI:
+ =A0 =A0 =A0 =A0tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
+ =A0 =A0 =A0 =A0gen_load_gpr(t0, rt);
+ =A0 =A0 =A0 =A0tcg= _gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, 1);
+ =A0 =A0 =A0= =A0opn =3D "seqi";
+ =A0 =A0 =A0 =A0break;
+ =A0 =A0case OPC_SNEI:
+ = =A0 =A0 =A0 =A0tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
+= =A0 =A0 =A0 =A0gen_load_gpr(t0, rt);
+ =A0 =A0 =A0 =A0gen_load_g= pr(t1, 0);
+ =A0 =A0 =A0 =A0tcg_gen_setcond_tl(TCG_COND_LTU, cpu_= gpr[rt], t1, t0);
+ =A0 =A0 =A0 =A0opn =3D "snei";
+ =A0 =A0 =A0 =A0= break;
+ =A0 =A0}
+}
+#endif
=A0/* = Logic with immediate operand */
=A0static void gen_logic_imm (CPU= State *env, uint32_t opc, int rt, int rs, int16_t imm)
=A0{
@@ -1583,7 +1654,86 @@ static void gen_shift_imm(CPUSta= te *env, DisasContext *ctx, uint32_t opc,
=A0=A0 =A0 MIPS_DEBUG(&= quot;%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm= );
=A0=A0 =A0 tcg_temp_free(t0);
=A0}
+#if defined(TA= RGET_MIPS64)
+static void gen_LMI (CPUMIPSState *env, DisasContex= t *ctx, uint32_t opc,
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 int rs, int rt, int= rd)
+{
+ =A0 =A0const char *opn =3D "LMI";
+= =A0 =A0TCGv t0, t1;
+ =A0 =A0t0 =3D tcg_temp_new();
+ = =A0 =A0t1 =3D tcg_temp_new();
+ =A0 =A0int nomul =3D env->acti= ve_tc.cvmctl & 0x8000000;
+ =A0 =A0if (!nomul) {
+ =A0 =A0 =A0 =A0switch (opc) {
=
+ =A0 =A0 =A0 =A0case OPC_MTM0:
+ =A0 =A0 =A0 =A0 =A0 =A0tcg= _gen_mov_tl(mpl0, cpu_gpr[rs]);
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_= movi_tl(p0, 0);
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_movi_tl(p1, 0);<= /div>
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_movi_tl(p2, 0);
+ =A0 =A0 = =A0 =A0 =A0 =A0opn =3D "mtm0";
+ =A0 =A0 =A0 =A0 =A0 = =A0break;
+ =A0 =A0 =A0 =A0case OPC_MTM1:
+ =A0 =A0 =A0= =A0 =A0 =A0tcg_gen_mov_tl(mpl1, cpu_gpr[rs]);
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_movi_tl(p0, 0);
+ =A0 =A0 =A0 = =A0 =A0 =A0tcg_gen_movi_tl(p1, 0);
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_g= en_movi_tl(p2, 0);
+ =A0 =A0 =A0 =A0 =A0 =A0opn =3D "mtm1&qu= ot;;
+ =A0 =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0c= ase OPC_MTM2:
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_mov_tl(mpl2, cpu_gpr[rs]);
= + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_movi_tl(p0, 0);
+ =A0 =A0 =A0 = =A0 =A0 =A0tcg_gen_movi_tl(p1, 0);
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_g= en_movi_tl(p2, 0);
+ =A0 =A0 =A0 =A0 =A0 =A0opn =3D "mtm2&qu= ot;;
+ =A0 =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_MT= P0:
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_mov_tl(p0, cpu_gpr[rs]);
+ =A0 =A0 =A0 =A0 =A0 =A0opn =3D "mtp0";
+ =A0 = =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_MTP1:
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_mov_tl(p1, cpu_gpr[rs]);
+ = =A0 =A0 =A0 =A0 =A0 =A0opn =3D "mtp1";
+ =A0 =A0 =A0 = =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_MTP2:
+ =A0= =A0 =A0 =A0 =A0 =A0tcg_gen_mov_tl(p2, cpu_gpr[rs]);
+ =A0 =A0 =A0 =A0 =A0 =A0opn =3D "mtp2";
+ =A0 =A0= =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_VMM0:
= + =A0 =A0 =A0 =A0 =A0 =A0gen_load_gpr(t1, rs);
+ =A0 =A0 =A0 =A0 = =A0 =A0gen_helper_dmultu(t1, mpl0);
+ =A0 =A0 =A0 =A0 =A0 =A0gen_= load_gpr(t0, rt);
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_add_tl(t0, t0, cpu_LO[0]);
= + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_add_tl(t0, t0, p0);
+ =A0 =A0 = =A0 =A0 =A0 =A0gen_store_gpr(t0, rd);
+ =A0 =A0 =A0 =A0 =A0 =A0tc= g_gen_mov_tl(mpl0, cpu_gpr[rd]);
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_gen= _movi_tl(p0, 0);
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_movi_tl(p1, 0);
+ =A0 =A0 = =A0 =A0 =A0 =A0tcg_gen_movi_tl(p2, 0);
+ =A0 =A0 =A0 =A0 =A0 =A0o= pn =3D "vmm0";
+ =A0 =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_VMULU:
+ =A0 =A0 =A0 =A0 gen_load_gpr(t0, rs);=
+ =A0 =A0 =A0 =A0 =A0 =A0gen_load_gpr(t1, rt);
+ =A0 =A0 =A0= =A0 =A0 =A0gen_helper_2i(vmulu, t0, t1, rd);
+ =A0 =A0 =A0 =A0 = =A0 =A0opn =3D "vmulu";
+ =A0 =A0 =A0 =A0 =A0 =A0break;=
+ =A0 =A0 =A0 =A0case OPC_V3MULU:
+ =A0 =A0 =A0 =A0 =A0 =A0gen_load_gpr(t0, rs);
+ =A0 =A0 =A0 =A0 = =A0 =A0gen_load_gpr(t1, rt);
+ =A0 =A0 =A0 =A0 =A0 =A0gen_helper_= 2i(v3mulu, t0, t1, rd);
+ =A0 =A0 =A0 =A0 =A0 =A0opn =3D "v3= mulu";
+ =A0 =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0}
+
+ =A0 =A0} else {
+= =A0 =A0 =A0 =A0generate_exception(ctx, EXCP_RI);
+ =A0 =A0}
+ =A0 =A0tcg_temp_free(t0);
+ =A0 =A0tcg_temp_free(t1);
+}
+
=A0
+#endif
=A0/* Arithmetic */
=A0static voi= d gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
=A0= =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0int rd, int rs, int rt)
@@ -1637,6 +1787,25 @@ static void gen_arith (CPUState *env, DisasCon= text *ctx, uint32_t opc,
=A0=A0 =A0 =A0 =A0 }
=A0=A0 =A0 =A0 =A0 opn =3D "addu&q= uot;;
=A0=A0 =A0 =A0 =A0 break;
+ =A0 =A0case OPC_BADDU= :
+ =A0 =A0 =A0 =A0{
+ =A0 =A0 =A0 =A0 =A0 =A0TCGv t0 = =3D tcg_temp_new();
+ =A0 =A0 =A0 =A0 =A0 =A0TCGv t1 =3D tcg_temp= _new();
+ =A0 =A0 =A0 =A0 =A0 =A0TCGv t2 =3D tcg_temp_new();
+ =A0 = =A0 =A0 =A0 =A0 =A0gen_load_gpr(t1, rs);
+ =A0 =A0 =A0 =A0 =A0 = =A0gen_load_gpr(t2, rt);
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_andi_tl= (t1, t1, 0xff);
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_andi_tl(t2, t2, = 0xff);
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_add_tl(t0, t1, t2);
+ =A0 = =A0 =A0 =A0 =A0 =A0tcg_gen_andi_tl(t0, t0, 0xff);
+ =A0 =A0 =A0 = =A0 =A0 =A0gen_store_gpr(t0, rd);
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_te= mp_free(t0);
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_temp_free(t1);
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_temp_free(t2);
+ =A0 =A0 =A0 = =A0}
+
+ =A0 =A0 =A0 opn =3D "baddu";
+ =A0 =A0 =A0 break;
=A0=A0 =A0 case OPC_SUB:
=A0=A0= =A0 =A0 =A0 {
=A0=A0 =A0 =A0 =A0 =A0 =A0 TCGv t0 =3D tcg_temp_lo= cal_new();
@@ -2013,7 +2182,70 @@ static void gen_HILO (DisasContext *ctx, uint32= _t opc, int reg)
=A0=A0 =A0 (void)opn; /* avoid a compiler warnin= g */
=A0=A0 =A0 MIPS_DEBUG("%s %s", opn, regnames[reg])= ;
=A0}
+#if defined(TARGET_MIPS64)
+static void gen_seqsn= e (DisasContext *ctx, uint32_t opc,
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0= =A0 =A0 =A0 =A0 =A0int rd, int rs, int rt)
+{
+ =A0 = =A0const char *opn =3D "seq/sne";
+ =A0 =A0TCGv t0, t1;
+ =A0 =A0t0 =3D tcg_temp_new();
<= div>+ =A0 =A0t1 =3D tcg_temp_new();
+ =A0 =A0switch (opc) {
=
+ =A0 =A0case OPC_SEQ:
+ =A0 =A0 =A0 =A0tcg_gen_xor_tl(cpu_g= pr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ =A0 =A0 =A0 =A0gen_load_gpr(t0, rd);
+ =A0 =A0 =A0 =A0tcg_= gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rd], t0, 1);
+ =A0 =A0 =A0 = =A0opn =3D "seq";
+ =A0 =A0 =A0 =A0break;
+ = =A0 =A0case OPC_SNE:
+ =A0 =A0 =A0 =A0tcg_gen_xor_tl(cpu_gpr[rd],= cpu_gpr[rs], cpu_gpr[rt]);
+ =A0 =A0 =A0 =A0gen_load_gpr(t0, rd);
+ =A0 =A0 =A0 =A0gen_= load_gpr(t1, 0);
+ =A0 =A0 =A0 =A0tcg_gen_setcond_tl(TCG_COND_LTU= , cpu_gpr[rd], t1, t0);
+ =A0 =A0 =A0 =A0opn =3D "sne";=
+ =A0 =A0 =A0 =A0break;
+ =A0 =A0default:
+ =A0 =A0 =A0 =A0MIPS_INVAL(opn);
+ =A0 =A0 =A0 =A0generate_exception(ctx, EXCP_RI);
+ =A0 =A0 = =A0 =A0goto out;
+ =A0 =A0}
+out:
+ =A0 =A0 = =A0 =A0tcg_temp_free(t0);
+ =A0 =A0 =A0 =A0tcg_temp_free(t1);
+
+}
+
+static void gen_saa (CPUState *e= nv, DisasContext *ctx, uint32_t opc,
+ =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 int rt, int base)
+{
+ =A0 =A0const cha= r *opn =3D "saa";
+ =A0 =A0TCGv t0, t1, temp;
+ =A0 =A0t0 =3D tcg_temp_new();<= /div>
+ =A0 =A0t1 =3D tcg_temp_new();
+ =A0 =A0temp =3D tcg_t= emp_new();
+ =A0 =A0gen_load_gpr(t1, rt);
+ =A0 =A0gen_= base_offset_addr(ctx, t0, base, 0);
+ =A0 =A0switch (opc) {
+ =A0 =A0case OPC_SAA:
+ = =A0 =A0 =A0 =A0save_cpu_state(ctx, 1);
+ =A0 =A0 =A0 =A0op_ld_lw(= temp, t0, ctx);
+ =A0 =A0 =A0 =A0tcg_gen_add_tl(temp, temp, t1);<= /div>
+ =A0 =A0 =A0 =A0op_st_sw(temp, t0, ctx);
+ =A0 =A0 =A0 =A0opn =3D "saa";
+ =A0 =A0 =A0 =A0b= reak;
+ =A0 =A0case OPC_SAAD:
+ =A0 =A0 =A0 =A0save_cpu= _state(ctx, 0);
+ =A0 =A0 =A0 =A0op_ld_ld(temp, t0, ctx);
+ =A0 =A0 =A0 =A0tcg_gen_add_tl(temp, temp, t1);
+ =A0 =A0 =A0 =A0op_st_sd(temp, t0, ctx);
+ =A0 =A0 =A0 =A0o= pn =3D "saad";
+ =A0 =A0 =A0 =A0break;
+ =A0 = =A0}
=A0
+ =A0 =A0tcg_temp_free(t0);
+ =A0 = =A0tcg_temp_free(t1);
+}
+#endif
=A0static void gen_muldiv (DisasContext *ctx, uint32= _t opc,
=A0=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 int rs= , int rt)
=A0{
@@ -2149,6 +2381,10 @@ static void gen_m= uldiv (DisasContext *ctx, uint32_t opc,
=A0=A0 =A0 =A0 =A0 gen_helper_dmult(t0, t1);
=A0=A0 =A0 =A0 = =A0 opn =3D "dmult";
=A0=A0 =A0 =A0 =A0 break;
+ =A0 =A0case OPC_DMUL:
+ =A0 =A0 =A0 =A0gen_helper_dmult(t0, t= 1);
+ =A0 =A0 =A0 =A0opn =3D "dmul";
+ =A0 =A0 =A0 =A0break;
=A0=A0 =A0 case OPC_DMULTU:
=A0=A0 =A0 =A0 =A0 gen_helper_dmultu(t0, t1);
=A0=A0 =A0 =A0 = =A0 opn =3D "dmultu";
@@ -2368,7 +2604,26 @@ static voi= d gen_cl (DisasContext *ctx, uint32_t opc,
=A0=A0 =A0 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnam= es[rs]);
=A0=A0 =A0 tcg_temp_free(t0);
=A0}
-=
+#if defined(TARGET_MIPS64)
+static void gen_pop_count= (DisasContext *ctx, uint32_t opc, int rd, int rs)
+{
+ =A0 =A0const char *opn =3D "pop";
+= =A0 =A0 =A0 =A0TCGv t0;
+ =A0 =A0 =A0 =A0t0 =3D tcg_temp_new();<= /div>
+ =A0 =A0 =A0 =A0gen_load_gpr(t0, rs);
+ =A0 =A0 =A0 = =A0switch (opc) {
+ =A0 =A0 =A0 =A0case OPC_DPOP:
+ =A0 =A0 =A0 =A0 =A0 =A0gen_helper_1i(dpop, t0, rd);
+ =A0 = =A0 =A0 =A0 =A0 =A0opn =3D "dpop";
+ =A0 =A0 =A0 =A0 = =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_POP:
+ =A0 =A0 = =A0 =A0 =A0 =A0gen_helper_1i(pop, t0, rd);
+ =A0 =A0 =A0 =A0 =A0 = =A0opn =3D "pop";
+ =A0 =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0}
+ =A0 =A0 =A0 =A0tcg_temp_free(t0);
+}
+#endif
=A0/* Godson integer instructions */
=A0static void gen_loongs= on_integer (DisasContext *ctx, uint32_t opc,
=A0=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 int= rd, int rs, int rt)
@@ -2705,6 +2960,7 @@ static void gen_comput= e_branch (DisasContext *ctx, uint32_t opc,
=A0=A0 =A0 target_ulon= g btgt =3D -1;
=A0=A0 =A0 int blink =3D 0;
=A0=A0 =A0 int bcond_compute =3D 0;
+ =A0 =A0target_ulong ma= skb; /* Used in BBIT0 and BBIT1 */
=A0=A0 =A0 TCGv t0 =3D tcg_tem= p_new();
=A0=A0 =A0 TCGv t1 =3D tcg_temp_new();
=A0
@@ -2730,6 +2986,39 @@ static void gen_compute_branch (DisasContext = *ctx, uint32_t opc,
=A0=A0 =A0 =A0 =A0 }
=A0=A0 =A0 =A0 =A0 btgt =3D ctx->pc = + insn_bytes + offset;
=A0=A0 =A0 =A0 =A0 break;
+ =A0 = =A0case OPC_BBIT1:
+ =A0 =A0 =A0 =A0gen_load_gpr(t0, rs);
+ =A0 =A0 =A0 =A0gen_load_gpr(t1, 0);
+ =A0 =A0 =A0 =A0maskb =3D 1ULL << rt;
+ =A0 =A0 =A0 =A0tcg= _gen_andi_tl(t0, t0, maskb);
+ =A0 =A0 =A0 =A0bcond_compute =3D 1= ;
+ =A0 =A0 =A0 =A0btgt =3D ctx->pc + insn_bytes + offset;
+ =A0 =A0 =A0 =A0break;
+ =A0 =A0case OPC_BBIT132:
+ =A0 =A0 =A0 =A0gen_load_gpr(t0, rs);
+ =A0 =A0 =A0 =A0gen_= load_gpr(t1, 0);
+ =A0 =A0 =A0 =A0maskb =3D 1ULL << (rt + 3= 2);
+ =A0 =A0 =A0 =A0tcg_gen_andi_tl(t0, t0, maskb);
+ = =A0 =A0 =A0 =A0bcond_compute =3D 1;
+ =A0 =A0 =A0 =A0btgt =3D ctx->pc + insn_bytes + offset;
= + =A0 =A0 =A0 =A0break;
+ =A0 =A0case OPC_BBIT0:
+ =A0 = =A0 =A0 =A0gen_load_gpr(t0, rs);
+ =A0 =A0 =A0 =A0gen_load_gpr(t1= , 0);
+ =A0 =A0 =A0 =A0maskb =3D 1ULL << rt;
+ =A0 =A0 =A0 =A0tcg_gen_andi_tl(t0, t0, maskb);
+ =A0 =A0 = =A0 =A0bcond_compute =3D 1;
+ =A0 =A0 =A0 =A0btgt =3D ctx->pc = + insn_bytes + offset;
+ =A0 =A0 =A0 =A0break;
+ =A0 = =A0case OPC_BBIT032:
+ =A0 =A0 =A0 =A0gen_load_gpr(t0, rs);
+ =A0 =A0 =A0 =A0gen_load_gpr(t1, 0);
+ =A0 =A0 =A0 =A0maskb= =3D 1ULL << (rt + 32);
+ =A0 =A0 =A0 =A0tcg_gen_andi_tl(t0= , t0, maskb);
+ =A0 =A0 =A0 =A0bcond_compute =3D 1;
+ = =A0 =A0 =A0 =A0btgt =3D ctx->pc + insn_bytes + offset;
+ =A0 =A0 =A0 =A0break;
+
=A0=A0 =A0 case OPC_BGEZ= :
=A0=A0 =A0 case OPC_BGEZAL:
=A0=A0 =A0 case OPC_BGEZA= LS:
@@ -2888,6 +3177,18 @@ static void gen_compute_branch (DisasC= ontext *ctx, uint32_t opc,
=A0=A0 =A0 =A0 =A0 =A0 =A0 MIPS_DEBUG("bne %s, %s, " TARGET_= FMT_lx,
=A0=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0regname= s[rs], regnames[rt], btgt);
=A0=A0 =A0 =A0 =A0 =A0 =A0 goto not_l= ikely;
+ =A0 =A0 =A0 =A0case OPC_BBIT1:
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
+ =A0 =A0 =A0 =A0 =A0 =A0goto not_likely;
+ =A0 =A0 =A0 = =A0case OPC_BBIT132:
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_setcond_tl(= TCG_COND_NE, bcond, t0, t1);
+ =A0 =A0 =A0 =A0 =A0 =A0goto not_li= kely;
+ =A0 =A0 =A0 =A0 =A0 =A0case OPC_BBIT0:
+ =A0 =A0 =A0 =A0 = =A0 =A0tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
+ =A0 =A0 = =A0 =A0 =A0 =A0goto not_likely;
+ =A0 =A0 =A0 =A0case OPC_BBIT032= :
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_setcond_tl(TCG_COND_EQ, bcond,= t0, t1);
+ =A0 =A0 =A0 =A0 =A0 =A0goto not_likely;
=A0=A0 =A0 =A0 =A0= case OPC_BNEL:
=A0=A0 =A0 =A0 =A0 =A0 =A0 tcg_gen_setcond_tl(TCG= _COND_NE, bcond, t0, t1);
=A0=A0 =A0 =A0 =A0 =A0 =A0 MIPS_DEBUG(&= quot;bnel %s, %s, " TARGET_FMT_lx,
@@ -2983,7 +3284,42 @@ static void gen_compute_branch (DisasContext *ctx, u= int32_t opc,
=A0=A0 =A0 tcg_temp_free(t0);
=A0=A0 =A0 t= cg_temp_free(t1);
=A0}
+/* For cavium specific extract = instructions */
+#if defined(TARGET_MIPS64)
+static void gen_exts (CPUState = *env,DisasContext *ctx, uint32_t opc, int rt,
+ =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0int rs, int lsb, int msb)
+{
+ =A0 =A0TCGv t0 =3D tcg_temp_new();
+ =A0 =A0TCGv t1 =3D tcg_temp_new();
+ =A0 =A0target_ulong m= ask;
+ =A0 =A0gen_load_gpr(t1, rs);
+ =A0 =A0switch (op= c) {
+ =A0 =A0case OPC_EXTS:
+ =A0 =A0 =A0 =A0tcg_gen_s= hri_tl(t0, t1, lsb);
+ =A0 =A0 =A0 =A0tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1= );
+ =A0 =A0 =A0 =A0/* To sign extened the remaining bits accordi= ng to
+ =A0 =A0 =A0 =A0 =A0 the msb of the bit field */
+ =A0 =A0 =A0 =A0mask =3D 1ULL << msb;
+ =A0 =A0 =A0 =A0tcg_gen_andi_tl(t1, t0, mask);
+ =A0 =A0 = =A0 =A0tcg_gen_addi_tl(t1, t1, -1);
+ =A0 =A0 =A0 =A0tcg_gen_orc_= tl(t0, t0, t1);
+ =A0 =A0 =A0 =A0gen_store_gpr(t0, rt);
+ =A0 =A0 =A0 =A0break;
+ =A0 =A0case OPC_EXTS32:
+ =A0 =A0 =A0 =A0tcg_gen_shri_tl(t0, t1, lsb + 32);
+ =A0 = =A0 =A0 =A0tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
+ =A0 =A0 =A0 =A0mask =3D 1ULL << msb;
+ =A0 =A0 =A0 =A0t= cg_gen_andi_tl(t1, t0, mask);
+ =A0 =A0 =A0 =A0tcg_gen_addi_tl(t1, t1, -1);
+ =A0 =A0 =A0 = =A0tcg_gen_orc_tl(t0, t0, t1);
+ =A0 =A0 =A0 =A0gen_store_gpr(t0,= rt);
+ =A0 =A0 =A0 =A0break;
=A0
+ =A0 =A0}<= /div>
+ =A0 =A0tcg_temp_free(t0);
+ =A0 =A0tcg_temp_free(t1);
+}
+#endif
= =A0/* special3 bitfield operations */
=A0static void gen_bitops (= DisasContext *ctx, uint32_t opc, int rt,
=A0=A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0 int rs, int lsb, int msb)
@@ -3063,6 +3399,22 @@ static void gen_bitops (DisasContext *ctx, uint= 32_t opc, int rt,
=A0=A0 =A0 =A0 =A0 tcg_gen_andi_tl(t1, t1, mask= );
=A0=A0 =A0 =A0 =A0 tcg_gen_or_tl(t0, t0, t1);
=A0=A0= =A0 =A0 =A0 break;
+ =A0 =A0case OPC_CINS:
+ =A0 =A0 =A0 =A0mask =3D =A0(1ULL <&l= t; (msb+1))-1;
+ =A0 =A0 =A0 =A0gen_load_gpr(t0, rt);
+= =A0 =A0 =A0 =A0tcg_gen_andi_tl(t0, t0, 0);
+ =A0 =A0 =A0 =A0tcg_= gen_andi_tl(t1, t1, mask);
+ =A0 =A0 =A0 =A0tcg_gen_shli_tl(t1, t1, lsb);
+ =A0 =A0 =A0 =A0t= cg_gen_or_tl(t0, t0, t1);
+ =A0 =A0 =A0 =A0break;
+ =A0= =A0case OPC_CINS32:
+ =A0 =A0 =A0 =A0mask =3D =A0(1ULL << = (msb+1))-1;
+ =A0 =A0 =A0 =A0gen_load_gpr(t0, rt);
+ =A0 =A0 =A0 =A0tcg_gen_andi_tl(t0, t0, 0);
+ =A0 =A0 =A0 = =A0tcg_gen_andi_tl(t1, t1, mask);
+ =A0 =A0 =A0 =A0tcg_gen_shli_t= l(t1, t1, (lsb+32));
+ =A0 =A0 =A0 =A0tcg_gen_or_tl(t0, t0, t1);<= /div>
+ =A0 =A0 =A0 =A0break;
=A0#endif
=A0=A0 =A0 default:
=A0fail:
@= @ -11609,8 +11961,8 @@ static void decode_opc (CPUState *env, DisasContext = *ctx, int *is_branch)
=A0=A0 =A0 int32_t offset;
=A0=A0= =A0 int rs, rt, rd, sa;
=A0=A0 =A0 uint32_t op, op1, op2;
- =A0 =A0int16_t imm;
-
+ =A0 =A0int16_t imm, imm10;
+ =A0 =A0int TARGE= T_OCTEON =3D env->TARGET_OCTEON;
=A0=A0 =A0 /* make sure instr= uctions are on a word boundary */
=A0=A0 =A0 if (ctx->pc & 0x3) {
=A0=A0 =A0 =A0 =A0 en= v->CP0_BadVAddr =3D ctx->pc;
@@ -11638,6 +11990,9 @@ static= void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
=A0=A0 =A0 rd =3D (ctx->opcode >> 11) & 0x1f;
=A0=A0 =A0 sa =3D (ctx->opcode >> 6) & 0x1f;
= =A0=A0 =A0 imm =3D (int16_t)ctx->opcode;
+ =A0 =A0/* 10 bit Im= mediate value For SEQI,SNEI */
+ =A0 =A0imm10 =3D (ctx->opcode= >> 6) & 0x3ff;
+
=A0=A0 =A0 switch (op) {
=A0=A0 =A0 case OPC_SPE= CIAL:
=A0=A0 =A0 =A0 =A0 op1 =3D MASK_SPECIAL(ctx->opcode);
@@ -11863,6 +12218,84 @@ static void decode_opc (CPUState *env, Dis= asContext *ctx, int *is_branch)
=A0=A0 =A0 =A0 =A0 case OPC_MUL:
=A0=A0 =A0 =A0 =A0 =A0 =A0 = gen_arith(env, ctx, op1, rd, rs, rt);
=A0=A0 =A0 =A0 =A0 =A0 =A0 = break;
+#if defined(TARGET_MIPS64)
+
+ =A0 = =A0 =A0 =A0case OPC_DMUL:
+ =A0 =A0 =A0 =A0 =A0 =A0check_insn(env= , ctx, ISA_MIPS3);
+ =A0 =A0 =A0 =A0 =A0 =A0check_mips_64(ctx);
+ =A0 =A0 =A0 = =A0 =A0 =A0check_octeon(ctx, env);
+ =A0 =A0 =A0 =A0 =A0 =A0gen_m= uldiv(ctx, op1, rs, rt);
+ =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_mov_tl(= cpu_gpr[rd], cpu_LO[0]);
+ =A0 =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_CINS:
+ =A0 =A0 =A0 =A0 =A0 =A0che= ck_insn(env, ctx, ISA_MIPS64R2);
+ =A0 =A0 =A0 =A0 =A0 =A0check_m= ips_64(ctx);
+ =A0 =A0 =A0 =A0 =A0 =A0check_octeon(ctx, env);
+ =A0 =A0 =A0 =A0 =A0 =A0gen_bitops(ctx, op1, rt, rs, sa, rd);
+ =A0 =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_CI= NS32:
+ =A0 =A0 =A0 =A0 =A0 =A0check_mips_64(ctx);
+ = =A0 =A0 =A0 =A0 =A0 =A0check_octeon(ctx, env);
+ =A0 =A0 =A0 =A0 = =A0 =A0gen_bitops(ctx, op1, rt, rs, sa, rd);
+ =A0 =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_MTM0:
+ =A0 =A0 =A0 =A0 =A0 =A0check_mips_64(ctx);
+ =A0 =A0 = =A0 =A0 =A0 =A0check_octeon(ctx, env);
+ =A0 =A0 =A0 =A0 =A0 =A0g= en_LMI(env, ctx, op1, rs, rt, rd);
+ =A0 =A0 =A0 =A0 =A0 =A0break= ;
+ =A0 =A0 =A0 =A0case OPC_MTM1:
+ =A0 =A0 =A0 =A0 =A0 =A0che= ck_mips_64(ctx);
+ =A0 =A0 =A0 =A0 =A0 =A0check_octeon(ctx, env);=
+ =A0 =A0 =A0 =A0 =A0 =A0gen_LMI(env, ctx, op1, rs, rt, rd);
+ =A0 =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_= MTM2:
+ =A0 =A0 =A0 =A0 =A0 =A0check_mips_64(ctx);
+ =A0 =A0 =A0 = =A0 =A0 =A0check_octeon(ctx, env);
+ =A0 =A0 =A0 =A0 =A0 =A0gen_L= MI(env, ctx, op1, rs, rt, rd);
+ =A0 =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_MTP0:
+ =A0 =A0 =A0 =A0 =A0 =A0= check_mips_64(ctx);
+ =A0 =A0 =A0 =A0 =A0 =A0check_octeon(ctx, env);
+ =A0 =A0 = =A0 =A0 =A0 =A0gen_LMI(env, ctx, op1, rs, rt, rd);
+ =A0 =A0 =A0 = =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_MTP1:
+ =A0= =A0 =A0 =A0 =A0 =A0check_mips_64(ctx);
+ =A0 =A0 =A0 =A0 =A0 =A0= check_octeon(ctx, env);
+ =A0 =A0 =A0 =A0 =A0 =A0gen_LMI(env, ctx, op1, rs, rt, rd);
+ =A0 =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_MTP2:<= /div>
+ =A0 =A0 =A0 =A0 =A0 =A0check_mips_64(ctx);
+ =A0 =A0 = =A0 =A0 =A0 =A0check_octeon(ctx, env);
+ =A0 =A0 =A0 =A0 =A0 =A0g= en_LMI(env, ctx, op1, rs, rt, rd);
+ =A0 =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_VM= ULU:
+ =A0 =A0 =A0 =A0 =A0 =A0check_mips_64(ctx);
+ =A0= =A0 =A0 =A0 =A0 =A0gen_LMI(env, ctx, op1, rs, rt, rd);
+ =A0 =A0= =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_BADDU:
+ =A0 =A0 =A0 =A0 =A0 =A0check_octeon(ctx, env);
+ =A0 =A0 = =A0 =A0 =A0 =A0gen_arith(env, ctx, op1, rd, rs, rt);
+ =A0 =A0 = =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_EXTS:
+= =A0 =A0 =A0 =A0 =A0 =A0check_mips_64(ctx);
+ =A0 =A0 =A0 =A0 =A0= =A0check_octeon(ctx, env);
+ =A0 =A0 =A0 =A0 =A0 =A0gen_exts(env, ctx, op1, rt, rs, sa, rd);
+ =A0 =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_E= XTS32:
+ =A0 =A0 =A0 =A0 =A0 =A0check_mips_64(ctx);
+ = =A0 =A0 =A0 =A0 =A0 =A0check_octeon(ctx, env);
+ =A0 =A0 =A0 =A0 =A0 =A0gen_exts(env, ctx, op1, rt, rs, sa, rd);
+ =A0 =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_SAA:
+ =A0 =A0 =A0 =A0 =A0 =A0check_octeon(ctx, env);
+ =A0 = =A0 =A0 =A0 =A0 =A0gen_saa(env, ctx, op1, rt, rs);
+ =A0 =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_SA= AD:
+ =A0 =A0 =A0 =A0 =A0 =A0check_octeon(ctx, env);
+ = =A0 =A0 =A0 =A0 =A0 =A0check_mips_64(ctx);
+ =A0 =A0 =A0 =A0 =A0 = =A0gen_saa(env, ctx, op1, rt, rs);
+ =A0 =A0 =A0 =A0 =A0 =A0break= ;
+#endif
=A0=A0 =A0 =A0 =A0 case OPC_CLO:
=A0=A0 = =A0 =A0 =A0 case OPC_CLZ:
=A0=A0 =A0 =A0 =A0 =A0 =A0 check_insn(e= nv, ctx, ISA_MIPS32);
@@ -11882,13 +12315,25 @@ static void decod= e_opc (CPUState *env, DisasContext *ctx, int *is_branch)
=A0=A0 =A0 =A0 =A0 =A0 =A0 break;
=A0=A0 =A0 =A0 =A0 case OP= C_DIV_G_2F:
=A0=A0 =A0 =A0 =A0 case OPC_DIVU_G_2F:
- = =A0 =A0 =A0 =A0case OPC_MULT_G_2F:
=A0=A0 =A0 =A0 =A0 case OPC_MU= LTU_G_2F:
=A0=A0 =A0 =A0 =A0 case OPC_MOD_G_2F:
=A0=A0 =A0 =A0 =A0 case OPC_MODU_G_2F:
=A0=A0 =A0 =A0 =A0 = =A0 =A0 check_insn(env, ctx, INSN_LOONGSON2F);
=A0=A0 =A0 =A0 =A0= =A0 =A0 gen_loongson_integer(ctx, op1, rd, rs, rt);
=A0=A0 =A0 = =A0 =A0 =A0 =A0 break;
+ =A0 =A0 =A0 =A0case OPC_MULT_G_2F:
+ =A0 =A0 =A0 =A0 =A0 =A0if (!TARGET_OCTEON) {
+ =A0 =A0 =A0= =A0 =A0 =A0 =A0 =A0check_insn(env, ctx, INSN_LOONGSON2F);
+ =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0gen_loongson_integer(ctx, op1, rd, rs, rt);
+ =A0 =A0 =A0 =A0 =A0 =A0} else {
+#if defined(TARGET_MIPS6= 4)
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* Cavium Specific vmm0 */
= + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0check_mips_64(ctx);
+ =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0check_octeon(ctx, env);
+ =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0gen_LMI(env, ctx, op1, rs, rt, rd);
+#endif
+ =A0 =A0 =A0 =A0 =A0 =A0}
+ =A0 =A0 =A0 =A0 =A0 =A0break;
=A0#if defined(TARGET_MIPS64)
=A0=A0 =A0 =A0 =A0 case OP= C_DCLO:
=A0=A0 =A0 =A0 =A0 case OPC_DCLZ:
@@ -11896,7 += 12341,6 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *i= s_branch)
=A0=A0 =A0 =A0 =A0 =A0 =A0 check_mips_64(ctx);
=A0=A0 =A0 = =A0 =A0 =A0 =A0 gen_cl(ctx, op1, rd, rs);
=A0=A0 =A0 =A0 =A0 =A0 = =A0 break;
- =A0 =A0 =A0 =A0case OPC_DMULT_G_2F:
=A0=A0= =A0 =A0 =A0 case OPC_DMULTU_G_2F:
=A0=A0 =A0 =A0 =A0 case OPC_DD= IV_G_2F:
=A0=A0 =A0 =A0 =A0 case OPC_DDIVU_G_2F:
@@ -11905,6 +12349,4= 6 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_bran= ch)
=A0=A0 =A0 =A0 =A0 =A0 =A0 check_insn(env, ctx, INSN_LOONGSON= 2F);
=A0=A0 =A0 =A0 =A0 =A0 =A0 gen_loongson_integer(ctx, op1, rd= , rs, rt);
=A0=A0 =A0 =A0 =A0 =A0 =A0 break;
+ =A0 =A0 =A0 =A0case OPC_= DMULT_G_2F:
+ =A0 =A0 =A0 =A0 =A0 =A0if (!TARGET_OCTEON) {
<= div>+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0check_insn(env, ctx, INSN_LOONGSON2F);=
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0gen_loongson_integer(ctx, op1, = rd, rs, rt);
+ =A0 =A0 =A0 =A0 =A0 =A0} else {
+ =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0/* Cavium Specific instruction v3mulu */
+ =A0 =A0 =A0 =A0= =A0 =A0 =A0 =A0check_mips_64(ctx);
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0= =A0check_octeon(ctx, env);
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0gen_= LMI(env, ctx, op1, rs, rt, rd);
+ =A0 =A0 =A0 =A0 =A0 =A0}
+ =A0 =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_SEQ:
+ =A0 =A0 =A0 =A0 =A0 =A0= check_mips_64(ctx);
+ =A0 =A0 =A0 =A0 =A0 =A0check_octeon(ctx, en= v);
+ =A0 =A0 =A0 =A0 =A0 =A0gen_seqsne(ctx, op1, rd, rs, rt);
+ =A0 =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_SN= E:
+ =A0 =A0 =A0 =A0 =A0 =A0check_mips_64(ctx);
+ =A0 = =A0 =A0 =A0 =A0 =A0check_octeon(ctx, env);
+ =A0 =A0 =A0 =A0 =A0 = =A0gen_seqsne(ctx, op1, rd, rs, rt);
+ =A0 =A0 =A0 =A0 =A0 =A0bre= ak;
+ =A0 =A0 =A0 =A0case OPC_SEQI:
+ =A0 =A0 =A0 =A0 =A0 =A0che= ck_mips_64(ctx);
+ =A0 =A0 =A0 =A0 =A0 =A0check_octeon(ctx, env);=
+ =A0 =A0 =A0 =A0 =A0 =A0gen_set_imm(env, op1, rt, rs, imm10);
+ =A0 =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OP= C_SNEI:
+ =A0 =A0 =A0 =A0 =A0 =A0check_mips_64(ctx);
+ =A0 =A0 =A0 = =A0 =A0 =A0check_octeon(ctx, env);
+ =A0 =A0 =A0 =A0 =A0 =A0gen_s= et_imm(env, op1, rt, rs, imm10);
+ =A0 =A0 =A0 =A0 =A0 =A0break;<= /div>
+ =A0 =A0 =A0 =A0case OPC_POP:
+ =A0 =A0 =A0 =A0 =A0 = =A0check_octeon(ctx, env);
+ =A0 =A0 =A0 =A0 =A0 =A0gen_pop_count(ctx, op1, rd, rs);
+ = =A0 =A0 =A0 =A0 =A0 =A0break;
+ =A0 =A0 =A0 =A0case OPC_DPOP:
+ =A0 =A0 =A0 =A0 =A0 =A0check_mips_64(ctx);
+ =A0 =A0 =A0= =A0 =A0 =A0check_octeon(ctx, env);
+ =A0 =A0 =A0 =A0 =A0 =A0gen_= pop_count(ctx, op1, rd, rs);
+ =A0 =A0 =A0 =A0 =A0 =A0break;
=A0#endif
=A0=A0 = =A0 =A0 =A0 default: =A0 =A0 =A0 =A0 =A0 =A0/* Invalid */
=A0=A0 = =A0 =A0 =A0 =A0 =A0 MIPS_INVAL("special2");
@@ -12196,1= 0 +12680,32 @@ static void decode_opc (CPUState *env, DisasContext *ctx, in= t *is_branch)
=A0=A0 =A0 =A0 =A0 break;
=A0
=A0=A0 =A0 /* COP2. = =A0*/
- =A0 =A0case OPC_LWC2:
- =A0 =A0case OPC_LDC2:
- =A0 =A0case OPC_SWC2:
- =A0 =A0case OPC_SDC2:
+ =A0 =A0/* Conflicting opcodes with Cavium specific branch instructions<= /div>
+ =A0 =A0 =A0 if TARGET_OCTEON is set these opcodes will belong to Cav= ium */
+ =A0 =A0case OPC_LWC2: /* BBIT0 */
+ =A0 =A0 = =A0 =A0if (TARGET_OCTEON) {
+ =A0 =A0 =A0 =A0 =A0 =A0gen_compute_= branch(ctx, op, 4, rs, rt, imm << 2);
+ =A0 =A0 =A0 =A0 =A0 =A0*is_branch =3D 1;
+ =A0 =A0 =A0 =A0= =A0 =A0break;
+ =A0 =A0 =A0 =A0}
+ =A0 =A0case OPC_LDC= 2: /* BBIT032 */
+ =A0 =A0 =A0 =A0if (TARGET_OCTEON) {
= + =A0 =A0 =A0 =A0 =A0 =A0gen_compute_branch(ctx, op, 4, rs, rt, imm <<= ; 2);
+ =A0 =A0 =A0 =A0 =A0 =A0*is_branch =3D 1;
+ =A0 =A0 =A0 =A0= =A0 =A0break;
+ =A0 =A0 =A0 =A0}
+ =A0 =A0case OPC_SWC= 2: /* BBIT1 */
+ =A0 =A0 =A0 =A0if (TARGET_OCTEON) {
+ = =A0 =A0 =A0 =A0 =A0 =A0gen_compute_branch(ctx, op, 4, rs, rt, imm << = 2);
+ =A0 =A0 =A0 =A0 =A0 =A0*is_branch =3D 1;
+ =A0 =A0 =A0 =A0= =A0 =A0break;
+ =A0 =A0 =A0 =A0}
+ =A0 =A0case OPC_SDC= 2: /* BBIT132 */
+ =A0 =A0 =A0 =A0if (TARGET_OCTEON) {
= + =A0 =A0 =A0 =A0 =A0 =A0gen_compute_branch(ctx, op, 4, rs, rt, imm <<= ; 2);
+ =A0 =A0 =A0 =A0 =A0 =A0*is_branch =3D 1;
+ =A0 =A0 =A0 =A0= =A0 =A0break;
+ =A0 =A0 =A0 =A0}
=A0=A0 =A0 case OPC_C= P2:
=A0=A0 =A0 =A0 =A0 /* COP2: Not implemented. */
=A0= =A0 =A0 =A0 =A0 generate_exception_err(ctx, EXCP_CpU, 2);
@@ -12588,6 +13094,18 @@ static void mips_tcg_init(void)
=A0= =A0 =A0 cpu_dspctrl =3D tcg_global_mem_new(TCG_AREG0,
=A0=A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0offsetof= (CPUState, active_tc.DSPControl),
=A0=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0"DSPControl");
+ =A0 =A0mpl0 =3D tcg_global_mem_new(= TCG_AREG0,
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0offsetof(CPUState, active_tc.MPL0), "MPL0");
+ =A0 =A0mpl1 =3D tcg_global_mem_new(TCG_AREG0,
+ =A0 =A0 =A0 =A0= =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0offsetof(CPUState, active_tc.MP= L1), "MPL1");
+ =A0 =A0mpl2 =3D tcg_global_mem_new(TCG_= AREG0,
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0offsetof(CPUState, active_tc.MPL2), "MPL2");
+ =A0 =A0p0 =3D tcg_global_mem_new(TCG_AREG0,
+ =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0offsetof(CPUState, active_tc.P0)= , "P0");
+ =A0 =A0p1 =3D tcg_global_mem_new(TCG_AREG0,<= /div>
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0offsetof= (CPUState, active_tc.P1), "P1");
+ =A0 =A0p2 =3D tcg_global_mem_new(TCG_AREG0,
+ =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0offsetof(CPUState, active_tc.P2)= , "P2");
=A0=A0 =A0 bcond =3D tcg_global_mem_new(TCG_AR= EG0,
=A0=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0offsetof(CPUState, bcond), "bcond");
=A0=A0 =A0 btarget =3D tcg_global_mem_new(TCG_AREG0,
@@ -126= 11,6 +13129,18 @@ static void mips_tcg_init(void)
=A0
= =A0#include "translate_init.c"
=A0
+#if defin= ed(TARGET_MIPS64)
+
+static void set_cvmctl_register(CPUMIPSState *env)
<= div>+{
+ =A0 =A0env->active_tc.cvmctl =3D env->active_tc.cv= mctl
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 ^ env->active_tc.cvmctl;
+ =A0 =A0env->active_tc.cvmctl =3D FUSE_START_BIT(env->active_tc= .cvmctl);
+ =A0 =A0env->active_tc.cvmctl =3D KASUMI(env->ac= tive_tc.cvmctl);
+ =A0 =A0env->active_tc.cvmctl =3D IPPCI(env-= >active_tc.cvmctl);
+ =A0 =A0env->active_tc.cvmctl =3D IPTI(env->active_tc.cvmctl);<= /div>
+}
+#endif
=A0CPUMIPSState *cpu_mips_init (co= nst char *cpu_model)
=A0{
=A0=A0 =A0 CPUMIPSState *env;=
@@ -12623,6 +13153,10 @@ CPUMIPSState *cpu_mips_init (const char= *cpu_model)
=A0=A0 =A0 env->cpu_model =3D def;
=A0=A0 =A0 env->cpu= _model_str =3D cpu_model;
=A0
+#if defined(TARGET_MIPS6= 4)
+ =A0 =A0/* Function for setting cvmctl register */
= + =A0 =A0set_cvmctl_register(env);
+#endif
=A0=A0 =A0 cpu_exec_init(env);
=A0#ifndef = CONFIG_USER_ONLY
=A0=A0 =A0 mmu_init(env, def);
--=A0
1.7.3.4

--00235433362e03106904a07a5388--