(define_constraint "R"
"@internal"
(and (match_code "const_int")
- (match_test "!h8300_shift_needs_scratch_p (ival, QImode)")))
+ (match_test "!h8300_shift_needs_scratch_p (ival, QImode, CLOBBER)")))
(define_constraint "C"
"@internal"
(define_constraint "S"
"@internal"
(and (match_code "const_int")
- (match_test "!h8300_shift_needs_scratch_p (ival, HImode)")))
+ (match_test "!h8300_shift_needs_scratch_p (ival, HImode, CLOBBER)")))
(define_constraint "T"
"@internal"
(and (match_code "const_int")
- (match_test "!h8300_shift_needs_scratch_p (ival, SImode)")))
+ (match_test "!h8300_shift_needs_scratch_p (ival, SImode, CLOBBER)")))
(define_constraint "U"
"An operand valid for a bset destination."
extern void h8300_expand_branch (rtx[]);
extern void h8300_expand_store (rtx[]);
extern bool expand_a_shift (machine_mode, enum rtx_code, rtx[]);
-extern int h8300_shift_needs_scratch_p (int, machine_mode);
+extern int h8300_shift_needs_scratch_p (int, machine_mode, rtx_code);
extern int expand_a_rotate (rtx[]);
extern int fix_bit_operand (rtx *, enum rtx_code);
extern int h8300_adjust_insn_length (rtx, int);
break;
}
- emit_move_insn (copy_rtx (operands[0]), operands[1]);
-
/* Need a loop to get all the bits we want - we generate the
code at emit time, but need to allocate a scratch reg now. */
-
- emit_insn (gen_rtx_PARALLEL
- (VOIDmode,
- gen_rtvec (2,
- gen_rtx_SET (copy_rtx (operands[0]),
- gen_rtx_fmt_ee (code, mode,
- copy_rtx (operands[0]), operands[2])),
- gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_SCRATCH (QImode)))));
+ emit_move_insn (copy_rtx (operands[0]), operands[1]);
+ if (operands[2] == CONST0_RTX (QImode))
+ ;
+ else if (GET_CODE (operands[2]) == CONST_INT
+ && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), mode, code))
+ emit_insn (gen_rtx_SET (copy_rtx (operands[0]),
+ gen_rtx_fmt_ee (code, mode,
+ copy_rtx (operands[1]), operands[2])));
+ else
+ emit_insn (gen_rtx_PARALLEL
+ (VOIDmode,
+ gen_rtvec (2,
+ gen_rtx_SET (copy_rtx (operands[0]),
+ gen_rtx_fmt_ee (code, mode,
+ copy_rtx (operands[0]), operands[2])),
+ gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_SCRATCH (QImode)))));
return true;
}
needed for some shift with COUNT and MODE. Return 0 otherwise. */
int
-h8300_shift_needs_scratch_p (int count, machine_mode mode)
+h8300_shift_needs_scratch_p (int count, machine_mode mode, enum rtx_code type)
{
enum h8_cpu cpu;
int a, lr, ar;
}
/* On H8/300H, count == 8 uses a scratch register. */
- return (a == SHIFT_LOOP || lr == SHIFT_LOOP || ar == SHIFT_LOOP
- || (TARGET_H8300H && mode == SImode && count == 8));
+ if (type == CLOBBER)
+ return (a == SHIFT_LOOP || lr == SHIFT_LOOP || ar == SHIFT_LOOP
+ || (TARGET_H8300H && mode == SImode && count == 8));
+ else if (type == ASHIFT)
+ return (a == SHIFT_LOOP
+ || (TARGET_H8300H && mode == SImode && count == 8));
+ else if (type == LSHIFTRT)
+ return (lr == SHIFT_LOOP
+ || (TARGET_H8300H && mode == SImode && count == 8));
+ else if (type == ASHIFTRT)
+ return (ar == SHIFT_LOOP
+ || (TARGET_H8300H && mode == SImode && count == 8));
}
/* Output the assembler code for doing shifts. */
(set (attr "cc")
(symbol_ref "compute_a_shift_cc (insn, operands)"))])
+(define_insn "*shiftqi_noscratch"
+ [(set (match_operand:QI 0 "register_operand" "=r,r")
+ (match_operator:QI 3 "nshift_operator"
+ [(match_operand:QI 1 "register_operand" "0,0")
+ (match_operand:QI 2 "nonmemory_operand" "R,rn")]))]
+ "(GET_CODE (operands[2]) == CONST_INT
+ && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode,
+ GET_CODE (operands[3])))"
+{
+ return output_a_shift (operands);
+}
+ [(set (attr "length")
+ (symbol_ref "compute_a_shift_length (insn, operands)"))
+ (set (attr "cc")
+ (symbol_ref "compute_a_shift_cc (insn, operands)"))])
+
(define_insn "*shifthi"
[(set (match_operand:HI 0 "register_operand" "=r,r")
(match_operator:HI 3 "nshift_operator"
(set (attr "cc")
(symbol_ref "compute_a_shift_cc (insn, operands)"))])
+(define_insn "*shifthi_noscratch"
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (match_operator:HI 3 "nshift_operator"
+ [(match_operand:HI 1 "register_operand" "0,0")
+ (match_operand:QI 2 "nonmemory_operand" "S,rn")]))]
+ "(GET_CODE (operands[2]) == CONST_INT
+ && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode,
+ GET_CODE (operands[3])))"
+{
+ return output_a_shift (operands);
+}
+ [(set (attr "length")
+ (symbol_ref "compute_a_shift_length (insn, operands)"))
+ (set (attr "cc")
+ (symbol_ref "compute_a_shift_cc (insn, operands)"))])
+
(define_insn "*shiftsi"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(match_operator:SI 3 "nshift_operator"
(set (attr "cc")
(symbol_ref "compute_a_shift_cc (insn, operands)"))])
+(define_insn "*shiftsi_noscratch"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (match_operator:SI 3 "nshift_operator"
+ [(match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:QI 2 "nonmemory_operand" "T,rn")]))]
+ "(GET_CODE (operands[2]) == CONST_INT
+ && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode,
+ GET_CODE (operands[3])))"
+{
+ return output_a_shift (operands);
+}
+ [(set (attr "length")
+ (symbol_ref "compute_a_shift_length (insn, operands)"))
+ (set (attr "cc")
+ (symbol_ref "compute_a_shift_cc (insn, operands)"))])
+
;; Split a variable shift into a loop. If the register containing
;; the shift count dies, then we just use that register.