OSDN Git Service

* config/sparc/sparc.h (sparc_compare_emitted): New extern.
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 6 Jul 2005 07:49:05 +0000 (07:49 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 6 Jul 2005 07:49:05 +0000 (07:49 +0000)
* config/sparc/sparc.c (sparc_compare_emitted): New variable.
(gen_compare_reg): If sparc_compare_emitted is set, clear it
and return its previous value.
(emit_v9_brxx_insn): Assert sparc_compare_emitted is NULL.
* config/sparc/sparc.md (UNSPEC_SP_SET, UNSPEC_SP_TEST): New
constants.
(stack_protect_set, stack_protect_test): New expanders.
(stack_protect_setsi, stack_protect_setdi, stack_protect_testsi,
stack_protect_testdi): New insns.
* config/sparc/linux.h (TARGET_THREAD_SSP_OFFSET): Define.
* config/sparc/linux64.h (TARGET_THREAD_SSP_OFFSET): Define.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@101653 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/sparc/linux.h
gcc/config/sparc/linux64.h
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.h
gcc/config/sparc/sparc.md

index fa01f31..4343b43 100644 (file)
@@ -1,3 +1,18 @@
+2005-07-06  Jakub Jelinek  <jakub@redhat.com>
+
+       * config/sparc/sparc.h (sparc_compare_emitted): New extern.
+       * config/sparc/sparc.c (sparc_compare_emitted): New variable.
+       (gen_compare_reg): If sparc_compare_emitted is set, clear it
+       and return its previous value.
+       (emit_v9_brxx_insn): Assert sparc_compare_emitted is NULL.
+       * config/sparc/sparc.md (UNSPEC_SP_SET, UNSPEC_SP_TEST): New
+       constants.
+       (stack_protect_set, stack_protect_test): New expanders.
+       (stack_protect_setsi, stack_protect_setdi, stack_protect_testsi,
+       stack_protect_testdi): New insns.
+       * config/sparc/linux.h (TARGET_THREAD_SSP_OFFSET): Define.
+       * config/sparc/linux64.h (TARGET_THREAD_SSP_OFFSET): Define.
+
 2005-07-06  Jeff Law  <law@redhat.com>
 
        * tree-ssa-dce.c (cfg_altered): New global.
index 2e10987..87a043e 100644 (file)
@@ -229,3 +229,8 @@ do {                                                                        \
 
 #undef NEED_INDICATE_EXEC_STACK
 #define NEED_INDICATE_EXEC_STACK 1
+
+#ifdef TARGET_LIBC_PROVIDES_SSP
+/* sparc glibc provides __stack_chk_guard in [%g7 + 0x14].  */
+#define TARGET_THREAD_SSP_OFFSET       0x14
+#endif
index a331dfc..82860fe 100644 (file)
@@ -363,3 +363,9 @@ do {                                                                        \
 
 #undef NEED_INDICATE_EXEC_STACK
 #define NEED_INDICATE_EXEC_STACK 1
+
+#ifdef TARGET_LIBC_PROVIDES_SSP
+/* sparc glibc provides __stack_chk_guard in [%g7 + 0x14],
+   sparc64 glibc provides it at [%g7 + 0x28].  */
+#define TARGET_THREAD_SSP_OFFSET       (TARGET_ARCH64 ? 0x28 : 0x14)
+#endif
index 69bde4b..b0cde28 100644 (file)
@@ -232,7 +232,7 @@ static GTY(()) int struct_value_alias_set;
 
 /* Save the operands last given to a compare for use when we
    generate a scc or bcc insn.  */
-rtx sparc_compare_op0, sparc_compare_op1;
+rtx sparc_compare_op0, sparc_compare_op1, sparc_compare_emitted;
 
 /* Vector to say how input registers are mapped to output registers.
    HARD_FRAME_POINTER_REGNUM cannot be remapped by this function to
@@ -1905,6 +1905,13 @@ gen_compare_reg (enum rtx_code code, rtx x, rtx y)
   enum machine_mode mode = SELECT_CC_MODE (code, x, y);
   rtx cc_reg;
 
+  if (sparc_compare_emitted != NULL_RTX)
+    {
+      cc_reg = sparc_compare_emitted;
+      sparc_compare_emitted = NULL_RTX;
+      return cc_reg;
+    }
+
   /* ??? We don't have movcc patterns so we cannot generate pseudo regs for the
      fcc regs (cse can't tell they're really call clobbered regs and will
      remove a duplicate comparison even if there is an intervening function
@@ -2071,6 +2078,7 @@ gen_v9_scc (enum rtx_code compare_code, register rtx *operands)
 void
 emit_v9_brxx_insn (enum rtx_code code, rtx op0, rtx label)
 {
+  gcc_assert (sparc_compare_emitted == NULL_RTX);
   emit_jump_insn (gen_rtx_SET (VOIDmode,
                           pc_rtx,
                           gen_rtx_IF_THEN_ELSE (VOIDmode,
index 95fd760..35b8dd5 100644 (file)
@@ -1584,6 +1584,7 @@ function_arg_padding ((MODE), (TYPE))
 
 extern GTY(()) rtx sparc_compare_op0;
 extern GTY(()) rtx sparc_compare_op1;
+extern GTY(()) rtx sparc_compare_emitted;
 
 \f
 /* Generate the special assembly code needed to tell the assembler whatever
index 9335515..ee601d0 100644 (file)
@@ -57,6 +57,9 @@
    (UNSPEC_ALIGNDATA           48)
    (UNSPEC_ALIGNADDR           49)
    (UNSPEC_PDIST               50)
+
+   (UNSPEC_SP_SET              60)
+   (UNSPEC_SP_TEST             61)
   ])
 
 (define_constants
   [(set_attr "type" "store")])
 
 
+;; Stack protector instructions.
+
+(define_expand "stack_protect_set"
+  [(match_operand 0 "memory_operand" "")
+   (match_operand 1 "memory_operand" "")]
+  ""
+{
+#ifdef TARGET_THREAD_SSP_OFFSET
+  rtx tlsreg = gen_rtx_REG (Pmode, 7);
+  rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
+  operands[1] = gen_rtx_MEM (Pmode, addr);
+#endif
+  if (TARGET_ARCH64)
+    emit_insn (gen_stack_protect_setdi (operands[0], operands[1]));
+  else
+    emit_insn (gen_stack_protect_setsi (operands[0], operands[1]));
+  DONE;
+})
+
+(define_insn "stack_protect_setsi"
+  [(set (match_operand:SI 0 "memory_operand" "=m")
+       (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
+   (set (match_scratch:SI 2 "=&r") (const_int 0))]
+  "TARGET_ARCH32"
+  "ld\t%1, %2\;st\t%2, %0\;mov\t0, %2"
+  [(set_attr "type" "multi")
+   (set_attr "length" "3")])
+
+(define_insn "stack_protect_setdi"
+  [(set (match_operand:DI 0 "memory_operand" "=m")
+       (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
+   (set (match_scratch:DI 2 "=&r") (const_int 0))]
+  "TARGET_ARCH64"
+  "ldx\t%1, %2\;stx\t%2, %0\;mov\t0, %2"
+  [(set_attr "type" "multi")
+   (set_attr "length" "3")])
+
+(define_expand "stack_protect_test"
+  [(match_operand 0 "memory_operand" "")
+   (match_operand 1 "memory_operand" "")
+   (match_operand 2 "" "")]
+  ""
+{
+#ifdef TARGET_THREAD_SSP_OFFSET
+  rtx tlsreg = gen_rtx_REG (Pmode, 7);
+  rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
+  operands[1] = gen_rtx_MEM (Pmode, addr);
+#endif
+  if (TARGET_ARCH64)
+    {
+      rtx temp = gen_reg_rtx (Pmode);
+      emit_insn (gen_stack_protect_testdi (temp, operands[0], operands[1]));
+      sparc_compare_op0 = temp;
+      sparc_compare_op1 = const0_rtx;
+    }
+  else
+    {
+      emit_insn (gen_stack_protect_testsi (operands[0], operands[1]));
+      sparc_compare_op0 = operands[0];
+      sparc_compare_op1 = operands[1];
+      sparc_compare_emitted = gen_rtx_REG (CCmode, SPARC_ICC_REG);
+    }
+  emit_jump_insn (gen_beq (operands[2]));
+  DONE;
+})
+
+(define_insn "stack_protect_testsi"
+  [(set (reg:CC 100)
+       (unspec:CC [(match_operand:SI 0 "memory_operand" "m")
+                   (match_operand:SI 1 "memory_operand" "m")]
+                  UNSPEC_SP_TEST))
+   (clobber (match_scratch:SI 2 "=&r"))
+   (set (match_scratch:SI 3 "=r") (const_int 0))]
+  "TARGET_ARCH32"
+  "ld\t%0, %2\;ld\t%1, %3\;xorcc\t%2, %3, %2\;mov\t0, %3"
+  [(set_attr "type" "multi")
+   (set_attr "length" "4")])
+
+(define_insn "stack_protect_testdi"
+  [(set (match_operand:DI 0 "register_operand" "=&r")
+       (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
+                   (match_operand:DI 2 "memory_operand" "m")]
+                  UNSPEC_SP_TEST))
+   (set (match_scratch:DI 3 "=r") (const_int 0))]
+  "TARGET_ARCH64"
+  "ldx\t%1, %0\;ldx\t%2, %3\;xor\t%0, %3, %0\;mov\t0, %3"
+  [(set_attr "type" "multi")
+   (set_attr "length" "4")])
+
+
 ;; Vector instructions.
 
 (define_insn "addv2si3"