aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2021-03-24 08:33:33 +0100
committerJan Beulich <jbeulich@suse.com>2021-03-24 08:33:33 +0100
commit9a182d0461cc34912da51f445a242b392389edd6 (patch)
tree23378054b7425ee896162d67940c240b42064d61 /gas
parent3564871692e324301c2950679aa0fbb04c6d12dc (diff)
downloadgdb-9a182d0461cc34912da51f445a242b392389edd6.zip
gdb-9a182d0461cc34912da51f445a242b392389edd6.tar.gz
gdb-9a182d0461cc34912da51f445a242b392389edd6.tar.bz2
x86: derive opcode length from opcode value
In the majority of cases we can easily determine the length from the encoding, irrespective of whether a prefix is specified there as well. We further don't even need to record the value in the table entries, as it's easy enough to determine it (without any guesswork, unless an insn with major opcode 00 appeared that requires a 2nd opcode byte to be specified explicitly) when installing the chosen template for further processing. Should an encoding appear which - has a major opcode byte of 66, F3, or F2, - requires a 2nd opcode byte to be specified explicitly, - doesn't have a mandatory prefix we'd need to convert all templates presently encoding a mandatory prefix this way to the Prefix_0X<nn> model to eliminate the respective guessing i386-gen does.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog12
-rw-r--r--gas/config/tc-i386.c50
2 files changed, 46 insertions, 16 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 72d48d7..49e69dc 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,5 +1,17 @@
2021-03-24 Jan Beulich <jbeulich@suse.com>
+ * config/tc-i386.c (struct _i386_insn): New field
+ opcode_length.
+ (md_begin): Drop assertion.
+ (install_template): New.
+ (build_vex_prefix): Call install_template.
+ (match_template): Likewise.
+ (process_operands): Use new opcode_length field.
+ (output_jump): Likewise.
+ (output_insn): Likewise. Adjust psedo prefix check.
+
+2021-03-24 Jan Beulich <jbeulich@suse.com>
+
* config/tc-i386.c (md_begin): Add assertion.
(build_vex_prefix): Drop implied prefix calculation.
(build_evex_prefix): Likewise.
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 9773b02..654f435 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -314,6 +314,9 @@ struct _i386_insn
or qword, if given. */
char suffix;
+ /* OPCODE_LENGTH holds the number of base opcode bytes. */
+ unsigned char opcode_length;
+
/* OPERANDS gives the number of given operands. */
unsigned int operands;
@@ -3065,8 +3068,6 @@ md_begin (void)
while (1)
{
- gas_assert (optab->opcode_length == 4
- || !(optab->base_opcode >> (8 * optab->opcode_length)));
++optab;
if (optab->name == NULL
|| strcmp (optab->name, (optab - 1)->name) != 0)
@@ -3584,6 +3585,22 @@ intel_float_operand (const char *mnemonic)
return 1;
}
+static INLINE void
+install_template (const insn_template *t)
+{
+ unsigned int l;
+
+ i.tm = *t;
+
+ /* Note that for pseudo prefixes this produces a length of 1. But for them
+ the length isn't interesting at all. */
+ for (l = 1; l < 4; ++l)
+ if (!(t->base_opcode >> (8 * l)))
+ break;
+
+ i.opcode_length = l;
+}
+
/* Build the VEX prefix. */
static void
@@ -3636,7 +3653,7 @@ build_vex_prefix (const insn_template *t)
i.tm.base_opcode ^= (i.tm.base_opcode & 0xee) != 0x6e
? Opcode_SIMD_FloatD : Opcode_SIMD_IntD;
else /* Use the next insn. */
- i.tm = t[1];
+ install_template (&t[1]);
}
/* Use 2-byte VEX prefix by swapping commutative source operands if there
@@ -6665,7 +6682,7 @@ match_template (char mnem_suffix)
}
/* Copy the template we found. */
- i.tm = *t;
+ install_template (t);
if (addr_prefix_disp != -1)
i.tm.operand_types[addr_prefix_disp]
@@ -7661,10 +7678,10 @@ process_operands (void)
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 )
+ if ( i.op[0].regs->reg_num > 3 && i.opcode_length == 1 )
{
i.tm.base_opcode ^= POP_SEG_SHORT ^ POP_SEG386_SHORT;
- i.tm.opcode_length = 2;
+ i.opcode_length = 2;
}
i.tm.base_opcode |= (i.op[0].regs->reg_num << 3);
}
@@ -8657,12 +8674,12 @@ output_jump (void)
if (now_seg == absolute_section)
{
- abs_section_offset += i.tm.opcode_length + size;
+ abs_section_offset += i.opcode_length + size;
return;
}
- p = frag_more (i.tm.opcode_length + size);
- switch (i.tm.opcode_length)
+ p = frag_more (i.opcode_length + size);
+ switch (i.opcode_length)
{
case 2:
*p++ = i.tm.base_opcode >> 8;
@@ -9385,14 +9402,15 @@ output_insn (void)
add_prefix (0xf3);
break;
case PREFIX_NONE:
- switch (i.tm.opcode_length)
+ switch (i.opcode_length)
{
case 3:
case 2:
- case 1:
break;
- case 0:
+ case 1:
/* Check for pseudo prefixes. */
+ if (!i.tm.opcode_modifier.isprefix || i.tm.base_opcode)
+ break;
as_bad_where (insn_start_frag->fr_file,
insn_start_frag->fr_line,
_("pseudo prefix without instruction"));
@@ -9458,14 +9476,14 @@ output_insn (void)
/* Now the opcode; be careful about word order here! */
if (now_seg == absolute_section)
- abs_section_offset += i.tm.opcode_length;
- else if (i.tm.opcode_length == 1)
+ abs_section_offset += i.opcode_length;
+ else if (i.opcode_length == 1)
{
FRAG_APPEND_1_CHAR (i.tm.base_opcode);
}
else
{
- switch (i.tm.opcode_length)
+ switch (i.opcode_length)
{
case 4:
p = frag_more (4);
@@ -9541,7 +9559,7 @@ output_insn (void)
/* Count prefixes for extended opcode maps. */
if (!i.vex.length)
- switch (i.tm.opcode_length)
+ switch (i.opcode_length)
{
case 3:
if (((i.tm.base_opcode >> 16) & 0xff) == 0xf)