;;- Machine description for HP PA-RISC architecture for GCC compiler
-;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-;; 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1992-2020 Free Software Foundation, Inc.
;; Contributed by the Center for Software Science at the University
;; of Utah.
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
-;; This gcc Version 2 machine description is inspired by sparc.md and
-;; mips.md.
+;; This machine description is inspired by sparc.md and to a lesser
+;; extent mips.md.
+
+;; Possible improvements:
+;;
+;; * With PA1.1, most computational instructions can conditionally nullify
+;; the execution of the following instruction. A nullified instruction
+;; does not cause the instruction pipeline to stall, making it a very
+;; efficient alternative to e.g. branching or conditional moves.
+;;
+;; Nullification is performed conditionally based on the outcome of a
+;; test specified in the opcode. The test result is stored in PSW[N]
+;; and can only be used to nullify the instruction following immediately
+;; after the test. For example:
+;;
+;; ldi 10,%r26
+;; ldi 5,%r25
+;; sub,< %r26,%r25,%r28
+;; sub %r28,%r25,%r28 ; %r28 == 0
+;; sub,> %r26,%r25,%r29
+;; sub %r29,%r25,%r29 ; %r29 == 5
+;;
+;; This could be tricky to implement because the result of the test has
+;; to be propagated one instruction forward, which, in the worst case,
+;; would involve (1) adding a fake register for PSW[N]; (2) adding the
+;; variants of the computational instructions that set or consume this
+;; fake register. The cond_exec infrastructure is probably not helpful
+;; for this.
+;;
+;; * PA-RISC includes a set of conventions for branch instruction usage
+;; to indicate whether a particular branch is more likely to be taken
+;; or not taken. For example, the prediction for CMPB instructions
+;; (CMPB,cond,n r1,r2,target) depends on the direction of the branch
+;; (forward or backward) and on the order of the operands:
+;;
+;; | branch | operand | branch |
+;; | direction | compare | prediction |
+;; +-----------+----------+------------+
+;; | backward | r1 < r2 | taken |
+;; | backward | r1 >= r2 | not taken |
+;; | forward | r1 < r2 | not taken |
+;; | forward | r1 >= r2 | taken |
+;;
+;; By choosing instructions and operand order carefully, the compiler
+;; could give the CPU branch predictor some help.
+;;
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
;; Uses of UNSPEC in this file:
-(define_constants
- [(UNSPEC_CFFC 0) ; canonicalize_funcptr_for_compare
- (UNSPEC_GOTO 1) ; indirect_goto
- (UNSPEC_DLTIND14R 2) ;
- (UNSPEC_TP 3)
- (UNSPEC_TLSGD 4)
- (UNSPEC_TLSLDM 5)
- (UNSPEC_TLSLDO 6)
- (UNSPEC_TLSLDBASE 7)
- (UNSPEC_TLSIE 8)
- (UNSPEC_TLSLE 9)
- (UNSPEC_TLSGD_PIC 10)
- (UNSPEC_TLSLDM_PIC 11)
- (UNSPEC_TLSIE_PIC 12)
+(define_c_enum "unspec"
+ [UNSPEC_CFFC ; canonicalize_funcptr_for_compare
+ UNSPEC_GOTO ; indirect_goto
+ UNSPEC_DLTIND14R
+ UNSPEC_TP
+ UNSPEC_TLSGD
+ UNSPEC_TLSLDM
+ UNSPEC_TLSLDO
+ UNSPEC_TLSLDBASE
+ UNSPEC_TLSIE
+ UNSPEC_TLSLE
+ UNSPEC_TLSGD_PIC
+ UNSPEC_TLSLDM_PIC
+ UNSPEC_TLSIE_PIC
+ UNSPEC_MEMORY_BARRIER
])
;; UNSPEC_VOLATILE:
-(define_constants
- [(UNSPECV_BLOCKAGE 0) ; blockage
- (UNSPECV_DCACHE 1) ; dcacheflush
- (UNSPECV_ICACHE 2) ; icacheflush
- (UNSPECV_OPC 3) ; outline_prologue_call
- (UNSPECV_OEC 4) ; outline_epilogue_call
- (UNSPECV_LONGJMP 5) ; builtin_longjmp
+(define_c_enum "unspecv"
+ [UNSPECV_BLOCKAGE ; blockage
+ UNSPECV_DCACHE ; dcacheflush
+ UNSPECV_ICACHE ; icacheflush
+ UNSPECV_OPC ; outline_prologue_call
+ UNSPECV_OEC ; outline_epilogue_call
+ UNSPECV_LONGJMP ; builtin_longjmp
])
;; Maximum pc-relative branch offsets.
;; type "binary" insns have two input operands (1,2) and one output (0)
(define_attr "type"
- "move,unary,binary,shift,nullshift,compare,load,store,uncond_branch,btable_branch,branch,cbranch,fbranch,call,dyncall,fpload,fpstore,fpalu,fpcc,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,multi,milli,parallel_branch,fpstore_load,store_fpload"
+ "move,unary,binary,shift,nullshift,compare,load,store,uncond_branch,branch,cbranch,fbranch,call,sibcall,dyncall,fpload,fpstore,fpalu,fpcc,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,multi,milli,sh_func_adrs,parallel_branch,fpstore_load,store_fpload,trap"
(const_string "binary"))
(define_attr "pa_combine_type"
;; Attributes for instruction and branch scheduling
-;; For conditional branches.
+;; For conditional branches. Frame related instructions are not allowed
+;; because they confuse the unwind support.
(define_attr "in_branch_delay" "false,true"
- (if_then_else (and (eq_attr "type" "!uncond_branch,btable_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,parallel_branch")
- (eq_attr "length" "4"))
+ (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,sibcall,dyncall,multi,milli,sh_func_adrs,parallel_branch,trap")
+ (eq_attr "length" "4")
+ (not (match_test "RTX_FRAME_RELATED_P (insn)")))
(const_string "true")
(const_string "false")))
;; Disallow instructions which use the FPU since they will tie up the FPU
;; even if the instruction is nullified.
(define_attr "in_nullified_branch_delay" "false,true"
- (if_then_else (and (eq_attr "type" "!uncond_branch,btable_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,parallel_branch")
- (eq_attr "length" "4"))
+ (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,sibcall,dyncall,multi,milli,sh_func_adrs,fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,parallel_branch,trap")
+ (eq_attr "length" "4")
+ (not (match_test "RTX_FRAME_RELATED_P (insn)")))
(const_string "true")
(const_string "false")))
-;; For calls and millicode calls. Allow unconditional branches in the
-;; delay slot.
+;; For calls and millicode calls.
(define_attr "in_call_delay" "false,true"
- (cond [(and (eq_attr "type" "!uncond_branch,btable_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,parallel_branch")
- (eq_attr "length" "4"))
- (const_string "true")
- (eq_attr "type" "uncond_branch")
- (if_then_else (match_test "TARGET_JUMP_IN_DELAY")
- (const_string "true")
- (const_string "false"))]
- (const_string "false")))
-
+ (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,sibcall,dyncall,multi,milli,sh_func_adrs,parallel_branch,trap")
+ (eq_attr "length" "4")
+ (not (match_test "RTX_FRAME_RELATED_P (insn)")))
+ (const_string "true")
+ (const_string "false")))
;; Call delay slot description.
(define_delay (eq_attr "type" "call")
[(eq_attr "in_call_delay" "true") (nil) (nil)])
+;; Sibcall delay slot description.
+(define_delay (eq_attr "type" "sibcall")
+ [(eq_attr "in_call_delay" "true") (nil) (nil)])
+
;; Millicode call delay slot description.
(define_delay (eq_attr "type" "milli")
[(eq_attr "in_call_delay" "true") (nil) (nil)])
;; Return and other similar instructions.
-(define_delay (eq_attr "type" "btable_branch,branch,parallel_branch")
+(define_delay (eq_attr "type" "branch,parallel_branch")
[(eq_attr "in_branch_delay" "true") (nil) (nil)])
;; Floating point conditional branch delay slot description.
(and (eq_attr "in_nullified_branch_delay" "true")
(attr_flag "backward"))])
-(define_delay (and (eq_attr "type" "uncond_branch")
- (not (match_test "pa_following_call (insn)")))
+(define_delay (eq_attr "type" "uncond_branch")
[(eq_attr "in_branch_delay" "true") (nil) (nil)])
;; Memory. Disregarding Cache misses, the Mustang memory times are:
;; to assume have zero latency.
(define_insn_reservation "Z3" 0
(and
- (eq_attr "type" "!load,fpload,store,fpstore,uncond_branch,btable_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,parallel_branch,fpcc,fpalu,fpmulsgl,fpmuldbl,fpsqrtsgl,fpsqrtdbl,fpdivsgl,fpdivdbl,fpstore_load,store_fpload")
+ (eq_attr "type" "!load,fpload,store,fpstore,uncond_branch,branch,cbranch,fbranch,call,sibcall,dyncall,multi,milli,sh_func_adrs,parallel_branch,fpcc,fpalu,fpmulsgl,fpmuldbl,fpsqrtsgl,fpsqrtdbl,fpdivsgl,fpdivdbl,fpstore_load,store_fpload")
(eq_attr "cpu" "8000"))
"inm_8000,rnm_8000")
;; retirement unit.
(define_insn_reservation "Z4" 0
(and
- (eq_attr "type" "uncond_branch,btable_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,parallel_branch")
+ (eq_attr "type" "uncond_branch,branch,cbranch,fbranch,call,sibcall,dyncall,multi,milli,sh_func_adrs,parallel_branch")
(eq_attr "cpu" "8000"))
"inm0_8000+inm1_8000,rnm0_8000+rnm1_8000")
(define_insn "scc"
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operator:SI 3 "comparison_operator"
- [(match_operand:SI 1 "register_operand" "r")
+ [(match_operand:SI 1 "reg_or_0_operand" "rM")
(match_operand:SI 2 "arith11_operand" "rI")]))]
""
- "{com%I2clr|cmp%I2clr},%B3 %2,%1,%0\;ldi 1,%0"
+ "{com%I2clr|cmp%I2clr},%B3 %2,%r1,%0\;ldi 1,%0"
[(set_attr "type" "binary")
(set_attr "length" "8")])
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
(match_operator:DI 3 "comparison_operator"
- [(match_operand:DI 1 "register_operand" "r")
+ [(match_operand:DI 1 "reg_or_0_operand" "rM")
(match_operand:DI 2 "arith11_operand" "rI")]))]
"TARGET_64BIT"
- "cmp%I2clr,*%B3 %2,%1,%0\;ldi 1,%0"
+ "cmp%I2clr,*%B3 %2,%r1,%0\;ldi 1,%0"
[(set_attr "type" "binary")
(set_attr "length" "8")])
(define_insn "iorscc"
[(set (match_operand:SI 0 "register_operand" "=r")
(ior:SI (match_operator:SI 3 "comparison_operator"
- [(match_operand:SI 1 "register_operand" "r")
+ [(match_operand:SI 1 "reg_or_0_operand" "rM")
(match_operand:SI 2 "arith11_operand" "rI")])
(match_operator:SI 6 "comparison_operator"
- [(match_operand:SI 4 "register_operand" "r")
+ [(match_operand:SI 4 "reg_or_0_operand" "rM")
(match_operand:SI 5 "arith11_operand" "rI")])))]
""
- "{com%I2clr|cmp%I2clr},%S3 %2,%1,%%r0\;{com%I5clr|cmp%I5clr},%B6 %5,%4,%0\;ldi 1,%0"
+ "{com%I2clr|cmp%I2clr},%S3 %2,%r1,%%r0\;{com%I5clr|cmp%I5clr},%B6 %5,%r4,%0\;ldi 1,%0"
[(set_attr "type" "binary")
(set_attr "length" "12")])
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
(ior:DI (match_operator:DI 3 "comparison_operator"
- [(match_operand:DI 1 "register_operand" "r")
+ [(match_operand:DI 1 "reg_or_0_operand" "rM")
(match_operand:DI 2 "arith11_operand" "rI")])
(match_operator:DI 6 "comparison_operator"
- [(match_operand:DI 4 "register_operand" "r")
+ [(match_operand:DI 4 "reg_or_0_operand" "rM")
(match_operand:DI 5 "arith11_operand" "rI")])))]
"TARGET_64BIT"
- "cmp%I2clr,*%S3 %2,%1,%%r0\;cmp%I5clr,*%B6 %5,%4,%0\;ldi 1,%0"
+ "cmp%I2clr,*%S3 %2,%r1,%%r0\;cmp%I5clr,*%B6 %5,%r4,%0\;ldi 1,%0"
[(set_attr "type" "binary")
(set_attr "length" "12")])
(define_insn "negscc"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_operator:SI 3 "comparison_operator"
- [(match_operand:SI 1 "register_operand" "r")
+ [(match_operand:SI 1 "reg_or_0_operand" "rM")
(match_operand:SI 2 "arith11_operand" "rI")])))]
""
- "{com%I2clr|cmp%I2clr},%B3 %2,%1,%0\;ldi -1,%0"
+ "{com%I2clr|cmp%I2clr},%B3 %2,%r1,%0\;ldi -1,%0"
[(set_attr "type" "binary")
(set_attr "length" "8")])
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
(neg:DI (match_operator:DI 3 "comparison_operator"
- [(match_operand:DI 1 "register_operand" "r")
+ [(match_operand:DI 1 "reg_or_0_operand" "rM")
(match_operand:DI 2 "arith11_operand" "rI")])))]
"TARGET_64BIT"
- "cmp%I2clr,*%B3 %2,%1,%0\;ldi -1,%0"
+ "cmp%I2clr,*%B3 %2,%r1,%0\;ldi -1,%0"
[(set_attr "type" "binary")
(set_attr "length" "8")])
[(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"
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+ emit_insn (gen_rtx_SET (operands[0], operands[1]));
DONE;
}")
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+ emit_insn (gen_rtx_SET (operands[0], operands[1]));
DONE;
}")
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+ emit_insn (gen_rtx_SET (operands[0], operands[1]));
DONE;
}")
; computes the address to be deleted if the register it sets is dead.
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "")
- (const_int 4))
+ (plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
+ (const_int 2))
(match_operand:SI 2 "register_operand" "")))
(set (mem:SI (match_dup 0))
(match_operand:SI 3 "register_operand" ""))]
&& FP_REGNO_P (REGNO (operands[3]))"
[(set (mem:SI (plus:SI (mult:SI (match_dup 1) (const_int 4)) (match_dup 2)))
(match_dup 3))
- (set (match_dup 0) (plus:SI (mult:SI (match_dup 1) (const_int 4))
- (match_dup 2)))]
- "")
-
-(define_peephole2
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (match_operand:SI 2 "register_operand" "")
- (mult:SI (match_operand:SI 1 "register_operand" "")
- (const_int 4))))
- (set (mem:SI (match_dup 0))
- (match_operand:SI 3 "register_operand" ""))]
- "!TARGET_SOFT_FLOAT
- && !TARGET_DISABLE_INDEXING
- && REG_OK_FOR_BASE_P (operands[2])
- && FP_REGNO_P (REGNO (operands[3]))"
- [(set (mem:SI (plus:SI (mult:SI (match_dup 1) (const_int 4)) (match_dup 2)))
- (match_dup 3))
- (set (match_dup 0) (plus:SI (mult:SI (match_dup 1) (const_int 4))
+ (set (match_dup 0) (plus:SI (ashift:SI (match_dup 1) (const_int 2))
(match_dup 2)))]
"")
(define_peephole2
[(set (match_operand:DI 0 "register_operand" "")
- (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "")
- (const_int 4))
+ (plus:DI (ashift:DI (match_operand:DI 1 "register_operand" "")
+ (const_int 2))
(match_operand:DI 2 "register_operand" "")))
(set (mem:SI (match_dup 0))
(match_operand:SI 3 "register_operand" ""))]
&& FP_REGNO_P (REGNO (operands[3]))"
[(set (mem:SI (plus:DI (mult:DI (match_dup 1) (const_int 4)) (match_dup 2)))
(match_dup 3))
- (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 4))
- (match_dup 2)))]
- "")
-
-(define_peephole2
- [(set (match_operand:DI 0 "register_operand" "")
- (plus:DI (match_operand:DI 2 "register_operand" "")
- (mult:DI (match_operand:DI 1 "register_operand" "")
- (const_int 4))))
- (set (mem:SI (match_dup 0))
- (match_operand:SI 3 "register_operand" ""))]
- "!TARGET_SOFT_FLOAT
- && !TARGET_DISABLE_INDEXING
- && TARGET_64BIT
- && REG_OK_FOR_BASE_P (operands[2])
- && FP_REGNO_P (REGNO (operands[3]))"
- [(set (mem:SI (plus:DI (mult:DI (match_dup 1) (const_int 4)) (match_dup 2)))
- (match_dup 3))
- (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 4))
+ (set (match_dup 0) (plus:DI (ashift:DI (match_dup 1) (const_int 2))
(match_dup 2)))]
"")
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")
+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand 2 "" "")] UNSPEC_DLTIND14R)))]
+ "symbolic_operand (operands[2], Pmode)
+ && ! function_label_operand (operands[2], Pmode)
+ && flag_pic"
+ "ldo RT'%G2(%1),%0"
+ [(set_attr "type" "binary")
+ (set_attr "length" "4")])
+
+(define_insn ""
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand 2 "" "")] UNSPEC_DLTIND14R)))]
+ "symbolic_operand (operands[2], Pmode)
+ && ! function_label_operand (operands[2], Pmode)
+ && TARGET_64BIT
+ && flag_pic"
+ "ldo RT'%G2(%1),%0"
+ [(set_attr "type" "binary")
+ (set_attr "length" "4")])
+
;; Always use addil rather than ldil;add sequences. This allows the
;; HP linker to eliminate the dp relocation if the symbolic operand
;; lives in the TEXT space.
;; a 2 insn store with some creative RTL rewriting.
(define_split
[(set (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "shadd_operand" ""))
+ (match_operand:SI 1 "mem_shadd_operand" ""))
(plus:SI (match_operand:SI 2 "register_operand" "")
(match_operand:SI 3 "const_int_operand" ""))))
(match_operand:SI 4 "register_operand" ""))
(clobber (match_operand:SI 5 "register_operand" ""))]
""
- [(set (match_dup 5) (plus:SI (mult:SI (match_dup 0) (match_dup 1))
+ [(set (match_dup 5) (plus:SI (ashift:SI (match_dup 0) (match_dup 1))
(match_dup 2)))
(set (mem:SI (plus:SI (match_dup 5) (match_dup 3))) (match_dup 4))]
- "")
+ "
+{
+ operands[1] = GEN_INT (exact_log2 (INTVAL (operands[1])));
+
+}")
(define_split
[(set (mem:HI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "shadd_operand" ""))
+ (match_operand:SI 1 "mem_shadd_operand" ""))
(plus:SI (match_operand:SI 2 "register_operand" "")
(match_operand:SI 3 "const_int_operand" ""))))
(match_operand:HI 4 "register_operand" ""))
(clobber (match_operand:SI 5 "register_operand" ""))]
""
- [(set (match_dup 5) (plus:SI (mult:SI (match_dup 0) (match_dup 1))
+ [(set (match_dup 5) (plus:SI (ashift:SI (match_dup 0) (match_dup 1))
(match_dup 2)))
(set (mem:HI (plus:SI (match_dup 5) (match_dup 3))) (match_dup 4))]
- "")
+ "
+{
+ operands[1] = GEN_INT (exact_log2 (INTVAL (operands[1])));
+
+}")
(define_split
[(set (mem:QI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "shadd_operand" ""))
+ (match_operand:SI 1 "mem_shadd_operand" ""))
(plus:SI (match_operand:SI 2 "register_operand" "")
(match_operand:SI 3 "const_int_operand" ""))))
(match_operand:QI 4 "register_operand" ""))
(clobber (match_operand:SI 5 "register_operand" ""))]
""
- [(set (match_dup 5) (plus:SI (mult:SI (match_dup 0) (match_dup 1))
+ [(set (match_dup 5) (plus:SI (ashift:SI (match_dup 0) (match_dup 1))
(match_dup 2)))
(set (mem:QI (plus:SI (match_dup 5) (match_dup 3))) (match_dup 4))]
- "")
+ "
+{
+ operands[1] = GEN_INT (exact_log2 (INTVAL (operands[1])));
+
+}")
(define_expand "movhi"
[(set (match_operand:HI 0 "general_operand" "")
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+ emit_insn (gen_rtx_SET (operands[0], operands[1]));
DONE;
}")
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+ emit_insn (gen_rtx_SET (operands[0], operands[1]));
DONE;
}")
[(set_attr "type" "store")
(set_attr "length" "4")])
-(define_insn ""
- [(set (match_operand:HI 0 "register_operand" "=r")
- (plus:HI (match_operand:HI 1 "register_operand" "r")
- (match_operand 2 "const_int_operand" "J")))]
+(define_insn "addhi3"
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (plus:HI (match_operand:HI 1 "register_operand" "%r,r")
+ (match_operand:HI 2 "arith14_operand" "r,J")))]
""
- "ldo %2(%1),%0"
- [(set_attr "type" "binary")
+ "@
+ {addl|add,l} %1,%2,%0
+ ldo %2(%1),%0"
+ [(set_attr "type" "binary,binary")
(set_attr "pa_combine_type" "addmove")
- (set_attr "length" "4")])
+ (set_attr "length" "4,4")])
(define_expand "movqi"
[(set (match_operand:QI 0 "general_operand" "")
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+ emit_insn (gen_rtx_SET (operands[0], operands[1]));
DONE;
}")
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+ emit_insn (gen_rtx_SET (operands[0], operands[1]));
DONE;
}")
;; The definition of this insn does not really explain what it does,
;; but it should suffice that anything generated as this insn will be
-;; recognized as a movmemsi operation, and that it will not successfully
+;; recognized as a cpymemsi operation, and that it will not successfully
;; combine with anything.
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
[(parallel [(set (match_operand:BLK 0 "" "")
(match_operand:BLK 1 "" ""))
(clobber (match_dup 4))
;; operands 0 and 1 are both equivalent to symbolic MEMs. Thus, we are
;; forced to internally copy operands 0 and 1 to operands 7 and 8,
;; respectively. We then split or peephole optimize after reload.
-(define_insn "movmemsi_prereload"
+(define_insn "cpymemsi_prereload"
[(set (mem:BLK (match_operand:SI 0 "register_operand" "r,r"))
(mem:BLK (match_operand:SI 1 "register_operand" "r,r")))
(clobber (match_operand:SI 2 "register_operand" "=&r,&r")) ;loop cnt/tmp
operands[7] = addr;
else
{
- emit_insn (gen_rtx_SET (VOIDmode, operands[7], addr));
+ emit_insn (gen_rtx_SET (operands[7], addr));
operands[0] = replace_equiv_address (operands[0], operands[7]);
}
operands[8] = addr;
else
{
- emit_insn (gen_rtx_SET (VOIDmode, operands[8], addr));
+ emit_insn (gen_rtx_SET (operands[8], addr));
operands[1] = replace_equiv_address (operands[1], operands[8]);
}
}")
-(define_insn "movmemsi_postreload"
+(define_insn "cpymemsi_postreload"
[(set (mem:BLK (match_operand:SI 0 "register_operand" "+r,r"))
(mem:BLK (match_operand:SI 1 "register_operand" "+r,r")))
(clobber (match_operand:SI 2 "register_operand" "=&r,&r")) ;loop cnt/tmp
"* return pa_output_block_move (operands, !which_alternative);"
[(set_attr "type" "multi,multi")])
-(define_expand "movmemdi"
+(define_expand "cpymemdi"
[(parallel [(set (match_operand:BLK 0 "" "")
(match_operand:BLK 1 "" ""))
(clobber (match_dup 4))
;; operands 0 and 1 are both equivalent to symbolic MEMs. Thus, we are
;; forced to internally copy operands 0 and 1 to operands 7 and 8,
;; respectively. We then split or peephole optimize after reload.
-(define_insn "movmemdi_prereload"
+(define_insn "cpymemdi_prereload"
[(set (mem:BLK (match_operand:DI 0 "register_operand" "r,r"))
(mem:BLK (match_operand:DI 1 "register_operand" "r,r")))
(clobber (match_operand:DI 2 "register_operand" "=&r,&r")) ;loop cnt/tmp
operands[7] = addr;
else
{
- emit_insn (gen_rtx_SET (VOIDmode, operands[7], addr));
+ emit_insn (gen_rtx_SET (operands[7], addr));
operands[0] = replace_equiv_address (operands[0], operands[7]);
}
operands[8] = addr;
else
{
- emit_insn (gen_rtx_SET (VOIDmode, operands[8], addr));
+ emit_insn (gen_rtx_SET (operands[8], addr));
operands[1] = replace_equiv_address (operands[1], operands[8]);
}
}")
-(define_insn "movmemdi_postreload"
+(define_insn "cpymemdi_postreload"
[(set (mem:BLK (match_operand:DI 0 "register_operand" "+r,r"))
(mem:BLK (match_operand:DI 1 "register_operand" "+r,r")))
(clobber (match_operand:DI 2 "register_operand" "=&r,&r")) ;loop cnt/tmp
operands[4] = addr;
else
{
- emit_insn (gen_rtx_SET (VOIDmode, operands[4], addr));
+ emit_insn (gen_rtx_SET (operands[4], addr));
operands[0] = replace_equiv_address (operands[0], operands[4]);
}
}")
operands[4] = addr;
else
{
- emit_insn (gen_rtx_SET (VOIDmode, operands[4], addr));
+ emit_insn (gen_rtx_SET (operands[4], addr));
operands[0] = replace_equiv_address (operands[0], operands[4]);
}
}")
\f
;; Floating point move insns
-;; This pattern forces (set (reg:DF ...) (const_double ...))
-;; to be reloaded by putting the constant into memory when
-;; reg is a floating point register.
-;;
-;; For integer registers we use ldil;ldo to set the appropriate
-;; value.
-;;
-;; This must come before the movdf pattern, and it must be present
-;; to handle obscure reloading cases.
-(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=?r,f")
- (match_operand:DF 1 "" "?F,m"))]
- "GET_CODE (operands[1]) == CONST_DOUBLE
- && operands[1] != CONST0_RTX (DFmode)
- && !TARGET_64BIT
- && !TARGET_SOFT_FLOAT"
- "* return (which_alternative == 0 ? pa_output_move_double (operands)
- : \"fldd%F1 %1,%0\");"
- [(set_attr "type" "move,fpload")
- (set_attr "length" "16,4")])
-
(define_expand "movdf"
[(set (match_operand:DF 0 "general_operand" "")
(match_operand:DF 1 "general_operand" ""))]
""
"
{
- if (GET_CODE (operands[1]) == CONST_DOUBLE
- && operands[1] != CONST0_RTX (DFmode))
- {
- /* Reject CONST_DOUBLE loads to all hard registers when
- generating 64-bit code and to floating point registers
- when generating 32-bit code. */
- if (REG_P (operands[0])
- && HARD_REGISTER_P (operands[0])
- && (TARGET_64BIT || REGNO (operands[0]) >= 32))
- FAIL;
-
- if (TARGET_64BIT)
- operands[1] = force_const_mem (DFmode, operands[1]);
- }
-
if (pa_emit_move_sequence (operands, DFmode, 0))
DONE;
}")
+;; Handle DFmode input reloads requiring %r1 as a scratch register.
+(define_expand "reload_indf_r1"
+ [(set (match_operand:DF 0 "register_operand" "=Z")
+ (match_operand:DF 1 "non_hard_reg_operand" ""))
+ (clobber (match_operand:SI 2 "register_operand" "=&a"))]
+ ""
+ "
+{
+ if (pa_emit_move_sequence (operands, DFmode, operands[2]))
+ DONE;
+
+ /* We don't want the clobber emitted, so handle this ourselves. */
+ emit_insn (gen_rtx_SET (operands[0], operands[1]));
+ DONE;
+}")
+
;; Handle DFmode input reloads requiring a general register as a
;; scratch register.
(define_expand "reload_indf"
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+ emit_insn (gen_rtx_SET (operands[0], operands[1]));
DONE;
}")
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+ emit_insn (gen_rtx_SET (operands[0], operands[1]));
DONE;
}")
(define_insn ""
[(set (match_operand:DF 0 "move_dest_operand"
- "=f,*r,Q,?o,?Q,f,*r,*r,?*r,?f")
+ "=f,*r,T,?o,?Q,f,*r,*r,?*r,?f")
(match_operand:DF 1 "reg_or_0_or_nonsymb_mem_operand"
- "fG,*rG,f,*r,*r,RQ,o,RQ,f,*r"))]
+ "fG,*rG,f,*r,*r,RT,o,RQ,f,*r"))]
"(register_operand (operands[0], DFmode)
|| reg_or_0_operand (operands[1], DFmode))
&& !(GET_CODE (operands[1]) == CONST_DOUBLE
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "")
- (const_int 8))
+ (plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
+ (const_int 3))
(match_operand:SI 2 "register_operand" "")))
(set (mem:DF (match_dup 0))
(match_operand:DF 3 "register_operand" ""))]
&& FP_REGNO_P (REGNO (operands[3]))"
[(set (mem:DF (plus:SI (mult:SI (match_dup 1) (const_int 8)) (match_dup 2)))
(match_dup 3))
- (set (match_dup 0) (plus:SI (mult:SI (match_dup 1) (const_int 8))
+ (set (match_dup 0) (plus:SI (ashift:SI (match_dup 1) (const_int 3))
(match_dup 2)))]
"")
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
(plus:SI (match_operand:SI 2 "register_operand" "")
- (mult:SI (match_operand:SI 1 "register_operand" "")
- (const_int 8))))
+ (ashift:SI (match_operand:SI 1 "register_operand" "")
+ (const_int 3))))
(set (mem:DF (match_dup 0))
(match_operand:DF 3 "register_operand" ""))]
"!TARGET_SOFT_FLOAT
&& FP_REGNO_P (REGNO (operands[3]))"
[(set (mem:DF (plus:SI (mult:SI (match_dup 1) (const_int 8)) (match_dup 2)))
(match_dup 3))
- (set (match_dup 0) (plus:SI (mult:SI (match_dup 1) (const_int 8))
+ (set (match_dup 0) (plus:SI (ashift:SI (match_dup 1) (const_int 3))
(match_dup 2)))]
"")
(define_peephole2
[(set (match_operand:DI 0 "register_operand" "")
- (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "")
- (const_int 8))
+ (plus:DI (ashift:DI (match_operand:DI 1 "register_operand" "")
+ (const_int 3))
(match_operand:DI 2 "register_operand" "")))
(set (mem:DF (match_dup 0))
(match_operand:DF 3 "register_operand" ""))]
&& FP_REGNO_P (REGNO (operands[3]))"
[(set (mem:DF (plus:DI (mult:DI (match_dup 1) (const_int 8)) (match_dup 2)))
(match_dup 3))
- (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 8))
+ (set (match_dup 0) (plus:DI (ashift:DI (match_dup 1) (const_int 3))
(match_dup 2)))]
"")
(define_peephole2
[(set (match_operand:DI 0 "register_operand" "")
(plus:DI (match_operand:DI 2 "register_operand" "")
- (mult:DI (match_operand:DI 1 "register_operand" "")
- (const_int 8))))
+ (ashift:DI (match_operand:DI 1 "register_operand" "")
+ (const_int 3))))
(set (mem:DF (match_dup 0))
(match_operand:DF 3 "register_operand" ""))]
"!TARGET_SOFT_FLOAT
&& FP_REGNO_P (REGNO (operands[3]))"
[(set (mem:DF (plus:DI (mult:DI (match_dup 1) (const_int 8)) (match_dup 2)))
(match_dup 3))
- (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 8))
+ (set (match_dup 0) (plus:DI (ashift:DI (match_dup 1) (const_int 3))
(match_dup 2)))]
"")
""
"
{
- /* Except for zero, we don't support loading a CONST_INT directly
- to a hard floating-point register since a scratch register is
- needed for the operation. While the operation could be handled
- before register allocation, the simplest solution is to fail. */
- if (TARGET_64BIT
- && GET_CODE (operands[1]) == CONST_INT
- && operands[1] != CONST0_RTX (DImode)
- && REG_P (operands[0])
- && HARD_REGISTER_P (operands[0])
- && REGNO (operands[0]) >= 32)
- FAIL;
-
if (pa_emit_move_sequence (operands, DImode, 0))
DONE;
}")
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+ emit_insn (gen_rtx_SET (operands[0], operands[1]));
DONE;
}")
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+ emit_insn (gen_rtx_SET (operands[0], operands[1]));
DONE;
}")
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+ emit_insn (gen_rtx_SET (operands[0], operands[1]));
DONE;
}")
(define_insn ""
[(set (match_operand:DI 0 "move_dest_operand"
"=r,o,Q,r,r,r,*f,*f,T,?r,?*f")
- (match_operand:DI 1 "general_operand"
+ (match_operand:DI 1 "move_src_operand"
"rM,r,r,o*R,Q,i,*fM,RT,*f,*f,r"))]
"(register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))
(define_peephole2
[(set (match_operand:DI 0 "register_operand" "")
- (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "")
- (const_int 8))
+ (plus:DI (ashift:DI (match_operand:DI 1 "register_operand" "")
+ (const_int 3))
(match_operand:DI 2 "register_operand" "")))
(set (mem:DI (match_dup 0))
(match_operand:DI 3 "register_operand" ""))]
&& FP_REGNO_P (REGNO (operands[3]))"
[(set (mem:DI (plus:DI (mult:DI (match_dup 1) (const_int 8)) (match_dup 2)))
(match_dup 3))
- (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 8))
- (match_dup 2)))]
- "")
-
-(define_peephole2
- [(set (match_operand:DI 0 "register_operand" "")
- (plus:DI (match_operand:DI 2 "register_operand" "")
- (mult:DI (match_operand:DI 1 "register_operand" "")
- (const_int 8))))
- (set (mem:DI (match_dup 0))
- (match_operand:DI 3 "register_operand" ""))]
- "!TARGET_SOFT_FLOAT
- && !TARGET_DISABLE_INDEXING
- && TARGET_64BIT
- && REG_OK_FOR_BASE_P (operands[2])
- && FP_REGNO_P (REGNO (operands[3]))"
- [(set (mem:DI (plus:DI (mult:DI (match_dup 1) (const_int 8)) (match_dup 2)))
- (match_dup 3))
- (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 8))
+ (set (match_dup 0) (plus:DI (ashift:DI (match_dup 1) (const_int 3))
(match_dup 2)))]
"")
[(set_attr "type" "move,move")
(set_attr "length" "4,8")])
-;; This pattern forces (set (reg:SF ...) (const_double ...))
-;; to be reloaded by putting the constant into memory when
-;; reg is a floating point register.
-;;
-;; For integer registers we use ldil;ldo to set the appropriate
-;; value.
-;;
-;; This must come before the movsf pattern, and it must be present
-;; to handle obscure reloading cases.
-(define_insn ""
- [(set (match_operand:SF 0 "register_operand" "=?r,f")
- (match_operand:SF 1 "" "?F,m"))]
- "GET_CODE (operands[1]) == CONST_DOUBLE
- && operands[1] != CONST0_RTX (SFmode)
- && ! TARGET_SOFT_FLOAT"
- "* return (which_alternative == 0 ? pa_singlemove_string (operands)
- : \" fldw%F1 %1,%0\");"
- [(set_attr "type" "move,fpload")
- (set_attr "length" "8,4")])
-
(define_expand "movsf"
[(set (match_operand:SF 0 "general_operand" "")
(match_operand:SF 1 "general_operand" ""))]
""
"
{
- /* Reject CONST_DOUBLE loads to floating point registers. */
- if (GET_CODE (operands[1]) == CONST_DOUBLE
- && operands[1] != CONST0_RTX (SFmode)
- && REG_P (operands[0])
- && HARD_REGISTER_P (operands[0])
- && REGNO (operands[0]) >= 32)
- FAIL;
-
if (pa_emit_move_sequence (operands, SFmode, 0))
DONE;
}")
+;; Handle SFmode input reloads requiring %r1 as a scratch register.
+(define_expand "reload_insf_r1"
+ [(set (match_operand:SF 0 "register_operand" "=Z")
+ (match_operand:SF 1 "non_hard_reg_operand" ""))
+ (clobber (match_operand:SI 2 "register_operand" "=&a"))]
+ ""
+ "
+{
+ if (pa_emit_move_sequence (operands, SFmode, operands[2]))
+ DONE;
+
+ /* We don't want the clobber emitted, so handle this ourselves. */
+ emit_insn (gen_rtx_SET (operands[0], operands[1]));
+ DONE;
+}")
+
;; Handle SFmode input reloads requiring a general register as a
;; scratch register.
(define_expand "reload_insf"
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+ emit_insn (gen_rtx_SET (operands[0], operands[1]));
DONE;
}")
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+ emit_insn (gen_rtx_SET (operands[0], operands[1]));
DONE;
}")
(define_insn ""
[(set (match_operand:SF 0 "move_dest_operand"
- "=f,!*r,f,*r,Q,Q,?*r,?f")
+ "=f,!*r,f,*r,T,Q,?*r,?f")
(match_operand:SF 1 "reg_or_0_or_nonsymb_mem_operand"
- "fG,!*rG,RQ,RQ,f,*rG,f,*r"))]
+ "fG,!*rG,RT,RQ,f,*rG,f,*r"))]
"(register_operand (operands[0], SFmode)
|| reg_or_0_operand (operands[1], SFmode))
&& !TARGET_SOFT_FLOAT
(define_insn ""
[(set (match_operand:SF 0 "move_dest_operand"
- "=f,!*r,f,*r,Q,Q")
+ "=f,!*r,f,*r,T,Q")
(match_operand:SF 1 "reg_or_0_or_nonsymb_mem_operand"
- "fG,!*rG,RQ,RQ,f,*rG"))]
+ "fG,!*rG,RT,RQ,f,*rG"))]
"(register_operand (operands[0], SFmode)
|| reg_or_0_operand (operands[1], SFmode))
&& !TARGET_SOFT_FLOAT
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "")
- (const_int 4))
+ (plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
+ (const_int 2))
(match_operand:SI 2 "register_operand" "")))
(set (mem:SF (match_dup 0))
(match_operand:SF 3 "register_operand" ""))]
&& FP_REGNO_P (REGNO (operands[3]))"
[(set (mem:SF (plus:SI (mult:SI (match_dup 1) (const_int 4)) (match_dup 2)))
(match_dup 3))
- (set (match_dup 0) (plus:SI (mult:SI (match_dup 1) (const_int 4))
- (match_dup 2)))]
- "")
-
-(define_peephole2
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (match_operand:SI 2 "register_operand" "")
- (mult:SI (match_operand:SI 1 "register_operand" "")
- (const_int 4))))
- (set (mem:SF (match_dup 0))
- (match_operand:SF 3 "register_operand" ""))]
- "!TARGET_SOFT_FLOAT
- && !TARGET_DISABLE_INDEXING
- && REG_OK_FOR_BASE_P (operands[2])
- && FP_REGNO_P (REGNO (operands[3]))"
- [(set (mem:SF (plus:SI (mult:SI (match_dup 1) (const_int 4)) (match_dup 2)))
- (match_dup 3))
- (set (match_dup 0) (plus:SI (mult:SI (match_dup 1) (const_int 4))
+ (set (match_dup 0) (plus:SI (ashift:SI (match_dup 1) (const_int 2))
(match_dup 2)))]
"")
(define_peephole2
[(set (match_operand:DI 0 "register_operand" "")
- (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "")
- (const_int 4))
+ (plus:DI (ashift:DI (match_operand:DI 1 "register_operand" "")
+ (const_int 2))
(match_operand:DI 2 "register_operand" "")))
(set (mem:SF (match_dup 0))
(match_operand:SF 3 "register_operand" ""))]
&& FP_REGNO_P (REGNO (operands[3]))"
[(set (mem:SF (plus:DI (mult:DI (match_dup 1) (const_int 4)) (match_dup 2)))
(match_dup 3))
- (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 4))
- (match_dup 2)))]
- "")
-
-(define_peephole2
- [(set (match_operand:DI 0 "register_operand" "")
- (plus:DI (match_operand:DI 2 "register_operand" "")
- (mult:DI (match_operand:DI 1 "register_operand" "")
- (const_int 4))))
- (set (mem:SF (match_dup 0))
- (match_operand:SF 3 "register_operand" ""))]
- "!TARGET_SOFT_FLOAT
- && !TARGET_DISABLE_INDEXING
- && TARGET_64BIT
- && REG_OK_FOR_BASE_P (operands[2])
- && FP_REGNO_P (REGNO (operands[3]))"
- [(set (mem:SF (plus:DI (mult:DI (match_dup 1) (const_int 4)) (match_dup 2)))
- (match_dup 3))
- (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 4))
+ (set (match_dup 0) (plus:DI (ashift:DI (match_dup 1) (const_int 2))
(match_dup 2)))]
"")
(plus:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "const_int_operand" "")))
(clobber (match_operand:SI 4 "register_operand" ""))]
- "! pa_cint_ok_for_move (INTVAL (operands[2]))
+ "! pa_cint_ok_for_move (UINTVAL (operands[2]))
&& VAL_14_BITS_P (INTVAL (operands[2]) >> 1)"
[(set (match_dup 4) (plus:SI (match_dup 1) (match_dup 2)))
(set (match_dup 0) (plus:SI (match_dup 4) (match_dup 3)))]
(plus:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "const_int_operand" "")))
(clobber (match_operand:SI 4 "register_operand" ""))]
- "! pa_cint_ok_for_move (INTVAL (operands[2]))"
+ "! pa_cint_ok_for_move (UINTVAL (operands[2]))"
[(set (match_dup 4) (match_dup 2))
- (set (match_dup 0) (plus:SI (mult:SI (match_dup 4) (match_dup 3))
+ (set (match_dup 0) (plus:SI (ashift:SI (match_dup 4) (match_dup 3))
(match_dup 1)))]
"
{
- HOST_WIDE_INT intval = INTVAL (operands[2]);
+ unsigned HOST_WIDE_INT intval = UINTVAL (operands[2]);
/* Try dividing the constant by 2, then 4, and finally 8 to see
if we can get a constant which can be loaded into a register
if (intval % 2 == 0 && pa_cint_ok_for_move (intval / 2))
{
operands[2] = GEN_INT (intval / 2);
- operands[3] = const2_rtx;
+ operands[3] = const1_rtx;
}
else if (intval % 4 == 0 && pa_cint_ok_for_move (intval / 4))
{
operands[2] = GEN_INT (intval / 4);
- operands[3] = GEN_INT (4);
+ operands[3] = const2_rtx;
}
else if (intval % 8 == 0 && pa_cint_ok_for_move (intval / 8))
{
operands[2] = GEN_INT (intval / 8);
- operands[3] = GEN_INT (8);
+ operands[3] = GEN_INT (3);
}
else if (pa_cint_ok_for_move (-intval))
{
- emit_insn (gen_rtx_SET (VOIDmode, operands[4], GEN_INT (-intval)));
+ emit_insn (gen_rtx_SET (operands[4], GEN_INT (-intval)));
emit_insn (gen_subsi3 (operands[0], operands[1], operands[4]));
DONE;
}
[(set_attr "type" "binary,binary")
(set_attr "length" "4,4")])
+;; Trap instructions.
+
+(define_insn "trap"
+ [(trap_if (const_int 1) (const_int 0))]
+ ""
+ "{addit|addi,tc},<> 1,%%r0,%%r0"
+ [(set_attr "type" "trap")
+ (set_attr "length" "4")])
+
;; Clobbering a "register_operand" instead of a match_scratch
;; in operand3 of millicode calls avoids spilling %r1 and
;; produces better code.
}")
(define_insn "umulsidi3"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=f")
- (mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "f"))
- (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "f"))))]
+ [(set (match_operand:DI 0 "register_operand" "=f")
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "f"))
+ (zero_extend:DI (match_operand:SI 2 "register_operand" "f"))))]
"TARGET_PA_11 && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT"
"xmpyu %1,%2,%0"
[(set_attr "type" "fpmuldbl")
(set_attr "length" "4")])
(define_insn ""
- [(set (match_operand:DI 0 "nonimmediate_operand" "=f")
- (mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "f"))
+ [(set (match_operand:DI 0 "register_operand" "=f")
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "f"))
(match_operand:DI 2 "uint32_operand" "f")))]
"TARGET_PA_11 && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT && !TARGET_64BIT"
"xmpyu %1,%R2,%0"
(set_attr "length" "4")])
(define_insn ""
- [(set (match_operand:DI 0 "nonimmediate_operand" "=f")
- (mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "f"))
+ [(set (match_operand:DI 0 "register_operand" "=f")
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "f"))
(match_operand:DI 2 "uint32_operand" "f")))]
"TARGET_PA_11 && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT && TARGET_64BIT"
"xmpyu %1,%2R,%0"
"!TARGET_64BIT"
"* return pa_output_mul_insn (0, insn);"
[(set_attr "type" "milli")
- (set (attr "length") (symbol_ref "pa_attr_length_millicode_call (insn)"))])
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_millicode_call (insn)")))])
(define_insn ""
[(set (reg:SI 29) (mult:SI (reg:SI 26) (reg:SI 25)))
"TARGET_64BIT"
"* return pa_output_mul_insn (0, insn);"
[(set_attr "type" "milli")
- (set (attr "length") (symbol_ref "pa_attr_length_millicode_call (insn)"))])
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_millicode_call (insn)")))])
(define_expand "muldi3"
[(set (match_operand:DI 0 "register_operand" "")
"*
return pa_output_div_insn (operands, 0, insn);"
[(set_attr "type" "milli")
- (set (attr "length") (symbol_ref "pa_attr_length_millicode_call (insn)"))])
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_millicode_call (insn)")))])
(define_insn ""
[(set (reg:SI 29)
"*
return pa_output_div_insn (operands, 0, insn);"
[(set_attr "type" "milli")
- (set (attr "length") (symbol_ref "pa_attr_length_millicode_call (insn)"))])
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_millicode_call (insn)")))])
(define_expand "udivsi3"
[(set (reg:SI 26) (match_operand:SI 1 "move_src_operand" ""))
"*
return pa_output_div_insn (operands, 1, insn);"
[(set_attr "type" "milli")
- (set (attr "length") (symbol_ref "pa_attr_length_millicode_call (insn)"))])
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_millicode_call (insn)")))])
(define_insn ""
[(set (reg:SI 29)
"*
return pa_output_div_insn (operands, 1, insn);"
[(set_attr "type" "milli")
- (set (attr "length") (symbol_ref "pa_attr_length_millicode_call (insn)"))])
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_millicode_call (insn)")))])
(define_expand "modsi3"
[(set (reg:SI 26) (match_operand:SI 1 "move_src_operand" ""))
"*
return pa_output_mod_insn (0, insn);"
[(set_attr "type" "milli")
- (set (attr "length") (symbol_ref "pa_attr_length_millicode_call (insn)"))])
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_millicode_call (insn)")))])
(define_insn ""
[(set (reg:SI 29) (mod:SI (reg:SI 26) (reg:SI 25)))
"*
return pa_output_mod_insn (0, insn);"
[(set_attr "type" "milli")
- (set (attr "length") (symbol_ref "pa_attr_length_millicode_call (insn)"))])
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_millicode_call (insn)")))])
(define_expand "umodsi3"
[(set (reg:SI 26) (match_operand:SI 1 "move_src_operand" ""))
"*
return pa_output_mod_insn (1, insn);"
[(set_attr "type" "milli")
- (set (attr "length") (symbol_ref "pa_attr_length_millicode_call (insn)"))])
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_millicode_call (insn)")))])
(define_insn ""
[(set (reg:SI 29) (umod:SI (reg:SI 26) (reg:SI 25)))
"*
return pa_output_mod_insn (1, insn);"
[(set_attr "type" "milli")
- (set (attr "length") (symbol_ref "pa_attr_length_millicode_call (insn)"))])
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_millicode_call (insn)")))])
;;- and instructions
;; We define DImode `and` so with DImode `not` we can get
[(set (match_operand:DI 0 "register_operand" "")
(and:DI (match_operand:DI 1 "register_operand" "")
(match_operand:DI 2 "and_operand" "")))]
- ""
- "
-{
- /* Both operands must be register operands. */
- if (!TARGET_64BIT && !register_operand (operands[2], DImode))
- FAIL;
-}")
-
-(define_insn ""
- [(set (match_operand:DI 0 "register_operand" "=r")
- (and:DI (match_operand:DI 1 "register_operand" "%r")
- (match_operand:DI 2 "register_operand" "r")))]
- "!TARGET_64BIT"
- "and %1,%2,%0\;and %R1,%R2,%R0"
- [(set_attr "type" "binary")
- (set_attr "length" "8")])
+ "TARGET_64BIT"
+ "")
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r,r")
[(set (match_operand:DI 0 "register_operand" "=r")
(and:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
(match_operand:DI 2 "register_operand" "r")))]
- "!TARGET_64BIT"
- "andcm %2,%1,%0\;andcm %R2,%R1,%R0"
+ "TARGET_64BIT"
+ "andcm %2,%1,%0"
[(set_attr "type" "binary")
- (set_attr "length" "8")])
-
-(define_insn ""
- [(set (match_operand:DI 0 "register_operand" "=r")
- (and:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
- (match_operand:DI 2 "register_operand" "r")))]
- "TARGET_64BIT"
- "andcm %2,%1,%0"
- [(set_attr "type" "binary")
- (set_attr "length" "4")])
+ (set_attr "length" "4")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
[(set (match_operand:DI 0 "register_operand" "")
(ior:DI (match_operand:DI 1 "register_operand" "")
(match_operand:DI 2 "reg_or_cint_ior_operand" "")))]
- ""
- "
-{
- /* Both operands must be register operands. */
- if (!TARGET_64BIT && !register_operand (operands[2], DImode))
- FAIL;
-}")
-
-(define_insn ""
- [(set (match_operand:DI 0 "register_operand" "=r")
- (ior:DI (match_operand:DI 1 "register_operand" "%r")
- (match_operand:DI 2 "register_operand" "r")))]
- "!TARGET_64BIT"
- "or %1,%2,%0\;or %R1,%R2,%R0"
- [(set_attr "type" "binary")
- (set_attr "length" "8")])
+ "TARGET_64BIT"
+ "")
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r,r")
[(set (match_operand:DI 0 "register_operand" "")
(xor:DI (match_operand:DI 1 "register_operand" "")
(match_operand:DI 2 "register_operand" "")))]
- ""
- "
-{
-}")
-
-(define_insn ""
- [(set (match_operand:DI 0 "register_operand" "=r")
- (xor:DI (match_operand:DI 1 "register_operand" "%r")
- (match_operand:DI 2 "register_operand" "r")))]
- "!TARGET_64BIT"
- "xor %1,%2,%0\;xor %R1,%R2,%R0"
- [(set_attr "type" "binary")
- (set_attr "length" "8")])
+ "TARGET_64BIT"
+ "")
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
[(set_attr "type" "load")
(set_attr "length" "4")])
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (ashift:SI (match_operand:SI 2 "register_operand" "r")
+ (match_operand:SI 3 "shadd_operand" ""))
+ (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "{sh%o3addl %2,%1,%0|shladd,l %2,%o3,%1,%0} "
+ [(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 "shadd_operand" ""))
+ (match_operand:SI 3 "mem_shadd_operand" ""))
(match_operand:SI 1 "register_operand" "r")))]
""
- "{sh%O3addl %2,%1,%0|shladd,l %2,%O3,%1,%0} "
+ "*
+{
+ 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")
+ (match_operand:DI 3 "shadd_operand" ""))
+ (match_operand:DI 1 "register_operand" "r")))]
+ "TARGET_64BIT"
+ "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 (mult:DI (match_operand:DI 2 "register_operand" "r")
- (match_operand:DI 3 "shadd_operand" ""))
+ (match_operand:DI 3 "mem_shadd_operand" ""))
(match_operand:DI 1 "register_operand" "r")))]
"TARGET_64BIT"
- "shladd,l %2,%O3,%1,%0"
+ "*
+{
+ 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")])
""
"*
{
- int x = INTVAL (operands[1]);
+ unsigned HOST_WIDE_INT x = UINTVAL (operands[1]);
operands[2] = GEN_INT (4 + exact_log2 ((x >> 4) + 1));
operands[1] = GEN_INT ((x & 0xf) - 0x10);
return \"{zvdepi %1,%2,%0|depwi,z %1,%%sar,%2,%0}\";
"exact_log2 (INTVAL (operands[1]) + 1) > 0"
"*
{
- int x = INTVAL (operands[1]);
+ HOST_WIDE_INT x = INTVAL (operands[1]);
operands[2] = GEN_INT (exact_log2 (x + 1));
return \"{vdepi -1,%2,%0|depwi -1,%%sar,%2,%0}\";
}"
"INTVAL (operands[1]) == -2"
"*
{
- int x = INTVAL (operands[1]);
+ HOST_WIDE_INT x = INTVAL (operands[1]);
operands[2] = GEN_INT (exact_log2 ((~x) + 1));
return \"{vdepi 0,%2,%0|depwi 0,%%sar,%2,%0}\";
}"
"TARGET_64BIT"
"*
{
- int x = INTVAL (operands[1]);
+ unsigned HOST_WIDE_INT x = UINTVAL (operands[1]);
operands[2] = GEN_INT (4 + exact_log2 ((x >> 4) + 1));
operands[1] = GEN_INT ((x & 0x1f) - 0x20);
return \"depdi,z %1,%%sar,%2,%0\";
"TARGET_64BIT && exact_log2 (INTVAL (operands[1]) + 1) > 0"
"*
{
- int x = INTVAL (operands[1]);
+ HOST_WIDE_INT x = INTVAL (operands[1]);
operands[2] = GEN_INT (exact_log2 (x + 1));
return \"depdi -1,%%sar,%2,%0\";
}"
"TARGET_64BIT && INTVAL (operands[1]) == -2"
"*
{
- int x = INTVAL (operands[1]);
+ HOST_WIDE_INT x = INTVAL (operands[1]);
operands[2] = GEN_INT (exact_log2 ((~x) + 1));
return \"depdi 0,%%sar,%2,%0\";
}"
(define_insn "lshrsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
- (match_operand:SI 2 "arith32_operand" "q,n")))]
+ (match_operand:SI 2 "shift5_operand" "q,n")))]
""
"@
{vshd %%r0,%1,%0|shrpw %%r0,%1,%%sar,%0}
(define_insn "lshrdi3"
[(set (match_operand:DI 0 "register_operand" "=r,r")
(lshiftrt:DI (match_operand:DI 1 "register_operand" "r,r")
- (match_operand:DI 2 "arith32_operand" "q,n")))]
+ (match_operand:DI 2 "shift6_operand" "q,n")))]
"TARGET_64BIT"
"@
shrpd %%r0,%1,%%sar,%0
[(set_attr "type" "shift")
(set_attr "length" "4")])
+; Shift right pair word 0 to 31 bits.
+(define_insn "shrpsi4"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r,r")
+ (minus:SI (const_int 32)
+ (match_operand:SI 3 "shift5_operand" "q,n")))
+ (lshiftrt:SI (match_operand:SI 2 "register_operand" "r,r")
+ (match_dup 3))))]
+ ""
+ "@
+ {vshd %1,%2,%0|shrpw %1,%2,%%sar,%0}
+ {shd|shrpw} %1,%2,%3,%0"
+ [(set_attr "type" "shift")
+ (set_attr "length" "4")])
+
+; Shift right pair doubleword 0 to 63 bits.
+(define_insn "shrpdi4"
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (ior:DI (ashift:DI (match_operand:SI 1 "register_operand" "r,r")
+ (minus:DI (const_int 64)
+ (match_operand:DI 3 "shift6_operand" "q,n")))
+ (lshiftrt:DI (match_operand:DI 2 "register_operand" "r,r")
+ (match_dup 3))))]
+ "TARGET_64BIT"
+ "@
+ shrpd %1,%2,%%sar,%0
+ shrpd %1,%2,%3,%0"
+ [(set_attr "type" "shift")
+ (set_attr "length" "4")])
+
(define_insn "rotrsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(rotatert:SI (match_operand:SI 1 "register_operand" "r,r")
- (match_operand:SI 2 "arith32_operand" "q,n")))]
+ (match_operand:SI 2 "shift5_operand" "q,n")))]
""
"*
{
[(set_attr "type" "uncond_branch")
(set_attr "pa_combine_type" "uncond_branch")
(set (attr "length")
- (cond [(match_test "pa_jump_in_call_delay (insn)")
- (if_then_else (lt (abs (minus (match_dup 0)
- (plus (pc) (const_int 8))))
- (const_int MAX_12BIT_OFFSET))
- (const_int 4)
- (const_int 8))
- (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
+ (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
(const_int MAX_17BIT_OFFSET))
(const_int 4)
(match_test "TARGET_PORTABLE_RUNTIME")
;;; Hope this is only within a function...
(define_insn "indirect_jump"
- [(set (pc) (match_operand 0 "register_operand" "r"))]
- "GET_MODE (operands[0]) == word_mode"
+ [(set (pc) (match_operand 0 "pmode_register_operand" "r"))]
+ ""
"bv%* %%r0(%0)"
[(set_attr "type" "branch")
(set_attr "length" "4")])
rtx stack = operands[2];
rtx fp = operands[3];
- lab = copy_to_reg (lab);
-
emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
- /* Restore the frame pointer. The virtual_stack_vars_rtx is saved
- instead of the hard_frame_pointer_rtx in the save area. As a
- result, an extra instruction is needed to adjust for the offset
- of the virtual stack variables and the hard frame pointer. */
- if (GET_CODE (fp) != REG)
- fp = force_reg (Pmode, fp);
- emit_move_insn (hard_frame_pointer_rtx, plus_constant (fp, -8));
+ lab = copy_to_reg (lab);
+ /* Restore the stack and frame pointers. */
+ fp = copy_to_reg (fp);
emit_stack_restore (SAVE_NONLOCAL, stack);
+ /* Ensure the frame pointer move is not optimized. */
+ emit_insn (gen_blockage ());
+ emit_clobber (hard_frame_pointer_rtx);
+ emit_clobber (frame_pointer_rtx);
+ emit_move_insn (hard_frame_pointer_rtx, fp);
+
emit_use (hard_frame_pointer_rtx);
emit_use (stack_pointer_rtx);
[(set_attr "type" "branch")
(set_attr "length" "4")])
-;;; This jump is used in branch tables where the insn length is fixed.
-;;; The length of this insn is adjusted if the delay slot is not filled.
-(define_insn "short_jump"
- [(set (pc) (label_ref (match_operand 0 "" "")))
- (const_int 0)]
- ""
- "b%* %l0%#"
- [(set_attr "type" "btable_branch")
- (set_attr "length" "4")])
-
;; Subroutines of "casesi".
;; operand 0 is index
;; operand 1 is the minimum bound
operands[0] = index;
}
- if (TARGET_BIG_SWITCH)
- {
- if (TARGET_64BIT)
- emit_jump_insn (gen_casesi64p (operands[0], operands[3]));
- else if (flag_pic)
- emit_jump_insn (gen_casesi32p (operands[0], operands[3]));
- else
- emit_jump_insn (gen_casesi32 (operands[0], operands[3]));
- }
+ if (TARGET_64BIT)
+ emit_jump_insn (gen_casesi64p (operands[0], operands[3]));
+ else if (flag_pic)
+ emit_jump_insn (gen_casesi32p (operands[0], operands[3]));
else
- emit_jump_insn (gen_casesi0 (operands[0], operands[3]));
+ emit_jump_insn (gen_casesi32 (operands[0], operands[3]));
DONE;
}")
-;;; The rtl for this pattern doesn't accurately describe what the insn
-;;; actually does, particularly when case-vector elements are exploded
-;;; in pa_reorg. However, the initial SET in these patterns must show
-;;; the connection of the insn to the following jump table.
-(define_insn "casesi0"
- [(set (pc) (mem:SI (plus:SI
- (mult:SI (match_operand:SI 0 "register_operand" "r")
- (const_int 4))
- (label_ref (match_operand 1 "" "")))))]
- ""
- "blr,n %0,%%r0\;nop"
- [(set_attr "type" "multi")
- (set_attr "length" "8")])
-
;;; 32-bit code, absolute branch table.
(define_insn "casesi32"
[(set (pc) (mem:SI (plus:SI
if (TARGET_PORTABLE_RUNTIME)
op = force_reg (SImode, XEXP (operands[0], 0));
else
- op = XEXP (operands[0], 0);
+ {
+ op = XEXP (operands[0], 0);
+
+ /* Generate indirect long calls to non-local functions. */
+ 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)))
+ op = force_reg (word_mode, op);
+ }
+ }
if (TARGET_64BIT)
{
return pa_output_call (insn, operands[0], 0);
}"
[(set_attr "type" "call")
- (set (attr "length") (symbol_ref "pa_attr_length_call (insn, 0)"))])
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_call (insn, 0)")))])
(define_insn "call_symref_pic"
- [(set (match_operand:SI 2 "register_operand" "=&r") (reg:SI 19))
- (call (mem:SI (match_operand 0 "call_operand_address" ""))
+ [(call (mem:SI (match_operand 0 "call_operand_address" ""))
(match_operand 1 "" "i"))
(clobber (reg:SI 1))
(clobber (reg:SI 2))
- (use (match_dup 2))
+ (clobber (match_operand 2))
(use (reg:SI 19))
(use (const_int 0))]
"!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
;; terminate the basic block. The split has to contain more than one
;; insn.
(define_split
- [(parallel [(set (match_operand:SI 2 "register_operand" "") (reg:SI 19))
- (call (mem:SI (match_operand 0 "call_operand_address" ""))
+ [(parallel [(call (mem:SI (match_operand 0 "call_operand_address" ""))
(match_operand 1 "" ""))
(clobber (reg:SI 1))
(clobber (reg:SI 2))
- (use (match_dup 2))
+ (clobber (match_operand 2))
(use (reg:SI 19))
(use (const_int 0))])]
"!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && reload_completed
"")
(define_split
- [(parallel [(set (match_operand:SI 2 "register_operand" "") (reg:SI 19))
- (call (mem:SI (match_operand 0 "call_operand_address" ""))
+ [(parallel [(call (mem:SI (match_operand 0 "call_operand_address" ""))
(match_operand 1 "" ""))
(clobber (reg:SI 1))
(clobber (reg:SI 2))
- (use (match_dup 2))
+ (clobber (match_operand 2))
(use (reg:SI 19))
(use (const_int 0))])]
"!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && reload_completed"
return pa_output_call (insn, operands[0], 0);
}"
[(set_attr "type" "call")
- (set (attr "length") (symbol_ref "pa_attr_length_call (insn, 0)"))])
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_call (insn, 0)")))])
;; This pattern is split if it is necessary to save and restore the
;; PIC register.
(define_insn "call_symref_64bit"
- [(set (match_operand:DI 2 "register_operand" "=&r") (reg:DI 27))
- (call (mem:SI (match_operand 0 "call_operand_address" ""))
+ [(call (mem:SI (match_operand 0 "call_operand_address" ""))
(match_operand 1 "" "i"))
(clobber (reg:DI 1))
(clobber (reg:DI 2))
- (use (match_dup 2))
+ (clobber (match_operand 2))
(use (reg:DI 27))
(use (reg:DI 29))
(use (const_int 0))]
;; terminate the basic block. The split has to contain more than one
;; insn.
(define_split
- [(parallel [(set (match_operand:DI 2 "register_operand" "") (reg:DI 27))
- (call (mem:SI (match_operand 0 "call_operand_address" ""))
+ [(parallel [(call (mem:SI (match_operand 0 "call_operand_address" ""))
(match_operand 1 "" ""))
(clobber (reg:DI 1))
(clobber (reg:DI 2))
- (use (match_dup 2))
+ (clobber (match_operand 2))
(use (reg:DI 27))
(use (reg:DI 29))
(use (const_int 0))])]
"")
(define_split
- [(parallel [(set (match_operand:DI 2 "register_operand" "") (reg:DI 27))
- (call (mem:SI (match_operand 0 "call_operand_address" ""))
+ [(parallel [(call (mem:SI (match_operand 0 "call_operand_address" ""))
(match_operand 1 "" ""))
(clobber (reg:DI 1))
(clobber (reg:DI 2))
- (use (match_dup 2))
+ (clobber (match_operand 2))
(use (reg:DI 27))
(use (reg:DI 29))
(use (const_int 0))])]
"TARGET_64BIT"
"*
{
- pa_output_arg_descriptor (insn);
return pa_output_call (insn, operands[0], 0);
}"
[(set_attr "type" "call")
- (set (attr "length") (symbol_ref "pa_attr_length_call (insn, 0)"))])
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_call (insn, 0)")))])
(define_insn "call_reg"
[(call (mem:SI (reg:SI 22))
return pa_output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
}"
[(set_attr "type" "dyncall")
- (set (attr "length") (symbol_ref "pa_attr_length_indirect_call (insn)"))])
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_indirect_call (insn)")))])
;; This pattern is split if it is necessary to save and restore the
;; PIC register.
(define_insn "call_reg_pic"
- [(set (match_operand:SI 1 "register_operand" "=&r") (reg:SI 19))
- (call (mem:SI (reg:SI 22))
+ [(call (mem:SI (reg:SI 22))
(match_operand 0 "" "i"))
(clobber (reg:SI 1))
(clobber (reg:SI 2))
- (use (match_dup 1))
+ (clobber (match_operand 1))
(use (reg:SI 19))
(use (const_int 1))]
"!TARGET_64BIT"
;; terminate the basic block. The split has to contain more than one
;; insn.
(define_split
- [(parallel [(set (match_operand:SI 1 "register_operand" "") (reg:SI 19))
- (call (mem:SI (reg:SI 22))
+ [(parallel [(call (mem:SI (reg:SI 22))
(match_operand 0 "" ""))
(clobber (reg:SI 1))
(clobber (reg:SI 2))
- (use (match_dup 1))
+ (clobber (match_operand 1))
(use (reg:SI 19))
(use (const_int 1))])]
"!TARGET_64BIT && reload_completed
"")
(define_split
- [(parallel [(set (match_operand:SI 1 "register_operand" "") (reg:SI 19))
- (call (mem:SI (reg:SI 22))
+ [(parallel [(call (mem:SI (reg:SI 22))
(match_operand 0 "" ""))
(clobber (reg:SI 1))
(clobber (reg:SI 2))
- (use (match_dup 1))
+ (clobber (match_operand 1))
(use (reg:SI 19))
(use (const_int 1))])]
"!TARGET_64BIT && reload_completed"
return pa_output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
}"
[(set_attr "type" "dyncall")
- (set (attr "length") (symbol_ref "pa_attr_length_indirect_call (insn)"))])
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_indirect_call (insn)")))])
;; This pattern is split if it is necessary to save and restore the
;; PIC register.
(define_insn "call_reg_64bit"
- [(set (match_operand:DI 2 "register_operand" "=&r") (reg:DI 27))
- (call (mem:SI (match_operand:DI 0 "register_operand" "r"))
+ [(call (mem:SI (match_operand:DI 0 "register_operand" "r"))
(match_operand 1 "" "i"))
- (clobber (reg:DI 1))
(clobber (reg:DI 2))
- (use (match_dup 2))
+ (clobber (match_operand 2))
(use (reg:DI 27))
(use (reg:DI 29))
(use (const_int 1))]
;; terminate the basic block. The split has to contain more than one
;; insn.
(define_split
- [(parallel [(set (match_operand:DI 2 "register_operand" "") (reg:DI 27))
- (call (mem:SI (match_operand 0 "register_operand" ""))
+ [(parallel [(call (mem:SI (match_operand 0 "register_operand" ""))
(match_operand 1 "" ""))
- (clobber (reg:DI 1))
(clobber (reg:DI 2))
- (use (match_dup 2))
+ (clobber (match_operand 2))
(use (reg:DI 27))
(use (reg:DI 29))
(use (const_int 1))])]
[(set (match_dup 2) (reg:DI 27))
(parallel [(call (mem:SI (match_dup 0))
(match_dup 1))
- (clobber (reg:DI 1))
(clobber (reg:DI 2))
(use (reg:DI 27))
(use (reg:DI 29))
"")
(define_split
- [(parallel [(set (match_operand:DI 2 "register_operand" "") (reg:DI 27))
- (call (mem:SI (match_operand 0 "register_operand" ""))
+ [(parallel [(call (mem:SI (match_operand 0 "register_operand" ""))
(match_operand 1 "" ""))
- (clobber (reg:DI 1))
(clobber (reg:DI 2))
- (use (match_dup 2))
+ (clobber (match_operand 2))
(use (reg:DI 27))
(use (reg:DI 29))
(use (const_int 1))])]
[(set (match_dup 2) (reg:DI 27))
(parallel [(call (mem:SI (match_dup 0))
(match_dup 1))
- (clobber (reg:DI 1))
(clobber (reg:DI 2))
(use (reg:DI 27))
(use (reg:DI 29))
(define_insn "*call_reg_64bit_post_reload"
[(call (mem:SI (match_operand:DI 0 "register_operand" "r"))
(match_operand 1 "" "i"))
- (clobber (reg:DI 1))
(clobber (reg:DI 2))
(use (reg:DI 27))
(use (reg:DI 29))
return pa_output_indirect_call (insn, operands[0]);
}"
[(set_attr "type" "dyncall")
- (set (attr "length") (symbol_ref "pa_attr_length_indirect_call (insn)"))])
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 12)]
+ (symbol_ref "pa_attr_length_indirect_call (insn)")))])
(define_expand "call_value"
[(parallel [(set (match_operand 0 "" "")
(match_operand 2 "" "")))
(clobber (reg:SI 2))])]
""
- "
{
rtx op;
rtx dst = operands[0];
rtx nb = operands[2];
+ bool call_powf = false;
if (TARGET_PORTABLE_RUNTIME)
op = force_reg (SImode, XEXP (operands[1], 0));
else
- op = XEXP (operands[1], 0);
+ {
+ op = XEXP (operands[1], 0);
+ if (GET_CODE (op) == SYMBOL_REF)
+ {
+ /* Handle special call to buggy powf function. */
+ if (TARGET_HPUX && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT
+ && !strcmp (targetm.strip_name_encoding (XSTR (op, 0)), "powf"))
+ call_powf = true;
+
+ /* Generate indirect long calls to non-local functions. */
+ else if (TARGET_LONG_CALLS)
+ {
+ tree call_decl = SYMBOL_REF_DECL (op);
+ if (!(call_decl && targetm.binds_local_p (call_decl)))
+ op = force_reg (word_mode, op);
+ }
+ }
+ }
if (TARGET_64BIT)
{
{
rtx r4 = gen_rtx_REG (word_mode, 4);
if (GET_CODE (op) == SYMBOL_REF)
- emit_call_insn (gen_call_val_symref_64bit (dst, op, nb, r4));
+ {
+ if (call_powf)
+ emit_call_insn (gen_call_val_powf_64bit (dst, op, nb, r4));
+ else
+ emit_call_insn (gen_call_val_symref_64bit (dst, op, nb, r4));
+ }
else
{
op = force_reg (word_mode, op);
if (flag_pic)
{
rtx r4 = gen_rtx_REG (word_mode, 4);
- emit_call_insn (gen_call_val_symref_pic (dst, op, nb, r4));
+
+ if (call_powf)
+ emit_call_insn (gen_call_val_powf_pic (dst, op, nb, r4));
+ else
+ emit_call_insn (gen_call_val_symref_pic (dst, op, nb, r4));
}
else
- emit_call_insn (gen_call_val_symref (dst, op, nb));
+ {
+ if (call_powf)
+ emit_call_insn (gen_call_val_powf (dst, op, nb));
+ else
+ emit_call_insn (gen_call_val_symref (dst, op, nb));
+ }
}
else
{
}
DONE;
-}")
+})
(define_insn "call_val_symref"
[(set (match_operand 0 "" "")
return pa_output_call (insn, operands[1], 0);
}"
[(set_attr "type" "call")
- (set (attr "length") (symbol_ref "pa_attr_length_call (insn, 0)"))])
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_call (insn, 0)")))])
+
+;; powf function clobbers %fr12
+(define_insn "call_val_powf"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand 1 "call_operand_address" ""))
+ (match_operand 2 "" "i")))
+ (clobber (reg:SI 1))
+ (clobber (reg:SI 2))
+ (clobber (reg:DF 48))
+ (use (const_int 1))]
+ "TARGET_HPUX && !TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
+ "*
+{
+ pa_output_arg_descriptor (insn);
+ return pa_output_call (insn, operands[1], 0);
+}"
+ [(set_attr "type" "call")
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_call (insn, 0)")))])
(define_insn "call_val_symref_pic"
- [(set (match_operand:SI 3 "register_operand" "=&r") (reg:SI 19))
- (set (match_operand 0 "" "")
+ [(set (match_operand 0 "" "")
(call (mem:SI (match_operand 1 "call_operand_address" ""))
(match_operand 2 "" "i")))
(clobber (reg:SI 1))
(clobber (reg:SI 2))
- (use (match_dup 3))
+ (clobber (match_operand 3))
(use (reg:SI 19))
(use (const_int 0))]
"!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
;; terminate the basic block. The split has to contain more than one
;; insn.
(define_split
- [(parallel [(set (match_operand:SI 3 "register_operand" "") (reg:SI 19))
- (set (match_operand 0 "" "")
+ [(parallel [(set (match_operand 0 "" "")
(call (mem:SI (match_operand 1 "call_operand_address" ""))
(match_operand 2 "" "")))
(clobber (reg:SI 1))
(clobber (reg:SI 2))
- (use (match_dup 3))
+ (clobber (match_operand 3))
(use (reg:SI 19))
(use (const_int 0))])]
"!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && reload_completed
"")
(define_split
- [(parallel [(set (match_operand:SI 3 "register_operand" "") (reg:SI 19))
- (set (match_operand 0 "" "")
+ [(parallel [(set (match_operand 0 "" "")
(call (mem:SI (match_operand 1 "call_operand_address" ""))
(match_operand 2 "" "")))
(clobber (reg:SI 1))
(clobber (reg:SI 2))
- (use (match_dup 3))
+ (clobber (match_operand 3))
(use (reg:SI 19))
(use (const_int 0))])]
"!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && reload_completed"
return pa_output_call (insn, operands[1], 0);
}"
[(set_attr "type" "call")
- (set (attr "length") (symbol_ref "pa_attr_length_call (insn, 0)"))])
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_call (insn, 0)")))])
+
+;; powf function clobbers %fr12
+(define_insn "call_val_powf_pic"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand 1 "call_operand_address" ""))
+ (match_operand 2 "" "i")))
+ (clobber (reg:SI 1))
+ (clobber (reg:SI 2))
+ (clobber (reg:DF 48))
+ (clobber (match_operand 3))
+ (use (reg:SI 19))
+ (use (const_int 1))]
+ "TARGET_HPUX && !TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
+ "#")
+
+;; Split out the PIC register save and restore after reload. As the
+;; split is done after reload, there are some situations in which we
+;; unnecessarily save and restore %r4. This happens when there is a
+;; single call and the PIC register is not used after the call.
+;;
+;; The split has to be done since call_from_call_insn () can't handle
+;; the pattern as is. Noreturn calls are special because they have to
+;; terminate the basic block. The split has to contain more than one
+;; insn.
+(define_split
+ [(parallel [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand 1 "call_operand_address" ""))
+ (match_operand 2 "" "")))
+ (clobber (reg:SI 1))
+ (clobber (reg:SI 2))
+ (clobber (reg:DF 48))
+ (clobber (match_operand 3))
+ (use (reg:SI 19))
+ (use (const_int 1))])]
+ "TARGET_HPUX && !TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && reload_completed
+ && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
+ [(set (match_dup 3) (reg:SI 19))
+ (parallel [(set (match_dup 0)
+ (call (mem:SI (match_dup 1))
+ (match_dup 2)))
+ (clobber (reg:SI 1))
+ (clobber (reg:SI 2))
+ (clobber (reg:DF 48))
+ (use (reg:SI 19))
+ (use (const_int 1))])]
+ "")
+
+(define_split
+ [(parallel [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand 1 "call_operand_address" ""))
+ (match_operand 2 "" "")))
+ (clobber (reg:SI 1))
+ (clobber (reg:SI 2))
+ (clobber (reg:DF 48))
+ (clobber (match_operand 3))
+ (use (reg:SI 19))
+ (use (const_int 1))])]
+ "TARGET_HPUX && !TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && reload_completed"
+ [(set (match_dup 3) (reg:SI 19))
+ (parallel [(set (match_dup 0)
+ (call (mem:SI (match_dup 1))
+ (match_dup 2)))
+ (clobber (reg:SI 1))
+ (clobber (reg:SI 2))
+ (clobber (reg:DF 48))
+ (use (reg:SI 19))
+ (use (const_int 1))])
+ (set (reg:SI 19) (match_dup 3))]
+ "")
+
+(define_insn "*call_val_powf_pic_post_reload"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand 1 "call_operand_address" ""))
+ (match_operand 2 "" "i")))
+ (clobber (reg:SI 1))
+ (clobber (reg:SI 2))
+ (clobber (reg:DF 48))
+ (use (reg:SI 19))
+ (use (const_int 1))]
+ "TARGET_HPUX && !TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
+ "*
+{
+ pa_output_arg_descriptor (insn);
+ return pa_output_call (insn, operands[1], 0);
+}"
+ [(set_attr "type" "call")
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_call (insn, 0)")))])
;; This pattern is split if it is necessary to save and restore the
;; PIC register.
(define_insn "call_val_symref_64bit"
- [(set (match_operand:DI 3 "register_operand" "=&r") (reg:DI 27))
- (set (match_operand 0 "" "")
+ [(set (match_operand 0 "" "")
(call (mem:SI (match_operand 1 "call_operand_address" ""))
(match_operand 2 "" "i")))
(clobber (reg:DI 1))
(clobber (reg:DI 2))
- (use (match_dup 3))
+ (clobber (match_operand 3))
(use (reg:DI 27))
(use (reg:DI 29))
(use (const_int 0))]
;; terminate the basic block. The split has to contain more than one
;; insn.
(define_split
- [(parallel [(set (match_operand:DI 3 "register_operand" "") (reg:DI 27))
- (set (match_operand 0 "" "")
+ [(parallel [(set (match_operand 0 "" "")
(call (mem:SI (match_operand 1 "call_operand_address" ""))
(match_operand 2 "" "")))
(clobber (reg:DI 1))
(clobber (reg:DI 2))
- (use (match_dup 3))
+ (clobber (match_operand 3))
(use (reg:DI 27))
(use (reg:DI 29))
(use (const_int 0))])]
"")
(define_split
- [(parallel [(set (match_operand:DI 3 "register_operand" "") (reg:DI 27))
- (set (match_operand 0 "" "")
+ [(parallel [(set (match_operand 0 "" "")
(call (mem:SI (match_operand 1 "call_operand_address" ""))
(match_operand 2 "" "")))
(clobber (reg:DI 1))
(clobber (reg:DI 2))
- (use (match_dup 3))
+ (clobber (match_operand 3))
(use (reg:DI 27))
(use (reg:DI 29))
(use (const_int 0))])]
"TARGET_64BIT"
"*
{
- pa_output_arg_descriptor (insn);
return pa_output_call (insn, operands[1], 0);
}"
[(set_attr "type" "call")
- (set (attr "length") (symbol_ref "pa_attr_length_call (insn, 0)"))])
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_call (insn, 0)")))])
-(define_insn "call_val_reg"
+;; powf function clobbers %fr12
+(define_insn "call_val_powf_64bit"
[(set (match_operand 0 "" "")
- (call (mem:SI (reg:SI 22))
- (match_operand 1 "" "i")))
- (clobber (reg:SI 1))
- (clobber (reg:SI 2))
- (use (const_int 1))]
- "!TARGET_64BIT"
- "*
-{
- return pa_output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
-}"
- [(set_attr "type" "dyncall")
- (set (attr "length") (symbol_ref "pa_attr_length_indirect_call (insn)"))])
-
-;; This pattern is split if it is necessary to save and restore the
-;; PIC register.
-(define_insn "call_val_reg_pic"
- [(set (match_operand:SI 2 "register_operand" "=&r") (reg:SI 19))
- (set (match_operand 0 "" "")
- (call (mem:SI (reg:SI 22))
- (match_operand 1 "" "i")))
- (clobber (reg:SI 1))
- (clobber (reg:SI 2))
- (use (match_dup 2))
- (use (reg:SI 19))
+ (call (mem:SI (match_operand 1 "call_operand_address" ""))
+ (match_operand 2 "" "i")))
+ (clobber (reg:DI 1))
+ (clobber (reg:DI 2))
+ (clobber (reg:DF 40))
+ (clobber (match_operand 3))
+ (use (reg:DI 27))
+ (use (reg:DI 29))
(use (const_int 1))]
- "!TARGET_64BIT"
+ "TARGET_64BIT && TARGET_HPUX"
"#")
;; Split out the PIC register save and restore after reload. As the
;; terminate the basic block. The split has to contain more than one
;; insn.
(define_split
- [(parallel [(set (match_operand:SI 2 "register_operand" "") (reg:SI 19))
- (set (match_operand 0 "" "")
+ [(parallel [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand 1 "call_operand_address" ""))
+ (match_operand 2 "" "")))
+ (clobber (reg:DI 1))
+ (clobber (reg:DI 2))
+ (clobber (reg:DF 40))
+ (clobber (match_operand 3))
+ (use (reg:DI 27))
+ (use (reg:DI 29))
+ (use (const_int 1))])]
+ "TARGET_64BIT && TARGET_HPUX && reload_completed
+ && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
+ [(set (match_dup 3) (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))
+ (clobber (reg:DF 40))
+ (use (reg:DI 27))
+ (use (reg:DI 29))
+ (use (const_int 1))])]
+ "")
+
+(define_split
+ [(parallel [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand 1 "call_operand_address" ""))
+ (match_operand 2 "" "")))
+ (clobber (reg:DI 1))
+ (clobber (reg:DI 2))
+ (clobber (reg:DF 40))
+ (clobber (match_operand 3))
+ (use (reg:DI 27))
+ (use (reg:DI 29))
+ (use (const_int 1))])]
+ "TARGET_64BIT && TARGET_HPUX && reload_completed"
+ [(set (match_dup 3) (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))
+ (clobber (reg:DF 40))
+ (use (reg:DI 27))
+ (use (reg:DI 29))
+ (use (const_int 1))])
+ (set (reg:DI 27) (match_dup 3))]
+ "")
+
+(define_insn "*call_val_powf_64bit_post_reload"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand 1 "call_operand_address" ""))
+ (match_operand 2 "" "i")))
+ (clobber (reg:DI 1))
+ (clobber (reg:DI 2))
+ (clobber (reg:DF 40))
+ (use (reg:DI 27))
+ (use (reg:DI 29))
+ (use (const_int 1))]
+ "TARGET_64BIT && TARGET_HPUX"
+ "*
+{
+ return pa_output_call (insn, operands[1], 0);
+}"
+ [(set_attr "type" "call")
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_call (insn, 0)")))])
+
+(define_insn "call_val_reg"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (reg:SI 22))
+ (match_operand 1 "" "i")))
+ (clobber (reg:SI 1))
+ (clobber (reg:SI 2))
+ (use (const_int 1))]
+ "!TARGET_64BIT"
+ "*
+{
+ return pa_output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
+}"
+ [(set_attr "type" "dyncall")
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_indirect_call (insn)")))])
+
+;; This pattern is split if it is necessary to save and restore the
+;; PIC register.
+(define_insn "call_val_reg_pic"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (reg:SI 22))
+ (match_operand 1 "" "i")))
+ (clobber (reg:SI 1))
+ (clobber (reg:SI 2))
+ (clobber (match_operand 2))
+ (use (reg:SI 19))
+ (use (const_int 1))]
+ "!TARGET_64BIT"
+ "#")
+
+;; Split out the PIC register save and restore after reload. As the
+;; split is done after reload, there are some situations in which we
+;; unnecessarily save and restore %r4. This happens when there is a
+;; single call and the PIC register is not used after the call.
+;;
+;; The split has to be done since call_from_call_insn () can't handle
+;; the pattern as is. Noreturn calls are special because they have to
+;; terminate the basic block. The split has to contain more than one
+;; insn.
+(define_split
+ [(parallel [(set (match_operand 0 "" "")
(call (mem:SI (reg:SI 22))
(match_operand 1 "" "")))
(clobber (reg:SI 1))
(clobber (reg:SI 2))
- (use (match_dup 2))
+ (clobber (match_operand 2))
(use (reg:SI 19))
(use (const_int 1))])]
"!TARGET_64BIT && reload_completed
"")
(define_split
- [(parallel [(set (match_operand:SI 2 "register_operand" "") (reg:SI 19))
- (set (match_operand 0 "" "")
+ [(parallel [(set (match_operand 0 "" "")
(call (mem:SI (reg:SI 22))
(match_operand 1 "" "")))
(clobber (reg:SI 1))
(clobber (reg:SI 2))
- (use (match_dup 2))
+ (clobber (match_operand 2))
(use (reg:SI 19))
(use (const_int 1))])]
"!TARGET_64BIT && reload_completed"
return pa_output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
}"
[(set_attr "type" "dyncall")
- (set (attr "length") (symbol_ref "pa_attr_length_indirect_call (insn)"))])
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_indirect_call (insn)")))])
;; This pattern is split if it is necessary to save and restore the
;; PIC register.
(define_insn "call_val_reg_64bit"
- [(set (match_operand:DI 3 "register_operand" "=&r") (reg:DI 27))
- (set (match_operand 0 "" "")
+ [(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 (match_dup 3))
+ (clobber (match_operand 3))
(use (reg:DI 27))
(use (reg:DI 29))
(use (const_int 1))]
;; terminate the basic block. The split has to contain more than one
;; insn.
(define_split
- [(parallel [(set (match_operand:DI 3 "register_operand" "") (reg:DI 27))
- (set (match_operand 0 "" "")
+ [(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))
- (use (match_dup 3))
+ (clobber (match_operand 3))
(use (reg:DI 27))
(use (reg:DI 29))
(use (const_int 1))])]
(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))
"")
(define_split
- [(parallel [(set (match_operand:DI 3 "register_operand" "") (reg:DI 27))
- (set (match_operand 0 "" "")
+ [(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))
- (use (match_dup 3))
+ (clobber (match_operand 3))
(use (reg:DI 27))
(use (reg:DI 29))
(use (const_int 1))])]
(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))
return pa_output_indirect_call (insn, operands[1]);
}"
[(set_attr "type" "dyncall")
- (set (attr "length") (symbol_ref "pa_attr_length_indirect_call (insn)"))])
+ (set (attr "length")
+ (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.
{
int i;
- emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
+ emit_call_insn (gen_call (operands[0], const0_rtx));
for (i = 0; i < XVECLEN (operands[2], 0); i++)
{
pa_output_arg_descriptor (insn);
return pa_output_call (insn, operands[0], 1);
}"
- [(set_attr "type" "call")
- (set (attr "length") (symbol_ref "pa_attr_length_call (insn, 1)"))])
+ [(set_attr "type" "sibcall")
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_call (insn, 1)")))])
(define_insn "sibcall_internal_symref_64bit"
[(call (mem:SI (match_operand 0 "call_operand_address" ""))
"TARGET_64BIT"
"*
{
- pa_output_arg_descriptor (insn);
return pa_output_call (insn, operands[0], 1);
}"
- [(set_attr "type" "call")
- (set (attr "length") (symbol_ref "pa_attr_length_call (insn, 1)"))])
+ [(set_attr "type" "sibcall")
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_call (insn, 1)")))])
(define_expand "sibcall_value"
[(set (match_operand 0 "" "")
pa_output_arg_descriptor (insn);
return pa_output_call (insn, operands[1], 1);
}"
- [(set_attr "type" "call")
- (set (attr "length") (symbol_ref "pa_attr_length_call (insn, 1)"))])
+ [(set_attr "type" "sibcall")
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_call (insn, 1)")))])
(define_insn "sibcall_value_internal_symref_64bit"
[(set (match_operand 0 "" "")
"TARGET_64BIT"
"*
{
- pa_output_arg_descriptor (insn);
return pa_output_call (insn, operands[1], 1);
}"
- [(set_attr "type" "call")
- (set (attr "length") (symbol_ref "pa_attr_length_call (insn, 1)"))])
+ [(set_attr "type" "sibcall")
+ (set (attr "length")
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+ (symbol_ref "pa_attr_length_call (insn, 1)")))])
(define_insn "nop"
[(const_int 0)]
[(set_attr "type" "move")
(set_attr "length" "4")])
-;; These are just placeholders so we know where branch tables
-;; begin and end.
-(define_insn "begin_brtab"
- [(const_int 1)]
- ""
- "*
-{
- /* Only GAS actually supports this pseudo-op. */
- if (TARGET_GAS)
- return \".begin_brtab\";
- else
- return \"\";
-}"
- [(set_attr "type" "move")
- (set_attr "length" "0")])
-
-(define_insn "end_brtab"
- [(const_int 2)]
- ""
- "*
-{
- /* Only GAS actually supports this pseudo-op. */
- if (TARGET_GAS)
- return \".end_brtab\";
- else
- return \"\";
-}"
- [(set_attr "type" "move")
- (set_attr "length" "0")])
-
;;; EH does longjmp's from and within the data section. Thus,
;;; an interspace branch is required for the longjmp implementation.
;;; Registers r1 and r2 are used as scratch registers for the jump
{
/* The elements of the buffer are, in order: */
rtx fp = gen_rtx_MEM (Pmode, operands[0]);
- rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0],
+ rtx lab = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0],
POINTER_SIZE / BITS_PER_UNIT));
- rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0],
+ rtx stack = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0],
(POINTER_SIZE * 2) / BITS_PER_UNIT));
rtx pv = gen_rtx_REG (Pmode, 1);
emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
- /* Restore the frame pointer. The virtual_stack_vars_rtx is saved
- instead of the hard_frame_pointer_rtx in the save area. We need
- to adjust for the offset between these two values. */
- if (GET_CODE (fp) != REG)
- fp = force_reg (Pmode, fp);
- emit_move_insn (hard_frame_pointer_rtx, plus_constant (fp, -8));
-
- /* This bit is the same as expand_builtin_longjmp. */
- emit_stack_restore (SAVE_NONLOCAL, stack);
- emit_use (hard_frame_pointer_rtx);
- emit_use (stack_pointer_rtx);
-
/* Load the label we are jumping through into r1 so that we know
where to look for it when we get back to setjmp's function for
restoring the gp. */
emit_move_insn (pv, lab);
+ /* Restore the stack and frame pointers. */
+ fp = copy_to_reg (fp);
+ emit_stack_restore (SAVE_NONLOCAL, stack);
+
+ /* Ensure the frame pointer move is not optimized. */
+ emit_insn (gen_blockage ());
+ emit_clobber (hard_frame_pointer_rtx);
+ emit_clobber (frame_pointer_rtx);
+ emit_move_insn (hard_frame_pointer_rtx, fp);
+
+ emit_use (hard_frame_pointer_rtx);
+ emit_use (stack_pointer_rtx);
+
/* Prevent the insns above from being scheduled into the delay slot
of the interspace jump because the space register could change. */
emit_insn (gen_blockage ());
}")
;;; Operands 2 and 3 are assumed to be CONST_INTs.
-(define_expand "extzv"
- [(set (match_operand 0 "register_operand" "")
- (zero_extract (match_operand 1 "register_operand" "")
- (match_operand 2 "uint32_operand" "")
- (match_operand 3 "uint32_operand" "")))]
+(define_expand "extzvsi"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "uint5_operand" "")
+ (match_operand:SI 3 "uint5_operand" "")))]
""
"
{
- HOST_WIDE_INT len = INTVAL (operands[2]);
- HOST_WIDE_INT pos = INTVAL (operands[3]);
+ unsigned HOST_WIDE_INT len = UINTVAL (operands[2]);
+ unsigned HOST_WIDE_INT pos = UINTVAL (operands[3]);
/* PA extraction insns don't support zero length bitfields or fields
- extending beyond the left or right-most bits. Also, we reject lengths
- equal to a word as they are better handled by the move patterns. */
- if (len <= 0 || len >= BITS_PER_WORD || pos < 0 || pos + len > BITS_PER_WORD)
+ extending beyond the left or right-most bits. Also, the predicate
+ rejects lengths equal to a word as they are better handled by
+ the move patterns. */
+ if (len == 0 || pos + len > 32)
FAIL;
/* From mips.md: extract_bit_field doesn't verify that our source
if (!register_operand (operands[1], VOIDmode))
FAIL;
- if (TARGET_64BIT)
- emit_insn (gen_extzv_64 (operands[0], operands[1],
- operands[2], operands[3]));
- else
- emit_insn (gen_extzv_32 (operands[0], operands[1],
- operands[2], operands[3]));
+ emit_insn (gen_extzv_32 (operands[0], operands[1],
+ operands[2], operands[3]));
DONE;
}")
(zero_extract:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "uint5_operand" "")
(match_operand:SI 3 "uint5_operand" "")))]
- ""
+ "UINTVAL (operands[2]) > 0
+ && UINTVAL (operands[2]) + UINTVAL (operands[3]) <= 32"
"{extru|extrw,u} %1,%3+%2-1,%2,%0"
[(set_attr "type" "shift")
(set_attr "length" "4")])
[(set_attr "type" "shift")
(set_attr "length" "4")])
+(define_expand "extzvdi"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (zero_extract:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "uint6_operand" "")
+ (match_operand:DI 3 "uint6_operand" "")))]
+ "TARGET_64BIT"
+ "
+{
+ unsigned HOST_WIDE_INT len = UINTVAL (operands[2]);
+ unsigned HOST_WIDE_INT pos = UINTVAL (operands[3]);
+
+ /* PA extraction insns don't support zero length bitfields or fields
+ extending beyond the left or right-most bits. Also, the predicate
+ rejects lengths equal to a doubleword as they are better handled by
+ the move patterns. */
+ if (len == 0 || pos + len > 64)
+ FAIL;
+
+ /* From mips.md: extract_bit_field doesn't verify that our source
+ matches the predicate, so check it again here. */
+ if (!register_operand (operands[1], VOIDmode))
+ FAIL;
+
+ emit_insn (gen_extzv_64 (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+}")
+
(define_insn "extzv_64"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extract:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:DI 2 "uint32_operand" "")
- (match_operand:DI 3 "uint32_operand" "")))]
- "TARGET_64BIT"
+ (match_operand:DI 2 "uint6_operand" "")
+ (match_operand:DI 3 "uint6_operand" "")))]
+ "TARGET_64BIT
+ && UINTVAL (operands[2]) > 0
+ && UINTVAL (operands[2]) + UINTVAL (operands[3]) <= 64"
"extrd,u %1,%3+%2-1,%2,%0"
[(set_attr "type" "shift")
(set_attr "length" "4")])
(set_attr "length" "4")])
;;; Operands 2 and 3 are assumed to be CONST_INTs.
-(define_expand "extv"
- [(set (match_operand 0 "register_operand" "")
- (sign_extract (match_operand 1 "register_operand" "")
- (match_operand 2 "uint32_operand" "")
- (match_operand 3 "uint32_operand" "")))]
+(define_expand "extvsi"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (sign_extract:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "uint5_operand" "")
+ (match_operand:SI 3 "uint5_operand" "")))]
""
"
{
- HOST_WIDE_INT len = INTVAL (operands[2]);
- HOST_WIDE_INT pos = INTVAL (operands[3]);
+ unsigned HOST_WIDE_INT len = UINTVAL (operands[2]);
+ unsigned HOST_WIDE_INT pos = UINTVAL (operands[3]);
/* PA extraction insns don't support zero length bitfields or fields
- extending beyond the left or right-most bits. Also, we reject lengths
- equal to a word as they are better handled by the move patterns. */
- if (len <= 0 || len >= BITS_PER_WORD || pos < 0 || pos + len > BITS_PER_WORD)
+ extending beyond the left or right-most bits. Also, the predicate
+ rejects lengths equal to a word as they are better handled by
+ the move patterns. */
+ if (len == 0 || pos + len > 32)
FAIL;
/* From mips.md: extract_bit_field doesn't verify that our source
if (!register_operand (operands[1], VOIDmode))
FAIL;
- if (TARGET_64BIT)
- emit_insn (gen_extv_64 (operands[0], operands[1],
- operands[2], operands[3]));
- else
- emit_insn (gen_extv_32 (operands[0], operands[1],
- operands[2], operands[3]));
+ emit_insn (gen_extv_32 (operands[0], operands[1],
+ operands[2], operands[3]));
DONE;
}")
(sign_extract:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "uint5_operand" "")
(match_operand:SI 3 "uint5_operand" "")))]
- ""
+ "UINTVAL (operands[2]) > 0
+ && UINTVAL (operands[2]) + UINTVAL (operands[3]) <= 32"
"{extrs|extrw,s} %1,%3+%2-1,%2,%0"
[(set_attr "type" "shift")
(set_attr "length" "4")])
[(set_attr "type" "shift")
(set_attr "length" "4")])
+(define_expand "extvdi"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (sign_extract:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "uint6_operand" "")
+ (match_operand:DI 3 "uint6_operand" "")))]
+ "TARGET_64BIT"
+ "
+{
+ unsigned HOST_WIDE_INT len = UINTVAL (operands[2]);
+ unsigned HOST_WIDE_INT pos = UINTVAL (operands[3]);
+
+ /* PA extraction insns don't support zero length bitfields or fields
+ extending beyond the left or right-most bits. Also, the predicate
+ rejects lengths equal to a doubleword as they are better handled by
+ the move patterns. */
+ if (len == 0 || pos + len > 64)
+ FAIL;
+
+ /* From mips.md: extract_bit_field doesn't verify that our source
+ matches the predicate, so check it again here. */
+ if (!register_operand (operands[1], VOIDmode))
+ FAIL;
+
+ emit_insn (gen_extv_64 (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+}")
+
(define_insn "extv_64"
[(set (match_operand:DI 0 "register_operand" "=r")
(sign_extract:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:DI 2 "uint32_operand" "")
- (match_operand:DI 3 "uint32_operand" "")))]
- "TARGET_64BIT"
+ (match_operand:DI 2 "uint6_operand" "")
+ (match_operand:DI 3 "uint6_operand" "")))]
+ "TARGET_64BIT
+ && UINTVAL (operands[2]) > 0
+ && UINTVAL (operands[2]) + UINTVAL (operands[3]) <= 64"
"extrd,s %1,%3+%2-1,%2,%0"
[(set_attr "type" "shift")
(set_attr "length" "4")])
(set_attr "length" "4")])
;;; Operands 1 and 2 are assumed to be CONST_INTs.
-(define_expand "insv"
- [(set (zero_extract (match_operand 0 "register_operand" "")
- (match_operand 1 "uint32_operand" "")
- (match_operand 2 "uint32_operand" ""))
- (match_operand 3 "arith5_operand" ""))]
+(define_expand "insvsi"
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "uint5_operand" "")
+ (match_operand:SI 2 "uint5_operand" ""))
+ (match_operand:SI 3 "arith5_operand" ""))]
""
"
{
- HOST_WIDE_INT len = INTVAL (operands[1]);
- HOST_WIDE_INT pos = INTVAL (operands[2]);
+ unsigned HOST_WIDE_INT len = UINTVAL (operands[1]);
+ unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
/* PA insertion insns don't support zero length bitfields or fields
- extending beyond the left or right-most bits. Also, we reject lengths
- equal to a word as they are better handled by the move patterns. */
- if (len <= 0 || len >= BITS_PER_WORD || pos < 0 || pos + len > BITS_PER_WORD)
+ extending beyond the left or right-most bits. Also, the predicate
+ rejects lengths equal to a word as they are better handled by
+ the move patterns. */
+ if (len <= 0 || pos + len > 32)
FAIL;
/* From mips.md: insert_bit_field doesn't verify that our destination
if (!register_operand (operands[0], VOIDmode))
FAIL;
- if (TARGET_64BIT)
- emit_insn (gen_insv_64 (operands[0], operands[1],
- operands[2], operands[3]));
- else
- emit_insn (gen_insv_32 (operands[0], operands[1],
- operands[2], operands[3]));
+ emit_insn (gen_insv_32 (operands[0], operands[1],
+ operands[2], operands[3]));
DONE;
}")
(match_operand:SI 1 "uint5_operand" "")
(match_operand:SI 2 "uint5_operand" ""))
(match_operand:SI 3 "arith5_operand" "r,L"))]
- ""
+ "UINTVAL (operands[1]) > 0
+ && UINTVAL (operands[1]) + UINTVAL (operands[2]) <= 32"
"@
{dep|depw} %3,%2+%1-1,%1,%0
{depi|depwi} %3,%2+%1-1,%1,%0"
[(set_attr "type" "shift")
(set_attr "length" "4")])
+(define_expand "insvdi"
+ [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "uint6_operand" "")
+ (match_operand:DI 2 "uint6_operand" ""))
+ (match_operand:DI 3 "arith5_operand" ""))]
+ "TARGET_64BIT"
+ "
+{
+ unsigned HOST_WIDE_INT len = UINTVAL (operands[1]);
+ unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
+
+ /* PA insertion insns don't support zero length bitfields or fields
+ extending beyond the left or right-most bits. Also, the predicate
+ rejects lengths equal to a doubleword as they are better handled by
+ the move patterns. */
+ if (len <= 0 || pos + len > 64)
+ FAIL;
+
+ /* From mips.md: insert_bit_field doesn't verify that our destination
+ matches the predicate, so check it again here. */
+ if (!register_operand (operands[0], VOIDmode))
+ FAIL;
+
+ emit_insn (gen_insv_64 (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+}")
+
(define_insn "insv_64"
[(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r,r")
- (match_operand:DI 1 "uint32_operand" "")
- (match_operand:DI 2 "uint32_operand" ""))
- (match_operand:DI 3 "arith32_operand" "r,L"))]
- "TARGET_64BIT"
+ (match_operand:DI 1 "uint6_operand" "")
+ (match_operand:DI 2 "uint6_operand" ""))
+ (match_operand:DI 3 "arith5_operand" "r,L"))]
+ "TARGET_64BIT
+ && UINTVAL (operands[1]) > 0
+ && UINTVAL (operands[1]) + UINTVAL (operands[2]) <= 64"
"@
depd %3,%2+%1-1,%1,%0
depdi %3,%2+%1-1,%1,%0"
;; Optimize insertion of const_int values of type 1...1xxxx.
(define_insn ""
[(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
- (match_operand:DI 1 "uint32_operand" "")
- (match_operand:DI 2 "uint32_operand" ""))
+ (match_operand:DI 1 "uint6_operand" "")
+ (match_operand:DI 2 "uint6_operand" ""))
(match_operand:DI 3 "const_int_operand" ""))]
"(INTVAL (operands[3]) & 0x10) != 0
&& TARGET_64BIT
;; strength reduction is used. It is actually created when the instruction
;; combination phase combines the special loop test. Since this insn
;; is both a jump insn and has an output, it must deal with its own
-;; reloads, hence the `m' constraints. The `!' constraints direct reload
+;; reloads, hence the `Q' constraints. The `!' constraints direct reload
;; to not choose the register alternatives in the event a reload is needed.
(define_insn "decrement_and_branch_until_zero"
[(set (pc)
(if_then_else
(match_operator 2 "comparison_operator"
[(plus:SI
- (match_operand:SI 0 "reg_before_reload_operand" "+!r,!*f,*m")
+ (match_operand:SI 0 "reg_before_reload_operand" "+!r,!*f,*Q")
(match_operand:SI 1 "int5_operand" "L,L,L"))
(const_int 0)])
(label_ref (match_operand 3 "" ""))
[(match_operand:SI 1 "register_operand" "r,r,r,r") (const_int 0)])
(label_ref (match_operand 3 "" ""))
(pc)))
- (set (match_operand:SI 0 "reg_before_reload_operand" "=!r,!*f,*m,!*q")
+ (set (match_operand:SI 0 "reg_before_reload_operand" "=!r,!*f,*Q,!*q")
(match_dup 1))]
""
"* return pa_output_movb (operands, insn, which_alternative, 0); "
[(match_operand:SI 1 "register_operand" "r,r,r,r") (const_int 0)])
(pc)
(label_ref (match_operand 3 "" ""))))
- (set (match_operand:SI 0 "reg_before_reload_operand" "=!r,!*f,*m,!*q")
+ (set (match_operand:SI 0 "reg_before_reload_operand" "=!r,!*f,*Q,!*q")
(match_dup 1))]
""
"* return pa_output_movb (operands, insn, which_alternative, 1); "
emit_library_call_value (canonicalize_funcptr_for_compare_libfunc,
operands[0], LCT_NORMAL, Pmode,
- 1, operands[1], Pmode);
+ operands[1], Pmode);
DONE;
}
gen_rtx_SYMBOL_REF (SImode,
\"$$sh_func_adrs\"));
}"
- [(set_attr "type" "multi")
+ [(set_attr "type" "sh_func_adrs")
(set (attr "length")
- (plus (symbol_ref "pa_attr_length_millicode_call (insn)")
- (const_int 20)))])
+ (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 28)]
+ (plus (symbol_ref "pa_attr_length_millicode_call (insn)")
+ (const_int 20))))])
;; On the PA, the PIC register is call clobbered, so it must
;; be saved & restored around calls by the caller. If the call
"addil LR'%1-$tls_leoff$,%2\;ldo RR'%1-$tls_leoff$(%%r1),%0"
[(set_attr "type" "multi")
(set_attr "length" "8")])
+
+;; Atomic instructions
+
+;; All memory loads and stores access storage atomically except
+;; for one exception. The STORE BYTES, STORE DOUBLE BYTES, and
+;; doubleword loads and stores are not guaranteed to be atomic
+;; when referencing the I/O address space.
+
+;; These patterns are at the bottom so the non atomic versions are preferred.
+
+(define_expand "atomic_storeqi"
+ [(match_operand:QI 0 "memory_operand") ;; memory
+ (match_operand:QI 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 HImode stores using exchange.
+
+(define_expand "atomic_storehi"
+ [(match_operand:HI 0 "memory_operand") ;; memory
+ (match_operand:HI 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 SImode store using exchange.
+
+(define_expand "atomic_storesi"
+ [(match_operand:SI 0 "memory_operand") ;; memory
+ (match_operand:SI 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.
+
+(define_expand "atomic_loaddi"
+ [(match_operand:DI 0 "register_operand") ;; val out
+ (match_operand:DI 1 "memory_operand") ;; memory
+ (match_operand:SI 2 "const_int_operand")] ;; model
+ ""
+{
+ 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));
+ 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" "=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),%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 "reg_or_cint_move_operand") ;; val out
+ (match_operand:SI 2 "const_int_operand")] ;; model
+ ""
+{
+ 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));
+ 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))
+ expand_mem_thread_fence (model);
+ DONE;
+})
+
+(define_insn "atomic_storedi_1"
+ [(set (mem:DI (match_operand:SI 0 "register_operand" "r,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"
+ "@
+ {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")])
+
+;; PA 2.0 hardware supports out-of-order execution of loads and stores, so
+;; we need memory barriers to enforce program order for memory references
+;; when the TLB and PSW O bits are not set. We assume all PA 2.0 systems
+;; are weakly ordered since neither HP-UX or Linux set the PSW O bit. Since
+;; we want PA 1.x code to be PA 2.0 compatible, we also need barriers when
+;; generating PA 1.x code even though all PA 1.x systems are strongly ordered.
+
+;; When barriers are needed, we use a strongly ordered ldcw instruction as
+;; the barrier. Most PA 2.0 targets are cache coherent. In that case, we
+;; can use the coherent cache control hint and avoid aligning the ldcw
+;; address. In spite of its description, it is not clear that the sync
+;; instruction works as a barrier.
+
+(define_expand "memory_barrier"
+ [(parallel
+ [(set (match_dup 0) (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))
+ (clobber (match_dup 1))])]
+ ""
+{
+ /* We don't need a barrier if the target uses ordered memory references. */
+ if (TARGET_ORDERED)
+ FAIL;
+ operands[1] = gen_reg_rtx (Pmode);
+ operands[0] = gen_rtx_MEM (BLKmode, operands[1]);
+ MEM_VOLATILE_P (operands[0]) = 1;
+})
+
+(define_insn "*memory_barrier_coherent"
+ [(set (match_operand:BLK 0 "" "")
+ (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))
+ (clobber (match_operand 1 "pmode_register_operand" "=r"))]
+ "TARGET_PA_20 && TARGET_COHERENT_LDCW"
+ "ldcw,co 0(%%sp),%1"
+ [(set_attr "type" "binary")
+ (set_attr "length" "4")])
+
+(define_insn "*memory_barrier_64"
+ [(set (match_operand:BLK 0 "" "")
+ (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))
+ (clobber (match_operand 1 "pmode_register_operand" "=&r"))]
+ "TARGET_64BIT"
+ "ldo 15(%%sp),%1\n\tdepd %%r0,63,3,%1\n\tldcw 0(%1),%1"
+ [(set_attr "type" "binary")
+ (set_attr "length" "12")])
+
+(define_insn "*memory_barrier_32"
+ [(set (match_operand:BLK 0 "" "")
+ (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))
+ (clobber (match_operand 1 "pmode_register_operand" "=&r"))]
+ ""
+ "ldo 15(%%sp),%1\n\t{dep|depw} %%r0,31,3,%1\n\tldcw 0(%1),%1"
+ [(set_attr "type" "binary")
+ (set_attr "length" "12")])