[PATCH 4/5] x86-64: special case LEA when determining signedness of displacement
H.J. Lu
hjl.tools@gmail.com
Thu Apr 22 11:54:21 GMT 2021
On Thu, Apr 22, 2021 at 1:40 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> LEA behavior without a 64-bit destination is independent of address size
> - in particular LEA with 32-bit addressing and 64-bit destination is the
> same as LEA with 64-bit addressing and 32-bit destination. IOW checking
> merely i.prefix[ADDR_PREFIX] is insufficient. This also means wrong
> relocation types (R_X86_64_32S when R_X86_64_32 is needed) were used so
> far in such cases.
Do you have a testcase for the wrong relocation type?
> Note that in one case in build_modrm_byte() the 64-bit check came too
> early altogether, and hence gets dropped in favor of the one included in
> the new helper. This is benign to non-64-bit code from all I can tell,
> but the failure to clear disp16 could have been a latent problem.
>
> gas/
> 2021-04-XX Jan Beulich <jbeulich@suse.com>
>
> * config/tc-i386.c (want_disp32): New.
> (md_assemble): Use it.
> (optimize_disp): Likewise.
> (build_modrm_byte): Likewise.
>
> --- a/gas/config/tc-i386.c
> +++ b/gas/config/tc-i386.c
> @@ -3555,6 +3555,16 @@ tc_i386_fix_adjustable (fixS *fixP ATTRI
> return 1;
> }
>
> +static INLINE bool
> +want_disp32 (const insn_template *t)
> +{
> + return flag_code != CODE_64BIT
> + || i.prefix[ADDR_PREFIX]
> + || (t->base_opcode == 0x8d
> + && t->opcode_modifier.opcodespace == SPACE_BASE
> + && !i.types[1].bitfield.qword);
> +}
> +
> static int
> intel_float_operand (const char *mnemonic)
> {
> @@ -4740,7 +4750,7 @@ md_assemble (char *line)
> if (i.imm_operands)
> optimize_imm ();
>
> - if (i.disp_operands && flag_code == CODE_64BIT && !i.prefix[ADDR_PREFIX])
> + if (i.disp_operands && !want_disp32 (current_templates->start))
> {
> for (j = 0; j < i.operands; ++j)
> {
> @@ -5748,7 +5758,7 @@ optimize_disp (void)
> #ifdef BFD64
> else if (flag_code == CODE_64BIT)
> {
> - if (i.prefix[ADDR_PREFIX]
> + if (want_disp32 (current_templates->start)
> && fits_in_unsigned_long (op_disp))
> i.types[op].bitfield.disp32 = 1;
>
> @@ -8108,7 +8118,7 @@ build_modrm_byte (void)
> i.types[op].bitfield.disp8 = 0;
> i.types[op].bitfield.disp16 = 0;
> i.types[op].bitfield.disp64 = 0;
> - if (flag_code != CODE_64BIT || i.prefix[ADDR_PREFIX])
> + if (want_disp32 (&i.tm))
> {
> /* Must be 32 bit */
> i.types[op].bitfield.disp32 = 1;
> @@ -8159,7 +8169,7 @@ build_modrm_byte (void)
> i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
> i.sib.base = NO_BASE_REGISTER;
> i.sib.index = NO_INDEX_REGISTER;
> - newdisp = (!i.prefix[ADDR_PREFIX] ? disp32s : disp32);
> + newdisp = (want_disp32(&i.tm) ? disp32 : disp32s);
> }
> else if ((flag_code == CODE_16BIT)
> ^ (i.prefix[ADDR_PREFIX] != 0))
> @@ -8188,7 +8198,7 @@ build_modrm_byte (void)
> i.types[op].bitfield.disp8 = 0;
> i.types[op].bitfield.disp16 = 0;
> i.types[op].bitfield.disp64 = 0;
> - if (flag_code != CODE_64BIT || i.prefix[ADDR_PREFIX])
> + if (want_disp32 (&i.tm))
> {
> /* Must be 32 bit */
> i.types[op].bitfield.disp32 = 1;
> @@ -8263,12 +8273,11 @@ build_modrm_byte (void)
> }
> else /* i.base_reg and 32/64 bit mode */
> {
> - if (flag_code == CODE_64BIT
> - && operand_type_check (i.types[op], disp))
> + if (operand_type_check (i.types[op], disp))
> {
> i.types[op].bitfield.disp16 = 0;
> i.types[op].bitfield.disp64 = 0;
> - if (i.prefix[ADDR_PREFIX] == 0)
> + if (!want_disp32 (&i.tm))
> {
> i.types[op].bitfield.disp32 = 0;
> i.types[op].bitfield.disp32s = 1;
>
--
H.J.
More information about the Binutils
mailing list