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;