+ "t%C0\t%%xcc, %1"
+ [(set_attr "type" "trap")])
+
+
+;; TLS support instructions.
+
+(define_insn "tgd_hi22"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (high:SI (unspec:SI [(match_operand 1 "tgd_symbolic_operand" "")]
+ UNSPEC_TLSGD)))]
+ "TARGET_TLS"
+ "sethi\\t%%tgd_hi22(%a1), %0")
+
+(define_insn "tgd_lo10"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand 2 "tgd_symbolic_operand" "")]
+ UNSPEC_TLSGD)))]
+ "TARGET_TLS"
+ "add\\t%1, %%tgd_lo10(%a2), %0")
+
+(define_insn "tgd_add32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tgd_symbolic_operand" "")]
+ UNSPEC_TLSGD)))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "add\\t%1, %2, %0, %%tgd_add(%a3)")
+
+(define_insn "tgd_add64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tgd_symbolic_operand" "")]
+ UNSPEC_TLSGD)))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "add\\t%1, %2, %0, %%tgd_add(%a3)")
+
+(define_insn "tgd_call32"
+ [(set (match_operand 0 "register_operand" "=r")
+ (call (mem:SI (unspec:SI [(match_operand:SI 1 "symbolic_operand" "s")
+ (match_operand 2 "tgd_symbolic_operand" "")]
+ UNSPEC_TLSGD))
+ (match_operand 3 "" "")))
+ (clobber (reg:SI 15))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "call\t%a1, %%tgd_call(%a2)%#"
+ [(set_attr "type" "call")])
+
+(define_insn "tgd_call64"
+ [(set (match_operand 0 "register_operand" "=r")
+ (call (mem:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "s")
+ (match_operand 2 "tgd_symbolic_operand" "")]
+ UNSPEC_TLSGD))
+ (match_operand 3 "" "")))
+ (clobber (reg:DI 15))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "call\t%a1, %%tgd_call(%a2)%#"
+ [(set_attr "type" "call")])
+
+(define_insn "tldm_hi22"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (high:SI (unspec:SI [(const_int 0)] UNSPEC_TLSLDM)))]
+ "TARGET_TLS"
+ "sethi\\t%%tldm_hi22(%&), %0")
+
+(define_insn "tldm_lo10"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(const_int 0)] UNSPEC_TLSLDM)))]
+ "TARGET_TLS"
+ "add\\t%1, %%tldm_lo10(%&), %0")
+
+(define_insn "tldm_add32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand:SI 2 "register_operand" "r")]
+ UNSPEC_TLSLDM)))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "add\\t%1, %2, %0, %%tldm_add(%&)")
+
+(define_insn "tldm_add64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand:SI 2 "register_operand" "r")]
+ UNSPEC_TLSLDM)))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "add\\t%1, %2, %0, %%tldm_add(%&)")
+
+(define_insn "tldm_call32"
+ [(set (match_operand 0 "register_operand" "=r")
+ (call (mem:SI (unspec:SI [(match_operand:SI 1 "symbolic_operand" "s")]
+ UNSPEC_TLSLDM))
+ (match_operand 2 "" "")))
+ (clobber (reg:SI 15))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "call\t%a1, %%tldm_call(%&)%#"
+ [(set_attr "type" "call")])
+
+(define_insn "tldm_call64"
+ [(set (match_operand 0 "register_operand" "=r")
+ (call (mem:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "s")]
+ UNSPEC_TLSLDM))
+ (match_operand 2 "" "")))
+ (clobber (reg:DI 15))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "call\t%a1, %%tldm_call(%&)%#"
+ [(set_attr "type" "call")])
+
+(define_insn "tldo_hix22"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (high:SI (unspec:SI [(match_operand 1 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)))]
+ "TARGET_TLS"
+ "sethi\\t%%tldo_hix22(%a1), %0")
+
+(define_insn "tldo_lox10"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand 2 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)))]
+ "TARGET_TLS"
+ "xor\\t%1, %%tldo_lox10(%a2), %0")
+
+(define_insn "tldo_add32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "add\\t%1, %2, %0, %%tldo_add(%a3)")
+
+(define_insn "tldo_add64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "add\\t%1, %2, %0, %%tldo_add(%a3)")
+
+(define_insn "tie_hi22"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (high:SI (unspec:SI [(match_operand 1 "tie_symbolic_operand" "")]
+ UNSPEC_TLSIE)))]
+ "TARGET_TLS"
+ "sethi\\t%%tie_hi22(%a1), %0")
+
+(define_insn "tie_lo10"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand 2 "tie_symbolic_operand" "")]
+ UNSPEC_TLSIE)))]
+ "TARGET_TLS"
+ "add\\t%1, %%tie_lo10(%a2), %0")
+
+(define_insn "tie_ld32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tie_symbolic_operand" "")]
+ UNSPEC_TLSIE))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "ld\\t[%1 + %2], %0, %%tie_ld(%a3)"
+ [(set_attr "type" "load")])
+
+(define_insn "tie_ld64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tie_symbolic_operand" "")]
+ UNSPEC_TLSIE))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldx\\t[%1 + %2], %0, %%tie_ldx(%a3)"
+ [(set_attr "type" "load")])
+
+(define_insn "tie_add32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tie_symbolic_operand" "")]
+ UNSPEC_TLSIE)))]
+ "TARGET_SUN_TLS && TARGET_ARCH32"
+ "add\\t%1, %2, %0, %%tie_add(%a3)")
+
+(define_insn "tie_add64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand:DI 2 "register_operand" "r")
+ (match_operand 3 "tie_symbolic_operand" "")]
+ UNSPEC_TLSIE)))]
+ "TARGET_SUN_TLS && TARGET_ARCH64"
+ "add\\t%1, %2, %0, %%tie_add(%a3)")
+
+(define_insn "tle_hix22_sp32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (high:SI (unspec:SI [(match_operand 1 "tle_symbolic_operand" "")]
+ UNSPEC_TLSLE)))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "sethi\\t%%tle_hix22(%a1), %0")
+
+(define_insn "tle_lox10_sp32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand 2 "tle_symbolic_operand" "")]
+ UNSPEC_TLSLE)))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "xor\\t%1, %%tle_lox10(%a2), %0")
+
+(define_insn "tle_hix22_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (high:DI (unspec:DI [(match_operand 1 "tle_symbolic_operand" "")]
+ UNSPEC_TLSLE)))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "sethi\\t%%tle_hix22(%a1), %0")
+
+(define_insn "tle_lox10_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand 2 "tle_symbolic_operand" "")]
+ UNSPEC_TLSLE)))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "xor\\t%1, %%tle_lox10(%a2), %0")
+
+;; Now patterns combining tldo_add{32,64} with some integer loads or stores
+(define_insn "*tldo_ldub_sp32"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (mem:QI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r"))))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "ldub\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldub1_sp32"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (zero_extend:HI (mem:QI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "ldub\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldub2_sp32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (mem:QI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "ldub\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldsb1_sp32"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (sign_extend:HI (mem:QI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "ldsb\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldsb2_sp32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (mem:QI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "ldsb\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldub_sp64"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r"))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldub\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldub1_sp64"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (zero_extend:HI (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldub\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldub2_sp64"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldub\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldub3_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldub\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldsb1_sp64"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (sign_extend:HI (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldsb\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldsb2_sp64"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldsb\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldsb3_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (sign_extend:DI (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldsb\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_lduh_sp32"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (mem:HI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r"))))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "lduh\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_lduh1_sp32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (mem:HI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "lduh\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldsh1_sp32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (mem:HI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "ldsh\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_lduh_sp64"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (mem:HI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r"))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "lduh\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_lduh1_sp64"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (mem:HI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "lduh\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_lduh2_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (mem:HI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "lduh\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldsh1_sp64"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (mem:HI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldsh\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldsh2_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (sign_extend:DI (mem:HI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldsh\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_lduw_sp32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mem:SI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r"))))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "ld\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")])
+
+(define_insn "*tldo_lduw_sp64"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mem:SI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r"))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "lduw\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")])
+
+(define_insn "*tldo_lduw1_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (mem:SI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "lduw\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")])
+
+(define_insn "*tldo_ldsw1_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (sign_extend:DI (mem:SI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldsw\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldx_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (mem:DI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r"))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldx\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")])
+
+(define_insn "*tldo_stb_sp32"
+ [(set (mem:QI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r")))
+ (match_operand:QI 0 "register_operand" "=r"))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "stb\t%0, [%1 + %2], %%tldo_add(%3)"
+ [(set_attr "type" "store")])
+
+(define_insn "*tldo_stb_sp64"
+ [(set (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))
+ (match_operand:QI 0 "register_operand" "=r"))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "stb\t%0, [%1 + %2], %%tldo_add(%3)"
+ [(set_attr "type" "store")])
+
+(define_insn "*tldo_sth_sp32"
+ [(set (mem:HI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r")))
+ (match_operand:HI 0 "register_operand" "=r"))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "sth\t%0, [%1 + %2], %%tldo_add(%3)"
+ [(set_attr "type" "store")])
+
+(define_insn "*tldo_sth_sp64"
+ [(set (mem:HI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))
+ (match_operand:HI 0 "register_operand" "=r"))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "sth\t%0, [%1 + %2], %%tldo_add(%3)"
+ [(set_attr "type" "store")])
+
+(define_insn "*tldo_stw_sp32"
+ [(set (mem:SI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r")))
+ (match_operand:SI 0 "register_operand" "=r"))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "st\t%0, [%1 + %2], %%tldo_add(%3)"
+ [(set_attr "type" "store")])
+
+(define_insn "*tldo_stw_sp64"
+ [(set (mem:SI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))
+ (match_operand:SI 0 "register_operand" "=r"))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "stw\t%0, [%1 + %2], %%tldo_add(%3)"
+ [(set_attr "type" "store")])
+
+(define_insn "*tldo_stx_sp64"
+ [(set (mem:DI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))
+ (match_operand:DI 0 "register_operand" "=r"))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "stx\t%0, [%1 + %2], %%tldo_add(%3)"
+ [(set_attr "type" "store")])
+
+
+;; Stack protector instructions.
+
+(define_expand "stack_protect_set"
+ [(match_operand 0 "memory_operand" "")
+ (match_operand 1 "memory_operand" "")]
+ ""
+{
+#ifdef TARGET_THREAD_SSP_OFFSET
+ rtx tlsreg = gen_rtx_REG (Pmode, 7);
+ rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
+ operands[1] = gen_rtx_MEM (Pmode, addr);
+#endif
+ if (TARGET_ARCH64)
+ emit_insn (gen_stack_protect_setdi (operands[0], operands[1]));
+ else
+ emit_insn (gen_stack_protect_setsi (operands[0], operands[1]));
+ DONE;
+})
+
+(define_insn "stack_protect_setsi"
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
+ (set (match_scratch:SI 2 "=&r") (const_int 0))]
+ "TARGET_ARCH32"
+ "ld\t%1, %2\;st\t%2, %0\;mov\t0, %2"
+ [(set_attr "type" "multi")
+ (set_attr "length" "3")])
+
+(define_insn "stack_protect_setdi"
+ [(set (match_operand:DI 0 "memory_operand" "=m")
+ (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
+ (set (match_scratch:DI 2 "=&r") (const_int 0))]
+ "TARGET_ARCH64"
+ "ldx\t%1, %2\;stx\t%2, %0\;mov\t0, %2"
+ [(set_attr "type" "multi")
+ (set_attr "length" "3")])
+
+(define_expand "stack_protect_test"
+ [(match_operand 0 "memory_operand" "")
+ (match_operand 1 "memory_operand" "")
+ (match_operand 2 "" "")]
+ ""
+{
+#ifdef TARGET_THREAD_SSP_OFFSET
+ rtx tlsreg = gen_rtx_REG (Pmode, 7);
+ rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
+ operands[1] = gen_rtx_MEM (Pmode, addr);
+#endif
+ if (TARGET_ARCH64)
+ {
+ rtx temp = gen_reg_rtx (Pmode);
+ emit_insn (gen_stack_protect_testdi (temp, operands[0], operands[1]));
+ sparc_compare_op0 = temp;
+ sparc_compare_op1 = const0_rtx;
+ }
+ else
+ {
+ emit_insn (gen_stack_protect_testsi (operands[0], operands[1]));
+ sparc_compare_op0 = operands[0];
+ sparc_compare_op1 = operands[1];
+ sparc_compare_emitted = gen_rtx_REG (CCmode, SPARC_ICC_REG);
+ }
+ emit_jump_insn (gen_beq (operands[2]));
+ DONE;
+})
+
+(define_insn "stack_protect_testsi"
+ [(set (reg:CC 100)
+ (unspec:CC [(match_operand:SI 0 "memory_operand" "m")
+ (match_operand:SI 1 "memory_operand" "m")]
+ UNSPEC_SP_TEST))
+ (set (match_scratch:SI 3 "=r") (const_int 0))
+ (clobber (match_scratch:SI 2 "=&r"))]
+ "TARGET_ARCH32"
+ "ld\t%0, %2\;ld\t%1, %3\;xorcc\t%2, %3, %2\;mov\t0, %3"
+ [(set_attr "type" "multi")
+ (set_attr "length" "4")])
+
+(define_insn "stack_protect_testdi"
+ [(set (match_operand:DI 0 "register_operand" "=&r")
+ (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
+ (match_operand:DI 2 "memory_operand" "m")]
+ UNSPEC_SP_TEST))
+ (set (match_scratch:DI 3 "=r") (const_int 0))]
+ "TARGET_ARCH64"
+ "ldx\t%1, %0\;ldx\t%2, %3\;xor\t%0, %3, %0\;mov\t0, %3"
+ [(set_attr "type" "multi")
+ (set_attr "length" "4")])
+
+
+;; Vector instructions.
+
+(define_insn "addv2si3"
+ [(set (match_operand:V2SI 0 "register_operand" "=e")
+ (plus:V2SI (match_operand:V2SI 1 "register_operand" "e")
+ (match_operand:V2SI 2 "register_operand" "e")))]
+ "TARGET_VIS"
+ "fpadd32\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "addv4hi3"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (plus:V4HI (match_operand:V4HI 1 "register_operand" "e")
+ (match_operand:V4HI 2 "register_operand" "e")))]
+ "TARGET_VIS"
+ "fpadd16\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+;; fpadd32s is emitted by the addsi3 pattern.
+
+(define_insn "addv2hi3"
+ [(set (match_operand:V2HI 0 "register_operand" "=f")
+ (plus:V2HI (match_operand:V2HI 1 "register_operand" "f")
+ (match_operand:V2HI 2 "register_operand" "f")))]
+ "TARGET_VIS"
+ "fpadd16s\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "single")])
+
+(define_insn "subv2si3"
+ [(set (match_operand:V2SI 0 "register_operand" "=e")
+ (minus:V2SI (match_operand:V2SI 1 "register_operand" "e")
+ (match_operand:V2SI 2 "register_operand" "e")))]
+ "TARGET_VIS"
+ "fpsub32\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "subv4hi3"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (minus:V4HI (match_operand:V4HI 1 "register_operand" "e")
+ (match_operand:V4HI 2 "register_operand" "e")))]
+ "TARGET_VIS"
+ "fpsub16\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+;; fpsub32s is emitted by the subsi3 pattern.
+
+(define_insn "subv2hi3"
+ [(set (match_operand:V2HI 0 "register_operand" "=f")
+ (minus:V2HI (match_operand:V2HI 1 "register_operand" "f")
+ (match_operand:V2HI 2 "register_operand" "f")))]
+ "TARGET_VIS"
+ "fpsub16s\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "single")])
+
+;; All other logical instructions have integer equivalents so they
+;; are defined together.
+
+;; (ior (not (op1)) (not (op2))) is the canonical form of NAND.
+
+(define_insn "*nand<V64mode>_vis"
+ [(set (match_operand:V64 0 "register_operand" "=e")
+ (ior:V64 (not:V64 (match_operand:V64 1 "register_operand" "e"))
+ (not:V64 (match_operand:V64 2 "register_operand" "e"))))]
+ "TARGET_VIS"
+ "fnand\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "*nand<V32mode>_vis"
+ [(set (match_operand:V32 0 "register_operand" "=f")
+ (ior:V32 (not:V32 (match_operand:V32 1 "register_operand" "f"))
+ (not:V32 (match_operand:V32 2 "register_operand" "f"))))]
+ "TARGET_VIS"
+ "fnands\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "single")])
+
+;; Hard to generate VIS instructions. We have builtins for these.
+
+(define_insn "fpack16_vis"
+ [(set (match_operand:V4QI 0 "register_operand" "=f")
+ (unspec:V4QI [(match_operand:V4HI 1 "register_operand" "e")]
+ UNSPEC_FPACK16))]
+ "TARGET_VIS"
+ "fpack16\t%1, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "fpackfix_vis"
+ [(set (match_operand:V2HI 0 "register_operand" "=f")
+ (unspec:V2HI [(match_operand:V2SI 1 "register_operand" "e")]
+ UNSPEC_FPACKFIX))]
+ "TARGET_VIS"
+ "fpackfix\t%1, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "fpack32_vis"
+ [(set (match_operand:V8QI 0 "register_operand" "=e")
+ (unspec:V8QI [(match_operand:V2SI 1 "register_operand" "e")
+ (match_operand:V8QI 2 "register_operand" "e")]
+ UNSPEC_FPACK32))]
+ "TARGET_VIS"
+ "fpack32\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "fexpand_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (unspec:V4HI [(match_operand:V4QI 1 "register_operand" "f")]
+ UNSPEC_FEXPAND))]
+ "TARGET_VIS"
+ "fexpand\t%1, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+;; It may be possible to describe this operation as (1 indexed):
+;; (vec_select (vec_duplicate (vec_duplicate (vec_concat 1 2)))
+;; 1,5,10,14,19,23,28,32)
+;; Note that (vec_merge:V8QI [(V4QI) (V4QI)] (10101010 = 170) doesn't work
+;; because vec_merge expects all the operands to be of the same type.
+(define_insn "fpmerge_vis"
+ [(set (match_operand:V8QI 0 "register_operand" "=e")
+ (unspec:V8QI [(match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V4QI 2 "register_operand" "f")]
+ UNSPEC_FPMERGE))]
+ "TARGET_VIS"
+ "fpmerge\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+;; Partitioned multiply instructions
+(define_insn "fmul8x16_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (mult:V4HI (match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V4HI 2 "register_operand" "e")))]
+ "TARGET_VIS"
+ "fmul8x16\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+;; Only one of the following two insns can be a multiply.
+(define_insn "fmul8x16au_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (mult:V4HI (match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V2HI 2 "register_operand" "f")))]
+ "TARGET_VIS"
+ "fmul8x16au\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+(define_insn "fmul8x16al_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (unspec:V4HI [(match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V2HI 2 "register_operand" "f")]
+ UNSPEC_MUL16AL))]
+ "TARGET_VIS"
+ "fmul8x16al\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+;; Only one of the following two insns can be a multiply.
+(define_insn "fmul8sux16_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (mult:V4HI (match_operand:V8QI 1 "register_operand" "e")
+ (match_operand:V4HI 2 "register_operand" "e")))]
+ "TARGET_VIS"
+ "fmul8sux16\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+(define_insn "fmul8ulx16_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (unspec:V4HI [(match_operand:V8QI 1 "register_operand" "e")
+ (match_operand:V4HI 2 "register_operand" "e")]
+ UNSPEC_MUL8UL))]
+ "TARGET_VIS"
+ "fmul8ulx16\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+;; Only one of the following two insns can be a multiply.
+(define_insn "fmuld8sux16_vis"
+ [(set (match_operand:V2SI 0 "register_operand" "=e")
+ (mult:V2SI (match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V2HI 2 "register_operand" "f")))]
+ "TARGET_VIS"
+ "fmuld8sux16\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+(define_insn "fmuld8ulx16_vis"
+ [(set (match_operand:V2SI 0 "register_operand" "=e")
+ (unspec:V2SI [(match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V2HI 2 "register_operand" "f")]
+ UNSPEC_MULDUL))]
+ "TARGET_VIS"
+ "fmuld8ulx16\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+;; Using faligndata only makes sense after an alignaddr since the choice of
+;; bytes to take out of each operand is dependent on the results of the last
+;; alignaddr.
+(define_insn "faligndata<V64I:mode>_vis"
+ [(set (match_operand:V64I 0 "register_operand" "=e")
+ (unspec:V64I [(match_operand:V64I 1 "register_operand" "e")
+ (match_operand:V64I 2 "register_operand" "e")]
+ UNSPEC_ALIGNDATA))]
+ "TARGET_VIS"
+ "faligndata\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "alignaddr<P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
+ UNSPEC_ALIGNADDR))]
+ "TARGET_VIS"
+ "alignaddr\t%r1, %r2, %0")
+
+(define_insn "pdist_vis"
+ [(set (match_operand:DI 0 "register_operand" "=e")
+ (unspec:DI [(match_operand:V8QI 1 "register_operand" "e")
+ (match_operand:V8QI 2 "register_operand" "e")
+ (match_operand:DI 3 "register_operand" "0")]
+ UNSPEC_PDIST))]
+ "TARGET_VIS"
+ "pdist\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(include "sync.md")