Browse Source

Merge remote-tracking branch 'remotes/amarkovic/tags/mips-queue-jan-29-2020' into staging

MIPS queue for January 29th, 2020

# gpg: Signature made Wed 29 Jan 2020 18:29:43 GMT
# gpg:                using RSA key D4972A8967F75A65
# gpg: Good signature from "Aleksandar Markovic <amarkovic@wavecomp.com>" [full]
# Primary key fingerprint: 8526 FBF1 5DA3 811F 4A01  DD75 D497 2A89 67F7 5A65

* remotes/amarkovic/tags/mips-queue-jan-29-2020:
  target/mips: Add implementation of GINVT instruction
  target/mips: Amend CP0 WatchHi register implementation
  hw/core/loader: Let load_elf() populate a field with CPU-specific flags
  target/mips: semihosting: Remove 'uhi_done' label in helper_do_semihosting()
  disas: Add a field for target-dependant data to disassemble_info
  target/mips: Rectify documentation on deprecating MIPS r4k machine

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Peter Maydell 5 years ago
parent
commit
204aa60b37

+ 10 - 0
disas/mips.c

@@ -1409,6 +1409,16 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"dvp",        "t",     0x41600024, 0xffe0ffff, TRAP|WR_t,            0, I32R6},
 {"dvp",        "t",     0x41600024, 0xffe0ffff, TRAP|WR_t,            0, I32R6},
 {"evp",        "",      0x41600004, 0xffffffff, TRAP,                 0, I32R6},
 {"evp",        "",      0x41600004, 0xffffffff, TRAP,                 0, I32R6},
 {"evp",        "t",     0x41600004, 0xffe0ffff, TRAP|WR_t,            0, I32R6},
 {"evp",        "t",     0x41600004, 0xffe0ffff, TRAP|WR_t,            0, I32R6},
+{"ginvi",      "v",     0x7c00003d, 0xfc1ffcff, TRAP | INSN_TLB,      0, I32R6},
+{"ginvt",      "v",     0x7c0000bd, 0xfc1ffcff, TRAP | INSN_TLB,      0, I32R6},
+{"crc32b",     "t,v,t", 0x7c00000f, 0xfc00ff3f, WR_d | RD_s | RD_t,   0, I32R6},
+{"crc32h",     "t,v,t", 0x7c00004f, 0xfc00ff3f, WR_d | RD_s | RD_t,   0, I32R6},
+{"crc32w",     "t,v,t", 0x7c00008f, 0xfc00ff3f, WR_d | RD_s | RD_t,   0, I32R6},
+{"crc32d",     "t,v,t", 0x7c0000cf, 0xfc00ff3f, WR_d | RD_s | RD_t,   0, I64R6},
+{"crc32cb",    "t,v,t", 0x7c00010f, 0xfc00ff3f, WR_d | RD_s | RD_t,   0, I32R6},
+{"crc32ch",    "t,v,t", 0x7c00014f, 0xfc00ff3f, WR_d | RD_s | RD_t,   0, I32R6},
+{"crc32cw",    "t,v,t", 0x7c00018f, 0xfc00ff3f, WR_d | RD_s | RD_t,   0, I32R6},
+{"crc32cd",    "t,v,t", 0x7c0001cf, 0xfc00ff3f, WR_d | RD_s | RD_t,   0, I64R6},
 
 
 /* MSA */
 /* MSA */
 {"sll.b",   "+d,+e,+f", 0x7800000d, 0xffe0003f, WR_VD|RD_VS|RD_VT,  0, MSA},
 {"sll.b",   "+d,+e,+f", 0x7800000d, 0xffe0003f, WR_VD|RD_VS|RD_VT,  0, MSA},

+ 2 - 2
hw/alpha/dp264.c

@@ -115,7 +115,7 @@ static void clipper_init(MachineState *machine)
         exit(1);
         exit(1);
     }
     }
     size = load_elf(palcode_filename, NULL, cpu_alpha_superpage_to_phys,
     size = load_elf(palcode_filename, NULL, cpu_alpha_superpage_to_phys,
-                    NULL, &palcode_entry, &palcode_low, &palcode_high,
+                    NULL, &palcode_entry, &palcode_low, &palcode_high, NULL,
                     0, EM_ALPHA, 0, 0);
                     0, EM_ALPHA, 0, 0);
     if (size < 0) {
     if (size < 0) {
         error_report("could not load palcode '%s'", palcode_filename);
         error_report("could not load palcode '%s'", palcode_filename);
@@ -134,7 +134,7 @@ static void clipper_init(MachineState *machine)
         uint64_t param_offset;
         uint64_t param_offset;
 
 
         size = load_elf(kernel_filename, NULL, cpu_alpha_superpage_to_phys,
         size = load_elf(kernel_filename, NULL, cpu_alpha_superpage_to_phys,
-                        NULL, &kernel_entry, &kernel_low, &kernel_high,
+                        NULL, &kernel_entry, &kernel_low, &kernel_high, NULL,
                         0, EM_ALPHA, 0, 0);
                         0, EM_ALPHA, 0, 0);
         if (size < 0) {
         if (size < 0) {
             error_report("could not load kernel '%s'", kernel_filename);
             error_report("could not load kernel '%s'", kernel_filename);

+ 1 - 1
hw/arm/armv7m.c

@@ -331,7 +331,7 @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
 
 
     if (kernel_filename) {
     if (kernel_filename) {
         image_size = load_elf_as(kernel_filename, NULL, NULL, NULL,
         image_size = load_elf_as(kernel_filename, NULL, NULL, NULL,
-                                 &entry, &lowaddr,
+                                 &entry, &lowaddr, NULL,
                                  NULL, big_endian, EM_ARM, 1, 0, as);
                                  NULL, big_endian, EM_ARM, 1, 0, as);
         if (image_size < 0) {
         if (image_size < 0) {
             image_size = load_image_targphys_as(kernel_filename, 0,
             image_size = load_image_targphys_as(kernel_filename, 0,

+ 1 - 1
hw/arm/boot.c

@@ -903,7 +903,7 @@ static int64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
     }
     }
 
 
     ret = load_elf_as(info->kernel_filename, NULL, NULL, NULL,
     ret = load_elf_as(info->kernel_filename, NULL, NULL, NULL,
-                      pentry, lowaddr, highaddr, big_endian, elf_machine,
+                      pentry, lowaddr, highaddr, NULL, big_endian, elf_machine,
                       1, data_swab, as);
                       1, data_swab, as);
     if (ret <= 0) {
     if (ret <= 0) {
         /* The header loaded but the image didn't */
         /* The header loaded but the image didn't */

+ 1 - 1
hw/core/generic-loader.c

@@ -140,7 +140,7 @@ static void generic_loader_realize(DeviceState *dev, Error **errp)
 
 
         if (!s->force_raw) {
         if (!s->force_raw) {
             size = load_elf_as(s->file, NULL, NULL, NULL, &entry, NULL, NULL,
             size = load_elf_as(s->file, NULL, NULL, NULL, &entry, NULL, NULL,
-                               big_endian, 0, 0, 0, as);
+                               NULL, big_endian, 0, 0, 0, as);
 
 
             if (size < 0) {
             if (size < 0) {
                 size = load_uimage_as(s->file, &entry, NULL, NULL, NULL, NULL,
                 size = load_uimage_as(s->file, &entry, NULL, NULL, NULL, NULL,

+ 19 - 18
hw/core/loader.c

@@ -406,12 +406,12 @@ int load_elf(const char *filename,
              uint64_t (*elf_note_fn)(void *, void *, bool),
              uint64_t (*elf_note_fn)(void *, void *, bool),
              uint64_t (*translate_fn)(void *, uint64_t),
              uint64_t (*translate_fn)(void *, uint64_t),
              void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
              void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
-             uint64_t *highaddr, int big_endian, int elf_machine,
-             int clear_lsb, int data_swab)
+             uint64_t *highaddr, uint32_t *pflags, int big_endian,
+             int elf_machine, int clear_lsb, int data_swab)
 {
 {
     return load_elf_as(filename, elf_note_fn, translate_fn, translate_opaque,
     return load_elf_as(filename, elf_note_fn, translate_fn, translate_opaque,
-                       pentry, lowaddr, highaddr, big_endian, elf_machine,
-                       clear_lsb, data_swab, NULL);
+                       pentry, lowaddr, highaddr, pflags, big_endian,
+                       elf_machine, clear_lsb, data_swab, NULL);
 }
 }
 
 
 /* return < 0 if error, otherwise the number of bytes loaded in memory */
 /* return < 0 if error, otherwise the number of bytes loaded in memory */
@@ -419,12 +419,12 @@ int load_elf_as(const char *filename,
                 uint64_t (*elf_note_fn)(void *, void *, bool),
                 uint64_t (*elf_note_fn)(void *, void *, bool),
                 uint64_t (*translate_fn)(void *, uint64_t),
                 uint64_t (*translate_fn)(void *, uint64_t),
                 void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
                 void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
-                uint64_t *highaddr, int big_endian, int elf_machine,
-                int clear_lsb, int data_swab, AddressSpace *as)
+                uint64_t *highaddr, uint32_t *pflags, int big_endian,
+                int elf_machine, int clear_lsb, int data_swab, AddressSpace *as)
 {
 {
     return load_elf_ram(filename, elf_note_fn, translate_fn, translate_opaque,
     return load_elf_ram(filename, elf_note_fn, translate_fn, translate_opaque,
-                        pentry, lowaddr, highaddr, big_endian, elf_machine,
-                        clear_lsb, data_swab, as, true);
+                        pentry, lowaddr, highaddr, pflags, big_endian,
+                        elf_machine, clear_lsb, data_swab, as, true);
 }
 }
 
 
 /* return < 0 if error, otherwise the number of bytes loaded in memory */
 /* return < 0 if error, otherwise the number of bytes loaded in memory */
@@ -432,13 +432,13 @@ int load_elf_ram(const char *filename,
                  uint64_t (*elf_note_fn)(void *, void *, bool),
                  uint64_t (*elf_note_fn)(void *, void *, bool),
                  uint64_t (*translate_fn)(void *, uint64_t),
                  uint64_t (*translate_fn)(void *, uint64_t),
                  void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
                  void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
-                 uint64_t *highaddr, int big_endian, int elf_machine,
-                 int clear_lsb, int data_swab, AddressSpace *as,
-                 bool load_rom)
+                 uint64_t *highaddr, uint32_t *pflags, int big_endian,
+                 int elf_machine, int clear_lsb, int data_swab,
+                 AddressSpace *as, bool load_rom)
 {
 {
     return load_elf_ram_sym(filename, elf_note_fn,
     return load_elf_ram_sym(filename, elf_note_fn,
                             translate_fn, translate_opaque,
                             translate_fn, translate_opaque,
-                            pentry, lowaddr, highaddr, big_endian,
+                            pentry, lowaddr, highaddr, pflags, big_endian,
                             elf_machine, clear_lsb, data_swab, as,
                             elf_machine, clear_lsb, data_swab, as,
                             load_rom, NULL);
                             load_rom, NULL);
 }
 }
@@ -448,8 +448,9 @@ int load_elf_ram_sym(const char *filename,
                      uint64_t (*elf_note_fn)(void *, void *, bool),
                      uint64_t (*elf_note_fn)(void *, void *, bool),
                      uint64_t (*translate_fn)(void *, uint64_t),
                      uint64_t (*translate_fn)(void *, uint64_t),
                      void *translate_opaque, uint64_t *pentry,
                      void *translate_opaque, uint64_t *pentry,
-                     uint64_t *lowaddr, uint64_t *highaddr, int big_endian,
-                     int elf_machine, int clear_lsb, int data_swab,
+                     uint64_t *lowaddr, uint64_t *highaddr, uint32_t *pflags,
+                     int big_endian, int elf_machine,
+                     int clear_lsb, int data_swab,
                      AddressSpace *as, bool load_rom, symbol_fn_t sym_cb)
                      AddressSpace *as, bool load_rom, symbol_fn_t sym_cb)
 {
 {
     int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED;
     int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED;
@@ -490,13 +491,13 @@ int load_elf_ram_sym(const char *filename,
     if (e_ident[EI_CLASS] == ELFCLASS64) {
     if (e_ident[EI_CLASS] == ELFCLASS64) {
         ret = load_elf64(filename, fd, elf_note_fn,
         ret = load_elf64(filename, fd, elf_note_fn,
                          translate_fn, translate_opaque, must_swab,
                          translate_fn, translate_opaque, must_swab,
-                         pentry, lowaddr, highaddr, elf_machine, clear_lsb,
-                         data_swab, as, load_rom, sym_cb);
+                         pentry, lowaddr, highaddr, pflags, elf_machine,
+                         clear_lsb, data_swab, as, load_rom, sym_cb);
     } else {
     } else {
         ret = load_elf32(filename, fd, elf_note_fn,
         ret = load_elf32(filename, fd, elf_note_fn,
                          translate_fn, translate_opaque, must_swab,
                          translate_fn, translate_opaque, must_swab,
-                         pentry, lowaddr, highaddr, elf_machine, clear_lsb,
-                         data_swab, as, load_rom, sym_cb);
+                         pentry, lowaddr, highaddr, pflags, elf_machine,
+                         clear_lsb, data_swab, as, load_rom, sym_cb);
     }
     }
 
 
  fail:
  fail:

+ 1 - 1
hw/cris/boot.c

@@ -76,7 +76,7 @@ void cris_load_image(CRISCPU *cpu, struct cris_load_info *li)
        devboard SDK.  */
        devboard SDK.  */
     image_size = load_elf(li->image_filename, NULL,
     image_size = load_elf(li->image_filename, NULL,
                           translate_kernel_address, NULL,
                           translate_kernel_address, NULL,
-                          &entry, NULL, &high, 0, EM_CRIS, 0, 0);
+                          &entry, NULL, &high, NULL, 0, EM_CRIS, 0, 0);
     li->entry = entry;
     li->entry = entry;
     if (image_size < 0) {
     if (image_size < 0) {
         /* Takes a kimage from the axis devboard SDK.  */
         /* Takes a kimage from the axis devboard SDK.  */

+ 2 - 2
hw/hppa/machine.c

@@ -155,7 +155,7 @@ static void machine_hppa_init(MachineState *machine)
     }
     }
 
 
     size = load_elf(firmware_filename, NULL, NULL, NULL,
     size = load_elf(firmware_filename, NULL, NULL, NULL,
-                    &firmware_entry, &firmware_low, &firmware_high,
+                    &firmware_entry, &firmware_low, &firmware_high, NULL,
                     true, EM_PARISC, 0, 0);
                     true, EM_PARISC, 0, 0);
 
 
     /* Unfortunately, load_elf sign-extends reading elf32.  */
     /* Unfortunately, load_elf sign-extends reading elf32.  */
@@ -184,7 +184,7 @@ static void machine_hppa_init(MachineState *machine)
     /* Load kernel */
     /* Load kernel */
     if (kernel_filename) {
     if (kernel_filename) {
         size = load_elf(kernel_filename, NULL, &cpu_hppa_to_phys,
         size = load_elf(kernel_filename, NULL, &cpu_hppa_to_phys,
-                        NULL, &kernel_entry, &kernel_low, &kernel_high,
+                        NULL, &kernel_entry, &kernel_low, &kernel_high, NULL,
                         true, EM_PARISC, 0, 0);
                         true, EM_PARISC, 0, 0);
 
 
         /* Unfortunately, load_elf sign-extends reading elf32.  */
         /* Unfortunately, load_elf sign-extends reading elf32.  */

+ 1 - 1
hw/i386/multiboot.c

@@ -199,7 +199,7 @@ int load_multiboot(FWCfgState *fw_cfg,
         }
         }
 
 
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry,
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry,
-                               &elf_low, &elf_high, 0, I386_ELF_MACHINE,
+                               &elf_low, &elf_high, NULL, 0, I386_ELF_MACHINE,
                                0, 0);
                                0, 0);
         if (kernel_size < 0) {
         if (kernel_size < 0) {
             error_report("Error while loading elf kernel");
             error_report("Error while loading elf kernel");

+ 1 - 1
hw/i386/x86.c

@@ -413,7 +413,7 @@ static bool load_elfboot(const char *kernel_filename,
     uint64_t elf_note_type = XEN_ELFNOTE_PHYS32_ENTRY;
     uint64_t elf_note_type = XEN_ELFNOTE_PHYS32_ENTRY;
     kernel_size = load_elf(kernel_filename, read_pvh_start_addr,
     kernel_size = load_elf(kernel_filename, read_pvh_start_addr,
                            NULL, &elf_note_type, &elf_entry,
                            NULL, &elf_note_type, &elf_entry,
-                           &elf_low, &elf_high, 0, I386_ELF_MACHINE,
+                           &elf_low, &elf_high, NULL, 0, I386_ELF_MACHINE,
                            0, 0);
                            0, 0);
 
 
     if (kernel_size < 0) {
     if (kernel_size < 0) {

+ 2 - 2
hw/lm32/lm32_boards.c

@@ -138,7 +138,7 @@ static void lm32_evr_init(MachineState *machine)
         int kernel_size;
         int kernel_size;
 
 
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
-                               &entry, NULL, NULL,
+                               &entry, NULL, NULL, NULL,
                                1, EM_LATTICEMICO32, 0, 0);
                                1, EM_LATTICEMICO32, 0, 0);
         reset_info->bootstrap_pc = entry;
         reset_info->bootstrap_pc = entry;
 
 
@@ -232,7 +232,7 @@ static void lm32_uclinux_init(MachineState *machine)
         int kernel_size;
         int kernel_size;
 
 
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
-                               &entry, NULL, NULL,
+                               &entry, NULL, NULL, NULL,
                                1, EM_LATTICEMICO32, 0, 0);
                                1, EM_LATTICEMICO32, 0, 0);
         reset_info->bootstrap_pc = entry;
         reset_info->bootstrap_pc = entry;
 
 

+ 1 - 1
hw/lm32/milkymist.c

@@ -177,7 +177,7 @@ milkymist_init(MachineState *machine)
 
 
         /* Boots a kernel elf binary.  */
         /* Boots a kernel elf binary.  */
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
-                               &entry, NULL, NULL,
+                               &entry, NULL, NULL, NULL,
                                1, EM_LATTICEMICO32, 0, 0);
                                1, EM_LATTICEMICO32, 0, 0);
         reset_info->bootstrap_pc = entry;
         reset_info->bootstrap_pc = entry;
 
 

+ 1 - 1
hw/m68k/an5206.c

@@ -65,7 +65,7 @@ static void an5206_init(MachineState *machine)
     }
     }
 
 
     kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry,
     kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry,
-                           NULL, NULL, 1, EM_68K, 0, 0);
+                           NULL, NULL, NULL, 1, EM_68K, 0, 0);
     entry = elf_entry;
     entry = elf_entry;
     if (kernel_size < 0) {
     if (kernel_size < 0) {
         kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
         kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,

+ 1 - 1
hw/m68k/mcf5208.c

@@ -329,7 +329,7 @@ static void mcf5208evb_init(MachineState *machine)
     }
     }
 
 
     kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry,
     kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry,
-                           NULL, NULL, 1, EM_68K, 0, 0);
+                           NULL, NULL, NULL, 1, EM_68K, 0, 0);
     entry = elf_entry;
     entry = elf_entry;
     if (kernel_size < 0) {
     if (kernel_size < 0) {
         kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
         kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,

+ 1 - 1
hw/m68k/q800.c

@@ -342,7 +342,7 @@ static void q800_init(MachineState *machine)
     if (linux_boot) {
     if (linux_boot) {
         uint64_t high;
         uint64_t high;
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
-                               &elf_entry, NULL, &high, 1,
+                               &elf_entry, NULL, &high, NULL, 1,
                                EM_68K, 0, 0);
                                EM_68K, 0, 0);
         if (kernel_size < 0) {
         if (kernel_size < 0) {
             error_report("could not load kernel '%s'", kernel_filename);
             error_report("could not load kernel '%s'", kernel_filename);

+ 2 - 2
hw/microblaze/boot.c

@@ -145,13 +145,13 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
 
 
         /* Boots a kernel elf binary.  */
         /* Boots a kernel elf binary.  */
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
-                               &entry, &low, &high,
+                               &entry, &low, &high, NULL,
                                big_endian, EM_MICROBLAZE, 0, 0);
                                big_endian, EM_MICROBLAZE, 0, 0);
         base32 = entry;
         base32 = entry;
         if (base32 == 0xc0000000) {
         if (base32 == 0xc0000000) {
             kernel_size = load_elf(kernel_filename, NULL,
             kernel_size = load_elf(kernel_filename, NULL,
                                    translate_kernel_address, NULL,
                                    translate_kernel_address, NULL,
-                                   &entry, NULL, NULL,
+                                   &entry, NULL, NULL, NULL,
                                    big_endian, EM_MICROBLAZE, 0, 0);
                                    big_endian, EM_MICROBLAZE, 0, 0);
         }
         }
         /* Always boot into physical ram.  */
         /* Always boot into physical ram.  */

+ 1 - 1
hw/mips/mips_fulong2e.c

@@ -119,7 +119,7 @@ static int64_t load_kernel(CPUMIPSState *env)
                            cpu_mips_kseg0_to_phys, NULL,
                            cpu_mips_kseg0_to_phys, NULL,
                            (uint64_t *)&kernel_entry,
                            (uint64_t *)&kernel_entry,
                            (uint64_t *)&kernel_low, (uint64_t *)&kernel_high,
                            (uint64_t *)&kernel_low, (uint64_t *)&kernel_high,
-                           0, EM_MIPS, 1, 0);
+                           NULL, 0, EM_MIPS, 1, 0);
     if (kernel_size < 0) {
     if (kernel_size < 0) {
         error_report("could not load kernel '%s': %s",
         error_report("could not load kernel '%s': %s",
                      loaderparams.kernel_filename,
                      loaderparams.kernel_filename,

+ 2 - 1
hw/mips/mips_malta.c

@@ -1039,7 +1039,8 @@ static int64_t load_kernel(void)
     kernel_size = load_elf(loaderparams.kernel_filename, NULL,
     kernel_size = load_elf(loaderparams.kernel_filename, NULL,
                            cpu_mips_kseg0_to_phys, NULL,
                            cpu_mips_kseg0_to_phys, NULL,
                            (uint64_t *)&kernel_entry, NULL,
                            (uint64_t *)&kernel_entry, NULL,
-                           (uint64_t *)&kernel_high, big_endian, EM_MIPS, 1, 0);
+                           (uint64_t *)&kernel_high, NULL, big_endian, EM_MIPS,
+                           1, 0);
     if (kernel_size < 0) {
     if (kernel_size < 0) {
         error_report("could not load kernel '%s': %s",
         error_report("could not load kernel '%s': %s",
                      loaderparams.kernel_filename,
                      loaderparams.kernel_filename,

+ 1 - 1
hw/mips/mips_mipssim.c

@@ -74,7 +74,7 @@ static int64_t load_kernel(void)
     kernel_size = load_elf(loaderparams.kernel_filename, NULL,
     kernel_size = load_elf(loaderparams.kernel_filename, NULL,
                            cpu_mips_kseg0_to_phys, NULL,
                            cpu_mips_kseg0_to_phys, NULL,
                            (uint64_t *)&entry, NULL,
                            (uint64_t *)&entry, NULL,
-                           (uint64_t *)&kernel_high, big_endian,
+                           (uint64_t *)&kernel_high, NULL, big_endian,
                            EM_MIPS, 1, 0);
                            EM_MIPS, 1, 0);
     if (kernel_size >= 0) {
     if (kernel_size >= 0) {
         if ((entry & ~0x7fffffffULL) == 0x80000000) {
         if ((entry & ~0x7fffffffULL) == 0x80000000) {

+ 1 - 1
hw/mips/mips_r4k.c

@@ -98,7 +98,7 @@ static int64_t load_kernel(void)
     kernel_size = load_elf(loaderparams.kernel_filename, NULL,
     kernel_size = load_elf(loaderparams.kernel_filename, NULL,
                            cpu_mips_kseg0_to_phys, NULL,
                            cpu_mips_kseg0_to_phys, NULL,
                            (uint64_t *)&entry, NULL,
                            (uint64_t *)&entry, NULL,
-                           (uint64_t *)&kernel_high, big_endian,
+                           (uint64_t *)&kernel_high, NULL, big_endian,
                            EM_MIPS, 1, 0);
                            EM_MIPS, 1, 0);
     if (kernel_size >= 0) {
     if (kernel_size >= 0) {
         if ((entry & ~0x7fffffffULL) == 0x80000000) {
         if ((entry & ~0x7fffffffULL) == 0x80000000) {

+ 1 - 1
hw/moxie/moxiesim.c

@@ -58,7 +58,7 @@ static void load_kernel(MoxieCPU *cpu, LoaderParams *loader_params)
     ram_addr_t initrd_offset;
     ram_addr_t initrd_offset;
 
 
     kernel_size = load_elf(loader_params->kernel_filename,  NULL, NULL, NULL,
     kernel_size = load_elf(loader_params->kernel_filename,  NULL, NULL, NULL,
-                           &entry, &kernel_low, &kernel_high, 1, EM_MOXIE,
+                           &entry, &kernel_low, &kernel_high, NULL, 1, EM_MOXIE,
                            0, 0);
                            0, 0);
 
 
     if (kernel_size <= 0) {
     if (kernel_size <= 0) {

+ 2 - 2
hw/nios2/boot.c

@@ -147,7 +147,7 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
 
 
         /* Boots a kernel elf binary. */
         /* Boots a kernel elf binary. */
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
-                               &entry, &low, &high,
+                               &entry, &low, &high, NULL,
                                big_endian, EM_ALTERA_NIOS2, 0, 0);
                                big_endian, EM_ALTERA_NIOS2, 0, 0);
         if ((uint32_t)entry == 0xc0000000) {
         if ((uint32_t)entry == 0xc0000000) {
             /*
             /*
@@ -158,7 +158,7 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
              */
              */
             kernel_size = load_elf(kernel_filename, NULL,
             kernel_size = load_elf(kernel_filename, NULL,
                                    translate_kernel_address, NULL,
                                    translate_kernel_address, NULL,
-                                   &entry, NULL, NULL,
+                                   &entry, NULL, NULL, NULL,
                                    big_endian, EM_ALTERA_NIOS2, 0, 0);
                                    big_endian, EM_ALTERA_NIOS2, 0, 0);
             boot_info.bootstrap_pc = ddr_base + 0xc0000000 +
             boot_info.bootstrap_pc = ddr_base + 0xc0000000 +
                 (entry & 0x07ffffff);
                 (entry & 0x07ffffff);

+ 1 - 1
hw/openrisc/openrisc_sim.c

@@ -98,7 +98,7 @@ static void openrisc_load_kernel(ram_addr_t ram_size,
 
 
     if (kernel_filename && !qtest_enabled()) {
     if (kernel_filename && !qtest_enabled()) {
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
-                               &elf_entry, NULL, NULL, 1, EM_OPENRISC,
+                               &elf_entry, NULL, NULL, NULL, 1, EM_OPENRISC,
                                1, 0);
                                1, 0);
         entry = elf_entry;
         entry = elf_entry;
         if (kernel_size < 0) {
         if (kernel_size < 0) {

+ 2 - 1
hw/pci-host/prep.c

@@ -335,7 +335,8 @@ static void raven_realize(PCIDevice *d, Error **errp)
         if (filename) {
         if (filename) {
             if (s->elf_machine != EM_NONE) {
             if (s->elf_machine != EM_NONE) {
                 bios_size = load_elf(filename, NULL, NULL, NULL, NULL,
                 bios_size = load_elf(filename, NULL, NULL, NULL, NULL,
-                                     NULL, NULL, 1, s->elf_machine, 0, 0);
+                                     NULL, NULL, NULL, 1, s->elf_machine,
+                                     0, 0);
             }
             }
             if (bios_size < 0) {
             if (bios_size < 0) {
                 bios_size = get_image_size(filename);
                 bios_size = get_image_size(filename);

+ 1 - 1
hw/ppc/e500.c

@@ -1049,7 +1049,7 @@ void ppce500_init(MachineState *machine)
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, payload_name);
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, payload_name);
 
 
     payload_size = load_elf(filename, NULL, NULL, NULL,
     payload_size = load_elf(filename, NULL, NULL, NULL,
-                            &bios_entry, &loadaddr, NULL,
+                            &bios_entry, &loadaddr, NULL, NULL,
                             1, PPC_ELF_MACHINE, 0, 0);
                             1, PPC_ELF_MACHINE, 0, 0);
     if (payload_size < 0) {
     if (payload_size < 0) {
         /*
         /*

+ 2 - 2
hw/ppc/mac_newworld.c

@@ -168,7 +168,7 @@ static void ppc_core99_init(MachineState *machine)
     /* Load OpenBIOS (ELF) */
     /* Load OpenBIOS (ELF) */
     if (filename) {
     if (filename) {
         bios_size = load_elf(filename, NULL, NULL, NULL, NULL,
         bios_size = load_elf(filename, NULL, NULL, NULL, NULL,
-                             NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0);
+                             NULL, NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0);
 
 
         g_free(filename);
         g_free(filename);
     } else {
     } else {
@@ -192,7 +192,7 @@ static void ppc_core99_init(MachineState *machine)
 
 
         kernel_size = load_elf(kernel_filename, NULL,
         kernel_size = load_elf(kernel_filename, NULL,
                                translate_kernel_address, NULL,
                                translate_kernel_address, NULL,
-                               NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE,
+                               NULL, &lowaddr, NULL, NULL, 1, PPC_ELF_MACHINE,
                                0, 0);
                                0, 0);
         if (kernel_size < 0)
         if (kernel_size < 0)
             kernel_size = load_aout(kernel_filename, kernel_base,
             kernel_size = load_aout(kernel_filename, kernel_base,

+ 2 - 2
hw/ppc/mac_oldworld.c

@@ -143,7 +143,7 @@ static void ppc_heathrow_init(MachineState *machine)
 
 
     /* Load OpenBIOS (ELF) */
     /* Load OpenBIOS (ELF) */
     if (filename) {
     if (filename) {
-        bios_size = load_elf(filename, NULL, 0, NULL, NULL, NULL, NULL,
+        bios_size = load_elf(filename, NULL, 0, NULL, NULL, NULL, NULL, NULL,
                              1, PPC_ELF_MACHINE, 0, 0);
                              1, PPC_ELF_MACHINE, 0, 0);
         g_free(filename);
         g_free(filename);
     } else {
     } else {
@@ -166,7 +166,7 @@ static void ppc_heathrow_init(MachineState *machine)
         kernel_base = KERNEL_LOAD_ADDR;
         kernel_base = KERNEL_LOAD_ADDR;
         kernel_size = load_elf(kernel_filename, NULL,
         kernel_size = load_elf(kernel_filename, NULL,
                                translate_kernel_address, NULL,
                                translate_kernel_address, NULL,
-                               NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE,
+                               NULL, &lowaddr, NULL, NULL, 1, PPC_ELF_MACHINE,
                                0, 0);
                                0, 0);
         if (kernel_size < 0)
         if (kernel_size < 0)
             kernel_size = load_aout(kernel_filename, kernel_base,
             kernel_size = load_aout(kernel_filename, kernel_base,

+ 1 - 1
hw/ppc/ppc440_bamboo.c

@@ -253,7 +253,7 @@ static void bamboo_init(MachineState *machine)
                               NULL, NULL);
                               NULL, NULL);
         if (success < 0) {
         if (success < 0) {
             success = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry,
             success = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry,
-                               &elf_lowaddr, NULL, 1, PPC_ELF_MACHINE,
+                               &elf_lowaddr, NULL, NULL, 1, PPC_ELF_MACHINE,
                                0, 0);
                                0, 0);
             entry = elf_entry;
             entry = elf_entry;
             loadaddr = elf_lowaddr;
             loadaddr = elf_lowaddr;

+ 2 - 1
hw/ppc/sam460ex.c

@@ -439,7 +439,8 @@ static void sam460ex_init(MachineState *machine)
 
 
             success = load_elf(machine->kernel_filename, NULL,
             success = load_elf(machine->kernel_filename, NULL,
                                NULL, NULL, &elf_entry,
                                NULL, NULL, &elf_entry,
-                               &elf_lowaddr, NULL, 1, PPC_ELF_MACHINE, 0, 0);
+                               &elf_lowaddr, NULL, NULL, 1, PPC_ELF_MACHINE, 0,
+                               0);
             entry = elf_entry;
             entry = elf_entry;
             loadaddr = elf_lowaddr;
             loadaddr = elf_lowaddr;
         }
         }

+ 3 - 3
hw/ppc/spapr.c

@@ -2895,13 +2895,13 @@ static void spapr_machine_init(MachineState *machine)
 
 
         spapr->kernel_size = load_elf(kernel_filename, NULL,
         spapr->kernel_size = load_elf(kernel_filename, NULL,
                                       translate_kernel_address, NULL,
                                       translate_kernel_address, NULL,
-                                      NULL, &lowaddr, NULL, 1,
+                                      NULL, &lowaddr, NULL, NULL, 1,
                                       PPC_ELF_MACHINE, 0, 0);
                                       PPC_ELF_MACHINE, 0, 0);
         if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) {
         if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) {
             spapr->kernel_size = load_elf(kernel_filename, NULL,
             spapr->kernel_size = load_elf(kernel_filename, NULL,
                                           translate_kernel_address, NULL, NULL,
                                           translate_kernel_address, NULL, NULL,
-                                          &lowaddr, NULL, 0, PPC_ELF_MACHINE,
-                                          0, 0);
+                                          &lowaddr, NULL, NULL, 0,
+                                          PPC_ELF_MACHINE, 0, 0);
             spapr->kernel_le = spapr->kernel_size > 0;
             spapr->kernel_le = spapr->kernel_size > 0;
         }
         }
         if (spapr->kernel_size < 0) {
         if (spapr->kernel_size < 0) {

+ 1 - 1
hw/ppc/virtex_ml507.c

@@ -259,7 +259,7 @@ static void virtex_init(MachineState *machine)
 
 
         /* Boots a kernel elf binary.  */
         /* Boots a kernel elf binary.  */
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
-                               &entry, &low, &high, 1, PPC_ELF_MACHINE,
+                               &entry, &low, &high, NULL, 1, PPC_ELF_MACHINE,
                                0, 0);
                                0, 0);
         boot_info.bootstrap_pc = entry & 0x00ffffff;
         boot_info.bootstrap_pc = entry & 0x00ffffff;
 
 

+ 2 - 2
hw/riscv/boot.c

@@ -101,7 +101,7 @@ target_ulong riscv_load_firmware(const char *firmware_filename,
     uint64_t firmware_entry, firmware_start, firmware_end;
     uint64_t firmware_entry, firmware_start, firmware_end;
 
 
     if (load_elf(firmware_filename, NULL, NULL, NULL, &firmware_entry,
     if (load_elf(firmware_filename, NULL, NULL, NULL, &firmware_entry,
-                 &firmware_start, &firmware_end, 0, EM_RISCV, 1, 0) > 0) {
+                 &firmware_start, &firmware_end, NULL, 0, EM_RISCV, 1, 0) > 0) {
         return firmware_entry;
         return firmware_entry;
     }
     }
 
 
@@ -119,7 +119,7 @@ target_ulong riscv_load_kernel(const char *kernel_filename, symbol_fn_t sym_cb)
     uint64_t kernel_entry, kernel_high;
     uint64_t kernel_entry, kernel_high;
 
 
     if (load_elf_ram_sym(kernel_filename, NULL, NULL, NULL,
     if (load_elf_ram_sym(kernel_filename, NULL, NULL, NULL,
-                         &kernel_entry, NULL, &kernel_high, 0,
+                         &kernel_entry, NULL, &kernel_high, NULL, 0,
                          EM_RISCV, 1, 0, NULL, true, sym_cb) > 0) {
                          EM_RISCV, 1, 0, NULL, true, sym_cb) > 0) {
         return kernel_entry;
         return kernel_entry;
     }
     }

+ 4 - 3
hw/s390x/ipl.c

@@ -139,7 +139,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
 
 
         bios_size = load_elf(bios_filename, NULL,
         bios_size = load_elf(bios_filename, NULL,
                              bios_translate_addr, &fwbase,
                              bios_translate_addr, &fwbase,
-                             &ipl->bios_start_addr, NULL, NULL, 1,
+                             &ipl->bios_start_addr, NULL, NULL, NULL, 1,
                              EM_S390, 0, 0);
                              EM_S390, 0, 0);
         if (bios_size > 0) {
         if (bios_size > 0) {
             /* Adjust ELF start address to final location */
             /* Adjust ELF start address to final location */
@@ -164,7 +164,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
     if (ipl->kernel) {
     if (ipl->kernel) {
         kernel_size = load_elf(ipl->kernel, NULL, NULL, NULL,
         kernel_size = load_elf(ipl->kernel, NULL, NULL, NULL,
                                &pentry, NULL,
                                &pentry, NULL,
-                               NULL, 1, EM_S390, 0, 0);
+                               NULL, NULL, 1, EM_S390, 0, 0);
         if (kernel_size < 0) {
         if (kernel_size < 0) {
             kernel_size = load_image_targphys(ipl->kernel, 0, ram_size);
             kernel_size = load_image_targphys(ipl->kernel, 0, ram_size);
             if (kernel_size < 0) {
             if (kernel_size < 0) {
@@ -473,7 +473,8 @@ static int load_netboot_image(Error **errp)
 
 
     img_size = load_elf_ram(netboot_filename, NULL, NULL, NULL,
     img_size = load_elf_ram(netboot_filename, NULL, NULL, NULL,
                             &ipl->start_addr,
                             &ipl->start_addr,
-                            NULL, NULL, 1, EM_S390, 0, 0, NULL, false);
+                            NULL, NULL, NULL, 1, EM_S390, 0, 0, NULL,
+                            false);
 
 
     if (img_size < 0) {
     if (img_size < 0) {
         img_size = load_image_size(netboot_filename, ram_ptr, ram_size);
         img_size = load_image_size(netboot_filename, ram_ptr, ram_size);

+ 1 - 1
hw/sparc/leon3.c

@@ -297,7 +297,7 @@ static void leon3_generic_hw_init(MachineState *machine)
         uint64_t entry;
         uint64_t entry;
 
 
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
-                               &entry, NULL, NULL,
+                               &entry, NULL, NULL, NULL,
                                1 /* big endian */, EM_SPARC, 0, 0);
                                1 /* big endian */, EM_SPARC, 0, 0);
         if (kernel_size < 0) {
         if (kernel_size < 0) {
             kernel_size = load_uimage(kernel_filename, NULL, &entry,
             kernel_size = load_uimage(kernel_filename, NULL, &entry,

+ 2 - 2
hw/sparc/sun4m.c

@@ -270,7 +270,7 @@ static unsigned long sun4m_load_kernel(const char *kernel_filename,
 #endif
 #endif
         kernel_size = load_elf(kernel_filename, NULL,
         kernel_size = load_elf(kernel_filename, NULL,
                                translate_kernel_address, NULL,
                                translate_kernel_address, NULL,
-                               NULL, NULL, NULL, 1, EM_SPARC, 0, 0);
+                               NULL, NULL, NULL, NULL, 1, EM_SPARC, 0, 0);
         if (kernel_size < 0)
         if (kernel_size < 0)
             kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
             kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
                                     RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
                                     RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
@@ -721,7 +721,7 @@ static void prom_init(hwaddr addr, const char *bios_name)
     if (filename) {
     if (filename) {
         ret = load_elf(filename, NULL,
         ret = load_elf(filename, NULL,
                        translate_prom_address, &addr, NULL,
                        translate_prom_address, &addr, NULL,
-                       NULL, NULL, 1, EM_SPARC, 0, 0);
+                       NULL, NULL, NULL, 1, EM_SPARC, 0, 0);
         if (ret < 0 || ret > PROM_SIZE_MAX) {
         if (ret < 0 || ret > PROM_SIZE_MAX) {
             ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
             ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
         }
         }

+ 3 - 2
hw/sparc64/sun4u.c

@@ -175,7 +175,8 @@ static uint64_t sun4u_load_kernel(const char *kernel_filename,
         bswap_needed = 0;
         bswap_needed = 0;
 #endif
 #endif
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, kernel_entry,
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, kernel_entry,
-                               kernel_addr, &kernel_top, 1, EM_SPARCV9, 0, 0);
+                               kernel_addr, &kernel_top, NULL, 1, EM_SPARCV9, 0,
+                               0);
         if (kernel_size < 0) {
         if (kernel_size < 0) {
             *kernel_addr = KERNEL_LOAD_ADDR;
             *kernel_addr = KERNEL_LOAD_ADDR;
             *kernel_entry = KERNEL_LOAD_ADDR;
             *kernel_entry = KERNEL_LOAD_ADDR;
@@ -439,7 +440,7 @@ static void prom_init(hwaddr addr, const char *bios_name)
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
     if (filename) {
     if (filename) {
         ret = load_elf(filename, NULL, translate_prom_address, &addr,
         ret = load_elf(filename, NULL, translate_prom_address, &addr,
-                       NULL, NULL, NULL, 1, EM_SPARCV9, 0, 0);
+                       NULL, NULL, NULL, NULL, 1, EM_SPARCV9, 0, 0);
         if (ret < 0 || ret > PROM_SIZE_MAX) {
         if (ret < 0 || ret > PROM_SIZE_MAX) {
             ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
             ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
         }
         }

+ 1 - 1
hw/tricore/tricore_testboard.c

@@ -42,7 +42,7 @@ static void tricore_load_kernel(CPUTriCoreState *env)
 
 
     kernel_size = load_elf(tricoretb_binfo.kernel_filename, NULL,
     kernel_size = load_elf(tricoretb_binfo.kernel_filename, NULL,
                            NULL, NULL, &entry, NULL,
                            NULL, NULL, &entry, NULL,
-                           NULL, 0,
+                           NULL, NULL, 0,
                            EM_TRICORE, 1, 0);
                            EM_TRICORE, 1, 0);
     if (kernel_size <= 0) {
     if (kernel_size <= 0) {
         error_report("no kernel file '%s'",
         error_report("no kernel file '%s'",

+ 1 - 1
hw/xtensa/sim.c

@@ -108,7 +108,7 @@ void xtensa_sim_load_kernel(XtensaCPU *cpu, MachineState *machine)
         uint64_t elf_entry;
         uint64_t elf_entry;
         uint64_t elf_lowaddr;
         uint64_t elf_lowaddr;
         int success = load_elf(kernel_filename, NULL, translate_phys_addr, cpu,
         int success = load_elf(kernel_filename, NULL, translate_phys_addr, cpu,
-                               &elf_entry, &elf_lowaddr, NULL, big_endian,
+                               &elf_entry, &elf_lowaddr, NULL, NULL, big_endian,
                                EM_XTENSA, 0, 0);
                                EM_XTENSA, 0, 0);
 
 
         if (success > 0) {
         if (success > 0) {

+ 1 - 1
hw/xtensa/xtfpga.c

@@ -415,7 +415,7 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine)
         uint64_t elf_entry;
         uint64_t elf_entry;
         uint64_t elf_lowaddr;
         uint64_t elf_lowaddr;
         int success = load_elf(kernel_filename, NULL, translate_phys_addr, cpu,
         int success = load_elf(kernel_filename, NULL, translate_phys_addr, cpu,
-                &elf_entry, &elf_lowaddr, NULL, be, EM_XTENSA, 0, 0);
+                &elf_entry, &elf_lowaddr, NULL, NULL, be, EM_XTENSA, 0, 0);
         if (success > 0) {
         if (success > 0) {
             entry_point = elf_entry;
             entry_point = elf_entry;
         } else {
         } else {

+ 3 - 0
include/disas/dis-asm.h

@@ -372,6 +372,9 @@ typedef struct disassemble_info {
   /* Command line options specific to the target disassembler.  */
   /* Command line options specific to the target disassembler.  */
   char * disassembler_options;
   char * disassembler_options;
 
 
+  /* Field intended to be used by targets in any way they deem suitable.  */
+  int64_t target_info;
+
   /* Options for Capstone disassembly.  */
   /* Options for Capstone disassembly.  */
   int cap_arch;
   int cap_arch;
   int cap_mode;
   int cap_mode;

+ 5 - 1
include/hw/elf_ops.h

@@ -316,7 +316,8 @@ static int glue(load_elf, SZ)(const char *name, int fd,
                               void *translate_opaque,
                               void *translate_opaque,
                               int must_swab, uint64_t *pentry,
                               int must_swab, uint64_t *pentry,
                               uint64_t *lowaddr, uint64_t *highaddr,
                               uint64_t *lowaddr, uint64_t *highaddr,
-                              int elf_machine, int clear_lsb, int data_swab,
+                              uint32_t *pflags, int elf_machine,
+                              int clear_lsb, int data_swab,
                               AddressSpace *as, bool load_rom,
                               AddressSpace *as, bool load_rom,
                               symbol_fn_t sym_cb)
                               symbol_fn_t sym_cb)
 {
 {
@@ -389,6 +390,9 @@ static int glue(load_elf, SZ)(const char *name, int fd,
             }
             }
     }
     }
 
 
+    if (pflags) {
+        *pflags = (elf_word)ehdr.e_flags;
+    }
     if (pentry)
     if (pentry)
         *pentry = (uint64_t)(elf_sword)ehdr.e_entry;
         *pentry = (uint64_t)(elf_sword)ehdr.e_entry;
 
 

+ 12 - 9
include/hw/loader.h

@@ -101,6 +101,7 @@ const char *load_elf_strerror(int error);
  * @pentry: Populated with program entry point. Ignored if NULL.
  * @pentry: Populated with program entry point. Ignored if NULL.
  * @lowaddr: Populated with lowest loaded address. Ignored if NULL.
  * @lowaddr: Populated with lowest loaded address. Ignored if NULL.
  * @highaddr: Populated with highest loaded address. Ignored if NULL.
  * @highaddr: Populated with highest loaded address. Ignored if NULL.
+ * @pflags: Populated with ELF processor-specific flags. Ignore if NULL.
  * @bigendian: Expected ELF endianness. 0 for LE otherwise BE
  * @bigendian: Expected ELF endianness. 0 for LE otherwise BE
  * @elf_machine: Expected ELF machine type
  * @elf_machine: Expected ELF machine type
  * @clear_lsb: Set to mask off LSB of addresses (Some architectures use
  * @clear_lsb: Set to mask off LSB of addresses (Some architectures use
@@ -131,8 +132,9 @@ int load_elf_ram_sym(const char *filename,
                      uint64_t (*elf_note_fn)(void *, void *, bool),
                      uint64_t (*elf_note_fn)(void *, void *, bool),
                      uint64_t (*translate_fn)(void *, uint64_t),
                      uint64_t (*translate_fn)(void *, uint64_t),
                      void *translate_opaque, uint64_t *pentry,
                      void *translate_opaque, uint64_t *pentry,
-                     uint64_t *lowaddr, uint64_t *highaddr, int big_endian,
-                     int elf_machine, int clear_lsb, int data_swab,
+                     uint64_t *lowaddr, uint64_t *highaddr, uint32_t *pflags,
+                     int big_endian, int elf_machine,
+                     int clear_lsb, int data_swab,
                      AddressSpace *as, bool load_rom, symbol_fn_t sym_cb);
                      AddressSpace *as, bool load_rom, symbol_fn_t sym_cb);
 
 
 /** load_elf_ram:
 /** load_elf_ram:
@@ -143,9 +145,9 @@ int load_elf_ram(const char *filename,
                  uint64_t (*elf_note_fn)(void *, void *, bool),
                  uint64_t (*elf_note_fn)(void *, void *, bool),
                  uint64_t (*translate_fn)(void *, uint64_t),
                  uint64_t (*translate_fn)(void *, uint64_t),
                  void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
                  void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
-                 uint64_t *highaddr, int big_endian, int elf_machine,
-                 int clear_lsb, int data_swab, AddressSpace *as,
-                 bool load_rom);
+                 uint64_t *highaddr, uint32_t *pflags, int big_endian,
+                 int elf_machine, int clear_lsb, int data_swab,
+                 AddressSpace *as, bool load_rom);
 
 
 /** load_elf_as:
 /** load_elf_as:
  * Same as load_elf_ram(), but always loads the elf as ROM
  * Same as load_elf_ram(), but always loads the elf as ROM
@@ -154,8 +156,9 @@ int load_elf_as(const char *filename,
                 uint64_t (*elf_note_fn)(void *, void *, bool),
                 uint64_t (*elf_note_fn)(void *, void *, bool),
                 uint64_t (*translate_fn)(void *, uint64_t),
                 uint64_t (*translate_fn)(void *, uint64_t),
                 void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
                 void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
-                uint64_t *highaddr, int big_endian, int elf_machine,
-                int clear_lsb, int data_swab, AddressSpace *as);
+                uint64_t *highaddr, uint32_t *pflags, int big_endian,
+                int elf_machine, int clear_lsb, int data_swab,
+                AddressSpace *as);
 
 
 /** load_elf:
 /** load_elf:
  * Same as load_elf_as(), but doesn't allow the caller to specify an
  * Same as load_elf_as(), but doesn't allow the caller to specify an
@@ -165,8 +168,8 @@ int load_elf(const char *filename,
              uint64_t (*elf_note_fn)(void *, void *, bool),
              uint64_t (*elf_note_fn)(void *, void *, bool),
              uint64_t (*translate_fn)(void *, uint64_t),
              uint64_t (*translate_fn)(void *, uint64_t),
              void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
              void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
-             uint64_t *highaddr, int big_endian, int elf_machine,
-             int clear_lsb, int data_swab);
+             uint64_t *highaddr, uint32_t *pflags, int big_endian,
+             int elf_machine, int clear_lsb, int data_swab);
 
 
 /** load_elf_hdr:
 /** load_elf_hdr:
  * @filename: Path of ELF file
  * @filename: Path of ELF file

+ 1 - 1
qemu-deprecated.texi

@@ -260,7 +260,7 @@ The 'scsi-disk' device is deprecated. Users should use 'scsi-hd' or
 
 
 @section System emulator machines
 @section System emulator machines
 
 
-@subsection mips r4k platform (since 4.2)
+@subsection mips r4k platform (since 5.0)
 
 
 This machine type is very old and unmaintained. Users should use the 'malta'
 This machine type is very old and unmaintained. Users should use the 'malta'
 machine type instead.
 machine type instead.

+ 2 - 2
target/mips/cpu.h

@@ -309,7 +309,7 @@ typedef struct mips_def_t mips_def_t;
 #define CP0_REG04__USERLOCAL       2
 #define CP0_REG04__USERLOCAL       2
 #define CP0_REG04__XCONTEXTCONFIG  3
 #define CP0_REG04__XCONTEXTCONFIG  3
 #define CP0_REG04__DBGCONTEXTID    4
 #define CP0_REG04__DBGCONTEXTID    4
-#define CP0_REG00__MMID            5
+#define CP0_REG04__MMID            5
 /* CP0 Register 05 */
 /* CP0 Register 05 */
 #define CP0_REG05__PAGEMASK        0
 #define CP0_REG05__PAGEMASK        0
 #define CP0_REG05__PAGEGRAIN       1
 #define CP0_REG05__PAGEGRAIN       1
@@ -961,7 +961,7 @@ struct CPUMIPSState {
 /*
 /*
  * CP0 Register 19
  * CP0 Register 19
  */
  */
-    int32_t CP0_WatchHi[8];
+    uint64_t CP0_WatchHi[8];
 #define CP0WH_ASID 16
 #define CP0WH_ASID 16
 /*
 /*
  * CP0 Register 20
  * CP0 Register 20

+ 16 - 4
target/mips/helper.c

@@ -72,8 +72,13 @@ int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
                     target_ulong address, int rw, int access_type)
                     target_ulong address, int rw, int access_type)
 {
 {
     uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
     uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
+    uint32_t MMID = env->CP0_MemoryMapID;
+    bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
+    uint32_t tlb_mmid;
     int i;
     int i;
 
 
+    MMID = mi ? MMID : (uint32_t) ASID;
+
     for (i = 0; i < env->tlb->tlb_in_use; i++) {
     for (i = 0; i < env->tlb->tlb_in_use; i++) {
         r4k_tlb_t *tlb = &env->tlb->mmu.r4k.tlb[i];
         r4k_tlb_t *tlb = &env->tlb->mmu.r4k.tlb[i];
         /* 1k pages are not supported. */
         /* 1k pages are not supported. */
@@ -84,8 +89,9 @@ int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
         tag &= env->SEGMask;
         tag &= env->SEGMask;
 #endif
 #endif
 
 
-        /* Check ASID, virtual page number & size */
-        if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag && !tlb->EHINV) {
+        /* Check ASID/MMID, virtual page number & size */
+        tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
+        if ((tlb->G == 1 || tlb_mmid == MMID) && VPN == tag && !tlb->EHINV) {
             /* TLB match */
             /* TLB match */
             int n = !!(address & mask & ~(mask >> 1));
             int n = !!(address & mask & ~(mask >> 1));
             /* Check access rights */
             /* Check access rights */
@@ -1418,14 +1424,20 @@ void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra)
     target_ulong addr;
     target_ulong addr;
     target_ulong end;
     target_ulong end;
     uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
     uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
+    uint32_t MMID = env->CP0_MemoryMapID;
+    bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
+    uint32_t tlb_mmid;
     target_ulong mask;
     target_ulong mask;
 
 
+    MMID = mi ? MMID : (uint32_t) ASID;
+
     tlb = &env->tlb->mmu.r4k.tlb[idx];
     tlb = &env->tlb->mmu.r4k.tlb[idx];
     /*
     /*
-     * The qemu TLB is flushed when the ASID changes, so no need to
+     * The qemu TLB is flushed when the ASID/MMID changes, so no need to
      * flush these entries again.
      * flush these entries again.
      */
      */
-    if (tlb->G == 0 && tlb->ASID != ASID) {
+    tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
+    if (tlb->G == 0 && tlb_mmid != MMID) {
         return;
         return;
     }
     }
 
 

+ 5 - 0
target/mips/helper.h

@@ -78,6 +78,7 @@ DEF_HELPER_1(mfc0_maar, tl, env)
 DEF_HELPER_1(mfhc0_maar, tl, env)
 DEF_HELPER_1(mfhc0_maar, tl, env)
 DEF_HELPER_2(mfc0_watchlo, tl, env, i32)
 DEF_HELPER_2(mfc0_watchlo, tl, env, i32)
 DEF_HELPER_2(mfc0_watchhi, tl, env, i32)
 DEF_HELPER_2(mfc0_watchhi, tl, env, i32)
+DEF_HELPER_2(mfhc0_watchhi, tl, env, i32)
 DEF_HELPER_1(mfc0_debug, tl, env)
 DEF_HELPER_1(mfc0_debug, tl, env)
 DEF_HELPER_1(mftc0_debug, tl, env)
 DEF_HELPER_1(mftc0_debug, tl, env)
 #ifdef TARGET_MIPS64
 #ifdef TARGET_MIPS64
@@ -89,6 +90,7 @@ DEF_HELPER_1(dmfc0_tcschefback, tl, env)
 DEF_HELPER_1(dmfc0_lladdr, tl, env)
 DEF_HELPER_1(dmfc0_lladdr, tl, env)
 DEF_HELPER_1(dmfc0_maar, tl, env)
 DEF_HELPER_1(dmfc0_maar, tl, env)
 DEF_HELPER_2(dmfc0_watchlo, tl, env, i32)
 DEF_HELPER_2(dmfc0_watchlo, tl, env, i32)
+DEF_HELPER_2(dmfc0_watchhi, tl, env, i32)
 DEF_HELPER_1(dmfc0_saar, tl, env)
 DEF_HELPER_1(dmfc0_saar, tl, env)
 #endif /* TARGET_MIPS64 */
 #endif /* TARGET_MIPS64 */
 
 
@@ -118,6 +120,7 @@ DEF_HELPER_2(mtc0_tcschefback, void, env, tl)
 DEF_HELPER_2(mttc0_tcschefback, void, env, tl)
 DEF_HELPER_2(mttc0_tcschefback, void, env, tl)
 DEF_HELPER_2(mtc0_entrylo1, void, env, tl)
 DEF_HELPER_2(mtc0_entrylo1, void, env, tl)
 DEF_HELPER_2(mtc0_context, void, env, tl)
 DEF_HELPER_2(mtc0_context, void, env, tl)
+DEF_HELPER_2(mtc0_memorymapid, void, env, tl)
 DEF_HELPER_2(mtc0_pagemask, void, env, tl)
 DEF_HELPER_2(mtc0_pagemask, void, env, tl)
 DEF_HELPER_2(mtc0_pagegrain, void, env, tl)
 DEF_HELPER_2(mtc0_pagegrain, void, env, tl)
 DEF_HELPER_2(mtc0_segctl0, void, env, tl)
 DEF_HELPER_2(mtc0_segctl0, void, env, tl)
@@ -159,6 +162,7 @@ DEF_HELPER_2(mthc0_maar, void, env, tl)
 DEF_HELPER_2(mtc0_maari, void, env, tl)
 DEF_HELPER_2(mtc0_maari, void, env, tl)
 DEF_HELPER_3(mtc0_watchlo, void, env, tl, i32)
 DEF_HELPER_3(mtc0_watchlo, void, env, tl, i32)
 DEF_HELPER_3(mtc0_watchhi, void, env, tl, i32)
 DEF_HELPER_3(mtc0_watchhi, void, env, tl, i32)
+DEF_HELPER_3(mthc0_watchhi, void, env, tl, i32)
 DEF_HELPER_2(mtc0_xcontext, void, env, tl)
 DEF_HELPER_2(mtc0_xcontext, void, env, tl)
 DEF_HELPER_2(mtc0_framemask, void, env, tl)
 DEF_HELPER_2(mtc0_framemask, void, env, tl)
 DEF_HELPER_2(mtc0_debug, void, env, tl)
 DEF_HELPER_2(mtc0_debug, void, env, tl)
@@ -373,6 +377,7 @@ DEF_HELPER_1(ei, tl, env)
 DEF_HELPER_1(eret, void, env)
 DEF_HELPER_1(eret, void, env)
 DEF_HELPER_1(eretnc, void, env)
 DEF_HELPER_1(eretnc, void, env)
 DEF_HELPER_1(deret, void, env)
 DEF_HELPER_1(deret, void, env)
+DEF_HELPER_3(ginvt, void, env, tl, i32)
 #endif /* !CONFIG_USER_ONLY */
 #endif /* !CONFIG_USER_ONLY */
 DEF_HELPER_1(rdhwr_cpunum, tl, env)
 DEF_HELPER_1(rdhwr_cpunum, tl, env)
 DEF_HELPER_1(rdhwr_synci_step, tl, env)
 DEF_HELPER_1(rdhwr_synci_step, tl, env)

+ 1 - 0
target/mips/internal.h

@@ -95,6 +95,7 @@ struct r4k_tlb_t {
     target_ulong VPN;
     target_ulong VPN;
     uint32_t PageMask;
     uint32_t PageMask;
     uint16_t ASID;
     uint16_t ASID;
+    uint32_t MMID;
     unsigned int G:1;
     unsigned int G:1;
     unsigned int C0:3;
     unsigned int C0:3;
     unsigned int C1:3;
     unsigned int C1:3;

+ 3 - 3
target/mips/machine.c

@@ -212,8 +212,8 @@ const VMStateDescription vmstate_tlb = {
 
 
 const VMStateDescription vmstate_mips_cpu = {
 const VMStateDescription vmstate_mips_cpu = {
     .name = "cpu",
     .name = "cpu",
-    .version_id = 18,
-    .minimum_version_id = 18,
+    .version_id = 19,
+    .minimum_version_id = 19,
     .post_load = cpu_post_load,
     .post_load = cpu_post_load,
     .fields = (VMStateField[]) {
     .fields = (VMStateField[]) {
         /* Active TC */
         /* Active TC */
@@ -296,7 +296,7 @@ const VMStateDescription vmstate_mips_cpu = {
         VMSTATE_INT32(env.CP0_MAARI, MIPSCPU),
         VMSTATE_INT32(env.CP0_MAARI, MIPSCPU),
         VMSTATE_UINTTL(env.lladdr, MIPSCPU),
         VMSTATE_UINTTL(env.lladdr, MIPSCPU),
         VMSTATE_UINTTL_ARRAY(env.CP0_WatchLo, MIPSCPU, 8),
         VMSTATE_UINTTL_ARRAY(env.CP0_WatchLo, MIPSCPU, 8),
-        VMSTATE_INT32_ARRAY(env.CP0_WatchHi, MIPSCPU, 8),
+        VMSTATE_UINT64_ARRAY(env.CP0_WatchHi, MIPSCPU, 8),
         VMSTATE_UINTTL(env.CP0_XContext, MIPSCPU),
         VMSTATE_UINTTL(env.CP0_XContext, MIPSCPU),
         VMSTATE_INT32(env.CP0_Framemask, MIPSCPU),
         VMSTATE_INT32(env.CP0_Framemask, MIPSCPU),
         VMSTATE_INT32(env.CP0_Debug, MIPSCPU),
         VMSTATE_INT32(env.CP0_Debug, MIPSCPU),

+ 7 - 8
target/mips/mips-semi.c

@@ -218,7 +218,7 @@ static int copy_argn_to_target(CPUMIPSState *env, int arg_num,
         if (!p) {                               \
         if (!p) {                               \
             gpr[2] = -1;                        \
             gpr[2] = -1;                        \
             gpr[3] = EFAULT;                    \
             gpr[3] = EFAULT;                    \
-            goto uhi_done;                      \
+            return;                             \
         }                                       \
         }                                       \
     } while (0)
     } while (0)
 
 
@@ -228,14 +228,14 @@ static int copy_argn_to_target(CPUMIPSState *env, int arg_num,
         if (!p) {                                       \
         if (!p) {                                       \
             gpr[2] = -1;                                \
             gpr[2] = -1;                                \
             gpr[3] = EFAULT;                            \
             gpr[3] = EFAULT;                            \
-            goto uhi_done;                              \
+            return;                                     \
         }                                               \
         }                                               \
         p2 = lock_user_string(addr2);                   \
         p2 = lock_user_string(addr2);                   \
         if (!p2) {                                      \
         if (!p2) {                                      \
             unlock_user(p, addr, 0);                    \
             unlock_user(p, addr, 0);                    \
             gpr[2] = -1;                                \
             gpr[2] = -1;                                \
             gpr[3] = EFAULT;                            \
             gpr[3] = EFAULT;                            \
-            goto uhi_done;                              \
+            return;                                     \
         }                                               \
         }                                               \
     } while (0)
     } while (0)
 
 
@@ -272,7 +272,7 @@ void helper_do_semihosting(CPUMIPSState *env)
         if (gpr[4] < 3) {
         if (gpr[4] < 3) {
             /* ignore closing stdin/stdout/stderr */
             /* ignore closing stdin/stdout/stderr */
             gpr[2] = 0;
             gpr[2] = 0;
-            goto uhi_done;
+            return;
         }
         }
         gpr[2] = close(gpr[4]);
         gpr[2] = close(gpr[4]);
         gpr[3] = errno_mips(errno);
         gpr[3] = errno_mips(errno);
@@ -302,7 +302,7 @@ void helper_do_semihosting(CPUMIPSState *env)
             gpr[2] = fstat(gpr[4], &sbuf);
             gpr[2] = fstat(gpr[4], &sbuf);
             gpr[3] = errno_mips(errno);
             gpr[3] = errno_mips(errno);
             if (gpr[2]) {
             if (gpr[2]) {
-                goto uhi_done;
+                return;
             }
             }
             gpr[2] = copy_stat_to_target(env, &sbuf, gpr[5]);
             gpr[2] = copy_stat_to_target(env, &sbuf, gpr[5]);
             gpr[3] = errno_mips(errno);
             gpr[3] = errno_mips(errno);
@@ -314,14 +314,14 @@ void helper_do_semihosting(CPUMIPSState *env)
     case UHI_argnlen:
     case UHI_argnlen:
         if (gpr[4] >= semihosting_get_argc()) {
         if (gpr[4] >= semihosting_get_argc()) {
             gpr[2] = -1;
             gpr[2] = -1;
-            goto uhi_done;
+            return;
         }
         }
         gpr[2] = strlen(semihosting_get_arg(gpr[4]));
         gpr[2] = strlen(semihosting_get_arg(gpr[4]));
         break;
         break;
     case UHI_argn:
     case UHI_argn:
         if (gpr[4] >= semihosting_get_argc()) {
         if (gpr[4] >= semihosting_get_argc()) {
             gpr[2] = -1;
             gpr[2] = -1;
-            goto uhi_done;
+            return;
         }
         }
         gpr[2] = copy_argn_to_target(env, gpr[4], gpr[5]);
         gpr[2] = copy_argn_to_target(env, gpr[4], gpr[5]);
         break;
         break;
@@ -369,6 +369,5 @@ void helper_do_semihosting(CPUMIPSState *env)
         fprintf(stderr, "Unknown UHI operation %d\n", op);
         fprintf(stderr, "Unknown UHI operation %d\n", op);
         abort();
         abort();
     }
     }
-uhi_done:
     return;
     return;
 }
 }

+ 131 - 21
target/mips/op_helper.c

@@ -945,7 +945,12 @@ target_ulong helper_mfc0_watchlo(CPUMIPSState *env, uint32_t sel)
 
 
 target_ulong helper_mfc0_watchhi(CPUMIPSState *env, uint32_t sel)
 target_ulong helper_mfc0_watchhi(CPUMIPSState *env, uint32_t sel)
 {
 {
-    return env->CP0_WatchHi[sel];
+    return (int32_t) env->CP0_WatchHi[sel];
+}
+
+target_ulong helper_mfhc0_watchhi(CPUMIPSState *env, uint32_t sel)
+{
+    return env->CP0_WatchHi[sel] >> 32;
 }
 }
 
 
 target_ulong helper_mfc0_debug(CPUMIPSState *env)
 target_ulong helper_mfc0_debug(CPUMIPSState *env)
@@ -1016,6 +1021,11 @@ target_ulong helper_dmfc0_watchlo(CPUMIPSState *env, uint32_t sel)
     return env->CP0_WatchLo[sel];
     return env->CP0_WatchLo[sel];
 }
 }
 
 
+target_ulong helper_dmfc0_watchhi(CPUMIPSState *env, uint32_t sel)
+{
+    return env->CP0_WatchHi[sel];
+}
+
 target_ulong helper_dmfc0_saar(CPUMIPSState *env)
 target_ulong helper_dmfc0_saar(CPUMIPSState *env)
 {
 {
     if ((env->CP0_SAARI & 0x3f) < 2) {
     if ((env->CP0_SAARI & 0x3f) < 2) {
@@ -1379,6 +1389,17 @@ void helper_mtc0_context(CPUMIPSState *env, target_ulong arg1)
     env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (arg1 & ~0x007FFFFF);
     env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (arg1 & ~0x007FFFFF);
 }
 }
 
 
+void helper_mtc0_memorymapid(CPUMIPSState *env, target_ulong arg1)
+{
+    int32_t old;
+    old = env->CP0_MemoryMapID;
+    env->CP0_MemoryMapID = (int32_t) arg1;
+    /* If the MemoryMapID changes, flush qemu's TLB.  */
+    if (old != env->CP0_MemoryMapID) {
+        cpu_mips_tlb_flush(env);
+    }
+}
+
 void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask)
 void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask)
 {
 {
     uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1);
     uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1);
@@ -1815,6 +1836,8 @@ void helper_mtc0_config5(CPUMIPSState *env, target_ulong arg1)
 {
 {
     env->CP0_Config5 = (env->CP0_Config5 & (~env->CP0_Config5_rw_bitmask)) |
     env->CP0_Config5 = (env->CP0_Config5 & (~env->CP0_Config5_rw_bitmask)) |
                        (arg1 & env->CP0_Config5_rw_bitmask);
                        (arg1 & env->CP0_Config5_rw_bitmask);
+    env->CP0_EntryHi_ASID_mask = (env->CP0_Config5 & (1 << CP0C5_MI)) ?
+            0x0 : (env->CP0_Config4 & (1 << CP0C4_AE)) ? 0x3ff : 0xff;
     compute_hflags(env);
     compute_hflags(env);
 }
 }
 
 
@@ -1869,11 +1892,20 @@ void helper_mtc0_watchlo(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
 
 
 void helper_mtc0_watchhi(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
 void helper_mtc0_watchhi(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
 {
 {
-    int mask = 0x40000FF8 | (env->CP0_EntryHi_ASID_mask << CP0WH_ASID);
+    uint64_t mask = 0x40000FF8 | (env->CP0_EntryHi_ASID_mask << CP0WH_ASID);
+    if ((env->CP0_Config5 >> CP0C5_MI) & 1) {
+        mask |= 0xFFFFFFFF00000000ULL; /* MMID */
+    }
     env->CP0_WatchHi[sel] = arg1 & mask;
     env->CP0_WatchHi[sel] = arg1 & mask;
     env->CP0_WatchHi[sel] &= ~(env->CP0_WatchHi[sel] & arg1 & 0x7);
     env->CP0_WatchHi[sel] &= ~(env->CP0_WatchHi[sel] & arg1 & 0x7);
 }
 }
 
 
+void helper_mthc0_watchhi(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
+{
+    env->CP0_WatchHi[sel] = ((uint64_t) (arg1) << 32) |
+                            (env->CP0_WatchHi[sel] & 0x00000000ffffffffULL);
+}
+
 void helper_mtc0_xcontext(CPUMIPSState *env, target_ulong arg1)
 void helper_mtc0_xcontext(CPUMIPSState *env, target_ulong arg1)
 {
 {
     target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
     target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
@@ -2249,6 +2281,7 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx)
     tlb->VPN &= env->SEGMask;
     tlb->VPN &= env->SEGMask;
 #endif
 #endif
     tlb->ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
     tlb->ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
+    tlb->MMID = env->CP0_MemoryMapID;
     tlb->PageMask = env->CP0_PageMask;
     tlb->PageMask = env->CP0_PageMask;
     tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
     tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
     tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
     tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
@@ -2267,13 +2300,18 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx)
 
 
 void r4k_helper_tlbinv(CPUMIPSState *env)
 void r4k_helper_tlbinv(CPUMIPSState *env)
 {
 {
-    int idx;
-    r4k_tlb_t *tlb;
+    bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
     uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
     uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
+    uint32_t MMID = env->CP0_MemoryMapID;
+    uint32_t tlb_mmid;
+    r4k_tlb_t *tlb;
+    int idx;
 
 
+    MMID = mi ? MMID : (uint32_t) ASID;
     for (idx = 0; idx < env->tlb->nb_tlb; idx++) {
     for (idx = 0; idx < env->tlb->nb_tlb; idx++) {
         tlb = &env->tlb->mmu.r4k.tlb[idx];
         tlb = &env->tlb->mmu.r4k.tlb[idx];
-        if (!tlb->G && tlb->ASID == ASID) {
+        tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
+        if (!tlb->G && tlb_mmid == MMID) {
             tlb->EHINV = 1;
             tlb->EHINV = 1;
         }
         }
     }
     }
@@ -2292,11 +2330,16 @@ void r4k_helper_tlbinvf(CPUMIPSState *env)
 
 
 void r4k_helper_tlbwi(CPUMIPSState *env)
 void r4k_helper_tlbwi(CPUMIPSState *env)
 {
 {
-    r4k_tlb_t *tlb;
-    int idx;
+    bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
     target_ulong VPN;
     target_ulong VPN;
-    uint16_t ASID;
+    uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
+    uint32_t MMID = env->CP0_MemoryMapID;
+    uint32_t tlb_mmid;
     bool EHINV, G, V0, D0, V1, D1, XI0, XI1, RI0, RI1;
     bool EHINV, G, V0, D0, V1, D1, XI0, XI1, RI0, RI1;
+    r4k_tlb_t *tlb;
+    int idx;
+
+    MMID = mi ? MMID : (uint32_t) ASID;
 
 
     idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
     idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
     tlb = &env->tlb->mmu.r4k.tlb[idx];
     tlb = &env->tlb->mmu.r4k.tlb[idx];
@@ -2304,7 +2347,6 @@ void r4k_helper_tlbwi(CPUMIPSState *env)
 #if defined(TARGET_MIPS64)
 #if defined(TARGET_MIPS64)
     VPN &= env->SEGMask;
     VPN &= env->SEGMask;
 #endif
 #endif
-    ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
     EHINV = (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) != 0;
     EHINV = (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) != 0;
     G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
     G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
     V0 = (env->CP0_EntryLo0 & 2) != 0;
     V0 = (env->CP0_EntryLo0 & 2) != 0;
@@ -2316,11 +2358,12 @@ void r4k_helper_tlbwi(CPUMIPSState *env)
     XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) &1;
     XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) &1;
     RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) &1;
     RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) &1;
 
 
+    tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
     /*
     /*
      * Discard cached TLB entries, unless tlbwi is just upgrading access
      * Discard cached TLB entries, unless tlbwi is just upgrading access
      * permissions on the current entry.
      * permissions on the current entry.
      */
      */
-    if (tlb->VPN != VPN || tlb->ASID != ASID || tlb->G != G ||
+    if (tlb->VPN != VPN || tlb_mmid != MMID || tlb->G != G ||
         (!tlb->EHINV && EHINV) ||
         (!tlb->EHINV && EHINV) ||
         (tlb->V0 && !V0) || (tlb->D0 && !D0) ||
         (tlb->V0 && !V0) || (tlb->D0 && !D0) ||
         (!tlb->XI0 && XI0) || (!tlb->RI0 && RI0) ||
         (!tlb->XI0 && XI0) || (!tlb->RI0 && RI0) ||
@@ -2343,14 +2386,17 @@ void r4k_helper_tlbwr(CPUMIPSState *env)
 
 
 void r4k_helper_tlbp(CPUMIPSState *env)
 void r4k_helper_tlbp(CPUMIPSState *env)
 {
 {
+    bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
     r4k_tlb_t *tlb;
     r4k_tlb_t *tlb;
     target_ulong mask;
     target_ulong mask;
     target_ulong tag;
     target_ulong tag;
     target_ulong VPN;
     target_ulong VPN;
-    uint16_t ASID;
+    uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
+    uint32_t MMID = env->CP0_MemoryMapID;
+    uint32_t tlb_mmid;
     int i;
     int i;
 
 
-    ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
+    MMID = mi ? MMID : (uint32_t) ASID;
     for (i = 0; i < env->tlb->nb_tlb; i++) {
     for (i = 0; i < env->tlb->nb_tlb; i++) {
         tlb = &env->tlb->mmu.r4k.tlb[i];
         tlb = &env->tlb->mmu.r4k.tlb[i];
         /* 1k pages are not supported. */
         /* 1k pages are not supported. */
@@ -2360,8 +2406,9 @@ void r4k_helper_tlbp(CPUMIPSState *env)
 #if defined(TARGET_MIPS64)
 #if defined(TARGET_MIPS64)
         tag &= env->SEGMask;
         tag &= env->SEGMask;
 #endif
 #endif
-        /* Check ASID, virtual page number & size */
-        if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag && !tlb->EHINV) {
+        tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
+        /* Check ASID/MMID, virtual page number & size */
+        if ((tlb->G == 1 || tlb_mmid == MMID) && VPN == tag && !tlb->EHINV) {
             /* TLB match */
             /* TLB match */
             env->CP0_Index = i;
             env->CP0_Index = i;
             break;
             break;
@@ -2378,8 +2425,9 @@ void r4k_helper_tlbp(CPUMIPSState *env)
 #if defined(TARGET_MIPS64)
 #if defined(TARGET_MIPS64)
             tag &= env->SEGMask;
             tag &= env->SEGMask;
 #endif
 #endif
-            /* Check ASID, virtual page number & size */
-            if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
+            tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
+            /* Check ASID/MMID, virtual page number & size */
+            if ((tlb->G == 1 || tlb_mmid == MMID) && VPN == tag) {
                 r4k_mips_tlb_flush_extra(env, i);
                 r4k_mips_tlb_flush_extra(env, i);
                 break;
                 break;
             }
             }
@@ -2401,16 +2449,20 @@ static inline uint64_t get_entrylo_pfn_from_tlb(uint64_t tlb_pfn)
 
 
 void r4k_helper_tlbr(CPUMIPSState *env)
 void r4k_helper_tlbr(CPUMIPSState *env)
 {
 {
+    bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
+    uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
+    uint32_t MMID = env->CP0_MemoryMapID;
+    uint32_t tlb_mmid;
     r4k_tlb_t *tlb;
     r4k_tlb_t *tlb;
-    uint16_t ASID;
     int idx;
     int idx;
 
 
-    ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
+    MMID = mi ? MMID : (uint32_t) ASID;
     idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
     idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
     tlb = &env->tlb->mmu.r4k.tlb[idx];
     tlb = &env->tlb->mmu.r4k.tlb[idx];
 
 
-    /* If this will change the current ASID, flush qemu's TLB.  */
-    if (ASID != tlb->ASID) {
+    tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
+    /* If this will change the current ASID/MMID, flush qemu's TLB.  */
+    if (MMID != tlb_mmid) {
         cpu_mips_tlb_flush(env);
         cpu_mips_tlb_flush(env);
     }
     }
 
 
@@ -2422,7 +2474,8 @@ void r4k_helper_tlbr(CPUMIPSState *env)
         env->CP0_EntryLo0 = 0;
         env->CP0_EntryLo0 = 0;
         env->CP0_EntryLo1 = 0;
         env->CP0_EntryLo1 = 0;
     } else {
     } else {
-        env->CP0_EntryHi = tlb->VPN | tlb->ASID;
+        env->CP0_EntryHi = mi ? tlb->VPN : tlb->VPN | tlb->ASID;
+        env->CP0_MemoryMapID = tlb->MMID;
         env->CP0_PageMask = tlb->PageMask;
         env->CP0_PageMask = tlb->PageMask;
         env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
         env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
                         ((uint64_t)tlb->RI0 << CP0EnLo_RI) |
                         ((uint64_t)tlb->RI0 << CP0EnLo_RI) |
@@ -2465,6 +2518,63 @@ void helper_tlbinvf(CPUMIPSState *env)
     env->tlb->helper_tlbinvf(env);
     env->tlb->helper_tlbinvf(env);
 }
 }
 
 
+static void global_invalidate_tlb(CPUMIPSState *env,
+                           uint32_t invMsgVPN2,
+                           uint8_t invMsgR,
+                           uint32_t invMsgMMid,
+                           bool invAll,
+                           bool invVAMMid,
+                           bool invMMid,
+                           bool invVA)
+{
+
+    int idx;
+    r4k_tlb_t *tlb;
+    bool VAMatch;
+    bool MMidMatch;
+
+    for (idx = 0; idx < env->tlb->nb_tlb; idx++) {
+        tlb = &env->tlb->mmu.r4k.tlb[idx];
+        VAMatch =
+            (((tlb->VPN & ~tlb->PageMask) == (invMsgVPN2 & ~tlb->PageMask))
+#ifdef TARGET_MIPS64
+            &&
+            (extract64(env->CP0_EntryHi, 62, 2) == invMsgR)
+#endif
+            );
+        MMidMatch = tlb->MMID == invMsgMMid;
+        if ((invAll && (idx > env->CP0_Wired)) ||
+            (VAMatch && invVAMMid && (tlb->G || MMidMatch)) ||
+            (VAMatch && invVA) ||
+            (MMidMatch && !(tlb->G) && invMMid)) {
+            tlb->EHINV = 1;
+        }
+    }
+    cpu_mips_tlb_flush(env);
+}
+
+void helper_ginvt(CPUMIPSState *env, target_ulong arg, uint32_t type)
+{
+    bool invAll = type == 0;
+    bool invVA = type == 1;
+    bool invMMid = type == 2;
+    bool invVAMMid = type == 3;
+    uint32_t invMsgVPN2 = arg & (TARGET_PAGE_MASK << 1);
+    uint8_t invMsgR = 0;
+    uint32_t invMsgMMid = env->CP0_MemoryMapID;
+    CPUState *other_cs = first_cpu;
+
+#ifdef TARGET_MIPS64
+    invMsgR = extract64(arg, 62, 2);
+#endif
+
+    CPU_FOREACH(other_cs) {
+        MIPSCPU *other_cpu = MIPS_CPU(other_cs);
+        global_invalidate_tlb(&other_cpu->env, invMsgVPN2, invMsgR, invMsgMMid,
+                              invAll, invVAMMid, invMMid, invVA);
+    }
+}
+
 /* Specials */
 /* Specials */
 target_ulong helper_di(CPUMIPSState *env)
 target_ulong helper_di(CPUMIPSState *env)
 {
 {

+ 85 - 3
target/mips/translate.c

@@ -388,6 +388,7 @@ enum {
     OPC_BSHFL    = 0x20 | OPC_SPECIAL3,
     OPC_BSHFL    = 0x20 | OPC_SPECIAL3,
     OPC_DBSHFL   = 0x24 | OPC_SPECIAL3,
     OPC_DBSHFL   = 0x24 | OPC_SPECIAL3,
     OPC_RDHWR    = 0x3B | OPC_SPECIAL3,
     OPC_RDHWR    = 0x3B | OPC_SPECIAL3,
+    OPC_GINV     = 0x3D | OPC_SPECIAL3,
 
 
     /* Loongson 2E */
     /* Loongson 2E */
     OPC_MULT_G_2E   = 0x18 | OPC_SPECIAL3,
     OPC_MULT_G_2E   = 0x18 | OPC_SPECIAL3,
@@ -2547,6 +2548,8 @@ typedef struct DisasContext {
     bool nan2008;
     bool nan2008;
     bool abs2008;
     bool abs2008;
     bool saar;
     bool saar;
+    bool mi;
+    int gi;
 } DisasContext;
 } DisasContext;
 
 
 #define DISAS_STOP       DISAS_TARGET_0
 #define DISAS_STOP       DISAS_TARGET_0
@@ -6783,6 +6786,25 @@ static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             goto cp0_unimplemented;
             goto cp0_unimplemented;
         }
         }
         break;
         break;
+    case CP0_REGISTER_19:
+        switch (sel) {
+        case CP0_REG19__WATCHHI0:
+        case CP0_REG19__WATCHHI1:
+        case CP0_REG19__WATCHHI2:
+        case CP0_REG19__WATCHHI3:
+        case CP0_REG19__WATCHHI4:
+        case CP0_REG19__WATCHHI5:
+        case CP0_REG19__WATCHHI6:
+        case CP0_REG19__WATCHHI7:
+            /* upper 32 bits are only available when Config5MI != 0 */
+            CP0_CHECK(ctx->mi);
+            gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
+            register_name = "WatchHi";
+            break;
+        default:
+            goto cp0_unimplemented;
+        }
+        break;
     case CP0_REGISTER_28:
     case CP0_REGISTER_28:
         switch (sel) {
         switch (sel) {
         case 0:
         case 0:
@@ -6869,6 +6891,25 @@ static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             goto cp0_unimplemented;
             goto cp0_unimplemented;
         }
         }
         break;
         break;
+    case CP0_REGISTER_19:
+        switch (sel) {
+        case CP0_REG19__WATCHHI0:
+        case CP0_REG19__WATCHHI1:
+        case CP0_REG19__WATCHHI2:
+        case CP0_REG19__WATCHHI3:
+        case CP0_REG19__WATCHHI4:
+        case CP0_REG19__WATCHHI5:
+        case CP0_REG19__WATCHHI6:
+        case CP0_REG19__WATCHHI7:
+            /* upper 32 bits are only available when Config5MI != 0 */
+            CP0_CHECK(ctx->mi);
+            gen_helper_0e1i(mthc0_watchhi, arg, sel);
+            register_name = "WatchHi";
+            break;
+        default:
+            goto cp0_unimplemented;
+        }
+        break;
     case CP0_REGISTER_28:
     case CP0_REGISTER_28:
         switch (sel) {
         switch (sel) {
         case 0:
         case 0:
@@ -7092,6 +7133,11 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             tcg_gen_ext32s_tl(arg, arg);
             tcg_gen_ext32s_tl(arg, arg);
             register_name = "UserLocal";
             register_name = "UserLocal";
             break;
             break;
+        case CP0_REG04__MMID:
+            CP0_CHECK(ctx->mi);
+            gen_helper_mtc0_memorymapid(cpu_env, arg);
+            register_name = "MMID";
+            break;
         default:
         default:
             goto cp0_unimplemented;
             goto cp0_unimplemented;
         }
         }
@@ -7832,6 +7878,11 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
                           offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
                           offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
             register_name = "UserLocal";
             register_name = "UserLocal";
             break;
             break;
+        case CP0_REG04__MMID:
+            CP0_CHECK(ctx->mi);
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
+            register_name = "MMID";
+            break;
         default:
         default:
             goto cp0_unimplemented;
             goto cp0_unimplemented;
         }
         }
@@ -8590,6 +8641,11 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
                           offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
                           offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
             register_name = "UserLocal";
             register_name = "UserLocal";
             break;
             break;
+        case CP0_REG04__MMID:
+            CP0_CHECK(ctx->mi);
+            gen_helper_mtc0_memorymapid(cpu_env, arg);
+            register_name = "MMID";
+            break;
         default:
         default:
             goto cp0_unimplemented;
             goto cp0_unimplemented;
         }
         }
@@ -8922,7 +8978,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
         case CP0_REG19__WATCHHI6:
         case CP0_REG19__WATCHHI6:
         case CP0_REG19__WATCHHI7:
         case CP0_REG19__WATCHHI7:
             CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
             CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
-            gen_helper_1e0i(mfc0_watchhi, arg, sel);
+            gen_helper_1e0i(dmfc0_watchhi, arg, sel);
             register_name = "WatchHi";
             register_name = "WatchHi";
             break;
             break;
         default:
         default:
@@ -9312,6 +9368,11 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
                           offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
                           offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
             register_name = "UserLocal";
             register_name = "UserLocal";
             break;
             break;
+        case CP0_REG04__MMID:
+            CP0_CHECK(ctx->mi);
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
+            register_name = "MMID";
+            break;
         default:
         default:
             goto cp0_unimplemented;
             goto cp0_unimplemented;
         }
         }
@@ -27170,6 +27231,25 @@ static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
             }
             }
         }
         }
         break;
         break;
+#ifndef CONFIG_USER_ONLY
+    case OPC_GINV:
+        if (unlikely(ctx->gi <= 1)) {
+            generate_exception_end(ctx, EXCP_RI);
+        }
+        check_cp0_enabled(ctx);
+        switch ((ctx->opcode >> 6) & 3) {
+        case 0:    /* GINVI */
+            /* Treat as NOP. */
+            break;
+        case 2:    /* GINVT */
+            gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
+            break;
+        default:
+            generate_exception_end(ctx, EXCP_RI);
+            break;
+        }
+        break;
+#endif
 #if defined(TARGET_MIPS64)
 #if defined(TARGET_MIPS64)
     case R6_OPC_SCD:
     case R6_OPC_SCD:
         gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
         gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
@@ -30727,6 +30807,8 @@ static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
     ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
     ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
     ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
     ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
     ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
+    ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
+    ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
     restore_cpu_state(env, ctx);
     restore_cpu_state(env, ctx);
 #ifdef CONFIG_USER_ONLY
 #ifdef CONFIG_USER_ONLY
         ctx->mem_idx = MIPS_HFLAG_UM;
         ctx->mem_idx = MIPS_HFLAG_UM;
@@ -31187,8 +31269,8 @@ void cpu_state_reset(CPUMIPSState *env)
     if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
     if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
         env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
         env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
     }
     }
-    env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
-                                 0x3ff : 0xff;
+    env->CP0_EntryHi_ASID_mask = (env->CP0_Config5 & (1 << CP0C5_MI)) ?
+            0x0 : (env->CP0_Config4 & (1 << CP0C4_AE)) ? 0x3ff : 0xff;
     env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
     env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
     /*
     /*
      * Vectored interrupts not implemented, timer on int 7,
      * Vectored interrupts not implemented, timer on int 7,