[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] MIPS64 user mode emulation Patch
From: |
Riku Voipio |
Subject: |
Re: [Qemu-devel] MIPS64 user mode emulation Patch |
Date: |
Tue, 29 Mar 2011 11:55:58 +0300 |
User-agent: |
Mutt/1.5.18 (2008-05-17) |
Hi,
First, do you have some instructions on howto build Octeon usermode
64bit binaries. Second, I think we would prefer that the patch was split
to smaller patches. At least the target-mips changes should be a separate
patch.
Some more comments included inline between the code.
On Sat, Mar 26, 2011 at 11:58:37AM +0500, Khansa Butt wrote:
> >From cd88be1263d0fc9802cd4dd358ed0299c0d106b0 Mon Sep 17 00:00:00 2001
> From: Khansa Butt & Ehsan-ul-Haq <address@hidden>
> Date: Sat, 26 Mar 2011 11:53:11 +0500
> Subject: [PATCH] MIPS64 user mode emulation in QEMU
> This patch adds support for Cavium Network's
> Octeon 57XX user mode instructions. Octeon
> 57xx is based on MIPS64. So this patch is
> the first MIPS64 User Mode Emulation in QEMU
> This is the team(Khansa Butt, Ehsan-ul-Haq, Abdul Qadeer, Abdul Waheed)
> work of HPCNL Lab at KICS-UET Lahore.
>
>
> Signed-off-by: Khansa Butt <address@hidden>
> ---
> configure | 1 +
> default-configs/mips64-linux-user.mak | 1 +
> exec.c | 1 +
> linux-user/elfload.c | 15 +-
> linux-user/main.c | 20 +-
> linux-user/mips64/syscall.h | 2 +
> linux-user/signal.c | 3 +-
> linux-user/syscall.c | 2 +
> target-mips/cpu.h | 16 +
> target-mips/translate.c | 659
> ++++++++++++++++++++++++++++++++-
> 10 files changed, 704 insertions(+), 16 deletions(-)
> create mode 100644 default-configs/mips64-linux-user.mak
>
> diff --git a/configure b/configure
> index 438219b..045a4ef 100755
> --- a/configure
> +++ b/configure
> @@ -1011,6 +1011,7 @@ cris-linux-user \
> m68k-linux-user \
> microblaze-linux-user \
> mips-linux-user \
> +mips64-linux-user \
> mipsel-linux-user \
> ppc-linux-user \
> ppc64-linux-user \
> diff --git a/default-configs/mips64-linux-user.mak
> b/default-configs/mips64-linux-user.mak
> new file mode 100644
> index 0000000..1598bfc
> --- /dev/null
> +++ b/default-configs/mips64-linux-user.mak
> @@ -0,0 +1 @@
> +# Default configuration for mips64-linux-user
> diff --git a/exec.c b/exec.c
> index 49c28b1..ee3f78e 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -2441,6 +2441,7 @@ int page_check_range(target_ulong start, target_ulong
> len, int flags)
> for (addr = start, len = end - start;
> len != 0;
> len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
> + addr &= qemu_host_page_mask;
> p = page_find(addr >> TARGET_PAGE_BITS);
Are you sure this will not generate ill effect on other target/host architecture
combinations?
> if( !p )
> return -1;
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index 33d776d..60fe85e 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -16,6 +16,8 @@
> #include "qemu.h"
> #include "disas.h"
>
> +extern int TARGET_OCTEON;
> +
> #ifdef _ARCH_PPC64
> #undef ARCH_DLINFO
> #undef ELF_PLATFORM
> @@ -25,6 +27,9 @@
> #undef ELF_ARCH
> #endif
>
> +#define EF_MIPS_MARCH 16711680
> +#define E_MIPS_MACH_OCTEON 9109504
> +
please use hexadecimal values.
> #define ELF_OSABI ELFOSABI_SYSV
>
> /* from personality.h */
> @@ -1313,7 +1318,7 @@ static void load_elf_image(const char *image_name, int
> image_fd,
> vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
> vaddr_ps = TARGET_ELF_PAGESTART(vaddr);
>
> - error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
> + error = target_mmap(vaddr_ps, eppnt->p_memsz + vaddr_po,
> elf_prot, MAP_PRIVATE | MAP_FIXED,
> image_fd, eppnt->p_offset - vaddr_po);
> if (error == -1) {
> @@ -1588,7 +1593,13 @@ int load_elf_binary(struct linux_binprm * bprm,
> struct target_pt_regs * regs,
> If we do nothing, we'll have overwritten this when we re-use
> bprm->buf
> 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) {
> + TARGET_OCTEON = 1;
> + } else {
> + TARGET_OCTEON = 0;
> + }
> +#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 0d627d6..8b4b90b 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -1937,10 +1937,16 @@ static int do_store_exclusive(CPUMIPSState *env)
> int d;
>
> addr = env->lladdr;
> + /* 64 bit address is converted to 32 bit value so that a valid
> + * l1_map value can be accessed. This thing is needed for target
> + * mips64 and host 32 bit x86
> + */
> + addr &= qemu_host_page_mask;
same as earlier.
> page_addr = addr & TARGET_PAGE_MASK;
> start_exclusive();
> mmap_lock();
> flags = page_get_flags(page_addr);
> + addr = env->lladdr;
> if ((flags & PAGE_READ) == 0) {
> segv = 1;
> } else {
> @@ -1978,7 +1984,8 @@ static int do_store_exclusive(CPUMIPSState *env)
> void cpu_loop(CPUMIPSState *env)
> {
> target_siginfo_t info;
> - int trapnr, ret;
> + int trapnr;
> + abi_long ret;
> unsigned int syscall_num;
>
> for(;;) {
> @@ -1987,7 +1994,11 @@ void cpu_loop(CPUMIPSState *env)
> cpu_exec_end(env);
> switch(trapnr) {
> case EXCP_SYSCALL:
> +#if defined(TARGET_MIPS64)
> + syscall_num = env->active_tc.gpr[2] - 5000;
> +#else
> syscall_num = env->active_tc.gpr[2] - 4000;
> +#endif
> env->active_tc.PC += 4;
> if (syscall_num >= sizeof(mips_syscall_args)) {
> ret = -ENOSYS;
> @@ -2013,7 +2024,8 @@ void cpu_loop(CPUMIPSState *env)
> env->active_tc.gpr[5],
> env->active_tc.gpr[6],
> env->active_tc.gpr[7],
> - arg5, arg6/*, arg7, arg8*/);
> + env->active_tc.gpr[8],
> + env->active_tc.gpr[9]/*, arg7, arg8*/);
> }
> if (ret == -TARGET_QEMU_ESIGRETURN) {
> /* Returning from a successful sigreturn syscall.
> @@ -2926,7 +2938,9 @@ int main(int argc, char **argv, char **envp)
> #endif
> #elif defined(TARGET_MIPS)
> #if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
> - cpu_model = "20Kc";
> + /* we use this model so that we can decode MIPS64r2
> + reserved instruction */
> + cpu_model = "MIPS64R2-generic";
> #else
> cpu_model = "24Kf";
> #endif
> diff --git a/linux-user/mips64/syscall.h b/linux-user/mips64/syscall.h
> index 668a2b9..1395e61 100644
> --- a/linux-user/mips64/syscall.h
> +++ b/linux-user/mips64/syscall.h
> @@ -217,5 +217,7 @@ struct target_pt_regs {
> #define TARGET_ENOTRECOVERABLE 166 /* State not recoverable */
>
>
> +/* Nasty hack: define a fake errno value for use by sigreturn. */
> +#define TARGET_QEMU_ESIGRETURN 255
>
> #define UNAME_MACHINE "mips64"
> diff --git a/linux-user/signal.c b/linux-user/signal.c
> index c846b8c..114116c 100644
> --- a/linux-user/signal.c
> +++ b/linux-user/signal.c
> @@ -2410,7 +2410,8 @@ void sparc64_get_context(CPUSPARCState *env)
> #endif
> #elif defined(TARGET_ABI_MIPSN64)
>
> -# warning signal handling not implemented
> +/*this line is commented out to avoid compile time error*/
> +/*# warning signal handling not implemented*/
>
> static void setup_frame(int sig, struct target_sigaction *ka,
> target_sigset_t *set, CPUState *env)
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 499c4d7..47fef05 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -7195,6 +7195,8 @@ 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;
> + /*tls entry is moved to k0 so that this can be used later*/
> + ((CPUMIPSState *) cpu_env)->active_tc.gpr[26] = arg1;
Does this affect the non-octeon mips ?
> ret = 0;
> break;
> #elif defined(TARGET_CRIS)
And someone else will need to comment the TCG changes.
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index 2419aa9..59bcc0f 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -140,6 +140,20 @@ typedef struct mips_def_t mips_def_t;
> #define MIPS_FPU_MAX 1
> #define MIPS_DSP_ACC 4
>
> +typedef struct cavium_mul cavium_mul;
> +struct cavium_mul {
> + target_ulong MPL0;
> + target_ulong MPL1;
> + target_ulong MPL2;
> + target_ulong P0;
> + target_ulong P1;
> + target_ulong P2;
> +};
> +typedef struct cvmctl_register cvmctl_register;
> +struct cvmctl_register {
> + target_ulong cvmctl;
> +};
> +
> typedef struct TCState TCState;
> struct TCState {
> target_ulong gpr[32];
> @@ -178,6 +192,8 @@ struct CPUMIPSState {
> TCState active_tc;
> CPUMIPSFPUContext active_fpu;
>
> + cavium_mul Reg;
> + cvmctl_register CvmCtlRegister;
> uint32_t current_tc;
> uint32_t current_fpu;
>
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index cce77be..9c3d772 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -36,6 +36,15 @@
> #define GEN_HELPER 1
> #include "helper.h"
>
> +int TARGET_OCTEON;
> +#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 +79,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(one of the upper 32
> bits)*/
> + OPC_BBIT0 = (0x32 << 26), /*jump on bit clear, cavium specific*/
> + OPC_BBIT032 = (0x36 << 26), /*jump on bit set(one of the upper 32
> bits)*/
> OPC_BEQL = (0x14 << 26),
> OPC_BNE = (0x05 << 26),
> OPC_BNEL = (0x15 << 26),
> @@ -265,6 +279,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 +522,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;
>
> @@ -779,7 +818,9 @@ static inline void gen_op_addr_add (DisasContext *ctx,
> TCGv ret, TCGv arg0, TCGv
> See the MIPS64 PRA manual, section 4.10. */
> if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
> !(ctx->hflags & MIPS_HFLAG_UX)) {
> - tcg_gen_ext32s_i64(ret, ret);
> + /*This function sign extend 32 bit value to 64 bit, was causing
> error
> + when ld instruction came.Thats why it is commmented out*/
> + /* tcg_gen_ext32s_i64(ret, ret);*/
> }
> #endif
> }
> @@ -1419,7 +1460,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,13 +1650,196 @@ 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)
> +/* Addition and carry detection*/
> +static void gen_addc (TCGv arg1, TCGv arg2, TCGv res, TCGv c)
> +{
> + tcg_gen_add_tl(res, arg1, arg2);
> + tcg_gen_setcond_tl(TCG_COND_LTU, c, res, arg1);
> +}
> +static void gen_LMI (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
> + int rs, int rt, int rd)
> +{
> + const char *opn = "LMI";
> + TCGv t0, t1;
> + int nomul = env->CvmCtlRegister.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:
> + t0 = tcg_temp_new();
> + t1 = tcg_temp_new();
> + 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);
> + tcg_temp_free(t0);
> + tcg_temp_free(t1);
> + opn = "vmm0";
> + break;
> + case OPC_VMULU:
> + {
> + TCGv t2, c;
> + t0 = tcg_temp_new();
> + t1 = tcg_temp_new();
> + t2 = tcg_temp_new();
> + c = tcg_temp_new();
> + gen_load_gpr(t1, rs);
> + gen_load_gpr(t2, rt);
> + gen_helper_dmultu(t1, mpl0);
> + tcg_gen_mov_tl(t0, cpu_LO[0]);
> + /*if carry comes due to addition of rt and LO register,
> + * this carry should be added to HI register.
> + */
> + gen_addc(t0, t2, t1, c);
>
> + tcg_gen_add_tl(cpu_HI[0], cpu_HI[0], c);
> + /* t0 = t1 + p0 where t1 = LO+rt*/
> + gen_addc(t1, p0, t0, c);
> + tcg_gen_add_tl(cpu_HI[0], cpu_HI[0], c);
> +
> + tcg_gen_mov_tl(cpu_gpr[rd], t0);
> + tcg_gen_mov_tl(p0, cpu_HI[0]);
> + tcg_temp_free(t0);
> + tcg_temp_free(t1);
> + tcg_temp_free(t2);
> + opn = "vmulu";
> + break;
> + }
> + case OPC_V3MULU:
> + {
> + TCGv temp[4];
> + TCGv c;
> + TCGv trs, trt, tc1, tc2, tc3;
> + temp[0] = tcg_temp_new();
> + temp[1] = tcg_temp_new();
> + temp[2] = tcg_temp_new();
> + temp[3] = tcg_temp_new();
> + trs = tcg_temp_new();
> + trt = tcg_temp_new();
> + tc1 = tcg_temp_new();
> + tc2 = tcg_temp_new();
> + tc3 = tcg_temp_new();
> + c = tcg_temp_new();
> + gen_load_gpr(trs, rs);
> + gen_load_gpr(trt, rt);
> + /* rs × (MPL2 || MPL1 || MPL0) (192X64 bit multiplication)
> */
> + gen_helper_dmultu(trs, mpl0);
> + tcg_gen_mov_tl(temp[0], cpu_LO[0]);
> + tcg_gen_mov_tl(temp[1], cpu_HI[0]);
> +
> + gen_helper_dmultu(trs, mpl1);
> + tcg_gen_mov_tl(temp[2], cpu_HI[0]);
> + gen_addc(cpu_LO[0], temp[1], tc1, tc2);
> + gen_addc(temp[2], tc2, tc3, c);
> + tcg_gen_mov_tl(temp[1], tc1);
> + tcg_gen_mov_tl(temp[2], tc3);
> + tcg_gen_mov_tl(temp[3], c);
> +
> + gen_helper_dmultu(trs, mpl2);
> + tcg_gen_add_tl(temp[3], temp[3], cpu_HI[0]);
> + gen_addc(cpu_LO[0], temp[2], tc1, tc2);
> + tcg_gen_mov_tl(temp[2], tc1);
> + tcg_gen_add_tl(temp[3], temp[3], tc2);
> + /* Addition of rt in 256 bit result
> + (t3 t2 t1 t0 contain result) */
> + gen_addc(temp[0], trt, tc1, c);
> + tcg_gen_mov_tl(temp[0], tc1);
> + gen_addc(temp[1], c, tc1, tc2);
> + tcg_gen_mov_tl(temp[1], tc1);
> + gen_addc(temp[2], tc2, tc1, c);
> + tcg_gen_mov_tl(temp[2], tc1);
> + tcg_gen_add_tl(temp[3], temp[3], c);
> + /* Addition of p2 p1 p0 in 256 bit result */
> + gen_addc(temp[0], p0, tc1, c);
> + tcg_gen_mov_tl(temp[0], tc1);
> + gen_addc(temp[1], c, tc1, tc2);
> + tcg_gen_mov_tl(temp[1], tc1);
> + gen_addc(temp[2], tc2, tc1, c);
> + tcg_gen_mov_tl(temp[2], tc1);
> + tcg_gen_add_tl(temp[3], temp[3], c);
> +
> + gen_addc(temp[1], p1, tc1, c);
> + tcg_gen_mov_tl(temp[1], tc1);
> + gen_addc(temp[2], c, tc1, tc2);
> + tcg_gen_mov_tl(temp[2], tc1);
> + tcg_gen_add_tl(temp[3], temp[3], tc2);
> +
> + gen_addc(temp[2], p2, tc1, c);
> + tcg_gen_mov_tl(temp[2], tc1);
> + tcg_gen_add_tl(temp[3], temp[3], c);
> + /* final step */
> + tcg_gen_mov_tl(cpu_gpr[rd], temp[0]);
> + tcg_gen_mov_tl(p0, temp[1]);
> + tcg_gen_mov_tl(p1, temp[2]);
> + tcg_gen_mov_tl(p2, temp[3]);
> + tcg_temp_free(temp[0]);
> + tcg_temp_free(temp[1]);
> + tcg_temp_free(temp[2]);
> + tcg_temp_free(temp[3]);
> + tcg_temp_free(trs);
> + tcg_temp_free(trt);
> + tcg_temp_free(tc1);
> + tcg_temp_free(tc2);
> + tcg_temp_free(tc3);
> + tcg_temp_free(c);
> + opn = "v3mulu";
> + break;
> + }
> + }
> +
> + } else {
> + generate_exception(ctx, EXCP_RI);
> + }
> +}
> +
> +
> +#endif
> /* Arithmetic */
> static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
> int rd, int rs, int rt)
> {
> const char *opn = "arith";
>
> + target_ulong mask = 0xFF;
> if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
> && opc != OPC_DADD && opc != OPC_DSUB) {
> /* If no destination, treat it as a NOP.
> @@ -1637,6 +1887,22 @@ 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, mask);
> + tcg_gen_andi_tl(t2, t2, mask);
> + tcg_gen_add_tl(t0, t1, t2);
> + tcg_gen_andi_tl(t0, t0, mask);
> + gen_store_gpr(t0, rd);
> + }
> +
> + opn = "baddu";
> + break;
> case OPC_SUB:
> {
> TCGv t0 = tcg_temp_local_new();
> @@ -2013,7 +2279,74 @@ 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 +2482,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 +2705,49 @@ 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 insn_opc_pop (DisasContext *ctx, CPUState *env, uint32_t opc,
> + int rd, int rs, int rt)
> +{
> + TCGv num = tcg_temp_new();
> + TCGv res = tcg_temp_new();
> + target_ulong maskb = 1;
> + gen_load_gpr(num, rs);
> + TCGv ones=tcg_temp_new();
> + gen_load_gpr(ones, 0);
> + int x=1;
> + tcg_gen_andi_tl(res, num, maskb);
> + tcg_gen_add_tl(ones,ones, res);
> + while (x <= 31) {
> + tcg_gen_shri_i64(num, num, 1);
> + tcg_gen_andi_tl(res, num, maskb);
> + tcg_gen_add_tl(ones, ones, res);
> + x++;
> + }
> + gen_store_gpr(ones, rd);
> +}
> +static void insn_opc_dpop (DisasContext *ctx, CPUState *env, uint32_t opc,
> + int rd, int rs, int rt)
> +{
> + TCGv num, res, ones;
> + num = tcg_temp_new();
> + res = tcg_temp_new();
> + ones = tcg_temp_new();
> + target_ulong maskb = 1;
> + gen_load_gpr(num, rs);
> + int x = 1;
> + tcg_gen_andi_tl(res, num, maskb);
> + tcg_gen_mov_tl(ones, res);
>
> + while (x <= 63) {
> + tcg_gen_shri_i64(num, num, 1);
> + tcg_gen_andi_tl(res, num, maskb);
> + tcg_gen_add_tl(ones, ones, res);
> + x++;
> + }
> + gen_store_gpr(ones, rd);
> +}
> +#endif
> /* Godson integer instructions */
> static void gen_loongson_integer (DisasContext *ctx, uint32_t opc,
> int rd, int rs, int rt)
> @@ -2705,6 +3084,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 +3110,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 +3301,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 +3408,44 @@ 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_not_i64(t1, t1);
> + tcg_gen_or_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_not_i64(t1, t1);
> + tcg_gen_or_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 +3525,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:
> @@ -11605,7 +12083,7 @@ static void decode_opc (CPUState *env, DisasContext
> *ctx, int *is_branch)
> int32_t offset;
> int rs, rt, rd, sa;
> uint32_t op, op1, op2;
> - int16_t imm;
> + int16_t imm, imm10;
>
> /* make sure instructions are on a word boundary */
> if (ctx->pc & 0x3) {
> @@ -11634,6 +12112,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);
> @@ -11859,6 +12340,71 @@ 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);
> + 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);
> + gen_bitops(ctx, op1, rt, rs, sa, rd);
> + break;
> + case OPC_CINS32:
> + check_mips_64(ctx);
> + gen_bitops(ctx, op1, rt, rs, sa, rd);
> + break;
> + case OPC_MTM0:
> + check_mips_64(ctx);
> + gen_LMI(env, ctx, op1, rs, rt, rd);
> + break;
> + case OPC_MTM1:
> + check_mips_64(ctx);
> + gen_LMI(env, ctx, op1, rs, rt, rd);
> + break;
> + case OPC_MTM2:
> + check_mips_64(ctx);
> + gen_LMI(env, ctx, op1, rs, rt, rd);
> + break;
> + case OPC_MTP0:
> + check_mips_64(ctx);
> + gen_LMI(env, ctx, op1, rs, rt, rd);
> + break;
> + case OPC_MTP1:
> + check_mips_64(ctx);
> + gen_LMI(env, ctx, op1, rs, rt, rd);
> + break;
> + case OPC_MTP2:
> + check_mips_64(ctx);
> + 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:
> + gen_arith(env, ctx, op1, rd, rs, rt);
> + break;
> + case OPC_EXTS:
> + check_mips_64(ctx);
> + gen_exts(env, ctx, op1, rt, rs, sa, rd);
> + break;
> + case OPC_EXTS32:
> + check_mips_64(ctx);
> + gen_exts(env, ctx, op1, rt, rs, sa, rd);
> + break;
> + case OPC_SAA:
> + gen_saa(env, ctx, op1, rt, rs);
> + break;
> + case OPC_SAAD:
> + 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);
> @@ -11878,13 +12424,24 @@ static void decode_opc (CPUState *env,
> DisasContext *ctx, int *is_branch)
> break;
> case OPC_DIV_G_2F:
> case OPC_DIVU_G_2F:
> - case OPC_MULT_G_2F:
> case OPC_MULTU_G_2F:
> case OPC_MOD_G_2F:
> case OPC_MODU_G_2F:
> check_insn(env, ctx, INSN_LOONGSON2F);
> gen_loongson_integer(ctx, op1, rd, rs, rt);
> break;
> + case OPC_MULT_G_2F:
> + if (!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);
> + gen_LMI(env, ctx, op1, rs, rt, rd);
> +#endif
> + }
> + break;
> #if defined(TARGET_MIPS64)
> case OPC_DCLO:
> case OPC_DCLZ:
> @@ -11892,7 +12449,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:
> @@ -11901,6 +12457,39 @@ 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);
> + gen_LMI(env, ctx, op1, rs, rt, rd);
> + }
> + break;
> + case OPC_SEQ:
> + check_mips_64(ctx);
> + gen_seqsne(ctx, op1, rd, rs, rt);
> + break;
> + case OPC_SNE:
> + check_mips_64(ctx);
> + gen_seqsne(ctx, op1, rd, rs, rt);
> + break;
> + case OPC_SEQI:
> + check_mips_64(ctx);
> + gen_set_imm(env, op1, rt, rs, imm10);
> + break;
> + case OPC_SNEI:
> + check_mips_64(ctx);
> + gen_set_imm(env, op1, rt, rs, imm10);
> + break;
> + case OPC_POP:
> + insn_opc_pop(ctx, env, op1, rd, rs, rt);
> + break;
> + case OPC_DPOP:
> + check_mips_64(ctx);
> + insn_opc_dpop(ctx, env, op1, rd, rs, rt);
> + break;
> #endif
> default: /* Invalid */
> MIPS_INVAL("special2");
> @@ -12192,10 +12781,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);
> @@ -12584,6 +13195,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, Reg.MPL0), "MPL0");
> + mpl1 = tcg_global_mem_new(TCG_AREG0,
> + offsetof(CPUState, Reg.MPL1), "MPL1");
> + mpl2 = tcg_global_mem_new(TCG_AREG0,
> + offsetof(CPUState, Reg.MPL2), "MPL2");
> + p0 = tcg_global_mem_new(TCG_AREG0,
> + offsetof(CPUState, Reg.P0), "P0");
> + p1 = tcg_global_mem_new(TCG_AREG0,
> + offsetof(CPUState, Reg.P1), "P1");
> + p2 = tcg_global_mem_new(TCG_AREG0,
> + offsetof(CPUState, Reg.P2), "P2");
> bcond = tcg_global_mem_new(TCG_AREG0,
> offsetof(CPUState, bcond), "bcond");
> btarget = tcg_global_mem_new(TCG_AREG0,
> @@ -12607,6 +13230,18 @@ static void mips_tcg_init(void)
>
> #include "translate_init.c"
>
> +#if defined(TARGET_MIPS64)
> +
> +static void set_cvmctl_register(CPUMIPSState *env)
> +{
> + env->CvmCtlRegister.cvmctl = env->CvmCtlRegister.cvmctl
> + ^ env->CvmCtlRegister.cvmctl;
> + env->CvmCtlRegister.cvmctl =
> FUSE_START_BIT(env->CvmCtlRegister.cvmctl);
> + env->CvmCtlRegister.cvmctl = KASUMI(env->CvmCtlRegister.cvmctl);
> + env->CvmCtlRegister.cvmctl = IPPCI(env->CvmCtlRegister.cvmctl);
> + env->CvmCtlRegister.cvmctl = IPTI(env->CvmCtlRegister.cvmctl);
> +}
> +#endif
> CPUMIPSState *cpu_mips_init (const char *cpu_model)
> {
> CPUMIPSState *env;
> @@ -12619,6 +13254,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