Commit 3b7d443c by Jeff Law

h8300.md: Add more comments about things which seem wrong...

        * h8300.md: Add more comments about things which seem
        wrong, stupid, or just don't make any sense yet.

        * h8300.c (adds_subs_operand): New function.
        (output_adds_subs): New function.
        * h8300.md (addhi3): Turn into a define_expand.
        (addhi3 using adds_subs): New pattern.
        (H8300 addhi): Derived from old addhi pattern.  Simplified.
        (H8300H addhi): Likewise.
        (addsi using adds_subs): New pattern.  Only used on H8300H.
        (addsi_h8300): Allow "a" registers as destination.
        (addsi_h8300h):  Simplify.  Allow "a" registers as destination.

        * h8300.md (bcs): New attribute type.
        (default_length): Compute correct length for bcs insns.
        (bcs_qiqi, bcs_hihi, bs_hiqi): Use new type and update
        to account for correct length computation.

        * h8300.md (movhi_internal): Demand at least one operand to
        be a register.
        (movsi_h8300): Optimize loading certain constants.
        (movsi_h8300h): Likewise.

        * h8300.h (NO_FUNCTION_CSE): Comment out.
        (FUNCTION_ARG_REGNO_P): Properly define for TARGET_QUICKCALL.
        (RETURN_IN_MEMORY): Don't return small structs in regs.

From-SVN: r11751
parent 2ca96cdf
...@@ -431,6 +431,89 @@ call_insn_operand (op, mode) ...@@ -431,6 +431,89 @@ call_insn_operand (op, mode)
return 0; return 0;
} }
int
adds_subs_operand (op, mode)
rtx op;
enum machine_mode mode;
{
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
&& INTVAL (op) != 7
&& (INTVAL (op) <= 8 || INTVAL (op) >= 0))
return 1;
if (TARGET_H8300H
&& INTVAL (op) != -7
&& (INTVAL (op) >= -8 || INTVAL (op) <= 0))
return 1;
}
return 0;
}
char *
output_adds_subs (operands)
rtx *operands;
{
int val = INTVAL (operands[2]);
/* First get the value into the range -4..4 inclusive.
The only way it can be out of this range is when TARGET_H8300H
is true, thus it is safe to use adds #4 and subs #4. */
if (val > 4)
{
output_asm_insn ("adds #4,%A0", operands);
val -= 4;
}
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. */
if (TARGET_H8300H && val == 4)
return "adds #4,%A0";
if (TARGET_H8300H && val == -4)
return "subs #4,%A0";
if (val > 2)
{
output_asm_insn ("adds #2,%A0", operands);
val -= 2;
}
if (val < -2)
{
output_asm_insn ("subs #2,%A0", operands);
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";
/* In theory, this can't happen. */
abort ();
}
/* Return true if OP is a valid call operand, and OP represents /* Return true if OP is a valid call operand, and OP represents
an operand for a small call (4 bytes instead of 6 bytes). */ an operand for a small call (4 bytes instead of 6 bytes). */
......
...@@ -126,7 +126,7 @@ do { \ ...@@ -126,7 +126,7 @@ do { \
shouldn't be put through pseudo regs where they can be cse'd. shouldn't be put through pseudo regs where they can be cse'd.
Desirable on machines where ordinary constants are expensive Desirable on machines where ordinary constants are expensive
but a CALL with constant address is cheap. */ but a CALL with constant address is cheap. */
#define NO_FUNCTION_CSE /* #define NO_FUNCTION_CSE */
/* Target machine storage layout */ /* Target machine storage layout */
...@@ -541,9 +541,8 @@ enum reg_class { ...@@ -541,9 +541,8 @@ enum reg_class {
/* 1 if N is a possible register number for function argument passing. /* 1 if N is a possible register number for function argument passing.
On the H8, no registers are used in this way. */ On the H8, no registers are used in this way. */
/* ??? What about TARGET_QUICKCALL? */
#define FUNCTION_ARG_REGNO_P(N) 0 #define FUNCTION_ARG_REGNO_P(N) (TARGET_QUICKCALL ? N < 3 : 0)
/* Register in which address to store a structure value /* Register in which address to store a structure value
is passed to a function. */ is passed to a function. */
...@@ -551,8 +550,8 @@ enum reg_class { ...@@ -551,8 +550,8 @@ enum reg_class {
#define STRUCT_VALUE 0 #define STRUCT_VALUE 0
/* Return true if X should be returned in memory. */ /* Return true if X should be returned in memory. */
/* ??? This will return small structs in regs. */ #define RETURN_IN_MEMORY(X) \
#define RETURN_IN_MEMORY(X) (GET_MODE_SIZE (TYPE_MODE (X)) > 4) (TYPE_MODE (X) == BLKmode || GET_MODE_SIZE (TYPE_MODE (X)) > 4)
/* When defined, the compiler allows registers explicitly used in the /* When defined, the compiler allows registers explicitly used in the
rtl to be used as spill registers but prevents the compiler from rtl to be used as spill registers but prevents the compiler from
...@@ -1342,3 +1341,4 @@ do { char dstr[30]; \ ...@@ -1342,3 +1341,4 @@ do { char dstr[30]; \
/* Declarations for functions used in insn-output.c. */ /* Declarations for functions used in insn-output.c. */
char *emit_a_shift (); char *emit_a_shift ();
int h8300_funcvec_function_p (); int h8300_funcvec_function_p ();
char *output_adds_subs();
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