[3/5] x86-64: defer 32-bit signed displacement check

Message ID 1aa237ba-ba09-4f71-0f24-1fa88d0c777b@suse.com
State New
Headers show
Series
  • x86: assorted relocation handling related adjustment (part I)
Related show

Commit Message

Nick Alcock via Binutils April 22, 2021, 8:39 a.m.
In preparation for extending the conditions here defer this check until
operands have been parsed, as certain further attributes will need to
be known for determining applicability of this check to be correct to
LEA.

gas/
2021-04-XX  Jan Beulich  <jbeulich@suse.com>

	* config/tc-i386.c (i386_finalize_displacement): Move Disp32S
	check ...
	(md_assemble): ... here.

---
Even with it moved later, the check still seems misplaced (too early,
and hence not covering all cases) and overly ad-hoc (there shouldn't be
anything CODE_64BIT specific here). But with the way optimize_disp() and
other logic works, moving it even later doesn't look to be easily
possible.

Comments

Nick Alcock via Binutils April 22, 2021, 11:54 a.m. | #1
On Thu, Apr 22, 2021 at 1:39 AM Jan Beulich <jbeulich@suse.com> wrote:
>

> In preparation for extending the conditions here defer this check until

> operands have been parsed, as certain further attributes will need to

> be known for determining applicability of this check to be correct to

> LEA.

>

> gas/

> 2021-04-XX  Jan Beulich  <jbeulich@suse.com>

>

>         * config/tc-i386.c (i386_finalize_displacement): Move Disp32S

>         check ...

>         (md_assemble): ... here.

>

> ---

> Even with it moved later, the check still seems misplaced (too early,

> and hence not covering all cases) and overly ad-hoc (there shouldn't be

> anything CODE_64BIT specific here). But with the way optimize_disp() and

> other logic works, moving it even later doesn't look to be easily

> possible.

>

> --- a/gas/config/tc-i386.c

> +++ b/gas/config/tc-i386.c

> @@ -4740,6 +4740,34 @@ md_assemble (char *line)

>    if (i.imm_operands)

>      optimize_imm ();

>

> +  if (i.disp_operands && flag_code == CODE_64BIT && !i.prefix[ADDR_PREFIX])

> +    {

> +      for (j = 0; j < i.operands; ++j)

> +       {

> +         const expressionS *exp = i.op[j].disps;

> +

> +         if (!operand_type_check (i.types[j], disp))

> +           continue;

> +

> +         if (exp->X_op != O_constant)

> +           continue;

> +

> +         /* Since displacement is signed extended to 64bit, don't allow

> +            disp32 and turn off disp32s if they are out of range.  */

> +         i.types[j].bitfield.disp32 = 0;

> +         if (fits_in_signed_long (exp->X_add_number))

> +           continue;

> +

> +         i.types[j].bitfield.disp32s = 0;

> +         if (i.types[j].bitfield.baseindex)

> +           {

> +             as_bad (_("0x%" BFD_VMA_FMT "x out of range of signed 32bit displacement"),

> +                     exp->X_add_number);

> +             return;

> +           }

> +       }

> +    }

> +

>    /* Don't optimize displacement for movabs since it only takes 64bit

>       displacement.  */

>    if (i.disp_operands

> @@ -10912,25 +10940,6 @@ i386_finalize_displacement (segT exp_seg

>        ret = 0;

>      }

>

> -  else if (flag_code == CODE_64BIT

> -          && !i.prefix[ADDR_PREFIX]

> -          && exp->X_op == O_constant)

> -    {

> -      /* Since displacement is signed extended to 64bit, don't allow

> -        disp32 and turn off disp32s if they are out of range.  */

> -      i.types[this_operand].bitfield.disp32 = 0;

> -      if (!fits_in_signed_long (exp->X_add_number))

> -       {

> -         i.types[this_operand].bitfield.disp32s = 0;

> -         if (i.types[this_operand].bitfield.baseindex)

> -           {

> -             as_bad (_("0x%" BFD_VMA_FMT "x out of range of signed 32bit displacement"),

> -                     exp->X_add_number);

> -             ret = 0;

> -           }

> -       }

> -    }

> -

>  #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))

>    else if (exp->X_op != O_constant

>            && OUTPUT_FLAVOR == bfd_target_aout_flavour

>


OK.

Thanks.

-- 
H.J.

Patch

--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -4740,6 +4740,34 @@  md_assemble (char *line)
   if (i.imm_operands)
     optimize_imm ();
 
+  if (i.disp_operands && flag_code == CODE_64BIT && !i.prefix[ADDR_PREFIX])
+    {
+      for (j = 0; j < i.operands; ++j)
+	{
+	  const expressionS *exp = i.op[j].disps;
+
+	  if (!operand_type_check (i.types[j], disp))
+	    continue;
+
+	  if (exp->X_op != O_constant)
+	    continue;
+
+	  /* Since displacement is signed extended to 64bit, don't allow
+	     disp32 and turn off disp32s if they are out of range.  */
+	  i.types[j].bitfield.disp32 = 0;
+	  if (fits_in_signed_long (exp->X_add_number))
+	    continue;
+
+	  i.types[j].bitfield.disp32s = 0;
+	  if (i.types[j].bitfield.baseindex)
+	    {
+	      as_bad (_("0x%" BFD_VMA_FMT "x out of range of signed 32bit displacement"),
+		      exp->X_add_number);
+	      return;
+	    }
+	}
+    }
+
   /* Don't optimize displacement for movabs since it only takes 64bit
      displacement.  */
   if (i.disp_operands
@@ -10912,25 +10940,6 @@  i386_finalize_displacement (segT exp_seg
       ret = 0;
     }
 
-  else if (flag_code == CODE_64BIT
-	   && !i.prefix[ADDR_PREFIX]
-	   && exp->X_op == O_constant)
-    {
-      /* Since displacement is signed extended to 64bit, don't allow
-	 disp32 and turn off disp32s if they are out of range.  */
-      i.types[this_operand].bitfield.disp32 = 0;
-      if (!fits_in_signed_long (exp->X_add_number))
-	{
-	  i.types[this_operand].bitfield.disp32s = 0;
-	  if (i.types[this_operand].bitfield.baseindex)
-	    {
-	      as_bad (_("0x%" BFD_VMA_FMT "x out of range of signed 32bit displacement"),
-		      exp->X_add_number);
-	      ret = 0;
-	    }
-	}
-    }
-
 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
   else if (exp->X_op != O_constant
 	   && OUTPUT_FLAVOR == bfd_target_aout_flavour