diff options
author | Faraz Shahbazker <fshahbazker@wavecomp.com> | 2019-06-19 15:55:04 -0700 |
---|---|---|
committer | Faraz Shahbazker <fshahbazker@wavecomp.com> | 2019-06-25 09:29:55 -0700 |
commit | 9b444f9533c38016e4f2de0198c889b13a62d2bc (patch) | |
tree | 9e52e1c2e2f88433121434c4b0871e2b750368d0 /gas/config | |
parent | 5c2c8c694de18370ac6161a21217627ddadeafc7 (diff) | |
download | gdb-9b444f9533c38016e4f2de0198c889b13a62d2bc.zip gdb-9b444f9533c38016e4f2de0198c889b13a62d2bc.tar.gz gdb-9b444f9533c38016e4f2de0198c889b13a62d2bc.tar.bz2 |
MIPS/gas: Fix order of instructions in LI macro expansion
When MTHC1 instruction is paired with MTC1 to write a value to a
64-bit FPR, the MTC1 must be executed first, because the semantic
definition of MTC1 is not aware that software will be using an MTHC1
to complete the operation, and sets the upper half of the 64-bit FPR
to an UNPREDICTABLE value[1].
Fix the order of MTHC1 and MTC1 instructions in LI macro expansion.
Modify the expansions to exploit moves from $zero directly by-passing
the use of $AT, where ever possible.
[1] "MIPS Architecture for Programmers Volume II-A: The MIPS32
Instruction Set Manual", Wave Computing, Inc., Document
Number: MD00086, Revision 5.04, December 11, 2013, Section 3.2
"Alphabetical List of Instructions", pp. 217.
gas/
* config/tc-mips.c (macro) <M_LI>: Re-order MTHC1 with
respect to MTC1 and use $0 for either part where possible.
* testsuite/gas/mips/li-d.s: Add test cases for non-zero
words in double precision constants.
* testsuite/gas/mips/li-d.d: Update reference output.
* testsuite/gas/mips/micromips@isa-override-1.d: Likewise.
* testsuite/gas/mips/mips32r2@isa-override-1.d: Likewise.
* testsuite/gas/mips/mips64r2@isa-override-1.d: Likewise.
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-mips.c | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 0f0ace5..671d74a 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -12780,20 +12780,28 @@ macro (struct mips_cl_insn *ip, char *str) OFFSET_EXPR. */ if (imm_expr.X_op == O_constant) { - used_at = 1; - load_register (AT, &imm_expr, FPR_SIZE == 64); + tempreg = ZERO; + if (((FPR_SIZE == 64 && GPR_SIZE == 64) + || !ISA_HAS_MXHC1 (mips_opts.isa)) + && imm_expr.X_add_number != 0) + { + used_at = 1; + tempreg = AT; + load_register (AT, &imm_expr, FPR_SIZE == 64); + } if (FPR_SIZE == 64 && GPR_SIZE == 64) - macro_build (NULL, "dmtc1", "t,S", AT, op[0]); + macro_build (NULL, "dmtc1", "t,S", tempreg, op[0]); else { - if (ISA_HAS_MXHC1 (mips_opts.isa)) - macro_build (NULL, "mthc1", "t,G", AT, op[0]); - else if (FPR_SIZE != 32) - as_bad (_("Unable to generate `%s' compliant code " - "without mthc1"), - (FPR_SIZE == 64) ? "fp64" : "fpxx"); - else - macro_build (NULL, "mtc1", "t,G", AT, op[0] + 1); + if (!ISA_HAS_MXHC1 (mips_opts.isa)) + { + if (FPR_SIZE != 32) + as_bad (_("Unable to generate `%s' compliant code " + "without mthc1"), + (FPR_SIZE == 64) ? "fp64" : "fpxx"); + else + macro_build (NULL, "mtc1", "t,G", tempreg, op[0] + 1); + } if (offset_expr.X_op == O_absent) macro_build (NULL, "mtc1", "t,G", 0, op[0]); else @@ -12802,6 +12810,16 @@ macro (struct mips_cl_insn *ip, char *str) load_register (AT, &offset_expr, 0); macro_build (NULL, "mtc1", "t,G", AT, op[0]); } + if (ISA_HAS_MXHC1 (mips_opts.isa)) + { + if (imm_expr.X_add_number != 0) + { + used_at = 1; + tempreg = AT; + load_register (AT, &imm_expr, 0); + } + macro_build (NULL, "mthc1", "t,G", tempreg, op[0]); + } } break; } |