diff options
author | Jan Beulich <jbeulich@novell.com> | 2018-09-13 11:05:27 +0200 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2018-09-13 11:05:27 +0200 |
commit | 64c49ab3fb5eea7ba382cf7b0955795ae15e06e5 (patch) | |
tree | 577b53f7e5d384f509680a018cf258c424c78ca4 /gas/config | |
parent | 07d5e9534b11ea9df17eb9d01799000a10c7567f (diff) | |
download | gdb-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.c | 40 |
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; |