From f7377a91b5183977d0702280d4aad90e1829e154 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 31 Mar 2023 08:21:30 +0200 Subject: [PATCH] x86: handle EVEX Disp8 for .insn In particular the scaling factor cannot always be determined from pre- existing operand attributes. Introduce a new {:d} vector operand syntax extension, restricted to .insn only, to allow specifying this in (at least) otherwise ambiguous cases. --- gas/config/tc-i386.c | 98 +++++++++++++++++++++++++++++++- gas/testsuite/gas/i386/insn-32.d | 10 ++++ gas/testsuite/gas/i386/insn-32.s | 16 ++++++ gas/testsuite/gas/i386/insn-64.d | 10 ++++ gas/testsuite/gas/i386/insn-64.s | 16 ++++++ 5 files changed, 149 insertions(+), 1 deletion(-) diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 748cf1cfd17..fe59bf3b540 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -10931,8 +10931,11 @@ s_insn (int dummy ATTRIBUTE_UNUSED) if (*line == ',') { i386_operand_type combined; + expressionS *disp_exp = NULL; bool changed; + i.memshift = -1; + ptr = parse_operands (line + 1, &i386_mnemonics[MN__insn]); this_operand = -1; if (!ptr) @@ -11078,12 +11081,40 @@ s_insn (int dummy ATTRIBUTE_UNUSED) /* Establish operand size encoding. */ operand_type_set (&combined, 0); + for (j = i.imm_operands; j < i.operands; ++j) { i.types[j].bitfield.instance = InstanceNone; if (operand_type_check (i.types[j], disp)) - i.types[j].bitfield.baseindex = 1; + { + i.types[j].bitfield.baseindex = 1; + disp_exp = i.op[j].disps; + } + + if (evex && i.types[j].bitfield.baseindex) + { + unsigned int n = i.memshift; + + if (i.types[j].bitfield.byte) + n = 0; + else if (i.types[j].bitfield.word) + n = 1; + else if (i.types[j].bitfield.dword) + n = 2; + else if (i.types[j].bitfield.qword) + n = 3; + else if (i.types[j].bitfield.xmmword) + n = 4; + else if (i.types[j].bitfield.ymmword) + n = 5; + else if (i.types[j].bitfield.zmmword) + n = 6; + + if (i.memshift < 32 && n != i.memshift) + as_warn ("conflicting memory operand size specifiers"); + i.memshift = n; + } if ((i.broadcast.type || i.broadcast.bytes) && j == i.broadcast.operand) @@ -11093,6 +11124,16 @@ s_insn (int dummy ATTRIBUTE_UNUSED) combined.bitfield.class = ClassNone; } + switch ((i.broadcast.type ? i.broadcast.type : 1) + << (i.memshift < 32 ? i.memshift : 0)) + { + case 64: combined.bitfield.zmmword = 1; break; + case 32: combined.bitfield.ymmword = 1; break; + case 16: combined.bitfield.xmmword = 1; break; + case 8: combined.bitfield.qword = 1; break; + case 4: combined.bitfield.dword = 1; break; + } + if (i.vec_encoding == vex_encoding_default) { if (flag_code == CODE_64BIT && combined.bitfield.qword) @@ -11138,8 +11179,40 @@ s_insn (int dummy ATTRIBUTE_UNUSED) else if (combined.bitfield.xmmword) i.tm.opcode_modifier.evex = EVEX128; } + + if (i.memshift >= 32) + { + unsigned int n = 0; + + switch (i.tm.opcode_modifier.evex) + { + case EVEX512: n = 64; break; + case EVEX256: n = 32; break; + case EVEX128: n = 16; break; + } + + if (i.broadcast.type) + n /= i.broadcast.type; + + if (n > 0) + for (i.memshift = 0; !(n & 1); n >>= 1) + ++i.memshift; + else if (disp_exp != NULL && disp_exp->X_op == O_constant + && disp_exp->X_add_number != 0 + && i.disp_encoding != disp_encoding_32bit) + { + if (!quiet_warnings) + as_warn ("cannot determine memory operand size"); + i.disp_encoding = disp_encoding_32bit; + } + } } + if (i.memshift >= 32) + i.memshift = 0; + else if (!evex) + i.vec_encoding = vex_encoding_error; + if (i.disp_operands && !optimize_disp (&i.tm)) goto done; @@ -11314,6 +11387,29 @@ check_VecOperations (char *op_string) i.broadcast.type = bcst_type; i.broadcast.operand = this_operand; + + /* For .insn a data size specifier may be appended. */ + if (dot_insn () && *op_string == ':') + goto dot_insn_modifier; + } + /* Check .insn special cases. */ + else if (dot_insn () && *op_string == ':') + { + dot_insn_modifier: + if (op_string[1] == 'd') + { + unsigned long n; + + if (i.memshift < 32) + goto duplicated_vec_op; + + n = strtoul (op_string + 2, &end_op, 0); + if (n) + for (i.memshift = 0; !(n & 1); n >>= 1) + ++i.memshift; + if (i.memshift < 32 && n == 1) + op_string = end_op; + } } /* Check masking operation. */ else if ((mask = parse_register (op_string, &end_op)) != NULL) diff --git a/gas/testsuite/gas/i386/insn-32.d b/gas/testsuite/gas/i386/insn-32.d index fdd9ae75867..d898a71e437 100644 --- a/gas/testsuite/gas/i386/insn-32.d +++ b/gas/testsuite/gas/i386/insn-32.d @@ -23,6 +23,7 @@ Disassembly of section .text: [ ]*[a-f0-9]+: c5 f1 58 d0[ ]+vaddpd %xmm0,%xmm1,%xmm2 [ ]*[a-f0-9]+: c5 f5 58 d0[ ]+vaddpd %ymm0,%ymm1,%ymm2 [ ]*[a-f0-9]+: c5 f2 58 d0[ ]+vaddss %xmm0,%xmm1,%xmm2 +[ ]*[a-f0-9]+: 62 f1 76 08 58 50 01[ ]+\{evex\} vaddss (0x)?4\(%eax\),%xmm1,%xmm2 [ ]*[a-f0-9]+: c4 e3 69 68 19 00[ ]+vfmaddps %xmm0,\(%ecx\),%xmm2,%xmm3 [ ]*[a-f0-9]+: c4 e3 e9 68 19 00[ ]+vfmaddps \(%ecx\),%xmm0,%xmm2,%xmm3 [ ]*[a-f0-9]+: c4 e3 e9 68 18 10[ ]+vfmaddps \(%eax\),%xmm1,%xmm2,%xmm3 @@ -31,4 +32,13 @@ Disassembly of section .text: [ ]*[a-f0-9]+: 62 f1 74 18 58 d0[ ]+vaddps \{rn-sae\},%zmm0,%zmm1,%zmm2 [ ]*[a-f0-9]+: c4 e2 79 92 1c 48[ ]+vgatherdps %xmm0,\(%eax,%xmm1,2\),%xmm3 [ ]*[a-f0-9]+: 62 f2 fd 0c 93 1c 48[ ]+vgatherqpd \(%eax,%xmm1,2\),%xmm3\{%k4\} +[ ]*[a-f0-9]+: 62 f2 7d 28 88 48 01[ ]+vexpandps (0x)?4\(%eax\),%ymm1 +[ ]*[a-f0-9]+: 62 f5 fd 48 5a 40 01[ ]+vcvtpd2phz 0x40\(%eax\),%xmm0 +[ ]*[a-f0-9]+: 62 f5 fd 48 5a 40 01[ ]+vcvtpd2phz 0x40\(%eax\),%xmm0 +[ ]*[a-f0-9]+: 62 f5 fd 48 5a 40 01[ ]+vcvtpd2phz 0x40\(%eax\),%xmm0 +[ ]*[a-f0-9]+: 62 f5 fd 58 5a 40 01[ ]+vcvtpd2ph (0x)?8\(%eax\)\{1to8\},%xmm0 +[ ]*[a-f0-9]+: 62 f5 fd 58 5a 40 01[ ]+vcvtpd2ph (0x)?8\(%eax\)\{1to8\},%xmm0 +[ ]*[a-f0-9]+: 62 f5 fd 58 5a 40 01[ ]+vcvtpd2ph (0x)?8\(%eax\)\{1to8\},%xmm0 +[ ]*[a-f0-9]+: 62 f5 7c 48 5a 40 01[ ]+vcvtph2pd 0x10\(%eax\),%zmm0 +[ ]*[a-f0-9]+: 62 f5 7c 58 5a 40 01[ ]+vcvtph2pd (0x)?2\(%eax\)\{1to8\},%zmm0 #pass diff --git a/gas/testsuite/gas/i386/insn-32.s b/gas/testsuite/gas/i386/insn-32.s index 73491e49abe..d54ad3bb3c8 100644 --- a/gas/testsuite/gas/i386/insn-32.s +++ b/gas/testsuite/gas/i386/insn-32.s @@ -36,6 +36,7 @@ insn: # vaddss .insn VEX.LIG.F3.0F 0x58, %xmm0, %xmm1, %xmm2 + .insn EVEX.LIG.F3.0F.W0 0x58, 4(%eax){:d4}, %xmm1, %xmm2 # vfmaddps .insn VEX.66.0F3A.W0 0x68, %xmm0, (%ecx), %xmm2, %xmm3 @@ -52,3 +53,18 @@ insn: # vgather... .insn VEX.66.0f38.W0 0x92, %xmm0, (%eax, %xmm1, 2), %xmm3 .insn EVEX.66.0f38.W1 0x93, (%eax, %xmm1, 2), %xmm3{%k4} + + # vexpandps + .insn EVEX.66.0F38.W0 0x88, 4(%eax){:d4}, %ymm1 + + # vcvtpd2phz + .insn EVEX.512.66.M5.W1 0x5a, 64(%eax), %xmm0 + .insn EVEX.66.M5.W1 0x5a, 64(%eax), %zmm0 + .insn EVEX.66.M5.W1 0x5a, 64(%eax){:d64}, %xmm0 + .insn EVEX.512.66.M5.W1 0x5a, 8(%eax){1to8}, %xmm0 + .insn EVEX.66.M5.W1 0x5a, 8(%eax){1to8}, %zmm0 + .insn EVEX.66.M5.W1 0x5a, 8(%eax){1to8:d8}, %xmm0 + + # vcvtph2pd + .insn EVEX.M5.W0 0x5a, 16(%eax){:d16}, %zmm0 + .insn EVEX.M5.W0 0x5a, 2(%eax){1to8:d2}, %zmm0 diff --git a/gas/testsuite/gas/i386/insn-64.d b/gas/testsuite/gas/i386/insn-64.d index 229960f939a..0f1ec882a51 100644 --- a/gas/testsuite/gas/i386/insn-64.d +++ b/gas/testsuite/gas/i386/insn-64.d @@ -25,6 +25,7 @@ Disassembly of section .text: [ ]*[a-f0-9]+: c4 c1 71 58 d0[ ]+vaddpd %xmm8,%xmm1,%xmm2 [ ]*[a-f0-9]+: c5 b5 58 d0[ ]+vaddpd %ymm0,%ymm9,%ymm2 [ ]*[a-f0-9]+: c5 72 58 d0[ ]+vaddss %xmm0,%xmm1,%xmm10 +[ ]*[a-f0-9]+: 62 f1 76 08 58 50 01[ ]+\{evex\} vaddss (0x)?4\(%rax\),%xmm1,%xmm2 [ ]*[a-f0-9]+: c4 e3 69 68 19 80[ ]+vfmaddps %xmm8,\(%rcx\),%xmm2,%xmm3 [ ]*[a-f0-9]+: 67 c4 e3 e9 68 19 00[ ]+vfmaddps \(%ecx\),%xmm0,%xmm2,%xmm3 [ ]*[a-f0-9]+: c4 c3 e9 68 18 10[ ]+vfmaddps \(%r8\),%xmm1,%xmm2,%xmm3 @@ -42,4 +43,13 @@ Disassembly of section .text: [ ]*[a-f0-9]+: 62 f2 fd 04 93 1c 48[ ]+vgatherqpd \(%rax,%xmm17,2\),%xmm3\{%k4\} [ ]*[a-f0-9]+: 62 72 fd 0c 93 1c 48[ ]+vgatherqpd \(%rax,%xmm1,2\),%xmm11\{%k4\} [ ]*[a-f0-9]+: 62 e2 fd 0c 93 1c 48[ ]+vgatherqpd \(%rax,%xmm1,2\),%xmm19\{%k4\} +[ ]*[a-f0-9]+: 62 f2 7d 28 88 48 01[ ]+vexpandps (0x)?4\(%rax\),%ymm1 +[ ]*[a-f0-9]+: 62 f5 fd 48 5a 40 01[ ]+vcvtpd2phz 0x40\(%rax\),%xmm0 +[ ]*[a-f0-9]+: 62 f5 fd 48 5a 40 01[ ]+vcvtpd2phz 0x40\(%rax\),%xmm0 +[ ]*[a-f0-9]+: 62 f5 fd 48 5a 40 01[ ]+vcvtpd2phz 0x40\(%rax\),%xmm0 +[ ]*[a-f0-9]+: 62 f5 fd 58 5a 40 01[ ]+vcvtpd2ph (0x)?8\(%rax\)\{1to8\},%xmm0 +[ ]*[a-f0-9]+: 62 f5 fd 58 5a 40 01[ ]+vcvtpd2ph (0x)?8\(%rax\)\{1to8\},%xmm0 +[ ]*[a-f0-9]+: 62 f5 fd 58 5a 40 01[ ]+vcvtpd2ph (0x)?8\(%rax\)\{1to8\},%xmm0 +[ ]*[a-f0-9]+: 62 f5 7c 48 5a 40 01[ ]+vcvtph2pd 0x10\(%rax\),%zmm0 +[ ]*[a-f0-9]+: 62 f5 7c 58 5a 40 01[ ]+vcvtph2pd (0x)?2\(%rax\)\{1to8\},%zmm0 #pass diff --git a/gas/testsuite/gas/i386/insn-64.s b/gas/testsuite/gas/i386/insn-64.s index b8f5ede652d..9dfdd3a622b 100644 --- a/gas/testsuite/gas/i386/insn-64.s +++ b/gas/testsuite/gas/i386/insn-64.s @@ -38,6 +38,7 @@ insn: # vaddss .insn VEX.LIG.F3.0F 0x58, %xmm0, %xmm1, %xmm10 + .insn EVEX.LIG.F3.0F.W0 0x58, 4(%rax){:d4}, %xmm1, %xmm2 # vfmaddps .insn VEX.66.0F3A.W0 0x68, %xmm8, (%rcx), %xmm2, %xmm3 @@ -63,3 +64,18 @@ insn: .insn EVEX.66.0f38.W1 0x93, (%rax, %xmm17, 2), %xmm3{%k4} .insn EVEX.66.0f38.W1 0x93, (%rax, %xmm1, 2), %xmm11{%k4} .insn EVEX.66.0f38.W1 0x93, (%rax, %xmm1, 2), %xmm19{%k4} + + # vexpandps + .insn EVEX.66.0F38.W0 0x88, 4(%rax){:d4}, %ymm1 + + # vcvtpd2phz + .insn EVEX.512.66.M5.W1 0x5a, 64(%rax), %xmm0 + .insn EVEX.66.M5.W1 0x5a, 64(%rax), %zmm0 + .insn EVEX.66.M5.W1 0x5a, 64(%rax){:d64}, %xmm0 + .insn EVEX.512.66.M5.W1 0x5a, 8(%rax){1to8}, %xmm0 + .insn EVEX.66.M5.W1 0x5a, 8(%rax){1to8}, %zmm0 + .insn EVEX.66.M5.W1 0x5a, 8(%rax){1to8:d8}, %xmm0 + + # vcvtph2pd + .insn EVEX.M5.W0 0x5a, 16(%rax){:d16}, %zmm0 + .insn EVEX.M5.W0 0x5a, 2(%rax){1to8:d2}, %zmm0 -- 2.30.2