Merge "goldfish_audio: Fix updating of status bits for output buffers" into studio-1.3-dev
diff --git a/hw/mips/mips_ranchu.c b/hw/mips/mips_ranchu.c
index 5db26ee..a6bad1d 100644
--- a/hw/mips/mips_ranchu.c
+++ b/hw/mips/mips_ranchu.c
@@ -18,6 +18,8 @@
#include "elf.h"
#include "hw/intc/goldfish_pic.h"
#include "hw/irq.h"
+#include "hw/display/goldfish_fb.h"
+#include "hw/input/goldfish_sensors.h"
#define PHYS_TO_VIRT(x) ((x) | ~(target_ulong)0x7fffffff)
@@ -34,6 +36,7 @@
#define TYPE_MIPS_RANCHU "mips-ranchu"
#define MIPS_RANCHU(obj) OBJECT_CHECK(RanchuState, (obj), TYPE_MIPS_RANCHU)
+#define MIPS_RANCHU_REV "1"
typedef struct {
SysBusDevice parent_obj;
@@ -41,6 +44,8 @@
qemu_irq *gfpic;
} RanchuState;
+#define MAX_RAM_SIZE_MB 4079UL
+
enum {
RANCHU_GF_PIC,
RANCHU_GF_TTY,
@@ -95,11 +100,48 @@
struct machine_params {
uint64_t kernel_entry;
- uint64_t ram_size;
uint64_t cmdline_ptr;
MIPSCPU *cpu;
} ranchu_params;
+static int ranchu_rotation_state = 0; /* 0-3 */
+
+static void android_console_rotate_screen(Monitor *mon, const QDict *qdict)
+{
+ ranchu_rotation_state = ((ranchu_rotation_state + 1) % 4);
+ goldfish_sensors_set_rotation(ranchu_rotation_state);
+ /* The mapping between QEMU and Android's idea of rotation are
+ reversed */
+ switch (ranchu_rotation_state) {
+ case 0:
+ goldfish_fb_set_rotation(0);
+ graphic_rotate = 0;
+ break;
+ case 1:
+ goldfish_fb_set_rotation(3);
+ graphic_rotate = 90;
+ break;
+ case 2:
+ goldfish_fb_set_rotation(2);
+ graphic_rotate = 180;
+ break;
+ case 3:
+ goldfish_fb_set_rotation(1);
+ graphic_rotate = 270;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
+static mon_cmd_t rotate_cmd = {
+ .name = "rotate",
+ .args_type = "",
+ .params = "",
+ .help = "rotate the screen by 90 degrees",
+ .mhandler.cmd = android_console_rotate_screen,
+};
+
static void main_cpu_reset(void* opaque1)
{
struct machine_params *opaque = (struct machine_params *)opaque1;
@@ -109,7 +151,7 @@
cpu->env.active_tc.PC = opaque->kernel_entry;
cpu->env.active_tc.gpr[4] = opaque->cmdline_ptr; /* a0 */
- cpu->env.active_tc.gpr[5] = opaque->ram_size; /* a1 */
+ cpu->env.active_tc.gpr[5] = 0; /* a1 */
cpu->env.active_tc.gpr[6] = 0; /* a2 */
cpu->env.active_tc.gpr[7] = 0; /* a3 */
@@ -155,6 +197,7 @@
int baseport = ANDROID_CONSOLE_BASEPORT;
int tries = MAX_ANDROID_EMULATORS;
CharDriverState *chr;
+ struct Monitor* android_monitor;
for (; tries > 0; tries--, baseport += 2) {
chr = try_to_create_console_chardev(baseport);
@@ -172,7 +215,13 @@
* This is equivalent to
* "-mon chardev=private-chardev,mode=android-console"
*/
- monitor_init(chr, MONITOR_ANDROID_CONSOLE | MONITOR_USE_READLINE);
+ /* monitor_init(chr, MONITOR_ANDROID_CONSOLE | MONITOR_USE_READLINE); */
+ android_monitor = monitor_init(chr,
+ MONITOR_ANDROID_CONSOLE |
+ MONITOR_USE_READLINE |
+ MONITOR_DYNAMIC_CMDS);
+ monitor_add_command(android_monitor,
+ &rotate_cmd);
printf("console on port %d, ADB on port %d\n", baseport, baseport + 1);
return;
@@ -286,7 +335,7 @@
qemu_fdt_setprop(fdt, nodename, "compatible",
dev->dt_compatible,
strlen(dev->dt_compatible) + 1);
- qemu_fdt_setprop_sized_cells(fdt, nodename, "reg", 1, base, 1, dev->size);
+ qemu_fdt_setprop_sized_cells(fdt, nodename, "reg", 1, base, 2, dev->size);
if (pic == NULL) {
qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0);
@@ -323,7 +372,8 @@
DeviceState *dev = qdev_create(NULL, TYPE_MIPS_RANCHU);
RanchuState *s = MIPS_RANCHU(dev);
- MemoryRegion *ram = g_new(MemoryRegion, 1);
+ MemoryRegion *ram_lo = g_new(MemoryRegion, 1);
+ MemoryRegion *ram_hi = g_new(MemoryRegion, 1);
/* init CPUs */
if (machine->cpu_model == NULL) {
@@ -351,9 +401,11 @@
qemu_register_reset(main_cpu_reset, &ranchu_params);
- /* avoid overlap of ram and IO regs */
- if (ram_size > GOLDFISH_IO_SPACE)
- ram_size = GOLDFISH_IO_SPACE;
+ if (ram_size > (MAX_RAM_SIZE_MB << 20)) {
+ fprintf(stderr, "qemu: Too much memory for this machine. "
+ "RAM size reduced to %lu MB\n", MAX_RAM_SIZE_MB);
+ ram_size = MAX_RAM_SIZE_MB << 20;
+ }
fdt = create_device_tree(&fdt_size);
@@ -362,11 +414,19 @@
exit(1);
}
- memory_region_init_ram(ram, NULL, "ranchu.ram", ram_size, &error_abort);
- vmstate_register_ram_global(ram);
- memory_region_add_subregion(get_system_memory(), 0, ram);
+ memory_region_init_ram(ram_lo, NULL, "ranchu_low.ram",
+ MIN(ram_size, GOLDFISH_IO_SPACE), &error_abort);
+ vmstate_register_ram_global(ram_lo);
+ memory_region_add_subregion(get_system_memory(), 0, ram_lo);
- ranchu_params.ram_size = ram_size;
+ /* post IO hole, if there is enough RAM */
+ if (ram_size > GOLDFISH_IO_SPACE) {
+ memory_region_init_ram(ram_hi, NULL, "ranchu_high.ram",
+ ram_size - GOLDFISH_IO_SPACE, &error_abort);
+ vmstate_register_ram_global(ram_hi);
+ memory_region_add_subregion(get_system_memory(), 0x20000000, ram_hi);
+ }
+
ranchu_params.cpu = cpu;
cpu_mips_irq_init_cpu(env);
@@ -381,9 +441,16 @@
qemu_fdt_setprop_string(fdt, "/", "model", "ranchu");
qemu_fdt_setprop_string(fdt, "/", "compatible", "mti,goldfish");
qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x1);
- qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x1);
+ qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
qemu_fdt_setprop_cell(fdt, "/", "interrupt-parent", devmap[RANCHU_GF_PIC].irq);
+ /* Firmware node */
+ qemu_fdt_add_subnode(fdt, "/firmware");
+ qemu_fdt_add_subnode(fdt, "/firmware/android");
+ qemu_fdt_setprop_string(fdt, "/firmware/android", "compatible", "android,firmware");
+ qemu_fdt_setprop_string(fdt, "/firmware/android", "hardware", "ranchu");
+ qemu_fdt_setprop_string(fdt, "/firmware/android", "revision", MIPS_RANCHU_REV);
+
/* CPU node */
qemu_fdt_add_subnode(fdt, "/cpus");
qemu_fdt_add_subnode(fdt, "/cpus/cpu@0");
@@ -393,7 +460,13 @@
/* Memory node */
qemu_fdt_add_subnode(fdt, "/memory");
qemu_fdt_setprop_string(fdt, "/memory", "device_type", "memory");
- qemu_fdt_setprop_sized_cells(fdt, "/memory", "reg", 1, 0, 1, ram_size);
+ if (ram_size > GOLDFISH_IO_SPACE) {
+ qemu_fdt_setprop_sized_cells(fdt, "/memory", "reg",
+ 1, 0, 2, GOLDFISH_IO_SPACE,
+ 1, 0x20000000, 2, ram_size - GOLDFISH_IO_SPACE);
+ } else {
+ qemu_fdt_setprop_sized_cells(fdt, "/memory", "reg", 1, 0, 2, ram_size);
+ }
/* Create goldfish_pic controller node in dt */
create_device(fdt, &devmap[RANCHU_GF_PIC], NULL, 1, 0);
@@ -411,10 +484,13 @@
initialize_console_and_adb();
- android_load_kernel(env, ram_size, machine->kernel_filename,
- machine->kernel_cmdline,
- machine->initrd_filename,
- fdt, fdt_size);
+ qemu_fdt_dumpdtb(fdt, fdt_size);
+
+ android_load_kernel(env, MIN(ram_size, GOLDFISH_IO_SPACE),
+ machine->kernel_filename,
+ machine->kernel_cmdline,
+ machine->initrd_filename,
+ fdt, fdt_size);
}
static int mips_ranchu_sysbus_device_init(SysBusDevice *sysbusdev)
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 2098f1c..3d6fb50 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -121,7 +121,8 @@
void (*do_interrupt)(CPUState *cpu);
CPUUnassignedAccess do_unassigned_access;
void (*do_unaligned_access)(CPUState *cpu, vaddr addr,
- int is_write, int is_user, uintptr_t retaddr);
+ int is_write, int is_user, uintptr_t retaddr,
+ unsigned size);
bool (*virtio_is_big_endian)(CPUState *cpu);
int (*memory_rw_debug)(CPUState *cpu, vaddr addr,
uint8_t *buf, int len, bool is_write);
@@ -576,11 +577,12 @@
static inline void cpu_unaligned_access(CPUState *cpu, vaddr addr,
int is_write, int is_user,
- uintptr_t retaddr)
+ uintptr_t retaddr, unsigned size)
{
CPUClass *cc = CPU_GET_CLASS(cpu);
- return cc->do_unaligned_access(cpu, addr, is_write, is_user, retaddr);
+ return cc->do_unaligned_access(cpu, addr, is_write, is_user, retaddr,
+ size);
}
#endif
diff --git a/softmmu_template.h b/softmmu_template.h
index 6b4e615..18548af 100644
--- a/softmmu_template.h
+++ b/softmmu_template.h
@@ -183,7 +183,7 @@
#ifdef ALIGNED_ONLY
if ((addr & (DATA_SIZE - 1)) != 0) {
cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
- mmu_idx, retaddr);
+ mmu_idx, retaddr, DATA_SIZE);
}
#endif
if (!VICTIM_TLB_HIT(ADDR_READ)) {
@@ -218,7 +218,7 @@
do_unaligned_access:
#ifdef ALIGNED_ONLY
cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
- mmu_idx, retaddr);
+ mmu_idx, retaddr, DATA_SIZE);
#endif
addr1 = addr & ~(DATA_SIZE - 1);
addr2 = addr1 + DATA_SIZE;
@@ -237,7 +237,7 @@
#ifdef ALIGNED_ONLY
if ((addr & (DATA_SIZE - 1)) != 0) {
cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
- mmu_idx, retaddr);
+ mmu_idx, retaddr, DATA_SIZE);
}
#endif
@@ -271,7 +271,7 @@
#ifdef ALIGNED_ONLY
if ((addr & (DATA_SIZE - 1)) != 0) {
cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
- mmu_idx, retaddr);
+ mmu_idx, retaddr, DATA_SIZE);
}
#endif
if (!VICTIM_TLB_HIT(ADDR_READ)) {
@@ -306,7 +306,7 @@
do_unaligned_access:
#ifdef ALIGNED_ONLY
cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
- mmu_idx, retaddr);
+ mmu_idx, retaddr, DATA_SIZE);
#endif
addr1 = addr & ~(DATA_SIZE - 1);
addr2 = addr1 + DATA_SIZE;
@@ -325,7 +325,7 @@
#ifdef ALIGNED_ONLY
if ((addr & (DATA_SIZE - 1)) != 0) {
cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
- mmu_idx, retaddr);
+ mmu_idx, retaddr, DATA_SIZE);
}
#endif
@@ -397,7 +397,7 @@
#ifdef ALIGNED_ONLY
if ((addr & (DATA_SIZE - 1)) != 0) {
cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
- mmu_idx, retaddr);
+ mmu_idx, retaddr, DATA_SIZE);
}
#endif
if (!VICTIM_TLB_HIT(addr_write)) {
@@ -429,7 +429,7 @@
do_unaligned_access:
#ifdef ALIGNED_ONLY
cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
- mmu_idx, retaddr);
+ mmu_idx, retaddr, DATA_SIZE);
#endif
/* XXX: not efficient, but simple */
/* Note: relies on the fact that tlb_fill() does not remove the
@@ -449,7 +449,7 @@
#ifdef ALIGNED_ONLY
if ((addr & (DATA_SIZE - 1)) != 0) {
cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
- mmu_idx, retaddr);
+ mmu_idx, retaddr, DATA_SIZE);
}
#endif
@@ -478,7 +478,7 @@
#ifdef ALIGNED_ONLY
if ((addr & (DATA_SIZE - 1)) != 0) {
cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
- mmu_idx, retaddr);
+ mmu_idx, retaddr, DATA_SIZE);
}
#endif
if (!VICTIM_TLB_HIT(addr_write)) {
@@ -510,7 +510,7 @@
do_unaligned_access:
#ifdef ALIGNED_ONLY
cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
- mmu_idx, retaddr);
+ mmu_idx, retaddr, DATA_SIZE);
#endif
/* XXX: not efficient, but simple */
/* Note: relies on the fact that tlb_fill() does not remove the
@@ -530,7 +530,7 @@
#ifdef ALIGNED_ONLY
if ((addr & (DATA_SIZE - 1)) != 0) {
cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
- mmu_idx, retaddr);
+ mmu_idx, retaddr, DATA_SIZE);
}
#endif
diff --git a/target-alpha/cpu-qom.h b/target-alpha/cpu-qom.h
index b01c6c8..273a8ed 100644
--- a/target-alpha/cpu-qom.h
+++ b/target-alpha/cpu-qom.h
@@ -86,6 +86,7 @@
int alpha_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int alpha_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void alpha_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
- int is_write, int is_user, uintptr_t retaddr);
+ int is_write, int is_user, uintptr_t retaddr,
+ unsigned size);
#endif
diff --git a/target-alpha/mem_helper.c b/target-alpha/mem_helper.c
index fc4f57a..1d4666a 100644
--- a/target-alpha/mem_helper.c
+++ b/target-alpha/mem_helper.c
@@ -97,7 +97,8 @@
}
void alpha_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
- int is_write, int is_user, uintptr_t retaddr)
+ int is_write, int is_user, uintptr_t retaddr,
+ unsigned size)
{
AlphaCPU *cpu = ALPHA_CPU(cs);
CPUAlphaState *env = &cpu->env;
diff --git a/target-mips/cpu-qom.h b/target-mips/cpu-qom.h
index 2ffc1bf..cbd626b 100644
--- a/target-mips/cpu-qom.h
+++ b/target-mips/cpu-qom.h
@@ -82,6 +82,7 @@
int mips_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int mips_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void mips_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
- int is_write, int is_user, uintptr_t retaddr);
+ int is_write, int is_user, uintptr_t retaddr,
+ unsigned size);
#endif
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 5185e00..b649451 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -101,6 +101,7 @@
float_status fp_status;
/* fpu implementation/revision register (fir) */
uint32_t fcr0;
+#define FCR0_FREP 29
#define FCR0_UFRP 28
#define FCR0_F64 22
#define FCR0_L 21
@@ -468,6 +469,8 @@
#define CP0C5_CV 29
#define CP0C5_EVA 28
#define CP0C5_MSAEn 27
+#define CP0C5_UFE 9
+#define CP0C5_FRE 8
#define CP0C5_SBRI 6
#define CP0C5_LLB 4
#define CP0C5_UFR 2
@@ -521,7 +524,7 @@
#define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */
uint32_t hflags; /* CPU State */
/* TMASK defines different execution modes */
-#define MIPS_HFLAG_TMASK 0x15807FF
+#define MIPS_HFLAG_TMASK 0x75807FF
#define MIPS_HFLAG_MODE 0x00007 /* execution modes */
/* The KSU flags must be the lowest bits in hflags. The flag order
must be the same as defined for CP0 Status. This allows to use
@@ -568,6 +571,8 @@
#define MIPS_HFLAG_SBRI 0x400000 /* R6 SDBBP causes RI excpt. in user mode */
#define MIPS_HFLAG_FBNSLOT 0x800000 /* Forbidden slot */
#define MIPS_HFLAG_MSA 0x1000000
+#define MIPS_HFLAG_LLBIT 0x2000000 /* In this mode we snoop all stores */
+#define MIPS_HFLAG_FRE 0x4000000 /* FRE enabled */
target_ulong btarget; /* Jump / branch target */
target_ulong bcond; /* Branch condition (if needed) */
@@ -776,6 +781,8 @@
void r4k_invalidate_tlb (CPUMIPSState *env, int idx, int use_extra);
hwaddr cpu_mips_translate_address (CPUMIPSState *env, target_ulong address,
int rw);
+bool cpu_mips_validate_access(CPUMIPSState *env, target_ulong address,
+ target_ulong badvaddr, unsigned data_size, int rw);
#endif
target_ulong exception_resume_pc (CPUMIPSState *env);
@@ -830,7 +837,7 @@
env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2 |
- MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA);
+ MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA | MIPS_HFLAG_FRE);
if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
!(env->CP0_Status & (1 << CP0St_ERL)) &&
!(env->hflags & MIPS_HFLAG_DM)) {
@@ -908,6 +915,11 @@
env->hflags |= MIPS_HFLAG_MSA;
}
}
+ if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
+ if (env->CP0_Config5 & (1 << CP0C5_FRE)) {
+ env->hflags |= MIPS_HFLAG_FRE;
+ }
+ }
}
#endif /* !defined (__MIPS_CPU_H__) */
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 75005cf..e3634d5 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -319,6 +319,7 @@
#define KERNEL_PGD_C0_CONTEXT (1 << 1)
#define KERNEL_HUGE_TLB (1 << 2)
#define KERNEL_RIXI (1 << 3)
+#define KERNEL_HIGHMEM (1 << 4)
/* TLB maintenance PTE software flags.
*
@@ -371,12 +372,63 @@
int softshift;
} linux_pte_info = {0};
+static inline target_ulong cpu_debug_translate_address(CPUMIPSState *env, target_ulong address) {
+
+#if defined(TARGET_MIPS64)
+ if (!(linux_pte_info.config & KERNEL_64_BIT))
+ address = (int32_t)address;
+#endif
+
+ if (address <= USEG_LIMIT) {
+ /* useg */
+ if (env->CP0_Status & (1 << CP0St_ERL)) {
+ return address & 0xFFFFFFFF;
+ } else {
+ return address;
+ }
+#if defined(TARGET_MIPS64)
+ } else if (address < 0x4000000000000000ULL) {
+ return address;
+ } else if (address < 0x8000000000000000ULL) {
+ return address;
+ } else if (address < 0xC000000000000000ULL) {
+ /* xkphys */
+ if ((address & 0x07FFFFFFFFFFFFFFULL) <= env->PAMask) {
+ return address & env->PAMask;
+ } else {
+ return address;
+ }
+ } else if (address < 0xFFFFFFFF80000000ULL) {
+ /* xkseg */
+ return address;
+#endif
+ } else if (address < (int32_t)KSEG1_BASE) {
+ /* kseg0 */
+ return address - (int32_t)KSEG0_BASE;
+ } else if (address < (int32_t)KSEG2_BASE) {
+ /* kseg1 */
+ return address - (int32_t)KSEG1_BASE;
+ } else
+ return address;
+}
+
+static inline target_ulong get_mtc0_entrylo_mask(const CPUMIPSState *env)
+{
+#if defined(TARGET_MIPS64)
+ return env->PAMask >> 6;
+#else
+ return (env->PAMask >> 6) & 0x3FFFFFFF;
+#endif
+}
+
static inline void pagetable_walk32(CPUState *cs,
target_ulong pgd_addr, target_ulong vaddr,
target_ulong *entrylo0, target_ulong *entrylo1,
target_ulong *sw_pte_lo0, target_ulong *sw_pte_lo1)
{
target_ulong ptw_phys, pt_addr, index;
+ MIPSCPU *cpu = MIPS_CPU(cs);
+ CPUMIPSState *env = &cpu->env;
#if defined(TARGET_MIPS64)
/* workaround when running a 32bit
@@ -385,29 +437,63 @@
vaddr = (uint32_t)vaddr;
#endif
- ptw_phys = pgd_addr & 0x1fffffffUL; /* Assume pgd is in KSEG0/KSEG1 */
/* 32bit PTE lookup */
+ ptw_phys = cpu_debug_translate_address(env, pgd_addr);
index = (vaddr >> 22) << 2; /* Use bits 31..22 to index pgd */
ptw_phys += index;
pt_addr = ldl_phys(cs->as, ptw_phys);
- ptw_phys = pt_addr & 0x1fffffffUL; /* Assume pgt is in KSEG0/KSEG1 */
+ ptw_phys = cpu_debug_translate_address(env, pt_addr);
index = ((vaddr >> 13) & 0x1ff) << 3; /* Use bits 21..13 to index pgt */
ptw_phys += index;
/* Get the entrylo values from pgt */
- *entrylo0 = ldl_phys(cs->as, ptw_phys);
- if (sw_pte_lo0) {
- *sw_pte_lo0 = *entrylo0 & ((target_ulong)(1 << linux_pte_info.softshift) - 1);
- }
- *entrylo0 >>= linux_pte_info.softshift;
+ if (linux_pte_info.config & KERNEL_RIXI) {
+ target_ulong mask = ~(-1 << linux_pte_info.softshift);
- *entrylo1 = ldl_phys(cs->as, ptw_phys + 4);
- if (sw_pte_lo1) {
- *sw_pte_lo1 = *entrylo1 & ((target_ulong)(1 << linux_pte_info.softshift) - 1);
+ *entrylo0 = ldl_phys(cs->as, ptw_phys);
+ if (sw_pte_lo0) {
+ if (linux_pte_info.config & KERNEL_HIGHMEM)
+ *sw_pte_lo0 = *entrylo0 & ~(-1 << (linux_pte_info.softshift + 4));
+ else
+ *sw_pte_lo0 = *entrylo0 & ~(-1 << (linux_pte_info.softshift));
+ }
+ if (linux_pte_info.config & KERNEL_HIGHMEM)
+ *entrylo0 = (*entrylo0) >> 4;
+ *entrylo0 = ((*entrylo0 & mask) << (32 - linux_pte_info.softshift)) |
+ ((uint32_t)*entrylo0 >> linux_pte_info.softshift);
+ *entrylo0 = (*entrylo0 & get_mtc0_entrylo_mask(env)) |
+ ((*entrylo0 & (env->CP0_PageGrain & (3u << CP0PG_XIE))) <<
+ (CP0EnLo_XI - 30));
+
+ *entrylo1 = ldl_phys(cs->as, ptw_phys + 4);
+ if (sw_pte_lo1) {
+ if (linux_pte_info.config & KERNEL_HIGHMEM)
+ *sw_pte_lo1 = *entrylo1 & ~(-1 << (linux_pte_info.softshift + 4));
+ else
+ *sw_pte_lo1 = *entrylo1 & ~(-1 << (linux_pte_info.softshift));
+ }
+ if (linux_pte_info.config & KERNEL_HIGHMEM)
+ *entrylo1 = (*entrylo1) >> 4;
+ *entrylo1 = ((*entrylo1 & mask) << (32 - linux_pte_info.softshift)) |
+ ((uint32_t)*entrylo1 >> linux_pte_info.softshift);
+ *entrylo1 = (*entrylo1 & get_mtc0_entrylo_mask(env)) |
+ ((*entrylo1 & (env->CP0_PageGrain & (3u << CP0PG_XIE))) <<
+ (CP0EnLo_XI - 30));
+ } else {
+ *entrylo0 = ldl_phys(cs->as, ptw_phys);
+ if (sw_pte_lo0) {
+ *sw_pte_lo0 = *entrylo0 & ((target_ulong)(1 << linux_pte_info.softshift) - 1);
+ }
+ *entrylo0 >>= linux_pte_info.softshift;
+
+ *entrylo1 = ldl_phys(cs->as, ptw_phys + 4);
+ if (sw_pte_lo1) {
+ *sw_pte_lo1 = *entrylo1 & ((target_ulong)(1 << linux_pte_info.softshift) - 1);
+ }
+ *entrylo1 >>= linux_pte_info.softshift;
}
- *entrylo1 >>= linux_pte_info.softshift;
}
static inline void pagetable_walk64(CPUState *cs,
@@ -417,22 +503,21 @@
{
MIPSCPU *cpu = MIPS_CPU(cs);
CPUMIPSState *env = &cpu->env;
-
target_ulong ptw_phys, pt_addr, index;
- pgd_addr = pgd_addr & 0x1fffffffUL;
+ pgd_addr = cpu_debug_translate_address(env, pgd_addr);
index = ((uint64_t)vaddr >> 0x1b) & 0x1ff8;
pgd_addr += index;
- pgd_addr = ldl_phys(cs->as, pgd_addr);
+ pgd_addr = ldq_phys(cs->as, pgd_addr);
- ptw_phys = pgd_addr & 0x1fffffffUL;
+ ptw_phys = cpu_debug_translate_address(env, pgd_addr);
index = ((uint64_t)vaddr >> 0x12) & 0xff8;
ptw_phys += index;
- pt_addr = ldl_phys(cs->as, ptw_phys);
+ pt_addr = ldq_phys(cs->as, ptw_phys);
- ptw_phys = pt_addr & 0x1fffffffUL;
+ ptw_phys = cpu_debug_translate_address(env, pt_addr);
index = (((vaddr & 0xC00000000000ULL) >> (55 - env->SEGBITS)) |
((vaddr & ((1ULL << env->SEGBITS) - 1) & 0xFFFFFFFFFFFFE000ULL) >> 9)) & 0xff0;
ptw_phys += index;
@@ -440,32 +525,32 @@
if (linux_pte_info.config & KERNEL_RIXI) {
target_ulong mask = ~(-1 << linux_pte_info.softshift);
- *entrylo0 = ldl_phys(cs->as, ptw_phys);
+ *entrylo0 = ldq_phys(cs->as, ptw_phys);
if (sw_pte_lo0) {
*sw_pte_lo0 = *entrylo0 & ((target_ulong)(1 << linux_pte_info.softshift) - 1);
}
*entrylo0 = ((*entrylo0 & mask) << (64 - linux_pte_info.softshift)) |
((uint64_t)*entrylo0 >> linux_pte_info.softshift);
- *entrylo0 = (*entrylo0 & 0x3FFFFFFF) |
+ *entrylo0 = (*entrylo0 & get_mtc0_entrylo_mask(env)) |
(*entrylo0 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32));
- *entrylo1 = ldl_phys(cs->as, ptw_phys + 8);
+ *entrylo1 = ldq_phys(cs->as, ptw_phys + 8);
if (sw_pte_lo1) {
*sw_pte_lo1 = *entrylo1 & ((target_ulong)(1 << linux_pte_info.softshift) - 1);
}
*entrylo1 = ((*entrylo1 & mask) << (64 - linux_pte_info.softshift)) |
((uint64_t)*entrylo1 >> linux_pte_info.softshift);
- *entrylo1 = (*entrylo1 & 0x3FFFFFFF) |
+ *entrylo1 = (*entrylo1 & get_mtc0_entrylo_mask(env)) |
(*entrylo1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32));
} else {
/* Get the entrylo values from pgt */
- *entrylo0 = ldl_phys(cs->as, ptw_phys);
+ *entrylo0 = ldq_phys(cs->as, ptw_phys);
if (sw_pte_lo0) {
*sw_pte_lo0 = *entrylo0 & ((target_ulong)(1 << linux_pte_info.softshift) - 1);
}
*entrylo0 >>= linux_pte_info.softshift;
- *entrylo1 = ldl_phys(cs->as, ptw_phys + 8);
+ *entrylo1 = ldq_phys(cs->as, ptw_phys + 8);
if (sw_pte_lo1) {
*sw_pte_lo1 = *entrylo1 & ((target_ulong)(1 << linux_pte_info.softshift) - 1);
}
@@ -498,12 +583,33 @@
uint32_t mask;
} lui, lw, srl;
} handlers[] = {
- /* 2.6.29+ 32-bit Kernel */
+ /* 3.10+ 32-bit R6 Kernel */
+ {
+ KERNEL_RIXI,
+ {0x00, 0x3c1b0000, 0xffff0000}, /* 0x3c1b803f : lui k1,%hi(pgd_current_p) */
+ {0x08, 0x8f7b0000, 0xffff0000}, /* 0x8f7b3000 : lw k1,%lo(k1) */
+ {0x2c, 0x003ad002, 0xfffff83f} /* 0x003ad082 : ror k0,k0,#shift */
+ },
+ /* 3.10+ 32-bit R6 Kernel */
+ {
+ KERNEL_RIXI | KERNEL_HIGHMEM,
+ {0x00, 0x3c1b0000, 0xffff0000}, /* 0x3c1b803f : lui k1,%hi(pgd_current_p) */
+ {0x08, 0x8f7b0000, 0xffff0000}, /* 0x8f7b3000 : lw k1,%lo(k1) */
+ {0x34, 0x003ad002, 0xfffff83f} /* 0x003ad082 : ror k0,k0,#shift */
+ },
+ /* 3.10+ 32-bit R6 Kernel */
+ {
+ KERNEL_RIXI | KERNEL_HIGHMEM,
+ {0x00, 0x3c1b0000, 0xffff0000}, /* 0x3c1b803f : lui k1,%hi(pgd_current_p) */
+ {0x08, 0x8f7b0000, 0xffff0000}, /* 0x8f7b3000 : lw k1,%lo(k1) */
+ {0x38, 0x003ad002, 0xfffff83f} /* 0x003ad082 : ror k0,k0,#shift */
+ },
+ /* 3.10+ 32-bit R2 Kernel */
{
0,
{0x00, 0x3c1b0000, 0xffff0000}, /* 0x3c1b803f : lui k1,%hi(pgd_current_p) */
{0x08, 0x8f7b0000, 0xffff0000}, /* 0x8f7b3000 : lw k1,%lo(k1) */
- {0x34, 0x001ad002, 0xfffff83f} /* 0x001ad002 : srl k0,k0,#shift */
+ {0x2c, 0x001ad002, 0xfffff83f} /* 0x001ad002 : srl k0,k0,#shift */
},
/* 3.10+ 64-bit R2 Kernel */
{
@@ -557,20 +663,13 @@
linux_pte_info.pagetable_walk = &pagetable_walk32;
}
- if (config & KERNEL_PGD_C0_CONTEXT) {
- /* swapper_pg_dir address */
- address = (lui_ins & 0xffff) << 16;
- linux_pte_info.swapper_pg_dir = address;
- } else {
- address = (lui_ins & 0xffff) << 16;
- linux_pte_info.swapper_pg_dir = address;
+ /* swapper_pg_dir address */
+ address = (int32_t)((lui_ins & 0xffff) << 16);
+ linux_pte_info.swapper_pg_dir = cpu_debug_translate_address(env, address);
+
+ if (!(config & KERNEL_PGD_C0_CONTEXT)) {
address += (((int32_t)(lw_ins & 0xffff)) << 16) >> 16;
- if (address >= 0x80000000 && address < 0xa0000000)
- address -= 0x80000000;
- else if (address >= 0xa0000000 && address <= 0xc0000000)
- address -= 0xa0000000;
- else
- cpu_abort(cs, "pgd_current_p not in KSEG0/KSEG1\n");
+ address = cpu_debug_translate_address(env, address);
}
linux_pte_info.state = USEFASTTLB;
@@ -745,10 +844,10 @@
int prot, ret;
#if defined(TARGET_MIPS64)
- if (!(linux_pte_info.config & KERNEL_64_BIT) &&
- (linux_pte_info.state == USEFASTTLB))
- addr = ((int64_t)addr << 32) >> 32;
+ if (!(linux_pte_info.config & KERNEL_64_BIT))
+ addr = (int32_t)addr;
#endif
+
ret = get_physical_address(env, &phys_addr, &prot, addr, 0, ACCESS_INT);
if (ret != TLBRET_MATCH) {
target_ulong pgd_addr = cpu_mips_get_pgd(cs, addr);
@@ -844,6 +943,39 @@
return physical;
}
}
+
+bool cpu_mips_validate_access(CPUMIPSState *env, target_ulong address,
+ target_ulong badvaddr, unsigned data_size, int rw)
+{
+ hwaddr physical;
+ int prot;
+ int access_type = ACCESS_INT;
+ int ret;
+ target_ulong addr;
+
+ addr = address & ~((target_ulong) data_size - 1);
+ ret = get_physical_address(env, &physical, &prot,
+ addr, rw, access_type);
+ if (ret != TLBRET_MATCH) {
+ raise_mmu_exception(env, badvaddr, rw, ret);
+ return false;
+ }
+ if (data_size > 1
+ && unlikely((address & ~TARGET_PAGE_MASK) + data_size - 1
+ >= TARGET_PAGE_SIZE)) {
+ addr += data_size;
+ ret = get_physical_address(env, &physical, &prot,
+ addr, rw, access_type);
+ if (ret != TLBRET_MATCH) {
+ if (ret != TLBRET_BADADDR) {
+ badvaddr = addr;
+ }
+ raise_mmu_exception(env, badvaddr, rw, ret);
+ return false;
+ }
+ }
+ return true;
+}
#endif
static const char * const excp_names[EXCP_LAST + 1] = {
diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c
index b08f37f..fd66905 100644
--- a/target-mips/msa_helper.c
+++ b/target-mips/msa_helper.c
@@ -2650,6 +2650,8 @@
wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
uint32_t i;
+ clear_msacsr_cause(env);
+
switch (df) {
case DF_WORD:
for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
@@ -3201,6 +3203,8 @@
wr_t *pws = &(env->active_fpu.fpr[ws].wr);
uint32_t i;
+ clear_msacsr_cause(env);
+
switch (df) {
case DF_WORD:
for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
@@ -3233,6 +3237,8 @@
wr_t *pws = &(env->active_fpu.fpr[ws].wr);
uint32_t i;
+ clear_msacsr_cause(env);
+
switch (df) {
case DF_WORD:
for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 8630d44..734207f 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1423,10 +1423,12 @@
uint32_t mask = env->CP0_Status_rw_bitmask;
if (env->insn_flags & ISA_MIPS32R6) {
- if (extract32(env->CP0_Status, CP0St_KSU, 2) == 0x3) {
+ bool has_supervisor = extract32(mask, CP0St_KSU, 2) == 0x3;
+
+ if (has_supervisor && extract32(arg1, CP0St_KSU, 2) == 0x3) {
mask &= ~(3 << CP0St_KSU);
}
- mask &= ~(0x00180000 & arg1);
+ mask &= ~(((1 << CP0St_SR) | (1 << CP0St_NMI)) & arg1);
}
val = arg1 & mask;
@@ -2280,13 +2282,26 @@
void mips_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
int access_type, int is_user,
- uintptr_t retaddr)
+ uintptr_t retaddr, unsigned size)
{
MIPSCPU *cpu = MIPS_CPU(cs);
CPUMIPSState *env = &cpu->env;
int error_code = 0;
int excp;
+ if (env->insn_flags & ISA_MIPS32R6) {
+ /* Release 6 provides support for misaligned memory access for
+ * all ordinary memory reference instructions
+ * */
+ if (!cpu_mips_validate_access(env, addr, addr, size, access_type)) {
+ CPUState *cs = CPU(mips_env_get_cpu(env));
+ do_raise_exception_err(env, cs->exception_index,
+ env->error_code, retaddr);
+ return;
+ }
+ return;
+ }
+
env->CP0_BadVAddr = addr;
if (access_type == MMU_DATA_STORE) {
@@ -2387,6 +2402,16 @@
}
}
break;
+ case 5:
+ /* FRE support - read Config5.FRE bit */
+ if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
+ if (env->CP0_Config5 & (1 << CP0C5_UFE)) {
+ arg1 = (env->CP0_Config5 >> CP0C5_FRE) & 1;
+ } else {
+ helper_raise_exception(env, EXCP_RI);
+ }
+ }
+ break;
case 25:
arg1 = ((env->active_fpu.fcr31 >> 24) & 0xfe) | ((env->active_fpu.fcr31 >> 23) & 0x1);
break;
@@ -2431,6 +2456,30 @@
helper_raise_exception(env, EXCP_RI);
}
break;
+ case 5:
+ /* FRE Support - clear Config5.FRE bit */
+ if (!((env->active_fpu.fcr0 & (1 << FCR0_FREP)) && (rt == 0))) {
+ return;
+ }
+ if (env->CP0_Config5 & (1 << CP0C5_UFE)) {
+ env->CP0_Config5 &= ~(1 << CP0C5_FRE);
+ compute_hflags(env);
+ } else {
+ helper_raise_exception(env, EXCP_RI);
+ }
+ break;
+ case 6:
+ /* FRE support - set Config5.FRE bit */
+ if (!((env->active_fpu.fcr0 & (1 << FCR0_FREP)) && (rt == 0))) {
+ return;
+ }
+ if (env->CP0_Config5 & (1 << CP0C5_UFE)) {
+ env->CP0_Config5 |= (1 << CP0C5_FRE);
+ compute_hflags(env);
+ } else {
+ helper_raise_exception(env, EXCP_RI);
+ }
+ break;
case 25:
if ((env->insn_flags & ISA_MIPS32R6) || (arg1 & 0xffffff00)) {
return;
@@ -3643,6 +3692,24 @@
/* Element-by-element access macros */
#define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df))
+#if !defined(CONFIG_USER_ONLY)
+static bool cpu_mips_validate_msa_block_access(CPUMIPSState *env,
+ target_ulong address, int df, int rw)
+{
+ int i;
+ for (i = 0; i < DF_ELEMENTS(df); i++) {
+ if (!cpu_mips_validate_access(env, address + (i << df),
+ address, (1 << df), rw)) {
+ CPUState *cs = CPU(mips_env_get_cpu(env));
+ do_raise_exception_err(env, cs->exception_index,
+ env->error_code, GETRA());
+ return false;
+ }
+ }
+ return true;
+}
+#endif
+
void helper_msa_ld_df(CPUMIPSState *env, uint32_t df, uint32_t wd, uint32_t rs,
int32_t s10)
{
@@ -3650,6 +3717,12 @@
target_ulong addr = env->active_tc.gpr[rs] + (s10 << df);
int i;
+#if !defined(CONFIG_USER_ONLY)
+ if (!cpu_mips_validate_msa_block_access(env, addr, df, MMU_DATA_LOAD)) {
+ return;
+ }
+#endif
+
switch (df) {
case DF_BYTE:
for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {
@@ -3685,6 +3758,12 @@
target_ulong addr = env->active_tc.gpr[rs] + (s10 << df);
int i;
+#if !defined(CONFIG_USER_ONLY)
+ if (!cpu_mips_validate_msa_block_access(env, addr, df, MMU_DATA_STORE)) {
+ return;
+ }
+#endif
+
switch (df) {
case DF_BYTE:
for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 2682c13..84bdaba 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1557,14 +1557,22 @@
}
}
+static inline void generate_exception (DisasContext *ctx, int excp);
+
/* Floating point register moves. */
-static void gen_load_fpr32(TCGv_i32 t, int reg)
+static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
{
+ if (ctx->hflags & MIPS_HFLAG_FRE) {
+ generate_exception(ctx, EXCP_RI);
+ }
tcg_gen_trunc_i64_i32(t, fpu_f64[reg]);
}
-static void gen_store_fpr32(TCGv_i32 t, int reg)
+static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
{
+ if (ctx->hflags & MIPS_HFLAG_FRE) {
+ generate_exception(ctx, EXCP_RI);
+ }
TCGv_i64 t64 = tcg_temp_new_i64();
tcg_gen_extu_i32_i64(t64, t);
tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
@@ -1579,7 +1587,7 @@
tcg_gen_trunc_i64_i32(t, t64);
tcg_temp_free_i64(t64);
} else {
- gen_load_fpr32(t, reg | 1);
+ gen_load_fpr32(ctx, t, reg | 1);
}
}
@@ -1591,7 +1599,7 @@
tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
tcg_temp_free_i64(t64);
} else {
- gen_store_fpr32(t, reg | 1);
+ gen_store_fpr32(ctx, t, reg | 1);
}
}
@@ -1819,7 +1827,7 @@
calling interface for 32 and 64-bit FPRs. No sense in changing
all callers for gen_load_fpr32 when we need the CTX parameter for
this one use. */
-#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
+#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
@@ -1965,7 +1973,7 @@
}
FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
-FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(fp0, fd))
+FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
#undef FOP_CONDNS
#undef gen_ldcmp_fpr32
#undef gen_ldcmp_fpr64
@@ -2350,7 +2358,7 @@
{
TCGv_i32 fp0 = tcg_temp_new_i32();
tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL);
- gen_store_fpr32(fp0, ft);
+ gen_store_fpr32(ctx, fp0, ft);
tcg_temp_free_i32(fp0);
}
opn = "lwc1";
@@ -2358,7 +2366,7 @@
case OPC_SWC1:
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, ft);
+ gen_load_fpr32(ctx, fp0, ft);
tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
tcg_temp_free_i32(fp0);
}
@@ -7544,7 +7552,7 @@
if (h == 0) {
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, rt);
+ gen_load_fpr32(ctx, fp0, rt);
tcg_gen_ext_i32_tl(t0, fp0);
tcg_temp_free_i32(fp0);
} else {
@@ -7743,7 +7751,7 @@
TCGv_i32 fp0 = tcg_temp_new_i32();
tcg_gen_trunc_tl_i32(fp0, t0);
- gen_store_fpr32(fp0, rd);
+ gen_store_fpr32(ctx, fp0, rd);
tcg_temp_free_i32(fp0);
} else {
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -8341,7 +8349,7 @@
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
+ gen_load_fpr32(ctx, fp0, fs);
tcg_gen_ext_i32_tl(t0, fp0);
tcg_temp_free_i32(fp0);
}
@@ -8354,7 +8362,7 @@
TCGv_i32 fp0 = tcg_temp_new_i32();
tcg_gen_trunc_tl_i32(fp0, t0);
- gen_store_fpr32(fp0, fs);
+ gen_store_fpr32(ctx, fp0, fs);
tcg_temp_free_i32(fp0);
}
opn = "mtc1";
@@ -8452,7 +8460,7 @@
gen_set_label(l1);
}
-static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
+static inline void gen_movcf_s (DisasContext *ctx, int fs, int fd, int cc, int tf)
{
int cond;
TCGv_i32 t0 = tcg_temp_new_i32();
@@ -8465,8 +8473,8 @@
tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
tcg_gen_brcondi_i32(cond, t0, 0, l1);
- gen_load_fpr32(t0, fs);
- gen_store_fpr32(t0, fd);
+ gen_load_fpr32(ctx, t0, fs);
+ gen_store_fpr32(ctx, t0, fd);
gen_set_label(l1);
tcg_temp_free_i32(t0);
}
@@ -8508,8 +8516,8 @@
tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
tcg_gen_brcondi_i32(cond, t0, 0, l1);
- gen_load_fpr32(t0, fs);
- gen_store_fpr32(t0, fd);
+ gen_load_fpr32(ctx, t0, fs);
+ gen_store_fpr32(ctx, t0, fd);
gen_set_label(l1);
tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
@@ -8527,9 +8535,9 @@
TCGv_i32 fp0 = tcg_temp_new_i32();
TCGv_i32 fp1 = tcg_temp_new_i32();
TCGv_i32 fp2 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fd);
- gen_load_fpr32(fp1, ft);
- gen_load_fpr32(fp2, fs);
+ gen_load_fpr32(ctx, fp0, fd);
+ gen_load_fpr32(ctx, fp1, ft);
+ gen_load_fpr32(ctx, fp2, fs);
switch (op1) {
case OPC_SEL_S:
@@ -8550,7 +8558,7 @@
break;
}
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp2);
tcg_temp_free_i32(fp1);
tcg_temp_free_i32(fp0);
@@ -8643,11 +8651,11 @@
TCGv_i32 fp0 = tcg_temp_new_i32();
TCGv_i32 fp1 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
- gen_load_fpr32(fp1, ft);
+ gen_load_fpr32(ctx, fp0, fs);
+ gen_load_fpr32(ctx, fp1, ft);
gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
tcg_temp_free_i32(fp1);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "add.s";
@@ -8658,11 +8666,11 @@
TCGv_i32 fp0 = tcg_temp_new_i32();
TCGv_i32 fp1 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
- gen_load_fpr32(fp1, ft);
+ gen_load_fpr32(ctx, fp0, fs);
+ gen_load_fpr32(ctx, fp1, ft);
gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
tcg_temp_free_i32(fp1);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "sub.s";
@@ -8673,11 +8681,11 @@
TCGv_i32 fp0 = tcg_temp_new_i32();
TCGv_i32 fp1 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
- gen_load_fpr32(fp1, ft);
+ gen_load_fpr32(ctx, fp0, fs);
+ gen_load_fpr32(ctx, fp1, ft);
gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
tcg_temp_free_i32(fp1);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "mul.s";
@@ -8688,11 +8696,11 @@
TCGv_i32 fp0 = tcg_temp_new_i32();
TCGv_i32 fp1 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
- gen_load_fpr32(fp1, ft);
+ gen_load_fpr32(ctx, fp0, fs);
+ gen_load_fpr32(ctx, fp1, ft);
gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
tcg_temp_free_i32(fp1);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "div.s";
@@ -8702,9 +8710,9 @@
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
+ gen_load_fpr32(ctx, fp0, fs);
gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "sqrt.s";
@@ -8713,9 +8721,9 @@
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
+ gen_load_fpr32(ctx, fp0, fs);
gen_helper_float_abs_s(fp0, fp0);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "abs.s";
@@ -8724,8 +8732,8 @@
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
- gen_store_fpr32(fp0, fd);
+ gen_load_fpr32(ctx, fp0, fs);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "mov.s";
@@ -8734,9 +8742,9 @@
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
+ gen_load_fpr32(ctx, fp0, fs);
gen_helper_float_chs_s(fp0, fp0);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "neg.s";
@@ -8747,7 +8755,7 @@
TCGv_i32 fp32 = tcg_temp_new_i32();
TCGv_i64 fp64 = tcg_temp_new_i64();
- gen_load_fpr32(fp32, fs);
+ gen_load_fpr32(ctx, fp32, fs);
gen_helper_float_roundl_s(fp64, cpu_env, fp32);
tcg_temp_free_i32(fp32);
gen_store_fpr64(ctx, fp64, fd);
@@ -8761,7 +8769,7 @@
TCGv_i32 fp32 = tcg_temp_new_i32();
TCGv_i64 fp64 = tcg_temp_new_i64();
- gen_load_fpr32(fp32, fs);
+ gen_load_fpr32(ctx, fp32, fs);
gen_helper_float_truncl_s(fp64, cpu_env, fp32);
tcg_temp_free_i32(fp32);
gen_store_fpr64(ctx, fp64, fd);
@@ -8775,7 +8783,7 @@
TCGv_i32 fp32 = tcg_temp_new_i32();
TCGv_i64 fp64 = tcg_temp_new_i64();
- gen_load_fpr32(fp32, fs);
+ gen_load_fpr32(ctx, fp32, fs);
gen_helper_float_ceill_s(fp64, cpu_env, fp32);
tcg_temp_free_i32(fp32);
gen_store_fpr64(ctx, fp64, fd);
@@ -8789,7 +8797,7 @@
TCGv_i32 fp32 = tcg_temp_new_i32();
TCGv_i64 fp64 = tcg_temp_new_i64();
- gen_load_fpr32(fp32, fs);
+ gen_load_fpr32(ctx, fp32, fs);
gen_helper_float_floorl_s(fp64, cpu_env, fp32);
tcg_temp_free_i32(fp32);
gen_store_fpr64(ctx, fp64, fd);
@@ -8801,9 +8809,9 @@
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
+ gen_load_fpr32(ctx, fp0, fs);
gen_helper_float_roundw_s(fp0, cpu_env, fp0);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "round.w.s";
@@ -8812,9 +8820,9 @@
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
+ gen_load_fpr32(ctx, fp0, fs);
gen_helper_float_truncw_s(fp0, cpu_env, fp0);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "trunc.w.s";
@@ -8823,9 +8831,9 @@
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
+ gen_load_fpr32(ctx, fp0, fs);
gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "ceil.w.s";
@@ -8834,9 +8842,9 @@
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
+ gen_load_fpr32(ctx, fp0, fs);
gen_helper_float_floorw_s(fp0, cpu_env, fp0);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "floor.w.s";
@@ -8858,7 +8866,7 @@
break;
case OPC_MOVCF_S:
check_insn_opc_removed(ctx, ISA_MIPS32R6);
- gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
+ gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
opn = "movcf.s";
break;
case OPC_MOVZ_S:
@@ -8871,8 +8879,8 @@
tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
}
fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
- gen_store_fpr32(fp0, fd);
+ gen_load_fpr32(ctx, fp0, fs);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
gen_set_label(l1);
}
@@ -8887,8 +8895,8 @@
if (ft != 0) {
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
- gen_store_fpr32(fp0, fd);
+ gen_load_fpr32(ctx, fp0, fs);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
gen_set_label(l1);
}
@@ -8900,9 +8908,9 @@
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
+ gen_load_fpr32(ctx, fp0, fs);
gen_helper_float_recip_s(fp0, cpu_env, fp0);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "recip.s";
@@ -8912,9 +8920,9 @@
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
+ gen_load_fpr32(ctx, fp0, fs);
gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "rsqrt.s";
@@ -8925,11 +8933,11 @@
TCGv_i32 fp0 = tcg_temp_new_i32();
TCGv_i32 fp1 = tcg_temp_new_i32();
TCGv_i32 fp2 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
- gen_load_fpr32(fp1, ft);
- gen_load_fpr32(fp2, fd);
+ gen_load_fpr32(ctx, fp0, fs);
+ gen_load_fpr32(ctx, fp1, ft);
+ gen_load_fpr32(ctx, fp2, fd);
gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
- gen_store_fpr32(fp2, fd);
+ gen_store_fpr32(ctx, fp2, fd);
tcg_temp_free_i32(fp2);
tcg_temp_free_i32(fp1);
tcg_temp_free_i32(fp0);
@@ -8942,11 +8950,11 @@
TCGv_i32 fp0 = tcg_temp_new_i32();
TCGv_i32 fp1 = tcg_temp_new_i32();
TCGv_i32 fp2 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
- gen_load_fpr32(fp1, ft);
- gen_load_fpr32(fp2, fd);
+ gen_load_fpr32(ctx, fp0, fs);
+ gen_load_fpr32(ctx, fp1, ft);
+ gen_load_fpr32(ctx, fp2, fd);
gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
- gen_store_fpr32(fp2, fd);
+ gen_store_fpr32(ctx, fp2, fd);
tcg_temp_free_i32(fp2);
tcg_temp_free_i32(fp1);
tcg_temp_free_i32(fp0);
@@ -8957,9 +8965,9 @@
check_insn(ctx, ISA_MIPS32R6);
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
+ gen_load_fpr32(ctx, fp0, fs);
gen_helper_float_rint_s(fp0, cpu_env, fp0);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
opn = "rint.s";
}
@@ -8968,9 +8976,9 @@
check_insn(ctx, ISA_MIPS32R6);
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
+ gen_load_fpr32(ctx, fp0, fs);
gen_helper_float_class_s(fp0, fp0);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
opn = "class.s";
}
@@ -8981,10 +8989,10 @@
TCGv_i32 fp0 = tcg_temp_new_i32();
TCGv_i32 fp1 = tcg_temp_new_i32();
TCGv_i32 fp2 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
- gen_load_fpr32(fp1, ft);
+ gen_load_fpr32(ctx, fp0, fs);
+ gen_load_fpr32(ctx, fp1, ft);
gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
- gen_store_fpr32(fp2, fd);
+ gen_store_fpr32(ctx, fp2, fd);
tcg_temp_free_i32(fp2);
tcg_temp_free_i32(fp1);
tcg_temp_free_i32(fp0);
@@ -8996,11 +9004,11 @@
TCGv_i32 fp0 = tcg_temp_new_i32();
TCGv_i32 fp1 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
- gen_load_fpr32(fp1, ft);
+ gen_load_fpr32(ctx, fp0, fs);
+ gen_load_fpr32(ctx, fp1, ft);
gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
tcg_temp_free_i32(fp1);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "recip2.s";
@@ -9012,10 +9020,10 @@
TCGv_i32 fp0 = tcg_temp_new_i32();
TCGv_i32 fp1 = tcg_temp_new_i32();
TCGv_i32 fp2 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
- gen_load_fpr32(fp1, ft);
+ gen_load_fpr32(ctx, fp0, fs);
+ gen_load_fpr32(ctx, fp1, ft);
gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
- gen_store_fpr32(fp2, fd);
+ gen_store_fpr32(ctx, fp2, fd);
tcg_temp_free_i32(fp2);
tcg_temp_free_i32(fp1);
tcg_temp_free_i32(fp0);
@@ -9026,9 +9034,9 @@
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
+ gen_load_fpr32(ctx, fp0, fs);
gen_helper_float_recip1_s(fp0, cpu_env, fp0);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "recip1.s";
@@ -9039,10 +9047,10 @@
/* OPC_MAX_S */
TCGv_i32 fp0 = tcg_temp_new_i32();
TCGv_i32 fp1 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
- gen_load_fpr32(fp1, ft);
+ gen_load_fpr32(ctx, fp0, fs);
+ gen_load_fpr32(ctx, fp1, ft);
gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
- gen_store_fpr32(fp1, fd);
+ gen_store_fpr32(ctx, fp1, fd);
tcg_temp_free_i32(fp1);
tcg_temp_free_i32(fp0);
opn = "max.s";
@@ -9052,9 +9060,9 @@
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
+ gen_load_fpr32(ctx, fp0, fs);
gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "rsqrt1.s";
@@ -9065,10 +9073,10 @@
/* OPC_MAXA_S */
TCGv_i32 fp0 = tcg_temp_new_i32();
TCGv_i32 fp1 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
- gen_load_fpr32(fp1, ft);
+ gen_load_fpr32(ctx, fp0, fs);
+ gen_load_fpr32(ctx, fp1, ft);
gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
- gen_store_fpr32(fp1, fd);
+ gen_store_fpr32(ctx, fp1, fd);
tcg_temp_free_i32(fp1);
tcg_temp_free_i32(fp0);
opn = "maxa.s";
@@ -9079,11 +9087,11 @@
TCGv_i32 fp0 = tcg_temp_new_i32();
TCGv_i32 fp1 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
- gen_load_fpr32(fp1, ft);
+ gen_load_fpr32(ctx, fp0, fs);
+ gen_load_fpr32(ctx, fp1, ft);
gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
tcg_temp_free_i32(fp1);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "rsqrt2.s";
@@ -9095,7 +9103,7 @@
TCGv_i32 fp32 = tcg_temp_new_i32();
TCGv_i64 fp64 = tcg_temp_new_i64();
- gen_load_fpr32(fp32, fs);
+ gen_load_fpr32(ctx, fp32, fs);
gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
tcg_temp_free_i32(fp32);
gen_store_fpr64(ctx, fp64, fd);
@@ -9107,9 +9115,9 @@
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
+ gen_load_fpr32(ctx, fp0, fs);
gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "cvt.w.s";
@@ -9120,7 +9128,7 @@
TCGv_i32 fp32 = tcg_temp_new_i32();
TCGv_i64 fp64 = tcg_temp_new_i64();
- gen_load_fpr32(fp32, fs);
+ gen_load_fpr32(ctx, fp32, fs);
gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
tcg_temp_free_i32(fp32);
gen_store_fpr64(ctx, fp64, fd);
@@ -9136,8 +9144,8 @@
TCGv_i32 fp32_0 = tcg_temp_new_i32();
TCGv_i32 fp32_1 = tcg_temp_new_i32();
- gen_load_fpr32(fp32_0, fs);
- gen_load_fpr32(fp32_1, ft);
+ gen_load_fpr32(ctx, fp32_0, fs);
+ gen_load_fpr32(ctx, fp32_1, ft);
tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
tcg_temp_free_i32(fp32_1);
tcg_temp_free_i32(fp32_0);
@@ -9339,7 +9347,7 @@
gen_load_fpr64(ctx, fp64, fs);
gen_helper_float_roundw_d(fp32, cpu_env, fp64);
tcg_temp_free_i64(fp64);
- gen_store_fpr32(fp32, fd);
+ gen_store_fpr32(ctx, fp32, fd);
tcg_temp_free_i32(fp32);
}
opn = "round.w.d";
@@ -9353,7 +9361,7 @@
gen_load_fpr64(ctx, fp64, fs);
gen_helper_float_truncw_d(fp32, cpu_env, fp64);
tcg_temp_free_i64(fp64);
- gen_store_fpr32(fp32, fd);
+ gen_store_fpr32(ctx, fp32, fd);
tcg_temp_free_i32(fp32);
}
opn = "trunc.w.d";
@@ -9367,7 +9375,7 @@
gen_load_fpr64(ctx, fp64, fs);
gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
tcg_temp_free_i64(fp64);
- gen_store_fpr32(fp32, fd);
+ gen_store_fpr32(ctx, fp32, fd);
tcg_temp_free_i32(fp32);
}
opn = "ceil.w.d";
@@ -9381,7 +9389,7 @@
gen_load_fpr64(ctx, fp64, fs);
gen_helper_float_floorw_d(fp32, cpu_env, fp64);
tcg_temp_free_i64(fp64);
- gen_store_fpr32(fp32, fd);
+ gen_store_fpr32(ctx, fp32, fd);
tcg_temp_free_i32(fp32);
}
opn = "floor.w.d";
@@ -9664,7 +9672,7 @@
gen_load_fpr64(ctx, fp64, fs);
gen_helper_float_cvts_d(fp32, cpu_env, fp64);
tcg_temp_free_i64(fp64);
- gen_store_fpr32(fp32, fd);
+ gen_store_fpr32(ctx, fp32, fd);
tcg_temp_free_i32(fp32);
}
opn = "cvt.s.d";
@@ -9678,7 +9686,7 @@
gen_load_fpr64(ctx, fp64, fs);
gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
tcg_temp_free_i64(fp64);
- gen_store_fpr32(fp32, fd);
+ gen_store_fpr32(ctx, fp32, fd);
tcg_temp_free_i32(fp32);
}
opn = "cvt.w.d";
@@ -9699,9 +9707,9 @@
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
+ gen_load_fpr32(ctx, fp0, fs);
gen_helper_float_cvts_w(fp0, cpu_env, fp0);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "cvt.s.w";
@@ -9712,7 +9720,7 @@
TCGv_i32 fp32 = tcg_temp_new_i32();
TCGv_i64 fp64 = tcg_temp_new_i64();
- gen_load_fpr32(fp32, fs);
+ gen_load_fpr32(ctx, fp32, fs);
gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
tcg_temp_free_i32(fp32);
gen_store_fpr64(ctx, fp64, fd);
@@ -9729,7 +9737,7 @@
gen_load_fpr64(ctx, fp64, fs);
gen_helper_float_cvts_l(fp32, cpu_env, fp64);
tcg_temp_free_i64(fp64);
- gen_store_fpr32(fp32, fd);
+ gen_store_fpr32(ctx, fp32, fd);
tcg_temp_free_i32(fp32);
}
opn = "cvt.s.l";
@@ -9968,7 +9976,7 @@
gen_load_fpr32h(ctx, fp0, fs);
gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "cvt.s.pu";
@@ -9990,9 +9998,9 @@
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
+ gen_load_fpr32(ctx, fp0, fs);
gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "cvt.s.pl";
@@ -10003,10 +10011,10 @@
TCGv_i32 fp0 = tcg_temp_new_i32();
TCGv_i32 fp1 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
- gen_load_fpr32(fp1, ft);
+ gen_load_fpr32(ctx, fp0, fs);
+ gen_load_fpr32(ctx, fp1, ft);
gen_store_fpr32h(ctx, fp0, fd);
- gen_store_fpr32(fp1, fd);
+ gen_store_fpr32(ctx, fp1, fd);
tcg_temp_free_i32(fp0);
tcg_temp_free_i32(fp1);
}
@@ -10018,9 +10026,9 @@
TCGv_i32 fp0 = tcg_temp_new_i32();
TCGv_i32 fp1 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
+ gen_load_fpr32(ctx, fp0, fs);
gen_load_fpr32h(ctx, fp1, ft);
- gen_store_fpr32(fp1, fd);
+ gen_store_fpr32(ctx, fp1, fd);
gen_store_fpr32h(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
tcg_temp_free_i32(fp1);
@@ -10034,8 +10042,8 @@
TCGv_i32 fp1 = tcg_temp_new_i32();
gen_load_fpr32h(ctx, fp0, fs);
- gen_load_fpr32(fp1, ft);
- gen_store_fpr32(fp1, fd);
+ gen_load_fpr32(ctx, fp1, ft);
+ gen_store_fpr32(ctx, fp1, fd);
gen_store_fpr32h(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
tcg_temp_free_i32(fp1);
@@ -10050,7 +10058,7 @@
gen_load_fpr32h(ctx, fp0, fs);
gen_load_fpr32h(ctx, fp1, ft);
- gen_store_fpr32(fp1, fd);
+ gen_store_fpr32(ctx, fp1, fd);
gen_store_fpr32h(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
tcg_temp_free_i32(fp1);
@@ -10125,7 +10133,7 @@
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
tcg_gen_trunc_tl_i32(fp0, t0);
- gen_store_fpr32(fp0, fd);
+ gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
opn = "lwxc1";
@@ -10157,7 +10165,7 @@
check_cop1x(ctx);
{
TCGv_i32 fp0 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
+ gen_load_fpr32(ctx, fp0, fs);
tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
tcg_temp_free_i32(fp0);
}
@@ -10214,23 +10222,23 @@
tcg_gen_andi_tl(t0, t0, 0x7);
tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
- gen_load_fpr32(fp, fs);
+ gen_load_fpr32(ctx, fp, fs);
gen_load_fpr32h(ctx, fph, fs);
- gen_store_fpr32(fp, fd);
+ gen_store_fpr32(ctx, fp, fd);
gen_store_fpr32h(ctx, fph, fd);
tcg_gen_br(l2);
gen_set_label(l1);
tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
tcg_temp_free(t0);
#ifdef TARGET_WORDS_BIGENDIAN
- gen_load_fpr32(fp, fs);
+ gen_load_fpr32(ctx, fp, fs);
gen_load_fpr32h(ctx, fph, ft);
gen_store_fpr32h(ctx, fp, fd);
- gen_store_fpr32(fph, fd);
+ gen_store_fpr32(ctx, fph, fd);
#else
gen_load_fpr32h(ctx, fph, fs);
- gen_load_fpr32(fp, ft);
- gen_store_fpr32(fph, fd);
+ gen_load_fpr32(ctx, fp, ft);
+ gen_store_fpr32(ctx, fph, fd);
gen_store_fpr32h(ctx, fp, fd);
#endif
gen_set_label(l2);
@@ -10246,13 +10254,13 @@
TCGv_i32 fp1 = tcg_temp_new_i32();
TCGv_i32 fp2 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
- gen_load_fpr32(fp1, ft);
- gen_load_fpr32(fp2, fr);
+ gen_load_fpr32(ctx, fp0, fs);
+ gen_load_fpr32(ctx, fp1, ft);
+ gen_load_fpr32(ctx, fp2, fr);
gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
tcg_temp_free_i32(fp0);
tcg_temp_free_i32(fp1);
- gen_store_fpr32(fp2, fd);
+ gen_store_fpr32(ctx, fp2, fd);
tcg_temp_free_i32(fp2);
}
opn = "madd.s";
@@ -10301,13 +10309,13 @@
TCGv_i32 fp1 = tcg_temp_new_i32();
TCGv_i32 fp2 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
- gen_load_fpr32(fp1, ft);
- gen_load_fpr32(fp2, fr);
+ gen_load_fpr32(ctx, fp0, fs);
+ gen_load_fpr32(ctx, fp1, ft);
+ gen_load_fpr32(ctx, fp2, fr);
gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
tcg_temp_free_i32(fp0);
tcg_temp_free_i32(fp1);
- gen_store_fpr32(fp2, fd);
+ gen_store_fpr32(ctx, fp2, fd);
tcg_temp_free_i32(fp2);
}
opn = "msub.s";
@@ -10356,13 +10364,13 @@
TCGv_i32 fp1 = tcg_temp_new_i32();
TCGv_i32 fp2 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
- gen_load_fpr32(fp1, ft);
- gen_load_fpr32(fp2, fr);
+ gen_load_fpr32(ctx, fp0, fs);
+ gen_load_fpr32(ctx, fp1, ft);
+ gen_load_fpr32(ctx, fp2, fr);
gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
tcg_temp_free_i32(fp0);
tcg_temp_free_i32(fp1);
- gen_store_fpr32(fp2, fd);
+ gen_store_fpr32(ctx, fp2, fd);
tcg_temp_free_i32(fp2);
}
opn = "nmadd.s";
@@ -10411,13 +10419,13 @@
TCGv_i32 fp1 = tcg_temp_new_i32();
TCGv_i32 fp2 = tcg_temp_new_i32();
- gen_load_fpr32(fp0, fs);
- gen_load_fpr32(fp1, ft);
- gen_load_fpr32(fp2, fr);
+ gen_load_fpr32(ctx, fp0, fs);
+ gen_load_fpr32(ctx, fp1, ft);
+ gen_load_fpr32(ctx, fp2, fr);
gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
tcg_temp_free_i32(fp0);
tcg_temp_free_i32(fp1);
- gen_store_fpr32(fp2, fd);
+ gen_store_fpr32(ctx, fp2, fd);
tcg_temp_free_i32(fp2);
}
opn = "nmsub.s";
@@ -10526,14 +10534,25 @@
tcg_temp_free(t0);
}
+static inline void clear_branch_hflags(DisasContext *ctx)
+{
+ ctx->hflags &= ~MIPS_HFLAG_BMASK;
+ if (ctx->bstate == BS_NONE) {
+ save_cpu_state(ctx, 0);
+ } else {
+ /* it is not safe to save ctx->hflags as hflags may be changed
+ in execution time by the instruction in delay / forbidden slot. */
+ tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
+ }
+}
+
static void gen_branch(DisasContext *ctx, int insn_bytes)
{
if (ctx->hflags & MIPS_HFLAG_BMASK) {
int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
/* Branches completion */
- ctx->hflags &= ~MIPS_HFLAG_BMASK;
+ clear_branch_hflags(ctx);
ctx->bstate = BS_BRANCH;
- save_cpu_state(ctx, 0);
/* FIXME: Need to clear can_do_io. */
switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
case MIPS_HFLAG_FBNSLOT:
@@ -10591,8 +10610,8 @@
tcg_gen_exit_tb(0);
break;
default:
- MIPS_DEBUG("unknown branch");
- break;
+ fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
+ abort();
}
}
}
@@ -13432,7 +13451,7 @@
case MOVF_FMT:
switch (fmt) {
case FMT_SDPS_S:
- gen_movcf_s(rs, rt, cc, 0);
+ gen_movcf_s(ctx, rs, rt, cc, 0);
break;
case FMT_SDPS_D:
gen_movcf_d(ctx, rs, rt, cc, 0);
@@ -13447,7 +13466,7 @@
case MOVT_FMT:
switch (fmt) {
case FMT_SDPS_S:
- gen_movcf_s(rs, rt, cc, 1);
+ gen_movcf_s(ctx, rs, rt, cc, 1);
break;
case FMT_SDPS_D:
gen_movcf_d(ctx, rs, rt, cc, 1);
@@ -18324,12 +18343,14 @@
case OPC_LD_H:
case OPC_LD_W:
case OPC_LD_D:
+ save_cpu_state(ctx, 1);
gen_helper_msa_ld_df(cpu_env, tdf, twd, trs, ts10);
break;
case OPC_ST_B:
case OPC_ST_H:
case OPC_ST_W:
case OPC_ST_D:
+ save_cpu_state(ctx, 1);
gen_helper_msa_st_df(cpu_env, tdf, twd, trs, ts10);
break;
}
diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index 4b70cca..eae4f0e 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -380,6 +380,43 @@
.insn_flags = CPU_MIPS32R5 | ASE_MIPS16 | 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) | (3 << CP0C1_IL) | (3 << CP0C1_IA) |
+ (2 << CP0C1_DS) | (3 << CP0C1_DL) | (3 << CP0C1_DA) |
+ (0 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
+ .CP0_Config2 = MIPS_CONFIG2,
+ .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_RXI) | (1 << CP0C3_BP) |
+ (1 << CP0C3_BI) | (1 << CP0C3_ULRI) | (1 << CP0C3_MSAP) |
+ (1U << CP0C3_M),
+ .CP0_Config4 = MIPS_CONFIG4 | (0xfc << CP0C4_KScrExist) |
+ (3 << CP0C4_IE) | (1U << CP0C4_M),
+ .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_LLB),
+ .CP0_Config5_rw_bitmask = (1 << CP0C5_SBRI) | (1 << CP0C5_FRE) |
+ (1 << CP0C5_UFE) | (1 << CP0C5_MSAEn),
+ .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_F64) | (1 << FCR0_L) |
+ (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) |
+ (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
+ .SEGBITS = 32,
+ .PABITS = 32,
+ .insn_flags = CPU_MIPS32R6 | ASE_MSA,
+ .mmu_type = MMU_TYPE_R4000,
+ },
#if defined(TARGET_MIPS64)
{
.name = "R4000",
@@ -521,23 +558,25 @@
},
{
/* A generic CPU supporting MIPS64 Release 6 ISA.
- FIXME: Support IEEE 754-2008 FP and misaligned memory accesses.
+ FIXME: Support IEEE 754-2008 FP.
Eventually this should be replaced by a real CPU model. */
.name = "MIPS64R6-generic",
.CP0_PRid = 0x00010000,
.CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AR) | (0x2 << CP0C0_AT) |
(MMU_TYPE_R4000 << CP0C0_MT),
- .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
+ .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (0x1F << CP0C1_MMU) |
(2 << CP0C1_IS) | (3 << CP0C1_IL) | (3 << CP0C1_IA) |
(2 << CP0C1_DS) | (3 << CP0C1_DL) | (3 << CP0C1_DA) |
(0 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
.CP0_Config2 = MIPS_CONFIG2,
- .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_RXI) | (1 << CP0C3_BP) |
- (1 << CP0C3_BI) | (1 << CP0C3_ULRI) | (1U << CP0C3_M),
+ .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),
.CP0_Config4 = MIPS_CONFIG4 | (0xfc << CP0C4_KScrExist) |
- (3 << CP0C4_IE) | (1 << CP0C4_M),
+ (3 << CP0C4_IE) | (1U << CP0C4_M),
.CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_LLB),
- .CP0_Config5_rw_bitmask = (1 << CP0C5_SBRI),
+ .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,
@@ -546,15 +585,13 @@
.CP0_PageGrain = (1 << CP0PG_IEC) | (1 << CP0PG_XIE) |
(1U << CP0PG_RIE),
.CP0_PageGrain_rw_bitmask = 0,
- .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
- (1 << FCR0_D) | (1 << FCR0_S) | (0x00 << FCR0_PRID) |
- (0x0 << FCR0_REV),
+ .CP1_fcr0 = (1 << FCR0_FREP) | (1 << FCR0_F64) | (1 << FCR0_L) |
+ (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) |
+ (0x03 << FCR0_PRID) | (0x20 << FCR0_REV),
+ .MSAIR = 0x03 << MSAIR_ProcID | 0x20 << MSAIR_Rev,
.SEGBITS = 42,
- /* The architectural limit is 59, but we have hardcoded 36 bit
- in some places...
- .PABITS = 59, */ /* the architectural limit */
- .PABITS = 36,
- .insn_flags = CPU_MIPS64R6,
+ .PABITS = 48,
+ .insn_flags = CPU_MIPS64R6 | ASE_MSA,
.mmu_type = MMU_TYPE_R4000,
},
{
diff --git a/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h
index 477c4d5..4bfbb84 100644
--- a/target-sparc/cpu-qom.h
+++ b/target-sparc/cpu-qom.h
@@ -83,6 +83,7 @@
int sparc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void QEMU_NORETURN sparc_cpu_do_unaligned_access(CPUState *cpu,
vaddr addr, int is_write,
- int is_user, uintptr_t retaddr);
+ int is_user, uintptr_t retaddr,
+ unsigned size);
#endif
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index 1a62e19..b032608 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -2420,7 +2420,8 @@
#if !defined(CONFIG_USER_ONLY)
void QEMU_NORETURN sparc_cpu_do_unaligned_access(CPUState *cs,
vaddr addr, int is_write,
- int is_user, uintptr_t retaddr)
+ int is_user, uintptr_t retaddr,
+ unsigned size)
{
SPARCCPU *cpu = SPARC_CPU(cs);
CPUSPARCState *env = &cpu->env;
diff --git a/target-xtensa/cpu-qom.h b/target-xtensa/cpu-qom.h
index 9de5c6e..e232bbf 100644
--- a/target-xtensa/cpu-qom.h
+++ b/target-xtensa/cpu-qom.h
@@ -91,6 +91,7 @@
int xtensa_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int xtensa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void xtensa_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
- int is_write, int is_user, uintptr_t retaddr);
+ int is_write, int is_user,
+ uintptr_t retaddr, unsigned size);
#endif
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index 872e5a8..3d431de 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -33,7 +33,7 @@
#include "qemu/timer.h"
void xtensa_cpu_do_unaligned_access(CPUState *cs,
- vaddr addr, int is_write, int is_user, uintptr_t retaddr)
+ vaddr addr, int is_write, int is_user, uintptr_t retaddr, unsigned size)
{
XtensaCPU *cpu = XTENSA_CPU(cs);
CPUXtensaState *env = &cpu->env;