mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-05 08:43:55 -06:00
Move target-* CPU file into a target/ folder
We've currently got 18 architectures in QEMU, and thus 18 target-xxx folders in the root folder of the QEMU source tree. More architectures (e.g. RISC-V, AVR) are likely to be included soon, too, so the main folder of the QEMU sources slowly gets quite overcrowded with the target-xxx folders. To disburden the main folder a little bit, let's move the target-xxx folders into a dedicated target/ folder, so that target-xxx/ simply becomes target/xxx/ instead. Acked-by: Laurent Vivier <laurent@vivier.eu> [m68k part] Acked-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de> [tricore part] Acked-by: Michael Walle <michael@walle.cc> [lm32 part] Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com> [s390x part] Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com> [s390x part] Acked-by: Eduardo Habkost <ehabkost@redhat.com> [i386 part] Acked-by: Artyom Tarasenko <atar4qemu@gmail.com> [sparc part] Acked-by: Richard Henderson <rth@twiddle.net> [alpha part] Acked-by: Max Filippov <jcmvbkbc@gmail.com> [xtensa part] Reviewed-by: David Gibson <david@gibson.dropbear.id.au> [ppc part] Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> [crisµblaze part] Acked-by: Guan Xuetao <gxt@mprc.pku.edu.cn> [unicore32 part] Signed-off-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
parent
82ecffa8c0
commit
fcf5ef2ab5
369 changed files with 78 additions and 80 deletions
4
target/mips/Makefile.objs
Normal file
4
target/mips/Makefile.objs
Normal file
|
@ -0,0 +1,4 @@
|
|||
obj-y += translate.o dsp_helper.o op_helper.o lmi_helper.o helper.o cpu.o
|
||||
obj-y += gdbstub.o msa_helper.o mips-semi.o
|
||||
obj-$(CONFIG_SOFTMMU) += machine.o
|
||||
obj-$(CONFIG_KVM) += kvm.o
|
51
target/mips/TODO
Normal file
51
target/mips/TODO
Normal file
|
@ -0,0 +1,51 @@
|
|||
Unsolved issues/bugs in the mips/mipsel backend
|
||||
-----------------------------------------------
|
||||
|
||||
General
|
||||
-------
|
||||
- Unimplemented ASEs:
|
||||
- MDMX
|
||||
- SmartMIPS
|
||||
- microMIPS DSP r1 & r2 encodings
|
||||
- MT ASE only partially implemented and not functional
|
||||
- Shadow register support only partially implemented,
|
||||
lacks set switching on interrupt/exception.
|
||||
- 34K ITC not implemented.
|
||||
- A general lack of documentation, especially for technical internals.
|
||||
Existing documentation is x86-centric.
|
||||
- Reverse endianness bit not implemented
|
||||
- The TLB emulation is very inefficient:
|
||||
QEMU's softmmu implements a x86-style MMU, with separate entries
|
||||
for read/write/execute, a TLB index which is just a modulo of the
|
||||
virtual address, and a set of TLBs for each user/kernel/supervisor
|
||||
MMU mode.
|
||||
MIPS has a single entry for read/write/execute and only one MMU mode.
|
||||
But it is fully associative with randomized entry indices, and uses
|
||||
up to 256 ASID tags as additional matching criterion (which roughly
|
||||
equates to 256 MMU modes). It also has a global flag which causes
|
||||
entries to match regardless of ASID.
|
||||
To cope with these differences, QEMU currently flushes the TLB at
|
||||
each ASID change. Using the MMU modes to implement ASIDs hinges on
|
||||
implementing the global bit efficiently.
|
||||
- save/restore of the CPU state is not implemented (see machine.c).
|
||||
|
||||
MIPS64
|
||||
------
|
||||
- Userland emulation (both n32 and n64) not functional.
|
||||
|
||||
"Generic" 4Kc system emulation
|
||||
------------------------------
|
||||
- Doesn't correspond to any real hardware. Should be removed some day,
|
||||
U-Boot is the last remaining user.
|
||||
|
||||
PICA 61 system emulation
|
||||
------------------------
|
||||
- No framebuffer support yet.
|
||||
|
||||
MALTA system emulation
|
||||
----------------------
|
||||
- We fake firmware support instead of doing the real thing
|
||||
- Real firmware (YAMON) falls over when trying to init RAM, presumably
|
||||
due to lacking system controller emulation.
|
||||
- Bonito system controller not implemented
|
||||
- MSC1 system controller not implemented
|
56
target/mips/cpu-qom.h
Normal file
56
target/mips/cpu-qom.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* QEMU MIPS CPU
|
||||
*
|
||||
* Copyright (c) 2012 SUSE LINUX Products GmbH
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <http://www.gnu.org/licenses/lgpl-2.1.html>
|
||||
*/
|
||||
#ifndef QEMU_MIPS_CPU_QOM_H
|
||||
#define QEMU_MIPS_CPU_QOM_H
|
||||
|
||||
#include "qom/cpu.h"
|
||||
|
||||
#ifdef TARGET_MIPS64
|
||||
#define TYPE_MIPS_CPU "mips64-cpu"
|
||||
#else
|
||||
#define TYPE_MIPS_CPU "mips-cpu"
|
||||
#endif
|
||||
|
||||
#define MIPS_CPU_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(MIPSCPUClass, (klass), TYPE_MIPS_CPU)
|
||||
#define MIPS_CPU(obj) \
|
||||
OBJECT_CHECK(MIPSCPU, (obj), TYPE_MIPS_CPU)
|
||||
#define MIPS_CPU_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(MIPSCPUClass, (obj), TYPE_MIPS_CPU)
|
||||
|
||||
/**
|
||||
* MIPSCPUClass:
|
||||
* @parent_realize: The parent class' realize handler.
|
||||
* @parent_reset: The parent class' reset handler.
|
||||
*
|
||||
* A MIPS CPU model.
|
||||
*/
|
||||
typedef struct MIPSCPUClass {
|
||||
/*< private >*/
|
||||
CPUClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
DeviceRealize parent_realize;
|
||||
void (*parent_reset)(CPUState *cpu);
|
||||
} MIPSCPUClass;
|
||||
|
||||
typedef struct MIPSCPU MIPSCPU;
|
||||
|
||||
#endif
|
203
target/mips/cpu.c
Normal file
203
target/mips/cpu.c
Normal file
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* QEMU MIPS CPU
|
||||
*
|
||||
* Copyright (c) 2012 SUSE LINUX Products GmbH
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <http://www.gnu.org/licenses/lgpl-2.1.html>
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "cpu.h"
|
||||
#include "kvm_mips.h"
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
|
||||
static void mips_cpu_set_pc(CPUState *cs, vaddr value)
|
||||
{
|
||||
MIPSCPU *cpu = MIPS_CPU(cs);
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
|
||||
env->active_tc.PC = value & ~(target_ulong)1;
|
||||
if (value & 1) {
|
||||
env->hflags |= MIPS_HFLAG_M16;
|
||||
} else {
|
||||
env->hflags &= ~(MIPS_HFLAG_M16);
|
||||
}
|
||||
}
|
||||
|
||||
static void mips_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
|
||||
{
|
||||
MIPSCPU *cpu = MIPS_CPU(cs);
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
|
||||
env->active_tc.PC = tb->pc;
|
||||
env->hflags &= ~MIPS_HFLAG_BMASK;
|
||||
env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
|
||||
}
|
||||
|
||||
static bool mips_cpu_has_work(CPUState *cs)
|
||||
{
|
||||
MIPSCPU *cpu = MIPS_CPU(cs);
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
bool has_work = false;
|
||||
|
||||
/* Prior to MIPS Release 6 it is implementation dependent if non-enabled
|
||||
interrupts wake-up the CPU, however most of the implementations only
|
||||
check for interrupts that can be taken. */
|
||||
if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
|
||||
cpu_mips_hw_interrupts_pending(env)) {
|
||||
if (cpu_mips_hw_interrupts_enabled(env) ||
|
||||
(env->insn_flags & ISA_MIPS32R6)) {
|
||||
has_work = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* MIPS-MT has the ability to halt the CPU. */
|
||||
if (env->CP0_Config3 & (1 << CP0C3_MT)) {
|
||||
/* The QEMU model will issue an _WAKE request whenever the CPUs
|
||||
should be woken up. */
|
||||
if (cs->interrupt_request & CPU_INTERRUPT_WAKE) {
|
||||
has_work = true;
|
||||
}
|
||||
|
||||
if (!mips_vpe_active(env)) {
|
||||
has_work = false;
|
||||
}
|
||||
}
|
||||
/* MIPS Release 6 has the ability to halt the CPU. */
|
||||
if (env->CP0_Config5 & (1 << CP0C5_VP)) {
|
||||
if (cs->interrupt_request & CPU_INTERRUPT_WAKE) {
|
||||
has_work = true;
|
||||
}
|
||||
if (!mips_vp_active(env)) {
|
||||
has_work = false;
|
||||
}
|
||||
}
|
||||
return has_work;
|
||||
}
|
||||
|
||||
/* CPUClass::reset() */
|
||||
static void mips_cpu_reset(CPUState *s)
|
||||
{
|
||||
MIPSCPU *cpu = MIPS_CPU(s);
|
||||
MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu);
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
|
||||
mcc->parent_reset(s);
|
||||
|
||||
memset(env, 0, offsetof(CPUMIPSState, mvp));
|
||||
tlb_flush(s, 1);
|
||||
|
||||
cpu_state_reset(env);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (kvm_enabled()) {
|
||||
kvm_mips_reset_vcpu(cpu);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void mips_cpu_disas_set_info(CPUState *s, disassemble_info *info) {
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
info->print_insn = print_insn_big_mips;
|
||||
#else
|
||||
info->print_insn = print_insn_little_mips;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void mips_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
{
|
||||
CPUState *cs = CPU(dev);
|
||||
MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(dev);
|
||||
Error *local_err = NULL;
|
||||
|
||||
cpu_exec_realizefn(cs, &local_err);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
cpu_reset(cs);
|
||||
qemu_init_vcpu(cs);
|
||||
|
||||
mcc->parent_realize(dev, errp);
|
||||
}
|
||||
|
||||
static void mips_cpu_initfn(Object *obj)
|
||||
{
|
||||
CPUState *cs = CPU(obj);
|
||||
MIPSCPU *cpu = MIPS_CPU(obj);
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
|
||||
cs->env_ptr = env;
|
||||
|
||||
if (tcg_enabled()) {
|
||||
mips_tcg_init();
|
||||
}
|
||||
}
|
||||
|
||||
static void mips_cpu_class_init(ObjectClass *c, void *data)
|
||||
{
|
||||
MIPSCPUClass *mcc = MIPS_CPU_CLASS(c);
|
||||
CPUClass *cc = CPU_CLASS(c);
|
||||
DeviceClass *dc = DEVICE_CLASS(c);
|
||||
|
||||
mcc->parent_realize = dc->realize;
|
||||
dc->realize = mips_cpu_realizefn;
|
||||
|
||||
mcc->parent_reset = cc->reset;
|
||||
cc->reset = mips_cpu_reset;
|
||||
|
||||
cc->has_work = mips_cpu_has_work;
|
||||
cc->do_interrupt = mips_cpu_do_interrupt;
|
||||
cc->cpu_exec_interrupt = mips_cpu_exec_interrupt;
|
||||
cc->dump_state = mips_cpu_dump_state;
|
||||
cc->set_pc = mips_cpu_set_pc;
|
||||
cc->synchronize_from_tb = mips_cpu_synchronize_from_tb;
|
||||
cc->gdb_read_register = mips_cpu_gdb_read_register;
|
||||
cc->gdb_write_register = mips_cpu_gdb_write_register;
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
cc->handle_mmu_fault = mips_cpu_handle_mmu_fault;
|
||||
#else
|
||||
cc->do_unassigned_access = mips_cpu_unassigned_access;
|
||||
cc->do_unaligned_access = mips_cpu_do_unaligned_access;
|
||||
cc->get_phys_page_debug = mips_cpu_get_phys_page_debug;
|
||||
cc->vmsd = &vmstate_mips_cpu;
|
||||
#endif
|
||||
cc->disas_set_info = mips_cpu_disas_set_info;
|
||||
|
||||
cc->gdb_num_core_regs = 73;
|
||||
cc->gdb_stop_before_watchpoint = true;
|
||||
}
|
||||
|
||||
static const TypeInfo mips_cpu_type_info = {
|
||||
.name = TYPE_MIPS_CPU,
|
||||
.parent = TYPE_CPU,
|
||||
.instance_size = sizeof(MIPSCPU),
|
||||
.instance_init = mips_cpu_initfn,
|
||||
.abstract = false,
|
||||
.class_size = sizeof(MIPSCPUClass),
|
||||
.class_init = mips_cpu_class_init,
|
||||
};
|
||||
|
||||
static void mips_cpu_register_types(void)
|
||||
{
|
||||
type_register_static(&mips_cpu_type_info);
|
||||
}
|
||||
|
||||
type_init(mips_cpu_register_types)
|
1069
target/mips/cpu.h
Normal file
1069
target/mips/cpu.h
Normal file
File diff suppressed because it is too large
Load diff
3762
target/mips/dsp_helper.c
Normal file
3762
target/mips/dsp_helper.c
Normal file
File diff suppressed because it is too large
Load diff
149
target/mips/gdbstub.c
Normal file
149
target/mips/gdbstub.c
Normal file
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* MIPS gdb server stub
|
||||
*
|
||||
* Copyright (c) 2003-2005 Fabrice Bellard
|
||||
* Copyright (c) 2013 SUSE LINUX Products GmbH
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/gdbstub.h"
|
||||
|
||||
int mips_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
{
|
||||
MIPSCPU *cpu = MIPS_CPU(cs);
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
|
||||
if (n < 32) {
|
||||
return gdb_get_regl(mem_buf, env->active_tc.gpr[n]);
|
||||
}
|
||||
if (env->CP0_Config1 & (1 << CP0C1_FP) && n >= 38 && n < 72) {
|
||||
switch (n) {
|
||||
case 70:
|
||||
return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr31);
|
||||
case 71:
|
||||
return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr0);
|
||||
default:
|
||||
if (env->CP0_Status & (1 << CP0St_FR)) {
|
||||
return gdb_get_regl(mem_buf,
|
||||
env->active_fpu.fpr[n - 38].d);
|
||||
} else {
|
||||
return gdb_get_regl(mem_buf,
|
||||
env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX]);
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (n) {
|
||||
case 32:
|
||||
return gdb_get_regl(mem_buf, (int32_t)env->CP0_Status);
|
||||
case 33:
|
||||
return gdb_get_regl(mem_buf, env->active_tc.LO[0]);
|
||||
case 34:
|
||||
return gdb_get_regl(mem_buf, env->active_tc.HI[0]);
|
||||
case 35:
|
||||
return gdb_get_regl(mem_buf, env->CP0_BadVAddr);
|
||||
case 36:
|
||||
return gdb_get_regl(mem_buf, (int32_t)env->CP0_Cause);
|
||||
case 37:
|
||||
return gdb_get_regl(mem_buf, env->active_tc.PC |
|
||||
!!(env->hflags & MIPS_HFLAG_M16));
|
||||
case 72:
|
||||
return gdb_get_regl(mem_buf, 0); /* fp */
|
||||
case 89:
|
||||
return gdb_get_regl(mem_buf, (int32_t)env->CP0_PRid);
|
||||
default:
|
||||
if (n > 89) {
|
||||
return 0;
|
||||
}
|
||||
/* 16 embedded regs. */
|
||||
return gdb_get_regl(mem_buf, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mips_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
{
|
||||
MIPSCPU *cpu = MIPS_CPU(cs);
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
target_ulong tmp;
|
||||
|
||||
tmp = ldtul_p(mem_buf);
|
||||
|
||||
if (n < 32) {
|
||||
env->active_tc.gpr[n] = tmp;
|
||||
return sizeof(target_ulong);
|
||||
}
|
||||
if (env->CP0_Config1 & (1 << CP0C1_FP) && n >= 38 && n < 72) {
|
||||
switch (n) {
|
||||
case 70:
|
||||
env->active_fpu.fcr31 = (tmp & env->active_fpu.fcr31_rw_bitmask) |
|
||||
(env->active_fpu.fcr31 & ~(env->active_fpu.fcr31_rw_bitmask));
|
||||
restore_fp_status(env);
|
||||
break;
|
||||
case 71:
|
||||
/* FIR is read-only. Ignore writes. */
|
||||
break;
|
||||
default:
|
||||
if (env->CP0_Status & (1 << CP0St_FR)) {
|
||||
env->active_fpu.fpr[n - 38].d = tmp;
|
||||
} else {
|
||||
env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX] = tmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return sizeof(target_ulong);
|
||||
}
|
||||
switch (n) {
|
||||
case 32:
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
cpu_mips_store_status(env, tmp);
|
||||
#endif
|
||||
break;
|
||||
case 33:
|
||||
env->active_tc.LO[0] = tmp;
|
||||
break;
|
||||
case 34:
|
||||
env->active_tc.HI[0] = tmp;
|
||||
break;
|
||||
case 35:
|
||||
env->CP0_BadVAddr = tmp;
|
||||
break;
|
||||
case 36:
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
cpu_mips_store_cause(env, tmp);
|
||||
#endif
|
||||
break;
|
||||
case 37:
|
||||
env->active_tc.PC = tmp & ~(target_ulong)1;
|
||||
if (tmp & 1) {
|
||||
env->hflags |= MIPS_HFLAG_M16;
|
||||
} else {
|
||||
env->hflags &= ~(MIPS_HFLAG_M16);
|
||||
}
|
||||
break;
|
||||
case 72: /* fp, ignored */
|
||||
break;
|
||||
default:
|
||||
if (n > 89) {
|
||||
return 0;
|
||||
}
|
||||
/* Other registers are readonly. Ignore writes. */
|
||||
break;
|
||||
}
|
||||
|
||||
return sizeof(target_ulong);
|
||||
}
|
969
target/mips/helper.c
Normal file
969
target/mips/helper.c
Normal file
|
@ -0,0 +1,969 @@
|
|||
/*
|
||||
* MIPS emulation helpers for qemu.
|
||||
*
|
||||
* Copyright (c) 2004-2005 Jocelyn Mayer
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include "cpu.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "exec/log.h"
|
||||
|
||||
enum {
|
||||
TLBRET_XI = -6,
|
||||
TLBRET_RI = -5,
|
||||
TLBRET_DIRTY = -4,
|
||||
TLBRET_INVALID = -3,
|
||||
TLBRET_NOMATCH = -2,
|
||||
TLBRET_BADADDR = -1,
|
||||
TLBRET_MATCH = 0
|
||||
};
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
|
||||
/* no MMU emulation */
|
||||
int no_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
|
||||
target_ulong address, int rw, int access_type)
|
||||
{
|
||||
*physical = address;
|
||||
*prot = PAGE_READ | PAGE_WRITE;
|
||||
return TLBRET_MATCH;
|
||||
}
|
||||
|
||||
/* fixed mapping MMU emulation */
|
||||
int fixed_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
|
||||
target_ulong address, int rw, int access_type)
|
||||
{
|
||||
if (address <= (int32_t)0x7FFFFFFFUL) {
|
||||
if (!(env->CP0_Status & (1 << CP0St_ERL)))
|
||||
*physical = address + 0x40000000UL;
|
||||
else
|
||||
*physical = address;
|
||||
} else if (address <= (int32_t)0xBFFFFFFFUL)
|
||||
*physical = address & 0x1FFFFFFF;
|
||||
else
|
||||
*physical = address;
|
||||
|
||||
*prot = PAGE_READ | PAGE_WRITE;
|
||||
return TLBRET_MATCH;
|
||||
}
|
||||
|
||||
/* MIPS32/MIPS64 R4000-style MMU emulation */
|
||||
int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
|
||||
target_ulong address, int rw, int access_type)
|
||||
{
|
||||
uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < env->tlb->tlb_in_use; i++) {
|
||||
r4k_tlb_t *tlb = &env->tlb->mmu.r4k.tlb[i];
|
||||
/* 1k pages are not supported. */
|
||||
target_ulong mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
|
||||
target_ulong tag = address & ~mask;
|
||||
target_ulong VPN = tlb->VPN & ~mask;
|
||||
#if defined(TARGET_MIPS64)
|
||||
tag &= env->SEGMask;
|
||||
#endif
|
||||
|
||||
/* Check ASID, virtual page number & size */
|
||||
if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag && !tlb->EHINV) {
|
||||
/* TLB match */
|
||||
int n = !!(address & mask & ~(mask >> 1));
|
||||
/* Check access rights */
|
||||
if (!(n ? tlb->V1 : tlb->V0)) {
|
||||
return TLBRET_INVALID;
|
||||
}
|
||||
if (rw == MMU_INST_FETCH && (n ? tlb->XI1 : tlb->XI0)) {
|
||||
return TLBRET_XI;
|
||||
}
|
||||
if (rw == MMU_DATA_LOAD && (n ? tlb->RI1 : tlb->RI0)) {
|
||||
return TLBRET_RI;
|
||||
}
|
||||
if (rw != MMU_DATA_STORE || (n ? tlb->D1 : tlb->D0)) {
|
||||
*physical = tlb->PFN[n] | (address & (mask >> 1));
|
||||
*prot = PAGE_READ;
|
||||
if (n ? tlb->D1 : tlb->D0)
|
||||
*prot |= PAGE_WRITE;
|
||||
return TLBRET_MATCH;
|
||||
}
|
||||
return TLBRET_DIRTY;
|
||||
}
|
||||
}
|
||||
return TLBRET_NOMATCH;
|
||||
}
|
||||
|
||||
static int get_physical_address (CPUMIPSState *env, hwaddr *physical,
|
||||
int *prot, target_ulong real_address,
|
||||
int rw, int access_type)
|
||||
{
|
||||
/* User mode can only access useg/xuseg */
|
||||
int user_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM;
|
||||
int supervisor_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_SM;
|
||||
int kernel_mode = !user_mode && !supervisor_mode;
|
||||
#if defined(TARGET_MIPS64)
|
||||
int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
|
||||
int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;
|
||||
int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0;
|
||||
#endif
|
||||
int ret = TLBRET_MATCH;
|
||||
/* effective address (modified for KVM T&E kernel segments) */
|
||||
target_ulong address = real_address;
|
||||
|
||||
#define USEG_LIMIT 0x7FFFFFFFUL
|
||||
#define KSEG0_BASE 0x80000000UL
|
||||
#define KSEG1_BASE 0xA0000000UL
|
||||
#define KSEG2_BASE 0xC0000000UL
|
||||
#define KSEG3_BASE 0xE0000000UL
|
||||
|
||||
#define KVM_KSEG0_BASE 0x40000000UL
|
||||
#define KVM_KSEG2_BASE 0x60000000UL
|
||||
|
||||
if (kvm_enabled()) {
|
||||
/* KVM T&E adds guest kernel segments in useg */
|
||||
if (real_address >= KVM_KSEG0_BASE) {
|
||||
if (real_address < KVM_KSEG2_BASE) {
|
||||
/* kseg0 */
|
||||
address += KSEG0_BASE - KVM_KSEG0_BASE;
|
||||
} else if (real_address <= USEG_LIMIT) {
|
||||
/* kseg2/3 */
|
||||
address += KSEG2_BASE - KVM_KSEG2_BASE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (address <= USEG_LIMIT) {
|
||||
/* useg */
|
||||
if (env->CP0_Status & (1 << CP0St_ERL)) {
|
||||
*physical = address & 0xFFFFFFFF;
|
||||
*prot = PAGE_READ | PAGE_WRITE;
|
||||
} else {
|
||||
ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type);
|
||||
}
|
||||
#if defined(TARGET_MIPS64)
|
||||
} else if (address < 0x4000000000000000ULL) {
|
||||
/* xuseg */
|
||||
if (UX && address <= (0x3FFFFFFFFFFFFFFFULL & env->SEGMask)) {
|
||||
ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type);
|
||||
} else {
|
||||
ret = TLBRET_BADADDR;
|
||||
}
|
||||
} else if (address < 0x8000000000000000ULL) {
|
||||
/* xsseg */
|
||||
if ((supervisor_mode || kernel_mode) &&
|
||||
SX && address <= (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) {
|
||||
ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type);
|
||||
} else {
|
||||
ret = TLBRET_BADADDR;
|
||||
}
|
||||
} else if (address < 0xC000000000000000ULL) {
|
||||
/* xkphys */
|
||||
if (kernel_mode && KX &&
|
||||
(address & 0x07FFFFFFFFFFFFFFULL) <= env->PAMask) {
|
||||
*physical = address & env->PAMask;
|
||||
*prot = PAGE_READ | PAGE_WRITE;
|
||||
} else {
|
||||
ret = TLBRET_BADADDR;
|
||||
}
|
||||
} else if (address < 0xFFFFFFFF80000000ULL) {
|
||||
/* xkseg */
|
||||
if (kernel_mode && KX &&
|
||||
address <= (0xFFFFFFFF7FFFFFFFULL & env->SEGMask)) {
|
||||
ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type);
|
||||
} else {
|
||||
ret = TLBRET_BADADDR;
|
||||
}
|
||||
#endif
|
||||
} else if (address < (int32_t)KSEG1_BASE) {
|
||||
/* kseg0 */
|
||||
if (kernel_mode) {
|
||||
*physical = address - (int32_t)KSEG0_BASE;
|
||||
*prot = PAGE_READ | PAGE_WRITE;
|
||||
} else {
|
||||
ret = TLBRET_BADADDR;
|
||||
}
|
||||
} else if (address < (int32_t)KSEG2_BASE) {
|
||||
/* kseg1 */
|
||||
if (kernel_mode) {
|
||||
*physical = address - (int32_t)KSEG1_BASE;
|
||||
*prot = PAGE_READ | PAGE_WRITE;
|
||||
} else {
|
||||
ret = TLBRET_BADADDR;
|
||||
}
|
||||
} else if (address < (int32_t)KSEG3_BASE) {
|
||||
/* sseg (kseg2) */
|
||||
if (supervisor_mode || kernel_mode) {
|
||||
ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type);
|
||||
} else {
|
||||
ret = TLBRET_BADADDR;
|
||||
}
|
||||
} else {
|
||||
/* kseg3 */
|
||||
/* XXX: debug segment is not emulated */
|
||||
if (kernel_mode) {
|
||||
ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type);
|
||||
} else {
|
||||
ret = TLBRET_BADADDR;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cpu_mips_tlb_flush(CPUMIPSState *env, int flush_global)
|
||||
{
|
||||
MIPSCPU *cpu = mips_env_get_cpu(env);
|
||||
|
||||
/* Flush qemu's TLB and discard all shadowed entries. */
|
||||
tlb_flush(CPU(cpu), flush_global);
|
||||
env->tlb->tlb_in_use = env->tlb->nb_tlb;
|
||||
}
|
||||
|
||||
/* Called for updates to CP0_Status. */
|
||||
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 */
|
||||
cpu_mips_tlb_flush(env, 1);
|
||||
}
|
||||
#endif
|
||||
if (env->CP0_Config3 & (1 << CP0C3_MT)) {
|
||||
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
|
||||
|
||||
static void raise_mmu_exception(CPUMIPSState *env, target_ulong address,
|
||||
int rw, int tlb_error)
|
||||
{
|
||||
CPUState *cs = CPU(mips_env_get_cpu(env));
|
||||
int exception = 0, error_code = 0;
|
||||
|
||||
if (rw == MMU_INST_FETCH) {
|
||||
error_code |= EXCP_INST_NOTAVAIL;
|
||||
}
|
||||
|
||||
switch (tlb_error) {
|
||||
default:
|
||||
case TLBRET_BADADDR:
|
||||
/* Reference to kernel address from user mode or supervisor mode */
|
||||
/* Reference to supervisor address from user mode */
|
||||
if (rw == MMU_DATA_STORE) {
|
||||
exception = EXCP_AdES;
|
||||
} else {
|
||||
exception = EXCP_AdEL;
|
||||
}
|
||||
break;
|
||||
case TLBRET_NOMATCH:
|
||||
/* No TLB match for a mapped address */
|
||||
if (rw == MMU_DATA_STORE) {
|
||||
exception = EXCP_TLBS;
|
||||
} else {
|
||||
exception = EXCP_TLBL;
|
||||
}
|
||||
error_code |= EXCP_TLB_NOMATCH;
|
||||
break;
|
||||
case TLBRET_INVALID:
|
||||
/* TLB match with no valid bit */
|
||||
if (rw == MMU_DATA_STORE) {
|
||||
exception = EXCP_TLBS;
|
||||
} else {
|
||||
exception = EXCP_TLBL;
|
||||
}
|
||||
break;
|
||||
case TLBRET_DIRTY:
|
||||
/* TLB match but 'D' bit is cleared */
|
||||
exception = EXCP_LTLBL;
|
||||
break;
|
||||
case TLBRET_XI:
|
||||
/* Execute-Inhibit Exception */
|
||||
if (env->CP0_PageGrain & (1 << CP0PG_IEC)) {
|
||||
exception = EXCP_TLBXI;
|
||||
} else {
|
||||
exception = EXCP_TLBL;
|
||||
}
|
||||
break;
|
||||
case TLBRET_RI:
|
||||
/* Read-Inhibit Exception */
|
||||
if (env->CP0_PageGrain & (1 << CP0PG_IEC)) {
|
||||
exception = EXCP_TLBRI;
|
||||
} else {
|
||||
exception = EXCP_TLBL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Raise exception */
|
||||
env->CP0_BadVAddr = address;
|
||||
env->CP0_Context = (env->CP0_Context & ~0x007fffff) |
|
||||
((address >> 9) & 0x007ffff0);
|
||||
env->CP0_EntryHi = (env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask) |
|
||||
(env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) |
|
||||
(address & (TARGET_PAGE_MASK << 1));
|
||||
#if defined(TARGET_MIPS64)
|
||||
env->CP0_EntryHi &= env->SEGMask;
|
||||
env->CP0_XContext =
|
||||
/* PTEBase */ (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 7))) |
|
||||
/* R */ (extract64(address, 62, 2) << (env->SEGBITS - 9)) |
|
||||
/* BadVPN2 */ (extract64(address, 13, env->SEGBITS - 13) << 4);
|
||||
#endif
|
||||
cs->exception_index = exception;
|
||||
env->error_code = error_code;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
hwaddr mips_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
|
||||
{
|
||||
MIPSCPU *cpu = MIPS_CPU(cs);
|
||||
hwaddr phys_addr;
|
||||
int prot;
|
||||
|
||||
if (get_physical_address(&cpu->env, &phys_addr, &prot, addr, 0,
|
||||
ACCESS_INT) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return phys_addr;
|
||||
}
|
||||
#endif
|
||||
|
||||
int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
|
||||
int mmu_idx)
|
||||
{
|
||||
MIPSCPU *cpu = MIPS_CPU(cs);
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
hwaddr physical;
|
||||
int prot;
|
||||
int access_type;
|
||||
#endif
|
||||
int ret = 0;
|
||||
|
||||
#if 0
|
||||
log_cpu_state(cs, 0);
|
||||
#endif
|
||||
qemu_log_mask(CPU_LOG_MMU,
|
||||
"%s pc " TARGET_FMT_lx " ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
|
||||
__func__, env->active_tc.PC, address, rw, mmu_idx);
|
||||
|
||||
/* data access */
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
/* XXX: put correct access by using cpu_restore_state()
|
||||
correctly */
|
||||
access_type = ACCESS_INT;
|
||||
ret = get_physical_address(env, &physical, &prot,
|
||||
address, rw, access_type);
|
||||
qemu_log_mask(CPU_LOG_MMU,
|
||||
"%s address=%" VADDR_PRIx " ret %d physical " TARGET_FMT_plx
|
||||
" prot %d\n",
|
||||
__func__, address, ret, physical, prot);
|
||||
if (ret == TLBRET_MATCH) {
|
||||
tlb_set_page(cs, address & TARGET_PAGE_MASK,
|
||||
physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
|
||||
mmu_idx, TARGET_PAGE_SIZE);
|
||||
ret = 0;
|
||||
} else if (ret < 0)
|
||||
#endif
|
||||
{
|
||||
raise_mmu_exception(env, address, rw, ret);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int rw)
|
||||
{
|
||||
hwaddr physical;
|
||||
int prot;
|
||||
int access_type;
|
||||
int ret = 0;
|
||||
|
||||
/* data access */
|
||||
access_type = ACCESS_INT;
|
||||
ret = get_physical_address(env, &physical, &prot,
|
||||
address, rw, access_type);
|
||||
if (ret != TLBRET_MATCH) {
|
||||
raise_mmu_exception(env, address, rw, ret);
|
||||
return -1LL;
|
||||
} else {
|
||||
return physical;
|
||||
}
|
||||
}
|
||||
|
||||
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",
|
||||
};
|
||||
#endif
|
||||
|
||||
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. */
|
||||
env->hflags &= ~(MIPS_HFLAG_M16);
|
||||
/* ...except that microMIPS lets you choose. */
|
||||
if (env->insn_flags & ASE_MICROMIPS) {
|
||||
env->hflags |= (!!(env->CP0_Config3
|
||||
& (1 << CP0C3_ISA_ON_EXC))
|
||||
<< MIPS_HFLAG_M16_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void set_badinstr_registers(CPUMIPSState *env)
|
||||
{
|
||||
if (env->hflags & MIPS_HFLAG_M16) {
|
||||
/* TODO: add BadInstr support for microMIPS */
|
||||
return;
|
||||
}
|
||||
if (env->CP0_Config3 & (1 << CP0C3_BI)) {
|
||||
env->CP0_BadInstr = cpu_ldl_code(env, env->active_tc.PC);
|
||||
}
|
||||
if ((env->CP0_Config3 & (1 << CP0C3_BP)) &&
|
||||
(env->hflags & MIPS_HFLAG_BMASK)) {
|
||||
env->CP0_BadInstrP = cpu_ldl_code(env, env->active_tc.PC - 4);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void mips_cpu_do_interrupt(CPUState *cs)
|
||||
{
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
MIPSCPU *cpu = MIPS_CPU(cs);
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
bool update_badinstr = 0;
|
||||
target_ulong offset;
|
||||
int cause = -1;
|
||||
const char *name;
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_INT)
|
||||
&& cs->exception_index != EXCP_EXT_INTERRUPT) {
|
||||
if (cs->exception_index < 0 || cs->exception_index > EXCP_LAST) {
|
||||
name = "unknown";
|
||||
} else {
|
||||
name = excp_names[cs->exception_index];
|
||||
}
|
||||
|
||||
qemu_log("%s enter: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx
|
||||
" %s exception\n",
|
||||
__func__, env->active_tc.PC, env->CP0_EPC, name);
|
||||
}
|
||||
if (cs->exception_index == EXCP_EXT_INTERRUPT &&
|
||||
(env->hflags & MIPS_HFLAG_DM)) {
|
||||
cs->exception_index = EXCP_DINT;
|
||||
}
|
||||
offset = 0x180;
|
||||
switch (cs->exception_index) {
|
||||
case EXCP_DSS:
|
||||
env->CP0_Debug |= 1 << CP0DB_DSS;
|
||||
/* Debug single step cannot be raised inside a delay slot and
|
||||
resume will always occur on the next instruction
|
||||
(but we assume the pc has always been updated during
|
||||
code translation). */
|
||||
env->CP0_DEPC = env->active_tc.PC | !!(env->hflags & MIPS_HFLAG_M16);
|
||||
goto enter_debug_mode;
|
||||
case EXCP_DINT:
|
||||
env->CP0_Debug |= 1 << CP0DB_DINT;
|
||||
goto set_DEPC;
|
||||
case EXCP_DIB:
|
||||
env->CP0_Debug |= 1 << CP0DB_DIB;
|
||||
goto set_DEPC;
|
||||
case EXCP_DBp:
|
||||
env->CP0_Debug |= 1 << CP0DB_DBp;
|
||||
goto set_DEPC;
|
||||
case EXCP_DDBS:
|
||||
env->CP0_Debug |= 1 << CP0DB_DDBS;
|
||||
goto set_DEPC;
|
||||
case EXCP_DDBL:
|
||||
env->CP0_Debug |= 1 << CP0DB_DDBL;
|
||||
set_DEPC:
|
||||
env->CP0_DEPC = exception_resume_pc(env);
|
||||
env->hflags &= ~MIPS_HFLAG_BMASK;
|
||||
enter_debug_mode:
|
||||
if (env->insn_flags & ISA_MIPS3) {
|
||||
env->hflags |= MIPS_HFLAG_64;
|
||||
if (!(env->insn_flags & ISA_MIPS64R6) ||
|
||||
env->CP0_Status & (1 << CP0St_KX)) {
|
||||
env->hflags &= ~MIPS_HFLAG_AWRAP;
|
||||
}
|
||||
}
|
||||
env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_CP0;
|
||||
env->hflags &= ~(MIPS_HFLAG_KSU);
|
||||
/* EJTAG probe trap enable is not implemented... */
|
||||
if (!(env->CP0_Status & (1 << CP0St_EXL)))
|
||||
env->CP0_Cause &= ~(1U << CP0Ca_BD);
|
||||
env->active_tc.PC = env->exception_base + 0x480;
|
||||
set_hflags_for_handler(env);
|
||||
break;
|
||||
case EXCP_RESET:
|
||||
cpu_reset(CPU(cpu));
|
||||
break;
|
||||
case EXCP_SRESET:
|
||||
env->CP0_Status |= (1 << CP0St_SR);
|
||||
memset(env->CP0_WatchLo, 0, sizeof(env->CP0_WatchLo));
|
||||
goto set_error_EPC;
|
||||
case EXCP_NMI:
|
||||
env->CP0_Status |= (1 << CP0St_NMI);
|
||||
set_error_EPC:
|
||||
env->CP0_ErrorEPC = exception_resume_pc(env);
|
||||
env->hflags &= ~MIPS_HFLAG_BMASK;
|
||||
env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
|
||||
if (env->insn_flags & ISA_MIPS3) {
|
||||
env->hflags |= MIPS_HFLAG_64;
|
||||
if (!(env->insn_flags & ISA_MIPS64R6) ||
|
||||
env->CP0_Status & (1 << CP0St_KX)) {
|
||||
env->hflags &= ~MIPS_HFLAG_AWRAP;
|
||||
}
|
||||
}
|
||||
env->hflags |= MIPS_HFLAG_CP0;
|
||||
env->hflags &= ~(MIPS_HFLAG_KSU);
|
||||
if (!(env->CP0_Status & (1 << CP0St_EXL)))
|
||||
env->CP0_Cause &= ~(1U << CP0Ca_BD);
|
||||
env->active_tc.PC = env->exception_base;
|
||||
set_hflags_for_handler(env);
|
||||
break;
|
||||
case EXCP_EXT_INTERRUPT:
|
||||
cause = 0;
|
||||
if (env->CP0_Cause & (1 << CP0Ca_IV)) {
|
||||
uint32_t spacing = (env->CP0_IntCtl >> CP0IntCtl_VS) & 0x1f;
|
||||
|
||||
if ((env->CP0_Status & (1 << CP0St_BEV)) || spacing == 0) {
|
||||
offset = 0x200;
|
||||
} else {
|
||||
uint32_t vector = 0;
|
||||
uint32_t pending = (env->CP0_Cause & CP0Ca_IP_mask) >> CP0Ca_IP;
|
||||
|
||||
if (env->CP0_Config3 & (1 << CP0C3_VEIC)) {
|
||||
/* For VEIC mode, the external interrupt controller feeds
|
||||
* the vector through the CP0Cause IP lines. */
|
||||
vector = pending;
|
||||
} else {
|
||||
/* Vectored Interrupts
|
||||
* Mask with Status.IM7-IM0 to get enabled interrupts. */
|
||||
pending &= (env->CP0_Status >> CP0St_IM) & 0xff;
|
||||
/* Find the highest-priority interrupt. */
|
||||
while (pending >>= 1) {
|
||||
vector++;
|
||||
}
|
||||
}
|
||||
offset = 0x200 + (vector * (spacing << 5));
|
||||
}
|
||||
}
|
||||
goto set_EPC;
|
||||
case EXCP_LTLBL:
|
||||
cause = 1;
|
||||
update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL);
|
||||
goto set_EPC;
|
||||
case EXCP_TLBL:
|
||||
cause = 2;
|
||||
update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL);
|
||||
if ((env->error_code & EXCP_TLB_NOMATCH) &&
|
||||
!(env->CP0_Status & (1 << CP0St_EXL))) {
|
||||
#if defined(TARGET_MIPS64)
|
||||
int R = env->CP0_BadVAddr >> 62;
|
||||
int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
|
||||
int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;
|
||||
int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0;
|
||||
|
||||
if (((R == 0 && UX) || (R == 1 && SX) || (R == 3 && KX)) &&
|
||||
(!(env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F))))
|
||||
offset = 0x080;
|
||||
else
|
||||
#endif
|
||||
offset = 0x000;
|
||||
}
|
||||
goto set_EPC;
|
||||
case EXCP_TLBS:
|
||||
cause = 3;
|
||||
update_badinstr = 1;
|
||||
if ((env->error_code & EXCP_TLB_NOMATCH) &&
|
||||
!(env->CP0_Status & (1 << CP0St_EXL))) {
|
||||
#if defined(TARGET_MIPS64)
|
||||
int R = env->CP0_BadVAddr >> 62;
|
||||
int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
|
||||
int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;
|
||||
int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0;
|
||||
|
||||
if (((R == 0 && UX) || (R == 1 && SX) || (R == 3 && KX)) &&
|
||||
(!(env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F))))
|
||||
offset = 0x080;
|
||||
else
|
||||
#endif
|
||||
offset = 0x000;
|
||||
}
|
||||
goto set_EPC;
|
||||
case EXCP_AdEL:
|
||||
cause = 4;
|
||||
update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL);
|
||||
goto set_EPC;
|
||||
case EXCP_AdES:
|
||||
cause = 5;
|
||||
update_badinstr = 1;
|
||||
goto set_EPC;
|
||||
case EXCP_IBE:
|
||||
cause = 6;
|
||||
goto set_EPC;
|
||||
case EXCP_DBE:
|
||||
cause = 7;
|
||||
goto set_EPC;
|
||||
case EXCP_SYSCALL:
|
||||
cause = 8;
|
||||
update_badinstr = 1;
|
||||
goto set_EPC;
|
||||
case EXCP_BREAK:
|
||||
cause = 9;
|
||||
update_badinstr = 1;
|
||||
goto set_EPC;
|
||||
case EXCP_RI:
|
||||
cause = 10;
|
||||
update_badinstr = 1;
|
||||
goto set_EPC;
|
||||
case EXCP_CpU:
|
||||
cause = 11;
|
||||
update_badinstr = 1;
|
||||
env->CP0_Cause = (env->CP0_Cause & ~(0x3 << CP0Ca_CE)) |
|
||||
(env->error_code << CP0Ca_CE);
|
||||
goto set_EPC;
|
||||
case EXCP_OVERFLOW:
|
||||
cause = 12;
|
||||
update_badinstr = 1;
|
||||
goto set_EPC;
|
||||
case EXCP_TRAP:
|
||||
cause = 13;
|
||||
update_badinstr = 1;
|
||||
goto set_EPC;
|
||||
case EXCP_MSAFPE:
|
||||
cause = 14;
|
||||
update_badinstr = 1;
|
||||
goto set_EPC;
|
||||
case EXCP_FPE:
|
||||
cause = 15;
|
||||
update_badinstr = 1;
|
||||
goto set_EPC;
|
||||
case EXCP_C2E:
|
||||
cause = 18;
|
||||
goto set_EPC;
|
||||
case EXCP_TLBRI:
|
||||
cause = 19;
|
||||
update_badinstr = 1;
|
||||
goto set_EPC;
|
||||
case EXCP_TLBXI:
|
||||
cause = 20;
|
||||
goto set_EPC;
|
||||
case EXCP_MSADIS:
|
||||
cause = 21;
|
||||
update_badinstr = 1;
|
||||
goto set_EPC;
|
||||
case EXCP_MDMX:
|
||||
cause = 22;
|
||||
goto set_EPC;
|
||||
case EXCP_DWATCH:
|
||||
cause = 23;
|
||||
/* XXX: TODO: manage deferred watch exceptions */
|
||||
goto set_EPC;
|
||||
case EXCP_MCHECK:
|
||||
cause = 24;
|
||||
goto set_EPC;
|
||||
case EXCP_THREAD:
|
||||
cause = 25;
|
||||
goto set_EPC;
|
||||
case EXCP_DSPDIS:
|
||||
cause = 26;
|
||||
goto set_EPC;
|
||||
case EXCP_CACHE:
|
||||
cause = 30;
|
||||
if (env->CP0_Status & (1 << CP0St_BEV)) {
|
||||
offset = 0x100;
|
||||
} else {
|
||||
offset = 0x20000100;
|
||||
}
|
||||
set_EPC:
|
||||
if (!(env->CP0_Status & (1 << CP0St_EXL))) {
|
||||
env->CP0_EPC = exception_resume_pc(env);
|
||||
if (update_badinstr) {
|
||||
set_badinstr_registers(env);
|
||||
}
|
||||
if (env->hflags & MIPS_HFLAG_BMASK) {
|
||||
env->CP0_Cause |= (1U << CP0Ca_BD);
|
||||
} else {
|
||||
env->CP0_Cause &= ~(1U << CP0Ca_BD);
|
||||
}
|
||||
env->CP0_Status |= (1 << CP0St_EXL);
|
||||
if (env->insn_flags & ISA_MIPS3) {
|
||||
env->hflags |= MIPS_HFLAG_64;
|
||||
if (!(env->insn_flags & ISA_MIPS64R6) ||
|
||||
env->CP0_Status & (1 << CP0St_KX)) {
|
||||
env->hflags &= ~MIPS_HFLAG_AWRAP;
|
||||
}
|
||||
}
|
||||
env->hflags |= MIPS_HFLAG_CP0;
|
||||
env->hflags &= ~(MIPS_HFLAG_KSU);
|
||||
}
|
||||
env->hflags &= ~MIPS_HFLAG_BMASK;
|
||||
if (env->CP0_Status & (1 << CP0St_BEV)) {
|
||||
env->active_tc.PC = env->exception_base + 0x200;
|
||||
} else {
|
||||
env->active_tc.PC = (int32_t)(env->CP0_EBase & ~0x3ff);
|
||||
}
|
||||
env->active_tc.PC += offset;
|
||||
set_hflags_for_handler(env);
|
||||
env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
if (qemu_loglevel_mask(CPU_LOG_INT)
|
||||
&& cs->exception_index != EXCP_EXT_INTERRUPT) {
|
||||
qemu_log("%s: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d\n"
|
||||
" S %08x C %08x A " TARGET_FMT_lx " D " TARGET_FMT_lx "\n",
|
||||
__func__, env->active_tc.PC, env->CP0_EPC, cause,
|
||||
env->CP0_Status, env->CP0_Cause, env->CP0_BadVAddr,
|
||||
env->CP0_DEPC);
|
||||
}
|
||||
#endif
|
||||
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)
|
||||
{
|
||||
MIPSCPU *cpu = mips_env_get_cpu(env);
|
||||
CPUState *cs;
|
||||
r4k_tlb_t *tlb;
|
||||
target_ulong addr;
|
||||
target_ulong end;
|
||||
uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
|
||||
target_ulong mask;
|
||||
|
||||
tlb = &env->tlb->mmu.r4k.tlb[idx];
|
||||
/* The qemu TLB is flushed when the ASID changes, so no need to
|
||||
flush these entries again. */
|
||||
if (tlb->G == 0 && tlb->ASID != ASID) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (use_extra && env->tlb->tlb_in_use < MIPS_TLB_MAX) {
|
||||
/* For tlbwr, we can shadow the discarded entry into
|
||||
a new (fake) TLB entry, as long as the guest can not
|
||||
tell that it's there. */
|
||||
env->tlb->mmu.r4k.tlb[env->tlb->tlb_in_use] = *tlb;
|
||||
env->tlb->tlb_in_use++;
|
||||
return;
|
||||
}
|
||||
|
||||
/* 1k pages are not supported. */
|
||||
mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
|
||||
if (tlb->V0) {
|
||||
cs = CPU(cpu);
|
||||
addr = tlb->VPN & ~mask;
|
||||
#if defined(TARGET_MIPS64)
|
||||
if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) {
|
||||
addr |= 0x3FFFFF0000000000ULL;
|
||||
}
|
||||
#endif
|
||||
end = addr | (mask >> 1);
|
||||
while (addr < end) {
|
||||
tlb_flush_page(cs, addr);
|
||||
addr += TARGET_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
if (tlb->V1) {
|
||||
cs = CPU(cpu);
|
||||
addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1);
|
||||
#if defined(TARGET_MIPS64)
|
||||
if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) {
|
||||
addr |= 0x3FFFFF0000000000ULL;
|
||||
}
|
||||
#endif
|
||||
end = addr | mask;
|
||||
while (addr - 1 < end) {
|
||||
tlb_flush_page(cs, addr);
|
||||
addr += TARGET_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env,
|
||||
uint32_t exception,
|
||||
int error_code,
|
||||
uintptr_t pc)
|
||||
{
|
||||
CPUState *cs = CPU(mips_env_get_cpu(env));
|
||||
|
||||
if (exception < EXCP_SC) {
|
||||
qemu_log_mask(CPU_LOG_INT, "%s: %d %d\n",
|
||||
__func__, exception, error_code);
|
||||
}
|
||||
cs->exception_index = exception;
|
||||
env->error_code = error_code;
|
||||
|
||||
cpu_loop_exit_restore(cs, pc);
|
||||
}
|
962
target/mips/helper.h
Normal file
962
target/mips/helper.h
Normal file
|
@ -0,0 +1,962 @@
|
|||
DEF_HELPER_3(raise_exception_err, noreturn, env, i32, int)
|
||||
DEF_HELPER_2(raise_exception, noreturn, env, i32)
|
||||
DEF_HELPER_1(raise_exception_debug, noreturn, env)
|
||||
|
||||
DEF_HELPER_1(do_semihosting, void, env)
|
||||
|
||||
#ifdef TARGET_MIPS64
|
||||
DEF_HELPER_4(sdl, void, env, tl, tl, int)
|
||||
DEF_HELPER_4(sdr, void, env, tl, tl, int)
|
||||
#endif
|
||||
DEF_HELPER_4(swl, void, env, tl, tl, int)
|
||||
DEF_HELPER_4(swr, void, env, tl, tl, int)
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
DEF_HELPER_3(ll, tl, env, tl, int)
|
||||
DEF_HELPER_4(sc, tl, env, tl, tl, int)
|
||||
#ifdef TARGET_MIPS64
|
||||
DEF_HELPER_3(lld, tl, env, tl, int)
|
||||
DEF_HELPER_4(scd, tl, env, tl, tl, int)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
DEF_HELPER_FLAGS_1(clo, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#ifdef TARGET_MIPS64
|
||||
DEF_HELPER_FLAGS_1(dclo, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(dclz, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#endif
|
||||
|
||||
DEF_HELPER_3(muls, tl, env, tl, tl)
|
||||
DEF_HELPER_3(mulsu, tl, env, tl, tl)
|
||||
DEF_HELPER_3(macc, tl, env, tl, tl)
|
||||
DEF_HELPER_3(maccu, tl, env, tl, tl)
|
||||
DEF_HELPER_3(msac, tl, env, tl, tl)
|
||||
DEF_HELPER_3(msacu, tl, env, tl, tl)
|
||||
DEF_HELPER_3(mulhi, tl, env, tl, tl)
|
||||
DEF_HELPER_3(mulhiu, tl, env, tl, tl)
|
||||
DEF_HELPER_3(mulshi, tl, env, tl, tl)
|
||||
DEF_HELPER_3(mulshiu, tl, env, tl, tl)
|
||||
DEF_HELPER_3(macchi, tl, env, tl, tl)
|
||||
DEF_HELPER_3(macchiu, tl, env, tl, tl)
|
||||
DEF_HELPER_3(msachi, tl, env, tl, tl)
|
||||
DEF_HELPER_3(msachiu, tl, env, tl, tl)
|
||||
|
||||
DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#ifdef TARGET_MIPS64
|
||||
DEF_HELPER_FLAGS_1(dbitswap, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* CP0 helpers */
|
||||
DEF_HELPER_1(mfc0_mvpcontrol, tl, env)
|
||||
DEF_HELPER_1(mfc0_mvpconf0, tl, env)
|
||||
DEF_HELPER_1(mfc0_mvpconf1, tl, env)
|
||||
DEF_HELPER_1(mftc0_vpecontrol, tl, env)
|
||||
DEF_HELPER_1(mftc0_vpeconf0, tl, env)
|
||||
DEF_HELPER_1(mfc0_random, tl, env)
|
||||
DEF_HELPER_1(mfc0_tcstatus, tl, env)
|
||||
DEF_HELPER_1(mftc0_tcstatus, tl, env)
|
||||
DEF_HELPER_1(mfc0_tcbind, tl, env)
|
||||
DEF_HELPER_1(mftc0_tcbind, tl, env)
|
||||
DEF_HELPER_1(mfc0_tcrestart, tl, env)
|
||||
DEF_HELPER_1(mftc0_tcrestart, tl, env)
|
||||
DEF_HELPER_1(mfc0_tchalt, tl, env)
|
||||
DEF_HELPER_1(mftc0_tchalt, tl, env)
|
||||
DEF_HELPER_1(mfc0_tccontext, tl, env)
|
||||
DEF_HELPER_1(mftc0_tccontext, tl, env)
|
||||
DEF_HELPER_1(mfc0_tcschedule, tl, env)
|
||||
DEF_HELPER_1(mftc0_tcschedule, tl, env)
|
||||
DEF_HELPER_1(mfc0_tcschefback, tl, env)
|
||||
DEF_HELPER_1(mftc0_tcschefback, tl, env)
|
||||
DEF_HELPER_1(mfc0_count, tl, env)
|
||||
DEF_HELPER_1(mftc0_entryhi, tl, env)
|
||||
DEF_HELPER_1(mftc0_status, tl, env)
|
||||
DEF_HELPER_1(mftc0_cause, tl, env)
|
||||
DEF_HELPER_1(mftc0_epc, tl, env)
|
||||
DEF_HELPER_1(mftc0_ebase, tl, env)
|
||||
DEF_HELPER_2(mftc0_configx, tl, env, tl)
|
||||
DEF_HELPER_1(mfc0_lladdr, tl, env)
|
||||
DEF_HELPER_1(mfc0_maar, tl, env)
|
||||
DEF_HELPER_1(mfhc0_maar, tl, env)
|
||||
DEF_HELPER_2(mfc0_watchlo, tl, env, i32)
|
||||
DEF_HELPER_2(mfc0_watchhi, tl, env, i32)
|
||||
DEF_HELPER_1(mfc0_debug, tl, env)
|
||||
DEF_HELPER_1(mftc0_debug, tl, env)
|
||||
#ifdef TARGET_MIPS64
|
||||
DEF_HELPER_1(dmfc0_tcrestart, tl, env)
|
||||
DEF_HELPER_1(dmfc0_tchalt, tl, env)
|
||||
DEF_HELPER_1(dmfc0_tccontext, tl, env)
|
||||
DEF_HELPER_1(dmfc0_tcschedule, tl, env)
|
||||
DEF_HELPER_1(dmfc0_tcschefback, tl, env)
|
||||
DEF_HELPER_1(dmfc0_lladdr, tl, env)
|
||||
DEF_HELPER_1(dmfc0_maar, tl, env)
|
||||
DEF_HELPER_2(dmfc0_watchlo, tl, env, i32)
|
||||
#endif /* TARGET_MIPS64 */
|
||||
|
||||
DEF_HELPER_2(mtc0_index, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_mvpcontrol, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_vpecontrol, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_vpecontrol, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_vpeconf0, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_vpeconf0, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_vpeconf1, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_yqmask, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_vpeopt, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_entrylo0, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_tcstatus, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_tcstatus, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_tcbind, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_tcbind, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_tcrestart, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_tcrestart, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_tchalt, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_tchalt, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_tccontext, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_tccontext, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_tcschedule, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_tcschedule, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_tcschefback, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_tcschefback, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_entrylo1, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_context, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_pagemask, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_pagegrain, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_wired, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_srsconf0, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_srsconf1, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_srsconf2, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_srsconf3, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_srsconf4, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_hwrena, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_count, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_entryhi, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_entryhi, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_compare, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_status, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_status, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_intctl, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_srsctl, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_cause, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_cause, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_ebase, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_ebase, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_config0, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_config2, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_config3, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_config4, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_config5, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_lladdr, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_maar, void, env, tl)
|
||||
DEF_HELPER_2(mthc0_maar, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_maari, void, env, tl)
|
||||
DEF_HELPER_3(mtc0_watchlo, void, env, tl, i32)
|
||||
DEF_HELPER_3(mtc0_watchhi, void, env, tl, i32)
|
||||
DEF_HELPER_2(mtc0_xcontext, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_framemask, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_debug, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_debug, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_performance0, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_errctl, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_taglo, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_datalo, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_taghi, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_datahi, void, env, tl)
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_2(dmtc0_entrylo0, void, env, i64)
|
||||
DEF_HELPER_2(dmtc0_entrylo1, void, env, i64)
|
||||
#endif
|
||||
|
||||
/* MIPS MT functions */
|
||||
DEF_HELPER_2(mftgpr, tl, env, i32)
|
||||
DEF_HELPER_2(mftlo, tl, env, i32)
|
||||
DEF_HELPER_2(mfthi, tl, env, i32)
|
||||
DEF_HELPER_2(mftacx, tl, env, i32)
|
||||
DEF_HELPER_1(mftdsp, tl, env)
|
||||
DEF_HELPER_3(mttgpr, void, env, tl, i32)
|
||||
DEF_HELPER_3(mttlo, void, env, tl, i32)
|
||||
DEF_HELPER_3(mtthi, void, env, tl, i32)
|
||||
DEF_HELPER_3(mttacx, void, env, tl, i32)
|
||||
DEF_HELPER_2(mttdsp, void, env, tl)
|
||||
DEF_HELPER_0(dmt, tl)
|
||||
DEF_HELPER_0(emt, tl)
|
||||
DEF_HELPER_1(dvpe, tl, env)
|
||||
DEF_HELPER_1(evpe, tl, env)
|
||||
|
||||
/* R6 Multi-threading */
|
||||
DEF_HELPER_1(dvp, tl, env)
|
||||
DEF_HELPER_1(evp, tl, env)
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
/* microMIPS functions */
|
||||
DEF_HELPER_4(lwm, void, env, tl, tl, i32)
|
||||
DEF_HELPER_4(swm, void, env, tl, tl, i32)
|
||||
#ifdef TARGET_MIPS64
|
||||
DEF_HELPER_4(ldm, void, env, tl, tl, i32)
|
||||
DEF_HELPER_4(sdm, void, env, tl, tl, i32)
|
||||
#endif
|
||||
|
||||
DEF_HELPER_2(fork, void, tl, tl)
|
||||
DEF_HELPER_2(yield, tl, env, tl)
|
||||
|
||||
/* CP1 functions */
|
||||
DEF_HELPER_2(cfc1, tl, env, i32)
|
||||
DEF_HELPER_4(ctc1, void, env, tl, i32, i32)
|
||||
|
||||
DEF_HELPER_2(float_cvtd_s, i64, env, i32)
|
||||
DEF_HELPER_2(float_cvtd_w, i64, env, i32)
|
||||
DEF_HELPER_2(float_cvtd_l, i64, env, i64)
|
||||
DEF_HELPER_2(float_cvtps_pw, i64, env, i64)
|
||||
DEF_HELPER_2(float_cvtpw_ps, i64, env, i64)
|
||||
DEF_HELPER_2(float_cvts_d, i32, env, i64)
|
||||
DEF_HELPER_2(float_cvts_w, i32, env, i32)
|
||||
DEF_HELPER_2(float_cvts_l, i32, env, i64)
|
||||
DEF_HELPER_2(float_cvts_pl, i32, env, i32)
|
||||
DEF_HELPER_2(float_cvts_pu, i32, env, i32)
|
||||
|
||||
DEF_HELPER_3(float_addr_ps, i64, env, i64, i64)
|
||||
DEF_HELPER_3(float_mulr_ps, i64, env, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(float_class_s, TCG_CALL_NO_RWG_SE, i32, env, i32)
|
||||
DEF_HELPER_FLAGS_2(float_class_d, TCG_CALL_NO_RWG_SE, i64, env, i64)
|
||||
|
||||
#define FOP_PROTO(op) \
|
||||
DEF_HELPER_4(float_ ## op ## _s, i32, env, i32, i32, i32) \
|
||||
DEF_HELPER_4(float_ ## op ## _d, i64, env, i64, i64, i64)
|
||||
FOP_PROTO(maddf)
|
||||
FOP_PROTO(msubf)
|
||||
#undef FOP_PROTO
|
||||
|
||||
#define FOP_PROTO(op) \
|
||||
DEF_HELPER_3(float_ ## op ## _s, i32, env, i32, i32) \
|
||||
DEF_HELPER_3(float_ ## op ## _d, i64, env, i64, i64)
|
||||
FOP_PROTO(max)
|
||||
FOP_PROTO(maxa)
|
||||
FOP_PROTO(min)
|
||||
FOP_PROTO(mina)
|
||||
#undef FOP_PROTO
|
||||
|
||||
#define FOP_PROTO(op) \
|
||||
DEF_HELPER_2(float_ ## op ## _l_s, i64, env, i32) \
|
||||
DEF_HELPER_2(float_ ## op ## _l_d, i64, env, i64) \
|
||||
DEF_HELPER_2(float_ ## op ## _w_s, i32, env, i32) \
|
||||
DEF_HELPER_2(float_ ## op ## _w_d, i32, env, i64)
|
||||
FOP_PROTO(cvt)
|
||||
FOP_PROTO(round)
|
||||
FOP_PROTO(trunc)
|
||||
FOP_PROTO(ceil)
|
||||
FOP_PROTO(floor)
|
||||
FOP_PROTO(cvt_2008)
|
||||
FOP_PROTO(round_2008)
|
||||
FOP_PROTO(trunc_2008)
|
||||
FOP_PROTO(ceil_2008)
|
||||
FOP_PROTO(floor_2008)
|
||||
#undef FOP_PROTO
|
||||
|
||||
#define FOP_PROTO(op) \
|
||||
DEF_HELPER_2(float_ ## op ## _s, i32, env, i32) \
|
||||
DEF_HELPER_2(float_ ## op ## _d, i64, env, i64)
|
||||
FOP_PROTO(sqrt)
|
||||
FOP_PROTO(rsqrt)
|
||||
FOP_PROTO(recip)
|
||||
FOP_PROTO(rint)
|
||||
#undef FOP_PROTO
|
||||
|
||||
#define FOP_PROTO(op) \
|
||||
DEF_HELPER_1(float_ ## op ## _s, i32, i32) \
|
||||
DEF_HELPER_1(float_ ## op ## _d, i64, i64) \
|
||||
DEF_HELPER_1(float_ ## op ## _ps, i64, i64)
|
||||
FOP_PROTO(abs)
|
||||
FOP_PROTO(chs)
|
||||
#undef FOP_PROTO
|
||||
|
||||
#define FOP_PROTO(op) \
|
||||
DEF_HELPER_2(float_ ## op ## _s, i32, env, i32) \
|
||||
DEF_HELPER_2(float_ ## op ## _d, i64, env, i64) \
|
||||
DEF_HELPER_2(float_ ## op ## _ps, i64, env, i64)
|
||||
FOP_PROTO(recip1)
|
||||
FOP_PROTO(rsqrt1)
|
||||
#undef FOP_PROTO
|
||||
|
||||
#define FOP_PROTO(op) \
|
||||
DEF_HELPER_3(float_ ## op ## _s, i32, env, i32, i32) \
|
||||
DEF_HELPER_3(float_ ## op ## _d, i64, env, i64, i64) \
|
||||
DEF_HELPER_3(float_ ## op ## _ps, i64, env, i64, i64)
|
||||
FOP_PROTO(add)
|
||||
FOP_PROTO(sub)
|
||||
FOP_PROTO(mul)
|
||||
FOP_PROTO(div)
|
||||
FOP_PROTO(recip2)
|
||||
FOP_PROTO(rsqrt2)
|
||||
#undef FOP_PROTO
|
||||
|
||||
#define FOP_PROTO(op) \
|
||||
DEF_HELPER_4(float_ ## op ## _s, i32, env, i32, i32, i32) \
|
||||
DEF_HELPER_4(float_ ## op ## _d, i64, env, i64, i64, i64) \
|
||||
DEF_HELPER_4(float_ ## op ## _ps, i64, env, i64, i64, i64)
|
||||
FOP_PROTO(madd)
|
||||
FOP_PROTO(msub)
|
||||
FOP_PROTO(nmadd)
|
||||
FOP_PROTO(nmsub)
|
||||
#undef FOP_PROTO
|
||||
|
||||
#define FOP_PROTO(op) \
|
||||
DEF_HELPER_4(cmp_d_ ## op, void, env, i64, i64, int) \
|
||||
DEF_HELPER_4(cmpabs_d_ ## op, void, env, i64, i64, int) \
|
||||
DEF_HELPER_4(cmp_s_ ## op, void, env, i32, i32, int) \
|
||||
DEF_HELPER_4(cmpabs_s_ ## op, void, env, i32, i32, int) \
|
||||
DEF_HELPER_4(cmp_ps_ ## op, void, env, i64, i64, int) \
|
||||
DEF_HELPER_4(cmpabs_ps_ ## op, void, env, i64, i64, int)
|
||||
FOP_PROTO(f)
|
||||
FOP_PROTO(un)
|
||||
FOP_PROTO(eq)
|
||||
FOP_PROTO(ueq)
|
||||
FOP_PROTO(olt)
|
||||
FOP_PROTO(ult)
|
||||
FOP_PROTO(ole)
|
||||
FOP_PROTO(ule)
|
||||
FOP_PROTO(sf)
|
||||
FOP_PROTO(ngle)
|
||||
FOP_PROTO(seq)
|
||||
FOP_PROTO(ngl)
|
||||
FOP_PROTO(lt)
|
||||
FOP_PROTO(nge)
|
||||
FOP_PROTO(le)
|
||||
FOP_PROTO(ngt)
|
||||
#undef FOP_PROTO
|
||||
|
||||
#define FOP_PROTO(op) \
|
||||
DEF_HELPER_3(r6_cmp_d_ ## op, i64, env, i64, i64) \
|
||||
DEF_HELPER_3(r6_cmp_s_ ## op, i32, env, i32, i32)
|
||||
FOP_PROTO(af)
|
||||
FOP_PROTO(un)
|
||||
FOP_PROTO(eq)
|
||||
FOP_PROTO(ueq)
|
||||
FOP_PROTO(lt)
|
||||
FOP_PROTO(ult)
|
||||
FOP_PROTO(le)
|
||||
FOP_PROTO(ule)
|
||||
FOP_PROTO(saf)
|
||||
FOP_PROTO(sun)
|
||||
FOP_PROTO(seq)
|
||||
FOP_PROTO(sueq)
|
||||
FOP_PROTO(slt)
|
||||
FOP_PROTO(sult)
|
||||
FOP_PROTO(sle)
|
||||
FOP_PROTO(sule)
|
||||
FOP_PROTO(or)
|
||||
FOP_PROTO(une)
|
||||
FOP_PROTO(ne)
|
||||
FOP_PROTO(sor)
|
||||
FOP_PROTO(sune)
|
||||
FOP_PROTO(sne)
|
||||
#undef FOP_PROTO
|
||||
|
||||
/* Special functions */
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
DEF_HELPER_1(tlbwi, void, env)
|
||||
DEF_HELPER_1(tlbwr, void, env)
|
||||
DEF_HELPER_1(tlbp, void, env)
|
||||
DEF_HELPER_1(tlbr, void, env)
|
||||
DEF_HELPER_1(tlbinv, void, env)
|
||||
DEF_HELPER_1(tlbinvf, void, env)
|
||||
DEF_HELPER_1(di, tl, env)
|
||||
DEF_HELPER_1(ei, tl, env)
|
||||
DEF_HELPER_1(eret, void, env)
|
||||
DEF_HELPER_1(eretnc, void, env)
|
||||
DEF_HELPER_1(deret, void, env)
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
DEF_HELPER_1(rdhwr_cpunum, tl, env)
|
||||
DEF_HELPER_1(rdhwr_synci_step, tl, env)
|
||||
DEF_HELPER_1(rdhwr_cc, tl, env)
|
||||
DEF_HELPER_1(rdhwr_ccres, tl, env)
|
||||
DEF_HELPER_1(rdhwr_performance, tl, env)
|
||||
DEF_HELPER_1(rdhwr_xnp, tl, env)
|
||||
DEF_HELPER_2(pmon, void, env, int)
|
||||
DEF_HELPER_1(wait, void, env)
|
||||
|
||||
/* Loongson multimedia functions. */
|
||||
DEF_HELPER_FLAGS_2(paddsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(paddush, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(paddh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(paddw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(paddsb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(paddusb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(paddb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(psubsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psubush, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psubh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psubw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psubsb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psubusb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psubb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(pshufh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(packsswh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(packsshb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(packushb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(punpcklhw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(punpckhhw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(punpcklbh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(punpckhbh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(punpcklwd, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(punpckhwd, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(pavgh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pavgb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmaxsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pminsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmaxub, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pminub, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(pcmpeqw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pcmpgtw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pcmpeqh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pcmpgth, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pcmpeqb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pcmpgtb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(psllw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psllh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psrlw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psrlh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psraw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psrah, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(pmullh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmulhh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmulhuh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmaddhw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(pasubub, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_1(biadd, TCG_CALL_NO_RWG_SE, i64, i64)
|
||||
DEF_HELPER_FLAGS_1(pmovmskb, TCG_CALL_NO_RWG_SE, i64, i64)
|
||||
|
||||
/*** MIPS DSP ***/
|
||||
/* DSP Arithmetic Sub-class insns */
|
||||
DEF_HELPER_FLAGS_3(addq_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(addq_s_ph, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(addq_qh, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(addq_s_qh, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(addq_s_w, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(addq_pw, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(addq_s_pw, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(addu_qb, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(addu_s_qb, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(adduh_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(adduh_r_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(addu_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(addu_s_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(addqh_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(addqh_r_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(addqh_w, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(addqh_r_w, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(addu_ob, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(addu_s_ob, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(adduh_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(adduh_r_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(addu_qh, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(addu_s_qh, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(subq_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(subq_s_ph, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(subq_qh, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(subq_s_qh, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(subq_s_w, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(subq_pw, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(subq_s_pw, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(subu_qb, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(subu_s_qb, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(subuh_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(subuh_r_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(subu_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(subu_s_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(subqh_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(subqh_r_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(subqh_w, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(subqh_r_w, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(subu_ob, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(subu_s_ob, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(subuh_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(subuh_r_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(subu_qh, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(subu_s_qh, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(addsc, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(addwc, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(modsub, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(raddu_w_qb, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_1(raddu_l_ob, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_2(absq_s_qb, 0, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(absq_s_ph, 0, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(absq_s_w, 0, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_2(absq_s_ob, 0, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(absq_s_qh, 0, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(absq_s_pw, 0, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_2(precr_qb_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(precrq_qb_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(precr_sra_ph_w, TCG_CALL_NO_RWG_SE,
|
||||
tl, i32, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(precr_sra_r_ph_w, TCG_CALL_NO_RWG_SE,
|
||||
tl, i32, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(precrq_ph_w, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(precrq_rs_ph_w, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_2(precr_ob_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(precr_sra_qh_pw,
|
||||
TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
|
||||
DEF_HELPER_FLAGS_3(precr_sra_r_qh_pw,
|
||||
TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
|
||||
DEF_HELPER_FLAGS_2(precrq_ob_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(precrq_qh_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(precrq_rs_qh_pw,
|
||||
TCG_CALL_NO_RWG_SE, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(precrq_pw_l, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(precrqu_s_qb_ph, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(precrqu_s_ob_qh,
|
||||
TCG_CALL_NO_RWG_SE, tl, tl, tl, env)
|
||||
|
||||
DEF_HELPER_FLAGS_1(preceq_pw_qhl, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(preceq_pw_qhr, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(preceq_pw_qhla, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(preceq_pw_qhra, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_1(precequ_ph_qbl, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(precequ_ph_qbr, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(precequ_ph_qbla, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(precequ_ph_qbra, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_1(precequ_qh_obl, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(precequ_qh_obr, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(precequ_qh_obla, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(precequ_qh_obra, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_1(preceu_ph_qbl, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(preceu_ph_qbr, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(preceu_ph_qbla, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(preceu_ph_qbra, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_1(preceu_qh_obl, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(preceu_qh_obr, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(preceu_qh_obla, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(preceu_qh_obra, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#endif
|
||||
|
||||
/* DSP GPR-Based Shift Sub-class insns */
|
||||
DEF_HELPER_FLAGS_3(shll_qb, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(shll_ob, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(shll_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(shll_s_ph, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(shll_qh, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(shll_s_qh, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(shll_s_w, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(shll_pw, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(shll_s_pw, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_2(shrl_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(shrl_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_2(shrl_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(shrl_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_2(shra_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(shra_r_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_2(shra_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(shra_r_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_2(shra_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(shra_r_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(shra_r_w, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_2(shra_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(shra_r_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(shra_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(shra_r_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#endif
|
||||
|
||||
/* DSP Multiply Sub-class insns */
|
||||
DEF_HELPER_FLAGS_3(muleu_s_ph_qbl, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(muleu_s_ph_qbr, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(muleu_s_qh_obl, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(muleu_s_qh_obr, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(mulq_rs_ph, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(mulq_rs_qh, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(muleq_s_w_phl, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(muleq_s_w_phr, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(muleq_s_pw_qhl, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(muleq_s_pw_qhr, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpau_h_qbl, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dpau_h_qbr, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpau_h_obl, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(dpau_h_obr, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpsu_h_qbl, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dpsu_h_qbr, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpsu_h_obl, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(dpsu_h_obr, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpa_w_ph, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpa_w_qh, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpax_w_ph, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dpaq_s_w_ph, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpaq_s_w_qh, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpaqx_s_w_ph, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dpaqx_sa_w_ph, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dps_w_ph, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dps_w_qh, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpsx_w_ph, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dpsq_s_w_ph, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpsq_s_w_qh, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpsqx_s_w_ph, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dpsqx_sa_w_ph, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(mulsaq_s_w_ph, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(mulsaq_s_w_qh, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpaq_sa_l_w, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpaq_sa_l_pw, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpsq_sa_l_w, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpsq_sa_l_pw, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(mulsaq_s_l_pw, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(maq_s_w_phl, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(maq_s_w_phr, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(maq_sa_w_phl, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(maq_sa_w_phr, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(mul_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(mul_s_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(mulq_s_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(mulq_s_w, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(mulq_rs_w, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(mulsa_w_ph, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(maq_s_w_qhll, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_s_w_qhlr, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_s_w_qhrl, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_s_w_qhrr, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_sa_w_qhll, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_sa_w_qhlr, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_sa_w_qhrl, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_sa_w_qhrr, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_s_l_pwl, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_s_l_pwr, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(dmadd, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(dmaddu, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(dmsub, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(dmsubu, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
|
||||
/* DSP Bit/Manipulation Sub-class insns */
|
||||
DEF_HELPER_FLAGS_1(bitrev, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(insv, 0, tl, env, tl, tl)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(dinsv, 0, tl, env, tl, tl)
|
||||
#endif
|
||||
|
||||
/* DSP Compare-Pick Sub-class insns */
|
||||
DEF_HELPER_FLAGS_3(cmpu_eq_qb, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmpu_lt_qb, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmpu_le_qb, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(cmpgu_eq_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(cmpgu_lt_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(cmpgu_le_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(cmp_eq_ph, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmp_lt_ph, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmp_le_ph, 0, void, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(cmpu_eq_ob, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmpu_lt_ob, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmpu_le_ob, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmpgdu_eq_ob, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmpgdu_lt_ob, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmpgdu_le_ob, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(cmpgu_eq_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(cmpgu_lt_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(cmpgu_le_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(cmp_eq_qh, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmp_lt_qh, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmp_le_qh, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmp_eq_pw, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmp_lt_pw, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(cmp_le_pw, 0, void, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(pick_qb, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(pick_ph, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(pick_ob, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(pick_qh, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(pick_pw, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_2(packrl_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_2(packrl_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#endif
|
||||
|
||||
/* DSP Accumulator and DSPControl Access Sub-class insns */
|
||||
DEF_HELPER_FLAGS_3(extr_w, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(extr_r_w, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(extr_rs_w, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(dextr_w, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(dextr_r_w, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(dextr_rs_w, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(dextr_l, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(dextr_r_l, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(dextr_rs_l, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(extr_s_h, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(dextr_s_h, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(extp, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(extpdp, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(dextp, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(dextpdp, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(shilo, 0, void, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(dshilo, 0, void, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(mthlip, 0, void, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(dmthlip, 0, void, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(wrdsp, 0, void, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env)
|
||||
|
||||
/* MIPS SIMD Architecture */
|
||||
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_sll_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_sra_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_srl_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_bclr_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_bset_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_bneg_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_5(msa_addv_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_subv_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_max_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_max_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_min_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_min_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_max_a_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_min_a_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_ceq_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_clt_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_clt_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_cle_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_cle_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_add_a_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_adds_a_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_adds_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_adds_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_ave_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_ave_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_aver_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_aver_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_subs_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_subs_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_subsus_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_subsuu_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_asub_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_asub_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_maddv_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_msubv_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_div_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_div_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_mod_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_mod_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_dotp_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_dotp_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_dpadd_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_dpadd_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_dpsub_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_dpsub_u_df, void, env, i32, 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_pckev_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_pckod_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_ilvl_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_ilvr_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_ilvev_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_ilvod_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_vshf_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_srar_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_srlr_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_hadd_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_hadd_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_hsub_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_hsub_u_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_copy_s_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_copy_u_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_insert_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_3(msa_move_v, void, env, i32, 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_and_v, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_or_v, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_nor_v, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_xor_v, 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_fill_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_pcnt_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_nloc_df, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msa_nlzc_df, 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)
|
1060
target/mips/kvm.c
Normal file
1060
target/mips/kvm.c
Normal file
File diff suppressed because it is too large
Load diff
26
target/mips/kvm_mips.h
Normal file
26
target/mips/kvm_mips.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* KVM/MIPS: MIPS specific KVM APIs
|
||||
*
|
||||
* Copyright (C) 2012-2014 Imagination Technologies Ltd.
|
||||
* Authors: Sanjay Lal <sanjayl@kymasys.com>
|
||||
*/
|
||||
|
||||
#ifndef KVM_MIPS_H
|
||||
#define KVM_MIPS_H
|
||||
|
||||
/**
|
||||
* kvm_mips_reset_vcpu:
|
||||
* @cpu: MIPSCPU
|
||||
*
|
||||
* Called at reset time to set kernel registers to their initial values.
|
||||
*/
|
||||
void kvm_mips_reset_vcpu(MIPSCPU *cpu);
|
||||
|
||||
int kvm_mips_set_interrupt(MIPSCPU *cpu, int irq, int level);
|
||||
int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level);
|
||||
|
||||
#endif /* KVM_MIPS_H */
|
745
target/mips/lmi_helper.c
Normal file
745
target/mips/lmi_helper.c
Normal file
|
@ -0,0 +1,745 @@
|
|||
/*
|
||||
* Loongson Multimedia Instruction emulation helpers for QEMU.
|
||||
*
|
||||
* Copyright (c) 2011 Richard Henderson <rth@twiddle.net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
||||
/* If the byte ordering doesn't matter, i.e. all columns are treated
|
||||
identically, then this union can be used directly. If byte ordering
|
||||
does matter, we generally ignore dumping to memory. */
|
||||
typedef union {
|
||||
uint8_t ub[8];
|
||||
int8_t sb[8];
|
||||
uint16_t uh[4];
|
||||
int16_t sh[4];
|
||||
uint32_t uw[2];
|
||||
int32_t sw[2];
|
||||
uint64_t d;
|
||||
} LMIValue;
|
||||
|
||||
/* Some byte ordering issues can be mitigated by XORing in the following. */
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
# define BYTE_ORDER_XOR(N) N
|
||||
#else
|
||||
# define BYTE_ORDER_XOR(N) 0
|
||||
#endif
|
||||
|
||||
#define SATSB(x) (x < -0x80 ? -0x80 : x > 0x7f ? 0x7f : x)
|
||||
#define SATUB(x) (x > 0xff ? 0xff : x)
|
||||
|
||||
#define SATSH(x) (x < -0x8000 ? -0x8000 : x > 0x7fff ? 0x7fff : x)
|
||||
#define SATUH(x) (x > 0xffff ? 0xffff : x)
|
||||
|
||||
#define SATSW(x) \
|
||||
(x < -0x80000000ll ? -0x80000000ll : x > 0x7fffffff ? 0x7fffffff : x)
|
||||
#define SATUW(x) (x > 0xffffffffull ? 0xffffffffull : x)
|
||||
|
||||
uint64_t helper_paddsb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
int r = vs.sb[i] + vt.sb[i];
|
||||
vs.sb[i] = SATSB(r);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_paddusb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
int r = vs.ub[i] + vt.ub[i];
|
||||
vs.ub[i] = SATUB(r);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_paddsh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
int r = vs.sh[i] + vt.sh[i];
|
||||
vs.sh[i] = SATSH(r);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_paddush(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
int r = vs.uh[i] + vt.uh[i];
|
||||
vs.uh[i] = SATUH(r);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_paddb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
vs.ub[i] += vt.ub[i];
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_paddh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
vs.uh[i] += vt.uh[i];
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_paddw(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 2; ++i) {
|
||||
vs.uw[i] += vt.uw[i];
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psubsb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
int r = vs.sb[i] - vt.sb[i];
|
||||
vs.sb[i] = SATSB(r);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psubusb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
int r = vs.ub[i] - vt.ub[i];
|
||||
vs.ub[i] = SATUB(r);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psubsh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
int r = vs.sh[i] - vt.sh[i];
|
||||
vs.sh[i] = SATSH(r);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psubush(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
int r = vs.uh[i] - vt.uh[i];
|
||||
vs.uh[i] = SATUH(r);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psubb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
vs.ub[i] -= vt.ub[i];
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psubh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
vs.uh[i] -= vt.uh[i];
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psubw(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned int i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 2; ++i) {
|
||||
vs.uw[i] -= vt.uw[i];
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pshufh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
unsigned host = BYTE_ORDER_XOR(3);
|
||||
LMIValue vd, vs;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vd.d = 0;
|
||||
for (i = 0; i < 4; i++, ft >>= 2) {
|
||||
vd.uh[i ^ host] = vs.uh[(ft & 3) ^ host];
|
||||
}
|
||||
return vd.d;
|
||||
}
|
||||
|
||||
uint64_t helper_packsswh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
uint64_t fd = 0;
|
||||
int64_t tmp;
|
||||
|
||||
tmp = (int32_t)(fs >> 0);
|
||||
tmp = SATSH(tmp);
|
||||
fd |= (tmp & 0xffff) << 0;
|
||||
|
||||
tmp = (int32_t)(fs >> 32);
|
||||
tmp = SATSH(tmp);
|
||||
fd |= (tmp & 0xffff) << 16;
|
||||
|
||||
tmp = (int32_t)(ft >> 0);
|
||||
tmp = SATSH(tmp);
|
||||
fd |= (tmp & 0xffff) << 32;
|
||||
|
||||
tmp = (int32_t)(ft >> 32);
|
||||
tmp = SATSH(tmp);
|
||||
fd |= (tmp & 0xffff) << 48;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
uint64_t helper_packsshb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
uint64_t fd = 0;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
int16_t tmp = fs >> (i * 16);
|
||||
tmp = SATSB(tmp);
|
||||
fd |= (uint64_t)(tmp & 0xff) << (i * 8);
|
||||
}
|
||||
for (i = 0; i < 4; ++i) {
|
||||
int16_t tmp = ft >> (i * 16);
|
||||
tmp = SATSB(tmp);
|
||||
fd |= (uint64_t)(tmp & 0xff) << (i * 8 + 32);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
uint64_t helper_packushb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
uint64_t fd = 0;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
int16_t tmp = fs >> (i * 16);
|
||||
tmp = SATUB(tmp);
|
||||
fd |= (uint64_t)(tmp & 0xff) << (i * 8);
|
||||
}
|
||||
for (i = 0; i < 4; ++i) {
|
||||
int16_t tmp = ft >> (i * 16);
|
||||
tmp = SATUB(tmp);
|
||||
fd |= (uint64_t)(tmp & 0xff) << (i * 8 + 32);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
uint64_t helper_punpcklwd(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
return (fs & 0xffffffff) | (ft << 32);
|
||||
}
|
||||
|
||||
uint64_t helper_punpckhwd(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
return (fs >> 32) | (ft & ~0xffffffffull);
|
||||
}
|
||||
|
||||
uint64_t helper_punpcklhw(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
unsigned host = BYTE_ORDER_XOR(3);
|
||||
LMIValue vd, vs, vt;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
vd.uh[0 ^ host] = vs.uh[0 ^ host];
|
||||
vd.uh[1 ^ host] = vt.uh[0 ^ host];
|
||||
vd.uh[2 ^ host] = vs.uh[1 ^ host];
|
||||
vd.uh[3 ^ host] = vt.uh[1 ^ host];
|
||||
|
||||
return vd.d;
|
||||
}
|
||||
|
||||
uint64_t helper_punpckhhw(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
unsigned host = BYTE_ORDER_XOR(3);
|
||||
LMIValue vd, vs, vt;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
vd.uh[0 ^ host] = vs.uh[2 ^ host];
|
||||
vd.uh[1 ^ host] = vt.uh[2 ^ host];
|
||||
vd.uh[2 ^ host] = vs.uh[3 ^ host];
|
||||
vd.uh[3 ^ host] = vt.uh[3 ^ host];
|
||||
|
||||
return vd.d;
|
||||
}
|
||||
|
||||
uint64_t helper_punpcklbh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
unsigned host = BYTE_ORDER_XOR(7);
|
||||
LMIValue vd, vs, vt;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
vd.ub[0 ^ host] = vs.ub[0 ^ host];
|
||||
vd.ub[1 ^ host] = vt.ub[0 ^ host];
|
||||
vd.ub[2 ^ host] = vs.ub[1 ^ host];
|
||||
vd.ub[3 ^ host] = vt.ub[1 ^ host];
|
||||
vd.ub[4 ^ host] = vs.ub[2 ^ host];
|
||||
vd.ub[5 ^ host] = vt.ub[2 ^ host];
|
||||
vd.ub[6 ^ host] = vs.ub[3 ^ host];
|
||||
vd.ub[7 ^ host] = vt.ub[3 ^ host];
|
||||
|
||||
return vd.d;
|
||||
}
|
||||
|
||||
uint64_t helper_punpckhbh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
unsigned host = BYTE_ORDER_XOR(7);
|
||||
LMIValue vd, vs, vt;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
vd.ub[0 ^ host] = vs.ub[4 ^ host];
|
||||
vd.ub[1 ^ host] = vt.ub[4 ^ host];
|
||||
vd.ub[2 ^ host] = vs.ub[5 ^ host];
|
||||
vd.ub[3 ^ host] = vt.ub[5 ^ host];
|
||||
vd.ub[4 ^ host] = vs.ub[6 ^ host];
|
||||
vd.ub[5 ^ host] = vt.ub[6 ^ host];
|
||||
vd.ub[6 ^ host] = vs.ub[7 ^ host];
|
||||
vd.ub[7 ^ host] = vt.ub[7 ^ host];
|
||||
|
||||
return vd.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pavgh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; i++) {
|
||||
vs.uh[i] = (vs.uh[i] + vt.uh[i] + 1) >> 1;
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pavgb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 8; i++) {
|
||||
vs.ub[i] = (vs.ub[i] + vt.ub[i] + 1) >> 1;
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pmaxsh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; i++) {
|
||||
vs.sh[i] = (vs.sh[i] >= vt.sh[i] ? vs.sh[i] : vt.sh[i]);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pminsh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; i++) {
|
||||
vs.sh[i] = (vs.sh[i] <= vt.sh[i] ? vs.sh[i] : vt.sh[i]);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pmaxub(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; i++) {
|
||||
vs.ub[i] = (vs.ub[i] >= vt.ub[i] ? vs.ub[i] : vt.ub[i]);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pminub(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; i++) {
|
||||
vs.ub[i] = (vs.ub[i] <= vt.ub[i] ? vs.ub[i] : vt.ub[i]);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pcmpeqw(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 2; i++) {
|
||||
vs.uw[i] = -(vs.uw[i] == vt.uw[i]);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pcmpgtw(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 2; i++) {
|
||||
vs.uw[i] = -(vs.uw[i] > vt.uw[i]);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pcmpeqh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; i++) {
|
||||
vs.uh[i] = -(vs.uh[i] == vt.uh[i]);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pcmpgth(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; i++) {
|
||||
vs.uh[i] = -(vs.uh[i] > vt.uh[i]);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pcmpeqb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 8; i++) {
|
||||
vs.ub[i] = -(vs.ub[i] == vt.ub[i]);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pcmpgtb(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 8; i++) {
|
||||
vs.ub[i] = -(vs.ub[i] > vt.ub[i]);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psllw(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs;
|
||||
unsigned i;
|
||||
|
||||
ft &= 0x7f;
|
||||
if (ft > 31) {
|
||||
return 0;
|
||||
}
|
||||
vs.d = fs;
|
||||
for (i = 0; i < 2; ++i) {
|
||||
vs.uw[i] <<= ft;
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psrlw(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs;
|
||||
unsigned i;
|
||||
|
||||
ft &= 0x7f;
|
||||
if (ft > 31) {
|
||||
return 0;
|
||||
}
|
||||
vs.d = fs;
|
||||
for (i = 0; i < 2; ++i) {
|
||||
vs.uw[i] >>= ft;
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psraw(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs;
|
||||
unsigned i;
|
||||
|
||||
ft &= 0x7f;
|
||||
if (ft > 31) {
|
||||
ft = 31;
|
||||
}
|
||||
vs.d = fs;
|
||||
for (i = 0; i < 2; ++i) {
|
||||
vs.sw[i] >>= ft;
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psllh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs;
|
||||
unsigned i;
|
||||
|
||||
ft &= 0x7f;
|
||||
if (ft > 15) {
|
||||
return 0;
|
||||
}
|
||||
vs.d = fs;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
vs.uh[i] <<= ft;
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psrlh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs;
|
||||
unsigned i;
|
||||
|
||||
ft &= 0x7f;
|
||||
if (ft > 15) {
|
||||
return 0;
|
||||
}
|
||||
vs.d = fs;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
vs.uh[i] >>= ft;
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_psrah(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs;
|
||||
unsigned i;
|
||||
|
||||
ft &= 0x7f;
|
||||
if (ft > 15) {
|
||||
ft = 15;
|
||||
}
|
||||
vs.d = fs;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
vs.sh[i] >>= ft;
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pmullh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
vs.sh[i] *= vt.sh[i];
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pmulhh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
int32_t r = vs.sh[i] * vt.sh[i];
|
||||
vs.sh[i] = r >> 16;
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pmulhuh(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
uint32_t r = vs.uh[i] * vt.uh[i];
|
||||
vs.uh[i] = r >> 16;
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_pmaddhw(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
unsigned host = BYTE_ORDER_XOR(3);
|
||||
LMIValue vs, vt;
|
||||
uint32_t p0, p1;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
p0 = vs.sh[0 ^ host] * vt.sh[0 ^ host];
|
||||
p0 += vs.sh[1 ^ host] * vt.sh[1 ^ host];
|
||||
p1 = vs.sh[2 ^ host] * vt.sh[2 ^ host];
|
||||
p1 += vs.sh[3 ^ host] * vt.sh[3 ^ host];
|
||||
|
||||
return ((uint64_t)p1 << 32) | p0;
|
||||
}
|
||||
|
||||
uint64_t helper_pasubub(uint64_t fs, uint64_t ft)
|
||||
{
|
||||
LMIValue vs, vt;
|
||||
unsigned i;
|
||||
|
||||
vs.d = fs;
|
||||
vt.d = ft;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
int r = vs.ub[i] - vt.ub[i];
|
||||
vs.ub[i] = (r < 0 ? -r : r);
|
||||
}
|
||||
return vs.d;
|
||||
}
|
||||
|
||||
uint64_t helper_biadd(uint64_t fs)
|
||||
{
|
||||
unsigned i, fd;
|
||||
|
||||
for (i = fd = 0; i < 8; ++i) {
|
||||
fd += (fs >> (i * 8)) & 0xff;
|
||||
}
|
||||
return fd & 0xffff;
|
||||
}
|
||||
|
||||
uint64_t helper_pmovmskb(uint64_t fs)
|
||||
{
|
||||
unsigned fd = 0;
|
||||
|
||||
fd |= ((fs >> 7) & 1) << 0;
|
||||
fd |= ((fs >> 15) & 1) << 1;
|
||||
fd |= ((fs >> 23) & 1) << 2;
|
||||
fd |= ((fs >> 31) & 1) << 3;
|
||||
fd |= ((fs >> 39) & 1) << 4;
|
||||
fd |= ((fs >> 47) & 1) << 5;
|
||||
fd |= ((fs >> 55) & 1) << 6;
|
||||
fd |= ((fs >> 63) & 1) << 7;
|
||||
|
||||
return fd & 0xff;
|
||||
}
|
302
target/mips/machine.c
Normal file
302
target/mips/machine.c
Normal file
|
@ -0,0 +1,302 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "hw/hw.h"
|
||||
#include "migration/cpu.h"
|
||||
|
||||
static int cpu_post_load(void *opaque, int version_id)
|
||||
{
|
||||
MIPSCPU *cpu = opaque;
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
|
||||
restore_fp_status(env);
|
||||
restore_msa_fp_status(env);
|
||||
compute_hflags(env);
|
||||
restore_pamask(env);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FPU state */
|
||||
|
||||
static int get_fpr(QEMUFile *f, void *pv, size_t size)
|
||||
{
|
||||
int i;
|
||||
fpr_t *v = pv;
|
||||
/* Restore entire MSA vector register */
|
||||
for (i = 0; i < MSA_WRLEN/64; i++) {
|
||||
qemu_get_sbe64s(f, &v->wr.d[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void put_fpr(QEMUFile *f, void *pv, size_t size)
|
||||
{
|
||||
int i;
|
||||
fpr_t *v = pv;
|
||||
/* Save entire MSA vector register */
|
||||
for (i = 0; i < MSA_WRLEN/64; i++) {
|
||||
qemu_put_sbe64s(f, &v->wr.d[i]);
|
||||
}
|
||||
}
|
||||
|
||||
const VMStateInfo vmstate_info_fpr = {
|
||||
.name = "fpr",
|
||||
.get = get_fpr,
|
||||
.put = put_fpr,
|
||||
};
|
||||
|
||||
#define VMSTATE_FPR_ARRAY_V(_f, _s, _n, _v) \
|
||||
VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_fpr, fpr_t)
|
||||
|
||||
#define VMSTATE_FPR_ARRAY(_f, _s, _n) \
|
||||
VMSTATE_FPR_ARRAY_V(_f, _s, _n, 0)
|
||||
|
||||
static VMStateField vmstate_fpu_fields[] = {
|
||||
VMSTATE_FPR_ARRAY(fpr, CPUMIPSFPUContext, 32),
|
||||
VMSTATE_UINT32(fcr0, CPUMIPSFPUContext),
|
||||
VMSTATE_UINT32(fcr31, CPUMIPSFPUContext),
|
||||
VMSTATE_END_OF_LIST()
|
||||
};
|
||||
|
||||
const VMStateDescription vmstate_fpu = {
|
||||
.name = "cpu/fpu",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = vmstate_fpu_fields
|
||||
};
|
||||
|
||||
const VMStateDescription vmstate_inactive_fpu = {
|
||||
.name = "cpu/inactive_fpu",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = vmstate_fpu_fields
|
||||
};
|
||||
|
||||
/* TC state */
|
||||
|
||||
static VMStateField vmstate_tc_fields[] = {
|
||||
VMSTATE_UINTTL_ARRAY(gpr, TCState, 32),
|
||||
VMSTATE_UINTTL(PC, TCState),
|
||||
VMSTATE_UINTTL_ARRAY(HI, TCState, MIPS_DSP_ACC),
|
||||
VMSTATE_UINTTL_ARRAY(LO, TCState, MIPS_DSP_ACC),
|
||||
VMSTATE_UINTTL_ARRAY(ACX, TCState, MIPS_DSP_ACC),
|
||||
VMSTATE_UINTTL(DSPControl, TCState),
|
||||
VMSTATE_INT32(CP0_TCStatus, TCState),
|
||||
VMSTATE_INT32(CP0_TCBind, TCState),
|
||||
VMSTATE_UINTTL(CP0_TCHalt, TCState),
|
||||
VMSTATE_UINTTL(CP0_TCContext, TCState),
|
||||
VMSTATE_UINTTL(CP0_TCSchedule, TCState),
|
||||
VMSTATE_UINTTL(CP0_TCScheFBack, TCState),
|
||||
VMSTATE_INT32(CP0_Debug_tcstatus, TCState),
|
||||
VMSTATE_UINTTL(CP0_UserLocal, TCState),
|
||||
VMSTATE_INT32(msacsr, TCState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
};
|
||||
|
||||
const VMStateDescription vmstate_tc = {
|
||||
.name = "cpu/tc",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = vmstate_tc_fields
|
||||
};
|
||||
|
||||
const VMStateDescription vmstate_inactive_tc = {
|
||||
.name = "cpu/inactive_tc",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = vmstate_tc_fields
|
||||
};
|
||||
|
||||
/* MVP state */
|
||||
|
||||
const VMStateDescription vmstate_mvp = {
|
||||
.name = "cpu/mvp",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_INT32(CP0_MVPControl, CPUMIPSMVPContext),
|
||||
VMSTATE_INT32(CP0_MVPConf0, CPUMIPSMVPContext),
|
||||
VMSTATE_INT32(CP0_MVPConf1, CPUMIPSMVPContext),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
/* TLB state */
|
||||
|
||||
static int get_tlb(QEMUFile *f, void *pv, size_t size)
|
||||
{
|
||||
r4k_tlb_t *v = pv;
|
||||
uint16_t flags;
|
||||
|
||||
qemu_get_betls(f, &v->VPN);
|
||||
qemu_get_be32s(f, &v->PageMask);
|
||||
qemu_get_be16s(f, &v->ASID);
|
||||
qemu_get_be16s(f, &flags);
|
||||
v->G = (flags >> 10) & 1;
|
||||
v->C0 = (flags >> 7) & 3;
|
||||
v->C1 = (flags >> 4) & 3;
|
||||
v->V0 = (flags >> 3) & 1;
|
||||
v->V1 = (flags >> 2) & 1;
|
||||
v->D0 = (flags >> 1) & 1;
|
||||
v->D1 = (flags >> 0) & 1;
|
||||
v->EHINV = (flags >> 15) & 1;
|
||||
v->RI1 = (flags >> 14) & 1;
|
||||
v->RI0 = (flags >> 13) & 1;
|
||||
v->XI1 = (flags >> 12) & 1;
|
||||
v->XI0 = (flags >> 11) & 1;
|
||||
qemu_get_be64s(f, &v->PFN[0]);
|
||||
qemu_get_be64s(f, &v->PFN[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void put_tlb(QEMUFile *f, void *pv, size_t size)
|
||||
{
|
||||
r4k_tlb_t *v = pv;
|
||||
|
||||
uint16_t asid = v->ASID;
|
||||
uint16_t flags = ((v->EHINV << 15) |
|
||||
(v->RI1 << 14) |
|
||||
(v->RI0 << 13) |
|
||||
(v->XI1 << 12) |
|
||||
(v->XI0 << 11) |
|
||||
(v->G << 10) |
|
||||
(v->C0 << 7) |
|
||||
(v->C1 << 4) |
|
||||
(v->V0 << 3) |
|
||||
(v->V1 << 2) |
|
||||
(v->D0 << 1) |
|
||||
(v->D1 << 0));
|
||||
|
||||
qemu_put_betls(f, &v->VPN);
|
||||
qemu_put_be32s(f, &v->PageMask);
|
||||
qemu_put_be16s(f, &asid);
|
||||
qemu_put_be16s(f, &flags);
|
||||
qemu_put_be64s(f, &v->PFN[0]);
|
||||
qemu_put_be64s(f, &v->PFN[1]);
|
||||
}
|
||||
|
||||
const VMStateInfo vmstate_info_tlb = {
|
||||
.name = "tlb_entry",
|
||||
.get = get_tlb,
|
||||
.put = put_tlb,
|
||||
};
|
||||
|
||||
#define VMSTATE_TLB_ARRAY_V(_f, _s, _n, _v) \
|
||||
VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_tlb, r4k_tlb_t)
|
||||
|
||||
#define VMSTATE_TLB_ARRAY(_f, _s, _n) \
|
||||
VMSTATE_TLB_ARRAY_V(_f, _s, _n, 0)
|
||||
|
||||
const VMStateDescription vmstate_tlb = {
|
||||
.name = "cpu/tlb",
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32(nb_tlb, CPUMIPSTLBContext),
|
||||
VMSTATE_UINT32(tlb_in_use, CPUMIPSTLBContext),
|
||||
VMSTATE_TLB_ARRAY(mmu.r4k.tlb, CPUMIPSTLBContext, MIPS_TLB_MAX),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
/* MIPS CPU state */
|
||||
|
||||
const VMStateDescription vmstate_mips_cpu = {
|
||||
.name = "cpu",
|
||||
.version_id = 8,
|
||||
.minimum_version_id = 8,
|
||||
.post_load = cpu_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
/* Active TC */
|
||||
VMSTATE_STRUCT(env.active_tc, MIPSCPU, 1, vmstate_tc, TCState),
|
||||
|
||||
/* Active FPU */
|
||||
VMSTATE_STRUCT(env.active_fpu, MIPSCPU, 1, vmstate_fpu,
|
||||
CPUMIPSFPUContext),
|
||||
|
||||
/* MVP */
|
||||
VMSTATE_STRUCT_POINTER(env.mvp, MIPSCPU, vmstate_mvp,
|
||||
CPUMIPSMVPContext),
|
||||
|
||||
/* TLB */
|
||||
VMSTATE_STRUCT_POINTER(env.tlb, MIPSCPU, vmstate_tlb,
|
||||
CPUMIPSTLBContext),
|
||||
|
||||
/* CPU metastate */
|
||||
VMSTATE_UINT32(env.current_tc, MIPSCPU),
|
||||
VMSTATE_UINT32(env.current_fpu, MIPSCPU),
|
||||
VMSTATE_INT32(env.error_code, MIPSCPU),
|
||||
VMSTATE_UINTTL(env.btarget, MIPSCPU),
|
||||
VMSTATE_UINTTL(env.bcond, MIPSCPU),
|
||||
|
||||
/* Remaining CP0 registers */
|
||||
VMSTATE_INT32(env.CP0_Index, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_Random, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_VPEControl, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_VPEConf0, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_VPEConf1, MIPSCPU),
|
||||
VMSTATE_UINTTL(env.CP0_YQMask, MIPSCPU),
|
||||
VMSTATE_UINTTL(env.CP0_VPESchedule, MIPSCPU),
|
||||
VMSTATE_UINTTL(env.CP0_VPEScheFBack, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_VPEOpt, MIPSCPU),
|
||||
VMSTATE_UINT64(env.CP0_EntryLo0, MIPSCPU),
|
||||
VMSTATE_UINT64(env.CP0_EntryLo1, MIPSCPU),
|
||||
VMSTATE_UINTTL(env.CP0_Context, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_PageMask, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_PageGrain, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_Wired, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_SRSConf0, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_SRSConf1, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_SRSConf2, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_SRSConf3, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_SRSConf4, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_HWREna, MIPSCPU),
|
||||
VMSTATE_UINTTL(env.CP0_BadVAddr, MIPSCPU),
|
||||
VMSTATE_UINT32(env.CP0_BadInstr, MIPSCPU),
|
||||
VMSTATE_UINT32(env.CP0_BadInstrP, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_Count, MIPSCPU),
|
||||
VMSTATE_UINTTL(env.CP0_EntryHi, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_Compare, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_Status, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_IntCtl, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_SRSCtl, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_SRSMap, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_Cause, MIPSCPU),
|
||||
VMSTATE_UINTTL(env.CP0_EPC, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_PRid, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_EBase, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_Config0, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_Config1, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_Config2, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_Config3, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_Config6, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_Config7, MIPSCPU),
|
||||
VMSTATE_UINT64_ARRAY(env.CP0_MAAR, MIPSCPU, MIPS_MAAR_MAX),
|
||||
VMSTATE_INT32(env.CP0_MAARI, MIPSCPU),
|
||||
VMSTATE_UINT64(env.lladdr, MIPSCPU),
|
||||
VMSTATE_UINTTL_ARRAY(env.CP0_WatchLo, MIPSCPU, 8),
|
||||
VMSTATE_INT32_ARRAY(env.CP0_WatchHi, MIPSCPU, 8),
|
||||
VMSTATE_UINTTL(env.CP0_XContext, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_Framemask, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_Debug, MIPSCPU),
|
||||
VMSTATE_UINTTL(env.CP0_DEPC, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_Performance0, MIPSCPU),
|
||||
VMSTATE_UINT64(env.CP0_TagLo, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_DataLo, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_TagHi, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_DataHi, MIPSCPU),
|
||||
VMSTATE_UINTTL(env.CP0_ErrorEPC, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_DESAVE, MIPSCPU),
|
||||
VMSTATE_UINTTL_ARRAY(env.CP0_KScratch, MIPSCPU, MIPS_KSCRATCH_NUM),
|
||||
|
||||
/* Inactive TC */
|
||||
VMSTATE_STRUCT_ARRAY(env.tcs, MIPSCPU, MIPS_SHADOW_SET_MAX, 1,
|
||||
vmstate_inactive_tc, TCState),
|
||||
VMSTATE_STRUCT_ARRAY(env.fpus, MIPSCPU, MIPS_FPU_MAX, 1,
|
||||
vmstate_inactive_fpu, CPUMIPSFPUContext),
|
||||
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
};
|
91
target/mips/mips-defs.h
Normal file
91
target/mips/mips-defs.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
#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 TARGET_PAGE_BITS 12
|
||||
#define MIPS_TLB_MAX 128
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
#define TARGET_LONG_BITS 64
|
||||
#define TARGET_PHYS_ADDR_SPACE_BITS 48
|
||||
#define TARGET_VIRT_ADDR_SPACE_BITS 48
|
||||
#else
|
||||
#define TARGET_LONG_BITS 32
|
||||
#define TARGET_PHYS_ADDR_SPACE_BITS 40
|
||||
#define TARGET_VIRT_ADDR_SPACE_BITS 32
|
||||
#endif
|
||||
|
||||
/* Masks used to mark instructions to indicate which ISA level they
|
||||
were introduced in. */
|
||||
#define ISA_MIPS1 0x00000001
|
||||
#define ISA_MIPS2 0x00000002
|
||||
#define ISA_MIPS3 0x00000004
|
||||
#define ISA_MIPS4 0x00000008
|
||||
#define ISA_MIPS5 0x00000010
|
||||
#define ISA_MIPS32 0x00000020
|
||||
#define ISA_MIPS32R2 0x00000040
|
||||
#define ISA_MIPS64 0x00000080
|
||||
#define ISA_MIPS64R2 0x00000100
|
||||
#define ISA_MIPS32R3 0x00000200
|
||||
#define ISA_MIPS64R3 0x00000400
|
||||
#define ISA_MIPS32R5 0x00000800
|
||||
#define ISA_MIPS64R5 0x00001000
|
||||
#define ISA_MIPS32R6 0x00002000
|
||||
#define ISA_MIPS64R6 0x00004000
|
||||
|
||||
/* MIPS ASEs. */
|
||||
#define ASE_MIPS16 0x00010000
|
||||
#define ASE_MIPS3D 0x00020000
|
||||
#define ASE_MDMX 0x00040000
|
||||
#define ASE_DSP 0x00080000
|
||||
#define ASE_DSPR2 0x00100000
|
||||
#define ASE_MT 0x00200000
|
||||
#define ASE_SMARTMIPS 0x00400000
|
||||
#define ASE_MICROMIPS 0x00800000
|
||||
#define ASE_MSA 0x01000000
|
||||
|
||||
/* Chip specific instructions. */
|
||||
#define INSN_LOONGSON2E 0x20000000
|
||||
#define INSN_LOONGSON2F 0x40000000
|
||||
#define INSN_VR54XX 0x80000000
|
||||
|
||||
/* MIPS CPU defines. */
|
||||
#define CPU_MIPS1 (ISA_MIPS1)
|
||||
#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_LOONGSON2E (CPU_MIPS3 | INSN_LOONGSON2E)
|
||||
#define CPU_LOONGSON2F (CPU_MIPS3 | INSN_LOONGSON2F)
|
||||
|
||||
#define CPU_MIPS5 (CPU_MIPS4 | ISA_MIPS5)
|
||||
|
||||
/* MIPS Technologies "Release 1" */
|
||||
#define CPU_MIPS32 (CPU_MIPS2 | ISA_MIPS32)
|
||||
#define CPU_MIPS64 (CPU_MIPS5 | CPU_MIPS32 | ISA_MIPS64)
|
||||
|
||||
/* MIPS Technologies "Release 2" */
|
||||
#define CPU_MIPS32R2 (CPU_MIPS32 | ISA_MIPS32R2)
|
||||
#define CPU_MIPS64R2 (CPU_MIPS64 | CPU_MIPS32R2 | ISA_MIPS64R2)
|
||||
|
||||
/* MIPS Technologies "Release 3" */
|
||||
#define CPU_MIPS32R3 (CPU_MIPS32R2 | ISA_MIPS32R3)
|
||||
#define CPU_MIPS64R3 (CPU_MIPS64R2 | CPU_MIPS32R3 | ISA_MIPS64R3)
|
||||
|
||||
/* MIPS Technologies "Release 5" */
|
||||
#define CPU_MIPS32R5 (CPU_MIPS32R3 | ISA_MIPS32R5)
|
||||
#define CPU_MIPS64R5 (CPU_MIPS64R3 | CPU_MIPS32R5 | ISA_MIPS64R5)
|
||||
|
||||
/* MIPS Technologies "Release 6" */
|
||||
#define CPU_MIPS32R6 (CPU_MIPS32R5 | ISA_MIPS32R6)
|
||||
#define CPU_MIPS64R6 (CPU_MIPS64R5 | CPU_MIPS32R6 | ISA_MIPS64R6)
|
||||
|
||||
/* Strictly follow the architecture standard:
|
||||
- Disallow "special" instruction handling for PMON/SPIM.
|
||||
Note that we still maintain Count/Compare to match the host clock. */
|
||||
//#define MIPS_STRICT_STANDARD 1
|
||||
|
||||
#endif /* QEMU_MIPS_DEFS_H */
|
374
target/mips/mips-semi.c
Normal file
374
target/mips/mips-semi.c
Normal file
|
@ -0,0 +1,374 @@
|
|||
/*
|
||||
* Unified Hosting Interface syscalls.
|
||||
*
|
||||
* Copyright (c) 2015 Imagination Technologies
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "qemu/log.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/softmmu-semi.h"
|
||||
#include "exec/semihost.h"
|
||||
|
||||
typedef enum UHIOp {
|
||||
UHI_exit = 1,
|
||||
UHI_open = 2,
|
||||
UHI_close = 3,
|
||||
UHI_read = 4,
|
||||
UHI_write = 5,
|
||||
UHI_lseek = 6,
|
||||
UHI_unlink = 7,
|
||||
UHI_fstat = 8,
|
||||
UHI_argc = 9,
|
||||
UHI_argnlen = 10,
|
||||
UHI_argn = 11,
|
||||
UHI_plog = 13,
|
||||
UHI_assert = 14,
|
||||
UHI_pread = 19,
|
||||
UHI_pwrite = 20,
|
||||
UHI_link = 22
|
||||
} UHIOp;
|
||||
|
||||
typedef struct UHIStat {
|
||||
int16_t uhi_st_dev;
|
||||
uint16_t uhi_st_ino;
|
||||
uint32_t uhi_st_mode;
|
||||
uint16_t uhi_st_nlink;
|
||||
uint16_t uhi_st_uid;
|
||||
uint16_t uhi_st_gid;
|
||||
int16_t uhi_st_rdev;
|
||||
uint64_t uhi_st_size;
|
||||
uint64_t uhi_st_atime;
|
||||
uint64_t uhi_st_spare1;
|
||||
uint64_t uhi_st_mtime;
|
||||
uint64_t uhi_st_spare2;
|
||||
uint64_t uhi_st_ctime;
|
||||
uint64_t uhi_st_spare3;
|
||||
uint64_t uhi_st_blksize;
|
||||
uint64_t uhi_st_blocks;
|
||||
uint64_t uhi_st_spare4[2];
|
||||
} UHIStat;
|
||||
|
||||
enum UHIOpenFlags {
|
||||
UHIOpen_RDONLY = 0x0,
|
||||
UHIOpen_WRONLY = 0x1,
|
||||
UHIOpen_RDWR = 0x2,
|
||||
UHIOpen_APPEND = 0x8,
|
||||
UHIOpen_CREAT = 0x200,
|
||||
UHIOpen_TRUNC = 0x400,
|
||||
UHIOpen_EXCL = 0x800
|
||||
};
|
||||
|
||||
/* Errno values taken from asm-mips/errno.h */
|
||||
static uint16_t host_to_mips_errno[] = {
|
||||
[ENAMETOOLONG] = 78,
|
||||
#ifdef EOVERFLOW
|
||||
[EOVERFLOW] = 79,
|
||||
#endif
|
||||
#ifdef ELOOP
|
||||
[ELOOP] = 90,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int errno_mips(int err)
|
||||
{
|
||||
if (err < 0 || err >= ARRAY_SIZE(host_to_mips_errno)) {
|
||||
return EINVAL;
|
||||
} else if (host_to_mips_errno[err]) {
|
||||
return host_to_mips_errno[err];
|
||||
} else {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
static int copy_stat_to_target(CPUMIPSState *env, const struct stat *src,
|
||||
target_ulong vaddr)
|
||||
{
|
||||
hwaddr len = sizeof(struct UHIStat);
|
||||
UHIStat *dst = lock_user(VERIFY_WRITE, vaddr, len, 0);
|
||||
if (!dst) {
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
dst->uhi_st_dev = tswap16(src->st_dev);
|
||||
dst->uhi_st_ino = tswap16(src->st_ino);
|
||||
dst->uhi_st_mode = tswap32(src->st_mode);
|
||||
dst->uhi_st_nlink = tswap16(src->st_nlink);
|
||||
dst->uhi_st_uid = tswap16(src->st_uid);
|
||||
dst->uhi_st_gid = tswap16(src->st_gid);
|
||||
dst->uhi_st_rdev = tswap16(src->st_rdev);
|
||||
dst->uhi_st_size = tswap64(src->st_size);
|
||||
dst->uhi_st_atime = tswap64(src->st_atime);
|
||||
dst->uhi_st_mtime = tswap64(src->st_mtime);
|
||||
dst->uhi_st_ctime = tswap64(src->st_ctime);
|
||||
#ifdef _WIN32
|
||||
dst->uhi_st_blksize = 0;
|
||||
dst->uhi_st_blocks = 0;
|
||||
#else
|
||||
dst->uhi_st_blksize = tswap64(src->st_blksize);
|
||||
dst->uhi_st_blocks = tswap64(src->st_blocks);
|
||||
#endif
|
||||
unlock_user(dst, vaddr, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_open_flags(target_ulong target_flags)
|
||||
{
|
||||
int open_flags = 0;
|
||||
|
||||
if (target_flags & UHIOpen_RDWR) {
|
||||
open_flags |= O_RDWR;
|
||||
} else if (target_flags & UHIOpen_WRONLY) {
|
||||
open_flags |= O_WRONLY;
|
||||
} else {
|
||||
open_flags |= O_RDONLY;
|
||||
}
|
||||
|
||||
open_flags |= (target_flags & UHIOpen_APPEND) ? O_APPEND : 0;
|
||||
open_flags |= (target_flags & UHIOpen_CREAT) ? O_CREAT : 0;
|
||||
open_flags |= (target_flags & UHIOpen_TRUNC) ? O_TRUNC : 0;
|
||||
open_flags |= (target_flags & UHIOpen_EXCL) ? O_EXCL : 0;
|
||||
|
||||
return open_flags;
|
||||
}
|
||||
|
||||
static int write_to_file(CPUMIPSState *env, target_ulong fd, target_ulong vaddr,
|
||||
target_ulong len, target_ulong offset)
|
||||
{
|
||||
int num_of_bytes;
|
||||
void *dst = lock_user(VERIFY_READ, vaddr, len, 1);
|
||||
if (!dst) {
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (offset) {
|
||||
#ifdef _WIN32
|
||||
num_of_bytes = 0;
|
||||
#else
|
||||
num_of_bytes = pwrite(fd, dst, len, offset);
|
||||
#endif
|
||||
} else {
|
||||
num_of_bytes = write(fd, dst, len);
|
||||
}
|
||||
|
||||
unlock_user(dst, vaddr, 0);
|
||||
return num_of_bytes;
|
||||
}
|
||||
|
||||
static int read_from_file(CPUMIPSState *env, target_ulong fd,
|
||||
target_ulong vaddr, target_ulong len,
|
||||
target_ulong offset)
|
||||
{
|
||||
int num_of_bytes;
|
||||
void *dst = lock_user(VERIFY_WRITE, vaddr, len, 0);
|
||||
if (!dst) {
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (offset) {
|
||||
#ifdef _WIN32
|
||||
num_of_bytes = 0;
|
||||
#else
|
||||
num_of_bytes = pread(fd, dst, len, offset);
|
||||
#endif
|
||||
} else {
|
||||
num_of_bytes = read(fd, dst, len);
|
||||
}
|
||||
|
||||
unlock_user(dst, vaddr, len);
|
||||
return num_of_bytes;
|
||||
}
|
||||
|
||||
static int copy_argn_to_target(CPUMIPSState *env, int arg_num,
|
||||
target_ulong vaddr)
|
||||
{
|
||||
int strsize = strlen(semihosting_get_arg(arg_num)) + 1;
|
||||
char *dst = lock_user(VERIFY_WRITE, vaddr, strsize, 0);
|
||||
if (!dst) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(dst, semihosting_get_arg(arg_num));
|
||||
|
||||
unlock_user(dst, vaddr, strsize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define GET_TARGET_STRING(p, addr) \
|
||||
do { \
|
||||
p = lock_user_string(addr); \
|
||||
if (!p) { \
|
||||
gpr[2] = -1; \
|
||||
gpr[3] = EFAULT; \
|
||||
goto uhi_done; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define GET_TARGET_STRINGS_2(p, addr, p2, addr2) \
|
||||
do { \
|
||||
p = lock_user_string(addr); \
|
||||
if (!p) { \
|
||||
gpr[2] = -1; \
|
||||
gpr[3] = EFAULT; \
|
||||
goto uhi_done; \
|
||||
} \
|
||||
p2 = lock_user_string(addr2); \
|
||||
if (!p2) { \
|
||||
unlock_user(p, addr, 0); \
|
||||
gpr[2] = -1; \
|
||||
gpr[3] = EFAULT; \
|
||||
goto uhi_done; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FREE_TARGET_STRING(p, gpr) \
|
||||
do { \
|
||||
unlock_user(p, gpr, 0); \
|
||||
} while (0)
|
||||
|
||||
void helper_do_semihosting(CPUMIPSState *env)
|
||||
{
|
||||
target_ulong *gpr = env->active_tc.gpr;
|
||||
const UHIOp op = gpr[25];
|
||||
char *p, *p2;
|
||||
|
||||
switch (op) {
|
||||
case UHI_exit:
|
||||
qemu_log("UHI(%d): exit(%d)\n", op, (int)gpr[4]);
|
||||
exit(gpr[4]);
|
||||
case UHI_open:
|
||||
GET_TARGET_STRING(p, gpr[4]);
|
||||
if (!strcmp("/dev/stdin", p)) {
|
||||
gpr[2] = 0;
|
||||
} else if (!strcmp("/dev/stdout", p)) {
|
||||
gpr[2] = 1;
|
||||
} else if (!strcmp("/dev/stderr", p)) {
|
||||
gpr[2] = 2;
|
||||
} else {
|
||||
gpr[2] = open(p, get_open_flags(gpr[5]), gpr[6]);
|
||||
gpr[3] = errno_mips(errno);
|
||||
}
|
||||
FREE_TARGET_STRING(p, gpr[4]);
|
||||
break;
|
||||
case UHI_close:
|
||||
if (gpr[4] < 3) {
|
||||
/* ignore closing stdin/stdout/stderr */
|
||||
gpr[2] = 0;
|
||||
goto uhi_done;
|
||||
}
|
||||
gpr[2] = close(gpr[4]);
|
||||
gpr[3] = errno_mips(errno);
|
||||
break;
|
||||
case UHI_read:
|
||||
gpr[2] = read_from_file(env, gpr[4], gpr[5], gpr[6], 0);
|
||||
gpr[3] = errno_mips(errno);
|
||||
break;
|
||||
case UHI_write:
|
||||
gpr[2] = write_to_file(env, gpr[4], gpr[5], gpr[6], 0);
|
||||
gpr[3] = errno_mips(errno);
|
||||
break;
|
||||
case UHI_lseek:
|
||||
gpr[2] = lseek(gpr[4], gpr[5], gpr[6]);
|
||||
gpr[3] = errno_mips(errno);
|
||||
break;
|
||||
case UHI_unlink:
|
||||
GET_TARGET_STRING(p, gpr[4]);
|
||||
gpr[2] = remove(p);
|
||||
gpr[3] = errno_mips(errno);
|
||||
FREE_TARGET_STRING(p, gpr[4]);
|
||||
break;
|
||||
case UHI_fstat:
|
||||
{
|
||||
struct stat sbuf;
|
||||
memset(&sbuf, 0, sizeof(sbuf));
|
||||
gpr[2] = fstat(gpr[4], &sbuf);
|
||||
gpr[3] = errno_mips(errno);
|
||||
if (gpr[2]) {
|
||||
goto uhi_done;
|
||||
}
|
||||
gpr[2] = copy_stat_to_target(env, &sbuf, gpr[5]);
|
||||
gpr[3] = errno_mips(errno);
|
||||
}
|
||||
break;
|
||||
case UHI_argc:
|
||||
gpr[2] = semihosting_get_argc();
|
||||
break;
|
||||
case UHI_argnlen:
|
||||
if (gpr[4] >= semihosting_get_argc()) {
|
||||
gpr[2] = -1;
|
||||
goto uhi_done;
|
||||
}
|
||||
gpr[2] = strlen(semihosting_get_arg(gpr[4]));
|
||||
break;
|
||||
case UHI_argn:
|
||||
if (gpr[4] >= semihosting_get_argc()) {
|
||||
gpr[2] = -1;
|
||||
goto uhi_done;
|
||||
}
|
||||
gpr[2] = copy_argn_to_target(env, gpr[4], gpr[5]);
|
||||
break;
|
||||
case UHI_plog:
|
||||
GET_TARGET_STRING(p, gpr[4]);
|
||||
p2 = strstr(p, "%d");
|
||||
if (p2) {
|
||||
int char_num = p2 - p;
|
||||
char *buf = g_malloc(char_num + 1);
|
||||
strncpy(buf, p, char_num);
|
||||
buf[char_num] = '\0';
|
||||
gpr[2] = printf("%s%d%s", buf, (int)gpr[5], p2 + 2);
|
||||
g_free(buf);
|
||||
} else {
|
||||
gpr[2] = printf("%s", p);
|
||||
}
|
||||
FREE_TARGET_STRING(p, gpr[4]);
|
||||
break;
|
||||
case UHI_assert:
|
||||
GET_TARGET_STRINGS_2(p, gpr[4], p2, gpr[5]);
|
||||
printf("assertion '");
|
||||
printf("\"%s\"", p);
|
||||
printf("': file \"%s\", line %d\n", p2, (int)gpr[6]);
|
||||
FREE_TARGET_STRING(p2, gpr[5]);
|
||||
FREE_TARGET_STRING(p, gpr[4]);
|
||||
abort();
|
||||
break;
|
||||
case UHI_pread:
|
||||
gpr[2] = read_from_file(env, gpr[4], gpr[5], gpr[6], gpr[7]);
|
||||
gpr[3] = errno_mips(errno);
|
||||
break;
|
||||
case UHI_pwrite:
|
||||
gpr[2] = write_to_file(env, gpr[4], gpr[5], gpr[6], gpr[7]);
|
||||
gpr[3] = errno_mips(errno);
|
||||
break;
|
||||
#ifndef _WIN32
|
||||
case UHI_link:
|
||||
GET_TARGET_STRINGS_2(p, gpr[4], p2, gpr[5]);
|
||||
gpr[2] = link(p, p2);
|
||||
gpr[3] = errno_mips(errno);
|
||||
FREE_TARGET_STRING(p2, gpr[5]);
|
||||
FREE_TARGET_STRING(p, gpr[4]);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(stderr, "Unknown UHI operation %d\n", op);
|
||||
abort();
|
||||
}
|
||||
uhi_done:
|
||||
return;
|
||||
}
|
3453
target/mips/msa_helper.c
Normal file
3453
target/mips/msa_helper.c
Normal file
File diff suppressed because it is too large
Load diff
4196
target/mips/op_helper.c
Normal file
4196
target/mips/op_helper.c
Normal file
File diff suppressed because it is too large
Load diff
20423
target/mips/translate.c
Normal file
20423
target/mips/translate.c
Normal file
File diff suppressed because it is too large
Load diff
944
target/mips/translate_init.c
Normal file
944
target/mips/translate_init.c
Normal file
|
@ -0,0 +1,944 @@
|
|||
/*
|
||||
* MIPS emulation for qemu: CPU initialisation routines.
|
||||
*
|
||||
* Copyright (c) 2004-2005 Jocelyn Mayer
|
||||
* Copyright (c) 2007 Herve Poussineau
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* CPU / CPU family specific config register values. */
|
||||
|
||||
/* Have config1, uncached coherency */
|
||||
#define MIPS_CONFIG0 \
|
||||
((1U << CP0C0_M) | (0x2 << CP0C0_K0))
|
||||
|
||||
/* Have config2, no coprocessor2 attached, no MDMX support attached,
|
||||
no performance counters, watch registers present,
|
||||
no code compression, EJTAG present, no FPU */
|
||||
#define MIPS_CONFIG1 \
|
||||
((1U << CP0C1_M) | \
|
||||
(0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) | \
|
||||
(1 << CP0C1_WR) | (0 << CP0C1_CA) | (1 << CP0C1_EP) | \
|
||||
(0 << CP0C1_FP))
|
||||
|
||||
/* Have config3, no tertiary/secondary caches implemented */
|
||||
#define MIPS_CONFIG2 \
|
||||
((1U << CP0C2_M))
|
||||
|
||||
/* No config4, no DSP ASE, no large physaddr (PABITS),
|
||||
no external interrupt controller, no vectored interrupts,
|
||||
no 1kb pages, no SmartMIPS ASE, no trace logic */
|
||||
#define MIPS_CONFIG3 \
|
||||
((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) | \
|
||||
(0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) | \
|
||||
(0 << CP0C3_SM) | (0 << CP0C3_TL))
|
||||
|
||||
#define MIPS_CONFIG4 \
|
||||
((0 << CP0C4_M))
|
||||
|
||||
#define MIPS_CONFIG5 \
|
||||
((0 << CP0C5_M))
|
||||
|
||||
/* MMU types, the first four entries have the same layout as the
|
||||
CP0C0_MT field. */
|
||||
enum mips_mmu_types {
|
||||
MMU_TYPE_NONE,
|
||||
MMU_TYPE_R4000,
|
||||
MMU_TYPE_RESERVED,
|
||||
MMU_TYPE_FMT,
|
||||
MMU_TYPE_R3000,
|
||||
MMU_TYPE_R6000,
|
||||
MMU_TYPE_R8000
|
||||
};
|
||||
|
||||
struct mips_def_t {
|
||||
const char *name;
|
||||
int32_t CP0_PRid;
|
||||
int32_t CP0_Config0;
|
||||
int32_t CP0_Config1;
|
||||
int32_t CP0_Config2;
|
||||
int32_t CP0_Config3;
|
||||
int32_t CP0_Config4;
|
||||
int32_t CP0_Config4_rw_bitmask;
|
||||
int32_t CP0_Config5;
|
||||
int32_t CP0_Config5_rw_bitmask;
|
||||
int32_t CP0_Config6;
|
||||
int32_t CP0_Config7;
|
||||
target_ulong CP0_LLAddr_rw_bitmask;
|
||||
int CP0_LLAddr_shift;
|
||||
int32_t SYNCI_Step;
|
||||
int32_t CCRes;
|
||||
int32_t CP0_Status_rw_bitmask;
|
||||
int32_t CP0_TCStatus_rw_bitmask;
|
||||
int32_t CP0_SRSCtl;
|
||||
int32_t CP1_fcr0;
|
||||
int32_t CP1_fcr31_rw_bitmask;
|
||||
int32_t CP1_fcr31;
|
||||
int32_t MSAIR;
|
||||
int32_t SEGBITS;
|
||||
int32_t PABITS;
|
||||
int32_t CP0_SRSConf0_rw_bitmask;
|
||||
int32_t CP0_SRSConf0;
|
||||
int32_t CP0_SRSConf1_rw_bitmask;
|
||||
int32_t CP0_SRSConf1;
|
||||
int32_t CP0_SRSConf2_rw_bitmask;
|
||||
int32_t CP0_SRSConf2;
|
||||
int32_t CP0_SRSConf3_rw_bitmask;
|
||||
int32_t CP0_SRSConf3;
|
||||
int32_t CP0_SRSConf4_rw_bitmask;
|
||||
int32_t CP0_SRSConf4;
|
||||
int32_t CP0_PageGrain_rw_bitmask;
|
||||
int32_t CP0_PageGrain;
|
||||
int insn_flags;
|
||||
enum mips_mmu_types mmu_type;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/* MIPS CPU definitions */
|
||||
static const mips_def_t mips_defs[] =
|
||||
{
|
||||
{
|
||||
.name = "4Kc",
|
||||
.CP0_PRid = 0x00018000,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU) |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(0 << CP0C1_CA),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3,
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x1278FF17,
|
||||
.SEGBITS = 32,
|
||||
.PABITS = 32,
|
||||
.insn_flags = CPU_MIPS32,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.name = "4Km",
|
||||
.CP0_PRid = 0x00018300,
|
||||
/* Config1 implemented, fixed mapping MMU,
|
||||
no virtual icache, uncached coherency. */
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (MMU_TYPE_FMT << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_CA),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3,
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x1258FF17,
|
||||
.SEGBITS = 32,
|
||||
.PABITS = 32,
|
||||
.insn_flags = CPU_MIPS32 | ASE_MIPS16,
|
||||
.mmu_type = MMU_TYPE_FMT,
|
||||
},
|
||||
{
|
||||
.name = "4KEcR1",
|
||||
.CP0_PRid = 0x00018400,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU) |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(0 << CP0C1_CA),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3,
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x1278FF17,
|
||||
.SEGBITS = 32,
|
||||
.PABITS = 32,
|
||||
.insn_flags = CPU_MIPS32,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.name = "4KEmR1",
|
||||
.CP0_PRid = 0x00018500,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (MMU_TYPE_FMT << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_CA),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3,
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x1258FF17,
|
||||
.SEGBITS = 32,
|
||||
.PABITS = 32,
|
||||
.insn_flags = CPU_MIPS32 | ASE_MIPS16,
|
||||
.mmu_type = MMU_TYPE_FMT,
|
||||
},
|
||||
{
|
||||
.name = "4KEc",
|
||||
.CP0_PRid = 0x00019000,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU) |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(0 << CP0C1_CA),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt),
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x1278FF17,
|
||||
.SEGBITS = 32,
|
||||
.PABITS = 32,
|
||||
.insn_flags = CPU_MIPS32R2,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.name = "4KEm",
|
||||
.CP0_PRid = 0x00019100,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
|
||||
(MMU_TYPE_FMT << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_CA),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3,
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x1258FF17,
|
||||
.SEGBITS = 32,
|
||||
.PABITS = 32,
|
||||
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16,
|
||||
.mmu_type = MMU_TYPE_FMT,
|
||||
},
|
||||
{
|
||||
.name = "24Kc",
|
||||
.CP0_PRid = 0x00019300,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU) |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_CA),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt),
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
/* No DSP implemented. */
|
||||
.CP0_Status_rw_bitmask = 0x1278FF1F,
|
||||
.SEGBITS = 32,
|
||||
.PABITS = 32,
|
||||
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.name = "24KEc",
|
||||
.CP0_PRid = 0x00019600,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU) |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_CA),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_DSPP) | (0 << CP0C3_VInt),
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
/* we have a DSP, but no FPU */
|
||||
.CP0_Status_rw_bitmask = 0x1378FF1F,
|
||||
.SEGBITS = 32,
|
||||
.PABITS = 32,
|
||||
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.name = "24Kf",
|
||||
.CP0_PRid = 0x00019300,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_CA),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt),
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
/* No DSP implemented. */
|
||||
.CP0_Status_rw_bitmask = 0x3678FF1F,
|
||||
.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
|
||||
(1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
|
||||
.CP1_fcr31 = 0,
|
||||
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
|
||||
.SEGBITS = 32,
|
||||
.PABITS = 32,
|
||||
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.name = "34Kf",
|
||||
.CP0_PRid = 0x00019500,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_CA),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_VInt) | (1 << CP0C3_MT) |
|
||||
(1 << CP0C3_DSPP),
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 0,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x3778FF1F,
|
||||
.CP0_TCStatus_rw_bitmask = (0 << CP0TCSt_TCU3) | (0 << CP0TCSt_TCU2) |
|
||||
(1 << CP0TCSt_TCU1) | (1 << CP0TCSt_TCU0) |
|
||||
(0 << CP0TCSt_TMX) | (1 << CP0TCSt_DT) |
|
||||
(1 << CP0TCSt_DA) | (1 << CP0TCSt_A) |
|
||||
(0x3 << CP0TCSt_TKSU) | (1 << CP0TCSt_IXMT) |
|
||||
(0xff << CP0TCSt_TASID),
|
||||
.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
|
||||
(1 << FCR0_D) | (1 << FCR0_S) | (0x95 << FCR0_PRID),
|
||||
.CP1_fcr31 = 0,
|
||||
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
|
||||
.CP0_SRSCtl = (0xf << CP0SRSCtl_HSS),
|
||||
.CP0_SRSConf0_rw_bitmask = 0x3fffffff,
|
||||
.CP0_SRSConf0 = (1U << CP0SRSC0_M) | (0x3fe << CP0SRSC0_SRS3) |
|
||||
(0x3fe << CP0SRSC0_SRS2) | (0x3fe << CP0SRSC0_SRS1),
|
||||
.CP0_SRSConf1_rw_bitmask = 0x3fffffff,
|
||||
.CP0_SRSConf1 = (1U << CP0SRSC1_M) | (0x3fe << CP0SRSC1_SRS6) |
|
||||
(0x3fe << CP0SRSC1_SRS5) | (0x3fe << CP0SRSC1_SRS4),
|
||||
.CP0_SRSConf2_rw_bitmask = 0x3fffffff,
|
||||
.CP0_SRSConf2 = (1U << CP0SRSC2_M) | (0x3fe << CP0SRSC2_SRS9) |
|
||||
(0x3fe << CP0SRSC2_SRS8) | (0x3fe << CP0SRSC2_SRS7),
|
||||
.CP0_SRSConf3_rw_bitmask = 0x3fffffff,
|
||||
.CP0_SRSConf3 = (1U << CP0SRSC3_M) | (0x3fe << CP0SRSC3_SRS12) |
|
||||
(0x3fe << CP0SRSC3_SRS11) | (0x3fe << CP0SRSC3_SRS10),
|
||||
.CP0_SRSConf4_rw_bitmask = 0x3fffffff,
|
||||
.CP0_SRSConf4 = (0x3fe << CP0SRSC4_SRS15) |
|
||||
(0x3fe << CP0SRSC4_SRS14) | (0x3fe << CP0SRSC4_SRS13),
|
||||
.SEGBITS = 32,
|
||||
.PABITS = 32,
|
||||
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_MT,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.name = "74Kf",
|
||||
.CP0_PRid = 0x00019700,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_CA),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_DSP2P) | (1 << CP0C3_DSPP) |
|
||||
(1 << CP0C3_VInt),
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x3778FF1F,
|
||||
.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
|
||||
(1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
|
||||
.CP1_fcr31 = 0,
|
||||
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
|
||||
.SEGBITS = 32,
|
||||
.PABITS = 32,
|
||||
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.name = "M14K",
|
||||
.CP0_PRid = 0x00019b00,
|
||||
/* Config1 implemented, fixed mapping MMU,
|
||||
no virtual icache, uncached coherency. */
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_KU) | (0x2 << CP0C0_K23) |
|
||||
(0x1 << CP0C0_AR) | (MMU_TYPE_FMT << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1,
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3 | (0x2 << CP0C3_ISA) | (1 << CP0C3_VInt),
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x1258FF17,
|
||||
.SEGBITS = 32,
|
||||
.PABITS = 32,
|
||||
.insn_flags = CPU_MIPS32R2 | ASE_MICROMIPS,
|
||||
.mmu_type = MMU_TYPE_FMT,
|
||||
},
|
||||
{
|
||||
.name = "M14Kc",
|
||||
/* This is the TLB-based MMU core. */
|
||||
.CP0_PRid = 0x00019c00,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU) |
|
||||
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3 | (0x2 << CP0C3_ISA) | (0 << CP0C3_VInt),
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x1278FF17,
|
||||
.SEGBITS = 32,
|
||||
.PABITS = 32,
|
||||
.insn_flags = CPU_MIPS32R2 | ASE_MICROMIPS,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
/* FIXME:
|
||||
* Config3: CMGCR, SC, PW, VZ, CTXTC, CDMM, TL
|
||||
* Config4: MMUExtDef
|
||||
* Config5: EVA, MRP
|
||||
* FIR(FCR0): Has2008
|
||||
* */
|
||||
.name = "P5600",
|
||||
.CP0_PRid = 0x0001A800,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (1 << CP0C0_MM) | (1 << CP0C0_AR) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (0x3F << CP0C1_MMU) |
|
||||
(2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
|
||||
(2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
|
||||
(1 << CP0C1_PC) | (1 << CP0C1_FP),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP) |
|
||||
(1 << CP0C3_BP) | (1 << CP0C3_BI) | (1 << CP0C3_ULRI) |
|
||||
(1 << CP0C3_RXI) | (1 << CP0C3_LPA) | (1 << CP0C3_VInt),
|
||||
.CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (2 << CP0C4_IE) |
|
||||
(0x1c << CP0C4_KScrExist),
|
||||
.CP0_Config4_rw_bitmask = 0,
|
||||
.CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_MVH) | (1 << CP0C5_LLB) |
|
||||
(1 << CP0C5_MRP),
|
||||
.CP0_Config5_rw_bitmask = (1 << CP0C5_K) | (1 << CP0C5_CV) |
|
||||
(1 << CP0C5_MSAEn) | (1 << CP0C5_UFE) |
|
||||
(1 << CP0C5_FRE) | (1 << CP0C5_UFR),
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 0,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x3C68FF1F,
|
||||
.CP0_PageGrain_rw_bitmask = (1U << CP0PG_RIE) | (1 << CP0PG_XIE) |
|
||||
(1 << CP0PG_ELPA) | (1 << CP0PG_IEC),
|
||||
.CP1_fcr0 = (1 << FCR0_FREP) | (1 << FCR0_UFRP) | (1 << FCR0_HAS2008) |
|
||||
(1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
|
||||
(1 << FCR0_D) | (1 << FCR0_S) | (0x03 << FCR0_PRID),
|
||||
.CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008),
|
||||
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
|
||||
.SEGBITS = 32,
|
||||
.PABITS = 40,
|
||||
.insn_flags = CPU_MIPS32R5 | ASE_MSA,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
/* A generic CPU supporting MIPS32 Release 6 ISA.
|
||||
FIXME: Support IEEE 754-2008 FP.
|
||||
Eventually this should be replaced by a real CPU model. */
|
||||
.name = "mips32r6-generic",
|
||||
.CP0_PRid = 0x00010000,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AR) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (31 << CP0C1_MMU) |
|
||||
(2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
|
||||
(2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
|
||||
(0 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_BP) | (1 << CP0C3_BI) |
|
||||
(2 << CP0C3_ISA) | (1 << CP0C3_ULRI) |
|
||||
(1 << CP0C3_RXI) | (1U << CP0C3_M),
|
||||
.CP0_Config4 = MIPS_CONFIG4 | (0xfc << CP0C4_KScrExist) |
|
||||
(3 << CP0C4_IE) | (1U << CP0C4_M),
|
||||
.CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_XNP) | (1 << CP0C5_LLB),
|
||||
.CP0_Config5_rw_bitmask = (1 << CP0C5_SBRI) | (1 << CP0C5_FRE) |
|
||||
(1 << CP0C5_UFE),
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 0,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x3058FF1F,
|
||||
.CP0_PageGrain = (1 << CP0PG_IEC) | (1 << CP0PG_XIE) |
|
||||
(1U << CP0PG_RIE),
|
||||
.CP0_PageGrain_rw_bitmask = 0,
|
||||
.CP1_fcr0 = (1 << FCR0_FREP) | (1 << FCR0_HAS2008) | (1 << FCR0_F64) |
|
||||
(1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
|
||||
(1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
.CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008),
|
||||
.CP1_fcr31_rw_bitmask = 0x0103FFFF,
|
||||
.SEGBITS = 32,
|
||||
.PABITS = 32,
|
||||
.insn_flags = CPU_MIPS32R6 | ASE_MICROMIPS,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
#if defined(TARGET_MIPS64)
|
||||
{
|
||||
.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),
|
||||
/* Note: Config1 is only used internally, the R4000 has only Config0. */
|
||||
.CP0_Config1 = (1 << CP0C1_FP) | (47 << CP0C1_MMU),
|
||||
.CP0_LLAddr_rw_bitmask = 0xFFFFFFFF,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 16,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x3678FFFF,
|
||||
/* The R4000 has a full 64bit FPU but doesn't use the fcr0 bits. */
|
||||
.CP1_fcr0 = (0x5 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
.CP1_fcr31 = 0,
|
||||
.CP1_fcr31_rw_bitmask = 0x0183FFFF,
|
||||
.SEGBITS = 40,
|
||||
.PABITS = 36,
|
||||
.insn_flags = CPU_MIPS3,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.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_Config1 = (1 << CP0C1_FP) | (47 << CP0C1_MMU),
|
||||
.CP0_LLAddr_rw_bitmask = 0xFFFFFFFFL,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 16,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x3678FFFF,
|
||||
/* The VR5432 has a full 64bit FPU but doesn't use the fcr0 bits. */
|
||||
.CP1_fcr0 = (0x54 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
.CP1_fcr31 = 0,
|
||||
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
|
||||
.SEGBITS = 40,
|
||||
.PABITS = 32,
|
||||
.insn_flags = CPU_VR54XX,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.name = "5Kc",
|
||||
.CP0_PRid = 0x00018100,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (31 << CP0C1_MMU) |
|
||||
(1 << CP0C1_IS) | (4 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3,
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x12F8FFFF,
|
||||
.SEGBITS = 42,
|
||||
.PABITS = 36,
|
||||
.insn_flags = CPU_MIPS64,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.name = "5Kf",
|
||||
.CP0_PRid = 0x00018100,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (31 << CP0C1_MMU) |
|
||||
(1 << CP0C1_IS) | (4 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3,
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x36F8FFFF,
|
||||
/* The 5Kf has F64 / L / W but doesn't use the fcr0 bits. */
|
||||
.CP1_fcr0 = (1 << FCR0_D) | (1 << FCR0_S) |
|
||||
(0x81 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
.CP1_fcr31 = 0,
|
||||
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
|
||||
.SEGBITS = 42,
|
||||
.PABITS = 36,
|
||||
.insn_flags = CPU_MIPS64,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.name = "20Kc",
|
||||
/* We emulate a later version of the 20Kc, earlier ones had a broken
|
||||
WAIT instruction. */
|
||||
.CP0_PRid = 0x000182a0,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT) | (1 << CP0C0_VI),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (47 << CP0C1_MMU) |
|
||||
(2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
|
||||
(2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
|
||||
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3,
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 0,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 1,
|
||||
.CP0_Status_rw_bitmask = 0x36FBFFFF,
|
||||
/* The 20Kc has F64 / L / W but doesn't use the fcr0 bits. */
|
||||
.CP1_fcr0 = (1 << FCR0_3D) | (1 << FCR0_PS) |
|
||||
(1 << FCR0_D) | (1 << FCR0_S) |
|
||||
(0x82 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
.CP1_fcr31 = 0,
|
||||
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
|
||||
.SEGBITS = 40,
|
||||
.PABITS = 36,
|
||||
.insn_flags = CPU_MIPS64 | ASE_MIPS3D,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
/* A generic CPU providing MIPS64 Release 2 features.
|
||||
FIXME: Eventually this should be replaced by a real CPU model. */
|
||||
.name = "MIPS64R2-generic",
|
||||
.CP0_PRid = 0x00010000,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
|
||||
(2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
|
||||
(2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
|
||||
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_LPA),
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 0,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x36FBFFFF,
|
||||
.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_3D) | (1 << FCR0_PS) |
|
||||
(1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
|
||||
(1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
.CP1_fcr31 = 0,
|
||||
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
|
||||
.SEGBITS = 42,
|
||||
.PABITS = 36,
|
||||
.insn_flags = CPU_MIPS64R2 | ASE_MIPS3D,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.name = "5KEc",
|
||||
.CP0_PRid = 0x00018900,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (31 << CP0C1_MMU) |
|
||||
(1 << CP0C1_IS) | (4 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3,
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x12F8FFFF,
|
||||
.SEGBITS = 42,
|
||||
.PABITS = 36,
|
||||
.insn_flags = CPU_MIPS64R2,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.name = "5KEf",
|
||||
.CP0_PRid = 0x00018900,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (31 << CP0C1_MMU) |
|
||||
(1 << CP0C1_IS) | (4 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3,
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x36F8FFFF,
|
||||
.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
|
||||
(1 << FCR0_D) | (1 << FCR0_S) |
|
||||
(0x89 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
.SEGBITS = 42,
|
||||
.PABITS = 36,
|
||||
.insn_flags = CPU_MIPS64R2,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.name = "I6400",
|
||||
.CP0_PRid = 0x1A900,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AR) | (0x2 << CP0C0_AT) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) |
|
||||
(2 << CP0C1_IS) | (5 << CP0C1_IL) | (3 << CP0C1_IA) |
|
||||
(2 << CP0C1_DS) | (5 << CP0C1_DL) | (3 << CP0C1_DA) |
|
||||
(0 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) |
|
||||
(1 << CP0C3_CMGCR) | (1 << CP0C3_MSAP) |
|
||||
(1 << CP0C3_BP) | (1 << CP0C3_BI) | (1 << CP0C3_ULRI) |
|
||||
(1 << CP0C3_RXI) | (1 << CP0C3_LPA) | (1 << CP0C3_VInt),
|
||||
.CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (3 << CP0C4_IE) |
|
||||
(1 << CP0C4_AE) | (0xfc << CP0C4_KScrExist),
|
||||
.CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_XNP) | (1 << CP0C5_VP) |
|
||||
(1 << CP0C5_LLB) | (1 << CP0C5_MRP),
|
||||
.CP0_Config5_rw_bitmask = (1 << CP0C5_MSAEn) | (1 << CP0C5_SBRI) |
|
||||
(1 << CP0C5_FRE) | (1 << CP0C5_UFE),
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 0,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x30D8FFFF,
|
||||
.CP0_PageGrain = (1 << CP0PG_IEC) | (1 << CP0PG_XIE) |
|
||||
(1U << CP0PG_RIE),
|
||||
.CP0_PageGrain_rw_bitmask = (1 << CP0PG_ELPA),
|
||||
.CP1_fcr0 = (1 << FCR0_FREP) | (1 << FCR0_HAS2008) | (1 << FCR0_F64) |
|
||||
(1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
|
||||
(1 << FCR0_S) | (0x03 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
.CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008),
|
||||
.CP1_fcr31_rw_bitmask = 0x0103FFFF,
|
||||
.MSAIR = 0x03 << MSAIR_ProcID,
|
||||
.SEGBITS = 48,
|
||||
.PABITS = 48,
|
||||
.insn_flags = CPU_MIPS64R6 | ASE_MSA,
|
||||
.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),
|
||||
/* Note: Config1 is only used internally,
|
||||
Loongson-2E has only Config0. */
|
||||
.CP0_Config1 = (1 << CP0C1_FP) | (47 << CP0C1_MMU),
|
||||
.SYNCI_Step = 16,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x35D0FFFF,
|
||||
.CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV),
|
||||
.CP1_fcr31 = 0,
|
||||
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
|
||||
.SEGBITS = 40,
|
||||
.PABITS = 40,
|
||||
.insn_flags = CPU_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),
|
||||
/* Note: Config1 is only used internally,
|
||||
Loongson-2F has only Config0. */
|
||||
.CP0_Config1 = (1 << CP0C1_FP) | (47 << CP0C1_MMU),
|
||||
.SYNCI_Step = 16,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0xF5D0FF1F, /* Bits 7:5 not writable. */
|
||||
.CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV),
|
||||
.CP1_fcr31 = 0,
|
||||
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
|
||||
.SEGBITS = 40,
|
||||
.PABITS = 40,
|
||||
.insn_flags = CPU_LOONGSON2F,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
/* A generic CPU providing MIPS64 ASE DSP 2 features.
|
||||
FIXME: Eventually this should be replaced by a real CPU model. */
|
||||
.name = "mips64dspr2",
|
||||
.CP0_PRid = 0x00010000,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
|
||||
(2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
|
||||
(2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
|
||||
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_DSP2P) |
|
||||
(1 << CP0C3_DSPP) | (1 << CP0C3_LPA),
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 0,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x37FBFFFF,
|
||||
.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_3D) | (1 << FCR0_PS) |
|
||||
(1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
|
||||
(1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
.CP1_fcr31 = 0,
|
||||
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
|
||||
.SEGBITS = 42,
|
||||
.PABITS = 36,
|
||||
.insn_flags = CPU_MIPS64R2 | ASE_DSP | ASE_DSPR2,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
static const mips_def_t *cpu_mips_find_by_name (const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mips_defs); i++) {
|
||||
if (strcasecmp(name, mips_defs[i].name) == 0) {
|
||||
return &mips_defs[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mips_defs); i++) {
|
||||
(*cpu_fprintf)(f, "MIPS '%s'\n",
|
||||
mips_defs[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
MIPSCPU *cpu = mips_env_get_cpu(env);
|
||||
|
||||
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(CPU(cpu), "MMU type not supported\n");
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_USER_ONLY */
|
||||
|
||||
static void fpu_init (CPUMIPSState *env, const mips_def_t *def)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MIPS_FPU_MAX; i++)
|
||||
env->fpus[i].fcr0 = def->CP1_fcr0;
|
||||
|
||||
memcpy(&env->active_fpu, &env->fpus[0], sizeof(env->active_fpu));
|
||||
}
|
||||
|
||||
static void mvp_init (CPUMIPSState *env, const mips_def_t *def)
|
||||
{
|
||||
env->mvp = g_malloc0(sizeof(CPUMIPSMVPContext));
|
||||
|
||||
/* MVPConf1 implemented, TLB sharable, no gating storage support,
|
||||
programmable cache partitioning implemented, number of allocatable
|
||||
and sharable TLB entries, MVP has allocatable TCs, 2 VPEs
|
||||
implemented, 5 TCs implemented. */
|
||||
env->mvp->CP0_MVPConf0 = (1U << CP0MVPC0_M) | (1 << CP0MVPC0_TLBS) |
|
||||
(0 << CP0MVPC0_GS) | (1 << CP0MVPC0_PCP) |
|
||||
// TODO: actually do 2 VPEs.
|
||||
// (1 << CP0MVPC0_TCA) | (0x1 << CP0MVPC0_PVPE) |
|
||||
// (0x04 << CP0MVPC0_PTC);
|
||||
(1 << CP0MVPC0_TCA) | (0x0 << CP0MVPC0_PVPE) |
|
||||
(0x00 << CP0MVPC0_PTC);
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
/* Usermode has no TLB support */
|
||||
env->mvp->CP0_MVPConf0 |= (env->tlb->nb_tlb << CP0MVPC0_PTLBE);
|
||||
#endif
|
||||
|
||||
/* Allocatable CP1 have media extensions, allocatable CP1 have FP support,
|
||||
no UDI implemented, no CP2 implemented, 1 CP1 implemented. */
|
||||
env->mvp->CP0_MVPConf1 = (1U << CP0MVPC1_CIM) | (1 << CP0MVPC1_CIF) |
|
||||
(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);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue