h8300.c (ok_for_bclr): Take a HOST_WIDE_INT.
* config/h8300/h8300.c (ok_for_bclr): Take a HOST_WIDE_INT. (small_power_of_two): Likewise; use exact_log2. (adds_subs_operand, one_insn_adds_subs_operand): Remove. (output_adds_subs): Remove. (two_insn_adds_subs_operand): New. (split_adds_subs): New. * config/h8300/h8300-protos.h: Update. * config/h8300/h8300.h (CONST_OK_FOR_J): Cast to uns HOST_WIDE_INT. (CONST_OK_FOR_L): Match strict adds operands. (CONST_OK_FOR_N): Match struct subs operands. * config/h8300/h8300.md (adds_subs insns): Remove. (addhi patterns): Output adds/subs directly. (addsi_h8300h): Likewise. (addhi/addsi splitters): New. Decompose two_insn_adds_subs_operand. From-SVN: r33985
This commit is contained in:
parent
15dad1d908
commit
009ac3d324
5 changed files with 134 additions and 193 deletions
|
@ -1,3 +1,20 @@
|
|||
2000-05-18 Richard Henderson <rth@cygnus.com>
|
||||
|
||||
* config/h8300/h8300.c (ok_for_bclr): Take a HOST_WIDE_INT.
|
||||
(small_power_of_two): Likewise; use exact_log2.
|
||||
(adds_subs_operand, one_insn_adds_subs_operand): Remove.
|
||||
(output_adds_subs): Remove.
|
||||
(two_insn_adds_subs_operand): New.
|
||||
(split_adds_subs): New.
|
||||
* config/h8300/h8300-protos.h: Update.
|
||||
* config/h8300/h8300.h (CONST_OK_FOR_J): Cast to uns HOST_WIDE_INT.
|
||||
(CONST_OK_FOR_L): Match strict adds operands.
|
||||
(CONST_OK_FOR_N): Match struct subs operands.
|
||||
* config/h8300/h8300.md (adds_subs insns): Remove.
|
||||
(addhi patterns): Output adds/subs directly.
|
||||
(addsi_h8300h): Likewise.
|
||||
(addhi/addsi splitters): New. Decompose two_insn_adds_subs_operand.
|
||||
|
||||
2000-05-18 Zack Weinberg <zack@wolery.cumb.org>
|
||||
|
||||
* cppexp.c (parse_assertion): New.
|
||||
|
|
|
@ -36,14 +36,14 @@ extern void notice_update_cc PARAMS ((rtx, rtx));
|
|||
extern int expand_a_shift PARAMS ((enum machine_mode, int, rtx[]));
|
||||
extern int fix_bit_operand PARAMS ((rtx *, int, enum rtx_code));
|
||||
extern int h8300_adjust_insn_length PARAMS ((rtx, int));
|
||||
extern void split_adds_subs PARAMS ((enum machine_mode, rtx[]));
|
||||
|
||||
extern int general_operand_src PARAMS ((rtx, enum machine_mode));
|
||||
extern int general_operand_dst PARAMS ((rtx, enum machine_mode));
|
||||
extern int o_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int p_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int call_insn_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int adds_subs_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int one_insn_adds_subs_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int two_insn_adds_subs_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int small_call_insn_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int jump_address_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int bit_operand PARAMS ((rtx, enum machine_mode));
|
||||
|
@ -70,6 +70,6 @@ extern void function_prologue PARAMS ((FILE *, int));
|
|||
extern void function_epilogue PARAMS ((FILE *, int));
|
||||
extern void asm_file_start PARAMS ((FILE *));
|
||||
extern void asm_file_end PARAMS ((FILE *));
|
||||
extern int ok_for_bclr PARAMS ((int));
|
||||
extern int small_power_of_two PARAMS ((int));
|
||||
extern int ok_for_bclr PARAMS ((HOST_WIDE_INT));
|
||||
extern int small_power_of_two PARAMS ((HOST_WIDE_INT));
|
||||
extern int initial_offset PARAMS ((int, int));
|
||||
|
|
|
@ -542,29 +542,10 @@ asm_file_end (file)
|
|||
|
||||
int
|
||||
small_power_of_two (value)
|
||||
int value;
|
||||
HOST_WIDE_INT value;
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
case 16:
|
||||
case 32:
|
||||
case 64:
|
||||
case 128:
|
||||
case 256:
|
||||
case 512:
|
||||
case 1024:
|
||||
case 2048:
|
||||
case 4096:
|
||||
case 8192:
|
||||
case 16384:
|
||||
case 32768:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
int power = exact_log2 (value);
|
||||
return power >= 0 && power <= 15;
|
||||
}
|
||||
|
||||
/* Return true if VALUE is a valid constant for constraint 'O', which
|
||||
|
@ -573,7 +554,7 @@ small_power_of_two (value)
|
|||
|
||||
int
|
||||
ok_for_bclr (value)
|
||||
int value;
|
||||
HOST_WIDE_INT value;
|
||||
{
|
||||
return small_power_of_two ((~value) & 0xff);
|
||||
}
|
||||
|
@ -645,107 +626,92 @@ call_insn_operand (op, mode)
|
|||
}
|
||||
|
||||
int
|
||||
adds_subs_operand (op, mode)
|
||||
two_insn_adds_subs_operand (op, mode)
|
||||
rtx op;
|
||||
enum machine_mode mode ATTRIBUTE_UNUSED;
|
||||
{
|
||||
if (GET_CODE (op) == CONST_INT)
|
||||
{
|
||||
if (INTVAL (op) <= 4 && INTVAL (op) >= 0)
|
||||
return 1;
|
||||
if (INTVAL (op) >= -4 && INTVAL (op) <= 0)
|
||||
return 1;
|
||||
if ((TARGET_H8300H || TARGET_H8300S)
|
||||
&& INTVAL (op) != 7
|
||||
&& (INTVAL (op) <= 8 && INTVAL (op) >= 0))
|
||||
return 1;
|
||||
if ((TARGET_H8300H || TARGET_H8300S)
|
||||
&& INTVAL (op) != -7
|
||||
&& (INTVAL (op) >= -8 && INTVAL (op) <= 0))
|
||||
return 1;
|
||||
HOST_WIDE_INT value = INTVAL (op);
|
||||
|
||||
if (TARGET_H8300H || TARGET_H8300S)
|
||||
{
|
||||
if (value >= -8 && value < -4 && value != -7)
|
||||
return 1;
|
||||
if (value > 4 && value <= 8 && value != 7)
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value == -4 || value == -3 || value == 3 || value == 4)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return nonzero if op is an adds/subs operand which only requires
|
||||
one insn to implement. It is assumed that OP is already an adds/subs
|
||||
operand. */
|
||||
int
|
||||
one_insn_adds_subs_operand (op, mode)
|
||||
rtx op;
|
||||
enum machine_mode mode ATTRIBUTE_UNUSED;
|
||||
{
|
||||
int val = INTVAL (op);
|
||||
/* Split an add of a small constant into two adds/subs insns. */
|
||||
|
||||
if (val == 1 || val == -1
|
||||
|| val == 2 || val == -2
|
||||
|| ((TARGET_H8300H || TARGET_H8300S)
|
||||
&& (val == 4 || val == -4)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
output_adds_subs (operands)
|
||||
void
|
||||
split_adds_subs (mode, operands)
|
||||
enum machine_mode mode;
|
||||
rtx *operands;
|
||||
{
|
||||
int val = INTVAL (operands[2]);
|
||||
HOST_WIDE_INT val = INTVAL (operands[1]);
|
||||
rtx reg = operands[0];
|
||||
rtx tmp;
|
||||
|
||||
/* First get the value into the range -4..4 inclusive.
|
||||
|
||||
The only way it can be out of this range is when TARGET_H8300H
|
||||
or TARGET_H8300S is true, thus it is safe to use adds #4 and subs #4. */
|
||||
if (val > 4)
|
||||
/* Take care of +/- 4 for H8300H and H8300S. */
|
||||
if (TARGET_H8300H || TARGET_H8300S)
|
||||
{
|
||||
output_asm_insn ("adds #4,%A0", operands);
|
||||
val -= 4;
|
||||
/* Get the value in range of +/- 4. */
|
||||
if (val > 4)
|
||||
{
|
||||
tmp = gen_rtx_PLUS (mode, reg, GEN_INT (4));
|
||||
emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
|
||||
val -= 4;
|
||||
}
|
||||
else if (val < -4)
|
||||
{
|
||||
tmp = gen_rtx_PLUS (mode, reg, GEN_INT (-4));
|
||||
emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
|
||||
val += 4;
|
||||
}
|
||||
|
||||
if (val == 4 || val == -4)
|
||||
{
|
||||
tmp = gen_rtx_PLUS (mode, reg, GEN_INT (val));
|
||||
emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (val < -4)
|
||||
{
|
||||
output_asm_insn ("subs #4,%A0", operands);
|
||||
val += 4;
|
||||
}
|
||||
|
||||
/* Handle case were val == 4 or val == -4 and we're compiling
|
||||
for TARGET_H8300H or TARGET_H8300S. */
|
||||
if ((TARGET_H8300H || TARGET_H8300S)
|
||||
&& val == 4)
|
||||
return "adds #4,%A0";
|
||||
|
||||
if ((TARGET_H8300H || TARGET_H8300S)
|
||||
&& val == -4)
|
||||
return "subs #4,%A0";
|
||||
|
||||
/* Get the value in range of +/- 2. */
|
||||
if (val > 2)
|
||||
{
|
||||
output_asm_insn ("adds #2,%A0", operands);
|
||||
tmp = gen_rtx_PLUS (mode, reg, GEN_INT (2));
|
||||
emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
|
||||
val -= 2;
|
||||
}
|
||||
|
||||
if (val < -2)
|
||||
else if (val < -2)
|
||||
{
|
||||
output_asm_insn ("subs #2,%A0", operands);
|
||||
tmp = gen_rtx_PLUS (mode, reg, GEN_INT (-2));
|
||||
emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
|
||||
val += 2;
|
||||
}
|
||||
|
||||
/* val should be one or two now. */
|
||||
if (val == 2)
|
||||
return "adds #2,%A0";
|
||||
|
||||
if (val == -2)
|
||||
return "subs #2,%A0";
|
||||
|
||||
/* val should be one now. */
|
||||
if (val == 1)
|
||||
return "adds #1,%A0";
|
||||
|
||||
if (val == -1)
|
||||
return "subs #1,%A0";
|
||||
|
||||
/* If not optimizing, we might be asked to add 0. */
|
||||
if (val == 0)
|
||||
return "";
|
||||
return;
|
||||
|
||||
/* We should have one or two now. */
|
||||
if (val >= -2 && val <= 2)
|
||||
{
|
||||
tmp = gen_rtx_PLUS (mode, reg, GEN_INT (val));
|
||||
emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
|
||||
return;
|
||||
}
|
||||
|
||||
/* In theory, this can't happen. */
|
||||
abort ();
|
||||
|
|
|
@ -399,11 +399,17 @@ enum reg_class {
|
|||
Return 1 if VALUE is in the range specified by C. */
|
||||
|
||||
#define CONST_OK_FOR_I(VALUE) ((VALUE) == 0)
|
||||
#define CONST_OK_FOR_J(VALUE) ((unsigned) (VALUE) < 256)
|
||||
#define CONST_OK_FOR_K(VALUE) (((VALUE) == 1) || (VALUE) == 2)
|
||||
#define CONST_OK_FOR_L(VALUE) (((VALUE) == -1) || (VALUE) == -2)
|
||||
#define CONST_OK_FOR_M(VALUE) (((VALUE) == 3) || (VALUE) == 4)
|
||||
#define CONST_OK_FOR_N(VALUE) (((VALUE) == -3) || (VALUE) == -4)
|
||||
#define CONST_OK_FOR_J(VALUE) ((unsigned HOST_WIDE_INT) (VALUE) < 256)
|
||||
#define CONST_OK_FOR_K(VALUE) ((VALUE) == 1 || (VALUE) == 2)
|
||||
#define CONST_OK_FOR_L(VALUE) \
|
||||
(TARGET_H8300H || TARGET_H8300S \
|
||||
? (VALUE) == 1 || (VALUE) == 2 || (VALUE) == 4 \
|
||||
: (VALUE) == 1 || (VALUE) == 2)
|
||||
#define CONST_OK_FOR_M(VALUE) ((VALUE) == 3 || (VALUE) == 4)
|
||||
#define CONST_OK_FOR_N(VALUE) \
|
||||
(TARGET_H8300H || TARGET_H8300S \
|
||||
? (VALUE) == -1 || (VALUE) == -2 || (VALUE) == -4 \
|
||||
: (VALUE) == -1 || (VALUE) == -2)
|
||||
#define CONST_OK_FOR_O(VALUE) (ok_for_bclr (VALUE))
|
||||
#define CONST_OK_FOR_P(VALUE) (small_power_of_two (VALUE))
|
||||
|
||||
|
@ -415,7 +421,7 @@ enum reg_class {
|
|||
(C) == 'M' ? CONST_OK_FOR_M (VALUE) : \
|
||||
(C) == 'N' ? CONST_OK_FOR_N (VALUE) : \
|
||||
(C) == 'O' ? CONST_OK_FOR_O (VALUE) : \
|
||||
(C) == 'P' ? CONST_OK_FOR_P(VALUE) : \
|
||||
(C) == 'P' ? CONST_OK_FOR_P (VALUE) : \
|
||||
0)
|
||||
|
||||
/* Similar, but for floating constants, and defining letters G and H.
|
||||
|
|
|
@ -614,43 +614,40 @@
|
|||
""
|
||||
"")
|
||||
|
||||
;; Specialized version using adds/subs. This must come before
|
||||
;; the more general patterns below.
|
||||
(define_insn ""
|
||||
[(set (match_operand:HI 0 "register_operand" "=r")
|
||||
(plus:HI (match_operand:HI 1 "register_operand" "%0")
|
||||
(match_operand:HI 2 "adds_subs_operand" "n")))]
|
||||
""
|
||||
"* return output_adds_subs (operands);"
|
||||
[(set_attr "cc" "none_0hit")
|
||||
(set (attr "length")
|
||||
(if_then_else (ne (match_operand:HI 2 "one_insn_adds_subs_operand" "")
|
||||
(const_int 0))
|
||||
(const_int 2)
|
||||
(const_int 4)))])
|
||||
|
||||
(define_insn ""
|
||||
[(set (match_operand:HI 0 "register_operand" "=&r,r,&r")
|
||||
(plus:HI (match_operand:HI 1 "register_operand" "%0,0,g")
|
||||
(match_operand:HI 2 "nonmemory_operand" "n,r,r")))]
|
||||
[(set (match_operand:HI 0 "register_operand" "=r,r,r,r,&r")
|
||||
(plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,g")
|
||||
(match_operand:HI 2 "nonmemory_operand" "L,N,n,r,r")))]
|
||||
"TARGET_H8300"
|
||||
"@
|
||||
adds %2,%A0
|
||||
subs %2,%A0
|
||||
add.b %s2,%s0\;addx %t2,%t0
|
||||
add.w %T2,%T0
|
||||
mov.w %T1,%T0\;add.w %T2,%T0"
|
||||
[(set_attr "length" "4,2,6")
|
||||
(set_attr "cc" "clobber,set_zn,set_zn")])
|
||||
[(set_attr "length" "2,2,4,2,6")
|
||||
(set_attr "cc" "none_0hit,none_0hit,clobber,set_zn,set_zn")])
|
||||
|
||||
(define_insn ""
|
||||
[(set (match_operand:HI 0 "register_operand" "=r,r")
|
||||
(plus:HI (match_operand:HI 1 "register_operand" "%0,0")
|
||||
(match_operand:HI 2 "nonmemory_operand" "n,r")))]
|
||||
[(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
|
||||
(plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
|
||||
(match_operand:HI 2 "nonmemory_operand" "L,N,n,r")))]
|
||||
"TARGET_H8300H || TARGET_H8300S"
|
||||
"@
|
||||
adds %2,%A0
|
||||
subs %2,%A0
|
||||
add.w %T2,%T0
|
||||
add.w %T2,%T0"
|
||||
[(set_attr "length" "4,2")
|
||||
(set_attr "cc" "set_zn,set_zn")])
|
||||
[(set_attr "length" "2,2,4,2")
|
||||
(set_attr "cc" "none_0hit,none_0hit,set_zn,set_zn")])
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:HI 0 "register_operand" "")
|
||||
(plus:HI (match_dup 0)
|
||||
(match_operand:HI 1 "two_insn_adds_subs_operand" "")))]
|
||||
""
|
||||
[(const_int 0)]
|
||||
"split_adds_subs (HImode, operands); DONE;")
|
||||
|
||||
(define_expand "addsi3"
|
||||
[(set (match_operand:SI 0 "register_operand" "")
|
||||
|
@ -659,21 +656,6 @@
|
|||
""
|
||||
"")
|
||||
|
||||
;; Specialized version using adds/subs. This must come before
|
||||
;; the more general patterns below.
|
||||
(define_insn ""
|
||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||
(plus:SI (match_operand:SI 1 "register_operand" "%0")
|
||||
(match_operand:SI 2 "adds_subs_operand" "n")))]
|
||||
"TARGET_H8300H || TARGET_H8300S"
|
||||
"* return output_adds_subs (operands);"
|
||||
[(set_attr "cc" "none_0hit")
|
||||
(set (attr "length")
|
||||
(if_then_else (ne (match_operand:HI 2 "one_insn_adds_subs_operand" "")
|
||||
(const_int 0))
|
||||
(const_int 2)
|
||||
(const_int 4)))])
|
||||
|
||||
(define_insn "addsi_h8300"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r,r,&r")
|
||||
(plus:SI (match_operand:SI 1 "register_operand" "%0,0,r")
|
||||
|
@ -687,15 +669,25 @@
|
|||
(set_attr "cc" "clobber")])
|
||||
|
||||
(define_insn "addsi_h8300h"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r,r")
|
||||
(plus:SI (match_operand:SI 1 "register_operand" "%0,0")
|
||||
(match_operand:SI 2 "nonmemory_operand" "i,r")))]
|
||||
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
|
||||
(plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
|
||||
(match_operand:SI 2 "nonmemory_operand" "L,N,i,r")))]
|
||||
"TARGET_H8300H || TARGET_H8300S"
|
||||
"@
|
||||
adds %2,%A0
|
||||
subs %2,%A0
|
||||
add.l %S2,%S0
|
||||
add.l %S2,%S0"
|
||||
[(set_attr "length" "6,2")
|
||||
(set_attr "cc" "set_zn,set_zn")])
|
||||
[(set_attr "length" "2,2,6,2")
|
||||
(set_attr "cc" "none_0hit,none_0hit,set_zn,set_zn")])
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:SI 0 "register_operand" "")
|
||||
(plus:SI (match_dup 0)
|
||||
(match_operand:SI 1 "two_insn_adds_subs_operand" "")))]
|
||||
"TARGET_H8300H || TARGET_H8300S"
|
||||
[(const_int 0)]
|
||||
"split_adds_subs (SImode, operands); DONE;")
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; SUBTRACT INSTRUCTIONS
|
||||
|
@ -719,26 +711,6 @@
|
|||
""
|
||||
"")
|
||||
|
||||
;; Specialized version using adds/subs. This must come before
|
||||
;; the more general patterns below. This may not be needed
|
||||
;; due to instruction canonicalization.
|
||||
(define_insn ""
|
||||
[(set (match_operand:HI 0 "register_operand" "=r")
|
||||
(minus:HI (match_operand:HI 1 "register_operand" "r")
|
||||
(match_operand:HI 2 "adds_subs_operand" "n")))]
|
||||
""
|
||||
"*
|
||||
{
|
||||
operands[2] = GEN_INT (-INTVAL (operands[2]));
|
||||
return output_adds_subs (operands);
|
||||
}"
|
||||
[(set_attr "cc" "none_0hit")
|
||||
(set (attr "length")
|
||||
(if_then_else (ne (match_operand:HI 2 "one_insn_adds_subs_operand" "")
|
||||
(const_int 0))
|
||||
(const_int 2)
|
||||
(const_int 4)))])
|
||||
|
||||
(define_insn ""
|
||||
[(set (match_operand:HI 0 "register_operand" "=r,&r")
|
||||
(minus:HI (match_operand:HI 1 "general_operand" "0,0")
|
||||
|
@ -777,26 +749,6 @@
|
|||
[(set_attr "length" "6")
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
;; Specialized version using adds/subs. This must come before
|
||||
;; the more general patterns below. This may not be needed
|
||||
;; due to instruction canonicalization.
|
||||
(define_insn ""
|
||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||
(minus:SI (match_operand:SI 1 "general_operand" "0")
|
||||
(match_operand:SI 2 "adds_subs_operand" "n")))]
|
||||
"TARGET_H8300H || TARGET_H8300S"
|
||||
"*
|
||||
{
|
||||
operands[2] = GEN_INT (-INTVAL (operands[2]));
|
||||
return output_adds_subs (operands);
|
||||
}"
|
||||
[(set_attr "cc" "none_0hit")
|
||||
(set (attr "length")
|
||||
(if_then_else (ne (match_operand:HI 2 "one_insn_adds_subs_operand" "")
|
||||
(const_int 0))
|
||||
(const_int 2)
|
||||
(const_int 4)))])
|
||||
|
||||
(define_insn "subsi3_h8300h"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r,r")
|
||||
(minus:SI (match_operand:SI 1 "general_operand" "0,0")
|
||||
|
|
Loading…
Add table
Reference in a new issue