diff mbox

PATCH: PR target/45213: "suffix or operands invalid for `push'" triggered by optimisations on x86_64

Message ID AANLkTinK-086rHBJbuEX4LNBf0=fUB0LoW6+Fj7Ch8LF@mail.gmail.com
State New
Headers show

Commit Message

H.J. Lu Aug. 7, 2010, 3:52 p.m. UTC
On Sat, Aug 7, 2010 at 3:45 AM, Uros Bizjak <ubizjak@gmail.com> wrote:
> On Sat, Aug 7, 2010 at 12:11 PM, Uros Bizjak <ubizjak@gmail.com> wrote:
>
>>> "pushq $imm32S" only takes 32bit signed extended immediate. You can't push
>>> 0xbf800000. Instead, you push -1082130432 or 0xffffffffbf800000.  This
>>> patch makes it signed.  OK for trunk/4.5/4.4?
>>
>> No, see the comment in real.h:
>>
>> /* IN is a REAL_VALUE_TYPE.  OUT is a long.  */
>> #define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT) \
>>  ((OUT) = real_to_target (NULL, &(IN), mode_for_size (32, MODE_FLOAT, 0)))
>
> IMO, this is correct patch, to also generate correct extension on ILP32 hosts.
>
> Index: i386.c
> ===================================================================
> --- i386.c      (revision 162975)
> +++ i386.c      (working copy)
> @@ -12921,7 +12921,7 @@
>
>       if (ASSEMBLER_DIALECT == ASM_ATT)
>        putc ('$', file);
> -      fprintf (file, "0x%08lx", (long unsigned int) l);
> +      fprintf (file, "0x%08llx", (unsigned long long) (int) l);
>     }
>
>   /* These float cases don't actually occur as immediate operands.  */
>

SF is 4 bytes, the same as SI. pushq takes 32bit signed extended immediate.
It is safe for pushq since the upper 4 bytes, which are all 1s, are unused.
For everything else, we use 32bit unsigned int.  We don't want

movl	$0xffffffffbf800000, (%rsp)

How does this patch look?
diff mbox

Patch

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 204211a..4914299 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -12921,7 +12921,12 @@  ix86_print_operand (FILE *file, rtx x, int code)

       if (ASSEMBLER_DIALECT == ASM_ATT)
   putc ('$', file);
-      fprintf (file, "0x%08lx", (long unsigned int) l);
+      /* 'q' is only used on pushq which takes 32bit signed extended
+   immediate.  */
+      if (code == 'q')
+  fprintf (file, "%d", (int) l);
+      else
+  fprintf (file, "0x%08x", (unsigned int) l);
     }

   /* These float cases don't actually occur as immediate operands.  */