diff options
author | Maciej W. Rozycki <macro@imgtec.com> | 2017-06-30 07:21:55 +0100 |
---|---|---|
committer | Maciej W. Rozycki <macro@imgtec.com> | 2017-06-30 07:21:55 +0100 |
commit | 9785fc2a4d220322ce6cd1d79e768345ea5234d2 (patch) | |
tree | 275033dcff24aa9a5b87300fe32dbd8ca3936da2 /opcodes/mips-dis.c | |
parent | 8d011e87dfa4e1719bd909b9adcbd1a0f5a75228 (diff) | |
download | gdb-9785fc2a4d220322ce6cd1d79e768345ea5234d2.zip gdb-9785fc2a4d220322ce6cd1d79e768345ea5234d2.tar.gz gdb-9785fc2a4d220322ce6cd1d79e768345ea5234d2.tar.bz2 |
MIPS: Fix XPA base and Virtualization ASE instruction handling
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.
Diffstat (limited to 'opcodes/mips-dis.c')
-rw-r--r-- | opcodes/mips-dis.c | 48 |
1 files changed, 32 insertions, 16 deletions
diff --git a/opcodes/mips-dis.c b/opcodes/mips-dis.c index 588247a..4519500 100644 --- a/opcodes/mips-dis.c +++ b/opcodes/mips-dis.c @@ -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++) |