+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.
/* 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
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
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,
(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"