fix conflicts
This commit is contained in:
@ -1,3 +0,0 @@
|
||||
obj-y += translate.o dsp_helper.o op_helper.o lmi_helper.o helper.o cpu.o
|
||||
obj-y += msa_helper.o
|
||||
obj-y += unicorn.o
|
@ -1,51 +0,0 @@
|
||||
Unsolved issues/bugs in the mips/mipsel backend
|
||||
-----------------------------------------------
|
||||
|
||||
General
|
||||
-------
|
||||
- Unimplemented ASEs:
|
||||
- MDMX
|
||||
- SmartMIPS
|
||||
- microMIPS DSP r1 & r2 encodings
|
||||
- MT ASE only partially implemented and not functional
|
||||
- Shadow register support only partially implemented,
|
||||
lacks set switching on interrupt/exception.
|
||||
- 34K ITC not implemented.
|
||||
- A general lack of documentation, especially for technical internals.
|
||||
Existing documentation is x86-centric.
|
||||
- Reverse endianness bit not implemented
|
||||
- The TLB emulation is very inefficient:
|
||||
QEMU's softmmu implements a x86-style MMU, with separate entries
|
||||
for read/write/execute, a TLB index which is just a modulo of the
|
||||
virtual address, and a set of TLBs for each user/kernel/supervisor
|
||||
MMU mode.
|
||||
MIPS has a single entry for read/write/execute and only one MMU mode.
|
||||
But it is fully associative with randomized entry indices, and uses
|
||||
up to 256 ASID tags as additional matching criterion (which roughly
|
||||
equates to 256 MMU modes). It also has a global flag which causes
|
||||
entries to match regardless of ASID.
|
||||
To cope with these differences, QEMU currently flushes the TLB at
|
||||
each ASID change. Using the MMU modes to implement ASIDs hinges on
|
||||
implementing the global bit efficiently.
|
||||
- save/restore of the CPU state is not implemented (see machine.c).
|
||||
|
||||
MIPS64
|
||||
------
|
||||
- Userland emulation (both n32 and n64) not functional.
|
||||
|
||||
"Generic" 4Kc system emulation
|
||||
------------------------------
|
||||
- Doesn't correspond to any real hardware. Should be removed some day,
|
||||
U-Boot is the last remaining user.
|
||||
|
||||
PICA 61 system emulation
|
||||
------------------------
|
||||
- No framebuffer support yet.
|
||||
|
||||
MALTA system emulation
|
||||
----------------------
|
||||
- We fake firmware support instead of doing the real thing
|
||||
- Real firmware (YAMON) falls over when trying to init RAM, presumably
|
||||
due to lacking system controller emulation.
|
||||
- Bonito system controller not implemented
|
||||
- MSC1 system controller not implemented
|
@ -1,84 +0,0 @@
|
||||
/*
|
||||
* QEMU MIPS CPU
|
||||
*
|
||||
* Copyright (c) 2012 SUSE LINUX Products GmbH
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <http://www.gnu.org/licenses/lgpl-2.1.html>
|
||||
*/
|
||||
#ifndef QEMU_MIPS_CPU_QOM_H
|
||||
#define QEMU_MIPS_CPU_QOM_H
|
||||
|
||||
#include "qom/cpu.h"
|
||||
|
||||
#ifdef TARGET_MIPS64
|
||||
#define TYPE_MIPS_CPU "mips64-cpu"
|
||||
#else
|
||||
#define TYPE_MIPS_CPU "mips-cpu"
|
||||
#endif
|
||||
|
||||
#define MIPS_CPU_CLASS(uc, klass) \
|
||||
OBJECT_CLASS_CHECK(uc, MIPSCPUClass, (klass), TYPE_MIPS_CPU)
|
||||
#define MIPS_CPU(uc, obj) ((MIPSCPU *)obj)
|
||||
#define MIPS_CPU_GET_CLASS(uc, obj) \
|
||||
OBJECT_GET_CLASS(uc, MIPSCPUClass, (obj), TYPE_MIPS_CPU)
|
||||
|
||||
/**
|
||||
* MIPSCPUClass:
|
||||
* @parent_realize: The parent class' realize handler.
|
||||
* @parent_reset: The parent class' reset handler.
|
||||
*
|
||||
* A MIPS CPU model.
|
||||
*/
|
||||
typedef struct MIPSCPUClass {
|
||||
/*< private >*/
|
||||
CPUClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
DeviceRealize parent_realize;
|
||||
void (*parent_reset)(CPUState *cpu);
|
||||
} MIPSCPUClass;
|
||||
|
||||
/**
|
||||
* MIPSCPU:
|
||||
* @env: #CPUMIPSState
|
||||
*
|
||||
* A MIPS CPU.
|
||||
*/
|
||||
typedef struct MIPSCPU {
|
||||
/*< private >*/
|
||||
CPUState parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
CPUMIPSState env;
|
||||
} MIPSCPU;
|
||||
|
||||
static inline MIPSCPU *mips_env_get_cpu(CPUMIPSState *env)
|
||||
{
|
||||
return container_of(env, MIPSCPU, env);
|
||||
}
|
||||
|
||||
#define ENV_GET_CPU(e) CPU(mips_env_get_cpu(e))
|
||||
|
||||
#define ENV_OFFSET offsetof(MIPSCPU, env)
|
||||
|
||||
void mips_cpu_do_interrupt(CPUState *cpu);
|
||||
bool mips_cpu_exec_interrupt(CPUState *cpu, int int_req);
|
||||
hwaddr mips_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
|
||||
int mips_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
int mips_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
void mips_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
|
||||
int is_write, int is_user, uintptr_t retaddr);
|
||||
|
||||
#endif
|
@ -1,170 +0,0 @@
|
||||
/*
|
||||
* QEMU MIPS CPU
|
||||
*
|
||||
* Copyright (c) 2012 SUSE LINUX Products GmbH
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <http://www.gnu.org/licenses/lgpl-2.1.html>
|
||||
*/
|
||||
|
||||
#include "cpu.h"
|
||||
#include "qemu-common.h"
|
||||
#include "hw/mips/mips.h"
|
||||
|
||||
|
||||
static void mips_cpu_set_pc(CPUState *cs, vaddr value)
|
||||
{
|
||||
MIPSCPU *cpu = MIPS_CPU(cs->uc, cs);
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
|
||||
env->active_tc.PC = value & ~(target_ulong)1;
|
||||
if (value & 1) {
|
||||
env->hflags |= MIPS_HFLAG_M16;
|
||||
} else {
|
||||
env->hflags &= ~(MIPS_HFLAG_M16);
|
||||
}
|
||||
}
|
||||
|
||||
static void mips_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
|
||||
{
|
||||
MIPSCPU *cpu = MIPS_CPU(cs->uc, cs);
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
|
||||
env->active_tc.PC = tb->pc;
|
||||
env->hflags &= ~MIPS_HFLAG_BMASK;
|
||||
env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
|
||||
}
|
||||
|
||||
static bool mips_cpu_has_work(CPUState *cs)
|
||||
{
|
||||
MIPSCPU *cpu = MIPS_CPU(cs->uc, cs);
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
bool has_work = false;
|
||||
|
||||
/* It is implementation dependent if non-enabled interrupts
|
||||
wake-up the CPU, however most of the implementations only
|
||||
check for interrupts that can be taken. */
|
||||
if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
|
||||
cpu_mips_hw_interrupts_pending(env)) {
|
||||
has_work = true;
|
||||
}
|
||||
|
||||
/* MIPS-MT has the ability to halt the CPU. */
|
||||
if (env->CP0_Config3 & (1 << CP0C3_MT)) {
|
||||
/* The QEMU model will issue an _WAKE request whenever the CPUs
|
||||
should be woken up. */
|
||||
if (cs->interrupt_request & CPU_INTERRUPT_WAKE) {
|
||||
has_work = true;
|
||||
}
|
||||
|
||||
if (!mips_vpe_active(env)) {
|
||||
has_work = false;
|
||||
}
|
||||
}
|
||||
return has_work;
|
||||
}
|
||||
|
||||
/* CPUClass::reset() */
|
||||
static void mips_cpu_reset(CPUState *s)
|
||||
{
|
||||
MIPSCPU *cpu = MIPS_CPU(s->uc, s);
|
||||
MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(s->uc, cpu);
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
|
||||
mcc->parent_reset(s);
|
||||
|
||||
memset(env, 0, offsetof(CPUMIPSState, mvp));
|
||||
tlb_flush(s, 1);
|
||||
|
||||
cpu_state_reset(env);
|
||||
}
|
||||
|
||||
static int mips_cpu_realizefn(struct uc_struct *uc, DeviceState *dev, Error **errp)
|
||||
{
|
||||
CPUState *cs = CPU(dev);
|
||||
MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(uc, dev);
|
||||
|
||||
cpu_reset(cs);
|
||||
qemu_init_vcpu(cs);
|
||||
|
||||
mcc->parent_realize(uc, dev, errp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mips_cpu_initfn(struct uc_struct *uc, Object *obj, void *opaque)
|
||||
{
|
||||
CPUState *cs = CPU(obj);
|
||||
MIPSCPU *cpu = MIPS_CPU(uc, obj);
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
|
||||
cs->env_ptr = env;
|
||||
cpu_exec_init(env, opaque);
|
||||
|
||||
if (tcg_enabled(uc)) {
|
||||
mips_tcg_init(uc);
|
||||
}
|
||||
}
|
||||
|
||||
static void mips_cpu_class_init(struct uc_struct *uc, ObjectClass *c, void *data)
|
||||
{
|
||||
MIPSCPUClass *mcc = MIPS_CPU_CLASS(uc, c);
|
||||
CPUClass *cc = CPU_CLASS(uc, c);
|
||||
DeviceClass *dc = DEVICE_CLASS(uc, c);
|
||||
|
||||
mcc->parent_realize = dc->realize;
|
||||
dc->realize = mips_cpu_realizefn;
|
||||
|
||||
mcc->parent_reset = cc->reset;
|
||||
cc->reset = mips_cpu_reset;
|
||||
|
||||
cc->has_work = mips_cpu_has_work;
|
||||
cc->do_interrupt = mips_cpu_do_interrupt;
|
||||
cc->cpu_exec_interrupt = mips_cpu_exec_interrupt;
|
||||
cc->set_pc = mips_cpu_set_pc;
|
||||
cc->synchronize_from_tb = mips_cpu_synchronize_from_tb;
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
cc->handle_mmu_fault = mips_cpu_handle_mmu_fault;
|
||||
#else
|
||||
cc->do_unassigned_access = mips_cpu_unassigned_access;
|
||||
cc->do_unaligned_access = mips_cpu_do_unaligned_access;
|
||||
cc->get_phys_page_debug = mips_cpu_get_phys_page_debug;
|
||||
#endif
|
||||
}
|
||||
|
||||
void mips_cpu_register_types(void *opaque)
|
||||
{
|
||||
const TypeInfo mips_cpu_type_info = {
|
||||
TYPE_MIPS_CPU,
|
||||
TYPE_CPU,
|
||||
|
||||
sizeof(MIPSCPUClass),
|
||||
sizeof(MIPSCPU),
|
||||
opaque,
|
||||
|
||||
mips_cpu_initfn,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
NULL,
|
||||
|
||||
mips_cpu_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
false,
|
||||
};
|
||||
|
||||
type_register_static(opaque, &mips_cpu_type_info);
|
||||
}
|
@ -1,901 +0,0 @@
|
||||
#if !defined (__MIPS_CPU_H__)
|
||||
#define __MIPS_CPU_H__
|
||||
|
||||
//#define DEBUG_OP
|
||||
|
||||
#define ALIGNED_ONLY
|
||||
#define TARGET_HAS_ICE 1
|
||||
|
||||
#define ELF_MACHINE EM_MIPS
|
||||
|
||||
#define CPUArchState struct CPUMIPSState
|
||||
|
||||
#include "config.h"
|
||||
#include "qemu-common.h"
|
||||
#include "mips-defs.h"
|
||||
#include "exec/cpu-defs.h"
|
||||
#include "fpu/softfloat.h"
|
||||
|
||||
struct CPUMIPSState;
|
||||
|
||||
typedef struct r4k_tlb_t r4k_tlb_t;
|
||||
struct r4k_tlb_t {
|
||||
target_ulong VPN;
|
||||
uint32_t PageMask;
|
||||
uint_fast8_t ASID;
|
||||
uint_fast16_t G:1;
|
||||
uint_fast16_t C0:3;
|
||||
uint_fast16_t C1:3;
|
||||
uint_fast16_t V0:1;
|
||||
uint_fast16_t V1:1;
|
||||
uint_fast16_t D0:1;
|
||||
uint_fast16_t D1:1;
|
||||
uint_fast16_t XI0:1;
|
||||
uint_fast16_t XI1:1;
|
||||
uint_fast16_t RI0:1;
|
||||
uint_fast16_t RI1:1;
|
||||
uint_fast16_t EHINV:1;
|
||||
target_ulong PFN[2];
|
||||
};
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
typedef struct CPUMIPSTLBContext CPUMIPSTLBContext;
|
||||
struct CPUMIPSTLBContext {
|
||||
uint32_t nb_tlb;
|
||||
uint32_t tlb_in_use;
|
||||
int (*map_address) (struct CPUMIPSState *env, hwaddr *physical, int *prot, target_ulong address, int rw, int access_type);
|
||||
void (*helper_tlbwi)(struct CPUMIPSState *env);
|
||||
void (*helper_tlbwr)(struct CPUMIPSState *env);
|
||||
void (*helper_tlbp)(struct CPUMIPSState *env);
|
||||
void (*helper_tlbr)(struct CPUMIPSState *env);
|
||||
void (*helper_tlbinv)(struct CPUMIPSState *env);
|
||||
void (*helper_tlbinvf)(struct CPUMIPSState *env);
|
||||
union {
|
||||
struct {
|
||||
r4k_tlb_t tlb[MIPS_TLB_MAX];
|
||||
} r4k;
|
||||
} mmu;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* MSA Context */
|
||||
#define MSA_WRLEN (128)
|
||||
|
||||
enum CPUMIPSMSADataFormat {
|
||||
DF_BYTE = 0,
|
||||
DF_HALF,
|
||||
DF_WORD,
|
||||
DF_DOUBLE
|
||||
};
|
||||
|
||||
typedef union wr_t wr_t;
|
||||
union wr_t {
|
||||
int8_t b[MSA_WRLEN/8];
|
||||
int16_t h[MSA_WRLEN/16];
|
||||
int32_t w[MSA_WRLEN/32];
|
||||
int64_t d[MSA_WRLEN/64];
|
||||
};
|
||||
|
||||
typedef union fpr_t fpr_t;
|
||||
union fpr_t {
|
||||
float64 fd; /* ieee double precision */
|
||||
float32 fs[2];/* ieee single precision */
|
||||
uint64_t d; /* binary double fixed-point */
|
||||
uint32_t w[2]; /* binary single fixed-point */
|
||||
/* FPU/MSA register mapping is not tested on big-endian hosts. */
|
||||
wr_t wr; /* vector data */
|
||||
};
|
||||
/* define FP_ENDIAN_IDX to access the same location
|
||||
* in the fpr_t union regardless of the host endianness
|
||||
*/
|
||||
#if defined(HOST_WORDS_BIGENDIAN)
|
||||
# define FP_ENDIAN_IDX 1
|
||||
#else
|
||||
# define FP_ENDIAN_IDX 0
|
||||
#endif
|
||||
|
||||
typedef struct CPUMIPSFPUContext CPUMIPSFPUContext;
|
||||
struct CPUMIPSFPUContext {
|
||||
/* Floating point registers */
|
||||
fpr_t fpr[32];
|
||||
float_status fp_status;
|
||||
/* fpu implementation/revision register (fir) */
|
||||
uint32_t fcr0;
|
||||
#define FCR0_UFRP 28
|
||||
#define FCR0_F64 22
|
||||
#define FCR0_L 21
|
||||
#define FCR0_W 20
|
||||
#define FCR0_3D 19
|
||||
#define FCR0_PS 18
|
||||
#define FCR0_D 17
|
||||
#define FCR0_S 16
|
||||
#define FCR0_PRID 8
|
||||
#define FCR0_REV 0
|
||||
/* fcsr */
|
||||
uint32_t fcr31;
|
||||
#define SET_FP_COND(num,env) do { ((env).fcr31) |= ((num) ? ((int)(1U << (((num) + 24) & 0x1f))) : (1 << 23)); } while(0)
|
||||
#define CLEAR_FP_COND(num,env) do { ((env).fcr31) &= ~((num) ? ((int)(1U << (((num) + 24) & 0x1f))) : (1 << 23)); } while(0)
|
||||
#define GET_FP_COND(env) ((((env).fcr31 >> 24) & 0xfe) | (((env).fcr31 >> 23) & 0x1))
|
||||
#define GET_FP_CAUSE(reg) (((reg) >> 12) & 0x3f)
|
||||
#define GET_FP_ENABLE(reg) (((reg) >> 7) & 0x1f)
|
||||
#define GET_FP_FLAGS(reg) (((reg) >> 2) & 0x1f)
|
||||
#define SET_FP_CAUSE(reg,v) do { (reg) = ((reg) & ~(0x3f << 12)) | ((v & 0x3f) << 12); } while(0)
|
||||
#define SET_FP_ENABLE(reg,v) do { (reg) = ((reg) & ~(0x1f << 7)) | ((v & 0x1f) << 7); } while(0)
|
||||
#define SET_FP_FLAGS(reg,v) do { (reg) = ((reg) & ~(0x1f << 2)) | ((v & 0x1f) << 2); } while(0)
|
||||
#define UPDATE_FP_FLAGS(reg,v) do { (reg) |= ((v & 0x1f) << 2); } while(0)
|
||||
#define FP_INEXACT 1
|
||||
#define FP_UNDERFLOW 2
|
||||
#define FP_OVERFLOW 4
|
||||
#define FP_DIV0 8
|
||||
#define FP_INVALID 16
|
||||
#define FP_UNIMPLEMENTED 32
|
||||
};
|
||||
|
||||
#define NB_MMU_MODES 3
|
||||
|
||||
typedef struct CPUMIPSMVPContext CPUMIPSMVPContext;
|
||||
struct CPUMIPSMVPContext {
|
||||
int32_t CP0_MVPControl;
|
||||
#define CP0MVPCo_CPA 3
|
||||
#define CP0MVPCo_STLB 2
|
||||
#define CP0MVPCo_VPC 1
|
||||
#define CP0MVPCo_EVP 0
|
||||
int32_t CP0_MVPConf0;
|
||||
#define CP0MVPC0_M 31
|
||||
#define CP0MVPC0_TLBS 29
|
||||
#define CP0MVPC0_GS 28
|
||||
#define CP0MVPC0_PCP 27
|
||||
#define CP0MVPC0_PTLBE 16
|
||||
#define CP0MVPC0_TCA 15
|
||||
#define CP0MVPC0_PVPE 10
|
||||
#define CP0MVPC0_PTC 0
|
||||
int32_t CP0_MVPConf1;
|
||||
#define CP0MVPC1_CIM 31
|
||||
#define CP0MVPC1_CIF 30
|
||||
#define CP0MVPC1_PCX 20
|
||||
#define CP0MVPC1_PCP2 10
|
||||
#define CP0MVPC1_PCP1 0
|
||||
};
|
||||
|
||||
typedef struct mips_def_t mips_def_t;
|
||||
|
||||
#define MIPS_SHADOW_SET_MAX 16
|
||||
#define MIPS_TC_MAX 5
|
||||
#define MIPS_FPU_MAX 1
|
||||
#define MIPS_DSP_ACC 4
|
||||
#define MIPS_KSCRATCH_NUM 6
|
||||
|
||||
typedef struct TCState TCState;
|
||||
struct TCState {
|
||||
target_ulong gpr[32];
|
||||
target_ulong PC;
|
||||
target_ulong HI[MIPS_DSP_ACC];
|
||||
target_ulong LO[MIPS_DSP_ACC];
|
||||
target_ulong ACX[MIPS_DSP_ACC];
|
||||
target_ulong DSPControl;
|
||||
int32_t CP0_TCStatus;
|
||||
#define CP0TCSt_TCU3 31
|
||||
#define CP0TCSt_TCU2 30
|
||||
#define CP0TCSt_TCU1 29
|
||||
#define CP0TCSt_TCU0 28
|
||||
#define CP0TCSt_TMX 27
|
||||
#define CP0TCSt_RNST 23
|
||||
#define CP0TCSt_TDS 21
|
||||
#define CP0TCSt_DT 20
|
||||
#define CP0TCSt_DA 15
|
||||
#define CP0TCSt_A 13
|
||||
#define CP0TCSt_TKSU 11
|
||||
#define CP0TCSt_IXMT 10
|
||||
#define CP0TCSt_TASID 0
|
||||
int32_t CP0_TCBind;
|
||||
#define CP0TCBd_CurTC 21
|
||||
#define CP0TCBd_TBE 17
|
||||
#define CP0TCBd_CurVPE 0
|
||||
target_ulong CP0_TCHalt;
|
||||
target_ulong CP0_TCContext;
|
||||
target_ulong CP0_TCSchedule;
|
||||
target_ulong CP0_TCScheFBack;
|
||||
int32_t CP0_Debug_tcstatus;
|
||||
target_ulong CP0_UserLocal;
|
||||
|
||||
int32_t msacsr;
|
||||
|
||||
#define MSACSR_FS 24
|
||||
#define MSACSR_FS_MASK (1 << MSACSR_FS)
|
||||
#define MSACSR_NX 18
|
||||
#define MSACSR_NX_MASK (1 << MSACSR_NX)
|
||||
#define MSACSR_CEF 2
|
||||
#define MSACSR_CEF_MASK (0xffff << MSACSR_CEF)
|
||||
#define MSACSR_RM 0
|
||||
#define MSACSR_RM_MASK (0x3 << MSACSR_RM)
|
||||
#define MSACSR_MASK (MSACSR_RM_MASK | MSACSR_CEF_MASK | MSACSR_NX_MASK | \
|
||||
MSACSR_FS_MASK)
|
||||
|
||||
float_status msa_fp_status;
|
||||
};
|
||||
|
||||
typedef struct CPUMIPSState CPUMIPSState;
|
||||
struct CPUMIPSState {
|
||||
TCState active_tc;
|
||||
CPUMIPSFPUContext active_fpu;
|
||||
|
||||
uint32_t current_tc;
|
||||
uint32_t current_fpu;
|
||||
|
||||
uint32_t SEGBITS;
|
||||
uint32_t PABITS;
|
||||
target_ulong SEGMask;
|
||||
target_ulong PAMask;
|
||||
|
||||
int32_t msair;
|
||||
#define MSAIR_ProcID 8
|
||||
#define MSAIR_Rev 0
|
||||
|
||||
int32_t CP0_Index;
|
||||
/* CP0_MVP* are per MVP registers. */
|
||||
int32_t CP0_Random;
|
||||
int32_t CP0_VPEControl;
|
||||
#define CP0VPECo_YSI 21
|
||||
#define CP0VPECo_GSI 20
|
||||
#define CP0VPECo_EXCPT 16
|
||||
#define CP0VPECo_TE 15
|
||||
#define CP0VPECo_TargTC 0
|
||||
int32_t CP0_VPEConf0;
|
||||
#define CP0VPEC0_M 31
|
||||
#define CP0VPEC0_XTC 21
|
||||
#define CP0VPEC0_TCS 19
|
||||
#define CP0VPEC0_SCS 18
|
||||
#define CP0VPEC0_DSC 17
|
||||
#define CP0VPEC0_ICS 16
|
||||
#define CP0VPEC0_MVP 1
|
||||
#define CP0VPEC0_VPA 0
|
||||
int32_t CP0_VPEConf1;
|
||||
#define CP0VPEC1_NCX 20
|
||||
#define CP0VPEC1_NCP2 10
|
||||
#define CP0VPEC1_NCP1 0
|
||||
target_ulong CP0_YQMask;
|
||||
target_ulong CP0_VPESchedule;
|
||||
target_ulong CP0_VPEScheFBack;
|
||||
int32_t CP0_VPEOpt;
|
||||
#define CP0VPEOpt_IWX7 15
|
||||
#define CP0VPEOpt_IWX6 14
|
||||
#define CP0VPEOpt_IWX5 13
|
||||
#define CP0VPEOpt_IWX4 12
|
||||
#define CP0VPEOpt_IWX3 11
|
||||
#define CP0VPEOpt_IWX2 10
|
||||
#define CP0VPEOpt_IWX1 9
|
||||
#define CP0VPEOpt_IWX0 8
|
||||
#define CP0VPEOpt_DWX7 7
|
||||
#define CP0VPEOpt_DWX6 6
|
||||
#define CP0VPEOpt_DWX5 5
|
||||
#define CP0VPEOpt_DWX4 4
|
||||
#define CP0VPEOpt_DWX3 3
|
||||
#define CP0VPEOpt_DWX2 2
|
||||
#define CP0VPEOpt_DWX1 1
|
||||
#define CP0VPEOpt_DWX0 0
|
||||
target_ulong CP0_EntryLo0;
|
||||
target_ulong CP0_EntryLo1;
|
||||
#if defined(TARGET_MIPS64)
|
||||
# define CP0EnLo_RI 63
|
||||
# define CP0EnLo_XI 62
|
||||
#else
|
||||
# define CP0EnLo_RI 31
|
||||
# define CP0EnLo_XI 30
|
||||
#endif
|
||||
target_ulong CP0_Context;
|
||||
target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM];
|
||||
int32_t CP0_PageMask;
|
||||
int32_t CP0_PageGrain_rw_bitmask;
|
||||
int32_t CP0_PageGrain;
|
||||
#define CP0PG_RIE 31
|
||||
#define CP0PG_XIE 30
|
||||
#define CP0PG_IEC 27
|
||||
int32_t CP0_Wired;
|
||||
int32_t CP0_SRSConf0_rw_bitmask;
|
||||
int32_t CP0_SRSConf0;
|
||||
#define CP0SRSC0_M 31
|
||||
#define CP0SRSC0_SRS3 20
|
||||
#define CP0SRSC0_SRS2 10
|
||||
#define CP0SRSC0_SRS1 0
|
||||
int32_t CP0_SRSConf1_rw_bitmask;
|
||||
int32_t CP0_SRSConf1;
|
||||
#define CP0SRSC1_M 31
|
||||
#define CP0SRSC1_SRS6 20
|
||||
#define CP0SRSC1_SRS5 10
|
||||
#define CP0SRSC1_SRS4 0
|
||||
int32_t CP0_SRSConf2_rw_bitmask;
|
||||
int32_t CP0_SRSConf2;
|
||||
#define CP0SRSC2_M 31
|
||||
#define CP0SRSC2_SRS9 20
|
||||
#define CP0SRSC2_SRS8 10
|
||||
#define CP0SRSC2_SRS7 0
|
||||
int32_t CP0_SRSConf3_rw_bitmask;
|
||||
int32_t CP0_SRSConf3;
|
||||
#define CP0SRSC3_M 31
|
||||
#define CP0SRSC3_SRS12 20
|
||||
#define CP0SRSC3_SRS11 10
|
||||
#define CP0SRSC3_SRS10 0
|
||||
int32_t CP0_SRSConf4_rw_bitmask;
|
||||
int32_t CP0_SRSConf4;
|
||||
#define CP0SRSC4_SRS15 20
|
||||
#define CP0SRSC4_SRS14 10
|
||||
#define CP0SRSC4_SRS13 0
|
||||
int32_t CP0_HWREna;
|
||||
target_ulong CP0_BadVAddr;
|
||||
uint32_t CP0_BadInstr;
|
||||
uint32_t CP0_BadInstrP;
|
||||
int32_t CP0_Count;
|
||||
target_ulong CP0_EntryHi;
|
||||
#define CP0EnHi_EHINV 10
|
||||
int32_t CP0_Compare;
|
||||
int32_t CP0_Status;
|
||||
#define CP0St_CU3 31
|
||||
#define CP0St_CU2 30
|
||||
#define CP0St_CU1 29
|
||||
#define CP0St_CU0 28
|
||||
#define CP0St_RP 27
|
||||
#define CP0St_FR 26
|
||||
#define CP0St_RE 25
|
||||
#define CP0St_MX 24
|
||||
#define CP0St_PX 23
|
||||
#define CP0St_BEV 22
|
||||
#define CP0St_TS 21
|
||||
#define CP0St_SR 20
|
||||
#define CP0St_NMI 19
|
||||
#define CP0St_IM 8
|
||||
#define CP0St_KX 7
|
||||
#define CP0St_SX 6
|
||||
#define CP0St_UX 5
|
||||
#define CP0St_KSU 3
|
||||
#define CP0St_ERL 2
|
||||
#define CP0St_EXL 1
|
||||
#define CP0St_IE 0
|
||||
int32_t CP0_IntCtl;
|
||||
#define CP0IntCtl_IPTI 29
|
||||
#define CP0IntCtl_IPPC1 26
|
||||
#define CP0IntCtl_VS 5
|
||||
int32_t CP0_SRSCtl;
|
||||
#define CP0SRSCtl_HSS 26
|
||||
#define CP0SRSCtl_EICSS 18
|
||||
#define CP0SRSCtl_ESS 12
|
||||
#define CP0SRSCtl_PSS 6
|
||||
#define CP0SRSCtl_CSS 0
|
||||
int32_t CP0_SRSMap;
|
||||
#define CP0SRSMap_SSV7 28
|
||||
#define CP0SRSMap_SSV6 24
|
||||
#define CP0SRSMap_SSV5 20
|
||||
#define CP0SRSMap_SSV4 16
|
||||
#define CP0SRSMap_SSV3 12
|
||||
#define CP0SRSMap_SSV2 8
|
||||
#define CP0SRSMap_SSV1 4
|
||||
#define CP0SRSMap_SSV0 0
|
||||
int32_t CP0_Cause;
|
||||
#define CP0Ca_BD 31
|
||||
#define CP0Ca_TI 30
|
||||
#define CP0Ca_CE 28
|
||||
#define CP0Ca_DC 27
|
||||
#define CP0Ca_PCI 26
|
||||
#define CP0Ca_IV 23
|
||||
#define CP0Ca_WP 22
|
||||
#define CP0Ca_IP 8
|
||||
#define CP0Ca_IP_mask 0x0000FF00
|
||||
#define CP0Ca_EC 2
|
||||
target_ulong CP0_EPC;
|
||||
int32_t CP0_PRid;
|
||||
int32_t CP0_EBase;
|
||||
int32_t CP0_Config0;
|
||||
#define CP0C0_M 31
|
||||
#define CP0C0_K23 28
|
||||
#define CP0C0_KU 25
|
||||
#define CP0C0_MDU 20
|
||||
#define CP0C0_MM 17
|
||||
#define CP0C0_BM 16
|
||||
#define CP0C0_BE 15
|
||||
#define CP0C0_AT 13
|
||||
#define CP0C0_AR 10
|
||||
#define CP0C0_MT 7
|
||||
#define CP0C0_VI 3
|
||||
#define CP0C0_K0 0
|
||||
int32_t CP0_Config1;
|
||||
#define CP0C1_M 31
|
||||
#define CP0C1_MMU 25
|
||||
#define CP0C1_IS 22
|
||||
#define CP0C1_IL 19
|
||||
#define CP0C1_IA 16
|
||||
#define CP0C1_DS 13
|
||||
#define CP0C1_DL 10
|
||||
#define CP0C1_DA 7
|
||||
#define CP0C1_C2 6
|
||||
#define CP0C1_MD 5
|
||||
#define CP0C1_PC 4
|
||||
#define CP0C1_WR 3
|
||||
#define CP0C1_CA 2
|
||||
#define CP0C1_EP 1
|
||||
#define CP0C1_FP 0
|
||||
int32_t CP0_Config2;
|
||||
#define CP0C2_M 31
|
||||
#define CP0C2_TU 28
|
||||
#define CP0C2_TS 24
|
||||
#define CP0C2_TL 20
|
||||
#define CP0C2_TA 16
|
||||
#define CP0C2_SU 12
|
||||
#define CP0C2_SS 8
|
||||
#define CP0C2_SL 4
|
||||
#define CP0C2_SA 0
|
||||
int32_t CP0_Config3;
|
||||
#define CP0C3_M 31
|
||||
#define CP0C3_BPG 30
|
||||
#define CP0C3_CMCGR 29
|
||||
#define CP0C3_MSAP 28
|
||||
#define CP0C3_BP 27
|
||||
#define CP0C3_BI 26
|
||||
#define CP0C3_IPLW 21
|
||||
#define CP0C3_MMAR 18
|
||||
#define CP0C3_MCU 17
|
||||
#define CP0C3_ISA_ON_EXC 16
|
||||
#define CP0C3_ISA 14
|
||||
#define CP0C3_ULRI 13
|
||||
#define CP0C3_RXI 12
|
||||
#define CP0C3_DSP2P 11
|
||||
#define CP0C3_DSPP 10
|
||||
#define CP0C3_LPA 7
|
||||
#define CP0C3_VEIC 6
|
||||
#define CP0C3_VInt 5
|
||||
#define CP0C3_SP 4
|
||||
#define CP0C3_CDMM 3
|
||||
#define CP0C3_MT 2
|
||||
#define CP0C3_SM 1
|
||||
#define CP0C3_TL 0
|
||||
uint32_t CP0_Config4;
|
||||
uint32_t CP0_Config4_rw_bitmask;
|
||||
#define CP0C4_M 31
|
||||
#define CP0C4_IE 29
|
||||
#define CP0C4_KScrExist 16
|
||||
#define CP0C4_MMUExtDef 14
|
||||
#define CP0C4_FTLBPageSize 8
|
||||
#define CP0C4_FTLBWays 4
|
||||
#define CP0C4_FTLBSets 0
|
||||
#define CP0C4_MMUSizeExt 0
|
||||
uint32_t CP0_Config5;
|
||||
uint32_t CP0_Config5_rw_bitmask;
|
||||
#define CP0C5_M 31
|
||||
#define CP0C5_K 30
|
||||
#define CP0C5_CV 29
|
||||
#define CP0C5_EVA 28
|
||||
#define CP0C5_MSAEn 27
|
||||
#define CP0C5_SBRI 6
|
||||
#define CP0C5_UFR 2
|
||||
#define CP0C5_NFExists 0
|
||||
int32_t CP0_Config6;
|
||||
int32_t CP0_Config7;
|
||||
/* XXX: Maybe make LLAddr per-TC? */
|
||||
target_ulong lladdr;
|
||||
target_ulong llval;
|
||||
target_ulong llnewval;
|
||||
target_ulong llreg;
|
||||
target_ulong CP0_LLAddr_rw_bitmask;
|
||||
int CP0_LLAddr_shift;
|
||||
target_ulong CP0_WatchLo[8];
|
||||
int32_t CP0_WatchHi[8];
|
||||
target_ulong CP0_XContext;
|
||||
int32_t CP0_Framemask;
|
||||
int32_t CP0_Debug;
|
||||
#define CP0DB_DBD 31
|
||||
#define CP0DB_DM 30
|
||||
#define CP0DB_LSNM 28
|
||||
#define CP0DB_Doze 27
|
||||
#define CP0DB_Halt 26
|
||||
#define CP0DB_CNT 25
|
||||
#define CP0DB_IBEP 24
|
||||
#define CP0DB_DBEP 21
|
||||
#define CP0DB_IEXI 20
|
||||
#define CP0DB_VER 15
|
||||
#define CP0DB_DEC 10
|
||||
#define CP0DB_SSt 8
|
||||
#define CP0DB_DINT 5
|
||||
#define CP0DB_DIB 4
|
||||
#define CP0DB_DDBS 3
|
||||
#define CP0DB_DDBL 2
|
||||
#define CP0DB_DBp 1
|
||||
#define CP0DB_DSS 0
|
||||
target_ulong CP0_DEPC;
|
||||
int32_t CP0_Performance0;
|
||||
int32_t CP0_TagLo;
|
||||
int32_t CP0_DataLo;
|
||||
int32_t CP0_TagHi;
|
||||
int32_t CP0_DataHi;
|
||||
target_ulong CP0_ErrorEPC;
|
||||
int32_t CP0_DESAVE;
|
||||
/* We waste some space so we can handle shadow registers like TCs. */
|
||||
TCState tcs[MIPS_SHADOW_SET_MAX];
|
||||
CPUMIPSFPUContext fpus[MIPS_FPU_MAX];
|
||||
/* QEMU */
|
||||
int error_code;
|
||||
#define EXCP_TLB_NOMATCH 0x1
|
||||
#define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */
|
||||
uint32_t hflags; /* CPU State */
|
||||
/* TMASK defines different execution modes */
|
||||
#define MIPS_HFLAG_TMASK 0x15807FF
|
||||
#define MIPS_HFLAG_MODE 0x00007 /* execution modes */
|
||||
/* The KSU flags must be the lowest bits in hflags. The flag order
|
||||
must be the same as defined for CP0 Status. This allows to use
|
||||
the bits as the value of mmu_idx. */
|
||||
#define MIPS_HFLAG_KSU 0x00003 /* kernel/supervisor/user mode mask */
|
||||
#define MIPS_HFLAG_UM 0x00002 /* user mode flag */
|
||||
#define MIPS_HFLAG_SM 0x00001 /* supervisor mode flag */
|
||||
#define MIPS_HFLAG_KM 0x00000 /* kernel mode flag */
|
||||
#define MIPS_HFLAG_DM 0x00004 /* Debug mode */
|
||||
#define MIPS_HFLAG_64 0x00008 /* 64-bit instructions enabled */
|
||||
#define MIPS_HFLAG_CP0 0x00010 /* CP0 enabled */
|
||||
#define MIPS_HFLAG_FPU 0x00020 /* FPU enabled */
|
||||
#define MIPS_HFLAG_F64 0x00040 /* 64-bit FPU enabled */
|
||||
/* True if the MIPS IV COP1X instructions can be used. This also
|
||||
controls the non-COP1X instructions RECIP.S, RECIP.D, RSQRT.S
|
||||
and RSQRT.D. */
|
||||
#define MIPS_HFLAG_COP1X 0x00080 /* COP1X instructions enabled */
|
||||
#define MIPS_HFLAG_RE 0x00100 /* Reversed endianness */
|
||||
#define MIPS_HFLAG_AWRAP 0x00200 /* 32-bit compatibility address wrapping */
|
||||
#define MIPS_HFLAG_M16 0x00400 /* MIPS16 mode flag */
|
||||
#define MIPS_HFLAG_M16_SHIFT 10
|
||||
/* If translation is interrupted between the branch instruction and
|
||||
* the delay slot, record what type of branch it is so that we can
|
||||
* resume translation properly. It might be possible to reduce
|
||||
* this from three bits to two. */
|
||||
#define MIPS_HFLAG_BMASK_BASE 0x803800
|
||||
#define MIPS_HFLAG_B 0x00800 /* Unconditional branch */
|
||||
#define MIPS_HFLAG_BC 0x01000 /* Conditional branch */
|
||||
#define MIPS_HFLAG_BL 0x01800 /* Likely branch */
|
||||
#define MIPS_HFLAG_BR 0x02000 /* branch to register (can't link TB) */
|
||||
/* Extra flags about the current pending branch. */
|
||||
#define MIPS_HFLAG_BMASK_EXT 0x7C000
|
||||
#define MIPS_HFLAG_B16 0x04000 /* branch instruction was 16 bits */
|
||||
#define MIPS_HFLAG_BDS16 0x08000 /* branch requires 16-bit delay slot */
|
||||
#define MIPS_HFLAG_BDS32 0x10000 /* branch requires 32-bit delay slot */
|
||||
#define MIPS_HFLAG_BDS_STRICT 0x20000 /* Strict delay slot size */
|
||||
#define MIPS_HFLAG_BX 0x40000 /* branch exchanges execution mode */
|
||||
#define MIPS_HFLAG_BMASK (MIPS_HFLAG_BMASK_BASE | MIPS_HFLAG_BMASK_EXT)
|
||||
/* MIPS DSP resources access. */
|
||||
#define MIPS_HFLAG_DSP 0x080000 /* Enable access to MIPS DSP resources. */
|
||||
#define MIPS_HFLAG_DSPR2 0x100000 /* Enable access to MIPS DSPR2 resources. */
|
||||
/* Extra flag about HWREna register. */
|
||||
#define MIPS_HFLAG_HWRENA_ULR 0x200000 /* ULR bit from HWREna is set. */
|
||||
#define MIPS_HFLAG_SBRI 0x400000 /* R6 SDBBP causes RI excpt. in user mode */
|
||||
#define MIPS_HFLAG_FBNSLOT 0x800000 /* Forbidden slot */
|
||||
#define MIPS_HFLAG_MSA 0x1000000
|
||||
target_ulong btarget; /* Jump / branch target */
|
||||
target_ulong bcond; /* Branch condition (if needed) */
|
||||
|
||||
int SYNCI_Step; /* Address step size for SYNCI */
|
||||
int CCRes; /* Cycle count resolution/divisor */
|
||||
uint32_t CP0_Status_rw_bitmask; /* Read/write bits in CP0_Status */
|
||||
uint32_t CP0_TCStatus_rw_bitmask; /* Read/write bits in CP0_TCStatus */
|
||||
int insn_flags; /* Supported instruction set */
|
||||
|
||||
CPU_COMMON
|
||||
|
||||
/* Fields from here on are preserved across CPU reset. */
|
||||
CPUMIPSMVPContext *mvp;
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
CPUMIPSTLBContext *tlb;
|
||||
#endif
|
||||
|
||||
const mips_def_t *cpu_model;
|
||||
//void *irq[8];
|
||||
//QEMUTimer *timer; /* Internal timer */
|
||||
|
||||
// Unicorn engine
|
||||
struct uc_struct *uc;
|
||||
};
|
||||
|
||||
#include "cpu-qom.h"
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
int no_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
|
||||
target_ulong address, int rw, int access_type);
|
||||
int fixed_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
|
||||
target_ulong address, int rw, int access_type);
|
||||
int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
|
||||
target_ulong address, int rw, int access_type);
|
||||
void r4k_helper_tlbwi(CPUMIPSState *env);
|
||||
void r4k_helper_tlbwr(CPUMIPSState *env);
|
||||
void r4k_helper_tlbp(CPUMIPSState *env);
|
||||
void r4k_helper_tlbr(CPUMIPSState *env);
|
||||
void r4k_helper_tlbinv(CPUMIPSState *env);
|
||||
void r4k_helper_tlbinvf(CPUMIPSState *env);
|
||||
|
||||
void mips_cpu_unassigned_access(CPUState *cpu, hwaddr addr,
|
||||
bool is_write, bool is_exec, int unused,
|
||||
unsigned size);
|
||||
#endif
|
||||
|
||||
void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf);
|
||||
|
||||
#define cpu_exec cpu_mips_exec
|
||||
#define cpu_gen_code cpu_mips_gen_code
|
||||
#define cpu_signal_handler cpu_mips_signal_handler
|
||||
#define cpu_list mips_cpu_list
|
||||
|
||||
extern void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env);
|
||||
extern uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env);
|
||||
|
||||
#define CPU_SAVE_VERSION 5
|
||||
|
||||
/* MMU modes definitions. We carefully match the indices with our
|
||||
hflags layout. */
|
||||
#define MMU_MODE0_SUFFIX _kernel
|
||||
#define MMU_MODE1_SUFFIX _super
|
||||
#define MMU_MODE2_SUFFIX _user
|
||||
#define MMU_USER_IDX 2
|
||||
static inline int cpu_mmu_index (CPUMIPSState *env)
|
||||
{
|
||||
return env->hflags & MIPS_HFLAG_KSU;
|
||||
}
|
||||
|
||||
static inline int cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
|
||||
{
|
||||
int32_t pending;
|
||||
int32_t status;
|
||||
int r;
|
||||
|
||||
if (!(env->CP0_Status & (1 << CP0St_IE)) ||
|
||||
(env->CP0_Status & (1 << CP0St_EXL)) ||
|
||||
(env->CP0_Status & (1 << CP0St_ERL)) ||
|
||||
/* Note that the TCStatus IXMT field is initialized to zero,
|
||||
and only MT capable cores can set it to one. So we don't
|
||||
need to check for MT capabilities here. */
|
||||
(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_IXMT)) ||
|
||||
(env->hflags & MIPS_HFLAG_DM)) {
|
||||
/* Interrupts are disabled */
|
||||
return 0;
|
||||
}
|
||||
|
||||
pending = env->CP0_Cause & CP0Ca_IP_mask;
|
||||
status = env->CP0_Status & CP0Ca_IP_mask;
|
||||
|
||||
if (env->CP0_Config3 & (1 << CP0C3_VEIC)) {
|
||||
/* A MIPS configured with a vectorizing external interrupt controller
|
||||
will feed a vector into the Cause pending lines. The core treats
|
||||
the status lines as a vector level, not as indiviual masks. */
|
||||
r = pending > status;
|
||||
} else {
|
||||
/* A MIPS configured with compatibility or VInt (Vectored Interrupts)
|
||||
treats the pending lines as individual interrupt lines, the status
|
||||
lines are individual masks. */
|
||||
r = pending & status;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#include "exec/cpu-all.h"
|
||||
|
||||
/* Memory access type :
|
||||
* may be needed for precise access rights control and precise exceptions.
|
||||
*/
|
||||
enum {
|
||||
/* 1 bit to define user level / supervisor access */
|
||||
ACCESS_USER = 0x00,
|
||||
ACCESS_SUPER = 0x01,
|
||||
/* 1 bit to indicate direction */
|
||||
ACCESS_STORE = 0x02,
|
||||
/* Type of instruction that generated the access */
|
||||
ACCESS_CODE = 0x10, /* Code fetch access */
|
||||
ACCESS_INT = 0x20, /* Integer load/store access */
|
||||
ACCESS_FLOAT = 0x30, /* floating point load/store access */
|
||||
};
|
||||
|
||||
/* Exceptions */
|
||||
enum {
|
||||
EXCP_NONE = -1,
|
||||
EXCP_RESET = 0,
|
||||
EXCP_SRESET,
|
||||
EXCP_DSS,
|
||||
EXCP_DINT,
|
||||
EXCP_DDBL,
|
||||
EXCP_DDBS,
|
||||
EXCP_NMI,
|
||||
EXCP_MCHECK,
|
||||
EXCP_EXT_INTERRUPT, /* 8 */
|
||||
EXCP_DFWATCH,
|
||||
EXCP_DIB,
|
||||
EXCP_IWATCH,
|
||||
EXCP_AdEL,
|
||||
EXCP_AdES,
|
||||
EXCP_TLBF,
|
||||
EXCP_IBE,
|
||||
EXCP_DBp, /* 16 */
|
||||
EXCP_SYSCALL,
|
||||
EXCP_BREAK,
|
||||
EXCP_CpU,
|
||||
EXCP_RI,
|
||||
EXCP_OVERFLOW,
|
||||
EXCP_TRAP,
|
||||
EXCP_FPE,
|
||||
EXCP_DWATCH, /* 24 */
|
||||
EXCP_LTLBL,
|
||||
EXCP_TLBL,
|
||||
EXCP_TLBS,
|
||||
EXCP_DBE,
|
||||
EXCP_THREAD,
|
||||
EXCP_MDMX,
|
||||
EXCP_C2E,
|
||||
EXCP_CACHE, /* 32 */
|
||||
EXCP_DSPDIS,
|
||||
EXCP_MSADIS,
|
||||
EXCP_MSAFPE,
|
||||
EXCP_TLBXI,
|
||||
EXCP_TLBRI,
|
||||
|
||||
EXCP_LAST = EXCP_TLBRI,
|
||||
};
|
||||
/* Dummy exception for conditional stores. */
|
||||
#define EXCP_SC 0x100
|
||||
|
||||
/*
|
||||
* This is an interrnally generated WAKE request line.
|
||||
* It is driven by the CPU itself. Raised when the MT
|
||||
* block wants to wake a VPE from an inactive state and
|
||||
* cleared when VPE goes from active to inactive.
|
||||
*/
|
||||
#define CPU_INTERRUPT_WAKE CPU_INTERRUPT_TGT_INT_0
|
||||
|
||||
int cpu_mips_exec(struct uc_struct *uc, CPUMIPSState *s);
|
||||
void mips_tcg_init(struct uc_struct *uc);
|
||||
MIPSCPU *cpu_mips_init(struct uc_struct *uc, const char *cpu_model);
|
||||
int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc);
|
||||
|
||||
/* TODO QOM'ify CPU reset and remove */
|
||||
void cpu_state_reset(CPUMIPSState *s);
|
||||
|
||||
/* mips_timer.c */
|
||||
uint32_t cpu_mips_get_random (CPUMIPSState *env);
|
||||
uint32_t cpu_mips_get_count (CPUMIPSState *env);
|
||||
void cpu_mips_store_count (CPUMIPSState *env, uint32_t value);
|
||||
void cpu_mips_store_compare (CPUMIPSState *env, uint32_t value);
|
||||
void cpu_mips_start_count(CPUMIPSState *env);
|
||||
void cpu_mips_stop_count(CPUMIPSState *env);
|
||||
|
||||
/* mips_int.c */
|
||||
void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level);
|
||||
|
||||
/* helper.c */
|
||||
int mips_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
|
||||
int mmu_idx);
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
void r4k_invalidate_tlb (CPUMIPSState *env, int idx, int use_extra);
|
||||
hwaddr cpu_mips_translate_address (CPUMIPSState *env, target_ulong address,
|
||||
int rw);
|
||||
#endif
|
||||
target_ulong exception_resume_pc (CPUMIPSState *env);
|
||||
|
||||
/* op_helper.c */
|
||||
extern unsigned int ieee_rm[];
|
||||
int ieee_ex_to_mips(int xcpt);
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc,
|
||||
target_ulong *cs_base, int *flags)
|
||||
{
|
||||
*pc = env->active_tc.PC;
|
||||
*cs_base = 0;
|
||||
*flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK |
|
||||
MIPS_HFLAG_HWRENA_ULR);
|
||||
}
|
||||
|
||||
static inline int mips_vpe_active(CPUMIPSState *env)
|
||||
{
|
||||
int active = 1;
|
||||
|
||||
/* Check that the VPE is enabled. */
|
||||
if (!(env->mvp->CP0_MVPControl & (1 << CP0MVPCo_EVP))) {
|
||||
active = 0;
|
||||
}
|
||||
/* Check that the VPE is activated. */
|
||||
if (!(env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))) {
|
||||
active = 0;
|
||||
}
|
||||
|
||||
/* Now verify that there are active thread contexts in the VPE.
|
||||
|
||||
This assumes the CPU model will internally reschedule threads
|
||||
if the active one goes to sleep. If there are no threads available
|
||||
the active one will be in a sleeping state, and we can turn off
|
||||
the entire VPE. */
|
||||
if (!(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_A))) {
|
||||
/* TC is not activated. */
|
||||
active = 0;
|
||||
}
|
||||
if (env->active_tc.CP0_TCHalt & 1) {
|
||||
/* TC is in halt state. */
|
||||
active = 0;
|
||||
}
|
||||
|
||||
return active;
|
||||
}
|
||||
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
static inline void compute_hflags(CPUMIPSState *env)
|
||||
{
|
||||
env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
|
||||
MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
|
||||
MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2 |
|
||||
MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA);
|
||||
if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
|
||||
!(env->CP0_Status & (1 << CP0St_ERL)) &&
|
||||
!(env->hflags & MIPS_HFLAG_DM)) {
|
||||
env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
|
||||
}
|
||||
#if defined(TARGET_MIPS64)
|
||||
if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
|
||||
(env->CP0_Status & (1 << CP0St_PX)) ||
|
||||
(env->CP0_Status & (1 << CP0St_UX))) {
|
||||
env->hflags |= MIPS_HFLAG_64;
|
||||
}
|
||||
|
||||
if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
|
||||
!(env->CP0_Status & (1 << CP0St_UX))) {
|
||||
env->hflags |= MIPS_HFLAG_AWRAP;
|
||||
} else if (env->insn_flags & ISA_MIPS32R6) {
|
||||
/* Address wrapping for Supervisor and Kernel is specified in R6 */
|
||||
if ((((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_SM) &&
|
||||
!(env->CP0_Status & (1 << CP0St_SX))) ||
|
||||
(((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_KM) &&
|
||||
!(env->CP0_Status & (1 << CP0St_KX)))) {
|
||||
env->hflags |= MIPS_HFLAG_AWRAP;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (((env->CP0_Status & (1 << CP0St_CU0)) &&
|
||||
!(env->insn_flags & ISA_MIPS32R6)) ||
|
||||
!(env->hflags & MIPS_HFLAG_KSU)) {
|
||||
env->hflags |= MIPS_HFLAG_CP0;
|
||||
}
|
||||
if (env->CP0_Status & (1 << CP0St_CU1)) {
|
||||
env->hflags |= MIPS_HFLAG_FPU;
|
||||
}
|
||||
if (env->CP0_Status & (1 << CP0St_FR)) {
|
||||
env->hflags |= MIPS_HFLAG_F64;
|
||||
}
|
||||
if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_KM) &&
|
||||
(env->CP0_Config5 & (1 << CP0C5_SBRI))) {
|
||||
env->hflags |= MIPS_HFLAG_SBRI;
|
||||
}
|
||||
if (env->insn_flags & ASE_DSPR2) {
|
||||
/* Enables access MIPS DSP resources, now our cpu is DSP ASER2,
|
||||
so enable to access DSPR2 resources. */
|
||||
if (env->CP0_Status & (1 << CP0St_MX)) {
|
||||
env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2;
|
||||
}
|
||||
|
||||
} else if (env->insn_flags & ASE_DSP) {
|
||||
/* Enables access MIPS DSP resources, now our cpu is DSP ASE,
|
||||
so enable to access DSP resources. */
|
||||
if (env->CP0_Status & (1 << CP0St_MX)) {
|
||||
env->hflags |= MIPS_HFLAG_DSP;
|
||||
}
|
||||
|
||||
}
|
||||
if (env->insn_flags & ISA_MIPS32R2) {
|
||||
if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
|
||||
env->hflags |= MIPS_HFLAG_COP1X;
|
||||
}
|
||||
} else if (env->insn_flags & ISA_MIPS32) {
|
||||
if (env->hflags & MIPS_HFLAG_64) {
|
||||
env->hflags |= MIPS_HFLAG_COP1X;
|
||||
}
|
||||
} else if (env->insn_flags & ISA_MIPS4) {
|
||||
/* All supported MIPS IV CPUs use the XX (CU3) to enable
|
||||
and disable the MIPS IV extensions to the MIPS III ISA.
|
||||
Some other MIPS IV CPUs ignore the bit, so the check here
|
||||
would be too restrictive for them. */
|
||||
if (env->CP0_Status & (1U << CP0St_CU3)) {
|
||||
env->hflags |= MIPS_HFLAG_COP1X;
|
||||
}
|
||||
}
|
||||
if (env->insn_flags & ASE_MSA) {
|
||||
if (env->CP0_Config5 & (1 << CP0C5_MSAEn)) {
|
||||
env->hflags |= MIPS_HFLAG_MSA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !defined (__MIPS_CPU_H__) */
|
File diff suppressed because it is too large
Load Diff
@ -1,826 +0,0 @@
|
||||
/*
|
||||
* MIPS emulation helpers for qemu.
|
||||
*
|
||||
* Copyright (c) 2004-2005 Jocelyn Mayer
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "unicorn/platform.h"
|
||||
#include <signal.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
|
||||
enum {
|
||||
TLBRET_XI = -6,
|
||||
TLBRET_RI = -5,
|
||||
TLBRET_DIRTY = -4,
|
||||
TLBRET_INVALID = -3,
|
||||
TLBRET_NOMATCH = -2,
|
||||
TLBRET_BADADDR = -1,
|
||||
TLBRET_MATCH = 0
|
||||
};
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
|
||||
/* no MMU emulation */
|
||||
int no_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
|
||||
target_ulong address, int rw, int access_type)
|
||||
{
|
||||
*physical = address;
|
||||
*prot = PAGE_READ | PAGE_WRITE;
|
||||
return TLBRET_MATCH;
|
||||
}
|
||||
|
||||
/* fixed mapping MMU emulation */
|
||||
int fixed_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
|
||||
target_ulong address, int rw, int access_type)
|
||||
{
|
||||
if (address <= (int32_t)0x7FFFFFFFUL) {
|
||||
if (!(env->CP0_Status & (1 << CP0St_ERL)))
|
||||
*physical = address + 0x40000000UL;
|
||||
else
|
||||
*physical = address;
|
||||
} else if (address <= (int32_t)0xBFFFFFFFUL)
|
||||
*physical = address & 0x1FFFFFFF;
|
||||
else
|
||||
*physical = address;
|
||||
|
||||
*prot = PAGE_READ | PAGE_WRITE;
|
||||
return TLBRET_MATCH;
|
||||
}
|
||||
|
||||
/* MIPS32/MIPS64 R4000-style MMU emulation */
|
||||
int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
|
||||
target_ulong address, int rw, int access_type)
|
||||
{
|
||||
uint8_t ASID = env->CP0_EntryHi & 0xFF;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < env->tlb->tlb_in_use; i++) {
|
||||
r4k_tlb_t *tlb = &env->tlb->mmu.r4k.tlb[i];
|
||||
/* 1k pages are not supported. */
|
||||
target_ulong mask = tlb->PageMask | ~(((unsigned int)TARGET_PAGE_MASK) << 1);
|
||||
target_ulong tag = address & ~mask;
|
||||
target_ulong VPN = tlb->VPN & ~mask;
|
||||
#if defined(TARGET_MIPS64)
|
||||
tag &= env->SEGMask;
|
||||
#endif
|
||||
|
||||
/* Check ASID, virtual page number & size */
|
||||
if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag && !tlb->EHINV) {
|
||||
/* TLB match */
|
||||
int n = !!(address & mask & ~(mask >> 1));
|
||||
/* Check access rights */
|
||||
if (!(n ? tlb->V1 : tlb->V0)) {
|
||||
return TLBRET_INVALID;
|
||||
}
|
||||
if (rw == MMU_INST_FETCH && (n ? tlb->XI1 : tlb->XI0)) {
|
||||
return TLBRET_XI;
|
||||
}
|
||||
if (rw == MMU_DATA_LOAD && (n ? tlb->RI1 : tlb->RI0)) {
|
||||
return TLBRET_RI;
|
||||
}
|
||||
if (rw != MMU_DATA_STORE || (n ? tlb->D1 : tlb->D0)) {
|
||||
*physical = tlb->PFN[n] | (address & (mask >> 1));
|
||||
*prot = PAGE_READ;
|
||||
if (n ? tlb->D1 : tlb->D0)
|
||||
*prot |= PAGE_WRITE;
|
||||
return TLBRET_MATCH;
|
||||
}
|
||||
return TLBRET_DIRTY;
|
||||
}
|
||||
}
|
||||
return TLBRET_NOMATCH;
|
||||
}
|
||||
|
||||
static int get_physical_address (CPUMIPSState *env, hwaddr *physical,
|
||||
int *prot, target_ulong real_address,
|
||||
int rw, int access_type)
|
||||
{
|
||||
/* User mode can only access useg/xuseg */
|
||||
int user_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM;
|
||||
int supervisor_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_SM;
|
||||
int kernel_mode = !user_mode && !supervisor_mode;
|
||||
#if defined(TARGET_MIPS64)
|
||||
int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
|
||||
int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;
|
||||
int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0;
|
||||
#endif
|
||||
int ret = TLBRET_MATCH;
|
||||
/* effective address (modified for KVM T&E kernel segments) */
|
||||
target_ulong address = real_address;
|
||||
|
||||
#if 0
|
||||
qemu_log("user mode %d h %08x\n", user_mode, env->hflags);
|
||||
#endif
|
||||
|
||||
#define USEG_LIMIT 0x7FFFFFFFUL
|
||||
#define KSEG0_BASE 0x80000000UL
|
||||
#define KSEG1_BASE 0xA0000000UL
|
||||
#define KSEG2_BASE 0xC0000000UL
|
||||
#define KSEG3_BASE 0xE0000000UL
|
||||
|
||||
#define KVM_KSEG0_BASE 0x40000000UL
|
||||
#define KVM_KSEG2_BASE 0x60000000UL
|
||||
|
||||
if (address <= USEG_LIMIT) {
|
||||
/* useg */
|
||||
if (env->CP0_Status & (1 << CP0St_ERL)) {
|
||||
*physical = address & 0xFFFFFFFF;
|
||||
*prot = PAGE_READ | PAGE_WRITE;
|
||||
} else {
|
||||
ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type);
|
||||
}
|
||||
#if defined(TARGET_MIPS64)
|
||||
} else if (address < 0x4000000000000000ULL) {
|
||||
/* xuseg */
|
||||
if (UX && address <= (0x3FFFFFFFFFFFFFFFULL & env->SEGMask)) {
|
||||
ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type);
|
||||
} else {
|
||||
ret = TLBRET_BADADDR;
|
||||
}
|
||||
} else if (address < 0x8000000000000000ULL) {
|
||||
/* xsseg */
|
||||
if ((supervisor_mode || kernel_mode) &&
|
||||
SX && address <= (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) {
|
||||
ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type);
|
||||
} else {
|
||||
ret = TLBRET_BADADDR;
|
||||
}
|
||||
} else if (address < 0xC000000000000000ULL) {
|
||||
/* xkphys */
|
||||
if (kernel_mode && KX &&
|
||||
(address & 0x07FFFFFFFFFFFFFFULL) <= env->PAMask) {
|
||||
*physical = address & env->PAMask;
|
||||
*prot = PAGE_READ | PAGE_WRITE;
|
||||
} else {
|
||||
ret = TLBRET_BADADDR;
|
||||
}
|
||||
} else if (address < 0xFFFFFFFF80000000ULL) {
|
||||
/* xkseg */
|
||||
if (kernel_mode && KX &&
|
||||
address <= (0xFFFFFFFF7FFFFFFFULL & env->SEGMask)) {
|
||||
ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type);
|
||||
} else {
|
||||
ret = TLBRET_BADADDR;
|
||||
}
|
||||
#endif
|
||||
} else if (address < (int32_t)KSEG1_BASE) {
|
||||
/* kseg0 */
|
||||
if (kernel_mode) {
|
||||
*physical = address - (int32_t)KSEG0_BASE;
|
||||
*prot = PAGE_READ | PAGE_WRITE;
|
||||
} else {
|
||||
ret = TLBRET_BADADDR;
|
||||
}
|
||||
} else if (address < (int32_t)KSEG2_BASE) {
|
||||
/* kseg1 */
|
||||
if (kernel_mode) {
|
||||
*physical = address - (int32_t)KSEG1_BASE;
|
||||
*prot = PAGE_READ | PAGE_WRITE;
|
||||
} else {
|
||||
ret = TLBRET_BADADDR;
|
||||
}
|
||||
} else if (address < (int32_t)KSEG3_BASE) {
|
||||
/* sseg (kseg2) */
|
||||
if (supervisor_mode || kernel_mode) {
|
||||
ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type);
|
||||
} else {
|
||||
ret = TLBRET_BADADDR;
|
||||
}
|
||||
} else {
|
||||
/* kseg3 */
|
||||
/* XXX: debug segment is not emulated */
|
||||
if (kernel_mode) {
|
||||
ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type);
|
||||
} else {
|
||||
ret = TLBRET_BADADDR;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
qemu_log(TARGET_FMT_lx " %d %d => %" HWADDR_PRIx " %d (%d)\n",
|
||||
address, rw, access_type, *physical, *prot, ret);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void raise_mmu_exception(CPUMIPSState *env, target_ulong address,
|
||||
int rw, int tlb_error)
|
||||
{
|
||||
CPUState *cs = CPU(mips_env_get_cpu(env));
|
||||
int exception = 0, error_code = 0;
|
||||
|
||||
if (rw == MMU_INST_FETCH) {
|
||||
error_code |= EXCP_INST_NOTAVAIL;
|
||||
}
|
||||
|
||||
switch (tlb_error) {
|
||||
default:
|
||||
case TLBRET_BADADDR:
|
||||
/* Reference to kernel address from user mode or supervisor mode */
|
||||
/* Reference to supervisor address from user mode */
|
||||
if (rw == MMU_DATA_STORE) {
|
||||
exception = EXCP_AdES;
|
||||
} else {
|
||||
exception = EXCP_AdEL;
|
||||
}
|
||||
break;
|
||||
case TLBRET_NOMATCH:
|
||||
/* No TLB match for a mapped address */
|
||||
if (rw == MMU_DATA_STORE) {
|
||||
exception = EXCP_TLBS;
|
||||
} else {
|
||||
exception = EXCP_TLBL;
|
||||
}
|
||||
error_code |= EXCP_TLB_NOMATCH;
|
||||
break;
|
||||
case TLBRET_INVALID:
|
||||
/* TLB match with no valid bit */
|
||||
if (rw == MMU_DATA_STORE) {
|
||||
exception = EXCP_TLBS;
|
||||
} else {
|
||||
exception = EXCP_TLBL;
|
||||
}
|
||||
break;
|
||||
case TLBRET_DIRTY:
|
||||
/* TLB match but 'D' bit is cleared */
|
||||
exception = EXCP_LTLBL;
|
||||
break;
|
||||
case TLBRET_XI:
|
||||
/* Execute-Inhibit Exception */
|
||||
if (env->CP0_PageGrain & (1 << CP0PG_IEC)) {
|
||||
exception = EXCP_TLBXI;
|
||||
} else {
|
||||
exception = EXCP_TLBL;
|
||||
}
|
||||
break;
|
||||
case TLBRET_RI:
|
||||
/* Read-Inhibit Exception */
|
||||
if (env->CP0_PageGrain & (1 << CP0PG_IEC)) {
|
||||
exception = EXCP_TLBRI;
|
||||
} else {
|
||||
exception = EXCP_TLBL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Raise exception */
|
||||
env->CP0_BadVAddr = address;
|
||||
env->CP0_Context = (env->CP0_Context & ~0x007fffff) |
|
||||
((address >> 9) & 0x007ffff0);
|
||||
env->CP0_EntryHi =
|
||||
(env->CP0_EntryHi & 0xFF) | (address & (((unsigned int)TARGET_PAGE_MASK) << 1));
|
||||
#if defined(TARGET_MIPS64)
|
||||
env->CP0_EntryHi &= env->SEGMask;
|
||||
env->CP0_XContext = (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 7))) |
|
||||
((address & 0xC00000000000ULL) >> (55 - env->SEGBITS)) |
|
||||
((address & ((1ULL << env->SEGBITS) - 1) & 0xFFFFFFFFFFFFE000ULL) >> 9);
|
||||
#endif
|
||||
cs->exception_index = exception;
|
||||
env->error_code = error_code;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
hwaddr mips_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
|
||||
{
|
||||
MIPSCPU *cpu = MIPS_CPU(cs->uc, cs);
|
||||
hwaddr phys_addr;
|
||||
int prot;
|
||||
|
||||
if (get_physical_address(&cpu->env, &phys_addr, &prot, addr, 0,
|
||||
ACCESS_INT) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return phys_addr;
|
||||
}
|
||||
#endif
|
||||
|
||||
int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
|
||||
int mmu_idx)
|
||||
{
|
||||
MIPSCPU *cpu = MIPS_CPU(cs->uc, cs);
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
hwaddr physical;
|
||||
int prot;
|
||||
int access_type;
|
||||
#endif
|
||||
int ret = 0;
|
||||
|
||||
#if 0
|
||||
log_cpu_state(cs, 0);
|
||||
#endif
|
||||
qemu_log("%s pc " TARGET_FMT_lx " ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
|
||||
__func__, env->active_tc.PC, address, rw, mmu_idx);
|
||||
|
||||
/* data access */
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
/* XXX: put correct access by using cpu_restore_state()
|
||||
correctly */
|
||||
access_type = ACCESS_INT;
|
||||
ret = get_physical_address(env, &physical, &prot,
|
||||
address, rw, access_type);
|
||||
qemu_log("%s address=%" VADDR_PRIx " ret %d physical " TARGET_FMT_plx
|
||||
" prot %d\n",
|
||||
__func__, address, ret, physical, prot);
|
||||
if (ret == TLBRET_MATCH) {
|
||||
if (mmu_idx < 0 || mmu_idx >= NB_MMU_MODES) {
|
||||
raise_mmu_exception(env, address, rw, ret);
|
||||
ret = 1;
|
||||
} else {
|
||||
tlb_set_page(cs, address & TARGET_PAGE_MASK,
|
||||
physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
|
||||
mmu_idx, TARGET_PAGE_SIZE);
|
||||
ret = 0;
|
||||
}
|
||||
} else if (ret < 0)
|
||||
#endif
|
||||
{
|
||||
raise_mmu_exception(env, address, rw, ret);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int rw)
|
||||
{
|
||||
hwaddr physical;
|
||||
int prot;
|
||||
int access_type;
|
||||
int ret = 0;
|
||||
|
||||
/* data access */
|
||||
access_type = ACCESS_INT;
|
||||
ret = get_physical_address(env, &physical, &prot,
|
||||
address, rw, access_type);
|
||||
if (ret != TLBRET_MATCH) {
|
||||
raise_mmu_exception(env, address, rw, ret);
|
||||
return -1LL;
|
||||
} else {
|
||||
return physical;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char * const excp_names[EXCP_LAST + 1] = {
|
||||
"reset",
|
||||
"soft reset",
|
||||
"debug single step",
|
||||
"debug interrupt",
|
||||
"debug data break load",
|
||||
"debug data break store",
|
||||
"non-maskable interrupt",
|
||||
"machine check",
|
||||
"interrupt",
|
||||
"deferred watchpoint",
|
||||
"debug instruction breakpoint",
|
||||
"instruction fetch watchpoint",
|
||||
"address error load",
|
||||
"address error store",
|
||||
"TLB refill",
|
||||
"instruction bus error",
|
||||
"debug breakpoint",
|
||||
"syscall",
|
||||
"break",
|
||||
"coprocessor unusable",
|
||||
"reserved instruction",
|
||||
"arithmetic overflow",
|
||||
"trap",
|
||||
"floating point",
|
||||
"data watchpoint",
|
||||
"TLB modify",
|
||||
"TLB load",
|
||||
"TLB store",
|
||||
"data bus error",
|
||||
"thread",
|
||||
"MDMX",
|
||||
"precise coprocessor 2",
|
||||
"cache error",
|
||||
"DSP disabled",
|
||||
"MSA disabled",
|
||||
"MSA floating point",
|
||||
"TLB execute-inhibit",
|
||||
"TLB read-inhibit",
|
||||
};
|
||||
|
||||
target_ulong exception_resume_pc (CPUMIPSState *env)
|
||||
{
|
||||
target_ulong bad_pc;
|
||||
target_ulong isa_mode;
|
||||
|
||||
isa_mode = !!(env->hflags & MIPS_HFLAG_M16);
|
||||
bad_pc = env->active_tc.PC | isa_mode;
|
||||
if (env->hflags & MIPS_HFLAG_BMASK) {
|
||||
/* If the exception was raised from a delay slot, come back to
|
||||
the jump. */
|
||||
bad_pc -= (env->hflags & MIPS_HFLAG_B16 ? 2 : 4);
|
||||
}
|
||||
|
||||
return bad_pc;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
static void set_hflags_for_handler (CPUMIPSState *env)
|
||||
{
|
||||
/* Exception handlers are entered in 32-bit mode. */
|
||||
env->hflags &= ~(MIPS_HFLAG_M16);
|
||||
/* ...except that microMIPS lets you choose. */
|
||||
if (env->insn_flags & ASE_MICROMIPS) {
|
||||
env->hflags |= (!!(env->CP0_Config3
|
||||
& (1 << CP0C3_ISA_ON_EXC))
|
||||
<< MIPS_HFLAG_M16_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void set_badinstr_registers(CPUMIPSState *env)
|
||||
{
|
||||
if (env->hflags & MIPS_HFLAG_M16) {
|
||||
/* TODO: add BadInstr support for microMIPS */
|
||||
return;
|
||||
}
|
||||
if (env->CP0_Config3 & (1 << CP0C3_BI)) {
|
||||
env->CP0_BadInstr = cpu_ldl_code(env, env->active_tc.PC);
|
||||
}
|
||||
if ((env->CP0_Config3 & (1 << CP0C3_BP)) &&
|
||||
(env->hflags & MIPS_HFLAG_BMASK)) {
|
||||
env->CP0_BadInstrP = cpu_ldl_code(env, env->active_tc.PC - 4);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void mips_cpu_do_interrupt(CPUState *cs)
|
||||
{
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
MIPSCPU *cpu = MIPS_CPU(cs->uc, cs);
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
bool update_badinstr = 0;
|
||||
target_ulong offset;
|
||||
int cause = -1;
|
||||
const char *name;
|
||||
|
||||
if (qemu_log_enabled() && cs->exception_index != EXCP_EXT_INTERRUPT) {
|
||||
if (cs->exception_index < 0 || cs->exception_index > EXCP_LAST) {
|
||||
name = "unknown";
|
||||
} else {
|
||||
name = excp_names[cs->exception_index];
|
||||
}
|
||||
|
||||
qemu_log("%s enter: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " %s exception\n",
|
||||
__func__, env->active_tc.PC, env->CP0_EPC, name);
|
||||
}
|
||||
if (cs->exception_index == EXCP_EXT_INTERRUPT &&
|
||||
(env->hflags & MIPS_HFLAG_DM)) {
|
||||
cs->exception_index = EXCP_DINT;
|
||||
}
|
||||
offset = 0x180;
|
||||
switch (cs->exception_index) {
|
||||
case EXCP_DSS:
|
||||
env->CP0_Debug |= 1 << CP0DB_DSS;
|
||||
/* Debug single step cannot be raised inside a delay slot and
|
||||
resume will always occur on the next instruction
|
||||
(but we assume the pc has always been updated during
|
||||
code translation). */
|
||||
env->CP0_DEPC = env->active_tc.PC | !!(env->hflags & MIPS_HFLAG_M16);
|
||||
goto enter_debug_mode;
|
||||
case EXCP_DINT:
|
||||
env->CP0_Debug |= 1 << CP0DB_DINT;
|
||||
goto set_DEPC;
|
||||
case EXCP_DIB:
|
||||
env->CP0_Debug |= 1 << CP0DB_DIB;
|
||||
goto set_DEPC;
|
||||
case EXCP_DBp:
|
||||
env->CP0_Debug |= 1 << CP0DB_DBp;
|
||||
goto set_DEPC;
|
||||
case EXCP_DDBS:
|
||||
env->CP0_Debug |= 1 << CP0DB_DDBS;
|
||||
goto set_DEPC;
|
||||
case EXCP_DDBL:
|
||||
env->CP0_Debug |= 1 << CP0DB_DDBL;
|
||||
set_DEPC:
|
||||
env->CP0_DEPC = exception_resume_pc(env);
|
||||
env->hflags &= ~MIPS_HFLAG_BMASK;
|
||||
enter_debug_mode:
|
||||
env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
|
||||
env->hflags &= ~(MIPS_HFLAG_KSU);
|
||||
/* EJTAG probe trap enable is not implemented... */
|
||||
if (!(env->CP0_Status & (1 << CP0St_EXL)))
|
||||
env->CP0_Cause &= ~(1U << CP0Ca_BD);
|
||||
env->active_tc.PC = (int32_t)0xBFC00480;
|
||||
set_hflags_for_handler(env);
|
||||
break;
|
||||
case EXCP_RESET:
|
||||
cpu_reset(CPU(cpu));
|
||||
break;
|
||||
case EXCP_SRESET:
|
||||
env->CP0_Status |= (1 << CP0St_SR);
|
||||
/* memset CP0_WatchLo which is fixed size array. */
|
||||
memset(env->CP0_WatchLo, 0, sizeof(env->CP0_WatchLo));
|
||||
goto set_error_EPC;
|
||||
case EXCP_NMI:
|
||||
env->CP0_Status |= (1 << CP0St_NMI);
|
||||
set_error_EPC:
|
||||
env->CP0_ErrorEPC = exception_resume_pc(env);
|
||||
env->hflags &= ~MIPS_HFLAG_BMASK;
|
||||
env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
|
||||
env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
|
||||
env->hflags &= ~(MIPS_HFLAG_KSU);
|
||||
if (!(env->CP0_Status & (1 << CP0St_EXL)))
|
||||
env->CP0_Cause &= ~(1U << CP0Ca_BD);
|
||||
env->active_tc.PC = (int32_t)0xBFC00000;
|
||||
set_hflags_for_handler(env);
|
||||
break;
|
||||
case EXCP_EXT_INTERRUPT:
|
||||
cause = 0;
|
||||
if (env->CP0_Cause & (1 << CP0Ca_IV))
|
||||
offset = 0x200;
|
||||
|
||||
if (env->CP0_Config3 & ((1 << CP0C3_VInt) | (1 << CP0C3_VEIC))) {
|
||||
/* Vectored Interrupts. */
|
||||
unsigned int spacing;
|
||||
unsigned int vector;
|
||||
unsigned int pending = (env->CP0_Cause & CP0Ca_IP_mask) >> 8;
|
||||
|
||||
pending &= env->CP0_Status >> 8;
|
||||
/* Compute the Vector Spacing. */
|
||||
spacing = (env->CP0_IntCtl >> CP0IntCtl_VS) & ((1 << 6) - 1);
|
||||
spacing <<= 5;
|
||||
|
||||
if (env->CP0_Config3 & (1 << CP0C3_VInt)) {
|
||||
/* For VInt mode, the MIPS computes the vector internally. */
|
||||
for (vector = 7; vector > 0; vector--) {
|
||||
if (pending & (1 << vector)) {
|
||||
/* Found it. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* For VEIC mode, the external interrupt controller feeds the
|
||||
vector through the CP0Cause IP lines. */
|
||||
vector = pending;
|
||||
}
|
||||
offset = 0x200 + vector * spacing;
|
||||
}
|
||||
goto set_EPC;
|
||||
case EXCP_LTLBL:
|
||||
cause = 1;
|
||||
update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL);
|
||||
goto set_EPC;
|
||||
case EXCP_TLBL:
|
||||
cause = 2;
|
||||
update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL);
|
||||
if ((env->error_code & EXCP_TLB_NOMATCH) &&
|
||||
!(env->CP0_Status & (1 << CP0St_EXL))) {
|
||||
#if defined(TARGET_MIPS64)
|
||||
int R = env->CP0_BadVAddr >> 62;
|
||||
int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
|
||||
int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;
|
||||
int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0;
|
||||
|
||||
if (((R == 0 && UX) || (R == 1 && SX) || (R == 3 && KX)) &&
|
||||
(!(env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F))))
|
||||
offset = 0x080;
|
||||
else
|
||||
#endif
|
||||
offset = 0x000;
|
||||
}
|
||||
goto set_EPC;
|
||||
case EXCP_TLBS:
|
||||
cause = 3;
|
||||
update_badinstr = 1;
|
||||
if ((env->error_code & EXCP_TLB_NOMATCH) &&
|
||||
!(env->CP0_Status & (1 << CP0St_EXL))) {
|
||||
#if defined(TARGET_MIPS64)
|
||||
int R = env->CP0_BadVAddr >> 62;
|
||||
int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
|
||||
int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;
|
||||
int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0;
|
||||
|
||||
if (((R == 0 && UX) || (R == 1 && SX) || (R == 3 && KX)) &&
|
||||
(!(env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F))))
|
||||
offset = 0x080;
|
||||
else
|
||||
#endif
|
||||
offset = 0x000;
|
||||
}
|
||||
goto set_EPC;
|
||||
case EXCP_AdEL:
|
||||
cause = 4;
|
||||
update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL);
|
||||
goto set_EPC;
|
||||
case EXCP_AdES:
|
||||
cause = 5;
|
||||
update_badinstr = 1;
|
||||
goto set_EPC;
|
||||
case EXCP_IBE:
|
||||
cause = 6;
|
||||
goto set_EPC;
|
||||
case EXCP_DBE:
|
||||
cause = 7;
|
||||
goto set_EPC;
|
||||
case EXCP_SYSCALL:
|
||||
cause = 8;
|
||||
update_badinstr = 1;
|
||||
goto set_EPC;
|
||||
case EXCP_BREAK:
|
||||
cause = 9;
|
||||
update_badinstr = 1;
|
||||
goto set_EPC;
|
||||
case EXCP_RI:
|
||||
cause = 10;
|
||||
update_badinstr = 1;
|
||||
goto set_EPC;
|
||||
case EXCP_CpU:
|
||||
cause = 11;
|
||||
update_badinstr = 1;
|
||||
env->CP0_Cause = (env->CP0_Cause & ~(0x3 << CP0Ca_CE)) |
|
||||
(env->error_code << CP0Ca_CE);
|
||||
goto set_EPC;
|
||||
case EXCP_OVERFLOW:
|
||||
cause = 12;
|
||||
update_badinstr = 1;
|
||||
goto set_EPC;
|
||||
case EXCP_TRAP:
|
||||
cause = 13;
|
||||
update_badinstr = 1;
|
||||
goto set_EPC;
|
||||
case EXCP_MSAFPE:
|
||||
cause = 14;
|
||||
update_badinstr = 1;
|
||||
goto set_EPC;
|
||||
case EXCP_FPE:
|
||||
cause = 15;
|
||||
update_badinstr = 1;
|
||||
goto set_EPC;
|
||||
case EXCP_C2E:
|
||||
cause = 18;
|
||||
goto set_EPC;
|
||||
case EXCP_TLBRI:
|
||||
cause = 19;
|
||||
update_badinstr = 1;
|
||||
goto set_EPC;
|
||||
case EXCP_TLBXI:
|
||||
cause = 20;
|
||||
goto set_EPC;
|
||||
case EXCP_MSADIS:
|
||||
cause = 21;
|
||||
update_badinstr = 1;
|
||||
goto set_EPC;
|
||||
case EXCP_MDMX:
|
||||
cause = 22;
|
||||
goto set_EPC;
|
||||
case EXCP_DWATCH:
|
||||
cause = 23;
|
||||
/* XXX: TODO: manage defered watch exceptions */
|
||||
goto set_EPC;
|
||||
case EXCP_MCHECK:
|
||||
cause = 24;
|
||||
goto set_EPC;
|
||||
case EXCP_THREAD:
|
||||
cause = 25;
|
||||
goto set_EPC;
|
||||
case EXCP_DSPDIS:
|
||||
cause = 26;
|
||||
goto set_EPC;
|
||||
case EXCP_CACHE:
|
||||
cause = 30;
|
||||
if (env->CP0_Status & (1 << CP0St_BEV)) {
|
||||
offset = 0x100;
|
||||
} else {
|
||||
offset = 0x20000100;
|
||||
}
|
||||
set_EPC:
|
||||
if (!(env->CP0_Status & (1 << CP0St_EXL))) {
|
||||
env->CP0_EPC = exception_resume_pc(env);
|
||||
if (update_badinstr) {
|
||||
set_badinstr_registers(env);
|
||||
}
|
||||
if (env->hflags & MIPS_HFLAG_BMASK) {
|
||||
env->CP0_Cause |= (1U << CP0Ca_BD);
|
||||
} else {
|
||||
env->CP0_Cause &= ~(1U << CP0Ca_BD);
|
||||
}
|
||||
env->CP0_Status |= (1 << CP0St_EXL);
|
||||
env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
|
||||
env->hflags &= ~(MIPS_HFLAG_KSU);
|
||||
}
|
||||
env->hflags &= ~MIPS_HFLAG_BMASK;
|
||||
if (env->CP0_Status & (1 << CP0St_BEV)) {
|
||||
env->active_tc.PC = (int32_t)0xBFC00200;
|
||||
} else {
|
||||
env->active_tc.PC = (int32_t)(env->CP0_EBase & ~0x3ff);
|
||||
}
|
||||
env->active_tc.PC += offset;
|
||||
set_hflags_for_handler(env);
|
||||
env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC);
|
||||
break;
|
||||
default:
|
||||
qemu_log("Invalid MIPS exception %d. Exiting\n", cs->exception_index);
|
||||
printf("Invalid MIPS exception %d. Exiting\n", cs->exception_index);
|
||||
exit(1);
|
||||
}
|
||||
if (qemu_log_enabled() && cs->exception_index != EXCP_EXT_INTERRUPT) {
|
||||
qemu_log("%s: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d\n"
|
||||
" S %08x C %08x A " TARGET_FMT_lx " D " TARGET_FMT_lx "\n",
|
||||
__func__, env->active_tc.PC, env->CP0_EPC, cause,
|
||||
env->CP0_Status, env->CP0_Cause, env->CP0_BadVAddr,
|
||||
env->CP0_DEPC);
|
||||
}
|
||||
#endif
|
||||
cs->exception_index = EXCP_NONE;
|
||||
}
|
||||
|
||||
bool mips_cpu_exec_interrupt(CPUState *cs, int interrupt_request) // qq
|
||||
{
|
||||
if (interrupt_request & CPU_INTERRUPT_HARD) {
|
||||
MIPSCPU *cpu = MIPS_CPU(cs->uc, cs);
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
|
||||
if (cpu_mips_hw_interrupts_pending(env)) {
|
||||
/* Raise it */
|
||||
cs->exception_index = EXCP_EXT_INTERRUPT;
|
||||
env->error_code = 0;
|
||||
mips_cpu_do_interrupt(cs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
void r4k_invalidate_tlb (CPUMIPSState *env, int idx, int use_extra)
|
||||
{
|
||||
MIPSCPU *cpu = mips_env_get_cpu(env);
|
||||
CPUState *cs;
|
||||
r4k_tlb_t *tlb;
|
||||
target_ulong addr;
|
||||
target_ulong end;
|
||||
uint8_t ASID = env->CP0_EntryHi & 0xFF;
|
||||
target_ulong mask;
|
||||
|
||||
tlb = &env->tlb->mmu.r4k.tlb[idx];
|
||||
/* The qemu TLB is flushed when the ASID changes, so no need to
|
||||
flush these entries again. */
|
||||
if (tlb->G == 0 && tlb->ASID != ASID) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (use_extra && env->tlb->tlb_in_use < MIPS_TLB_MAX) {
|
||||
/* For tlbwr, we can shadow the discarded entry into
|
||||
a new (fake) TLB entry, as long as the guest can not
|
||||
tell that it's there. */
|
||||
env->tlb->mmu.r4k.tlb[env->tlb->tlb_in_use] = *tlb;
|
||||
env->tlb->tlb_in_use++;
|
||||
return;
|
||||
}
|
||||
|
||||
/* 1k pages are not supported. */
|
||||
mask = tlb->PageMask | ~(((unsigned int)TARGET_PAGE_MASK) << 1);
|
||||
if (tlb->V0) {
|
||||
cs = CPU(cpu);
|
||||
addr = tlb->VPN & ~mask;
|
||||
#if defined(TARGET_MIPS64)
|
||||
if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) {
|
||||
addr |= 0x3FFFFF0000000000ULL;
|
||||
}
|
||||
#endif
|
||||
end = addr | (mask >> 1);
|
||||
while (addr < end) {
|
||||
tlb_flush_page(cs, addr);
|
||||
addr += TARGET_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
if (tlb->V1) {
|
||||
cs = CPU(cpu);
|
||||
addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1);
|
||||
#if defined(TARGET_MIPS64)
|
||||
if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) {
|
||||
addr |= 0x3FFFFF0000000000ULL;
|
||||
}
|
||||
#endif
|
||||
end = addr | mask;
|
||||
while (addr - 1 < end) {
|
||||
tlb_flush_page(cs, addr);
|
||||
addr += TARGET_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,936 +0,0 @@
|
||||
DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64)
|
||||
|
||||
DEF_HELPER_3(raise_exception_err, noreturn, env, i32, int)
|
||||
DEF_HELPER_2(raise_exception, noreturn, env, i32)
|
||||
|
||||
#ifdef TARGET_MIPS64
|
||||
DEF_HELPER_4(sdl, void, env, tl, tl, int)
|
||||
DEF_HELPER_4(sdr, void, env, tl, tl, int)
|
||||
#endif
|
||||
DEF_HELPER_4(swl, void, env, tl, tl, int)
|
||||
DEF_HELPER_4(swr, void, env, tl, tl, int)
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
DEF_HELPER_3(ll, tl, env, tl, int)
|
||||
DEF_HELPER_4(sc, tl, env, tl, tl, int)
|
||||
#ifdef TARGET_MIPS64
|
||||
DEF_HELPER_3(lld, tl, env, tl, int)
|
||||
DEF_HELPER_4(scd, tl, env, tl, tl, int)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
DEF_HELPER_FLAGS_1(clo, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#ifdef TARGET_MIPS64
|
||||
DEF_HELPER_FLAGS_1(dclo, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(dclz, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#endif
|
||||
|
||||
DEF_HELPER_3(muls, tl, env, tl, tl)
|
||||
DEF_HELPER_3(mulsu, tl, env, tl, tl)
|
||||
DEF_HELPER_3(macc, tl, env, tl, tl)
|
||||
DEF_HELPER_3(maccu, tl, env, tl, tl)
|
||||
DEF_HELPER_3(msac, tl, env, tl, tl)
|
||||
DEF_HELPER_3(msacu, tl, env, tl, tl)
|
||||
DEF_HELPER_3(mulhi, tl, env, tl, tl)
|
||||
DEF_HELPER_3(mulhiu, tl, env, tl, tl)
|
||||
DEF_HELPER_3(mulshi, tl, env, tl, tl)
|
||||
DEF_HELPER_3(mulshiu, tl, env, tl, tl)
|
||||
DEF_HELPER_3(macchi, tl, env, tl, tl)
|
||||
DEF_HELPER_3(macchiu, tl, env, tl, tl)
|
||||
DEF_HELPER_3(msachi, tl, env, tl, tl)
|
||||
DEF_HELPER_3(msachiu, tl, env, tl, tl)
|
||||
|
||||
DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#ifdef TARGET_MIPS64
|
||||
DEF_HELPER_FLAGS_1(dbitswap, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* CP0 helpers */
|
||||
DEF_HELPER_1(mfc0_mvpcontrol, tl, env)
|
||||
DEF_HELPER_1(mfc0_mvpconf0, tl, env)
|
||||
DEF_HELPER_1(mfc0_mvpconf1, tl, env)
|
||||
DEF_HELPER_1(mftc0_vpecontrol, tl, env)
|
||||
DEF_HELPER_1(mftc0_vpeconf0, tl, env)
|
||||
DEF_HELPER_1(mfc0_random, tl, env)
|
||||
DEF_HELPER_1(mfc0_tcstatus, tl, env)
|
||||
DEF_HELPER_1(mftc0_tcstatus, tl, env)
|
||||
DEF_HELPER_1(mfc0_tcbind, tl, env)
|
||||
DEF_HELPER_1(mftc0_tcbind, tl, env)
|
||||
DEF_HELPER_1(mfc0_tcrestart, tl, env)
|
||||
DEF_HELPER_1(mftc0_tcrestart, tl, env)
|
||||
DEF_HELPER_1(mfc0_tchalt, tl, env)
|
||||
DEF_HELPER_1(mftc0_tchalt, tl, env)
|
||||
DEF_HELPER_1(mfc0_tccontext, tl, env)
|
||||
DEF_HELPER_1(mftc0_tccontext, tl, env)
|
||||
DEF_HELPER_1(mfc0_tcschedule, tl, env)
|
||||
DEF_HELPER_1(mftc0_tcschedule, tl, env)
|
||||
DEF_HELPER_1(mfc0_tcschefback, tl, env)
|
||||
DEF_HELPER_1(mftc0_tcschefback, tl, env)
|
||||
DEF_HELPER_1(mfc0_count, tl, env)
|
||||
DEF_HELPER_1(mftc0_entryhi, tl, env)
|
||||
DEF_HELPER_1(mftc0_status, tl, env)
|
||||
DEF_HELPER_1(mftc0_cause, tl, env)
|
||||
DEF_HELPER_1(mftc0_epc, tl, env)
|
||||
DEF_HELPER_1(mftc0_ebase, tl, env)
|
||||
DEF_HELPER_2(mftc0_configx, tl, env, tl)
|
||||
DEF_HELPER_1(mfc0_lladdr, tl, env)
|
||||
DEF_HELPER_2(mfc0_watchlo, tl, env, i32)
|
||||
DEF_HELPER_2(mfc0_watchhi, tl, env, i32)
|
||||
DEF_HELPER_1(mfc0_debug, tl, env)
|
||||
DEF_HELPER_1(mftc0_debug, tl, env)
|
||||
#ifdef TARGET_MIPS64
|
||||
DEF_HELPER_1(dmfc0_tcrestart, tl, env)
|
||||
DEF_HELPER_1(dmfc0_tchalt, tl, env)
|
||||
DEF_HELPER_1(dmfc0_tccontext, tl, env)
|
||||
DEF_HELPER_1(dmfc0_tcschedule, tl, env)
|
||||
DEF_HELPER_1(dmfc0_tcschefback, tl, env)
|
||||
DEF_HELPER_1(dmfc0_lladdr, tl, env)
|
||||
DEF_HELPER_2(dmfc0_watchlo, tl, env, i32)
|
||||
#endif /* TARGET_MIPS64 */
|
||||
|
||||
DEF_HELPER_2(mtc0_index, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_mvpcontrol, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_vpecontrol, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_vpecontrol, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_vpeconf0, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_vpeconf0, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_vpeconf1, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_yqmask, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_vpeopt, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_entrylo0, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_tcstatus, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_tcstatus, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_tcbind, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_tcbind, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_tcrestart, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_tcrestart, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_tchalt, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_tchalt, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_tccontext, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_tccontext, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_tcschedule, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_tcschedule, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_tcschefback, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_tcschefback, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_entrylo1, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_context, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_pagemask, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_pagegrain, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_wired, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_srsconf0, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_srsconf1, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_srsconf2, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_srsconf3, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_srsconf4, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_hwrena, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_count, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_entryhi, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_entryhi, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_compare, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_status, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_status, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_intctl, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_srsctl, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_cause, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_cause, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_ebase, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_ebase, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_config0, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_config2, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_config4, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_config5, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_lladdr, void, env, tl)
|
||||
DEF_HELPER_3(mtc0_watchlo, void, env, tl, i32)
|
||||
DEF_HELPER_3(mtc0_watchhi, void, env, tl, i32)
|
||||
DEF_HELPER_2(mtc0_xcontext, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_framemask, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_debug, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_debug, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_performance0, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_taglo, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_datalo, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_taghi, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_datahi, void, env, tl)
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_2(dmtc0_entrylo0, void, env, i64)
|
||||
DEF_HELPER_2(dmtc0_entrylo1, void, env, i64)
|
||||
#endif
|
||||
|
||||
/* MIPS MT functions */
|
||||
DEF_HELPER_2(mftgpr, tl, env, i32)
|
||||
DEF_HELPER_2(mftlo, tl, env, i32)
|
||||
DEF_HELPER_2(mfthi, tl, env, i32)
|
||||
DEF_HELPER_2(mftacx, tl, env, i32)
|
||||
DEF_HELPER_1(mftdsp, tl, env)
|
||||
DEF_HELPER_3(mttgpr, void, env, tl, i32)
|
||||
DEF_HELPER_3(mttlo, void, env, tl, i32)
|
||||
DEF_HELPER_3(mtthi, void, env, tl, i32)
|
||||
DEF_HELPER_3(mttacx, void, env, tl, i32)
|
||||
DEF_HELPER_2(mttdsp, void, env, tl)
|
||||
DEF_HELPER_0(dmt, tl)
|
||||
DEF_HELPER_0(emt, tl)
|
||||
DEF_HELPER_1(dvpe, tl, env)
|
||||
DEF_HELPER_1(evpe, tl, env)
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
/* microMIPS functions */
|
||||
DEF_HELPER_4(lwm, void, env, tl, tl, i32)
|
||||
DEF_HELPER_4(swm, void, env, tl, tl, i32)
|
||||
#ifdef TARGET_MIPS64
|
||||
DEF_HELPER_4(ldm, void, env, tl, tl, i32)
|
||||
DEF_HELPER_4(sdm, void, env, tl, tl, i32)
|
||||
#endif
|
||||
|
||||
DEF_HELPER_2(fork, void, tl, tl)
|
||||
DEF_HELPER_2(yield, tl, env, tl)
|
||||
|
||||
/* CP1 functions */
|
||||
DEF_HELPER_2(cfc1, tl, env, i32)
|
||||
DEF_HELPER_4(ctc1, void, env, tl, i32, i32)
|
||||
|
||||
DEF_HELPER_2(float_cvtd_s, i64, env, i32)
|
||||
DEF_HELPER_2(float_cvtd_w, i64, env, i32)
|
||||
DEF_HELPER_2(float_cvtd_l, i64, env, i64)
|
||||
DEF_HELPER_2(float_cvtl_d, i64, env, i64)
|
||||
DEF_HELPER_2(float_cvtl_s, i64, env, i32)
|
||||
DEF_HELPER_2(float_cvtps_pw, i64, env, i64)
|
||||
DEF_HELPER_2(float_cvtpw_ps, i64, env, i64)
|
||||
DEF_HELPER_2(float_cvts_d, i32, env, i64)
|
||||
DEF_HELPER_2(float_cvts_w, i32, env, i32)
|
||||
DEF_HELPER_2(float_cvts_l, i32, env, i64)
|
||||
DEF_HELPER_2(float_cvts_pl, i32, env, i32)
|
||||
DEF_HELPER_2(float_cvts_pu, i32, env, i32)
|
||||
DEF_HELPER_2(float_cvtw_s, i32, env, i32)
|
||||
DEF_HELPER_2(float_cvtw_d, i32, env, i64)
|
||||
|
||||
DEF_HELPER_3(float_addr_ps, i64, env, i64, i64)
|
||||
DEF_HELPER_3(float_mulr_ps, i64, env, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_1(float_class_s, TCG_CALL_NO_RWG_SE, i32, i32)
|
||||
DEF_HELPER_FLAGS_1(float_class_d, TCG_CALL_NO_RWG_SE, i64, i64)
|
||||
|
||||
#define FOP_PROTO(op) \
|
||||
DEF_HELPER_4(float_ ## op ## _s, i32, env, i32, i32, i32) \
|
||||
DEF_HELPER_4(float_ ## op ## _d, i64, env, i64, i64, i64)
|
||||
FOP_PROTO(maddf)
|
||||
FOP_PROTO(msubf)
|
||||
#undef FOP_PROTO
|
||||
|
||||
#define FOP_PROTO(op) \
|
||||
DEF_HELPER_3(float_ ## op ## _s, i32, env, i32, i32) \
|
||||
DEF_HELPER_3(float_ ## op ## _d, i64, env, i64, i64)
|
||||
FOP_PROTO(max)
|
||||
FOP_PROTO(maxa)
|
||||
FOP_PROTO(min)
|
||||
FOP_PROTO(mina)
|
||||
#undef FOP_PROTO
|
||||
|
||||
#define FOP_PROTO(op) \
|
||||
DEF_HELPER_2(float_ ## op ## l_s, i64, env, i32) \
|
||||
DEF_HELPER_2(float_ ## op ## l_d, i64, env, i64) \
|
||||
DEF_HELPER_2(float_ ## op ## w_s, i32, env, i32) \
|
||||
DEF_HELPER_2(float_ ## op ## w_d, i32, env, i64)
|
||||
FOP_PROTO(round)
|
||||
FOP_PROTO(trunc)
|
||||
FOP_PROTO(ceil)
|
||||
FOP_PROTO(floor)
|
||||
#undef FOP_PROTO
|
||||
|
||||
#define FOP_PROTO(op) \
|
||||
DEF_HELPER_2(float_ ## op ## _s, i32, env, i32) \
|
||||
DEF_HELPER_2(float_ ## op ## _d, i64, env, i64)
|
||||
FOP_PROTO(sqrt)
|
||||
FOP_PROTO(rsqrt)
|
||||
FOP_PROTO(recip)
|
||||
FOP_PROTO(rint)
|
||||
#undef FOP_PROTO
|
||||
|
||||
#define FOP_PROTO(op) \
|
||||
DEF_HELPER_1(float_ ## op ## _s, i32, i32) \
|
||||
DEF_HELPER_1(float_ ## op ## _d, i64, i64) \
|
||||
DEF_HELPER_1(float_ ## op ## _ps, i64, i64)
|
||||
FOP_PROTO(abs)
|
||||
FOP_PROTO(chs)
|
||||
#undef FOP_PROTO
|
||||
|
||||
#define FOP_PROTO(op) \
|
||||
DEF_HELPER_2(float_ ## op ## _s, i32, env, i32) \
|
||||
DEF_HELPER_2(float_ ## op ## _d, i64, env, i64) \
|
||||
DEF_HELPER_2(float_ ## op ## _ps, i64, env, i64)
|
||||
FOP_PROTO(recip1)
|
||||
FOP_PROTO(rsqrt1)
|
||||
#undef FOP_PROTO
|
||||
|
||||
#define FOP_PROTO(op) \
|
||||
DEF_HELPER_3(float_ ## op ## _s, i32, env, i32, i32) \
|
||||
DEF_HELPER_3(float_ ## op ## _d, i64, env, i64, i64) \
|
||||
DEF_HELPER_3(float_ ## op ## _ps, i64, env, i64, i64)
|
||||
FOP_PROTO(add)
|
||||
FOP_PROTO(sub)
|
||||
FOP_PROTO(mul)
|
||||
FOP_PROTO(div)
|
||||
FOP_PROTO(recip2)
|
||||
FOP_PROTO(rsqrt2)
|
||||
#undef FOP_PROTO
|
||||
|
||||
#define FOP_PROTO(op) \
|
||||
DEF_HELPER_4(float_ ## op ## _s, i32, env, i32, i32, i32) \
|
||||
DEF_HELPER_4(float_ ## op ## _d, i64, env, i64, i64, i64) \
|
||||
DEF_HELPER_4(float_ ## op ## _ps, i64, env, i64, i64, i64)
|
||||
FOP_PROTO(madd)
|
||||
FOP_PROTO(msub)
|
||||
FOP_PROTO(nmadd)
|
||||
FOP_PROTO(nmsub)
|
||||
#undef FOP_PROTO
|
||||
|
||||
#define FOP_PROTO(op) \
|
||||
DEF_HELPER_4(cmp_d_ ## op, void, env, i64, i64, int) \
|
||||
DEF_HELPER_4(cmpabs_d_ ## op, void, env, i64, i64, int) \
|
||||
DEF_HELPER_4(cmp_s_ ## op, void, env, i32, i32, int) \
|
||||
DEF_HELPER_4(cmpabs_s_ ## op, void, env, i32, i32, int) \
|
||||
DEF_HELPER_4(cmp_ps_ ## op, void, env, i64, i64, int) \
|
||||
DEF_HELPER_4(cmpabs_ps_ ## op, void, env, i64, i64, int)
|
||||
FOP_PROTO(f)
|
||||
FOP_PROTO(un)
|
||||
FOP_PROTO(eq)
|
||||
FOP_PROTO(ueq)
|
||||
FOP_PROTO(olt)
|
||||
FOP_PROTO(ult)
|
||||
FOP_PROTO(ole)
|
||||
FOP_PROTO(ule)
|
||||
FOP_PROTO(sf)
|
||||
FOP_PROTO(ngle)
|
||||
FOP_PROTO(seq)
|
||||
FOP_PROTO(ngl)
|
||||
FOP_PROTO(lt)
|
||||
FOP_PROTO(nge)
|
||||
FOP_PROTO(le)
|
||||
FOP_PROTO(ngt)
|
||||
#undef FOP_PROTO
|
||||
|
||||
#define FOP_PROTO(op) \
|
||||
DEF_HELPER_3(r6_cmp_d_ ## op, i64, env, i64, i64) \
|
||||
DEF_HELPER_3(r6_cmp_s_ ## op, i32, env, i32, i32)
|
||||
FOP_PROTO(af)
|
||||
FOP_PROTO(un)
|
||||
FOP_PROTO(eq)
|
||||
FOP_PROTO(ueq)
|
||||
FOP_PROTO(lt)
|
||||
FOP_PROTO(ult)
|
||||
FOP_PROTO(le)
|
||||
FOP_PROTO(ule)
|
||||
FOP_PROTO(saf)
|
||||
FOP_PROTO(sun)
|
||||
FOP_PROTO(seq)
|
||||
FOP_PROTO(sueq)
|
||||
FOP_PROTO(slt)
|
||||
FOP_PROTO(sult)
|
||||
FOP_PROTO(sle)
|
||||
FOP_PROTO(sule)
|
||||
FOP_PROTO(or)
|
||||
FOP_PROTO(une)
|
||||
FOP_PROTO(ne)
|
||||
FOP_PROTO(sor)
|
||||
FOP_PROTO(sune)
|
||||
FOP_PROTO(sne)
|
||||
#undef FOP_PROTO
|
||||
|
||||
/* Special functions */
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
DEF_HELPER_1(tlbwi, void, env)
|
||||
DEF_HELPER_1(tlbwr, void, env)
|
||||
DEF_HELPER_1(tlbp, void, env)
|
||||
DEF_HELPER_1(tlbr, void, env)
|
||||
DEF_HELPER_1(tlbinv, void, env)
|
||||
DEF_HELPER_1(tlbinvf, void, env)
|
||||
DEF_HELPER_1(di, tl, env)
|
||||
DEF_HELPER_1(ei, tl, env)
|
||||
DEF_HELPER_1(eret, void, env)
|
||||
DEF_HELPER_1(deret, void, env)
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
DEF_HELPER_1(rdhwr_cpunum, tl, env)
|
||||
DEF_HELPER_1(rdhwr_synci_step, tl, env)
|
||||
DEF_HELPER_1(rdhwr_cc, tl, env)
|
||||
DEF_HELPER_1(rdhwr_ccres, tl, env)
|
||||
DEF_HELPER_2(pmon, void, env, int)
|
||||
DEF_HELPER_1(wait, void, env)
|
||||
|
||||
/* Loongson multimedia functions. */
|
||||
DEF_HELPER_FLAGS_2(paddsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(paddush, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(paddh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(paddw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(paddsb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(paddusb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(paddb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(psubsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psubush, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psubh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psubw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psubsb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psubusb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psubb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(pshufh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(packsswh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(packsshb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(packushb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(punpcklhw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(punpckhhw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(punpcklbh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(punpckhbh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(punpcklwd, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(punpckhwd, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(pavgh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pavgb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmaxsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pminsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmaxub, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pminub, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(pcmpeqw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pcmpgtw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pcmpeqh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pcmpgth, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pcmpeqb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pcmpgtb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(psllw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psllh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psrlw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psrlh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psraw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psrah, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(pmullh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmulhh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmulhuh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmaddhw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(pasubub, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_1(biadd, TCG_CALL_NO_RWG_SE, i64, i64)
|
||||
DEF_HELPER_FLAGS_1(pmovmskb, TCG_CALL_NO_RWG_SE, i64, i64)
|
||||
|
||||
/*** MIPS DSP ***/
|
||||
/* DSP Arithmetic Sub-class insns */
|
||||
DEF_HELPER_FLAGS_3(addq_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(addq_s_ph, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(addq_qh, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(addq_s_qh, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(addq_s_w, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(addq_pw, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(addq_s_pw, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(addu_qb, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(addu_s_qb, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(adduh_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(adduh_r_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(addu_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(addu_s_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(addqh_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(addqh_r_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(addqh_w, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(addqh_r_w, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(addu_ob, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(addu_s_ob, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(adduh_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(adduh_r_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(addu_qh, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(addu_s_qh, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(subq_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(subq_s_ph, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(subq_qh, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(subq_s_qh, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(subq_s_w, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(subq_pw, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(subq_s_pw, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(subu_qb, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(subu_s_qb, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(subuh_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(subuh_r_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(subu_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(subu_s_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(subqh_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(subqh_r_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(subqh_w, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(subqh_r_w, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(subu_ob, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(subu_s_ob, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(subuh_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(subuh_r_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(subu_qh, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(subu_s_qh, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(addsc, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(addwc, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(modsub, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(raddu_w_qb, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_1(raddu_l_ob, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_2(absq_s_qb, 0, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(absq_s_ph, 0, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(absq_s_w, 0, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_2(absq_s_ob, 0, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(absq_s_qh, 0, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(absq_s_pw, 0, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_2(precr_qb_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(precrq_qb_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(precr_sra_ph_w, TCG_CALL_NO_RWG_SE,
|
||||
tl, i32, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(precr_sra_r_ph_w, TCG_CALL_NO_RWG_SE,
|
||||
tl, i32, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(precrq_ph_w, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(precrq_rs_ph_w, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_2(precr_ob_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(precr_sra_qh_pw,
|
||||
TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
|
||||
DEF_HELPER_FLAGS_3(precr_sra_r_qh_pw,
|
||||
TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
|
||||
DEF_HELPER_FLAGS_2(precrq_ob_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(precrq_qh_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(precrq_rs_qh_pw,
|
||||
TCG_CALL_NO_RWG_SE, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(precrq_pw_l, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(precrqu_s_qb_ph, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(precrqu_s_ob_qh,
|
||||
TCG_CALL_NO_RWG_SE, tl, tl, tl, env)
|
||||
|
||||
DEF_HELPER_FLAGS_1(preceq_pw_qhl, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(preceq_pw_qhr, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(preceq_pw_qhla, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(preceq_pw_qhra, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_1(precequ_ph_qbl, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(precequ_ph_qbr, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(precequ_ph_qbla, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(precequ_ph_qbra, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_1(precequ_qh_obl, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(precequ_qh_obr, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(precequ_qh_obla, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(precequ_qh_obra, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_1(preceu_ph_qbl, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(preceu_ph_qbr, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(preceu_ph_qbla, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(preceu_ph_qbra, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_1(preceu_qh_obl, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(preceu_qh_obr, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(preceu_qh_obla, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(preceu_qh_obra, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#endif
|
||||
|
||||
/* DSP GPR-Based Shift Sub-class insns */
|
||||
DEF_HELPER_FLAGS_3(shll_qb, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(shll_ob, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(shll_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(shll_s_ph, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(shll_qh, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(shll_s_qh, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(shll_s_w, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(shll_pw, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(shll_s_pw, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_2(shrl_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(shrl_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_2(shrl_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(shrl_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_2(shra_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(shra_r_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_2(shra_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(shra_r_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_2(shra_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(shra_r_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(shra_r_w, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_2(shra_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(shra_r_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(shra_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(shra_r_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#endif
|
||||
|
||||
/* DSP Multiply Sub-class insns */
|
||||
DEF_HELPER_FLAGS_3(muleu_s_ph_qbl, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(muleu_s_ph_qbr, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(muleu_s_qh_obl, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(muleu_s_qh_obr, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(mulq_rs_ph, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(mulq_rs_qh, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(muleq_s_w_phl, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(muleq_s_w_phr, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(muleq_s_pw_qhl, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(muleq_s_pw_qhr, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpau_h_qbl, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dpau_h_qbr, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpau_h_obl, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(dpau_h_obr, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpsu_h_qbl, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dpsu_h_qbr, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpsu_h_obl, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(dpsu_h_obr, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpa_w_ph, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpa_w_qh, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpax_w_ph, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dpaq_s_w_ph, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpaq_s_w_qh, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpaqx_s_w_ph, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dpaqx_sa_w_ph, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dps_w_ph, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dps_w_qh, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpsx_w_ph, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dpsq_s_w_ph, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpsq_s_w_qh, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpsqx_s_w_ph, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dpsqx_sa_w_ph, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(mulsaq_s_w_ph, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(mulsaq_s_w_qh, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpaq_sa_l_w, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpaq_sa_l_pw, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpsq_sa_l_w, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpsq_sa_l_pw, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(mulsaq_s_l_pw, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(maq_s_w_phl, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(maq_s_w_phr, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(maq_sa_w_phl, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(maq_sa_w_phr, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(mul_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(mul_s_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(mulq_s_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(mulq_s_w, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(mulq_rs_w, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(mulsa_w_ph, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(maq_s_w_qhll, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_s_w_qhlr, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_s_w_qhrl, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_s_w_qhrr, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_sa_w_qhll, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_sa_w_qhlr, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_sa_w_qhrl, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_sa_w_qhrr, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_s_l_pwl, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_s_l_pwr, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(dmadd, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(dmaddu, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(dmsub, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(dmsubu, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
|
||||
/* DSP Bit/Manipulation Sub-class insns */
|
||||
DEF_HELPER_FLAGS_1(bitrev, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(insv, 0, tl, env, tl, tl)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(dinsv, 0, tl, env, tl, tl)
|
||||
#endif
|
||||
|
||||
/* DSP Compare-Pick Sub-class insns */
|
||||
DEF_HELPER_FLAGS_3(cmpu_eq_qb, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmpu_lt_qb, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmpu_le_qb, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(cmpgu_eq_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(cmpgu_lt_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(cmpgu_le_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(cmp_eq_ph, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmp_lt_ph, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmp_le_ph, 0, void, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(cmpu_eq_ob, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmpu_lt_ob, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmpu_le_ob, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmpgdu_eq_ob, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmpgdu_lt_ob, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmpgdu_le_ob, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(cmpgu_eq_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(cmpgu_lt_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(cmpgu_le_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(cmp_eq_qh, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmp_lt_qh, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmp_le_qh, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmp_eq_pw, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmp_lt_pw, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmp_le_pw, 0, void, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(pick_qb, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(pick_ph, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(pick_ob, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(pick_qh, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(pick_pw, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_2(packrl_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_2(packrl_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#endif
|
||||
|
||||
/* DSP Accumulator and DSPControl Access Sub-class insns */
|
||||
DEF_HELPER_FLAGS_3(extr_w, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(extr_r_w, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(extr_rs_w, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(dextr_w, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(dextr_r_w, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(dextr_rs_w, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(dextr_l, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(dextr_r_l, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(dextr_rs_l, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(extr_s_h, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(dextr_s_h, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(extp, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(extpdp, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(dextp, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(dextpdp, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(shilo, 0, void, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(dshilo, 0, void, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(mthlip, 0, void, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(dmthlip, 0, void, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(wrdsp, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env)
|
||||
|
||||
/* MIPS SIMD Architecture */
|
||||
DEF_HELPER_4(msa_andi_b, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_ori_b, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_nori_b, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_xori_b, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_bmnzi_b, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_bmzi_b, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_bseli_b, void, env, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_shf_df, void, env, i32, i32, i32, i32)
|
||||
|
||||
DEF_HELPER_5(msa_addvi_df, void, env, i32, i32, i32, s32)
|
||||
DEF_HELPER_5(msa_subvi_df, void, env, i32, i32, i32, s32)
|
||||
DEF_HELPER_5(msa_maxi_s_df, void, env, i32, i32, i32, s32)
|
||||
DEF_HELPER_5(msa_maxi_u_df, void, env, i32, i32, i32, s32)
|
||||
DEF_HELPER_5(msa_mini_s_df, void, env, i32, i32, i32, s32)
|
||||
DEF_HELPER_5(msa_mini_u_df, void, env, i32, i32, i32, s32)
|
||||
DEF_HELPER_5(msa_ceqi_df, void, env, i32, i32, i32, s32)
|
||||
DEF_HELPER_5(msa_clti_s_df, void, env, i32, i32, i32, s32)
|
||||
DEF_HELPER_5(msa_clti_u_df, void, env, i32, i32, i32, s32)
|
||||
DEF_HELPER_5(msa_clei_s_df, void, env, i32, i32, i32, s32)
|
||||
DEF_HELPER_5(msa_clei_u_df, void, env, i32, i32, i32, s32)
|
||||
DEF_HELPER_4(msa_ldi_df, void, env, i32, i32, s32)
|
||||
|
||||
DEF_HELPER_5(msa_slli_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_srai_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_srli_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_bclri_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_bseti_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_bnegi_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_binsli_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_binsri_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_sat_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_sat_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_srari_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32)
|
||||
|
||||
DEF_HELPER_5(msa_sll_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_sra_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_srl_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_bclr_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_bset_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_bneg_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_binsl_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_binsr_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_addv_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_subv_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_max_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_max_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_min_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_min_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_max_a_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_min_a_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_ceq_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_clt_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_clt_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_cle_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_cle_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_add_a_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_adds_a_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_adds_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_adds_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_ave_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_ave_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_aver_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_aver_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_subs_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_subs_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_subsus_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_subsuu_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_asub_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_asub_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_maddv_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_msubv_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_div_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_div_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_mod_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_mod_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_dotp_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_dotp_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_dpadd_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_dpadd_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_dpsub_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_dpsub_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_sld_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_splat_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_pckev_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_pckod_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_ilvl_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_ilvr_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_ilvev_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_ilvod_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_vshf_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_srar_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_srlr_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_hadd_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_hadd_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_hsub_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_hsub_u_df, void, env, i32, i32, i32, i32)
|
||||
|
||||
DEF_HELPER_5(msa_sldi_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_splati_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_copy_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_copy_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_insert_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_3(msa_ctcmsa, void, env, tl, i32)
|
||||
DEF_HELPER_2(msa_cfcmsa, tl, env, i32)
|
||||
DEF_HELPER_3(msa_move_v, void, env, i32, i32)
|
||||
|
||||
DEF_HELPER_5(msa_fcaf_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fcun_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fceq_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fcueq_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fclt_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fcult_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fcle_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fcule_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fsaf_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fsun_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fseq_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fsueq_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fslt_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fsult_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fsle_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fsule_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fadd_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fsub_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fmul_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fdiv_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fmadd_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fmsub_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fexp2_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fexdo_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_ftq_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fmin_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fmin_a_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fmax_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fmax_a_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fcor_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fcune_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fcne_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_mul_q_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_madd_q_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_msub_q_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fsor_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fsune_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_fsne_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_mulr_q_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_maddr_q_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_msubr_q_df, void, env, i32, i32, i32, i32)
|
||||
|
||||
DEF_HELPER_4(msa_and_v, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_or_v, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_nor_v, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_xor_v, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_bmnz_v, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_bmz_v, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_bsel_v, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_fill_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_pcnt_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_nloc_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_nlzc_df, void, env, i32, i32, i32)
|
||||
|
||||
DEF_HELPER_4(msa_fclass_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_ftrunc_s_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_ftrunc_u_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_fsqrt_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_frsqrt_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_frcp_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_frint_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_flog2_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_fexupl_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_fexupr_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_ffql_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_ffqr_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_ftint_s_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_ftint_u_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_ffint_s_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_ffint_u_df, void, env, i32, i32, i32)
|
||||
|
||||
DEF_HELPER_5(msa_ld_df, void, env, i32, i32, i32, s32)
|
||||
DEF_HELPER_5(msa_st_df, void, env, i32, i32, i32, s32)
|
@ -1,744 +0,0 @@
|
||||
/*
|
||||
* Loongson Multimedia Instruction emulation helpers for QEMU.
|
||||
*
|
||||
* Copyright (c) 2011 Richard Henderson <rth@twiddle.net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "cpu.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
||||
/* If the byte ordering doesn't matter, i.e. all columns are treated
|
||||
identically, then this union can be used directly. If byte ordering
|
||||
does matter, we generally ignore dumping to memory. */
|
||||
typedef union {
|
||||
uint8_t ub[8];
|
||||
int8_t sb[8];
|
||||
uint16_t uh[4];
|
||||
int16_t sh[4];
|
||||
uint32_t uw[2];
|
||||
int32_t sw[2];
|
||||
uint64_t d;
|
||||
} LMIValue;
|
||||
|
||||
/* Some byte ordering issues can be mitigated by XORing in the following. */
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
# define BYTE_ORDER_XOR(N) N
|
||||
#else
|
||||
# define BYTE_ORDER_XOR(N) 0
|
||||
#endif
|
||||
|
||||
#define SATSB(x) (x < -0x80 ? -0x80 : x > 0x7f ? 0x7f : x)
|
||||
#define SATUB(x) (x > 0xff ? 0xff : x)
|
||||
|
||||
#define SATSH(x) (x < -0x8000 ? -0x8000 : x > 0x7fff ? 0x7fff : x)
|
||||
#define SATUH(x) (x > 0xffff ? 0xffff : x)
|
||||
|
||||
#define SATSW(x) \
|
||||
(x < -0x80000000ll ? -0x80000000ll : x > 0x7fffffff ? 0x7fffffff : x)
|
||||
#define SATUW(x) (x > 0xffffffffull ? 0xffffffffull : x)
|
||||
|
||||
uint64_t helper_paddsb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
int r = vs.sb[i] + vt.sb[i];
|
||||
vs.sb[i] = SATSB(r);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_paddusb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
int r = vs.ub[i] + vt.ub[i];
|
||||
vs.ub[i] = SATUB(r);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_paddsh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
int r = vs.sh[i] + vt.sh[i];
|
||||
vs.sh[i] = SATSH(r);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_paddush(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
int r = vs.uh[i] + vt.uh[i];
|
||||
vs.uh[i] = SATUH(r);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_paddb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
vs.ub[i] += vt.ub[i];
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_paddh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
vs.uh[i] += vt.uh[i];
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_paddw(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 2; ++i) {
|
||||
vs.uw[i] += vt.uw[i];
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psubsb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
int r = vs.sb[i] - vt.sb[i];
|
||||
vs.sb[i] = SATSB(r);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psubusb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
int r = vs.ub[i] - vt.ub[i];
|
||||
vs.ub[i] = SATUB(r);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psubsh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
int r = vs.sh[i] - vt.sh[i];
|
||||
vs.sh[i] = SATSH(r);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psubush(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
int r = vs.uh[i] - vt.uh[i];
|
||||
vs.uh[i] = SATUH(r);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psubb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
vs.ub[i] -= vt.ub[i];
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psubh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
vs.uh[i] -= vt.uh[i];
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psubw(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 2; ++i) {
|
||||
vs.uw[i] -= vt.uw[i];
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pshufh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
unsigned host = BYTE_ORDER_XOR(3);
|
||||
LMIValue vd, vs;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vd.d = 0;
|
||||
for (i = 0; i < 4; i++, ft >>= 2) {
|
||||
vd.uh[i ^ host] = vs.uh[(ft & 3) ^ host];
|
||||
}
|
||||
return vd.d;
|
||||
}
|
||||
|
||||
uint64_t helper_packsswh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
uint64_t fd = 0;
|
||||
int64_t tmp;
|
||||
|
||||
tmp = (int32_t)(fs >> 0);
|
||||
tmp = SATSH(tmp);
|
||||
fd |= (tmp & 0xffff) << 0;
|
||||
|
||||
tmp = (int32_t)(fs >> 32);
|
||||
tmp = SATSH(tmp);
|
||||
fd |= (tmp & 0xffff) << 16;
|
||||
|
||||
tmp = (int32_t)(ft >> 0);
|
||||
tmp = SATSH(tmp);
|
||||
fd |= (tmp & 0xffff) << 32;
|
||||
|
||||
tmp = (int32_t)(ft >> 32);
|
||||
tmp = SATSH(tmp);
|
||||
fd |= (tmp & 0xffff) << 48;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
uint64_t helper_packsshb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
uint64_t fd = 0;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
int16_t tmp = fs >> (i * 16);
|
||||
tmp = SATSB(tmp);
|
||||
fd |= (uint64_t)(tmp & 0xff) << (i * 8);
|
||||
}
|
||||
for (i = 0; i < 4; ++i) {
|
||||
int16_t tmp = ft >> (i * 16);
|
||||
tmp = SATSB(tmp);
|
||||
fd |= (uint64_t)(tmp & 0xff) << (i * 8 + 32);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
uint64_t helper_packushb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
uint64_t fd = 0;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
int16_t tmp = fs >> (i * 16);
|
||||
tmp = SATUB(tmp);
|
||||
fd |= (uint64_t)(tmp & 0xff) << (i * 8);
|
||||
}
|
||||
for (i = 0; i < 4; ++i) {
|
||||
int16_t tmp = ft >> (i * 16);
|
||||
tmp = SATUB(tmp);
|
||||
fd |= (uint64_t)(tmp & 0xff) << (i * 8 + 32);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
uint64_t helper_punpcklwd(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
return (fs & 0xffffffff) | (ft << 32);
|
||||
}
|
||||
|
||||
uint64_t helper_punpckhwd(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
return (fs >> 32) | (ft & ~0xffffffffull);
|
||||
}
|
||||
|
||||
uint64_t helper_punpcklhw(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
unsigned host = BYTE_ORDER_XOR(3);
|
||||
LMIValue vd, vs, vt;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
vd.uh[0 ^ host] = vs.uh[0 ^ host];
|
||||
vd.uh[1 ^ host] = vt.uh[0 ^ host];
|
||||
vd.uh[2 ^ host] = vs.uh[1 ^ host];
|
||||
vd.uh[3 ^ host] = vt.uh[1 ^ host];
|
||||
|
||||
return vd.d;
|
||||
}
|
||||
|
||||
uint64_t helper_punpckhhw(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
unsigned host = BYTE_ORDER_XOR(3);
|
||||
LMIValue vd, vs, vt;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
vd.uh[0 ^ host] = vs.uh[2 ^ host];
|
||||
vd.uh[1 ^ host] = vt.uh[2 ^ host];
|
||||
vd.uh[2 ^ host] = vs.uh[3 ^ host];
|
||||
vd.uh[3 ^ host] = vt.uh[3 ^ host];
|
||||
|
||||
return vd.d;
|
||||
}
|
||||
|
||||
uint64_t helper_punpcklbh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
unsigned host = BYTE_ORDER_XOR(7);
|
||||
LMIValue vd, vs, vt;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
vd.ub[0 ^ host] = vs.ub[0 ^ host];
|
||||
vd.ub[1 ^ host] = vt.ub[0 ^ host];
|
||||
vd.ub[2 ^ host] = vs.ub[1 ^ host];
|
||||
vd.ub[3 ^ host] = vt.ub[1 ^ host];
|
||||
vd.ub[4 ^ host] = vs.ub[2 ^ host];
|
||||
vd.ub[5 ^ host] = vt.ub[2 ^ host];
|
||||
vd.ub[6 ^ host] = vs.ub[3 ^ host];
|
||||
vd.ub[7 ^ host] = vt.ub[3 ^ host];
|
||||
|
||||
return vd.d;
|
||||
}
|
||||
|
||||
uint64_t helper_punpckhbh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
unsigned host = BYTE_ORDER_XOR(7);
|
||||
LMIValue vd, vs, vt;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
vd.ub[0 ^ host] = vs.ub[4 ^ host];
|
||||
vd.ub[1 ^ host] = vt.ub[4 ^ host];
|
||||
vd.ub[2 ^ host] = vs.ub[5 ^ host];
|
||||
vd.ub[3 ^ host] = vt.ub[5 ^ host];
|
||||
vd.ub[4 ^ host] = vs.ub[6 ^ host];
|
||||
vd.ub[5 ^ host] = vt.ub[6 ^ host];
|
||||
vd.ub[6 ^ host] = vs.ub[7 ^ host];
|
||||
vd.ub[7 ^ host] = vt.ub[7 ^ host];
|
||||
|
||||
return vd.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pavgh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; i++) {
|
||||
vs.uh[i] = (vs.uh[i] + vt.uh[i] + 1) >> 1;
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pavgb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 8; i++) {
|
||||
vs.ub[i] = (vs.ub[i] + vt.ub[i] + 1) >> 1;
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pmaxsh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; i++) {
|
||||
vs.sh[i] = (vs.sh[i] >= vt.sh[i] ? vs.sh[i] : vt.sh[i]);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pminsh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; i++) {
|
||||
vs.sh[i] = (vs.sh[i] <= vt.sh[i] ? vs.sh[i] : vt.sh[i]);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pmaxub(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; i++) {
|
||||
vs.ub[i] = (vs.ub[i] >= vt.ub[i] ? vs.ub[i] : vt.ub[i]);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pminub(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; i++) {
|
||||
vs.ub[i] = (vs.ub[i] <= vt.ub[i] ? vs.ub[i] : vt.ub[i]);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pcmpeqw(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 2; i++) {
|
||||
vs.uw[i] = -(vs.uw[i] == vt.uw[i]);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pcmpgtw(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 2; i++) {
|
||||
vs.uw[i] = -(vs.uw[i] > vt.uw[i]);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pcmpeqh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; i++) {
|
||||
vs.uh[i] = -(vs.uh[i] == vt.uh[i]);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pcmpgth(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; i++) {
|
||||
vs.uh[i] = -(vs.uh[i] > vt.uh[i]);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pcmpeqb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 8; i++) {
|
||||
vs.ub[i] = -(vs.ub[i] == vt.ub[i]);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pcmpgtb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 8; i++) {
|
||||
vs.ub[i] = -(vs.ub[i] > vt.ub[i]);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psllw(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs;
|
||||
unsigned i;
|
||||
|
||||
ft &= 0x7f;
|
||||
if (ft > 31) {
|
||||
return 0;
|
||||
}
|
||||
vs.d = fs;
|
||||
for (i = 0; i < 2; ++i) {
|
||||
vs.uw[i] <<= ft;
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psrlw(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs;
|
||||
unsigned i;
|
||||
|
||||
ft &= 0x7f;
|
||||
if (ft > 31) {
|
||||
return 0;
|
||||
}
|
||||
vs.d = fs;
|
||||
for (i = 0; i < 2; ++i) {
|
||||
vs.uw[i] >>= ft;
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psraw(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs;
|
||||
unsigned i;
|
||||
|
||||
ft &= 0x7f;
|
||||
if (ft > 31) {
|
||||
ft = 31;
|
||||
}
|
||||
vs.d = fs;
|
||||
for (i = 0; i < 2; ++i) {
|
||||
vs.sw[i] >>= ft;
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psllh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs;
|
||||
unsigned i;
|
||||
|
||||
ft &= 0x7f;
|
||||
if (ft > 15) {
|
||||
return 0;
|
||||
}
|
||||
vs.d = fs;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
vs.uh[i] <<= ft;
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psrlh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs;
|
||||
unsigned i;
|
||||
|
||||
ft &= 0x7f;
|
||||
if (ft > 15) {
|
||||
return 0;
|
||||
}
|
||||
vs.d = fs;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
vs.uh[i] >>= ft;
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psrah(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs;
|
||||
unsigned i;
|
||||
|
||||
ft &= 0x7f;
|
||||
if (ft > 15) {
|
||||
ft = 15;
|
||||
}
|
||||
vs.d = fs;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
vs.sh[i] >>= ft;
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pmullh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
vs.sh[i] *= vt.sh[i];
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pmulhh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
int32_t r = vs.sh[i] * vt.sh[i];
|
||||
vs.sh[i] = r >> 16;
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pmulhuh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
uint32_t r = vs.uh[i] * vt.uh[i];
|
||||
vs.uh[i] = r >> 16;
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pmaddhw(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
unsigned host = BYTE_ORDER_XOR(3);
|
||||
LMIValue vs, vt;
|
||||
uint32_t p0, p1;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
p0 = vs.sh[0 ^ host] * vt.sh[0 ^ host];
|
||||
p0 += vs.sh[1 ^ host] * vt.sh[1 ^ host];
|
||||
p1 = vs.sh[2 ^ host] * vt.sh[2 ^ host];
|
||||
p1 += vs.sh[3 ^ host] * vt.sh[3 ^ host];
|
||||
|
||||
return ((uint64_t)p1 << 32) | p0;
|
||||
}
|
||||
|
||||
uint64_t helper_pasubub(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
int r = vs.ub[i] - vt.ub[i];
|
||||
vs.ub[i] = (r < 0 ? -r : r);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_biadd(uint64_t fs)
|
||||
{
|
||||
unsigned i, fd;
|
||||
|
||||
for (i = fd = 0; i < 8; ++i) {
|
||||
fd += (fs >> (i * 8)) & 0xff;
|
||||
}
|
||||
return fd & 0xffff;
|
||||
}
|
||||
|
||||
uint64_t helper_pmovmskb(uint64_t fs)
|
||||
{
|
||||
unsigned fd = 0;
|
||||
|
||||
fd |= ((fs >> 7) & 1) << 0;
|
||||
fd |= ((fs >> 15) & 1) << 1;
|
||||
fd |= ((fs >> 23) & 1) << 2;
|
||||
fd |= ((fs >> 31) & 1) << 3;
|
||||
fd |= ((fs >> 39) & 1) << 4;
|
||||
fd |= ((fs >> 47) & 1) << 5;
|
||||
fd |= ((fs >> 55) & 1) << 6;
|
||||
fd |= ((fs >> 63) & 1) << 7;
|
||||
|
||||
return fd & 0xff;
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
#if !defined (__QEMU_MIPS_DEFS_H__)
|
||||
#define __QEMU_MIPS_DEFS_H__
|
||||
|
||||
/* If we want to use host float regs... */
|
||||
//#define USE_HOST_FLOAT_REGS
|
||||
|
||||
/* Real pages are variable size... */
|
||||
#define TARGET_PAGE_BITS 12
|
||||
#define MIPS_TLB_MAX 128
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
#define TARGET_LONG_BITS 64
|
||||
#define TARGET_PHYS_ADDR_SPACE_BITS 36
|
||||
#define TARGET_VIRT_ADDR_SPACE_BITS 42
|
||||
#else
|
||||
#define TARGET_LONG_BITS 32
|
||||
#define TARGET_PHYS_ADDR_SPACE_BITS 36
|
||||
#define TARGET_VIRT_ADDR_SPACE_BITS 32
|
||||
#endif
|
||||
|
||||
/* Masks used to mark instructions to indicate which ISA level they
|
||||
were introduced in. */
|
||||
#define ISA_MIPS1 0x00000001
|
||||
#define ISA_MIPS2 0x00000002
|
||||
#define ISA_MIPS3 0x00000004
|
||||
#define ISA_MIPS4 0x00000008
|
||||
#define ISA_MIPS5 0x00000010
|
||||
#define ISA_MIPS32 0x00000020
|
||||
#define ISA_MIPS32R2 0x00000040
|
||||
#define ISA_MIPS64 0x00000080
|
||||
#define ISA_MIPS64R2 0x00000100
|
||||
#define ISA_MIPS32R3 0x00000200
|
||||
#define ISA_MIPS64R3 0x00000400
|
||||
#define ISA_MIPS32R5 0x00000800
|
||||
#define ISA_MIPS64R5 0x00001000
|
||||
#define ISA_MIPS32R6 0x00002000
|
||||
#define ISA_MIPS64R6 0x00004000
|
||||
|
||||
/* MIPS ASEs. */
|
||||
#define ASE_MIPS16 0x00010000
|
||||
#define ASE_MIPS3D 0x00020000
|
||||
#define ASE_MDMX 0x00040000
|
||||
#define ASE_DSP 0x00080000
|
||||
#define ASE_DSPR2 0x00100000
|
||||
#define ASE_MT 0x00200000
|
||||
#define ASE_SMARTMIPS 0x00400000
|
||||
#define ASE_MICROMIPS 0x00800000
|
||||
#define ASE_MSA 0x01000000
|
||||
|
||||
/* Chip specific instructions. */
|
||||
#define INSN_LOONGSON2E 0x20000000
|
||||
#define INSN_LOONGSON2F 0x40000000
|
||||
#define INSN_VR54XX 0x80000000
|
||||
|
||||
/* MIPS CPU defines. */
|
||||
#define CPU_MIPS1 (ISA_MIPS1)
|
||||
#define CPU_MIPS2 (CPU_MIPS1 | ISA_MIPS2)
|
||||
#define CPU_MIPS3 (CPU_MIPS2 | ISA_MIPS3)
|
||||
#define CPU_MIPS4 (CPU_MIPS3 | ISA_MIPS4)
|
||||
#define CPU_VR54XX (CPU_MIPS4 | INSN_VR54XX)
|
||||
#define CPU_LOONGSON2E (CPU_MIPS3 | INSN_LOONGSON2E)
|
||||
#define CPU_LOONGSON2F (CPU_MIPS3 | INSN_LOONGSON2F)
|
||||
|
||||
#define CPU_MIPS5 (CPU_MIPS4 | ISA_MIPS5)
|
||||
|
||||
/* MIPS Technologies "Release 1" */
|
||||
#define CPU_MIPS32 (CPU_MIPS2 | ISA_MIPS32)
|
||||
#define CPU_MIPS64 (CPU_MIPS5 | CPU_MIPS32 | ISA_MIPS64)
|
||||
|
||||
/* MIPS Technologies "Release 2" */
|
||||
#define CPU_MIPS32R2 (CPU_MIPS32 | ISA_MIPS32R2)
|
||||
#define CPU_MIPS64R2 (CPU_MIPS64 | CPU_MIPS32R2 | ISA_MIPS64R2)
|
||||
|
||||
/* MIPS Technologies "Release 3" */
|
||||
#define CPU_MIPS32R3 (CPU_MIPS32R2 | ISA_MIPS32R3)
|
||||
#define CPU_MIPS64R3 (CPU_MIPS64R2 | CPU_MIPS32R3 | ISA_MIPS64R3)
|
||||
|
||||
/* MIPS Technologies "Release 5" */
|
||||
#define CPU_MIPS32R5 (CPU_MIPS32R3 | ISA_MIPS32R5)
|
||||
#define CPU_MIPS64R5 (CPU_MIPS64R3 | CPU_MIPS32R5 | ISA_MIPS64R5)
|
||||
|
||||
/* MIPS Technologies "Release 6" */
|
||||
#define CPU_MIPS32R6 (CPU_MIPS32R5 | ISA_MIPS32R6)
|
||||
#define CPU_MIPS64R6 (CPU_MIPS64R5 | CPU_MIPS32R6 | ISA_MIPS64R6)
|
||||
|
||||
/* Strictly follow the architecture standard:
|
||||
- Disallow "special" instruction handling for PMON/SPIM.
|
||||
Note that we still maintain Count/Compare to match the host clock. */
|
||||
//#define MIPS_STRICT_STANDARD 1
|
||||
|
||||
#endif /* !defined (__QEMU_MIPS_DEFS_H__) */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,948 +0,0 @@
|
||||
/*
|
||||
* MIPS emulation for qemu: CPU initialisation routines.
|
||||
*
|
||||
* Copyright (c) 2004-2005 Jocelyn Mayer
|
||||
* Copyright (c) 2007 Herve Poussineau
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* CPU / CPU family specific config register values. */
|
||||
|
||||
/* Have config1, uncached coherency */
|
||||
#define MIPS_CONFIG0 \
|
||||
((1U << CP0C0_M) | (0x2 << CP0C0_K0))
|
||||
|
||||
/* Have config2, no coprocessor2 attached, no MDMX support attached,
|
||||
no performance counters, watch registers present,
|
||||
no code compression, EJTAG present, no FPU */
|
||||
#define MIPS_CONFIG1 \
|
||||
((1U << CP0C1_M) | \
|
||||
(0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) | \
|
||||
(1 << CP0C1_WR) | (0 << CP0C1_CA) | (1 << CP0C1_EP) | \
|
||||
(0 << CP0C1_FP))
|
||||
|
||||
/* Have config3, no tertiary/secondary caches implemented */
|
||||
#define MIPS_CONFIG2 \
|
||||
((1U << CP0C2_M))
|
||||
|
||||
/* No config4, no DSP ASE, no large physaddr (PABITS),
|
||||
no external interrupt controller, no vectored interrupts,
|
||||
no 1kb pages, no SmartMIPS ASE, no trace logic */
|
||||
#define MIPS_CONFIG3 \
|
||||
((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) | \
|
||||
(0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) | \
|
||||
(0 << CP0C3_SM) | (0 << CP0C3_TL))
|
||||
#define MIPS_CONFIG4 \
|
||||
((0 << CP0C4_M))
|
||||
|
||||
#define MIPS_CONFIG5 \
|
||||
((0 << CP0C5_M))
|
||||
|
||||
/* MMU types, the first four entries have the same layout as the
|
||||
CP0C0_MT field. */
|
||||
enum mips_mmu_types {
|
||||
MMU_TYPE_NONE,
|
||||
MMU_TYPE_R4000,
|
||||
MMU_TYPE_RESERVED,
|
||||
MMU_TYPE_FMT,
|
||||
MMU_TYPE_R3000,
|
||||
MMU_TYPE_R6000,
|
||||
MMU_TYPE_R8000
|
||||
};
|
||||
|
||||
struct mips_def_t {
|
||||
const char *name;
|
||||
int32_t CP0_PRid;
|
||||
int32_t CP0_Config0;
|
||||
int32_t CP0_Config1;
|
||||
int32_t CP0_Config2;
|
||||
int32_t CP0_Config3;
|
||||
int32_t CP0_Config4;
|
||||
int32_t CP0_Config4_rw_bitmask;
|
||||
int32_t CP0_Config5;
|
||||
int32_t CP0_Config5_rw_bitmask;
|
||||
int32_t CP0_Config6;
|
||||
int32_t CP0_Config7;
|
||||
target_ulong CP0_LLAddr_rw_bitmask;
|
||||
int CP0_LLAddr_shift;
|
||||
int32_t SYNCI_Step;
|
||||
int32_t CCRes;
|
||||
int32_t CP0_Status_rw_bitmask;
|
||||
int32_t CP0_TCStatus_rw_bitmask;
|
||||
int32_t CP0_SRSCtl;
|
||||
int32_t CP1_fcr0;
|
||||
int32_t MSAIR;
|
||||
int32_t SEGBITS;
|
||||
int32_t PABITS;
|
||||
int32_t CP0_SRSConf0_rw_bitmask;
|
||||
int32_t CP0_SRSConf0;
|
||||
int32_t CP0_SRSConf1_rw_bitmask;
|
||||
int32_t CP0_SRSConf1;
|
||||
int32_t CP0_SRSConf2_rw_bitmask;
|
||||
int32_t CP0_SRSConf2;
|
||||
int32_t CP0_SRSConf3_rw_bitmask;
|
||||
int32_t CP0_SRSConf3;
|
||||
int32_t CP0_SRSConf4_rw_bitmask;
|
||||
int32_t CP0_SRSConf4;
|
||||
int32_t CP0_PageGrain_rw_bitmask;
|
||||
int32_t CP0_PageGrain;
|
||||
int insn_flags;
|
||||
enum mips_mmu_types mmu_type;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/* MIPS CPU definitions */
|
||||
static const mips_def_t mips_defs[] =
|
||||
{
|
||||
{
|
||||
"4Kc",
|
||||
0x00018000,
|
||||
MIPS_CONFIG0 | (MMU_TYPE_R4000 << CP0C0_MT),
|
||||
MIPS_CONFIG1 | (15 << CP0C1_MMU) |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(0 << CP0C1_CA),
|
||||
MIPS_CONFIG2,
|
||||
MIPS_CONFIG3,
|
||||
0,0,
|
||||
0,0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
32,
|
||||
2,
|
||||
0x1278FF17,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
32,
|
||||
32,
|
||||
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
|
||||
CPU_MIPS32,
|
||||
MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
"4Km",
|
||||
0x00018300,
|
||||
/* Config1 implemented, fixed mapping MMU,
|
||||
no virtual icache, uncached coherency. */
|
||||
MIPS_CONFIG0 | (MMU_TYPE_FMT << CP0C0_MT),
|
||||
MIPS_CONFIG1 |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_CA),
|
||||
MIPS_CONFIG2,
|
||||
MIPS_CONFIG3,
|
||||
0,0,
|
||||
0,0,
|
||||
0,
|
||||
0,
|
||||
|
||||
0,
|
||||
4,
|
||||
32,
|
||||
2,
|
||||
0x1258FF17,
|
||||
0,
|
||||
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
32,
|
||||
32,
|
||||
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
|
||||
CPU_MIPS32 | ASE_MIPS16,
|
||||
MMU_TYPE_FMT,
|
||||
},
|
||||
{
|
||||
"4KEcR1",
|
||||
0x00018400,
|
||||
MIPS_CONFIG0 | (MMU_TYPE_R4000 << CP0C0_MT),
|
||||
MIPS_CONFIG1 | (15 << CP0C1_MMU) |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(0 << CP0C1_CA),
|
||||
MIPS_CONFIG2,
|
||||
MIPS_CONFIG3,
|
||||
0,0,
|
||||
0,0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
32,
|
||||
2,
|
||||
0x1278FF17,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
32,
|
||||
32,
|
||||
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
|
||||
CPU_MIPS32,
|
||||
MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
"4KEmR1",
|
||||
0x00018500,
|
||||
MIPS_CONFIG0 | (MMU_TYPE_FMT << CP0C0_MT),
|
||||
MIPS_CONFIG1 |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_CA),
|
||||
MIPS_CONFIG2,
|
||||
MIPS_CONFIG3,
|
||||
0,0,
|
||||
0,0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
32,
|
||||
2,
|
||||
0x1258FF17,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
32,
|
||||
32,
|
||||
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
|
||||
CPU_MIPS32 | ASE_MIPS16,
|
||||
MMU_TYPE_FMT,
|
||||
},
|
||||
{
|
||||
"4KEc",
|
||||
0x00019000,
|
||||
MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
MIPS_CONFIG1 | (15 << CP0C1_MMU) |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(0 << CP0C1_CA),
|
||||
MIPS_CONFIG2,
|
||||
MIPS_CONFIG3 | (0 << CP0C3_VInt),
|
||||
0,0,
|
||||
0,0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
32,
|
||||
2,
|
||||
0x1278FF17,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
32,
|
||||
32,
|
||||
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
|
||||
CPU_MIPS32R2,
|
||||
MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
"4KEm",
|
||||
0x00019100,
|
||||
MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
|
||||
(MMU_TYPE_FMT << CP0C0_MT),
|
||||
MIPS_CONFIG1 |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_CA),
|
||||
MIPS_CONFIG2,
|
||||
MIPS_CONFIG3,
|
||||
0,0,
|
||||
0,0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
32,
|
||||
2,
|
||||
0x1258FF17,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
32,
|
||||
32,
|
||||
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
|
||||
CPU_MIPS32R2 | ASE_MIPS16,
|
||||
MMU_TYPE_FMT,
|
||||
},
|
||||
{
|
||||
"24Kc",
|
||||
0x00019300,
|
||||
MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
MIPS_CONFIG1 | (15 << CP0C1_MMU) |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_CA),
|
||||
MIPS_CONFIG2,
|
||||
MIPS_CONFIG3 | (0 << CP0C3_VInt),
|
||||
0,0,
|
||||
0,0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
32,
|
||||
2,
|
||||
/* No DSP implemented. */
|
||||
0x1278FF1F,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
32,
|
||||
32,
|
||||
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
|
||||
CPU_MIPS32R2 | ASE_MIPS16,
|
||||
MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
"24Kf",
|
||||
0x00019300,
|
||||
MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_CA),
|
||||
MIPS_CONFIG2,
|
||||
MIPS_CONFIG3 | (0 << CP0C3_VInt),
|
||||
0,0,
|
||||
0,0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
32,
|
||||
2,
|
||||
/* No DSP implemented. */
|
||||
0x3678FF1F,
|
||||
0,
|
||||
0,
|
||||
(1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
|
||||
(1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
|
||||
0,
|
||||
32,
|
||||
32,
|
||||
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
|
||||
CPU_MIPS32R2 | ASE_MIPS16,
|
||||
MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
"34Kf",
|
||||
0x00019500,
|
||||
MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_CA),
|
||||
MIPS_CONFIG2,
|
||||
MIPS_CONFIG3 | (1 << CP0C3_VInt) | (1 << CP0C3_MT) |
|
||||
(1 << CP0C3_DSPP),
|
||||
0,
|
||||
0,
|
||||
32,
|
||||
2,
|
||||
0x3778FF1F,
|
||||
(0 << CP0TCSt_TCU3) | (0 << CP0TCSt_TCU2) |
|
||||
(1 << CP0TCSt_TCU1) | (1 << CP0TCSt_TCU0) |
|
||||
(0 << CP0TCSt_TMX) | (1 << CP0TCSt_DT) |
|
||||
(1 << CP0TCSt_DA) | (1 << CP0TCSt_A) |
|
||||
(0x3 << CP0TCSt_TKSU) | (1 << CP0TCSt_IXMT) |
|
||||
(0xff << CP0TCSt_TASID),
|
||||
(0xf << CP0SRSCtl_HSS),
|
||||
0,
|
||||
32,
|
||||
32,
|
||||
(1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
|
||||
(1 << FCR0_D) | (1 << FCR0_S) | (0x95 << FCR0_PRID),
|
||||
0x3fffffff,
|
||||
(1U << CP0SRSC0_M) | (0x3fe << CP0SRSC0_SRS3) |
|
||||
(0x3fe << CP0SRSC0_SRS2) | (0x3fe << CP0SRSC0_SRS1),
|
||||
0x3fffffff,
|
||||
(1U << CP0SRSC1_M) | (0x3fe << CP0SRSC1_SRS6) |
|
||||
(0x3fe << CP0SRSC1_SRS5) | (0x3fe << CP0SRSC1_SRS4),
|
||||
0x3fffffff,
|
||||
(1U << CP0SRSC2_M) | (0x3fe << CP0SRSC2_SRS9) |
|
||||
(0x3fe << CP0SRSC2_SRS8) | (0x3fe << CP0SRSC2_SRS7),
|
||||
0x3fffffff,
|
||||
(1U << CP0SRSC3_M) | (0x3fe << CP0SRSC3_SRS12) |
|
||||
(0x3fe << CP0SRSC3_SRS11) | (0x3fe << CP0SRSC3_SRS10),
|
||||
0x3fffffff,
|
||||
(0x3fe << CP0SRSC4_SRS15) |
|
||||
(0x3fe << CP0SRSC4_SRS14) | (0x3fe << CP0SRSC4_SRS13),
|
||||
0,0,
|
||||
CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_MT,
|
||||
MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
"74Kf",
|
||||
0x00019700,
|
||||
MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_CA),
|
||||
MIPS_CONFIG2,
|
||||
MIPS_CONFIG3 | (1 << CP0C3_DSP2P) | (1 << CP0C3_DSPP) |
|
||||
(0 << CP0C3_VInt),
|
||||
0,0,
|
||||
0,0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
32,
|
||||
2,
|
||||
0x3778FF1F,
|
||||
0,
|
||||
0,
|
||||
(1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
|
||||
(1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
|
||||
0,
|
||||
32,
|
||||
32,
|
||||
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
|
||||
CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2,
|
||||
MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
/* A generic CPU providing MIPS32 Release 5 features.
|
||||
FIXME: Eventually this should be replaced by a real CPU model. */
|
||||
"mips32r5-generic",
|
||||
0x00019700,
|
||||
MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_CA),
|
||||
MIPS_CONFIG2,
|
||||
MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP),
|
||||
MIPS_CONFIG4 | (1U << CP0C4_M),
|
||||
0,
|
||||
MIPS_CONFIG5 | (1 << CP0C5_UFR),
|
||||
(0 << CP0C5_M) | (1 << CP0C5_K) |
|
||||
(1 << CP0C5_CV) | (0 << CP0C5_EVA) |
|
||||
(1 << CP0C5_MSAEn) | (1 << CP0C5_UFR) |
|
||||
(0 << CP0C5_NFExists),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
32,
|
||||
2,
|
||||
0x3778FF1F,
|
||||
0,
|
||||
0,
|
||||
(1 << FCR0_UFRP) | (1 << FCR0_F64) | (1 << FCR0_L) |
|
||||
(1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) |
|
||||
(0x93 << FCR0_PRID),
|
||||
0,
|
||||
32,
|
||||
32,
|
||||
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
|
||||
CPU_MIPS32R5 | ASE_MIPS16 | ASE_MSA,
|
||||
MMU_TYPE_R4000,
|
||||
},
|
||||
#if defined(TARGET_MIPS64)
|
||||
{
|
||||
"R4000",
|
||||
0x00000400,
|
||||
/* No L2 cache, icache size 8k, dcache size 8k, uncached coherency. */
|
||||
(1 << 17) | (0x1 << 9) | (0x1 << 6) | (0x2 << CP0C0_K0),
|
||||
/* Note: Config1 is only used internally, the R4000 has only Config0. */
|
||||
(1 << CP0C1_FP) | (47 << CP0C1_MMU),
|
||||
0,
|
||||
0,
|
||||
0,0,
|
||||
0,0,
|
||||
0,
|
||||
0,
|
||||
0xFFFFFFFF,
|
||||
4,
|
||||
16,
|
||||
2,
|
||||
0x3678FFFF,
|
||||
0,
|
||||
0,
|
||||
/* The R4000 has a full 64bit FPU but doesn't use the fcr0 bits. */
|
||||
(0x5 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
0,
|
||||
40,
|
||||
36,
|
||||
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
|
||||
CPU_MIPS3,
|
||||
MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
"VR5432",
|
||||
0x00005400,
|
||||
/* No L2 cache, icache size 8k, dcache size 8k, uncached coherency. */
|
||||
(1 << 17) | (0x1 << 9) | (0x1 << 6) | (0x2 << CP0C0_K0),
|
||||
(1 << CP0C1_FP) | (47 << CP0C1_MMU),
|
||||
0,
|
||||
0,
|
||||
0,0,
|
||||
0,0,
|
||||
0,
|
||||
0,
|
||||
0xFFFFFFFFL,
|
||||
4,
|
||||
16,
|
||||
2,
|
||||
0x3678FFFF,
|
||||
0,
|
||||
0,
|
||||
/* The VR5432 has a full 64bit FPU but doesn't use the fcr0 bits. */
|
||||
(0x54 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
0,
|
||||
40,
|
||||
32,
|
||||
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
|
||||
CPU_VR54XX,
|
||||
MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
"5Kc",
|
||||
0x00018100,
|
||||
MIPS_CONFIG0 | (0x2 << CP0C0_AT) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
MIPS_CONFIG1 | (31 << CP0C1_MMU) |
|
||||
(1 << CP0C1_IS) | (4 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
|
||||
MIPS_CONFIG2,
|
||||
MIPS_CONFIG3,
|
||||
0,0,
|
||||
0,0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
32,
|
||||
2,
|
||||
0x32F8FFFF,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
42,
|
||||
36,
|
||||
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
|
||||
CPU_MIPS64,
|
||||
MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
"5Kf",
|
||||
0x00018100,
|
||||
MIPS_CONFIG0 | (0x2 << CP0C0_AT) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
MIPS_CONFIG1 | (1 << CP0C1_FP) | (31 << CP0C1_MMU) |
|
||||
(1 << CP0C1_IS) | (4 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
|
||||
MIPS_CONFIG2,
|
||||
MIPS_CONFIG3,
|
||||
0,0,
|
||||
0,0,
|
||||
0,
|
||||
0,
|
||||
|
||||
0,
|
||||
4,
|
||||
32,
|
||||
2,
|
||||
0x36F8FFFF,
|
||||
0,
|
||||
0,
|
||||
/* The 5Kf has F64 / L / W but doesn't use the fcr0 bits. */
|
||||
(1 << FCR0_D) | (1 << FCR0_S) |
|
||||
(0x81 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
0,
|
||||
42,
|
||||
36,
|
||||
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
|
||||
CPU_MIPS64,
|
||||
MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
"20Kc",
|
||||
/* We emulate a later version of the 20Kc, earlier ones had a broken
|
||||
WAIT instruction. */
|
||||
0x000182a0,
|
||||
MIPS_CONFIG0 | (0x2 << CP0C0_AT) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT) | (1 << CP0C0_VI),
|
||||
MIPS_CONFIG1 | (1 << CP0C1_FP) | (47 << CP0C1_MMU) |
|
||||
(2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
|
||||
(2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
|
||||
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
|
||||
MIPS_CONFIG2,
|
||||
MIPS_CONFIG3,
|
||||
0,.0,
|
||||
0,0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
32,
|
||||
1,
|
||||
0x36FBFFFF,
|
||||
0,
|
||||
0,
|
||||
/* The 20Kc has F64 / L / W but doesn't use the fcr0 bits. */
|
||||
(1 << FCR0_3D) | (1 << FCR0_PS) |
|
||||
(1 << FCR0_D) | (1 << FCR0_S) |
|
||||
(0x82 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
0,
|
||||
40,
|
||||
36,
|
||||
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
|
||||
CPU_MIPS64 | ASE_MIPS3D,
|
||||
MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
/* A generic CPU providing MIPS64 Release 2 features.
|
||||
FIXME: Eventually this should be replaced by a real CPU model. */
|
||||
"MIPS64R2-generic",
|
||||
0x00010000,
|
||||
MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
|
||||
(2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
|
||||
(2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
|
||||
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
|
||||
MIPS_CONFIG2,
|
||||
MIPS_CONFIG3 | (1 << CP0C3_LPA),
|
||||
0,0,
|
||||
0,0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
32,
|
||||
2,
|
||||
0x36FBFFFF,
|
||||
0,
|
||||
0,
|
||||
(1 << FCR0_F64) | (1 << FCR0_3D) | (1 << FCR0_PS) |
|
||||
(1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
|
||||
(1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
0,
|
||||
42,
|
||||
/* The architectural limit is 59, but we have hardcoded 36 bit
|
||||
in some places...
|
||||
59, */ /* the architectural limit */
|
||||
36,
|
||||
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
|
||||
CPU_MIPS64R2 | ASE_MIPS3D,
|
||||
MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
/* A generic CPU supporting MIPS64 Release 6 ISA.
|
||||
FIXME: Support IEEE 754-2008 FP and misaligned memory accesses.
|
||||
Eventually this should be replaced by a real CPU model. */
|
||||
"MIPS64R6-generic",
|
||||
0x00010000,
|
||||
MIPS_CONFIG0 | (0x2 << CP0C0_AR) | (0x2 << CP0C0_AT) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
|
||||
(2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
|
||||
(2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
|
||||
(0 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
|
||||
MIPS_CONFIG2,
|
||||
MIPS_CONFIG3 | (1 << CP0C3_RXI) | (1 << CP0C3_BP) |
|
||||
(1 << CP0C3_BI) | (1 << CP0C3_ULRI) | (1U << CP0C3_M),
|
||||
MIPS_CONFIG4 | (0xfc << CP0C4_KScrExist) |
|
||||
(3 << CP0C4_IE) | (1 << CP0C4_M),
|
||||
0,
|
||||
0,
|
||||
(1 << CP0C5_SBRI),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
32,
|
||||
2,
|
||||
0x30D8FFFF,
|
||||
0,
|
||||
0,
|
||||
(1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
|
||||
(1 << FCR0_D) | (1 << FCR0_S) | (0x00 << FCR0_PRID) |
|
||||
(0x0 << FCR0_REV),
|
||||
0,
|
||||
42,
|
||||
/* The architectural limit is 59, but we have hardcoded 36 bit
|
||||
in some places...
|
||||
59, */ /* the architectural limit */
|
||||
36,
|
||||
0,0, 0,0, 0,0, 0,0, 0,0,
|
||||
(1 << CP0PG_IEC) | (1 << CP0PG_XIE) |
|
||||
(1U << CP0PG_RIE),
|
||||
0,
|
||||
CPU_MIPS64R6,
|
||||
MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
"Loongson-2E",
|
||||
0x6302,
|
||||
/*64KB I-cache and d-cache. 4 way with 32 bit cache line size*/
|
||||
(0x1<<17) | (0x1<<16) | (0x1<<11) | (0x1<<8) | (0x1<<5) |
|
||||
(0x1<<4) | (0x1<<1),
|
||||
/* Note: Config1 is only used internally, Loongson-2E has only Config0. */
|
||||
(1 << CP0C1_FP) | (47 << CP0C1_MMU),
|
||||
0,
|
||||
0,
|
||||
0,0,
|
||||
0,0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
16,
|
||||
2,
|
||||
0x35D0FFFF,
|
||||
0,
|
||||
0,
|
||||
(0x5 << FCR0_PRID) | (0x1 << FCR0_REV),
|
||||
0,
|
||||
40,
|
||||
40,
|
||||
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
|
||||
CPU_LOONGSON2E,
|
||||
MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
"Loongson-2F",
|
||||
0x6303,
|
||||
/*64KB I-cache and d-cache. 4 way with 32 bit cache line size*/
|
||||
(0x1<<17) | (0x1<<16) | (0x1<<11) | (0x1<<8) | (0x1<<5) |
|
||||
(0x1<<4) | (0x1<<1),
|
||||
/* Note: Config1 is only used internally, Loongson-2F has only Config0. */
|
||||
(1 << CP0C1_FP) | (47 << CP0C1_MMU),
|
||||
0,
|
||||
0,
|
||||
0,0,
|
||||
0,0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
16,
|
||||
2,
|
||||
0xF5D0FF1F, /*bit5:7 not writable*/
|
||||
0,
|
||||
0,
|
||||
(0x5 << FCR0_PRID) | (0x1 << FCR0_REV),
|
||||
0,
|
||||
40,
|
||||
40,
|
||||
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
|
||||
CPU_LOONGSON2F,
|
||||
MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
/* A generic CPU providing MIPS64 ASE DSP 2 features.
|
||||
FIXME: Eventually this should be replaced by a real CPU model. */
|
||||
"mips64dspr2",
|
||||
0x00010000,
|
||||
MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
|
||||
(2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
|
||||
(2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
|
||||
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
|
||||
MIPS_CONFIG2,
|
||||
MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_DSP2P) |
|
||||
(1 << CP0C3_DSPP) | (1 << CP0C3_LPA),
|
||||
0,0,
|
||||
0,0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
32,
|
||||
2,
|
||||
0x37FBFFFF,
|
||||
0,
|
||||
0,
|
||||
(1 << FCR0_F64) | (1 << FCR0_3D) | (1 << FCR0_PS) |
|
||||
(1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
|
||||
(1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
0,
|
||||
42,
|
||||
/* The architectural limit is 59, but we have hardcoded 36 bit
|
||||
in some places...
|
||||
59, */ /* the architectural limit */
|
||||
36,
|
||||
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
|
||||
CPU_MIPS64R2 | ASE_DSP | ASE_DSPR2,
|
||||
MMU_TYPE_R4000,
|
||||
},
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
static const mips_def_t *cpu_mips_find_by_name (const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mips_defs); i++) {
|
||||
if (strcasecmp(name, mips_defs[i].name) == 0) {
|
||||
return &mips_defs[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mips_defs); i++) {
|
||||
(*cpu_fprintf)(f, "MIPS '%s'\n",
|
||||
mips_defs[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static void no_mmu_init (CPUMIPSState *env, const mips_def_t *def)
|
||||
{
|
||||
env->tlb->nb_tlb = 1;
|
||||
env->tlb->map_address = &no_mmu_map_address;
|
||||
}
|
||||
|
||||
static void fixed_mmu_init (CPUMIPSState *env, const mips_def_t *def)
|
||||
{
|
||||
env->tlb->nb_tlb = 1;
|
||||
env->tlb->map_address = &fixed_mmu_map_address;
|
||||
}
|
||||
|
||||
static void r4k_mmu_init (CPUMIPSState *env, const mips_def_t *def)
|
||||
{
|
||||
env->tlb->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63);
|
||||
env->tlb->map_address = &r4k_map_address;
|
||||
env->tlb->helper_tlbwi = r4k_helper_tlbwi;
|
||||
env->tlb->helper_tlbwr = r4k_helper_tlbwr;
|
||||
env->tlb->helper_tlbp = r4k_helper_tlbp;
|
||||
env->tlb->helper_tlbr = r4k_helper_tlbr;
|
||||
env->tlb->helper_tlbinv = r4k_helper_tlbinv;
|
||||
env->tlb->helper_tlbinvf = r4k_helper_tlbinvf;
|
||||
}
|
||||
|
||||
static void mmu_init (CPUMIPSState *env, const mips_def_t *def)
|
||||
{
|
||||
MIPSCPU *cpu = mips_env_get_cpu(env);
|
||||
|
||||
env->tlb = g_malloc0(sizeof(CPUMIPSTLBContext));
|
||||
|
||||
switch (def->mmu_type) {
|
||||
case MMU_TYPE_NONE:
|
||||
no_mmu_init(env, def);
|
||||
break;
|
||||
case MMU_TYPE_R4000:
|
||||
r4k_mmu_init(env, def);
|
||||
break;
|
||||
case MMU_TYPE_FMT:
|
||||
fixed_mmu_init(env, def);
|
||||
break;
|
||||
case MMU_TYPE_R3000:
|
||||
case MMU_TYPE_R6000:
|
||||
case MMU_TYPE_R8000:
|
||||
default:
|
||||
cpu_abort(CPU(cpu), "MMU type not supported\n");
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_USER_ONLY */
|
||||
|
||||
static void fpu_init (CPUMIPSState *env, const mips_def_t *def)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MIPS_FPU_MAX; i++)
|
||||
env->fpus[i].fcr0 = def->CP1_fcr0;
|
||||
|
||||
memcpy(&env->active_fpu, &env->fpus[0], sizeof(env->active_fpu));
|
||||
}
|
||||
|
||||
static void mvp_init (CPUMIPSState *env, const mips_def_t *def)
|
||||
{
|
||||
env->mvp = g_malloc0(sizeof(CPUMIPSMVPContext));
|
||||
|
||||
/* MVPConf1 implemented, TLB sharable, no gating storage support,
|
||||
programmable cache partitioning implemented, number of allocatable
|
||||
and sharable TLB entries, MVP has allocatable TCs, 2 VPEs
|
||||
implemented, 5 TCs implemented. */
|
||||
env->mvp->CP0_MVPConf0 = (1U << CP0MVPC0_M) | (1 << CP0MVPC0_TLBS) |
|
||||
(0 << CP0MVPC0_GS) | (1 << CP0MVPC0_PCP) |
|
||||
// TODO: actually do 2 VPEs.
|
||||
// (1 << CP0MVPC0_TCA) | (0x1 << CP0MVPC0_PVPE) |
|
||||
// (0x04 << CP0MVPC0_PTC);
|
||||
(1 << CP0MVPC0_TCA) | (0x0 << CP0MVPC0_PVPE) |
|
||||
(0x00 << CP0MVPC0_PTC);
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
/* Usermode has no TLB support */
|
||||
env->mvp->CP0_MVPConf0 |= (env->tlb->nb_tlb << CP0MVPC0_PTLBE);
|
||||
#endif
|
||||
|
||||
/* Allocatable CP1 have media extensions, allocatable CP1 have FP support,
|
||||
no UDI implemented, no CP2 implemented, 1 CP1 implemented. */
|
||||
env->mvp->CP0_MVPConf1 = (1U << CP0MVPC1_CIM) | (1 << CP0MVPC1_CIF) |
|
||||
(0x0 << CP0MVPC1_PCX) | (0x0 << CP0MVPC1_PCP2) |
|
||||
(0x1 << CP0MVPC1_PCP1);
|
||||
}
|
||||
|
||||
static void msa_reset(CPUMIPSState *env)
|
||||
{
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
/* MSA access enabled */
|
||||
env->CP0_Config5 |= 1 << CP0C5_MSAEn;
|
||||
env->CP0_Status |= (1 << CP0St_CU1) | (1 << CP0St_FR);
|
||||
#endif
|
||||
|
||||
/* MSA CSR:
|
||||
- non-signaling floating point exception mode off (NX bit is 0)
|
||||
- Cause, Enables, and Flags are all 0
|
||||
- round to nearest / ties to even (RM bits are 0) */
|
||||
env->active_tc.msacsr = 0;
|
||||
|
||||
/* tininess detected after rounding.*/
|
||||
set_float_detect_tininess(float_tininess_after_rounding,
|
||||
&env->active_tc.msa_fp_status);
|
||||
|
||||
/* clear float_status exception flags */
|
||||
set_float_exception_flags(0, &env->active_tc.msa_fp_status);
|
||||
|
||||
/* set float_status rounding mode */
|
||||
set_float_rounding_mode(float_round_nearest_even,
|
||||
&env->active_tc.msa_fp_status);
|
||||
|
||||
/* set float_status flush modes */
|
||||
set_flush_to_zero(0, &env->active_tc.msa_fp_status);
|
||||
set_flush_inputs_to_zero(0, &env->active_tc.msa_fp_status);
|
||||
|
||||
/* clear float_status nan mode */
|
||||
set_default_nan_mode(0, &env->active_tc.msa_fp_status);
|
||||
}
|
@ -1,169 +0,0 @@
|
||||
/* Unicorn Emulator Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2015 */
|
||||
|
||||
#include "hw/boards.h"
|
||||
#include "hw/mips/mips.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "unicorn.h"
|
||||
#include "cpu.h"
|
||||
#include "unicorn_common.h"
|
||||
#include "uc_priv.h"
|
||||
|
||||
#ifdef TARGET_MIPS64
|
||||
const int MIPS64_REGS_STORAGE_SIZE = offsetof(CPUMIPSState, tlb_table);
|
||||
#else // MIPS32
|
||||
const int MIPS_REGS_STORAGE_SIZE = offsetof(CPUMIPSState, tlb_table);
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_MIPS64
|
||||
typedef uint64_t mipsreg_t;
|
||||
#else
|
||||
typedef uint32_t mipsreg_t;
|
||||
#endif
|
||||
|
||||
static uint64_t mips_mem_redirect(uint64_t address)
|
||||
{
|
||||
// kseg0 range masks off high address bit
|
||||
if (address >= 0x80000000 && address <= 0x9fffffff)
|
||||
return address & 0x7fffffff;
|
||||
|
||||
// kseg1 range masks off top 3 address bits
|
||||
if (address >= 0xa0000000 && address <= 0xbfffffff) {
|
||||
return address & 0x1fffffff;
|
||||
}
|
||||
|
||||
// no redirect
|
||||
return address;
|
||||
}
|
||||
|
||||
static void mips_set_pc(struct uc_struct *uc, uint64_t address)
|
||||
{
|
||||
((CPUMIPSState *)uc->current_cpu->env_ptr)->active_tc.PC = address;
|
||||
}
|
||||
|
||||
|
||||
void mips_release(void *ctx);
|
||||
void mips_release(void *ctx)
|
||||
{
|
||||
MIPSCPU* cpu;
|
||||
int i;
|
||||
TCGContext *tcg_ctx = (TCGContext *) ctx;
|
||||
release_common(ctx);
|
||||
cpu = MIPS_CPU(tcg_ctx->uc, tcg_ctx->uc->cpu);
|
||||
g_free(cpu->env.tlb);
|
||||
g_free(cpu->env.mvp);
|
||||
|
||||
for (i = 0; i < MIPS_DSP_ACC; i++) {
|
||||
g_free(tcg_ctx->cpu_HI[i]);
|
||||
g_free(tcg_ctx->cpu_LO[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
g_free(tcg_ctx->cpu_gpr[i]);
|
||||
}
|
||||
|
||||
g_free(tcg_ctx->cpu_PC);
|
||||
g_free(tcg_ctx->btarget);
|
||||
g_free(tcg_ctx->bcond);
|
||||
g_free(tcg_ctx->cpu_dspctrl);
|
||||
|
||||
g_free(tcg_ctx->tb_ctx.tbs);
|
||||
}
|
||||
|
||||
void mips_reg_reset(struct uc_struct *uc)
|
||||
{
|
||||
CPUArchState *env;
|
||||
(void)uc;
|
||||
env = uc->cpu->env_ptr;
|
||||
memset(env->active_tc.gpr, 0, sizeof(env->active_tc.gpr));
|
||||
|
||||
env->active_tc.PC = 0;
|
||||
}
|
||||
|
||||
int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count)
|
||||
{
|
||||
CPUState *mycpu = uc->cpu;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31)
|
||||
*(mipsreg_t *)value = MIPS_CPU(uc, mycpu)->env.active_tc.gpr[regid - UC_MIPS_REG_0];
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_MIPS_REG_PC:
|
||||
*(mipsreg_t *)value = MIPS_CPU(uc, mycpu)->env.active_tc.PC;
|
||||
break;
|
||||
case UC_MIPS_REG_CP0_CONFIG3:
|
||||
*(mipsreg_t *)value = MIPS_CPU(uc, mycpu)->env.CP0_Config3;
|
||||
break;
|
||||
case UC_MIPS_REG_CP0_USERLOCAL:
|
||||
*(mipsreg_t *)value = MIPS_CPU(uc, mycpu)->env.active_tc.CP0_UserLocal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count)
|
||||
{
|
||||
CPUState *mycpu = uc->cpu;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31)
|
||||
MIPS_CPU(uc, mycpu)->env.active_tc.gpr[regid - UC_MIPS_REG_0] = *(mipsreg_t *)value;
|
||||
else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_MIPS_REG_PC:
|
||||
MIPS_CPU(uc, mycpu)->env.active_tc.PC = *(mipsreg_t *)value;
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
break;
|
||||
case UC_MIPS_REG_CP0_CONFIG3:
|
||||
MIPS_CPU(uc, mycpu)->env.CP0_Config3 = *(mipsreg_t *)value;
|
||||
break;
|
||||
case UC_MIPS_REG_CP0_USERLOCAL:
|
||||
MIPS_CPU(uc, mycpu)->env.active_tc.CP0_UserLocal = *(mipsreg_t *)value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
#ifdef TARGET_MIPS64
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
void mips64_uc_init(struct uc_struct* uc)
|
||||
#else
|
||||
void mips64el_uc_init(struct uc_struct* uc)
|
||||
#endif
|
||||
#else // if TARGET_MIPS
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
void mips_uc_init(struct uc_struct* uc)
|
||||
#else
|
||||
void mipsel_uc_init(struct uc_struct* uc)
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
register_accel_types(uc);
|
||||
mips_cpu_register_types(uc);
|
||||
mips_machine_init(uc);
|
||||
uc->reg_read = mips_reg_read;
|
||||
uc->reg_write = mips_reg_write;
|
||||
uc->reg_reset = mips_reg_reset;
|
||||
uc->release = mips_release;
|
||||
uc->set_pc = mips_set_pc;
|
||||
uc->mem_redirect = mips_mem_redirect;
|
||||
uc_common_init(uc);
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
/* Unicorn Emulator Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2015 */
|
||||
|
||||
#ifndef UC_QEMU_TARGET_MIPS_H
|
||||
#define UC_QEMU_TARGET_MIPS_H
|
||||
|
||||
// functions to read & write registers
|
||||
int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count);
|
||||
int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count);
|
||||
|
||||
void mips_reg_reset(struct uc_struct *uc);
|
||||
|
||||
void mips_uc_init(struct uc_struct* uc);
|
||||
void mipsel_uc_init(struct uc_struct* uc);
|
||||
void mips64_uc_init(struct uc_struct* uc);
|
||||
void mips64el_uc_init(struct uc_struct* uc);
|
||||
|
||||
extern const int MIPS_REGS_STORAGE_SIZE_mips;
|
||||
extern const int MIPS_REGS_STORAGE_SIZE_mipsel;
|
||||
extern const int MIPS64_REGS_STORAGE_SIZE_mips64;
|
||||
extern const int MIPS64_REGS_STORAGE_SIZE_mips64el;
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user