;; Attribute that specifies whether the alternative uses MOVPRFX.
(define_attr "movprfx" "no,yes" (const_string "no"))
+;; Attribute to specify that an alternative has the length of a single
+;; instruction plus a speculation barrier.
+(define_attr "sls_length" "none,retbr,casesi" (const_string "none"))
+
(define_attr "length" ""
(cond [(eq_attr "movprfx" "yes")
(const_int 8)
- ] (const_int 4)))
+
+ (eq_attr "sls_length" "retbr")
+ (cond [(match_test "!aarch64_harden_sls_retbr_p ()") (const_int 4)
+ (match_test "TARGET_SB") (const_int 8)]
+ (const_int 12))
+
+ (eq_attr "sls_length" "casesi")
+ (cond [(match_test "!aarch64_harden_sls_retbr_p ()") (const_int 16)
+ (match_test "TARGET_SB") (const_int 20)]
+ (const_int 24))
+ ]
+ (const_int 4)))
;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
;; no predicated insns.
(include "../arm/xgene1.md")
(include "thunderx2t99.md")
(include "tsv110.md")
+(include "thunderx3t110.md")
;; -------------------------------------------------------------------
;; Jumps and other miscellaneous insns
;; -------------------------------------------------------------------
(define_insn "indirect_jump"
- [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
+ [(set (pc) (match_operand 0 "pmode_register_operand" "r"))]
""
- "br\\t%0"
- [(set_attr "type" "branch")]
+ {
+ output_asm_insn ("br\\t%0", operands);
+ return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
+ }
+ [(set_attr "type" "branch")
+ (set_attr "sls_length" "retbr")]
)
(define_insn "jump"
const0_rtx),
operands[0], operands[2], operands[4]));
- operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[3]));
+ operands[2] = force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, operands[3]));
operands[2]
= gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[2], operands[0]),
UNSPEC_CASESI);
- operands[2] = gen_rtx_MEM (DImode, operands[2]);
+ operands[2] = gen_rtx_MEM (Pmode, operands[2]);
MEM_READONLY_P (operands[2]) = 1;
MEM_NOTRAP_P (operands[2]) = 1;
- emit_jump_insn (gen_casesi_dispatch (operands[2], operands[3]));
+
+ emit_jump_insn (gen_casesi_dispatch (Pmode, operands[2], operands[3]));
DONE;
}
)
-(define_expand "casesi_dispatch"
+(define_expand "@casesi_dispatch<mode>"
[(parallel
- [(set (pc) (match_operand:DI 0 ""))
+ [(set (pc) (match_operand:ADDR 0 ""))
(clobber (reg:CC CC_REGNUM))
- (clobber (match_scratch:DI 2))
- (clobber (match_scratch:DI 3))
- (use (label_ref:DI (match_operand 1 "")))])]
+ (clobber (match_scratch:ADDR 2))
+ (clobber (match_scratch:ADDR 3))
+ (use (label_ref:ADDR (match_operand 1 "")))])]
"")
(define_insn "*casesi_dispatch"
[(parallel
[(set (pc)
- (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
- (match_operand:SI 1 "register_operand" "r")]
+ (mem:ADDR (unspec [(match_operand:ADDR 0 "register_operand" "r")
+ (match_operand:SI 1 "register_operand" "r")]
UNSPEC_CASESI)))
(clobber (reg:CC CC_REGNUM))
- (clobber (match_scratch:DI 3 "=r"))
- (clobber (match_scratch:DI 4 "=r"))
- (use (label_ref:DI (match_operand 2 "" "")))])]
+ (clobber (match_scratch:ADDR 3 "=r"))
+ (clobber (match_scratch:ADDR 4 "=r"))
+ (use (label_ref:ADDR (match_operand 2 "" "")))])]
""
"*
return aarch64_output_casesi (operands);
"
- [(set_attr "length" "16")
+ [(set_attr "sls_length" "casesi")
(set_attr "type" "branch")]
)
[(return)]
""
{
+ const char *ret = NULL;
if (aarch64_return_address_signing_enabled ()
&& TARGET_ARMV8_3
&& !crtl->calls_eh_return)
{
if (aarch64_ra_sign_key == AARCH64_KEY_B)
- return "retab";
+ ret = "retab";
else
- return "retaa";
+ ret = "retaa";
}
- return "ret";
+ else
+ ret = "ret";
+ output_asm_insn (ret, operands);
+ return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
}
- [(set_attr "type" "branch")]
+ [(set_attr "type" "branch")
+ (set_attr "sls_length" "retbr")]
)
(define_expand "return"
(define_insn "simple_return"
[(simple_return)]
""
- "ret"
- [(set_attr "type" "branch")]
+ {
+ output_asm_insn ("ret", operands);
+ return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
+ }
+ [(set_attr "type" "branch")
+ (set_attr "sls_length" "retbr")]
)
(define_insn "*cb<optab><mode>1"
)
(define_insn "*call_insn"
- [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "r, Usf"))
+ [(call (mem:DI (match_operand:ADDR 0 "aarch64_call_insn_operand" "Ucr, Usf"))
(match_operand 1 "" ""))
(unspec:DI [(match_operand:DI 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
- (clobber (reg:DI LR_REGNUM))]
+ (clobber (reg:ADDR LR_REGNUM))]
""
"@
- blr\\t%0
+ * return aarch64_indirect_call_asm (operands[0]);
bl\\t%c0"
- [(set_attr "type" "call, call")]
-)
+ [(set_attr "type" "call, call")])
(define_expand "call_value"
[(parallel
(define_insn "*call_value_insn"
[(set (match_operand 0 "" "")
- (call (mem:DI (match_operand:DI 1 "aarch64_call_insn_operand" "r, Usf"))
+ (call (mem:DI (match_operand:ADDR 1 "aarch64_call_insn_operand" "Ucr, Usf"))
(match_operand 2 "" "")))
(unspec:DI [(match_operand:DI 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
- (clobber (reg:DI LR_REGNUM))]
+ (clobber (reg:ADDR LR_REGNUM))]
""
"@
- blr\\t%1
+ * return aarch64_indirect_call_asm (operands[1]);
bl\\t%c1"
[(set_attr "type" "call, call")]
)
)
(define_insn "*sibcall_insn"
- [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
+ [(call (mem:DI (match_operand:ADDR 0 "aarch64_call_insn_operand" "Ucs, Usf"))
(match_operand 1 ""))
(unspec:DI [(match_operand:DI 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
(return)]
"SIBLING_CALL_P (insn)"
- "@
- br\\t%0
- b\\t%c0"
- [(set_attr "type" "branch, branch")]
+ {
+ if (which_alternative == 0)
+ {
+ output_asm_insn ("br\\t%0", operands);
+ return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
+ }
+ return "b\\t%c0";
+ }
+ [(set_attr "type" "branch, branch")
+ (set_attr "sls_length" "retbr,none")]
)
(define_insn "*sibcall_value_insn"
[(set (match_operand 0 "")
(call (mem:DI
- (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
+ (match_operand:ADDR 1 "aarch64_call_insn_operand" "Ucs, Usf"))
(match_operand 2 "")))
(unspec:DI [(match_operand:DI 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
(return)]
"SIBLING_CALL_P (insn)"
- "@
- br\\t%1
- b\\t%c1"
- [(set_attr "type" "branch, branch")]
+ {
+ if (which_alternative == 0)
+ {
+ output_asm_insn ("br\\t%1", operands);
+ return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
+ }
+ return "b\\t%c1";
+ }
+ [(set_attr "type" "branch, branch")
+ (set_attr "sls_length" "retbr,none")]
)
;; Call subroutine returning any type.
)
(define_expand "mov<mode>"
- [(set (match_operand:GPI 0 "nonimmediate_operand")
- (match_operand:GPI 1 "general_operand"))]
+ [(set (match_operand:GPIC 0 "nonimmediate_operand")
+ (match_operand:GPIC 1 "general_operand"))]
""
"
if (MEM_P (operands[0]) && !MEM_VOLATILE_P (operands[0])
[(set_attr "type" "mov_imm")]
)
+;; Match MOVK as a normal AND and IOR operation.
+(define_insn "aarch64_movk<mode>"
+ [(set (match_operand:GPI 0 "register_operand" "=r")
+ (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "0")
+ (match_operand:GPI 2 "const_int_operand"))
+ (match_operand:GPI 3 "const_int_operand")))]
+ "aarch64_movk_shift (rtx_mode_t (operands[2], <MODE>mode),
+ rtx_mode_t (operands[3], <MODE>mode)) >= 0"
+ {
+ int shift = aarch64_movk_shift (rtx_mode_t (operands[2], <MODE>mode),
+ rtx_mode_t (operands[3], <MODE>mode));
+ operands[2] = gen_int_mode (UINTVAL (operands[3]) >> shift, SImode);
+ operands[3] = gen_int_mode (shift, SImode);
+ return "movk\\t%<w>0, #%X2, lsl %3";
+ }
+ [(set_attr "type" "mov_imm")]
+)
+
(define_expand "movti"
[(set (match_operand:TI 0 "nonimmediate_operand")
(match_operand:TI 1 "general_operand"))]
if (!TARGET_FLOAT)
{
aarch64_err_no_fpadvsimd (<MODE>mode);
- FAIL;
+ machine_mode intmode
+ = int_mode_for_size (GET_MODE_BITSIZE (<MODE>mode), 0).require ();
+ emit_move_insn (gen_lowpart (intmode, operands[0]),
+ gen_lowpart (intmode, operands[1]));
+ DONE;
}
if (GET_CODE (operands[0]) == MEM
XEXP (operands[1], 0),
GET_MODE_SIZE (<SX:MODE>mode)))"
"@
- ldp\\t%w0, %w2, %1
- ldp\\t%s0, %s2, %1"
+ ldp\\t%w0, %w2, %z1
+ ldp\\t%s0, %s2, %z1"
[(set_attr "type" "load_8,neon_load1_2reg")
(set_attr "arch" "*,fp")]
)
XEXP (operands[1], 0),
GET_MODE_SIZE (<DX:MODE>mode)))"
"@
- ldp\\t%x0, %x2, %1
- ldp\\t%d0, %d2, %1"
+ ldp\\t%x0, %x2, %z1
+ ldp\\t%d0, %d2, %z1"
[(set_attr "type" "load_16,neon_load1_2reg")
(set_attr "arch" "*,fp")]
)
plus_constant (Pmode,
XEXP (operands[1], 0),
GET_MODE_SIZE (TFmode)))"
- "ldp\\t%q0, %q2, %1"
+ "ldp\\t%q0, %q2, %z1"
[(set_attr "type" "neon_ldp_q")
(set_attr "fp" "yes")]
)
XEXP (operands[0], 0),
GET_MODE_SIZE (<SX:MODE>mode)))"
"@
- stp\\t%w1, %w3, %0
- stp\\t%s1, %s3, %0"
+ stp\\t%w1, %w3, %z0
+ stp\\t%s1, %s3, %z0"
[(set_attr "type" "store_8,neon_store1_2reg")
(set_attr "arch" "*,fp")]
)
XEXP (operands[0], 0),
GET_MODE_SIZE (<DX:MODE>mode)))"
"@
- stp\\t%x1, %x3, %0
- stp\\t%d1, %d3, %0"
+ stp\\t%x1, %x3, %z0
+ stp\\t%d1, %d3, %z0"
[(set_attr "type" "store_16,neon_store1_2reg")
(set_attr "arch" "*,fp")]
)
plus_constant (Pmode,
XEXP (operands[0], 0),
GET_MODE_SIZE (TFmode)))"
- "stp\\t%q1, %q3, %0"
+ "stp\\t%q1, %q3, %z0"
[(set_attr "type" "neon_stp_q")
(set_attr "fp" "yes")]
)
;; Load pair with post-index writeback. This is primarily used in function
;; epilogues.
-(define_insn "loadwb_pair<GPI:mode>_<P:mode>"
+;;
+;; MORELLO TODO: pure-cap.
+(define_insn "@loadwb_pair<GPI:mode>_<ADDR:mode>"
[(parallel
- [(set (match_operand:P 0 "register_operand" "=k")
- (plus:P (match_operand:P 1 "register_operand" "0")
- (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
+ [(set (match_operand:ADDR 0 "register_operand" "=k")
+ (<ADDR:PLUS>:ADDR
+ (match_operand:ADDR 1 "register_operand" "0")
+ (match_operand:DI 4 "aarch64_mem_pair_offset" "n")))
(set (match_operand:GPI 2 "register_operand" "=r")
(mem:GPI (match_dup 1)))
(set (match_operand:GPI 3 "register_operand" "=r")
- (mem:GPI (plus:P (match_dup 1)
- (match_operand:P 5 "const_int_operand" "n"))))])]
+ (mem:GPI (<ADDR:PLUS>:ADDR
+ (match_dup 1)
+ (match_operand:DI 5 "const_int_operand" "n"))))])]
"INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
"ldp\\t%<GPI:w>2, %<GPI:w>3, [%1], %4"
[(set_attr "type" "load_<GPI:ldpstp_sz>")]
)
-(define_insn "loadwb_pair<GPF:mode>_<P:mode>"
+(define_insn "@loadwb_pair<GPF:mode>_<ADDR:mode>"
[(parallel
- [(set (match_operand:P 0 "register_operand" "=k")
- (plus:P (match_operand:P 1 "register_operand" "0")
- (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
+ [(set (match_operand:ADDR 0 "register_operand" "=k")
+ (<ADDR:PLUS>:ADDR
+ (match_operand:ADDR 1 "register_operand" "0")
+ (match_operand:DI 4 "aarch64_mem_pair_offset" "n")))
(set (match_operand:GPF 2 "register_operand" "=w")
(mem:GPF (match_dup 1)))
(set (match_operand:GPF 3 "register_operand" "=w")
- (mem:GPF (plus:P (match_dup 1)
- (match_operand:P 5 "const_int_operand" "n"))))])]
+ (mem:GPF (<ADDR:PLUS>:ADDR
+ (match_dup 1)
+ (match_operand:DI 5 "const_int_operand" "n"))))])]
"INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
"ldp\\t%<GPF:w>2, %<GPF:w>3, [%1], %4"
[(set_attr "type" "neon_load1_2reg")]
)
-(define_insn "loadwb_pair<TX:mode>_<P:mode>"
+(define_insn "@loadwb_pair<TX:mode>_<ADDR:mode>"
[(parallel
- [(set (match_operand:P 0 "register_operand" "=k")
- (plus:P (match_operand:P 1 "register_operand" "0")
- (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
+ [(set (match_operand:ADDR 0 "register_operand" "=k")
+ (<ADDR:PLUS>:ADDR
+ (match_operand:ADDR 1 "register_operand" "0")
+ (match_operand:DI 4 "aarch64_mem_pair_offset" "n")))
(set (match_operand:TX 2 "register_operand" "=w")
(mem:TX (match_dup 1)))
(set (match_operand:TX 3 "register_operand" "=w")
- (mem:TX (plus:P (match_dup 1)
- (match_operand:P 5 "const_int_operand" "n"))))])]
+ (mem:TX (<ADDR:PLUS>:ADDR
+ (match_dup 1)
+ (match_operand:DI 5 "const_int_operand" "n"))))])]
"TARGET_SIMD && INTVAL (operands[5]) == GET_MODE_SIZE (<TX:MODE>mode)"
"ldp\\t%q2, %q3, [%1], %4"
[(set_attr "type" "neon_ldp_q")]
;; Store pair with pre-index writeback. This is primarily used in function
;; prologues.
-(define_insn "storewb_pair<GPI:mode>_<P:mode>"
+;;
+;; MORELLO TODO: pure-cap.
+(define_insn "@storewb_pair<GPI:mode>_<ADDR:mode>"
[(parallel
- [(set (match_operand:P 0 "register_operand" "=&k")
- (plus:P (match_operand:P 1 "register_operand" "0")
- (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
- (set (mem:GPI (plus:P (match_dup 0)
- (match_dup 4)))
+ [(set (match_operand:ADDR 0 "register_operand" "=&k")
+ (<ADDR:PLUS>:ADDR
+ (match_operand:ADDR 1 "register_operand" "0")
+ (match_operand:DI 4 "aarch64_mem_pair_offset" "n")))
+ (set (mem:GPI (<ADDR:PLUS>:ADDR (match_dup 0) (match_dup 4)))
(match_operand:GPI 2 "register_operand" "r"))
- (set (mem:GPI (plus:P (match_dup 0)
- (match_operand:P 5 "const_int_operand" "n")))
+ (set (mem:GPI (<ADDR:PLUS>:ADDR
+ (match_dup 0)
+ (match_operand:DI 5 "const_int_operand" "n")))
(match_operand:GPI 3 "register_operand" "r"))])]
"INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
"stp\\t%<GPI:w>2, %<GPI:w>3, [%0, %4]!"
[(set_attr "type" "store_<GPI:ldpstp_sz>")]
)
-(define_insn "storewb_pair<GPF:mode>_<P:mode>"
+(define_insn "@storewb_pair<GPF:mode>_<ADDR:mode>"
[(parallel
- [(set (match_operand:P 0 "register_operand" "=&k")
- (plus:P (match_operand:P 1 "register_operand" "0")
- (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
- (set (mem:GPF (plus:P (match_dup 0)
- (match_dup 4)))
+ [(set (match_operand:ADDR 0 "register_operand" "=&k")
+ (<ADDR:PLUS>:ADDR
+ (match_operand:ADDR 1 "register_operand" "0")
+ (match_operand:DI 4 "aarch64_mem_pair_offset" "n")))
+ (set (mem:GPF (<ADDR:PLUS>:ADDR (match_dup 0) (match_dup 4)))
(match_operand:GPF 2 "register_operand" "w"))
- (set (mem:GPF (plus:P (match_dup 0)
- (match_operand:P 5 "const_int_operand" "n")))
+ (set (mem:GPF (<ADDR:PLUS>:ADDR
+ (match_dup 0)
+ (match_operand:DI 5 "const_int_operand" "n")))
(match_operand:GPF 3 "register_operand" "w"))])]
"INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
"stp\\t%<GPF:w>2, %<GPF:w>3, [%0, %4]!"
[(set_attr "type" "neon_store1_2reg<q>")]
)
-(define_insn "storewb_pair<TX:mode>_<P:mode>"
+(define_insn "@storewb_pair<TX:mode>_<ADDR:mode>"
[(parallel
- [(set (match_operand:P 0 "register_operand" "=&k")
- (plus:P (match_operand:P 1 "register_operand" "0")
- (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
- (set (mem:TX (plus:P (match_dup 0)
- (match_dup 4)))
+ [(set (match_operand:ADDR 0 "register_operand" "=&k")
+ (<ADDR:PLUS>:ADDR
+ (match_operand:ADDR 1 "register_operand" "0")
+ (match_operand:DI 4 "aarch64_mem_pair_offset" "n")))
+ (set (mem:TX (<ADDR:PLUS>:ADDR (match_dup 0) (match_dup 4)))
(match_operand:TX 2 "register_operand" "w"))
- (set (mem:TX (plus:P (match_dup 0)
- (match_operand:P 5 "const_int_operand" "n")))
+ (set (mem:TX (<ADDR:PLUS>:ADDR
+ (match_dup 0)
+ (match_operand:DI 5 "const_int_operand" "n")))
(match_operand:TX 3 "register_operand" "w"))])]
"TARGET_SIMD
&& INTVAL (operands[5])
plus_constant (Pmode,
XEXP (operands[1], 0),
GET_MODE_SIZE (SImode)))"
- "ldpsw\\t%0, %2, %1"
+ "ldpsw\\t%0, %2, %z1"
[(set_attr "type" "load_8")]
)
XEXP (operands[1], 0),
GET_MODE_SIZE (SImode)))"
"@
- ldp\t%w0, %w2, %1
- ldp\t%s0, %s2, %1"
+ ldp\t%w0, %w2, %z1
+ ldp\t%s0, %s2, %z1"
[(set_attr "type" "load_8,neon_load1_2reg")
(set_attr "arch" "*,fp")]
)
[(set_attr "type" "csel")]
)
+(define_insn "*csinv3_uxtw_insn1"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (if_then_else:DI
+ (match_operand 1 "aarch64_comparison_operation" "")
+ (zero_extend:DI
+ (match_operand:SI 2 "register_operand" "r"))
+ (zero_extend:DI
+ (NEG_NOT:SI (match_operand:SI 3 "register_operand" "r")))))]
+ ""
+ "cs<neg_not_cs>\\t%w0, %w2, %w3, %m1"
+ [(set_attr "type" "csel")]
+)
+
+(define_insn "*csinv3_uxtw_insn2"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (if_then_else:DI
+ (match_operand 1 "aarch64_comparison_operation" "")
+ (zero_extend:DI
+ (NEG_NOT:SI (match_operand:SI 2 "register_operand" "r")))
+ (zero_extend:DI
+ (match_operand:SI 3 "register_operand" "r"))))]
+ ""
+ "cs<neg_not_cs>\\t%w0, %w3, %w2, %M1"
+ [(set_attr "type" "csel")]
+)
+
+(define_insn "*csinv3_uxtw_insn3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (if_then_else:DI
+ (match_operand 1 "aarch64_comparison_operation" "")
+ (zero_extend:DI
+ (NEG_NOT:SI (match_operand:SI 2 "register_operand" "r")))
+ (const_int 0)))]
+ ""
+ "cs<neg_not_cs>\\t%w0, wzr, %w2, %M1"
+ [(set_attr "type" "csel")]
+)
+
;; If X can be loaded by a single CNT[BHWD] instruction,
;;
;; A = UMAX (B, X)
(set_attr "arch" "*,simd")]
)
+(define_insn "*one_cmpl_zero_extend"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI
+ (not:SI (match_operand:SI 1 "register_operand" "r"))))]
+ ""
+ "mvn\\t%w0, %w1"
+ [(set_attr "type" "logic_reg")]
+)
+
(define_insn "*one_cmpl_<optab><mode>2"
[(set (match_operand:GPI 0 "register_operand" "=r")
(not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
{
rtx v = gen_reg_rtx (V8QImode);
rtx v1 = gen_reg_rtx (V8QImode);
- rtx r = gen_reg_rtx (QImode);
rtx in = operands[1];
rtx out = operands[0];
if(<MODE>mode == SImode)
}
emit_move_insn (v, gen_lowpart (V8QImode, in));
emit_insn (gen_popcountv8qi2 (v1, v));
- emit_insn (gen_reduc_plus_scal_v8qi (r, v1));
- emit_insn (gen_zero_extendqi<mode>2 (out, r));
+ emit_insn (gen_aarch64_zero_extend<mode>_reduc_plus_v8qi (out, v1));
DONE;
})
""
{
machine_mode mode = GET_MODE (operands[0]);
-
- emit_insn ((mode == DImode
- ? gen_add_losym_di
- : gen_add_losym_si) (operands[0],
- operands[1],
- operands[2]));
+ emit_insn (gen_add_losym (mode, operands[0], operands[1], operands[2]));
DONE;
})
-(define_insn "add_losym_<mode>"
+(define_insn "@add_losym_<mode>"
[(set (match_operand:P 0 "register_operand" "=r")
(lo_sum:P (match_operand:P 1 "register_operand" "r")
(match_operand 2 "aarch64_valid_symref" "S")))]
[(set_attr "type" "alu_imm")]
)
-(define_insn "ldr_got_small_<mode>"
+(define_insn "@ldr_got_small_<mode>"
[(set (match_operand:PTR 0 "register_operand" "=r")
(unspec:PTR [(mem:PTR (lo_sum:PTR
(match_operand:PTR 1 "register_operand" "r")
[(set_attr "type" "load_4")]
)
-(define_insn "ldr_got_small_28k_<mode>"
+(define_insn "@ldr_got_small_28k_<mode>"
[(set (match_operand:PTR 0 "register_operand" "=r")
(unspec:PTR [(mem:PTR (lo_sum:PTR
(match_operand:PTR 1 "register_operand" "r")
[(set_attr "type" "load_4")]
)
-(define_insn "ldr_got_tiny"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
- UNSPEC_GOTTINYPIC))]
+(define_insn "@ldr_got_tiny_<mode>"
+ [(set (match_operand:PTR 0 "register_operand" "=r")
+ (unspec:PTR [(match_operand:PTR 1 "aarch64_valid_symref" "S")]
+ UNSPEC_GOTTINYPIC))]
""
- "ldr\\t%0, %L1"
- [(set_attr "type" "load_8")]
+ "ldr\t%<w>0, %L1"
+ [(set_attr "type" "load_<ldst_sz>")]
)
-(define_insn "aarch64_load_tp_hard"
+(define_insn "ldr_got_tiny_sidi"
[(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(const_int 0)] UNSPEC_TLS))]
+ (zero_extend:DI
+ (unspec:SI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
+ UNSPEC_GOTTINYPIC)))]
+ "TARGET_ILP32"
+ "ldr\t%w0, %L1"
+ [(set_attr "type" "load_4")]
+)
+
+(define_insn "@aarch64_load_tp_hard_<mode>"
+ [(set (match_operand:ADDR 0 "register_operand" "=r")
+ (unspec:ADDR [(const_int 0)] UNSPEC_TLS))]
""
"mrs\\t%0, tpidr_el0"
[(set_attr "type" "mrs")]
[(set_attr "type" "call")
(set_attr "length" "16")])
-(define_insn "tlsie_small_<mode>"
- [(set (match_operand:PTR 0 "register_operand" "=r")
- (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
+(define_insn "@tlsie_small_<mode>"
+ [(set (match_operand:<PTR_OFF> 0 "register_operand" "=r")
+ (unspec:<PTR_OFF>
+ [(match_operand 1 "aarch64_tls_ie_symref" "S")
+ (match_operand:PTR 2 "register_operand" "r")]
UNSPEC_GOTSMALLTLS))]
- ""
+ "aarch64_lowpart_regs_p (operands[0], operands[2])"
"adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
[(set_attr "type" "load_4")
(set_attr "length" "8")]
(set_attr "length" "8")]
)
-(define_insn "tlsie_tiny_<mode>"
+(define_insn "@tlsie_tiny_<mode>"
[(set (match_operand:PTR 0 "register_operand" "=&r")
(unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
(match_operand:PTR 2 "register_operand" "r")]
(set_attr "length" "8")]
)
-(define_insn "tlsle12_<mode>"
+(define_insn "@tlsle12_<mode>"
[(set (match_operand:P 0 "register_operand" "=r")
(unspec:P [(match_operand:P 1 "register_operand" "r")
(match_operand 2 "aarch64_tls_le_symref" "S")]
(set_attr "length" "4")]
)
-(define_insn "tlsle24_<mode>"
+(define_insn "@tlsle24_<mode>"
[(set (match_operand:P 0 "register_operand" "=r")
(unspec:P [(match_operand:P 1 "register_operand" "r")
(match_operand 2 "aarch64_tls_le_symref" "S")]
(set_attr "length" "8")]
)
-(define_insn "tlsle32_<mode>"
+(define_insn "@tlsle32_<mode>"
[(set (match_operand:P 0 "register_operand" "=r")
(unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
UNSPEC_TLSLE32))]
(set_attr "length" "8")]
)
-(define_insn "tlsle48_<mode>"
+(define_insn "@tlsle48_<mode>"
[(set (match_operand:P 0 "register_operand" "=r")
(unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
UNSPEC_TLSLE48))]
(set_attr "length" "12")]
)
-(define_expand "tlsdesc_small_<mode>"
+(define_expand "@tlsdesc_small_<mode>"
[(unspec:PTR [(match_operand 0 "aarch64_valid_symref")] UNSPEC_TLSDESC)]
"TARGET_TLS_DESC"
{
[(set (reg:PTR R0_REGNUM)
(unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
UNSPEC_TLSDESC))
- (clobber (reg:DI LR_REGNUM))
+ (clobber (reg:<P_OF_PTR> LR_REGNUM))
(clobber (reg:CC CC_REGNUM))
- (clobber (match_scratch:DI 1 "=r"))
- (use (reg:DI FP_REGNUM))]
+ (clobber (match_scratch:<P_OF_PTR> 1 "=r"))
+ (use (reg:<P_OF_PTR> FP_REGNUM))]
"TARGET_TLS_DESC && !TARGET_SVE"
- "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
+ {
+ if (<MODE>mode == CADImode)
+ return "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\tx0, x0, %L0\;.tlsdesccall\\t%0\;blr\\t%1";
+ else
+ return "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1";
+ }
[(set_attr "type" "call")
(set_attr "length" "16")])
(define_insn "stack_tie"
[(set (mem:BLK (scratch))
- (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
- (match_operand:DI 1 "register_operand" "rk")]
+ (unspec:BLK [(match_operand 0 "pmode_register_operand" "rk")
+ (match_operand 1 "pmode_register_operand" "rk")]
UNSPEC_PRLG_STK))]
""
""
(define_insn "aarch64_fjcvtzs"
[(set (match_operand:SI 0 "register_operand" "=r")
(unspec:SI [(match_operand:DF 1 "register_operand" "w")]
- UNSPEC_FJCVTZS))]
+ UNSPEC_FJCVTZS))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_JSCVT"
"fjcvtzs\\t%w0, %d1"
[(set_attr "type" "f_cvtf2i")]
(set_attr "type" "block")]
)
-(define_insn "probe_stack_range"
- [(set (match_operand:DI 0 "register_operand" "=rk")
- (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "register_operand" "r")]
+(define_insn "probe_stack_range_<mode>"
+ [(set (match_operand:ADDR 0 "register_operand" "=rk")
+ (unspec_volatile:ADDR [(match_operand:ADDR 1 "register_operand" "0")
+ (match_operand:ADDR 2 "register_operand" "r")]
UNSPECV_PROBE_STACK_RANGE))]
""
{
;; probing loop. We can't change the control flow during prologue and epilogue
;; code generation. So we must emit a volatile unspec and expand it later on.
+;; MORELLO TODO The pattern here uses Pmode for everything, but the
+;; min_probe_threshold, adjustment, and guard_size should all be in POmode.
(define_insn "@probe_sve_stack_clash_<mode>"
[(set (match_operand:P 0 "register_operand" "=rk")
(unspec_volatile:P [(match_operand:P 1 "register_operand" "0")
{
/* Generate access through the system register. */
rtx tmp_reg = gen_reg_rtx (mode);
- if (mode == DImode)
- {
- emit_insn (gen_reg_stack_protect_address_di (tmp_reg));
- emit_insn (gen_adddi3 (tmp_reg, tmp_reg,
- GEN_INT (aarch64_stack_protector_guard_offset)));
- }
- else
- {
- emit_insn (gen_reg_stack_protect_address_si (tmp_reg));
- emit_insn (gen_addsi3 (tmp_reg, tmp_reg,
- GEN_INT (aarch64_stack_protector_guard_offset)));
-
- }
+ emit_insn (gen_reg_stack_protect_address (mode, tmp_reg));
+ emit_insn (gen_add3_insn (tmp_reg, tmp_reg,
+ GEN_INT (aarch64_stack_protector_guard_offset)));
operands[1] = gen_rtx_MEM (mode, tmp_reg);
}
-
- emit_insn ((mode == DImode
- ? gen_stack_protect_set_di
- : gen_stack_protect_set_si) (operands[0], operands[1]));
+
+ emit_insn (gen_stack_protect_set (mode, operands[0], operands[1]));
DONE;
})
-(define_insn "reg_stack_protect_address_<mode>"
+(define_insn "@reg_stack_protect_address_<mode>"
[(set (match_operand:PTR 0 "register_operand" "=r")
(unspec:PTR [(const_int 0)]
UNSPEC_SSP_SYSREG))]
;; DO NOT SPLIT THIS PATTERN. It is important for security reasons that the
;; canary value does not live beyond the life of this sequence.
-(define_insn "stack_protect_set_<mode>"
+(define_insn "@stack_protect_set_<mode>"
[(set (match_operand:PTR 0 "memory_operand" "=m")
(unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
UNSPEC_SP_SET))
(match_operand 2)]
""
{
- rtx result;
machine_mode mode = GET_MODE (operands[0]);
- result = gen_reg_rtx(mode);
if (aarch64_stack_protector_guard != SSP_GLOBAL)
{
/* Generate access through the system register. The
mrs scratch_reg, <system_register>
add scratch_reg, scratch_reg, :lo12:offset. */
rtx tmp_reg = gen_reg_rtx (mode);
- if (mode == DImode)
- {
- emit_insn (gen_reg_stack_protect_address_di (tmp_reg));
- emit_insn (gen_adddi3 (tmp_reg, tmp_reg,
- GEN_INT (aarch64_stack_protector_guard_offset)));
- }
- else
- {
- emit_insn (gen_reg_stack_protect_address_si (tmp_reg));
- emit_insn (gen_addsi3 (tmp_reg, tmp_reg,
- GEN_INT (aarch64_stack_protector_guard_offset)));
- }
+ emit_insn (gen_reg_stack_protect_address (mode, tmp_reg));
+ emit_insn (gen_add3_insn (tmp_reg, tmp_reg,
+ GEN_INT (aarch64_stack_protector_guard_offset)));
operands[1] = gen_rtx_MEM (mode, tmp_reg);
}
- emit_insn ((mode == DImode
- ? gen_stack_protect_test_di
- : gen_stack_protect_test_si) (result,
- operands[0],
- operands[1]));
-
- if (mode == DImode)
- emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
- result, const0_rtx, operands[2]));
- else
- emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
- result, const0_rtx, operands[2]));
+ emit_insn (gen_stack_protect_test (mode, operands[0], operands[1]));
+
+ rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
+ emit_jump_insn (gen_condjump (gen_rtx_EQ (VOIDmode, cc_reg, const0_rtx),
+ cc_reg, operands[2]));
DONE;
})
-(define_insn "stack_protect_test_<mode>"
- [(set (match_operand:PTR 0 "register_operand" "=r")
- (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
- (match_operand:PTR 2 "memory_operand" "m")]
- UNSPEC_SP_TEST))
+;; DO NOT SPLIT THIS PATTERN. It is important for security reasons that the
+;; canary value does not live beyond the end of this sequence.
+(define_insn "@stack_protect_test_<mode>"
+ [(set (reg:CC CC_REGNUM)
+ (unspec:CC [(match_operand:PTR 0 "memory_operand" "m")
+ (match_operand:PTR 1 "memory_operand" "m")]
+ UNSPEC_SP_TEST))
+ (clobber (match_scratch:PTR 2 "=&r"))
(clobber (match_scratch:PTR 3 "=&r"))]
""
- "ldr\t%<w>3, %1\;ldr\t%<w>0, %2\;eor\t%<w>0, %<w>3, %<w>0"
- [(set_attr "length" "12")
+ "ldr\t%<w>2, %0\;ldr\t%<w>3, %1\;subs\t%<w>2, %<w>2, %<w>3\;mov\t%3, 0"
+ [(set_attr "length" "16")
(set_attr "type" "multiple")])
-;; Write Floating-point Control Register.
-(define_insn "set_fpcr"
- [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
- ""
- "msr\\tfpcr, %0"
- [(set_attr "type" "mrs")])
-
-;; Read Floating-point Control Register.
-(define_insn "get_fpcr"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
- ""
- "mrs\\t%0, fpcr"
- [(set_attr "type" "mrs")])
-
-;; Write Floating-point Status Register.
-(define_insn "set_fpsr"
- [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
+;; Write into the Floating-point Status or Control Register.
+(define_insn "@aarch64_set_<fpscr_name><GPI:mode>"
+ [(unspec_volatile [(match_operand:GPI 0 "register_operand" "r")] SET_FPSCR)]
""
- "msr\\tfpsr, %0"
+ "msr\\t<fpscr_name>, %0"
[(set_attr "type" "mrs")])
-;; Read Floating-point Status Register.
-(define_insn "get_fpsr"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
+;; Read into the Floating-point Status or Control Register.
+(define_insn "@aarch64_get_<fpscr_name><GPI:mode>"
+ [(set (match_operand:GPI 0 "register_operand" "=r")
+ (unspec_volatile:GPI [(const_int 0)] GET_FPSCR))]
""
- "mrs\\t%0, fpsr"
+ "mrs\\t%0, <fpscr_name>"
[(set_attr "type" "mrs")])
-
;; Define the subtract-one-and-jump insns so loop.c
;; knows what to generate.
(define_expand "doloop_end"
;; SVE2.
(include "aarch64-sve2.md")
+
+;; Morello
+(include "aarch64-morello.md")