Commit 009ac3d3 by Richard Henderson Committed by Richard Henderson

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
parent 15dad1d9
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;
}
return 0;
}
HOST_WIDE_INT value = INTVAL (op);
/* 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);
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;
}
}
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)
/* Split an add of a small constant into two adds/subs insns. */
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)
{
output_asm_insn ("subs #4,%A0", operands);
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;
}
}
/* 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")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment