]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/config/aarch64/aarch64.md
aarch64: Fix up casesi patterns for purecap
[gcc.git] / gcc / config / aarch64 / aarch64.md
index e4f9005c27f6f57efba31004389dbed9fd91a360..d885eb8de3e464bed961603435dac3f8373e71b5 100644 (file)
@@ -1,5 +1,5 @@
 ;; Machine description for AArch64 architecture.
-;; Copyright (C) 2009-2019 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2020 Free Software Foundation, Inc.
 ;; Contributed by ARM Ltd.
 ;;
 ;; This file is part of GCC.
@@ -85,7 +85,6 @@
     (V29_REGNUM                61)
     (V30_REGNUM                62)
     (V31_REGNUM                63)
-    (LAST_SAVED_REGNUM 63)
     (SFP_REGNUM                64)
     (AP_REGNUM         65)
     (CC_REGNUM         66)
     (P13_REGNUM                81)
     (P14_REGNUM                82)
     (P15_REGNUM                83)
+    (LAST_SAVED_REGNUM 83)
+    (FFR_REGNUM                84)
+    ;; "FFR token": a fake register used for representing the scheduling
+    ;; restrictions on FFR-related operations.
+    (FFRT_REGNUM       85)
     ;; Scratch register used by stack clash protection to calculate
     ;; SVE CFA offsets during probing.
     (STACK_CLASH_SVE_CFA_REGNUM 11)
     UNSPEC_AUTIB1716
     UNSPEC_AUTIASP
     UNSPEC_AUTIBSP
+    UNSPEC_CALLEE_ABI
     UNSPEC_CASESI
     UNSPEC_CRC32B
     UNSPEC_CRC32CB
     UNSPEC_XPACLRI
     UNSPEC_LD1_SVE
     UNSPEC_ST1_SVE
+    UNSPEC_LDNT1_SVE
+    UNSPEC_STNT1_SVE
     UNSPEC_LD1RQ
     UNSPEC_LD1_GATHER
+    UNSPEC_LDFF1_GATHER
+    UNSPEC_LDNT1_GATHER
     UNSPEC_ST1_SCATTER
+    UNSPEC_STNT1_SCATTER
     UNSPEC_PRED_X
     UNSPEC_PRED_Z
     UNSPEC_PTEST
+    UNSPEC_PTRUE
     UNSPEC_UNPACKSHI
     UNSPEC_UNPACKUHI
     UNSPEC_UNPACKSLO
     UNSPEC_UNPACKULO
     UNSPEC_PACK
-    UNSPEC_WHILE_LO
+    UNSPEC_WHILEGE
+    UNSPEC_WHILEGT
+    UNSPEC_WHILEHI
+    UNSPEC_WHILEHS
+    UNSPEC_WHILELE
+    UNSPEC_WHILELO
+    UNSPEC_WHILELS
+    UNSPEC_WHILELT
+    UNSPEC_WHILERW
+    UNSPEC_WHILEWR
     UNSPEC_LDN
     UNSPEC_STN
     UNSPEC_INSR
+    UNSPEC_CLASTA
     UNSPEC_CLASTB
     UNSPEC_FADDA
     UNSPEC_REV_SUBREG
     UNSPEC_REINTERPRET
     UNSPEC_SPECULATION_TRACKER
+    UNSPEC_SPECULATION_TRACKER_REV
     UNSPEC_COPYSIGN
     UNSPEC_TTEST               ; Represent transaction test.
+    UNSPEC_UPDATE_FFR
+    UNSPEC_UPDATE_FFRT
+    UNSPEC_RDFFR
+    UNSPEC_WRFFR
+    ;; Represents an SVE-style lane index, in which the indexing applies
+    ;; within the containing 128-bit block.
+    UNSPEC_SVE_LANE_SELECT
+    UNSPEC_SVE_CNT_PAT
+    UNSPEC_SVE_PREFETCH
+    UNSPEC_SVE_PREFETCH_GATHER
+    UNSPEC_SVE_COMPACT
+    UNSPEC_SVE_SPLICE
+    UNSPEC_GEN_TAG             ; Generate a 4-bit MTE tag.
+    UNSPEC_GEN_TAG_RND         ; Generate a random 4-bit MTE tag.
+    UNSPEC_TAG_SPACE           ; Translate address to MTE tag address space.
+    UNSPEC_LD1RO
 ])
 
 (define_c_enum "unspecv" [
     UNSPECV_TSTART             ; Represent transaction start.
     UNSPECV_TCOMMIT            ; Represent transaction commit.
     UNSPECV_TCANCEL            ; Represent transaction cancel.
+    UNSPEC_RNDR                        ; Represent RNDR
+    UNSPEC_RNDRRS              ; Represent RNDRRS
   ]
 )
 
 ;; 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"
   ""
   "")
 
-(define_insn "ccmp<mode>"
-  [(set (match_operand:CC 1 "cc_register" "")
-       (if_then_else:CC
+(define_insn "@ccmp<CC_ONLY:mode><GPI:mode>"
+  [(set (match_operand:CC_ONLY 1 "cc_register" "")
+       (if_then_else:CC_ONLY
          (match_operator 4 "aarch64_comparison_operator"
           [(match_operand 0 "cc_register" "")
            (const_int 0)])
-         (compare:CC
+         (compare:CC_ONLY
            (match_operand:GPI 2 "register_operand" "r,r,r")
            (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))
-         (unspec:CC [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
+         (unspec:CC_ONLY
+           [(match_operand 5 "immediate_operand")]
+           UNSPEC_NZCV)))]
   ""
   "@
    ccmp\\t%<w>2, %<w>3, %k5, %m4
   [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
 )
 
-(define_insn "fccmp<mode>"
-  [(set (match_operand:CCFP 1 "cc_register" "")
-       (if_then_else:CCFP
+(define_insn "@ccmp<CCFP_CCFPE:mode><GPF:mode>"
+  [(set (match_operand:CCFP_CCFPE 1 "cc_register" "")
+       (if_then_else:CCFP_CCFPE
          (match_operator 4 "aarch64_comparison_operator"
           [(match_operand 0 "cc_register" "")
            (const_int 0)])
-         (compare:CCFP
+         (compare:CCFP_CCFPE
            (match_operand:GPF 2 "register_operand" "w")
            (match_operand:GPF 3 "register_operand" "w"))
-         (unspec:CCFP [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
+         (unspec:CCFP_CCFPE
+           [(match_operand 5 "immediate_operand")]
+           UNSPEC_NZCV)))]
   "TARGET_FLOAT"
-  "fccmp\\t%<s>2, %<s>3, %k5, %m4"
+  "fccmp<e>\\t%<s>2, %<s>3, %k5, %m4"
   [(set_attr "type" "fccmp<s>")]
 )
 
-(define_insn "fccmpe<mode>"
-  [(set (match_operand:CCFPE 1 "cc_register" "")
-        (if_then_else:CCFPE
+(define_insn "@ccmp<CC_ONLY:mode><GPI:mode>_rev"
+  [(set (match_operand:CC_ONLY 1 "cc_register" "")
+       (if_then_else:CC_ONLY
          (match_operator 4 "aarch64_comparison_operator"
           [(match_operand 0 "cc_register" "")
-         (const_int 0)])
-          (compare:CCFPE
+           (const_int 0)])
+         (unspec:CC_ONLY
+           [(match_operand 5 "immediate_operand")]
+           UNSPEC_NZCV)
+         (compare:CC_ONLY
+           (match_operand:GPI 2 "register_operand" "r,r,r")
+           (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))))]
+  ""
+  "@
+   ccmp\\t%<w>2, %<w>3, %k5, %M4
+   ccmp\\t%<w>2, %3, %k5, %M4
+   ccmn\\t%<w>2, #%n3, %k5, %M4"
+  [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
+)
+
+(define_insn "@ccmp<CCFP_CCFPE:mode><GPF:mode>_rev"
+  [(set (match_operand:CCFP_CCFPE 1 "cc_register" "")
+       (if_then_else:CCFP_CCFPE
+         (match_operator 4 "aarch64_comparison_operator"
+          [(match_operand 0 "cc_register" "")
+           (const_int 0)])
+         (unspec:CCFP_CCFPE
+           [(match_operand 5 "immediate_operand")]
+           UNSPEC_NZCV)
+         (compare:CCFP_CCFPE
            (match_operand:GPF 2 "register_operand" "w")
-           (match_operand:GPF 3 "register_operand" "w"))
-         (unspec:CCFPE [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
+           (match_operand:GPF 3 "register_operand" "w"))))]
   "TARGET_FLOAT"
-  "fccmpe\\t%<s>2, %<s>3, %k5, %m4"
+  "fccmp<e>\\t%<s>2, %<s>3, %k5, %M4"
   [(set_attr "type" "fccmp<s>")]
 )
 
                                                 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)]
-  "aarch64_use_simple_return_insn_p ()"
-  "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_expand "call"
-  [(parallel [(call (match_operand 0 "memory_operand")
-                   (match_operand 1 "general_operand"))
-             (use (match_operand 2 "" ""))
-             (clobber (reg:DI LR_REGNUM))])]
+  [(parallel
+     [(call (match_operand 0 "memory_operand")
+           (match_operand 1 "general_operand"))
+      (unspec:DI [(match_operand 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
+      (clobber (reg:DI LR_REGNUM))])]
   ""
   "
   {
-    aarch64_expand_call (NULL_RTX, operands[0], false);
+    aarch64_expand_call (NULL_RTX, operands[0], operands[2], false);
     DONE;
   }"
 )
 
 (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 "" ""))
-   (clobber (reg:DI LR_REGNUM))]
+   (unspec:DI [(match_operand:DI 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
+   (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 [(set (match_operand 0 "" "")
-                  (call (match_operand 1 "memory_operand")
-                        (match_operand 2 "general_operand")))
-             (use (match_operand 3 "" ""))
-             (clobber (reg:DI LR_REGNUM))])]
+  [(parallel
+     [(set (match_operand 0 "")
+          (call (match_operand 1 "memory_operand")
+                (match_operand 2 "general_operand")))
+     (unspec:DI [(match_operand 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
+     (clobber (reg:DI LR_REGNUM))])]
   ""
   "
   {
-    aarch64_expand_call (operands[0], operands[1], false);
+    aarch64_expand_call (operands[0], operands[1], operands[3], false);
     DONE;
   }"
 )
 
 (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 "" "")))
-   (clobber (reg:DI LR_REGNUM))]
+   (unspec:DI [(match_operand:DI 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
+   (clobber (reg:ADDR LR_REGNUM))]
   ""
   "@
-  blr\\t%1
+  * return aarch64_indirect_call_asm (operands[1]);
   bl\\t%c1"
   [(set_attr "type" "call, call")]
 )
 
 (define_expand "sibcall"
-  [(parallel [(call (match_operand 0 "memory_operand")
-                   (match_operand 1 "general_operand"))
-             (return)
-             (use (match_operand 2 "" ""))])]
+  [(parallel
+     [(call (match_operand 0 "memory_operand")
+           (match_operand 1 "general_operand"))
+      (unspec:DI [(match_operand 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
+      (return)])]
   ""
   {
-    aarch64_expand_call (NULL_RTX, operands[0], true);
+    aarch64_expand_call (NULL_RTX, operands[0], operands[2], true);
     DONE;
   }
 )
 
 (define_expand "sibcall_value"
-  [(parallel [(set (match_operand 0 "" "")
-                  (call (match_operand 1 "memory_operand")
-                        (match_operand 2 "general_operand")))
-             (return)
-             (use (match_operand 3 "" ""))])]
+  [(parallel
+     [(set (match_operand 0 "")
+          (call (match_operand 1 "memory_operand")
+                (match_operand 2 "general_operand")))
+      (unspec:DI [(match_operand 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
+      (return)])]
   ""
   {
-    aarch64_expand_call (operands[0], operands[1], true);
+    aarch64_expand_call (operands[0], operands[1], operands[3], true);
     DONE;
   }
 )
 
 (define_insn "*sibcall_insn"
-  [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
-        (match_operand 1 "" ""))
+  [(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 "" "")
+  [(set (match_operand 0 "")
        (call (mem:DI
-               (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
-             (match_operand 2 "" "")))
+               (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.
 {
   int i;
 
-  emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
+  /* Untyped calls always use the default ABI.  It's only possible to use
+     ABI variants if we know the type of the target function.  */
+  emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
 
   for (i = 0; i < XVECLEN (operands[2], 0); i++)
     {
 )
 
 (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]) && CONST_INT_P (operands[1])
-       && <MODE>mode == DImode
+    if (MEM_P (operands[0]) && !MEM_VOLATILE_P (operands[0])
+       && CONST_INT_P (operands[1]) && <MODE>mode == DImode
        && aarch64_split_dimode_const_store (operands[0], operands[1]))
       DONE;
 
   [(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"))]
 })
 
 (define_expand "mov<mode>"
-  [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand")
-       (match_operand:GPF_TF_F16 1 "general_operand"))]
+  [(set (match_operand:GPF_TF_F16_MOV 0 "nonimmediate_operand")
+       (match_operand:GPF_TF_F16_MOV 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
   }
 )
 
-(define_insn "*movhf_aarch64"
-  [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w  , w,?r,w,w  ,w  ,w,m,r,m ,r")
-       (match_operand:HF 1 "general_operand"      "Y ,?rY,?r, w,w,Ufc,Uvi,m,w,m,rY,r"))]
-  "TARGET_FLOAT && (register_operand (operands[0], HFmode)
-    || aarch64_reg_or_fp_zero (operands[1], HFmode))"
+(define_insn "*mov<mode>_aarch64"
+  [(set (match_operand:HFBF 0 "nonimmediate_operand" "=w,w  , w,?r,w,w  ,w  ,w,m,r,m ,r")
+       (match_operand:HFBF 1 "general_operand"      "Y ,?rY,?r, w,w,Ufc,Uvi,m,w,m,rY,r"))]
+  "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode)
+    || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))"
   "@
    movi\\t%0.4h, #0
    fmov\\t%h0, %w1
                                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;
 })
 
   [(set_attr "type" "bfx")]
 )
 
+(define_insn "*ashiftsi_extvdi_bfiz"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ashift:SI
+         (match_operator:SI 4 "subreg_lowpart_operator"
+           [(sign_extract:DI
+              (match_operand:DI 1 "register_operand" "r")
+              (match_operand 2 "aarch64_simd_shift_imm_offset_si")
+              (const_int 0))])
+         (match_operand 3 "aarch64_simd_shift_imm_si")))]
+  "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
+            1, GET_MODE_BITSIZE (SImode) - 1)"
+  "sbfiz\\t%w0, %w1, %3, %2"
+  [(set_attr "type" "bfx")]
+)
+
 ;; When the bit position and width of the equivalent extraction add up to 32
 ;; we can use a W-reg LSL instruction taking advantage of the implicit
 ;; zero-extension of the X-reg.
   ""
 {
   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")]
 ;; instructions in the TLS stubs, in order to enable linker relaxation.
 ;; Therefore we treat the stubs as an atomic sequence.
 (define_expand "tlsgd_small_<mode>"
- [(parallel [(set (match_operand 0 "register_operand")
+ [(parallel [(set (match_operand:PTR 0 "register_operand")
                   (call (mem:DI (match_dup 2)) (const_int 1)))
-            (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref")] UNSPEC_GOTSMALLTLS)
+            (unspec:DI [(const_int 0)] UNSPEC_CALLEE_ABI)
+            (unspec:DI [(match_operand 1 "aarch64_valid_symref")] UNSPEC_GOTSMALLTLS)
             (clobber (reg:DI LR_REGNUM))])]
  ""
 {
 })
 
 (define_insn "*tlsgd_small_<mode>"
-  [(set (match_operand 0 "register_operand" "")
+  [(set (match_operand:PTR 0 "register_operand" "")
        (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
-   (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
+   (unspec:DI [(const_int 0)] UNSPEC_CALLEE_ABI)
+   (unspec:DI [(match_operand 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
    (clobber (reg:DI LR_REGNUM))
   ]
   ""
   [(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"
   {
     if (TARGET_SVE)
-      emit_insn (gen_tlsdesc_small_sve_<mode> (operands[0]));
+      {
+       rtx abi = gen_int_mode (aarch64_tlsdesc_abi_id (), DImode);
+       rtx_insn *call
+         = emit_call_insn (gen_tlsdesc_small_sve_<mode> (operands[0], abi));
+       RTL_CONST_CALL_P (call) = 1;
+      }
     else
       emit_insn (gen_tlsdesc_small_advsimd_<mode> (operands[0]));
     DONE;
   [(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")])
 
-;; For SVE, model tlsdesc calls as clobbering the lower 128 bits of
-;; all vector registers, and clobber all predicate registers, on
-;; top of the usual R0 and LR.
+;; For SVE, model tlsdesc calls as normal calls, with the callee ABI
+;; describing the extra call-preserved guarantees.  This would work
+;; for non-SVE too, but avoiding a call is probably better if we can.
 (define_insn "tlsdesc_small_sve_<mode>"
   [(set (reg:PTR R0_REGNUM)
-        (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
-                   UNSPEC_TLSDESC))
+       (call (mem:DI (unspec:PTR
+                       [(match_operand 0 "aarch64_valid_symref")]
+                       UNSPEC_TLSDESC))
+             (const_int 0)))
+   (unspec:DI [(match_operand:DI 1 "const_int_operand")] UNSPEC_CALLEE_ABI)
    (clobber (reg:DI LR_REGNUM))
-   (clobber (reg:CC CC_REGNUM))
-   (clobber_high (reg:TI V0_REGNUM))
-   (clobber_high (reg:TI V1_REGNUM))
-   (clobber_high (reg:TI V2_REGNUM))
-   (clobber_high (reg:TI V3_REGNUM))
-   (clobber_high (reg:TI V4_REGNUM))
-   (clobber_high (reg:TI V5_REGNUM))
-   (clobber_high (reg:TI V6_REGNUM))
-   (clobber_high (reg:TI V7_REGNUM))
-   (clobber_high (reg:TI V8_REGNUM))
-   (clobber_high (reg:TI V9_REGNUM))
-   (clobber_high (reg:TI V10_REGNUM))
-   (clobber_high (reg:TI V11_REGNUM))
-   (clobber_high (reg:TI V12_REGNUM))
-   (clobber_high (reg:TI V13_REGNUM))
-   (clobber_high (reg:TI V14_REGNUM))
-   (clobber_high (reg:TI V15_REGNUM))
-   (clobber_high (reg:TI V16_REGNUM))
-   (clobber_high (reg:TI V17_REGNUM))
-   (clobber_high (reg:TI V18_REGNUM))
-   (clobber_high (reg:TI V19_REGNUM))
-   (clobber_high (reg:TI V20_REGNUM))
-   (clobber_high (reg:TI V21_REGNUM))
-   (clobber_high (reg:TI V22_REGNUM))
-   (clobber_high (reg:TI V23_REGNUM))
-   (clobber_high (reg:TI V24_REGNUM))
-   (clobber_high (reg:TI V25_REGNUM))
-   (clobber_high (reg:TI V26_REGNUM))
-   (clobber_high (reg:TI V27_REGNUM))
-   (clobber_high (reg:TI V28_REGNUM))
-   (clobber_high (reg:TI V29_REGNUM))
-   (clobber_high (reg:TI V30_REGNUM))
-   (clobber_high (reg:TI V31_REGNUM))
-   (clobber (reg:VNx2BI P0_REGNUM))
-   (clobber (reg:VNx2BI P1_REGNUM))
-   (clobber (reg:VNx2BI P2_REGNUM))
-   (clobber (reg:VNx2BI P3_REGNUM))
-   (clobber (reg:VNx2BI P4_REGNUM))
-   (clobber (reg:VNx2BI P5_REGNUM))
-   (clobber (reg:VNx2BI P6_REGNUM))
-   (clobber (reg:VNx2BI P7_REGNUM))
-   (clobber (reg:VNx2BI P8_REGNUM))
-   (clobber (reg:VNx2BI P9_REGNUM))
-   (clobber (reg:VNx2BI P10_REGNUM))
-   (clobber (reg:VNx2BI P11_REGNUM))
-   (clobber (reg:VNx2BI P12_REGNUM))
-   (clobber (reg:VNx2BI P13_REGNUM))
-   (clobber (reg:VNx2BI P14_REGNUM))
-   (clobber (reg:VNx2BI P15_REGNUM))
-   (clobber (match_scratch:DI 1 "=r"))
-   (use (reg:DI FP_REGNUM))]
+   (clobber (match_scratch:DI 2 "=r"))]
   "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"
+  "adrp\\tx0, %A0\;ldr\\t%<w>2, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%2"
   [(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)]
+;; 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\\tfpcr, %0"
+  "msr\\t<fpscr_name>, %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)]
-  ""
-  "msr\\tfpsr, %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"
   [(set_attr "type" "csel")]
 )
 
+;; Like speculation_tracker, but track the inverse condition.
+(define_insn "speculation_tracker_rev"
+  [(set (reg:DI SPECULATION_TRACKER_REGNUM)
+       (unspec:DI [(reg:DI SPECULATION_TRACKER_REGNUM) (match_operand 0)]
+        UNSPEC_SPECULATION_TRACKER_REV))]
+  ""
+  {
+    operands[1] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
+    output_asm_insn ("csel\\t%1, %1, xzr, %M0", operands);
+    return "";
+  }
+  [(set_attr "type" "csel")]
+)
+
 ;; BTI <target> instructions
 (define_insn "bti_noarg"
   [(unspec_volatile [(const_int 0)] UNSPECV_BTI_NOARG)]
   [(set_attr "type" "tme")]
 )
 
+(define_insn "aarch64_rndr"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (unspec_volatile:DI [(const_int 0)] UNSPEC_RNDR))
+   (set (reg:CC_Z CC_REGNUM)
+       (unspec_volatile:CC_Z [(const_int 0)] UNSPEC_RNDR))]
+  "TARGET_RNG"
+  "mrs\t%0, RNDR"
+  [(set_attr "type" "mrs")]
+)
+
+(define_insn "aarch64_rndrrs"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (unspec_volatile:DI [(const_int 0)] UNSPEC_RNDRRS))
+   (set (reg:CC_Z CC_REGNUM)
+       (unspec_volatile:CC_Z [(const_int 0)] UNSPEC_RNDRRS))]
+  "TARGET_RNG"
+  "mrs\t%0, RNDRRS"
+  [(set_attr "type" "mrs")]
+)
+
+;; Memory Tagging Extension (MTE) instructions.
+
+(define_insn "irg"
+  [(set (match_operand:DI 0 "register_operand" "=rk")
+       (ior:DI
+        (and:DI (match_operand:DI 1 "register_operand" "rk")
+                (const_int -1080863910568919041)) ;; 0xf0ff...
+        (ashift:DI (unspec:QI [(match_operand:DI 2 "register_operand" "r")]
+                    UNSPEC_GEN_TAG_RND)
+                   (const_int 56))))]
+  "TARGET_MEMTAG"
+  "irg\\t%0, %1, %2"
+  [(set_attr "type" "memtag")]
+)
+
+(define_insn "gmi"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (ior:DI (ashift:DI
+                (const_int 1)
+                (and:QI (lshiftrt:DI
+                         (match_operand:DI 1 "register_operand" "rk")
+                         (const_int 56)) (const_int 15)))
+               (match_operand:DI 2 "register_operand" "r")))]
+  "TARGET_MEMTAG"
+  "gmi\\t%0, %1, %2"
+  [(set_attr "type" "memtag")]
+)
+
+(define_insn "addg"
+  [(set (match_operand:DI 0 "register_operand" "=rk")
+       (ior:DI
+        (and:DI (plus:DI (match_operand:DI 1 "register_operand" "rk")
+                         (match_operand:DI 2 "aarch64_granule16_uimm6" "i"))
+                (const_int -1080863910568919041)) ;; 0xf0ff...
+        (ashift:DI
+         (unspec:QI
+          [(and:QI (lshiftrt:DI (match_dup 1) (const_int 56)) (const_int 15))
+           (match_operand:QI 3 "aarch64_memtag_tag_offset" "i")]
+          UNSPEC_GEN_TAG)
+         (const_int 56))))]
+  "TARGET_MEMTAG"
+  "addg\\t%0, %1, #%2, #%3"
+  [(set_attr "type" "memtag")]
+)
+
+(define_insn "subp"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (minus:DI
+         (and:DI (match_operand:DI 1 "register_operand" "rk")
+                 (const_int 72057594037927935)) ;; 0x00ff...
+         (and:DI (match_operand:DI 2 "register_operand" "rk")
+                 (const_int 72057594037927935))))] ;; 0x00ff...
+  "TARGET_MEMTAG"
+  "subp\\t%0, %1, %2"
+  [(set_attr "type" "memtag")]
+)
+
+;; LDG will use the 16-byte aligned value of the address.
+(define_insn "ldg"
+  [(set (match_operand:DI 0 "register_operand" "+r")
+       (ior:DI
+        (and:DI (match_dup 0) (const_int -1080863910568919041)) ;; 0xf0ff...
+        (ashift:DI
+         (mem:QI (unspec:DI
+          [(and:DI (plus:DI (match_operand:DI 1 "register_operand" "rk")
+                            (match_operand:DI 2 "aarch64_granule16_simm9" "i"))
+                   (const_int -16))] UNSPEC_TAG_SPACE))
+         (const_int 56))))]
+  "TARGET_MEMTAG"
+  "ldg\\t%0, [%1, #%2]"
+  [(set_attr "type" "memtag")]
+)
+
+;; STG doesn't align the address but aborts with alignment fault
+;; when the address is not 16-byte aligned.
+(define_insn "stg"
+  [(set (mem:QI (unspec:DI
+        [(plus:DI (match_operand:DI 1 "register_operand" "rk")
+                  (match_operand:DI 2 "aarch64_granule16_simm9" "i"))]
+        UNSPEC_TAG_SPACE))
+       (and:QI (lshiftrt:DI (match_operand:DI 0 "register_operand" "rk")
+                            (const_int 56)) (const_int 15)))]
+  "TARGET_MEMTAG"
+  "stg\\t%0, [%1, #%2]"
+  [(set_attr "type" "memtag")]
+)
+
 ;; AdvSIMD Stuff
 (include "aarch64-simd.md")
 
 
 ;; SVE2.
 (include "aarch64-sve2.md")
+
+;; Morello
+(include "aarch64-morello.md")
This page took 0.086259 seconds and 5 git commands to generate.