x86: allow to request ModR/M encoding
authorJan Beulich <jbeulich@suse.com>
Fri, 24 Feb 2023 13:00:11 +0000 (14:00 +0100)
committerJan Beulich <jbeulich@suse.com>
Fri, 24 Feb 2023 13:00:11 +0000 (14:00 +0100)
Several insns have a (typically shorter) non-ModR/M and a (typically
longer) ModR/M encoding. In most cases the former is used by default.
This isn't too dissimilar from register-only insns sometimes having two
encoding forms. In those cases {load} or {store} can be used to control
the encoding used. Extend this to ModR/M-less encodings which have a
ModR/M counterpart (note that BSWAP hasn't). For insn reading and
writing their (explicit) memory operand, both prefixes are honored;
otherwise only the applicable one is.

Note that for some forms of XCHG, {store} has already been performing
this function, apparently as an unnoticed side effect of adding D to
the template.

gas/config/tc-i386.c
gas/testsuite/gas/i386/pseudos.d
gas/testsuite/gas/i386/pseudos.s
gas/testsuite/gas/i386/x86-64-pseudos.d
gas/testsuite/gas/i386/x86-64-pseudos.s

index 3df0a47a030b10334953734ed112083bc7bd86b8..a9314f560b71a0af0892cd6955a0f5945296ecc0 100644 (file)
@@ -6883,19 +6883,40 @@ match_template (char mnem_suffix)
        case 1:
          if (!operand_type_match (overlap0, i.types[0]))
            continue;
+
+         /* Allow the ModR/M encoding to be requested by using the {load} or
+            {store} pseudo prefix on an applicable insn.  */
+         if (!t->opcode_modifier.modrm
+             && i.reg_operands == 1
+             && ((i.dir_encoding == dir_encoding_load
+                  && t->mnem_off != MN_pop)
+                 || (i.dir_encoding == dir_encoding_store
+                     && t->mnem_off != MN_push))
+             /* Avoid BSWAP.  */
+             && t->mnem_off != MN_bswap)
+           continue;
          break;
+
        case 2:
          /* xchg %eax, %eax is a special case. It is an alias for nop
             only in 32bit mode and we can use opcode 0x90.  In 64bit
             mode, we can't use 0x90 for xchg %eax, %eax since it should
             zero-extend %eax to %rax.  */
-         if (flag_code == CODE_64BIT
-             && t->base_opcode == 0x90
-             && t->opcode_space == SPACE_BASE
-             && i.types[0].bitfield.instance == Accum
-             && i.types[0].bitfield.dword
-             && i.types[1].bitfield.instance == Accum)
-           continue;
+         if (t->base_opcode == 0x90
+             && t->opcode_space == SPACE_BASE)
+           {
+             if (flag_code == CODE_64BIT
+                 && i.types[0].bitfield.instance == Accum
+                 && i.types[0].bitfield.dword
+                 && i.types[1].bitfield.instance == Accum)
+               continue;
+
+             /* Allow the ModR/M encoding to be requested by using the
+                {load} or {store} pseudo prefix.  */
+             if (i.dir_encoding == dir_encoding_load
+                 || i.dir_encoding == dir_encoding_store)
+               continue;
+           }
 
          if (t->base_opcode == MOV_AX_DISP32
              && t->opcode_space == SPACE_BASE
@@ -6909,6 +6930,38 @@ match_template (char mnem_suffix)
                 match the accumulator-only encoding of mov.  */
              if (i.hle_prefix)
                continue;
+
+             /* Allow the ModR/M encoding to be requested by using a suitable
+                {load} or {store} pseudo prefix.  */
+             if (i.dir_encoding == (i.types[0].bitfield.instance == Accum
+                                    ? dir_encoding_store
+                                    : dir_encoding_load)
+                 && !i.types[0].bitfield.disp64
+                 && !i.types[1].bitfield.disp64)
+               continue;
+           }
+
+         /* Allow the ModR/M encoding to be requested by using the {load} or
+            {store} pseudo prefix on an applicable insn.  */
+         if (!t->opcode_modifier.modrm
+             && i.reg_operands == 1
+             && i.imm_operands == 1
+             && (i.dir_encoding == dir_encoding_load
+                 || i.dir_encoding == dir_encoding_store)
+             && t->opcode_space == SPACE_BASE)
+           {
+             if (t->base_opcode == 0xb0 /* mov $imm, %reg */
+                 && i.dir_encoding == dir_encoding_store)
+               continue;
+
+             if ((t->base_opcode | 0x38) == 0x3c /* <alu> $imm, %acc */
+                 && (t->base_opcode != 0x3c /* cmp $imm, %acc */
+                     || i.dir_encoding == dir_encoding_load))
+               continue;
+
+             if (t->base_opcode == 0xa8 /* test $imm, %acc */
+                 && i.dir_encoding == dir_encoding_load)
+               continue;
            }
          /* Fall through.  */
 
index 0df9b7265aab7b971158718dc40935c3b598a04a..98e1149c19bd24b8de3df7aa22557940ec3e295a 100644 (file)
@@ -54,10 +54,10 @@ Disassembly of section .text:
  +[a-f0-9]+:   31 c8                   xor    %ecx,%eax
  +[a-f0-9]+:   33 c1                   xor    %ecx,%eax
  +[a-f0-9]+:   31 c8                   xor    %ecx,%eax
- +[a-f0-9]+:   a1 78 56 34 12          mov    0x12345678,%eax
+ +[a-f0-9]+:   8b 05 78 56 34 12       mov    0x12345678,%eax
  +[a-f0-9]+:   a3 78 56 34 12          mov    %eax,0x12345678
  +[a-f0-9]+:   a1 78 56 34 12          mov    0x12345678,%eax
- +[a-f0-9]+:   a3 78 56 34 12          mov    %eax,0x12345678
+ +[a-f0-9]+:   89 05 78 56 34 12       mov    %eax,0x12345678
  +[a-f0-9]+:   89 07                   mov    %eax,\(%edi\)
  +[a-f0-9]+:   8b 07                   mov    \(%edi\),%eax
  +[a-f0-9]+:   89 07                   mov    %eax,\(%edi\)
@@ -126,6 +126,91 @@ Disassembly of section .text:
  +[a-f0-9]+:   33 07                   xor    \(%edi\),%eax
  +[a-f0-9]+:   31 07                   xor    %eax,\(%edi\)
  +[a-f0-9]+:   33 07                   xor    \(%edi\),%eax
+ +[a-f0-9]+:   b0 12                   mov    \$0x12,%al
+ +[a-f0-9]+:   b8 45 03 00 00          mov    \$0x345,%eax
+ +[a-f0-9]+:   b0 12                   mov    \$0x12,%al
+ +[a-f0-9]+:   b8 45 03 00 00          mov    \$0x345,%eax
+ +[a-f0-9]+:   c6 c0 12                mov    \$0x12,%al
+ +[a-f0-9]+:   c7 c0 45 03 00 00       mov    \$0x345,%eax
+ +[a-f0-9]+:   14 12                   adc    \$0x12,%al
+ +[a-f0-9]+:   15 45 03 00 00          adc    \$0x345,%eax
+ +[a-f0-9]+:   80 d0 12                adc    \$0x12,%al
+ +[a-f0-9]+:   81 d0 45 03 00 00       adc    \$0x345,%eax
+ +[a-f0-9]+:   80 d0 12                adc    \$0x12,%al
+ +[a-f0-9]+:   81 d0 45 03 00 00       adc    \$0x345,%eax
+ +[a-f0-9]+:   04 12                   add    \$0x12,%al
+ +[a-f0-9]+:   05 45 03 00 00          add    \$0x345,%eax
+ +[a-f0-9]+:   80 c0 12                add    \$0x12,%al
+ +[a-f0-9]+:   81 c0 45 03 00 00       add    \$0x345,%eax
+ +[a-f0-9]+:   80 c0 12                add    \$0x12,%al
+ +[a-f0-9]+:   81 c0 45 03 00 00       add    \$0x345,%eax
+ +[a-f0-9]+:   24 12                   and    \$0x12,%al
+ +[a-f0-9]+:   25 45 03 00 00          and    \$0x345,%eax
+ +[a-f0-9]+:   80 e0 12                and    \$0x12,%al
+ +[a-f0-9]+:   81 e0 45 03 00 00       and    \$0x345,%eax
+ +[a-f0-9]+:   80 e0 12                and    \$0x12,%al
+ +[a-f0-9]+:   81 e0 45 03 00 00       and    \$0x345,%eax
+ +[a-f0-9]+:   3c 12                   cmp    \$0x12,%al
+ +[a-f0-9]+:   3d 45 03 00 00          cmp    \$0x345,%eax
+ +[a-f0-9]+:   80 f8 12                cmp    \$0x12,%al
+ +[a-f0-9]+:   81 f8 45 03 00 00       cmp    \$0x345,%eax
+ +[a-f0-9]+:   3c 12                   cmp    \$0x12,%al
+ +[a-f0-9]+:   3d 45 03 00 00          cmp    \$0x345,%eax
+ +[a-f0-9]+:   0c 12                   or     \$0x12,%al
+ +[a-f0-9]+:   0d 45 03 00 00          or     \$0x345,%eax
+ +[a-f0-9]+:   80 c8 12                or     \$0x12,%al
+ +[a-f0-9]+:   81 c8 45 03 00 00       or     \$0x345,%eax
+ +[a-f0-9]+:   80 c8 12                or     \$0x12,%al
+ +[a-f0-9]+:   81 c8 45 03 00 00       or     \$0x345,%eax
+ +[a-f0-9]+:   1c 12                   sbb    \$0x12,%al
+ +[a-f0-9]+:   1d 45 03 00 00          sbb    \$0x345,%eax
+ +[a-f0-9]+:   80 d8 12                sbb    \$0x12,%al
+ +[a-f0-9]+:   81 d8 45 03 00 00       sbb    \$0x345,%eax
+ +[a-f0-9]+:   80 d8 12                sbb    \$0x12,%al
+ +[a-f0-9]+:   81 d8 45 03 00 00       sbb    \$0x345,%eax
+ +[a-f0-9]+:   2c 12                   sub    \$0x12,%al
+ +[a-f0-9]+:   2d 45 03 00 00          sub    \$0x345,%eax
+ +[a-f0-9]+:   80 e8 12                sub    \$0x12,%al
+ +[a-f0-9]+:   81 e8 45 03 00 00       sub    \$0x345,%eax
+ +[a-f0-9]+:   80 e8 12                sub    \$0x12,%al
+ +[a-f0-9]+:   81 e8 45 03 00 00       sub    \$0x345,%eax
+ +[a-f0-9]+:   a8 12                   test   \$0x12,%al
+ +[a-f0-9]+:   a9 45 03 00 00          test   \$0x345,%eax
+ +[a-f0-9]+:   f6 c0 12                test   \$0x12,%al
+ +[a-f0-9]+:   f7 c0 45 03 00 00       test   \$0x345,%eax
+ +[a-f0-9]+:   a8 12                   test   \$0x12,%al
+ +[a-f0-9]+:   a9 45 03 00 00          test   \$0x345,%eax
+ +[a-f0-9]+:   34 12                   xor    \$0x12,%al
+ +[a-f0-9]+:   35 45 03 00 00          xor    \$0x345,%eax
+ +[a-f0-9]+:   80 f0 12                xor    \$0x12,%al
+ +[a-f0-9]+:   81 f0 45 03 00 00       xor    \$0x345,%eax
+ +[a-f0-9]+:   80 f0 12                xor    \$0x12,%al
+ +[a-f0-9]+:   81 f0 45 03 00 00       xor    \$0x345,%eax
+ +[a-f0-9]+:   41                      inc    %ecx
+ +[a-f0-9]+:   ff c1                   inc    %ecx
+ +[a-f0-9]+:   ff c1                   inc    %ecx
+ +[a-f0-9]+:   49                      dec    %ecx
+ +[a-f0-9]+:   ff c9                   dec    %ecx
+ +[a-f0-9]+:   ff c9                   dec    %ecx
+ +[a-f0-9]+:   51                      push   %ecx
+ +[a-f0-9]+:   ff f1                   push   %ecx
+ +[a-f0-9]+:   51                      push   %ecx
+ +[a-f0-9]+:   59                      pop    %ecx
+ +[a-f0-9]+:   59                      pop    %ecx
+ +[a-f0-9]+:   8f c1                   pop    %ecx
+ +[a-f0-9]+:   0f c9                   bswap  %ecx
+ +[a-f0-9]+:   0f c9                   bswap  %ecx
+ +[a-f0-9]+:   0f c9                   bswap  %ecx
+ +[a-f0-9]+:   87 ce                   xchg   %ecx,%esi
+ +[a-f0-9]+:   87 f1                   xchg   %esi,%ecx
+ +[a-f0-9]+:   87 f1                   xchg   %esi,%ecx
+ +[a-f0-9]+:   87 ce                   xchg   %ecx,%esi
+ +[a-f0-9]+:   96                      xchg   %eax,%esi
+ +[a-f0-9]+:   87 f0                   xchg   %esi,%eax
+ +[a-f0-9]+:   87 c6                   xchg   %eax,%esi
+ +[a-f0-9]+:   91                      xchg   %eax,%ecx
+ +[a-f0-9]+:   87 c1                   xchg   %eax,%ecx
+ +[a-f0-9]+:   87 c8                   xchg   %ecx,%eax
  +[a-f0-9]+:   d8 c0                   fadd   %st\(0\),%st
  +[a-f0-9]+:   d8 c0                   fadd   %st\(0\),%st
  +[a-f0-9]+:   dc c0                   fadd   %st,%st\(0\)
index 34a461c262e56167d187040f4d69cc38e5efdc40..7e3600eb250e10fc12871c2f513679078410eb55 100644 (file)
@@ -124,6 +124,34 @@ _start:
        {store} xor %eax, (%edi)
        {store} xor (%edi), %eax
 
+       .irp m, mov, adc, add, and, cmp, or, sbb, sub, test, xor
+       \m      $0x12, %al
+       \m      $0x345, %eax
+       {load} \m $0x12, %al            # bogus for MOV
+       {load} \m $0x345, %eax          # bogus for MOV
+       {store} \m $0x12, %al
+       {store} \m $0x345, %eax
+       .endr
+
+       .irp m, inc, dec, push, pop, bswap
+       \m      %ecx
+       {load} \m %ecx                  # bogus for POP
+       {store} \m %ecx                 # bogus for PUSH
+       .endr
+
+       xchg    %ecx, %esi
+       xchg    %esi, %ecx
+       {load} xchg %ecx, %esi
+       {store} xchg %ecx, %esi
+
+       xchg    %eax, %esi
+       {load} xchg %eax, %esi
+       {store} xchg %eax, %esi
+
+       xchg    %ecx, %eax
+       {load} xchg %ecx, %eax
+       {store} xchg %ecx, %eax
+
        fadd %st, %st
        {load} fadd %st, %st
        {store} fadd %st, %st
index fb71942046d9ac9d371c148527fb29a5e7c18924..0cc75ef2457929fd8217df270048dc9287391362 100644 (file)
@@ -137,6 +137,91 @@ Disassembly of section .text:
  +[a-f0-9]+:   33 07                   xor    \(%rdi\),%eax
  +[a-f0-9]+:   31 07                   xor    %eax,\(%rdi\)
  +[a-f0-9]+:   33 07                   xor    \(%rdi\),%eax
+ +[a-f0-9]+:   b0 12                   mov    \$0x12,%al
+ +[a-f0-9]+:   b8 45 03 00 00          mov    \$0x345,%eax
+ +[a-f0-9]+:   b0 12                   mov    \$0x12,%al
+ +[a-f0-9]+:   b8 45 03 00 00          mov    \$0x345,%eax
+ +[a-f0-9]+:   c6 c0 12                mov    \$0x12,%al
+ +[a-f0-9]+:   c7 c0 45 03 00 00       mov    \$0x345,%eax
+ +[a-f0-9]+:   14 12                   adc    \$0x12,%al
+ +[a-f0-9]+:   15 45 03 00 00          adc    \$0x345,%eax
+ +[a-f0-9]+:   80 d0 12                adc    \$0x12,%al
+ +[a-f0-9]+:   81 d0 45 03 00 00       adc    \$0x345,%eax
+ +[a-f0-9]+:   80 d0 12                adc    \$0x12,%al
+ +[a-f0-9]+:   81 d0 45 03 00 00       adc    \$0x345,%eax
+ +[a-f0-9]+:   04 12                   add    \$0x12,%al
+ +[a-f0-9]+:   05 45 03 00 00          add    \$0x345,%eax
+ +[a-f0-9]+:   80 c0 12                add    \$0x12,%al
+ +[a-f0-9]+:   81 c0 45 03 00 00       add    \$0x345,%eax
+ +[a-f0-9]+:   80 c0 12                add    \$0x12,%al
+ +[a-f0-9]+:   81 c0 45 03 00 00       add    \$0x345,%eax
+ +[a-f0-9]+:   24 12                   and    \$0x12,%al
+ +[a-f0-9]+:   25 45 03 00 00          and    \$0x345,%eax
+ +[a-f0-9]+:   80 e0 12                and    \$0x12,%al
+ +[a-f0-9]+:   81 e0 45 03 00 00       and    \$0x345,%eax
+ +[a-f0-9]+:   80 e0 12                and    \$0x12,%al
+ +[a-f0-9]+:   81 e0 45 03 00 00       and    \$0x345,%eax
+ +[a-f0-9]+:   3c 12                   cmp    \$0x12,%al
+ +[a-f0-9]+:   3d 45 03 00 00          cmp    \$0x345,%eax
+ +[a-f0-9]+:   80 f8 12                cmp    \$0x12,%al
+ +[a-f0-9]+:   81 f8 45 03 00 00       cmp    \$0x345,%eax
+ +[a-f0-9]+:   3c 12                   cmp    \$0x12,%al
+ +[a-f0-9]+:   3d 45 03 00 00          cmp    \$0x345,%eax
+ +[a-f0-9]+:   0c 12                   or     \$0x12,%al
+ +[a-f0-9]+:   0d 45 03 00 00          or     \$0x345,%eax
+ +[a-f0-9]+:   80 c8 12                or     \$0x12,%al
+ +[a-f0-9]+:   81 c8 45 03 00 00       or     \$0x345,%eax
+ +[a-f0-9]+:   80 c8 12                or     \$0x12,%al
+ +[a-f0-9]+:   81 c8 45 03 00 00       or     \$0x345,%eax
+ +[a-f0-9]+:   1c 12                   sbb    \$0x12,%al
+ +[a-f0-9]+:   1d 45 03 00 00          sbb    \$0x345,%eax
+ +[a-f0-9]+:   80 d8 12                sbb    \$0x12,%al
+ +[a-f0-9]+:   81 d8 45 03 00 00       sbb    \$0x345,%eax
+ +[a-f0-9]+:   80 d8 12                sbb    \$0x12,%al
+ +[a-f0-9]+:   81 d8 45 03 00 00       sbb    \$0x345,%eax
+ +[a-f0-9]+:   2c 12                   sub    \$0x12,%al
+ +[a-f0-9]+:   2d 45 03 00 00          sub    \$0x345,%eax
+ +[a-f0-9]+:   80 e8 12                sub    \$0x12,%al
+ +[a-f0-9]+:   81 e8 45 03 00 00       sub    \$0x345,%eax
+ +[a-f0-9]+:   80 e8 12                sub    \$0x12,%al
+ +[a-f0-9]+:   81 e8 45 03 00 00       sub    \$0x345,%eax
+ +[a-f0-9]+:   a8 12                   test   \$0x12,%al
+ +[a-f0-9]+:   a9 45 03 00 00          test   \$0x345,%eax
+ +[a-f0-9]+:   f6 c0 12                test   \$0x12,%al
+ +[a-f0-9]+:   f7 c0 45 03 00 00       test   \$0x345,%eax
+ +[a-f0-9]+:   a8 12                   test   \$0x12,%al
+ +[a-f0-9]+:   a9 45 03 00 00          test   \$0x345,%eax
+ +[a-f0-9]+:   34 12                   xor    \$0x12,%al
+ +[a-f0-9]+:   35 45 03 00 00          xor    \$0x345,%eax
+ +[a-f0-9]+:   80 f0 12                xor    \$0x12,%al
+ +[a-f0-9]+:   81 f0 45 03 00 00       xor    \$0x345,%eax
+ +[a-f0-9]+:   80 f0 12                xor    \$0x12,%al
+ +[a-f0-9]+:   81 f0 45 03 00 00       xor    \$0x345,%eax
+ +[a-f0-9]+:   48 b9 89 67 45 23 01 00 00 00   movabs \$0x123456789,%rcx
+ +[a-f0-9]+:   48 b9 89 67 45 23 01 00 00 00   movabs \$0x123456789,%rcx
+ +[a-f0-9]+:   48 b9 89 67 45 23 01 00 00 00   movabs \$0x123456789,%rcx
+ +[a-f0-9]+:   48 b9 78 56 34 12 00 00 00 00   movabs \$0x12345678,%rcx
+ +[a-f0-9]+:   48 b9 78 56 34 12 00 00 00 00   movabs \$0x12345678,%rcx
+ +[a-f0-9]+:   48 b9 78 56 34 12 00 00 00 00   movabs \$0x12345678,%rcx
+ +[a-f0-9]+:   51                      push   %rcx
+ +[a-f0-9]+:   ff f1                   push   %rcx
+ +[a-f0-9]+:   51                      push   %rcx
+ +[a-f0-9]+:   59                      pop    %rcx
+ +[a-f0-9]+:   59                      pop    %rcx
+ +[a-f0-9]+:   8f c1                   pop    %rcx
+ +[a-f0-9]+:   48 0f c9                bswap  %rcx
+ +[a-f0-9]+:   48 0f c9                bswap  %rcx
+ +[a-f0-9]+:   48 0f c9                bswap  %rcx
+ +[a-f0-9]+:   87 ce                   xchg   %ecx,%esi
+ +[a-f0-9]+:   87 f1                   xchg   %esi,%ecx
+ +[a-f0-9]+:   87 f1                   xchg   %esi,%ecx
+ +[a-f0-9]+:   87 ce                   xchg   %ecx,%esi
+ +[a-f0-9]+:   96                      xchg   %eax,%esi
+ +[a-f0-9]+:   87 f0                   xchg   %esi,%eax
+ +[a-f0-9]+:   87 c6                   xchg   %eax,%esi
+ +[a-f0-9]+:   91                      xchg   %eax,%ecx
+ +[a-f0-9]+:   87 c1                   xchg   %eax,%ecx
+ +[a-f0-9]+:   87 c8                   xchg   %ecx,%eax
  +[a-f0-9]+:   d8 c0                   fadd   %st\(0\),%st
  +[a-f0-9]+:   d8 c0                   fadd   %st\(0\),%st
  +[a-f0-9]+:   dc c0                   fadd   %st,%st\(0\)
index 3818df9708e612849a28e73b990e7864c4fefadf..08fac8381c61ca43464561144392fa195e5c7ada 100644 (file)
@@ -135,6 +135,42 @@ _start:
        {store} xor %eax, (%rdi)
        {store} xor (%rdi), %eax
 
+       .irp m, mov, adc, add, and, cmp, or, sbb, sub, test, xor
+       \m      $0x12, %al
+       \m      $0x345, %eax
+       {load} \m $0x12, %al            # bogus for MOV
+       {load} \m $0x345, %eax          # bogus for MOV
+       {store} \m $0x12, %al
+       {store} \m $0x345, %eax
+       .endr
+
+       # There should be no effect of the pseudo-prefixes on any of these.
+       mov     $0x123456789, %rcx
+       {load} mov $0x123456789, %rcx
+       {store} mov $0x123456789, %rcx
+       movabs  $0x12345678, %rcx
+       {load} movabs $0x12345678, %rcx
+       {store} movabs $0x12345678, %rcx
+
+       .irp m, push, pop, bswap
+       \m      %rcx
+       {load} \m %rcx                  # bogus for POP
+       {store} \m %rcx                 # bogus for PUSH
+       .endr
+
+       xchg    %ecx, %esi
+       xchg    %esi, %ecx
+       {load} xchg %ecx, %esi
+       {store} xchg %ecx, %esi
+
+       xchg    %eax, %esi
+       {load} xchg %eax, %esi
+       {store} xchg %eax, %esi
+
+       xchg    %ecx, %eax
+       {load} xchg %ecx, %eax
+       {store} xchg %ecx, %eax
+
        fadd %st, %st
        {load} fadd %st, %st
        {store} fadd %st, %st