MIPS: Fix XPA base and Virtualization ASE instruction handling
authorMaciej W. Rozycki <macro@imgtec.com>
Fri, 30 Jun 2017 06:21:55 +0000 (07:21 +0100)
committerMaciej W. Rozycki <macro@imgtec.com>
Fri, 30 Jun 2017 06:21:55 +0000 (07:21 +0100)
Correct a commit 7d64c587c15f ("Add support for the MIPS eXtended
Physical Address (XPA) ASE.") bug, causing XPA base and Virtualization
ASE instructions to be wrongly always enabled with the selection of the
MIPS32r2 or higher ISA.

For example this source assembles successfully as shown below:

$ cat xpa.s
mfhc0 $2, $1
$ as -32 -mips32 -o xpa.o xpa.s
xpa.s: Assembler messages:
xpa.s:1: Error: opcode not supported on this processor: mips32 (mips32) `mfhc0 $2,$1'
$ as -32 -mips32r2 -o xpa.o xpa.s
$ objdump -d xpa.o

xpa.o:     file format elf32-tradbigmips

Disassembly of section .text:

00000000 <.text>:
   0: 40420800  mfhc0 v0,c0_random
...
$

To address this issue remove the I33 (INSN_ISA32R2) marking from all XPA
instructions in the opcode table.  Additionally, for XPA Virtualization
ASE instructions implement an XPAVZ (ASE_XPA_VIRT) combination ASE flag
and use it in place of IVIRT|XPA (ASE_VIRT|ASE_XPA).

Now the same source is correctly rejected unless the `-mxpa' option is
also used:

$ as -32 -mips32r2 -o xpa.o xpa.s
xpa.s: Assembler messages:
xpa.s:1: Error: opcode not supported on this processor: mips32r2 (mips32r2) `mfhc0 $2,$1'
$ as -32 -mips32r2 -mxpa -o xpa.o xpa.s
$

Add test cases for XPA base and XPA Virtualization ASE instructions.

Parts of this change by Andrew Bennett.

include/
* opcode/mips.h (ASE_XPA_VIRT): New macro.

opcodes/
* mips-dis.c (mips_calculate_combination_ases): Handle the
ASE_XPA_VIRT flag.
(parse_mips_ase_option): New function.
(parse_mips_dis_option): Factor out ASE option handling to the
new function.  Call `mips_calculate_combination_ases'.
* mips-opc.c (XPAVZ): New macro.
(mips_builtin_opcodes): Correct ISA and ASE flags for "mfhc0",
"mfhgc0", "mthc0" and "mthgc0".

gas/
* config/tc-mips.c (mips_set_ase): Handle the ASE_XPA_VIRT flag.
* testsuite/gas/mips/xpa.d: Remove `xpa' from `-M' in `objdump'
flags.  Add `-mvirt' to `as' flags.
* testsuite/gas/mips/xpa-err.d: New test.
* testsuite/gas/mips/xpa-virt-err.d: New test.
* testsuite/gas/mips/xpa-err.l: New stderr output.
* testsuite/gas/mips/xpa-virt-err.l: New stderr output.
* testsuite/gas/mips/xpa-err.s: New test source.
* testsuite/gas/mips/xpa-virt-err.s: New test source.
* testsuite/gas/mips/mips.exp: Run the new tests.

binutils/
* testsuite/binutils-all/mips/mips-xpa-virt-1.d: New test.
* testsuite/binutils-all/mips/mips-xpa-virt-2.d: New test.
* testsuite/binutils-all/mips/mips-xpa-virt-3.d: New test.
* testsuite/binutils-all/mips/mips-xpa-virt-4.d: New test.
* testsuite/binutils-all/mips/mips-xpa-virt.s: New test source.
* testsuite/binutils-all/mips/mips.exp: Run the new tests.

22 files changed:
binutils/ChangeLog
binutils/testsuite/binutils-all/mips/mips-xpa-virt-1.d [new file with mode: 0644]
binutils/testsuite/binutils-all/mips/mips-xpa-virt-2.d [new file with mode: 0644]
binutils/testsuite/binutils-all/mips/mips-xpa-virt-3.d [new file with mode: 0644]
binutils/testsuite/binutils-all/mips/mips-xpa-virt-4.d [new file with mode: 0644]
binutils/testsuite/binutils-all/mips/mips-xpa-virt.s [new file with mode: 0644]
binutils/testsuite/binutils-all/mips/mips.exp
gas/ChangeLog
gas/config/tc-mips.c
gas/testsuite/gas/mips/mips.exp
gas/testsuite/gas/mips/xpa-err.d [new file with mode: 0644]
gas/testsuite/gas/mips/xpa-err.l [new file with mode: 0644]
gas/testsuite/gas/mips/xpa-err.s [new file with mode: 0644]
gas/testsuite/gas/mips/xpa-virt-err.d [new file with mode: 0644]
gas/testsuite/gas/mips/xpa-virt-err.l [new file with mode: 0644]
gas/testsuite/gas/mips/xpa-virt-err.s [new file with mode: 0644]
gas/testsuite/gas/mips/xpa.d
include/ChangeLog
include/opcode/mips.h
opcodes/ChangeLog
opcodes/mips-dis.c
opcodes/mips-opc.c

index d8577b0af3ff89db20c73be23e078c59cf41d710..797bfd454cce4274e821c2fdcfa65e15b32461f6 100644 (file)
@@ -1,3 +1,12 @@
+2017-06-30  Maciej W. Rozycki  <macro@imgtec.com>
+
+       * testsuite/binutils-all/mips/mips-xpa-virt-1.d: New test.
+       * testsuite/binutils-all/mips/mips-xpa-virt-2.d: New test.
+       * testsuite/binutils-all/mips/mips-xpa-virt-3.d: New test.
+       * testsuite/binutils-all/mips/mips-xpa-virt-4.d: New test.
+       * testsuite/binutils-all/mips/mips-xpa-virt.s: New test source.
+       * testsuite/binutils-all/mips/mips.exp: Run the new tests.
+
 2017-06-29  Anton Kolesov  <Anton.Kolesov@synopsys.com>
 
        * testsuite/binutils-all/arc/double_store.s: New file.
diff --git a/binutils/testsuite/binutils-all/mips/mips-xpa-virt-1.d b/binutils/testsuite/binutils-all/mips/mips-xpa-virt-1.d
new file mode 100644 (file)
index 0000000..1bb38ac
--- /dev/null
@@ -0,0 +1,13 @@
+#PROG: objcopy
+#objdump: -d --prefix-addresses --show-raw-insn -M cp0-names=mips32
+#name: MIPS XPA and Virtualization ASE instruction disassembly 1
+#source: mips-xpa-virt.s
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+[0-9a-f]+ <[^>]*> 40020800     mfc0    v0,c0_random
+[0-9a-f]+ <[^>]*> 40420800     cfc0    v0,c0_random
+[0-9a-f]+ <[^>]*> 40620800     0x40620800
+[0-9a-f]+ <[^>]*> 40620c00     0x40620c00
+       \.\.\.
diff --git a/binutils/testsuite/binutils-all/mips/mips-xpa-virt-2.d b/binutils/testsuite/binutils-all/mips/mips-xpa-virt-2.d
new file mode 100644 (file)
index 0000000..58bd5fa
--- /dev/null
@@ -0,0 +1,13 @@
+#PROG: objcopy
+#objdump: -d --prefix-addresses --show-raw-insn -M xpa,cp0-names=mips32
+#name: MIPS XPA and Virtualization ASE instruction disassembly 2
+#source: mips-xpa-virt.s
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+[0-9a-f]+ <[^>]*> 40020800     mfc0    v0,c0_random
+[0-9a-f]+ <[^>]*> 40420800     mfhc0   v0,c0_random
+[0-9a-f]+ <[^>]*> 40620800     0x40620800
+[0-9a-f]+ <[^>]*> 40620c00     0x40620c00
+       \.\.\.
diff --git a/binutils/testsuite/binutils-all/mips/mips-xpa-virt-3.d b/binutils/testsuite/binutils-all/mips/mips-xpa-virt-3.d
new file mode 100644 (file)
index 0000000..f42f7d7
--- /dev/null
@@ -0,0 +1,13 @@
+#PROG: objcopy
+#objdump: -d --prefix-addresses --show-raw-insn -M virt,cp0-names=mips32
+#name: MIPS XPA and Virtualization ASE instruction disassembly 3
+#source: mips-xpa-virt.s
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+[0-9a-f]+ <[^>]*> 40020800     mfc0    v0,c0_random
+[0-9a-f]+ <[^>]*> 40420800     cfc0    v0,c0_random
+[0-9a-f]+ <[^>]*> 40620800     mfgc0   v0,c0_random
+[0-9a-f]+ <[^>]*> 40620c00     0x40620c00
+       \.\.\.
diff --git a/binutils/testsuite/binutils-all/mips/mips-xpa-virt-4.d b/binutils/testsuite/binutils-all/mips/mips-xpa-virt-4.d
new file mode 100644 (file)
index 0000000..a88c4ef
--- /dev/null
@@ -0,0 +1,13 @@
+#PROG: objcopy
+#objdump: -d --prefix-addresses --show-raw-insn -M xpa,virt,cp0-names=mips32
+#name: MIPS XPA and Virtualization ASE instruction disassembly 4
+#source: mips-xpa-virt.s
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+[0-9a-f]+ <[^>]*> 40020800     mfc0    v0,c0_random
+[0-9a-f]+ <[^>]*> 40420800     mfhc0   v0,c0_random
+[0-9a-f]+ <[^>]*> 40620800     mfgc0   v0,c0_random
+[0-9a-f]+ <[^>]*> 40620c00     mfhgc0  v0,c0_random
+       \.\.\.
diff --git a/binutils/testsuite/binutils-all/mips/mips-xpa-virt.s b/binutils/testsuite/binutils-all/mips/mips-xpa-virt.s
new file mode 100644 (file)
index 0000000..416016a
--- /dev/null
@@ -0,0 +1,14 @@
+       .set    mips64r5
+       .set    xpa
+       .set    virt
+
+       .text
+foo:
+       mfc0    $2, $1
+       mfhc0   $2, $1
+       mfgc0   $2, $1
+       mfhgc0  $2, $1
+
+# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
+        .align  4, 0
+        .space  16
index 28c2197eeb6775376c7ac1e38e87de0545dcc86a..0070929a7f66cdc9dc53ad8b2552ba17b3468402 100644 (file)
@@ -36,6 +36,10 @@ set has_newabi [expr [istarget *-*-irix6*] \
 run_dump_test "mips-ase-1"
 run_dump_test "mips-ase-2"
 run_dump_test "mips-ase-3"
+run_dump_test "mips-xpa-virt-1"
+run_dump_test "mips-xpa-virt-2"
+run_dump_test "mips-xpa-virt-3"
+run_dump_test "mips-xpa-virt-4"
 run_dump_test "mixed-mips16"
 run_dump_test "mixed-micromips"
 run_dump_test "mixed-mips16-micromips"
index d1529099480b48cc4e522860b5beb5765da9e52a..4d8f552847f5d567b810fe7738cdb03154b4a18c 100644 (file)
@@ -1,3 +1,17 @@
+2017-06-30  Maciej W. Rozycki  <macro@imgtec.com>
+           Andrew Bennett  <andrew.bennett@imgtec.com>
+
+       * config/tc-mips.c (mips_set_ase): Handle the ASE_XPA_VIRT flag.
+       * testsuite/gas/mips/xpa.d: Remove `xpa' from `-M' in `objdump'
+       flags.  Add `-mvirt' to `as' flags.
+       * testsuite/gas/mips/xpa-err.d: New test.
+       * testsuite/gas/mips/xpa-virt-err.d: New test.
+       * testsuite/gas/mips/xpa-err.l: New stderr output.
+       * testsuite/gas/mips/xpa-virt-err.l: New stderr output.
+       * testsuite/gas/mips/xpa-err.s: New test source.
+       * testsuite/gas/mips/xpa-virt-err.s: New test source.
+       * testsuite/gas/mips/mips.exp: Run the new tests.
+
 2017-06-29  Maciej W. Rozycki  <macro@imgtec.com>
 
        * testsuite/gas/mips/mips16e2@mips16e2-mt-sub.d: Adjust for the
index d06143a1f94d879e424857c8167571bed916cc05..9b42ef8962d85bbbc13f59f3e74155ddc1bb7af5 100644 (file)
@@ -2133,11 +2133,19 @@ mips_set_ase (const struct mips_ase *ase, struct mips_set_options *opts,
 
   /* Clear combination ASE flags, which need to be recalculated based on
      updated regular ASE settings.  */
-  opts->ase &= ~ASE_MIPS16E2_MT;
+  opts->ase &= ~(ASE_MIPS16E2_MT | ASE_XPA_VIRT);
 
   if (enabled_p)
     opts->ase |= ase->flags;
 
+  /* The Virtualization ASE has eXtended Physical Addressing (XPA)
+     instructions which are only valid when both ASEs are enabled.
+     This sets the ASE_XPA_VIRT flag when both ASEs are present.  */
+  if ((opts->ase & (ASE_XPA | ASE_VIRT)) == (ASE_XPA | ASE_VIRT))
+    {
+      opts->ase |= ASE_XPA_VIRT;
+      mask |= ASE_XPA_VIRT;
+    }
   if ((opts->ase & (ASE_MIPS16E2 | ASE_MT)) == (ASE_MIPS16E2 | ASE_MT))
     {
       opts->ase |= ASE_MIPS16E2_MT;
index 26d29e4b7d527347fd7a262fa4434fbaf6f85042..6a6b47dcaa3331670bcdd54a1e230c83b30f9515 100644 (file)
@@ -1562,6 +1562,9 @@ if { [istarget mips*-*-vxworks*] } {
     run_dump_test_arches "msa-branch"  [mips_arch_list_matching mips32r2]
 
     run_dump_test_arches "xpa"         [mips_arch_list_matching mips32r2 !micromips]
+    run_dump_test_arches "xpa-err"     [mips_arch_list_matching mips32r2 !micromips]
+    run_dump_test_arches "xpa-virt-err" \
+                               [mips_arch_list_matching mips32r2 !micromips]
     run_dump_test_arches "r5" "-32"    [mips_arch_list_matching mips32r5 !micromips]
 
     run_dump_test "pcrel-1"
diff --git a/gas/testsuite/gas/mips/xpa-err.d b/gas/testsuite/gas/mips/xpa-err.d
new file mode 100644 (file)
index 0000000..772bd49
--- /dev/null
@@ -0,0 +1,3 @@
+#name: MIPS XPA instruction errors
+#as: -32 -mxpa
+#error-output: xpa-err.l
diff --git a/gas/testsuite/gas/mips/xpa-err.l b/gas/testsuite/gas/mips/xpa-err.l
new file mode 100644 (file)
index 0000000..0ea0fc9
--- /dev/null
@@ -0,0 +1,2 @@
+.*: Assembler messages:
+.*:8: Error: opcode not supported on this processor: [^ ]+ \([^)]+\) `mthc0 \$2,\$1'
diff --git a/gas/testsuite/gas/mips/xpa-err.s b/gas/testsuite/gas/mips/xpa-err.s
new file mode 100644 (file)
index 0000000..0bd9daf
--- /dev/null
@@ -0,0 +1,8 @@
+# Verify that switching off either `xpa' causes an assembly error
+# with an XPA instruction.
+
+       .text
+foo:
+       mfhc0   $2, $1
+       .set    noxpa
+       mthc0   $2, $1
diff --git a/gas/testsuite/gas/mips/xpa-virt-err.d b/gas/testsuite/gas/mips/xpa-virt-err.d
new file mode 100644 (file)
index 0000000..bc51319
--- /dev/null
@@ -0,0 +1,3 @@
+#name: MIPS XPA Virtualization ASE instruction errors
+#as: -32 -mxpa -mvirt
+#error-output: xpa-virt-err.l
diff --git a/gas/testsuite/gas/mips/xpa-virt-err.l b/gas/testsuite/gas/mips/xpa-virt-err.l
new file mode 100644 (file)
index 0000000..8f964c5
--- /dev/null
@@ -0,0 +1,3 @@
+.*: Assembler messages:
+.*:9: Error: opcode not supported on this processor: [^ ]+ \([^)]+\) `mthgc0 \$2,\$1'
+.*:13: Error: opcode not supported on this processor: [^ ]+ \([^)]+\) `mthgc0 \$2,\$1'
diff --git a/gas/testsuite/gas/mips/xpa-virt-err.s b/gas/testsuite/gas/mips/xpa-virt-err.s
new file mode 100644 (file)
index 0000000..fcc0c73
--- /dev/null
@@ -0,0 +1,15 @@
+# Verify that switching off either `xpa' or `virt' causes an assembly
+# error with an XPA Virtualization ASE instruction, which requires
+# both at a time.
+
+       .text
+foo:
+       mfhgc0  $2, $1
+       .set    noxpa
+       mthgc0  $2, $1
+       .set    xpa
+       mfhgc0  $2, $1
+       .set    novirt
+       mthgc0  $2, $1
+       .set    virt
+       mfhgc0  $2, $1
index f1047c9b167b2f4b0141aebf5ce4d6fb7bef9b08..32098f1f154b92113653ab9f259c74e85a77f3e2 100644 (file)
@@ -1,6 +1,6 @@
-#objdump: -dr --prefix-addresses --show-raw-insn -Mxpa,cp0-names=mips32r2
+#objdump: -dr --prefix-addresses --show-raw-insn -M cp0-names=mips32r2
 #name: XPA instructions
-#as: -32 -mxpa
+#as: -32 -mxpa -mvirt
 
 .*: +file format .*mips.*
 
index 171d4bdb3c59fdae6b38b261b979b001917e25b5..b9405040106469d56ea30cae33761e91ddd7a64b 100644 (file)
@@ -1,3 +1,8 @@
+2017-06-30  Maciej W. Rozycki  <macro@imgtec.com>
+           Andrew Bennett  <andrew.bennett@imgtec.com>
+
+       * opcode/mips.h (ASE_XPA_VIRT): New macro.
+
 2017-06-29  Andreas Arnez  <arnez@linux.vnet.ibm.com>
 
        * elf/common.h (NT_S390_GS_CB): New macro.
index 1b3b2c62f67647ec60c1aaafdfcddb1292535b36..ceae9ec50a4c203b7a7982db784d3b03446d2359 100644 (file)
@@ -1291,6 +1291,9 @@ static const unsigned int mips_isa_table[] = {
 #define ASE_MIPS16E2           0x00008000
 /* MIPS16e2 MT ASE instructions.  */
 #define ASE_MIPS16E2_MT                0x00010000
+/* The Virtualization ASE has eXtended Physical Addressing (XPA)
+   instructions which are only valid when both ASEs are enabled.  */
+#define ASE_XPA_VIRT           0x00020000
 
 /* MIPS ISA defines, use instead of hardcoding ISA level.  */
 
index e4b24705af2e153380335d2d1cc428e60b4733af..8e6a052e6b968219e6549cbd85191fc0a486e258 100644 (file)
@@ -1,3 +1,15 @@
+2017-06-30  Maciej W. Rozycki  <macro@imgtec.com>
+           Andrew Bennett  <andrew.bennett@imgtec.com>
+
+       * mips-dis.c (mips_calculate_combination_ases): Handle the
+       ASE_XPA_VIRT flag.
+       (parse_mips_ase_option): New function.
+       (parse_mips_dis_option): Factor out ASE option handling to the
+       new function.  Call `mips_calculate_combination_ases'.
+       * mips-opc.c (XPAVZ): New macro.
+       (mips_builtin_opcodes): Correct ISA and ASE flags for "mfhc0",
+       "mfhgc0", "mthc0" and "mthgc0".
+
 2017-06-29  Maciej W. Rozycki  <macro@imgtec.com>
 
        * mips-dis.c (mips_calculate_combination_ases): New function.
index 588247a9bb47e999954e4f1bf7be8b3183474883..45195007c1e47f6065e8834e6235c4493882b1b0 100644 (file)
@@ -815,6 +815,8 @@ mips_calculate_combination_ases (unsigned long opcode_ases)
 {
   unsigned long combination_ases = 0;
 
+  if ((opcode_ases & (ASE_XPA | ASE_VIRT)) == (ASE_XPA | ASE_VIRT))
+    combination_ases |= ASE_XPA_VIRT;
   if ((opcode_ases & (ASE_MIPS16E2 | ASE_MT)) == (ASE_MIPS16E2 | ASE_MT))
     combination_ases |= ASE_MIPS16E2_MT;
   return combination_ases;
@@ -892,21 +894,12 @@ set_default_mips_dis_options (struct disassemble_info *info)
   mips_ase |= mips_calculate_combination_ases (mips_ase);
 }
 
-static void
-parse_mips_dis_option (const char *option, unsigned int len)
-{
-  unsigned int i, optionlen, vallen;
-  const char *val;
-  const struct mips_abi_choice *chosen_abi;
-  const struct mips_arch_choice *chosen_arch;
-
-  /* Try to match options that are simple flags */
-  if (CONST_STRNEQ (option, "no-aliases"))
-    {
-      no_aliases = 1;
-      return;
-    }
+/* Parse an ASE disassembler option and set the corresponding global
+   ASE flag(s).  Return TRUE if successful, FALSE otherwise.  */
 
+static bfd_boolean
+parse_mips_ase_option (const char *option)
+{
   if (CONST_STRNEQ (option, "msa"))
     {
       mips_ase |= ASE_MSA;
@@ -915,7 +908,7 @@ parse_mips_dis_option (const char *option, unsigned int len)
           || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R5
           || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6)
          mips_ase |= ASE_MSA64;
-      return;
+      return TRUE;
     }
 
   if (CONST_STRNEQ (option, "virt"))
@@ -926,15 +919,38 @@ parse_mips_dis_option (const char *option, unsigned int len)
          || mips_isa & ISA_MIPS64R5
          || mips_isa & ISA_MIPS64R6)
        mips_ase |= ASE_VIRT64;
-      return;
+      return TRUE;
     }
 
   if (CONST_STRNEQ (option, "xpa"))
     {
       mips_ase |= ASE_XPA;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+parse_mips_dis_option (const char *option, unsigned int len)
+{
+  unsigned int i, optionlen, vallen;
+  const char *val;
+  const struct mips_abi_choice *chosen_abi;
+  const struct mips_arch_choice *chosen_arch;
+
+  /* Try to match options that are simple flags */
+  if (CONST_STRNEQ (option, "no-aliases"))
+    {
+      no_aliases = 1;
       return;
     }
 
+  if (parse_mips_ase_option (option))
+    {
+      mips_ase |= mips_calculate_combination_ases (mips_ase);
+      return;
+    }
 
   /* Look for the = that delimits the end of the option name.  */
   for (i = 0; i < len; i++)
index b151baea0c29bba1d590299f057e94eb272d3200..9c392ba32d07477ad59ce2c2e94458e1d2211f19 100644 (file)
@@ -402,6 +402,7 @@ decode_mips_operand (const char *p)
 
 /* eXtended Physical Address (XPA) support.  */
 #define XPA     ASE_XPA
+#define XPAVZ  ASE_XPA_VIRT
 
 /* The order of overloaded instructions matters.  Label arguments and
    register arguments look the same. Instructions that can have either
@@ -1390,10 +1391,10 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"mfc0",               "t,G,H",        0x40000000, 0xffe007f8, WR_1|RD_C0|LC,          0,              I32,            0,      0 },
 {"mfgc0",              "t,G",          0x40600000, 0xffe007ff, WR_1|RD_C0|LC,          0,              0,              IVIRT,  0 },
 {"mfgc0",              "t,G,H",        0x40600000, 0xffe007f8, WR_1|RD_C0|LC,          0,              0,              IVIRT,  0 },
-{"mfhc0",              "t,G",          0x40400000, 0xffe007ff, WR_1|RD_C0|LC,          0,              I33,            XPA,    0 },
-{"mfhc0",              "t,G,H",        0x40400000, 0xffe007f8, WR_1|RD_C0|LC,          0,              I33,            XPA,    0 },
-{"mfhgc0",             "t,G",          0x40600400, 0xffe007ff, WR_1|RD_C0|LC,          0,              I33,            IVIRT|XPA,      0 },
-{"mfhgc0",             "t,G,H",        0x40600400, 0xffe007f8, WR_1|RD_C0|LC,          0,              I33,            IVIRT|XPA,      0 },
+{"mfhc0",              "t,G",          0x40400000, 0xffe007ff, WR_1|RD_C0|LC,          0,              0,              XPA,    0 },
+{"mfhc0",              "t,G,H",        0x40400000, 0xffe007f8, WR_1|RD_C0|LC,          0,              0,              XPA,    0 },
+{"mfhgc0",             "t,G",          0x40600400, 0xffe007ff, WR_1|RD_C0|LC,          0,              0,              XPAVZ,  0 },
+{"mfhgc0",             "t,G,H",        0x40600400, 0xffe007f8, WR_1|RD_C0|LC,          0,              0,              XPAVZ,  0 },
 {"mfc1",               "t,S",          0x44000000, 0xffe007ff, WR_1|RD_2|LC|FP_S,      0,              I1,             0,      0 },
 {"mfc1",               "t,G",          0x44000000, 0xffe007ff, WR_1|RD_2|LC|FP_S,      0,              I1,             0,      0 },
 {"mfhc1",              "t,S",          0x44600000, 0xffe007ff, WR_1|RD_2|LC|FP_D,      0,              I33,            0,      0 },
@@ -1488,10 +1489,10 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"mtc0",               "t,G,H",        0x40800000, 0xffe007f8, RD_1|WR_C0|WR_CC|CM,    0,              I32,            0,      0 },
 {"mtgc0",              "t,G",          0x40600200, 0xffe007ff, RD_1|WR_C0|WR_CC|CM,    0,              0,              IVIRT,  0 },
 {"mtgc0",              "t,G,H",        0x40600200, 0xffe007f8, RD_1|WR_C0|WR_CC|CM,   0,               0,              IVIRT,  0 },
-{"mthc0",              "t,G",          0x40c00000, 0xffe007ff, RD_1|WR_C0|WR_CC|CM,    0,              I33,            XPA,    0 },
-{"mthc0",              "t,G,H",        0x40c00000, 0xffe007f8, RD_1|WR_C0|WR_CC|CM,    0,              I33,            XPA,    0 },
-{"mthgc0",             "t,G",          0x40600600, 0xffe007ff, RD_1|WR_C0|WR_CC|CM,    0,              I33,            IVIRT|XPA,      0 },
-{"mthgc0",             "t,G,H",        0x40600600, 0xffe007f8, RD_1|WR_C0|WR_CC|CM,    0,              I33,            IVIRT|XPA,      0 },
+{"mthc0",              "t,G",          0x40c00000, 0xffe007ff, RD_1|WR_C0|WR_CC|CM,    0,              0,              XPA,    0 },
+{"mthc0",              "t,G,H",        0x40c00000, 0xffe007f8, RD_1|WR_C0|WR_CC|CM,    0,              0,              XPA,    0 },
+{"mthgc0",             "t,G",          0x40600600, 0xffe007ff, RD_1|WR_C0|WR_CC|CM,    0,              0,              XPAVZ,  0 },
+{"mthgc0",             "t,G,H",        0x40600600, 0xffe007f8, RD_1|WR_C0|WR_CC|CM,    0,              0,              XPAVZ,  0 },
 {"mtc1",               "t,S",          0x44800000, 0xffe007ff, RD_1|WR_2|CM|FP_S,      0,              I1,             0,      0 },
 {"mtc1",               "t,G",          0x44800000, 0xffe007ff, RD_1|WR_2|CM|FP_S,      0,              I1,             0,      0 },
 {"mthc1",              "t,S",          0x44e00000, 0xffe007ff, RD_1|WR_2|CM|FP_D,      0,              I33,            0,      0 },