mirror of https://gitee.com/openkylin/qemu.git
MIPS patches 2017-09-21
Changes: QOMify MIPS cpu Improve macro parenthesization -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (GNU/Linux) iQIVAwUAWcO1nSI464bV95fCAQKxoQ//fdSg3qfK4ga8RIRfG5T4Rcu658Z6O6JK nOJSyvzun1avSUjN9gKxH+WA5SvxjoVdeUngYFA7TiOrMZuzUcCoIULjsZMyZTIA 6aEqslb+p3yrRgzwNW6ySNJMAV+d7ZlHY5W4oV+7fRRXZ2jbaHSqK1WOFZJ6f2sJ pib3pqpq6qPvXBnRrpPTRtarP4h+501GL9WGcIVwSx5Ofj3D+Spykjsk7mmIsjL3 WI4L655So1TUqFQfWbt7jyHL/WB0emP6GElpIpU6BtgtvehrOWaHs9/EexaRUL+z qhGl7fYaTS6MuQuurCsBlSO4PNiB4hBCOk4+jMGH/oZNTbnQfWqcJA8il9q2uBXX vynQuhLdkbeEXBkGdNcg97q+/nMPgK/Y/spfE9rKIEYOncZFKcvJB5ui+PTsUU/6 V6mTTUVKC6nsKsVQqtNZCPAqSLvrT3/9XrVYFTAb7o/x9KYF58o425dJxwPIFFL0 OTy79BOskkHiXLRPieKplsuCyeb/mLNJr+LW8db6YCT6hm5tKJi+DqymUtCVHhNk WggUZ/1iaDSdIeXwnvcv1cKQS4emdxIrW364A78WuNSIu7VI6aTTBQ5IwQzF6RG0 FpxOBVmTJn/7v9SeYY1AbMzzzgIPaX4g8r8jEEObquqnIsbmuP5o1IwFBp//vasj AXak0ee0hX4= =ZgOo -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/yongbok/tags/mips-20170921' into staging MIPS patches 2017-09-21 Changes: QOMify MIPS cpu Improve macro parenthesization # gpg: Signature made Thu 21 Sep 2017 13:50:37 BST # gpg: using RSA key 0x2238EB86D5F797C2 # gpg: Good signature from "Yongbok Kim <yongbok.kim@imgtec.com>" # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 8600 4CF5 3415 A5D9 4CFA 2B5C 2238 EB86 D5F7 97C2 * remotes/yongbok/tags/mips-20170921: mips: Improve macro parenthesization mips: replace cpu_mips_init() with cpu_generic_init() mips: MIPSCPU model subclasses mips: call cpu_mips_realize_env() from mips_cpu_realizefn() mips: split cpu_mips_realize_env() out of cpu_mips_init() mips: introduce internal.h and cleanup cpu.h mips: move hw/mips/cputimer.c to target/mips/ Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
9ee660e7c1
|
@ -1,5 +1,5 @@
|
|||
obj-y += mips_r4k.o mips_malta.o mips_mipssim.o
|
||||
obj-y += addr.o cputimer.o mips_int.o
|
||||
obj-y += addr.o mips_int.o
|
||||
obj-$(CONFIG_JAZZ) += mips_jazz.o
|
||||
obj-$(CONFIG_FULONG) += mips_fulong2e.o
|
||||
obj-y += gt64xxx_pci.o
|
||||
|
|
|
@ -71,7 +71,7 @@ static void mips_cps_realize(DeviceState *dev, Error **errp)
|
|||
bool itu_present = false;
|
||||
|
||||
for (i = 0; i < s->num_vp; i++) {
|
||||
cpu = cpu_mips_init(s->cpu_model);
|
||||
cpu = MIPS_CPU(cpu_generic_init(TYPE_MIPS_CPU, s->cpu_model));
|
||||
|
||||
/* Init internal devices */
|
||||
cpu_mips_irq_init_cpu(cpu);
|
||||
|
|
|
@ -280,7 +280,7 @@ static void mips_fulong2e_init(MachineState *machine)
|
|||
if (cpu_model == NULL) {
|
||||
cpu_model = "Loongson-2E";
|
||||
}
|
||||
cpu = cpu_mips_init(cpu_model);
|
||||
cpu = MIPS_CPU(cpu_generic_init(TYPE_MIPS_CPU, cpu_model));
|
||||
env = &cpu->env;
|
||||
|
||||
qemu_register_reset(main_cpu_reset, cpu);
|
||||
|
|
|
@ -151,7 +151,7 @@ static void mips_jazz_init(MachineState *machine,
|
|||
if (cpu_model == NULL) {
|
||||
cpu_model = "R4000";
|
||||
}
|
||||
cpu = cpu_mips_init(cpu_model);
|
||||
cpu = MIPS_CPU(cpu_generic_init(TYPE_MIPS_CPU, cpu_model));
|
||||
env = &cpu->env;
|
||||
qemu_register_reset(main_cpu_reset, cpu);
|
||||
|
||||
|
|
|
@ -931,7 +931,7 @@ static void create_cpu_without_cps(const char *cpu_model,
|
|||
int i;
|
||||
|
||||
for (i = 0; i < smp_cpus; i++) {
|
||||
cpu = cpu_mips_init(cpu_model);
|
||||
cpu = MIPS_CPU(cpu_generic_init(TYPE_MIPS_CPU, cpu_model));
|
||||
|
||||
/* Init internal devices */
|
||||
cpu_mips_irq_init_cpu(cpu);
|
||||
|
|
|
@ -163,7 +163,7 @@ mips_mipssim_init(MachineState *machine)
|
|||
cpu_model = "24Kf";
|
||||
#endif
|
||||
}
|
||||
cpu = cpu_mips_init(cpu_model);
|
||||
cpu = MIPS_CPU(cpu_generic_init(TYPE_MIPS_CPU, cpu_model));
|
||||
env = &cpu->env;
|
||||
|
||||
reset_info = g_malloc0(sizeof(ResetData));
|
||||
|
|
|
@ -193,7 +193,7 @@ void mips_r4k_init(MachineState *machine)
|
|||
cpu_model = "24Kf";
|
||||
#endif
|
||||
}
|
||||
cpu = cpu_mips_init(cpu_model);
|
||||
cpu = MIPS_CPU(cpu_generic_init(TYPE_MIPS_CPU, cpu_model));
|
||||
env = &cpu->env;
|
||||
|
||||
reset_info = g_malloc0(sizeof(ResetData));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
obj-y += translate.o dsp_helper.o op_helper.o lmi_helper.o helper.o cpu.o
|
||||
obj-y += gdbstub.o msa_helper.o mips-semi.o
|
||||
obj-$(CONFIG_SOFTMMU) += machine.o
|
||||
obj-$(CONFIG_SOFTMMU) += machine.o cp0_timer.o
|
||||
obj-$(CONFIG_KVM) += kvm.o
|
||||
|
|
|
@ -21,10 +21,10 @@
|
|||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/mips/cpudevs.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "internal.h"
|
||||
|
||||
#define TIMER_PERIOD 10 /* 10 ns period for 100 Mhz frequency */
|
||||
|
|
@ -49,6 +49,7 @@ typedef struct MIPSCPUClass {
|
|||
|
||||
DeviceRealize parent_realize;
|
||||
void (*parent_reset)(CPUState *cpu);
|
||||
const struct mips_def_t *cpu_def;
|
||||
} MIPSCPUClass;
|
||||
|
||||
typedef struct MIPSCPU MIPSCPU;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "kvm_mips.h"
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu/kvm.h"
|
||||
|
@ -122,6 +123,7 @@ static void mips_cpu_disas_set_info(CPUState *s, disassemble_info *info) {
|
|||
static void mips_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
{
|
||||
CPUState *cs = CPU(dev);
|
||||
MIPSCPU *cpu = MIPS_CPU(dev);
|
||||
MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(dev);
|
||||
Error *local_err = NULL;
|
||||
|
||||
|
@ -131,6 +133,8 @@ static void mips_cpu_realizefn(DeviceState *dev, Error **errp)
|
|||
return;
|
||||
}
|
||||
|
||||
cpu_mips_realize_env(&cpu->env);
|
||||
|
||||
cpu_reset(cs);
|
||||
qemu_init_vcpu(cs);
|
||||
|
||||
|
@ -142,14 +146,36 @@ static void mips_cpu_initfn(Object *obj)
|
|||
CPUState *cs = CPU(obj);
|
||||
MIPSCPU *cpu = MIPS_CPU(obj);
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(obj);
|
||||
|
||||
cs->env_ptr = env;
|
||||
env->cpu_model = mcc->cpu_def;
|
||||
|
||||
if (tcg_enabled()) {
|
||||
mips_tcg_init();
|
||||
}
|
||||
}
|
||||
|
||||
static char *mips_cpu_type_name(const char *cpu_model)
|
||||
{
|
||||
return g_strdup_printf("%s-" TYPE_MIPS_CPU, cpu_model);
|
||||
}
|
||||
|
||||
static ObjectClass *mips_cpu_class_by_name(const char *cpu_model)
|
||||
{
|
||||
ObjectClass *oc;
|
||||
char *typename;
|
||||
|
||||
if (cpu_model == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
typename = mips_cpu_type_name(cpu_model);
|
||||
oc = object_class_by_name(typename);
|
||||
g_free(typename);
|
||||
return oc;
|
||||
}
|
||||
|
||||
static void mips_cpu_class_init(ObjectClass *c, void *data)
|
||||
{
|
||||
MIPSCPUClass *mcc = MIPS_CPU_CLASS(c);
|
||||
|
@ -162,6 +188,7 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
|
|||
mcc->parent_reset = cc->reset;
|
||||
cc->reset = mips_cpu_reset;
|
||||
|
||||
cc->class_by_name = mips_cpu_class_by_name;
|
||||
cc->has_work = mips_cpu_has_work;
|
||||
cc->do_interrupt = mips_cpu_do_interrupt;
|
||||
cc->cpu_exec_interrupt = mips_cpu_exec_interrupt;
|
||||
|
@ -189,14 +216,39 @@ static const TypeInfo mips_cpu_type_info = {
|
|||
.parent = TYPE_CPU,
|
||||
.instance_size = sizeof(MIPSCPU),
|
||||
.instance_init = mips_cpu_initfn,
|
||||
.abstract = false,
|
||||
.abstract = true,
|
||||
.class_size = sizeof(MIPSCPUClass),
|
||||
.class_init = mips_cpu_class_init,
|
||||
};
|
||||
|
||||
static void mips_cpu_cpudef_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MIPSCPUClass *mcc = MIPS_CPU_CLASS(oc);
|
||||
mcc->cpu_def = data;
|
||||
}
|
||||
|
||||
static void mips_register_cpudef_type(const struct mips_def_t *def)
|
||||
{
|
||||
char *typename = mips_cpu_type_name(def->name);
|
||||
TypeInfo ti = {
|
||||
.name = typename,
|
||||
.parent = TYPE_MIPS_CPU,
|
||||
.class_init = mips_cpu_cpudef_class_init,
|
||||
.class_data = (void *)def,
|
||||
};
|
||||
|
||||
type_register(&ti);
|
||||
g_free(typename);
|
||||
}
|
||||
|
||||
static void mips_cpu_register_types(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
type_register_static(&mips_cpu_type_info);
|
||||
for (i = 0; i < mips_defs_number; i++) {
|
||||
mips_register_cpudef_type(&mips_defs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
type_init(mips_cpu_register_types)
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#ifndef MIPS_CPU_H
|
||||
#define MIPS_CPU_H
|
||||
|
||||
//#define DEBUG_OP
|
||||
|
||||
#define ALIGNED_ONLY
|
||||
|
||||
#define CPUArchState struct CPUMIPSState
|
||||
|
@ -15,56 +13,11 @@
|
|||
|
||||
struct CPUMIPSState;
|
||||
|
||||
typedef struct r4k_tlb_t r4k_tlb_t;
|
||||
struct r4k_tlb_t {
|
||||
target_ulong VPN;
|
||||
uint32_t PageMask;
|
||||
uint16_t ASID;
|
||||
unsigned int G:1;
|
||||
unsigned int C0:3;
|
||||
unsigned int C1:3;
|
||||
unsigned int V0:1;
|
||||
unsigned int V1:1;
|
||||
unsigned int D0:1;
|
||||
unsigned int D1:1;
|
||||
unsigned int XI0:1;
|
||||
unsigned int XI1:1;
|
||||
unsigned int RI0:1;
|
||||
unsigned int RI1:1;
|
||||
unsigned int EHINV:1;
|
||||
uint64_t 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];
|
||||
|
@ -682,40 +635,6 @@ static inline MIPSCPU *mips_env_get_cpu(CPUMIPSState *env)
|
|||
|
||||
#define ENV_OFFSET offsetof(MIPSCPU, env)
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
extern const struct VMStateDescription vmstate_mips_cpu;
|
||||
#endif
|
||||
|
||||
void mips_cpu_do_interrupt(CPUState *cpu);
|
||||
bool mips_cpu_exec_interrupt(CPUState *cpu, int int_req);
|
||||
void mips_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
|
||||
int flags);
|
||||
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,
|
||||
MMUAccessType access_type,
|
||||
int mmu_idx, uintptr_t retaddr);
|
||||
|
||||
#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_signal_handler cpu_mips_signal_handler
|
||||
|
@ -746,42 +665,6 @@ static inline int cpu_mmu_index (CPUMIPSState *env, bool ifetch)
|
|||
return hflags_mmu_index(env->hflags);
|
||||
}
|
||||
|
||||
static inline bool cpu_mips_hw_interrupts_enabled(CPUMIPSState *env)
|
||||
{
|
||||
return (env->CP0_Status & (1 << CP0St_IE)) &&
|
||||
!(env->CP0_Status & (1 << CP0St_EXL)) &&
|
||||
!(env->CP0_Status & (1 << CP0St_ERL)) &&
|
||||
!(env->hflags & MIPS_HFLAG_DM) &&
|
||||
/* 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));
|
||||
}
|
||||
|
||||
/* Check if there is pending and not masked out interrupt */
|
||||
static inline bool cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
|
||||
{
|
||||
int32_t pending;
|
||||
int32_t status;
|
||||
bool r;
|
||||
|
||||
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) != 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#include "exec/cpu-all.h"
|
||||
|
||||
/* Memory access type :
|
||||
|
@ -847,100 +730,32 @@ enum {
|
|||
#define EXCP_SC 0x100
|
||||
|
||||
/*
|
||||
* This is an interrnally generated WAKE request line.
|
||||
* This is an internally 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
|
||||
|
||||
void mips_tcg_init(void);
|
||||
MIPSCPU *cpu_mips_init(const char *cpu_model);
|
||||
int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc);
|
||||
|
||||
#define cpu_init(cpu_model) CPU(cpu_mips_init(cpu_model))
|
||||
#define cpu_init(cpu_model) cpu_generic_init(TYPE_MIPS_CPU, cpu_model)
|
||||
bool cpu_supports_cps_smp(const char *cpu_model);
|
||||
bool cpu_supports_isa(const char *cpu_model, unsigned int isa);
|
||||
void cpu_set_exception_base(int vp_index, target_ulong address);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* op_helper.c */
|
||||
uint32_t float_class_s(uint32_t arg, float_status *fst);
|
||||
uint64_t float_class_d(uint64_t arg, float_status *fst);
|
||||
|
||||
#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 restore_rounding_mode(CPUMIPSState *env)
|
||||
{
|
||||
set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3],
|
||||
&env->active_fpu.fp_status);
|
||||
}
|
||||
|
||||
static inline void restore_flush_mode(CPUMIPSState *env)
|
||||
{
|
||||
set_flush_to_zero((env->active_fpu.fcr31 & (1 << FCR31_FS)) != 0,
|
||||
&env->active_fpu.fp_status);
|
||||
}
|
||||
|
||||
static inline void restore_snan_bit_mode(CPUMIPSState *env)
|
||||
{
|
||||
set_snan_bit_is_one((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) == 0,
|
||||
&env->active_fpu.fp_status);
|
||||
}
|
||||
|
||||
static inline void restore_fp_status(CPUMIPSState *env)
|
||||
{
|
||||
restore_rounding_mode(env);
|
||||
restore_flush_mode(env);
|
||||
restore_snan_bit_mode(env);
|
||||
}
|
||||
|
||||
static inline void restore_msa_fp_status(CPUMIPSState *env)
|
||||
{
|
||||
float_status *status = &env->active_tc.msa_fp_status;
|
||||
int rounding_mode = (env->active_tc.msacsr & MSACSR_RM_MASK) >> MSACSR_RM;
|
||||
bool flush_to_zero = (env->active_tc.msacsr & MSACSR_FS_MASK) != 0;
|
||||
|
||||
set_float_rounding_mode(ieee_rm[rounding_mode], status);
|
||||
set_flush_to_zero(flush_to_zero, status);
|
||||
set_flush_inputs_to_zero(flush_to_zero, status);
|
||||
}
|
||||
|
||||
static inline void restore_pamask(CPUMIPSState *env)
|
||||
{
|
||||
if (env->hflags & MIPS_HFLAG_ELPA) {
|
||||
env->PAMask = (1ULL << env->PABITS) - 1;
|
||||
} else {
|
||||
env->PAMask = PAMASK_BASE;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc,
|
||||
target_ulong *cs_base, uint32_t *flags)
|
||||
{
|
||||
|
@ -950,172 +765,4 @@ static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc,
|
|||
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;
|
||||
}
|
||||
|
||||
static inline int mips_vp_active(CPUMIPSState *env)
|
||||
{
|
||||
CPUState *other_cs = first_cpu;
|
||||
|
||||
/* Check if the VP disabled other VPs (which means the VP is enabled) */
|
||||
if ((env->CP0_VPControl >> CP0VPCtl_DIS) & 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check if the virtual processor is disabled due to a DVP */
|
||||
CPU_FOREACH(other_cs) {
|
||||
MIPSCPU *other_cpu = MIPS_CPU(other_cs);
|
||||
if ((&other_cpu->env != env) &&
|
||||
((other_cpu->env.CP0_VPControl >> CP0VPCtl_DIS) & 1)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
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 | MIPS_HFLAG_FRE |
|
||||
MIPS_HFLAG_ELPA | MIPS_HFLAG_ERL);
|
||||
if (env->CP0_Status & (1 << CP0St_ERL)) {
|
||||
env->hflags |= MIPS_HFLAG_ERL;
|
||||
}
|
||||
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->insn_flags & ISA_MIPS3) &&
|
||||
(((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->insn_flags & ISA_MIPS3)) {
|
||||
env->hflags |= MIPS_HFLAG_AWRAP;
|
||||
} else 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_MIPS64R6) {
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
|
||||
if (env->CP0_Config5 & (1 << CP0C5_FRE)) {
|
||||
env->hflags |= MIPS_HFLAG_FRE;
|
||||
}
|
||||
}
|
||||
if (env->CP0_Config3 & (1 << CP0C3_LPA)) {
|
||||
if (env->CP0_PageGrain & (1 << CP0PG_ELPA)) {
|
||||
env->hflags |= MIPS_HFLAG_ELPA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cpu_mips_tlb_flush(CPUMIPSState *env);
|
||||
void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc);
|
||||
void cpu_mips_store_status(CPUMIPSState *env, target_ulong val);
|
||||
void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val);
|
||||
|
||||
void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, uint32_t exception,
|
||||
int error_code, uintptr_t pc);
|
||||
|
||||
static inline void QEMU_NORETURN do_raise_exception(CPUMIPSState *env,
|
||||
uint32_t exception,
|
||||
uintptr_t pc)
|
||||
{
|
||||
do_raise_exception_err(env, exception, 0, pc);
|
||||
}
|
||||
|
||||
#endif /* MIPS_CPU_H */
|
||||
|
|
|
@ -45,9 +45,9 @@ typedef union {
|
|||
} DSP64Value;
|
||||
|
||||
/*** MIPS DSP internal functions begin ***/
|
||||
#define MIPSDSP_ABS(x) (((x) >= 0) ? x : -x)
|
||||
#define MIPSDSP_OVERFLOW_ADD(a, b, c, d) (~(a ^ b) & (a ^ c) & d)
|
||||
#define MIPSDSP_OVERFLOW_SUB(a, b, c, d) ((a ^ b) & (a ^ c) & d)
|
||||
#define MIPSDSP_ABS(x) (((x) >= 0) ? (x) : -(x))
|
||||
#define MIPSDSP_OVERFLOW_ADD(a, b, c, d) (~((a) ^ (b)) & ((a) ^ (c)) & (d))
|
||||
#define MIPSDSP_OVERFLOW_SUB(a, b, c, d) (((a) ^ (b)) & ((a) ^ (c)) & (d))
|
||||
|
||||
static inline void set_DSPControl_overflow_flag(uint32_t flag, int position,
|
||||
CPUMIPSState *env)
|
||||
|
@ -1047,47 +1047,47 @@ static inline int32_t mipsdsp_cmpu_lt(uint32_t a, uint32_t b)
|
|||
|
||||
#define MIPSDSP_SPLIT32_8(num, a, b, c, d) \
|
||||
do { \
|
||||
a = (num >> 24) & MIPSDSP_Q0; \
|
||||
b = (num >> 16) & MIPSDSP_Q0; \
|
||||
c = (num >> 8) & MIPSDSP_Q0; \
|
||||
d = num & MIPSDSP_Q0; \
|
||||
a = ((num) >> 24) & MIPSDSP_Q0; \
|
||||
b = ((num) >> 16) & MIPSDSP_Q0; \
|
||||
c = ((num) >> 8) & MIPSDSP_Q0; \
|
||||
d = (num) & MIPSDSP_Q0; \
|
||||
} while (0)
|
||||
|
||||
#define MIPSDSP_SPLIT32_16(num, a, b) \
|
||||
do { \
|
||||
a = (num >> 16) & MIPSDSP_LO; \
|
||||
b = num & MIPSDSP_LO; \
|
||||
a = ((num) >> 16) & MIPSDSP_LO; \
|
||||
b = (num) & MIPSDSP_LO; \
|
||||
} while (0)
|
||||
|
||||
#define MIPSDSP_RETURN32_8(a, b, c, d) ((target_long)(int32_t) \
|
||||
(((uint32_t)a << 24) | \
|
||||
(((uint32_t)b << 16) | \
|
||||
(((uint32_t)c << 8) | \
|
||||
((uint32_t)d & 0xFF)))))
|
||||
#define MIPSDSP_RETURN32_16(a, b) ((target_long)(int32_t) \
|
||||
(((uint32_t)a << 16) | \
|
||||
((uint32_t)b & 0xFFFF)))
|
||||
#define MIPSDSP_RETURN32_8(a, b, c, d) ((target_long)(int32_t) \
|
||||
(((uint32_t)(a) << 24) | \
|
||||
((uint32_t)(b) << 16) | \
|
||||
((uint32_t)(c) << 8) | \
|
||||
((uint32_t)(d) & 0xFF)))
|
||||
#define MIPSDSP_RETURN32_16(a, b) ((target_long)(int32_t) \
|
||||
(((uint32_t)(a) << 16) | \
|
||||
((uint32_t)(b) & 0xFFFF)))
|
||||
|
||||
#ifdef TARGET_MIPS64
|
||||
#define MIPSDSP_SPLIT64_16(num, a, b, c, d) \
|
||||
do { \
|
||||
a = (num >> 48) & MIPSDSP_LO; \
|
||||
b = (num >> 32) & MIPSDSP_LO; \
|
||||
c = (num >> 16) & MIPSDSP_LO; \
|
||||
d = num & MIPSDSP_LO; \
|
||||
a = ((num) >> 48) & MIPSDSP_LO; \
|
||||
b = ((num) >> 32) & MIPSDSP_LO; \
|
||||
c = ((num) >> 16) & MIPSDSP_LO; \
|
||||
d = (num) & MIPSDSP_LO; \
|
||||
} while (0)
|
||||
|
||||
#define MIPSDSP_SPLIT64_32(num, a, b) \
|
||||
do { \
|
||||
a = (num >> 32) & MIPSDSP_LLO; \
|
||||
b = num & MIPSDSP_LLO; \
|
||||
a = ((num) >> 32) & MIPSDSP_LLO; \
|
||||
b = (num) & MIPSDSP_LLO; \
|
||||
} while (0)
|
||||
|
||||
#define MIPSDSP_RETURN64_16(a, b, c, d) (((uint64_t)a << 48) | \
|
||||
((uint64_t)b << 32) | \
|
||||
((uint64_t)c << 16) | \
|
||||
(uint64_t)d)
|
||||
#define MIPSDSP_RETURN64_32(a, b) (((uint64_t)a << 32) | (uint64_t)b)
|
||||
#define MIPSDSP_RETURN64_16(a, b, c, d) (((uint64_t)(a) << 48) | \
|
||||
((uint64_t)(b) << 32) | \
|
||||
((uint64_t)(c) << 16) | \
|
||||
(uint64_t)(d))
|
||||
#define MIPSDSP_RETURN64_32(a, b) (((uint64_t)(a) << 32) | (uint64_t)(b))
|
||||
#endif
|
||||
|
||||
/** DSP Arithmetic Sub-class insns **/
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "exec/gdbstub.h"
|
||||
|
||||
int mips_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "qemu/osdep.h"
|
||||
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "exec/log.h"
|
||||
|
|
|
@ -0,0 +1,422 @@
|
|||
/* mips internal definitions and helpers
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef MIPS_INTERNAL_H
|
||||
#define MIPS_INTERNAL_H
|
||||
|
||||
|
||||
/* 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 CP1_fcr31_rw_bitmask;
|
||||
int32_t CP1_fcr31;
|
||||
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;
|
||||
target_ulong CP0_EBaseWG_rw_bitmask;
|
||||
int insn_flags;
|
||||
enum mips_mmu_types mmu_type;
|
||||
};
|
||||
|
||||
extern const struct mips_def_t mips_defs[];
|
||||
extern const int mips_defs_number;
|
||||
|
||||
enum CPUMIPSMSADataFormat {
|
||||
DF_BYTE = 0,
|
||||
DF_HALF,
|
||||
DF_WORD,
|
||||
DF_DOUBLE
|
||||
};
|
||||
|
||||
void mips_cpu_do_interrupt(CPUState *cpu);
|
||||
bool mips_cpu_exec_interrupt(CPUState *cpu, int int_req);
|
||||
void mips_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
|
||||
int flags);
|
||||
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,
|
||||
MMUAccessType access_type,
|
||||
int mmu_idx, uintptr_t retaddr);
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
|
||||
typedef struct r4k_tlb_t r4k_tlb_t;
|
||||
struct r4k_tlb_t {
|
||||
target_ulong VPN;
|
||||
uint32_t PageMask;
|
||||
uint16_t ASID;
|
||||
unsigned int G:1;
|
||||
unsigned int C0:3;
|
||||
unsigned int C1:3;
|
||||
unsigned int V0:1;
|
||||
unsigned int V1:1;
|
||||
unsigned int D0:1;
|
||||
unsigned int D1:1;
|
||||
unsigned int XI0:1;
|
||||
unsigned int XI1:1;
|
||||
unsigned int RI0:1;
|
||||
unsigned int RI1:1;
|
||||
unsigned int EHINV:1;
|
||||
uint64_t PFN[2];
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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 r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra);
|
||||
|
||||
void mips_cpu_unassigned_access(CPUState *cpu, hwaddr addr,
|
||||
bool is_write, bool is_exec, int unused,
|
||||
unsigned size);
|
||||
hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address,
|
||||
int rw);
|
||||
#endif
|
||||
|
||||
#define cpu_signal_handler cpu_mips_signal_handler
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
extern const struct VMStateDescription vmstate_mips_cpu;
|
||||
#endif
|
||||
|
||||
static inline bool cpu_mips_hw_interrupts_enabled(CPUMIPSState *env)
|
||||
{
|
||||
return (env->CP0_Status & (1 << CP0St_IE)) &&
|
||||
!(env->CP0_Status & (1 << CP0St_EXL)) &&
|
||||
!(env->CP0_Status & (1 << CP0St_ERL)) &&
|
||||
!(env->hflags & MIPS_HFLAG_DM) &&
|
||||
/* 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));
|
||||
}
|
||||
|
||||
/* Check if there is pending and not masked out interrupt */
|
||||
static inline bool cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
|
||||
{
|
||||
int32_t pending;
|
||||
int32_t status;
|
||||
bool r;
|
||||
|
||||
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) != 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void mips_tcg_init(void);
|
||||
|
||||
/* TODO QOM'ify CPU reset and remove */
|
||||
void cpu_state_reset(CPUMIPSState *s);
|
||||
void cpu_mips_realize_env(CPUMIPSState *env);
|
||||
|
||||
/* cp0_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);
|
||||
|
||||
/* helper.c */
|
||||
int mips_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
|
||||
int mmu_idx);
|
||||
|
||||
/* op_helper.c */
|
||||
uint32_t float_class_s(uint32_t arg, float_status *fst);
|
||||
uint64_t float_class_d(uint64_t arg, float_status *fst);
|
||||
|
||||
extern unsigned int ieee_rm[];
|
||||
int ieee_ex_to_mips(int xcpt);
|
||||
|
||||
static inline void restore_rounding_mode(CPUMIPSState *env)
|
||||
{
|
||||
set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3],
|
||||
&env->active_fpu.fp_status);
|
||||
}
|
||||
|
||||
static inline void restore_flush_mode(CPUMIPSState *env)
|
||||
{
|
||||
set_flush_to_zero((env->active_fpu.fcr31 & (1 << FCR31_FS)) != 0,
|
||||
&env->active_fpu.fp_status);
|
||||
}
|
||||
|
||||
static inline void restore_fp_status(CPUMIPSState *env)
|
||||
{
|
||||
restore_rounding_mode(env);
|
||||
restore_flush_mode(env);
|
||||
restore_snan_bit_mode(env);
|
||||
}
|
||||
|
||||
static inline void restore_msa_fp_status(CPUMIPSState *env)
|
||||
{
|
||||
float_status *status = &env->active_tc.msa_fp_status;
|
||||
int rounding_mode = (env->active_tc.msacsr & MSACSR_RM_MASK) >> MSACSR_RM;
|
||||
bool flush_to_zero = (env->active_tc.msacsr & MSACSR_FS_MASK) != 0;
|
||||
|
||||
set_float_rounding_mode(ieee_rm[rounding_mode], status);
|
||||
set_flush_to_zero(flush_to_zero, status);
|
||||
set_flush_inputs_to_zero(flush_to_zero, status);
|
||||
}
|
||||
|
||||
static inline void restore_pamask(CPUMIPSState *env)
|
||||
{
|
||||
if (env->hflags & MIPS_HFLAG_ELPA) {
|
||||
env->PAMask = (1ULL << env->PABITS) - 1;
|
||||
} else {
|
||||
env->PAMask = PAMASK_BASE;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static inline int mips_vp_active(CPUMIPSState *env)
|
||||
{
|
||||
CPUState *other_cs = first_cpu;
|
||||
|
||||
/* Check if the VP disabled other VPs (which means the VP is enabled) */
|
||||
if ((env->CP0_VPControl >> CP0VPCtl_DIS) & 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check if the virtual processor is disabled due to a DVP */
|
||||
CPU_FOREACH(other_cs) {
|
||||
MIPSCPU *other_cpu = MIPS_CPU(other_cs);
|
||||
if ((&other_cpu->env != env) &&
|
||||
((other_cpu->env.CP0_VPControl >> CP0VPCtl_DIS) & 1)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
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 | MIPS_HFLAG_FRE |
|
||||
MIPS_HFLAG_ELPA | MIPS_HFLAG_ERL);
|
||||
if (env->CP0_Status & (1 << CP0St_ERL)) {
|
||||
env->hflags |= MIPS_HFLAG_ERL;
|
||||
}
|
||||
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->insn_flags & ISA_MIPS3) &&
|
||||
(((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->insn_flags & ISA_MIPS3)) {
|
||||
env->hflags |= MIPS_HFLAG_AWRAP;
|
||||
} else 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_MIPS64R6) {
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
|
||||
if (env->CP0_Config5 & (1 << CP0C5_FRE)) {
|
||||
env->hflags |= MIPS_HFLAG_FRE;
|
||||
}
|
||||
}
|
||||
if (env->CP0_Config3 & (1 << CP0C3_LPA)) {
|
||||
if (env->CP0_PageGrain & (1 << CP0PG_ELPA)) {
|
||||
env->hflags |= MIPS_HFLAG_ELPA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cpu_mips_tlb_flush(CPUMIPSState *env);
|
||||
void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc);
|
||||
void cpu_mips_store_status(CPUMIPSState *env, target_ulong val);
|
||||
void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val);
|
||||
|
||||
void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, uint32_t exception,
|
||||
int error_code, uintptr_t pc);
|
||||
|
||||
static inline void QEMU_NORETURN do_raise_exception(CPUMIPSState *env,
|
||||
uint32_t exception,
|
||||
uintptr_t pc)
|
||||
{
|
||||
do_raise_exception_err(env, exception, 0, pc);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "hw/hw.h"
|
||||
#include "migration/cpu.h"
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "disas/disas.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "tcg-op.h"
|
||||
|
@ -20511,29 +20512,15 @@ void mips_tcg_init(void)
|
|||
|
||||
#include "translate_init.c"
|
||||
|
||||
MIPSCPU *cpu_mips_init(const char *cpu_model)
|
||||
void cpu_mips_realize_env(CPUMIPSState *env)
|
||||
{
|
||||
MIPSCPU *cpu;
|
||||
CPUMIPSState *env;
|
||||
const mips_def_t *def;
|
||||
|
||||
def = cpu_mips_find_by_name(cpu_model);
|
||||
if (!def)
|
||||
return NULL;
|
||||
cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
|
||||
env = &cpu->env;
|
||||
env->cpu_model = def;
|
||||
env->exception_base = (int32_t)0xBFC00000;
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
mmu_init(env, def);
|
||||
mmu_init(env, env->cpu_model);
|
||||
#endif
|
||||
fpu_init(env, def);
|
||||
mvp_init(env, def);
|
||||
|
||||
object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
|
||||
|
||||
return cpu;
|
||||
fpu_init(env, env->cpu_model);
|
||||
mvp_init(env, env->cpu_model);
|
||||
}
|
||||
|
||||
bool cpu_supports_cps_smp(const char *cpu_model)
|
||||
|
|
|
@ -51,64 +51,9 @@
|
|||
#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 CP1_fcr31_rw_bitmask;
|
||||
int32_t CP1_fcr31;
|
||||
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;
|
||||
target_ulong CP0_EBaseWG_rw_bitmask;
|
||||
int insn_flags;
|
||||
enum mips_mmu_types mmu_type;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/* MIPS CPU definitions */
|
||||
static const mips_def_t mips_defs[] =
|
||||
const mips_def_t mips_defs[] =
|
||||
{
|
||||
{
|
||||
.name = "4Kc",
|
||||
|
@ -808,6 +753,7 @@ static const mips_def_t mips_defs[] =
|
|||
|
||||
#endif
|
||||
};
|
||||
const int mips_defs_number = ARRAY_SIZE(mips_defs);
|
||||
|
||||
static const mips_def_t *cpu_mips_find_by_name (const char *name)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue