aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2019-11-04 15:48:38 +0100
committerJan Beulich <jbeulich@suse.com>2019-11-04 15:48:38 +0100
commit85b80b0f9bf628971b1a051d8b89c0caa932e734 (patch)
tree98fa89b233a03971ed1a24294cb08add784c8714 /gas
parent5103274ffc537711574f9611cb64c51fa9a65546 (diff)
downloadfsf-binutils-gdb-85b80b0f9bf628971b1a051d8b89c0caa932e734.zip
fsf-binutils-gdb-85b80b0f9bf628971b1a051d8b89c0caa932e734.tar.gz
fsf-binutils-gdb-85b80b0f9bf628971b1a051d8b89c0caa932e734.tar.bz2
x86: re-arrange process_operands()
Alter the sequence of conditions evaluated, without affecting the overall result. This is going to help subsequent changes (and as a nice side effect also slightly reduces overall indentation depth). While doing this take the liberty of simplifying the calculation of the operand index of the register operand in ShortForm handling.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog5
-rw-r--r--gas/config/tc-i386.c106
2 files changed, 54 insertions, 57 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index fc99adc..185469f 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,8 @@
+2019-11-04 Jan Beulich <jbeulich@suse.com>
+
+ * config/tc-i386.c (process_operands): Handle ShortForm insns
+ later, splitting out their segment register sub-form.
+
2019-10-31 H.J. Lu <hongjiu.lu@intel.com>
* testsuite/gas/i386/general.s: Add .code16gcc fldenv tests.
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index f26b17c..5866bd6 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -7004,63 +7004,7 @@ duplicate:
i.reg_operands++;
}
- if (i.tm.opcode_modifier.shortform)
- {
- if (i.types[0].bitfield.sreg)
- {
- if (flag_code != CODE_64BIT
- ? i.tm.base_opcode == POP_SEG_SHORT
- && i.op[0].regs->reg_num == 1
- : (i.tm.base_opcode | 1) == POP_SEG386_SHORT
- && i.op[0].regs->reg_num < 4)
- {
- as_bad (_("you can't `%s %s%s'"),
- i.tm.name, register_prefix, i.op[0].regs->reg_name);
- return 0;
- }
- if ( i.op[0].regs->reg_num > 3 && i.tm.opcode_length == 1 )
- {
- i.tm.base_opcode ^= POP_SEG_SHORT ^ POP_SEG386_SHORT;
- i.tm.opcode_length = 2;
- }
- i.tm.base_opcode |= (i.op[0].regs->reg_num << 3);
- }
- else
- {
- /* The register or float register operand is in operand
- 0 or 1. */
- unsigned int op;
-
- if ((i.types[0].bitfield.reg && i.types[0].bitfield.tbyte)
- || operand_type_check (i.types[0], reg))
- op = 0;
- else
- op = 1;
- /* Register goes in low 3 bits of opcode. */
- i.tm.base_opcode |= i.op[op].regs->reg_num;
- if ((i.op[op].regs->reg_flags & RegRex) != 0)
- i.rex |= REX_B;
- if (!quiet_warnings && i.tm.opcode_modifier.ugh)
- {
- /* Warn about some common errors, but press on regardless.
- The first case can be generated by gcc (<= 2.8.1). */
- if (i.operands == 2)
- {
- /* Reversed arguments on faddp, fsubp, etc. */
- as_warn (_("translating to `%s %s%s,%s%s'"), i.tm.name,
- register_prefix, i.op[!intel_syntax].regs->reg_name,
- register_prefix, i.op[intel_syntax].regs->reg_name);
- }
- else
- {
- /* Extraneous `l' suffix on fp insn. */
- as_warn (_("translating to `%s %s%s'"), i.tm.name,
- register_prefix, i.op[0].regs->reg_name);
- }
- }
- }
- }
- else if (i.tm.opcode_modifier.modrm)
+ if (i.tm.opcode_modifier.modrm)
{
/* The opcode is completed (modulo i.tm.extension_opcode which
must be put into the modrm byte). Now, we make the modrm and
@@ -7068,6 +7012,25 @@ duplicate:
default_seg = build_modrm_byte ();
}
+ else if (i.types[0].bitfield.sreg)
+ {
+ if (flag_code != CODE_64BIT
+ ? i.tm.base_opcode == POP_SEG_SHORT
+ && i.op[0].regs->reg_num == 1
+ : (i.tm.base_opcode | 1) == POP_SEG386_SHORT
+ && i.op[0].regs->reg_num < 4)
+ {
+ as_bad (_("you can't `%s %s%s'"),
+ i.tm.name, register_prefix, i.op[0].regs->reg_name);
+ return 0;
+ }
+ if ( i.op[0].regs->reg_num > 3 && i.tm.opcode_length == 1 )
+ {
+ i.tm.base_opcode ^= POP_SEG_SHORT ^ POP_SEG386_SHORT;
+ i.tm.opcode_length = 2;
+ }
+ i.tm.base_opcode |= (i.op[0].regs->reg_num << 3);
+ }
else if ((i.tm.base_opcode & ~0x3) == MOV_AX_DISP32)
{
default_seg = &ds;
@@ -7078,6 +7041,35 @@ duplicate:
on one of their operands, the default segment is ds. */
default_seg = &ds;
}
+ else if (i.tm.opcode_modifier.shortform)
+ {
+ /* The register or float register operand is in operand
+ 0 or 1. */
+ unsigned int op = !i.tm.operand_types[0].bitfield.reg;
+
+ /* Register goes in low 3 bits of opcode. */
+ i.tm.base_opcode |= i.op[op].regs->reg_num;
+ if ((i.op[op].regs->reg_flags & RegRex) != 0)
+ i.rex |= REX_B;
+ if (!quiet_warnings && i.tm.opcode_modifier.ugh)
+ {
+ /* Warn about some common errors, but press on regardless.
+ The first case can be generated by gcc (<= 2.8.1). */
+ if (i.operands == 2)
+ {
+ /* Reversed arguments on faddp, fsubp, etc. */
+ as_warn (_("translating to `%s %s%s,%s%s'"), i.tm.name,
+ register_prefix, i.op[!intel_syntax].regs->reg_name,
+ register_prefix, i.op[intel_syntax].regs->reg_name);
+ }
+ else
+ {
+ /* Extraneous `l' suffix on fp insn. */
+ as_warn (_("translating to `%s %s%s'"), i.tm.name,
+ register_prefix, i.op[0].regs->reg_name);
+ }
+ }
+ }
if (i.tm.base_opcode == 0x8d /* lea */
&& i.seg[0]