diff options
Diffstat (limited to 'qemu/target-mips')
-rw-r--r-- | qemu/target-mips/cpu.c | 36 | ||||
-rw-r--r-- | qemu/target-mips/cpu.h | 160 | ||||
-rw-r--r-- | qemu/target-mips/dsp_helper.c | 1 | ||||
-rw-r--r-- | qemu/target-mips/gdbstub.c | 2 | ||||
-rw-r--r-- | qemu/target-mips/helper.c | 62 | ||||
-rw-r--r-- | qemu/target-mips/helper.h | 16 | ||||
-rw-r--r-- | qemu/target-mips/kvm.c | 395 | ||||
-rw-r--r-- | qemu/target-mips/lmi_helper.c | 1 | ||||
-rw-r--r-- | qemu/target-mips/machine.c | 7 | ||||
-rw-r--r-- | qemu/target-mips/mips-semi.c | 2 | ||||
-rw-r--r-- | qemu/target-mips/msa_helper.c | 195 | ||||
-rw-r--r-- | qemu/target-mips/op_helper.c | 458 | ||||
-rw-r--r-- | qemu/target-mips/translate.c | 1548 | ||||
-rw-r--r-- | qemu/target-mips/translate_init.c | 78 |
14 files changed, 1590 insertions, 1371 deletions
diff --git a/qemu/target-mips/cpu.c b/qemu/target-mips/cpu.c index 4027d0f41..0e2ecbebe 100644 --- a/qemu/target-mips/cpu.c +++ b/qemu/target-mips/cpu.c @@ -18,6 +18,8 @@ * <http://www.gnu.org/licenses/lgpl-2.1.html> */ +#include "qemu/osdep.h" +#include "qapi/error.h" #include "cpu.h" #include "kvm_mips.h" #include "qemu-common.h" @@ -53,12 +55,15 @@ static bool mips_cpu_has_work(CPUState *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 + /* Prior to MIPS Release 6 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; + if (cpu_mips_hw_interrupts_enabled(env) || + (env->insn_flags & ISA_MIPS32R6)) { + has_work = true; + } } /* MIPS-MT has the ability to halt the CPU. */ @@ -73,6 +78,15 @@ static bool mips_cpu_has_work(CPUState *cs) has_work = false; } } + /* MIPS Release 6 has the ability to halt the CPU. */ + if (env->CP0_Config5 & (1 << CP0C5_VP)) { + if (cs->interrupt_request & CPU_INTERRUPT_WAKE) { + has_work = true; + } + if (!mips_vp_active(env)) { + has_work = false; + } + } return has_work; } @@ -97,6 +111,14 @@ static void mips_cpu_reset(CPUState *s) #endif } +static void mips_cpu_disas_set_info(CPUState *s, disassemble_info *info) { +#ifdef TARGET_WORDS_BIGENDIAN + info->print_insn = print_insn_big_mips; +#else + info->print_insn = print_insn_little_mips; +#endif +} + static void mips_cpu_realizefn(DeviceState *dev, Error **errp) { CPUState *cs = CPU(dev); @@ -150,9 +172,17 @@ static void mips_cpu_class_init(ObjectClass *c, void *data) cc->get_phys_page_debug = mips_cpu_get_phys_page_debug; cc->vmsd = &vmstate_mips_cpu; #endif + cc->disas_set_info = mips_cpu_disas_set_info; cc->gdb_num_core_regs = 73; cc->gdb_stop_before_watchpoint = true; + + /* + * Reason: mips_cpu_initfn() calls cpu_exec_init(), which saves + * the object in cpus -> dangling pointer after final + * object_unref(). + */ + dc->cannot_destroy_with_object_finalize_yet = true; } static const TypeInfo mips_cpu_type_info = { diff --git a/qemu/target-mips/cpu.h b/qemu/target-mips/cpu.h index 075c561c8..866924d18 100644 --- a/qemu/target-mips/cpu.h +++ b/qemu/target-mips/cpu.h @@ -5,11 +5,8 @@ #define ALIGNED_ONLY -#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" @@ -21,19 +18,19 @@ 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; + uint8_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]; }; @@ -102,6 +99,7 @@ struct CPUMIPSFPUContext { uint32_t fcr0; #define FCR0_FREP 29 #define FCR0_UFRP 28 +#define FCR0_HAS2008 23 #define FCR0_F64 22 #define FCR0_L 21 #define FCR0_W 20 @@ -113,6 +111,8 @@ struct CPUMIPSFPUContext { #define FCR0_REV 0 /* fcsr */ uint32_t fcr31; +#define FCR31_ABS2008 19 +#define FCR31_NAN2008 18 #define SET_FP_COND(num,env) do { ((env).fcr31) |= ((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0) #define CLEAR_FP_COND(num,env) do { ((env).fcr31) &= ~((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0) #define GET_FP_COND(env) ((((env).fcr31 >> 24) & 0xfe) | (((env).fcr31 >> 23) & 0x1)) @@ -132,6 +132,7 @@ struct CPUMIPSFPUContext { }; #define NB_MMU_MODES 3 +#define TARGET_INSN_START_EXTRA_WORDS 2 typedef struct CPUMIPSMVPContext CPUMIPSMVPContext; struct CPUMIPSMVPContext { @@ -164,6 +165,7 @@ typedef struct mips_def_t mips_def_t; #define MIPS_FPU_MAX 1 #define MIPS_DSP_ACC 4 #define MIPS_KSCRATCH_NUM 6 +#define MIPS_MAAR_MAX 16 /* Must be an even number. */ typedef struct TCState TCState; struct TCState { @@ -239,6 +241,8 @@ struct CPUMIPSState { int32_t CP0_Index; /* CP0_MVP* are per MVP registers. */ + int32_t CP0_VPControl; +#define CP0VPCtl_DIS 0 int32_t CP0_Random; int32_t CP0_VPEControl; #define CP0VPECo_YSI 21 @@ -288,6 +292,8 @@ struct CPUMIPSState { # define CP0EnLo_RI 31 # define CP0EnLo_XI 30 #endif + int32_t CP0_GlobalNumber; +#define CP0GN_VPId 0 target_ulong CP0_Context; target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM]; int32_t CP0_PageMask; @@ -359,7 +365,7 @@ struct CPUMIPSState { #define CP0St_IE 0 int32_t CP0_IntCtl; #define CP0IntCtl_IPTI 29 -#define CP0IntCtl_IPPC1 26 +#define CP0IntCtl_IPPCI 26 #define CP0IntCtl_VS 5 int32_t CP0_SRSCtl; #define CP0SRSCtl_HSS 26 @@ -390,12 +396,13 @@ struct CPUMIPSState { target_ulong CP0_EPC; int32_t CP0_PRid; int32_t CP0_EBase; + target_ulong CP0_CMGCRBase; 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_MM 18 #define CP0C0_BM 16 #define CP0C0_BE 15 #define CP0C0_AT 13 @@ -432,7 +439,7 @@ struct CPUMIPSState { int32_t CP0_Config3; #define CP0C3_M 31 #define CP0C3_BPG 30 -#define CP0C3_CMCGR 29 +#define CP0C3_CMGCR 29 #define CP0C3_MSAP 28 #define CP0C3_BP 27 #define CP0C3_BI 26 @@ -470,15 +477,20 @@ struct CPUMIPSState { #define CP0C5_CV 29 #define CP0C5_EVA 28 #define CP0C5_MSAEn 27 +#define CP0C5_XNP 13 #define CP0C5_UFE 9 #define CP0C5_FRE 8 +#define CP0C5_VP 7 #define CP0C5_SBRI 6 #define CP0C5_MVH 5 #define CP0C5_LLB 4 +#define CP0C5_MRP 3 #define CP0C5_UFR 2 #define CP0C5_NFExists 0 int32_t CP0_Config6; int32_t CP0_Config7; + uint64_t CP0_MAAR[MIPS_MAAR_MAX]; + int32_t CP0_MAARI; /* XXX: Maybe make LLAddr per-TC? */ uint64_t lladdr; target_ulong llval; @@ -511,6 +523,10 @@ struct CPUMIPSState { #define CP0DB_DSS 0 target_ulong CP0_DEPC; int32_t CP0_Performance0; + int32_t CP0_ErrCtl; +#define CP0EC_WST 29 +#define CP0EC_SPR 28 +#define CP0EC_ITC 26 uint64_t CP0_TagLo; int32_t CP0_DataLo; int32_t CP0_TagHi; @@ -526,7 +542,7 @@ struct CPUMIPSState { #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 0x75807FF +#define MIPS_HFLAG_TMASK 0xF5807FF #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 @@ -575,6 +591,7 @@ struct CPUMIPSState { #define MIPS_HFLAG_MSA 0x1000000 #define MIPS_HFLAG_FRE 0x2000000 /* FRE enabled */ #define MIPS_HFLAG_ELPA 0x4000000 +#define MIPS_HFLAG_ITC_CACHE 0x8000000 /* CACHE instr. operates on ITC tag */ target_ulong btarget; /* Jump / branch target */ target_ulong bcond; /* Branch condition (if needed) */ @@ -595,6 +612,7 @@ struct CPUMIPSState { const mips_def_t *cpu_model; void *irq[8]; QEMUTimer *timer; /* Internal timer */ + MemoryRegion *itc_tag; /* ITC Configuration Tags */ }; #include "cpu-qom.h" @@ -621,7 +639,6 @@ void mips_cpu_unassigned_access(CPUState *cpu, hwaddr addr, 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 @@ -634,28 +651,29 @@ extern uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env); #define MMU_MODE1_SUFFIX _super #define MMU_MODE2_SUFFIX _user #define MMU_USER_IDX 2 -static inline int cpu_mmu_index (CPUMIPSState *env) +static inline int cpu_mmu_index (CPUMIPSState *env, bool ifetch) { return env->hflags & MIPS_HFLAG_KSU; } -static inline int cpu_mips_hw_interrupts_pending(CPUMIPSState *env) +static inline bool cpu_mips_hw_interrupts_enabled(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)) || + 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)) || - (env->hflags & MIPS_HFLAG_DM)) { - /* Interrupts are disabled */ - return 0; - } + !(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; @@ -669,7 +687,7 @@ static inline int cpu_mips_hw_interrupts_pending(CPUMIPSState *env) /* 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; + r = (pending & status) != 0; } return r; } @@ -752,6 +770,7 @@ 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)) +bool cpu_supports_cps_smp(const char *cpu_model); /* TODO QOM'ify CPU reset and remove */ void cpu_state_reset(CPUMIPSState *s); @@ -859,6 +878,26 @@ static inline int mips_vpe_active(CPUMIPSState *env) 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; +} + #include "exec/exec-all.h" static inline void compute_hflags(CPUMIPSState *env) @@ -961,6 +1000,15 @@ static inline void compute_hflags(CPUMIPSState *env) } #ifndef CONFIG_USER_ONLY +static inline void cpu_mips_tlb_flush(CPUMIPSState *env, int flush_global) +{ + MIPSCPU *cpu = mips_env_get_cpu(env); + + /* Flush qemu's TLB and discard all shadowed entries. */ + tlb_flush(CPU(cpu), flush_global); + env->tlb->tlb_in_use = env->tlb->nb_tlb; +} + /* Called for updates to CP0_Status. */ static inline void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc) { @@ -999,17 +1047,29 @@ static inline void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc) static inline void cpu_mips_store_status(CPUMIPSState *env, target_ulong val) { uint32_t mask = env->CP0_Status_rw_bitmask; + target_ulong old = env->CP0_Status; if (env->insn_flags & ISA_MIPS32R6) { bool has_supervisor = extract32(mask, CP0St_KSU, 2) == 0x3; - +#if defined(TARGET_MIPS64) + uint32_t ksux = (1 << CP0St_KX) & val; + ksux |= (ksux >> 1) & val; /* KX = 0 forces SX to be 0 */ + ksux |= (ksux >> 1) & val; /* SX = 0 forces UX to be 0 */ + val = (val & ~(7 << CP0St_UX)) | ksux; +#endif if (has_supervisor && extract32(val, CP0St_KSU, 2) == 0x3) { mask &= ~(3 << CP0St_KSU); } mask &= ~(((1 << CP0St_SR) | (1 << CP0St_NMI)) & val); } - env->CP0_Status = (env->CP0_Status & ~mask) | (val & mask); + env->CP0_Status = (old & ~mask) | (val & mask); +#if defined(TARGET_MIPS64) + if ((env->CP0_Status ^ old) & (old & (7 << CP0St_UX))) { + /* Access to at least one of the 64-bit segments has been disabled */ + cpu_mips_tlb_flush(env, 1); + } +#endif if (env->CP0_Config3 & (1 << CP0C3_MT)) { sync_c0_status(env, env, env->current_tc); } else { @@ -1049,4 +1109,28 @@ static inline void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val) } #endif +static inline void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, + uint32_t exception, + int error_code, + uintptr_t pc) +{ + CPUState *cs = CPU(mips_env_get_cpu(env)); + + if (exception < EXCP_SC) { + qemu_log_mask(CPU_LOG_INT, "%s: %d %d\n", + __func__, exception, error_code); + } + cs->exception_index = exception; + env->error_code = error_code; + + cpu_loop_exit_restore(cs, 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 /* !defined (__MIPS_CPU_H__) */ diff --git a/qemu/target-mips/dsp_helper.c b/qemu/target-mips/dsp_helper.c index 46528de32..df7d2204b 100644 --- a/qemu/target-mips/dsp_helper.c +++ b/qemu/target-mips/dsp_helper.c @@ -17,6 +17,7 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ +#include "qemu/osdep.h" #include "cpu.h" #include "exec/helper-proto.h" #include "qemu/bitops.h" diff --git a/qemu/target-mips/gdbstub.c b/qemu/target-mips/gdbstub.c index 9845d880a..b0b4a32ec 100644 --- a/qemu/target-mips/gdbstub.c +++ b/qemu/target-mips/gdbstub.c @@ -17,7 +17,7 @@ * 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 "config.h" +#include "qemu/osdep.h" #include "qemu-common.h" #include "exec/gdbstub.h" diff --git a/qemu/target-mips/helper.c b/qemu/target-mips/helper.c index 04ba19fd4..1004edee0 100644 --- a/qemu/target-mips/helper.c +++ b/qemu/target-mips/helper.c @@ -16,16 +16,12 @@ * 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 <inttypes.h> -#include <signal.h> +#include "qemu/osdep.h" #include "cpu.h" #include "sysemu/kvm.h" #include "exec/cpu_ldst.h" +#include "exec/log.h" enum { TLBRET_XI = -6, @@ -127,10 +123,6 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, /* 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 @@ -227,11 +219,6 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, 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 @@ -303,9 +290,10 @@ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address, (env->CP0_EntryHi & 0xFF) | (address & (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); + env->CP0_XContext = + /* PTEBase */ (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 7))) | + /* R */ (extract64(address, 62, 2) << (env->SEGBITS - 9)) | + /* BadVPN2 */ (extract64(address, 13, env->SEGBITS - 13) << 4); #endif cs->exception_index = exception; env->error_code = error_code; @@ -487,14 +475,16 @@ void mips_cpu_do_interrupt(CPUState *cs) int cause = -1; const char *name; - if (qemu_log_enabled() && cs->exception_index != EXCP_EXT_INTERRUPT) { + if (qemu_loglevel_mask(CPU_LOG_INT) + && 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", + 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 && @@ -531,6 +521,10 @@ void mips_cpu_do_interrupt(CPUState *cs) enter_debug_mode: if (env->insn_flags & ISA_MIPS3) { env->hflags |= MIPS_HFLAG_64; + if (!(env->insn_flags & ISA_MIPS64R6) || + env->CP0_Status & (1 << CP0St_KX)) { + env->hflags &= ~MIPS_HFLAG_AWRAP; + } } env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_CP0; env->hflags &= ~(MIPS_HFLAG_KSU); @@ -555,6 +549,10 @@ void mips_cpu_do_interrupt(CPUState *cs) env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); if (env->insn_flags & ISA_MIPS3) { env->hflags |= MIPS_HFLAG_64; + if (!(env->insn_flags & ISA_MIPS64R6) || + env->CP0_Status & (1 << CP0St_KX)) { + env->hflags &= ~MIPS_HFLAG_AWRAP; + } } env->hflags |= MIPS_HFLAG_CP0; env->hflags &= ~(MIPS_HFLAG_KSU); @@ -700,7 +698,7 @@ void mips_cpu_do_interrupt(CPUState *cs) goto set_EPC; case EXCP_DWATCH: cause = 23; - /* XXX: TODO: manage defered watch exceptions */ + /* XXX: TODO: manage deferred watch exceptions */ goto set_EPC; case EXCP_MCHECK: cause = 24; @@ -732,6 +730,10 @@ void mips_cpu_do_interrupt(CPUState *cs) env->CP0_Status |= (1 << CP0St_EXL); if (env->insn_flags & ISA_MIPS3) { env->hflags |= MIPS_HFLAG_64; + if (!(env->insn_flags & ISA_MIPS64R6) || + env->CP0_Status & (1 << CP0St_KX)) { + env->hflags &= ~MIPS_HFLAG_AWRAP; + } } env->hflags |= MIPS_HFLAG_CP0; env->hflags &= ~(MIPS_HFLAG_KSU); @@ -747,16 +749,15 @@ void mips_cpu_do_interrupt(CPUState *cs) 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); + abort(); } - if (qemu_log_enabled() && cs->exception_index != EXCP_EXT_INTERRUPT) { + if (qemu_loglevel_mask(CPU_LOG_INT) + && 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); + " 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; @@ -768,7 +769,8 @@ bool mips_cpu_exec_interrupt(CPUState *cs, int interrupt_request) MIPSCPU *cpu = MIPS_CPU(cs); CPUMIPSState *env = &cpu->env; - if (cpu_mips_hw_interrupts_pending(env)) { + if (cpu_mips_hw_interrupts_enabled(env) && + cpu_mips_hw_interrupts_pending(env)) { /* Raise it */ cs->exception_index = EXCP_EXT_INTERRUPT; env->error_code = 0; diff --git a/qemu/target-mips/helper.h b/qemu/target-mips/helper.h index 2b28e875c..594341d25 100644 --- a/qemu/target-mips/helper.h +++ b/qemu/target-mips/helper.h @@ -1,5 +1,6 @@ DEF_HELPER_3(raise_exception_err, noreturn, env, i32, int) DEF_HELPER_2(raise_exception, noreturn, env, i32) +DEF_HELPER_1(raise_exception_debug, noreturn, env) DEF_HELPER_1(do_semihosting, void, env) @@ -76,6 +77,8 @@ 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_1(mfc0_maar, tl, env) +DEF_HELPER_1(mfhc0_maar, 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) @@ -87,6 +90,7 @@ 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_1(dmfc0_maar, tl, env) DEF_HELPER_2(dmfc0_watchlo, tl, env, i32) #endif /* TARGET_MIPS64 */ @@ -143,6 +147,9 @@ DEF_HELPER_2(mtc0_config3, 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_2(mtc0_maar, void, env, tl) +DEF_HELPER_2(mthc0_maar, void, env, tl) +DEF_HELPER_2(mtc0_maari, 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) @@ -150,6 +157,7 @@ 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_errctl, 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) @@ -175,6 +183,10 @@ DEF_HELPER_0(dmt, tl) DEF_HELPER_0(emt, tl) DEF_HELPER_1(dvpe, tl, env) DEF_HELPER_1(evpe, tl, env) + +/* R6 Multi-threading */ +DEF_HELPER_1(dvp, tl, env) +DEF_HELPER_1(evp, tl, env) #endif /* !CONFIG_USER_ONLY */ /* microMIPS functions */ @@ -357,6 +369,8 @@ 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_1(rdhwr_performance, tl, env) +DEF_HELPER_1(rdhwr_xnp, tl, env) DEF_HELPER_2(pmon, void, env, int) DEF_HELPER_1(wait, void, env) @@ -942,3 +956,5 @@ MSALDST_PROTO(h) MSALDST_PROTO(w) MSALDST_PROTO(d) #undef MSALDST_PROTO + +DEF_HELPER_3(cache, void, env, tl, i32) diff --git a/qemu/target-mips/kvm.c b/qemu/target-mips/kvm.c index d287d4288..950bc05b7 100644 --- a/qemu/target-mips/kvm.c +++ b/qemu/target-mips/kvm.c @@ -9,7 +9,7 @@ * Authors: Sanjay Lal <sanjayl@kymasys.com> */ -#include <sys/types.h> +#include "qemu/osdep.h" #include <sys/ioctl.h> #include <sys/mman.h> @@ -30,6 +30,9 @@ #define DPRINTF(fmt, ...) \ do { if (DEBUG_KVM) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0) +static int kvm_mips_fpu_cap; +static int kvm_mips_msa_cap; + const KVMCapabilityInfo kvm_arch_required_capabilities[] = { KVM_CAP_LAST_INFO }; @@ -46,16 +49,39 @@ int kvm_arch_init(MachineState *ms, KVMState *s) /* MIPS has 128 signals */ kvm_set_sigmask_len(s, 16); + kvm_mips_fpu_cap = kvm_check_extension(s, KVM_CAP_MIPS_FPU); + kvm_mips_msa_cap = kvm_check_extension(s, KVM_CAP_MIPS_MSA); + DPRINTF("%s\n", __func__); return 0; } int kvm_arch_init_vcpu(CPUState *cs) { + MIPSCPU *cpu = MIPS_CPU(cs); + CPUMIPSState *env = &cpu->env; int ret = 0; qemu_add_vm_change_state_handler(kvm_mips_update_state, cs); + if (kvm_mips_fpu_cap && env->CP0_Config1 & (1 << CP0C1_FP)) { + ret = kvm_vcpu_enable_cap(cs, KVM_CAP_MIPS_FPU, 0, 0); + if (ret < 0) { + /* mark unsupported so it gets disabled on reset */ + kvm_mips_fpu_cap = 0; + ret = 0; + } + } + + if (kvm_mips_msa_cap && env->CP0_Config3 & (1 << CP0C3_MSAP)) { + ret = kvm_vcpu_enable_cap(cs, KVM_CAP_MIPS_MSA, 0, 0); + if (ret < 0) { + /* mark unsupported so it gets disabled on reset */ + kvm_mips_msa_cap = 0; + ret = 0; + } + } + DPRINTF("%s\n", __func__); return ret; } @@ -64,10 +90,14 @@ void kvm_mips_reset_vcpu(MIPSCPU *cpu) { CPUMIPSState *env = &cpu->env; - if (env->CP0_Config1 & (1 << CP0C1_FP)) { - fprintf(stderr, "Warning: FPU not supported with KVM, disabling\n"); + if (!kvm_mips_fpu_cap && env->CP0_Config1 & (1 << CP0C1_FP)) { + fprintf(stderr, "Warning: KVM does not support FPU, disabling\n"); env->CP0_Config1 &= ~(1 << CP0C1_FP); } + if (!kvm_mips_msa_cap && env->CP0_Config3 & (1 << CP0C3_MSAP)) { + fprintf(stderr, "Warning: KVM does not support MSA, disabling\n"); + env->CP0_Config3 &= ~(1 << CP0C3_MSAP); + } DPRINTF("%s\n", __func__); } @@ -88,7 +118,6 @@ static inline int cpu_mips_io_interrupts_pending(MIPSCPU *cpu) { CPUMIPSState *env = &cpu->env; - DPRINTF("%s: %#x\n", __func__, env->CP0_Cause & (1 << (2 + CP0Ca_IP))); return env->CP0_Cause & (0x1 << (2 + CP0Ca_IP)); } @@ -117,7 +146,6 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) { - DPRINTF("%s\n", __func__); return MEMTXATTRS_UNSPECIFIED; } @@ -230,6 +258,13 @@ int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level) #define KVM_REG_MIPS_CP0_STATUS MIPS_CP0_32(12, 0) #define KVM_REG_MIPS_CP0_CAUSE MIPS_CP0_32(13, 0) #define KVM_REG_MIPS_CP0_EPC MIPS_CP0_64(14, 0) +#define KVM_REG_MIPS_CP0_PRID MIPS_CP0_32(15, 0) +#define KVM_REG_MIPS_CP0_CONFIG MIPS_CP0_32(16, 0) +#define KVM_REG_MIPS_CP0_CONFIG1 MIPS_CP0_32(16, 1) +#define KVM_REG_MIPS_CP0_CONFIG2 MIPS_CP0_32(16, 2) +#define KVM_REG_MIPS_CP0_CONFIG3 MIPS_CP0_32(16, 3) +#define KVM_REG_MIPS_CP0_CONFIG4 MIPS_CP0_32(16, 4) +#define KVM_REG_MIPS_CP0_CONFIG5 MIPS_CP0_32(16, 5) #define KVM_REG_MIPS_CP0_ERROREPC MIPS_CP0_64(30, 0) static inline int kvm_mips_put_one_reg(CPUState *cs, uint64_t reg_id, @@ -243,6 +278,17 @@ static inline int kvm_mips_put_one_reg(CPUState *cs, uint64_t reg_id, return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); } +static inline int kvm_mips_put_one_ureg(CPUState *cs, uint64_t reg_id, + uint32_t *addr) +{ + struct kvm_one_reg cp0reg = { + .id = reg_id, + .addr = (uintptr_t)addr + }; + + return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); +} + static inline int kvm_mips_put_one_ulreg(CPUState *cs, uint64_t reg_id, target_ulong *addr) { @@ -256,7 +302,18 @@ static inline int kvm_mips_put_one_ulreg(CPUState *cs, uint64_t reg_id, } static inline int kvm_mips_put_one_reg64(CPUState *cs, uint64_t reg_id, - uint64_t *addr) + int64_t *addr) +{ + struct kvm_one_reg cp0reg = { + .id = reg_id, + .addr = (uintptr_t)addr + }; + + return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); +} + +static inline int kvm_mips_put_one_ureg64(CPUState *cs, uint64_t reg_id, + uint64_t *addr) { struct kvm_one_reg cp0reg = { .id = reg_id, @@ -277,7 +334,18 @@ static inline int kvm_mips_get_one_reg(CPUState *cs, uint64_t reg_id, return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); } -static inline int kvm_mips_get_one_ulreg(CPUState *cs, uint64 reg_id, +static inline int kvm_mips_get_one_ureg(CPUState *cs, uint64_t reg_id, + uint32_t *addr) +{ + struct kvm_one_reg cp0reg = { + .id = reg_id, + .addr = (uintptr_t)addr + }; + + return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); +} + +static inline int kvm_mips_get_one_ulreg(CPUState *cs, uint64_t reg_id, target_ulong *addr) { int ret; @@ -294,8 +362,8 @@ static inline int kvm_mips_get_one_ulreg(CPUState *cs, uint64 reg_id, return ret; } -static inline int kvm_mips_get_one_reg64(CPUState *cs, uint64 reg_id, - uint64_t *addr) +static inline int kvm_mips_get_one_reg64(CPUState *cs, uint64_t reg_id, + int64_t *addr) { struct kvm_one_reg cp0reg = { .id = reg_id, @@ -305,6 +373,50 @@ static inline int kvm_mips_get_one_reg64(CPUState *cs, uint64 reg_id, return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); } +static inline int kvm_mips_get_one_ureg64(CPUState *cs, uint64_t reg_id, + uint64_t *addr) +{ + struct kvm_one_reg cp0reg = { + .id = reg_id, + .addr = (uintptr_t)addr + }; + + return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); +} + +#define KVM_REG_MIPS_CP0_CONFIG_MASK (1U << CP0C0_M) +#define KVM_REG_MIPS_CP0_CONFIG1_MASK ((1U << CP0C1_M) | \ + (1U << CP0C1_FP)) +#define KVM_REG_MIPS_CP0_CONFIG2_MASK (1U << CP0C2_M) +#define KVM_REG_MIPS_CP0_CONFIG3_MASK ((1U << CP0C3_M) | \ + (1U << CP0C3_MSAP)) +#define KVM_REG_MIPS_CP0_CONFIG4_MASK (1U << CP0C4_M) +#define KVM_REG_MIPS_CP0_CONFIG5_MASK ((1U << CP0C5_MSAEn) | \ + (1U << CP0C5_UFE) | \ + (1U << CP0C5_FRE) | \ + (1U << CP0C5_UFR)) + +static inline int kvm_mips_change_one_reg(CPUState *cs, uint64_t reg_id, + int32_t *addr, int32_t mask) +{ + int err; + int32_t tmp, change; + + err = kvm_mips_get_one_reg(cs, reg_id, &tmp); + if (err < 0) { + return err; + } + + /* only change bits in mask */ + change = (*addr ^ tmp) & mask; + if (!change) { + return 0; + } + + tmp = tmp ^ change; + return kvm_mips_put_one_reg(cs, reg_id, &tmp); +} + /* * We freeze the KVM timer when either the VM clock is stopped or the state is * saved (the state is dirty). @@ -322,13 +434,13 @@ static int kvm_mips_save_count(CPUState *cs) int err, ret = 0; /* freeze KVM timer */ - err = kvm_mips_get_one_reg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); + err = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); if (err < 0) { DPRINTF("%s: Failed to get COUNT_CTL (%d)\n", __func__, err); ret = err; } else if (!(count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)) { count_ctl |= KVM_REG_MIPS_COUNT_CTL_DC; - err = kvm_mips_put_one_reg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); + err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); if (err < 0) { DPRINTF("%s: Failed to set COUNT_CTL.DC=1 (%d)\n", __func__, err); ret = err; @@ -364,14 +476,14 @@ static int kvm_mips_restore_count(CPUState *cs) int err_dc, err, ret = 0; /* check the timer is frozen */ - err_dc = kvm_mips_get_one_reg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); + err_dc = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); if (err_dc < 0) { DPRINTF("%s: Failed to get COUNT_CTL (%d)\n", __func__, err_dc); ret = err_dc; } else if (!(count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)) { /* freeze timer (sets COUNT_RESUME for us) */ count_ctl |= KVM_REG_MIPS_COUNT_CTL_DC; - err = kvm_mips_put_one_reg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); + err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); if (err < 0) { DPRINTF("%s: Failed to set COUNT_CTL.DC=1 (%d)\n", __func__, err); ret = err; @@ -395,7 +507,7 @@ static int kvm_mips_restore_count(CPUState *cs) /* resume KVM timer */ if (err_dc >= 0) { count_ctl &= ~KVM_REG_MIPS_COUNT_CTL_DC; - err = kvm_mips_put_one_reg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); + err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); if (err < 0) { DPRINTF("%s: Failed to set COUNT_CTL.DC=0 (%d)\n", __func__, err); ret = err; @@ -428,8 +540,8 @@ static void kvm_mips_update_state(void *opaque, int running, RunState state) } else { /* Set clock restore time to now */ count_resume = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); - ret = kvm_mips_put_one_reg64(cs, KVM_REG_MIPS_COUNT_RESUME, - &count_resume); + ret = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_RESUME, + &count_resume); if (ret < 0) { fprintf(stderr, "Failed setting COUNT_RESUME\n"); return; @@ -444,6 +556,167 @@ static void kvm_mips_update_state(void *opaque, int running, RunState state) } } +static int kvm_mips_put_fpu_registers(CPUState *cs, int level) +{ + MIPSCPU *cpu = MIPS_CPU(cs); + CPUMIPSState *env = &cpu->env; + int err, ret = 0; + unsigned int i; + + /* Only put FPU state if we're emulating a CPU with an FPU */ + if (env->CP0_Config1 & (1 << CP0C1_FP)) { + /* FPU Control Registers */ + if (level == KVM_PUT_FULL_STATE) { + err = kvm_mips_put_one_ureg(cs, KVM_REG_MIPS_FCR_IR, + &env->active_fpu.fcr0); + if (err < 0) { + DPRINTF("%s: Failed to put FCR_IR (%d)\n", __func__, err); + ret = err; + } + } + err = kvm_mips_put_one_ureg(cs, KVM_REG_MIPS_FCR_CSR, + &env->active_fpu.fcr31); + if (err < 0) { + DPRINTF("%s: Failed to put FCR_CSR (%d)\n", __func__, err); + ret = err; + } + + /* + * FPU register state is a subset of MSA vector state, so don't put FPU + * registers if we're emulating a CPU with MSA. + */ + if (!(env->CP0_Config3 & (1 << CP0C3_MSAP))) { + /* Floating point registers */ + for (i = 0; i < 32; ++i) { + if (env->CP0_Status & (1 << CP0St_FR)) { + err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_FPR_64(i), + &env->active_fpu.fpr[i].d); + } else { + err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FPR_32(i), + &env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]); + } + if (err < 0) { + DPRINTF("%s: Failed to put FPR%u (%d)\n", __func__, i, err); + ret = err; + } + } + } + } + + /* Only put MSA state if we're emulating a CPU with MSA */ + if (env->CP0_Config3 & (1 << CP0C3_MSAP)) { + /* MSA Control Registers */ + if (level == KVM_PUT_FULL_STATE) { + err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_MSA_IR, + &env->msair); + if (err < 0) { + DPRINTF("%s: Failed to put MSA_IR (%d)\n", __func__, err); + ret = err; + } + } + err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_MSA_CSR, + &env->active_tc.msacsr); + if (err < 0) { + DPRINTF("%s: Failed to put MSA_CSR (%d)\n", __func__, err); + ret = err; + } + + /* Vector registers (includes FP registers) */ + for (i = 0; i < 32; ++i) { + /* Big endian MSA not supported by QEMU yet anyway */ + err = kvm_mips_put_one_reg64(cs, KVM_REG_MIPS_VEC_128(i), + env->active_fpu.fpr[i].wr.d); + if (err < 0) { + DPRINTF("%s: Failed to put VEC%u (%d)\n", __func__, i, err); + ret = err; + } + } + } + + return ret; +} + +static int kvm_mips_get_fpu_registers(CPUState *cs) +{ + MIPSCPU *cpu = MIPS_CPU(cs); + CPUMIPSState *env = &cpu->env; + int err, ret = 0; + unsigned int i; + + /* Only get FPU state if we're emulating a CPU with an FPU */ + if (env->CP0_Config1 & (1 << CP0C1_FP)) { + /* FPU Control Registers */ + err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FCR_IR, + &env->active_fpu.fcr0); + if (err < 0) { + DPRINTF("%s: Failed to get FCR_IR (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FCR_CSR, + &env->active_fpu.fcr31); + if (err < 0) { + DPRINTF("%s: Failed to get FCR_CSR (%d)\n", __func__, err); + ret = err; + } else { + restore_fp_status(env); + } + + /* + * FPU register state is a subset of MSA vector state, so don't save FPU + * registers if we're emulating a CPU with MSA. + */ + if (!(env->CP0_Config3 & (1 << CP0C3_MSAP))) { + /* Floating point registers */ + for (i = 0; i < 32; ++i) { + if (env->CP0_Status & (1 << CP0St_FR)) { + err = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_FPR_64(i), + &env->active_fpu.fpr[i].d); + } else { + err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FPR_32(i), + &env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]); + } + if (err < 0) { + DPRINTF("%s: Failed to get FPR%u (%d)\n", __func__, i, err); + ret = err; + } + } + } + } + + /* Only get MSA state if we're emulating a CPU with MSA */ + if (env->CP0_Config3 & (1 << CP0C3_MSAP)) { + /* MSA Control Registers */ + err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_MSA_IR, + &env->msair); + if (err < 0) { + DPRINTF("%s: Failed to get MSA_IR (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_MSA_CSR, + &env->active_tc.msacsr); + if (err < 0) { + DPRINTF("%s: Failed to get MSA_CSR (%d)\n", __func__, err); + ret = err; + } else { + restore_msa_fp_status(env); + } + + /* Vector registers (includes FP registers) */ + for (i = 0; i < 32; ++i) { + /* Big endian MSA not supported by QEMU yet anyway */ + err = kvm_mips_get_one_reg64(cs, KVM_REG_MIPS_VEC_128(i), + env->active_fpu.fpr[i].wr.d); + if (err < 0) { + DPRINTF("%s: Failed to get VEC%u (%d)\n", __func__, i, err); + ret = err; + } + } + } + + return ret; +} + + static int kvm_mips_put_cp0_registers(CPUState *cs, int level) { MIPSCPU *cpu = MIPS_CPU(cs); @@ -522,6 +795,53 @@ static int kvm_mips_put_cp0_registers(CPUState *cs, int level) DPRINTF("%s: Failed to put CP0_EPC (%d)\n", __func__, err); ret = err; } + err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PRID, &env->CP0_PRid); + if (err < 0) { + DPRINTF("%s: Failed to put CP0_PRID (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG, + &env->CP0_Config0, + KVM_REG_MIPS_CP0_CONFIG_MASK); + if (err < 0) { + DPRINTF("%s: Failed to change CP0_CONFIG (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG1, + &env->CP0_Config1, + KVM_REG_MIPS_CP0_CONFIG1_MASK); + if (err < 0) { + DPRINTF("%s: Failed to change CP0_CONFIG1 (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG2, + &env->CP0_Config2, + KVM_REG_MIPS_CP0_CONFIG2_MASK); + if (err < 0) { + DPRINTF("%s: Failed to change CP0_CONFIG2 (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG3, + &env->CP0_Config3, + KVM_REG_MIPS_CP0_CONFIG3_MASK); + if (err < 0) { + DPRINTF("%s: Failed to change CP0_CONFIG3 (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG4, + &env->CP0_Config4, + KVM_REG_MIPS_CP0_CONFIG4_MASK); + if (err < 0) { + DPRINTF("%s: Failed to change CP0_CONFIG4 (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG5, + &env->CP0_Config5, + KVM_REG_MIPS_CP0_CONFIG5_MASK); + if (err < 0) { + DPRINTF("%s: Failed to change CP0_CONFIG5 (%d)\n", __func__, err); + ret = err; + } err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC, &env->CP0_ErrorEPC); if (err < 0) { @@ -608,6 +928,41 @@ static int kvm_mips_get_cp0_registers(CPUState *cs) DPRINTF("%s: Failed to get CP0_EPC (%d)\n", __func__, err); ret = err; } + err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PRID, &env->CP0_PRid); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_PRID (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG, &env->CP0_Config0); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_CONFIG (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG1, &env->CP0_Config1); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_CONFIG1 (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG2, &env->CP0_Config2); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_CONFIG2 (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG3, &env->CP0_Config3); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_CONFIG3 (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG4, &env->CP0_Config4); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_CONFIG4 (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG5, &env->CP0_Config5); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_CONFIG5 (%d)\n", __func__, err); + ret = err; + } err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC, &env->CP0_ErrorEPC); if (err < 0) { @@ -646,6 +1001,11 @@ int kvm_arch_put_registers(CPUState *cs, int level) return ret; } + ret = kvm_mips_put_fpu_registers(cs, level); + if (ret < 0) { + return ret; + } + return ret; } @@ -673,12 +1033,13 @@ int kvm_arch_get_registers(CPUState *cs) env->active_tc.PC = regs.pc; kvm_mips_get_cp0_registers(cs); + kvm_mips_get_fpu_registers(cs); return ret; } int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, - uint64_t address, uint32_t data) + uint64_t address, uint32_t data, PCIDevice *dev) { return 0; } diff --git a/qemu/target-mips/lmi_helper.c b/qemu/target-mips/lmi_helper.c index bbfcd59cd..fb1245b39 100644 --- a/qemu/target-mips/lmi_helper.c +++ b/qemu/target-mips/lmi_helper.c @@ -17,6 +17,7 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ +#include "qemu/osdep.h" #include "cpu.h" #include "exec/helper-proto.h" diff --git a/qemu/target-mips/machine.c b/qemu/target-mips/machine.c index b15c43a10..22bca1814 100644 --- a/qemu/target-mips/machine.c +++ b/qemu/target-mips/machine.c @@ -1,3 +1,4 @@ +#include "qemu/osdep.h" #include "hw/hw.h" #include "cpu.h" @@ -203,8 +204,8 @@ const VMStateDescription vmstate_tlb = { const VMStateDescription vmstate_mips_cpu = { .name = "cpu", - .version_id = 7, - .minimum_version_id = 7, + .version_id = 8, + .minimum_version_id = 8, .post_load = cpu_post_load, .fields = (VMStateField[]) { /* Active TC */ @@ -271,6 +272,8 @@ const VMStateDescription vmstate_mips_cpu = { VMSTATE_INT32(env.CP0_Config3, MIPSCPU), VMSTATE_INT32(env.CP0_Config6, MIPSCPU), VMSTATE_INT32(env.CP0_Config7, MIPSCPU), + VMSTATE_UINT64_ARRAY(env.CP0_MAAR, MIPSCPU, MIPS_MAAR_MAX), + VMSTATE_INT32(env.CP0_MAARI, MIPSCPU), VMSTATE_UINT64(env.lladdr, MIPSCPU), VMSTATE_UINTTL_ARRAY(env.CP0_WatchLo, MIPSCPU, 8), VMSTATE_INT32_ARRAY(env.CP0_WatchHi, MIPSCPU, 8), diff --git a/qemu/target-mips/mips-semi.c b/qemu/target-mips/mips-semi.c index 5050940c2..ed235de99 100644 --- a/qemu/target-mips/mips-semi.c +++ b/qemu/target-mips/mips-semi.c @@ -17,7 +17,7 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ -#include <sys/stat.h> +#include "qemu/osdep.h" #include "cpu.h" #include "exec/helper-proto.h" #include "exec/softmmu-semi.h" diff --git a/qemu/target-mips/msa_helper.c b/qemu/target-mips/msa_helper.c index a1cb48f2a..654a0d272 100644 --- a/qemu/target-mips/msa_helper.c +++ b/qemu/target-mips/msa_helper.c @@ -17,6 +17,7 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ +#include "qemu/osdep.h" #include "cpu.h" #include "exec/helper-proto.h" @@ -1352,7 +1353,7 @@ void helper_msa_ctcmsa(CPUMIPSState *env, target_ulong elm, uint32_t cd) /* check exception */ if ((GET_FP_ENABLE(env->active_tc.msacsr) | FP_UNIMPLEMENTED) & GET_FP_CAUSE(env->active_tc.msacsr)) { - helper_raise_exception(env, EXCP_MSAFPE); + do_raise_exception(env, EXCP_MSAFPE, GETPC()); } break; } @@ -1505,14 +1506,14 @@ static inline void clear_msacsr_cause(CPUMIPSState *env) SET_FP_CAUSE(env->active_tc.msacsr, 0); } -static inline void check_msacsr_cause(CPUMIPSState *env) +static inline void check_msacsr_cause(CPUMIPSState *env, uintptr_t retaddr) { if ((GET_FP_CAUSE(env->active_tc.msacsr) & (GET_FP_ENABLE(env->active_tc.msacsr) | FP_UNIMPLEMENTED)) == 0) { UPDATE_FP_FLAGS(env->active_tc.msacsr, GET_FP_CAUSE(env->active_tc.msacsr)); } else { - helper_raise_exception(env, EXCP_MSAFPE); + do_raise_exception(env, EXCP_MSAFPE, retaddr); } } @@ -1604,7 +1605,7 @@ static inline int get_enabled_exceptions(const CPUMIPSState *env, int c) return c & enable; } -static inline float16 float16_from_float32(int32 a, flag ieee, +static inline float16 float16_from_float32(int32_t a, flag ieee, float_status *status) { float16 f_val; @@ -1615,7 +1616,7 @@ static inline float16 float16_from_float32(int32 a, flag ieee, return a < 0 ? (f_val | (1 << 15)) : f_val; } -static inline float32 float32_from_float64(int64 a, float_status *status) +static inline float32 float32_from_float64(int64_t a, float_status *status) { float32 f_val; @@ -1636,7 +1637,7 @@ static inline float32 float32_from_float16(int16_t a, flag ieee, return a < 0 ? (f_val | (1 << 31)) : f_val; } -static inline float64 float64_from_float32(int32 a, float_status *status) +static inline float64 float64_from_float32(int32_t a, float_status *status) { float64 f_val; @@ -1657,7 +1658,7 @@ static inline float32 float32_from_q16(int16_t a, float_status *status) return f_val; } -static inline float64 float64_from_q32(int32 a, float_status *status) +static inline float64 float64_from_q32(int32_t a, float_status *status) { float64 f_val; @@ -1670,9 +1671,9 @@ static inline float64 float64_from_q32(int32 a, float_status *status) static inline int16_t float32_to_q16(float32 a, float_status *status) { - int32 q_val; - int32 q_min = 0xffff8000; - int32 q_max = 0x00007fff; + int32_t q_val; + int32_t q_min = 0xffff8000; + int32_t q_max = 0x00007fff; int ieee_ex; @@ -1690,7 +1691,7 @@ static inline int16_t float32_to_q16(float32 a, float_status *status) if (ieee_ex & float_flag_overflow) { float_raise(float_flag_inexact, status); - return (int32)a < 0 ? q_min : q_max; + return (int32_t)a < 0 ? q_min : q_max; } /* conversion to int */ @@ -1704,7 +1705,7 @@ static inline int16_t float32_to_q16(float32 a, float_status *status) set_float_exception_flags(ieee_ex & (~float_flag_invalid) , status); float_raise(float_flag_overflow | float_flag_inexact, status); - return (int32)a < 0 ? q_min : q_max; + return (int32_t)a < 0 ? q_min : q_max; } if (q_val < q_min) { @@ -1720,11 +1721,11 @@ static inline int16_t float32_to_q16(float32 a, float_status *status) return (int16_t)q_val; } -static inline int32 float64_to_q32(float64 a, float_status *status) +static inline int32_t float64_to_q32(float64 a, float_status *status) { - int64 q_val; - int64 q_min = 0xffffffff80000000LL; - int64 q_max = 0x000000007fffffffLL; + int64_t q_val; + int64_t q_min = 0xffffffff80000000LL; + int64_t q_max = 0x000000007fffffffLL; int ieee_ex; @@ -1742,7 +1743,7 @@ static inline int32 float64_to_q32(float64 a, float_status *status) if (ieee_ex & float_flag_overflow) { float_raise(float_flag_inexact, status); - return (int64)a < 0 ? q_min : q_max; + return (int64_t)a < 0 ? q_min : q_max; } /* conversion to integer */ @@ -1756,20 +1757,20 @@ static inline int32 float64_to_q32(float64 a, float_status *status) set_float_exception_flags(ieee_ex & (~float_flag_invalid) , status); float_raise(float_flag_overflow | float_flag_inexact, status); - return (int64)a < 0 ? q_min : q_max; + return (int64_t)a < 0 ? q_min : q_max; } if (q_val < q_min) { float_raise(float_flag_overflow | float_flag_inexact, status); - return (int32)q_min; + return (int32_t)q_min; } if (q_max < q_val) { float_raise(float_flag_overflow | float_flag_inexact, status); - return (int32)q_max; + return (int32_t)q_max; } - return (int32)q_val; + return (int32_t)q_val; } #define MSA_FLOAT_COND(DEST, OP, ARG1, ARG2, BITS, QUIET) \ @@ -1851,7 +1852,8 @@ static inline int32 float64_to_q32(float64 a, float_status *status) } while (0) static inline void compare_af(CPUMIPSState *env, wr_t *pwd, wr_t *pws, - wr_t *pwt, uint32_t df, int quiet) + wr_t *pwt, uint32_t df, int quiet, + uintptr_t retaddr) { wr_t wx, *pwx = &wx; uint32_t i; @@ -1873,13 +1875,14 @@ static inline void compare_af(CPUMIPSState *env, wr_t *pwd, wr_t *pws, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, retaddr); msa_move_v(pwd, pwx); } static inline void compare_un(CPUMIPSState *env, wr_t *pwd, wr_t *pws, - wr_t *pwt, uint32_t df, int quiet) + wr_t *pwt, uint32_t df, int quiet, + uintptr_t retaddr) { wr_t wx, *pwx = &wx; uint32_t i; @@ -1903,13 +1906,14 @@ static inline void compare_un(CPUMIPSState *env, wr_t *pwd, wr_t *pws, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, retaddr); msa_move_v(pwd, pwx); } static inline void compare_eq(CPUMIPSState *env, wr_t *pwd, wr_t *pws, - wr_t *pwt, uint32_t df, int quiet) + wr_t *pwt, uint32_t df, int quiet, + uintptr_t retaddr) { wr_t wx, *pwx = &wx; uint32_t i; @@ -1931,13 +1935,14 @@ static inline void compare_eq(CPUMIPSState *env, wr_t *pwd, wr_t *pws, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, retaddr); msa_move_v(pwd, pwx); } static inline void compare_ueq(CPUMIPSState *env, wr_t *pwd, wr_t *pws, - wr_t *pwt, uint32_t df, int quiet) + wr_t *pwt, uint32_t df, int quiet, + uintptr_t retaddr) { wr_t wx, *pwx = &wx; uint32_t i; @@ -1959,13 +1964,14 @@ static inline void compare_ueq(CPUMIPSState *env, wr_t *pwd, wr_t *pws, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, retaddr); msa_move_v(pwd, pwx); } static inline void compare_lt(CPUMIPSState *env, wr_t *pwd, wr_t *pws, - wr_t *pwt, uint32_t df, int quiet) + wr_t *pwt, uint32_t df, int quiet, + uintptr_t retaddr) { wr_t wx, *pwx = &wx; uint32_t i; @@ -1987,13 +1993,14 @@ static inline void compare_lt(CPUMIPSState *env, wr_t *pwd, wr_t *pws, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, retaddr); msa_move_v(pwd, pwx); } static inline void compare_ult(CPUMIPSState *env, wr_t *pwd, wr_t *pws, - wr_t *pwt, uint32_t df, int quiet) + wr_t *pwt, uint32_t df, int quiet, + uintptr_t retaddr) { wr_t wx, *pwx = &wx; uint32_t i; @@ -2015,13 +2022,14 @@ static inline void compare_ult(CPUMIPSState *env, wr_t *pwd, wr_t *pws, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, retaddr); msa_move_v(pwd, pwx); } static inline void compare_le(CPUMIPSState *env, wr_t *pwd, wr_t *pws, - wr_t *pwt, uint32_t df, int quiet) + wr_t *pwt, uint32_t df, int quiet, + uintptr_t retaddr) { wr_t wx, *pwx = &wx; uint32_t i; @@ -2043,13 +2051,14 @@ static inline void compare_le(CPUMIPSState *env, wr_t *pwd, wr_t *pws, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, retaddr); msa_move_v(pwd, pwx); } static inline void compare_ule(CPUMIPSState *env, wr_t *pwd, wr_t *pws, - wr_t *pwt, uint32_t df, int quiet) + wr_t *pwt, uint32_t df, int quiet, + uintptr_t retaddr) { wr_t wx, *pwx = &wx; uint32_t i; @@ -2071,13 +2080,14 @@ static inline void compare_ule(CPUMIPSState *env, wr_t *pwd, wr_t *pws, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, retaddr); msa_move_v(pwd, pwx); } static inline void compare_or(CPUMIPSState *env, wr_t *pwd, wr_t *pws, - wr_t *pwt, uint32_t df, int quiet) + wr_t *pwt, uint32_t df, int quiet, + uintptr_t retaddr) { wr_t wx, *pwx = &wx; uint32_t i; @@ -2099,13 +2109,14 @@ static inline void compare_or(CPUMIPSState *env, wr_t *pwd, wr_t *pws, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, retaddr); msa_move_v(pwd, pwx); } static inline void compare_une(CPUMIPSState *env, wr_t *pwd, wr_t *pws, - wr_t *pwt, uint32_t df, int quiet) + wr_t *pwt, uint32_t df, int quiet, + uintptr_t retaddr) { wr_t wx, *pwx = &wx; uint32_t i; @@ -2127,13 +2138,15 @@ static inline void compare_une(CPUMIPSState *env, wr_t *pwd, wr_t *pws, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, retaddr); msa_move_v(pwd, pwx); } static inline void compare_ne(CPUMIPSState *env, wr_t *pwd, wr_t *pws, - wr_t *pwt, uint32_t df, int quiet) { + wr_t *pwt, uint32_t df, int quiet, + uintptr_t retaddr) +{ wr_t wx, *pwx = &wx; uint32_t i; @@ -2154,7 +2167,7 @@ static inline void compare_ne(CPUMIPSState *env, wr_t *pwd, wr_t *pws, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, retaddr); msa_move_v(pwd, pwx); } @@ -2165,7 +2178,7 @@ void helper_msa_fcaf_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_af(env, pwd, pws, pwt, df, 1); + compare_af(env, pwd, pws, pwt, df, 1, GETPC()); } void helper_msa_fcun_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2174,7 +2187,7 @@ void helper_msa_fcun_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_un(env, pwd, pws, pwt, df, 1); + compare_un(env, pwd, pws, pwt, df, 1, GETPC()); } void helper_msa_fceq_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2183,7 +2196,7 @@ void helper_msa_fceq_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_eq(env, pwd, pws, pwt, df, 1); + compare_eq(env, pwd, pws, pwt, df, 1, GETPC()); } void helper_msa_fcueq_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2192,7 +2205,7 @@ void helper_msa_fcueq_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_ueq(env, pwd, pws, pwt, df, 1); + compare_ueq(env, pwd, pws, pwt, df, 1, GETPC()); } void helper_msa_fclt_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2201,7 +2214,7 @@ void helper_msa_fclt_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_lt(env, pwd, pws, pwt, df, 1); + compare_lt(env, pwd, pws, pwt, df, 1, GETPC()); } void helper_msa_fcult_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2210,7 +2223,7 @@ void helper_msa_fcult_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_ult(env, pwd, pws, pwt, df, 1); + compare_ult(env, pwd, pws, pwt, df, 1, GETPC()); } void helper_msa_fcle_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2219,7 +2232,7 @@ void helper_msa_fcle_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_le(env, pwd, pws, pwt, df, 1); + compare_le(env, pwd, pws, pwt, df, 1, GETPC()); } void helper_msa_fcule_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2228,7 +2241,7 @@ void helper_msa_fcule_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_ule(env, pwd, pws, pwt, df, 1); + compare_ule(env, pwd, pws, pwt, df, 1, GETPC()); } void helper_msa_fsaf_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2237,7 +2250,7 @@ void helper_msa_fsaf_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_af(env, pwd, pws, pwt, df, 0); + compare_af(env, pwd, pws, pwt, df, 0, GETPC()); } void helper_msa_fsun_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2246,7 +2259,7 @@ void helper_msa_fsun_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_un(env, pwd, pws, pwt, df, 0); + compare_un(env, pwd, pws, pwt, df, 0, GETPC()); } void helper_msa_fseq_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2255,7 +2268,7 @@ void helper_msa_fseq_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_eq(env, pwd, pws, pwt, df, 0); + compare_eq(env, pwd, pws, pwt, df, 0, GETPC()); } void helper_msa_fsueq_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2264,7 +2277,7 @@ void helper_msa_fsueq_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_ueq(env, pwd, pws, pwt, df, 0); + compare_ueq(env, pwd, pws, pwt, df, 0, GETPC()); } void helper_msa_fslt_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2273,7 +2286,7 @@ void helper_msa_fslt_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_lt(env, pwd, pws, pwt, df, 0); + compare_lt(env, pwd, pws, pwt, df, 0, GETPC()); } void helper_msa_fsult_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2282,7 +2295,7 @@ void helper_msa_fsult_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_ult(env, pwd, pws, pwt, df, 0); + compare_ult(env, pwd, pws, pwt, df, 0, GETPC()); } void helper_msa_fsle_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2291,7 +2304,7 @@ void helper_msa_fsle_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_le(env, pwd, pws, pwt, df, 0); + compare_le(env, pwd, pws, pwt, df, 0, GETPC()); } void helper_msa_fsule_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2300,7 +2313,7 @@ void helper_msa_fsule_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_ule(env, pwd, pws, pwt, df, 0); + compare_ule(env, pwd, pws, pwt, df, 0, GETPC()); } void helper_msa_fcor_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2309,7 +2322,7 @@ void helper_msa_fcor_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_or(env, pwd, pws, pwt, df, 1); + compare_or(env, pwd, pws, pwt, df, 1, GETPC()); } void helper_msa_fcune_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2318,7 +2331,7 @@ void helper_msa_fcune_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_une(env, pwd, pws, pwt, df, 1); + compare_une(env, pwd, pws, pwt, df, 1, GETPC()); } void helper_msa_fcne_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2327,7 +2340,7 @@ void helper_msa_fcne_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_ne(env, pwd, pws, pwt, df, 1); + compare_ne(env, pwd, pws, pwt, df, 1, GETPC()); } void helper_msa_fsor_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2336,7 +2349,7 @@ void helper_msa_fsor_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_or(env, pwd, pws, pwt, df, 0); + compare_or(env, pwd, pws, pwt, df, 0, GETPC()); } void helper_msa_fsune_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2345,7 +2358,7 @@ void helper_msa_fsune_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_une(env, pwd, pws, pwt, df, 0); + compare_une(env, pwd, pws, pwt, df, 0, GETPC()); } void helper_msa_fsne_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -2354,7 +2367,7 @@ void helper_msa_fsne_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - compare_ne(env, pwd, pws, pwt, df, 0); + compare_ne(env, pwd, pws, pwt, df, 0, GETPC()); } #define float16_is_zero(ARG) 0 @@ -2404,7 +2417,7 @@ void helper_msa_fadd_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -2434,7 +2447,7 @@ void helper_msa_fsub_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -2464,7 +2477,7 @@ void helper_msa_fmul_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -2495,7 +2508,7 @@ void helper_msa_fdiv_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -2542,7 +2555,7 @@ void helper_msa_fmadd_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -2577,7 +2590,7 @@ void helper_msa_fmsub_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -2614,7 +2627,7 @@ void helper_msa_fexp2_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -2666,7 +2679,7 @@ void helper_msa_fexdo_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -2712,7 +2725,7 @@ void helper_msa_ftq_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -2791,7 +2804,7 @@ void helper_msa_fmin_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -2822,7 +2835,7 @@ void helper_msa_fmin_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -2865,7 +2878,7 @@ void helper_msa_fmax_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -2896,7 +2909,7 @@ void helper_msa_fmax_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -2958,7 +2971,7 @@ void helper_msa_ftrunc_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -2988,7 +3001,7 @@ void helper_msa_ftrunc_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -3018,7 +3031,7 @@ void helper_msa_fsqrt_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -3067,7 +3080,7 @@ void helper_msa_frsqrt_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -3097,7 +3110,7 @@ void helper_msa_frcp_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -3127,7 +3140,7 @@ void helper_msa_frint_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -3181,7 +3194,7 @@ void helper_msa_flog2_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -3216,7 +3229,7 @@ void helper_msa_fexupl_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -3250,7 +3263,7 @@ void helper_msa_fexupr_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -3331,7 +3344,7 @@ void helper_msa_ftint_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -3361,7 +3374,7 @@ void helper_msa_ftint_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -3397,7 +3410,7 @@ void helper_msa_ffint_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } @@ -3427,7 +3440,7 @@ void helper_msa_ffint_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } - check_msacsr_cause(env); + check_msacsr_cause(env, GETPC()); msa_move_v(pwd, pwx); } diff --git a/qemu/target-mips/op_helper.c b/qemu/target-mips/op_helper.c index db4f6b946..4417e6ba2 100644 --- a/qemu/target-mips/op_helper.c +++ b/qemu/target-mips/op_helper.c @@ -16,55 +16,33 @@ * 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 <stdlib.h> +#include "qemu/osdep.h" #include "cpu.h" #include "qemu/host-utils.h" #include "exec/helper-proto.h" #include "exec/cpu_ldst.h" #include "sysemu/kvm.h" -#ifndef CONFIG_USER_ONLY -static inline void cpu_mips_tlb_flush (CPUMIPSState *env, int flush_global); -#endif - /*****************************************************************************/ /* Exceptions processing helpers */ -static inline void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, - uint32_t exception, - int error_code, - uintptr_t pc) +void helper_raise_exception_err(CPUMIPSState *env, uint32_t exception, + int error_code) { - CPUState *cs = CPU(mips_env_get_cpu(env)); - - if (exception < EXCP_SC) { - qemu_log("%s: %d %d\n", __func__, exception, error_code); - } - cs->exception_index = exception; - env->error_code = error_code; - - if (pc) { - /* now we have a real cpu fault */ - cpu_restore_state(cs, pc); - } - - cpu_loop_exit(cs); + do_raise_exception_err(env, exception, error_code, 0); } -static inline void QEMU_NORETURN do_raise_exception(CPUMIPSState *env, - uint32_t exception, - uintptr_t pc) +void helper_raise_exception(CPUMIPSState *env, uint32_t exception) { - do_raise_exception_err(env, exception, 0, pc); + do_raise_exception(env, exception, GETPC()); } -void helper_raise_exception_err(CPUMIPSState *env, uint32_t exception, - int error_code) +void helper_raise_exception_debug(CPUMIPSState *env) { - do_raise_exception_err(env, exception, error_code, 0); + do_raise_exception(env, EXCP_DEBUG, 0); } -void helper_raise_exception(CPUMIPSState *env, uint32_t exception) +static void raise_exception(CPUMIPSState *env, uint32_t exception) { do_raise_exception(env, exception, 0); } @@ -72,21 +50,21 @@ void helper_raise_exception(CPUMIPSState *env, uint32_t exception) #if defined(CONFIG_USER_ONLY) #define HELPER_LD(name, insn, type) \ static inline type do_##name(CPUMIPSState *env, target_ulong addr, \ - int mem_idx) \ + int mem_idx, uintptr_t retaddr) \ { \ - return (type) cpu_##insn##_data(env, addr); \ + return (type) cpu_##insn##_data_ra(env, addr, retaddr); \ } #else #define HELPER_LD(name, insn, type) \ static inline type do_##name(CPUMIPSState *env, target_ulong addr, \ - int mem_idx) \ + int mem_idx, uintptr_t retaddr) \ { \ switch (mem_idx) \ { \ - case 0: return (type) cpu_##insn##_kernel(env, addr); break; \ - case 1: return (type) cpu_##insn##_super(env, addr); break; \ + case 0: return (type) cpu_##insn##_kernel_ra(env, addr, retaddr); \ + case 1: return (type) cpu_##insn##_super_ra(env, addr, retaddr); \ default: \ - case 2: return (type) cpu_##insn##_user(env, addr); break; \ + case 2: return (type) cpu_##insn##_user_ra(env, addr, retaddr); \ } \ } #endif @@ -99,21 +77,21 @@ HELPER_LD(ld, ldq, int64_t) #if defined(CONFIG_USER_ONLY) #define HELPER_ST(name, insn, type) \ static inline void do_##name(CPUMIPSState *env, target_ulong addr, \ - type val, int mem_idx) \ + type val, int mem_idx, uintptr_t retaddr) \ { \ - cpu_##insn##_data(env, addr, val); \ + cpu_##insn##_data_ra(env, addr, val, retaddr); \ } #else #define HELPER_ST(name, insn, type) \ static inline void do_##name(CPUMIPSState *env, target_ulong addr, \ - type val, int mem_idx) \ + type val, int mem_idx, uintptr_t retaddr) \ { \ switch (mem_idx) \ { \ - case 0: cpu_##insn##_kernel(env, addr, val); break; \ - case 1: cpu_##insn##_super(env, addr, val); break; \ + case 0: cpu_##insn##_kernel_ra(env, addr, val, retaddr); break; \ + case 1: cpu_##insn##_super_ra(env, addr, val, retaddr); break; \ default: \ - case 2: cpu_##insn##_user(env, addr, val); break; \ + case 2: cpu_##insn##_user_ra(env, addr, val, retaddr); break; \ } \ } #endif @@ -292,14 +270,15 @@ target_ulong helper_bitswap(target_ulong rt) static inline hwaddr do_translate_address(CPUMIPSState *env, target_ulong address, - int rw) + int rw, uintptr_t retaddr) { hwaddr lladdr; + CPUState *cs = CPU(mips_env_get_cpu(env)); lladdr = cpu_mips_translate_address(env, address, rw); if (lladdr == -1LL) { - cpu_loop_exit(CPU(mips_env_get_cpu(env))); + cpu_loop_exit_restore(cs, retaddr); } else { return lladdr; } @@ -310,10 +289,10 @@ target_ulong helper_##name(CPUMIPSState *env, target_ulong arg, int mem_idx) \ { \ if (arg & almask) { \ env->CP0_BadVAddr = arg; \ - helper_raise_exception(env, EXCP_AdEL); \ + do_raise_exception(env, EXCP_AdEL, GETPC()); \ } \ - env->lladdr = do_translate_address(env, arg, 0); \ - env->llval = do_##insn(env, arg, mem_idx); \ + env->lladdr = do_translate_address(env, arg, 0, GETPC()); \ + env->llval = do_##insn(env, arg, mem_idx, GETPC()); \ return env->llval; \ } HELPER_LD_ATOMIC(ll, lw, 0x3) @@ -330,12 +309,12 @@ target_ulong helper_##name(CPUMIPSState *env, target_ulong arg1, \ \ if (arg2 & almask) { \ env->CP0_BadVAddr = arg2; \ - helper_raise_exception(env, EXCP_AdES); \ + do_raise_exception(env, EXCP_AdES, GETPC()); \ } \ - if (do_translate_address(env, arg2, 1) == env->lladdr) { \ - tmp = do_##ld_insn(env, arg2, mem_idx); \ + if (do_translate_address(env, arg2, 1, GETPC()) == env->lladdr) { \ + tmp = do_##ld_insn(env, arg2, mem_idx, GETPC()); \ if (tmp == env->llval) { \ - do_##st_insn(env, arg2, arg1, mem_idx); \ + do_##st_insn(env, arg2, arg1, mem_idx, GETPC()); \ return 1; \ } \ } \ @@ -359,31 +338,43 @@ HELPER_ST_ATOMIC(scd, ld, sd, 0x7) void helper_swl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2, int mem_idx) { - do_sb(env, arg2, (uint8_t)(arg1 >> 24), mem_idx); + do_sb(env, arg2, (uint8_t)(arg1 >> 24), mem_idx, GETPC()); - if (GET_LMASK(arg2) <= 2) - do_sb(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 16), mem_idx); + if (GET_LMASK(arg2) <= 2) { + do_sb(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 16), mem_idx, + GETPC()); + } - if (GET_LMASK(arg2) <= 1) - do_sb(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 8), mem_idx); + if (GET_LMASK(arg2) <= 1) { + do_sb(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 8), mem_idx, + GETPC()); + } - if (GET_LMASK(arg2) == 0) - do_sb(env, GET_OFFSET(arg2, 3), (uint8_t)arg1, mem_idx); + if (GET_LMASK(arg2) == 0) { + do_sb(env, GET_OFFSET(arg2, 3), (uint8_t)arg1, mem_idx, + GETPC()); + } } void helper_swr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2, int mem_idx) { - do_sb(env, arg2, (uint8_t)arg1, mem_idx); + do_sb(env, arg2, (uint8_t)arg1, mem_idx, GETPC()); - if (GET_LMASK(arg2) >= 1) - do_sb(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx); + if (GET_LMASK(arg2) >= 1) { + do_sb(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx, + GETPC()); + } - if (GET_LMASK(arg2) >= 2) - do_sb(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx); + if (GET_LMASK(arg2) >= 2) { + do_sb(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx, + GETPC()); + } - if (GET_LMASK(arg2) == 3) - do_sb(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx); + if (GET_LMASK(arg2) == 3) { + do_sb(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx, + GETPC()); + } } #if defined(TARGET_MIPS64) @@ -399,55 +390,83 @@ void helper_swr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2, void helper_sdl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2, int mem_idx) { - do_sb(env, arg2, (uint8_t)(arg1 >> 56), mem_idx); + do_sb(env, arg2, (uint8_t)(arg1 >> 56), mem_idx, GETPC()); - if (GET_LMASK64(arg2) <= 6) - do_sb(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 48), mem_idx); + if (GET_LMASK64(arg2) <= 6) { + do_sb(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 48), mem_idx, + GETPC()); + } - if (GET_LMASK64(arg2) <= 5) - do_sb(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 40), mem_idx); + if (GET_LMASK64(arg2) <= 5) { + do_sb(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 40), mem_idx, + GETPC()); + } - if (GET_LMASK64(arg2) <= 4) - do_sb(env, GET_OFFSET(arg2, 3), (uint8_t)(arg1 >> 32), mem_idx); + if (GET_LMASK64(arg2) <= 4) { + do_sb(env, GET_OFFSET(arg2, 3), (uint8_t)(arg1 >> 32), mem_idx, + GETPC()); + } - if (GET_LMASK64(arg2) <= 3) - do_sb(env, GET_OFFSET(arg2, 4), (uint8_t)(arg1 >> 24), mem_idx); + if (GET_LMASK64(arg2) <= 3) { + do_sb(env, GET_OFFSET(arg2, 4), (uint8_t)(arg1 >> 24), mem_idx, + GETPC()); + } - if (GET_LMASK64(arg2) <= 2) - do_sb(env, GET_OFFSET(arg2, 5), (uint8_t)(arg1 >> 16), mem_idx); + if (GET_LMASK64(arg2) <= 2) { + do_sb(env, GET_OFFSET(arg2, 5), (uint8_t)(arg1 >> 16), mem_idx, + GETPC()); + } - if (GET_LMASK64(arg2) <= 1) - do_sb(env, GET_OFFSET(arg2, 6), (uint8_t)(arg1 >> 8), mem_idx); + if (GET_LMASK64(arg2) <= 1) { + do_sb(env, GET_OFFSET(arg2, 6), (uint8_t)(arg1 >> 8), mem_idx, + GETPC()); + } - if (GET_LMASK64(arg2) <= 0) - do_sb(env, GET_OFFSET(arg2, 7), (uint8_t)arg1, mem_idx); + if (GET_LMASK64(arg2) <= 0) { + do_sb(env, GET_OFFSET(arg2, 7), (uint8_t)arg1, mem_idx, + GETPC()); + } } void helper_sdr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2, int mem_idx) { - do_sb(env, arg2, (uint8_t)arg1, mem_idx); + do_sb(env, arg2, (uint8_t)arg1, mem_idx, GETPC()); - if (GET_LMASK64(arg2) >= 1) - do_sb(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx); + if (GET_LMASK64(arg2) >= 1) { + do_sb(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx, + GETPC()); + } - if (GET_LMASK64(arg2) >= 2) - do_sb(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx); + if (GET_LMASK64(arg2) >= 2) { + do_sb(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx, + GETPC()); + } - if (GET_LMASK64(arg2) >= 3) - do_sb(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx); + if (GET_LMASK64(arg2) >= 3) { + do_sb(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx, + GETPC()); + } - if (GET_LMASK64(arg2) >= 4) - do_sb(env, GET_OFFSET(arg2, -4), (uint8_t)(arg1 >> 32), mem_idx); + if (GET_LMASK64(arg2) >= 4) { + do_sb(env, GET_OFFSET(arg2, -4), (uint8_t)(arg1 >> 32), mem_idx, + GETPC()); + } - if (GET_LMASK64(arg2) >= 5) - do_sb(env, GET_OFFSET(arg2, -5), (uint8_t)(arg1 >> 40), mem_idx); + if (GET_LMASK64(arg2) >= 5) { + do_sb(env, GET_OFFSET(arg2, -5), (uint8_t)(arg1 >> 40), mem_idx, + GETPC()); + } - if (GET_LMASK64(arg2) >= 6) - do_sb(env, GET_OFFSET(arg2, -6), (uint8_t)(arg1 >> 48), mem_idx); + if (GET_LMASK64(arg2) >= 6) { + do_sb(env, GET_OFFSET(arg2, -6), (uint8_t)(arg1 >> 48), mem_idx, + GETPC()); + } - if (GET_LMASK64(arg2) == 7) - do_sb(env, GET_OFFSET(arg2, -7), (uint8_t)(arg1 >> 56), mem_idx); + if (GET_LMASK64(arg2) == 7) { + do_sb(env, GET_OFFSET(arg2, -7), (uint8_t)(arg1 >> 56), mem_idx, + GETPC()); + } } #endif /* TARGET_MIPS64 */ @@ -464,13 +483,14 @@ void helper_lwm(CPUMIPSState *env, target_ulong addr, target_ulong reglist, for (i = 0; i < base_reglist; i++) { env->active_tc.gpr[multiple_regs[i]] = - (target_long)do_lw(env, addr, mem_idx); + (target_long)do_lw(env, addr, mem_idx, GETPC()); addr += 4; } } if (do_r31) { - env->active_tc.gpr[31] = (target_long)do_lw(env, addr, mem_idx); + env->active_tc.gpr[31] = (target_long)do_lw(env, addr, mem_idx, + GETPC()); } } @@ -484,13 +504,14 @@ void helper_swm(CPUMIPSState *env, target_ulong addr, target_ulong reglist, target_ulong i; for (i = 0; i < base_reglist; i++) { - do_sw(env, addr, env->active_tc.gpr[multiple_regs[i]], mem_idx); + do_sw(env, addr, env->active_tc.gpr[multiple_regs[i]], mem_idx, + GETPC()); addr += 4; } } if (do_r31) { - do_sw(env, addr, env->active_tc.gpr[31], mem_idx); + do_sw(env, addr, env->active_tc.gpr[31], mem_idx, GETPC()); } } @@ -505,13 +526,14 @@ void helper_ldm(CPUMIPSState *env, target_ulong addr, target_ulong reglist, target_ulong i; for (i = 0; i < base_reglist; i++) { - env->active_tc.gpr[multiple_regs[i]] = do_ld(env, addr, mem_idx); + env->active_tc.gpr[multiple_regs[i]] = do_ld(env, addr, mem_idx, + GETPC()); addr += 8; } } if (do_r31) { - env->active_tc.gpr[31] = do_ld(env, addr, mem_idx); + env->active_tc.gpr[31] = do_ld(env, addr, mem_idx, GETPC()); } } @@ -525,13 +547,14 @@ void helper_sdm(CPUMIPSState *env, target_ulong addr, target_ulong reglist, target_ulong i; for (i = 0; i < base_reglist; i++) { - do_sd(env, addr, env->active_tc.gpr[multiple_regs[i]], mem_idx); + do_sd(env, addr, env->active_tc.gpr[multiple_regs[i]], mem_idx, + GETPC()); addr += 8; } } if (do_r31) { - do_sd(env, addr, env->active_tc.gpr[31], mem_idx); + do_sd(env, addr, env->active_tc.gpr[31], mem_idx, GETPC()); } } #endif @@ -548,6 +571,14 @@ static bool mips_vpe_is_wfi(MIPSCPU *c) return cpu->halted && mips_vpe_active(env); } +static bool mips_vp_is_wfi(MIPSCPU *c) +{ + CPUState *cpu = CPU(c); + CPUMIPSState *env = &c->env; + + return cpu->halted && mips_vp_active(env); +} + static inline void mips_vpe_wake(MIPSCPU *c) { /* Dont set ->halted = 0 directly, let it be done via cpu_has_work @@ -858,6 +889,16 @@ target_ulong helper_mfc0_lladdr(CPUMIPSState *env) return (int32_t)(env->lladdr >> env->CP0_LLAddr_shift); } +target_ulong helper_mfc0_maar(CPUMIPSState *env) +{ + return (int32_t) env->CP0_MAAR[env->CP0_MAARI]; +} + +target_ulong helper_mfhc0_maar(CPUMIPSState *env) +{ + return env->CP0_MAAR[env->CP0_MAARI] >> 32; +} + target_ulong helper_mfc0_watchlo(CPUMIPSState *env, uint32_t sel) { return (int32_t)env->CP0_WatchLo[sel]; @@ -924,6 +965,11 @@ target_ulong helper_dmfc0_lladdr(CPUMIPSState *env) return env->lladdr >> env->CP0_LLAddr_shift; } +target_ulong helper_dmfc0_maar(CPUMIPSState *env) +{ + return env->CP0_MAAR[env->CP0_MAARI]; +} + target_ulong helper_dmfc0_watchlo(CPUMIPSState *env, uint32_t sel) { return env->CP0_WatchLo[sel]; @@ -1330,6 +1376,13 @@ void helper_mtc0_hwrena(CPUMIPSState *env, target_ulong arg1) { uint32_t mask = 0x0000000F; + if ((env->CP0_Config1 & (1 << CP0C1_PC)) && + (env->insn_flags & ISA_MIPS32R6)) { + mask |= (1 << 4); + } + if (env->insn_flags & ISA_MIPS32R6) { + mask |= (1 << 5); + } if (env->CP0_Config3 & (1 << CP0C3_ULRI)) { mask |= (1 << 29); @@ -1540,6 +1593,36 @@ void helper_mtc0_lladdr(CPUMIPSState *env, target_ulong arg1) env->lladdr = (env->lladdr & ~mask) | (arg1 & mask); } +#define MTC0_MAAR_MASK(env) \ + ((0x1ULL << 63) | ((env->PAMask >> 4) & ~0xFFFull) | 0x3) + +void helper_mtc0_maar(CPUMIPSState *env, target_ulong arg1) +{ + env->CP0_MAAR[env->CP0_MAARI] = arg1 & MTC0_MAAR_MASK(env); +} + +void helper_mthc0_maar(CPUMIPSState *env, target_ulong arg1) +{ + env->CP0_MAAR[env->CP0_MAARI] = + (((uint64_t) arg1 << 32) & MTC0_MAAR_MASK(env)) | + (env->CP0_MAAR[env->CP0_MAARI] & 0x00000000ffffffffULL); +} + +void helper_mtc0_maari(CPUMIPSState *env, target_ulong arg1) +{ + int index = arg1 & 0x3f; + if (index == 0x3f) { + /* Software may write all ones to INDEX to determine the + maximum value supported. */ + env->CP0_MAARI = MIPS_MAAR_MAX - 1; + } else if (index < MIPS_MAAR_MAX) { + env->CP0_MAARI = index; + } + /* Other than the all ones, if the + value written is not supported, then INDEX is unchanged + from its previous value. */ +} + void helper_mtc0_watchlo(CPUMIPSState *env, target_ulong arg1, uint32_t sel) { /* Watch exceptions for instructions, data loads, data stores @@ -1594,9 +1677,31 @@ void helper_mtc0_performance0(CPUMIPSState *env, target_ulong arg1) env->CP0_Performance0 = arg1 & 0x000007ff; } +void helper_mtc0_errctl(CPUMIPSState *env, target_ulong arg1) +{ + int32_t wst = arg1 & (1 << CP0EC_WST); + int32_t spr = arg1 & (1 << CP0EC_SPR); + int32_t itc = env->itc_tag ? (arg1 & (1 << CP0EC_ITC)) : 0; + + env->CP0_ErrCtl = wst | spr | itc; + + if (itc && !wst && !spr) { + env->hflags |= MIPS_HFLAG_ITC_CACHE; + } else { + env->hflags &= ~MIPS_HFLAG_ITC_CACHE; + } +} + void helper_mtc0_taglo(CPUMIPSState *env, target_ulong arg1) { - env->CP0_TagLo = arg1 & 0xFFFFFCF6; + if (env->hflags & MIPS_HFLAG_ITC_CACHE) { + /* If CACHE instruction is configured for ITC tags then make all + CP0.TagLo bits writable. The actual write to ITC Configuration + Tag will take care of the read-only bits. */ + env->CP0_TagLo = arg1; + } else { + env->CP0_TagLo = arg1 & 0xFFFFFCF6; + } } void helper_mtc0_datalo(CPUMIPSState *env, target_ulong arg1) @@ -1791,13 +1896,13 @@ target_ulong helper_yield(CPUMIPSState *env, target_ulong arg) env->active_tc.CP0_TCStatus & (1 << CP0TCSt_DT)) { env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT); env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT; - helper_raise_exception(env, EXCP_THREAD); + do_raise_exception(env, EXCP_THREAD, GETPC()); } } } else if (arg1 == 0) { if (0 /* TODO: TC underflow */) { env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT); - helper_raise_exception(env, EXCP_THREAD); + do_raise_exception(env, EXCP_THREAD, GETPC()); } else { // TODO: Deallocate TC } @@ -1805,22 +1910,53 @@ target_ulong helper_yield(CPUMIPSState *env, target_ulong arg) /* Yield qualifier inputs not implemented. */ env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT); env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT; - helper_raise_exception(env, EXCP_THREAD); + do_raise_exception(env, EXCP_THREAD, GETPC()); } return env->CP0_YQMask; } +/* R6 Multi-threading */ #ifndef CONFIG_USER_ONLY -/* TLB management */ -static void cpu_mips_tlb_flush (CPUMIPSState *env, int flush_global) +target_ulong helper_dvp(CPUMIPSState *env) { - MIPSCPU *cpu = mips_env_get_cpu(env); + CPUState *other_cs = first_cpu; + target_ulong prev = env->CP0_VPControl; + + if (!((env->CP0_VPControl >> CP0VPCtl_DIS) & 1)) { + CPU_FOREACH(other_cs) { + MIPSCPU *other_cpu = MIPS_CPU(other_cs); + /* Turn off all VPs except the one executing the dvp. */ + if (&other_cpu->env != env) { + mips_vpe_sleep(other_cpu); + } + } + env->CP0_VPControl |= (1 << CP0VPCtl_DIS); + } + return prev; +} - /* Flush qemu's TLB and discard all shadowed entries. */ - tlb_flush(CPU(cpu), flush_global); - env->tlb->tlb_in_use = env->tlb->nb_tlb; +target_ulong helper_evp(CPUMIPSState *env) +{ + CPUState *other_cs = first_cpu; + target_ulong prev = env->CP0_VPControl; + + if ((env->CP0_VPControl >> CP0VPCtl_DIS) & 1) { + CPU_FOREACH(other_cs) { + MIPSCPU *other_cpu = MIPS_CPU(other_cs); + if ((&other_cpu->env != env) && !mips_vp_is_wfi(other_cpu)) { + /* If the VP is WFI, don't disturb its sleep. + * Otherwise, wake it up. */ + mips_vpe_wake(other_cpu); + } + } + env->CP0_VPControl &= ~(1 << CP0VPCtl_DIS); + } + return prev; } +#endif /* !CONFIG_USER_ONLY */ +#ifndef CONFIG_USER_ONLY +/* TLB management */ static void r4k_mips_tlb_flush_extra (CPUMIPSState *env, int first) { /* Discard entries from env->tlb[first] onwards. */ @@ -2158,48 +2294,52 @@ void helper_deret(CPUMIPSState *env) } #endif /* !CONFIG_USER_ONLY */ -target_ulong helper_rdhwr_cpunum(CPUMIPSState *env) +static inline void check_hwrena(CPUMIPSState *env, int reg, uintptr_t pc) { - if ((env->hflags & MIPS_HFLAG_CP0) || - (env->CP0_HWREna & (1 << 0))) - return env->CP0_EBase & 0x3ff; - else - helper_raise_exception(env, EXCP_RI); + if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << reg))) { + return; + } + do_raise_exception(env, EXCP_RI, pc); +} - return 0; +target_ulong helper_rdhwr_cpunum(CPUMIPSState *env) +{ + check_hwrena(env, 0, GETPC()); + return env->CP0_EBase & 0x3ff; } target_ulong helper_rdhwr_synci_step(CPUMIPSState *env) { - if ((env->hflags & MIPS_HFLAG_CP0) || - (env->CP0_HWREna & (1 << 1))) - return env->SYNCI_Step; - else - helper_raise_exception(env, EXCP_RI); - - return 0; + check_hwrena(env, 1, GETPC()); + return env->SYNCI_Step; } target_ulong helper_rdhwr_cc(CPUMIPSState *env) { - if ((env->hflags & MIPS_HFLAG_CP0) || - (env->CP0_HWREna & (1 << 2))) - return env->CP0_Count; - else - helper_raise_exception(env, EXCP_RI); - - return 0; + check_hwrena(env, 2, GETPC()); +#ifdef CONFIG_USER_ONLY + return env->CP0_Count; +#else + return (int32_t)cpu_mips_get_count(env); +#endif } target_ulong helper_rdhwr_ccres(CPUMIPSState *env) { - if ((env->hflags & MIPS_HFLAG_CP0) || - (env->CP0_HWREna & (1 << 3))) - return env->CCRes; - else - helper_raise_exception(env, EXCP_RI); + check_hwrena(env, 3, GETPC()); + return env->CCRes; +} - return 0; +target_ulong helper_rdhwr_performance(CPUMIPSState *env) +{ + check_hwrena(env, 4, GETPC()); + return env->CP0_Performance0; +} + +target_ulong helper_rdhwr_xnp(CPUMIPSState *env) +{ + check_hwrena(env, 5, GETPC()); + return (env->CP0_Config5 >> CP0C5_XNP) & 1; } void helper_pmon(CPUMIPSState *env, int function) @@ -2234,7 +2374,9 @@ void helper_wait(CPUMIPSState *env) cs->halted = 1; cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE); - helper_raise_exception(env, EXCP_HLT); + /* Last instruction in the block, PC was updated before + - no need to recover PC and icount */ + raise_exception(env, EXCP_HLT); } #if !defined(CONFIG_USER_ONLY) @@ -2295,9 +2437,9 @@ void mips_cpu_unassigned_access(CPUState *cs, hwaddr addr, } if (is_exec) { - helper_raise_exception(env, EXCP_IBE); + raise_exception(env, EXCP_IBE); } else { - helper_raise_exception(env, EXCP_DBE); + raise_exception(env, EXCP_DBE); } } #endif /* !CONFIG_USER_ONLY */ @@ -2332,7 +2474,7 @@ target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg) arg1 = (int32_t) ((env->CP0_Status & (1 << CP0St_FR)) >> CP0St_FR); } else { - helper_raise_exception(env, EXCP_RI); + do_raise_exception(env, EXCP_RI, GETPC()); } } break; @@ -2375,7 +2517,7 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt) env->CP0_Status &= ~(1 << CP0St_FR); compute_hflags(env); } else { - helper_raise_exception(env, EXCP_RI); + do_raise_exception(env, EXCP_RI, GETPC()); } break; case 4: @@ -2387,7 +2529,7 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt) env->CP0_Status |= (1 << CP0St_FR); compute_hflags(env); } else { - helper_raise_exception(env, EXCP_RI); + do_raise_exception(env, EXCP_RI, GETPC()); } break; case 5: @@ -2518,6 +2660,7 @@ uint64_t helper_float_cvtd_s(CPUMIPSState *env, uint32_t fst0) uint64_t fdt2; fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status); + fdt2 = float64_maybe_silence_nan(fdt2); update_fcr31(env, GETPC()); return fdt2; } @@ -2607,6 +2750,7 @@ uint32_t helper_float_cvts_d(CPUMIPSState *env, uint64_t fdt0) uint32_t fst2; fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status); + fst2 = float32_maybe_silence_nan(fst2); update_fcr31(env, GETPC()); return fst2; } @@ -3628,7 +3772,7 @@ FOP_CONDN_S(sne, (float32_lt(fst1, fst0, &env->active_fpu.fp_status) #if !defined(CONFIG_USER_ONLY) #define MEMOP_IDX(DF) \ TCGMemOpIdx oi = make_memop_idx(MO_TE | DF | MO_UNALN, \ - cpu_mmu_index(env)); + cpu_mmu_index(env, false)); #else #define MEMOP_IDX(DF) #endif @@ -3684,7 +3828,7 @@ void helper_msa_st_ ## TYPE(CPUMIPSState *env, uint32_t wd, \ target_ulong addr) \ { \ wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ - int mmu_idx = cpu_mmu_index(env); \ + int mmu_idx = cpu_mmu_index(env, false); \ int i; \ MEMOP_IDX(DF) \ ensure_writable_pages(env, addr, mmu_idx, GETRA()); \ @@ -3704,3 +3848,19 @@ MSA_ST_DF(DF_HALF, h, cpu_stw_data) MSA_ST_DF(DF_WORD, w, cpu_stl_data) MSA_ST_DF(DF_DOUBLE, d, cpu_stq_data) #endif + +void helper_cache(CPUMIPSState *env, target_ulong addr, uint32_t op) +{ +#ifndef CONFIG_USER_ONLY + target_ulong index = addr & 0x1fffffff; + if (op == 9) { + /* Index Store Tag */ + memory_region_dispatch_write(env->itc_tag, index, env->CP0_TagLo, + 8, MEMTXATTRS_UNSPECIFIED); + } else if (op == 5) { + /* Index Load Tag */ + memory_region_dispatch_read(env->itc_tag, index, &env->CP0_TagLo, + 8, MEMTXATTRS_UNSPECIFIED); + } +#endif +} diff --git a/qemu/target-mips/translate.c b/qemu/target-mips/translate.c index 22ef84df9..a3a05ec66 100644 --- a/qemu/target-mips/translate.c +++ b/qemu/target-mips/translate.c @@ -21,6 +21,7 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ +#include "qemu/osdep.h" #include "cpu.h" #include "disas/disas.h" #include "tcg-op.h" @@ -32,10 +33,9 @@ #include "exec/semihost.h" #include "trace-tcg.h" - +#include "exec/log.h" #define MIPS_DEBUG_DISAS 0 -//#define MIPS_DEBUG_SIGN_EXTENSIONS /* MIPS major opcodes */ #define MASK_OP_MAJOR(op) (op & (0x3F << 26)) @@ -325,6 +325,7 @@ enum { OPC_TLTIU = (0x0B << 16) | OPC_REGIMM, OPC_TEQI = (0x0C << 16) | OPC_REGIMM, OPC_TNEI = (0x0E << 16) | OPC_REGIMM, + OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM, OPC_SYNCI = (0x1F << 16) | OPC_REGIMM, OPC_DAHI = (0x06 << 16) | OPC_REGIMM, @@ -893,6 +894,8 @@ enum { OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0, OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0, OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0, + OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0, + OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0, }; /* Coprocessor 0 (with rs == C0) */ @@ -1352,7 +1355,7 @@ enum { }; /* global register indices */ -static TCGv_ptr cpu_env; +static TCGv_env cpu_env; static TCGv cpu_gpr[32], cpu_PC; static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC]; static TCGv cpu_dspctrl, btarget, bcond; @@ -1361,9 +1364,6 @@ static TCGv_i32 fpu_fcr0, fpu_fcr31; static TCGv_i64 fpu_f64[32]; static TCGv_i64 msa_wr_d[64]; -static uint32_t gen_opc_hflags[OPC_BUF_SIZE]; -static target_ulong gen_opc_btarget[OPC_BUF_SIZE]; - #include "exec/gen-icount.h" #define gen_helper_0e0i(name, arg) do { \ @@ -1431,6 +1431,9 @@ typedef struct DisasContext { bool mvh; int CP0_LLAddr_shift; bool ps; + bool vp; + bool cmgcr; + bool mrp; } DisasContext; enum { @@ -1482,26 +1485,23 @@ static const char * const msaregnames[] = { "w30.d0", "w30.d1", "w31.d0", "w31.d1", }; -#define MIPS_DEBUG(fmt, ...) \ +#define LOG_DISAS(...) \ do { \ if (MIPS_DEBUG_DISAS) { \ - qemu_log_mask(CPU_LOG_TB_IN_ASM, \ - TARGET_FMT_lx ": %08x " fmt "\n", \ - ctx->pc, ctx->opcode , ## __VA_ARGS__); \ + qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \ } \ } while (0) -#define LOG_DISAS(...) \ +#define MIPS_INVAL(op) \ do { \ if (MIPS_DEBUG_DISAS) { \ - qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \ + qemu_log_mask(CPU_LOG_TB_IN_ASM, \ + TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \ + ctx->pc, ctx->opcode, op, ctx->opcode >> 26, \ + ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \ } \ } while (0) -#define MIPS_INVAL(op) \ - MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \ - ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)) - /* General purpose registers moves. */ static inline void gen_load_gpr (TCGv t, int reg) { @@ -1615,21 +1615,26 @@ static inline void generate_exception_err(DisasContext *ctx, int excp, int err) gen_helper_raise_exception_err(cpu_env, texcp, terr); tcg_temp_free_i32(terr); tcg_temp_free_i32(texcp); + ctx->bstate = BS_EXCP; } static inline void generate_exception(DisasContext *ctx, int excp) { - save_cpu_state(ctx, 1); gen_helper_0e0i(raise_exception, excp); } +static inline void generate_exception_end(DisasContext *ctx, int excp) +{ + generate_exception_err(ctx, excp, 0); +} + /* Floating point register moves. */ static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg) { if (ctx->hflags & MIPS_HFLAG_FRE) { generate_exception(ctx, EXCP_RI); } - tcg_gen_trunc_i64_i32(t, fpu_f64[reg]); + tcg_gen_extrl_i64_i32(t, fpu_f64[reg]); } static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg) @@ -1647,10 +1652,7 @@ static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg) static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg) { if (ctx->hflags & MIPS_HFLAG_F64) { - TCGv_i64 t64 = tcg_temp_new_i64(); - tcg_gen_shri_i64(t64, fpu_f64[reg], 32); - tcg_gen_trunc_i64_i32(t, t64); - tcg_temp_free_i64(t64); + tcg_gen_extrh_i64_i32(t, fpu_f64[reg]); } else { gen_load_fpr32(ctx, t, reg | 1); } @@ -1725,12 +1727,23 @@ static target_long addr_add(DisasContext *ctx, target_long base, return sum; } +/* Sign-extract the low 32-bits to a target_long. */ static inline void gen_move_low32(TCGv ret, TCGv_i64 arg) { #if defined(TARGET_MIPS64) - tcg_gen_ext32s_tl(ret, arg); + tcg_gen_ext32s_i64(ret, arg); +#else + tcg_gen_extrl_i64_i32(ret, arg); +#endif +} + +/* Sign-extract the high 32-bits to a target_long. */ +static inline void gen_move_high32(TCGv ret, TCGv_i64 arg) +{ +#if defined(TARGET_MIPS64) + tcg_gen_sari_i64(ret, arg, 32); #else - tcg_gen_trunc_i64_tl(ret, arg); + tcg_gen_extrh_i64_i32(ret, arg); #endif } @@ -1753,7 +1766,7 @@ static inline void check_cp1_enabled(DisasContext *ctx) static inline void check_cop1x(DisasContext *ctx) { if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } /* Verify that the processor is running with 64-bit floating-point @@ -1762,7 +1775,7 @@ static inline void check_cop1x(DisasContext *ctx) static inline void check_cp1_64bitmode(DisasContext *ctx) { if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } /* @@ -1779,7 +1792,7 @@ static inline void check_cp1_64bitmode(DisasContext *ctx) static inline void check_cp1_registers(DisasContext *ctx, int regs) { if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } /* Verify that the processor is running with DSP instructions enabled. @@ -1790,9 +1803,9 @@ static inline void check_dsp(DisasContext *ctx) { if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) { if (ctx->insn_flags & ASE_DSP) { - generate_exception(ctx, EXCP_DSPDIS); + generate_exception_end(ctx, EXCP_DSPDIS); } else { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } } } @@ -1801,9 +1814,9 @@ static inline void check_dspr2(DisasContext *ctx) { if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) { if (ctx->insn_flags & ASE_DSP) { - generate_exception(ctx, EXCP_DSPDIS); + generate_exception_end(ctx, EXCP_DSPDIS); } else { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } } } @@ -1813,7 +1826,7 @@ static inline void check_dspr2(DisasContext *ctx) static inline void check_insn(DisasContext *ctx, int flags) { if (unlikely(!(ctx->insn_flags & flags))) { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } } @@ -1823,7 +1836,7 @@ static inline void check_insn(DisasContext *ctx, int flags) static inline void check_insn_opc_removed(DisasContext *ctx, int flags) { if (unlikely(ctx->insn_flags & flags)) { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } } @@ -1843,7 +1856,7 @@ static inline void check_ps(DisasContext *ctx) static inline void check_mips_64(DisasContext *ctx) { if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } #endif @@ -2052,7 +2065,7 @@ static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \ tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \ tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \ - gen_helper_0e0i(raise_exception, EXCP_SC); \ + generate_exception_end(ctx, EXCP_SC); \ gen_set_label(l2); \ tcg_gen_movi_tl(t0, 0); \ gen_store_gpr(t0, rt); \ @@ -2105,14 +2118,12 @@ static target_ulong pc_relative_pc (DisasContext *ctx) static void gen_ld(DisasContext *ctx, uint32_t opc, int rt, int base, int16_t offset) { - const char *opn = "ld"; TCGv t0, t1, t2; if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) { /* Loongson CPU uses a load to zero register for prefetch. We emulate it as a NOP. On other CPU we must perform the actual memory access. */ - MIPS_DEBUG("NOP"); return; } @@ -2125,20 +2136,16 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL | ctx->default_tcg_memop_mask); gen_store_gpr(t0, rt); - opn = "lwu"; break; case OPC_LD: tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | ctx->default_tcg_memop_mask); gen_store_gpr(t0, rt); - opn = "ld"; break; case OPC_LLD: case R6_OPC_LLD: - save_cpu_state(ctx, 1); op_ld_lld(t0, t0, ctx); gen_store_gpr(t0, rt); - opn = "lld"; break; case OPC_LDL: t1 = tcg_temp_new(); @@ -2153,16 +2160,14 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, tcg_gen_andi_tl(t0, t0, ~7); tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ); tcg_gen_shl_tl(t0, t0, t1); - tcg_gen_xori_tl(t1, t1, 63); - t2 = tcg_const_tl(0x7fffffffffffffffull); - tcg_gen_shr_tl(t2, t2, t1); + t2 = tcg_const_tl(-1); + tcg_gen_shl_tl(t2, t2, t1); gen_load_gpr(t1, rt); - tcg_gen_and_tl(t1, t1, t2); + tcg_gen_andc_tl(t1, t1, t2); tcg_temp_free(t2); tcg_gen_or_tl(t0, t0, t1); tcg_temp_free(t1); gen_store_gpr(t0, rt); - opn = "ldl"; break; case OPC_LDR: t1 = tcg_temp_new(); @@ -2186,7 +2191,6 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, tcg_gen_or_tl(t0, t0, t1); tcg_temp_free(t1); gen_store_gpr(t0, rt); - opn = "ldr"; break; case OPC_LDPC: t1 = tcg_const_tl(pc_relative_pc(ctx)); @@ -2194,7 +2198,6 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, tcg_temp_free(t1); tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ); gen_store_gpr(t0, rt); - opn = "ldpc"; break; #endif case OPC_LWPC: @@ -2203,35 +2206,29 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, tcg_temp_free(t1); tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL); gen_store_gpr(t0, rt); - opn = "lwpc"; break; case OPC_LW: tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL | ctx->default_tcg_memop_mask); gen_store_gpr(t0, rt); - opn = "lw"; break; case OPC_LH: tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW | ctx->default_tcg_memop_mask); gen_store_gpr(t0, rt); - opn = "lh"; break; case OPC_LHU: tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW | ctx->default_tcg_memop_mask); gen_store_gpr(t0, rt); - opn = "lhu"; break; case OPC_LB: tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB); gen_store_gpr(t0, rt); - opn = "lb"; break; case OPC_LBU: tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB); gen_store_gpr(t0, rt); - opn = "lbu"; break; case OPC_LWL: t1 = tcg_temp_new(); @@ -2246,17 +2243,15 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, tcg_gen_andi_tl(t0, t0, ~3); tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL); tcg_gen_shl_tl(t0, t0, t1); - tcg_gen_xori_tl(t1, t1, 31); - t2 = tcg_const_tl(0x7fffffffull); - tcg_gen_shr_tl(t2, t2, t1); + t2 = tcg_const_tl(-1); + tcg_gen_shl_tl(t2, t2, t1); gen_load_gpr(t1, rt); - tcg_gen_and_tl(t1, t1, t2); + tcg_gen_andc_tl(t1, t1, t2); tcg_temp_free(t2); tcg_gen_or_tl(t0, t0, t1); tcg_temp_free(t1); tcg_gen_ext32s_tl(t0, t0); gen_store_gpr(t0, rt); - opn = "lwl"; break; case OPC_LWR: t1 = tcg_temp_new(); @@ -2281,18 +2276,13 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, tcg_temp_free(t1); tcg_gen_ext32s_tl(t0, t0); gen_store_gpr(t0, rt); - opn = "lwr"; break; case OPC_LL: case R6_OPC_LL: - save_cpu_state(ctx, 1); op_ld_ll(t0, t0, ctx); gen_store_gpr(t0, rt); - opn = "ll"; break; } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]); tcg_temp_free(t0); } @@ -2300,7 +2290,6 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, static void gen_st (DisasContext *ctx, uint32_t opc, int rt, int base, int16_t offset) { - const char *opn = "st"; TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); @@ -2311,46 +2300,32 @@ static void gen_st (DisasContext *ctx, uint32_t opc, int rt, case OPC_SD: tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | ctx->default_tcg_memop_mask); - opn = "sd"; break; case OPC_SDL: - save_cpu_state(ctx, 1); gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx); - opn = "sdl"; break; case OPC_SDR: - save_cpu_state(ctx, 1); gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx); - opn = "sdr"; break; #endif case OPC_SW: tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL | ctx->default_tcg_memop_mask); - opn = "sw"; break; case OPC_SH: tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW | ctx->default_tcg_memop_mask); - opn = "sh"; break; case OPC_SB: tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8); - opn = "sb"; break; case OPC_SWL: - save_cpu_state(ctx, 1); gen_helper_0e2i(swl, t1, t0, ctx->mem_idx); - opn = "swl"; break; case OPC_SWR: - save_cpu_state(ctx, 1); gen_helper_0e2i(swr, t1, t0, ctx->mem_idx); - opn = "swr"; break; } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]); tcg_temp_free(t0); tcg_temp_free(t1); } @@ -2360,7 +2335,6 @@ static void gen_st (DisasContext *ctx, uint32_t opc, int rt, static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt, int base, int16_t offset) { - const char *opn = "st_cond"; TCGv t0, t1; #ifdef CONFIG_USER_ONLY @@ -2376,20 +2350,14 @@ static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt, #if defined(TARGET_MIPS64) case OPC_SCD: case R6_OPC_SCD: - save_cpu_state(ctx, 1); op_st_scd(t1, t0, rt, ctx); - opn = "scd"; break; #endif case OPC_SC: case R6_OPC_SC: - save_cpu_state(ctx, 1); op_st_sc(t1, t0, rt, ctx); - opn = "sc"; break; } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]); tcg_temp_free(t1); tcg_temp_free(t0); } @@ -2398,7 +2366,6 @@ static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt, static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, int base, int16_t offset) { - const char *opn = "flt_ldst"; TCGv t0 = tcg_temp_new(); gen_base_offset_addr(ctx, t0, base, offset); @@ -2413,7 +2380,6 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, gen_store_fpr32(ctx, fp0, ft); tcg_temp_free_i32(fp0); } - opn = "lwc1"; break; case OPC_SWC1: { @@ -2423,7 +2389,6 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, ctx->default_tcg_memop_mask); tcg_temp_free_i32(fp0); } - opn = "swc1"; break; case OPC_LDC1: { @@ -2433,7 +2398,6 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, gen_store_fpr64(ctx, fp0, ft); tcg_temp_free_i64(fp0); } - opn = "ldc1"; break; case OPC_SDC1: { @@ -2443,15 +2407,12 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, ctx->default_tcg_memop_mask); tcg_temp_free_i64(fp0); } - opn = "sdc1"; break; default: - MIPS_INVAL(opn); - generate_exception(ctx, EXCP_RI); + MIPS_INVAL("flt_ldst"); + generate_exception_end(ctx, EXCP_RI); goto out; } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]); out: tcg_temp_free(t0); } @@ -2479,12 +2440,10 @@ static void gen_arith_imm(DisasContext *ctx, uint32_t opc, int rt, int rs, int16_t imm) { target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */ - const char *opn = "imm arith"; if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) { /* If no destination, treat it as a NOP. For addi, we must generate the overflow exception when needed. */ - MIPS_DEBUG("NOP"); return; } switch (opc) { @@ -2512,7 +2471,6 @@ static void gen_arith_imm(DisasContext *ctx, uint32_t opc, gen_store_gpr(t0, rt); tcg_temp_free(t0); } - opn = "addi"; break; case OPC_ADDIU: if (rs != 0) { @@ -2521,7 +2479,6 @@ static void gen_arith_imm(DisasContext *ctx, uint32_t opc, } else { tcg_gen_movi_tl(cpu_gpr[rt], uimm); } - opn = "addiu"; break; #if defined(TARGET_MIPS64) case OPC_DADDI: @@ -2546,7 +2503,6 @@ static void gen_arith_imm(DisasContext *ctx, uint32_t opc, gen_store_gpr(t0, rt); tcg_temp_free(t0); } - opn = "daddi"; break; case OPC_DADDIU: if (rs != 0) { @@ -2554,12 +2510,9 @@ static void gen_arith_imm(DisasContext *ctx, uint32_t opc, } else { tcg_gen_movi_tl(cpu_gpr[rt], uimm); } - opn = "daddiu"; break; #endif } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm); } /* Logic with immediate operand */ @@ -2570,7 +2523,6 @@ static void gen_logic_imm(DisasContext *ctx, uint32_t opc, if (rt == 0) { /* If no destination, treat it as a NOP. */ - MIPS_DEBUG("NOP"); return; } uimm = (uint16_t)imm; @@ -2580,39 +2532,30 @@ static void gen_logic_imm(DisasContext *ctx, uint32_t opc, tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm); else tcg_gen_movi_tl(cpu_gpr[rt], 0); - MIPS_DEBUG("andi %s, %s, " TARGET_FMT_lx, regnames[rt], - regnames[rs], uimm); break; case OPC_ORI: if (rs != 0) tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm); else tcg_gen_movi_tl(cpu_gpr[rt], uimm); - MIPS_DEBUG("ori %s, %s, " TARGET_FMT_lx, regnames[rt], - regnames[rs], uimm); break; case OPC_XORI: if (likely(rs != 0)) tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm); else tcg_gen_movi_tl(cpu_gpr[rt], uimm); - MIPS_DEBUG("xori %s, %s, " TARGET_FMT_lx, regnames[rt], - regnames[rs], uimm); break; case OPC_LUI: if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) { /* OPC_AUI */ tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16); tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); - MIPS_DEBUG("aui %s, %s, %04x", regnames[rt], regnames[rs], imm); } else { tcg_gen_movi_tl(cpu_gpr[rt], imm << 16); - MIPS_DEBUG("lui %s, " TARGET_FMT_lx, regnames[rt], uimm); } break; default: - MIPS_DEBUG("Unknown logical immediate opcode %08x", opc); break; } } @@ -2622,12 +2565,10 @@ static void gen_slt_imm(DisasContext *ctx, uint32_t opc, int rt, int rs, int16_t imm) { target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */ - const char *opn = "imm arith"; TCGv t0; if (rt == 0) { /* If no destination, treat it as a NOP. */ - MIPS_DEBUG("NOP"); return; } t0 = tcg_temp_new(); @@ -2635,15 +2576,11 @@ static void gen_slt_imm(DisasContext *ctx, uint32_t opc, switch (opc) { case OPC_SLTI: tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm); - opn = "slti"; break; case OPC_SLTIU: tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm); - opn = "sltiu"; break; } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm); tcg_temp_free(t0); } @@ -2652,12 +2589,10 @@ static void gen_shift_imm(DisasContext *ctx, uint32_t opc, int rt, int rs, int16_t imm) { target_ulong uimm = ((uint16_t)imm) & 0x1f; - const char *opn = "imm shift"; TCGv t0; if (rt == 0) { /* If no destination, treat it as a NOP. */ - MIPS_DEBUG("NOP"); return; } @@ -2667,11 +2602,9 @@ static void gen_shift_imm(DisasContext *ctx, uint32_t opc, case OPC_SLL: tcg_gen_shli_tl(t0, t0, uimm); tcg_gen_ext32s_tl(cpu_gpr[rt], t0); - opn = "sll"; break; case OPC_SRA: tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm); - opn = "sra"; break; case OPC_SRL: if (uimm != 0) { @@ -2680,7 +2613,6 @@ static void gen_shift_imm(DisasContext *ctx, uint32_t opc, } else { tcg_gen_ext32s_tl(cpu_gpr[rt], t0); } - opn = "srl"; break; case OPC_ROTR: if (uimm != 0) { @@ -2693,20 +2625,16 @@ static void gen_shift_imm(DisasContext *ctx, uint32_t opc, } else { tcg_gen_ext32s_tl(cpu_gpr[rt], t0); } - opn = "rotr"; break; #if defined(TARGET_MIPS64) case OPC_DSLL: tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm); - opn = "dsll"; break; case OPC_DSRA: tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm); - opn = "dsra"; break; case OPC_DSRL: tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm); - opn = "dsrl"; break; case OPC_DROTR: if (uimm != 0) { @@ -2714,28 +2642,21 @@ static void gen_shift_imm(DisasContext *ctx, uint32_t opc, } else { tcg_gen_mov_tl(cpu_gpr[rt], t0); } - opn = "drotr"; break; case OPC_DSLL32: tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32); - opn = "dsll32"; break; case OPC_DSRA32: tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32); - opn = "dsra32"; break; case OPC_DSRL32: tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32); - opn = "dsrl32"; break; case OPC_DROTR32: tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32); - opn = "drotr32"; break; #endif } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm); tcg_temp_free(t0); } @@ -2743,13 +2664,10 @@ static void gen_shift_imm(DisasContext *ctx, uint32_t opc, static void gen_arith(DisasContext *ctx, uint32_t opc, int rd, int rs, int rt) { - const char *opn = "arith"; - if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB && opc != OPC_DADD && opc != OPC_DSUB) { /* If no destination, treat it as a NOP. For add & sub, we must generate the overflow exception when needed. */ - MIPS_DEBUG("NOP"); return; } @@ -2777,7 +2695,6 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, gen_store_gpr(t0, rd); tcg_temp_free(t0); } - opn = "add"; break; case OPC_ADDU: if (rs != 0 && rt != 0) { @@ -2790,7 +2707,6 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, } else { tcg_gen_movi_tl(cpu_gpr[rd], 0); } - opn = "addu"; break; case OPC_SUB: { @@ -2815,7 +2731,6 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, gen_store_gpr(t0, rd); tcg_temp_free(t0); } - opn = "sub"; break; case OPC_SUBU: if (rs != 0 && rt != 0) { @@ -2829,7 +2744,6 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, } else { tcg_gen_movi_tl(cpu_gpr[rd], 0); } - opn = "subu"; break; #if defined(TARGET_MIPS64) case OPC_DADD: @@ -2854,7 +2768,6 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, gen_store_gpr(t0, rd); tcg_temp_free(t0); } - opn = "dadd"; break; case OPC_DADDU: if (rs != 0 && rt != 0) { @@ -2866,7 +2779,6 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, } else { tcg_gen_movi_tl(cpu_gpr[rd], 0); } - opn = "daddu"; break; case OPC_DSUB: { @@ -2890,7 +2802,6 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, gen_store_gpr(t0, rd); tcg_temp_free(t0); } - opn = "dsub"; break; case OPC_DSUBU: if (rs != 0 && rt != 0) { @@ -2902,7 +2813,6 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, } else { tcg_gen_movi_tl(cpu_gpr[rd], 0); } - opn = "dsubu"; break; #endif case OPC_MUL: @@ -2912,23 +2822,18 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, } else { tcg_gen_movi_tl(cpu_gpr[rd], 0); } - opn = "mul"; break; } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]); } /* Conditional move */ static void gen_cond_move(DisasContext *ctx, uint32_t opc, int rd, int rs, int rt) { - const char *opn = "cond move"; TCGv t0, t1, t2; if (rd == 0) { /* If no destination, treat it as a NOP. */ - MIPS_DEBUG("NOP"); return; } @@ -2940,38 +2845,28 @@ static void gen_cond_move(DisasContext *ctx, uint32_t opc, switch (opc) { case OPC_MOVN: tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]); - opn = "movn"; break; case OPC_MOVZ: tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]); - opn = "movz"; break; case OPC_SELNEZ: tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1); - opn = "selnez"; break; case OPC_SELEQZ: tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1); - opn = "seleqz"; break; } tcg_temp_free(t2); tcg_temp_free(t1); tcg_temp_free(t0); - - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]); } /* Logic */ static void gen_logic(DisasContext *ctx, uint32_t opc, int rd, int rs, int rt) { - const char *opn = "logic"; - if (rd == 0) { /* If no destination, treat it as a NOP. */ - MIPS_DEBUG("NOP"); return; } @@ -2982,7 +2877,6 @@ static void gen_logic(DisasContext *ctx, uint32_t opc, } else { tcg_gen_movi_tl(cpu_gpr[rd], 0); } - opn = "and"; break; case OPC_NOR: if (rs != 0 && rt != 0) { @@ -2994,7 +2888,6 @@ static void gen_logic(DisasContext *ctx, uint32_t opc, } else { tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0)); } - opn = "nor"; break; case OPC_OR: if (likely(rs != 0 && rt != 0)) { @@ -3006,7 +2899,6 @@ static void gen_logic(DisasContext *ctx, uint32_t opc, } else { tcg_gen_movi_tl(cpu_gpr[rd], 0); } - opn = "or"; break; case OPC_XOR: if (likely(rs != 0 && rt != 0)) { @@ -3018,23 +2910,18 @@ static void gen_logic(DisasContext *ctx, uint32_t opc, } else { tcg_gen_movi_tl(cpu_gpr[rd], 0); } - opn = "xor"; break; } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]); } /* Set on lower than */ static void gen_slt(DisasContext *ctx, uint32_t opc, int rd, int rs, int rt) { - const char *opn = "slt"; TCGv t0, t1; if (rd == 0) { /* If no destination, treat it as a NOP. */ - MIPS_DEBUG("NOP"); return; } @@ -3045,15 +2932,11 @@ static void gen_slt(DisasContext *ctx, uint32_t opc, switch (opc) { case OPC_SLT: tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1); - opn = "slt"; break; case OPC_SLTU: tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1); - opn = "sltu"; break; } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]); tcg_temp_free(t0); tcg_temp_free(t1); } @@ -3062,13 +2945,11 @@ static void gen_slt(DisasContext *ctx, uint32_t opc, static void gen_shift(DisasContext *ctx, uint32_t opc, int rd, int rs, int rt) { - const char *opn = "shifts"; TCGv t0, t1; if (rd == 0) { /* If no destination, treat it as a NOP. For add & sub, we must generate the overflow exception when needed. */ - MIPS_DEBUG("NOP"); return; } @@ -3081,19 +2962,16 @@ static void gen_shift(DisasContext *ctx, uint32_t opc, tcg_gen_andi_tl(t0, t0, 0x1f); tcg_gen_shl_tl(t0, t1, t0); tcg_gen_ext32s_tl(cpu_gpr[rd], t0); - opn = "sllv"; break; case OPC_SRAV: tcg_gen_andi_tl(t0, t0, 0x1f); tcg_gen_sar_tl(cpu_gpr[rd], t1, t0); - opn = "srav"; break; case OPC_SRLV: tcg_gen_ext32u_tl(t1, t1); tcg_gen_andi_tl(t0, t0, 0x1f); tcg_gen_shr_tl(t0, t1, t0); tcg_gen_ext32s_tl(cpu_gpr[rd], t0); - opn = "srlv"; break; case OPC_ROTRV: { @@ -3107,34 +2985,27 @@ static void gen_shift(DisasContext *ctx, uint32_t opc, tcg_gen_ext_i32_tl(cpu_gpr[rd], t2); tcg_temp_free_i32(t2); tcg_temp_free_i32(t3); - opn = "rotrv"; } break; #if defined(TARGET_MIPS64) case OPC_DSLLV: tcg_gen_andi_tl(t0, t0, 0x3f); tcg_gen_shl_tl(cpu_gpr[rd], t1, t0); - opn = "dsllv"; break; case OPC_DSRAV: tcg_gen_andi_tl(t0, t0, 0x3f); tcg_gen_sar_tl(cpu_gpr[rd], t1, t0); - opn = "dsrav"; break; case OPC_DSRLV: tcg_gen_andi_tl(t0, t0, 0x3f); tcg_gen_shr_tl(cpu_gpr[rd], t1, t0); - opn = "dsrlv"; break; case OPC_DROTRV: tcg_gen_andi_tl(t0, t0, 0x3f); tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0); - opn = "drotrv"; break; #endif } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]); tcg_temp_free(t0); tcg_temp_free(t1); } @@ -3142,11 +3013,8 @@ static void gen_shift(DisasContext *ctx, uint32_t opc, /* Arithmetic on HI/LO registers */ static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg) { - const char *opn = "hilo"; - if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) { /* Treat as NOP. */ - MIPS_DEBUG("NOP"); return; } @@ -3164,7 +3032,6 @@ static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg) { tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]); } - opn = "mfhi"; break; case OPC_MFLO: #if defined(TARGET_MIPS64) @@ -3175,7 +3042,6 @@ static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg) { tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]); } - opn = "mflo"; break; case OPC_MTHI: if (reg != 0) { @@ -3190,7 +3056,6 @@ static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg) } else { tcg_gen_movi_tl(cpu_HI[acc], 0); } - opn = "mthi"; break; case OPC_MTLO: if (reg != 0) { @@ -3205,11 +3070,8 @@ static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg) } else { tcg_gen_movi_tl(cpu_LO[acc], 0); } - opn = "mtlo"; break; } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s", opn, regnames[reg]); } static inline void gen_r6_ld(target_long addr, int reg, int memidx, @@ -3277,7 +3139,7 @@ static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc, #endif default: MIPS_INVAL("OPC_PCREL"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -3286,12 +3148,10 @@ static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc, static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) { - const char *opn = "r6 mul/div"; TCGv t0, t1; if (rd == 0) { /* Treat as NOP. */ - MIPS_DEBUG("NOP"); return; } @@ -3320,7 +3180,6 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) tcg_temp_free(t3); tcg_temp_free(t2); } - opn = "div"; break; case R6_OPC_MOD: { @@ -3340,7 +3199,6 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) tcg_temp_free(t3); tcg_temp_free(t2); } - opn = "mod"; break; case R6_OPC_DIVU: { @@ -3354,7 +3212,6 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) tcg_temp_free(t3); tcg_temp_free(t2); } - opn = "divu"; break; case R6_OPC_MODU: { @@ -3368,7 +3225,6 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) tcg_temp_free(t3); tcg_temp_free(t2); } - opn = "modu"; break; case R6_OPC_MUL: { @@ -3381,7 +3237,6 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) tcg_temp_free_i32(t2); tcg_temp_free_i32(t3); } - opn = "mul"; break; case R6_OPC_MUH: { @@ -3394,7 +3249,6 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) tcg_temp_free_i32(t2); tcg_temp_free_i32(t3); } - opn = "muh"; break; case R6_OPC_MULU: { @@ -3407,7 +3261,6 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) tcg_temp_free_i32(t2); tcg_temp_free_i32(t3); } - opn = "mulu"; break; case R6_OPC_MUHU: { @@ -3420,7 +3273,6 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) tcg_temp_free_i32(t2); tcg_temp_free_i32(t3); } - opn = "muhu"; break; #if defined(TARGET_MIPS64) case R6_OPC_DDIV: @@ -3438,7 +3290,6 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) tcg_temp_free(t3); tcg_temp_free(t2); } - opn = "ddiv"; break; case R6_OPC_DMOD: { @@ -3455,7 +3306,6 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) tcg_temp_free(t3); tcg_temp_free(t2); } - opn = "dmod"; break; case R6_OPC_DDIVU: { @@ -3466,7 +3316,6 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) tcg_temp_free(t3); tcg_temp_free(t2); } - opn = "ddivu"; break; case R6_OPC_DMODU: { @@ -3477,11 +3326,9 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) tcg_temp_free(t3); tcg_temp_free(t2); } - opn = "dmodu"; break; case R6_OPC_DMUL: tcg_gen_mul_i64(cpu_gpr[rd], t0, t1); - opn = "dmul"; break; case R6_OPC_DMUH: { @@ -3489,11 +3336,9 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1); tcg_temp_free(t2); } - opn = "dmuh"; break; case R6_OPC_DMULU: tcg_gen_mul_i64(cpu_gpr[rd], t0, t1); - opn = "dmulu"; break; case R6_OPC_DMUHU: { @@ -3501,16 +3346,13 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1); tcg_temp_free(t2); } - opn = "dmuhu"; break; #endif default: - MIPS_INVAL(opn); - generate_exception(ctx, EXCP_RI); + MIPS_INVAL("r6 mul/div"); + generate_exception_end(ctx, EXCP_RI); goto out; } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]); out: tcg_temp_free(t0); tcg_temp_free(t1); @@ -3519,7 +3361,6 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) static void gen_muldiv(DisasContext *ctx, uint32_t opc, int acc, int rs, int rt) { - const char *opn = "mul/div"; TCGv t0, t1; t0 = tcg_temp_new(); @@ -3553,7 +3394,6 @@ static void gen_muldiv(DisasContext *ctx, uint32_t opc, tcg_temp_free(t3); tcg_temp_free(t2); } - opn = "div"; break; case OPC_DIVU: { @@ -3569,7 +3409,6 @@ static void gen_muldiv(DisasContext *ctx, uint32_t opc, tcg_temp_free(t3); tcg_temp_free(t2); } - opn = "divu"; break; case OPC_MULT: { @@ -3583,7 +3422,6 @@ static void gen_muldiv(DisasContext *ctx, uint32_t opc, tcg_temp_free_i32(t2); tcg_temp_free_i32(t3); } - opn = "mult"; break; case OPC_MULTU: { @@ -3597,7 +3435,6 @@ static void gen_muldiv(DisasContext *ctx, uint32_t opc, tcg_temp_free_i32(t2); tcg_temp_free_i32(t3); } - opn = "multu"; break; #if defined(TARGET_MIPS64) case OPC_DDIV: @@ -3616,7 +3453,6 @@ static void gen_muldiv(DisasContext *ctx, uint32_t opc, tcg_temp_free(t3); tcg_temp_free(t2); } - opn = "ddiv"; break; case OPC_DDIVU: { @@ -3628,15 +3464,12 @@ static void gen_muldiv(DisasContext *ctx, uint32_t opc, tcg_temp_free(t3); tcg_temp_free(t2); } - opn = "ddivu"; break; case OPC_DMULT: tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1); - opn = "dmult"; break; case OPC_DMULTU: tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1); - opn = "dmultu"; break; #endif case OPC_MADD: @@ -3650,14 +3483,10 @@ static void gen_muldiv(DisasContext *ctx, uint32_t opc, tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); tcg_gen_add_i64(t2, t2, t3); tcg_temp_free_i64(t3); - tcg_gen_trunc_i64_tl(t0, t2); - tcg_gen_shri_i64(t2, t2, 32); - tcg_gen_trunc_i64_tl(t1, t2); + gen_move_low32(cpu_LO[acc], t2); + gen_move_high32(cpu_HI[acc], t2); tcg_temp_free_i64(t2); - tcg_gen_ext32s_tl(cpu_LO[acc], t0); - tcg_gen_ext32s_tl(cpu_HI[acc], t1); } - opn = "madd"; break; case OPC_MADDU: { @@ -3672,14 +3501,10 @@ static void gen_muldiv(DisasContext *ctx, uint32_t opc, tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); tcg_gen_add_i64(t2, t2, t3); tcg_temp_free_i64(t3); - tcg_gen_trunc_i64_tl(t0, t2); - tcg_gen_shri_i64(t2, t2, 32); - tcg_gen_trunc_i64_tl(t1, t2); + gen_move_low32(cpu_LO[acc], t2); + gen_move_high32(cpu_HI[acc], t2); tcg_temp_free_i64(t2); - tcg_gen_ext32s_tl(cpu_LO[acc], t0); - tcg_gen_ext32s_tl(cpu_HI[acc], t1); } - opn = "maddu"; break; case OPC_MSUB: { @@ -3692,14 +3517,10 @@ static void gen_muldiv(DisasContext *ctx, uint32_t opc, tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); tcg_gen_sub_i64(t2, t3, t2); tcg_temp_free_i64(t3); - tcg_gen_trunc_i64_tl(t0, t2); - tcg_gen_shri_i64(t2, t2, 32); - tcg_gen_trunc_i64_tl(t1, t2); + gen_move_low32(cpu_LO[acc], t2); + gen_move_high32(cpu_HI[acc], t2); tcg_temp_free_i64(t2); - tcg_gen_ext32s_tl(cpu_LO[acc], t0); - tcg_gen_ext32s_tl(cpu_HI[acc], t1); } - opn = "msub"; break; case OPC_MSUBU: { @@ -3714,22 +3535,16 @@ static void gen_muldiv(DisasContext *ctx, uint32_t opc, tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); tcg_gen_sub_i64(t2, t3, t2); tcg_temp_free_i64(t3); - tcg_gen_trunc_i64_tl(t0, t2); - tcg_gen_shri_i64(t2, t2, 32); - tcg_gen_trunc_i64_tl(t1, t2); + gen_move_low32(cpu_LO[acc], t2); + gen_move_high32(cpu_HI[acc], t2); tcg_temp_free_i64(t2); - tcg_gen_ext32s_tl(cpu_LO[acc], t0); - tcg_gen_ext32s_tl(cpu_HI[acc], t1); } - opn = "msubu"; break; default: - MIPS_INVAL(opn); - generate_exception(ctx, EXCP_RI); + MIPS_INVAL("mul/div"); + generate_exception_end(ctx, EXCP_RI); goto out; } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]); out: tcg_temp_free(t0); tcg_temp_free(t1); @@ -3738,7 +3553,6 @@ static void gen_muldiv(DisasContext *ctx, uint32_t opc, static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc, int rd, int rs, int rt) { - const char *opn = "mul vr54xx"; TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); @@ -3748,68 +3562,52 @@ static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc, switch (opc) { case OPC_VR54XX_MULS: gen_helper_muls(t0, cpu_env, t0, t1); - opn = "muls"; break; case OPC_VR54XX_MULSU: gen_helper_mulsu(t0, cpu_env, t0, t1); - opn = "mulsu"; break; case OPC_VR54XX_MACC: gen_helper_macc(t0, cpu_env, t0, t1); - opn = "macc"; break; case OPC_VR54XX_MACCU: gen_helper_maccu(t0, cpu_env, t0, t1); - opn = "maccu"; break; case OPC_VR54XX_MSAC: gen_helper_msac(t0, cpu_env, t0, t1); - opn = "msac"; break; case OPC_VR54XX_MSACU: gen_helper_msacu(t0, cpu_env, t0, t1); - opn = "msacu"; break; case OPC_VR54XX_MULHI: gen_helper_mulhi(t0, cpu_env, t0, t1); - opn = "mulhi"; break; case OPC_VR54XX_MULHIU: gen_helper_mulhiu(t0, cpu_env, t0, t1); - opn = "mulhiu"; break; case OPC_VR54XX_MULSHI: gen_helper_mulshi(t0, cpu_env, t0, t1); - opn = "mulshi"; break; case OPC_VR54XX_MULSHIU: gen_helper_mulshiu(t0, cpu_env, t0, t1); - opn = "mulshiu"; break; case OPC_VR54XX_MACCHI: gen_helper_macchi(t0, cpu_env, t0, t1); - opn = "macchi"; break; case OPC_VR54XX_MACCHIU: gen_helper_macchiu(t0, cpu_env, t0, t1); - opn = "macchiu"; break; case OPC_VR54XX_MSACHI: gen_helper_msachi(t0, cpu_env, t0, t1); - opn = "msachi"; break; case OPC_VR54XX_MSACHIU: gen_helper_msachiu(t0, cpu_env, t0, t1); - opn = "msachiu"; break; default: MIPS_INVAL("mul vr54xx"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); goto out; } gen_store_gpr(t0, rd); - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]); out: tcg_temp_free(t0); @@ -3819,12 +3617,10 @@ static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc, static void gen_cl (DisasContext *ctx, uint32_t opc, int rd, int rs) { - const char *opn = "CLx"; TCGv t0; if (rd == 0) { /* Treat as NOP. */ - MIPS_DEBUG("NOP"); return; } t0 = tcg_temp_new(); @@ -3833,28 +3629,22 @@ static void gen_cl (DisasContext *ctx, uint32_t opc, case OPC_CLO: case R6_OPC_CLO: gen_helper_clo(cpu_gpr[rd], t0); - opn = "clo"; break; case OPC_CLZ: case R6_OPC_CLZ: gen_helper_clz(cpu_gpr[rd], t0); - opn = "clz"; break; #if defined(TARGET_MIPS64) case OPC_DCLO: case R6_OPC_DCLO: gen_helper_dclo(cpu_gpr[rd], t0); - opn = "dclo"; break; case OPC_DCLZ: case R6_OPC_DCLZ: gen_helper_dclz(cpu_gpr[rd], t0); - opn = "dclz"; break; #endif } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]); tcg_temp_free(t0); } @@ -3862,12 +3652,10 @@ static void gen_cl (DisasContext *ctx, uint32_t opc, static void gen_loongson_integer(DisasContext *ctx, uint32_t opc, int rd, int rs, int rt) { - const char *opn = "loongson"; TCGv t0, t1; if (rd == 0) { /* Treat as NOP. */ - MIPS_DEBUG("NOP"); return; } @@ -3899,7 +3687,6 @@ static void gen_loongson_integer(DisasContext *ctx, uint32_t opc, case OPC_MULT_G_2F: tcg_gen_mul_tl(cpu_gpr[rd], t0, t1); tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); - opn = "mult.g"; break; case OPC_MULTU_G_2E: case OPC_MULTU_G_2F: @@ -3907,7 +3694,6 @@ static void gen_loongson_integer(DisasContext *ctx, uint32_t opc, tcg_gen_ext32u_tl(t1, t1); tcg_gen_mul_tl(cpu_gpr[rd], t0, t1); tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); - opn = "multu.g"; break; case OPC_DIV_G_2E: case OPC_DIV_G_2F: @@ -3930,7 +3716,6 @@ static void gen_loongson_integer(DisasContext *ctx, uint32_t opc, tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); gen_set_label(l3); } - opn = "div.g"; break; case OPC_DIVU_G_2E: case OPC_DIVU_G_2F: @@ -3947,7 +3732,6 @@ static void gen_loongson_integer(DisasContext *ctx, uint32_t opc, tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); gen_set_label(l2); } - opn = "divu.g"; break; case OPC_MOD_G_2E: case OPC_MOD_G_2F: @@ -3968,7 +3752,6 @@ static void gen_loongson_integer(DisasContext *ctx, uint32_t opc, tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); gen_set_label(l3); } - opn = "mod.g"; break; case OPC_MODU_G_2E: case OPC_MODU_G_2F: @@ -3985,18 +3768,15 @@ static void gen_loongson_integer(DisasContext *ctx, uint32_t opc, tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); gen_set_label(l2); } - opn = "modu.g"; break; #if defined(TARGET_MIPS64) case OPC_DMULT_G_2E: case OPC_DMULT_G_2F: tcg_gen_mul_tl(cpu_gpr[rd], t0, t1); - opn = "dmult.g"; break; case OPC_DMULTU_G_2E: case OPC_DMULTU_G_2F: tcg_gen_mul_tl(cpu_gpr[rd], t0, t1); - opn = "dmultu.g"; break; case OPC_DDIV_G_2E: case OPC_DDIV_G_2F: @@ -4016,7 +3796,6 @@ static void gen_loongson_integer(DisasContext *ctx, uint32_t opc, tcg_gen_div_tl(cpu_gpr[rd], t0, t1); gen_set_label(l3); } - opn = "ddiv.g"; break; case OPC_DDIVU_G_2E: case OPC_DDIVU_G_2F: @@ -4030,7 +3809,6 @@ static void gen_loongson_integer(DisasContext *ctx, uint32_t opc, tcg_gen_divu_tl(cpu_gpr[rd], t0, t1); gen_set_label(l2); } - opn = "ddivu.g"; break; case OPC_DMOD_G_2E: case OPC_DMOD_G_2F: @@ -4048,7 +3826,6 @@ static void gen_loongson_integer(DisasContext *ctx, uint32_t opc, tcg_gen_rem_tl(cpu_gpr[rd], t0, t1); gen_set_label(l3); } - opn = "dmod.g"; break; case OPC_DMODU_G_2E: case OPC_DMODU_G_2F: @@ -4062,13 +3839,10 @@ static void gen_loongson_integer(DisasContext *ctx, uint32_t opc, tcg_gen_remu_tl(cpu_gpr[rd], t0, t1); gen_set_label(l2); } - opn = "dmodu.g"; break; #endif } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]); tcg_temp_free(t0); tcg_temp_free(t1); } @@ -4076,7 +3850,6 @@ static void gen_loongson_integer(DisasContext *ctx, uint32_t opc, /* Loongson multimedia instructions */ static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt) { - const char *opn = "loongson_cp2"; uint32_t opc, shift_max; TCGv_i64 t0, t1; @@ -4099,11 +3872,11 @@ static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt) gen_load_fpr64(ctx, t1, rt); #define LMI_HELPER(UP, LO) \ - case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break + case OPC_##UP: gen_helper_##LO(t0, t0, t1); break #define LMI_HELPER_1(UP, LO) \ - case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break + case OPC_##UP: gen_helper_##LO(t0, t0); break #define LMI_DIRECT(UP, LO, OP) \ - case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break + case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break switch (opc) { LMI_HELPER(PADDSH, paddsh); @@ -4174,19 +3947,15 @@ static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt) case OPC_PINSRH_0: tcg_gen_deposit_i64(t0, t0, t1, 0, 16); - opn = "pinsrh_0"; break; case OPC_PINSRH_1: tcg_gen_deposit_i64(t0, t0, t1, 16, 16); - opn = "pinsrh_1"; break; case OPC_PINSRH_2: tcg_gen_deposit_i64(t0, t0, t1, 32, 16); - opn = "pinsrh_2"; break; case OPC_PINSRH_3: tcg_gen_deposit_i64(t0, t0, t1, 48, 16); - opn = "pinsrh_3"; break; case OPC_PEXTRH: @@ -4194,42 +3963,33 @@ static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt) tcg_gen_shli_i64(t1, t1, 4); tcg_gen_shr_i64(t0, t0, t1); tcg_gen_ext16u_i64(t0, t0); - opn = "pextrh"; break; case OPC_ADDU_CP2: tcg_gen_add_i64(t0, t0, t1); tcg_gen_ext32s_i64(t0, t0); - opn = "addu"; break; case OPC_SUBU_CP2: tcg_gen_sub_i64(t0, t0, t1); tcg_gen_ext32s_i64(t0, t0); - opn = "addu"; break; case OPC_SLL_CP2: - opn = "sll"; shift_max = 32; goto do_shift; case OPC_SRL_CP2: - opn = "srl"; shift_max = 32; goto do_shift; case OPC_SRA_CP2: - opn = "sra"; shift_max = 32; goto do_shift; case OPC_DSLL_CP2: - opn = "dsll"; shift_max = 64; goto do_shift; case OPC_DSRL_CP2: - opn = "dsrl"; shift_max = 64; goto do_shift; case OPC_DSRA_CP2: - opn = "dsra"; shift_max = 64; goto do_shift; do_shift: @@ -4284,8 +4044,6 @@ static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt) tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab); generate_exception(ctx, EXCP_OVERFLOW); gen_set_label(lab); - - opn = (opc == OPC_ADD_CP2 ? "add" : "dadd"); break; } @@ -4307,8 +4065,6 @@ static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt) tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab); generate_exception(ctx, EXCP_OVERFLOW); gen_set_label(lab); - - opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub"); break; } @@ -4316,7 +4072,6 @@ static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt) tcg_gen_ext32u_i64(t0, t0); tcg_gen_ext32u_i64(t1, t1); tcg_gen_mul_i64(t0, t0, t1); - opn = "pmuluw"; break; case OPC_SEQU_CP2: @@ -4328,8 +4083,8 @@ static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt) /* ??? Document is unclear: Set FCC[CC]. Does that mean the FD field is the CC field? */ default: - MIPS_INVAL(opn); - generate_exception(ctx, EXCP_RI); + MIPS_INVAL("loongson_cp2"); + generate_exception_end(ctx, EXCP_RI); return; } @@ -4338,9 +4093,6 @@ static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt) gen_store_fpr64(ctx, t0, rd); - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s, %s, %s", opn, - fregnames[rd], fregnames[rs], fregnames[rt]); tcg_temp_free_i64(t0); tcg_temp_free_i64(t1); } @@ -4392,7 +4144,7 @@ static void gen_trap (DisasContext *ctx, uint32_t opc, case OPC_TGEU: /* rs >= rs unsigned */ case OPC_TGEIU: /* r0 >= 0 unsigned */ /* Always trap */ - generate_exception(ctx, EXCP_TRAP); + generate_exception_end(ctx, EXCP_TRAP); break; case OPC_TLT: /* rs < rs */ case OPC_TLTI: /* r0 < 0 */ @@ -4452,7 +4204,7 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) gen_save_pc(dest); if (ctx->singlestep_enabled) { save_cpu_state(ctx, 0); - gen_helper_0e0i(raise_exception, EXCP_DEBUG); + gen_helper_raise_exception_debug(cpu_env); } tcg_gen_exit_tb(0); } @@ -4475,7 +4227,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc); #endif - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); goto out; } @@ -4535,14 +4287,14 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the others are reserved. */ MIPS_INVAL("jump hint"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); goto out; } gen_load_gpr(btarget, rs); break; default: MIPS_INVAL("branch/jump"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); goto out; } if (bcond_compute == 0) { @@ -4556,20 +4308,17 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, case OPC_BLEZL: /* 0 <= 0 likely */ /* Always take */ ctx->hflags |= MIPS_HFLAG_B; - MIPS_DEBUG("balways"); break; case OPC_BGEZAL: /* 0 >= 0 */ case OPC_BGEZALL: /* 0 >= 0 likely */ /* Always take and link */ blink = 31; ctx->hflags |= MIPS_HFLAG_B; - MIPS_DEBUG("balways and link"); break; case OPC_BNE: /* rx != rx */ case OPC_BGTZ: /* 0 > 0 */ case OPC_BLTZ: /* 0 < 0 */ /* Treat as NOP. */ - MIPS_DEBUG("bnever (NOP)"); goto out; case OPC_BLTZAL: /* 0 < 0 */ /* Handle as an unconditional branch to get correct delay @@ -4577,24 +4326,20 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, blink = 31; btgt = ctx->pc + insn_bytes + delayslot_size; ctx->hflags |= MIPS_HFLAG_B; - MIPS_DEBUG("bnever and link"); break; case OPC_BLTZALL: /* 0 < 0 likely */ tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8); /* Skip the instruction in the delay slot */ - MIPS_DEBUG("bnever, link and skip"); ctx->pc += 4; goto out; case OPC_BNEL: /* rx != rx likely */ case OPC_BGTZL: /* 0 > 0 likely */ case OPC_BLTZL: /* 0 < 0 likely */ /* Skip the instruction in the delay slot */ - MIPS_DEBUG("bnever and skip"); ctx->pc += 4; goto out; case OPC_J: ctx->hflags |= MIPS_HFLAG_B; - MIPS_DEBUG("j " TARGET_FMT_lx, btgt); break; case OPC_JALX: ctx->hflags |= MIPS_HFLAG_BX; @@ -4602,118 +4347,91 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, case OPC_JAL: blink = 31; ctx->hflags |= MIPS_HFLAG_B; - MIPS_DEBUG("jal " TARGET_FMT_lx, btgt); break; case OPC_JR: ctx->hflags |= MIPS_HFLAG_BR; - MIPS_DEBUG("jr %s", regnames[rs]); break; case OPC_JALR: blink = rt; ctx->hflags |= MIPS_HFLAG_BR; - MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]); break; default: MIPS_INVAL("branch/jump"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); goto out; } } else { switch (opc) { case OPC_BEQ: tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1); - MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx, - regnames[rs], regnames[rt], btgt); goto not_likely; case OPC_BEQL: tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1); - MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx, - regnames[rs], regnames[rt], btgt); goto likely; case OPC_BNE: tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1); - MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx, - regnames[rs], regnames[rt], btgt); goto not_likely; case OPC_BNEL: tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1); - MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx, - regnames[rs], regnames[rt], btgt); goto likely; case OPC_BGEZ: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0); - MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt); goto not_likely; case OPC_BGEZL: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0); - MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt); goto likely; case OPC_BGEZAL: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0); - MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt); blink = 31; goto not_likely; case OPC_BGEZALL: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0); blink = 31; - MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt); goto likely; case OPC_BGTZ: tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0); - MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt); goto not_likely; case OPC_BGTZL: tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0); - MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt); goto likely; case OPC_BLEZ: tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0); - MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt); goto not_likely; case OPC_BLEZL: tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0); - MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt); goto likely; case OPC_BLTZ: tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0); - MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt); goto not_likely; case OPC_BLTZL: tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0); - MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt); goto likely; case OPC_BPOSGE32: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32); - MIPS_DEBUG("bposge32 " TARGET_FMT_lx, btgt); goto not_likely; #if defined(TARGET_MIPS64) case OPC_BPOSGE64: tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64); - MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt); goto not_likely; #endif case OPC_BLTZAL: tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0); blink = 31; - MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt); not_likely: ctx->hflags |= MIPS_HFLAG_BC; break; case OPC_BLTZALL: tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0); blink = 31; - MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt); likely: ctx->hflags |= MIPS_HFLAG_BL; break; default: MIPS_INVAL("conditional branch/jump"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); goto out; } } - MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx, - blink, ctx->hflags, btgt); ctx->btarget = btgt; @@ -4804,7 +4522,7 @@ static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt, default: fail: MIPS_INVAL("bitops"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); tcg_temp_free(t0); tcg_temp_free(t1); return; @@ -4820,7 +4538,6 @@ static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd) if (rd == 0) { /* If no destination, treat it as a NOP. */ - MIPS_DEBUG("NOP"); return; } @@ -4877,7 +4594,7 @@ static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd) #endif default: MIPS_INVAL("bsfhl"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); tcg_temp_free(t0); return; } @@ -4920,7 +4637,16 @@ static void gen_align(DisasContext *ctx, int opc, int rd, int rs, int rt, t0 = tcg_temp_new(); gen_load_gpr(t0, rt); if (bp == 0) { - tcg_gen_mov_tl(cpu_gpr[rd], t0); + switch (opc) { + case OPC_ALIGN: + tcg_gen_ext32s_tl(cpu_gpr[rd], t0); + break; +#if defined(TARGET_MIPS64) + case OPC_DALIGN: + tcg_gen_mov_tl(cpu_gpr[rd], t0); + break; +#endif + } } else { TCGv t1 = tcg_temp_new(); gen_load_gpr(t1, rs); @@ -5050,19 +4776,18 @@ static inline void gen_mtc0_store32 (TCGv arg, target_ulong off) tcg_temp_free_i32(t0); } -static inline void gen_mtc0_store64 (TCGv arg, target_ulong off) -{ - tcg_gen_ext32s_tl(arg, arg); - tcg_gen_st_tl(arg, cpu_env, off); -} +#define CP0_CHECK(c) \ + do { \ + if (!(c)) { \ + goto cp0_unimplemented; \ + } \ + } while (0) static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel) { const char *rn = "invalid"; - if (!(ctx->hflags & MIPS_HFLAG_ELPA)) { - goto mfhc0_read_zero; - } + CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA); switch (reg) { case 2: @@ -5072,7 +4797,7 @@ static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel) rn = "EntryLo0"; break; default: - goto mfhc0_read_zero; + goto cp0_unimplemented; } break; case 3: @@ -5082,7 +4807,7 @@ static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel) rn = "EntryLo1"; break; default: - goto mfhc0_read_zero; + goto cp0_unimplemented; } break; case 17: @@ -5092,8 +4817,13 @@ static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel) ctx->CP0_LLAddr_shift); rn = "LLAddr"; break; + case 1: + CP0_CHECK(ctx->mrp); + gen_helper_mfhc0_maar(arg, cpu_env); + rn = "MAAR"; + break; default: - goto mfhc0_read_zero; + goto cp0_unimplemented; } break; case 28: @@ -5106,18 +4836,18 @@ static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel) rn = "TagLo"; break; default: - goto mfhc0_read_zero; + goto cp0_unimplemented; } break; default: - goto mfhc0_read_zero; + goto cp0_unimplemented; } (void)rn; /* avoid a compiler warning */ LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel); return; -mfhc0_read_zero: +cp0_unimplemented: LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel); tcg_gen_movi_tl(arg, 0); } @@ -5127,9 +4857,7 @@ static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel) const char *rn = "invalid"; uint64_t mask = ctx->PAMask >> 36; - if (!(ctx->hflags & MIPS_HFLAG_ELPA)) { - goto mthc0_nop; - } + CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA); switch (reg) { case 2: @@ -5140,7 +4868,7 @@ static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel) rn = "EntryLo0"; break; default: - goto mthc0_nop; + goto cp0_unimplemented; } break; case 3: @@ -5151,7 +4879,7 @@ static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel) rn = "EntryLo1"; break; default: - goto mthc0_nop; + goto cp0_unimplemented; } break; case 17: @@ -5163,8 +4891,13 @@ static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel) treating MTHC0 to LLAddr as NOP. */ rn = "LLAddr"; break; + case 1: + CP0_CHECK(ctx->mrp); + gen_helper_mthc0_maar(cpu_env, arg); + rn = "MAAR"; + break; default: - goto mthc0_nop; + goto cp0_unimplemented; } break; case 28: @@ -5178,15 +4911,15 @@ static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel) rn = "TagLo"; break; default: - goto mthc0_nop; + goto cp0_unimplemented; } break; default: - goto mthc0_nop; + goto cp0_unimplemented; } (void)rn; /* avoid a compiler warning */ -mthc0_nop: +cp0_unimplemented: LOG_DISAS("mthc0 %s (reg %d sel %d)\n", rn, reg, sel); } @@ -5199,13 +4932,6 @@ static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg) } } -#define CP0_CHECK(c) \ - do { \ - if (!(c)) { \ - goto cp0_unimplemented; \ - } \ - } while (0) - static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) { const char *rn = "invalid"; @@ -5235,6 +4961,11 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_helper_mfc0_mvpconf1(arg, cpu_env); rn = "MVPConf1"; break; + case 4: + CP0_CHECK(ctx->vp); + gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl)); + rn = "VPControl"; + break; default: goto cp0_unimplemented; } @@ -5362,6 +5093,11 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) } rn = "EntryLo1"; break; + case 1: + CP0_CHECK(ctx->vp); + gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber)); + rn = "GlobalNumber"; + break; default: goto cp0_unimplemented; } @@ -5570,6 +5306,13 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase)); rn = "EBase"; break; + case 3: + check_insn(ctx, ISA_MIPS32R2); + CP0_CHECK(ctx->cmgcr); + tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase)); + tcg_gen_ext32s_tl(arg, arg); + rn = "CMGCRBase"; + break; default: goto cp0_unimplemented; } @@ -5619,6 +5362,16 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_helper_mfc0_lladdr(arg, cpu_env); rn = "LLAddr"; break; + case 1: + CP0_CHECK(ctx->mrp); + gen_helper_mfc0_maar(arg, cpu_env); + rn = "MAAR"; + break; + case 2: + CP0_CHECK(ctx->mrp); + gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI)); + rn = "MAARI"; + break; default: goto cp0_unimplemented; } @@ -5750,8 +5503,14 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) } break; case 26: - tcg_gen_movi_tl(arg, 0); /* unimplemented */ - rn = "ECC"; + switch (sel) { + case 0: + gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl)); + rn = "ErrCtl"; + break; + default: + goto cp0_unimplemented; + } break; case 27: switch (sel) { @@ -5882,6 +5641,11 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) /* ignored */ rn = "MVPConf1"; break; + case 4: + CP0_CHECK(ctx->vp); + /* ignored */ + rn = "VPControl"; + break; default: goto cp0_unimplemented; } @@ -5914,12 +5678,14 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) break; case 5: CP0_CHECK(ctx->insn_flags & ASE_MT); - gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule)); + tcg_gen_st_tl(arg, cpu_env, + offsetof(CPUMIPSState, CP0_VPESchedule)); rn = "VPESchedule"; break; case 6: CP0_CHECK(ctx->insn_flags & ASE_MT); - gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack)); + tcg_gen_st_tl(arg, cpu_env, + offsetof(CPUMIPSState, CP0_VPEScheFBack)); rn = "VPEScheFBack"; break; case 7: @@ -5982,6 +5748,11 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_helper_mtc0_entrylo1(cpu_env, arg); rn = "EntryLo1"; break; + case 1: + CP0_CHECK(ctx->vp); + /* ignored */ + rn = "GlobalNumber"; + break; default: goto cp0_unimplemented; } @@ -6169,7 +5940,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 14: switch (sel) { case 0: - gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC)); + tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC)); rn = "EPC"; break; default: @@ -6246,6 +6017,16 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_helper_mtc0_lladdr(cpu_env, arg); rn = "LLAddr"; break; + case 1: + CP0_CHECK(ctx->mrp); + gen_helper_mtc0_maar(cpu_env, arg); + rn = "MAAR"; + break; + case 2: + CP0_CHECK(ctx->mrp); + gen_helper_mtc0_maari(cpu_env, arg); + rn = "MAARI"; + break; default: goto cp0_unimplemented; } @@ -6342,7 +6123,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) switch (sel) { case 0: /* EJTAG support */ - gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC)); + tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC)); rn = "DEPC"; break; default: @@ -6388,8 +6169,15 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) } break; case 26: - /* ignored */ - rn = "ECC"; + switch (sel) { + case 0: + gen_helper_mtc0_errctl(cpu_env, arg); + ctx->bstate = BS_STOP; + rn = "ErrCtl"; + break; + default: + goto cp0_unimplemented; + } break; case 27: switch (sel) { @@ -6445,7 +6233,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 30: switch (sel) { case 0: - gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC)); + tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC)); rn = "ErrorEPC"; break; default: @@ -6517,6 +6305,11 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_helper_mfc0_mvpconf1(arg, cpu_env); rn = "MVPConf1"; break; + case 4: + CP0_CHECK(ctx->vp); + gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl)); + rn = "VPControl"; + break; default: goto cp0_unimplemented; } @@ -6618,6 +6411,11 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1)); rn = "EntryLo1"; break; + case 1: + CP0_CHECK(ctx->vp); + gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber)); + rn = "GlobalNumber"; + break; default: goto cp0_unimplemented; } @@ -6822,6 +6620,12 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase)); rn = "EBase"; break; + case 3: + check_insn(ctx, ISA_MIPS32R2); + CP0_CHECK(ctx->cmgcr); + tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase)); + rn = "CMGCRBase"; + break; default: goto cp0_unimplemented; } @@ -6871,6 +6675,16 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_helper_dmfc0_lladdr(arg, cpu_env); rn = "LLAddr"; break; + case 1: + CP0_CHECK(ctx->mrp); + gen_helper_dmfc0_maar(arg, cpu_env); + rn = "MAAR"; + break; + case 2: + CP0_CHECK(ctx->mrp); + gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI)); + rn = "MAARI"; + break; default: goto cp0_unimplemented; } @@ -6998,8 +6812,14 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) } break; case 26: - tcg_gen_movi_tl(arg, 0); /* unimplemented */ - rn = "ECC"; + switch (sel) { + case 0: + gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl)); + rn = "ErrCtl"; + break; + default: + goto cp0_unimplemented; + } break; case 27: switch (sel) { @@ -7124,6 +6944,11 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) /* ignored */ rn = "MVPConf1"; break; + case 4: + CP0_CHECK(ctx->vp); + /* ignored */ + rn = "VPControl"; + break; default: goto cp0_unimplemented; } @@ -7224,6 +7049,11 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_helper_dmtc0_entrylo1(cpu_env, arg); rn = "EntryLo1"; break; + case 1: + CP0_CHECK(ctx->vp); + /* ignored */ + rn = "GlobalNumber"; + break; default: goto cp0_unimplemented; } @@ -7492,6 +7322,16 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_helper_mtc0_lladdr(cpu_env, arg); rn = "LLAddr"; break; + case 1: + CP0_CHECK(ctx->mrp); + gen_helper_mtc0_maar(cpu_env, arg); + rn = "MAAR"; + break; + case 2: + CP0_CHECK(ctx->mrp); + gen_helper_mtc0_maari(cpu_env, arg); + rn = "MAARI"; + break; default: goto cp0_unimplemented; } @@ -7630,8 +7470,15 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) } break; case 26: - /* ignored */ - rn = "ECC"; + switch (sel) { + case 0: + gen_helper_mtc0_errctl(cpu_env, arg); + ctx->bstate = BS_STOP; + rn = "ErrCtl"; + break; + default: + goto cp0_unimplemented; + } break; case 27: switch (sel) { @@ -7944,7 +7791,7 @@ static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd, die: tcg_temp_free(t0); LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt, @@ -8125,7 +7972,6 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt, break; case 3: /* XXX: For now we support only a single FPU context. */ - save_cpu_state(ctx, 1); { TCGv_i32 fs_tmp = tcg_const_i32(rd); @@ -8149,7 +7995,7 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt, die: tcg_temp_free(t0); LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd) @@ -8278,7 +8124,6 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, case OPC_ERET: /* OPC_ERETNC */ if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) { - MIPS_DEBUG("CTI in delay / forbidden slot"); goto die; } else { int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6; @@ -8301,12 +8146,11 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, check_insn(ctx, ISA_MIPS32); if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) { - MIPS_DEBUG("CTI in delay / forbidden slot"); goto die; } if (!(ctx->hflags & MIPS_HFLAG_DM)) { MIPS_INVAL(opn); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } else { gen_helper_deret(cpu_env); ctx->bstate = BS_EXCP; @@ -8317,7 +8161,6 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, check_insn(ctx, ISA_MIPS3 | ISA_MIPS32); if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) { - MIPS_DEBUG("CTI in delay / forbidden slot"); goto die; } /* If we get an exception, we want to restart at next instruction */ @@ -8330,11 +8173,10 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, default: die: MIPS_INVAL(opn); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); return; } (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd); } #endif /* !CONFIG_USER_ONLY */ @@ -8343,12 +8185,10 @@ static void gen_compute_branch1(DisasContext *ctx, uint32_t op, int32_t cc, int32_t offset) { target_ulong btarget; - const char *opn = "cp1 cond branch"; TCGv_i32 t0 = tcg_temp_new_i32(); if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) { - MIPS_DEBUG("CTI in delay / forbidden slot"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); goto out; } @@ -8363,26 +8203,22 @@ static void gen_compute_branch1(DisasContext *ctx, uint32_t op, tcg_gen_not_i32(t0, t0); tcg_gen_andi_i32(t0, t0, 1); tcg_gen_extu_i32_tl(bcond, t0); - opn = "bc1f"; goto not_likely; case OPC_BC1FL: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc)); tcg_gen_not_i32(t0, t0); tcg_gen_andi_i32(t0, t0, 1); tcg_gen_extu_i32_tl(bcond, t0); - opn = "bc1fl"; goto likely; case OPC_BC1T: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc)); tcg_gen_andi_i32(t0, t0, 1); tcg_gen_extu_i32_tl(bcond, t0); - opn = "bc1t"; goto not_likely; case OPC_BC1TL: tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc)); tcg_gen_andi_i32(t0, t0, 1); tcg_gen_extu_i32_tl(bcond, t0); - opn = "bc1tl"; likely: ctx->hflags |= MIPS_HFLAG_BL; break; @@ -8396,7 +8232,6 @@ static void gen_compute_branch1(DisasContext *ctx, uint32_t op, tcg_gen_andi_i32(t0, t0, 1); tcg_gen_extu_i32_tl(bcond, t0); } - opn = "bc1any2f"; goto not_likely; case OPC_BC1TANY2: { @@ -8408,7 +8243,6 @@ static void gen_compute_branch1(DisasContext *ctx, uint32_t op, tcg_gen_andi_i32(t0, t0, 1); tcg_gen_extu_i32_tl(bcond, t0); } - opn = "bc1any2t"; goto not_likely; case OPC_BC1FANY4: { @@ -8424,7 +8258,6 @@ static void gen_compute_branch1(DisasContext *ctx, uint32_t op, tcg_gen_andi_i32(t0, t0, 1); tcg_gen_extu_i32_tl(bcond, t0); } - opn = "bc1any4f"; goto not_likely; case OPC_BC1TANY4: { @@ -8440,18 +8273,14 @@ static void gen_compute_branch1(DisasContext *ctx, uint32_t op, tcg_gen_andi_i32(t0, t0, 1); tcg_gen_extu_i32_tl(bcond, t0); } - opn = "bc1any4t"; not_likely: ctx->hflags |= MIPS_HFLAG_BC; break; default: - MIPS_INVAL(opn); - generate_exception (ctx, EXCP_RI); + MIPS_INVAL("cp1 cond branch"); + generate_exception_end(ctx, EXCP_RI); goto out; } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn, - ctx->hflags, btarget); ctx->btarget = btarget; ctx->hflags |= MIPS_HFLAG_BDS32; out: @@ -8464,7 +8293,6 @@ static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op, int delayslot_size) { target_ulong btarget; - const char *opn = "cp1 cond branch"; TCGv_i64 t0 = tcg_temp_new_i64(); if (ctx->hflags & MIPS_HFLAG_BMASK) { @@ -8472,7 +8300,7 @@ static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op, LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc); #endif - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); goto out; } @@ -8484,25 +8312,20 @@ static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op, switch (op) { case OPC_BC1EQZ: tcg_gen_xori_i64(t0, t0, 1); - opn = "bc1eqz"; ctx->hflags |= MIPS_HFLAG_BC; break; case OPC_BC1NEZ: /* t0 already set */ - opn = "bc1nez"; ctx->hflags |= MIPS_HFLAG_BC; break; default: - MIPS_INVAL(opn); - generate_exception(ctx, EXCP_RI); + MIPS_INVAL("cp1 cond branch"); + generate_exception_end(ctx, EXCP_RI); goto out; } tcg_gen_trunc_i64_tl(bcond, t0); - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn, - ctx->hflags, btarget); ctx->btarget = btarget; switch (delayslot_size) { @@ -8733,7 +8556,6 @@ enum r6_f_cmp_op { }; static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) { - const char *opn = "cp1 move"; TCGv t0 = tcg_temp_new(); switch (opc) { @@ -8746,7 +8568,6 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) tcg_temp_free_i32(fp0); } gen_store_gpr(t0, rt); - opn = "mfc1"; break; case OPC_MTC1: gen_load_gpr(t0, rt); @@ -8757,16 +8578,14 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) gen_store_fpr32(ctx, fp0, fs); tcg_temp_free_i32(fp0); } - opn = "mtc1"; break; case OPC_CFC1: gen_helper_1e0i(cfc1, t0, fs); gen_store_gpr(t0, rt); - opn = "cfc1"; break; case OPC_CTC1: gen_load_gpr(t0, rt); - save_cpu_state(ctx, 1); + save_cpu_state(ctx, 0); { TCGv_i32 fs_tmp = tcg_const_i32(fs); @@ -8775,18 +8594,15 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) } /* Stop translation as we may have changed hflags */ ctx->bstate = BS_STOP; - opn = "ctc1"; break; #if defined(TARGET_MIPS64) case OPC_DMFC1: gen_load_fpr64(ctx, t0, fs); gen_store_gpr(t0, rt); - opn = "dmfc1"; break; case OPC_DMTC1: gen_load_gpr(t0, rt); gen_store_fpr64(ctx, t0, fs); - opn = "dmtc1"; break; #endif case OPC_MFHC1: @@ -8798,7 +8614,6 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) tcg_temp_free_i32(fp0); } gen_store_gpr(t0, rt); - opn = "mfhc1"; break; case OPC_MTHC1: gen_load_gpr(t0, rt); @@ -8809,15 +8624,12 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) gen_store_fpr32h(ctx, fp0, fs); tcg_temp_free_i32(fp0); } - opn = "mthc1"; break; default: - MIPS_INVAL(opn); - generate_exception (ctx, EXCP_RI); + MIPS_INVAL("cp1 move"); + generate_exception_end(ctx, EXCP_RI); goto out; } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]); out: tcg_temp_free(t0); @@ -8947,7 +8759,7 @@ static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft, break; default: MIPS_INVAL("gen_sel_s"); - generate_exception (ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } @@ -8984,7 +8796,7 @@ static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft, break; default: MIPS_INVAL("gen_sel_d"); - generate_exception (ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } @@ -8998,44 +8810,6 @@ static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft, static void gen_farith (DisasContext *ctx, enum fopcode op1, int ft, int fs, int fd, int cc) { - const char *opn = "farith"; - const char *condnames[] = { - "c.f", - "c.un", - "c.eq", - "c.ueq", - "c.olt", - "c.ult", - "c.ole", - "c.ule", - "c.sf", - "c.ngle", - "c.seq", - "c.ngl", - "c.lt", - "c.nge", - "c.le", - "c.ngt", - }; - const char *condnames_abs[] = { - "cabs.f", - "cabs.un", - "cabs.eq", - "cabs.ueq", - "cabs.olt", - "cabs.ult", - "cabs.ole", - "cabs.ule", - "cabs.sf", - "cabs.ngle", - "cabs.seq", - "cabs.ngl", - "cabs.lt", - "cabs.nge", - "cabs.le", - "cabs.ngt", - }; - enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP; uint32_t func = ctx->opcode & 0x3f; switch (op1) { case OPC_ADD_S: @@ -9050,8 +8824,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "add.s"; - optype = BINOP; break; case OPC_SUB_S: { @@ -9065,8 +8837,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "sub.s"; - optype = BINOP; break; case OPC_MUL_S: { @@ -9080,8 +8850,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "mul.s"; - optype = BINOP; break; case OPC_DIV_S: { @@ -9095,8 +8863,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "div.s"; - optype = BINOP; break; case OPC_SQRT_S: { @@ -9107,7 +8873,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "sqrt.s"; break; case OPC_ABS_S: { @@ -9118,7 +8883,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "abs.s"; break; case OPC_MOV_S: { @@ -9128,7 +8892,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "mov.s"; break; case OPC_NEG_S: { @@ -9139,7 +8902,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "neg.s"; break; case OPC_ROUND_L_S: check_cp1_64bitmode(ctx); @@ -9153,7 +8915,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp64, fd); tcg_temp_free_i64(fp64); } - opn = "round.l.s"; break; case OPC_TRUNC_L_S: check_cp1_64bitmode(ctx); @@ -9167,7 +8928,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp64, fd); tcg_temp_free_i64(fp64); } - opn = "trunc.l.s"; break; case OPC_CEIL_L_S: check_cp1_64bitmode(ctx); @@ -9181,7 +8941,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp64, fd); tcg_temp_free_i64(fp64); } - opn = "ceil.l.s"; break; case OPC_FLOOR_L_S: check_cp1_64bitmode(ctx); @@ -9195,7 +8954,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp64, fd); tcg_temp_free_i64(fp64); } - opn = "floor.l.s"; break; case OPC_ROUND_W_S: { @@ -9206,7 +8964,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "round.w.s"; break; case OPC_TRUNC_W_S: { @@ -9217,7 +8974,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "trunc.w.s"; break; case OPC_CEIL_W_S: { @@ -9228,7 +8984,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "ceil.w.s"; break; case OPC_FLOOR_W_S: { @@ -9239,27 +8994,22 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "floor.w.s"; break; case OPC_SEL_S: check_insn(ctx, ISA_MIPS32R6); gen_sel_s(ctx, op1, fd, ft, fs); - opn = "sel.s"; break; case OPC_SELEQZ_S: check_insn(ctx, ISA_MIPS32R6); gen_sel_s(ctx, op1, fd, ft, fs); - opn = "seleqz.s"; break; case OPC_SELNEZ_S: check_insn(ctx, ISA_MIPS32R6); gen_sel_s(ctx, op1, fd, ft, fs); - opn = "selnez.s"; break; case OPC_MOVCF_S: check_insn_opc_removed(ctx, ISA_MIPS32R6); gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1); - opn = "movcf.s"; break; case OPC_MOVZ_S: check_insn_opc_removed(ctx, ISA_MIPS32R6); @@ -9276,7 +9026,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, tcg_temp_free_i32(fp0); gen_set_label(l1); } - opn = "movz.s"; break; case OPC_MOVN_S: check_insn_opc_removed(ctx, ISA_MIPS32R6); @@ -9293,10 +9042,8 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_set_label(l1); } } - opn = "movn.s"; break; case OPC_RECIP_S: - check_cop1x(ctx); { TCGv_i32 fp0 = tcg_temp_new_i32(); @@ -9305,10 +9052,8 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "recip.s"; break; case OPC_RSQRT_S: - check_cop1x(ctx); { TCGv_i32 fp0 = tcg_temp_new_i32(); @@ -9317,7 +9062,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "rsqrt.s"; break; case OPC_MADDF_S: check_insn(ctx, ISA_MIPS32R6); @@ -9333,7 +9077,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, tcg_temp_free_i32(fp2); tcg_temp_free_i32(fp1); tcg_temp_free_i32(fp0); - opn = "maddf.s"; } break; case OPC_MSUBF_S: @@ -9350,7 +9093,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, tcg_temp_free_i32(fp2); tcg_temp_free_i32(fp1); tcg_temp_free_i32(fp0); - opn = "msubf.s"; } break; case OPC_RINT_S: @@ -9361,7 +9103,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_helper_float_rint_s(fp0, cpu_env, fp0); gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); - opn = "rint.s"; } break; case OPC_CLASS_S: @@ -9372,7 +9113,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_helper_float_class_s(fp0, fp0); gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); - opn = "class.s"; } break; case OPC_MIN_S: /* OPC_RECIP2_S */ @@ -9388,7 +9128,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, tcg_temp_free_i32(fp2); tcg_temp_free_i32(fp1); tcg_temp_free_i32(fp0); - opn = "min.s"; } else { /* OPC_RECIP2_S */ check_cp1_64bitmode(ctx); @@ -9403,7 +9142,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "recip2.s"; } break; case OPC_MINA_S: /* OPC_RECIP1_S */ @@ -9419,7 +9157,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, tcg_temp_free_i32(fp2); tcg_temp_free_i32(fp1); tcg_temp_free_i32(fp0); - opn = "mina.s"; } else { /* OPC_RECIP1_S */ check_cp1_64bitmode(ctx); @@ -9431,7 +9168,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "recip1.s"; } break; case OPC_MAX_S: /* OPC_RSQRT1_S */ @@ -9445,7 +9181,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp1, fd); tcg_temp_free_i32(fp1); tcg_temp_free_i32(fp0); - opn = "max.s"; } else { /* OPC_RSQRT1_S */ check_cp1_64bitmode(ctx); @@ -9457,7 +9192,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "rsqrt1.s"; } break; case OPC_MAXA_S: /* OPC_RSQRT2_S */ @@ -9471,7 +9205,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp1, fd); tcg_temp_free_i32(fp1); tcg_temp_free_i32(fp0); - opn = "maxa.s"; } else { /* OPC_RSQRT2_S */ check_cp1_64bitmode(ctx); @@ -9486,7 +9219,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "rsqrt2.s"; } break; case OPC_CVT_D_S: @@ -9501,7 +9233,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp64, fd); tcg_temp_free_i64(fp64); } - opn = "cvt.d.s"; break; case OPC_CVT_W_S: { @@ -9512,7 +9243,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "cvt.w.s"; break; case OPC_CVT_L_S: check_cp1_64bitmode(ctx); @@ -9526,7 +9256,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp64, fd); tcg_temp_free_i64(fp64); } - opn = "cvt.l.s"; break; case OPC_CVT_PS_S: check_ps(ctx); @@ -9543,7 +9272,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp64, fd); tcg_temp_free_i64(fp64); } - opn = "cvt.ps.s"; break; case OPC_CMP_F_S: case OPC_CMP_UN_S: @@ -9564,12 +9292,9 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, check_insn_opc_removed(ctx, ISA_MIPS32R6); if (ctx->opcode & (1 << 6)) { gen_cmpabs_s(ctx, func-48, ft, fs, cc); - opn = condnames_abs[func-48]; } else { gen_cmp_s(ctx, func-48, ft, fs, cc); - opn = condnames[func-48]; } - optype = CMPOP; break; case OPC_ADD_D: check_cp1_registers(ctx, fs | ft | fd); @@ -9584,8 +9309,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "add.d"; - optype = BINOP; break; case OPC_SUB_D: check_cp1_registers(ctx, fs | ft | fd); @@ -9600,8 +9323,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "sub.d"; - optype = BINOP; break; case OPC_MUL_D: check_cp1_registers(ctx, fs | ft | fd); @@ -9616,8 +9337,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "mul.d"; - optype = BINOP; break; case OPC_DIV_D: check_cp1_registers(ctx, fs | ft | fd); @@ -9632,8 +9351,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "div.d"; - optype = BINOP; break; case OPC_SQRT_D: check_cp1_registers(ctx, fs | fd); @@ -9645,7 +9362,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "sqrt.d"; break; case OPC_ABS_D: check_cp1_registers(ctx, fs | fd); @@ -9657,7 +9373,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "abs.d"; break; case OPC_MOV_D: check_cp1_registers(ctx, fs | fd); @@ -9668,7 +9383,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "mov.d"; break; case OPC_NEG_D: check_cp1_registers(ctx, fs | fd); @@ -9680,7 +9394,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "neg.d"; break; case OPC_ROUND_L_D: check_cp1_64bitmode(ctx); @@ -9692,7 +9405,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "round.l.d"; break; case OPC_TRUNC_L_D: check_cp1_64bitmode(ctx); @@ -9704,7 +9416,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "trunc.l.d"; break; case OPC_CEIL_L_D: check_cp1_64bitmode(ctx); @@ -9716,7 +9427,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "ceil.l.d"; break; case OPC_FLOOR_L_D: check_cp1_64bitmode(ctx); @@ -9728,7 +9438,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "floor.l.d"; break; case OPC_ROUND_W_D: check_cp1_registers(ctx, fs); @@ -9742,7 +9451,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp32, fd); tcg_temp_free_i32(fp32); } - opn = "round.w.d"; break; case OPC_TRUNC_W_D: check_cp1_registers(ctx, fs); @@ -9756,7 +9464,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp32, fd); tcg_temp_free_i32(fp32); } - opn = "trunc.w.d"; break; case OPC_CEIL_W_D: check_cp1_registers(ctx, fs); @@ -9770,7 +9477,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp32, fd); tcg_temp_free_i32(fp32); } - opn = "ceil.w.d"; break; case OPC_FLOOR_W_D: check_cp1_registers(ctx, fs); @@ -9784,27 +9490,22 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp32, fd); tcg_temp_free_i32(fp32); } - opn = "floor.w.d"; break; case OPC_SEL_D: check_insn(ctx, ISA_MIPS32R6); gen_sel_d(ctx, op1, fd, ft, fs); - opn = "sel.d"; break; case OPC_SELEQZ_D: check_insn(ctx, ISA_MIPS32R6); gen_sel_d(ctx, op1, fd, ft, fs); - opn = "seleqz.d"; break; case OPC_SELNEZ_D: check_insn(ctx, ISA_MIPS32R6); gen_sel_d(ctx, op1, fd, ft, fs); - opn = "selnez.d"; break; case OPC_MOVCF_D: check_insn_opc_removed(ctx, ISA_MIPS32R6); gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1); - opn = "movcf.d"; break; case OPC_MOVZ_D: check_insn_opc_removed(ctx, ISA_MIPS32R6); @@ -9821,7 +9522,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, tcg_temp_free_i64(fp0); gen_set_label(l1); } - opn = "movz.d"; break; case OPC_MOVN_D: check_insn_opc_removed(ctx, ISA_MIPS32R6); @@ -9838,10 +9538,9 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_set_label(l1); } } - opn = "movn.d"; break; case OPC_RECIP_D: - check_cp1_64bitmode(ctx); + check_cp1_registers(ctx, fs | fd); { TCGv_i64 fp0 = tcg_temp_new_i64(); @@ -9850,10 +9549,9 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "recip.d"; break; case OPC_RSQRT_D: - check_cp1_64bitmode(ctx); + check_cp1_registers(ctx, fs | fd); { TCGv_i64 fp0 = tcg_temp_new_i64(); @@ -9862,7 +9560,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "rsqrt.d"; break; case OPC_MADDF_D: check_insn(ctx, ISA_MIPS32R6); @@ -9878,7 +9575,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, tcg_temp_free_i64(fp2); tcg_temp_free_i64(fp1); tcg_temp_free_i64(fp0); - opn = "maddf.d"; } break; case OPC_MSUBF_D: @@ -9895,7 +9591,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, tcg_temp_free_i64(fp2); tcg_temp_free_i64(fp1); tcg_temp_free_i64(fp0); - opn = "msubf.d"; } break; case OPC_RINT_D: @@ -9906,7 +9601,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_helper_float_rint_d(fp0, cpu_env, fp0); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); - opn = "rint.d"; } break; case OPC_CLASS_D: @@ -9917,7 +9611,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_helper_float_class_d(fp0, fp0); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); - opn = "class.d"; } break; case OPC_MIN_D: /* OPC_RECIP2_D */ @@ -9931,7 +9624,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp1, fd); tcg_temp_free_i64(fp1); tcg_temp_free_i64(fp0); - opn = "min.d"; } else { /* OPC_RECIP2_D */ check_cp1_64bitmode(ctx); @@ -9946,7 +9638,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "recip2.d"; } break; case OPC_MINA_D: /* OPC_RECIP1_D */ @@ -9960,7 +9651,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp1, fd); tcg_temp_free_i64(fp1); tcg_temp_free_i64(fp0); - opn = "mina.d"; } else { /* OPC_RECIP1_D */ check_cp1_64bitmode(ctx); @@ -9972,7 +9662,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "recip1.d"; } break; case OPC_MAX_D: /* OPC_RSQRT1_D */ @@ -9986,7 +9675,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp1, fd); tcg_temp_free_i64(fp1); tcg_temp_free_i64(fp0); - opn = "max.d"; } else { /* OPC_RSQRT1_D */ check_cp1_64bitmode(ctx); @@ -9998,7 +9686,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "rsqrt1.d"; } break; case OPC_MAXA_D: /* OPC_RSQRT2_D */ @@ -10012,7 +9699,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp1, fd); tcg_temp_free_i64(fp1); tcg_temp_free_i64(fp0); - opn = "maxa.d"; } else { /* OPC_RSQRT2_D */ check_cp1_64bitmode(ctx); @@ -10027,7 +9713,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "rsqrt2.d"; } break; case OPC_CMP_F_D: @@ -10049,12 +9734,9 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, check_insn_opc_removed(ctx, ISA_MIPS32R6); if (ctx->opcode & (1 << 6)) { gen_cmpabs_d(ctx, func-48, ft, fs, cc); - opn = condnames_abs[func-48]; } else { gen_cmp_d(ctx, func-48, ft, fs, cc); - opn = condnames[func-48]; } - optype = CMPOP; break; case OPC_CVT_S_D: check_cp1_registers(ctx, fs); @@ -10068,7 +9750,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp32, fd); tcg_temp_free_i32(fp32); } - opn = "cvt.s.d"; break; case OPC_CVT_W_D: check_cp1_registers(ctx, fs); @@ -10082,7 +9763,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp32, fd); tcg_temp_free_i32(fp32); } - opn = "cvt.w.d"; break; case OPC_CVT_L_D: check_cp1_64bitmode(ctx); @@ -10094,7 +9774,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "cvt.l.d"; break; case OPC_CVT_S_W: { @@ -10105,7 +9784,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "cvt.s.w"; break; case OPC_CVT_D_W: check_cp1_registers(ctx, fd); @@ -10119,7 +9797,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp64, fd); tcg_temp_free_i64(fp64); } - opn = "cvt.d.w"; break; case OPC_CVT_S_L: check_cp1_64bitmode(ctx); @@ -10133,7 +9810,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp32, fd); tcg_temp_free_i32(fp32); } - opn = "cvt.s.l"; break; case OPC_CVT_D_L: check_cp1_64bitmode(ctx); @@ -10145,7 +9821,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "cvt.d.l"; break; case OPC_CVT_PS_PW: check_ps(ctx); @@ -10157,7 +9832,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "cvt.ps.pw"; break; case OPC_ADD_PS: check_ps(ctx); @@ -10172,7 +9846,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "add.ps"; break; case OPC_SUB_PS: check_ps(ctx); @@ -10187,7 +9860,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "sub.ps"; break; case OPC_MUL_PS: check_ps(ctx); @@ -10202,7 +9874,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "mul.ps"; break; case OPC_ABS_PS: check_ps(ctx); @@ -10214,7 +9885,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "abs.ps"; break; case OPC_MOV_PS: check_ps(ctx); @@ -10225,7 +9895,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "mov.ps"; break; case OPC_NEG_PS: check_ps(ctx); @@ -10237,12 +9906,10 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "neg.ps"; break; case OPC_MOVCF_PS: check_ps(ctx); gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1); - opn = "movcf.ps"; break; case OPC_MOVZ_PS: check_ps(ctx); @@ -10258,7 +9925,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, tcg_temp_free_i64(fp0); gen_set_label(l1); } - opn = "movz.ps"; break; case OPC_MOVN_PS: check_ps(ctx); @@ -10275,7 +9941,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_set_label(l1); } } - opn = "movn.ps"; break; case OPC_ADDR_PS: check_ps(ctx); @@ -10290,7 +9955,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "addr.ps"; break; case OPC_MULR_PS: check_ps(ctx); @@ -10305,7 +9969,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "mulr.ps"; break; case OPC_RECIP2_PS: check_ps(ctx); @@ -10320,7 +9983,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "recip2.ps"; break; case OPC_RECIP1_PS: check_ps(ctx); @@ -10332,7 +9994,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "recip1.ps"; break; case OPC_RSQRT1_PS: check_ps(ctx); @@ -10344,7 +10005,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "rsqrt1.ps"; break; case OPC_RSQRT2_PS: check_ps(ctx); @@ -10359,7 +10019,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "rsqrt2.ps"; break; case OPC_CVT_S_PU: check_cp1_64bitmode(ctx); @@ -10371,7 +10030,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "cvt.s.pu"; break; case OPC_CVT_PW_PS: check_ps(ctx); @@ -10383,7 +10041,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "cvt.pw.ps"; break; case OPC_CVT_S_PL: check_cp1_64bitmode(ctx); @@ -10395,7 +10052,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "cvt.s.pl"; break; case OPC_PLL_PS: check_ps(ctx); @@ -10410,7 +10066,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, tcg_temp_free_i32(fp0); tcg_temp_free_i32(fp1); } - opn = "pll.ps"; break; case OPC_PLU_PS: check_ps(ctx); @@ -10425,7 +10080,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, tcg_temp_free_i32(fp0); tcg_temp_free_i32(fp1); } - opn = "plu.ps"; break; case OPC_PUL_PS: check_ps(ctx); @@ -10440,7 +10094,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, tcg_temp_free_i32(fp0); tcg_temp_free_i32(fp1); } - opn = "pul.ps"; break; case OPC_PUU_PS: check_ps(ctx); @@ -10455,7 +10108,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, tcg_temp_free_i32(fp0); tcg_temp_free_i32(fp1); } - opn = "puu.ps"; break; case OPC_CMP_F_PS: case OPC_CMP_UN_PS: @@ -10475,38 +10127,21 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, case OPC_CMP_NGT_PS: if (ctx->opcode & (1 << 6)) { gen_cmpabs_ps(ctx, func-48, ft, fs, cc); - opn = condnames_abs[func-48]; } else { gen_cmp_ps(ctx, func-48, ft, fs, cc); - opn = condnames[func-48]; } - optype = CMPOP; break; default: - MIPS_INVAL(opn); - generate_exception (ctx, EXCP_RI); + MIPS_INVAL("farith"); + generate_exception_end(ctx, EXCP_RI); return; } - (void)opn; /* avoid a compiler warning */ - switch (optype) { - case BINOP: - MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]); - break; - case CMPOP: - MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]); - break; - default: - MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]); - break; - } } /* Coprocessor 3 (FPU) */ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, int fd, int fs, int base, int index) { - const char *opn = "extended float load/store"; - int store = 0; TCGv t0 = tcg_temp_new(); if (base == 0) { @@ -10529,7 +10164,6 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, gen_store_fpr32(ctx, fp0, fd); tcg_temp_free_i32(fp0); } - opn = "lwxc1"; break; case OPC_LDXC1: check_cop1x(ctx); @@ -10540,7 +10174,6 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "ldxc1"; break; case OPC_LUXC1: check_cp1_64bitmode(ctx); @@ -10552,7 +10185,6 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } - opn = "luxc1"; break; case OPC_SWXC1: check_cop1x(ctx); @@ -10562,8 +10194,6 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL); tcg_temp_free_i32(fp0); } - opn = "swxc1"; - store = 1; break; case OPC_SDXC1: check_cop1x(ctx); @@ -10574,8 +10204,6 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ); tcg_temp_free_i64(fp0); } - opn = "sdxc1"; - store = 1; break; case OPC_SUXC1: check_cp1_64bitmode(ctx); @@ -10586,21 +10214,14 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ); tcg_temp_free_i64(fp0); } - opn = "suxc1"; - store = 1; break; } tcg_temp_free(t0); - (void)opn; (void)store; /* avoid compiler warnings */ - MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd], - regnames[index], regnames[base]); } static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, int fd, int fr, int fs, int ft) { - const char *opn = "flt3_arith"; - switch (opc) { case OPC_ALNV_PS: check_ps(ctx); @@ -10638,7 +10259,6 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, tcg_temp_free_i32(fp); tcg_temp_free_i32(fph); } - opn = "alnv.ps"; break; case OPC_MADD_S: check_cop1x(ctx); @@ -10656,7 +10276,6 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_store_fpr32(ctx, fp2, fd); tcg_temp_free_i32(fp2); } - opn = "madd.s"; break; case OPC_MADD_D: check_cop1x(ctx); @@ -10675,7 +10294,6 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_store_fpr64(ctx, fp2, fd); tcg_temp_free_i64(fp2); } - opn = "madd.d"; break; case OPC_MADD_PS: check_ps(ctx); @@ -10693,7 +10311,6 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_store_fpr64(ctx, fp2, fd); tcg_temp_free_i64(fp2); } - opn = "madd.ps"; break; case OPC_MSUB_S: check_cop1x(ctx); @@ -10711,7 +10328,6 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_store_fpr32(ctx, fp2, fd); tcg_temp_free_i32(fp2); } - opn = "msub.s"; break; case OPC_MSUB_D: check_cop1x(ctx); @@ -10730,7 +10346,6 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_store_fpr64(ctx, fp2, fd); tcg_temp_free_i64(fp2); } - opn = "msub.d"; break; case OPC_MSUB_PS: check_ps(ctx); @@ -10748,7 +10363,6 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_store_fpr64(ctx, fp2, fd); tcg_temp_free_i64(fp2); } - opn = "msub.ps"; break; case OPC_NMADD_S: check_cop1x(ctx); @@ -10766,7 +10380,6 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_store_fpr32(ctx, fp2, fd); tcg_temp_free_i32(fp2); } - opn = "nmadd.s"; break; case OPC_NMADD_D: check_cop1x(ctx); @@ -10785,7 +10398,6 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_store_fpr64(ctx, fp2, fd); tcg_temp_free_i64(fp2); } - opn = "nmadd.d"; break; case OPC_NMADD_PS: check_ps(ctx); @@ -10803,7 +10415,6 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_store_fpr64(ctx, fp2, fd); tcg_temp_free_i64(fp2); } - opn = "nmadd.ps"; break; case OPC_NMSUB_S: check_cop1x(ctx); @@ -10821,7 +10432,6 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_store_fpr32(ctx, fp2, fd); tcg_temp_free_i32(fp2); } - opn = "nmsub.s"; break; case OPC_NMSUB_D: check_cop1x(ctx); @@ -10840,7 +10450,6 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_store_fpr64(ctx, fp2, fd); tcg_temp_free_i64(fp2); } - opn = "nmsub.d"; break; case OPC_NMSUB_PS: check_ps(ctx); @@ -10858,19 +10467,15 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_store_fpr64(ctx, fp2, fd); tcg_temp_free_i64(fp2); } - opn = "nmsub.ps"; break; default: - MIPS_INVAL(opn); - generate_exception (ctx, EXCP_RI); + MIPS_INVAL("flt3_arith"); + generate_exception_end(ctx, EXCP_RI); return; } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr], - fregnames[fs], fregnames[ft]); } -static void gen_rdhwr(DisasContext *ctx, int rt, int rd) +static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel) { TCGv t0; @@ -10883,25 +10488,37 @@ static void gen_rdhwr(DisasContext *ctx, int rt, int rd) switch (rd) { case 0: - save_cpu_state(ctx, 1); gen_helper_rdhwr_cpunum(t0, cpu_env); gen_store_gpr(t0, rt); break; case 1: - save_cpu_state(ctx, 1); gen_helper_rdhwr_synci_step(t0, cpu_env); gen_store_gpr(t0, rt); break; case 2: - save_cpu_state(ctx, 1); gen_helper_rdhwr_cc(t0, cpu_env); gen_store_gpr(t0, rt); break; case 3: - save_cpu_state(ctx, 1); gen_helper_rdhwr_ccres(t0, cpu_env); gen_store_gpr(t0, rt); break; + case 4: + check_insn(ctx, ISA_MIPS32R6); + if (sel != 0) { + /* Performance counter registers are not implemented other than + * control register 0. + */ + generate_exception(ctx, EXCP_RI); + } + gen_helper_rdhwr_performance(t0, cpu_env); + gen_store_gpr(t0, rt); + break; + case 5: + check_insn(ctx, ISA_MIPS32R6); + gen_helper_rdhwr_xnp(t0, cpu_env); + gen_store_gpr(t0, rt); + break; case 29: #if defined(CONFIG_USER_ONLY) tcg_gen_ld_tl(t0, cpu_env, @@ -10915,13 +10532,13 @@ static void gen_rdhwr(DisasContext *ctx, int rt, int rd) offsetof(CPUMIPSState, active_tc.CP0_UserLocal)); gen_store_gpr(t0, rt); } else { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } break; #endif default: /* Invalid */ MIPS_INVAL("rdhwr"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } tcg_temp_free(t0); @@ -10949,12 +10566,10 @@ static void gen_branch(DisasContext *ctx, int insn_bytes) /* FIXME: Need to clear can_do_io. */ switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) { case MIPS_HFLAG_FBNSLOT: - MIPS_DEBUG("forbidden slot"); gen_goto_tb(ctx, 0, ctx->pc + insn_bytes); break; case MIPS_HFLAG_B: /* unconditional branch */ - MIPS_DEBUG("unconditional branch"); if (proc_hflags & MIPS_HFLAG_BX) { tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16); } @@ -10962,12 +10577,10 @@ static void gen_branch(DisasContext *ctx, int insn_bytes) break; case MIPS_HFLAG_BL: /* blikely taken case */ - MIPS_DEBUG("blikely branch taken"); gen_goto_tb(ctx, 0, ctx->btarget); break; case MIPS_HFLAG_BC: /* Conditional branch */ - MIPS_DEBUG("conditional branch"); { TCGLabel *l1 = gen_new_label(); @@ -10979,7 +10592,6 @@ static void gen_branch(DisasContext *ctx, int insn_bytes) break; case MIPS_HFLAG_BR: /* unconditional branch to register */ - MIPS_DEBUG("branch to register"); if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) { TCGv t0 = tcg_temp_new(); TCGv_i32 t1 = tcg_temp_new_i32(); @@ -10998,7 +10610,7 @@ static void gen_branch(DisasContext *ctx, int insn_bytes) } if (ctx->singlestep_enabled) { save_cpu_state(ctx, 0); - gen_helper_0e0i(raise_exception, EXCP_DEBUG); + gen_helper_raise_exception_debug(cpu_env); } tcg_gen_exit_tb(0); break; @@ -11023,7 +10635,7 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc, LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc); #endif - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); goto out; } @@ -11085,7 +10697,7 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc, break; default: MIPS_INVAL("Compact branch/jump"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); goto out; } @@ -11106,7 +10718,7 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc, break; default: MIPS_INVAL("Compact branch/jump"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); goto out; } @@ -11229,7 +10841,7 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc, break; default: MIPS_INVAL("Compact conditional branch/jump"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); goto out; } @@ -11238,7 +10850,6 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc, gen_set_label(fs); ctx->hflags |= MIPS_HFLAG_FBNSLOT; - MIPS_DEBUG("Compact conditional branch"); } out: @@ -11404,7 +11015,7 @@ static void gen_mips16_save (DisasContext *ctx, args = 4; break; default: - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); return; } @@ -11500,7 +11111,7 @@ static void gen_mips16_save (DisasContext *ctx, astatic = 4; break; default: - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); return; } @@ -11606,7 +11217,7 @@ static void gen_mips16_restore (DisasContext *ctx, astatic = 4; break; default: - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); return; } @@ -11637,7 +11248,7 @@ static void gen_addiupc (DisasContext *ctx, int rx, int imm, TCGv t0; if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); return; } @@ -11652,6 +11263,15 @@ static void gen_addiupc (DisasContext *ctx, int rx, int imm, tcg_temp_free(t0); } +static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base, + int16_t offset) +{ + TCGv_i32 t0 = tcg_const_i32(op); + TCGv t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t1, base, offset); + gen_helper_cache(cpu_env, t1, t0); +} + #if defined(TARGET_MIPS64) static void decode_i64_mips16 (DisasContext *ctx, int ry, int funct, int16_t offset, @@ -11686,7 +11306,7 @@ static void decode_i64_mips16 (DisasContext *ctx, check_insn(ctx, ISA_MIPS3); check_mips_64(ctx); if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } else { offset = extended ? offset : offset << 3; gen_ld(ctx, OPC_LDPC, ry, 0, offset); @@ -11761,7 +11381,7 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx) check_mips_64(ctx); gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa); #else - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); #endif break; case 0x2: @@ -11789,7 +11409,7 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx) check_mips_64(ctx); gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm); #else - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); #endif } else { gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm); @@ -11841,7 +11461,7 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx) } break; default: - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -11904,7 +11524,7 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx) break; #endif default: - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } @@ -11985,7 +11605,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx) check_mips_64(ctx); gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa); #else - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); #endif break; case 0x2: @@ -12013,7 +11633,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx) check_mips_64(ctx); gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm); #else - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); #endif } else { gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm); @@ -12097,7 +11717,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx) gen_arith(ctx, OPC_ADDU, ry, reg32, 0); break; default: - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } } @@ -12187,7 +11807,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx) break; #endif default: - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); goto done; } @@ -12226,7 +11846,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx) * when in debug mode... */ check_insn(ctx, ISA_MIPS32); - generate_exception(ctx, EXCP_DBp); + generate_exception_end(ctx, EXCP_DBp); } break; case RR_SLT: @@ -12236,7 +11856,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx) gen_slt(ctx, OPC_SLTU, 24, rx, ry); break; case RR_BREAK: - generate_exception(ctx, EXCP_BREAK); + generate_exception_end(ctx, EXCP_BREAK); break; case RR_SLLV: gen_shift(ctx, OPC_SLLV, ry, rx, ry); @@ -12303,7 +11923,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx) break; #endif default: - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -12367,7 +11987,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx) break; #endif default: - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -12382,7 +12002,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx) break; #endif default: - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } @@ -12526,6 +12146,7 @@ enum { ROTR = 0x3, SELEQZ = 0x5, SELNEZ = 0x6, + R6_RDHWR = 0x7, SLLV = 0x0, SRLV = 0x1, @@ -12556,11 +12177,13 @@ enum { MODU = 0x7, /* The following can be distinguished by their lower 6 bits. */ + BREAK32 = 0x07, INS = 0x0c, LSA = 0x0f, ALIGN = 0x1f, EXT = 0x2c, - POOL32AXF = 0x3c + POOL32AXF = 0x3c, + SIGRIE = 0x3f }; /* POOL32AXF encoding of minor opcode field extension */ @@ -13029,12 +12652,11 @@ static void gen_andi16(DisasContext *ctx) static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist, int base, int16_t offset) { - const char *opn = "ldst_multiple"; TCGv t0, t1; TCGv_i32 t2; if (ctx->hflags & MIPS_HFLAG_BMASK) { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); return; } @@ -13049,25 +12671,19 @@ static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist, switch (opc) { case LWM32: gen_helper_lwm(cpu_env, t0, t1, t2); - opn = "lwm"; break; case SWM32: gen_helper_swm(cpu_env, t0, t1, t2); - opn = "swm"; break; #ifdef TARGET_MIPS64 case LDM: gen_helper_ldm(cpu_env, t0, t1, t2); - opn = "ldm"; break; case SDM: gen_helper_sdm(cpu_env, t0, t1, t2); - opn = "sdm"; break; #endif } - (void)opn; - MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]); tcg_temp_free(t0); tcg_temp_free(t1); tcg_temp_free_i32(t2); @@ -13164,7 +12780,7 @@ static void gen_pool16c_insn(DisasContext *ctx) gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode)); break; case BREAK16: - generate_exception(ctx, EXCP_BREAK); + generate_exception_end(ctx, EXCP_BREAK); break; case SDBBP16: if (is_uhi(extract32(ctx->opcode, 0, 4))) { @@ -13174,7 +12790,7 @@ static void gen_pool16c_insn(DisasContext *ctx) * when in debug mode... */ check_insn(ctx, ISA_MIPS32); - generate_exception(ctx, EXCP_DBp); + generate_exception_end(ctx, EXCP_DBp); } break; case JRADDIUSP + 0: @@ -13188,7 +12804,7 @@ static void gen_pool16c_insn(DisasContext *ctx) } break; default: - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } } @@ -13324,11 +12940,10 @@ static void gen_ldxs (DisasContext *ctx, int base, int index, int rd) static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd, int base, int16_t offset) { - const char *opn = "ldst_pair"; TCGv t0, t1; if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); return; } @@ -13340,7 +12955,7 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd, switch (opc) { case LWP: if (rd == base) { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); return; } tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); @@ -13349,7 +12964,6 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd, gen_op_addr_add(ctx, t0, t0, t1); tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); gen_store_gpr(t1, rd+1); - opn = "lwp"; break; case SWP: gen_load_gpr(t1, rd); @@ -13358,12 +12972,11 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd, gen_op_addr_add(ctx, t0, t0, t1); gen_load_gpr(t1, rd+1); tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); - opn = "swp"; break; #ifdef TARGET_MIPS64 case LDP: if (rd == base) { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); return; } tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ); @@ -13372,7 +12985,6 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd, gen_op_addr_add(ctx, t0, t0, t1); tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ); gen_store_gpr(t1, rd+1); - opn = "ldp"; break; case SDP: gen_load_gpr(t1, rd); @@ -13381,12 +12993,9 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd, gen_op_addr_add(ctx, t0, t0, t1); gen_load_gpr(t1, rd+1); tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ); - opn = "sdp"; break; #endif } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]); tcg_temp_free(t0); tcg_temp_free(t1); } @@ -13492,7 +13101,8 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs) gen_cl(ctx, mips32_op, rt, rs); break; case RDHWR: - gen_rdhwr(ctx, rt, rs); + check_insn_opc_removed(ctx, ISA_MIPS32R6); + gen_rdhwr(ctx, rt, rs, 0); break; case WSBH: gen_bshfl(ctx, OPC_WSBH, rs, rt); @@ -13668,8 +13278,7 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs) /* NOP */ break; case SYSCALL: - generate_exception(ctx, EXCP_SYSCALL); - ctx->bstate = BS_STOP; + generate_exception_end(ctx, EXCP_SYSCALL); break; case SDBBP: if (is_uhi(extract32(ctx->opcode, 16, 10))) { @@ -13677,9 +13286,9 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs) } else { check_insn(ctx, ISA_MIPS32); if (ctx->hflags & MIPS_HFLAG_SBRI) { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } else { - generate_exception(ctx, EXCP_DBp); + generate_exception_end(ctx, EXCP_DBp); } } break; @@ -13727,7 +13336,7 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs) default: pool32axf_invalid: MIPS_INVAL("pool32axf"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } } @@ -13995,7 +13604,7 @@ static void gen_pool32fxf(DisasContext *ctx, int rt, int rs) break; default: MIPS_INVAL("pool32fxf"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } } @@ -14048,6 +13657,10 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) check_insn(ctx, ISA_MIPS32R6); gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt); break; + case R6_RDHWR: + check_insn(ctx, ISA_MIPS32R6); + gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3)); + break; default: goto pool32a_invalid; } @@ -14191,13 +13804,17 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) case POOL32AXF: gen_pool32axf(env, ctx, rt, rs); break; - case 0x07: - generate_exception(ctx, EXCP_BREAK); + case BREAK32: + generate_exception_end(ctx, EXCP_BREAK); + break; + case SIGRIE: + check_insn(ctx, ISA_MIPS32R6); + generate_exception_end(ctx, EXCP_RI); break; default: pool32a_invalid: MIPS_INVAL("pool32a"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -14206,7 +13823,9 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) switch (minor) { case CACHE: check_cp0_enabled(ctx); - /* Treat as no-op. */ + if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) { + gen_cache_operation(ctx, rt, rs, imm); + } break; case LWC2: case SWC2: @@ -14237,7 +13856,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) break; default: MIPS_INVAL("pool32b"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -14717,7 +14336,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) default: pool32f_invalid: MIPS_INVAL("pool32f"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } } else { @@ -14873,7 +14492,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) /* Fall through */ default: MIPS_INVAL("pool32i"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -14962,7 +14581,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) break; default: MIPS_INVAL("pool32c"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -15240,7 +14859,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) gen_st(ctx, mips32_op, rt, rs, imm); break; default: - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } } @@ -15252,8 +14871,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx) /* make sure instructions are on a halfword boundary */ if (ctx->pc & 0x1) { env->CP0_BadVAddr = ctx->pc; - generate_exception(ctx, EXCP_AdEL); - ctx->bstate = BS_STOP; + generate_exception_end(ctx, EXCP_AdEL); return 2; } @@ -15272,9 +14890,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx) case 7: /* LB32, LH32, LWC132, LDC132, LW32 */ if (ctx->hflags & MIPS_HFLAG_BDS16) { - generate_exception(ctx, EXCP_RI); - /* Just stop translation; the user is confused. */ - ctx->bstate = BS_STOP; + generate_exception_end(ctx, EXCP_RI); return 2; } break; @@ -15285,9 +14901,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx) case 3: /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */ if (ctx->hflags & MIPS_HFLAG_BDS32) { - generate_exception(ctx, EXCP_RI); - /* Just stop translation; the user is confused. */ - ctx->bstate = BS_STOP; + generate_exception_end(ctx, EXCP_RI); return 2; } break; @@ -15359,7 +14973,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx) case POOL16F: check_insn_opc_removed(ctx, ISA_MIPS32R6); if (ctx->opcode & 1) { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } else { /* MOVEP */ int enc_dest = uMIPS_RD(ctx->opcode); @@ -15497,7 +15111,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx) case RES_29: case RES_31: case RES_39: - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; default: decode_micromips32_opc(env, ctx); @@ -15519,7 +15133,6 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx) static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc, int rd, int base, int offset) { - const char *opn = "ldx"; TCGv t0; check_dsp(ctx); @@ -15537,42 +15150,33 @@ static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc, case OPC_LBUX: tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB); gen_store_gpr(t0, rd); - opn = "lbux"; break; case OPC_LHX: tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW); gen_store_gpr(t0, rd); - opn = "lhx"; break; case OPC_LWX: tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL); gen_store_gpr(t0, rd); - opn = "lwx"; break; #if defined(TARGET_MIPS64) case OPC_LDX: tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ); gen_store_gpr(t0, rd); - opn = "ldx"; break; #endif } - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s %s, %s(%s)", opn, - regnames[rd], regnames[offset], regnames[base]); tcg_temp_free(t0); } static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2, int ret, int v1, int v2) { - const char *opn = "mipsdsp arith"; TCGv v1_t; TCGv v2_t; if (ret == 0) { /* Treat as NOP. */ - MIPS_DEBUG("NOP"); return; } @@ -16012,23 +15616,18 @@ static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2, tcg_temp_free(v1_t); tcg_temp_free(v2_t); - - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s", opn); } static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc, int ret, int v1, int v2) { uint32_t op2; - const char *opn = "mipsdsp shift"; TCGv t0; TCGv v1_t; TCGv v2_t; if (ret == 0) { /* Treat as NOP. */ - MIPS_DEBUG("NOP"); return; } @@ -16135,7 +15734,7 @@ static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc, break; default: /* Invalid */ MIPS_INVAL("MASK SHLL.QB"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -16250,7 +15849,7 @@ static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc, break; default: /* Invalid */ MIPS_INVAL("MASK SHLL.OB"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -16260,21 +15859,17 @@ static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc, tcg_temp_free(t0); tcg_temp_free(v1_t); tcg_temp_free(v2_t); - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s", opn); } static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2, int ret, int v1, int v2, int check_ret) { - const char *opn = "mipsdsp multiply"; TCGv_i32 t0; TCGv v1_t; TCGv v2_t; if ((ret == 0) && (check_ret == 1)) { /* Treat as NOP. */ - MIPS_DEBUG("NOP"); return; } @@ -16572,23 +16167,17 @@ static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2, tcg_temp_free_i32(t0); tcg_temp_free(v1_t); tcg_temp_free(v2_t); - - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s", opn); - } static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2, int ret, int val) { - const char *opn = "mipsdsp Bit/ Manipulation"; int16_t imm; TCGv t0; TCGv val_t; if (ret == 0) { /* Treat as NOP. */ - MIPS_DEBUG("NOP"); return; } @@ -16716,23 +16305,18 @@ static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2, } tcg_temp_free(t0); tcg_temp_free(val_t); - - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s", opn); } static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx, uint32_t op1, uint32_t op2, int ret, int v1, int v2, int check_ret) { - const char *opn = "mipsdsp add compare pick"; TCGv t1; TCGv v1_t; TCGv v2_t; if ((ret == 0) && (check_ret == 1)) { /* Treat as NOP. */ - MIPS_DEBUG("NOP"); return; } @@ -16907,22 +16491,17 @@ static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx, tcg_temp_free(t1); tcg_temp_free(v1_t); tcg_temp_free(v2_t); - - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s", opn); } static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx, uint32_t op1, int rt, int rs, int sa) { - const char *opn = "mipsdsp append/dappend"; TCGv t0; check_dspr2(ctx); if (rt == 0) { /* Treat as NOP. */ - MIPS_DEBUG("NOP"); return; } @@ -16959,7 +16538,7 @@ static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx, break; default: /* Invalid */ MIPS_INVAL("MASK APPEND"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -16993,22 +16572,19 @@ static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx, break; default: /* Invalid */ MIPS_INVAL("MASK DAPPEND"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; #endif } tcg_temp_free(t0); - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s", opn); } static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2, int ret, int v1, int v2, int check_ret) { - const char *opn = "mipsdsp accumulator"; TCGv t0; TCGv t1; TCGv v1_t; @@ -17017,7 +16593,6 @@ static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2, if ((ret == 0) && (check_ret == 1)) { /* Treat as NOP. */ - MIPS_DEBUG("NOP"); return; } @@ -17229,9 +16804,6 @@ static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2, tcg_temp_free(t1); tcg_temp_free(v1_t); tcg_temp_free(v2_t); - - (void)opn; /* avoid a compiler warning */ - MIPS_DEBUG("%s", opn); } /* End MIPSDSP functions. */ @@ -17266,7 +16838,7 @@ static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx) break; default: MIPS_INVAL("special_r6 muldiv"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -17281,7 +16853,7 @@ static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx) We need additionally to check other fields */ gen_cl(ctx, op1, rd, rs); } else { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } break; case R6_OPC_SDBBP: @@ -17289,9 +16861,9 @@ static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx) gen_helper_do_semihosting(cpu_env); } else { if (ctx->hflags & MIPS_HFLAG_SBRI) { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } else { - generate_exception(ctx, EXCP_DBp); + generate_exception_end(ctx, EXCP_DBp); } } break; @@ -17308,7 +16880,7 @@ static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx) check_mips_64(ctx); gen_cl(ctx, op1, rd, rs); } else { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } break; case OPC_DMULT ... OPC_DDIVU: @@ -17327,14 +16899,14 @@ static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx) break; default: MIPS_INVAL("special_r6 muldiv"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; #endif default: /* Invalid */ MIPS_INVAL("special_r6"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } } @@ -17402,16 +16974,16 @@ static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx) case OPC_SPIM: #ifdef MIPS_STRICT_STANDARD MIPS_INVAL("SPIM"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); #else /* Implemented as RI exception for now. */ MIPS_INVAL("spim (unofficial)"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); #endif break; default: /* Invalid */ MIPS_INVAL("special_legacy"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } } @@ -17433,8 +17005,7 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) rs == 0 && rt == 0) { /* PAUSE */ if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) { - MIPS_DEBUG("CTI in delay / forbidden slot"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } } @@ -17454,7 +17025,7 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) gen_shift_imm(ctx, op1, rd, rt, sa); break; default: - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -17477,7 +17048,7 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) gen_shift(ctx, op1, rd, rs, rt); break; default: - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -17507,18 +17078,17 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) /* Pmon entry point, also R4010 selsl */ #ifdef MIPS_STRICT_STANDARD MIPS_INVAL("PMON / selsl"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); #else gen_helper_0e0i(pmon, sa); #endif } break; case OPC_SYSCALL: - generate_exception(ctx, EXCP_SYSCALL); - ctx->bstate = BS_STOP; + generate_exception_end(ctx, EXCP_SYSCALL); break; case OPC_BREAK: - generate_exception(ctx, EXCP_BREAK); + generate_exception_end(ctx, EXCP_BREAK); break; case OPC_SYNC: check_insn(ctx, ISA_MIPS2); @@ -17549,7 +17119,7 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) gen_shift_imm(ctx, op1, rd, rt, sa); break; default: - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -17567,7 +17137,7 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) gen_shift_imm(ctx, op1, rd, rt, sa); break; default: - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -17596,7 +17166,7 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) gen_shift(ctx, op1, rd, rs, rt); break; default: - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -17659,7 +17229,7 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx) * when in debug mode... */ check_insn(ctx, ISA_MIPS32); - generate_exception(ctx, EXCP_DBp); + generate_exception_end(ctx, EXCP_DBp); } break; #if defined(TARGET_MIPS64) @@ -17681,7 +17251,7 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx) #endif default: /* Invalid */ MIPS_INVAL("special2_legacy"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } } @@ -17703,12 +17273,15 @@ static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx) case R6_OPC_PREF: if (rt >= 24) { /* hint codes 24-31 are reserved and signal RI */ - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } /* Treat as NOP. */ break; case R6_OPC_CACHE: - /* Treat as NOP. */ + check_cp0_enabled(ctx); + if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) { + gen_cache_operation(ctx, rt, rs, imm); + } break; case R6_OPC_SC: gen_st_cond(ctx, op1, rt, rs, imm); @@ -17762,7 +17335,7 @@ static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx) #endif default: /* Invalid */ MIPS_INVAL("special3_r6"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } } @@ -17808,13 +17381,13 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) break; default: MIPS_INVAL("MASK ADDUH.QB"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } } else if (ctx->insn_flags & INSN_LOONGSON2E) { gen_loongson_integer(ctx, op1, rd, rs, rt); } else { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } break; case OPC_LX_DSP: @@ -17830,7 +17403,7 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) break; default: /* Invalid */ MIPS_INVAL("MASK LX"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -17861,7 +17434,7 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) break; default: MIPS_INVAL("MASK ABSQ_S.PH"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -17898,7 +17471,7 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) break; default: /* Invalid */ MIPS_INVAL("MASK ADDU.QB"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } @@ -17938,7 +17511,7 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) break; default: /* Invalid */ MIPS_INVAL("MASK CMPU.EQ.QB"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -17974,7 +17547,7 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) break; default: /* Invalid */ MIPS_INVAL("MASK DPAW.PH"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -17987,7 +17560,6 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) TCGv t0, t1; if (rt == 0) { - MIPS_DEBUG("NOP"); break; } @@ -18005,7 +17577,7 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) } default: /* Invalid */ MIPS_INVAL("MASK INSV"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -18040,7 +17612,7 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) break; default: /* Invalid */ MIPS_INVAL("MASK EXTR.W"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -18083,7 +17655,7 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) break; default: /* Invalid */ MIPS_INVAL("MASK ABSQ_S.QH"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -18122,7 +17694,7 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) break; default: /* Invalid */ MIPS_INVAL("MASK ADDU.OB"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -18167,7 +17739,7 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) break; default: /* Invalid */ MIPS_INVAL("MASK CMPU_EQ.OB"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -18204,7 +17776,7 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) break; default: /* Invalid */ MIPS_INVAL("MASK EXTR.W"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -18243,7 +17815,7 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) break; default: /* Invalid */ MIPS_INVAL("MASK DPAQ.W.QH"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -18255,7 +17827,6 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) TCGv t0, t1; if (rt == 0) { - MIPS_DEBUG("NOP"); break; } check_dsp(ctx); @@ -18274,7 +17845,7 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) } default: /* Invalid */ MIPS_INVAL("MASK DINSV"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -18284,7 +17855,7 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) #endif default: /* Invalid */ MIPS_INVAL("special3_legacy"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } } @@ -18345,7 +17916,7 @@ static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx) break; #endif case OPC_RDHWR: - gen_rdhwr(ctx, rt, rd); + gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3)); break; case OPC_FORK: check_insn(ctx, ASE_MT); @@ -18365,7 +17936,6 @@ static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx) { TCGv t0 = tcg_temp_new(); - save_cpu_state(ctx, 1); gen_load_gpr(t0, rs); gen_helper_yield(t0, cpu_env, t0); gen_store_gpr(t0, rd); @@ -18386,16 +17956,16 @@ static inline int check_msa_access(DisasContext *ctx) { if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) && !(ctx->hflags & MIPS_HFLAG_F64))) { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); return 0; } if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) { if (ctx->insn_flags & ASE_MSA) { - generate_exception(ctx, EXCP_MSADIS); + generate_exception_end(ctx, EXCP_MSADIS); return 0; } else { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); return 0; } } @@ -18452,8 +18022,7 @@ static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1) check_msa_access(ctx); if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) { - MIPS_DEBUG("CTI in delay / forbidden slot"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); return; } switch (op1) { @@ -18528,7 +18097,7 @@ static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx) { uint8_t df = (ctx->opcode >> 24) & 0x3; if (df == DF_DOUBLE) { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } else { TCGv_i32 tdf = tcg_const_i32(df); gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8); @@ -18538,7 +18107,7 @@ static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx) break; default: MIPS_INVAL("MSA instruction"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } @@ -18610,7 +18179,7 @@ static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx) break; default: MIPS_INVAL("MSA instruction"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } @@ -18646,7 +18215,7 @@ static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx) m = dfm & 0x7; df = DF_BYTE; } else { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); return; } @@ -18694,7 +18263,7 @@ static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx) break; default: MIPS_INVAL("MSA instruction"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } @@ -18889,7 +18458,8 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx) case OPC_HSUB_S_df: case OPC_HSUB_U_df: if (df == DF_BYTE) { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); + break; } switch (MASK_MSA_3R(ctx->opcode)) { case OPC_DOTP_S_df: @@ -18926,7 +18496,7 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx) break; default: MIPS_INVAL("MSA instruction"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } tcg_temp_free_i32(twd); @@ -18958,7 +18528,7 @@ static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx) break; default: MIPS_INVAL("MSA instruction"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } @@ -18995,7 +18565,7 @@ static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df, #if !defined(TARGET_MIPS64) /* Double format valid only for MIPS64 */ if (df == DF_DOUBLE) { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } #endif @@ -19013,7 +18583,7 @@ static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df, break; default: MIPS_INVAL("MSA instruction"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } tcg_temp_free_i32(twd); tcg_temp_free_i32(tws); @@ -19043,7 +18613,7 @@ static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx) gen_msa_elm_3e(env, ctx); return; } else { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); return; } @@ -19198,7 +18768,7 @@ static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx) break; default: MIPS_INVAL("MSA instruction"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } @@ -19226,7 +18796,7 @@ static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx) #if !defined(TARGET_MIPS64) /* Double format valid only for MIPS64 */ if (df == DF_DOUBLE) { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } #endif @@ -19243,7 +18813,7 @@ static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx) break; default: MIPS_INVAL("MSA instruction"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } @@ -19358,7 +18928,7 @@ static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx) break; default: MIPS_INVAL("MSA instruction"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } @@ -19387,7 +18957,7 @@ static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx) break; default: MIPS_INVAL("MSA instruction"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } } @@ -19485,7 +19055,7 @@ static void gen_msa(CPUMIPSState *env, DisasContext *ctx) break; default: MIPS_INVAL("MSA instruction"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } @@ -19502,7 +19072,6 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) if (ctx->pc & 0x3) { env->CP0_BadVAddr = ctx->pc; generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL); - ctx->bstate = BS_STOP; return; } @@ -19510,17 +19079,12 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) { TCGLabel *l1 = gen_new_label(); - MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4); tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1); tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK); gen_goto_tb(ctx, 1, ctx->pc + 4); gen_set_label(l1); } - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(ctx->pc); - } - op = MASK_OP_MAJOR(ctx->opcode); rs = (ctx->opcode >> 21) & 0x1f; rt = (ctx->opcode >> 16) & 0x1f; @@ -19558,7 +19122,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) /* OPC_NAL, OPC_BAL */ gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4); } else { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } } else { gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4); @@ -19570,6 +19134,10 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) check_insn_opc_removed(ctx, ISA_MIPS32R6); gen_trap(ctx, op1, rs, -1, imm); break; + case OPC_SIGRIE: + check_insn(ctx, ISA_MIPS32R6); + generate_exception_end(ctx, EXCP_RI); + break; case OPC_SYNCI: check_insn(ctx, ISA_MIPS32R2); /* Break the TB to be able to sync copied instructions @@ -19590,7 +19158,6 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) if (rs != 0) { tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32); } - MIPS_DEBUG("dahi %s, %04x", regnames[rs], imm); break; case OPC_DATI: check_insn(ctx, ISA_MIPS32R6); @@ -19598,12 +19165,11 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) if (rs != 0) { tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48); } - MIPS_DEBUG("dati %s, %04x", regnames[rs], imm); break; #endif default: /* Invalid */ MIPS_INVAL("regimm"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -19658,6 +19224,20 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) gen_helper_evpe(t0, cpu_env); gen_store_gpr(t0, rt); break; + case OPC_DVP: + check_insn(ctx, ISA_MIPS32R6); + if (ctx->vp) { + gen_helper_dvp(t0, cpu_env); + gen_store_gpr(t0, rt); + } + break; + case OPC_EVP: + check_insn(ctx, ISA_MIPS32R6); + if (ctx->vp) { + gen_helper_evp(t0, cpu_env); + gen_store_gpr(t0, rt); + } + break; case OPC_DI: check_insn(ctx, ISA_MIPS32R2); save_cpu_state(ctx, 1); @@ -19678,7 +19258,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) break; default: /* Invalid */ MIPS_INVAL("mfmc0"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } tcg_temp_free(t0); @@ -19695,7 +19275,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) break; default: MIPS_INVAL("cp0"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -19730,7 +19310,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */ if (ctx->insn_flags & ISA_MIPS32R6) { if (rt == 0) { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */ @@ -19743,7 +19323,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */ if (ctx->insn_flags & ISA_MIPS32R6) { if (rt == 0) { - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */ @@ -19810,6 +19390,9 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) check_insn_opc_removed(ctx, ISA_MIPS32R6); check_cp0_enabled(ctx); check_insn(ctx, ISA_MIPS3 | ISA_MIPS32); + if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) { + gen_cache_operation(ctx, rt, rs, imm); + } /* Treat as NOP. */ break; case OPC_PREF: @@ -19973,7 +19556,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) break; default: MIPS_INVAL("cp1"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } break; @@ -20055,7 +19638,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) break; default: MIPS_INVAL("cp3"); - generate_exception (ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } } else { @@ -20111,7 +19694,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) gen_compute_compact_branch(ctx, op, rs, rt, imm << 2); } else { MIPS_INVAL("major opcode"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); } break; #endif @@ -20120,15 +19703,16 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) #if defined(TARGET_MIPS64) /* OPC_DAUI */ check_mips_64(ctx); - if (rt != 0) { + if (rs == 0) { + generate_exception(ctx, EXCP_RI); + } else if (rt != 0) { TCGv t0 = tcg_temp_new(); gen_load_gpr(t0, rs); tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16); tcg_temp_free(t0); } - MIPS_DEBUG("daui %s, %s, %04x", regnames[rt], regnames[rs], imm); #else - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); MIPS_INVAL("major opcode"); #endif } else { @@ -20148,30 +19732,23 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) break; default: /* Invalid */ MIPS_INVAL("major opcode"); - generate_exception(ctx, EXCP_RI); + generate_exception_end(ctx, EXCP_RI); break; } } -static inline void -gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, - bool search_pc) +void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb) { + MIPSCPU *cpu = mips_env_get_cpu(env); CPUState *cs = CPU(cpu); - CPUMIPSState *env = &cpu->env; DisasContext ctx; target_ulong pc_start; target_ulong next_page_start; - CPUBreakpoint *bp; - int j, lj = -1; int num_insns; int max_insns; int insn_bytes; int is_slot; - if (search_pc) - qemu_log("search pc %d\n", search_pc); - pc_start = tb->pc; next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; ctx.pc = pc_start; @@ -20181,6 +19758,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, ctx.CP0_Config1 = env->CP0_Config1; ctx.tb = tb; ctx.bstate = BS_NONE; + ctx.btarget = 0; ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff; ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1; ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3; @@ -20189,11 +19767,14 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, ctx.PAMask = env->PAMask; ctx.mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1; ctx.CP0_LLAddr_shift = env->CP0_LLAddr_shift; + ctx.cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1; /* Restore delay slot state from the tb context. */ ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */ ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1; ctx.ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) || (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)); + ctx.vp = (env->CP0_Config5 >> CP0C5_VP) & 1; + ctx.mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1; restore_cpu_state(env, &ctx); #ifdef CONFIG_USER_ONLY ctx.mem_idx = MIPS_HFLAG_UM; @@ -20204,40 +19785,34 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, MO_UNALN : MO_ALIGN; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; - if (max_insns == 0) + if (max_insns == 0) { max_insns = CF_COUNT_MASK; + } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } + LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags); gen_tb_start(tb); while (ctx.bstate == BS_NONE) { - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == ctx.pc) { - save_cpu_state(&ctx, 1); - ctx.bstate = BS_BRANCH; - gen_helper_0e0i(raise_exception, EXCP_DEBUG); - /* Include the breakpoint location or the tb won't - * be flushed when it must be. */ - ctx.pc += 4; - goto done_generating; - } - } - } + tcg_gen_insn_start(ctx.pc, ctx.hflags & MIPS_HFLAG_BMASK, ctx.btarget); + num_insns++; - if (search_pc) { - j = tcg_op_buf_count(); - if (lj < j) { - lj++; - while (lj < j) - tcg_ctx.gen_opc_instr_start[lj++] = 0; - } - tcg_ctx.gen_opc_pc[lj] = ctx.pc; - gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK; - gen_opc_btarget[lj] = ctx.btarget; - tcg_ctx.gen_opc_instr_start[lj] = 1; - tcg_ctx.gen_opc_icount[lj] = num_insns; + if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) { + save_cpu_state(&ctx, 1); + ctx.bstate = BS_BRANCH; + gen_helper_raise_exception_debug(cpu_env); + /* The address covered by the breakpoint must be included in + [tb->pc, tb->pc + tb->size) in order to for it to be + properly cleared -- thus we increment the PC here so that + the logic setting tb->size below does the right thing. */ + ctx.pc += 4; + goto done_generating; } - if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) + + if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); + } is_slot = ctx.hflags & MIPS_HFLAG_BMASK; if (!(ctx.hflags & MIPS_HFLAG_M16)) { @@ -20251,8 +19826,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, ctx.opcode = cpu_lduw_code(env, ctx.pc); insn_bytes = decode_mips16_opc(env, &ctx); } else { - generate_exception(&ctx, EXCP_RI); - ctx.bstate = BS_STOP; + generate_exception_end(&ctx, EXCP_RI); break; } @@ -20275,8 +19849,6 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, } ctx.pc += insn_bytes; - num_insns++; - /* Execute a branch and its delay slot as a single instruction. This is what GDB expects and is consistent with what the hardware does (e.g. if a delay slot instruction faults, the @@ -20304,7 +19876,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, } if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) { save_cpu_state(&ctx, ctx.bstate != BS_EXCP); - gen_helper_0e0i(raise_exception, EXCP_DEBUG); + gen_helper_raise_exception_debug(cpu_env); } else { switch (ctx.bstate) { case BS_STOP: @@ -20325,15 +19897,9 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, done_generating: gen_tb_end(tb, num_insns); - if (search_pc) { - j = tcg_op_buf_count(); - lj++; - while (lj <= j) - tcg_ctx.gen_opc_instr_start[lj++] = 0; - } else { - tb->size = ctx.pc - pc_start; - tb->icount = num_insns; - } + tb->size = ctx.pc - pc_start; + tb->icount = num_insns; + #ifdef DEBUG_DISAS LOG_DISAS("\n"); if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { @@ -20344,16 +19910,6 @@ done_generating: #endif } -void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(mips_env_get_cpu(env), tb, false); -} - -void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(mips_env_get_cpu(env), tb, true); -} - static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf, int flags) { @@ -20394,40 +19950,6 @@ static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fpri #undef printfpr } -#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS) -/* Debug help: The architecture requires 32bit code to maintain proper - sign-extended values on 64bit machines. */ - -#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff)) - -static void -cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f, - fprintf_function cpu_fprintf, - int flags) -{ - int i; - - if (!SIGN_EXT_P(env->active_tc.PC)) - cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC); - if (!SIGN_EXT_P(env->active_tc.HI[0])) - cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]); - if (!SIGN_EXT_P(env->active_tc.LO[0])) - cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]); - if (!SIGN_EXT_P(env->btarget)) - cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget); - - for (i = 0; i < 32; i++) { - if (!SIGN_EXT_P(env->active_tc.gpr[i])) - cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]); - } - - if (!SIGN_EXT_P(env->CP0_EPC)) - cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC); - if (!SIGN_EXT_P(env->lladdr)) - cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr); -} -#endif - void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, int flags) { @@ -20459,9 +19981,6 @@ void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, env->CP0_Config4, env->CP0_Config5); if (env->hflags & MIPS_HFLAG_FPU) fpu_dump_state(env, f, cpu_fprintf, flags); -#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS) - cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags); -#endif } void mips_tcg_init(void) @@ -20474,48 +19993,49 @@ void mips_tcg_init(void) return; cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); + TCGV_UNUSED(cpu_gpr[0]); for (i = 1; i < 32; i++) - cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0, + cpu_gpr[i] = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, active_tc.gpr[i]), regnames[i]); for (i = 0; i < 32; i++) { int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]); msa_wr_d[i * 2] = - tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2]); + tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]); /* The scalar floating-point unit (FPU) registers are mapped on * the MSA vector registers. */ fpu_f64[i] = msa_wr_d[i * 2]; off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]); msa_wr_d[i * 2 + 1] = - tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2 + 1]); + tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]); } - cpu_PC = tcg_global_mem_new(TCG_AREG0, + cpu_PC = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, active_tc.PC), "PC"); for (i = 0; i < MIPS_DSP_ACC; i++) { - cpu_HI[i] = tcg_global_mem_new(TCG_AREG0, + cpu_HI[i] = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, active_tc.HI[i]), regnames_HI[i]); - cpu_LO[i] = tcg_global_mem_new(TCG_AREG0, + cpu_LO[i] = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, active_tc.LO[i]), regnames_LO[i]); } - cpu_dspctrl = tcg_global_mem_new(TCG_AREG0, + cpu_dspctrl = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, active_tc.DSPControl), "DSPControl"); - bcond = tcg_global_mem_new(TCG_AREG0, + bcond = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, bcond), "bcond"); - btarget = tcg_global_mem_new(TCG_AREG0, + btarget = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, btarget), "btarget"); - hflags = tcg_global_mem_new_i32(TCG_AREG0, + hflags = tcg_global_mem_new_i32(cpu_env, offsetof(CPUMIPSState, hflags), "hflags"); - fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0, + fpu_fcr0 = tcg_global_mem_new_i32(cpu_env, offsetof(CPUMIPSState, active_fpu.fcr0), "fcr0"); - fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0, + fpu_fcr31 = tcg_global_mem_new_i32(cpu_env, offsetof(CPUMIPSState, active_fpu.fcr31), "fcr31"); @@ -20548,6 +20068,16 @@ MIPSCPU *cpu_mips_init(const char *cpu_model) return cpu; } +bool cpu_supports_cps_smp(const char *cpu_model) +{ + const mips_def_t *def = cpu_mips_find_by_name(cpu_model); + if (!def) { + return false; + } + + return (def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0; +} + void cpu_state_reset(CPUMIPSState *env) { MIPSCPU *cpu = mips_env_get_cpu(env); @@ -20598,6 +20128,7 @@ void cpu_state_reset(CPUMIPSState *env) env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask; env->CP0_PageGrain = env->cpu_model->CP0_PageGrain; env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0; + env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31; env->msair = env->cpu_model->MSAIR; env->insn_flags = env->cpu_model->insn_flags; @@ -20640,12 +20171,16 @@ void cpu_state_reset(CPUMIPSState *env) env->CP0_Random = env->tlb->nb_tlb - 1; env->tlb->tlb_in_use = env->tlb->nb_tlb; env->CP0_Wired = 0; + env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId; env->CP0_EBase = (cs->cpu_index & 0x3FF); if (kvm_enabled()) { env->CP0_EBase |= 0x40000000; } else { env->CP0_EBase |= 0x80000000; } + if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) { + env->CP0_CMGCRBase = 0x1fbf8000 >> 4; + } env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL); /* vectored interrupts not implemented, timer on int 7, no performance counters. */ @@ -20714,18 +20249,19 @@ void cpu_state_reset(CPUMIPSState *env) } } -void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos) +void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, + target_ulong *data) { - env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos]; + env->active_tc.PC = data[0]; env->hflags &= ~MIPS_HFLAG_BMASK; - env->hflags |= gen_opc_hflags[pc_pos]; + env->hflags |= data[1]; switch (env->hflags & MIPS_HFLAG_BMASK_BASE) { case MIPS_HFLAG_BR: break; case MIPS_HFLAG_BC: case MIPS_HFLAG_BL: case MIPS_HFLAG_B: - env->btarget = gen_opc_btarget[pc_pos]; + env->btarget = data[2]; break; } } diff --git a/qemu/target-mips/translate_init.c b/qemu/target-mips/translate_init.c index 9304e746b..5af077d0d 100644 --- a/qemu/target-mips/translate_init.c +++ b/qemu/target-mips/translate_init.c @@ -84,6 +84,7 @@ struct mips_def_t { int32_t CP0_TCStatus_rw_bitmask; int32_t CP0_SRSCtl; int32_t CP1_fcr0; + int32_t CP1_fcr31; int32_t MSAIR; int32_t SEGBITS; int32_t PABITS; @@ -389,39 +390,46 @@ static const mips_def_t mips_defs[] = .mmu_type = MMU_TYPE_R4000, }, { - /* A generic CPU providing MIPS32 Release 5 features. - FIXME: Eventually this should be replaced by a real CPU model. */ - .name = "mips32r5-generic", - .CP0_PRid = 0x00019700, - .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | + /* FIXME: + * Config3: CMGCR, SC, PW, VZ, CTXTC, CDMM, TL + * Config4: MMUExtDef + * Config5: EVA, MRP + * FIR(FCR0): Has2008 + * */ + .name = "P5600", + .CP0_PRid = 0x0001A800, + .CP0_Config0 = MIPS_CONFIG0 | (1 << CP0C0_MM) | (1 << CP0C0_AR) | (MMU_TYPE_R4000 << CP0C0_MT), - .CP0_Config1 = 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), + .CP0_Config1 = MIPS_CONFIG1 | (0x3F << 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_FP), .CP0_Config2 = MIPS_CONFIG2, .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP) | - (1 << CP0C3_LPA), - .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M), + (1 << CP0C3_BP) | (1 << CP0C3_BI) | (1 << CP0C3_ULRI) | + (1 << CP0C3_RXI) | (1 << CP0C3_LPA) | (1 << CP0C3_VInt), + .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (2 << CP0C4_IE) | + (0x1c << CP0C4_KScrExist), .CP0_Config4_rw_bitmask = 0, - .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_UFR) | (1 << CP0C5_LLB) | - (1 << CP0C5_MVH), - .CP0_Config5_rw_bitmask = (0 << CP0C5_M) | (1 << CP0C5_K) | - (1 << CP0C5_CV) | (0 << CP0C5_EVA) | - (1 << CP0C5_MSAEn) | (1 << CP0C5_UFR) | - (0 << CP0C5_NFExists), + .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_MVH) | (1 << CP0C5_LLB) | + (1 << CP0C5_MRP), + .CP0_Config5_rw_bitmask = (1 << CP0C5_K) | (1 << CP0C5_CV) | + (1 << CP0C5_MSAEn) | (1 << CP0C5_UFE) | + (1 << CP0C5_FRE) | (1 << CP0C5_UFR), .CP0_LLAddr_rw_bitmask = 0, - .CP0_LLAddr_shift = 4, + .CP0_LLAddr_shift = 0, .SYNCI_Step = 32, .CCRes = 2, - .CP0_Status_rw_bitmask = 0x3778FF1F, - .CP0_PageGrain_rw_bitmask = (1 << CP0PG_ELPA), - .CP1_fcr0 = (1 << FCR0_UFRP) | (1 << FCR0_F64) | (1 << FCR0_L) | - (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) | - (0x93 << FCR0_PRID), + .CP0_Status_rw_bitmask = 0x3C68FF1F, + .CP0_PageGrain_rw_bitmask = (1U << CP0PG_RIE) | (1 << CP0PG_XIE) | + (1 << CP0PG_ELPA) | (1 << CP0PG_IEC), + .CP1_fcr0 = (1 << FCR0_FREP) | (1 << FCR0_UFRP) | (1 << FCR0_HAS2008) | + (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | + (1 << FCR0_D) | (1 << FCR0_S) | (0x03 << FCR0_PRID), + .CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008), .SEGBITS = 32, .PABITS = 40, - .insn_flags = CPU_MIPS32R5 | ASE_MIPS16 | ASE_MSA, + .insn_flags = CPU_MIPS32R5 | ASE_MSA, .mmu_type = MMU_TYPE_R4000, }, { @@ -442,7 +450,7 @@ static const mips_def_t mips_defs[] = (1 << CP0C3_RXI) | (1U << CP0C3_M), .CP0_Config4 = MIPS_CONFIG4 | (0xfc << CP0C4_KScrExist) | (3 << CP0C4_IE) | (1U << CP0C4_M), - .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_LLB), + .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_XNP) | (1 << CP0C5_LLB), .CP0_Config5_rw_bitmask = (1 << CP0C5_SBRI) | (1 << CP0C5_FRE) | (1 << CP0C5_UFE), .CP0_LLAddr_rw_bitmask = 0, @@ -453,9 +461,10 @@ static const mips_def_t mips_defs[] = .CP0_PageGrain = (1 << CP0PG_IEC) | (1 << CP0PG_XIE) | (1U << CP0PG_RIE), .CP0_PageGrain_rw_bitmask = 0, - .CP1_fcr0 = (1 << FCR0_FREP) | (1 << FCR0_F64) | (1 << FCR0_L) | - (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) | - (0x00 << FCR0_PRID) | (0x0 << FCR0_REV), + .CP1_fcr0 = (1 << FCR0_FREP) | (1 << FCR0_HAS2008) | (1 << FCR0_F64) | + (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | + (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV), + .CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008), .SEGBITS = 32, .PABITS = 32, .insn_flags = CPU_MIPS32R6 | ASE_MICROMIPS, @@ -655,12 +664,14 @@ static const mips_def_t mips_defs[] = (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) | (0 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP), .CP0_Config2 = MIPS_CONFIG2, - .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP) | + .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | + (1 << CP0C3_CMGCR) | (1 << CP0C3_MSAP) | (1 << CP0C3_BP) | (1 << CP0C3_BI) | (1 << CP0C3_ULRI) | (1 << CP0C3_RXI) | (1 << CP0C3_LPA), .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (3 << CP0C4_IE) | (0xfc << CP0C4_KScrExist), - .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_LLB), + .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_XNP) | (1 << CP0C5_VP) | + (1 << CP0C5_LLB), .CP0_Config5_rw_bitmask = (1 << CP0C5_MSAEn) | (1 << CP0C5_SBRI) | (1 << CP0C5_FRE) | (1 << CP0C5_UFE), .CP0_LLAddr_rw_bitmask = 0, @@ -671,9 +682,10 @@ static const mips_def_t mips_defs[] = .CP0_PageGrain = (1 << CP0PG_IEC) | (1 << CP0PG_XIE) | (1U << CP0PG_RIE), .CP0_PageGrain_rw_bitmask = (1 << CP0PG_ELPA), - .CP1_fcr0 = (1 << FCR0_FREP) | (1 << FCR0_F64) | (1 << FCR0_L) | - (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) | - (0x00 << FCR0_PRID) | (0x0 << FCR0_REV), + .CP1_fcr0 = (1 << FCR0_FREP) | (1 << FCR0_HAS2008) | (1 << FCR0_F64) | + (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | + (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV), + .CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008), .SEGBITS = 48, .PABITS = 48, .insn_flags = CPU_MIPS64R6 | ASE_MSA, |