public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH, i386]: Fix PR 41900, call *%esp shouldn't be generated   because of CPU errata
@ 2009-11-03  7:48 Uros Bizjak
  2009-11-03 11:56 ` Jakub Jelinek
  2009-11-13  0:46 ` Richard Henderson
  0 siblings, 2 replies; 15+ messages in thread
From: Uros Bizjak @ 2009-11-03  7:48 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1755 bytes --]

Hello!

As explained in the PR:

Intel P6 family of processors (Pentium Pro, 2, 3) have a bug in call *%esp
instruction. The instruction should put current EIP to stack, decrement ESP by
4 and jump to a value of ESP before the decrement. P6 processors will jump to
the address after the decrement (so the will execute return address as code).
See Pentium Pro errata 70, Pentium 2 errata A33, Pentium 3 errata E17.

Attached patch avoids %esp by constraining available registers for a
call operand with "index_register_operand" which happens to exclude
%esp. Due to the way we define "generic" target, we have to include
i386, i486 and pentium in addition to PPRO, but since you have to use
lots of magic to trigger this bug (see attached testcase) I don't
think this matters at all.

Patch was bootstrapped and regression tested on x86_64-pc-linux-gnu
{,-m32}. Patch was committed to mainline, will be backported to 4.4
and 4.3 branches.

2009-11-03  Uros Bizjak  <ubizjak@gmail.com>

	PR target/41900
	* config/i386/i386.h (ix86_arch_indices) <X86_ARCH_CALL_ESP>: New.
	(TARGET_CALL_ESP): New define.
	* config/i386/i386.c (initial_ix86_tune_features): Initialize
	X86_ARCH_CALL_ESP.
	* config/i386/i386.md
	(*call_pop_1_esp, *call_1_esp, *call_value_pop_1_esp,
	*call_value_1_esp): Rename from *call_pop_1, *call_1,
	*call_value_pop_1 and *call_value_1.  Depend on TARGET_CALL_ESP.
	(*call_pop_1, *call_1, *call_value_pop_1, *call_value_1):
	New patterns, use "lsm" as operand 1 constraint.
	* config/i386/predicates.md (call_insn_operand): Depend on
	index_register_operand for !TARGET_CALL_ESP to avoid %esp register.

testsuite/ChangeLog:

2009-11-03  Uros Bizjak  <ubizjak@gmail.com>

	PR target/41900
	* gcc.target/i386/pr41900.c: New test.

Uros.

[-- Attachment #2: p.diff.txt --]
[-- Type: text/plain, Size: 9785 bytes --]

Index: testsuite/gcc.target/i386/pr41900.c
===================================================================
--- testsuite/gcc.target/i386/pr41900.c	(revision 0)
+++ testsuite/gcc.target/i386/pr41900.c	(revision 0)
@@ -0,0 +1,11 @@
+/* { dg-do run } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-options "-O2 -fomit-frame-pointer -mpreferred-stack-boundary=2" } */
+
+int main ()
+{
+  unsigned code = 0xc3;
+
+  ((void (*)(void)) &code) ();
+  return 0;
+}
Index: config/i386/i386.h
===================================================================
--- config/i386/i386.h	(revision 153837)
+++ config/i386/i386.h	(working copy)
@@ -400,6 +400,7 @@ enum ix86_arch_indices {
   X86_ARCH_CMPXCHG8B,
   X86_ARCH_XADD,
   X86_ARCH_BSWAP,
+  X86_ARCH_CALL_ESP,
 
   X86_ARCH_LAST
 };
@@ -411,6 +412,7 @@ extern unsigned char ix86_arch_features[
 #define TARGET_CMPXCHG8B	ix86_arch_features[X86_ARCH_CMPXCHG8B]
 #define TARGET_XADD		ix86_arch_features[X86_ARCH_XADD]
 #define TARGET_BSWAP		ix86_arch_features[X86_ARCH_BSWAP]
+#define TARGET_CALL_ESP		ix86_arch_features[X86_ARCH_CALL_ESP]
 
 #define TARGET_FISTTP		(TARGET_SSE3 && TARGET_80387)
 
Index: config/i386/i386.md
===================================================================
--- config/i386/i386.md	(revision 153837)
+++ config/i386/i386.md	(working copy)
@@ -14566,12 +14566,25 @@
 }
   [(set_attr "type" "call")])
 
-(define_insn "*call_pop_1"
+(define_insn "*call_pop_1_esp"
   [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "rsm"))
 	 (match_operand:SI 1 "" ""))
    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
 			    (match_operand:SI 2 "immediate_operand" "i")))]
-  "!SIBLING_CALL_P (insn) && !TARGET_64BIT"
+  "!TARGET_64BIT && TARGET_CALL_ESP && !SIBLING_CALL_P (insn)"
+{
+  if (constant_call_address_operand (operands[0], Pmode))
+    return "call\t%P0";
+  return "call\t%A0";
+}
+  [(set_attr "type" "call")])
+
+(define_insn "*call_pop_1"
+  [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lsm"))
+	 (match_operand:SI 1 "" ""))
+   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
+			    (match_operand:SI 2 "immediate_operand" "i")))]
+  "!TARGET_64BIT && !TARGET_CALL_ESP && !SIBLING_CALL_P (insn)"
 {
   if (constant_call_address_operand (operands[0], Pmode))
     return "call\t%P0";
@@ -14584,7 +14597,7 @@
 	 (match_operand:SI 1 "" ""))
    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
 			    (match_operand:SI 2 "immediate_operand" "i,i")))]
-  "SIBLING_CALL_P (insn) && !TARGET_64BIT"
+  "!TARGET_64BIT && SIBLING_CALL_P (insn)"
   "@
    jmp\t%P0
    jmp\t%A0"
@@ -14622,10 +14635,21 @@
 }
   [(set_attr "type" "call")])
 
-(define_insn "*call_1"
+(define_insn "*call_1_esp"
   [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "rsm"))
 	 (match_operand 1 "" ""))]
-  "!SIBLING_CALL_P (insn) && !TARGET_64BIT"
+  "!TARGET_64BIT && TARGET_CALL_ESP && !SIBLING_CALL_P (insn)"
+{
+  if (constant_call_address_operand (operands[0], Pmode))
+    return "call\t%P0";
+  return "call\t%A0";
+}
+  [(set_attr "type" "call")])
+
+(define_insn "*call_1"
+  [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lsm"))
+	 (match_operand 1 "" ""))]
+  "!TARGET_64BIT && !TARGET_CALL_ESP && !SIBLING_CALL_P (insn)"
 {
   if (constant_call_address_operand (operands[0], Pmode))
     return "call\t%P0";
@@ -14636,7 +14660,7 @@
 (define_insn "*sibcall_1"
   [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,U"))
 	 (match_operand 1 "" ""))]
-  "SIBLING_CALL_P (insn) && !TARGET_64BIT"
+  "!TARGET_64BIT && SIBLING_CALL_P (insn)"
   "@
    jmp\t%P0
    jmp\t%A0"
@@ -14645,7 +14669,7 @@
 (define_insn "*call_1_rex64"
   [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm"))
 	 (match_operand 1 "" ""))]
-  "!SIBLING_CALL_P (insn) && TARGET_64BIT
+  "TARGET_64BIT && !SIBLING_CALL_P (insn)
    && ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC"
 {
   if (constant_call_address_operand (operands[0], Pmode))
@@ -14670,7 +14694,7 @@
    (clobber (reg:TI XMM15_REG))
    (clobber (reg:DI SI_REG))
    (clobber (reg:DI DI_REG))]
-  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
+  "TARGET_64BIT && !SIBLING_CALL_P (insn)"
 {
   if (constant_call_address_operand (operands[0], Pmode))
     return "call\t%P0";
@@ -14681,14 +14705,14 @@
 (define_insn "*call_1_rex64_large"
   [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rm"))
 	 (match_operand 1 "" ""))]
-  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
+  "TARGET_64BIT && !SIBLING_CALL_P (insn)"
   "call\t%A0"
   [(set_attr "type" "call")])
 
 (define_insn "*sibcall_1_rex64"
   [(call (mem:QI (match_operand:DI 0 "sibcall_insn_operand" "s,U"))
 	 (match_operand 1 "" ""))]
-  "SIBLING_CALL_P (insn) && TARGET_64BIT"
+  "TARGET_64BIT && SIBLING_CALL_P (insn)"
   "@
    jmp\t%P0
    jmp\t%A0"
@@ -21084,13 +21108,27 @@
 }
   [(set_attr "type" "callv")])
 
-(define_insn "*call_value_pop_1"
+(define_insn "*call_value_pop_1_esp"
   [(set (match_operand 0 "" "")
 	(call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm"))
 	      (match_operand:SI 2 "" "")))
    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
 			    (match_operand:SI 3 "immediate_operand" "i")))]
-  "!SIBLING_CALL_P (insn) && !TARGET_64BIT"
+  "!TARGET_64BIT && TARGET_CALL_ESP && !SIBLING_CALL_P (insn)"
+{
+  if (constant_call_address_operand (operands[1], Pmode))
+    return "call\t%P1";
+  return "call\t%A1";
+}
+  [(set_attr "type" "callv")])
+
+(define_insn "*call_value_pop_1"
+  [(set (match_operand 0 "" "")
+	(call (mem:QI (match_operand:SI 1 "call_insn_operand" "lsm"))
+	      (match_operand:SI 2 "" "")))
+   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
+			    (match_operand:SI 3 "immediate_operand" "i")))]
+  "!TARGET_64BIT && !TARGET_CALL_ESP && !SIBLING_CALL_P (insn)"
 {
   if (constant_call_address_operand (operands[1], Pmode))
     return "call\t%P1";
@@ -21104,7 +21142,7 @@
 	      (match_operand:SI 2 "" "")))
    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
 			    (match_operand:SI 3 "immediate_operand" "i,i")))]
-  "SIBLING_CALL_P (insn) && !TARGET_64BIT"
+  "!TARGET_64BIT && SIBLING_CALL_P (insn)"
   "@
    jmp\t%P1
    jmp\t%A1"
@@ -21153,7 +21191,7 @@
    (clobber (reg:TI XMM15_REG))
    (clobber (reg:DI SI_REG))
    (clobber (reg:DI DI_REG))]
-  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
+  "TARGET_64BIT && !SIBLING_CALL_P (insn)"
 {
   if (SIBLING_CALL_P (insn))
     return "jmp\t%P1";
@@ -21162,11 +21200,23 @@
 }
   [(set_attr "type" "callv")])
 
-(define_insn "*call_value_1"
+(define_insn "*call_value_1_esp"
   [(set (match_operand 0 "" "")
 	(call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm"))
 	      (match_operand:SI 2 "" "")))]
-  "!SIBLING_CALL_P (insn) && !TARGET_64BIT"
+  "!TARGET_64BIT && TARGET_CALL_ESP && !SIBLING_CALL_P (insn)"
+{
+  if (constant_call_address_operand (operands[1], Pmode))
+    return "call\t%P1";
+  return "call\t%A1";
+}
+  [(set_attr "type" "callv")])
+
+(define_insn "*call_value_1"
+  [(set (match_operand 0 "" "")
+	(call (mem:QI (match_operand:SI 1 "call_insn_operand" "lsm"))
+	      (match_operand:SI 2 "" "")))]
+  "!TARGET_64BIT && !TARGET_CALL_ESP && !SIBLING_CALL_P (insn)"
 {
   if (constant_call_address_operand (operands[1], Pmode))
     return "call\t%P1";
@@ -21178,7 +21228,7 @@
   [(set (match_operand 0 "" "")
 	(call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,U"))
 	      (match_operand:SI 2 "" "")))]
-  "SIBLING_CALL_P (insn) && !TARGET_64BIT"
+  "!TARGET_64BIT && SIBLING_CALL_P (insn)"
   "@
    jmp\t%P1
    jmp\t%A1"
@@ -21188,7 +21238,7 @@
   [(set (match_operand 0 "" "")
 	(call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm"))
 	      (match_operand:DI 2 "" "")))]
-  "!SIBLING_CALL_P (insn) && TARGET_64BIT
+  "TARGET_64BIT && !SIBLING_CALL_P (insn)
    && ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC"
 {
   if (constant_call_address_operand (operands[1], Pmode))
@@ -21226,7 +21276,7 @@
   [(set (match_operand 0 "" "")
 	(call (mem:QI (match_operand:DI 1 "call_insn_operand" "rm"))
 	      (match_operand:DI 2 "" "")))]
-  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
+  "TARGET_64BIT && !SIBLING_CALL_P (insn)"
   "call\t%A1"
   [(set_attr "type" "callv")])
 
@@ -21234,7 +21284,7 @@
   [(set (match_operand 0 "" "")
 	(call (mem:QI (match_operand:DI 1 "sibcall_insn_operand" "s,U"))
 	      (match_operand:DI 2 "" "")))]
-  "SIBLING_CALL_P (insn) && TARGET_64BIT"
+  "TARGET_64BIT && SIBLING_CALL_P (insn)"
   "@
    jmp\t%P1
    jmp\t%A1"
Index: config/i386/predicates.md
===================================================================
--- config/i386/predicates.md	(revision 153837)
+++ config/i386/predicates.md	(working copy)
@@ -561,7 +561,9 @@
 ;; Test for a valid operand for a call instruction.
 (define_predicate "call_insn_operand"
   (ior (match_operand 0 "constant_call_address_operand")
-       (ior (match_operand 0 "register_no_elim_operand")
+       (ior (and (match_operand 0 "register_no_elim_operand")
+		 (ior (match_test "TARGET_CALL_ESP")
+		      (match_operand 0 "index_register_operand")))
 	    (match_operand 0 "memory_operand"))))
 
 ;; Similarly, but for tail calls, in which we cannot allow memory references.
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c	(revision 153837)
+++ config/i386/i386.c	(working copy)
@@ -1553,6 +1553,11 @@ static unsigned int initial_ix86_arch_fe
 
   /* X86_ARCH_BSWAP: Byteswap was added for 80486.  */
   ~m_386,
+
+  /* X86_ARCH_CALL_ESP: P6 processors will jump to the address after
+     the decrement (so they will execute return address as code).  See
+     Pentium Pro errata 70, Pentium 2 errata A33, Pentium 3 errata E17.  */
+  ~(m_386 | m_486 | m_PENT | m_PPRO),
 };
 
 static const unsigned int x86_accumulate_outgoing_args

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2009-11-14 15:19 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-03  7:48 [PATCH, i386]: Fix PR 41900, call *%esp shouldn't be generated because of CPU errata Uros Bizjak
2009-11-03 11:56 ` Jakub Jelinek
2009-11-03 15:08   ` Uros Bizjak
2009-11-03 15:13     ` Jakub Jelinek
2009-11-03 17:27       ` Uros Bizjak
2009-11-03 17:31         ` Jakub Jelinek
2009-11-03 18:47           ` Uros Bizjak
2009-11-03 19:37             ` Uros Bizjak
2009-11-13  0:46 ` Richard Henderson
2009-11-13  8:47   ` Uros Bizjak
2009-11-13 16:46     ` Richard Henderson
2009-11-13 17:42       ` Uros Bizjak
2009-11-14 11:03         ` Eric Botcazou
2009-11-14 11:48           ` Uros Bizjak
2009-11-14 18:25             ` Eric Botcazou

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).