+
+(define_expand "prefetch"
+ [(match_operand 0 "address_operand" "")
+ (match_operand 1 "const_int_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_PA_20"
+{
+ int locality = INTVAL (operands[2]);
+
+ gcc_assert (locality >= 0 && locality <= 3);
+
+ /* Change operand[0] to a MEM as we don't have the infrastructure
+ to output all the supported address modes for ldw/ldd when we use
+ the address directly. However, we do have it for MEMs. */
+ operands[0] = gen_rtx_MEM (QImode, operands[0]);
+
+ /* If the address isn't valid for the prefetch, replace it. */
+ if (locality)
+ {
+ if (!prefetch_nocc_operand (operands[0], QImode))
+ operands[0]
+ = replace_equiv_address (operands[0],
+ copy_to_mode_reg (Pmode,
+ XEXP (operands[0], 0)));
+ emit_insn (gen_prefetch_nocc (operands[0], operands[1], operands[2]));
+ }
+ else
+ {
+ if (!prefetch_cc_operand (operands[0], QImode))
+ operands[0]
+ = replace_equiv_address (operands[0],
+ copy_to_mode_reg (Pmode,
+ XEXP (operands[0], 0)));
+ emit_insn (gen_prefetch_cc (operands[0], operands[1], operands[2]));
+ }
+ DONE;
+})
+
+(define_insn "prefetch_cc"
+ [(prefetch (match_operand:QI 0 "prefetch_cc_operand" "RW")
+ (match_operand:SI 1 "const_int_operand" "n")
+ (match_operand:SI 2 "const_int_operand" "n"))]
+ "TARGET_PA_20 && operands[2] == const0_rtx"
+{
+ /* The SL cache-control completor indicates good spatial locality but
+ poor temporal locality. The ldw instruction with a target of general
+ register 0 prefetches a cache line for a read. The ldd instruction
+ prefetches a cache line for a write. */
+ static const char * const instr[2] = {
+ "ldw%M0,sl %0,%%r0",
+ "ldd%M0,sl %0,%%r0"
+ };
+ int read_or_write = INTVAL (operands[1]);
+
+ gcc_assert (read_or_write >= 0 && read_or_write <= 1);
+
+ return instr [read_or_write];
+}
+ [(set_attr "type" "load")
+ (set_attr "length" "4")])
+
+(define_insn "prefetch_nocc"
+ [(prefetch (match_operand:QI 0 "prefetch_nocc_operand" "A,RQ")
+ (match_operand:SI 1 "const_int_operand" "n,n")
+ (match_operand:SI 2 "const_int_operand" "n,n"))]
+ "TARGET_PA_20 && operands[2] != const0_rtx"
+{
+ /* The ldw instruction with a target of general register 0 prefetches
+ a cache line for a read. The ldd instruction prefetches a cache line
+ for a write. */
+ static const char * const instr[2][2] = {
+ {
+ "ldw RT'%A0,%%r0",
+ "ldd RT'%A0,%%r0",
+ },
+ {
+ "ldw%M0 %0,%%r0",
+ "ldd%M0 %0,%%r0",
+ }
+ };
+ int read_or_write = INTVAL (operands[1]);
+
+ gcc_assert (which_alternative == 0 || which_alternative == 1);
+ gcc_assert (read_or_write >= 0 && read_or_write <= 1);
+
+ return instr [which_alternative][read_or_write];
+}
+ [(set_attr "type" "load")
+ (set_attr "length" "4")])
+
+
+;; TLS Support
+(define_insn "tgd_load"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand 1 "tgd_symbolic_operand" "")] UNSPEC_TLSGD))
+ (clobber (reg:SI 1))
+ (use (reg:SI 27))]
+ ""
+ "*
+{
+ return \"addil LR'%1-$tls_gdidx$,%%r27\;ldo RR'%1-$tls_gdidx$(%%r1),%0\";
+}"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
+(define_insn "tgd_load_pic"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand 1 "tgd_symbolic_operand" "")] UNSPEC_TLSGD_PIC))
+ (clobber (reg:SI 1))
+ (use (reg:SI 19))]
+ ""
+ "*
+{
+ return \"addil LT'%1-$tls_gdidx$,%%r19\;ldo RT'%1-$tls_gdidx$(%%r1),%0\";
+}"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
+(define_insn "tld_load"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand 1 "tld_symbolic_operand" "")] UNSPEC_TLSLDM))
+ (clobber (reg:SI 1))
+ (use (reg:SI 27))]
+ ""
+ "*
+{
+ return \"addil LR'%1-$tls_ldidx$,%%r27\;ldo RR'%1-$tls_ldidx$(%%r1),%0\";
+}"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
+(define_insn "tld_load_pic"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand 1 "tld_symbolic_operand" "")] UNSPEC_TLSLDM_PIC))
+ (clobber (reg:SI 1))
+ (use (reg:SI 19))]
+ ""
+ "*
+{
+ return \"addil LT'%1-$tls_ldidx$,%%r19\;ldo RT'%1-$tls_ldidx$(%%r1),%0\";
+}"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
+(define_insn "tld_offset_load"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (unspec:SI [(match_operand 1 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 2 "register_operand" "r")))
+ (clobber (reg:SI 1))]
+ ""
+ "*
+{
+ return \"addil LR'%1-$tls_dtpoff$,%2\;ldo RR'%1-$tls_dtpoff$(%%r1),%0\";
+}"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
+(define_insn "tp_load"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(const_int 0)] UNSPEC_TP))]
+ ""
+ "mfctl %%cr27,%0"
+ [(set_attr "type" "multi")
+ (set_attr "length" "4")])
+
+(define_insn "tie_load"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand 1 "tie_symbolic_operand" "")] UNSPEC_TLSIE))
+ (clobber (reg:SI 1))
+ (use (reg:SI 27))]
+ ""
+ "*
+{
+ return \"addil LR'%1-$tls_ieoff$,%%r27\;ldw RR'%1-$tls_ieoff$(%%r1),%0\";
+}"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
+(define_insn "tie_load_pic"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand 1 "tie_symbolic_operand" "")] UNSPEC_TLSIE_PIC))
+ (clobber (reg:SI 1))
+ (use (reg:SI 19))]
+ ""
+ "*
+{
+ return \"addil LT'%1-$tls_ieoff$,%%r19\;ldw RT'%1-$tls_ieoff$(%%r1),%0\";
+}"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
+(define_insn "tle_load"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (unspec:SI [(match_operand 1 "tle_symbolic_operand" "")]
+ UNSPEC_TLSLE)
+ (match_operand:SI 2 "register_operand" "r")))
+ (clobber (reg:SI 1))]
+ ""
+ "addil LR'%1-$tls_leoff$,%2\;ldo RR'%1-$tls_leoff$(%%r1),%0"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])