diff options
author | Jan Beulich <jbeulich@suse.com> | 2021-03-24 08:33:33 +0100 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2021-03-24 08:33:33 +0100 |
commit | 9a182d0461cc34912da51f445a242b392389edd6 (patch) | |
tree | 23378054b7425ee896162d67940c240b42064d61 /gas | |
parent | 3564871692e324301c2950679aa0fbb04c6d12dc (diff) | |
download | gdb-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/ChangeLog | 12 | ||||
-rw-r--r-- | gas/config/tc-i386.c | 50 |
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) |