+2002-06-01 Kazu Hirata <kazu@cs.umass.edu>
+
+ * config/h8300/h8300-protos.h: Add a prototype for
+ h8300_shift_needs_scratch_p.
+ * config/h8300/h8300.c (h8300_shift_needs_scratch_p): New.
+ * config/h8300/h8300.h (OK_FOR_R): New.
+ (OK_FOR_S): Likewise.
+ (OK_FOR_T): Likewise.
+ (EXTRA_CONSTRAINT): Call OK_FOR_R, OK_FOR_S, and OK_FOR_T.
+ * config/h8300/h8300.md (anonymous shift patterns): Use
+ constraints R, S, and T.
+
Sat Jun 1 11:23:22 CEST 2002 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
* basic-block.h (struct basic_block_def): New field loop_father.
rtx *));
extern int compute_logical_op_cc PARAMS ((enum machine_mode, rtx *));
extern int expand_a_shift PARAMS ((enum machine_mode, int, rtx[]));
+extern int h8300_shift_needs_scratch_p PARAMS ((int, enum machine_mode));
extern int expand_a_rotate PARAMS ((enum rtx_code, rtx[]));
extern int fix_bit_operand PARAMS ((rtx *, int, enum rtx_code));
extern int h8300_adjust_insn_length PARAMS ((rtx, int));
info->shift2 = NULL;
}
+/* Given COUNT and MODE of a shift, return 1 if a scratch reg may be
+ needed for some shift with COUNT and MODE. Return 0 otherwise. */
+
+int
+h8300_shift_needs_scratch_p (count, mode)
+ int count;
+ enum machine_mode mode;
+{
+ int cpu;
+ int a, lr, ar;
+
+ if (GET_MODE_BITSIZE (mode) <= count)
+ return 1;
+
+ /* Find out the target CPU. */
+ if (TARGET_H8300)
+ cpu = 0;
+ else if (TARGET_H8300H)
+ cpu = 1;
+ else
+ cpu = 2;
+
+ /* Find the shift algorithm. */
+ switch (mode)
+ {
+ case QImode:
+ a = shift_alg_qi[cpu][SHIFT_ASHIFT][count];
+ lr = shift_alg_qi[cpu][SHIFT_LSHIFTRT][count];
+ ar = shift_alg_qi[cpu][SHIFT_ASHIFTRT][count];
+ break;
+
+ case HImode:
+ a = shift_alg_hi[cpu][SHIFT_ASHIFT][count];
+ lr = shift_alg_hi[cpu][SHIFT_LSHIFTRT][count];
+ ar = shift_alg_hi[cpu][SHIFT_ASHIFTRT][count];
+ break;
+
+ case SImode:
+ a = shift_alg_si[cpu][SHIFT_ASHIFT][count];
+ lr = shift_alg_si[cpu][SHIFT_LSHIFTRT][count];
+ ar = shift_alg_si[cpu][SHIFT_ASHIFTRT][count];
+ break;
+
+ default:
+ abort ();
+ }
+
+ /* On H8/300H and H8/S, count == 8 uses the scratch register. */
+ return (a == SHIFT_LOOP || lr == SHIFT_LOOP || ar == SHIFT_LOOP
+ || (!TARGET_H8300 && mode == SImode && count == 8));
+}
+
/* Emit the assembler code for doing shifts. */
const char *
/* Extra constraints. */
+#define OK_FOR_R(OP) \
+ (GET_CODE (OP) == CONST_INT \
+ ? !h8300_shift_needs_scratch_p (INTVAL (OP), QImode) \
+ : 0)
+
+#define OK_FOR_S(OP) \
+ (GET_CODE (OP) == CONST_INT \
+ ? !h8300_shift_needs_scratch_p (INTVAL (OP), HImode) \
+ : 0)
+
+#define OK_FOR_T(OP) \
+ (GET_CODE (OP) == CONST_INT \
+ ? !h8300_shift_needs_scratch_p (INTVAL (OP), SImode) \
+ : 0)
+
/* Nonzero if X is a constant address suitable as an 8-bit absolute on
the H8/300H, which is a special case of the 'R' operand. */
&& GET_CODE (XEXP (OP, 0)) == CONST_INT))
#define EXTRA_CONSTRAINT(OP, C) \
- ((C) == 'U' ? OK_FOR_U (OP) : \
+ ((C) == 'R' ? OK_FOR_R (OP) : \
+ (C) == 'S' ? OK_FOR_S (OP) : \
+ (C) == 'T' ? OK_FOR_T (OP) : \
+ (C) == 'U' ? OK_FOR_U (OP) : \
0)
\f
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
[(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" "KM,rn")]))
+ (match_operand:QI 2 "nonmemory_operand" "R,rn")]))
(clobber (match_scratch:QI 4 "=X,&r"))]
""
"* return output_a_shift (operands);"
[(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" "KM,rn")]))
+ (match_operand:QI 2 "nonmemory_operand" "S,rn")]))
(clobber (match_scratch:QI 4 "=X,&r"))]
""
"* return output_a_shift (operands);"
[(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" "K,rn")]))
+ (match_operand:QI 2 "nonmemory_operand" "T,rn")]))
(clobber (match_scratch:QI 4 "=X,&r"))]
""
"* return output_a_shift (operands);"