aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2018-09-13 11:05:27 +0200
committerJan Beulich <jbeulich@suse.com>2018-09-13 11:05:27 +0200
commit64c49ab3fb5eea7ba382cf7b0955795ae15e06e5 (patch)
tree577b53f7e5d384f509680a018cf258c424c78ca4 /gas/config
parent07d5e9534b11ea9df17eb9d01799000a10c7567f (diff)
downloadgdb-64c49ab3fb5eea7ba382cf7b0955795ae15e06e5.zip
gdb-64c49ab3fb5eea7ba382cf7b0955795ae15e06e5.tar.gz
gdb-64c49ab3fb5eea7ba382cf7b0955795ae15e06e5.tar.bz2
x86: improve operand reversal
In quite a few cases the .s suffix or {load} / {store} prefixes did not work as intended, or produced errors when they're supposed to be ignored when it is not possible to carry out the request. The change here re-purposes(?) the .s suffix to no longer mean "store" (if that's what 's' did stand for), since the forms used in the base templates are not consistently loads (and we unlikely want to change that). The pseudo prefixes will now fulfill what their names say, i.e. {load} now only ever produces a load form encoding (if available) while {store} only ever produces a store form one (again if available). This requires minimal test suite adjustments, while the majority of the changes there are simply additions.
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/tc-i386.c40
1 files changed, 33 insertions, 7 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index ccae048..b3c7334 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -376,7 +376,8 @@ struct _i386_insn
{
dir_encoding_default = 0,
dir_encoding_load,
- dir_encoding_store
+ dir_encoding_store,
+ dir_encoding_swap
} dir_encoding;
/* Prefer 8bit or 32bit displacement in encoding. */
@@ -4520,7 +4521,7 @@ parse_insn (char *line, char *mnemonic)
Check if we should swap operand or force 32bit displacement in
encoding. */
if (mnem_p - 2 == dot_p && dot_p[1] == 's')
- i.dir_encoding = dir_encoding_store;
+ i.dir_encoding = dir_encoding_swap;
else if (mnem_p - 3 == dot_p
&& dot_p[1] == 'd'
&& dot_p[2] == '8')
@@ -5700,15 +5701,40 @@ match_template (char mnem_suffix)
continue;
if (!(size_match & MATCH_STRAIGHT))
goto check_reverse;
- /* If we want store form, we reverse direction of operands. */
- if (i.dir_encoding == dir_encoding_store
- && t->opcode_modifier.d)
- goto check_reverse;
+ /* Reverse direction of operands if swapping is possible in the first
+ place (operands need to be symmetric) and
+ - the load form is requested, and the template is a store form,
+ - the store form is requested, and the template is a load form,
+ - the non-default (swapped) form is requested. */
+ overlap1 = operand_type_and (operand_types[0], operand_types[1]);
+ if (t->opcode_modifier.d && i.reg_operands == 2
+ && !operand_type_all_zero (&overlap1))
+ switch (i.dir_encoding)
+ {
+ case dir_encoding_load:
+ if (operand_type_check (operand_types[i.operands - 1], anymem)
+ || operand_types[i.operands - 1].bitfield.regmem)
+ goto check_reverse;
+ break;
+
+ case dir_encoding_store:
+ if (!operand_type_check (operand_types[i.operands - 1], anymem)
+ && !operand_types[i.operands - 1].bitfield.regmem)
+ goto check_reverse;
+ break;
+
+ case dir_encoding_swap:
+ goto check_reverse;
+
+ case dir_encoding_default:
+ break;
+ }
/* Fall through. */
case 3:
/* If we want store form, we skip the current load. */
- if (i.dir_encoding == dir_encoding_store
+ if ((i.dir_encoding == dir_encoding_store
+ || i.dir_encoding == dir_encoding_swap)
&& i.mem_operands == 0
&& t->opcode_modifier.load)
continue;