]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
x86: adjust NOP generation after potential non-insn
authorJan Beulich <jbeulich@suse.com>
Fri, 1 Dec 2023 07:29:11 +0000 (08:29 +0100)
committerJan Beulich <jbeulich@suse.com>
Fri, 1 Dec 2023 07:29:11 +0000 (08:29 +0100)
Just like avoiding to do certain transformations potentially affected by
stand-alone prefixes or direct data emission, also avoid emitting
optimized NOPs right afterwards; insert a plain old NOP first in such
cases.

gas/config/tc-i386.c
gas/config/tc-i386.h

index e984923ec3514da4db984520780548a6928eecfe..4f3864f2ba78a624f6bdc7e78b88f9a4dd479b3c 100644 (file)
@@ -1529,6 +1529,14 @@ i386_generate_nops (fragS *fragP, char *where, offsetT count, int limit)
   else if (fragP->fr_type != rs_machine_dependent)
     fragP->fr_var = count;
 
+  /* Emit a plain NOP first when the last thing we saw may not have been
+     a proper instruction (e.g. a stand-alone prefix or .byte).  */
+  if (!fragP->tc_frag_data.last_insn_normal)
+    {
+      *where++ = 0x90;
+      --count;
+    }
+
   if ((count / max_single_nop_size) > max_number_of_nops)
     {
       /* Generate jump over NOPs.  */
index c3022149fbeac3835ef071ef78f3ba7f692c1008..6d6f0b93681f2e2cfc66fe0c4861acf4d6d63253 100644 (file)
@@ -321,6 +321,7 @@ struct i386_tc_frag_data
   unsigned int branch_type : 3;
   unsigned int cpunop : 1;
   unsigned int isanop : 1;
+  unsigned int last_insn_normal : 1;
 };
 
 /* We need to emit the right NOP pattern in .align frags.  This is
@@ -347,7 +348,10 @@ struct i386_tc_frag_data
      (FRAGP)->tc_frag_data.cmp_size = 0;                       \
      (FRAGP)->tc_frag_data.classified = 0;                     \
      (FRAGP)->tc_frag_data.branch_type = 0;                    \
-     (FRAGP)->tc_frag_data.mf_type = 0;                        \
+     (FRAGP)->tc_frag_data.mf_type = 0;                                \
+     (FRAGP)->tc_frag_data.last_insn_normal                    \
+       = (seg_info(now_seg)->tc_segment_info_data.last_insn.kind \
+          == last_insn_other);                                 \
    }                                                           \
  while (0)