(UNSPEC_NSAU 1)
(UNSPEC_NOP 2)
(UNSPEC_PLT 3)
+ (UNSPEC_RET_ADDR 4)
(UNSPECV_SET_FP 1)
])
""
"
{
+ rtx srclo;
rtx dstlo = gen_lowpart (SImode, operands[0]);
rtx src1lo = gen_lowpart (SImode, operands[1]);
rtx src2lo = gen_lowpart (SImode, operands[2]);
rtx src1hi = gen_highpart (SImode, operands[1]);
rtx src2hi = gen_highpart (SImode, operands[2]);
+ /* Either source can be used for overflow checking, as long as it's
+ not clobbered by the first addition. */
+ if (!rtx_equal_p (dstlo, src1lo))
+ srclo = src1lo;
+ else if (!rtx_equal_p (dstlo, src2lo))
+ srclo = src2lo;
+ else
+ {
+ srclo = gen_reg_rtx (SImode);
+ emit_move_insn (srclo, src1lo);
+ }
+
emit_insn (gen_addsi3 (dstlo, src1lo, src2lo));
emit_insn (gen_addsi3 (dsthi, src1hi, src2hi));
- emit_insn (gen_adddi_carry (dsthi, dstlo, src2lo));
+ emit_insn (gen_adddi_carry (dsthi, dstlo, srclo));
DONE;
}")
(set_attr "mode" "SI")
(set_attr "length" "2,2,3,3,3")])
-(define_insn ""
+(define_insn "*addx2"
[(set (match_operand:SI 0 "register_operand" "=a")
(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
(const_int 2))
(set_attr "mode" "SI")
(set_attr "length" "3")])
-(define_insn ""
+(define_insn "*addx4"
[(set (match_operand:SI 0 "register_operand" "=a")
(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
(const_int 4))
(set_attr "mode" "SI")
(set_attr "length" "3")])
-(define_insn ""
+(define_insn "*addx8"
[(set (match_operand:SI 0 "register_operand" "=a")
(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
(const_int 8))
rtx src1hi = gen_highpart (SImode, operands[1]);
rtx src2hi = gen_highpart (SImode, operands[2]);
- emit_insn (gen_subsi3 (dstlo, src1lo, src2lo));
emit_insn (gen_subsi3 (dsthi, src1hi, src2hi));
emit_insn (gen_subdi_carry (dsthi, src1lo, src2lo));
+ emit_insn (gen_subsi3 (dstlo, src1lo, src2lo));
DONE;
}")
(set_attr "mode" "SI")
(set_attr "length" "3")])
-(define_insn ""
+(define_insn "*subx2"
[(set (match_operand:SI 0 "register_operand" "=a")
(minus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
(const_int 2))
(set_attr "mode" "SI")
(set_attr "length" "3")])
-(define_insn ""
+(define_insn "*subx4"
[(set (match_operand:SI 0 "register_operand" "=a")
(minus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
(const_int 4))
(set_attr "mode" "SI")
(set_attr "length" "3")])
-(define_insn ""
+(define_insn "*subx8"
[(set (match_operand:SI 0 "register_operand" "=a")
(minus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
(const_int 8))
(set_attr "mode" "SF")
(set_attr "length" "3")])
-(define_insn ""
+(define_insn "*recipsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
(div:SF (match_operand:SF 1 "const_float_1_operand" "")
(match_operand:SF 2 "register_operand" "f")))]
(set_attr "mode" "SF")
(set_attr "length" "3")])
-(define_insn ""
+(define_insn "*rsqrtsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
(div:SF (match_operand:SF 1 "const_float_1_operand" "")
(sqrt:SF (match_operand:SF 2 "register_operand" "f"))))]
&& !register_operand (operands[1], DImode))
operands[1] = force_reg (DImode, operands[1]);
- if (a7_overlap_mentioned_p (operands[1]))
- {
- emit_insn (gen_movdi_internal (operands[0], operands[1]));
- emit_insn (gen_set_frame_ptr ());
- DONE;
- }
+ if (xtensa_copy_incoming_a7 (operands, DImode))
+ DONE;
}
}")
(define_insn "movsi_internal"
[(set (match_operand:SI 0 "nonimmed_operand" "=D,D,D,D,R,R,a,q,a,a,a,U,*a,*A")
(match_operand:SI 1 "move_operand" "M,D,d,R,D,d,r,r,I,T,U,r,*A,*r"))]
- "non_acc_reg_operand (operands[0], SImode)
- || non_acc_reg_operand (operands[1], SImode)"
+ "xtensa_valid_move (SImode, operands)"
"@
movi.n\\t%0, %x1
mov.n\\t%0, %1
(define_insn "movhi_internal"
[(set (match_operand:HI 0 "nonimmed_operand" "=D,D,a,a,a,U,*a,*A")
(match_operand:HI 1 "move_operand" "M,d,r,I,U,r,*A,*r"))]
- "non_acc_reg_operand (operands[0], HImode)
- || non_acc_reg_operand (operands[1], HImode)"
+ "xtensa_valid_move (HImode, operands)"
"@
movi.n\\t%0, %x1
mov.n\\t%0, %1
(define_insn "movqi_internal"
[(set (match_operand:QI 0 "nonimmed_operand" "=D,D,a,a,a,U,*a,*A")
(match_operand:QI 1 "move_operand" "M,d,r,I,U,r,*A,*r"))]
- "non_acc_reg_operand (operands[0], QImode)
- || non_acc_reg_operand (operands[1], QImode)"
+ "xtensa_valid_move (QImode, operands)"
"@
movi.n\\t%0, %x1
mov.n\\t%0, %1
&& constantpool_mem_p (operands[1]))))
operands[1] = force_reg (SFmode, operands[1]);
- if (a7_overlap_mentioned_p (operands[1]))
- {
- emit_insn (gen_movsf_internal (operands[0], operands[1]));
- emit_insn (gen_set_frame_ptr ());
- DONE;
- }
+ if (xtensa_copy_incoming_a7 (operands, SFmode))
+ DONE;
}
}")
(set_attr "mode" "SF")
(set_attr "length" "3,3,3,2,2,2,3,3,3,3,3,3")])
-(define_insn ""
- [(parallel
- [(set (match_operand:SF 0 "register_operand" "=f")
- (mem:SF (plus:SI (match_operand:SI 1 "register_operand" "+a")
- (match_operand:SI 2 "fpmem_offset_operand" "i"))))
- (set (match_dup 1)
- (plus:SI (match_dup 1) (match_dup 2)))])]
+(define_insn "*lsiu"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (mem:SF (plus:SI (match_operand:SI 1 "register_operand" "+a")
+ (match_operand:SI 2 "fpmem_offset_operand" "i"))))
+ (set (match_dup 1)
+ (plus:SI (match_dup 1) (match_dup 2)))]
"TARGET_HARD_FLOAT"
"*
{
(set_attr "mode" "SF")
(set_attr "length" "3")])
-(define_insn ""
- [(parallel
- [(set (mem:SF (plus:SI (match_operand:SI 0 "register_operand" "+a")
- (match_operand:SI 1 "fpmem_offset_operand" "i")))
- (match_operand:SF 2 "register_operand" "f"))
- (set (match_dup 0)
- (plus:SI (match_dup 0) (match_dup 1)))])]
+(define_insn "*ssiu"
+ [(set (mem:SF (plus:SI (match_operand:SI 0 "register_operand" "+a")
+ (match_operand:SI 1 "fpmem_offset_operand" "i")))
+ (match_operand:SF 2 "register_operand" "f"))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0) (match_dup 1)))]
"TARGET_HARD_FLOAT"
"*
{
&& !register_operand (operands[1], DFmode))
operands[1] = force_reg (DFmode, operands[1]);
- if (a7_overlap_mentioned_p (operands[1]))
- {
- emit_insn (gen_movdf_internal (operands[0], operands[1]));
- emit_insn (gen_set_frame_ptr ());
- DONE;
- }
+ if (xtensa_copy_incoming_a7 (operands, DFmode))
+ DONE;
}
}")
}")
(define_insn "movstrsi_internal"
- [(parallel [(set (match_operand:BLK 0 "memory_operand" "=U")
- (match_operand:BLK 1 "memory_operand" "U"))
- (use (match_operand:SI 2 "arith_operand" ""))
- (use (match_operand:SI 3 "const_int_operand" ""))
- (clobber (match_scratch:SI 4 "=&r"))
- (clobber (match_scratch:SI 5 "=&r"))])]
+ [(set (match_operand:BLK 0 "memory_operand" "=U")
+ (match_operand:BLK 1 "memory_operand" "U"))
+ (use (match_operand:SI 2 "arith_operand" ""))
+ (use (match_operand:SI 3 "const_int_operand" ""))
+ (clobber (match_scratch:SI 4 "=&r"))
+ (clobber (match_scratch:SI 5 "=&r"))]
""
"*
{
(set_attr "mode" "SI")
(set_attr "length" "6,6")])
+
;;
;; ....................
;;
;; Branch patterns for standard integer comparisons
-(define_insn ""
+(define_insn "*btrue"
[(set (pc)
(if_then_else (match_operator 3 "branch_operator"
[(match_operand:SI 0 "register_operand" "r,r")
(set_attr "mode" "none")
(set_attr "length" "3,3")])
-(define_insn ""
+(define_insn "*bfalse"
[(set (pc)
(if_then_else (match_operator 3 "branch_operator"
[(match_operand:SI 0 "register_operand" "r,r")
(set_attr "mode" "none")
(set_attr "length" "3,3")])
-(define_insn ""
+(define_insn "*ubtrue"
[(set (pc)
(if_then_else (match_operator 3 "ubranch_operator"
[(match_operand:SI 0 "register_operand" "r,r")
(set_attr "mode" "none")
(set_attr "length" "3,3")])
-(define_insn ""
+(define_insn "*ubfalse"
[(set (pc)
(if_then_else (match_operator 3 "ubranch_operator"
[(match_operand:SI 0 "register_operand" "r,r")
;; Branch patterns for bit testing
-(define_insn ""
+(define_insn "*bittrue"
[(set (pc)
(if_then_else (match_operator 3 "boolean_operator"
[(zero_extract:SI
(set_attr "mode" "none")
(set_attr "length" "3")])
-(define_insn ""
+(define_insn "*bitfalse"
[(set (pc)
(if_then_else (match_operator 3 "boolean_operator"
[(zero_extract:SI
(set_attr "mode" "none")
(set_attr "length" "3")])
-(define_insn ""
+(define_insn "*masktrue"
[(set (pc)
(if_then_else (match_operator 3 "boolean_operator"
[(and:SI (match_operand:SI 0 "register_operand" "r")
(set_attr "mode" "none")
(set_attr "length" "3")])
-(define_insn ""
+(define_insn "*maskfalse"
[(set (pc)
(if_then_else (match_operator 3 "boolean_operator"
[(and:SI (match_operand:SI 0 "register_operand" "r")
;; since since loop end is handled in hardware.
(define_insn "zero_cost_loop_start"
- [(parallel [(set (pc) (if_then_else (eq (match_operand:SI 0 "register_operand" "a")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))
- (set (reg:SI 19)
- (plus:SI (match_dup 0)
- (const_int -1)))])]
+ [(set (pc) (if_then_else (eq (match_operand:SI 0 "register_operand" "a")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (reg:SI 19)
+ (plus:SI (match_dup 0) (const_int -1)))]
""
"loopnez %0, %l1"
[(set_attr "type" "jump")
(set_attr "length" "3")])
(define_insn "zero_cost_loop_end"
- [(parallel [(set (pc) (if_then_else (ne (reg:SI 19)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))
- (set (reg:SI 19)
- (plus:SI (reg:SI 19)
- (const_int -1)))])]
+ [(set (pc) (if_then_else (ne (reg:SI 19) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))
+ (set (reg:SI 19)
+ (plus:SI (reg:SI 19) (const_int -1)))]
""
"*
xtensa_emit_loop_end (insn, operands);
;; to set up the frame pointer.
(define_insn "set_frame_ptr"
- [(unspec_volatile [(const_int 0)] UNSPECV_SET_FP)]
+ [(set (reg:SI A7_REG) (unspec_volatile [(const_int 0)] UNSPECV_SET_FP))]
""
"*
{
;; Post-reload splitter to remove fp assignment when it's not needed.
(define_split
- [(unspec_volatile [(const_int 0)] UNSPECV_SET_FP)]
+ [(set (reg:SI A7_REG) (unspec_volatile [(const_int 0)] UNSPECV_SET_FP))]
"reload_completed && !frame_pointer_needed"
[(unspec [(const_int 0)] UNSPEC_NOP)]
"")
;; The preceding splitter needs something to split the insn into;
;; things start breaking if the result is just a "use" so instead we
;; generate the following insn.
-(define_insn ""
+(define_insn "*unspec_nop"
[(unspec [(const_int 0)] UNSPEC_NOP)]
""
""
(set_attr "mode" "none")
(set_attr "length" "0")])
+;; The fix_return_addr pattern sets the high 2 bits of an address in a
+;; register to match the high bits of the current PC.
+
+(define_insn "fix_return_addr"
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")]
+ UNSPEC_RET_ADDR))
+ (clobber (match_scratch:SI 2 "=r"))
+ (clobber (match_scratch:SI 3 "=r"))]
+ ""
+ "mov\\t%2, a0\;call0\\t0f\;.align\\t4\;0:\;mov\\t%3, a0\;mov\\ta0, %2\;\
+srli\\t%3, %3, 30\;slli\\t%0, %1, 2\;ssai\\t2\;src\\t%0, %3, %0"
+ [(set_attr "type" "multi")
+ (set_attr "mode" "SI")
+ (set_attr "length" "24")])
+
+
;;
;; ....................
;;
;; branch patterns
-(define_insn ""
+(define_insn "*booltrue"
[(set (pc)
(if_then_else (match_operator 2 "boolean_operator"
[(match_operand:CC 0 "register_operand" "b")
(set_attr "mode" "none")
(set_attr "length" "3")])
-(define_insn ""
+(define_insn "*boolfalse"
[(set (pc)
(if_then_else (match_operator 2 "boolean_operator"
[(match_operand:CC 0 "register_operand" "b")