On Mon, Dec 1, 2025 at 8:31 PM Mathias Krause <[email protected]> wrote:
>
> When generating 16-bit code via -m16, the NOP mcount code generation
> emits a 5-byte NOP. However, that is neither a valid i8086 instruction
> (long NOPs are PentiumPro+), nor would it get decoded as a 5-byte
> instruction. It's a 4-byte 'nopw 0(%si)' followed by a zero byte. The
> latter causes the following instruction to get misinterpreted as some
> form of ADD.
>
> Fix this by emiting a 3-byte no-op 'lea 0(%si)' instead which makes it
> compatible with systems lacking long NOP support.
>
> Add a test for this and change the existing one accordingly.
>
> gcc/ChangeLog:
>
>         * config/i386/i386.cc (x86_print_call_or_nop): Fix 16-bit NOP
>         generation.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.target/i386/nop-mcount-m16.c: New test.
>         * gcc.target/i386/nop-mcount.c: Adapt to test for 5-byte NOP.
>
> Signed-off-by: Mathias Krause <[email protected]>

OK.

Thanks,
Uros.


> ---
> v2: use 'scan-assembler-not' for checking missing of the NOPL sequence
>
>  gcc/config/i386/i386.cc                        | 12 +++++++++---
>  gcc/testsuite/gcc.target/i386/nop-mcount-m16.c | 13 +++++++++++++
>  gcc/testsuite/gcc.target/i386/nop-mcount.c     |  6 +++---
>  3 files changed, 25 insertions(+), 6 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/i386/nop-mcount-m16.c
>
> diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
> index 722c1713a6d3..db43045753bf 100644
> --- a/gcc/config/i386/i386.cc
> +++ b/gcc/config/i386/i386.cc
> @@ -23767,9 +23767,15 @@ x86_print_call_or_nop (FILE *file, const char 
> *target,
>                        const char *label)
>  {
>    if (flag_nop_mcount || !strcmp (target, "nop"))
> -    /* 5 byte nop: nopl 0(%[re]ax,%[re]ax,1) */
> -    fprintf (file, "%s" ASM_BYTE "0x0f, 0x1f, 0x44, 0x00, 0x00\n",
> -            label);
> +    {
> +      if (TARGET_16BIT)
> +       /* 3 byte no-op: lea 0(%si), %si */
> +       fprintf (file, "%s" ASM_BYTE "0x8d, 0x74, 0x00\n", label);
> +      else
> +       /* 5 byte nop: nopl 0(%[re]ax,%[re]ax,1) */
> +       fprintf (file, "%s" ASM_BYTE "0x0f, 0x1f, 0x44, 0x00, 0x00\n",
> +                label);
> +    }
>    else if (!TARGET_PECOFF && flag_pic)
>      {
>        gcc_assert (flag_plt);
> diff --git a/gcc/testsuite/gcc.target/i386/nop-mcount-m16.c 
> b/gcc/testsuite/gcc.target/i386/nop-mcount-m16.c
> new file mode 100644
> index 000000000000..15b8a38ac568
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/nop-mcount-m16.c
> @@ -0,0 +1,13 @@
> +/* Test -mnop-mcount for 16-bit code to generate a 3-byte NOP */
> +/* { dg-do compile { target { *-*-linux* && nonpic } } } */
> +/* { dg-require-effective-target mfentry } */
> +/* { dg-options "-pg -mfentry -mnop-mcount -m16" } */
> +/* { dg-final { scan-assembler-not "__fentry__" } } */
> +/* { dg-final { scan-assembler-not "0x0f, 0x1f, 0x44, 0x00, 0x00" } } */
> +/* { dg-final { scan-assembler-times "0x8d, 0x74, 0x00" 1 } } */
> +extern void foobar(char *);
> +
> +void func(void)
> +{
> +  foobar ("Hello world\n");
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/nop-mcount.c 
> b/gcc/testsuite/gcc.target/i386/nop-mcount.c
> index ee3c97f3a57c..35cfef0bc9d7 100644
> --- a/gcc/testsuite/gcc.target/i386/nop-mcount.c
> +++ b/gcc/testsuite/gcc.target/i386/nop-mcount.c
> @@ -1,8 +1,9 @@
>  /* Test -mnop-mcount */
>  /* { dg-do compile { target { *-*-linux* && nonpic } } } */
>  /* { dg-require-effective-target mfentry } */
> -/* { dg-options "-Wno-old-style-definition -pg -mfentry -mrecord-mcount 
> -mnop-mcount" } */
> +/* { dg-options "-pg -mfentry -mrecord-mcount -mnop-mcount" } */
>  /* { dg-final { scan-assembler-not "__fentry__" } } */
> +/* { dg-final { scan-assembler-times "0x0f, 0x1f, 0x44, 0x00, 0x00" 3 } } */
>  /* Origin: Andi Kleen */
>  extern void foobar(char *);
>
> @@ -18,8 +19,7 @@ void func2(void)
>      foobar ("Hello world");
>  }
>
> -void func3(a)
> -char *a;
> +void func3(char *a)
>  {
>    foobar("Hello world");
>  }
> --
> 2.47.3
>

Reply via email to