insns and emitted. */
extern struct rtx_def *alpha_emit_set_const ();
extern struct rtx_def *alpha_emit_set_long_const ();
+extern struct rtx_def *alpha_emit_conditional_branch ();
extern struct rtx_def *alpha_emit_conditional_move ();
/* Generate necessary RTL for __builtin_saveregs().
' Generates trap-mode suffix for instructions that accept the
su suffix only (cmpt et al).
+ ` Generates trap-mode suffix for instructions that accept the
+ v and sv suffix. The only instruction that needs this is cvtql.
+
( Generates trap-mode suffix for instructions that accept the
v, sv, and svi suffix. The only instruction that needs this
is cvttq.
*/
#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
- ((CODE) == '&' || (CODE) == '\'' || (CODE) == '(' || (CODE) == ')' \
- || (CODE) == '+' || (CODE) == ',' || (CODE) == '-')
+ ((CODE) == '&' || (CODE) == '`' || (CODE) == '\'' || (CODE) == '(' \
+ || (CODE) == ')' || (CODE) == '+' || (CODE) == ',' || (CODE) == '-')
\f
/* Print a memory address as an operand to reference that memory location. */
/* Prototypes for alpha.c functions used in the md file. */
extern struct rtx_def *get_unaligned_address ();
-
;; 2 insxh
;; 3 mskxh
;; 4 cvtlq
+;; 5 cvtql
;;
;; UNSPEC_VOLATILE:
;;
[(set_attr "type" "fadd")
(set_attr "trap" "yes")])
+;; Define conversion operators between DFmode and SImode, using the cvtql
+;; instruction. To allow combine et al to do useful things, we keep the
+;; operation as a unit until after reload, at which point we split the
+;; instructions.
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (fix:SI (match_operand:DF 1 "reg_or_fp0_operand" "")))
+ (clobber (match_scratch:DI 2 ""))]
+ "TARGET_FP && reload_completed"
+ [(set (match_dup 2) (fix:DI (match_dup 1)))
+ (set (match_dup 0) (unspec:SI [(match_dup 2)] 5))]
+ "")
+
+;; Due to issues with CLASS_CANNOT_CHANGE_SIZE, we cannot use a subreg here.
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (fix:SI (match_operand:DF 1 "reg_or_fp0_operand" "")))]
+ "TARGET_FP && reload_completed"
+ [(set (match_dup 2) (fix:DI (match_dup 1)))
+ (set (match_dup 0) (unspec:SI [(match_dup 2)] 5))]
+ "operands[2] = gen_rtx_REG (DImode, REGNO (operands[0]));")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=f")
+ (unspec:SI [(match_operand:DI 1 "reg_or_fp0_operand" "fG")] 5))]
+ "TARGET_FP"
+ "cvtql%` %R1,%0"
+ [(set_attr "type" "fadd")
+ (set_attr "trap" "yes")])
+
+(define_insn "fix_truncdfsi2_tp"
+ [(set (match_operand:SI 0 "register_operand" "=&f")
+ (fix:SI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))
+ (clobber (match_scratch:DI 2 "=&f"))]
+ "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+ "#"
+ [(set_attr "type" "fadd")
+ (set_attr "trap" "yes")])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=f")
+ (fix:SI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
+ "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+ "#"
+ [(set_attr "type" "fadd")
+ (set_attr "trap" "yes")])
+
+(define_expand "fix_truncdfsi2"
+ [(set (match_operand:SI 0 "register_operand" "=f")
+ (fix:SI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
+ "TARGET_FP"
+ "{ if (alpha_tp == ALPHA_TP_INSN)
+ { emit_insn(gen_fix_truncdfsi2_tp(operands[0], operands[1])); DONE; }
+ }")
+
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=&f")
(fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
[(set_attr "type" "fadd")
(set_attr "trap" "yes")])
+;; Likewise between SFmode and SImode.
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (fix:SI (float_extend:DF
+ (match_operand:SF 1 "reg_or_fp0_operand" ""))))
+ (clobber (match_scratch:DI 2 ""))]
+ "TARGET_FP && reload_completed"
+ [(set (match_dup 2) (fix:DI (float_extend:DF (match_dup 1))))
+ (set (match_dup 0) (unspec:SI [(match_dup 2)] 5))]
+ "")
+
+;; Due to issues with CLASS_CANNOT_CHANGE_SIZE, we cannot use a subreg here.
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (fix:SI (float_extend:DF
+ (match_operand:SF 1 "reg_or_fp0_operand" ""))))]
+ "TARGET_FP && reload_completed"
+ [(set (match_dup 2) (fix:DI (float_extend:DF (match_dup 1))))
+ (set (match_dup 0) (unspec:SI [(match_dup 2)] 5))]
+ "operands[2] = gen_rtx_REG (DImode, REGNO (operands[0]));")
+
+(define_insn "fix_truncsfsi2_tp"
+ [(set (match_operand:SI 0 "register_operand" "=&f")
+ (fix:SI (float_extend:DF
+ (match_operand:SF 1 "reg_or_fp0_operand" "fG"))))
+ (clobber (match_scratch:DI 2 "=&f"))]
+ "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+ "#"
+ [(set_attr "type" "fadd")
+ (set_attr "trap" "yes")])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=f")
+ (fix:SI (float_extend:DF
+ (match_operand:SF 1 "reg_or_fp0_operand" "fG"))))]
+ "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+ "#"
+ [(set_attr "type" "fadd")
+ (set_attr "trap" "yes")])
+
+(define_expand "fix_truncsfsi2"
+ [(set (match_operand:SI 0 "register_operand" "=f")
+ (fix:SI (float_extend:DF
+ (match_operand:SF 1 "reg_or_fp0_operand" "fG"))))]
+ "TARGET_FP"
+ "{ if (alpha_tp == ALPHA_TP_INSN)
+ { emit_insn(gen_fix_truncsfsi2_tp(operands[0], operands[1])); DONE; }
+ }")
+
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=&f")
(fix:DI (float_extend:DF
""
"trapb"
[(set_attr "type" "misc")])
+\f
+;; Peepholes go at the end.
+
+;; Optimize sign-extension of SImode loads. This shows up in the wake of
+;; reload when converting fp->int.
+;;
+;; ??? What to do when we are actually caring about the packing and
+;; alignment of instructions? Perhaps reload can be enlightened, or
+;; the peephole pass moved up after reload but before sched2.
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "memory_operand" "m"))
+ (set (match_operand:DI 2 "register_operand" "=r")
+ (sign_extend:DI (match_dup 0)))]
+ "dead_or_set_p (insn, operands[0])"
+ "ldl %2,%1")
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "hard_fp_register_operand" "f"))
+ (set (match_operand:DI 2 "register_operand" "=r")
+ (sign_extend:DI (match_dup 0)))]
+ "TARGET_CIX && dead_or_set_p (insn, operands[0])"
+ "ftois %1,%2")