MIPS/gas: Fix order of instructions in LI macro expansion

Message ID 1560984895-11017-1-git-send-email-fshahbazker@wavecomp.com
State New
Headers show
Series
  • MIPS/gas: Fix order of instructions in LI macro expansion
Related show

Commit Message

Faraz Shahbazker June 19, 2019, 10:55 p.m.
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.
---

Notes:
    https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00086-2B-MIPS32BIS-AFP-05.04.pdf

 gas/config/tc-mips.c                              | 40 +++++++++++++-----
 gas/testsuite/gas/mips/li-d.d                     | 51 +++++++++++++++++++----
 gas/testsuite/gas/mips/li-d.s                     | 39 +++++++++++++++++
 gas/testsuite/gas/mips/micromips@isa-override-1.d | 12 +++---
 gas/testsuite/gas/mips/mips32r2@isa-override-1.d  | 12 +++---
 gas/testsuite/gas/mips/mips64r2@isa-override-1.d  | 12 +++---
 6 files changed, 129 insertions(+), 37 deletions(-)

-- 
2.7.4

Comments

Paul Hua June 25, 2019, 12:29 p.m. | #1
ok.

On Thu, Jun 20, 2019 at 6:55 AM Faraz Shahbazker
<fshahbazker@wavecomp.com> wrote:
>

> 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.

> ---

>

> Notes:

>     https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00086-2B-MIPS32BIS-AFP-05.04.pdf

>

>  gas/config/tc-mips.c                              | 40 +++++++++++++-----

>  gas/testsuite/gas/mips/li-d.d                     | 51 +++++++++++++++++++----

>  gas/testsuite/gas/mips/li-d.s                     | 39 +++++++++++++++++

>  gas/testsuite/gas/mips/micromips@isa-override-1.d | 12 +++---

>  gas/testsuite/gas/mips/mips32r2@isa-override-1.d  | 12 +++---

>  gas/testsuite/gas/mips/mips64r2@isa-override-1.d  | 12 +++---

>  6 files changed, 129 insertions(+), 37 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;

>         }

> diff --git a/gas/testsuite/gas/mips/li-d.d b/gas/testsuite/gas/mips/li-d.d

> index ca24570..9c569a1 100644

> --- a/gas/testsuite/gas/mips/li-d.d

> +++ b/gas/testsuite/gas/mips/li-d.d

> @@ -10,22 +10,57 @@

>  Disassembly of section \.text:

>  [0-9a-f]+ <[^>]*> li   v(0|1),0

>  [0-9a-f]+ <[^>]*> move v(1|0),zero

> -[0-9a-f]+ <[^>]*> li   at,0

> +[0-9a-f]+ <[^>]*> mtc1 zero,\$f1

> +[0-9a-f]+ <[^>]*> mtc1 zero,\$f0

> +[0-9a-f]+ <[^>]*> mtc1 zero,\$f1

> +[0-9a-f]+ <[^>]*> mtc1 zero,\$f0

> +[0-9a-f]+ <[^>]*> ldc1 \$f0,0\(gp\)

> +[0-9a-f]+ <[^>]*> mtc1 zero,\$f0

> +[0-9a-f]+ <[^>]*> mthc1        zero,\$f0

> +[0-9a-f]+ <[^>]*> mtc1 zero,\$f0

> +[0-9a-f]+ <[^>]*> mthc1        zero,\$f0

> +[0-9a-f]+ <[^>]*> mtc1 zero,\$f0

> +[0-9a-f]+ <[^>]*> mthc1        zero,\$f0

> +[0-9a-f]+ <[^>]*> dmtc1        zero,\$f0

> +[0-9a-f]+ <[^>]*> lui  v[01],0x3ff0

> +[0-9a-f]+ <[^>]*> move v[01],zero

> +[0-9a-f]+ <[^>]*> lui  at,0x3ff0

>  [0-9a-f]+ <[^>]*> mtc1 at,\$f1

>  [0-9a-f]+ <[^>]*> mtc1 zero,\$f0

> -[0-9a-f]+ <[^>]*> li   at,0

> +[0-9a-f]+ <[^>]*> lui  at,0x3ff0

>  [0-9a-f]+ <[^>]*> mtc1 at,\$f1

>  [0-9a-f]+ <[^>]*> mtc1 zero,\$f0

> -[0-9a-f]+ <[^>]*> ldc1 \$f0,0\(gp\)

> -[0-9a-f]+ <[^>]*> li   at,0

> -[0-9a-f]+ <[^>]*> mthc1        at,\$f0

> +[0-9a-f]+ <[^>]*> ldc1 \$f0,(0|8)\(gp\)

>  [0-9a-f]+ <[^>]*> mtc1 zero,\$f0

> -[0-9a-f]+ <[^>]*> li   at,0

> +[0-9a-f]+ <[^>]*> lui  at,0x3ff0

>  [0-9a-f]+ <[^>]*> mthc1        at,\$f0

>  [0-9a-f]+ <[^>]*> mtc1 zero,\$f0

> -[0-9a-f]+ <[^>]*> li   at,0

> +[0-9a-f]+ <[^>]*> lui  at,0x3ff0

>  [0-9a-f]+ <[^>]*> mthc1        at,\$f0

>  [0-9a-f]+ <[^>]*> mtc1 zero,\$f0

> -[0-9a-f]+ <[^>]*> li   at,0

> +[0-9a-f]+ <[^>]*> lui  at,0x3ff0

> +[0-9a-f]+ <[^>]*> mthc1        at,\$f0

> +[0-9a-f]+ <[^>]*> li   at,0xffc0

> +[0-9a-f]+ <[^>]*> dsll32       at,at,0xe

> +[0-9a-f]+ <[^>]*> dmtc1        at,\$f0

> +[0-9a-f]+ <[^>]*> li   v[01],0

> +[0-9a-f]+ <[^>]*> li   v[01],4250

> +[0-9a-f]+ <[^>]*> mtc1 zero,\$f1

> +[0-9a-f]+ <[^>]*> li   at,4250

> +[0-9a-f]+ <[^>]*> mtc1 at,\$f0

> +[0-9a-f]+ <[^>]*> mtc1 zero,\$f1

> +[0-9a-f]+ <[^>]*> li   at,4250

> +[0-9a-f]+ <[^>]*> mtc1 at,\$f0

> +[0-9a-f]+ <[^>]*> ldc1 \$f0,(0|16)\(gp\)

> +[0-9a-f]+ <[^>]*> li   at,4250

> +[0-9a-f]+ <[^>]*> mtc1 at,\$f0

> +[0-9a-f]+ <[^>]*> mthc1        zero,\$f0

> +[0-9a-f]+ <[^>]*> li   at,4250

> +[0-9a-f]+ <[^>]*> mtc1 at,\$f0

> +[0-9a-f]+ <[^>]*> mthc1        zero,\$f0

> +[0-9a-f]+ <[^>]*> li   at,4250

> +[0-9a-f]+ <[^>]*> mtc1 at,\$f0

> +[0-9a-f]+ <[^>]*> mthc1        zero,\$f0

> +[0-9a-f]+ <[^>]*> li   at,4250

>  [0-9a-f]+ <[^>]*> dmtc1        at,\$f0

>         \.\.\.

> diff --git a/gas/testsuite/gas/mips/li-d.s b/gas/testsuite/gas/mips/li-d.s

> index 8578097..561f2bc 100644

> --- a/gas/testsuite/gas/mips/li-d.s

> +++ b/gas/testsuite/gas/mips/li-d.s

> @@ -1,6 +1,7 @@

>  # Source file used to test the li macro.

>

>  foo:

> +       # Both words zero

>         .set mips1

>         .set fp=32

>         li.d $2, 0

> @@ -19,6 +20,44 @@ foo:

>         .set mips3

>         li.d $f0, 0

>

> +       # Only upper 16 bits of 64 non-zero

> +       .set mips1

> +       .set fp=32

> +       li.d $2, 1.0

> +       li.d $f0, 1.0

> +       .set mips2

> +       li.d $f0, 1.0

> +       .set fp=xx

> +       li.d $f0, 1.0

> +       .set mips32r2

> +       .set fp=32

> +       li.d $f0, 1.0

> +       .set fp=xx

> +       li.d $f0, 1.0

> +       .set fp=64

> +       li.d $f0, 1.0

> +       .set mips3

> +       li.d $f0, 1.0

> +

> +       # Only lower 16 bits of 64 non-zero

> +       .set mips1

> +       .set fp=32

> +       li.d $2, 2.1e-320

> +       li.d $f0, 2.1e-320

> +       .set mips2

> +       li.d $f0, 2.1e-320

> +       .set fp=xx

> +       li.d $f0, 2.1e-320

> +       .set mips32r2

> +       .set fp=32

> +       li.d $f0, 2.1e-320

> +       .set fp=xx

> +       li.d $f0, 2.1e-320

> +       .set fp=64

> +       li.d $f0, 2.1e-320

> +       .set mips3

> +       li.d $f0, 2.1e-320

> +

>  # Force at least 8 (non-delay-slot) zero bytes, to make 'objdump' print ...

>         .align  2

>         .space  8

> diff --git a/gas/testsuite/gas/mips/micromips@isa-override-1.d b/gas/testsuite/gas/mips/micromips@isa-override-1.d

> index e600ff8..3403696 100644

> --- a/gas/testsuite/gas/mips/micromips@isa-override-1.d

> +++ b/gas/testsuite/gas/mips/micromips@isa-override-1.d

> @@ -11,10 +11,10 @@ Disassembly of section \.text:

>  [0-9a-f]+ <[^>]*> 41a1 89ab    lui     at,0x89ab

>  [0-9a-f]+ <[^>]*> 0022 1290    or      v0,v0,at

>  [0-9a-f]+ <[^>]*> bc44 0000    ldc1    \$f2,0\(a0\)

> -[0-9a-f]+ <[^>]*> 41a1 3ff0    lui     at,0x3ff0

> -[0-9a-f]+ <[^>]*> 5422 383b    mthc1   at,\$f2

>  [0-9a-f]+ <[^>]*> 41a1 89ab    lui     at,0x89ab

>  [0-9a-f]+ <[^>]*> 5422 283b    mtc1    at,\$f2

> +[0-9a-f]+ <[^>]*> 41a1 3ff0    lui     at,0x3ff0

> +[0-9a-f]+ <[^>]*> 5422 383b    mthc1   at,\$f2

>  [0-9a-f]+ <[^>]*> dc44 0000    ld      v0,0\(a0\)

>  [0-9a-f]+ <[^>]*> 5020 89ab    li      at,0x89ab

>  [0-9a-f]+ <[^>]*> 5821 8000    dsll    at,at,0x10

> @@ -34,17 +34,17 @@ Disassembly of section \.text:

>  [0-9a-f]+ <[^>]*> 41a1 89ab    lui     at,0x89ab

>  [0-9a-f]+ <[^>]*> 0022 1290    or      v0,v0,at

>  [0-9a-f]+ <[^>]*> bc44 0000    ldc1    \$f2,0\(a0\)

> -[0-9a-f]+ <[^>]*> 41a1 3ff0    lui     at,0x3ff0

> -[0-9a-f]+ <[^>]*> 5422 383b    mthc1   at,\$f2

>  [0-9a-f]+ <[^>]*> 41a1 89ab    lui     at,0x89ab

>  [0-9a-f]+ <[^>]*> 5422 283b    mtc1    at,\$f2

> +[0-9a-f]+ <[^>]*> 41a1 3ff0    lui     at,0x3ff0

> +[0-9a-f]+ <[^>]*> 5422 383b    mthc1   at,\$f2

>  [0-9a-f]+ <[^>]*> fc44 0000    lw      v0,0\(a0\)

>  [0-9a-f]+ <[^>]*> fc64 0004    lw      v1,4\(a0\)

>  [0-9a-f]+ <[^>]*> 41a1 89ab    lui     at,0x89ab

>  [0-9a-f]+ <[^>]*> 0022 1290    or      v0,v0,at

>  [0-9a-f]+ <[^>]*> bc44 0000    ldc1    \$f2,0\(a0\)

> -[0-9a-f]+ <[^>]*> 41a1 3ff0    lui     at,0x3ff0

> -[0-9a-f]+ <[^>]*> 5422 383b    mthc1   at,\$f2

>  [0-9a-f]+ <[^>]*> 41a1 89ab    lui     at,0x89ab

>  [0-9a-f]+ <[^>]*> 5422 283b    mtc1    at,\$f2

> +[0-9a-f]+ <[^>]*> 41a1 3ff0    lui     at,0x3ff0

> +[0-9a-f]+ <[^>]*> 5422 383b    mthc1   at,\$f2

>         \.\.\.

> diff --git a/gas/testsuite/gas/mips/mips32r2@isa-override-1.d b/gas/testsuite/gas/mips/mips32r2@isa-override-1.d

> index 0ab21b9..0dc753a 100644

> --- a/gas/testsuite/gas/mips/mips32r2@isa-override-1.d

> +++ b/gas/testsuite/gas/mips/mips32r2@isa-override-1.d

> @@ -11,10 +11,10 @@ Disassembly of section \.text:

>  [0-9a-f]+ <[^>]*> 3c0189ab     lui     at,0x89ab

>  [0-9a-f]+ <[^>]*> 00411025     or      v0,v0,at

>  [0-9a-f]+ <[^>]*> d4820000     ldc1    \$f2,0\(a0\)

> -[0-9a-f]+ <[^>]*> 3c013ff0     lui     at,0x3ff0

> -[0-9a-f]+ <[^>]*> 44e11000     mthc1   at,\$f2

>  [0-9a-f]+ <[^>]*> 3c0189ab     lui     at,0x89ab

>  [0-9a-f]+ <[^>]*> 44811000     mtc1    at,\$f2

> +[0-9a-f]+ <[^>]*> 3c013ff0     lui     at,0x3ff0

> +[0-9a-f]+ <[^>]*> 44e11000     mthc1   at,\$f2

>  [0-9a-f]+ <[^>]*> dc820000     ldc3    \$2,0\(a0\)

>  [0-9a-f]+ <[^>]*> 340189ab     li      at,0x89ab

>  [0-9a-f]+ <[^>]*> 00010c38     0x10c38

> @@ -34,17 +34,17 @@ Disassembly of section \.text:

>  [0-9a-f]+ <[^>]*> 3c0189ab     lui     at,0x89ab

>  [0-9a-f]+ <[^>]*> 00411025     or      v0,v0,at

>  [0-9a-f]+ <[^>]*> d4820000     ldc1    \$f2,0\(a0\)

> -[0-9a-f]+ <[^>]*> 3c013ff0     lui     at,0x3ff0

> -[0-9a-f]+ <[^>]*> 44e11000     mthc1   at,\$f2

>  [0-9a-f]+ <[^>]*> 3c0189ab     lui     at,0x89ab

>  [0-9a-f]+ <[^>]*> 44811000     mtc1    at,\$f2

> +[0-9a-f]+ <[^>]*> 3c013ff0     lui     at,0x3ff0

> +[0-9a-f]+ <[^>]*> 44e11000     mthc1   at,\$f2

>  [0-9a-f]+ <[^>]*> 8c820000     lw      v0,0\(a0\)

>  [0-9a-f]+ <[^>]*> 8c830004     lw      v1,4\(a0\)

>  [0-9a-f]+ <[^>]*> 3c0189ab     lui     at,0x89ab

>  [0-9a-f]+ <[^>]*> 00411025     or      v0,v0,at

>  [0-9a-f]+ <[^>]*> d4820000     ldc1    \$f2,0\(a0\)

> -[0-9a-f]+ <[^>]*> 3c013ff0     lui     at,0x3ff0

> -[0-9a-f]+ <[^>]*> 44e11000     mthc1   at,\$f2

>  [0-9a-f]+ <[^>]*> 3c0189ab     lui     at,0x89ab

>  [0-9a-f]+ <[^>]*> 44811000     mtc1    at,\$f2

> +[0-9a-f]+ <[^>]*> 3c013ff0     lui     at,0x3ff0

> +[0-9a-f]+ <[^>]*> 44e11000     mthc1   at,\$f2

>         \.\.\.

> diff --git a/gas/testsuite/gas/mips/mips64r2@isa-override-1.d b/gas/testsuite/gas/mips/mips64r2@isa-override-1.d

> index d53fb2c..1e81c4e 100644

> --- a/gas/testsuite/gas/mips/mips64r2@isa-override-1.d

> +++ b/gas/testsuite/gas/mips/mips64r2@isa-override-1.d

> @@ -11,10 +11,10 @@ Disassembly of section \.text:

>  [0-9a-f]+ <[^>]*> 3c0189ab     lui     at,0x89ab

>  [0-9a-f]+ <[^>]*> 00411025     or      v0,v0,at

>  [0-9a-f]+ <[^>]*> d4820000     ldc1    \$f2,0\(a0\)

> -[0-9a-f]+ <[^>]*> 3c013ff0     lui     at,0x3ff0

> -[0-9a-f]+ <[^>]*> 44e11000     mthc1   at,\$f2

>  [0-9a-f]+ <[^>]*> 3c0189ab     lui     at,0x89ab

>  [0-9a-f]+ <[^>]*> 44811000     mtc1    at,\$f2

> +[0-9a-f]+ <[^>]*> 3c013ff0     lui     at,0x3ff0

> +[0-9a-f]+ <[^>]*> 44e11000     mthc1   at,\$f2

>  [0-9a-f]+ <[^>]*> dc820000     ld      v0,0\(a0\)

>  [0-9a-f]+ <[^>]*> 340189ab     li      at,0x89ab

>  [0-9a-f]+ <[^>]*> 00010c38     dsll    at,at,0x10

> @@ -34,17 +34,17 @@ Disassembly of section \.text:

>  [0-9a-f]+ <[^>]*> 3c0189ab     lui     at,0x89ab

>  [0-9a-f]+ <[^>]*> 00411025     or      v0,v0,at

>  [0-9a-f]+ <[^>]*> d4820000     ldc1    \$f2,0\(a0\)

> -[0-9a-f]+ <[^>]*> 3c013ff0     lui     at,0x3ff0

> -[0-9a-f]+ <[^>]*> 44e11000     mthc1   at,\$f2

>  [0-9a-f]+ <[^>]*> 3c0189ab     lui     at,0x89ab

>  [0-9a-f]+ <[^>]*> 44811000     mtc1    at,\$f2

> +[0-9a-f]+ <[^>]*> 3c013ff0     lui     at,0x3ff0

> +[0-9a-f]+ <[^>]*> 44e11000     mthc1   at,\$f2

>  [0-9a-f]+ <[^>]*> 8c820000     lw      v0,0\(a0\)

>  [0-9a-f]+ <[^>]*> 8c830004     lw      v1,4\(a0\)

>  [0-9a-f]+ <[^>]*> 3c0189ab     lui     at,0x89ab

>  [0-9a-f]+ <[^>]*> 00411025     or      v0,v0,at

>  [0-9a-f]+ <[^>]*> d4820000     ldc1    \$f2,0\(a0\)

> -[0-9a-f]+ <[^>]*> 3c013ff0     lui     at,0x3ff0

> -[0-9a-f]+ <[^>]*> 44e11000     mthc1   at,\$f2

>  [0-9a-f]+ <[^>]*> 3c0189ab     lui     at,0x89ab

>  [0-9a-f]+ <[^>]*> 44811000     mtc1    at,\$f2

> +[0-9a-f]+ <[^>]*> 3c013ff0     lui     at,0x3ff0

> +[0-9a-f]+ <[^>]*> 44e11000     mthc1   at,\$f2

>         \.\.\.

> --

> 2.7.4

>

Patch

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;
 	}
diff --git a/gas/testsuite/gas/mips/li-d.d b/gas/testsuite/gas/mips/li-d.d
index ca24570..9c569a1 100644
--- a/gas/testsuite/gas/mips/li-d.d
+++ b/gas/testsuite/gas/mips/li-d.d
@@ -10,22 +10,57 @@ 
 Disassembly of section \.text:
 [0-9a-f]+ <[^>]*> li	v(0|1),0
 [0-9a-f]+ <[^>]*> move	v(1|0),zero
-[0-9a-f]+ <[^>]*> li	at,0
+[0-9a-f]+ <[^>]*> mtc1	zero,\$f1
+[0-9a-f]+ <[^>]*> mtc1	zero,\$f0
+[0-9a-f]+ <[^>]*> mtc1	zero,\$f1
+[0-9a-f]+ <[^>]*> mtc1	zero,\$f0
+[0-9a-f]+ <[^>]*> ldc1	\$f0,0\(gp\)
+[0-9a-f]+ <[^>]*> mtc1	zero,\$f0
+[0-9a-f]+ <[^>]*> mthc1	zero,\$f0
+[0-9a-f]+ <[^>]*> mtc1	zero,\$f0
+[0-9a-f]+ <[^>]*> mthc1	zero,\$f0
+[0-9a-f]+ <[^>]*> mtc1	zero,\$f0
+[0-9a-f]+ <[^>]*> mthc1	zero,\$f0
+[0-9a-f]+ <[^>]*> dmtc1	zero,\$f0
+[0-9a-f]+ <[^>]*> lui	v[01],0x3ff0
+[0-9a-f]+ <[^>]*> move	v[01],zero
+[0-9a-f]+ <[^>]*> lui	at,0x3ff0
 [0-9a-f]+ <[^>]*> mtc1	at,\$f1
 [0-9a-f]+ <[^>]*> mtc1	zero,\$f0
-[0-9a-f]+ <[^>]*> li	at,0
+[0-9a-f]+ <[^>]*> lui	at,0x3ff0
 [0-9a-f]+ <[^>]*> mtc1	at,\$f1
 [0-9a-f]+ <[^>]*> mtc1	zero,\$f0
-[0-9a-f]+ <[^>]*> ldc1	\$f0,0\(gp\)
-[0-9a-f]+ <[^>]*> li	at,0
-[0-9a-f]+ <[^>]*> mthc1	at,\$f0
+[0-9a-f]+ <[^>]*> ldc1	\$f0,(0|8)\(gp\)
 [0-9a-f]+ <[^>]*> mtc1	zero,\$f0
-[0-9a-f]+ <[^>]*> li	at,0
+[0-9a-f]+ <[^>]*> lui	at,0x3ff0
 [0-9a-f]+ <[^>]*> mthc1	at,\$f0
 [0-9a-f]+ <[^>]*> mtc1	zero,\$f0
-[0-9a-f]+ <[^>]*> li	at,0
+[0-9a-f]+ <[^>]*> lui	at,0x3ff0
 [0-9a-f]+ <[^>]*> mthc1	at,\$f0
 [0-9a-f]+ <[^>]*> mtc1	zero,\$f0
-[0-9a-f]+ <[^>]*> li	at,0
+[0-9a-f]+ <[^>]*> lui	at,0x3ff0
+[0-9a-f]+ <[^>]*> mthc1	at,\$f0
+[0-9a-f]+ <[^>]*> li	at,0xffc0
+[0-9a-f]+ <[^>]*> dsll32	at,at,0xe
+[0-9a-f]+ <[^>]*> dmtc1	at,\$f0
+[0-9a-f]+ <[^>]*> li	v[01],0
+[0-9a-f]+ <[^>]*> li	v[01],4250
+[0-9a-f]+ <[^>]*> mtc1	zero,\$f1
+[0-9a-f]+ <[^>]*> li	at,4250
+[0-9a-f]+ <[^>]*> mtc1	at,\$f0
+[0-9a-f]+ <[^>]*> mtc1	zero,\$f1
+[0-9a-f]+ <[^>]*> li	at,4250
+[0-9a-f]+ <[^>]*> mtc1	at,\$f0
+[0-9a-f]+ <[^>]*> ldc1	\$f0,(0|16)\(gp\)
+[0-9a-f]+ <[^>]*> li	at,4250
+[0-9a-f]+ <[^>]*> mtc1	at,\$f0
+[0-9a-f]+ <[^>]*> mthc1	zero,\$f0
+[0-9a-f]+ <[^>]*> li	at,4250
+[0-9a-f]+ <[^>]*> mtc1	at,\$f0
+[0-9a-f]+ <[^>]*> mthc1	zero,\$f0
+[0-9a-f]+ <[^>]*> li	at,4250
+[0-9a-f]+ <[^>]*> mtc1	at,\$f0
+[0-9a-f]+ <[^>]*> mthc1	zero,\$f0
+[0-9a-f]+ <[^>]*> li	at,4250
 [0-9a-f]+ <[^>]*> dmtc1	at,\$f0
 	\.\.\.
diff --git a/gas/testsuite/gas/mips/li-d.s b/gas/testsuite/gas/mips/li-d.s
index 8578097..561f2bc 100644
--- a/gas/testsuite/gas/mips/li-d.s
+++ b/gas/testsuite/gas/mips/li-d.s
@@ -1,6 +1,7 @@ 
 # Source file used to test the li macro.
 
 foo:
+	# Both words zero
 	.set mips1
 	.set fp=32
 	li.d $2, 0
@@ -19,6 +20,44 @@  foo:
 	.set mips3
 	li.d $f0, 0
 
+	# Only upper 16 bits of 64 non-zero
+	.set mips1
+	.set fp=32
+	li.d $2, 1.0
+	li.d $f0, 1.0
+	.set mips2
+	li.d $f0, 1.0
+	.set fp=xx
+	li.d $f0, 1.0
+	.set mips32r2
+	.set fp=32
+	li.d $f0, 1.0
+	.set fp=xx
+	li.d $f0, 1.0
+	.set fp=64
+	li.d $f0, 1.0
+	.set mips3
+	li.d $f0, 1.0
+
+	# Only lower 16 bits of 64 non-zero
+	.set mips1
+	.set fp=32
+	li.d $2, 2.1e-320
+	li.d $f0, 2.1e-320
+	.set mips2
+	li.d $f0, 2.1e-320
+	.set fp=xx
+	li.d $f0, 2.1e-320
+	.set mips32r2
+	.set fp=32
+	li.d $f0, 2.1e-320
+	.set fp=xx
+	li.d $f0, 2.1e-320
+	.set fp=64
+	li.d $f0, 2.1e-320
+	.set mips3
+	li.d $f0, 2.1e-320
+
 # Force at least 8 (non-delay-slot) zero bytes, to make 'objdump' print ...
 	.align  2
 	.space  8
diff --git a/gas/testsuite/gas/mips/micromips@isa-override-1.d b/gas/testsuite/gas/mips/micromips@isa-override-1.d
index e600ff8..3403696 100644
--- a/gas/testsuite/gas/mips/micromips@isa-override-1.d
+++ b/gas/testsuite/gas/mips/micromips@isa-override-1.d
@@ -11,10 +11,10 @@  Disassembly of section \.text:
 [0-9a-f]+ <[^>]*> 41a1 89ab 	lui	at,0x89ab
 [0-9a-f]+ <[^>]*> 0022 1290 	or	v0,v0,at
 [0-9a-f]+ <[^>]*> bc44 0000 	ldc1	\$f2,0\(a0\)
-[0-9a-f]+ <[^>]*> 41a1 3ff0 	lui	at,0x3ff0
-[0-9a-f]+ <[^>]*> 5422 383b 	mthc1	at,\$f2
 [0-9a-f]+ <[^>]*> 41a1 89ab 	lui	at,0x89ab
 [0-9a-f]+ <[^>]*> 5422 283b 	mtc1	at,\$f2
+[0-9a-f]+ <[^>]*> 41a1 3ff0 	lui	at,0x3ff0
+[0-9a-f]+ <[^>]*> 5422 383b 	mthc1	at,\$f2
 [0-9a-f]+ <[^>]*> dc44 0000 	ld	v0,0\(a0\)
 [0-9a-f]+ <[^>]*> 5020 89ab 	li	at,0x89ab
 [0-9a-f]+ <[^>]*> 5821 8000 	dsll	at,at,0x10
@@ -34,17 +34,17 @@  Disassembly of section \.text:
 [0-9a-f]+ <[^>]*> 41a1 89ab 	lui	at,0x89ab
 [0-9a-f]+ <[^>]*> 0022 1290 	or	v0,v0,at
 [0-9a-f]+ <[^>]*> bc44 0000 	ldc1	\$f2,0\(a0\)
-[0-9a-f]+ <[^>]*> 41a1 3ff0 	lui	at,0x3ff0
-[0-9a-f]+ <[^>]*> 5422 383b 	mthc1	at,\$f2
 [0-9a-f]+ <[^>]*> 41a1 89ab 	lui	at,0x89ab
 [0-9a-f]+ <[^>]*> 5422 283b 	mtc1	at,\$f2
+[0-9a-f]+ <[^>]*> 41a1 3ff0 	lui	at,0x3ff0
+[0-9a-f]+ <[^>]*> 5422 383b 	mthc1	at,\$f2
 [0-9a-f]+ <[^>]*> fc44 0000 	lw	v0,0\(a0\)
 [0-9a-f]+ <[^>]*> fc64 0004 	lw	v1,4\(a0\)
 [0-9a-f]+ <[^>]*> 41a1 89ab 	lui	at,0x89ab
 [0-9a-f]+ <[^>]*> 0022 1290 	or	v0,v0,at
 [0-9a-f]+ <[^>]*> bc44 0000 	ldc1	\$f2,0\(a0\)
-[0-9a-f]+ <[^>]*> 41a1 3ff0 	lui	at,0x3ff0
-[0-9a-f]+ <[^>]*> 5422 383b 	mthc1	at,\$f2
 [0-9a-f]+ <[^>]*> 41a1 89ab 	lui	at,0x89ab
 [0-9a-f]+ <[^>]*> 5422 283b 	mtc1	at,\$f2
+[0-9a-f]+ <[^>]*> 41a1 3ff0 	lui	at,0x3ff0
+[0-9a-f]+ <[^>]*> 5422 383b 	mthc1	at,\$f2
 	\.\.\.
diff --git a/gas/testsuite/gas/mips/mips32r2@isa-override-1.d b/gas/testsuite/gas/mips/mips32r2@isa-override-1.d
index 0ab21b9..0dc753a 100644
--- a/gas/testsuite/gas/mips/mips32r2@isa-override-1.d
+++ b/gas/testsuite/gas/mips/mips32r2@isa-override-1.d
@@ -11,10 +11,10 @@  Disassembly of section \.text:
 [0-9a-f]+ <[^>]*> 3c0189ab 	lui	at,0x89ab
 [0-9a-f]+ <[^>]*> 00411025 	or	v0,v0,at
 [0-9a-f]+ <[^>]*> d4820000 	ldc1	\$f2,0\(a0\)
-[0-9a-f]+ <[^>]*> 3c013ff0 	lui	at,0x3ff0
-[0-9a-f]+ <[^>]*> 44e11000 	mthc1	at,\$f2
 [0-9a-f]+ <[^>]*> 3c0189ab 	lui	at,0x89ab
 [0-9a-f]+ <[^>]*> 44811000 	mtc1	at,\$f2
+[0-9a-f]+ <[^>]*> 3c013ff0 	lui	at,0x3ff0
+[0-9a-f]+ <[^>]*> 44e11000 	mthc1	at,\$f2
 [0-9a-f]+ <[^>]*> dc820000 	ldc3	\$2,0\(a0\)
 [0-9a-f]+ <[^>]*> 340189ab 	li	at,0x89ab
 [0-9a-f]+ <[^>]*> 00010c38 	0x10c38
@@ -34,17 +34,17 @@  Disassembly of section \.text:
 [0-9a-f]+ <[^>]*> 3c0189ab 	lui	at,0x89ab
 [0-9a-f]+ <[^>]*> 00411025 	or	v0,v0,at
 [0-9a-f]+ <[^>]*> d4820000 	ldc1	\$f2,0\(a0\)
-[0-9a-f]+ <[^>]*> 3c013ff0 	lui	at,0x3ff0
-[0-9a-f]+ <[^>]*> 44e11000 	mthc1	at,\$f2
 [0-9a-f]+ <[^>]*> 3c0189ab 	lui	at,0x89ab
 [0-9a-f]+ <[^>]*> 44811000 	mtc1	at,\$f2
+[0-9a-f]+ <[^>]*> 3c013ff0 	lui	at,0x3ff0
+[0-9a-f]+ <[^>]*> 44e11000 	mthc1	at,\$f2
 [0-9a-f]+ <[^>]*> 8c820000 	lw	v0,0\(a0\)
 [0-9a-f]+ <[^>]*> 8c830004 	lw	v1,4\(a0\)
 [0-9a-f]+ <[^>]*> 3c0189ab 	lui	at,0x89ab
 [0-9a-f]+ <[^>]*> 00411025 	or	v0,v0,at
 [0-9a-f]+ <[^>]*> d4820000 	ldc1	\$f2,0\(a0\)
-[0-9a-f]+ <[^>]*> 3c013ff0 	lui	at,0x3ff0
-[0-9a-f]+ <[^>]*> 44e11000 	mthc1	at,\$f2
 [0-9a-f]+ <[^>]*> 3c0189ab 	lui	at,0x89ab
 [0-9a-f]+ <[^>]*> 44811000 	mtc1	at,\$f2
+[0-9a-f]+ <[^>]*> 3c013ff0 	lui	at,0x3ff0
+[0-9a-f]+ <[^>]*> 44e11000 	mthc1	at,\$f2
 	\.\.\.
diff --git a/gas/testsuite/gas/mips/mips64r2@isa-override-1.d b/gas/testsuite/gas/mips/mips64r2@isa-override-1.d
index d53fb2c..1e81c4e 100644
--- a/gas/testsuite/gas/mips/mips64r2@isa-override-1.d
+++ b/gas/testsuite/gas/mips/mips64r2@isa-override-1.d
@@ -11,10 +11,10 @@  Disassembly of section \.text:
 [0-9a-f]+ <[^>]*> 3c0189ab 	lui	at,0x89ab
 [0-9a-f]+ <[^>]*> 00411025 	or	v0,v0,at
 [0-9a-f]+ <[^>]*> d4820000 	ldc1	\$f2,0\(a0\)
-[0-9a-f]+ <[^>]*> 3c013ff0 	lui	at,0x3ff0
-[0-9a-f]+ <[^>]*> 44e11000 	mthc1	at,\$f2
 [0-9a-f]+ <[^>]*> 3c0189ab 	lui	at,0x89ab
 [0-9a-f]+ <[^>]*> 44811000 	mtc1	at,\$f2
+[0-9a-f]+ <[^>]*> 3c013ff0 	lui	at,0x3ff0
+[0-9a-f]+ <[^>]*> 44e11000 	mthc1	at,\$f2
 [0-9a-f]+ <[^>]*> dc820000 	ld	v0,0\(a0\)
 [0-9a-f]+ <[^>]*> 340189ab 	li	at,0x89ab
 [0-9a-f]+ <[^>]*> 00010c38 	dsll	at,at,0x10
@@ -34,17 +34,17 @@  Disassembly of section \.text:
 [0-9a-f]+ <[^>]*> 3c0189ab 	lui	at,0x89ab
 [0-9a-f]+ <[^>]*> 00411025 	or	v0,v0,at
 [0-9a-f]+ <[^>]*> d4820000 	ldc1	\$f2,0\(a0\)
-[0-9a-f]+ <[^>]*> 3c013ff0 	lui	at,0x3ff0
-[0-9a-f]+ <[^>]*> 44e11000 	mthc1	at,\$f2
 [0-9a-f]+ <[^>]*> 3c0189ab 	lui	at,0x89ab
 [0-9a-f]+ <[^>]*> 44811000 	mtc1	at,\$f2
+[0-9a-f]+ <[^>]*> 3c013ff0 	lui	at,0x3ff0
+[0-9a-f]+ <[^>]*> 44e11000 	mthc1	at,\$f2
 [0-9a-f]+ <[^>]*> 8c820000 	lw	v0,0\(a0\)
 [0-9a-f]+ <[^>]*> 8c830004 	lw	v1,4\(a0\)
 [0-9a-f]+ <[^>]*> 3c0189ab 	lui	at,0x89ab
 [0-9a-f]+ <[^>]*> 00411025 	or	v0,v0,at
 [0-9a-f]+ <[^>]*> d4820000 	ldc1	\$f2,0\(a0\)
-[0-9a-f]+ <[^>]*> 3c013ff0 	lui	at,0x3ff0
-[0-9a-f]+ <[^>]*> 44e11000 	mthc1	at,\$f2
 [0-9a-f]+ <[^>]*> 3c0189ab 	lui	at,0x89ab
 [0-9a-f]+ <[^>]*> 44811000 	mtc1	at,\$f2
+[0-9a-f]+ <[^>]*> 3c013ff0 	lui	at,0x3ff0
+[0-9a-f]+ <[^>]*> 44e11000 	mthc1	at,\$f2
 	\.\.\.