;;- Machine description for HP PA-RISC architecture for GCC compiler
-;; Copyright (C) 1992-2015 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2019 Free Software Foundation, Inc.
;; Contributed by the Center for Software Science at the University
;; of Utah.
UNSPEC_TLSGD_PIC
UNSPEC_TLSLDM_PIC
UNSPEC_TLSIE_PIC
+ UNSPEC_MEMORY_BARRIER
])
;; UNSPEC_VOLATILE:
[(set_attr "type" "multi,multi")
(set_attr "length" "8,8")])
+(define_insn "absqi2"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (abs:QI (match_operand:QI 1 "register_operand" "r")))]
+ ""
+ "{extrs|extrw,s},>= %1,31,8,%0\;subi 0,%0,%0"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
+(define_insn "abshi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (abs:HI (match_operand:HI 1 "register_operand" "r")))]
+ ""
+ "{extrs|extrw,s},>= %1,31,16,%0\;subi 0,%0,%0"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
(define_insn "abssi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(abs:SI (match_operand:SI 1 "register_operand" "r")))]
[(set_attr "type" "multi")
(set_attr "length" "8")])
+(define_insn "bswaphi2"
+ [(set (match_operand:HI 0 "register_operand" "=&r")
+ (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
+ ""
+ "{extru|extrw,u} %1,23,8,%0\;{dep|depw} %1,23,8,%0"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
+(define_insn "bswapsi2"
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (bswap:SI (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "{shd|shrpw} %1,%1,16,%0\;{dep|depw} %0,15,8,%0\;{shd|shrpw} %1,%0,8,%0"
+ [(set_attr "type" "multi")
+ (set_attr "length" "12")])
+
+(define_insn "bswapdi2"
+ [(set (match_operand:DI 0 "register_operand" "=&r")
+ (bswap:DI (match_operand:DI 1 "register_operand" "r")))
+ (clobber (match_scratch:DI 2 "=r"))]
+ "TARGET_64BIT"
+ "permh,3210 %1,%2\;hshl %2,8,%0\;hshr,u %2,8,%2\;or %0,%2,%0"
+ [(set_attr "type" "multi")
+ (set_attr "length" "16")])
+
;;; Experimental conditional move patterns
(define_expand "movsicc"
xoperands[0] = operands[0];
xoperands[1] = operands[1];
- xoperands[2] = gen_label_rtx ();
-
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (xoperands[2]));
- output_asm_insn (\"mfia %0\", xoperands);
- /* If we're trying to load the address of a label that happens to be
- close, then we can use a shorter sequence. */
if (GET_CODE (operands[1]) == LABEL_REF
- && !LABEL_REF_NONLOCAL_P (operands[1])
- && INSN_ADDRESSES_SET_P ()
- && abs (INSN_ADDRESSES (INSN_UID (XEXP (operands[1], 0)))
- - INSN_ADDRESSES (INSN_UID (insn))) < 8100)
- output_asm_insn (\"ldo %1-%2(%0),%0\", xoperands);
+ && !LABEL_REF_NONLOCAL_P (operands[1]))
+ {
+ xoperands[2] = gen_label_rtx ();
+ (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
+ CODE_LABEL_NUMBER (xoperands[2]));
+ output_asm_insn (\"mfia %0\", xoperands);
+
+ /* If we're trying to load the address of a label that happens to be
+ close, then we can use a shorter sequence. */
+ if (INSN_ADDRESSES_SET_P ()
+ && abs (INSN_ADDRESSES (INSN_UID (XEXP (operands[1], 0)))
+ - INSN_ADDRESSES (INSN_UID (insn))) < 8100)
+ output_asm_insn (\"ldo %1-%2(%0),%0\", xoperands);
+ else
+ {
+ output_asm_insn (\"addil L%%%1-%2,%0\", xoperands);
+ output_asm_insn (\"ldo R%%%1-%2(%0),%0\", xoperands);
+ }
+ }
else
{
- output_asm_insn (\"addil L%%%1-%2,%0\", xoperands);
- output_asm_insn (\"ldo R%%%1-%2(%0),%0\", xoperands);
+ /* Load using linkage table. */
+ if (TARGET_64BIT)
+ {
+ output_asm_insn (\"addil LT%%%1,%%r27\", xoperands);
+ output_asm_insn (\"ldd RT%%%1(%0),%0\", xoperands);
+ }
+ else
+ {
+ output_asm_insn (\"addil LT%%%1,%%r19\", xoperands);
+ output_asm_insn (\"ldw RT%%%1(%0),%0\", xoperands);
+ }
}
return \"\";
}"
xoperands[0] = operands[0];
xoperands[1] = operands[1];
- xoperands[2] = gen_label_rtx ();
-
- output_asm_insn (\"bl .+8,%0\", xoperands);
- output_asm_insn (\"depi 0,31,2,%0\", xoperands);
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (xoperands[2]));
- /* If we're trying to load the address of a label that happens to be
- close, then we can use a shorter sequence. */
if (GET_CODE (operands[1]) == LABEL_REF
- && !LABEL_REF_NONLOCAL_P (operands[1])
- && INSN_ADDRESSES_SET_P ()
- && abs (INSN_ADDRESSES (INSN_UID (XEXP (operands[1], 0)))
- - INSN_ADDRESSES (INSN_UID (insn))) < 8100)
- output_asm_insn (\"ldo %1-%2(%0),%0\", xoperands);
+ && !LABEL_REF_NONLOCAL_P (operands[1]))
+ {
+ xoperands[2] = gen_label_rtx ();
+ output_asm_insn (\"bl .+8,%0\", xoperands);
+ output_asm_insn (\"depi 0,31,2,%0\", xoperands);
+ (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
+ CODE_LABEL_NUMBER (xoperands[2]));
+
+ /* If we're trying to load the address of a label that happens to be
+ close, then we can use a shorter sequence. */
+ if (INSN_ADDRESSES_SET_P ()
+ && abs (INSN_ADDRESSES (INSN_UID (XEXP (operands[1], 0)))
+ - INSN_ADDRESSES (INSN_UID (insn))) < 8100)
+ output_asm_insn (\"ldo %1-%2(%0),%0\", xoperands);
+ else
+ {
+ output_asm_insn (\"addil L%%%1-%2,%0\", xoperands);
+ output_asm_insn (\"ldo R%%%1-%2(%0),%0\", xoperands);
+ }
+ }
else
{
- output_asm_insn (\"addil L%%%1-%2,%0\", xoperands);
- output_asm_insn (\"ldo R%%%1-%2(%0),%0\", xoperands);
+ /* Load using linkage table. */
+ output_asm_insn (\"addil LT%%%1,%%r19\", xoperands);
+ output_asm_insn (\"ldw RT%%%1(%0),%0\", xoperands);
}
return \"\";
}"
[(set_attr "type" "binary")
(set_attr "length" "4")])
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (mult:SI (match_operand:SI 2 "register_operand" "r")
+ (match_operand:SI 3 "mem_shadd_operand" ""))
+ (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "*
+{
+ int shift_val = exact_log2 (INTVAL (operands[3]));
+ operands[3] = GEN_INT (shift_val);
+ return \"{sh%o3addl %2,%1,%0|shladd,l %2,%o3,%1,%0}\";
+}"
+ [(set_attr "type" "binary")
+ (set_attr "length" "4")])
+
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (ashift:DI (match_operand:DI 2 "register_operand" "r")
[(set_attr "type" "binary")
(set_attr "length" "4")])
+(define_insn ""
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (mult:DI (match_operand:DI 2 "register_operand" "r")
+ (match_operand:DI 3 "mem_shadd_operand" ""))
+ (match_operand:DI 1 "register_operand" "r")))]
+ "TARGET_64BIT"
+ "*
+{
+ int shift_val = exact_log2 (INTVAL (operands[3]));
+ operands[3] = GEN_INT (shift_val);
+ return \"shladd,l %2,%o3,%1,%0\";
+}"
+ [(set_attr "type" "binary")
+ (set_attr "length" "4")])
+
(define_expand "ashlsi3"
[(set (match_operand:SI 0 "register_operand" "")
(ashift:SI (match_operand:SI 1 "lhs_lshift_operand" "")
op = XEXP (operands[0], 0);
/* Generate indirect long calls to non-local functions. */
- if (!TARGET_64BIT && TARGET_LONG_CALLS && GET_CODE (op) == SYMBOL_REF)
+ if (TARGET_LONG_CALLS && GET_CODE (op) == SYMBOL_REF)
{
tree call_decl = SYMBOL_REF_DECL (op);
if (!(call_decl && targetm.binds_local_p (call_decl)))
"TARGET_64BIT"
"*
{
- pa_output_arg_descriptor (insn);
return pa_output_call (insn, operands[0], 0);
}"
[(set_attr "type" "call")
call_powf = true;
/* Generate indirect long calls to non-local functions. */
- else if (!TARGET_64BIT && TARGET_LONG_CALLS)
+ else if (TARGET_LONG_CALLS)
{
tree call_decl = SYMBOL_REF_DECL (op);
if (!(call_decl && targetm.binds_local_p (call_decl)))
"TARGET_64BIT"
"*
{
- pa_output_arg_descriptor (insn);
return pa_output_call (insn, operands[1], 0);
}"
[(set_attr "type" "call")
"TARGET_64BIT && TARGET_HPUX"
"*
{
- pa_output_arg_descriptor (insn);
return pa_output_call (insn, operands[1], 0);
}"
[(set_attr "type" "call")
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand:DI 1 "register_operand" "r"))
(match_operand 2 "" "i")))
- (clobber (reg:DI 1))
(clobber (reg:DI 2))
(clobber (match_operand 3))
(use (reg:DI 27))
[(parallel [(set (match_operand 0 "" "")
(call (mem:SI (match_operand:DI 1 "register_operand" ""))
(match_operand 2 "" "")))
- (clobber (reg:DI 1))
(clobber (reg:DI 2))
(clobber (match_operand 3))
(use (reg:DI 27))
(parallel [(set (match_dup 0)
(call (mem:SI (match_dup 1))
(match_dup 2)))
- (clobber (reg:DI 1))
(clobber (reg:DI 2))
(use (reg:DI 27))
(use (reg:DI 29))
[(parallel [(set (match_operand 0 "" "")
(call (mem:SI (match_operand:DI 1 "register_operand" ""))
(match_operand 2 "" "")))
- (clobber (reg:DI 1))
(clobber (reg:DI 2))
(clobber (match_operand 3))
(use (reg:DI 27))
(parallel [(set (match_dup 0)
(call (mem:SI (match_dup 1))
(match_dup 2)))
- (clobber (reg:DI 1))
(clobber (reg:DI 2))
(use (reg:DI 27))
(use (reg:DI 29))
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand:DI 1 "register_operand" "r"))
(match_operand 2 "" "i")))
- (clobber (reg:DI 1))
(clobber (reg:DI 2))
(use (reg:DI 27))
(use (reg:DI 29))
(cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 12)]
(symbol_ref "pa_attr_length_indirect_call (insn)")))])
+/* Expand special pc-relative call to _mcount. */
+
+(define_expand "call_mcount"
+ [(parallel [(call (match_operand:SI 0 "" "")
+ (match_operand 1 "" ""))
+ (set (reg:SI 25)
+ (plus:SI (reg:SI 2)
+ (minus:SI (match_operand 2 "" "")
+ (plus:SI (pc) (const_int 4)))))
+ (clobber (reg:SI 2))])]
+ "!TARGET_PORTABLE_RUNTIME"
+ "
+{
+ rtx op = XEXP (operands[0], 0);
+ rtx nb = operands[1];
+ rtx lab = operands[2];
+
+ if (TARGET_64BIT)
+ {
+ rtx r4 = gen_rtx_REG (word_mode, 4);
+ emit_move_insn (arg_pointer_rtx,
+ gen_rtx_PLUS (word_mode, virtual_outgoing_args_rtx,
+ GEN_INT (64)));
+ emit_call_insn (gen_call_mcount_64bit (op, nb, lab, r4));
+ }
+ else
+ {
+ if (flag_pic)
+ {
+ rtx r4 = gen_rtx_REG (word_mode, 4);
+ emit_call_insn (gen_call_mcount_pic (op, nb, lab, r4));
+ }
+ else
+ emit_call_insn (gen_call_mcount_nonpic (op, nb, lab));
+ }
+
+ DONE;
+}")
+
+(define_insn "call_mcount_nonpic"
+ [(call (mem:SI (match_operand 0 "call_operand_address" ""))
+ (match_operand 1 "" "i"))
+ (set (reg:SI 25)
+ (plus:SI (reg:SI 2)
+ (minus:SI (match_operand 2 "" "")
+ (plus:SI (pc) (const_int 4)))))
+ (clobber (reg:SI 2))]
+ "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
+ "*
+{
+ pa_output_arg_descriptor (insn);
+ return \"{bl|b,l} %0,%%r2\;ldo %2-.-4(%%r2),%%r25\";
+}"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
+(define_insn "call_mcount_pic"
+ [(call (mem:SI (match_operand 0 "call_operand_address" ""))
+ (match_operand 1 "" "i"))
+ (set (reg:SI 25)
+ (plus:SI (reg:SI 2)
+ (minus:SI (match_operand 2 "" "")
+ (plus:SI (pc) (const_int 4)))))
+ (clobber (reg:SI 2))
+ (clobber (match_operand 3))
+ (use (reg:SI 19))]
+ "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
+ "#")
+
+(define_split
+ [(parallel [(call (mem:SI (match_operand 0 "call_operand_address" ""))
+ (match_operand 1 "" ""))
+ (set (reg:SI 25)
+ (plus:SI (reg:SI 2)
+ (minus:SI (match_operand 2 "" "")
+ (plus:SI (pc) (const_int 4)))))
+ (clobber (reg:SI 2))
+ (clobber (match_operand 3))
+ (use (reg:SI 19))])]
+ "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && reload_completed"
+ [(set (match_dup 3) (reg:SI 19))
+ (parallel [(call (mem:SI (match_dup 0))
+ (match_dup 1))
+ (set (reg:SI 25)
+ (plus:SI (reg:SI 2)
+ (minus:SI (match_dup 2)
+ (plus:SI (pc) (const_int 4)))))
+ (clobber (reg:SI 2))
+ (use (reg:SI 19))])
+ (set (reg:SI 19) (match_dup 3))]
+ "")
+
+(define_insn "*call_mcount_pic_post_reload"
+ [(call (mem:SI (match_operand 0 "call_operand_address" ""))
+ (match_operand 1 "" "i"))
+ (set (reg:SI 25)
+ (plus:SI (reg:SI 2)
+ (minus:SI (match_operand 2 "" "")
+ (plus:SI (pc) (const_int 4)))))
+ (clobber (reg:SI 2))
+ (use (reg:SI 19))]
+ "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
+ "*
+{
+ pa_output_arg_descriptor (insn);
+ return \"{bl|b,l} %0,%%r2\;ldo %2-.-4(%%r2),%%r25\";
+}"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
+(define_insn "call_mcount_64bit"
+ [(call (mem:SI (match_operand 0 "call_operand_address" ""))
+ (match_operand 1 "" "i"))
+ (set (reg:SI 25)
+ (plus:SI (reg:SI 2)
+ (minus:SI (match_operand 2 "" "")
+ (plus:SI (pc) (const_int 4)))))
+ (clobber (reg:DI 2))
+ (clobber (match_operand 3))
+ (use (reg:DI 27))
+ (use (reg:DI 29))]
+ "TARGET_64BIT"
+ "#")
+
+(define_split
+ [(parallel [(call (mem:SI (match_operand 0 "call_operand_address" ""))
+ (match_operand 1 "" ""))
+ (set (reg:SI 25)
+ (plus:SI (reg:SI 2)
+ (minus:SI (match_operand 2 "" "")
+ (plus:SI (pc) (const_int 4)))))
+ (clobber (reg:DI 2))
+ (clobber (match_operand 3))
+ (use (reg:DI 27))
+ (use (reg:DI 29))])]
+ "TARGET_64BIT && reload_completed"
+ [(set (match_dup 3) (reg:DI 27))
+ (parallel [(call (mem:SI (match_dup 0))
+ (match_dup 1))
+ (set (reg:SI 25)
+ (plus:SI (reg:SI 2)
+ (minus:SI (match_dup 2)
+ (plus:SI (pc) (const_int 4)))))
+ (clobber (reg:DI 2))
+ (use (reg:DI 27))
+ (use (reg:DI 29))])
+ (set (reg:DI 27) (match_dup 3))]
+ "")
+
+(define_insn "*call_mcount_64bit_post_reload"
+ [(call (mem:SI (match_operand 0 "call_operand_address" ""))
+ (match_operand 1 "" "i"))
+ (set (reg:SI 25)
+ (plus:SI (reg:SI 2)
+ (minus:SI (match_operand 2 "" "")
+ (plus:SI (pc) (const_int 4)))))
+ (clobber (reg:DI 2))
+ (use (reg:DI 27))
+ (use (reg:DI 29))]
+ "TARGET_64BIT"
+ "{bl|b,l} %0,%%r2\;ldo %2-.-4(%%r2),%%r25"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
;; Call subroutine returning any type.
(define_expand "untyped_call"
"TARGET_64BIT"
"*
{
- pa_output_arg_descriptor (insn);
return pa_output_call (insn, operands[0], 1);
}"
[(set_attr "type" "sibcall")
"TARGET_64BIT"
"*
{
- pa_output_arg_descriptor (insn);
return pa_output_call (insn, operands[1], 1);
}"
[(set_attr "type" "sibcall")
emit_library_call_value (canonicalize_funcptr_for_compare_libfunc,
operands[0], LCT_NORMAL, Pmode,
- 1, operands[1], Pmode);
+ operands[1], Pmode);
DONE;
}
;; doubleword loads and stores are not guaranteed to be atomic
;; when referencing the I/O address space.
-;; The kernel cmpxchg operation on linux is not atomic with respect to
-;; memory stores on SMP machines, so we must do stores using a cmpxchg
-;; operation.
-
;; These patterns are at the bottom so the non atomic versions are preferred.
-;; Implement atomic QImode store using exchange.
-
(define_expand "atomic_storeqi"
[(match_operand:QI 0 "memory_operand") ;; memory
(match_operand:QI 1 "register_operand") ;; val out
FAIL;
})
-;; Implement atomic SFmode store using exchange.
-
-(define_expand "atomic_storesf"
- [(match_operand:SF 0 "memory_operand") ;; memory
- (match_operand:SF 1 "register_operand") ;; val out
- (match_operand:SI 2 "const_int_operand")] ;; model
- ""
-{
- if (TARGET_SYNC_LIBCALL)
- {
- rtx mem = operands[0];
- rtx val = operands[1];
- if (pa_maybe_emit_compare_and_swap_exchange_loop (NULL_RTX, mem, val))
- DONE;
- }
- FAIL;
-})
-
-;; Implement atomic DImode load using 64-bit floating point load.
+;; Implement atomic DImode load.
(define_expand "atomic_loaddi"
[(match_operand:DI 0 "register_operand") ;; val out
model = memmodel_from_int (INTVAL (operands[2]));
operands[1] = force_reg (SImode, XEXP (operands[1], 0));
- expand_mem_thread_fence (model);
- emit_insn (gen_atomic_loaddi_1 (operands[0], operands[1]));
if (is_mm_seq_cst (model))
expand_mem_thread_fence (model);
+ emit_insn (gen_atomic_loaddi_1 (operands[0], operands[1]));
+ expand_mem_thread_fence (model);
DONE;
})
(define_insn "atomic_loaddi_1"
- [(set (match_operand:DI 0 "register_operand" "=f,r")
- (mem:DI (match_operand:SI 1 "register_operand" "r,r")))
- (clobber (match_scratch:DI 2 "=X,f"))]
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (mem:DI (match_operand:SI 1 "register_operand" "r")))
+ (clobber (match_scratch:DI 2 "=f"))]
"!TARGET_64BIT && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT"
- "@
- {fldds|fldd} 0(%1),%0
- {fldds|fldd} 0(%1),%2\n\t{fstds|fstd} %2,-16(%%sp)\n\t{ldws|ldw} -16(%%sp),%0\n\t{ldws|ldw} -12(%%sp),%R0"
- [(set_attr "type" "move,move")
- (set_attr "length" "4,16")])
+ "{fldds|fldd} 0(%1),%2\n\t{fstds|fstd} %2,-16(%%sp)\n\t{ldws|ldw} -16(%%sp),%0\n\t{ldws|ldw} -12(%%sp),%R0"
+ [(set_attr "type" "move")
+ (set_attr "length" "16")])
;; Implement atomic DImode store.
(define_expand "atomic_storedi"
[(match_operand:DI 0 "memory_operand") ;; memory
- (match_operand:DI 1 "register_operand") ;; val out
+ (match_operand:DI 1 "reg_or_cint_move_operand") ;; val out
(match_operand:SI 2 "const_int_operand")] ;; model
""
{
model = memmodel_from_int (INTVAL (operands[2]));
operands[0] = force_reg (SImode, XEXP (operands[0], 0));
+ if (operands[1] != CONST0_RTX (DImode))
+ operands[1] = force_reg (DImode, operands[1]);
expand_mem_thread_fence (model);
emit_insn (gen_atomic_storedi_1 (operands[0], operands[1]));
if (is_mm_seq_cst (model))
(define_insn "atomic_storedi_1"
[(set (mem:DI (match_operand:SI 0 "register_operand" "r,r"))
- (match_operand:DI 1 "register_operand" "f,r"))
+ (match_operand:DI 1 "reg_or_0_operand" "M,r"))
(clobber (match_scratch:DI 2 "=X,f"))]
- "!TARGET_64BIT && !TARGET_DISABLE_FPREGS
- && !TARGET_SOFT_FLOAT && !TARGET_SYNC_LIBCALL"
+ "!TARGET_64BIT && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT"
"@
- {fstds|fstd} %1,0(%0)
+ {fstds|fstd} %%fr0,0(%0)
{stws|stw} %1,-16(%%sp)\n\t{stws|stw} %R1,-12(%%sp)\n\t{fldds|fldd} -16(%%sp),%2\n\t{fstds|fstd} %2,0(%0)"
[(set_attr "type" "move,move")
(set_attr "length" "4,16")])
-;; Implement atomic DFmode load using 64-bit floating point load.
+;; PA 2.0 hardware supports out-of-order execution of loads and stores, so
+;; we need a memory barrier to enforce program order for memory references.
+;; Since we want PA 1.x code to be PA 2.0 compatible, we also need the
+;; barrier when generating PA 1.x code.
-(define_expand "atomic_loaddf"
- [(match_operand:DF 0 "register_operand") ;; val out
- (match_operand:DF 1 "memory_operand") ;; memory
- (match_operand:SI 2 "const_int_operand")] ;; model
+(define_expand "memory_barrier"
+ [(set (match_dup 0)
+ (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))]
""
{
- enum memmodel model;
-
- if (TARGET_64BIT || TARGET_DISABLE_FPREGS || TARGET_SOFT_FLOAT)
- FAIL;
-
- model = memmodel_from_int (INTVAL (operands[2]));
- operands[1] = force_reg (SImode, XEXP (operands[1], 0));
- expand_mem_thread_fence (model);
- emit_insn (gen_atomic_loaddf_1 (operands[0], operands[1]));
- if (is_mm_seq_cst (model))
- expand_mem_thread_fence (model);
- DONE;
+ operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+ MEM_VOLATILE_P (operands[0]) = 1;
})
-(define_insn "atomic_loaddf_1"
- [(set (match_operand:DF 0 "register_operand" "=f,r")
- (mem:DF (match_operand:SI 1 "register_operand" "r,r")))
- (clobber (match_scratch:DF 2 "=X,f"))]
- "!TARGET_64BIT && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT"
- "@
- {fldds|fldd} 0(%1),%0
- {fldds|fldd} 0(%1),%2\n\t{fstds|fstd} %2,-16(%%sp)\n\t{ldws|ldw} -16(%%sp),%0\n\t{ldws|ldw} -12(%%sp),%R0"
- [(set_attr "type" "move,move")
- (set_attr "length" "4,16")])
-
-;; Implement atomic DFmode store using 64-bit floating point store.
-
-(define_expand "atomic_storedf"
- [(match_operand:DF 0 "memory_operand") ;; memory
- (match_operand:DF 1 "register_operand") ;; val out
- (match_operand:SI 2 "const_int_operand")] ;; model
+(define_insn "*memory_barrier"
+ [(set (match_operand:BLK 0 "" "")
+ (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))]
""
-{
- enum memmodel model;
-
- if (TARGET_SYNC_LIBCALL)
- {
- rtx mem = operands[0];
- rtx val = operands[1];
- if (pa_maybe_emit_compare_and_swap_exchange_loop (NULL_RTX, mem, val))
- DONE;
- }
-
- if (TARGET_64BIT || TARGET_DISABLE_FPREGS || TARGET_SOFT_FLOAT)
- FAIL;
-
- model = memmodel_from_int (INTVAL (operands[2]));
- operands[0] = force_reg (SImode, XEXP (operands[0], 0));
- expand_mem_thread_fence (model);
- emit_insn (gen_atomic_storedf_1 (operands[0], operands[1]));
- if (is_mm_seq_cst (model))
- expand_mem_thread_fence (model);
- DONE;
-})
-
-(define_insn "atomic_storedf_1"
- [(set (mem:DF (match_operand:SI 0 "register_operand" "r,r"))
- (match_operand:DF 1 "register_operand" "f,r"))
- (clobber (match_scratch:DF 2 "=X,f"))]
- "!TARGET_64BIT && !TARGET_DISABLE_FPREGS
- && !TARGET_SOFT_FLOAT && !TARGET_SYNC_LIBCALL"
- "@
- {fstds|fstd} %1,0(%0)
- {stws|stw} %1,-16(%%sp)\n\t{stws|stw} %R1,-12(%%sp)\n\t{fldds|fldd} -16(%%sp),%2\n\t{fstds|fstd} %2,0(%0)"
- [(set_attr "type" "move,move")
- (set_attr "length" "4,16")])
+ "sync"
+ [(set_attr "type" "binary")
+ (set_attr "length" "4")])