summaryrefslogtreecommitdiff
path: root/gcc/config/i386/i386.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/i386/i386.md')
-rw-r--r--gcc/config/i386/i386.md449
1 files changed, 397 insertions, 52 deletions
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 3413b90028f..d48decbb7d9 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -62,7 +62,7 @@
;; ; -- print a semicolon (after prefixes due to bug in older gas).
;; ~ -- print "i" if TARGET_AVX2, "f" otherwise.
;; ^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode
-;; ! -- print MPX prefix for jxx/call/ret instructions if required.
+;; ! -- print MPX or NOTRACK prefix for jxx/call/ret instructions if required.
(define_c_enum "unspec" [
;; Relocation specifiers
@@ -99,6 +99,7 @@
UNSPEC_SCAS
UNSPEC_FNSTSW
UNSPEC_SAHF
+ UNSPEC_NOTRAP
UNSPEC_PARITY
UNSPEC_FSTCW
UNSPEC_FLDCW
@@ -112,6 +113,7 @@
UNSPEC_STOS
UNSPEC_PEEPSIB
UNSPEC_INSN_FALSE_DEP
+ UNSPEC_SBB
;; For SSE/MMX support:
UNSPEC_FIX_NOTRUNC
@@ -274,6 +276,17 @@
;; For RDPID support
UNSPECV_RDPID
+
+ ;; For CET support
+ UNSPECV_NOP_ENDBR
+ UNSPECV_NOP_RDSSP
+ UNSPECV_INCSSP
+ UNSPECV_SAVEPREVSSP
+ UNSPECV_RSTORSSP
+ UNSPECV_WRSS
+ UNSPECV_WRUSS
+ UNSPECV_SETSSBSY
+ UNSPECV_CLRSSBSY
])
;; Constants to represent rounding modes in the ROUND instruction
@@ -798,7 +811,7 @@
(define_attr "isa" "base,x64,x64_sse4,x64_sse4_noavx,x64_avx,nox64,
sse2,sse2_noavx,sse3,sse4,sse4_noavx,avx,noavx,
avx2,noavx2,bmi,bmi2,fma4,fma,avx512f,noavx512f,
- fma_avx512f,avx512bw,noavx512bw,avx512dq,noavx512dq,
+ avx512bw,noavx512bw,avx512dq,noavx512dq,
avx512vl,noavx512vl,x64_avx512dq,x64_avx512bw"
(const_string "base"))
@@ -832,8 +845,6 @@
(eq_attr "isa" "fma") (symbol_ref "TARGET_FMA")
(eq_attr "isa" "avx512f") (symbol_ref "TARGET_AVX512F")
(eq_attr "isa" "noavx512f") (symbol_ref "!TARGET_AVX512F")
- (eq_attr "isa" "fma_avx512f")
- (symbol_ref "TARGET_FMA || TARGET_AVX512F")
(eq_attr "isa" "avx512bw") (symbol_ref "TARGET_AVX512BW")
(eq_attr "isa" "noavx512bw") (symbol_ref "!TARGET_AVX512BW")
(eq_attr "isa" "avx512dq") (symbol_ref "TARGET_AVX512DQ")
@@ -1468,9 +1479,6 @@
;; FP compares, step 1:
;; Set the FP condition codes.
-;;
-;; CCFPmode compare with exceptions
-;; CCFPUmode compare with no exceptions
;; We may not use "#" to split and emit these, since the REG_DEAD notes
;; used to manage the reg stack popping would not be preserved.
@@ -1577,9 +1585,11 @@
(define_insn "*cmpu<mode>_i387"
[(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
- [(compare:CCFPU
- (match_operand:X87MODEF 1 "register_operand" "f")
- (match_operand:X87MODEF 2 "register_operand" "f"))]
+ [(unspec:CCFP
+ [(compare:CCFP
+ (match_operand:X87MODEF 1 "register_operand" "f")
+ (match_operand:X87MODEF 2 "register_operand" "f"))]
+ UNSPEC_NOTRAP)]
UNSPEC_FNSTSW))]
"TARGET_80387"
"* return output_fp_compare (insn, operands, false, true);"
@@ -1588,18 +1598,22 @@
(set_attr "mode" "<MODE>")])
(define_insn_and_split "*cmpu<mode>_cc_i387"
- [(set (reg:CCFPU FLAGS_REG)
- (compare:CCFPU
- (match_operand:X87MODEF 1 "register_operand" "f")
- (match_operand:X87MODEF 2 "register_operand" "f")))
+ [(set (reg:CCFP FLAGS_REG)
+ (unspec:CCFP
+ [(compare:CCFP
+ (match_operand:X87MODEF 1 "register_operand" "f")
+ (match_operand:X87MODEF 2 "register_operand" "f"))]
+ UNSPEC_NOTRAP))
(clobber (match_operand:HI 0 "register_operand" "=a"))]
"TARGET_80387 && TARGET_SAHF && !TARGET_CMOVE"
"#"
"&& reload_completed"
[(set (match_dup 0)
(unspec:HI
- [(compare:CCFPU (match_dup 1)(match_dup 2))]
- UNSPEC_FNSTSW))
+ [(unspec:CCFP
+ [(compare:CCFP (match_dup 1)(match_dup 2))]
+ UNSPEC_NOTRAP)]
+ UNSPEC_FNSTSW))
(set (reg:CC FLAGS_REG)
(unspec:CC [(match_dup 0)] UNSPEC_SAHF))]
""
@@ -1685,21 +1699,30 @@
(set_attr "mode" "SI")])
;; Pentium Pro can do steps 1 through 3 in one go.
-;; comi*, ucomi*, fcomi*, ficomi*, fucomi*
-;; (these i387 instructions set flags directly)
+;; (these instructions set flags directly)
-(define_mode_iterator FPCMP [CCFP CCFPU])
-(define_mode_attr unord [(CCFP "") (CCFPU "u")])
+(define_subst_attr "unord" "unord_subst" "" "u")
+(define_subst_attr "unordered" "unord_subst" "false" "true")
+
+(define_subst "unord_subst"
+ [(set (match_operand:CCFP 0)
+ (match_operand:CCFP 1))]
+ ""
+ [(set (match_dup 0)
+ (unspec:CCFP
+ [(match_dup 1)]
+ UNSPEC_NOTRAP))])
-(define_insn "*cmpi<FPCMP:unord><MODEF:mode>"
- [(set (reg:FPCMP FLAGS_REG)
- (compare:FPCMP
+(define_insn "*cmpi<unord><MODEF:mode>"
+ [(set (reg:CCFP FLAGS_REG)
+ (compare:CCFP
(match_operand:MODEF 0 "register_operand" "f,v")
(match_operand:MODEF 1 "register_ssemem_operand" "f,vm")))]
"(SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH)
|| (TARGET_80387 && TARGET_CMOVE)"
- "* return output_fp_compare (insn, operands, true,
- <FPCMP:MODE>mode == CCFPUmode);"
+ "@
+ * return output_fp_compare (insn, operands, true, <unordered>);
+ %v<unord>comi<MODEF:ssemodesuffix>\t{%1, %0|%0, %1}"
[(set_attr "type" "fcmp,ssecomi")
(set_attr "prefix" "orig,maybe_vex")
(set_attr "mode" "<MODEF:MODE>")
@@ -1728,13 +1751,12 @@
(symbol_ref "false"))))])
(define_insn "*cmpi<unord>xf_i387"
- [(set (reg:FPCMP FLAGS_REG)
- (compare:FPCMP
+ [(set (reg:CCFP FLAGS_REG)
+ (compare:CCFP
(match_operand:XF 0 "register_operand" "f")
(match_operand:XF 1 "register_operand" "f")))]
"TARGET_80387 && TARGET_CMOVE"
- "* return output_fp_compare (insn, operands, true,
- <MODE>mode == CCFPUmode);"
+ "* return output_fp_compare (insn, operands, true, <unordered>);"
[(set_attr "type" "fcmp")
(set_attr "mode" "XF")
(set_attr "athlon_decode" "vector")
@@ -3564,8 +3586,10 @@
/* movaps is one byte shorter for non-AVX targets. */
(eq_attr "alternative" "13,17")
- (cond [(ior (match_operand 0 "ext_sse_reg_operand")
- (match_operand 1 "ext_sse_reg_operand"))
+ (cond [(and (ior (not (match_test "TARGET_PREFER_AVX256"))
+ (not (match_test "TARGET_AVX512VL")))
+ (ior (match_operand 0 "ext_sse_reg_operand")
+ (match_operand 1 "ext_sse_reg_operand")))
(const_string "V8DF")
(ior (not (match_test "TARGET_SSE2"))
(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL"))
@@ -3739,8 +3763,10 @@
better to maintain the whole registers in single format
to avoid problems on using packed logical operations. */
(eq_attr "alternative" "6")
- (cond [(ior (match_operand 0 "ext_sse_reg_operand")
- (match_operand 1 "ext_sse_reg_operand"))
+ (cond [(and (ior (not (match_test "TARGET_PREFER_AVX256"))
+ (not (match_test "TARGET_AVX512VL")))
+ (ior (match_operand 0 "ext_sse_reg_operand")
+ (match_operand 1 "ext_sse_reg_operand")))
(const_string "V16SF")
(ior (match_test "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
(match_test "TARGET_SSE_SPLIT_REGS"))
@@ -6765,6 +6791,17 @@
[(set_attr "type" "alu")
(set_attr "mode" "<MODE>")])
+(define_peephole2
+ [(parallel
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_operand:SWI 0 "general_reg_operand")
+ (match_operand:SWI 1 "general_gr_operand")))
+ (set (match_dup 0)
+ (minus:SWI (match_dup 0) (match_dup 1)))])]
+ "find_regno_note (peep2_next_insn (0), REG_UNUSED, REGNO (operands[0])) != 0"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_dup 0) (match_dup 1)))])
+
(define_insn "*subsi_3_zext"
[(set (reg FLAGS_REG)
(compare (match_operand:SI 1 "register_operand" "0")
@@ -6818,15 +6855,19 @@
(define_insn "addcarry<mode>"
[(set (reg:CCC FLAGS_REG)
(compare:CCC
- (plus:SWI48
+ (zero_extend:<DWI>
(plus:SWI48
- (match_operator:SWI48 4 "ix86_carry_flag_operator"
- [(match_operand 3 "flags_reg_operand") (const_int 0)])
- (match_operand:SWI48 1 "nonimmediate_operand" "%0"))
- (match_operand:SWI48 2 "nonimmediate_operand" "rm"))
- (match_dup 1)))
+ (plus:SWI48
+ (match_operator:SWI48 5 "ix86_carry_flag_operator"
+ [(match_operand 3 "flags_reg_operand") (const_int 0)])
+ (match_operand:SWI48 1 "nonimmediate_operand" "%0"))
+ (match_operand:SWI48 2 "nonimmediate_operand" "rm")))
+ (plus:<DWI>
+ (zero_extend:<DWI> (match_dup 2))
+ (match_operator:<DWI> 4 "ix86_carry_flag_operator"
+ [(match_dup 3) (const_int 0)]))))
(set (match_operand:SWI48 0 "register_operand" "=r")
- (plus:SWI48 (plus:SWI48 (match_op_dup 4
+ (plus:SWI48 (plus:SWI48 (match_op_dup 5
[(match_dup 3) (const_int 0)])
(match_dup 1))
(match_dup 2)))]
@@ -6837,6 +6878,18 @@
(set_attr "pent_pair" "pu")
(set_attr "mode" "<MODE>")])
+(define_expand "addcarry<mode>_0"
+ [(parallel
+ [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (plus:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand")
+ (match_operand:SWI48 2 "x86_64_general_operand"))
+ (match_dup 1)))
+ (set (match_operand:SWI48 0 "register_operand")
+ (plus:SWI48 (match_dup 1) (match_dup 2)))])]
+ "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)")
+
(define_insn "sub<mode>3_carry"
[(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
(minus:SWI
@@ -6870,18 +6923,67 @@
(set_attr "pent_pair" "pu")
(set_attr "mode" "SI")])
+(define_insn "sub<mode>3_carry_ccc"
+ [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (zero_extend:<DWI> (match_operand:DWIH 1 "register_operand" "0"))
+ (plus:<DWI>
+ (ltu:<DWI> (reg:CC FLAGS_REG) (const_int 0))
+ (zero_extend:<DWI>
+ (match_operand:DWIH 2 "x86_64_sext_operand" "rmWe")))))
+ (clobber (match_scratch:DWIH 0 "=r"))]
+ ""
+ "sbb{<imodesuffix>}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*sub<mode>3_carry_ccc_1"
+ [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (zero_extend:<DWI> (match_operand:DWIH 1 "register_operand" "0"))
+ (plus:<DWI>
+ (ltu:<DWI> (reg:CC FLAGS_REG) (const_int 0))
+ (match_operand:<DWI> 2 "x86_64_dwzext_immediate_operand" "Wf"))))
+ (clobber (match_scratch:DWIH 0 "=r"))]
+ ""
+{
+ operands[3] = simplify_subreg (<MODE>mode, operands[2], <DWI>mode, 0);
+ return "sbb{<imodesuffix>}\t{%3, %0|%0, %3}";
+}
+ [(set_attr "type" "alu")
+ (set_attr "mode" "<MODE>")])
+
+;; The sign flag is set from the
+;; (compare (match_dup 1) (plus:DWIH (ltu:DWIH ...) (match_dup 2)))
+;; result, the overflow flag likewise, but the overflow flag is also
+;; set if the (plus:DWIH (ltu:DWIH ...) (match_dup 2)) overflows.
+(define_insn "sub<mode>3_carry_ccgz"
+ [(set (reg:CCGZ FLAGS_REG)
+ (unspec:CCGZ [(match_operand:DWIH 1 "register_operand" "0")
+ (match_operand:DWIH 2 "x86_64_general_operand" "rme")
+ (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))]
+ UNSPEC_SBB))
+ (clobber (match_scratch:DWIH 0 "=r"))]
+ ""
+ "sbb{<imodesuffix>}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "mode" "<MODE>")])
+
(define_insn "subborrow<mode>"
[(set (reg:CCC FLAGS_REG)
(compare:CCC
- (match_operand:SWI48 1 "nonimmediate_operand" "0")
- (plus:SWI48
- (match_operator:SWI48 4 "ix86_carry_flag_operator"
- [(match_operand 3 "flags_reg_operand") (const_int 0)])
- (match_operand:SWI48 2 "nonimmediate_operand" "rm"))))
+ (zero_extend:<DWI>
+ (match_operand:SWI48 1 "nonimmediate_operand" "0"))
+ (plus:<DWI>
+ (match_operator:<DWI> 4 "ix86_carry_flag_operator"
+ [(match_operand 3 "flags_reg_operand") (const_int 0)])
+ (zero_extend:<DWI>
+ (match_operand:SWI48 2 "nonimmediate_operand" "rm")))))
(set (match_operand:SWI48 0 "register_operand" "=r")
- (minus:SWI48 (minus:SWI48 (match_dup 1)
- (match_op_dup 4
- [(match_dup 3) (const_int 0)]))
+ (minus:SWI48 (minus:SWI48
+ (match_dup 1)
+ (match_operator:SWI48 5 "ix86_carry_flag_operator"
+ [(match_dup 3) (const_int 0)]))
(match_dup 2)))]
"ix86_binary_operator_ok (MINUS, <MODE>mode, operands)"
"sbb{<imodesuffix>}\t{%2, %0|%0, %2}"
@@ -6889,6 +6991,16 @@
(set_attr "use_carry" "1")
(set_attr "pent_pair" "pu")
(set_attr "mode" "<MODE>")])
+
+(define_expand "subborrow<mode>_0"
+ [(parallel
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC
+ (match_operand:SWI48 1 "nonimmediate_operand")
+ (match_operand:SWI48 2 "<general_operand>")))
+ (set (match_operand:SWI48 0 "register_operand")
+ (minus:SWI48 (match_dup 1) (match_dup 2)))])]
+ "ix86_binary_operator_ok (MINUS, <MODE>mode, operands)")
;; Overflow setting add instructions
@@ -12286,6 +12398,34 @@
ix86_expand_clear (operands[3]);
})
+(define_peephole2
+ [(set (reg FLAGS_REG) (match_operand 0))
+ (parallel [(set (reg FLAGS_REG) (match_operand 1))
+ (match_operand 5)])
+ (set (match_operand:QI 2 "register_operand")
+ (match_operator:QI 3 "ix86_comparison_operator"
+ [(reg FLAGS_REG) (const_int 0)]))
+ (set (match_operand 4 "any_QIreg_operand")
+ (zero_extend (match_dup 2)))]
+ "(peep2_reg_dead_p (4, operands[2])
+ || operands_match_p (operands[2], operands[4]))
+ && ! reg_overlap_mentioned_p (operands[4], operands[0])
+ && ! reg_overlap_mentioned_p (operands[4], operands[1])
+ && ! reg_set_p (operands[4], operands[5])
+ && refers_to_regno_p (FLAGS_REG, operands[1], (rtx *)NULL)
+ && peep2_regno_dead_p (0, FLAGS_REG)"
+ [(set (match_dup 6) (match_dup 0))
+ (parallel [(set (match_dup 7) (match_dup 1))
+ (match_dup 5)])
+ (set (strict_low_part (match_dup 8))
+ (match_dup 3))]
+{
+ operands[6] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG);
+ operands[7] = gen_rtx_REG (GET_MODE (operands[1]), FLAGS_REG);
+ operands[8] = gen_lowpart (QImode, operands[4]);
+ ix86_expand_clear (operands[4]);
+})
+
;; Similar, but match zero extend with andsi3.
(define_peephole2
@@ -12331,6 +12471,35 @@
operands[6] = gen_lowpart (QImode, operands[3]);
ix86_expand_clear (operands[3]);
})
+
+(define_peephole2
+ [(set (reg FLAGS_REG) (match_operand 0))
+ (parallel [(set (reg FLAGS_REG) (match_operand 1))
+ (match_operand 5)])
+ (set (match_operand:QI 2 "register_operand")
+ (match_operator:QI 3 "ix86_comparison_operator"
+ [(reg FLAGS_REG) (const_int 0)]))
+ (parallel [(set (match_operand 4 "any_QIreg_operand")
+ (zero_extend (match_dup 2)))
+ (clobber (reg:CC FLAGS_REG))])]
+ "(peep2_reg_dead_p (4, operands[2])
+ || operands_match_p (operands[2], operands[4]))
+ && ! reg_overlap_mentioned_p (operands[4], operands[0])
+ && ! reg_overlap_mentioned_p (operands[4], operands[1])
+ && ! reg_set_p (operands[4], operands[5])
+ && refers_to_regno_p (FLAGS_REG, operands[1], (rtx *)NULL)
+ && peep2_regno_dead_p (0, FLAGS_REG)"
+ [(set (match_dup 6) (match_dup 0))
+ (parallel [(set (match_dup 7) (match_dup 1))
+ (match_dup 5)])
+ (set (strict_low_part (match_dup 8))
+ (match_dup 3))]
+{
+ operands[6] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG);
+ operands[7] = gen_rtx_REG (GET_MODE (operands[1]), FLAGS_REG);
+ operands[8] = gen_lowpart (QImode, operands[4]);
+ ix86_expand_clear (operands[4]);
+})
;; Call instructions.
@@ -18135,6 +18304,28 @@
"* return output_probe_stack_range (operands[0], operands[2]);"
[(set_attr "type" "multi")])
+/* Additional processing for builtin_setjmp. Store the shadow stack pointer
+ as a forth element in jmpbuf. */
+(define_expand "builtin_setjmp_setup"
+ [(match_operand 0 "address_operand")]
+ "TARGET_SHSTK"
+{
+ if (flag_cf_protection & CF_RETURN)
+ {
+ rtx mem, reg_ssp;
+
+ mem = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0],
+ 3 * GET_MODE_SIZE (Pmode)));
+ reg_ssp = gen_reg_rtx (Pmode);
+ emit_insn (gen_rtx_SET (reg_ssp, const0_rtx));
+ emit_insn ((Pmode == SImode)
+ ? gen_rdsspsi (reg_ssp, reg_ssp)
+ : gen_rdsspdi (reg_ssp, reg_ssp));
+ emit_move_insn (mem, reg_ssp);
+ }
+ DONE;
+})
+
(define_expand "builtin_setjmp_receiver"
[(label_ref (match_operand 0))]
"!TARGET_64BIT && flag_pic"
@@ -18155,6 +18346,83 @@
DONE;
})
+(define_expand "builtin_longjmp"
+ [(match_operand 0 "address_operand")]
+ "TARGET_SHSTK"
+{
+ rtx fp, lab, stack;
+ rtx jump, label, reg_adj, reg_ssp, reg_minus, mem_buf, tmp, clob;
+ machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
+
+ /* Adjust the shadow stack pointer (ssp) to the value saved in the
+ jmp_buf. The saving was done in the builtin_setjmp_setup. */
+ if (flag_cf_protection & CF_RETURN)
+ {
+ /* Get current shadow stack pointer. The code below will check if
+ SHSTK feature is enabled. If it's not enabled RDSSP instruction
+ is a NOP. */
+ reg_ssp = gen_reg_rtx (Pmode);
+ emit_insn (gen_rtx_SET (reg_ssp, const0_rtx));
+ emit_insn ((Pmode == SImode)
+ ? gen_rdsspsi (reg_ssp, reg_ssp)
+ : gen_rdsspdi (reg_ssp, reg_ssp));
+ mem_buf = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0],
+ 3 * GET_MODE_SIZE (Pmode))),
+
+ /* Compare through substraction the saved and the current ssp to decide
+ if ssp has to be adjusted. */
+ reg_minus = gen_reg_rtx (Pmode);
+ tmp = gen_rtx_SET (reg_minus, gen_rtx_MINUS (Pmode, reg_ssp, mem_buf));
+ clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
+ tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
+ emit_insn (tmp);
+
+ /* Jump over adjustment code. */
+ label = gen_label_rtx ();
+ tmp = gen_rtx_REG (CCmode, FLAGS_REG);
+ tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
+ tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
+ gen_rtx_LABEL_REF (VOIDmode, label),
+ pc_rtx);
+ jump = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
+ JUMP_LABEL (jump) = label;
+
+ /* Adjust the ssp. */
+ reg_adj = gen_reg_rtx (Pmode);
+ tmp = gen_rtx_SET (reg_adj,
+ gen_rtx_LSHIFTRT (Pmode, negate_rtx (Pmode, reg_minus),
+ GEN_INT (3)));
+ clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
+ tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
+ emit_insn (tmp);
+ emit_insn ((Pmode == SImode)
+ ? gen_incsspsi (reg_adj)
+ : gen_incsspdi (reg_adj));
+
+ emit_label (label);
+ LABEL_NUSES (label) = 1;
+ }
+
+ /* This code is the same as in expand_buildin_longjmp. */
+ fp = gen_rtx_MEM (Pmode, operands[0]);
+ lab = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0],
+ GET_MODE_SIZE (Pmode)));
+ stack = gen_rtx_MEM (sa_mode, plus_constant (Pmode, operands[0],
+ 2 * GET_MODE_SIZE (Pmode)));
+ lab = copy_to_reg (lab);
+
+ emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
+ emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
+
+ emit_move_insn (hard_frame_pointer_rtx, fp);
+ emit_stack_restore (SAVE_NONLOCAL, stack);
+
+ emit_use (hard_frame_pointer_rtx);
+ emit_use (stack_pointer_rtx);
+ emit_indirect_jump (lab);
+})
+
+
;; Avoid redundant prefixes by splitting HImode arithmetic to SImode.
;; Do not split instructions with mask registers.
(define_split
@@ -18814,7 +19082,7 @@
(clobber (mem:BLK (scratch)))])]
"(TARGET_SINGLE_PUSH || optimize_insn_for_size_p ())
&& INTVAL (operands[0]) == -GET_MODE_SIZE (word_mode)
- && !ix86_using_red_zone ()"
+ && ix86_red_zone_size == 0"
[(clobber (match_dup 1))
(parallel [(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))
(clobber (mem:BLK (scratch)))])])
@@ -18828,7 +19096,7 @@
(clobber (mem:BLK (scratch)))])]
"(TARGET_DOUBLE_PUSH || optimize_insn_for_size_p ())
&& INTVAL (operands[0]) == -2*GET_MODE_SIZE (word_mode)
- && !ix86_using_red_zone ()"
+ && ix86_red_zone_size == 0"
[(clobber (match_dup 1))
(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))
(parallel [(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))
@@ -18843,7 +19111,7 @@
(clobber (reg:CC FLAGS_REG))])]
"(TARGET_SINGLE_PUSH || optimize_insn_for_size_p ())
&& INTVAL (operands[0]) == -GET_MODE_SIZE (word_mode)
- && !ix86_using_red_zone ()"
+ && ix86_red_zone_size == 0"
[(clobber (match_dup 1))
(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))])
@@ -18855,7 +19123,7 @@
(clobber (reg:CC FLAGS_REG))])]
"(TARGET_DOUBLE_PUSH || optimize_insn_for_size_p ())
&& INTVAL (operands[0]) == -2*GET_MODE_SIZE (word_mode)
- && !ix86_using_red_zone ()"
+ && ix86_red_zone_size == 0"
[(clobber (match_dup 1))
(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))
(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))])
@@ -19775,6 +20043,83 @@
[(set_attr "length" "2")
(set_attr "memory" "unknown")])
+;; CET instructions
+(define_insn "rdssp<mode>"
+ [(set (match_operand:SWI48x 0 "register_operand" "=r")
+ (unspec_volatile:SWI48x
+ [(match_operand:SWI48x 1 "register_operand" "0")]
+ UNSPECV_NOP_RDSSP))]
+ "TARGET_SHSTK"
+ "rdssp<mskmodesuffix>\t%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "other")])
+
+(define_insn "incssp<mode>"
+ [(unspec_volatile [(match_operand:SWI48x 0 "register_operand" "r")]
+ UNSPECV_INCSSP)]
+ "TARGET_SHSTK"
+ "incssp<mskmodesuffix>\t%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "other")])
+
+(define_insn "saveprevssp"
+ [(unspec_volatile [(const_int 0)] UNSPECV_SAVEPREVSSP)]
+ "TARGET_SHSTK"
+ "saveprevssp"
+ [(set_attr "length" "5")
+ (set_attr "type" "other")])
+
+(define_insn "rstorssp"
+ [(unspec_volatile [(match_operand 0 "memory_operand" "m")]
+ UNSPECV_RSTORSSP)]
+ "TARGET_SHSTK"
+ "rstorssp\t%0"
+ [(set_attr "length" "5")
+ (set_attr "type" "other")])
+
+(define_insn "wrss<mode>"
+ [(unspec_volatile [(match_operand:SWI48x 0 "register_operand" "r")
+ (match_operand:SWI48x 1 "memory_operand" "m")]
+ UNSPECV_WRSS)]
+ "TARGET_SHSTK"
+ "wrss<mskmodesuffix>\t%0, %1"
+ [(set_attr "length" "3")
+ (set_attr "type" "other")])
+
+(define_insn "wruss<mode>"
+ [(unspec_volatile [(match_operand:SWI48x 0 "register_operand" "r")
+ (match_operand:SWI48x 1 "memory_operand" "m")]
+ UNSPECV_WRUSS)]
+ "TARGET_SHSTK"
+ "wruss<mskmodesuffix>\t%0, %1"
+ [(set_attr "length" "4")
+ (set_attr "type" "other")])
+
+(define_insn "setssbsy"
+ [(unspec_volatile [(const_int 0)] UNSPECV_SETSSBSY)]
+ "TARGET_SHSTK"
+ "setssbsy"
+ [(set_attr "length" "4")
+ (set_attr "type" "other")])
+
+(define_insn "clrssbsy"
+ [(unspec_volatile [(match_operand 0 "memory_operand" "m")]
+ UNSPECV_CLRSSBSY)]
+ "TARGET_SHSTK"
+ "clrssbsy\t%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "other")])
+
+(define_insn "nop_endbr"
+ [(unspec_volatile [(const_int 0)] UNSPECV_NOP_ENDBR)]
+ "TARGET_IBT"
+ "*
+{ return (TARGET_64BIT)? \"endbr64\" : \"endbr32\"; }"
+ [(set_attr "length" "4")
+ (set_attr "length_immediate" "0")
+ (set_attr "modrm" "0")])
+
+;; For RTM support
(define_expand "xbegin"
[(set (match_operand:SI 0 "register_operand")
(unspec_volatile:SI [(const_int 0)] UNSPECV_XBEGIN))]