summaryrefslogtreecommitdiffstats
path: root/qemu/target-mips
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/target-mips')
-rw-r--r--qemu/target-mips/cpu.c36
-rw-r--r--qemu/target-mips/cpu.h160
-rw-r--r--qemu/target-mips/dsp_helper.c1
-rw-r--r--qemu/target-mips/gdbstub.c2
-rw-r--r--qemu/target-mips/helper.c62
-rw-r--r--qemu/target-mips/helper.h16
-rw-r--r--qemu/target-mips/kvm.c395
-rw-r--r--qemu/target-mips/lmi_helper.c1
-rw-r--r--qemu/target-mips/machine.c7
-rw-r--r--qemu/target-mips/mips-semi.c2
-rw-r--r--qemu/target-mips/msa_helper.c195
-rw-r--r--qemu/target-mips/op_helper.c458
-rw-r--r--qemu/target-mips/translate.c1548
-rw-r--r--qemu/target-mips/translate_init.c78
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,