diff options
author | Jan Beulich <jbeulich@suse.com> | 2022-07-06 15:40:04 +0200 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2022-07-06 15:40:04 +0200 |
commit | 8bd915b770e12eff67f6218f2d727069d04d5752 (patch) | |
tree | 33f15463f72a7894f528757b209b85aab3ffec5a /gas | |
parent | 3d0738af2a6dac3c729126f2ceb3af6529da7348 (diff) | |
download | gdb-8bd915b770e12eff67f6218f2d727069d04d5752.zip gdb-8bd915b770e12eff67f6218f2d727069d04d5752.tar.gz gdb-8bd915b770e12eff67f6218f2d727069d04d5752.tar.bz2 |
x86: make D attribute usable for XOP and FMA4 insns
This once again allows to reduce redundancy in (and size of) the opcode
table.
Don't go as far as also making D work on the two 5-operand XOP insns:
This would significantly complicate the code, as there the first
(immediate) operand would need special treatment in several places.
Note that the .s suffix isn't being enabled to have any effect, for
being deprecated. Whereas neither {load} nor {store} pseudo prefixes
make sense here, as the respective operands are inputs (loads) only
anyway, regardless of order. Hence there is (as before) no way for the
programmer to request the alternative encoding to be used for register-
only insns.
Note further that it is always the first original template which is
retained (and altered), to make sure the same encoding as before is
used for register-only insns. This has the slightly odd (but pre-
existing) effect of XOP register-only insns having XOP.W clear, but FMA4
ones having VEX.W set.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/config/tc-i386.c | 42 |
1 files changed, 35 insertions, 7 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 31b10d2..9cd33a9 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -2087,12 +2087,18 @@ operand_size_match (const insn_template *t) } /* Check reverse. */ - gas_assert (i.operands >= 2 && i.operands <= 3); + gas_assert ((i.operands >= 2 && i.operands <= 3) + || t->opcode_modifier.vexsources); for (j = 0; j < i.operands; j++) { unsigned int given = i.operands - j - 1; + /* For 4- and 5-operand insns VEX.W controls just the first two + register operands. */ + if (t->opcode_modifier.vexsources) + given = j < 2 ? 1 - j : j; + if (t->operand_types[j].bitfield.class == Reg && !match_operand_size (t, j, given)) goto mismatch; @@ -6722,18 +6728,19 @@ match_template (char mnem_suffix) if (!(size_match & MATCH_REVERSE)) continue; /* Try reversing direction of operands. */ - overlap0 = operand_type_and (i.types[0], operand_types[i.operands - 1]); - overlap1 = operand_type_and (i.types[i.operands - 1], operand_types[0]); + j = t->opcode_modifier.vexsources ? 1 : i.operands - 1; + overlap0 = operand_type_and (i.types[0], operand_types[j]); + overlap1 = operand_type_and (i.types[j], operand_types[0]); overlap2 = operand_type_and (i.types[1], operand_types[1]); gas_assert (t->operands != 3 || !check_register); if (!operand_type_match (overlap0, i.types[0]) - || !operand_type_match (overlap1, i.types[i.operands - 1]) + || !operand_type_match (overlap1, i.types[j]) || (t->operands == 3 && !operand_type_match (overlap2, i.types[1])) || (check_register && !operand_type_register_match (i.types[0], - operand_types[i.operands - 1], - i.types[i.operands - 1], + operand_types[j], + i.types[j], operand_types[0]))) { /* Does not match either direction. */ @@ -6745,6 +6752,11 @@ match_template (char mnem_suffix) found_reverse_match = 0; else if (operand_types[0].bitfield.tbyte) found_reverse_match = Opcode_FloatD; + else if (t->opcode_modifier.vexsources) + { + found_reverse_match = Opcode_VexW; + goto check_operands_345; + } else if (operand_types[0].bitfield.xmmword || operand_types[i.operands - 1].bitfield.xmmword || operand_types[0].bitfield.class == RegMMX @@ -6760,6 +6772,7 @@ match_template (char mnem_suffix) else { /* Found a forward 2 operand match here. */ + check_operands_345: switch (t->operands) { case 5: @@ -6928,8 +6941,12 @@ match_template (char mnem_suffix) i.tm.operand_types[addr_prefix_disp] = operand_types[addr_prefix_disp]; - if (found_reverse_match) + switch (found_reverse_match) { + case 0: + break; + + default: /* If we found a reverse match we must alter the opcode direction bit and clear/flip the regmem modifier one. found_reverse_match holds bits to change (different for int & float insns). */ @@ -6946,6 +6963,17 @@ match_template (char mnem_suffix) = i.tm.opcode_modifier.modrm && i.tm.opcode_modifier.d && i.tm.operands > 2U - i.tm.opcode_modifier.sse2avx && !i.tm.opcode_modifier.regmem; + break; + + case Opcode_VexW: + /* Only the first two register operands need reversing, alongside + flipping VEX.W. */ + i.tm.opcode_modifier.vexw ^= VEXW0 ^ VEXW1; + + j = i.tm.operand_types[0].bitfield.imm8; + i.tm.operand_types[j] = operand_types[j + 1]; + i.tm.operand_types[j + 1] = operand_types[j]; + break; } return t; |