MIPS patches queue

- Simplify CPU/ISA definitions
 - Various maintenance code movements in translate.c
 - Convert part of the MSA ASE instructions to decodetree
 - Convert some instructions removed from Release 6 to decodetree
 - Remove deprecated 'fulong2e' machine alias
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmAAbl0ACgkQ4+MsLN6t
 wN7dng//V7XlbAwjRjuDXpQ22bZgMI6ZGGSVr9mp2JXvCABQnE0Mrc0Td6MtyixB
 IWfdds+1TwgD3IWQzceWFod7m9YZFicF3c/yfgTpdrm9KTHR16WM/sykkc1mdiBO
 coxgy1i8JhICNk684M6+o3zRVbC/xpBWAr8zewy2CGFT5xnPsv56sft47RTrw9Tr
 syg8sD38gkUdrj+qbRTfdABw44R/zYb8UcJ67Xx4HKYS8Yri/NmgetHz9I23l5bL
 meAQ2L7oJl+YSBPSoxzzuHi6gKnsbxTKko3/nlz3Obpv0rbtMAIB9yNOYykr6pet
 o4pwwY6wlQKAJeZ19w3cpom7ihUbhNcGeGfqgI32dJevhamO/fJAwDidF2VAIbIu
 76AWRDyfKp+k2D8/Wi/uCB0hzw0DJlbYMC1VtlkQzkRyl8bAdnm+ZhPl2vfx286R
 X3xULVg9HNcvX+fiF/vgWlMJl7e8r35ZABMf+H+zzsQGUHG7hNOKRUuFQtakJrws
 53jck243BTHqYyr5L4UvyWRMyWSTVllVcAP6/WqF6Sz/8mhzSAvGPwrj1QPOstef
 xGfR2B8KSJ7/Yi3S7CpYuHxyv/uZpro5A/lT4xpcun3QuPArjxUk9OYra5PomCqb
 h1vBd4yWdIaQOL+LIU0H+FxJ8AYM0aP1nmbc2YnDZvpexzjHYes=
 =lS4p
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/philmd-gitlab/tags/mips-20210114' into staging

MIPS patches queue

- Simplify CPU/ISA definitions
- Various maintenance code movements in translate.c
- Convert part of the MSA ASE instructions to decodetree
- Convert some instructions removed from Release 6 to decodetree
- Remove deprecated 'fulong2e' machine alias

# gpg: Signature made Thu 14 Jan 2021 16:16:29 GMT
# gpg:                using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE
# gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full]
# Primary key fingerprint: FAAB E75E 1291 7221 DCFD  6BB2 E3E3 2C2C DEAD C0DE

* remotes/philmd-gitlab/tags/mips-20210114: (69 commits)
  docs/system: Remove deprecated 'fulong2e' machine alias
  target/mips: Remove vendor specific CPU definitions
  target/mips: Remove CPU_NANOMIPS32 definition
  target/mips: Remove CPU_R5900 definition
  target/mips: Convert Rel6 LL/SC opcodes to decodetree
  target/mips: Convert Rel6 LLD/SCD opcodes to decodetree
  target/mips: Convert Rel6 LDL/LDR/SDL/SDR opcodes to decodetree
  target/mips: Convert Rel6 LWLE/LWRE/SWLE/SWRE opcodes to decodetree
  target/mips: Convert Rel6 LWL/LWR/SWL/SWR opcodes to decodetree
  target/mips: Convert Rel6 CACHE/PREF opcodes to decodetree
  target/mips: Convert Rel6 COP1X opcode to decodetree
  target/mips: Convert Rel6 Special2 opcode to decodetree
  target/mips: Remove now unreachable LSA/DLSA opcodes code
  target/mips: Introduce decodetree helpers for Release6 LSA/DLSA opcodes
  target/mips: Introduce decodetree helpers for MSA LSA/DLSA opcodes
  target/mips: Extract LSA/DLSA translation generators
  target/mips: Use decode_ase_msa() generated from decodetree
  target/mips: Introduce decode tree bindings for MSA ASE
  target/mips: Pass TCGCond argument to MSA gen_check_zero_element()
  target/mips: Extract MSA translation routines
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2021-01-15 13:22:54 +00:00
commit 256af05f52
33 changed files with 4757 additions and 4433 deletions

View File

@ -309,11 +309,6 @@ The 'scsi-disk' device is deprecated. Users should use 'scsi-hd' or
System emulator machines
------------------------
mips ``fulong2e`` machine (since 5.1)
'''''''''''''''''''''''''''''''''''''
This machine has been renamed ``fuloong2e``.
``pc-1.0``, ``pc-1.1``, ``pc-1.2`` and ``pc-1.3`` (since 5.0)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

View File

@ -120,6 +120,11 @@ mips ``r4k`` platform (removed in 5.2)
This machine type was very old and unmaintained. Users should use the ``malta``
machine type instead.
mips ``fulong2e`` machine alias (removed in 6.0)
''''''''''''''''''''''''''''''''''''''''''''''''
This machine has been renamed ``fuloong2e``.
Related binaries
----------------

View File

@ -444,7 +444,6 @@ static void boston_mach_init(MachineState *machine)
DriveInfo *hd[6];
Chardev *chr;
int fw_size, fit_err;
bool is_64b;
if ((machine->ram_size % GiB) ||
(machine->ram_size > (2 * GiB))) {
@ -463,8 +462,6 @@ static void boston_mach_init(MachineState *machine)
exit(1);
}
is_64b = cpu_type_supports_isa(machine->cpu_type, ISA_MIPS64);
object_initialize_child(OBJECT(machine), "cps", &s->cps, TYPE_MIPS_CPS);
object_property_set_str(OBJECT(&s->cps), "cpu-type", machine->cpu_type,
&error_fatal);
@ -545,7 +542,8 @@ static void boston_mach_init(MachineState *machine)
}
gen_firmware(memory_region_get_ram_ptr(flash) + 0x7c00000,
s->kernel_entry, s->fdt_base, is_64b);
s->kernel_entry, s->fdt_base,
cpu_type_is_64bit(machine->cpu_type));
} else if (!qtest_enabled()) {
error_report("Please provide either a -kernel or -bios argument");
exit(1);

View File

@ -383,7 +383,6 @@ static void mips_fuloong2e_init(MachineState *machine)
static void mips_fuloong2e_machine_init(MachineClass *mc)
{
mc->desc = "Fuloong 2e mini pc";
mc->alias = "fulong2e"; /* Incorrect name used up to QEMU 4.2 */
mc->init = mips_fuloong2e_init;
mc->block_default_type = IF_IDE;
mc->default_cpu_type = MIPS_CPU_TYPE_NAME("Loongson-2E");

View File

@ -23,6 +23,7 @@
#include "cpu_loop-common.h"
#include "elf.h"
#include "internal.h"
#include "fpu_helper.h"
# ifdef TARGET_ABI_MIPSO32
# define MIPS_SYSCALL_NUMBER_UNUSED -1
@ -384,10 +385,8 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
prog_req.frdefault &= interp_req.frdefault;
prog_req.fre &= interp_req.fre;
bool cpu_has_mips_r2_r6 = env->insn_flags & ISA_MIPS32R2 ||
env->insn_flags & ISA_MIPS64R2 ||
env->insn_flags & ISA_MIPS32R6 ||
env->insn_flags & ISA_MIPS64R6;
bool cpu_has_mips_r2_r6 = env->insn_flags & ISA_MIPS_R2 ||
env->insn_flags & ISA_MIPS_R6;
if (prog_req.fre && !prog_req.frdefault && !prog_req.fr1) {
env->CP0_Config5 |= (1 << CP0C5_FRE);

View File

@ -40,6 +40,16 @@ uint64_t cpu_mips_kvm_um_phys_to_kseg0(void *opaque, uint64_t addr)
return addr | 0x40000000ll;
}
uint64_t cpu_mips_kseg1_to_phys(void *opaque, uint64_t addr)
{
return addr & 0x1fffffffll;
}
uint64_t cpu_mips_phys_to_kseg1(void *opaque, uint64_t addr)
{
return (addr & 0x1fffffffll) | 0xffffffffa0000000ll;
}
bool mips_um_ksegs_enabled(void)
{
return mips_um_ksegs;

View File

@ -527,7 +527,7 @@ void helper_mtc0_index(CPUMIPSState *env, target_ulong arg1)
uint32_t index_p = env->CP0_Index & 0x80000000;
uint32_t tlb_index = arg1 & 0x7fffffff;
if (tlb_index < env->tlb->nb_tlb) {
if (env->insn_flags & ISA_MIPS32R6) {
if (env->insn_flags & ISA_MIPS_R6) {
index_p |= arg1 & 0x80000000;
}
env->CP0_Index = index_p | tlb_index;
@ -960,7 +960,7 @@ void helper_mtc0_pwfield(CPUMIPSState *env, target_ulong arg1)
uint32_t old_ptei = (env->CP0_PWField >> CP0PF_PTEI) & 0x3FULL;
uint32_t new_ptei = (arg1 >> CP0PF_PTEI) & 0x3FULL;
if ((env->insn_flags & ISA_MIPS32R6)) {
if ((env->insn_flags & ISA_MIPS_R6)) {
if (((arg1 >> CP0PF_BDI) & 0x3FULL) < 12) {
mask &= ~(0x3FULL << CP0PF_BDI);
}
@ -980,7 +980,7 @@ void helper_mtc0_pwfield(CPUMIPSState *env, target_ulong arg1)
env->CP0_PWField = arg1 & mask;
if ((new_ptei >= 32) ||
((env->insn_flags & ISA_MIPS32R6) &&
((env->insn_flags & ISA_MIPS_R6) &&
(new_ptei == 0 || new_ptei == 1))) {
env->CP0_PWField = (env->CP0_PWField & ~0x3FULL) |
(old_ptei << CP0PF_PTEI);
@ -990,7 +990,7 @@ void helper_mtc0_pwfield(CPUMIPSState *env, target_ulong arg1)
uint32_t old_ptew = (env->CP0_PWField >> CP0PF_PTEW) & 0x3F;
uint32_t new_ptew = (arg1 >> CP0PF_PTEW) & 0x3F;
if ((env->insn_flags & ISA_MIPS32R6)) {
if ((env->insn_flags & ISA_MIPS_R6)) {
if (((arg1 >> CP0PF_GDW) & 0x3F) < 12) {
mask &= ~(0x3F << CP0PF_GDW);
}
@ -1007,7 +1007,7 @@ void helper_mtc0_pwfield(CPUMIPSState *env, target_ulong arg1)
env->CP0_PWField = arg1 & mask;
if ((new_ptew >= 32) ||
((env->insn_flags & ISA_MIPS32R6) &&
((env->insn_flags & ISA_MIPS_R6) &&
(new_ptew == 0 || new_ptew == 1))) {
env->CP0_PWField = (env->CP0_PWField & ~0x3F) |
(old_ptew << CP0PF_PTEW);
@ -1026,7 +1026,7 @@ void helper_mtc0_pwsize(CPUMIPSState *env, target_ulong arg1)
void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
{
if (env->insn_flags & ISA_MIPS32R6) {
if (env->insn_flags & ISA_MIPS_R6) {
if (arg1 < env->tlb->nb_tlb) {
env->CP0_Wired = arg1;
}
@ -1075,10 +1075,10 @@ void helper_mtc0_hwrena(CPUMIPSState *env, target_ulong arg1)
uint32_t mask = 0x0000000F;
if ((env->CP0_Config1 & (1 << CP0C1_PC)) &&
(env->insn_flags & ISA_MIPS32R6)) {
(env->insn_flags & ISA_MIPS_R6)) {
mask |= (1 << 4);
}
if (env->insn_flags & ISA_MIPS32R6) {
if (env->insn_flags & ISA_MIPS_R6) {
mask |= (1 << 5);
}
if (env->CP0_Config3 & (1 << CP0C3_ULRI)) {
@ -1149,7 +1149,7 @@ void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1)
/* 1k pages not implemented */
#if defined(TARGET_MIPS64)
if (env->insn_flags & ISA_MIPS32R6) {
if (env->insn_flags & ISA_MIPS_R6) {
int entryhi_r = extract64(arg1, 62, 2);
int config0_at = extract32(env->CP0_Config0, 13, 2);
bool no_supervisor = (env->CP0_Status_rw_bitmask & 0x8) == 0;

View File

@ -44,7 +44,7 @@ static void cpu_mips_timer_update(CPUMIPSState *env)
static void cpu_mips_timer_expire(CPUMIPSState *env)
{
cpu_mips_timer_update(env);
if (env->insn_flags & ISA_MIPS32R2) {
if (env->insn_flags & ISA_MIPS_R2) {
env->CP0_Cause |= 1 << CP0Ca_TI;
}
qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
@ -93,7 +93,7 @@ void cpu_mips_store_compare(CPUMIPSState *env, uint32_t value)
if (!(env->CP0_Cause & (1 << CP0Ca_DC))) {
cpu_mips_timer_update(env);
}
if (env->insn_flags & ISA_MIPS32R2) {
if (env->insn_flags & ISA_MIPS_R2) {
env->CP0_Cause &= ~(1 << CP0Ca_TI);
}
qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);

View File

@ -72,7 +72,7 @@ const mips_def_t mips_defs[] =
.CP0_Status_rw_bitmask = 0x1278FF17,
.SEGBITS = 32,
.PABITS = 32,
.insn_flags = CPU_MIPS32,
.insn_flags = CPU_MIPS32R1,
.mmu_type = MMU_TYPE_R4000,
},
{
@ -94,7 +94,7 @@ const mips_def_t mips_defs[] =
.CP0_Status_rw_bitmask = 0x1258FF17,
.SEGBITS = 32,
.PABITS = 32,
.insn_flags = CPU_MIPS32 | ASE_MIPS16,
.insn_flags = CPU_MIPS32R1 | ASE_MIPS16,
.mmu_type = MMU_TYPE_FMT,
},
{
@ -114,7 +114,7 @@ const mips_def_t mips_defs[] =
.CP0_Status_rw_bitmask = 0x1278FF17,
.SEGBITS = 32,
.PABITS = 32,
.insn_flags = CPU_MIPS32,
.insn_flags = CPU_MIPS32R1,
.mmu_type = MMU_TYPE_R4000,
},
{
@ -134,7 +134,7 @@ const mips_def_t mips_defs[] =
.CP0_Status_rw_bitmask = 0x1258FF17,
.SEGBITS = 32,
.PABITS = 32,
.insn_flags = CPU_MIPS32 | ASE_MIPS16,
.insn_flags = CPU_MIPS32R1 | ASE_MIPS16,
.mmu_type = MMU_TYPE_FMT,
},
{
@ -408,7 +408,7 @@ const mips_def_t mips_defs[] =
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 32,
.PABITS = 40,
.insn_flags = CPU_MIPS32R5 | ASE_MSA,
.insn_flags = CPU_MIPS32R5,
.mmu_type = MMU_TYPE_R4000,
},
{
@ -486,8 +486,8 @@ const mips_def_t mips_defs[] =
.CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008),
.SEGBITS = 32,
.PABITS = 32,
.insn_flags = CPU_NANOMIPS32 | ASE_DSP | ASE_DSP_R2 | ASE_DSP_R3 |
ASE_MT,
.insn_flags = CPU_MIPS32R6 | ISA_NANOMIPS32 |
ASE_DSP | ASE_DSP_R2 | ASE_DSP_R3 | ASE_MT,
.mmu_type = MMU_TYPE_R4000,
},
#if defined(TARGET_MIPS64)
@ -495,7 +495,8 @@ const mips_def_t mips_defs[] =
.name = "R4000",
.CP0_PRid = 0x00000400,
/* No L2 cache, icache size 8k, dcache size 8k, uncached coherency. */
.CP0_Config0 = (1 << 17) | (0x1 << 9) | (0x1 << 6) | (0x2 << CP0C0_K0),
.CP0_Config0 = (2 << CP0C0_Impl) | (1 << CP0C0_IC) | (1 << CP0C0_DC) |
(2 << CP0C0_K0),
/* Note: Config1 is only used internally, the R4000 has only Config0. */
.CP0_Config1 = (1 << CP0C1_FP) | (47 << CP0C1_MMU),
.CP0_LLAddr_rw_bitmask = 0xFFFFFFFF,
@ -516,7 +517,8 @@ const mips_def_t mips_defs[] =
.name = "VR5432",
.CP0_PRid = 0x00005400,
/* No L2 cache, icache size 8k, dcache size 8k, uncached coherency. */
.CP0_Config0 = (1 << 17) | (0x1 << 9) | (0x1 << 6) | (0x2 << CP0C0_K0),
.CP0_Config0 = (2 << CP0C0_Impl) | (1 << CP0C0_IC) | (1 << CP0C0_DC) |
(2 << CP0C0_K0),
.CP0_Config1 = (1 << CP0C1_FP) | (47 << CP0C1_MMU),
.CP0_LLAddr_rw_bitmask = 0xFFFFFFFFL,
.CP0_LLAddr_shift = 4,
@ -529,7 +531,7 @@ const mips_def_t mips_defs[] =
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 40,
.PABITS = 32,
.insn_flags = CPU_VR54XX,
.insn_flags = CPU_MIPS4 | INSN_VR54XX,
.mmu_type = MMU_TYPE_R4000,
},
{
@ -550,7 +552,7 @@ const mips_def_t mips_defs[] =
.CP0_Status_rw_bitmask = 0x12F8FFFF,
.SEGBITS = 42,
.PABITS = 36,
.insn_flags = CPU_MIPS64,
.insn_flags = CPU_MIPS64R1,
.mmu_type = MMU_TYPE_R4000,
},
{
@ -576,7 +578,7 @@ const mips_def_t mips_defs[] =
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 42,
.PABITS = 36,
.insn_flags = CPU_MIPS64,
.insn_flags = CPU_MIPS64R1,
.mmu_type = MMU_TYPE_R4000,
},
{
@ -605,7 +607,7 @@ const mips_def_t mips_defs[] =
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 40,
.PABITS = 36,
.insn_flags = CPU_MIPS64 | ASE_MIPS3D,
.insn_flags = CPU_MIPS64R1 | ASE_MIPS3D,
.mmu_type = MMU_TYPE_R4000,
},
{
@ -719,7 +721,7 @@ const mips_def_t mips_defs[] =
.MSAIR = 0x03 << MSAIR_ProcID,
.SEGBITS = 48,
.PABITS = 48,
.insn_flags = CPU_MIPS64R6 | ASE_MSA,
.insn_flags = CPU_MIPS64R6,
.mmu_type = MMU_TYPE_R4000,
},
{
@ -759,15 +761,15 @@ const mips_def_t mips_defs[] =
.MSAIR = 0x03 << MSAIR_ProcID,
.SEGBITS = 48,
.PABITS = 48,
.insn_flags = CPU_MIPS64R6 | ASE_MSA,
.insn_flags = CPU_MIPS64R6,
.mmu_type = MMU_TYPE_R4000,
},
{
.name = "Loongson-2E",
.CP0_PRid = 0x6302,
/* 64KB I-cache and d-cache. 4 way with 32 bit cache line size. */
.CP0_Config0 = (0x1<<17) | (0x1<<16) | (0x1<<11) | (0x1<<8) |
(0x1<<5) | (0x1<<4) | (0x1<<1),
.CP0_Config0 = (3 << CP0C0_Impl) | (4 << CP0C0_IC) | (4 << CP0C0_DC) |
(1 << CP0C0_IB) | (1 << CP0C0_DB) | (0x2 << CP0C0_K0),
/* Note: Config1 is only used internally,
Loongson-2E has only Config0. */
.CP0_Config1 = (1 << CP0C1_FP) | (47 << CP0C1_MMU),
@ -779,15 +781,15 @@ const mips_def_t mips_defs[] =
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 40,
.PABITS = 40,
.insn_flags = CPU_LOONGSON2E,
.insn_flags = CPU_MIPS3 | INSN_LOONGSON2E,
.mmu_type = MMU_TYPE_R4000,
},
{
.name = "Loongson-2F",
.CP0_PRid = 0x6303,
/* 64KB I-cache and d-cache. 4 way with 32 bit cache line size. */
.CP0_Config0 = (0x1<<17) | (0x1<<16) | (0x1<<11) | (0x1<<8) |
(0x1<<5) | (0x1<<4) | (0x1<<1),
.CP0_Config0 = (3 << CP0C0_Impl) | (4 << CP0C0_IC) | (4 << CP0C0_DC) |
(1 << CP0C0_IB) | (1 << CP0C0_DB) | (0x2 << CP0C0_K0),
/* Note: Config1 is only used internally,
Loongson-2F has only Config0. */
.CP0_Config1 = (1 << CP0C1_FP) | (47 << CP0C1_MMU),
@ -799,7 +801,7 @@ const mips_def_t mips_defs[] =
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 40,
.PABITS = 40,
.insn_flags = CPU_LOONGSON2F,
.insn_flags = CPU_MIPS3 | INSN_LOONGSON2F | ASE_LMMI,
.mmu_type = MMU_TYPE_R4000,
},
{
@ -828,7 +830,8 @@ const mips_def_t mips_defs[] =
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 42,
.PABITS = 48,
.insn_flags = CPU_LOONGSON3A,
.insn_flags = CPU_MIPS64R2 | INSN_LOONGSON3A |
ASE_LMMI | ASE_LEXT,
.mmu_type = MMU_TYPE_R4000,
},
{
@ -885,7 +888,8 @@ const mips_def_t mips_defs[] =
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 48,
.PABITS = 48,
.insn_flags = CPU_LOONGSON3A | ASE_MSA,
.insn_flags = CPU_MIPS64R2 | INSN_LOONGSON3A |
ASE_LMMI | ASE_LEXT,
.mmu_type = MMU_TYPE_R4000,
},
{
@ -931,54 +935,6 @@ void mips_cpu_list(void)
}
}
#ifndef CONFIG_USER_ONLY
static void no_mmu_init (CPUMIPSState *env, const mips_def_t *def)
{
env->tlb->nb_tlb = 1;
env->tlb->map_address = &no_mmu_map_address;
}
static void fixed_mmu_init (CPUMIPSState *env, const mips_def_t *def)
{
env->tlb->nb_tlb = 1;
env->tlb->map_address = &fixed_mmu_map_address;
}
static void r4k_mmu_init (CPUMIPSState *env, const mips_def_t *def)
{
env->tlb->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63);
env->tlb->map_address = &r4k_map_address;
env->tlb->helper_tlbwi = r4k_helper_tlbwi;
env->tlb->helper_tlbwr = r4k_helper_tlbwr;
env->tlb->helper_tlbp = r4k_helper_tlbp;
env->tlb->helper_tlbr = r4k_helper_tlbr;
env->tlb->helper_tlbinv = r4k_helper_tlbinv;
env->tlb->helper_tlbinvf = r4k_helper_tlbinvf;
}
static void mmu_init (CPUMIPSState *env, const mips_def_t *def)
{
env->tlb = g_malloc0(sizeof(CPUMIPSTLBContext));
switch (def->mmu_type) {
case MMU_TYPE_NONE:
no_mmu_init(env, def);
break;
case MMU_TYPE_R4000:
r4k_mmu_init(env, def);
break;
case MMU_TYPE_FMT:
fixed_mmu_init(env, def);
break;
case MMU_TYPE_R3000:
case MMU_TYPE_R6000:
case MMU_TYPE_R8000:
default:
cpu_abort(env_cpu(env), "MMU type not supported\n");
}
}
#endif /* CONFIG_USER_ONLY */
static void fpu_init (CPUMIPSState *env, const mips_def_t *def)
{
int i;
@ -1019,33 +975,3 @@ static void mvp_init(CPUMIPSState *env)
(0x0 << CP0MVPC1_PCX) | (0x0 << CP0MVPC1_PCP2) |
(0x1 << CP0MVPC1_PCP1);
}
static void msa_reset(CPUMIPSState *env)
{
#ifdef CONFIG_USER_ONLY
/* MSA access enabled */
env->CP0_Config5 |= 1 << CP0C5_MSAEn;
env->CP0_Status |= (1 << CP0St_CU1) | (1 << CP0St_FR);
#endif
/* MSA CSR:
- non-signaling floating point exception mode off (NX bit is 0)
- Cause, Enables, and Flags are all 0
- round to nearest / ties to even (RM bits are 0) */
env->active_tc.msacsr = 0;
restore_msa_fp_status(env);
/* tininess detected after rounding.*/
set_float_detect_tininess(float_tininess_after_rounding,
&env->active_tc.msa_fp_status);
/* clear float_status exception flags */
set_float_exception_flags(0, &env->active_tc.msa_fp_status);
/* clear float_status nan mode */
set_default_nan_mode(0, &env->active_tc.msa_fp_status);
/* set proper signanling bit meaning ("1" means "quiet") */
set_snan_bit_is_one(0, &env->active_tc.msa_fp_status);
}

View File

@ -33,6 +33,216 @@
#include "hw/qdev-clock.h"
#include "hw/semihosting/semihost.h"
#include "qapi/qapi-commands-machine-target.h"
#include "fpu_helper.h"
#if !defined(CONFIG_USER_ONLY)
/* Called for updates to CP0_Status. */
void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc)
{
int32_t tcstatus, *tcst;
uint32_t v = cpu->CP0_Status;
uint32_t cu, mx, asid, ksu;
uint32_t mask = ((1 << CP0TCSt_TCU3)
| (1 << CP0TCSt_TCU2)
| (1 << CP0TCSt_TCU1)
| (1 << CP0TCSt_TCU0)
| (1 << CP0TCSt_TMX)
| (3 << CP0TCSt_TKSU)
| (0xff << CP0TCSt_TASID));
cu = (v >> CP0St_CU0) & 0xf;
mx = (v >> CP0St_MX) & 0x1;
ksu = (v >> CP0St_KSU) & 0x3;
asid = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
tcstatus = cu << CP0TCSt_TCU0;
tcstatus |= mx << CP0TCSt_TMX;
tcstatus |= ksu << CP0TCSt_TKSU;
tcstatus |= asid;
if (tc == cpu->current_tc) {
tcst = &cpu->active_tc.CP0_TCStatus;
} else {
tcst = &cpu->tcs[tc].CP0_TCStatus;
}
*tcst &= ~mask;
*tcst |= tcstatus;
compute_hflags(cpu);
}
void cpu_mips_store_status(CPUMIPSState *env, target_ulong val)
{
uint32_t mask = env->CP0_Status_rw_bitmask;
target_ulong old = env->CP0_Status;
if (env->insn_flags & ISA_MIPS_R6) {
bool has_supervisor = extract32(mask, CP0St_KSU, 2) == 0x3;
#if defined(TARGET_MIPS64)
uint32_t ksux = (1 << CP0St_KX) & val;
ksux |= (ksux >> 1) & val; /* KX = 0 forces SX to be 0 */
ksux |= (ksux >> 1) & val; /* SX = 0 forces UX to be 0 */
val = (val & ~(7 << CP0St_UX)) | ksux;
#endif
if (has_supervisor && extract32(val, CP0St_KSU, 2) == 0x3) {
mask &= ~(3 << CP0St_KSU);
}
mask &= ~(((1 << CP0St_SR) | (1 << CP0St_NMI)) & val);
}
env->CP0_Status = (old & ~mask) | (val & mask);
#if defined(TARGET_MIPS64)
if ((env->CP0_Status ^ old) & (old & (7 << CP0St_UX))) {
/* Access to at least one of the 64-bit segments has been disabled */
tlb_flush(env_cpu(env));
}
#endif
if (ase_mt_available(env)) {
sync_c0_status(env, env, env->current_tc);
} else {
compute_hflags(env);
}
}
void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val)
{
uint32_t mask = 0x00C00300;
uint32_t old = env->CP0_Cause;
int i;
if (env->insn_flags & ISA_MIPS_R2) {
mask |= 1 << CP0Ca_DC;
}
if (env->insn_flags & ISA_MIPS_R6) {
mask &= ~((1 << CP0Ca_WP) & val);
}
env->CP0_Cause = (env->CP0_Cause & ~mask) | (val & mask);
if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
if (env->CP0_Cause & (1 << CP0Ca_DC)) {
cpu_mips_stop_count(env);
} else {
cpu_mips_start_count(env);
}
}
/* Set/reset software interrupts */
for (i = 0 ; i < 2 ; i++) {
if ((old ^ env->CP0_Cause) & (1 << (CP0Ca_IP + i))) {
cpu_mips_soft_irq(env, i, env->CP0_Cause & (1 << (CP0Ca_IP + i)));
}
}
}
#endif /* !CONFIG_USER_ONLY */
static const char * const excp_names[EXCP_LAST + 1] = {
[EXCP_RESET] = "reset",
[EXCP_SRESET] = "soft reset",
[EXCP_DSS] = "debug single step",
[EXCP_DINT] = "debug interrupt",
[EXCP_NMI] = "non-maskable interrupt",
[EXCP_MCHECK] = "machine check",
[EXCP_EXT_INTERRUPT] = "interrupt",
[EXCP_DFWATCH] = "deferred watchpoint",
[EXCP_DIB] = "debug instruction breakpoint",
[EXCP_IWATCH] = "instruction fetch watchpoint",
[EXCP_AdEL] = "address error load",
[EXCP_AdES] = "address error store",
[EXCP_TLBF] = "TLB refill",
[EXCP_IBE] = "instruction bus error",
[EXCP_DBp] = "debug breakpoint",
[EXCP_SYSCALL] = "syscall",
[EXCP_BREAK] = "break",
[EXCP_CpU] = "coprocessor unusable",
[EXCP_RI] = "reserved instruction",
[EXCP_OVERFLOW] = "arithmetic overflow",
[EXCP_TRAP] = "trap",
[EXCP_FPE] = "floating point",
[EXCP_DDBS] = "debug data break store",
[EXCP_DWATCH] = "data watchpoint",
[EXCP_LTLBL] = "TLB modify",
[EXCP_TLBL] = "TLB load",
[EXCP_TLBS] = "TLB store",
[EXCP_DBE] = "data bus error",
[EXCP_DDBL] = "debug data break load",
[EXCP_THREAD] = "thread",
[EXCP_MDMX] = "MDMX",
[EXCP_C2E] = "precise coprocessor 2",
[EXCP_CACHE] = "cache error",
[EXCP_TLBXI] = "TLB execute-inhibit",
[EXCP_TLBRI] = "TLB read-inhibit",
[EXCP_MSADIS] = "MSA disabled",
[EXCP_MSAFPE] = "MSA floating point",
};
const char *mips_exception_name(int32_t exception)
{
if (exception < 0 || exception > EXCP_LAST) {
return "unknown";
}
return excp_names[exception];
}
void cpu_set_exception_base(int vp_index, target_ulong address)
{
MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
vp->env.exception_base = address;
}
target_ulong exception_resume_pc(CPUMIPSState *env)
{
target_ulong bad_pc;
target_ulong isa_mode;
isa_mode = !!(env->hflags & MIPS_HFLAG_M16);
bad_pc = env->active_tc.PC | isa_mode;
if (env->hflags & MIPS_HFLAG_BMASK) {
/*
* If the exception was raised from a delay slot, come back to
* the jump.
*/
bad_pc -= (env->hflags & MIPS_HFLAG_B16 ? 2 : 4);
}
return bad_pc;
}
bool mips_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
if (interrupt_request & CPU_INTERRUPT_HARD) {
MIPSCPU *cpu = MIPS_CPU(cs);
CPUMIPSState *env = &cpu->env;
if (cpu_mips_hw_interrupts_enabled(env) &&
cpu_mips_hw_interrupts_pending(env)) {
/* Raise it */
cs->exception_index = EXCP_EXT_INTERRUPT;
env->error_code = 0;
mips_cpu_do_interrupt(cs);
return true;
}
}
return false;
}
void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env,
uint32_t exception,
int error_code,
uintptr_t pc)
{
CPUState *cs = env_cpu(env);
qemu_log_mask(CPU_LOG_INT, "%s: %d (%s) %d\n",
__func__, exception, mips_exception_name(exception),
error_code);
cs->exception_index = exception;
env->error_code = error_code;
cpu_loop_exit_restore(cs, pc);
}
static void mips_cpu_set_pc(CPUState *cs, vaddr value)
{
@ -72,7 +282,7 @@ static bool mips_cpu_has_work(CPUState *cs)
if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
cpu_mips_hw_interrupts_pending(env)) {
if (cpu_mips_hw_interrupts_enabled(env) ||
(env->insn_flags & ISA_MIPS32R6)) {
(env->insn_flags & ISA_MIPS_R6)) {
has_work = true;
}
}
@ -103,12 +313,18 @@ static bool mips_cpu_has_work(CPUState *cs)
return has_work;
}
#include "translate_init.c.inc"
#include "cpu-defs.c.inc"
/* TODO QOM'ify CPU reset and remove */
static void cpu_state_reset(CPUMIPSState *env)
static void mips_cpu_reset(DeviceState *dev)
{
CPUState *cs = env_cpu(env);
CPUState *cs = CPU(dev);
MIPSCPU *cpu = MIPS_CPU(cs);
MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu);
CPUMIPSState *env = &cpu->env;
mcc->parent_reset(dev);
memset(env, 0, offsetof(CPUMIPSState, end_reset_fields));
/* Reset registers to their default values */
env->CP0_PRid = env->cpu_model->CP0_PRid;
@ -288,13 +504,13 @@ static void cpu_state_reset(CPUMIPSState *env)
/* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
#endif /* !CONFIG_USER_ONLY */
if ((env->insn_flags & ISA_MIPS32R6) &&
if ((env->insn_flags & ISA_MIPS_R6) &&
(env->active_fpu.fcr0 & (1 << FCR0_F64))) {
/* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
env->CP0_Status |= (1 << CP0St_FR);
}
if (env->insn_flags & ISA_MIPS32R6) {
if (env->insn_flags & ISA_MIPS_R6) {
/* PTW = 1 */
env->CP0_PWSize = 0x40;
/* GDI = 12 */
@ -317,10 +533,7 @@ static void cpu_state_reset(CPUMIPSState *env)
env->hflags |= MIPS_HFLAG_M16;
}
/* MSA */
if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
msa_reset(env);
}
msa_reset(env);
compute_hflags(env);
restore_fp_status(env);
@ -331,20 +544,6 @@ static void cpu_state_reset(CPUMIPSState *env)
/* UHI interface can be used to obtain argc and argv */
env->active_tc.gpr[4] = -1;
}
}
static void mips_cpu_reset(DeviceState *dev)
{
CPUState *s = CPU(dev);
MIPSCPU *cpu = MIPS_CPU(s);
MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu);
CPUMIPSState *env = &cpu->env;
mcc->parent_reset(dev);
memset(env, 0, offsetof(CPUMIPSState, end_reset_fields));
cpu_state_reset(env);
#ifndef CONFIG_USER_ONLY
if (kvm_enabled()) {
@ -596,9 +795,3 @@ bool cpu_type_supports_cps_smp(const char *cpu_type)
const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
}
void cpu_set_exception_base(int vp_index, target_ulong address)
{
MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
vp->env.exception_base = address;
}

View File

@ -828,7 +828,7 @@ struct CPUMIPSState {
#define CP0EBase_WG 11
target_ulong CP0_CMGCRBase;
/*
* CP0 Register 16
* CP0 Register 16 (after Release 1)
*/
int32_t CP0_Config0;
#define CP0C0_M 31
@ -845,6 +845,14 @@ struct CPUMIPSState {
#define CP0C0_VI 3
#define CP0C0_K0 0 /* 2..0 */
#define CP0C0_AR_LENGTH 3
/*
* CP0 Register 16 (before Release 1)
*/
#define CP0C0_Impl 16 /* 24..16 */
#define CP0C0_IC 9 /* 11..9 */
#define CP0C0_DC 6 /* 8..6 */
#define CP0C0_IB 5
#define CP0C0_DB 4
int32_t CP0_Config1;
#define CP0C1_M 31
#define CP0C1_MMU 25 /* 30..25 */
@ -1291,12 +1299,23 @@ 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 MSA implementation */
static inline bool ase_msa_available(CPUMIPSState *env)
{
return env->CP0_Config3 & (1 << CP0C3_MSAP);
}
/* Check presence of multi-threading ASE implementation */
static inline bool ase_mt_available(CPUMIPSState *env)
{
return env->CP0_Config3 & (1 << CP0C3_MT);
}
static inline bool cpu_type_is_64bit(const char *cpu_type)
{
return cpu_type_supports_isa(cpu_type, CPU_MIPS64);
}
void cpu_set_exception_base(int vp_index, target_ulong address);
/* addr.c */
@ -1304,6 +1323,8 @@ uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr);
uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr);
uint64_t cpu_mips_kvm_um_phys_to_kseg0(void *opaque, uint64_t addr);
uint64_t cpu_mips_kseg1_to_phys(void *opaque, uint64_t addr);
uint64_t cpu_mips_phys_to_kseg1(void *opaque, uint64_t addr);
bool mips_um_ksegs_enabled(void);
void mips_um_ksegs_enable(void);

View File

@ -27,6 +27,7 @@
#include "exec/exec-all.h"
#include "exec/cpu_ldst.h"
#include "fpu/softfloat.h"
#include "fpu_helper.h"
/* Complex FPU operations which may need stack space. */
@ -145,7 +146,7 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
}
break;
case 25:
if ((env->insn_flags & ISA_MIPS32R6) || (arg1 & 0xffffff00)) {
if ((env->insn_flags & ISA_MIPS_R6) || (arg1 & 0xffffff00)) {
return;
}
env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017fffff) |
@ -172,7 +173,7 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
(env->active_fpu.fcr31 & ~(env->active_fpu.fcr31_rw_bitmask));
break;
default:
if (env->insn_flags & ISA_MIPS32R6) {
if (env->insn_flags & ISA_MIPS_R6) {
do_raise_exception(env, EXCP_RI, GETPC());
}
return;

59
target/mips/fpu_helper.h Normal file
View File

@ -0,0 +1,59 @@
/*
* Helpers for emulation of FPU-related MIPS instructions.
*
* Copyright (C) 2004-2005 Jocelyn Mayer
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "fpu/softfloat-helpers.h"
#include "cpu.h"
extern const FloatRoundMode ieee_rm[4];
uint32_t float_class_s(uint32_t arg, float_status *fst);
uint64_t float_class_d(uint64_t arg, float_status *fst);
static inline void restore_rounding_mode(CPUMIPSState *env)
{
set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3],
&env->active_fpu.fp_status);
}
static inline void restore_flush_mode(CPUMIPSState *env)
{
set_flush_to_zero((env->active_fpu.fcr31 & (1 << FCR31_FS)) != 0,
&env->active_fpu.fp_status);
}
static inline void restore_snan_bit_mode(CPUMIPSState *env)
{
set_snan_bit_is_one((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) == 0,
&env->active_fpu.fp_status);
}
static inline void restore_fp_status(CPUMIPSState *env)
{
restore_rounding_mode(env);
restore_flush_mode(env);
restore_snan_bit_mode(env);
}
/* MSA */
enum CPUMIPSMSADataFormat {
DF_BYTE = 0,
DF_HALF,
DF_WORD,
DF_DOUBLE
};
static inline void restore_msa_fp_status(CPUMIPSState *env)
{
float_status *status = &env->active_tc.msa_fp_status;
int rounding_mode = (env->active_tc.msacsr & MSACSR_RM_MASK) >> MSACSR_RM;
bool flush_to_zero = (env->active_tc.msacsr & MSACSR_FS_MASK) != 0;
set_float_rounding_mode(ieee_rm[rounding_mode], status);
set_flush_to_zero(flush_to_zero, status);
set_flush_inputs_to_zero(flush_to_zero, status);
}

View File

@ -21,6 +21,7 @@
#include "cpu.h"
#include "internal.h"
#include "exec/gdbstub.h"
#include "fpu_helper.h"
int mips_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{

View File

@ -781,438 +781,6 @@ DEF_HELPER_FLAGS_3(dmthlip, 0, void, tl, tl, env)
DEF_HELPER_FLAGS_3(wrdsp, 0, void, tl, tl, env)
DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env)
/* MIPS SIMD Architecture */
DEF_HELPER_3(msa_nloc_b, void, env, i32, i32)
DEF_HELPER_3(msa_nloc_h, void, env, i32, i32)
DEF_HELPER_3(msa_nloc_w, void, env, i32, i32)
DEF_HELPER_3(msa_nloc_d, void, env, i32, i32)
DEF_HELPER_3(msa_nlzc_b, void, env, i32, i32)
DEF_HELPER_3(msa_nlzc_h, void, env, i32, i32)
DEF_HELPER_3(msa_nlzc_w, void, env, i32, i32)
DEF_HELPER_3(msa_nlzc_d, void, env, i32, i32)
DEF_HELPER_3(msa_pcnt_b, void, env, i32, i32)
DEF_HELPER_3(msa_pcnt_h, void, env, i32, i32)
DEF_HELPER_3(msa_pcnt_w, void, env, i32, i32)
DEF_HELPER_3(msa_pcnt_d, void, env, i32, i32)
DEF_HELPER_4(msa_binsl_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_binsl_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_binsl_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_binsl_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_binsr_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_binsr_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_binsr_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_binsr_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bmnz_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bmz_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bsel_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bclr_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bclr_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bclr_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bclr_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bneg_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bneg_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bneg_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bneg_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bset_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bset_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bset_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bset_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_add_a_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_add_a_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_add_a_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_add_a_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_a_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_a_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_a_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_a_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_addv_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_addv_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_addv_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_addv_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hadd_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hadd_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hadd_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hadd_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hadd_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hadd_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ave_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ave_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ave_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ave_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ave_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ave_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ave_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ave_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_aver_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_aver_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_aver_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_aver_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_aver_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_aver_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_aver_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_aver_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ceq_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ceq_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ceq_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ceq_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_cle_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_cle_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_cle_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_cle_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_cle_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_cle_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_cle_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_cle_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_clt_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_clt_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_clt_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_clt_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_clt_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_clt_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_clt_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_clt_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_div_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_div_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_div_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_div_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_div_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_div_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_div_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_div_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_a_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_a_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_a_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_a_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_a_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_a_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_a_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_a_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mod_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mod_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mod_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mod_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mod_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mod_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mod_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mod_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_maddv_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_maddv_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_maddv_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_maddv_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_msubv_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_msubv_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_msubv_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_msubv_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mulv_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mulv_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mulv_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mulv_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_asub_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_asub_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_asub_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_asub_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_asub_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_asub_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_asub_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_asub_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hsub_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hsub_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hsub_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hsub_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hsub_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hsub_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subs_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subs_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subs_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subs_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subs_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subs_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subs_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subs_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subsus_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subsus_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subsus_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subsus_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subsuu_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subsuu_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subsuu_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subsuu_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subv_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subv_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subv_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subv_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvev_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvev_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvev_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvev_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvod_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvod_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvod_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvod_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvl_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvl_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvl_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvl_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvr_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvr_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvr_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvr_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_and_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_nor_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_or_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_xor_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_pckev_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_pckev_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_pckev_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_pckev_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_pckod_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_pckod_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_pckod_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_pckod_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_sll_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_sll_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_sll_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_sll_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_sra_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_sra_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_sra_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_sra_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srar_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srar_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srar_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srar_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srl_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srl_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srl_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srl_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srlr_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srlr_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srlr_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srlr_d, void, env, i32, i32, i32)
DEF_HELPER_3(msa_move_v, void, env, i32, i32)
DEF_HELPER_4(msa_andi_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ori_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_nori_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_xori_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bmnzi_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bmzi_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bseli_b, void, env, i32, i32, i32)
DEF_HELPER_5(msa_shf_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_addvi_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_subvi_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_maxi_s_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_maxi_u_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_mini_s_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_mini_u_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_ceqi_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_clti_s_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_clti_u_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_clei_s_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_clei_u_df, void, env, i32, i32, i32, s32)
DEF_HELPER_4(msa_ldi_df, void, env, i32, i32, s32)
DEF_HELPER_5(msa_slli_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_srai_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_srli_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_bclri_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_bseti_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_bnegi_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_binsli_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_binsri_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_sat_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_sat_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_srari_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_binsl_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_binsr_df, void, env, i32, i32, i32, i32)
DEF_HELPER_4(msa_dotp_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dotp_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dotp_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dotp_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dotp_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dotp_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpadd_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpadd_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpadd_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpadd_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpadd_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpadd_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpsub_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpsub_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpsub_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpsub_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpsub_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpsub_u_d, void, env, i32, i32, i32)
DEF_HELPER_5(msa_sld_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_splat_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_vshf_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_sldi_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_splati_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32)
DEF_HELPER_3(msa_ctcmsa, void, env, tl, i32)
DEF_HELPER_2(msa_cfcmsa, tl, env, i32)
DEF_HELPER_5(msa_fcaf_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcun_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fceq_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcueq_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fclt_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcult_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcle_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcule_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsaf_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsun_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fseq_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsueq_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fslt_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsult_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsle_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsule_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fadd_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsub_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmul_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fdiv_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmadd_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmsub_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fexp2_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fexdo_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_ftq_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmin_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmin_a_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmax_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmax_a_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcor_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcune_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcne_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_mul_q_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_madd_q_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_msub_q_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsor_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsune_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsne_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_mulr_q_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_maddr_q_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_msubr_q_df, void, env, i32, i32, i32, i32)
DEF_HELPER_4(msa_fill_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_copy_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_copy_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_copy_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_copy_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_copy_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_copy_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_copy_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_insert_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_insert_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_insert_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_insert_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_fclass_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ftrunc_s_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ftrunc_u_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_fsqrt_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_frsqrt_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_frcp_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_frint_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_flog2_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_fexupl_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_fexupr_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ffql_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ffqr_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ftint_s_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ftint_u_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ffint_s_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ffint_u_df, void, env, i32, i32, i32)
#define MSALDST_PROTO(type) \
DEF_HELPER_3(msa_ld_ ## type, void, env, i32, tl) \
DEF_HELPER_3(msa_st_ ## type, void, env, i32, tl)
MSALDST_PROTO(b)
MSALDST_PROTO(h)
MSALDST_PROTO(w)
MSALDST_PROTO(d)
#undef MSALDST_PROTO
DEF_HELPER_3(cache, void, env, tl, i32)
#include "msa_helper.h.inc"

View File

@ -9,7 +9,6 @@
#define MIPS_INTERNAL_H
#include "exec/memattrs.h"
#include "fpu/softfloat-helpers.h"
/*
* MMU types, the first four entries have the same layout as the
@ -75,13 +74,6 @@ struct mips_def_t {
extern const struct mips_def_t mips_defs[];
extern const int mips_defs_number;
enum CPUMIPSMSADataFormat {
DF_BYTE = 0,
DF_HALF,
DF_WORD,
DF_DOUBLE
};
void mips_cpu_do_interrupt(CPUState *cpu);
bool mips_cpu_exec_interrupt(CPUState *cpu, int int_req);
void mips_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
@ -207,6 +199,8 @@ static inline bool cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
void mips_tcg_init(void);
void msa_reset(CPUMIPSState *env);
/* cp0_timer.c */
uint32_t cpu_mips_get_count(CPUMIPSState *env);
void cpu_mips_store_count(CPUMIPSState *env, uint32_t value);
@ -215,54 +209,14 @@ void cpu_mips_start_count(CPUMIPSState *env);
void cpu_mips_stop_count(CPUMIPSState *env);
/* helper.c */
void mmu_init(CPUMIPSState *env, const mips_def_t *def);
bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr);
/* op_helper.c */
uint32_t float_class_s(uint32_t arg, float_status *fst);
uint64_t float_class_d(uint64_t arg, float_status *fst);
extern const FloatRoundMode ieee_rm[4];
void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask);
static inline void restore_rounding_mode(CPUMIPSState *env)
{
set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3],
&env->active_fpu.fp_status);
}
static inline void restore_flush_mode(CPUMIPSState *env)
{
set_flush_to_zero((env->active_fpu.fcr31 & (1 << FCR31_FS)) != 0,
&env->active_fpu.fp_status);
}
static inline void restore_snan_bit_mode(CPUMIPSState *env)
{
set_snan_bit_is_one((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) == 0,
&env->active_fpu.fp_status);
}
static inline void restore_fp_status(CPUMIPSState *env)
{
restore_rounding_mode(env);
restore_flush_mode(env);
restore_snan_bit_mode(env);
}
static inline void restore_msa_fp_status(CPUMIPSState *env)
{
float_status *status = &env->active_tc.msa_fp_status;
int rounding_mode = (env->active_tc.msacsr & MSACSR_RM_MASK) >> MSACSR_RM;
bool flush_to_zero = (env->active_tc.msacsr & MSACSR_FS_MASK) != 0;
set_float_rounding_mode(ieee_rm[rounding_mode], status);
set_flush_to_zero(flush_to_zero, status);
set_flush_inputs_to_zero(flush_to_zero, status);
}
static inline void restore_pamask(CPUMIPSState *env)
{
if (env->hflags & MIPS_HFLAG_ELPA) {
@ -354,7 +308,7 @@ static inline void compute_hflags(CPUMIPSState *env)
} else if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
!(env->CP0_Status & (1 << CP0St_UX))) {
env->hflags |= MIPS_HFLAG_AWRAP;
} else if (env->insn_flags & ISA_MIPS64R6) {
} else if (env->insn_flags & ISA_MIPS_R6) {
/* Address wrapping for Supervisor and Kernel is specified in R6 */
if ((((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_SM) &&
!(env->CP0_Status & (1 << CP0St_SX))) ||
@ -365,7 +319,7 @@ static inline void compute_hflags(CPUMIPSState *env)
}
#endif
if (((env->CP0_Status & (1 << CP0St_CU0)) &&
!(env->insn_flags & ISA_MIPS32R6)) ||
!(env->insn_flags & ISA_MIPS_R6)) ||
!(env->hflags & MIPS_HFLAG_KSU)) {
env->hflags |= MIPS_HFLAG_CP0;
}
@ -407,11 +361,11 @@ static inline void compute_hflags(CPUMIPSState *env)
}
}
if (env->insn_flags & ISA_MIPS32R2) {
if (env->insn_flags & ISA_MIPS_R2) {
if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
env->hflags |= MIPS_HFLAG_COP1X;
}
} else if (env->insn_flags & ISA_MIPS32) {
} else if (env->insn_flags & ISA_MIPS_R1) {
if (env->hflags & MIPS_HFLAG_64) {
env->hflags |= MIPS_HFLAG_COP1X;
}
@ -426,7 +380,7 @@ static inline void compute_hflags(CPUMIPSState *env)
env->hflags |= MIPS_HFLAG_COP1X;
}
}
if (env->insn_flags & ASE_MSA) {
if (ase_msa_available(env)) {
if (env->CP0_Config5 & (1 << CP0C5_MSAEn)) {
env->hflags |= MIPS_HFLAG_MSA;
}
@ -448,6 +402,8 @@ void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc);
void cpu_mips_store_status(CPUMIPSState *env, target_ulong val);
void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val);
const char *mips_exception_name(int32_t exception);
void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, uint32_t exception,
int error_code, uintptr_t pc);

View File

@ -24,6 +24,7 @@
#include "sysemu/runstate.h"
#include "kvm_mips.h"
#include "hw/boards.h"
#include "fpu_helper.h"
#define DEBUG_KVM 0
@ -78,7 +79,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
}
}
if (kvm_mips_msa_cap && env->CP0_Config3 & (1 << CP0C3_MSAP)) {
if (kvm_mips_msa_cap && ase_msa_available(env)) {
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_MIPS_MSA, 0, 0);
if (ret < 0) {
/* mark unsupported so it gets disabled on reset */
@ -104,7 +105,7 @@ void kvm_mips_reset_vcpu(MIPSCPU *cpu)
warn_report("KVM does not support FPU, disabling");
env->CP0_Config1 &= ~(1 << CP0C1_FP);
}
if (!kvm_mips_msa_cap && env->CP0_Config3 & (1 << CP0C3_MSAP)) {
if (!kvm_mips_msa_cap && ase_msa_available(env)) {
warn_report("KVM does not support MSA, disabling");
env->CP0_Config3 &= ~(1 << CP0C3_MSAP);
}
@ -617,7 +618,7 @@ static int kvm_mips_put_fpu_registers(CPUState *cs, int level)
* FPU register state is a subset of MSA vector state, so don't put FPU
* registers if we're emulating a CPU with MSA.
*/
if (!(env->CP0_Config3 & (1 << CP0C3_MSAP))) {
if (!ase_msa_available(env)) {
/* Floating point registers */
for (i = 0; i < 32; ++i) {
if (env->CP0_Status & (1 << CP0St_FR)) {
@ -636,7 +637,7 @@ static int kvm_mips_put_fpu_registers(CPUState *cs, int level)
}
/* Only put MSA state if we're emulating a CPU with MSA */
if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
if (ase_msa_available(env)) {
/* MSA Control Registers */
if (level == KVM_PUT_FULL_STATE) {
err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_MSA_IR,
@ -697,7 +698,7 @@ static int kvm_mips_get_fpu_registers(CPUState *cs)
* FPU register state is a subset of MSA vector state, so don't save FPU
* registers if we're emulating a CPU with MSA.
*/
if (!(env->CP0_Config3 & (1 << CP0C3_MSAP))) {
if (!ase_msa_available(env)) {
/* Floating point registers */
for (i = 0; i < 32; ++i) {
if (env->CP0_Status & (1 << CP0St_FR)) {
@ -716,7 +717,7 @@ static int kvm_mips_get_fpu_registers(CPUState *cs)
}
/* Only get MSA state if we're emulating a CPU with MSA */
if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
if (ase_msa_available(env)) {
/* MSA Control Registers */
err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_MSA_IR,
&env->msair);

View File

@ -2,6 +2,7 @@
#include "cpu.h"
#include "internal.h"
#include "migration/cpu.h"
#include "fpu_helper.h"
static int cpu_post_load(void *opaque, int version_id)
{

View File

@ -1,25 +1,40 @@
gen = [
decodetree.process('mips32r6.decode', extra_args: '--static-decode=decode_mips32r6'),
decodetree.process('mips64r6.decode', extra_args: '--static-decode=decode_mips64r6'),
decodetree.process('msa32.decode', extra_args: '--static-decode=decode_msa32'),
decodetree.process('msa64.decode', extra_args: '--static-decode=decode_msa64'),
]
mips_ss = ss.source_set()
mips_ss.add(gen)
mips_ss.add(files(
'cpu.c',
'gdbstub.c',
))
mips_ss.add(when: 'CONFIG_TCG', if_true: files(
'dsp_helper.c',
'fpu_helper.c',
'gdbstub.c',
'helper.c',
'lmmi_helper.c',
'msa_helper.c',
'msa_translate.c',
'op_helper.c',
'rel6_translate.c',
'tlb_helper.c',
'translate.c',
'translate_addr_const.c',
))
mips_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'))
mips_softmmu_ss = ss.source_set()
mips_softmmu_ss.add(files(
'addr.c',
'cp0_helper.c',
'cp0_timer.c',
'machine.c',
'mips-semi.c',
))
mips_softmmu_ss.add(when: 'CONFIG_TCG', if_true: files(
'cp0_helper.c',
))
target_arch += {'mips': mips_ss}
target_softmmu_arch += {'mips': mips_softmmu_ss}

View File

@ -1,12 +1,6 @@
#ifndef QEMU_MIPS_DEFS_H
#define QEMU_MIPS_DEFS_H
/*
* If we want to use host float regs...
*
* #define USE_HOST_FLOAT_REGS
*/
/* Real pages are variable size... */
#define MIPS_TLB_MAX 128
@ -19,19 +13,14 @@
*/
#define ISA_MIPS1 0x0000000000000001ULL
#define ISA_MIPS2 0x0000000000000002ULL
#define ISA_MIPS3 0x0000000000000004ULL
#define ISA_MIPS3 0x0000000000000004ULL /* 64-bit */
#define ISA_MIPS4 0x0000000000000008ULL
#define ISA_MIPS5 0x0000000000000010ULL
#define ISA_MIPS32 0x0000000000000020ULL
#define ISA_MIPS32R2 0x0000000000000040ULL
#define ISA_MIPS64 0x0000000000000080ULL
#define ISA_MIPS64R2 0x0000000000000100ULL
#define ISA_MIPS32R3 0x0000000000000200ULL
#define ISA_MIPS64R3 0x0000000000000400ULL
#define ISA_MIPS32R5 0x0000000000000800ULL
#define ISA_MIPS64R5 0x0000000000001000ULL
#define ISA_MIPS32R6 0x0000000000002000ULL
#define ISA_MIPS64R6 0x0000000000004000ULL
#define ISA_MIPS_R1 0x0000000000000020ULL
#define ISA_MIPS_R2 0x0000000000000040ULL
#define ISA_MIPS_R3 0x0000000000000080ULL
#define ISA_MIPS_R5 0x0000000000000100ULL
#define ISA_MIPS_R6 0x0000000000000200ULL
#define ISA_NANOMIPS32 0x0000000000008000ULL
/*
* bits 24-39: MIPS ASEs
@ -45,7 +34,6 @@
#define ASE_MT 0x0000000040000000ULL
#define ASE_SMARTMIPS 0x0000000080000000ULL
#define ASE_MICROMIPS 0x0000000100000000ULL
#define ASE_MSA 0x0000000200000000ULL
/*
* bits 40-51: vendor-specific base instruction sets
*/
@ -71,37 +59,29 @@
#define CPU_MIPS2 (CPU_MIPS1 | ISA_MIPS2)
#define CPU_MIPS3 (CPU_MIPS2 | ISA_MIPS3)
#define CPU_MIPS4 (CPU_MIPS3 | ISA_MIPS4)
#define CPU_VR54XX (CPU_MIPS4 | INSN_VR54XX)
#define CPU_R5900 (CPU_MIPS3 | INSN_R5900)
#define CPU_LOONGSON2E (CPU_MIPS3 | INSN_LOONGSON2E)
#define CPU_LOONGSON2F (CPU_MIPS3 | INSN_LOONGSON2F | ASE_LMMI)
#define CPU_MIPS5 (CPU_MIPS4 | ISA_MIPS5)
#define CPU_MIPS64 (ISA_MIPS3)
/* MIPS Technologies "Release 1" */
#define CPU_MIPS32 (CPU_MIPS2 | ISA_MIPS32)
#define CPU_MIPS64 (CPU_MIPS5 | CPU_MIPS32 | ISA_MIPS64)
#define CPU_MIPS32R1 (CPU_MIPS2 | ISA_MIPS_R1)
#define CPU_MIPS64R1 (CPU_MIPS5 | CPU_MIPS32R1)
/* MIPS Technologies "Release 2" */
#define CPU_MIPS32R2 (CPU_MIPS32 | ISA_MIPS32R2)
#define CPU_MIPS64R2 (CPU_MIPS64 | CPU_MIPS32R2 | ISA_MIPS64R2)
#define CPU_MIPS32R2 (CPU_MIPS32R1 | ISA_MIPS_R2)
#define CPU_MIPS64R2 (CPU_MIPS64R1 | CPU_MIPS32R2)
/* MIPS Technologies "Release 3" */
#define CPU_MIPS32R3 (CPU_MIPS32R2 | ISA_MIPS32R3)
#define CPU_MIPS64R3 (CPU_MIPS64R2 | CPU_MIPS32R3 | ISA_MIPS64R3)
#define CPU_MIPS32R3 (CPU_MIPS32R2 | ISA_MIPS_R3)
#define CPU_MIPS64R3 (CPU_MIPS64R2 | CPU_MIPS32R3)
/* MIPS Technologies "Release 5" */
#define CPU_MIPS32R5 (CPU_MIPS32R3 | ISA_MIPS32R5)
#define CPU_MIPS64R5 (CPU_MIPS64R3 | CPU_MIPS32R5 | ISA_MIPS64R5)
#define CPU_MIPS32R5 (CPU_MIPS32R3 | ISA_MIPS_R5)
#define CPU_MIPS64R5 (CPU_MIPS64R3 | CPU_MIPS32R5)
/* MIPS Technologies "Release 6" */
#define CPU_MIPS32R6 (CPU_MIPS32R5 | ISA_MIPS32R6)
#define CPU_MIPS64R6 (CPU_MIPS64R5 | CPU_MIPS32R6 | ISA_MIPS64R6)
/* Wave Computing: "nanoMIPS" */
#define CPU_NANOMIPS32 (CPU_MIPS32R6 | ISA_NANOMIPS32)
#define CPU_LOONGSON3A (CPU_MIPS64R2 | INSN_LOONGSON3A | ASE_LMMI | ASE_LEXT)
#define CPU_MIPS32R6 (CPU_MIPS32R5 | ISA_MIPS_R6)
#define CPU_MIPS64R6 (CPU_MIPS64R5 | CPU_MIPS32R6)
/*
* Strictly follow the architecture standard:

View File

@ -0,0 +1,36 @@
# MIPS32 Release 6 instruction set
#
# Copyright (C) 2020 Philippe Mathieu-Daudé
#
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# Reference:
# MIPS Architecture for Programmers Volume II-A
# The MIPS32 Instruction Set Reference Manual, Revision 6.06
# (Document Number: MD00086-2B-MIPS32BIS-AFP-06.06)
#
&rtype rs rt rd sa
@lsa ...... rs:5 rt:5 rd:5 ... sa:2 ...... &rtype
LSA 000000 ..... ..... ..... 000 .. 000101 @lsa
REMOVED 010011 ----- ----- ----- ----- ------ # COP1X (COP3)
REMOVED 011100 ----- ----- ----- ----- ------ # SPECIAL2
REMOVED 011111 ----- ----- ---------- 011001 # LWLE
REMOVED 011111 ----- ----- ---------- 011010 # LWRE
REMOVED 011111 ----- ----- ---------- 100001 # SWLE
REMOVED 011111 ----- ----- ---------- 100010 # SWRE
REMOVED 100010 ----- ----- ---------------- # LWL
REMOVED 100110 ----- ----- ---------------- # LWR
REMOVED 101010 ----- ----- ---------------- # SWL
REMOVED 101110 ----- ----- ---------------- # SWR
REMOVED 101111 ----- ----- ---------------- # CACHE
REMOVED 110000 ----- ----- ---------------- # LL
REMOVED 110011 ----- ----- ---------------- # PREF
REMOVED 111000 ----- ----- ---------------- # SC

View File

@ -0,0 +1,27 @@
# MIPS64 Release 6 instruction set
#
# Copyright (C) 2020 Philippe Mathieu-Daudé
#
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# Reference:
# MIPS Architecture for Programmers Volume II-A
# The MIPS64 Instruction Set Reference Manual, Revision 6.06
# (Document Number: MD00087-2B-MIPS64BIS-AFP-6.06)
#
&rtype rs rt rd sa !extern
&REMOVED !extern
@lsa ...... rs:5 rt:5 rd:5 ... sa:2 ...... &rtype
DLSA 000000 ..... ..... ..... 000 .. 010101 @lsa
REMOVED 011010 ----- ----- ---------------- # LDL
REMOVED 011011 ----- ----- ---------------- # LDR
REMOVED 101100 ----- ----- ---------------- # SDL
REMOVED 101101 ----- ----- ---------------- # SDR
REMOVED 110100 ----- ----- ---------------- # LLD
REMOVED 111100 ----- ----- ---------------- # SCD

29
target/mips/msa32.decode Normal file
View File

@ -0,0 +1,29 @@
# MIPS SIMD Architecture Module instruction set
#
# Copyright (C) 2020 Philippe Mathieu-Daudé
#
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# Reference:
# MIPS Architecture for Programmers Volume IV-j
# The MIPS32 SIMD Architecture Module, Revision 1.12
# (Document Number: MD00866-2B-MSA32-AFP-01.12)
#
&rtype rs rt rd sa
&msa_bz df wt s16
@lsa ...... rs:5 rt:5 rd:5 ... sa:2 ...... &rtype
@bz ...... ... .. wt:5 s16:16 &msa_bz df=3
@bz_df ...... ... df:2 wt:5 s16:16 &msa_bz
LSA 000000 ..... ..... ..... 000 .. 000101 @lsa
BZ_V 010001 01011 ..... ................ @bz
BNZ_V 010001 01111 ..... ................ @bz
BZ_x 010001 110 .. ..... ................ @bz_df
BNZ_x 010001 111 .. ..... ................ @bz_df
MSA 011110 --------------------------

17
target/mips/msa64.decode Normal file
View File

@ -0,0 +1,17 @@
# MIPS SIMD Architecture Module instruction set
#
# Copyright (C) 2020 Philippe Mathieu-Daudé
#
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# Reference:
# MIPS Architecture for Programmers Volume IV-j
# The MIPS64 SIMD Architecture Module, Revision 1.12
# (Document Number: MD00868-1D-MSA64-AFP-01.12)
#
&rtype rs rt rd sa !extern
@lsa ...... rs:5 rt:5 rd:5 ... sa:2 ...... &rtype
DLSA 000000 ..... ..... ..... 000 .. 010101 @lsa

View File

@ -22,7 +22,9 @@
#include "internal.h"
#include "exec/exec-all.h"
#include "exec/helper-proto.h"
#include "exec/memop.h"
#include "fpu/softfloat.h"
#include "fpu_helper.h"
/* Data format min and max values */
#define DF_BITS(df) (1 << ((df) + 3))
@ -8200,3 +8202,431 @@ void helper_msa_ffint_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
msa_move_v(pwd, pwx);
}
/* Data format min and max values */
#define DF_BITS(df) (1 << ((df) + 3))
/* Element-by-element access macros */
#define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df))
#if !defined(CONFIG_USER_ONLY)
#define MEMOP_IDX(DF) \
TCGMemOpIdx oi = make_memop_idx(MO_TE | DF | MO_UNALN, \
cpu_mmu_index(env, false));
#else
#define MEMOP_IDX(DF)
#endif
void helper_msa_ld_b(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
MEMOP_IDX(DF_BYTE)
#if !defined(CONFIG_USER_ONLY)
#if !defined(HOST_WORDS_BIGENDIAN)
pwd->b[0] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC());
pwd->b[1] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC());
pwd->b[2] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC());
pwd->b[3] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC());
pwd->b[4] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC());
pwd->b[5] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC());
pwd->b[6] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC());
pwd->b[7] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC());
pwd->b[8] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC());
pwd->b[9] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC());
pwd->b[10] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC());
pwd->b[11] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC());
pwd->b[12] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC());
pwd->b[13] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC());
pwd->b[14] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC());
pwd->b[15] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC());
#else
pwd->b[0] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC());
pwd->b[1] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC());
pwd->b[2] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC());
pwd->b[3] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC());
pwd->b[4] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC());
pwd->b[5] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC());
pwd->b[6] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC());
pwd->b[7] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC());
pwd->b[8] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC());
pwd->b[9] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC());
pwd->b[10] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC());
pwd->b[11] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC());
pwd->b[12] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC());
pwd->b[13] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC());
pwd->b[14] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC());
pwd->b[15] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC());
#endif
#else
#if !defined(HOST_WORDS_BIGENDIAN)
pwd->b[0] = cpu_ldub_data(env, addr + (0 << DF_BYTE));
pwd->b[1] = cpu_ldub_data(env, addr + (1 << DF_BYTE));
pwd->b[2] = cpu_ldub_data(env, addr + (2 << DF_BYTE));
pwd->b[3] = cpu_ldub_data(env, addr + (3 << DF_BYTE));
pwd->b[4] = cpu_ldub_data(env, addr + (4 << DF_BYTE));
pwd->b[5] = cpu_ldub_data(env, addr + (5 << DF_BYTE));
pwd->b[6] = cpu_ldub_data(env, addr + (6 << DF_BYTE));
pwd->b[7] = cpu_ldub_data(env, addr + (7 << DF_BYTE));
pwd->b[8] = cpu_ldub_data(env, addr + (8 << DF_BYTE));
pwd->b[9] = cpu_ldub_data(env, addr + (9 << DF_BYTE));
pwd->b[10] = cpu_ldub_data(env, addr + (10 << DF_BYTE));
pwd->b[11] = cpu_ldub_data(env, addr + (11 << DF_BYTE));
pwd->b[12] = cpu_ldub_data(env, addr + (12 << DF_BYTE));
pwd->b[13] = cpu_ldub_data(env, addr + (13 << DF_BYTE));
pwd->b[14] = cpu_ldub_data(env, addr + (14 << DF_BYTE));
pwd->b[15] = cpu_ldub_data(env, addr + (15 << DF_BYTE));
#else
pwd->b[0] = cpu_ldub_data(env, addr + (7 << DF_BYTE));
pwd->b[1] = cpu_ldub_data(env, addr + (6 << DF_BYTE));
pwd->b[2] = cpu_ldub_data(env, addr + (5 << DF_BYTE));
pwd->b[3] = cpu_ldub_data(env, addr + (4 << DF_BYTE));
pwd->b[4] = cpu_ldub_data(env, addr + (3 << DF_BYTE));
pwd->b[5] = cpu_ldub_data(env, addr + (2 << DF_BYTE));
pwd->b[6] = cpu_ldub_data(env, addr + (1 << DF_BYTE));
pwd->b[7] = cpu_ldub_data(env, addr + (0 << DF_BYTE));
pwd->b[8] = cpu_ldub_data(env, addr + (15 << DF_BYTE));
pwd->b[9] = cpu_ldub_data(env, addr + (14 << DF_BYTE));
pwd->b[10] = cpu_ldub_data(env, addr + (13 << DF_BYTE));
pwd->b[11] = cpu_ldub_data(env, addr + (12 << DF_BYTE));
pwd->b[12] = cpu_ldub_data(env, addr + (11 << DF_BYTE));
pwd->b[13] = cpu_ldub_data(env, addr + (10 << DF_BYTE));
pwd->b[14] = cpu_ldub_data(env, addr + (9 << DF_BYTE));
pwd->b[15] = cpu_ldub_data(env, addr + (8 << DF_BYTE));
#endif
#endif
}
void helper_msa_ld_h(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
MEMOP_IDX(DF_HALF)
#if !defined(CONFIG_USER_ONLY)
#if !defined(HOST_WORDS_BIGENDIAN)
pwd->h[0] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC());
pwd->h[1] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC());
pwd->h[2] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC());
pwd->h[3] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC());
pwd->h[4] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC());
pwd->h[5] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC());
pwd->h[6] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC());
pwd->h[7] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC());
#else
pwd->h[0] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC());
pwd->h[1] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC());
pwd->h[2] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC());
pwd->h[3] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC());
pwd->h[4] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC());
pwd->h[5] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC());
pwd->h[6] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC());
pwd->h[7] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC());
#endif
#else
#if !defined(HOST_WORDS_BIGENDIAN)
pwd->h[0] = cpu_lduw_data(env, addr + (0 << DF_HALF));
pwd->h[1] = cpu_lduw_data(env, addr + (1 << DF_HALF));
pwd->h[2] = cpu_lduw_data(env, addr + (2 << DF_HALF));
pwd->h[3] = cpu_lduw_data(env, addr + (3 << DF_HALF));
pwd->h[4] = cpu_lduw_data(env, addr + (4 << DF_HALF));
pwd->h[5] = cpu_lduw_data(env, addr + (5 << DF_HALF));
pwd->h[6] = cpu_lduw_data(env, addr + (6 << DF_HALF));
pwd->h[7] = cpu_lduw_data(env, addr + (7 << DF_HALF));
#else
pwd->h[0] = cpu_lduw_data(env, addr + (3 << DF_HALF));
pwd->h[1] = cpu_lduw_data(env, addr + (2 << DF_HALF));
pwd->h[2] = cpu_lduw_data(env, addr + (1 << DF_HALF));
pwd->h[3] = cpu_lduw_data(env, addr + (0 << DF_HALF));
pwd->h[4] = cpu_lduw_data(env, addr + (7 << DF_HALF));
pwd->h[5] = cpu_lduw_data(env, addr + (6 << DF_HALF));
pwd->h[6] = cpu_lduw_data(env, addr + (5 << DF_HALF));
pwd->h[7] = cpu_lduw_data(env, addr + (4 << DF_HALF));
#endif
#endif
}
void helper_msa_ld_w(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
MEMOP_IDX(DF_WORD)
#if !defined(CONFIG_USER_ONLY)
#if !defined(HOST_WORDS_BIGENDIAN)
pwd->w[0] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC());
pwd->w[1] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC());
pwd->w[2] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC());
pwd->w[3] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC());
#else
pwd->w[0] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC());
pwd->w[1] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC());
pwd->w[2] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC());
pwd->w[3] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC());
#endif
#else
#if !defined(HOST_WORDS_BIGENDIAN)
pwd->w[0] = cpu_ldl_data(env, addr + (0 << DF_WORD));
pwd->w[1] = cpu_ldl_data(env, addr + (1 << DF_WORD));
pwd->w[2] = cpu_ldl_data(env, addr + (2 << DF_WORD));
pwd->w[3] = cpu_ldl_data(env, addr + (3 << DF_WORD));
#else
pwd->w[0] = cpu_ldl_data(env, addr + (1 << DF_WORD));
pwd->w[1] = cpu_ldl_data(env, addr + (0 << DF_WORD));
pwd->w[2] = cpu_ldl_data(env, addr + (3 << DF_WORD));
pwd->w[3] = cpu_ldl_data(env, addr + (2 << DF_WORD));
#endif
#endif
}
void helper_msa_ld_d(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
MEMOP_IDX(DF_DOUBLE)
#if !defined(CONFIG_USER_ONLY)
pwd->d[0] = helper_ret_ldq_mmu(env, addr + (0 << DF_DOUBLE), oi, GETPC());
pwd->d[1] = helper_ret_ldq_mmu(env, addr + (1 << DF_DOUBLE), oi, GETPC());
#else
pwd->d[0] = cpu_ldq_data(env, addr + (0 << DF_DOUBLE));
pwd->d[1] = cpu_ldq_data(env, addr + (1 << DF_DOUBLE));
#endif
}
#define MSA_PAGESPAN(x) \
((((x) & ~TARGET_PAGE_MASK) + MSA_WRLEN / 8 - 1) >= TARGET_PAGE_SIZE)
static inline void ensure_writable_pages(CPUMIPSState *env,
target_ulong addr,
int mmu_idx,
uintptr_t retaddr)
{
/* FIXME: Probe the actual accesses (pass and use a size) */
if (unlikely(MSA_PAGESPAN(addr))) {
/* first page */
probe_write(env, addr, 0, mmu_idx, retaddr);
/* second page */
addr = (addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
probe_write(env, addr, 0, mmu_idx, retaddr);
}
}
void helper_msa_st_b(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
int mmu_idx = cpu_mmu_index(env, false);
MEMOP_IDX(DF_BYTE)
ensure_writable_pages(env, addr, mmu_idx, GETPC());
#if !defined(CONFIG_USER_ONLY)
#if !defined(HOST_WORDS_BIGENDIAN)
helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[0], oi, GETPC());
helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[1], oi, GETPC());
helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[2], oi, GETPC());
helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[3], oi, GETPC());
helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[4], oi, GETPC());
helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[5], oi, GETPC());
helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[6], oi, GETPC());
helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[7], oi, GETPC());
helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[8], oi, GETPC());
helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[9], oi, GETPC());
helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[10], oi, GETPC());
helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[11], oi, GETPC());
helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[12], oi, GETPC());
helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[13], oi, GETPC());
helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[14], oi, GETPC());
helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[15], oi, GETPC());
#else
helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[0], oi, GETPC());
helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[1], oi, GETPC());
helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[2], oi, GETPC());
helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[3], oi, GETPC());
helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[4], oi, GETPC());
helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[5], oi, GETPC());
helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[6], oi, GETPC());
helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[7], oi, GETPC());
helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[8], oi, GETPC());
helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[9], oi, GETPC());
helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[10], oi, GETPC());
helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[11], oi, GETPC());
helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[12], oi, GETPC());
helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[13], oi, GETPC());
helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[14], oi, GETPC());
helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[15], oi, GETPC());
#endif
#else
#if !defined(HOST_WORDS_BIGENDIAN)
cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[0]);
cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[1]);
cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[2]);
cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[3]);
cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[4]);
cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[5]);
cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[6]);
cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[7]);
cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[8]);
cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[9]);
cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[10]);
cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[11]);
cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[12]);
cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[13]);
cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[14]);
cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[15]);
#else
cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[0]);
cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[1]);
cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[2]);
cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[3]);
cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[4]);
cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[5]);
cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[6]);
cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[7]);
cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[8]);
cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[9]);
cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[10]);
cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[11]);
cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[12]);
cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[13]);
cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[14]);
cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[15]);
#endif
#endif
}
void helper_msa_st_h(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
int mmu_idx = cpu_mmu_index(env, false);
MEMOP_IDX(DF_HALF)
ensure_writable_pages(env, addr, mmu_idx, GETPC());
#if !defined(CONFIG_USER_ONLY)
#if !defined(HOST_WORDS_BIGENDIAN)
helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[0], oi, GETPC());
helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[1], oi, GETPC());
helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[2], oi, GETPC());
helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[3], oi, GETPC());
helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[4], oi, GETPC());
helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[5], oi, GETPC());
helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[6], oi, GETPC());
helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[7], oi, GETPC());
#else
helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[0], oi, GETPC());
helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[1], oi, GETPC());
helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[2], oi, GETPC());
helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[3], oi, GETPC());
helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[4], oi, GETPC());
helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[5], oi, GETPC());
helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[6], oi, GETPC());
helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[7], oi, GETPC());
#endif
#else
#if !defined(HOST_WORDS_BIGENDIAN)
cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[0]);
cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[1]);
cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[2]);
cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[3]);
cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[4]);
cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[5]);
cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[6]);
cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[7]);
#else
cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[0]);
cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[1]);
cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[2]);
cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[3]);
cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[4]);
cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[5]);
cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[6]);
cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[7]);
#endif
#endif
}
void helper_msa_st_w(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
int mmu_idx = cpu_mmu_index(env, false);
MEMOP_IDX(DF_WORD)
ensure_writable_pages(env, addr, mmu_idx, GETPC());
#if !defined(CONFIG_USER_ONLY)
#if !defined(HOST_WORDS_BIGENDIAN)
helper_ret_stl_mmu(env, addr + (0 << DF_WORD), pwd->w[0], oi, GETPC());
helper_ret_stl_mmu(env, addr + (1 << DF_WORD), pwd->w[1], oi, GETPC());
helper_ret_stl_mmu(env, addr + (2 << DF_WORD), pwd->w[2], oi, GETPC());
helper_ret_stl_mmu(env, addr + (3 << DF_WORD), pwd->w[3], oi, GETPC());
#else
helper_ret_stl_mmu(env, addr + (1 << DF_WORD), pwd->w[0], oi, GETPC());
helper_ret_stl_mmu(env, addr + (0 << DF_WORD), pwd->w[1], oi, GETPC());
helper_ret_stl_mmu(env, addr + (3 << DF_WORD), pwd->w[2], oi, GETPC());
helper_ret_stl_mmu(env, addr + (2 << DF_WORD), pwd->w[3], oi, GETPC());
#endif
#else
#if !defined(HOST_WORDS_BIGENDIAN)
cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[0]);
cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[1]);
cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[2]);
cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[3]);
#else
cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[0]);
cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[1]);
cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[2]);
cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[3]);
#endif
#endif
}
void helper_msa_st_d(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
int mmu_idx = cpu_mmu_index(env, false);
MEMOP_IDX(DF_DOUBLE)
ensure_writable_pages(env, addr, mmu_idx, GETPC());
#if !defined(CONFIG_USER_ONLY)
helper_ret_stq_mmu(env, addr + (0 << DF_DOUBLE), pwd->d[0], oi, GETPC());
helper_ret_stq_mmu(env, addr + (1 << DF_DOUBLE), pwd->d[1], oi, GETPC());
#else
cpu_stq_data(env, addr + (0 << DF_DOUBLE), pwd->d[0]);
cpu_stq_data(env, addr + (1 << DF_DOUBLE), pwd->d[1]);
#endif
}
void msa_reset(CPUMIPSState *env)
{
if (!ase_msa_available(env)) {
return;
}
#ifdef CONFIG_USER_ONLY
/* MSA access enabled */
env->CP0_Config5 |= 1 << CP0C5_MSAEn;
env->CP0_Status |= (1 << CP0St_CU1) | (1 << CP0St_FR);
#endif
/*
* MSA CSR:
* - non-signaling floating point exception mode off (NX bit is 0)
* - Cause, Enables, and Flags are all 0
* - round to nearest / ties to even (RM bits are 0)
*/
env->active_tc.msacsr = 0;
restore_msa_fp_status(env);
/* tininess detected after rounding.*/
set_float_detect_tininess(float_tininess_after_rounding,
&env->active_tc.msa_fp_status);
/* clear float_status exception flags */
set_float_exception_flags(0, &env->active_tc.msa_fp_status);
/* clear float_status nan mode */
set_default_nan_mode(0, &env->active_tc.msa_fp_status);
/* set proper signanling bit meaning ("1" means "quiet") */
set_snan_bit_is_one(0, &env->active_tc.msa_fp_status);
}

View File

@ -0,0 +1,443 @@
/*
* MIPS SIMD Architecture Module (MSA) helpers for QEMU.
*
* Copyright (c) 2004-2005 Jocelyn Mayer
* Copyright (c) 2006 Marius Groeger (FPU operations)
* Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
* Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
* Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
DEF_HELPER_3(msa_nloc_b, void, env, i32, i32)
DEF_HELPER_3(msa_nloc_h, void, env, i32, i32)
DEF_HELPER_3(msa_nloc_w, void, env, i32, i32)
DEF_HELPER_3(msa_nloc_d, void, env, i32, i32)
DEF_HELPER_3(msa_nlzc_b, void, env, i32, i32)
DEF_HELPER_3(msa_nlzc_h, void, env, i32, i32)
DEF_HELPER_3(msa_nlzc_w, void, env, i32, i32)
DEF_HELPER_3(msa_nlzc_d, void, env, i32, i32)
DEF_HELPER_3(msa_pcnt_b, void, env, i32, i32)
DEF_HELPER_3(msa_pcnt_h, void, env, i32, i32)
DEF_HELPER_3(msa_pcnt_w, void, env, i32, i32)
DEF_HELPER_3(msa_pcnt_d, void, env, i32, i32)
DEF_HELPER_4(msa_binsl_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_binsl_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_binsl_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_binsl_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_binsr_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_binsr_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_binsr_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_binsr_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bmnz_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bmz_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bsel_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bclr_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bclr_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bclr_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bclr_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bneg_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bneg_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bneg_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bneg_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bset_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bset_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bset_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bset_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_add_a_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_add_a_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_add_a_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_add_a_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_a_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_a_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_a_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_a_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_adds_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_addv_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_addv_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_addv_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_addv_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hadd_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hadd_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hadd_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hadd_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hadd_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hadd_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ave_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ave_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ave_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ave_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ave_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ave_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ave_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ave_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_aver_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_aver_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_aver_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_aver_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_aver_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_aver_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_aver_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_aver_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ceq_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ceq_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ceq_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ceq_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_cle_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_cle_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_cle_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_cle_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_cle_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_cle_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_cle_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_cle_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_clt_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_clt_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_clt_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_clt_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_clt_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_clt_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_clt_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_clt_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_div_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_div_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_div_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_div_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_div_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_div_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_div_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_div_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_a_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_a_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_a_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_a_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_max_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_a_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_a_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_a_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_a_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_min_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mod_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mod_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mod_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mod_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mod_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mod_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mod_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mod_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_maddv_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_maddv_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_maddv_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_maddv_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_msubv_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_msubv_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_msubv_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_msubv_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mulv_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mulv_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mulv_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_mulv_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_asub_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_asub_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_asub_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_asub_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_asub_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_asub_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_asub_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_asub_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hsub_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hsub_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hsub_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hsub_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hsub_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_hsub_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subs_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subs_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subs_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subs_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subs_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subs_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subs_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subs_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subsus_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subsus_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subsus_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subsus_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subsuu_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subsuu_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subsuu_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subsuu_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subv_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subv_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subv_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_subv_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvev_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvev_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvev_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvev_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvod_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvod_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvod_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvod_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvl_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvl_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvl_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvl_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvr_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvr_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvr_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ilvr_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_and_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_nor_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_or_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_xor_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_pckev_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_pckev_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_pckev_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_pckev_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_pckod_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_pckod_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_pckod_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_pckod_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_sll_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_sll_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_sll_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_sll_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_sra_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_sra_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_sra_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_sra_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srar_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srar_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srar_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srar_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srl_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srl_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srl_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srl_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srlr_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srlr_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srlr_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_srlr_d, void, env, i32, i32, i32)
DEF_HELPER_3(msa_move_v, void, env, i32, i32)
DEF_HELPER_4(msa_andi_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ori_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_nori_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_xori_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bmnzi_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bmzi_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bseli_b, void, env, i32, i32, i32)
DEF_HELPER_5(msa_shf_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_addvi_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_subvi_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_maxi_s_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_maxi_u_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_mini_s_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_mini_u_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_ceqi_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_clti_s_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_clti_u_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_clei_s_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_clei_u_df, void, env, i32, i32, i32, s32)
DEF_HELPER_4(msa_ldi_df, void, env, i32, i32, s32)
DEF_HELPER_5(msa_slli_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_srai_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_srli_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_bclri_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_bseti_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_bnegi_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_binsli_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_binsri_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_sat_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_sat_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_srari_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_binsl_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_binsr_df, void, env, i32, i32, i32, i32)
DEF_HELPER_4(msa_dotp_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dotp_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dotp_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dotp_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dotp_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dotp_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpadd_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpadd_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpadd_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpadd_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpadd_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpadd_u_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpsub_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpsub_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpsub_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpsub_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpsub_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_dpsub_u_d, void, env, i32, i32, i32)
DEF_HELPER_5(msa_sld_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_splat_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_vshf_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_sldi_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_splati_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32)
DEF_HELPER_3(msa_ctcmsa, void, env, tl, i32)
DEF_HELPER_2(msa_cfcmsa, tl, env, i32)
DEF_HELPER_5(msa_fcaf_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcun_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fceq_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcueq_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fclt_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcult_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcle_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcule_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsaf_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsun_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fseq_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsueq_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fslt_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsult_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsle_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsule_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fadd_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsub_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmul_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fdiv_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmadd_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmsub_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fexp2_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fexdo_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_ftq_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmin_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmin_a_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmax_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmax_a_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcor_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcune_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcne_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_mul_q_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_madd_q_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_msub_q_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsor_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsune_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsne_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_mulr_q_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_maddr_q_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_msubr_q_df, void, env, i32, i32, i32, i32)
DEF_HELPER_4(msa_fill_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_copy_s_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_copy_s_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_copy_s_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_copy_s_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_copy_u_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_copy_u_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_copy_u_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_insert_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_insert_h, void, env, i32, i32, i32)
DEF_HELPER_4(msa_insert_w, void, env, i32, i32, i32)
DEF_HELPER_4(msa_insert_d, void, env, i32, i32, i32)
DEF_HELPER_4(msa_fclass_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ftrunc_s_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ftrunc_u_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_fsqrt_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_frsqrt_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_frcp_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_frint_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_flog2_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_fexupl_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_fexupr_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ffql_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ffqr_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ftint_s_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ftint_u_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ffint_s_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ffint_u_df, void, env, i32, i32, i32)
#define MSALDST_PROTO(type) \
DEF_HELPER_3(msa_ld_ ## type, void, env, i32, tl) \
DEF_HELPER_3(msa_st_ ## type, void, env, i32, tl)
MSALDST_PROTO(b)
MSALDST_PROTO(h)
MSALDST_PROTO(w)
MSALDST_PROTO(d)
#undef MSALDST_PROTO

2286
target/mips/msa_translate.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@
#include "exec/helper-proto.h"
#include "exec/exec-all.h"
#include "exec/memop.h"
#include "fpu_helper.h"
/*****************************************************************************/
/* Exceptions processing helpers */
@ -1173,400 +1173,6 @@ void mips_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
}
#endif /* !CONFIG_USER_ONLY */
/* MSA */
/* Data format min and max values */
#define DF_BITS(df) (1 << ((df) + 3))
/* Element-by-element access macros */
#define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df))
#if !defined(CONFIG_USER_ONLY)
#define MEMOP_IDX(DF) \
TCGMemOpIdx oi = make_memop_idx(MO_TE | DF | MO_UNALN, \
cpu_mmu_index(env, false));
#else
#define MEMOP_IDX(DF)
#endif
void helper_msa_ld_b(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
MEMOP_IDX(DF_BYTE)
#if !defined(CONFIG_USER_ONLY)
#if !defined(HOST_WORDS_BIGENDIAN)
pwd->b[0] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC());
pwd->b[1] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC());
pwd->b[2] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC());
pwd->b[3] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC());
pwd->b[4] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC());
pwd->b[5] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC());
pwd->b[6] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC());
pwd->b[7] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC());
pwd->b[8] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC());
pwd->b[9] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC());
pwd->b[10] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC());
pwd->b[11] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC());
pwd->b[12] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC());
pwd->b[13] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC());
pwd->b[14] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC());
pwd->b[15] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC());
#else
pwd->b[0] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC());
pwd->b[1] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC());
pwd->b[2] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC());
pwd->b[3] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC());
pwd->b[4] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC());
pwd->b[5] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC());
pwd->b[6] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC());
pwd->b[7] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC());
pwd->b[8] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC());
pwd->b[9] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC());
pwd->b[10] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC());
pwd->b[11] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC());
pwd->b[12] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC());
pwd->b[13] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC());
pwd->b[14] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC());
pwd->b[15] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC());
#endif
#else
#if !defined(HOST_WORDS_BIGENDIAN)
pwd->b[0] = cpu_ldub_data(env, addr + (0 << DF_BYTE));
pwd->b[1] = cpu_ldub_data(env, addr + (1 << DF_BYTE));
pwd->b[2] = cpu_ldub_data(env, addr + (2 << DF_BYTE));
pwd->b[3] = cpu_ldub_data(env, addr + (3 << DF_BYTE));
pwd->b[4] = cpu_ldub_data(env, addr + (4 << DF_BYTE));
pwd->b[5] = cpu_ldub_data(env, addr + (5 << DF_BYTE));
pwd->b[6] = cpu_ldub_data(env, addr + (6 << DF_BYTE));
pwd->b[7] = cpu_ldub_data(env, addr + (7 << DF_BYTE));
pwd->b[8] = cpu_ldub_data(env, addr + (8 << DF_BYTE));
pwd->b[9] = cpu_ldub_data(env, addr + (9 << DF_BYTE));
pwd->b[10] = cpu_ldub_data(env, addr + (10 << DF_BYTE));
pwd->b[11] = cpu_ldub_data(env, addr + (11 << DF_BYTE));
pwd->b[12] = cpu_ldub_data(env, addr + (12 << DF_BYTE));
pwd->b[13] = cpu_ldub_data(env, addr + (13 << DF_BYTE));
pwd->b[14] = cpu_ldub_data(env, addr + (14 << DF_BYTE));
pwd->b[15] = cpu_ldub_data(env, addr + (15 << DF_BYTE));
#else
pwd->b[0] = cpu_ldub_data(env, addr + (7 << DF_BYTE));
pwd->b[1] = cpu_ldub_data(env, addr + (6 << DF_BYTE));
pwd->b[2] = cpu_ldub_data(env, addr + (5 << DF_BYTE));
pwd->b[3] = cpu_ldub_data(env, addr + (4 << DF_BYTE));
pwd->b[4] = cpu_ldub_data(env, addr + (3 << DF_BYTE));
pwd->b[5] = cpu_ldub_data(env, addr + (2 << DF_BYTE));
pwd->b[6] = cpu_ldub_data(env, addr + (1 << DF_BYTE));
pwd->b[7] = cpu_ldub_data(env, addr + (0 << DF_BYTE));
pwd->b[8] = cpu_ldub_data(env, addr + (15 << DF_BYTE));
pwd->b[9] = cpu_ldub_data(env, addr + (14 << DF_BYTE));
pwd->b[10] = cpu_ldub_data(env, addr + (13 << DF_BYTE));
pwd->b[11] = cpu_ldub_data(env, addr + (12 << DF_BYTE));
pwd->b[12] = cpu_ldub_data(env, addr + (11 << DF_BYTE));
pwd->b[13] = cpu_ldub_data(env, addr + (10 << DF_BYTE));
pwd->b[14] = cpu_ldub_data(env, addr + (9 << DF_BYTE));
pwd->b[15] = cpu_ldub_data(env, addr + (8 << DF_BYTE));
#endif
#endif
}
void helper_msa_ld_h(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
MEMOP_IDX(DF_HALF)
#if !defined(CONFIG_USER_ONLY)
#if !defined(HOST_WORDS_BIGENDIAN)
pwd->h[0] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC());
pwd->h[1] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC());
pwd->h[2] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC());
pwd->h[3] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC());
pwd->h[4] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC());
pwd->h[5] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC());
pwd->h[6] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC());
pwd->h[7] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC());
#else
pwd->h[0] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC());
pwd->h[1] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC());
pwd->h[2] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC());
pwd->h[3] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC());
pwd->h[4] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC());
pwd->h[5] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC());
pwd->h[6] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC());
pwd->h[7] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC());
#endif
#else
#if !defined(HOST_WORDS_BIGENDIAN)
pwd->h[0] = cpu_lduw_data(env, addr + (0 << DF_HALF));
pwd->h[1] = cpu_lduw_data(env, addr + (1 << DF_HALF));
pwd->h[2] = cpu_lduw_data(env, addr + (2 << DF_HALF));
pwd->h[3] = cpu_lduw_data(env, addr + (3 << DF_HALF));
pwd->h[4] = cpu_lduw_data(env, addr + (4 << DF_HALF));
pwd->h[5] = cpu_lduw_data(env, addr + (5 << DF_HALF));
pwd->h[6] = cpu_lduw_data(env, addr + (6 << DF_HALF));
pwd->h[7] = cpu_lduw_data(env, addr + (7 << DF_HALF));
#else
pwd->h[0] = cpu_lduw_data(env, addr + (3 << DF_HALF));
pwd->h[1] = cpu_lduw_data(env, addr + (2 << DF_HALF));
pwd->h[2] = cpu_lduw_data(env, addr + (1 << DF_HALF));
pwd->h[3] = cpu_lduw_data(env, addr + (0 << DF_HALF));
pwd->h[4] = cpu_lduw_data(env, addr + (7 << DF_HALF));
pwd->h[5] = cpu_lduw_data(env, addr + (6 << DF_HALF));
pwd->h[6] = cpu_lduw_data(env, addr + (5 << DF_HALF));
pwd->h[7] = cpu_lduw_data(env, addr + (4 << DF_HALF));
#endif
#endif
}
void helper_msa_ld_w(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
MEMOP_IDX(DF_WORD)
#if !defined(CONFIG_USER_ONLY)
#if !defined(HOST_WORDS_BIGENDIAN)
pwd->w[0] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC());
pwd->w[1] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC());
pwd->w[2] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC());
pwd->w[3] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC());
#else
pwd->w[0] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC());
pwd->w[1] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC());
pwd->w[2] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC());
pwd->w[3] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC());
#endif
#else
#if !defined(HOST_WORDS_BIGENDIAN)
pwd->w[0] = cpu_ldl_data(env, addr + (0 << DF_WORD));
pwd->w[1] = cpu_ldl_data(env, addr + (1 << DF_WORD));
pwd->w[2] = cpu_ldl_data(env, addr + (2 << DF_WORD));
pwd->w[3] = cpu_ldl_data(env, addr + (3 << DF_WORD));
#else
pwd->w[0] = cpu_ldl_data(env, addr + (1 << DF_WORD));
pwd->w[1] = cpu_ldl_data(env, addr + (0 << DF_WORD));
pwd->w[2] = cpu_ldl_data(env, addr + (3 << DF_WORD));
pwd->w[3] = cpu_ldl_data(env, addr + (2 << DF_WORD));
#endif
#endif
}
void helper_msa_ld_d(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
MEMOP_IDX(DF_DOUBLE)
#if !defined(CONFIG_USER_ONLY)
pwd->d[0] = helper_ret_ldq_mmu(env, addr + (0 << DF_DOUBLE), oi, GETPC());
pwd->d[1] = helper_ret_ldq_mmu(env, addr + (1 << DF_DOUBLE), oi, GETPC());
#else
pwd->d[0] = cpu_ldq_data(env, addr + (0 << DF_DOUBLE));
pwd->d[1] = cpu_ldq_data(env, addr + (1 << DF_DOUBLE));
#endif
}
#define MSA_PAGESPAN(x) \
((((x) & ~TARGET_PAGE_MASK) + MSA_WRLEN / 8 - 1) >= TARGET_PAGE_SIZE)
static inline void ensure_writable_pages(CPUMIPSState *env,
target_ulong addr,
int mmu_idx,
uintptr_t retaddr)
{
/* FIXME: Probe the actual accesses (pass and use a size) */
if (unlikely(MSA_PAGESPAN(addr))) {
/* first page */
probe_write(env, addr, 0, mmu_idx, retaddr);
/* second page */
addr = (addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
probe_write(env, addr, 0, mmu_idx, retaddr);
}
}
void helper_msa_st_b(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
int mmu_idx = cpu_mmu_index(env, false);
MEMOP_IDX(DF_BYTE)
ensure_writable_pages(env, addr, mmu_idx, GETPC());
#if !defined(CONFIG_USER_ONLY)
#if !defined(HOST_WORDS_BIGENDIAN)
helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[0], oi, GETPC());
helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[1], oi, GETPC());
helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[2], oi, GETPC());
helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[3], oi, GETPC());
helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[4], oi, GETPC());
helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[5], oi, GETPC());
helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[6], oi, GETPC());
helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[7], oi, GETPC());
helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[8], oi, GETPC());
helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[9], oi, GETPC());
helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[10], oi, GETPC());
helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[11], oi, GETPC());
helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[12], oi, GETPC());
helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[13], oi, GETPC());
helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[14], oi, GETPC());
helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[15], oi, GETPC());
#else
helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[0], oi, GETPC());
helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[1], oi, GETPC());
helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[2], oi, GETPC());
helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[3], oi, GETPC());
helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[4], oi, GETPC());
helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[5], oi, GETPC());
helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[6], oi, GETPC());
helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[7], oi, GETPC());
helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[8], oi, GETPC());
helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[9], oi, GETPC());
helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[10], oi, GETPC());
helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[11], oi, GETPC());
helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[12], oi, GETPC());
helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[13], oi, GETPC());
helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[14], oi, GETPC());
helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[15], oi, GETPC());
#endif
#else
#if !defined(HOST_WORDS_BIGENDIAN)
cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[0]);
cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[1]);
cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[2]);
cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[3]);
cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[4]);
cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[5]);
cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[6]);
cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[7]);
cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[8]);
cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[9]);
cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[10]);
cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[11]);
cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[12]);
cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[13]);
cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[14]);
cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[15]);
#else
cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[0]);
cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[1]);
cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[2]);
cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[3]);
cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[4]);
cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[5]);
cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[6]);
cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[7]);
cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[8]);
cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[9]);
cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[10]);
cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[11]);
cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[12]);
cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[13]);
cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[14]);
cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[15]);
#endif
#endif
}
void helper_msa_st_h(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
int mmu_idx = cpu_mmu_index(env, false);
MEMOP_IDX(DF_HALF)
ensure_writable_pages(env, addr, mmu_idx, GETPC());
#if !defined(CONFIG_USER_ONLY)
#if !defined(HOST_WORDS_BIGENDIAN)
helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[0], oi, GETPC());
helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[1], oi, GETPC());
helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[2], oi, GETPC());
helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[3], oi, GETPC());
helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[4], oi, GETPC());
helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[5], oi, GETPC());
helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[6], oi, GETPC());
helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[7], oi, GETPC());
#else
helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[0], oi, GETPC());
helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[1], oi, GETPC());
helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[2], oi, GETPC());
helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[3], oi, GETPC());
helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[4], oi, GETPC());
helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[5], oi, GETPC());
helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[6], oi, GETPC());
helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[7], oi, GETPC());
#endif
#else
#if !defined(HOST_WORDS_BIGENDIAN)
cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[0]);
cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[1]);
cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[2]);
cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[3]);
cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[4]);
cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[5]);
cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[6]);
cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[7]);
#else
cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[0]);
cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[1]);
cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[2]);
cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[3]);
cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[4]);
cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[5]);
cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[6]);
cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[7]);
#endif
#endif
}
void helper_msa_st_w(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
int mmu_idx = cpu_mmu_index(env, false);
MEMOP_IDX(DF_WORD)
ensure_writable_pages(env, addr, mmu_idx, GETPC());
#if !defined(CONFIG_USER_ONLY)
#if !defined(HOST_WORDS_BIGENDIAN)
helper_ret_stl_mmu(env, addr + (0 << DF_WORD), pwd->w[0], oi, GETPC());
helper_ret_stl_mmu(env, addr + (1 << DF_WORD), pwd->w[1], oi, GETPC());
helper_ret_stl_mmu(env, addr + (2 << DF_WORD), pwd->w[2], oi, GETPC());
helper_ret_stl_mmu(env, addr + (3 << DF_WORD), pwd->w[3], oi, GETPC());
#else
helper_ret_stl_mmu(env, addr + (1 << DF_WORD), pwd->w[0], oi, GETPC());
helper_ret_stl_mmu(env, addr + (0 << DF_WORD), pwd->w[1], oi, GETPC());
helper_ret_stl_mmu(env, addr + (3 << DF_WORD), pwd->w[2], oi, GETPC());
helper_ret_stl_mmu(env, addr + (2 << DF_WORD), pwd->w[3], oi, GETPC());
#endif
#else
#if !defined(HOST_WORDS_BIGENDIAN)
cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[0]);
cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[1]);
cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[2]);
cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[3]);
#else
cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[0]);
cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[1]);
cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[2]);
cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[3]);
#endif
#endif
}
void helper_msa_st_d(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
int mmu_idx = cpu_mmu_index(env, false);
MEMOP_IDX(DF_DOUBLE)
ensure_writable_pages(env, addr, mmu_idx, GETPC());
#if !defined(CONFIG_USER_ONLY)
helper_ret_stq_mmu(env, addr + (0 << DF_DOUBLE), pwd->d[0], oi, GETPC());
helper_ret_stq_mmu(env, addr + (1 << DF_DOUBLE), pwd->d[1], oi, GETPC());
#else
cpu_stq_data(env, addr + (0 << DF_DOUBLE), pwd->d[0]);
cpu_stq_data(env, addr + (1 << DF_DOUBLE), pwd->d[1]);
#endif
}
void helper_cache(CPUMIPSState *env, target_ulong addr, uint32_t op)
{
#ifndef CONFIG_USER_ONLY

View File

@ -0,0 +1,44 @@
/*
* MIPS emulation for QEMU - # Release 6 translation routines
*
* Copyright (c) 2004-2005 Jocelyn Mayer
* Copyright (c) 2006 Marius Groeger (FPU operations)
* Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
* Copyright (c) 2020 Philippe Mathieu-Daudé
*
* This code is licensed under the GNU GPLv2 and later.
*/
#include "qemu/osdep.h"
#include "tcg/tcg-op.h"
#include "exec/helper-gen.h"
#include "translate.h"
/* Include the auto-generated decoder. */
#include "decode-mips32r6.c.inc"
#include "decode-mips64r6.c.inc"
bool trans_REMOVED(DisasContext *ctx, arg_REMOVED *a)
{
gen_reserved_instruction(ctx);
return true;
}
static bool trans_LSA(DisasContext *ctx, arg_rtype *a)
{
return gen_lsa(ctx, a->rd, a->rt, a->rs, a->sa);
}
static bool trans_DLSA(DisasContext *ctx, arg_rtype *a)
{
return gen_dlsa(ctx, a->rd, a->rt, a->rs, a->sa);
}
bool decode_isa_rel6(DisasContext *ctx, uint32_t insn)
{
if (TARGET_LONG_BITS == 64 && decode_mips64r6(ctx, insn)) {
return true;
}
return decode_mips32r6(ctx, insn);
}

View File

@ -1,5 +1,5 @@
/*
* MIPS emulation helpers for qemu.
* MIPS TLB (Translation lookaside buffer) helpers.
*
* Copyright (c) 2004-2005 Jocelyn Mayer
*
@ -120,6 +120,52 @@ int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
return TLBRET_NOMATCH;
}
static void no_mmu_init(CPUMIPSState *env, const mips_def_t *def)
{
env->tlb->nb_tlb = 1;
env->tlb->map_address = &no_mmu_map_address;
}
static void fixed_mmu_init(CPUMIPSState *env, const mips_def_t *def)
{
env->tlb->nb_tlb = 1;
env->tlb->map_address = &fixed_mmu_map_address;
}
static void r4k_mmu_init(CPUMIPSState *env, const mips_def_t *def)
{
env->tlb->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63);
env->tlb->map_address = &r4k_map_address;
env->tlb->helper_tlbwi = r4k_helper_tlbwi;
env->tlb->helper_tlbwr = r4k_helper_tlbwr;
env->tlb->helper_tlbp = r4k_helper_tlbp;
env->tlb->helper_tlbr = r4k_helper_tlbr;
env->tlb->helper_tlbinv = r4k_helper_tlbinv;
env->tlb->helper_tlbinvf = r4k_helper_tlbinvf;
}
void mmu_init(CPUMIPSState *env, const mips_def_t *def)
{
env->tlb = g_malloc0(sizeof(CPUMIPSTLBContext));
switch (def->mmu_type) {
case MMU_TYPE_NONE:
no_mmu_init(env, def);
break;
case MMU_TYPE_R4000:
r4k_mmu_init(env, def);
break;
case MMU_TYPE_FMT:
fixed_mmu_init(env, def);
break;
case MMU_TYPE_R3000:
case MMU_TYPE_R6000:
case MMU_TYPE_R8000:
default:
cpu_abort(env_cpu(env), "MMU type not supported\n");
}
}
static int is_seg_am_mapped(unsigned int am, bool eu, int mmu_idx)
{
/*
@ -357,105 +403,7 @@ void cpu_mips_tlb_flush(CPUMIPSState *env)
env->tlb->tlb_in_use = env->tlb->nb_tlb;
}
/* Called for updates to CP0_Status. */
void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc)
{
int32_t tcstatus, *tcst;
uint32_t v = cpu->CP0_Status;
uint32_t cu, mx, asid, ksu;
uint32_t mask = ((1 << CP0TCSt_TCU3)
| (1 << CP0TCSt_TCU2)
| (1 << CP0TCSt_TCU1)
| (1 << CP0TCSt_TCU0)
| (1 << CP0TCSt_TMX)
| (3 << CP0TCSt_TKSU)
| (0xff << CP0TCSt_TASID));
cu = (v >> CP0St_CU0) & 0xf;
mx = (v >> CP0St_MX) & 0x1;
ksu = (v >> CP0St_KSU) & 0x3;
asid = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
tcstatus = cu << CP0TCSt_TCU0;
tcstatus |= mx << CP0TCSt_TMX;
tcstatus |= ksu << CP0TCSt_TKSU;
tcstatus |= asid;
if (tc == cpu->current_tc) {
tcst = &cpu->active_tc.CP0_TCStatus;
} else {
tcst = &cpu->tcs[tc].CP0_TCStatus;
}
*tcst &= ~mask;
*tcst |= tcstatus;
compute_hflags(cpu);
}
void cpu_mips_store_status(CPUMIPSState *env, target_ulong val)
{
uint32_t mask = env->CP0_Status_rw_bitmask;
target_ulong old = env->CP0_Status;
if (env->insn_flags & ISA_MIPS32R6) {
bool has_supervisor = extract32(mask, CP0St_KSU, 2) == 0x3;
#if defined(TARGET_MIPS64)
uint32_t ksux = (1 << CP0St_KX) & val;
ksux |= (ksux >> 1) & val; /* KX = 0 forces SX to be 0 */
ksux |= (ksux >> 1) & val; /* SX = 0 forces UX to be 0 */
val = (val & ~(7 << CP0St_UX)) | ksux;
#endif
if (has_supervisor && extract32(val, CP0St_KSU, 2) == 0x3) {
mask &= ~(3 << CP0St_KSU);
}
mask &= ~(((1 << CP0St_SR) | (1 << CP0St_NMI)) & val);
}
env->CP0_Status = (old & ~mask) | (val & mask);
#if defined(TARGET_MIPS64)
if ((env->CP0_Status ^ old) & (old & (7 << CP0St_UX))) {
/* Access to at least one of the 64-bit segments has been disabled */
tlb_flush(env_cpu(env));
}
#endif
if (ase_mt_available(env)) {
sync_c0_status(env, env, env->current_tc);
} else {
compute_hflags(env);
}
}
void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val)
{
uint32_t mask = 0x00C00300;
uint32_t old = env->CP0_Cause;
int i;
if (env->insn_flags & ISA_MIPS32R2) {
mask |= 1 << CP0Ca_DC;
}
if (env->insn_flags & ISA_MIPS32R6) {
mask &= ~((1 << CP0Ca_WP) & val);
}
env->CP0_Cause = (env->CP0_Cause & ~mask) | (val & mask);
if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
if (env->CP0_Cause & (1 << CP0Ca_DC)) {
cpu_mips_stop_count(env);
} else {
cpu_mips_start_count(env);
}
}
/* Set/reset software interrupts */
for (i = 0 ; i < 2 ; i++) {
if ((old ^ env->CP0_Cause) & (1 << (CP0Ca_IP + i))) {
cpu_mips_soft_irq(env, i, env->CP0_Cause & (1 << (CP0Ca_IP + i)));
}
}
}
#endif
#endif /* !CONFIG_USER_ONLY */
static void raise_mmu_exception(CPUMIPSState *env, target_ulong address,
int rw, int tlb_error)
@ -537,6 +485,7 @@ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address,
}
#if !defined(CONFIG_USER_ONLY)
hwaddr mips_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
{
MIPSCPU *cpu = MIPS_CPU(cs);
@ -550,9 +499,7 @@ hwaddr mips_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
}
return phys_addr;
}
#endif
#if !defined(CONFIG_USER_ONLY)
#if !defined(TARGET_MIPS64)
/*
@ -886,7 +833,7 @@ refill:
return true;
}
#endif
#endif
#endif /* !CONFIG_USER_ONLY */
bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
@ -977,75 +924,7 @@ hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address,
return physical;
}
}
#endif /* !CONFIG_USER_ONLY */
static const char * const excp_names[EXCP_LAST + 1] = {
[EXCP_RESET] = "reset",
[EXCP_SRESET] = "soft reset",
[EXCP_DSS] = "debug single step",
[EXCP_DINT] = "debug interrupt",
[EXCP_NMI] = "non-maskable interrupt",
[EXCP_MCHECK] = "machine check",
[EXCP_EXT_INTERRUPT] = "interrupt",
[EXCP_DFWATCH] = "deferred watchpoint",
[EXCP_DIB] = "debug instruction breakpoint",
[EXCP_IWATCH] = "instruction fetch watchpoint",
[EXCP_AdEL] = "address error load",
[EXCP_AdES] = "address error store",
[EXCP_TLBF] = "TLB refill",
[EXCP_IBE] = "instruction bus error",
[EXCP_DBp] = "debug breakpoint",
[EXCP_SYSCALL] = "syscall",
[EXCP_BREAK] = "break",
[EXCP_CpU] = "coprocessor unusable",
[EXCP_RI] = "reserved instruction",
[EXCP_OVERFLOW] = "arithmetic overflow",
[EXCP_TRAP] = "trap",
[EXCP_FPE] = "floating point",
[EXCP_DDBS] = "debug data break store",
[EXCP_DWATCH] = "data watchpoint",
[EXCP_LTLBL] = "TLB modify",
[EXCP_TLBL] = "TLB load",
[EXCP_TLBS] = "TLB store",
[EXCP_DBE] = "data bus error",
[EXCP_DDBL] = "debug data break load",
[EXCP_THREAD] = "thread",
[EXCP_MDMX] = "MDMX",
[EXCP_C2E] = "precise coprocessor 2",
[EXCP_CACHE] = "cache error",
[EXCP_TLBXI] = "TLB execute-inhibit",
[EXCP_TLBRI] = "TLB read-inhibit",
[EXCP_MSADIS] = "MSA disabled",
[EXCP_MSAFPE] = "MSA floating point",
};
static const char *mips_exception_name(int32_t exception)
{
if (exception < 0 || exception > EXCP_LAST) {
return "unknown";
}
return excp_names[exception];
}
target_ulong exception_resume_pc(CPUMIPSState *env)
{
target_ulong bad_pc;
target_ulong isa_mode;
isa_mode = !!(env->hflags & MIPS_HFLAG_M16);
bad_pc = env->active_tc.PC | isa_mode;
if (env->hflags & MIPS_HFLAG_BMASK) {
/*
* If the exception was raised from a delay slot, come back to
* the jump.
*/
bad_pc -= (env->hflags & MIPS_HFLAG_B16 ? 2 : 4);
}
return bad_pc;
}
#if !defined(CONFIG_USER_ONLY)
static void set_hflags_for_handler(CPUMIPSState *env)
{
/* Exception handlers are entered in 32-bit mode. */
@ -1088,7 +967,8 @@ static inline void set_badinstr_registers(CPUMIPSState *env)
env->CP0_BadInstrP = cpu_ldl_code(env, env->active_tc.PC - 4);
}
}
#endif
#endif /* !CONFIG_USER_ONLY */
void mips_cpu_do_interrupt(CPUState *cs)
{
@ -1145,7 +1025,7 @@ void mips_cpu_do_interrupt(CPUState *cs)
enter_debug_mode:
if (env->insn_flags & ISA_MIPS3) {
env->hflags |= MIPS_HFLAG_64;
if (!(env->insn_flags & ISA_MIPS64R6) ||
if (!(env->insn_flags & ISA_MIPS_R6) ||
env->CP0_Status & (1 << CP0St_KX)) {
env->hflags &= ~MIPS_HFLAG_AWRAP;
}
@ -1174,7 +1054,7 @@ void mips_cpu_do_interrupt(CPUState *cs)
env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
if (env->insn_flags & ISA_MIPS3) {
env->hflags |= MIPS_HFLAG_64;
if (!(env->insn_flags & ISA_MIPS64R6) ||
if (!(env->insn_flags & ISA_MIPS_R6) ||
env->CP0_Status & (1 << CP0St_KX)) {
env->hflags &= ~MIPS_HFLAG_AWRAP;
}
@ -1360,7 +1240,7 @@ void mips_cpu_do_interrupt(CPUState *cs)
env->CP0_Status |= (1 << CP0St_EXL);
if (env->insn_flags & ISA_MIPS3) {
env->hflags |= MIPS_HFLAG_64;
if (!(env->insn_flags & ISA_MIPS64R6) ||
if (!(env->insn_flags & ISA_MIPS_R6) ||
env->CP0_Status & (1 << CP0St_KX)) {
env->hflags &= ~MIPS_HFLAG_AWRAP;
}
@ -1399,24 +1279,6 @@ void mips_cpu_do_interrupt(CPUState *cs)
cs->exception_index = EXCP_NONE;
}
bool mips_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
if (interrupt_request & CPU_INTERRUPT_HARD) {
MIPSCPU *cpu = MIPS_CPU(cs);
CPUMIPSState *env = &cpu->env;
if (cpu_mips_hw_interrupts_enabled(env) &&
cpu_mips_hw_interrupts_pending(env)) {
/* Raise it */
cs->exception_index = EXCP_EXT_INTERRUPT;
env->error_code = 0;
mips_cpu_do_interrupt(cs);
return true;
}
}
return false;
}
#if !defined(CONFIG_USER_ONLY)
void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra)
{
@ -1482,20 +1344,4 @@ void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra)
}
}
}
#endif
void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env,
uint32_t exception,
int error_code,
uintptr_t pc)
{
CPUState *cs = env_cpu(env);
qemu_log_mask(CPU_LOG_INT, "%s: %d (%s) %d\n",
__func__, exception, mips_exception_name(exception),
error_code);
cs->exception_index = exception;
env->error_code = error_code;
cpu_loop_exit_restore(cs, pc);
}
#endif /* !CONFIG_USER_ONLY */

File diff suppressed because it is too large Load Diff

177
target/mips/translate.h Normal file
View File

@ -0,0 +1,177 @@
/*
* MIPS translation routines.
*
* Copyright (c) 2004-2005 Jocelyn Mayer
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef TARGET_MIPS_TRANSLATE_H
#define TARGET_MIPS_TRANSLATE_H
#include "exec/translator.h"
#define MIPS_DEBUG_DISAS 0
typedef struct DisasContext {
DisasContextBase base;
target_ulong saved_pc;
target_ulong page_start;
uint32_t opcode;
uint64_t insn_flags;
int32_t CP0_Config1;
int32_t CP0_Config2;
int32_t CP0_Config3;
int32_t CP0_Config5;
/* Routine used to access memory */
int mem_idx;
MemOp default_tcg_memop_mask;
uint32_t hflags, saved_hflags;
target_ulong btarget;
bool ulri;
int kscrexist;
bool rxi;
int ie;
bool bi;
bool bp;
uint64_t PAMask;
bool mvh;
bool eva;
bool sc;
int CP0_LLAddr_shift;
bool ps;
bool vp;
bool cmgcr;
bool mrp;
bool nan2008;
bool abs2008;
bool saar;
bool mi;
int gi;
} DisasContext;
/* MIPS major opcodes */
#define MASK_OP_MAJOR(op) (op & (0x3F << 26))
#define OPC_CP1 (0x11 << 26)
/* Coprocessor 1 (rs field) */
#define MASK_CP1(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
/* Values for the fmt field in FP instructions */
enum {
/* 0 - 15 are reserved */
FMT_S = 16, /* single fp */
FMT_D = 17, /* double fp */
FMT_E = 18, /* extended fp */
FMT_Q = 19, /* quad fp */
FMT_W = 20, /* 32-bit fixed */
FMT_L = 21, /* 64-bit fixed */
FMT_PS = 22, /* paired single fp */
/* 23 - 31 are reserved */
};
enum {
OPC_MFC1 = (0x00 << 21) | OPC_CP1,
OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
OPC_CFC1 = (0x02 << 21) | OPC_CP1,
OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
OPC_MTC1 = (0x04 << 21) | OPC_CP1,
OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
OPC_CTC1 = (0x06 << 21) | OPC_CP1,
OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
};
#define MASK_CP1_FUNC(op) (MASK_CP1(op) | (op & 0x3F))
#define MASK_BC1(op) (MASK_CP1(op) | (op & (0x3 << 16)))
enum {
OPC_BC1F = (0x00 << 16) | OPC_BC1,
OPC_BC1T = (0x01 << 16) | OPC_BC1,
OPC_BC1FL = (0x02 << 16) | OPC_BC1,
OPC_BC1TL = (0x03 << 16) | OPC_BC1,
};
enum {
OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
};
enum {
OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
};
void generate_exception(DisasContext *ctx, int excp);
void generate_exception_err(DisasContext *ctx, int excp, int err);
void generate_exception_end(DisasContext *ctx, int excp);
void gen_reserved_instruction(DisasContext *ctx);
void check_insn(DisasContext *ctx, uint64_t flags);
void check_mips_64(DisasContext *ctx);
void check_cp0_enabled(DisasContext *ctx);
void check_cp1_enabled(DisasContext *ctx);
void check_cp1_64bitmode(DisasContext *ctx);
void check_cp1_registers(DisasContext *ctx, int regs);
void check_cop1x(DisasContext *ctx);
void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset);
void gen_move_low32(TCGv ret, TCGv_i64 arg);
void gen_move_high32(TCGv ret, TCGv_i64 arg);
void gen_load_gpr(TCGv t, int reg);
void gen_store_gpr(TCGv t, int reg);
void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg);
void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg);
void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg);
void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg);
int get_fp_bit(int cc);
/*
* Address Computation and Large Constant Instructions
*/
void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1);
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);
extern TCGv cpu_gpr[32], cpu_PC;
extern TCGv_i32 fpu_fcr0, fpu_fcr31;
extern TCGv_i64 fpu_f64[32];
extern TCGv bcond;
#define LOG_DISAS(...) \
do { \
if (MIPS_DEBUG_DISAS) { \
qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
} \
} while (0)
#define MIPS_INVAL(op) \
do { \
if (MIPS_DEBUG_DISAS) { \
qemu_log_mask(CPU_LOG_TB_IN_ASM, \
TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
ctx->base.pc_next, ctx->opcode, op, \
ctx->opcode >> 26, ctx->opcode & 0x3F, \
((ctx->opcode >> 16) & 0x1F)); \
} \
} while (0)
/* MSA */
void msa_translate_init(void);
/* decodetree generated */
bool decode_isa_rel6(DisasContext *ctx, uint32_t insn);
bool decode_ase_msa(DisasContext *ctx, uint32_t insn);
#endif

View File

@ -0,0 +1,61 @@
/*
* Address Computation and Large Constant Instructions
*
* Copyright (c) 2004-2005 Jocelyn Mayer
* Copyright (c) 2006 Marius Groeger (FPU operations)
* Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
* Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
* Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
* Copyright (c) 2020 Philippe Mathieu-Daudé
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "qemu/osdep.h"
#include "tcg/tcg-op.h"
#include "translate.h"
bool gen_lsa(DisasContext *ctx, int rd, int rt, int rs, int sa)
{
TCGv t0;
TCGv 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_shli_tl(t0, t0, sa + 1);
tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
tcg_temp_free(t1);
tcg_temp_free(t0);
return true;
}
bool gen_dlsa(DisasContext *ctx, int rd, int rt, int rs, int sa)
{
TCGv t0;
TCGv t1;
check_mips_64(ctx);
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_shli_tl(t0, t0, sa + 1);
tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
tcg_temp_free(t1);
tcg_temp_free(t0);
return true;
}