x86: allow to request ModR/M encoding

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.
This commit is contained in:
Jan Beulich
2023-02-24 14:00:11 +01:00
parent cafa5ef72e
commit ae9a0a51e8
5 changed files with 296 additions and 9 deletions

View File

@ -6883,19 +6883,40 @@ match_template (char mnem_suffix)
case 1: case 1:
if (!operand_type_match (overlap0, i.types[0])) if (!operand_type_match (overlap0, i.types[0]))
continue; 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; break;
case 2: case 2:
/* xchg %eax, %eax is a special case. It is an alias for nop /* 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 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 mode, we can't use 0x90 for xchg %eax, %eax since it should
zero-extend %eax to %rax. */ zero-extend %eax to %rax. */
if (flag_code == CODE_64BIT if (t->base_opcode == 0x90
&& t->base_opcode == 0x90 && t->opcode_space == SPACE_BASE)
&& t->opcode_space == SPACE_BASE {
&& i.types[0].bitfield.instance == Accum if (flag_code == CODE_64BIT
&& i.types[0].bitfield.dword && i.types[0].bitfield.instance == Accum
&& i.types[1].bitfield.instance == Accum) && i.types[0].bitfield.dword
continue; && 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 if (t->base_opcode == MOV_AX_DISP32
&& t->opcode_space == SPACE_BASE && t->opcode_space == SPACE_BASE
@ -6909,6 +6930,38 @@ match_template (char mnem_suffix)
match the accumulator-only encoding of mov. */ match the accumulator-only encoding of mov. */
if (i.hle_prefix) if (i.hle_prefix)
continue; 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. */ /* Fall through. */

View File

@ -54,10 +54,10 @@ Disassembly of section .text:
+[a-f0-9]+: 31 c8 xor %ecx,%eax +[a-f0-9]+: 31 c8 xor %ecx,%eax
+[a-f0-9]+: 33 c1 xor %ecx,%eax +[a-f0-9]+: 33 c1 xor %ecx,%eax
+[a-f0-9]+: 31 c8 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]+: a3 78 56 34 12 mov %eax,0x12345678
+[a-f0-9]+: a1 78 56 34 12 mov 0x12345678,%eax +[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]+: 89 07 mov %eax,\(%edi\)
+[a-f0-9]+: 8b 07 mov \(%edi\),%eax +[a-f0-9]+: 8b 07 mov \(%edi\),%eax
+[a-f0-9]+: 89 07 mov %eax,\(%edi\) +[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]+: 33 07 xor \(%edi\),%eax
+[a-f0-9]+: 31 07 xor %eax,\(%edi\) +[a-f0-9]+: 31 07 xor %eax,\(%edi\)
+[a-f0-9]+: 33 07 xor \(%edi\),%eax +[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]+: d8 c0 fadd %st\(0\),%st +[a-f0-9]+: d8 c0 fadd %st\(0\),%st
+[a-f0-9]+: dc c0 fadd %st,%st\(0\) +[a-f0-9]+: dc c0 fadd %st,%st\(0\)

View File

@ -124,6 +124,34 @@ _start:
{store} xor %eax, (%edi) {store} xor %eax, (%edi)
{store} xor (%edi), %eax {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 fadd %st, %st
{load} fadd %st, %st {load} fadd %st, %st
{store} fadd %st, %st {store} fadd %st, %st

View File

@ -137,6 +137,91 @@ Disassembly of section .text:
+[a-f0-9]+: 33 07 xor \(%rdi\),%eax +[a-f0-9]+: 33 07 xor \(%rdi\),%eax
+[a-f0-9]+: 31 07 xor %eax,\(%rdi\) +[a-f0-9]+: 31 07 xor %eax,\(%rdi\)
+[a-f0-9]+: 33 07 xor \(%rdi\),%eax +[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]+: d8 c0 fadd %st\(0\),%st +[a-f0-9]+: d8 c0 fadd %st\(0\),%st
+[a-f0-9]+: dc c0 fadd %st,%st\(0\) +[a-f0-9]+: dc c0 fadd %st,%st\(0\)

View File

@ -135,6 +135,42 @@ _start:
{store} xor %eax, (%rdi) {store} xor %eax, (%rdi)
{store} xor (%rdi), %eax {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 fadd %st, %st
{load} fadd %st, %st {load} fadd %st, %st
{store} fadd %st, %st {store} fadd %st, %st