aboutsummaryrefslogtreecommitdiff
path: root/target/mips
diff options
context:
space:
mode:
Diffstat (limited to 'target/mips')
-rw-r--r--target/mips/Kconfig2
-rw-r--r--target/mips/cpu-defs.c.inc16
-rw-r--r--target/mips/cpu-param.h14
-rw-r--r--target/mips/cpu.c100
-rw-r--r--target/mips/cpu.h31
-rw-r--r--target/mips/fpu_helper.h48
-rw-r--r--target/mips/helper.h2
-rw-r--r--target/mips/internal.h14
-rw-r--r--target/mips/kvm.c15
-rw-r--r--target/mips/meson.build2
-rw-r--r--target/mips/mips-defs.h2
-rw-r--r--target/mips/msa.c36
-rw-r--r--target/mips/system/addr.c (renamed from target/mips/sysemu/addr.c)0
-rw-r--r--target/mips/system/cp0.c (renamed from target/mips/sysemu/cp0.c)2
-rw-r--r--target/mips/system/cp0_timer.c (renamed from target/mips/sysemu/cp0_timer.c)2
-rw-r--r--target/mips/system/machine.c (renamed from target/mips/sysemu/machine.c)9
-rw-r--r--target/mips/system/meson.build (renamed from target/mips/sysemu/meson.build)0
-rw-r--r--target/mips/system/mips-qmp-cmds.c (renamed from target/mips/sysemu/mips-qmp-cmds.c)12
-rw-r--r--target/mips/system/physaddr.c (renamed from target/mips/sysemu/physaddr.c)1
-rw-r--r--target/mips/tcg/exception.c2
-rw-r--r--target/mips/tcg/fpu_helper.c1
-rw-r--r--target/mips/tcg/godson2.decode27
-rw-r--r--target/mips/tcg/ldst_helper.c18
-rw-r--r--target/mips/tcg/loong-ext.decode28
-rw-r--r--target/mips/tcg/loong_translate.c271
-rw-r--r--target/mips/tcg/meson.build5
-rw-r--r--target/mips/tcg/micromips_translate.c.inc39
-rw-r--r--target/mips/tcg/mips16e_translate.c.inc118
-rw-r--r--target/mips/tcg/msa_helper.c57
-rw-r--r--target/mips/tcg/mxu_translate.c18
-rw-r--r--target/mips/tcg/nanomips_translate.c.inc162
-rw-r--r--target/mips/tcg/octeon_translate.c4
-rw-r--r--target/mips/tcg/op_helper.c1
-rw-r--r--target/mips/tcg/system/cp0_helper.c (renamed from target/mips/tcg/sysemu/cp0_helper.c)35
-rw-r--r--target/mips/tcg/system/lcsr_helper.c (renamed from target/mips/tcg/sysemu/lcsr_helper.c)0
-rw-r--r--target/mips/tcg/system/meson.build (renamed from target/mips/tcg/sysemu/meson.build)6
-rw-r--r--target/mips/tcg/system/mips-semi.c (renamed from target/mips/tcg/sysemu/mips-semi.c)44
-rw-r--r--target/mips/tcg/system/semihosting-stub.c16
-rw-r--r--target/mips/tcg/system/special_helper.c (renamed from target/mips/tcg/sysemu/special_helper.c)2
-rw-r--r--target/mips/tcg/system/tlb_helper.c (renamed from target/mips/tcg/sysemu/tlb_helper.c)78
-rw-r--r--target/mips/tcg/system_helper.h.inc (renamed from target/mips/tcg/sysemu_helper.h.inc)2
-rw-r--r--target/mips/tcg/tcg-internal.h4
-rw-r--r--target/mips/tcg/translate.c620
-rw-r--r--target/mips/tcg/translate.h21
-rw-r--r--target/mips/tcg/tx79_translate.c8
45 files changed, 1053 insertions, 842 deletions
diff --git a/target/mips/Kconfig b/target/mips/Kconfig
index eb19c94..876048b 100644
--- a/target/mips/Kconfig
+++ b/target/mips/Kconfig
@@ -1,6 +1,6 @@
config MIPS
bool
- select SEMIHOSTING
+ imply SEMIHOSTING if TCG
config MIPS64
bool
diff --git a/target/mips/cpu-defs.c.inc b/target/mips/cpu-defs.c.inc
index fbf787d..922fc39 100644
--- a/target/mips/cpu-defs.c.inc
+++ b/target/mips/cpu-defs.c.inc
@@ -314,7 +314,7 @@ const mips_def_t mips_defs[] =
(0x3fe << CP0SRSC4_SRS14) | (0x3fe << CP0SRSC4_SRS13),
.SEGBITS = 32,
.PABITS = 32,
- .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_MT,
+ .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP,
.mmu_type = MMU_TYPE_R4000,
},
{
@@ -478,14 +478,15 @@ 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 | (1 << CP0C3_BP) | (1 << CP0C3_BI) |
+ .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_MSAP) |
+ (1 << CP0C3_BP) | (1 << CP0C3_BI) |
(2 << CP0C3_ISA) | (1 << CP0C3_ULRI) |
(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_XNP) | (1 << CP0C5_LLB),
- .CP0_Config5_rw_bitmask = (1 << CP0C5_SBRI) | (1 << CP0C5_FRE) |
- (1 << CP0C5_UFE),
+ .CP0_Config5_rw_bitmask = (1 << CP0C5_MSAEn) | (1 << CP0C5_UFE) |
+ (1 << CP0C5_FRE) | (1 << CP0C5_SBRI),
.CP0_LLAddr_rw_bitmask = 0,
.CP0_LLAddr_shift = 0,
.SYNCI_Step = 32,
@@ -499,6 +500,7 @@ const mips_def_t mips_defs[] =
(1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
.CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008),
.CP1_fcr31_rw_bitmask = 0x0103FFFF,
+ .MSAIR = 0x03 << MSAIR_ProcID,
.SEGBITS = 32,
.PABITS = 32,
.insn_flags = CPU_MIPS32R6 | ASE_MICROMIPS,
@@ -541,7 +543,7 @@ const mips_def_t mips_defs[] =
.SEGBITS = 32,
.PABITS = 32,
.insn_flags = CPU_MIPS32R6 | ISA_NANOMIPS32 |
- ASE_DSP | ASE_DSP_R2 | ASE_DSP_R3 | ASE_MT,
+ ASE_DSP | ASE_DSP_R2 | ASE_DSP_R3,
.mmu_type = MMU_TYPE_R4000,
},
#if defined(TARGET_MIPS64)
@@ -661,7 +663,7 @@ const mips_def_t mips_defs[] =
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 40,
.PABITS = 36,
- .insn_flags = CPU_MIPS64R1 | ASE_MIPS3D,
+ .insn_flags = CPU_MIPS64R1,
.mmu_type = MMU_TYPE_R4000,
},
{
@@ -690,7 +692,7 @@ const mips_def_t mips_defs[] =
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 42,
.PABITS = 36,
- .insn_flags = CPU_MIPS64R2 | ASE_MIPS3D,
+ .insn_flags = CPU_MIPS64R2,
.mmu_type = MMU_TYPE_R4000,
},
{
diff --git a/target/mips/cpu-param.h b/target/mips/cpu-param.h
index 6f6ac16..58f4508 100644
--- a/target/mips/cpu-param.h
+++ b/target/mips/cpu-param.h
@@ -1,17 +1,12 @@
/*
* MIPS cpu parameters for qemu.
*
- * SPDX-License-Identifier: LGPL-2.0+
+ * SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef MIPS_CPU_PARAM_H
#define MIPS_CPU_PARAM_H
-#ifdef TARGET_MIPS64
-# define TARGET_LONG_BITS 64
-#else
-# define TARGET_LONG_BITS 32
-#endif
#ifdef TARGET_ABI_MIPSN64
#define TARGET_PHYS_ADDR_SPACE_BITS 48
#define TARGET_VIRT_ADDR_SPACE_BITS 48
@@ -23,13 +18,8 @@
# define TARGET_VIRT_ADDR_SPACE_BITS 32
#endif
#endif
-#ifdef CONFIG_USER_ONLY
#define TARGET_PAGE_BITS 12
-#else
-#define TARGET_PAGE_BITS_VARY
-#define TARGET_PAGE_BITS_MIN 12
-#endif
-#define TCG_GUEST_DEFAULT_MO (0)
+#define TARGET_INSN_START_EXTRA_WORDS 2
#endif
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index bbe01d0..1f6c41f 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -27,13 +27,14 @@
#include "internal.h"
#include "kvm_mips.h"
#include "qemu/module.h"
-#include "sysemu/kvm.h"
-#include "sysemu/qtest.h"
-#include "exec/exec-all.h"
+#include "system/kvm.h"
+#include "system/qtest.h"
#include "hw/qdev-properties.h"
#include "hw/qdev-clock.h"
-#include "semihosting/semihost.h"
#include "fpu_helper.h"
+#ifndef CONFIG_USER_ONLY
+#include "semihosting/semihost.h"
+#endif
const char regnames[32][3] = {
"r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
@@ -132,6 +133,7 @@ static vaddr mips_cpu_get_pc(CPUState *cs)
return cpu->env.active_tc.PC;
}
+#if !defined(CONFIG_USER_ONLY)
static bool mips_cpu_has_work(CPUState *cs)
{
CPUMIPSState *env = cpu_env(cs);
@@ -177,11 +179,7 @@ static bool mips_cpu_has_work(CPUState *cs)
}
return has_work;
}
-
-static int mips_cpu_mmu_index(CPUState *cs, bool ifunc)
-{
- return mips_env_mmu_index(cpu_env(cs));
-}
+#endif /* !CONFIG_USER_ONLY */
#include "cpu-defs.c.inc"
@@ -200,10 +198,8 @@ static void mips_cpu_reset_hold(Object *obj, ResetType type)
/* Reset registers to their default values */
env->CP0_PRid = env->cpu_model->CP0_PRid;
- env->CP0_Config0 = env->cpu_model->CP0_Config0;
-#if TARGET_BIG_ENDIAN
- env->CP0_Config0 |= (1 << CP0C0_BE);
-#endif
+ env->CP0_Config0 = deposit32(env->cpu_model->CP0_Config0,
+ CP0C0_BE, 1, cpu->is_big_endian);
env->CP0_Config1 = env->cpu_model->CP0_Config1;
env->CP0_Config2 = env->cpu_model->CP0_Config2;
env->CP0_Config3 = env->cpu_model->CP0_Config3;
@@ -409,18 +405,17 @@ static void mips_cpu_reset_hold(Object *obj, ResetType type)
}
msa_reset(env);
+ fp_reset(env);
compute_hflags(env);
- restore_fp_status(env);
restore_pamask(env);
cs->exception_index = EXCP_NONE;
+#ifndef CONFIG_USER_ONLY
if (semihosting_get_argc()) {
/* UHI interface can be used to obtain argc and argv */
env->active_tc.gpr[4] = -1;
}
-
-#ifndef CONFIG_USER_ONLY
if (kvm_enabled()) {
kvm_mips_reset_vcpu(cpu);
}
@@ -430,13 +425,13 @@ static void mips_cpu_reset_hold(Object *obj, ResetType type)
static void mips_cpu_disas_set_info(CPUState *s, disassemble_info *info)
{
if (!(cpu_env(s)->insn_flags & ISA_NANOMIPS32)) {
-#if TARGET_BIG_ENDIAN
- info->print_insn = print_insn_big_mips;
-#else
- info->print_insn = print_insn_little_mips;
-#endif
+ info->endian = TARGET_BIG_ENDIAN ? BFD_ENDIAN_BIG
+ : BFD_ENDIAN_LITTLE;
+ info->print_insn = TARGET_BIG_ENDIAN ? print_insn_big_mips
+ : print_insn_little_mips;
} else {
info->print_insn = print_insn_nanomips;
+ info->endian = BFD_ENDIAN_LITTLE;
}
}
@@ -536,25 +531,60 @@ static ObjectClass *mips_cpu_class_by_name(const char *cpu_model)
#include "hw/core/sysemu-cpu-ops.h"
static const struct SysemuCPUOps mips_sysemu_ops = {
+ .has_work = mips_cpu_has_work,
.get_phys_page_debug = mips_cpu_get_phys_page_debug,
.legacy_vmsd = &vmstate_mips_cpu,
};
#endif
+static const Property mips_cpu_properties[] = {
+ DEFINE_PROP_BOOL("big-endian", MIPSCPU, is_big_endian, TARGET_BIG_ENDIAN),
+};
+
#ifdef CONFIG_TCG
-#include "hw/core/tcg-cpu-ops.h"
-/*
- * NB: cannot be const, as some elements are changed for specific
- * mips hardware (see hw/mips/jazz.c).
- */
+#include "accel/tcg/cpu-ops.h"
+
+static int mips_cpu_mmu_index(CPUState *cs, bool ifunc)
+{
+ return mips_env_mmu_index(cpu_env(cs));
+}
+
+static TCGTBCPUState mips_get_tb_cpu_state(CPUState *cs)
+{
+ CPUMIPSState *env = cpu_env(cs);
+
+ return (TCGTBCPUState){
+ .pc = env->active_tc.PC,
+ .flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK |
+ MIPS_HFLAG_HWRENA_ULR),
+ };
+}
+
+#ifndef CONFIG_USER_ONLY
+static vaddr mips_pointer_wrap(CPUState *cs, int mmu_idx,
+ vaddr result, vaddr base)
+{
+ return cpu_env(cs)->hflags & MIPS_HFLAG_AWRAP ? (int32_t)result : result;
+}
+#endif
+
static const TCGCPUOps mips_tcg_ops = {
+ .mttcg_supported = TARGET_LONG_BITS == 32,
+ .guest_default_memory_order = 0,
+
.initialize = mips_tcg_init,
+ .translate_code = mips_translate_code,
+ .get_tb_cpu_state = mips_get_tb_cpu_state,
.synchronize_from_tb = mips_cpu_synchronize_from_tb,
.restore_state_to_opc = mips_restore_state_to_opc,
+ .mmu_index = mips_cpu_mmu_index,
#if !defined(CONFIG_USER_ONLY)
.tlb_fill = mips_cpu_tlb_fill,
+ .pointer_wrap = mips_pointer_wrap,
.cpu_exec_interrupt = mips_cpu_exec_interrupt,
+ .cpu_exec_halt = mips_cpu_has_work,
+ .cpu_exec_reset = cpu_reset,
.do_interrupt = mips_cpu_do_interrupt,
.do_transaction_failed = mips_cpu_do_transaction_failed,
.do_unaligned_access = mips_cpu_do_unaligned_access,
@@ -563,21 +593,20 @@ static const TCGCPUOps mips_tcg_ops = {
};
#endif /* CONFIG_TCG */
-static void mips_cpu_class_init(ObjectClass *c, void *data)
+static void mips_cpu_class_init(ObjectClass *c, const void *data)
{
MIPSCPUClass *mcc = MIPS_CPU_CLASS(c);
CPUClass *cc = CPU_CLASS(c);
DeviceClass *dc = DEVICE_CLASS(c);
ResettableClass *rc = RESETTABLE_CLASS(c);
+ device_class_set_props(dc, mips_cpu_properties);
device_class_set_parent_realize(dc, mips_cpu_realizefn,
&mcc->parent_realize);
resettable_class_set_parent_phases(rc, NULL, mips_cpu_reset_hold, NULL,
&mcc->parent_phases);
cc->class_by_name = mips_cpu_class_by_name;
- cc->has_work = mips_cpu_has_work;
- cc->mmu_index = mips_cpu_mmu_index;
cc->dump_state = mips_cpu_dump_state;
cc->set_pc = mips_cpu_set_pc;
cc->get_pc = mips_cpu_get_pc;
@@ -605,7 +634,7 @@ static const TypeInfo mips_cpu_type_info = {
.class_init = mips_cpu_class_init,
};
-static void mips_cpu_cpudef_class_init(ObjectClass *oc, void *data)
+static void mips_cpu_cpudef_class_init(ObjectClass *oc, const void *data)
{
MIPSCPUClass *mcc = MIPS_CPU_CLASS(oc);
mcc->cpu_def = data;
@@ -618,10 +647,10 @@ static void mips_register_cpudef_type(const struct mips_def_t *def)
.name = typename,
.parent = TYPE_MIPS_CPU,
.class_init = mips_cpu_cpudef_class_init,
- .class_data = (void *)def,
+ .class_data = def,
};
- type_register(&ti);
+ type_register_static(&ti);
g_free(typename);
}
@@ -638,12 +667,15 @@ static void mips_cpu_register_types(void)
type_init(mips_cpu_register_types)
/* Could be used by generic CPU object */
-MIPSCPU *mips_cpu_create_with_clock(const char *cpu_type, Clock *cpu_refclk)
+MIPSCPU *mips_cpu_create_with_clock(const char *cpu_type, Clock *cpu_refclk,
+ bool is_big_endian)
{
DeviceState *cpu;
- cpu = DEVICE(object_new(cpu_type));
+ cpu = qdev_new(cpu_type);
qdev_connect_clock_in(cpu, "clk-in", cpu_refclk);
+ object_property_set_bool(OBJECT(cpu), "big-endian", is_big_endian,
+ &error_abort);
qdev_realize(cpu, NULL, &error_abort);
return MIPS_CPU(cpu);
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 3e906a1..5cd4c6c 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -2,9 +2,11 @@
#define MIPS_CPU_H
#include "cpu-qom.h"
+#include "exec/cpu-common.h"
#include "exec/cpu-defs.h"
+#include "exec/cpu-interrupt.h"
#ifndef CONFIG_USER_ONLY
-#include "exec/memory.h"
+#include "system/memory.h"
#endif
#include "fpu/softfloat-types.h"
#include "hw/clock.h"
@@ -98,8 +100,6 @@ struct CPUMIPSFPUContext {
#define FP_UNIMPLEMENTED 32
};
-#define TARGET_INSN_START_EXTRA_WORDS 2
-
typedef struct CPUMIPSMVPContext CPUMIPSMVPContext;
struct CPUMIPSMVPContext {
int32_t CP0_MVPControl;
@@ -530,7 +530,6 @@ typedef struct CPUArchState {
CPUMIPSFPUContext active_fpu;
uint32_t current_tc;
- uint32_t current_fpu;
uint32_t SEGBITS;
uint32_t PABITS;
@@ -1209,6 +1208,9 @@ struct ArchCPU {
Clock *clock;
Clock *count_div; /* Divider for CP0_Count clock */
+
+ /* Properties */
+ bool is_big_endian;
};
/**
@@ -1254,8 +1256,6 @@ static inline int mips_env_mmu_index(CPUMIPSState *env)
return hflags_mmu_index(env->hflags);
}
-#include "exec/cpu-all.h"
-
/* Exceptions */
enum {
EXCP_NONE = -1,
@@ -1316,6 +1316,12 @@ bool cpu_type_supports_cps_smp(const char *cpu_type);
bool cpu_supports_isa(const CPUMIPSState *env, uint64_t isa_mask);
bool cpu_type_supports_isa(const char *cpu_type, uint64_t isa);
+/* Check presence of MIPS-3D ASE */
+static inline bool ase_3d_available(const CPUMIPSState *env)
+{
+ return env->active_fpu.fcr0 & (1 << FCR0_3D);
+}
+
/* Check presence of MSA implementation */
static inline bool ase_msa_available(CPUMIPSState *env)
{
@@ -1360,25 +1366,18 @@ void cpu_mips_clock_init(MIPSCPU *cpu);
/* helper.c */
target_ulong exception_resume_pc(CPUMIPSState *env);
-static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, vaddr *pc,
- uint64_t *cs_base, uint32_t *flags)
-{
- *pc = env->active_tc.PC;
- *cs_base = 0;
- *flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK |
- MIPS_HFLAG_HWRENA_ULR);
-}
-
/**
* mips_cpu_create_with_clock:
* @typename: a MIPS CPU type.
* @cpu_refclk: this cpu input clock (an output clock of another device)
+ * @is_big_endian: whether this CPU is configured in big endianness
*
* Instantiates a MIPS CPU, set the input clock of the CPU to @cpu_refclk,
* then realizes the CPU.
*
* Returns: A #CPUState or %NULL if an error occurred.
*/
-MIPSCPU *mips_cpu_create_with_clock(const char *cpu_type, Clock *cpu_refclk);
+MIPSCPU *mips_cpu_create_with_clock(const char *cpu_type, Clock *cpu_refclk,
+ bool is_big_endian);
#endif /* MIPS_CPU_H */
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
index ad1116e..08fb409 100644
--- a/target/mips/fpu_helper.h
+++ b/target/mips/fpu_helper.h
@@ -28,6 +28,8 @@ static inline void restore_flush_mode(CPUMIPSState *env)
static inline void restore_snan_bit_mode(CPUMIPSState *env)
{
bool nan2008 = env->active_fpu.fcr31 & (1 << FCR31_NAN2008);
+ FloatInfZeroNaNRule izn_rule;
+ Float3NaNPropRule nan3_rule;
/*
* With nan2008, SNaNs are silenced in the usual way.
@@ -35,6 +37,24 @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
*/
set_snan_bit_is_one(!nan2008, &env->active_fpu.fp_status);
set_default_nan_mode(!nan2008, &env->active_fpu.fp_status);
+ /*
+ * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
+ * case sets InvalidOp and returns the default NaN.
+ * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
+ * case sets InvalidOp and returns the input value 'c'.
+ */
+ izn_rule = nan2008 ? float_infzeronan_dnan_never : float_infzeronan_dnan_always;
+ set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
+ nan3_rule = nan2008 ? float_3nan_prop_s_cab : float_3nan_prop_s_abc;
+ set_float_3nan_prop_rule(nan3_rule, &env->active_fpu.fp_status);
+ /*
+ * With nan2008, the default NaN value has the sign bit clear and the
+ * frac msb set; with the older mode, the sign bit is clear, and all
+ * frac bits except the msb are set.
+ */
+ set_float_default_nan_pattern(nan2008 ? 0b01000000 : 0b00111111,
+ &env->active_fpu.fp_status);
+
}
static inline void restore_fp_status(CPUMIPSState *env)
@@ -44,6 +64,34 @@ static inline void restore_fp_status(CPUMIPSState *env)
restore_snan_bit_mode(env);
}
+static inline void fp_reset(CPUMIPSState *env)
+{
+ restore_fp_status(env);
+
+ /*
+ * According to MIPS specifications, if one of the two operands is
+ * a sNaN, a new qNaN has to be generated. This is done in
+ * floatXX_silence_nan(). For qNaN inputs the specifications
+ * says: "When possible, this QNaN result is one of the operand QNaN
+ * values." In practice it seems that most implementations choose
+ * the first operand if both operands are qNaN. In short this gives
+ * the following rules:
+ * 1. A if it is signaling
+ * 2. B if it is signaling
+ * 3. A (quiet)
+ * 4. B (quiet)
+ * A signaling NaN is always silenced before returning it.
+ */
+ set_float_2nan_prop_rule(float_2nan_prop_s_ab,
+ &env->active_fpu.fp_status);
+ /*
+ * TODO: the spec does't say clearly whether FTZ happens before
+ * or after rounding for normal FPU operations.
+ */
+ set_float_ftz_detection(float_ftz_before_rounding,
+ &env->active_fpu.fp_status);
+}
+
/* MSA */
enum CPUMIPSMSADataFormat {
diff --git a/target/mips/helper.h b/target/mips/helper.h
index 0f8462f..7e40041 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -594,7 +594,7 @@ DEF_HELPER_FLAGS_3(wrdsp, 0, void, tl, tl, env)
DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env)
#ifndef CONFIG_USER_ONLY
-#include "tcg/sysemu_helper.h.inc"
+#include "tcg/system_helper.h.inc"
#endif /* !CONFIG_USER_ONLY */
#include "tcg/msa_helper.h.inc"
diff --git a/target/mips/internal.h b/target/mips/internal.h
index a9a22ea..28eb289 100644
--- a/target/mips/internal.h
+++ b/target/mips/internal.h
@@ -162,8 +162,6 @@ void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val);
extern const VMStateDescription vmstate_mips_cpu;
-#endif /* !CONFIG_USER_ONLY */
-
static inline bool cpu_mips_hw_interrupts_enabled(CPUMIPSState *env)
{
return (env->CP0_Status & (1 << CP0St_IE)) &&
@@ -206,6 +204,8 @@ static inline bool cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
return r;
}
+#endif /* !CONFIG_USER_ONLY */
+
void msa_reset(CPUMIPSState *env);
/* cp0_timer.c */
@@ -225,6 +225,16 @@ static inline void mips_env_set_pc(CPUMIPSState *env, target_ulong value)
}
}
+static inline bool mips_env_is_bigendian(CPUMIPSState *env)
+{
+ return extract32(env->CP0_Config0, CP0C0_BE, 1);
+}
+
+static inline MemOp mo_endian_env(CPUMIPSState *env)
+{
+ return mips_env_is_bigendian(env) ? MO_BE : MO_LE;
+}
+
static inline void restore_pamask(CPUMIPSState *env)
{
if (env->hflags & MIPS_HFLAG_ELPA) {
diff --git a/target/mips/kvm.c b/target/mips/kvm.c
index a631ab5..ec53acb 100644
--- a/target/mips/kvm.c
+++ b/target/mips/kvm.c
@@ -18,9 +18,9 @@
#include "internal.h"
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
-#include "sysemu/kvm.h"
-#include "sysemu/kvm_int.h"
-#include "sysemu/runstate.h"
+#include "system/kvm.h"
+#include "system/kvm_int.h"
+#include "system/runstate.h"
#include "kvm_mips.h"
#include "hw/boards.h"
#include "fpu_helper.h"
@@ -61,6 +61,11 @@ int kvm_arch_irqchip_create(KVMState *s)
return 0;
}
+int kvm_arch_pre_create_vcpu(CPUState *cpu, Error **errp)
+{
+ return 0;
+}
+
int kvm_arch_init_vcpu(CPUState *cs)
{
CPUMIPSState *env = cpu_env(cs);
@@ -1172,7 +1177,7 @@ static int kvm_mips_get_cp0_registers(CPUState *cs)
return ret;
}
-int kvm_arch_put_registers(CPUState *cs, int level)
+int kvm_arch_put_registers(CPUState *cs, int level, Error **errp)
{
CPUMIPSState *env = cpu_env(cs);
struct kvm_regs regs;
@@ -1207,7 +1212,7 @@ int kvm_arch_put_registers(CPUState *cs, int level)
return ret;
}
-int kvm_arch_get_registers(CPUState *cs)
+int kvm_arch_get_registers(CPUState *cs, Error **errp)
{
CPUMIPSState *env = cpu_env(cs);
int ret = 0;
diff --git a/target/mips/meson.build b/target/mips/meson.build
index a26d1e1..247979a 100644
--- a/target/mips/meson.build
+++ b/target/mips/meson.build
@@ -9,7 +9,7 @@ mips_ss.add(files(
))
if have_system
- subdir('sysemu')
+ subdir('system')
endif
if 'CONFIG_TCG' in config_all_accel
diff --git a/target/mips/mips-defs.h b/target/mips/mips-defs.h
index a6cebe0..9d4d292 100644
--- a/target/mips/mips-defs.h
+++ b/target/mips/mips-defs.h
@@ -26,12 +26,10 @@
* bits 24-39: MIPS ASEs
*/
#define ASE_MIPS16 0x0000000001000000ULL
-#define ASE_MIPS3D 0x0000000002000000ULL
#define ASE_MDMX 0x0000000004000000ULL
#define ASE_DSP 0x0000000008000000ULL
#define ASE_DSP_R2 0x0000000010000000ULL
#define ASE_DSP_R3 0x0000000020000000ULL
-#define ASE_MT 0x0000000040000000ULL
#define ASE_SMARTMIPS 0x0000000080000000ULL
#define ASE_MICROMIPS 0x0000000100000000ULL
/*
diff --git a/target/mips/msa.c b/target/mips/msa.c
index 61f1a9a..32c6acb 100644
--- a/target/mips/msa.c
+++ b/target/mips/msa.c
@@ -48,6 +48,35 @@ void msa_reset(CPUMIPSState *env)
/* tininess detected after rounding.*/
set_float_detect_tininess(float_tininess_after_rounding,
&env->active_tc.msa_fp_status);
+ /*
+ * MSACSR.FS detects tiny results to flush to zero before rounding
+ * (per "MIPS Architecture for Programmers Volume IV-j: The MIPS64 SIMD
+ * Architecture Module, Revision 1.1" section 3.5.4), even though it
+ * detects tininess after rounding for underflow purposes (section 3.4.2
+ * table 3.3).
+ */
+ set_float_ftz_detection(float_ftz_before_rounding,
+ &env->active_tc.msa_fp_status);
+
+ /*
+ * According to MIPS specifications, if one of the two operands is
+ * a sNaN, a new qNaN has to be generated. This is done in
+ * floatXX_silence_nan(). For qNaN inputs the specifications
+ * says: "When possible, this QNaN result is one of the operand QNaN
+ * values." In practice it seems that most implementations choose
+ * the first operand if both operands are qNaN. In short this gives
+ * the following rules:
+ * 1. A if it is signaling
+ * 2. B if it is signaling
+ * 3. A (quiet)
+ * 4. B (quiet)
+ * A signaling NaN is always silenced before returning it.
+ */
+ set_float_2nan_prop_rule(float_2nan_prop_s_ab,
+ &env->active_tc.msa_fp_status);
+
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab,
+ &env->active_tc.msa_fp_status);
/* clear float_status exception flags */
set_float_exception_flags(0, &env->active_tc.msa_fp_status);
@@ -57,4 +86,11 @@ void msa_reset(CPUMIPSState *env)
/* set proper signanling bit meaning ("1" means "quiet") */
set_snan_bit_is_one(0, &env->active_tc.msa_fp_status);
+
+ /* Inf * 0 + NaN returns the input NaN */
+ set_float_infzeronan_rule(float_infzeronan_dnan_never,
+ &env->active_tc.msa_fp_status);
+ /* Default NaN: sign bit clear, frac msb set */
+ set_float_default_nan_pattern(0b01000000,
+ &env->active_tc.msa_fp_status);
}
diff --git a/target/mips/sysemu/addr.c b/target/mips/system/addr.c
index 4f025be..4f025be 100644
--- a/target/mips/sysemu/addr.c
+++ b/target/mips/system/addr.c
diff --git a/target/mips/sysemu/cp0.c b/target/mips/system/cp0.c
index bae37f5..ff7d3db 100644
--- a/target/mips/sysemu/cp0.c
+++ b/target/mips/system/cp0.c
@@ -21,7 +21,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
#include "internal.h"
-#include "exec/exec-all.h"
+#include "exec/cputlb.h"
/* Called for updates to CP0_Status. */
void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc)
diff --git a/target/mips/sysemu/cp0_timer.c b/target/mips/system/cp0_timer.c
index 62de502..ca16945 100644
--- a/target/mips/sysemu/cp0_timer.c
+++ b/target/mips/system/cp0_timer.c
@@ -23,7 +23,7 @@
#include "qemu/osdep.h"
#include "hw/irq.h"
#include "qemu/timer.h"
-#include "sysemu/kvm.h"
+#include "system/kvm.h"
#include "internal.h"
/* MIPS R4K timer */
diff --git a/target/mips/sysemu/machine.c b/target/mips/system/machine.c
index 213fd63..8af11fd 100644
--- a/target/mips/sysemu/machine.c
+++ b/target/mips/system/machine.c
@@ -142,6 +142,7 @@ static int get_tlb(QEMUFile *f, void *pv, size_t size,
qemu_get_betls(f, &v->VPN);
qemu_get_be32s(f, &v->PageMask);
qemu_get_be16s(f, &v->ASID);
+ qemu_get_be32s(f, &v->MMID);
qemu_get_be16s(f, &flags);
v->G = (flags >> 10) & 1;
v->C0 = (flags >> 7) & 3;
@@ -167,6 +168,7 @@ static int put_tlb(QEMUFile *f, void *pv, size_t size,
r4k_tlb_t *v = pv;
uint16_t asid = v->ASID;
+ uint32_t mmid = v->MMID;
uint16_t flags = ((v->EHINV << 15) |
(v->RI1 << 14) |
(v->RI0 << 13) |
@@ -183,6 +185,7 @@ static int put_tlb(QEMUFile *f, void *pv, size_t size,
qemu_put_betls(f, &v->VPN);
qemu_put_be32s(f, &v->PageMask);
qemu_put_be16s(f, &asid);
+ qemu_put_be32s(f, &mmid);
qemu_put_be16s(f, &flags);
qemu_put_be64s(f, &v->PFN[0]);
qemu_put_be64s(f, &v->PFN[1]);
@@ -204,8 +207,8 @@ static const VMStateInfo vmstate_info_tlb = {
static const VMStateDescription vmstate_tlb = {
.name = "cpu/tlb",
- .version_id = 2,
- .minimum_version_id = 2,
+ .version_id = 3,
+ .minimum_version_id = 3,
.fields = (const VMStateField[]) {
VMSTATE_UINT32(nb_tlb, CPUMIPSTLBContext),
VMSTATE_UINT32(tlb_in_use, CPUMIPSTLBContext),
@@ -239,7 +242,7 @@ const VMStateDescription vmstate_mips_cpu = {
/* CPU metastate */
VMSTATE_UINT32(env.current_tc, MIPSCPU),
- VMSTATE_UINT32(env.current_fpu, MIPSCPU),
+ VMSTATE_UNUSED(sizeof(uint32_t)), /* was current_fpu */
VMSTATE_INT32(env.error_code, MIPSCPU),
VMSTATE_UINTTL(env.btarget, MIPSCPU),
VMSTATE_UINTTL(env.bcond, MIPSCPU),
diff --git a/target/mips/sysemu/meson.build b/target/mips/system/meson.build
index 498cf28..498cf28 100644
--- a/target/mips/sysemu/meson.build
+++ b/target/mips/system/meson.build
diff --git a/target/mips/sysemu/mips-qmp-cmds.c b/target/mips/system/mips-qmp-cmds.c
index 7340ac7..d98d662 100644
--- a/target/mips/sysemu/mips-qmp-cmds.c
+++ b/target/mips/system/mips-qmp-cmds.c
@@ -7,9 +7,19 @@
*/
#include "qemu/osdep.h"
-#include "qapi/qapi-commands-machine-target.h"
+#include "qapi/error.h"
+#include "qapi/qapi-commands-machine.h"
#include "cpu.h"
+CpuModelExpansionInfo *
+qmp_query_cpu_model_expansion(CpuModelExpansionType type,
+ CpuModelInfo *model,
+ Error **errp)
+{
+ error_setg(errp, "CPU model expansion is not supported on this target");
+ return NULL;
+}
+
static void mips_cpu_add_definition(gpointer data, gpointer user_data)
{
ObjectClass *oc = data;
diff --git a/target/mips/sysemu/physaddr.c b/target/mips/system/physaddr.c
index 505781d..b8e1a5a 100644
--- a/target/mips/sysemu/physaddr.c
+++ b/target/mips/system/physaddr.c
@@ -18,7 +18,6 @@
*/
#include "qemu/osdep.h"
#include "cpu.h"
-#include "exec/exec-all.h"
#include "exec/page-protection.h"
#include "../internal.h"
diff --git a/target/mips/tcg/exception.c b/target/mips/tcg/exception.c
index 4886d08..d32bceb 100644
--- a/target/mips/tcg/exception.c
+++ b/target/mips/tcg/exception.c
@@ -23,7 +23,7 @@
#include "cpu.h"
#include "internal.h"
#include "exec/helper-proto.h"
-#include "exec/exec-all.h"
+#include "exec/translation-block.h"
target_ulong exception_resume_pc(CPUMIPSState *env)
{
diff --git a/target/mips/tcg/fpu_helper.c b/target/mips/tcg/fpu_helper.c
index 45d593d..36af980 100644
--- a/target/mips/tcg/fpu_helper.c
+++ b/target/mips/tcg/fpu_helper.c
@@ -24,7 +24,6 @@
#include "cpu.h"
#include "internal.h"
#include "exec/helper-proto.h"
-#include "exec/exec-all.h"
#include "fpu/softfloat.h"
#include "fpu_helper.h"
diff --git a/target/mips/tcg/godson2.decode b/target/mips/tcg/godson2.decode
new file mode 100644
index 0000000..25b396b
--- /dev/null
+++ b/target/mips/tcg/godson2.decode
@@ -0,0 +1,27 @@
+# Godson2 64-bit Integer instructions
+#
+# Copyright (C) 2021 Philippe Mathieu-Daudé
+#
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# Reference:
+# Godson-2E Software Manual
+# (Document Number: godson2e-user-manual-V0.6)
+#
+
+&muldiv rs rt rd
+
+@rs_rt_rd ...... rs:5 rt:5 rd:5 ..... ...... &muldiv
+
+MULTu_G 011111 ..... ..... ..... 00000 01100- @rs_rt_rd
+DMULTu_G 011111 ..... ..... ..... 00000 01110- @rs_rt_rd
+
+DIV_G 011111 ..... ..... ..... 00000 011010 @rs_rt_rd
+DIVU_G 011111 ..... ..... ..... 00000 011011 @rs_rt_rd
+DDIV_G 011111 ..... ..... ..... 00000 011110 @rs_rt_rd
+DDIVU_G 011111 ..... ..... ..... 00000 011111 @rs_rt_rd
+
+MOD_G 011111 ..... ..... ..... 00000 100010 @rs_rt_rd
+MODU_G 011111 ..... ..... ..... 00000 100011 @rs_rt_rd
+DMOD_G 011111 ..... ..... ..... 00000 100110 @rs_rt_rd
+DMODU_G 011111 ..... ..... ..... 00000 100111 @rs_rt_rd
diff --git a/target/mips/tcg/ldst_helper.c b/target/mips/tcg/ldst_helper.c
index 97056d0..10319bf 100644
--- a/target/mips/tcg/ldst_helper.c
+++ b/target/mips/tcg/ldst_helper.c
@@ -23,8 +23,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
#include "exec/helper-proto.h"
-#include "exec/exec-all.h"
-#include "exec/cpu_ldst.h"
+#include "accel/tcg/cpu-ldst.h"
#include "exec/memop.h"
#include "internal.h"
@@ -53,11 +52,6 @@ HELPER_LD_ATOMIC(lld, ldq, 0x7, (target_ulong))
#endif /* !CONFIG_USER_ONLY */
-static inline bool cpu_is_bigendian(CPUMIPSState *env)
-{
- return extract32(env->CP0_Config0, CP0C0_BE, 1);
-}
-
static inline target_ulong get_lmask(CPUMIPSState *env,
target_ulong value, unsigned bits)
{
@@ -65,7 +59,7 @@ static inline target_ulong get_lmask(CPUMIPSState *env,
value &= mask;
- if (!cpu_is_bigendian(env)) {
+ if (!mips_env_is_bigendian(env)) {
value ^= mask;
}
@@ -76,7 +70,7 @@ void helper_swl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
int mem_idx)
{
target_ulong lmask = get_lmask(env, arg2, 32);
- int dir = cpu_is_bigendian(env) ? 1 : -1;
+ int dir = mips_env_is_bigendian(env) ? 1 : -1;
cpu_stb_mmuidx_ra(env, arg2, (uint8_t)(arg1 >> 24), mem_idx, GETPC());
@@ -100,7 +94,7 @@ void helper_swr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
int mem_idx)
{
target_ulong lmask = get_lmask(env, arg2, 32);
- int dir = cpu_is_bigendian(env) ? 1 : -1;
+ int dir = mips_env_is_bigendian(env) ? 1 : -1;
cpu_stb_mmuidx_ra(env, arg2, (uint8_t)arg1, mem_idx, GETPC());
@@ -130,7 +124,7 @@ void helper_sdl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
int mem_idx)
{
target_ulong lmask = get_lmask(env, arg2, 64);
- int dir = cpu_is_bigendian(env) ? 1 : -1;
+ int dir = mips_env_is_bigendian(env) ? 1 : -1;
cpu_stb_mmuidx_ra(env, arg2, (uint8_t)(arg1 >> 56), mem_idx, GETPC());
@@ -174,7 +168,7 @@ void helper_sdr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
int mem_idx)
{
target_ulong lmask = get_lmask(env, arg2, 64);
- int dir = cpu_is_bigendian(env) ? 1 : -1;
+ int dir = mips_env_is_bigendian(env) ? 1 : -1;
cpu_stb_mmuidx_ra(env, arg2, (uint8_t)arg1, mem_idx, GETPC());
diff --git a/target/mips/tcg/loong-ext.decode b/target/mips/tcg/loong-ext.decode
new file mode 100644
index 0000000..b43979d
--- /dev/null
+++ b/target/mips/tcg/loong-ext.decode
@@ -0,0 +1,28 @@
+# Loongson 64-bit Extension instructions
+#
+# Copyright (C) 2021 Philippe Mathieu-Daudé
+#
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# Reference:
+# STLS2F01 User Manual
+# Appendix A: new integer instructions
+# (Document Number: UM0447)
+#
+
+&muldiv rs rt rd !extern
+
+@rs_rt_rd ...... rs:5 rt:5 rd:5 ..... ...... &muldiv
+
+MULTu_G 011100 ..... ..... ..... 00000 0100-0 @rs_rt_rd
+DMULTu_G 011100 ..... ..... ..... 00000 0100-1 @rs_rt_rd
+
+DIV_G 011100 ..... ..... ..... 00000 010100 @rs_rt_rd
+DDIV_G 011100 ..... ..... ..... 00000 010101 @rs_rt_rd
+DIVU_G 011100 ..... ..... ..... 00000 010110 @rs_rt_rd
+DDIVU_G 011100 ..... ..... ..... 00000 010111 @rs_rt_rd
+
+MOD_G 011100 ..... ..... ..... 00000 011100 @rs_rt_rd
+DMOD_G 011100 ..... ..... ..... 00000 011101 @rs_rt_rd
+MODU_G 011100 ..... ..... ..... 00000 011110 @rs_rt_rd
+DMODU_G 011100 ..... ..... ..... 00000 011111 @rs_rt_rd
diff --git a/target/mips/tcg/loong_translate.c b/target/mips/tcg/loong_translate.c
new file mode 100644
index 0000000..7d74cc3
--- /dev/null
+++ b/target/mips/tcg/loong_translate.c
@@ -0,0 +1,271 @@
+/*
+ * MIPS Loongson 64-bit translation routines
+ *
+ * Copyright (c) 2004-2005 Jocelyn Mayer
+ * Copyright (c) 2006 Marius Groeger (FPU operations)
+ * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
+ * Copyright (c) 2011 Richard Henderson <rth@twiddle.net>
+ * Copyright (c) 2021 Philippe Mathieu-Daudé
+ *
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+#include "qemu/osdep.h"
+#include "translate.h"
+
+/* Include the auto-generated decoder. */
+#include "decode-godson2.c.inc"
+#include "decode-loong-ext.c.inc"
+
+/*
+ * Word or double-word Fixed-point instructions.
+ * ---------------------------------------------
+ *
+ * Fixed-point multiplies and divisions write only
+ * one result into general-purpose registers.
+ */
+
+static bool gen_lext_DIV_G(DisasContext *s, int rd, int rs, int rt,
+ bool is_double)
+{
+ TCGv t0, t1;
+ TCGLabel *l1, *l2, *l3;
+
+ if (rd == 0) {
+ /* Treat as NOP. */
+ return true;
+ }
+
+ t0 = tcg_temp_new();
+ t1 = tcg_temp_new();
+ l1 = gen_new_label();
+ l2 = gen_new_label();
+ l3 = gen_new_label();
+
+ gen_load_gpr(t0, rs);
+ gen_load_gpr(t1, rt);
+
+ if (!is_double) {
+ tcg_gen_ext32s_tl(t0, t0);
+ tcg_gen_ext32s_tl(t1, t1);
+ }
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l3);
+ gen_set_label(l1);
+
+ tcg_gen_brcondi_tl(TCG_COND_NE, t0, is_double ? LLONG_MIN : INT_MIN, l2);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
+ tcg_gen_mov_tl(cpu_gpr[rd], t0);
+
+ tcg_gen_br(l3);
+ gen_set_label(l2);
+ tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
+ if (!is_double) {
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ }
+ gen_set_label(l3);
+
+ return true;
+}
+
+static bool trans_DIV_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_DIV_G(s, a->rd, a->rs, a->rt, false);
+}
+
+static bool trans_DDIV_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_DIV_G(s, a->rd, a->rs, a->rt, true);
+}
+
+static bool gen_lext_DIVU_G(DisasContext *s, int rd, int rs, int rt,
+ bool is_double)
+{
+ TCGv t0, t1;
+ TCGLabel *l1, *l2;
+
+ if (rd == 0) {
+ /* Treat as NOP. */
+ return true;
+ }
+
+ t0 = tcg_temp_new();
+ t1 = tcg_temp_new();
+ l1 = gen_new_label();
+ l2 = gen_new_label();
+
+ gen_load_gpr(t0, rs);
+ gen_load_gpr(t1, rt);
+
+ if (!is_double) {
+ tcg_gen_ext32u_tl(t0, t0);
+ tcg_gen_ext32u_tl(t1, t1);
+ }
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+
+ tcg_gen_br(l2);
+ gen_set_label(l1);
+ tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
+ if (!is_double) {
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ }
+ gen_set_label(l2);
+
+ return true;
+}
+
+static bool trans_DIVU_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_DIVU_G(s, a->rd, a->rs, a->rt, false);
+}
+
+static bool trans_DDIVU_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_DIVU_G(s, a->rd, a->rs, a->rt, true);
+}
+
+static bool gen_lext_MOD_G(DisasContext *s, int rd, int rs, int rt,
+ bool is_double)
+{
+ TCGv t0, t1;
+ TCGLabel *l1, *l2, *l3;
+
+ if (rd == 0) {
+ /* Treat as NOP. */
+ return true;
+ }
+
+ t0 = tcg_temp_new();
+ t1 = tcg_temp_new();
+ l1 = gen_new_label();
+ l2 = gen_new_label();
+ l3 = gen_new_label();
+
+ gen_load_gpr(t0, rs);
+ gen_load_gpr(t1, rt);
+
+ if (!is_double) {
+ tcg_gen_ext32u_tl(t0, t0);
+ tcg_gen_ext32u_tl(t1, t1);
+ }
+ tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t0, is_double ? LLONG_MIN : INT_MIN, l2);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
+ gen_set_label(l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l3);
+ gen_set_label(l2);
+ tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
+ if (!is_double) {
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ }
+ gen_set_label(l3);
+
+ return true;
+}
+
+static bool trans_MOD_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_MOD_G(s, a->rd, a->rs, a->rt, false);
+}
+
+static bool trans_DMOD_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_MOD_G(s, a->rd, a->rs, a->rt, true);
+}
+
+static bool gen_lext_MODU_G(DisasContext *s, int rd, int rs, int rt,
+ bool is_double)
+{
+ TCGv t0, t1;
+ TCGLabel *l1, *l2;
+
+ if (rd == 0) {
+ /* Treat as NOP. */
+ return true;
+ }
+
+ t0 = tcg_temp_new();
+ t1 = tcg_temp_new();
+ l1 = gen_new_label();
+ l2 = gen_new_label();
+
+ gen_load_gpr(t0, rs);
+ gen_load_gpr(t1, rt);
+
+ if (!is_double) {
+ tcg_gen_ext32u_tl(t0, t0);
+ tcg_gen_ext32u_tl(t1, t1);
+ }
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l2);
+ gen_set_label(l1);
+ tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
+ if (!is_double) {
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ }
+ gen_set_label(l2);
+
+ return true;
+}
+
+static bool trans_MODU_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_MODU_G(s, a->rd, a->rs, a->rt, false);
+}
+
+static bool trans_DMODU_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_MODU_G(s, a->rd, a->rs, a->rt, true);
+}
+
+static bool gen_lext_MULT_G(DisasContext *s, int rd, int rs, int rt,
+ bool is_double)
+{
+ TCGv t0, t1;
+
+ if (rd == 0) {
+ /* Treat as NOP. */
+ return true;
+ }
+
+ t0 = tcg_temp_new();
+ t1 = tcg_temp_new();
+
+ gen_load_gpr(t0, rs);
+ gen_load_gpr(t1, rt);
+
+ tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
+ if (!is_double) {
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ }
+
+ return true;
+}
+
+static bool trans_MULTu_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_MULT_G(s, a->rd, a->rs, a->rt, false);
+}
+
+static bool trans_DMULTu_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_MULT_G(s, a->rd, a->rs, a->rt, true);
+}
+
+bool decode_ext_loongson(DisasContext *ctx, uint32_t insn)
+{
+ if (!decode_64bit_enabled(ctx)) {
+ return false;
+ }
+ if ((ctx->insn_flags & INSN_LOONGSON2E) && decode_godson2(ctx, ctx->opcode)) {
+ return true;
+ }
+ if ((ctx->insn_flags & ASE_LEXT) && decode_loong_ext(ctx, ctx->opcode)) {
+ return true;
+ }
+ return false;
+}
diff --git a/target/mips/tcg/meson.build b/target/mips/tcg/meson.build
index ea7fb58..fff9cd6 100644
--- a/target/mips/tcg/meson.build
+++ b/target/mips/tcg/meson.build
@@ -5,6 +5,8 @@ gen = [
decodetree.process('vr54xx.decode', extra_args: '--decode=decode_ext_vr54xx'),
decodetree.process('octeon.decode', extra_args: '--decode=decode_ext_octeon'),
decodetree.process('lcsr.decode', extra_args: '--decode=decode_ase_lcsr'),
+ decodetree.process('godson2.decode', extra_args: ['--static-decode=decode_godson2']),
+ decodetree.process('loong-ext.decode', extra_args: ['--static-decode=decode_loong_ext']),
]
mips_ss.add(gen)
@@ -28,10 +30,11 @@ mips_ss.add(when: 'TARGET_MIPS64', if_true: files(
'tx79_translate.c',
'octeon_translate.c',
'lcsr_translate.c',
+ 'loong_translate.c',
), if_false: files(
'mxu_translate.c',
))
if have_system
- subdir('sysemu')
+ subdir('system')
endif
diff --git a/target/mips/tcg/micromips_translate.c.inc b/target/mips/tcg/micromips_translate.c.inc
index 7510831..c479bec 100644
--- a/target/mips/tcg/micromips_translate.c.inc
+++ b/target/mips/tcg/micromips_translate.c.inc
@@ -977,23 +977,21 @@ static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
gen_reserved_instruction(ctx);
return;
}
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL |
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_SL |
ctx->default_tcg_memop_mask);
gen_store_gpr(t1, rd);
- tcg_gen_movi_tl(t1, 4);
- gen_op_addr_add(ctx, t0, t0, t1);
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL |
+ gen_op_addr_addi(ctx, t0, t0, 4);
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_SL |
ctx->default_tcg_memop_mask);
gen_store_gpr(t1, rd + 1);
break;
case SWP:
gen_load_gpr(t1, rd);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL |
ctx->default_tcg_memop_mask);
- tcg_gen_movi_tl(t1, 4);
- gen_op_addr_add(ctx, t0, t0, t1);
+ gen_op_addr_addi(ctx, t0, t0, 4);
gen_load_gpr(t1, rd + 1);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL |
ctx->default_tcg_memop_mask);
break;
#ifdef TARGET_MIPS64
@@ -1002,23 +1000,21 @@ static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
gen_reserved_instruction(ctx);
return;
}
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
ctx->default_tcg_memop_mask);
gen_store_gpr(t1, rd);
- tcg_gen_movi_tl(t1, 8);
- gen_op_addr_add(ctx, t0, t0, t1);
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
+ gen_op_addr_addi(ctx, t0, t0, 8);
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
ctx->default_tcg_memop_mask);
gen_store_gpr(t1, rd + 1);
break;
case SDP:
gen_load_gpr(t1, rd);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
ctx->default_tcg_memop_mask);
- tcg_gen_movi_tl(t1, 8);
- gen_op_addr_add(ctx, t0, t0, t1);
+ gen_op_addr_addi(ctx, t0, t0, 8);
gen_load_gpr(t1, rd + 1);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
ctx->default_tcg_memop_mask);
break;
#endif
@@ -2488,7 +2484,10 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
mips32_op = OPC_BC1TANY4;
do_cp1mips3d:
check_cop1x(ctx);
- check_insn(ctx, ASE_MIPS3D);
+ if (!ase_3d_available(env)) {
+ gen_reserved_instruction(ctx);
+ break;
+ }
/* Fall through */
do_cp1branch:
if (env->CP0_Config1 & (1 << CP0C1_FP)) {
@@ -2572,13 +2571,13 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
gen_st(ctx, mips32_op, rt, rs, offset);
break;
case SC:
- gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
+ gen_st_cond(ctx, rt, rs, offset, mo_endian(ctx) | MO_SL, false);
break;
#if defined(TARGET_MIPS64)
case SCD:
check_insn(ctx, ISA_MIPS3);
check_mips_64(ctx);
- gen_st_cond(ctx, rt, rs, offset, MO_TEUQ, false);
+ gen_st_cond(ctx, rt, rs, offset, mo_endian(ctx) | MO_UQ, false);
break;
#endif
case LD_EVA:
@@ -2659,7 +2658,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
mips32_op = OPC_SHE;
goto do_st_lr;
case SCE:
- gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
+ gen_st_cond(ctx, rt, rs, offset, mo_endian(ctx) | MO_SL, true);
break;
case SWE:
mips32_op = OPC_SWE;
diff --git a/target/mips/tcg/mips16e_translate.c.inc b/target/mips/tcg/mips16e_translate.c.inc
index 5cffe0e..97da345 100644
--- a/target/mips/tcg/mips16e_translate.c.inc
+++ b/target/mips/tcg/mips16e_translate.c.inc
@@ -122,11 +122,21 @@ enum {
static int xlat(int r)
{
- static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
+ static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
return map[r];
}
+static void decr_and_store(DisasContext *ctx, unsigned regidx, TCGv t0)
+{
+ TCGv t1 = tcg_temp_new();
+
+ gen_op_addr_addi(ctx, t0, t0, -4);
+ gen_load_gpr(t1, regidx);
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL |
+ ctx->default_tcg_memop_mask);
+}
+
static void gen_mips16_save(DisasContext *ctx,
int xsregs, int aregs,
int do_ra, int do_s0, int do_s1,
@@ -134,7 +144,6 @@ static void gen_mips16_save(DisasContext *ctx,
{
TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
- TCGv t2 = tcg_temp_new();
int args, astatic;
switch (aregs) {
@@ -172,70 +181,62 @@ static void gen_mips16_save(DisasContext *ctx,
case 4:
gen_base_offset_addr(ctx, t0, 29, 12);
gen_load_gpr(t1, 7);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL |
ctx->default_tcg_memop_mask);
/* Fall through */
case 3:
gen_base_offset_addr(ctx, t0, 29, 8);
gen_load_gpr(t1, 6);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL |
ctx->default_tcg_memop_mask);
/* Fall through */
case 2:
gen_base_offset_addr(ctx, t0, 29, 4);
gen_load_gpr(t1, 5);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL |
ctx->default_tcg_memop_mask);
/* Fall through */
case 1:
gen_base_offset_addr(ctx, t0, 29, 0);
gen_load_gpr(t1, 4);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL |
ctx->default_tcg_memop_mask);
}
gen_load_gpr(t0, 29);
-#define DECR_AND_STORE(reg) do { \
- tcg_gen_movi_tl(t2, -4); \
- gen_op_addr_add(ctx, t0, t0, t2); \
- gen_load_gpr(t1, reg); \
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL | \
- ctx->default_tcg_memop_mask); \
- } while (0)
-
if (do_ra) {
- DECR_AND_STORE(31);
+ decr_and_store(ctx, 31, t0);
}
switch (xsregs) {
case 7:
- DECR_AND_STORE(30);
+ decr_and_store(ctx, 30, t0);
/* Fall through */
case 6:
- DECR_AND_STORE(23);
+ decr_and_store(ctx, 23, t0);
/* Fall through */
case 5:
- DECR_AND_STORE(22);
+ decr_and_store(ctx, 22, t0);
/* Fall through */
case 4:
- DECR_AND_STORE(21);
+ decr_and_store(ctx, 21, t0);
/* Fall through */
case 3:
- DECR_AND_STORE(20);
+ decr_and_store(ctx, 20, t0);
/* Fall through */
case 2:
- DECR_AND_STORE(19);
+ decr_and_store(ctx, 19, t0);
/* Fall through */
case 1:
- DECR_AND_STORE(18);
+ decr_and_store(ctx, 18, t0);
}
if (do_s1) {
- DECR_AND_STORE(17);
+ decr_and_store(ctx, 17, t0);
}
if (do_s0) {
- DECR_AND_STORE(16);
+ decr_and_store(ctx, 16, t0);
}
switch (aregs) {
@@ -270,21 +271,31 @@ static void gen_mips16_save(DisasContext *ctx,
}
if (astatic > 0) {
- DECR_AND_STORE(7);
+ decr_and_store(ctx, 7, t0);
if (astatic > 1) {
- DECR_AND_STORE(6);
+ decr_and_store(ctx, 6, t0);
if (astatic > 2) {
- DECR_AND_STORE(5);
+ decr_and_store(ctx, 5, t0);
if (astatic > 3) {
- DECR_AND_STORE(4);
+ decr_and_store(ctx, 4, t0);
}
}
}
}
-#undef DECR_AND_STORE
- tcg_gen_movi_tl(t2, -framesize);
- gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
+ gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], -framesize);
+}
+
+static void decr_and_load(DisasContext *ctx, unsigned regidx, TCGv t0)
+{
+ TCGv t1 = tcg_temp_new();
+ TCGv t2 = tcg_temp_new();
+
+ tcg_gen_movi_tl(t2, -4);
+ gen_op_addr_add(ctx, t0, t0, t2);
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TE | MO_SL |
+ ctx->default_tcg_memop_mask);
+ gen_store_gpr(t1, regidx);
}
static void gen_mips16_restore(DisasContext *ctx,
@@ -294,52 +305,41 @@ static void gen_mips16_restore(DisasContext *ctx,
{
int astatic;
TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- TCGv t2 = tcg_temp_new();
-
- tcg_gen_movi_tl(t2, framesize);
- gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
-#define DECR_AND_LOAD(reg) do { \
- tcg_gen_movi_tl(t2, -4); \
- gen_op_addr_add(ctx, t0, t0, t2); \
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL | \
- ctx->default_tcg_memop_mask); \
- gen_store_gpr(t1, reg); \
- } while (0)
+ gen_op_addr_addi(ctx, t0, cpu_gpr[29], framesize);
if (do_ra) {
- DECR_AND_LOAD(31);
+ decr_and_load(ctx, 31, t0);
}
switch (xsregs) {
case 7:
- DECR_AND_LOAD(30);
+ decr_and_load(ctx, 30, t0);
/* Fall through */
case 6:
- DECR_AND_LOAD(23);
+ decr_and_load(ctx, 23, t0);
/* Fall through */
case 5:
- DECR_AND_LOAD(22);
+ decr_and_load(ctx, 22, t0);
/* Fall through */
case 4:
- DECR_AND_LOAD(21);
+ decr_and_load(ctx, 21, t0);
/* Fall through */
case 3:
- DECR_AND_LOAD(20);
+ decr_and_load(ctx, 20, t0);
/* Fall through */
case 2:
- DECR_AND_LOAD(19);
+ decr_and_load(ctx, 19, t0);
/* Fall through */
case 1:
- DECR_AND_LOAD(18);
+ decr_and_load(ctx, 18, t0);
}
if (do_s1) {
- DECR_AND_LOAD(17);
+ decr_and_load(ctx, 17, t0);
}
if (do_s0) {
- DECR_AND_LOAD(16);
+ decr_and_load(ctx, 16, t0);
}
switch (aregs) {
@@ -374,21 +374,19 @@ static void gen_mips16_restore(DisasContext *ctx,
}
if (astatic > 0) {
- DECR_AND_LOAD(7);
+ decr_and_load(ctx, 7, t0);
if (astatic > 1) {
- DECR_AND_LOAD(6);
+ decr_and_load(ctx, 6, t0);
if (astatic > 2) {
- DECR_AND_LOAD(5);
+ decr_and_load(ctx, 5, t0);
if (astatic > 3) {
- DECR_AND_LOAD(4);
+ decr_and_load(ctx, 4, t0);
}
}
}
}
-#undef DECR_AND_LOAD
- tcg_gen_movi_tl(t2, framesize);
- gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
+ gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], framesize);
}
#if defined(TARGET_MIPS64)
diff --git a/target/mips/tcg/msa_helper.c b/target/mips/tcg/msa_helper.c
index d218176..f554b3d 100644
--- a/target/mips/tcg/msa_helper.c
+++ b/target/mips/tcg/msa_helper.c
@@ -21,10 +21,11 @@
#include "cpu.h"
#include "internal.h"
#include "tcg/tcg.h"
-#include "exec/exec-all.h"
-#include "exec/cpu_ldst.h"
+#include "accel/tcg/cpu-ldst.h"
+#include "accel/tcg/probe.h"
#include "exec/helper-proto.h"
#include "exec/memop.h"
+#include "exec/target_page.h"
#include "fpu/softfloat.h"
#include "fpu_helper.h"
@@ -5577,7 +5578,7 @@ static inline int64_t msa_mulr_q_df(uint32_t df, int64_t arg1, int64_t arg2)
{
int64_t q_min = DF_MIN_INT(df);
int64_t q_max = DF_MAX_INT(df);
- int64_t r_bit = 1 << (DF_BITS(df) - 2);
+ int64_t r_bit = 1LL << (DF_BITS(df) - 2);
if (arg1 == q_min && arg2 == q_min) {
return q_max;
@@ -5685,7 +5686,7 @@ static inline int64_t msa_maddr_q_df(uint32_t df, int64_t dest, int64_t arg1,
int64_t q_max = DF_MAX_INT(df);
int64_t q_min = DF_MIN_INT(df);
- int64_t r_bit = 1 << (DF_BITS(df) - 2);
+ int64_t r_bit = 1LL << (DF_BITS(df) - 2);
q_prod = arg1 * arg2;
q_ret = ((dest << (DF_BITS(df) - 1)) + q_prod + r_bit) >> (DF_BITS(df) - 1);
@@ -5700,7 +5701,7 @@ static inline int64_t msa_msubr_q_df(uint32_t df, int64_t dest, int64_t arg1,
int64_t q_max = DF_MAX_INT(df);
int64_t q_min = DF_MIN_INT(df);
- int64_t r_bit = 1 << (DF_BITS(df) - 2);
+ int64_t r_bit = 1LL << (DF_BITS(df) - 2);
q_prod = arg1 * arg2;
q_ret = ((dest << (DF_BITS(df) - 1)) - q_prod + r_bit) >> (DF_BITS(df) - 1);
@@ -6231,7 +6232,7 @@ static inline int update_msacsr(CPUMIPSState *env, int action, int denormal)
enable = GET_FP_ENABLE(env->active_tc.msacsr) | FP_UNIMPLEMENTED;
/* Set Inexact (I) when flushing inputs to zero */
- if ((ieee_exception_flags & float_flag_input_denormal) &&
+ if ((ieee_exception_flags & float_flag_input_denormal_flushed) &&
(env->active_tc.msacsr & MSACSR_FS_MASK) != 0) {
if (action & CLEAR_IS_INEXACT) {
mips_exception_flags &= ~FP_INEXACT;
@@ -6241,7 +6242,7 @@ static inline int update_msacsr(CPUMIPSState *env, int action, int denormal)
}
/* Set Inexact (I) and Underflow (U) when flushing outputs to zero */
- if ((ieee_exception_flags & float_flag_output_denormal) &&
+ if ((ieee_exception_flags & float_flag_output_denormal_flushed) &&
(env->active_tc.msacsr & MSACSR_FS_MASK) != 0) {
mips_exception_flags |= FP_INEXACT;
if (action & CLEAR_FS_UNDERFLOW) {
@@ -8211,15 +8212,6 @@ void helper_msa_ffint_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
/* Element-by-element access macros */
#define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df))
-#if !defined(CONFIG_USER_ONLY)
-#define MEMOP_IDX(DF) \
- MemOpIdx oi = make_memop_idx(MO_TE | DF | MO_UNALN, \
- mips_env_mmu_index(env));
-#else
-#define MEMOP_IDX(DF)
-#endif
-
-#if TARGET_BIG_ENDIAN
static inline uint64_t bswap16x4(uint64_t x)
{
uint64_t m = 0x00ff00ff00ff00ffull;
@@ -8230,7 +8222,6 @@ static inline uint64_t bswap32x2(uint64_t x)
{
return ror64(bswap64(x), 32);
}
-#endif
void helper_msa_ld_b(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
@@ -8259,10 +8250,10 @@ void helper_msa_ld_h(CPUMIPSState *env, uint32_t wd,
*/
d0 = cpu_ldq_le_data_ra(env, addr + 0, ra);
d1 = cpu_ldq_le_data_ra(env, addr + 8, ra);
-#if TARGET_BIG_ENDIAN
- d0 = bswap16x4(d0);
- d1 = bswap16x4(d1);
-#endif
+ if (mips_env_is_bigendian(env)) {
+ d0 = bswap16x4(d0);
+ d1 = bswap16x4(d1);
+ }
pwd->d[0] = d0;
pwd->d[1] = d1;
}
@@ -8280,10 +8271,10 @@ void helper_msa_ld_w(CPUMIPSState *env, uint32_t wd,
*/
d0 = cpu_ldq_le_data_ra(env, addr + 0, ra);
d1 = cpu_ldq_le_data_ra(env, addr + 8, ra);
-#if TARGET_BIG_ENDIAN
- d0 = bswap32x2(d0);
- d1 = bswap32x2(d1);
-#endif
+ if (mips_env_is_bigendian(env)) {
+ d0 = bswap32x2(d0);
+ d1 = bswap32x2(d1);
+ }
pwd->d[0] = d0;
pwd->d[1] = d1;
}
@@ -8346,10 +8337,10 @@ void helper_msa_st_h(CPUMIPSState *env, uint32_t wd,
/* Store 8 bytes at a time. See helper_msa_ld_h. */
d0 = pwd->d[0];
d1 = pwd->d[1];
-#if TARGET_BIG_ENDIAN
- d0 = bswap16x4(d0);
- d1 = bswap16x4(d1);
-#endif
+ if (mips_env_is_bigendian(env)) {
+ d0 = bswap16x4(d0);
+ d1 = bswap16x4(d1);
+ }
cpu_stq_le_data_ra(env, addr + 0, d0, ra);
cpu_stq_le_data_ra(env, addr + 8, d1, ra);
}
@@ -8367,10 +8358,10 @@ void helper_msa_st_w(CPUMIPSState *env, uint32_t wd,
/* Store 8 bytes at a time. See helper_msa_ld_w. */
d0 = pwd->d[0];
d1 = pwd->d[1];
-#if TARGET_BIG_ENDIAN
- d0 = bswap32x2(d0);
- d1 = bswap32x2(d1);
-#endif
+ if (mips_env_is_bigendian(env)) {
+ d0 = bswap32x2(d0);
+ d1 = bswap32x2(d1);
+ }
cpu_stq_le_data_ra(env, addr + 0, d0, ra);
cpu_stq_le_data_ra(env, addr + 8, d1, ra);
}
diff --git a/target/mips/tcg/mxu_translate.c b/target/mips/tcg/mxu_translate.c
index c517258..35ebb03 100644
--- a/target/mips/tcg/mxu_translate.c
+++ b/target/mips/tcg/mxu_translate.c
@@ -1533,7 +1533,7 @@ static void gen_mxu_s32ldxx(DisasContext *ctx, bool reversed, bool postinc)
tcg_gen_add_tl(t0, t0, t1);
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx,
- (MO_TESL ^ (reversed ? MO_BSWAP : 0)) |
+ MO_SL | mo_endian_rev(ctx, reversed) |
ctx->default_tcg_memop_mask);
gen_store_mxu_gpr(t1, XRa);
@@ -1569,7 +1569,7 @@ static void gen_mxu_s32stxx(DisasContext *ctx, bool reversed, bool postinc)
gen_load_mxu_gpr(t1, XRa);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
- (MO_TESL ^ (reversed ? MO_BSWAP : 0)) |
+ MO_SL | mo_endian_rev(ctx, reversed) |
ctx->default_tcg_memop_mask);
if (postinc) {
@@ -1605,7 +1605,7 @@ static void gen_mxu_s32ldxvx(DisasContext *ctx, bool reversed,
tcg_gen_add_tl(t0, t0, t1);
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx,
- (MO_TESL ^ (reversed ? MO_BSWAP : 0)) |
+ MO_SL | mo_endian_rev(ctx, reversed) |
ctx->default_tcg_memop_mask);
gen_store_mxu_gpr(t1, XRa);
@@ -1675,7 +1675,7 @@ static void gen_mxu_s32stxvx(DisasContext *ctx, bool reversed,
gen_load_mxu_gpr(t1, XRa);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
- (MO_TESL ^ (reversed ? MO_BSWAP : 0)) |
+ MO_SL | mo_endian_rev(ctx, reversed) |
ctx->default_tcg_memop_mask);
if (postinc) {
@@ -4803,19 +4803,19 @@ static void decode_opc_mxu__pool17(DisasContext *ctx)
switch (opcode) {
case OPC_MXU_LXW:
- gen_mxu_lxx(ctx, strd2, MO_TE | MO_UL);
+ gen_mxu_lxx(ctx, strd2, mo_endian(ctx) | MO_UL);
break;
case OPC_MXU_LXB:
- gen_mxu_lxx(ctx, strd2, MO_TE | MO_SB);
+ gen_mxu_lxx(ctx, strd2, mo_endian(ctx) | MO_SB);
break;
case OPC_MXU_LXH:
- gen_mxu_lxx(ctx, strd2, MO_TE | MO_SW);
+ gen_mxu_lxx(ctx, strd2, mo_endian(ctx) | MO_SW);
break;
case OPC_MXU_LXBU:
- gen_mxu_lxx(ctx, strd2, MO_TE | MO_UB);
+ gen_mxu_lxx(ctx, strd2, mo_endian(ctx) | MO_UB);
break;
case OPC_MXU_LXHU:
- gen_mxu_lxx(ctx, strd2, MO_TE | MO_UW);
+ gen_mxu_lxx(ctx, strd2, mo_endian(ctx) | MO_UW);
break;
default:
MIPS_INVAL("decode_opc_mxu");
diff --git a/target/mips/tcg/nanomips_translate.c.inc b/target/mips/tcg/nanomips_translate.c.inc
index b4b746d..1e27414 100644
--- a/target/mips/tcg/nanomips_translate.c.inc
+++ b/target/mips/tcg/nanomips_translate.c.inc
@@ -998,8 +998,9 @@ static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
TCGv tmp2 = tcg_temp_new();
gen_base_offset_addr(ctx, taddr, base, offset);
- tcg_gen_qemu_ld_i64(tval, taddr, ctx->mem_idx, MO_TEUQ | MO_ALIGN);
- if (cpu_is_bigendian(ctx)) {
+ tcg_gen_qemu_ld_i64(tval, taddr, ctx->mem_idx,
+ mo_endian(ctx) | MO_UQ | MO_ALIGN);
+ if (disas_is_bigendian(ctx)) {
tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
} else {
tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
@@ -1031,7 +1032,7 @@ static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
gen_load_gpr(tmp1, reg1);
gen_load_gpr(tmp2, reg2);
- if (cpu_is_bigendian(ctx)) {
+ if (disas_is_bigendian(ctx)) {
tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
} else {
tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
@@ -1052,8 +1053,7 @@ static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
tcg_gen_movi_tl(cpu_gpr[reg1], 0);
}
gen_set_label(lab_done);
- tcg_gen_movi_tl(lladdr, -1);
- tcg_gen_st_tl(lladdr, tcg_env, offsetof(CPUMIPSState, lladdr));
+ tcg_gen_st_tl(tcg_constant_tl(-1), tcg_env, offsetof(CPUMIPSState, lladdr));
}
static void gen_adjust_sp(DisasContext *ctx, int u)
@@ -1075,7 +1075,7 @@ static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
gen_base_offset_addr(ctx, va, 29, this_offset);
gen_load_gpr(t0, this_rt);
tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
- (MO_TEUL | ctx->default_tcg_memop_mask));
+ mo_endian(ctx) | MO_UL | ctx->default_tcg_memop_mask);
counter++;
}
@@ -1095,8 +1095,8 @@ static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
int this_offset = u - ((counter + 1) << 2);
gen_base_offset_addr(ctx, va, 29, this_offset);
- tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
- ctx->default_tcg_memop_mask);
+ tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx,
+ mo_endian(ctx) | MO_SL | ctx->default_tcg_memop_mask);
tcg_gen_ext32s_tl(t0, t0);
gen_store_gpr(t0, this_rt);
counter++;
@@ -1543,7 +1543,6 @@ static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
{
int16_t imm;
TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
TCGv v0_t = tcg_temp_new();
gen_load_gpr(v0_t, v1);
@@ -1570,12 +1569,10 @@ static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
check_dsp(ctx);
switch (extract32(ctx->opcode, 12, 2)) {
case NM_MTHLIP:
- tcg_gen_movi_tl(t0, v2 >> 3);
- gen_helper_mthlip(t0, v0_t, tcg_env);
+ gen_helper_mthlip(tcg_constant_tl(v2 >> 3), v0_t, tcg_env);
break;
case NM_SHILOV:
- tcg_gen_movi_tl(t0, v2 >> 3);
- gen_helper_shilo(t0, v0_t, tcg_env);
+ gen_helper_shilo(tcg_constant_tl(v2 >> 3), v0_t, tcg_env);
break;
default:
gen_reserved_instruction(ctx);
@@ -1587,39 +1584,34 @@ static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
imm = extract32(ctx->opcode, 14, 7);
switch (extract32(ctx->opcode, 12, 2)) {
case NM_RDDSP:
- tcg_gen_movi_tl(t0, imm);
- gen_helper_rddsp(t0, t0, tcg_env);
+ gen_helper_rddsp(t0, tcg_constant_tl(imm), tcg_env);
gen_store_gpr(t0, ret);
break;
case NM_WRDSP:
gen_load_gpr(t0, ret);
- tcg_gen_movi_tl(t1, imm);
- gen_helper_wrdsp(t0, t1, tcg_env);
+ gen_helper_wrdsp(t0, tcg_constant_tl(imm), tcg_env);
break;
case NM_EXTP:
- tcg_gen_movi_tl(t0, v2 >> 3);
- tcg_gen_movi_tl(t1, v1);
- gen_helper_extp(t0, t0, t1, tcg_env);
+ gen_helper_extp(t0, tcg_constant_tl(v2 >> 3),
+ tcg_constant_tl(v1), tcg_env);
gen_store_gpr(t0, ret);
break;
case NM_EXTPDP:
- tcg_gen_movi_tl(t0, v2 >> 3);
- tcg_gen_movi_tl(t1, v1);
- gen_helper_extpdp(t0, t0, t1, tcg_env);
+ gen_helper_extpdp(t0, tcg_constant_tl(v2 >> 3),
+ tcg_constant_tl(v1), tcg_env);
gen_store_gpr(t0, ret);
break;
}
break;
case NM_POOL32AXF_1_4:
check_dsp(ctx);
- tcg_gen_movi_tl(t0, v2 >> 2);
switch (extract32(ctx->opcode, 12, 1)) {
case NM_SHLL_QB:
- gen_helper_shll_qb(t0, t0, v0_t, tcg_env);
+ gen_helper_shll_qb(t0, tcg_constant_tl(v2 >> 2), v0_t, tcg_env);
gen_store_gpr(t0, ret);
break;
case NM_SHRL_QB:
- gen_helper_shrl_qb(t0, t0, v0_t);
+ gen_helper_shrl_qb(t0, tcg_constant_tl(v2 >> 2), v0_t);
gen_store_gpr(t0, ret);
break;
}
@@ -1630,23 +1622,25 @@ static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
break;
case NM_POOL32AXF_1_7:
check_dsp(ctx);
- tcg_gen_movi_tl(t0, v2 >> 3);
- tcg_gen_movi_tl(t1, v1);
switch (extract32(ctx->opcode, 12, 2)) {
case NM_EXTR_W:
- gen_helper_extr_w(t0, t0, t1, tcg_env);
+ gen_helper_extr_w(t0, tcg_constant_tl(v2 >> 3),
+ tcg_constant_tl(v1), tcg_env);
gen_store_gpr(t0, ret);
break;
case NM_EXTR_R_W:
- gen_helper_extr_r_w(t0, t0, t1, tcg_env);
+ gen_helper_extr_r_w(t0, tcg_constant_tl(v2 >> 3),
+ tcg_constant_tl(v1), tcg_env);
gen_store_gpr(t0, ret);
break;
case NM_EXTR_RS_W:
- gen_helper_extr_rs_w(t0, t0, t1, tcg_env);
+ gen_helper_extr_rs_w(t0, tcg_constant_tl(v2 >> 3),
+ tcg_constant_tl(v1), tcg_env);
gen_store_gpr(t0, ret);
break;
case NM_EXTR_S_H:
- gen_helper_extr_s_h(t0, t0, t1, tcg_env);
+ gen_helper_extr_s_h(t0, tcg_constant_tl(v2 >> 3),
+ tcg_constant_tl(v1), tcg_env);
gen_store_gpr(t0, ret);
break;
}
@@ -1848,8 +1842,7 @@ static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
case NM_EXTRV_W:
check_dsp(ctx);
gen_load_gpr(v1_t, rs);
- tcg_gen_movi_tl(t0, rd >> 3);
- gen_helper_extr_w(t0, t0, v1_t, tcg_env);
+ gen_helper_extr_w(t0, tcg_constant_tl(rd >> 3), v1_t, tcg_env);
gen_store_gpr(t0, ret);
break;
}
@@ -1903,8 +1896,7 @@ static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
break;
case NM_EXTRV_R_W:
check_dsp(ctx);
- tcg_gen_movi_tl(t0, rd >> 3);
- gen_helper_extr_r_w(t0, t0, v1_t, tcg_env);
+ gen_helper_extr_r_w(t0, tcg_constant_tl(rd >> 3), v1_t, tcg_env);
gen_store_gpr(t0, ret);
break;
default:
@@ -1923,8 +1915,7 @@ static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
break;
case NM_EXTPV:
check_dsp(ctx);
- tcg_gen_movi_tl(t0, rd >> 3);
- gen_helper_extp(t0, t0, v1_t, tcg_env);
+ gen_helper_extp(t0, tcg_constant_tl(rd >> 3), v1_t, tcg_env);
gen_store_gpr(t0, ret);
break;
case NM_MSUB:
@@ -1947,8 +1938,7 @@ static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
break;
case NM_EXTRV_RS_W:
check_dsp(ctx);
- tcg_gen_movi_tl(t0, rd >> 3);
- gen_helper_extr_rs_w(t0, t0, v1_t, tcg_env);
+ gen_helper_extr_rs_w(t0, tcg_constant_tl(rd >> 3), v1_t, tcg_env);
gen_store_gpr(t0, ret);
break;
}
@@ -1964,8 +1954,7 @@ static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
break;
case NM_EXTPDPV:
check_dsp(ctx);
- tcg_gen_movi_tl(t0, rd >> 3);
- gen_helper_extpdp(t0, t0, v1_t, tcg_env);
+ gen_helper_extpdp(t0, tcg_constant_tl(rd >> 3), v1_t, tcg_env);
gen_store_gpr(t0, ret);
break;
case NM_MSUBU:
@@ -1990,8 +1979,7 @@ static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
break;
case NM_EXTRV_S_H:
check_dsp(ctx);
- tcg_gen_movi_tl(t0, rd >> 3);
- gen_helper_extr_s_h(t0, t0, v1_t, tcg_env);
+ gen_helper_extr_s_h(t0, tcg_constant_tl(rd >> 3), v1_t, tcg_env);
gen_store_gpr(t0, ret);
break;
}
@@ -2149,24 +2137,22 @@ static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
switch (opc) {
case NM_SHRA_R_QB:
check_dsp_r2(ctx);
- tcg_gen_movi_tl(t0, rd >> 2);
switch (extract32(ctx->opcode, 12, 1)) {
case 0:
/* NM_SHRA_QB */
- gen_helper_shra_qb(t0, t0, rs_t);
+ gen_helper_shra_qb(t0, tcg_constant_tl(rd >> 2), rs_t);
gen_store_gpr(t0, rt);
break;
case 1:
/* NM_SHRA_R_QB */
- gen_helper_shra_r_qb(t0, t0, rs_t);
+ gen_helper_shra_r_qb(t0, tcg_constant_tl(rd >> 2), rs_t);
gen_store_gpr(t0, rt);
break;
}
break;
case NM_SHRL_PH:
check_dsp_r2(ctx);
- tcg_gen_movi_tl(t0, rd >> 1);
- gen_helper_shrl_ph(t0, t0, rs_t);
+ gen_helper_shrl_ph(t0, tcg_constant_tl(rd >> 1), rs_t);
gen_store_gpr(t0, rt);
break;
case NM_REPL_QB:
@@ -2180,8 +2166,7 @@ static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
(uint32_t)imm << 8 |
(uint32_t)imm;
result = (int32_t)result;
- tcg_gen_movi_tl(t0, result);
- gen_store_gpr(t0, rt);
+ gen_store_gpr(tcg_constant_tl(result), rt);
}
break;
default:
@@ -2302,10 +2287,9 @@ static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
{
TCGCond cond = TCG_COND_ALWAYS;
TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
+ TCGv timm = tcg_constant_tl(imm);
gen_load_gpr(t0, rt);
- tcg_gen_movi_tl(t1, imm);
ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
/* Load needed operands and calculate btarget */
@@ -2334,7 +2318,7 @@ static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
} else {
tcg_gen_shri_tl(t0, t0, imm);
tcg_gen_andi_tl(t0, t0, 1);
- tcg_gen_movi_tl(t1, 0);
+ timm = tcg_constant_tl(0);
if (opc == NM_BBEQZC) {
cond = TCG_COND_EQ;
} else {
@@ -2389,7 +2373,7 @@ static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
/* Conditional compact branch */
TCGLabel *fs = gen_new_label();
- tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
+ tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, timm, fs);
gen_goto_tb(ctx, 1, ctx->btarget);
gen_set_label(fs);
@@ -2403,7 +2387,6 @@ static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
int rt)
{
TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
/* load rs */
gen_load_gpr(t0, rs);
@@ -2415,8 +2398,7 @@ static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
/* calculate btarget */
tcg_gen_shli_tl(t0, t0, 1);
- tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
- gen_op_addr_add(ctx, btarget, t1, t0);
+ gen_op_addr_add(ctx, btarget, tcg_constant_tl(ctx->base.pc_next + 4), t0);
/* branch completion */
clear_branch_hflags(ctx);
@@ -2469,11 +2451,9 @@ static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
} else {
/* OPC_JIC, OPC_JIALC */
TCGv tbase = tcg_temp_new();
- TCGv toffset = tcg_temp_new();
gen_load_gpr(tbase, rt);
- tcg_gen_movi_tl(toffset, offset);
- gen_op_addr_add(ctx, btarget, tbase, toffset);
+ gen_op_addr_addi(ctx, btarget, tbase, offset);
}
break;
default:
@@ -2647,13 +2627,13 @@ static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
case NM_LHX:
/*case NM_LHXS:*/
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
- MO_TESW | ctx->default_tcg_memop_mask);
+ mo_endian(ctx) | MO_SW | ctx->default_tcg_memop_mask);
gen_store_gpr(t0, rd);
break;
case NM_LWX:
/*case NM_LWXS:*/
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
- MO_TESL | ctx->default_tcg_memop_mask);
+ mo_endian(ctx) | MO_SL | ctx->default_tcg_memop_mask);
gen_store_gpr(t0, rd);
break;
case NM_LBUX:
@@ -2663,7 +2643,7 @@ static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
case NM_LHUX:
/*case NM_LHUXS:*/
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
- MO_TEUW | ctx->default_tcg_memop_mask);
+ mo_endian(ctx) | MO_UW | ctx->default_tcg_memop_mask);
gen_store_gpr(t0, rd);
break;
case NM_SBX:
@@ -2676,14 +2656,14 @@ static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
check_nms(ctx);
gen_load_gpr(t1, rd);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
- MO_TEUW | ctx->default_tcg_memop_mask);
+ mo_endian(ctx) | MO_UW | ctx->default_tcg_memop_mask);
break;
case NM_SWX:
/*case NM_SWXS:*/
check_nms(ctx);
gen_load_gpr(t1, rd);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
- MO_TEUL | ctx->default_tcg_memop_mask);
+ mo_endian(ctx) | MO_UL | ctx->default_tcg_memop_mask);
break;
case NM_LWC1X:
/*case NM_LWC1XS:*/
@@ -3445,13 +3425,10 @@ static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
case NM_SHILO:
check_dsp(ctx);
{
- TCGv tv0 = tcg_temp_new();
- TCGv tv1 = tcg_temp_new();
int16_t imm = extract32(ctx->opcode, 16, 7);
- tcg_gen_movi_tl(tv0, rd >> 3);
- tcg_gen_movi_tl(tv1, imm);
- gen_helper_shilo(tv0, tv1, tcg_env);
+ gen_helper_shilo(tcg_constant_tl(rd >> 3),
+ tcg_constant_tl(imm), tcg_env);
}
break;
case NM_MULEQ_S_W_PHL:
@@ -3506,8 +3483,7 @@ static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
break;
case NM_SHRA_R_W:
check_dsp(ctx);
- tcg_gen_movi_tl(t0, rd);
- gen_helper_shra_r_w(v1_t, t0, v1_t);
+ gen_helper_shra_r_w(v1_t, tcg_constant_tl(rd), v1_t);
gen_store_gpr(v1_t, rt);
break;
case NM_SHRA_R_PH:
@@ -3547,8 +3523,7 @@ static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
break;
case NM_SHLL_S_W:
check_dsp(ctx);
- tcg_gen_movi_tl(t0, rd);
- gen_helper_shll_s_w(v1_t, t0, v1_t, tcg_env);
+ gen_helper_shll_s_w(v1_t, tcg_constant_tl(rd), v1_t, tcg_env);
gen_store_gpr(v1_t, rt);
break;
case NM_REPL_PH:
@@ -3729,32 +3704,29 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
case NM_LWPC48:
check_nms(ctx);
if (rt != 0) {
- TCGv t0;
- t0 = tcg_temp_new();
-
target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
addr_off);
- tcg_gen_movi_tl(t0, addr);
- tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx,
- MO_TESL | ctx->default_tcg_memop_mask);
+ tcg_gen_qemu_ld_tl(cpu_gpr[rt], tcg_constant_tl(addr),
+ ctx->mem_idx,
+ mo_endian(ctx) | MO_SL
+ | ctx->default_tcg_memop_mask);
}
break;
case NM_SWPC48:
check_nms(ctx);
{
- TCGv t0, t1;
- t0 = tcg_temp_new();
+ TCGv t1;
t1 = tcg_temp_new();
target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
addr_off);
- tcg_gen_movi_tl(t0, addr);
gen_load_gpr(t1, rt);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
- MO_TEUL | ctx->default_tcg_memop_mask);
+ tcg_gen_qemu_st_tl(t1, tcg_constant_tl(addr), ctx->mem_idx,
+ mo_endian(ctx) | MO_UL
+ | ctx->default_tcg_memop_mask);
}
break;
default:
@@ -4132,14 +4104,14 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
switch (extract32(ctx->opcode, 11, 4)) {
case NM_UALH:
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
- MO_UNALN);
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
+ mo_endian(ctx) | MO_SW | MO_UNALN);
gen_store_gpr(t0, rt);
break;
case NM_UASH:
gen_load_gpr(t1, rt);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
- MO_UNALN);
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
+ mo_endian(ctx) | MO_UW | MO_UNALN);
break;
}
}
@@ -4161,7 +4133,8 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
case NM_P_SC:
switch (ctx->opcode & 0x03) {
case NM_SC:
- gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
+ gen_st_cond(ctx, rt, rs, s, mo_endian(ctx) | MO_SL,
+ false);
break;
case NM_SCWP:
check_xnp(ctx);
@@ -4274,7 +4247,8 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
check_xnp(ctx);
check_eva(ctx);
check_cp0_enabled(ctx);
- gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
+ gen_st_cond(ctx, rt, rs, s, mo_endian(ctx) | MO_SL,
+ true);
break;
case NM_SCWPE:
check_xnp(ctx);
@@ -4317,7 +4291,7 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
switch (extract32(ctx->opcode, 11, 1)) {
case NM_LWM:
tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
- memop | MO_TESL);
+ memop | mo_endian(ctx) | MO_SL);
gen_store_gpr(t1, this_rt);
if ((this_rt == rs) &&
(counter != (count - 1))) {
@@ -4328,7 +4302,7 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
this_rt = (rt == 0) ? 0 : this_rt;
gen_load_gpr(t1, this_rt);
tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
- memop | MO_TEUL);
+ memop | mo_endian(ctx) | MO_UL);
break;
}
counter++;
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index e25c4cb..d9eb437 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -18,8 +18,8 @@ static bool trans_BBIT(DisasContext *ctx, arg_BBIT *a)
TCGv p;
if (ctx->hflags & MIPS_HFLAG_BMASK) {
- LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
- TARGET_FMT_lx "\n", ctx->base.pc_next);
+ LOG_DISAS("Branch in delay / forbidden slot at PC 0x%" VADDR_PRIx "\n",
+ ctx->base.pc_next);
generate_exception_end(ctx, EXCP_RI);
return true;
}
diff --git a/target/mips/tcg/op_helper.c b/target/mips/tcg/op_helper.c
index 65403f1..b906d10 100644
--- a/target/mips/tcg/op_helper.c
+++ b/target/mips/tcg/op_helper.c
@@ -22,7 +22,6 @@
#include "cpu.h"
#include "internal.h"
#include "exec/helper-proto.h"
-#include "exec/exec-all.h"
#include "exec/memop.h"
#include "fpu_helper.h"
diff --git a/target/mips/tcg/sysemu/cp0_helper.c b/target/mips/tcg/system/cp0_helper.c
index 79a5c83..101b1e6 100644
--- a/target/mips/tcg/sysemu/cp0_helper.c
+++ b/target/mips/tcg/system/cp0_helper.c
@@ -27,7 +27,8 @@
#include "internal.h"
#include "qemu/host-utils.h"
#include "exec/helper-proto.h"
-#include "exec/exec-all.h"
+#include "exec/cputlb.h"
+#include "exec/target_page.h"
/* SMP helpers. */
@@ -864,36 +865,24 @@ void helper_mtc0_memorymapid(CPUMIPSState *env, target_ulong arg1)
}
}
-void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask)
+uint32_t compute_pagemask(uint32_t val)
{
- uint32_t mask;
- int maskbits;
-
/* Don't care MASKX as we don't support 1KB page */
- mask = extract32((uint32_t)arg1, CP0PM_MASK, 16);
- maskbits = cto32(mask);
+ uint32_t mask = extract32(val, CP0PM_MASK, 16);
+ int maskbits = cto32(mask);
- /* Ensure no more set bit after first zero */
- if ((mask >> maskbits) != 0) {
- goto invalid;
- }
- /* We don't support VTLB entry smaller than target page */
- if ((maskbits + TARGET_PAGE_BITS_MIN) < TARGET_PAGE_BITS) {
- goto invalid;
+ /* Ensure no more set bit after first zero, and maskbits even. */
+ if ((mask >> maskbits) == 0 && maskbits % 2 == 0) {
+ return mask << CP0PM_MASK;
+ } else {
+ /* When invalid, set to default target page size. */
+ return 0;
}
- env->CP0_PageMask = mask << CP0PM_MASK;
-
- return;
-
-invalid:
- /* When invalid, set to default target page size. */
- mask = (~TARGET_PAGE_MASK >> TARGET_PAGE_BITS_MIN);
- env->CP0_PageMask = mask << CP0PM_MASK;
}
void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
{
- update_pagemask(env, arg1, &env->CP0_PageMask);
+ env->CP0_PageMask = compute_pagemask(arg1);
}
void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
diff --git a/target/mips/tcg/sysemu/lcsr_helper.c b/target/mips/tcg/system/lcsr_helper.c
index 25e0357..25e0357 100644
--- a/target/mips/tcg/sysemu/lcsr_helper.c
+++ b/target/mips/tcg/system/lcsr_helper.c
diff --git a/target/mips/tcg/sysemu/meson.build b/target/mips/tcg/system/meson.build
index ec665a4..911341a 100644
--- a/target/mips/tcg/sysemu/meson.build
+++ b/target/mips/tcg/system/meson.build
@@ -1,10 +1,12 @@
mips_system_ss.add(files(
'cp0_helper.c',
- 'mips-semi.c',
'special_helper.c',
'tlb_helper.c',
))
-
+mips_system_ss.add(when: ['CONFIG_SEMIHOSTING'],
+ if_true: files('mips-semi.c'),
+ if_false: files('semihosting-stub.c')
+)
mips_system_ss.add(when: 'TARGET_MIPS64', if_true: files(
'lcsr_helper.c',
))
diff --git a/target/mips/tcg/sysemu/mips-semi.c b/target/mips/tcg/system/mips-semi.c
index 5ba06e9..e822a42 100644
--- a/target/mips/tcg/sysemu/mips-semi.c
+++ b/target/mips/tcg/system/mips-semi.c
@@ -168,6 +168,7 @@ static void uhi_fstat_cb(CPUState *cs, uint64_t ret, int err)
if (!err) {
CPUMIPSState *env = cpu_env(cs);
+ bool swap_needed = HOST_BIG_ENDIAN != mips_env_is_bigendian(env);
target_ulong addr = env->active_tc.gpr[5];
UHIStat *dst = lock_user(VERIFY_WRITE, addr, sizeof(UHIStat), 1);
struct gdb_stat s;
@@ -179,19 +180,35 @@ static void uhi_fstat_cb(CPUState *cs, uint64_t ret, int err)
memcpy(&s, dst, sizeof(struct gdb_stat));
memset(dst, 0, sizeof(UHIStat));
- dst->uhi_st_dev = tswap16(be32_to_cpu(s.gdb_st_dev));
- dst->uhi_st_ino = tswap16(be32_to_cpu(s.gdb_st_ino));
- dst->uhi_st_mode = tswap32(be32_to_cpu(s.gdb_st_mode));
- dst->uhi_st_nlink = tswap16(be32_to_cpu(s.gdb_st_nlink));
- dst->uhi_st_uid = tswap16(be32_to_cpu(s.gdb_st_uid));
- dst->uhi_st_gid = tswap16(be32_to_cpu(s.gdb_st_gid));
- dst->uhi_st_rdev = tswap16(be32_to_cpu(s.gdb_st_rdev));
- dst->uhi_st_size = tswap64(be64_to_cpu(s.gdb_st_size));
- dst->uhi_st_atime = tswap64(be32_to_cpu(s.gdb_st_atime));
- dst->uhi_st_mtime = tswap64(be32_to_cpu(s.gdb_st_mtime));
- dst->uhi_st_ctime = tswap64(be32_to_cpu(s.gdb_st_ctime));
- dst->uhi_st_blksize = tswap64(be64_to_cpu(s.gdb_st_blksize));
- dst->uhi_st_blocks = tswap64(be64_to_cpu(s.gdb_st_blocks));
+ dst->uhi_st_dev = be32_to_cpu(s.gdb_st_dev);
+ dst->uhi_st_ino = be32_to_cpu(s.gdb_st_ino);
+ dst->uhi_st_mode = be32_to_cpu(s.gdb_st_mode);
+ dst->uhi_st_nlink = be32_to_cpu(s.gdb_st_nlink);
+ dst->uhi_st_uid = be32_to_cpu(s.gdb_st_uid);
+ dst->uhi_st_gid = be32_to_cpu(s.gdb_st_gid);
+ dst->uhi_st_rdev = be32_to_cpu(s.gdb_st_rdev);
+ dst->uhi_st_size = be64_to_cpu(s.gdb_st_size);
+ dst->uhi_st_atime = be32_to_cpu(s.gdb_st_atime);
+ dst->uhi_st_mtime = be32_to_cpu(s.gdb_st_mtime);
+ dst->uhi_st_ctime = be32_to_cpu(s.gdb_st_ctime);
+ dst->uhi_st_blksize = be64_to_cpu(s.gdb_st_blksize);
+ dst->uhi_st_blocks = be64_to_cpu(s.gdb_st_blocks);
+
+ if (swap_needed) {
+ dst->uhi_st_dev = bswap16(dst->uhi_st_dev);
+ dst->uhi_st_ino = bswap16(dst->uhi_st_ino);
+ dst->uhi_st_mode = bswap32(dst->uhi_st_mode);
+ dst->uhi_st_nlink = bswap16(dst->uhi_st_nlink);
+ dst->uhi_st_uid = bswap16(dst->uhi_st_uid);
+ dst->uhi_st_gid = bswap16(dst->uhi_st_gid);
+ dst->uhi_st_rdev = bswap16(dst->uhi_st_rdev);
+ dst->uhi_st_size = bswap64(dst->uhi_st_size);
+ dst->uhi_st_atime = bswap64(dst->uhi_st_atime);
+ dst->uhi_st_mtime = bswap64(dst->uhi_st_mtime);
+ dst->uhi_st_ctime = bswap64(dst->uhi_st_ctime);
+ dst->uhi_st_blksize = bswap64(dst->uhi_st_blksize);
+ dst->uhi_st_blocks = bswap64(dst->uhi_st_blocks);
+ }
unlock_user(dst, addr, sizeof(UHIStat));
}
@@ -357,5 +374,4 @@ void mips_semihosting(CPUMIPSState *env)
error_report("Unknown UHI operation %d", op);
abort();
}
- return;
}
diff --git a/target/mips/tcg/system/semihosting-stub.c b/target/mips/tcg/system/semihosting-stub.c
new file mode 100644
index 0000000..bb1f7aa
--- /dev/null
+++ b/target/mips/tcg/system/semihosting-stub.c
@@ -0,0 +1,16 @@
+/*
+ * MIPS semihosting stub
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (c) 2024 Linaro Ltd.
+ * Authors:
+ * Philippe Mathieu-Daudé
+ */
+
+#include "qemu/osdep.h"
+#include "internal.h"
+
+void mips_semihosting(CPUMIPSState *env)
+{
+ g_assert_not_reached();
+}
diff --git a/target/mips/tcg/sysemu/special_helper.c b/target/mips/tcg/system/special_helper.c
index 9ce5e2c..b54cbe8 100644
--- a/target/mips/tcg/sysemu/special_helper.c
+++ b/target/mips/tcg/system/special_helper.c
@@ -22,7 +22,7 @@
#include "qemu/log.h"
#include "cpu.h"
#include "exec/helper-proto.h"
-#include "exec/exec-all.h"
+#include "exec/translation-block.h"
#include "internal.h"
/* Specials */
diff --git a/target/mips/tcg/sysemu/tlb_helper.c b/target/mips/tcg/system/tlb_helper.c
index 3ba6d36..eccaf36 100644
--- a/target/mips/tcg/sysemu/tlb_helper.c
+++ b/target/mips/tcg/system/tlb_helper.c
@@ -21,9 +21,10 @@
#include "cpu.h"
#include "internal.h"
-#include "exec/exec-all.h"
+#include "exec/cputlb.h"
#include "exec/page-protection.h"
-#include "exec/cpu_ldst.h"
+#include "exec/target_page.h"
+#include "accel/tcg/cpu-ldst.h"
#include "exec/log.h"
#include "exec/helper-proto.h"
@@ -592,23 +593,29 @@ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address,
* resulting in a TLB or XTLB Refill exception.
*/
-static bool get_pte(CPUMIPSState *env, uint64_t vaddr, int entry_size,
- uint64_t *pte)
+static bool get_pte(CPUMIPSState *env, uint64_t vaddr, MemOp op,
+ uint64_t *pte, unsigned ptw_mmu_idx)
{
- if ((vaddr & ((entry_size >> 3) - 1)) != 0) {
+ MemOpIdx oi;
+
+ if ((vaddr & (memop_size(op) - 1)) != 0) {
return false;
}
- if (entry_size == 64) {
- *pte = cpu_ldq_code(env, vaddr);
+
+ oi = make_memop_idx(op | mo_endian_env(env), ptw_mmu_idx);
+ if (op == MO_64) {
+ *pte = cpu_ldq_mmu(env, vaddr, oi, 0);
} else {
- *pte = cpu_ldl_code(env, vaddr);
+ *pte = cpu_ldl_mmu(env, vaddr, oi, 0);
}
+
return true;
}
static uint64_t get_tlb_entry_layout(CPUMIPSState *env, uint64_t entry,
- int entry_size, int ptei)
+ MemOp op, int ptei)
{
+ unsigned entry_size = memop_size(op) << 3;
uint64_t result = entry;
uint64_t rixi;
if (ptei > entry_size) {
@@ -624,14 +631,12 @@ static uint64_t get_tlb_entry_layout(CPUMIPSState *env, uint64_t entry,
static int walk_directory(CPUMIPSState *env, uint64_t *vaddr,
int directory_index, bool *huge_page, bool *hgpg_directory_hit,
uint64_t *pw_entrylo0, uint64_t *pw_entrylo1,
- unsigned directory_shift, unsigned leaf_shift, int ptw_mmu_idx)
+ MemOp directory_mop, MemOp leaf_mop, int ptw_mmu_idx)
{
int dph = (env->CP0_PWCtl >> CP0PC_DPH) & 0x1;
int psn = (env->CP0_PWCtl >> CP0PC_PSN) & 0x3F;
int hugepg = (env->CP0_PWCtl >> CP0PC_HUGEPG) & 0x1;
int pf_ptew = (env->CP0_PWField >> CP0PF_PTEW) & 0x3F;
- uint32_t direntry_size = 1 << (directory_shift + 3);
- uint32_t leafentry_size = 1 << (leaf_shift + 3);
uint64_t entry;
uint64_t paddr;
int prot;
@@ -643,14 +648,14 @@ static int walk_directory(CPUMIPSState *env, uint64_t *vaddr,
/* wrong base address */
return 0;
}
- if (!get_pte(env, *vaddr, direntry_size, &entry)) {
+ if (!get_pte(env, *vaddr, directory_mop, &entry, ptw_mmu_idx)) {
return 0;
}
if ((entry & (1 << psn)) && hugepg) {
*huge_page = true;
*hgpg_directory_hit = true;
- entry = get_tlb_entry_layout(env, entry, leafentry_size, pf_ptew);
+ entry = get_tlb_entry_layout(env, entry, leaf_mop, pf_ptew);
w = directory_index - 1;
if (directory_index & 0x1) {
/* Generate adjacent page from same PTE for odd TLB page */
@@ -658,7 +663,7 @@ static int walk_directory(CPUMIPSState *env, uint64_t *vaddr,
*pw_entrylo0 = entry & ~lsb; /* even page */
*pw_entrylo1 = entry | lsb; /* odd page */
} else if (dph) {
- int oddpagebit = 1 << leaf_shift;
+ int oddpagebit = 1 << leaf_mop;
uint64_t vaddr2 = *vaddr ^ oddpagebit;
if (*vaddr & oddpagebit) {
*pw_entrylo1 = entry;
@@ -669,10 +674,10 @@ static int walk_directory(CPUMIPSState *env, uint64_t *vaddr,
ptw_mmu_idx) != TLBRET_MATCH) {
return 0;
}
- if (!get_pte(env, vaddr2, leafentry_size, &entry)) {
+ if (!get_pte(env, vaddr2, leaf_mop, &entry, ptw_mmu_idx)) {
return 0;
}
- entry = get_tlb_entry_layout(env, entry, leafentry_size, pf_ptew);
+ entry = get_tlb_entry_layout(env, entry, leaf_mop, pf_ptew);
if (*vaddr & oddpagebit) {
*pw_entrylo0 = entry;
} else {
@@ -711,7 +716,7 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr address,
/* Native pointer size */
/*For the 32-bit architectures, this bit is fixed to 0.*/
- int native_shift = (((env->CP0_PWSize >> CP0PS_PS) & 1) == 0) ? 2 : 3;
+ MemOp native_op = (((env->CP0_PWSize >> CP0PS_PS) & 1) == 0) ? MO_32 : MO_64;
/* Indices from PWField */
int pf_gdw = (env->CP0_PWField >> CP0PF_GDW) & 0x3F;
@@ -728,11 +733,10 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr address,
/* Other HTW configs */
int hugepg = (env->CP0_PWCtl >> CP0PC_HUGEPG) & 0x1;
- unsigned directory_shift, leaf_shift;
+ MemOp directory_mop, leaf_mop;
/* Offsets into tables */
unsigned goffset, uoffset, moffset, ptoffset0, ptoffset1;
- uint32_t leafentry_size;
/* Starting address - Page Table Base */
uint64_t vaddr = env->CP0_PWBase;
@@ -759,23 +763,21 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr address,
}
/* HTW Shift values (depend on entry size) */
- directory_shift = (hugepg && (ptew == 1)) ? native_shift + 1 : native_shift;
- leaf_shift = (ptew == 1) ? native_shift + 1 : native_shift;
-
- goffset = gindex << directory_shift;
- uoffset = uindex << directory_shift;
- moffset = mindex << directory_shift;
- ptoffset0 = (ptindex >> 1) << (leaf_shift + 1);
- ptoffset1 = ptoffset0 | (1 << (leaf_shift));
+ directory_mop = (hugepg && (ptew == 1)) ? native_op + 1 : native_op;
+ leaf_mop = (ptew == 1) ? native_op + 1 : native_op;
- leafentry_size = 1 << (leaf_shift + 3);
+ goffset = gindex << directory_mop;
+ uoffset = uindex << directory_mop;
+ moffset = mindex << directory_mop;
+ ptoffset0 = (ptindex >> 1) << (leaf_mop + 1);
+ ptoffset1 = ptoffset0 | (1 << (leaf_mop));
/* Global Directory */
if (gdw > 0) {
vaddr |= goffset;
switch (walk_directory(env, &vaddr, pf_gdw, &huge_page, &hgpg_gdhit,
&pw_entrylo0, &pw_entrylo1,
- directory_shift, leaf_shift, ptw_mmu_idx))
+ directory_mop, leaf_mop, ptw_mmu_idx))
{
case 0:
return false;
@@ -792,7 +794,7 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr address,
vaddr |= uoffset;
switch (walk_directory(env, &vaddr, pf_udw, &huge_page, &hgpg_udhit,
&pw_entrylo0, &pw_entrylo1,
- directory_shift, leaf_shift, ptw_mmu_idx))
+ directory_mop, leaf_mop, ptw_mmu_idx))
{
case 0:
return false;
@@ -809,7 +811,7 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr address,
vaddr |= moffset;
switch (walk_directory(env, &vaddr, pf_mdw, &huge_page, &hgpg_mdhit,
&pw_entrylo0, &pw_entrylo1,
- directory_shift, leaf_shift, ptw_mmu_idx))
+ directory_mop, leaf_mop, ptw_mmu_idx))
{
case 0:
return false;
@@ -827,10 +829,10 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr address,
ptw_mmu_idx) != TLBRET_MATCH) {
return false;
}
- if (!get_pte(env, vaddr, leafentry_size, &dir_entry)) {
+ if (!get_pte(env, vaddr, leaf_mop, &dir_entry, ptw_mmu_idx)) {
return false;
}
- dir_entry = get_tlb_entry_layout(env, dir_entry, leafentry_size, pf_ptew);
+ dir_entry = get_tlb_entry_layout(env, dir_entry, leaf_mop, pf_ptew);
pw_entrylo0 = dir_entry;
/* Leaf Level Page Table - Second half of PTE pair */
@@ -839,10 +841,10 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr address,
ptw_mmu_idx) != TLBRET_MATCH) {
return false;
}
- if (!get_pte(env, vaddr, leafentry_size, &dir_entry)) {
+ if (!get_pte(env, vaddr, leaf_mop, &dir_entry, ptw_mmu_idx)) {
return false;
}
- dir_entry = get_tlb_entry_layout(env, dir_entry, leafentry_size, pf_ptew);
+ dir_entry = get_tlb_entry_layout(env, dir_entry, leaf_mop, pf_ptew);
pw_entrylo1 = dir_entry;
refill:
@@ -873,8 +875,8 @@ refill:
break;
}
}
- pw_pagemask = m >> TARGET_PAGE_BITS_MIN;
- update_pagemask(env, pw_pagemask << CP0PM_MASK, &pw_pagemask);
+ pw_pagemask = m >> TARGET_PAGE_BITS;
+ pw_pagemask = compute_pagemask(pw_pagemask << CP0PM_MASK);
pw_entryhi = (address & ~0x1fff) | (env->CP0_EntryHi & 0xFF);
{
target_ulong tmp_entryhi = env->CP0_EntryHi;
diff --git a/target/mips/tcg/sysemu_helper.h.inc b/target/mips/tcg/system_helper.h.inc
index 1861d53..eaac5e2 100644
--- a/target/mips/tcg/sysemu_helper.h.inc
+++ b/target/mips/tcg/system_helper.h.inc
@@ -1,5 +1,5 @@
/*
- * QEMU MIPS sysemu helpers
+ * QEMU MIPS TCG system helpers
*
* Copyright (c) 2004-2005 Jocelyn Mayer
* Copyright (c) 2006 Marius Groeger (FPU operations)
diff --git a/target/mips/tcg/tcg-internal.h b/target/mips/tcg/tcg-internal.h
index aef032c..950e6af 100644
--- a/target/mips/tcg/tcg-internal.h
+++ b/target/mips/tcg/tcg-internal.h
@@ -16,6 +16,8 @@
#include "cpu.h"
void mips_tcg_init(void);
+void mips_translate_code(CPUState *cs, TranslationBlock *tb,
+ int *max_insns, vaddr pc, void *host_pc);
void mips_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb);
G_NORETURN void mips_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
@@ -45,7 +47,7 @@ bool mips_cpu_exec_interrupt(CPUState *cpu, int int_req);
void mmu_init(CPUMIPSState *env, const mips_def_t *def);
-void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask);
+uint32_t compute_pagemask(uint32_t val);
void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra);
uint32_t cpu_mips_get_random(CPUMIPSState *env);
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 333469b..8658315 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -27,6 +27,7 @@
#include "internal.h"
#include "exec/helper-proto.h"
#include "exec/translation-block.h"
+#include "exec/target_page.h"
#include "semihosting/semihost.h"
#include "trace.h"
#include "fpu_helper.h"
@@ -37,7 +38,7 @@
/*
- * Many sysemu-only helpers are not reachable for user-only.
+ * Many system-only helpers are not reachable for user-only.
* Define stub generators here, so that we need not either sprinkle
* ifdefs through the translator, nor provide the helper function.
*/
@@ -327,19 +328,6 @@ enum {
OPC_MUL = 0x02 | OPC_SPECIAL2,
OPC_MSUB = 0x04 | OPC_SPECIAL2,
OPC_MSUBU = 0x05 | OPC_SPECIAL2,
- /* Loongson 2F */
- OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
- OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
- OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
- OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
- OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
- OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
- OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
- OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
- OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
- OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
- OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
- OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
/* Misc */
OPC_CLZ = 0x20 | OPC_SPECIAL2,
OPC_CLO = 0x21 | OPC_SPECIAL2,
@@ -368,20 +356,6 @@ enum {
OPC_RDHWR = 0x3B | OPC_SPECIAL3,
OPC_GINV = 0x3D | OPC_SPECIAL3,
- /* Loongson 2E */
- OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
- OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
- OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
- OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
- OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
- OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
- OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
- OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
- OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
- OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
- OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
- OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
-
/* MIPS DSP Load */
OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
/* MIPS DSP Arithmetic */
@@ -389,16 +363,14 @@ enum {
OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
- /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
- /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
+ OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3,
OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
/* MIPS DSP GPR-Based Shift Sub-class */
OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
/* MIPS DSP Multiply Sub-class insns */
- /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
- /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
+ OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3,
OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
/* DSP Bit/Manipulation Sub-class */
@@ -556,7 +528,6 @@ enum {
OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
};
-#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* MIPS DSP Arithmetic Sub-class */
@@ -1456,8 +1427,7 @@ void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
#endif
}
-static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
- target_long ofs)
+void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base, target_long ofs)
{
tcg_gen_addi_tl(ret, base, ofs);
@@ -1646,13 +1616,18 @@ static inline void check_ps(DisasContext *ctx)
check_cp1_64bitmode(ctx);
}
+bool decode_64bit_enabled(DisasContext *ctx)
+{
+ return ctx->hflags & MIPS_HFLAG_64;
+}
+
/*
* This code generates a "reserved instruction" exception if cpu is not
* 64-bit or 64-bit instructions are not enabled.
*/
void check_mips_64(DisasContext *ctx)
{
- if (unlikely((TARGET_LONG_BITS != 64) || !(ctx->hflags & MIPS_HFLAG_64))) {
+ if (unlikely((TARGET_LONG_BITS != 64) || !decode_64bit_enabled(ctx))) {
gen_reserved_instruction(ctx);
}
}
@@ -1957,16 +1932,16 @@ static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
tcg_gen_st_tl(ret, tcg_env, offsetof(CPUMIPSState, llval)); \
}
#else
-#define OP_LD_ATOMIC(insn, fname) \
+#define OP_LD_ATOMIC(insn, ignored_memop) \
static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
DisasContext *ctx) \
{ \
gen_helper_##insn(ret, tcg_env, arg1, tcg_constant_i32(mem_idx)); \
}
#endif
-OP_LD_ATOMIC(ll, MO_TESL);
+OP_LD_ATOMIC(ll, mo_endian(ctx) | MO_SL);
#if defined(TARGET_MIPS64)
-OP_LD_ATOMIC(lld, MO_TEUQ);
+OP_LD_ATOMIC(lld, mo_endian(ctx) | MO_UQ);
#endif
#undef OP_LD_ATOMIC
@@ -2010,7 +1985,7 @@ static void gen_lxl(DisasContext *ctx, TCGv reg, TCGv addr,
*/
tcg_gen_qemu_ld_tl(t1, addr, mem_idx, MO_UB);
tcg_gen_andi_tl(t1, addr, sizem1);
- if (!cpu_is_bigendian(ctx)) {
+ if (!disas_is_bigendian(ctx)) {
tcg_gen_xori_tl(t1, t1, sizem1);
}
tcg_gen_shli_tl(t1, t1, 3);
@@ -2037,7 +2012,7 @@ static void gen_lxr(DisasContext *ctx, TCGv reg, TCGv addr,
*/
tcg_gen_qemu_ld_tl(t1, addr, mem_idx, MO_UB);
tcg_gen_andi_tl(t1, addr, sizem1);
- if (cpu_is_bigendian(ctx)) {
+ if (disas_is_bigendian(ctx)) {
tcg_gen_xori_tl(t1, t1, sizem1);
}
tcg_gen_shli_tl(t1, t1, 3);
@@ -2073,12 +2048,12 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
switch (opc) {
#if defined(TARGET_MIPS64)
case OPC_LWU:
- tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
+ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_UL |
ctx->default_tcg_memop_mask);
gen_store_gpr(t0, rt);
break;
case OPC_LD:
- tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUQ |
+ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_UQ |
ctx->default_tcg_memop_mask);
gen_store_gpr(t0, rt);
break;
@@ -2090,33 +2065,33 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
case OPC_LDL:
t1 = tcg_temp_new();
gen_load_gpr(t1, rt);
- gen_lxl(ctx, t1, t0, mem_idx, MO_TEUQ);
+ gen_lxl(ctx, t1, t0, mem_idx, mo_endian(ctx) | MO_UQ);
gen_store_gpr(t1, rt);
break;
case OPC_LDR:
t1 = tcg_temp_new();
gen_load_gpr(t1, rt);
- gen_lxr(ctx, t1, t0, mem_idx, MO_TEUQ);
+ gen_lxr(ctx, t1, t0, mem_idx, mo_endian(ctx) | MO_UQ);
gen_store_gpr(t1, rt);
break;
case OPC_LDPC:
t1 = tcg_constant_tl(pc_relative_pc(ctx));
gen_op_addr_add(ctx, t0, t0, t1);
- tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUQ);
+ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_UQ);
gen_store_gpr(t0, rt);
break;
#endif
case OPC_LWPC:
t1 = tcg_constant_tl(pc_relative_pc(ctx));
gen_op_addr_add(ctx, t0, t0, t1);
- tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
+ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_SL);
gen_store_gpr(t0, rt);
break;
case OPC_LWE:
mem_idx = MIPS_HFLAG_UM;
/* fall through */
case OPC_LW:
- tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
+ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_SL |
ctx->default_tcg_memop_mask);
gen_store_gpr(t0, rt);
break;
@@ -2124,7 +2099,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
mem_idx = MIPS_HFLAG_UM;
/* fall through */
case OPC_LH:
- tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
+ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_SW |
ctx->default_tcg_memop_mask);
gen_store_gpr(t0, rt);
break;
@@ -2132,7 +2107,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
mem_idx = MIPS_HFLAG_UM;
/* fall through */
case OPC_LHU:
- tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
+ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_UW |
ctx->default_tcg_memop_mask);
gen_store_gpr(t0, rt);
break;
@@ -2156,7 +2131,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
case OPC_LWL:
t1 = tcg_temp_new();
gen_load_gpr(t1, rt);
- gen_lxl(ctx, t1, t0, mem_idx, MO_TEUL);
+ gen_lxl(ctx, t1, t0, mem_idx, mo_endian(ctx) | MO_UL);
tcg_gen_ext32s_tl(t1, t1);
gen_store_gpr(t1, rt);
break;
@@ -2166,7 +2141,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
case OPC_LWR:
t1 = tcg_temp_new();
gen_load_gpr(t1, rt);
- gen_lxr(ctx, t1, t0, mem_idx, MO_TEUL);
+ gen_lxr(ctx, t1, t0, mem_idx, mo_endian(ctx) | MO_UL);
tcg_gen_ext32s_tl(t1, t1);
gen_store_gpr(t1, rt);
break;
@@ -2194,7 +2169,7 @@ static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
switch (opc) {
#if defined(TARGET_MIPS64)
case OPC_SD:
- tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUQ |
+ tcg_gen_qemu_st_tl(t1, t0, mem_idx, mo_endian(ctx) | MO_UQ |
ctx->default_tcg_memop_mask);
break;
case OPC_SDL:
@@ -2208,14 +2183,14 @@ static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
mem_idx = MIPS_HFLAG_UM;
/* fall through */
case OPC_SW:
- tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
+ tcg_gen_qemu_st_tl(t1, t0, mem_idx, mo_endian(ctx) | MO_UL |
ctx->default_tcg_memop_mask);
break;
case OPC_SHE:
mem_idx = MIPS_HFLAG_UM;
/* fall through */
case OPC_SH:
- tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
+ tcg_gen_qemu_st_tl(t1, t0, mem_idx, mo_endian(ctx) | MO_UW |
ctx->default_tcg_memop_mask);
break;
case OPC_SBE:
@@ -2253,8 +2228,7 @@ static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
/* compare the address against that of the preceding LL */
gen_base_offset_addr(ctx, addr, base, offset);
tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
- tcg_gen_movi_tl(t0, 0);
- gen_store_gpr(t0, rt);
+ gen_store_gpr(tcg_constant_tl(0), rt);
tcg_gen_br(done);
gen_set_label(l1);
@@ -2281,7 +2255,7 @@ static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
case OPC_LWC1:
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
+ tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SL |
ctx->default_tcg_memop_mask);
gen_store_fpr32(ctx, fp0, ft);
}
@@ -2290,14 +2264,14 @@ static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
{
TCGv_i32 fp0 = tcg_temp_new_i32();
gen_load_fpr32(ctx, fp0, ft);
- tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
+ tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL |
ctx->default_tcg_memop_mask);
}
break;
case OPC_LDC1:
{
TCGv_i64 fp0 = tcg_temp_new_i64();
- tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEUQ |
+ tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
ctx->default_tcg_memop_mask);
gen_store_fpr64(ctx, fp0, ft);
}
@@ -2306,7 +2280,7 @@ static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
{
TCGv_i64 fp0 = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp0, ft);
- tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEUQ |
+ tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
ctx->default_tcg_memop_mask);
}
break;
@@ -2987,14 +2961,14 @@ static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
case R6_OPC_LWPC:
offset = sextract32(ctx->opcode << 2, 0, 21);
addr = addr_add(ctx, pc, offset);
- gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
+ gen_r6_ld(addr, rs, ctx->mem_idx, mo_endian(ctx) | MO_SL);
break;
#if defined(TARGET_MIPS64)
case OPC_LWUPC:
check_mips_64(ctx);
offset = sextract32(ctx->opcode << 2, 0, 21);
addr = addr_add(ctx, pc, offset);
- gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
+ gen_r6_ld(addr, rs, ctx->mem_idx, mo_endian(ctx) | MO_UL);
break;
#endif
default:
@@ -3021,7 +2995,7 @@ static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
check_mips_64(ctx);
offset = sextract32(ctx->opcode << 3, 0, 21);
addr = addr_add(ctx, (pc & ~0x7), offset);
- gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUQ);
+ gen_r6_ld(addr, rs, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
break;
#endif
default:
@@ -3060,8 +3034,7 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
tcg_gen_and_tl(t2, t2, t3);
tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
tcg_gen_or_tl(t2, t2, t3);
- tcg_gen_movi_tl(t3, 0);
- tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
+ tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
}
@@ -3077,30 +3050,27 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
tcg_gen_and_tl(t2, t2, t3);
tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
tcg_gen_or_tl(t2, t2, t3);
- tcg_gen_movi_tl(t3, 0);
- tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
+ tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
}
break;
case R6_OPC_DIVU:
{
- TCGv t2 = tcg_constant_tl(0);
- TCGv t3 = tcg_constant_tl(1);
tcg_gen_ext32u_tl(t0, t0);
tcg_gen_ext32u_tl(t1, t1);
- tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
+ tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1,
+ tcg_constant_tl(0), tcg_constant_tl(1), t1);
tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
}
break;
case R6_OPC_MODU:
{
- TCGv t2 = tcg_constant_tl(0);
- TCGv t3 = tcg_constant_tl(1);
tcg_gen_ext32u_tl(t0, t0);
tcg_gen_ext32u_tl(t1, t1);
- tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
+ tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1,
+ tcg_constant_tl(0), tcg_constant_tl(1), t1);
tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
}
@@ -3155,8 +3125,7 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
tcg_gen_and_tl(t2, t2, t3);
tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
tcg_gen_or_tl(t2, t2, t3);
- tcg_gen_movi_tl(t3, 0);
- tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
+ tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
}
break;
@@ -3169,24 +3138,21 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
tcg_gen_and_tl(t2, t2, t3);
tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
tcg_gen_or_tl(t2, t2, t3);
- tcg_gen_movi_tl(t3, 0);
- tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
+ tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
}
break;
case R6_OPC_DDIVU:
{
- TCGv t2 = tcg_constant_tl(0);
- TCGv t3 = tcg_constant_tl(1);
- tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
+ tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1,
+ tcg_constant_tl(0), tcg_constant_tl(1), t1);
tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
}
break;
case R6_OPC_DMODU:
{
- TCGv t2 = tcg_constant_tl(0);
- TCGv t3 = tcg_constant_tl(1);
- tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
+ tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1,
+ tcg_constant_tl(0), tcg_constant_tl(1), t1);
tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
}
break;
@@ -3239,8 +3205,7 @@ static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
tcg_gen_and_tl(t2, t2, t3);
tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
tcg_gen_or_tl(t2, t2, t3);
- tcg_gen_movi_tl(t3, 0);
- tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
+ tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
tcg_gen_div_tl(cpu_LO[1], t0, t1);
tcg_gen_rem_tl(cpu_HI[1], t0, t1);
tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
@@ -3295,8 +3260,7 @@ static void gen_muldiv(DisasContext *ctx, uint32_t opc,
tcg_gen_and_tl(t2, t2, t3);
tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
tcg_gen_or_tl(t2, t2, t3);
- tcg_gen_movi_tl(t3, 0);
- tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
+ tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
tcg_gen_div_tl(cpu_LO[acc], t0, t1);
tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
@@ -3348,17 +3312,15 @@ static void gen_muldiv(DisasContext *ctx, uint32_t opc,
tcg_gen_and_tl(t2, t2, t3);
tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
tcg_gen_or_tl(t2, t2, t3);
- tcg_gen_movi_tl(t3, 0);
- tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
+ tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
tcg_gen_div_tl(cpu_LO[acc], t0, t1);
tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
}
break;
case OPC_DDIVU:
{
- TCGv t2 = tcg_constant_tl(0);
- TCGv t3 = tcg_constant_tl(1);
- tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
+ tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1,
+ tcg_constant_tl(0), tcg_constant_tl(1), t1);
tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
}
@@ -3600,184 +3562,6 @@ static void gen_cl(DisasContext *ctx, uint32_t opc,
}
}
-/* Godson integer instructions */
-static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
- int rd, int rs, int rt)
-{
- TCGv t0, t1;
-
- if (rd == 0) {
- /* Treat as NOP. */
- return;
- }
-
- t0 = tcg_temp_new();
- t1 = tcg_temp_new();
- gen_load_gpr(t0, rs);
- gen_load_gpr(t1, rt);
-
- switch (opc) {
- case OPC_MULT_G_2E:
- case OPC_MULT_G_2F:
- tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
- tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
- break;
- case OPC_MULTU_G_2E:
- case OPC_MULTU_G_2F:
- tcg_gen_ext32u_tl(t0, t0);
- 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]);
- break;
- case OPC_DIV_G_2E:
- case OPC_DIV_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- TCGLabel *l3 = gen_new_label();
- tcg_gen_ext32s_tl(t0, t0);
- tcg_gen_ext32s_tl(t1, t1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l3);
- gen_set_label(l1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
- tcg_gen_mov_tl(cpu_gpr[rd], t0);
- tcg_gen_br(l3);
- gen_set_label(l2);
- tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
- tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
- gen_set_label(l3);
- }
- break;
- case OPC_DIVU_G_2E:
- case OPC_DIVU_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- tcg_gen_ext32u_tl(t0, t0);
- tcg_gen_ext32u_tl(t1, t1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
- tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
- gen_set_label(l2);
- }
- break;
- case OPC_MOD_G_2E:
- case OPC_MOD_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- TCGLabel *l3 = gen_new_label();
- tcg_gen_ext32u_tl(t0, t0);
- tcg_gen_ext32u_tl(t1, t1);
- tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
- gen_set_label(l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l3);
- gen_set_label(l2);
- tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
- tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
- gen_set_label(l3);
- }
- break;
- case OPC_MODU_G_2E:
- case OPC_MODU_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- tcg_gen_ext32u_tl(t0, t0);
- tcg_gen_ext32u_tl(t1, t1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
- tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
- gen_set_label(l2);
- }
- break;
-#if defined(TARGET_MIPS64)
- case OPC_DMULT_G_2E:
- case OPC_DMULT_G_2F:
- tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
- break;
- case OPC_DMULTU_G_2E:
- case OPC_DMULTU_G_2F:
- tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
- break;
- case OPC_DDIV_G_2E:
- case OPC_DDIV_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- TCGLabel *l3 = gen_new_label();
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l3);
- gen_set_label(l1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
- tcg_gen_mov_tl(cpu_gpr[rd], t0);
- tcg_gen_br(l3);
- gen_set_label(l2);
- tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
- gen_set_label(l3);
- }
- break;
- case OPC_DDIVU_G_2E:
- case OPC_DDIVU_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
- gen_set_label(l2);
- }
- break;
- case OPC_DMOD_G_2E:
- case OPC_DMOD_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- TCGLabel *l3 = gen_new_label();
- tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
- gen_set_label(l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l3);
- gen_set_label(l2);
- tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
- gen_set_label(l3);
- }
- break;
- case OPC_DMODU_G_2E:
- case OPC_DMODU_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
- gen_set_label(l2);
- }
- break;
-#endif
- }
-}
-
/* Loongson multimedia instructions */
static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
{
@@ -4160,10 +3944,10 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt,
case OPC_GSLQ:
t1 = tcg_temp_new();
gen_base_offset_addr(ctx, t0, rs, lsq_offset);
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
ctx->default_tcg_memop_mask);
gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ |
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
ctx->default_tcg_memop_mask);
gen_store_gpr(t1, rt);
gen_store_gpr(t0, lsq_rt1);
@@ -4172,10 +3956,10 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt,
check_cp1_enabled(ctx);
t1 = tcg_temp_new();
gen_base_offset_addr(ctx, t0, rs, lsq_offset);
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
ctx->default_tcg_memop_mask);
gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ |
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
ctx->default_tcg_memop_mask);
gen_store_fpr64(ctx, t1, rt);
gen_store_fpr64(ctx, t0, lsq_rt1);
@@ -4184,11 +3968,11 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt,
t1 = tcg_temp_new();
gen_base_offset_addr(ctx, t0, rs, lsq_offset);
gen_load_gpr(t1, rt);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
ctx->default_tcg_memop_mask);
gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
gen_load_gpr(t1, lsq_rt1);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
ctx->default_tcg_memop_mask);
break;
case OPC_GSSQC1:
@@ -4196,11 +3980,11 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt,
t1 = tcg_temp_new();
gen_base_offset_addr(ctx, t0, rs, lsq_offset);
gen_load_fpr64(ctx, t1, rt);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
ctx->default_tcg_memop_mask);
gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
gen_load_fpr64(ctx, t1, lsq_rt1);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
ctx->default_tcg_memop_mask);
break;
#endif
@@ -4213,7 +3997,7 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt,
gen_load_fpr32(ctx, fp0, rt);
t1 = tcg_temp_new();
tcg_gen_ext_i32_tl(t1, fp0);
- gen_lxl(ctx, t1, t0, ctx->mem_idx, MO_TEUL);
+ gen_lxl(ctx, t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL);
tcg_gen_trunc_tl_i32(fp0, t1);
gen_store_fpr32(ctx, fp0, rt);
break;
@@ -4224,7 +4008,7 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt,
gen_load_fpr32(ctx, fp0, rt);
t1 = tcg_temp_new();
tcg_gen_ext_i32_tl(t1, fp0);
- gen_lxr(ctx, t1, t0, ctx->mem_idx, MO_TEUL);
+ gen_lxr(ctx, t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL);
tcg_gen_trunc_tl_i32(fp0, t1);
gen_store_fpr32(ctx, fp0, rt);
break;
@@ -4234,7 +4018,7 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt,
gen_base_offset_addr(ctx, t0, rs, shf_offset);
t1 = tcg_temp_new();
gen_load_fpr64(ctx, t1, rt);
- gen_lxl(ctx, t1, t0, ctx->mem_idx, MO_TEUQ);
+ gen_lxl(ctx, t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
gen_store_fpr64(ctx, t1, rt);
break;
case OPC_GSLDRC1:
@@ -4242,7 +4026,7 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt,
gen_base_offset_addr(ctx, t0, rs, shf_offset);
t1 = tcg_temp_new();
gen_load_fpr64(ctx, t1, rt);
- gen_lxr(ctx, t1, t0, ctx->mem_idx, MO_TEUQ);
+ gen_lxr(ctx, t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
gen_store_fpr64(ctx, t1, rt);
break;
#endif
@@ -4360,7 +4144,7 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
gen_store_gpr(t0, rt);
break;
case OPC_GSLHX:
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SW |
ctx->default_tcg_memop_mask);
gen_store_gpr(t0, rt);
break;
@@ -4369,7 +4153,7 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
if (rd) {
gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
}
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SL |
ctx->default_tcg_memop_mask);
gen_store_gpr(t0, rt);
break;
@@ -4379,7 +4163,7 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
if (rd) {
gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
}
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ |
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
ctx->default_tcg_memop_mask);
gen_store_gpr(t0, rt);
break;
@@ -4390,7 +4174,7 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
}
fp0 = tcg_temp_new_i32();
- tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
+ tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SL |
ctx->default_tcg_memop_mask);
gen_store_fpr32(ctx, fp0, rt);
break;
@@ -4400,7 +4184,7 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
if (rd) {
gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
}
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ |
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
ctx->default_tcg_memop_mask);
gen_store_fpr64(ctx, t0, rt);
break;
@@ -4413,34 +4197,34 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
case OPC_GSSHX:
t1 = tcg_temp_new();
gen_load_gpr(t1, rt);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UW |
ctx->default_tcg_memop_mask);
break;
case OPC_GSSWX:
t1 = tcg_temp_new();
gen_load_gpr(t1, rt);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL |
ctx->default_tcg_memop_mask);
break;
#if defined(TARGET_MIPS64)
case OPC_GSSDX:
t1 = tcg_temp_new();
gen_load_gpr(t1, rt);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
ctx->default_tcg_memop_mask);
break;
#endif
case OPC_GSSWXC1:
fp0 = tcg_temp_new_i32();
gen_load_fpr32(ctx, fp0, rt);
- tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
+ tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL |
ctx->default_tcg_memop_mask);
break;
#if defined(TARGET_MIPS64)
case OPC_GSSDXC1:
t1 = tcg_temp_new();
gen_load_fpr64(ctx, t1, rt);
- tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEUQ |
+ tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
ctx->default_tcg_memop_mask);
break;
#endif
@@ -5329,17 +5113,17 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
register_name = "Index";
break;
case CP0_REG00__MVPCONTROL:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mfc0_mvpcontrol(arg, tcg_env);
register_name = "MVPControl";
break;
case CP0_REG00__MVPCONF0:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mfc0_mvpconf0(arg, tcg_env);
register_name = "MVPConf0";
break;
case CP0_REG00__MVPCONF1:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mfc0_mvpconf1(arg, tcg_env);
register_name = "MVPConf1";
break;
@@ -5360,37 +5144,37 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
register_name = "Random";
break;
case CP0_REG01__VPECONTROL:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
register_name = "VPEControl";
break;
case CP0_REG01__VPECONF0:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
register_name = "VPEConf0";
break;
case CP0_REG01__VPECONF1:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
register_name = "VPEConf1";
break;
case CP0_REG01__YQMASK:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
register_name = "YQMask";
break;
case CP0_REG01__VPESCHEDULE:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
register_name = "VPESchedule";
break;
case CP0_REG01__VPESCHEFBACK:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
register_name = "VPEScheFBack";
break;
case CP0_REG01__VPEOPT:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
register_name = "VPEOpt";
break;
@@ -5417,37 +5201,37 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
register_name = "EntryLo0";
break;
case CP0_REG02__TCSTATUS:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mfc0_tcstatus(arg, tcg_env);
register_name = "TCStatus";
break;
case CP0_REG02__TCBIND:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mfc0_tcbind(arg, tcg_env);
register_name = "TCBind";
break;
case CP0_REG02__TCRESTART:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mfc0_tcrestart(arg, tcg_env);
register_name = "TCRestart";
break;
case CP0_REG02__TCHALT:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mfc0_tchalt(arg, tcg_env);
register_name = "TCHalt";
break;
case CP0_REG02__TCCONTEXT:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mfc0_tccontext(arg, tcg_env);
register_name = "TCContext";
break;
case CP0_REG02__TCSCHEDULE:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mfc0_tcschedule(arg, tcg_env);
register_name = "TCSchedule";
break;
case CP0_REG02__TCSCHEFBACK:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mfc0_tcschefback(arg, tcg_env);
register_name = "TCScheFBack";
break;
@@ -6086,17 +5870,17 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
register_name = "Index";
break;
case CP0_REG00__MVPCONTROL:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_mvpcontrol(tcg_env, arg);
register_name = "MVPControl";
break;
case CP0_REG00__MVPCONF0:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
/* ignored */
register_name = "MVPConf0";
break;
case CP0_REG00__MVPCONF1:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
/* ignored */
register_name = "MVPConf1";
break;
@@ -6116,39 +5900,39 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
register_name = "Random";
break;
case CP0_REG01__VPECONTROL:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_vpecontrol(tcg_env, arg);
register_name = "VPEControl";
break;
case CP0_REG01__VPECONF0:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_vpeconf0(tcg_env, arg);
register_name = "VPEConf0";
break;
case CP0_REG01__VPECONF1:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_vpeconf1(tcg_env, arg);
register_name = "VPEConf1";
break;
case CP0_REG01__YQMASK:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_yqmask(tcg_env, arg);
register_name = "YQMask";
break;
case CP0_REG01__VPESCHEDULE:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
tcg_gen_st_tl(arg, tcg_env,
offsetof(CPUMIPSState, CP0_VPESchedule));
register_name = "VPESchedule";
break;
case CP0_REG01__VPESCHEFBACK:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
tcg_gen_st_tl(arg, tcg_env,
offsetof(CPUMIPSState, CP0_VPEScheFBack));
register_name = "VPEScheFBack";
break;
case CP0_REG01__VPEOPT:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_vpeopt(tcg_env, arg);
register_name = "VPEOpt";
break;
@@ -6163,37 +5947,37 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
register_name = "EntryLo0";
break;
case CP0_REG02__TCSTATUS:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_tcstatus(tcg_env, arg);
register_name = "TCStatus";
break;
case CP0_REG02__TCBIND:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_tcbind(tcg_env, arg);
register_name = "TCBind";
break;
case CP0_REG02__TCRESTART:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_tcrestart(tcg_env, arg);
register_name = "TCRestart";
break;
case CP0_REG02__TCHALT:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_tchalt(tcg_env, arg);
register_name = "TCHalt";
break;
case CP0_REG02__TCCONTEXT:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_tccontext(tcg_env, arg);
register_name = "TCContext";
break;
case CP0_REG02__TCSCHEDULE:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_tcschedule(tcg_env, arg);
register_name = "TCSchedule";
break;
case CP0_REG02__TCSCHEFBACK:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_tcschefback(tcg_env, arg);
register_name = "TCScheFBack";
break;
@@ -6836,17 +6620,17 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
register_name = "Index";
break;
case CP0_REG00__MVPCONTROL:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mfc0_mvpcontrol(arg, tcg_env);
register_name = "MVPControl";
break;
case CP0_REG00__MVPCONF0:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mfc0_mvpconf0(arg, tcg_env);
register_name = "MVPConf0";
break;
case CP0_REG00__MVPCONF1:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mfc0_mvpconf1(arg, tcg_env);
register_name = "MVPConf1";
break;
@@ -6867,40 +6651,40 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
register_name = "Random";
break;
case CP0_REG01__VPECONTROL:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
register_name = "VPEControl";
break;
case CP0_REG01__VPECONF0:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
register_name = "VPEConf0";
break;
case CP0_REG01__VPECONF1:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
register_name = "VPEConf1";
break;
case CP0_REG01__YQMASK:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
tcg_gen_ld_tl(arg, tcg_env,
offsetof(CPUMIPSState, CP0_YQMask));
register_name = "YQMask";
break;
case CP0_REG01__VPESCHEDULE:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
tcg_gen_ld_tl(arg, tcg_env,
offsetof(CPUMIPSState, CP0_VPESchedule));
register_name = "VPESchedule";
break;
case CP0_REG01__VPESCHEFBACK:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
tcg_gen_ld_tl(arg, tcg_env,
offsetof(CPUMIPSState, CP0_VPEScheFBack));
register_name = "VPEScheFBack";
break;
case CP0_REG01__VPEOPT:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
register_name = "VPEOpt";
break;
@@ -6916,37 +6700,37 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
register_name = "EntryLo0";
break;
case CP0_REG02__TCSTATUS:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mfc0_tcstatus(arg, tcg_env);
register_name = "TCStatus";
break;
case CP0_REG02__TCBIND:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mfc0_tcbind(arg, tcg_env);
register_name = "TCBind";
break;
case CP0_REG02__TCRESTART:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_dmfc0_tcrestart(arg, tcg_env);
register_name = "TCRestart";
break;
case CP0_REG02__TCHALT:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_dmfc0_tchalt(arg, tcg_env);
register_name = "TCHalt";
break;
case CP0_REG02__TCCONTEXT:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_dmfc0_tccontext(arg, tcg_env);
register_name = "TCContext";
break;
case CP0_REG02__TCSCHEDULE:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_dmfc0_tcschedule(arg, tcg_env);
register_name = "TCSchedule";
break;
case CP0_REG02__TCSCHEFBACK:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_dmfc0_tcschefback(arg, tcg_env);
register_name = "TCScheFBack";
break;
@@ -7553,17 +7337,17 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
register_name = "Index";
break;
case CP0_REG00__MVPCONTROL:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_mvpcontrol(tcg_env, arg);
register_name = "MVPControl";
break;
case CP0_REG00__MVPCONF0:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
/* ignored */
register_name = "MVPConf0";
break;
case CP0_REG00__MVPCONF1:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
/* ignored */
register_name = "MVPConf1";
break;
@@ -7583,39 +7367,39 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
register_name = "Random";
break;
case CP0_REG01__VPECONTROL:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_vpecontrol(tcg_env, arg);
register_name = "VPEControl";
break;
case CP0_REG01__VPECONF0:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_vpeconf0(tcg_env, arg);
register_name = "VPEConf0";
break;
case CP0_REG01__VPECONF1:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_vpeconf1(tcg_env, arg);
register_name = "VPEConf1";
break;
case CP0_REG01__YQMASK:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_yqmask(tcg_env, arg);
register_name = "YQMask";
break;
case CP0_REG01__VPESCHEDULE:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
tcg_gen_st_tl(arg, tcg_env,
offsetof(CPUMIPSState, CP0_VPESchedule));
register_name = "VPESchedule";
break;
case CP0_REG01__VPESCHEFBACK:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
tcg_gen_st_tl(arg, tcg_env,
offsetof(CPUMIPSState, CP0_VPEScheFBack));
register_name = "VPEScheFBack";
break;
case CP0_REG01__VPEOPT:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_vpeopt(tcg_env, arg);
register_name = "VPEOpt";
break;
@@ -7630,37 +7414,37 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
register_name = "EntryLo0";
break;
case CP0_REG02__TCSTATUS:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_tcstatus(tcg_env, arg);
register_name = "TCStatus";
break;
case CP0_REG02__TCBIND:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_tcbind(tcg_env, arg);
register_name = "TCBind";
break;
case CP0_REG02__TCRESTART:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_tcrestart(tcg_env, arg);
register_name = "TCRestart";
break;
case CP0_REG02__TCHALT:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_tchalt(tcg_env, arg);
register_name = "TCHalt";
break;
case CP0_REG02__TCCONTEXT:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_tccontext(tcg_env, arg);
register_name = "TCContext";
break;
case CP0_REG02__TCSCHEDULE:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_tcschedule(tcg_env, arg);
register_name = "TCSchedule";
break;
case CP0_REG02__TCSCHEFBACK:
- CP0_CHECK(ctx->insn_flags & ASE_MT);
+ CP0_CHECK(disas_mt_available(ctx));
gen_helper_mtc0_tcschefback(tcg_env, arg);
register_name = "TCScheFBack";
break;
@@ -10779,7 +10563,7 @@ static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SL);
tcg_gen_trunc_tl_i32(fp0, t0);
gen_store_fpr32(ctx, fp0, fd);
}
@@ -10789,7 +10573,7 @@ static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
check_cp1_registers(ctx, fd);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
- tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEUQ);
+ tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
gen_store_fpr64(ctx, fp0, fd);
}
break;
@@ -10799,7 +10583,7 @@ static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
{
TCGv_i64 fp0 = tcg_temp_new_i64();
- tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEUQ);
+ tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
gen_store_fpr64(ctx, fp0, fd);
}
break;
@@ -10808,7 +10592,7 @@ static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
{
TCGv_i32 fp0 = tcg_temp_new_i32();
gen_load_fpr32(ctx, fp0, fs);
- tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
+ tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL);
}
break;
case OPC_SDXC1:
@@ -10817,7 +10601,7 @@ static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
{
TCGv_i64 fp0 = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp0, fs);
- tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEUQ);
+ tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
}
break;
case OPC_SUXC1:
@@ -10826,7 +10610,7 @@ static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
{
TCGv_i64 fp0 = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp0, fs);
- tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEUQ);
+ tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
}
break;
}
@@ -10856,7 +10640,7 @@ static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
tcg_gen_br(l2);
gen_set_label(l1);
tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
- if (cpu_is_bigendian(ctx)) {
+ if (disas_is_bigendian(ctx)) {
gen_load_fpr32(ctx, fp, fs);
gen_load_fpr32h(ctx, fph, ft);
gen_store_fpr32h(ctx, fp, fd);
@@ -11265,10 +11049,9 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
} else {
/* OPC_JIC, OPC_JIALC */
TCGv tbase = tcg_temp_new();
- TCGv toffset = tcg_constant_tl(offset);
gen_load_gpr(tbase, rt);
- gen_op_addr_add(ctx, btarget, tbase, toffset);
+ gen_op_addr_addi(ctx, btarget, tbase, offset);
}
break;
default:
@@ -11428,20 +11211,18 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
void gen_addiupc(DisasContext *ctx, int rx, int imm,
int is_64_bit, int extended)
{
- TCGv t0;
+ target_ulong npc;
if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
gen_reserved_instruction(ctx);
return;
}
- t0 = tcg_temp_new();
-
- tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
- tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
+ npc = pc_relative_pc(ctx) + imm;
if (!is_64_bit) {
- tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
+ npc = (int32_t)npc;
}
+ tcg_gen_movi_tl(cpu_gpr[rx], npc);
}
static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
@@ -11476,7 +11257,7 @@ void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
gen_op_addr_add(ctx, t0, t1, t0);
}
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_SL);
gen_store_gpr(t1, rd);
}
@@ -11567,16 +11348,16 @@ static void gen_mips_lx(DisasContext *ctx, uint32_t opc,
gen_store_gpr(t0, rd);
break;
case OPC_LHX:
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SW);
gen_store_gpr(t0, rd);
break;
case OPC_LWX:
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SL);
gen_store_gpr(t0, rd);
break;
#if defined(TARGET_MIPS64)
case OPC_LDX:
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ);
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
gen_store_gpr(t0, rd);
break;
#endif
@@ -11601,8 +11382,7 @@ static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
gen_load_gpr(v2_t, v2);
switch (op1) {
- /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
- case OPC_MULT_G_2E:
+ case OPC_ADDUH_QB_DSP:
check_dsp_r2(ctx);
switch (op2) {
case OPC_ADDUH_QB:
@@ -12285,11 +12065,7 @@ static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
gen_load_gpr(v2_t, v2);
switch (op1) {
- /*
- * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
- * the same mask and op1.
- */
- case OPC_MULT_G_2E:
+ case OPC_MUL_PH_DSP:
check_dsp_r2(ctx);
switch (op2) {
case OPC_MUL_PH:
@@ -13641,15 +13417,6 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
case OPC_MUL:
gen_arith(ctx, op1, rd, rs, rt);
break;
- case OPC_DIV_G_2F:
- case OPC_DIVU_G_2F:
- case OPC_MULT_G_2F:
- case OPC_MULTU_G_2F:
- case OPC_MOD_G_2F:
- case OPC_MODU_G_2F:
- check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
- gen_loongson_integer(ctx, op1, rd, rs, rt);
- break;
case OPC_CLO:
case OPC_CLZ:
check_insn(ctx, ISA_MIPS_R1);
@@ -13674,15 +13441,6 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
check_mips_64(ctx);
gen_cl(ctx, op1, rd, rs);
break;
- case OPC_DMULT_G_2F:
- case OPC_DMULTU_G_2F:
- case OPC_DDIV_G_2F:
- case OPC_DDIVU_G_2F:
- case OPC_DMOD_G_2F:
- case OPC_DMODU_G_2F:
- check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
- gen_loongson_integer(ctx, op1, rd, rs, rt);
- break;
#endif
default: /* Invalid */
MIPS_INVAL("special2_legacy");
@@ -13719,7 +13477,7 @@ static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
}
break;
case R6_OPC_SC:
- gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
+ gen_st_cond(ctx, rt, rs, imm, mo_endian(ctx) | MO_SL, false);
break;
case R6_OPC_LL:
gen_ld(ctx, op1, rt, rs, imm);
@@ -13765,7 +13523,7 @@ static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
#endif
#if defined(TARGET_MIPS64)
case R6_OPC_SCD:
- gen_st_cond(ctx, rt, rs, imm, MO_TEUQ, false);
+ gen_st_cond(ctx, rt, rs, imm, mo_endian(ctx) | MO_UQ, false);
break;
case R6_OPC_LLD:
gen_ld(ctx, op1, rt, rs, imm);
@@ -13815,17 +13573,12 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
op1 = MASK_SPECIAL3(ctx->opcode);
switch (op1) {
- case OPC_DIV_G_2E:
- case OPC_DIVU_G_2E:
- case OPC_MOD_G_2E:
- case OPC_MODU_G_2E:
- case OPC_MULT_G_2E:
- case OPC_MULTU_G_2E:
+ case OPC_MUL_PH_DSP:
/*
- * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
+ * OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
* the same mask and op1.
*/
- if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
+ if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MUL_PH_DSP)) {
op2 = MASK_ADDUH_QB(ctx->opcode);
switch (op2) {
case OPC_ADDUH_QB:
@@ -13853,8 +13606,6 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
gen_reserved_instruction(ctx);
break;
}
- } else if (ctx->insn_flags & INSN_LOONGSON2E) {
- gen_loongson_integer(ctx, op1, rd, rs, rt);
} else {
gen_reserved_instruction(ctx);
}
@@ -14083,15 +13834,6 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
}
break;
#if defined(TARGET_MIPS64)
- case OPC_DDIV_G_2E:
- case OPC_DDIVU_G_2E:
- case OPC_DMULT_G_2E:
- case OPC_DMULTU_G_2E:
- case OPC_DMOD_G_2E:
- case OPC_DMODU_G_2E:
- check_insn(ctx, INSN_LOONGSON2E);
- gen_loongson_integer(ctx, op1, rd, rs, rt);
- break;
case OPC_ABSQ_S_QH_DSP:
op2 = MASK_ABSQ_S_QH(ctx->opcode);
switch (op2) {
@@ -14448,7 +14190,7 @@ static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
return;
case OPC_SCE:
check_cp0_enabled(ctx);
- gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
+ gen_st_cond(ctx, rt, rs, imm, mo_endian(ctx) | MO_SL, true);
return;
case OPC_CACHEE:
check_eva(ctx);
@@ -14912,7 +14654,7 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
if (ctx->insn_flags & INSN_R5900) {
check_insn_opc_user_only(ctx, INSN_R5900);
}
- gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
+ gen_st_cond(ctx, rt, rs, imm, mo_endian(ctx) | MO_SL, false);
break;
case OPC_CACHE:
check_cp0_enabled(ctx);
@@ -14969,7 +14711,9 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
} else {
/* OPC_BC1ANY2 */
check_cop1x(ctx);
- check_insn(ctx, ASE_MIPS3D);
+ if (!ase_3d_available(env)) {
+ return false;
+ }
gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
(rt >> 2) & 0x7, imm << 2);
}
@@ -14984,7 +14728,9 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
check_cp1_enabled(ctx);
check_insn_opc_removed(ctx, ISA_MIPS_R6);
check_cop1x(ctx);
- check_insn(ctx, ASE_MIPS3D);
+ if (!ase_3d_available(env)) {
+ return false;
+ }
/* fall through */
case OPC_BC1:
check_cp1_enabled(ctx);
@@ -15191,7 +14937,7 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
check_insn_opc_user_only(ctx, INSN_R5900);
}
check_mips_64(ctx);
- gen_st_cond(ctx, rt, rs, imm, MO_TEUQ, false);
+ gen_st_cond(ctx, rt, rs, imm, mo_endian(ctx) | MO_UQ, false);
break;
case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
if (ctx->insn_flags & ISA_MIPS_R6) {
@@ -15284,6 +15030,9 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
if (cpu_supports_isa(env, INSN_VR54XX) && decode_ext_vr54xx(ctx, ctx->opcode)) {
return;
}
+ if (TARGET_LONG_BITS == 64 && decode_ext_loongson(ctx, ctx->opcode)) {
+ return;
+ }
#if defined(TARGET_MIPS64)
if (ase_lcsr_available(env) && decode_ase_lcsr(ctx, ctx->opcode)) {
return;
@@ -15362,7 +15111,8 @@ static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
* hardware does (e.g. if a delay slot instruction faults, the
* reported PC is the PC of the branch).
*/
- if (ctx->base.singlestep_enabled && (ctx->hflags & MIPS_HFLAG_BMASK)) {
+ if ((tb_cflags(ctx->base.tb) & CF_SINGLE_STEP) &&
+ (ctx->hflags & MIPS_HFLAG_BMASK)) {
ctx->base.max_insns = 2;
}
@@ -15445,7 +15195,7 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
* together with its delay slot.
*/
if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE
- && !ctx->base.singlestep_enabled) {
+ && !(tb_cflags(ctx->base.tb) & CF_SINGLE_STEP)) {
ctx->base.is_jmp = DISAS_TOO_MANY;
}
}
@@ -15482,8 +15232,8 @@ static const TranslatorOps mips_tr_ops = {
.tb_stop = mips_tr_tb_stop,
};
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
- vaddr pc, void *host_pc)
+void mips_translate_code(CPUState *cs, TranslationBlock *tb,
+ int *max_insns, vaddr pc, void *host_pc)
{
DisasContext ctx;
diff --git a/target/mips/tcg/translate.h b/target/mips/tcg/translate.h
index 2b6646b..1bf153d 100644
--- a/target/mips/tcg/translate.h
+++ b/target/mips/tcg/translate.h
@@ -176,6 +176,7 @@ void gen_addiupc(DisasContext *ctx, int rx, int imm,
* Address Computation and Large Constant Instructions
*/
void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1);
+void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base, target_long ofs);
bool gen_lsa(DisasContext *ctx, int rd, int rt, int rs, int sa);
bool gen_dlsa(DisasContext *ctx, int rd, int rt, int rs, int sa);
@@ -216,10 +217,13 @@ void msa_translate_init(void);
void mxu_translate_init(void);
bool decode_ase_mxu(DisasContext *ctx, uint32_t insn);
+bool decode_64bit_enabled(DisasContext *ctx);
+
/* decodetree generated */
bool decode_isa_rel6(DisasContext *ctx, uint32_t insn);
bool decode_ase_msa(DisasContext *ctx, uint32_t insn);
bool decode_ext_txx9(DisasContext *ctx, uint32_t insn);
+bool decode_ext_loongson(DisasContext *ctx, uint32_t insn);
#if defined(TARGET_MIPS64)
bool decode_ase_lcsr(DisasContext *ctx, uint32_t insn);
bool decode_ext_tx79(DisasContext *ctx, uint32_t insn);
@@ -227,6 +231,11 @@ bool decode_ext_octeon(DisasContext *ctx, uint32_t insn);
#endif
bool decode_ext_vr54xx(DisasContext *ctx, uint32_t insn);
+static inline bool disas_mt_available(DisasContext *ctx)
+{
+ return ctx->CP0_Config3 & (1 << CP0C3_MT);
+}
+
/*
* Helpers for implementing sets of trans_* functions.
* Defer the implementation of NAME to FUNC, with optional extra arguments.
@@ -235,9 +244,19 @@ bool decode_ext_vr54xx(DisasContext *ctx, uint32_t insn);
static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
{ return FUNC(ctx, a, __VA_ARGS__); }
-static inline bool cpu_is_bigendian(DisasContext *ctx)
+static inline bool disas_is_bigendian(DisasContext *ctx)
{
return extract32(ctx->CP0_Config0, CP0C0_BE, 1);
}
+static inline MemOp mo_endian(DisasContext *dc)
+{
+ return disas_is_bigendian(dc) ? MO_BE : MO_LE;
+}
+
+static inline MemOp mo_endian_rev(DisasContext *dc, bool reversed)
+{
+ return disas_is_bigendian(dc) ^ reversed ? MO_BE : MO_LE;
+}
+
#endif
diff --git a/target/mips/tcg/tx79_translate.c b/target/mips/tcg/tx79_translate.c
index dd6fb8a..ae3f5e1 100644
--- a/target/mips/tcg/tx79_translate.c
+++ b/target/mips/tcg/tx79_translate.c
@@ -340,12 +340,12 @@ static bool trans_LQ(DisasContext *ctx, arg_i *a)
tcg_gen_andi_tl(addr, addr, ~0xf);
/* Lower half */
- tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
+ tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
gen_store_gpr(t0, a->rt);
/* Upper half */
tcg_gen_addi_i64(addr, addr, 8);
- tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
+ tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
gen_store_gpr_hi(t0, a->rt);
return true;
}
@@ -364,12 +364,12 @@ static bool trans_SQ(DisasContext *ctx, arg_i *a)
/* Lower half */
gen_load_gpr(t0, a->rt);
- tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
+ tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
/* Upper half */
tcg_gen_addi_i64(addr, addr, 8);
gen_load_gpr_hi(t0, a->rt);
- tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
+ tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
return true;
}