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,20 +6883,41 @@ 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 (t->base_opcode == 0x90
&& t->opcode_space == SPACE_BASE)
{
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;
/* 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
&& t->mnem_off != MN_movabs)
@ -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. */

View 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\)

View 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

View 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\)

View 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