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();
...@@ -31,6 +31,10 @@ ...@@ -31,6 +31,10 @@
;; ??? If we can remove the operand type on all the insns, do it. ;; ??? If we can remove the operand type on all the insns, do it.
;; ??? Otherwise, try to have the operand type on all the insns. ;; ??? Otherwise, try to have the operand type on all the insns.
;; ??? Many patterns have overly conservative lengths. In particular:
;;
;; * movXX insns using register indirect addressing.
;; * insns referencing the 8-bit area with an 8-bit address.
;; Some move patterns have conditions which check that one operand ;; Some move patterns have conditions which check that one operand
;; is a register. Shouldn't all of them have such a condition? ;; is a register. Shouldn't all of them have such a condition?
...@@ -42,7 +46,7 @@ ...@@ -42,7 +46,7 @@
;; can be found using bit-set insns dec, etc ;; can be found using bit-set insns dec, etc
(define_attr "type" "branch,return,call,arith,move,float,multi" (define_attr "type" "branch,bcs,return,call,arith,move,float,multi"
(const_string "arith")) (const_string "arith"))
;; The size of instructions in bytes. ;; The size of instructions in bytes.
...@@ -61,6 +65,28 @@ ...@@ -61,6 +65,28 @@
(const_int 32000)))) (const_int 32000))))
(const_int 4) (const_int 4)
(const_int 6))) (const_int 6)))
(eq_attr "type" "bcs")
(if_then_else (and (ge (minus (pc) (match_dup 0))
(const_int -120))
(le (minus (pc) (match_dup 0))
(const_int 120)))
(if_then_else
(match_operand 2 "register_operand" "")
(const_int 4)
(const_int 6))
(if_then_else (and (eq_attr "cpu" "h8300h")
(and (ge (minus (pc) (match_dup 0))
(const_int -32000))
(le (minus (pc) (match_dup 0))
(const_int 32000))))
(if_then_else
(match_operand 2 "register_operand" "")
(const_int 6)
(const_int 8))
(if_then_else
(match_operand 2 "register_operand" "")
(const_int 8)
(const_int 10))))
(eq_attr "type" "move") (const_int 4) (eq_attr "type" "move") (const_int 4)
(eq_attr "type" "return") (const_int 2) (eq_attr "type" "return") (const_int 2)
(eq_attr "type" "float") (const_int 12) (eq_attr "type" "float") (const_int 12)
...@@ -150,6 +176,8 @@ ...@@ -150,6 +176,8 @@
;; movhi ;; movhi
;; ??? We use push.l on the h8300h to push a 16bit value?!? We have
;; 16bit push insns!
(define_insn "movhi_push" (define_insn "movhi_push"
[(set (match_operand:HI 0 "push_operand" "=<") [(set (match_operand:HI 0 "push_operand" "=<")
(match_operand:HI 1 "register_operand" "ra"))] (match_operand:HI 1 "register_operand" "ra"))]
...@@ -168,7 +196,8 @@ ...@@ -168,7 +196,8 @@
(define_insn "movhi_internal" (define_insn "movhi_internal"
[(set (match_operand:HI 0 "general_operand_dst" "=ra,ra,<,ra,o") [(set (match_operand:HI 0 "general_operand_dst" "=ra,ra,<,ra,o")
(match_operand:HI 1 "general_operand_src" "I,ra>,ra,ion,ra"))] (match_operand:HI 1 "general_operand_src" "I,ra>,ra,ion,ra"))]
"" "register_operand (operands[0],HImode)
|| register_operand (operands[1], HImode)"
"@ "@
sub.w %T0,%T0 sub.w %T0,%T0
mov.w %T1,%T0 mov.w %T1,%T0
...@@ -299,11 +328,19 @@ ...@@ -299,11 +328,19 @@
} }
else else
{ {
return \"mov.w %e1,%e0\;mov.w %f1,%f0\"; /* See if either half is zero. If so, use sub.w to clear
that half. */
if (GET_CODE (operands[1]) == CONST_INT)
{
if ((INTVAL (operands[1]) & 0xffff) == 0)
return \"mov.w %e1,%e0\;sub.w %f0,%f0\";
if (((INTVAL (operands[1]) >> 16) & 0xffff) == 0)
return \"sub.w %e0,%e0\;mov.w %f1,%f0\";
}
return \"mov.w %e1,%e0\;mov.w %f1,%f0\";
} }
case 3: case 3:
return \"mov.w %e1,%e0\;mov.w %f1,%f0\"; return \"mov.w %e1,%e0\;mov.w %f1,%f0\";
case 4: case 4:
return \"mov.w %f1,%T0\;mov.w %e1,%T0\"; return \"mov.w %f1,%T0\;mov.w %e1,%T0\";
case 5: case 5:
...@@ -380,13 +417,38 @@ ...@@ -380,13 +417,38 @@
"TARGET_H8300H "TARGET_H8300H
&& (register_operand (operands[0], SImode) && (register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))" || register_operand (operands[1], SImode))"
"@ "*
sub.l %S0,%S0 {
mov.l %S1,%S0 if (which_alternative == 0)
mov.l %S1,%S0 return \"sub.l %S0,%S0\";
mov.l %S1,%S0 if (GET_CODE (operands[1]) == CONST_INT)
mov.l %S1,%S0 {
mov.l %S1,%S0" int val = INTVAL (operands[1]);
/* Look for constants which can be made by adding an 8-bit
number to zero in one of the two low bytes. */
if (val == (val & 0xff))
{
operands[1] = GEN_INT ((char)val & 0xff);
return \"sub.l %S0,%S0\;add.b %1,%w0\";
}
if (val == (val & 0xff00))
{
operands[1] = GEN_INT ((char)(val >> 8) & 0xff);
return \"sub.l %S0,%S0\;add.b %1,%x0\";
}
/* Now look for small negative numbers. We can subtract them
from zero to get the desired constant. */
if (val == -4 || val == -2 || val == -1)
{
operands[1] = GEN_INT (-INTVAL (operands[1]));
return \"sub.l %S0,%S0\;subs %1,%S0\";
}
}
return \"mov.l %S1,%S0\";
}"
[(set_attr "type" "move") [(set_attr "type" "move")
(set_attr "length" "2,2,10,10,4,4") (set_attr "length" "2,2,10,10,4,4")
(set_attr "cc" "set_zn_c0,set,set,set,set,set")]) (set_attr "cc" "set_zn_c0,set,set,set,set,set")])
...@@ -514,23 +576,49 @@ ...@@ -514,23 +576,49 @@
;; h8300h: adds operates on the 32bit register. We can use it because we don't ;; h8300h: adds operates on the 32bit register. We can use it because we don't
;; use the e0-7 registers. ;; use the e0-7 registers.
;; ??? 4 can be handled in one insn on the 300h.
(define_insn "addhi3" (define_expand "addhi3"
[(set (match_operand:HI 0 "register_operand" "=ra,ra,ra,ra,r,ra") [(set (match_operand:HI 0 "register_operand" "")
(plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0") (plus:HI (match_operand:HI 1 "register_operand" "")
(match_operand:HI 2 "nonmemory_operand" "K,M,L,N,n,ra")))] (match_operand:HI 2 "nonmemory_operand" "")))]
""
"")
;; Specialized version using adds/subs. This must come before
;; the more general patterns below.
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=ra")
(plus:HI (match_operand:HI 1 "register_operand" "%0")
(match_operand:HI 2 "adds_subs_operand" "i")))]
"" ""
"* return output_adds_subs (operands);"
[(set_attr "type" "arith")
(set_attr "length" "4")
(set_attr "cc" "none_0hit")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=&ra,ra")
(plus:HI (match_operand:HI 1 "register_operand" "%0,0")
(match_operand:HI 2 "nonmemory_operand" "n,ra")))]
"TARGET_H8300"
"@ "@
adds %T2,%A0
adds #2,%A0\;adds %C2,%A0
subs %M2,%A0
subs #2,%A0\;subs %M2,%A0
add.b %s2,%s0\;addx %t2,%t0 add.b %s2,%s0\;addx %t2,%t0
add.w %T2,%T0" add.w %T2,%T0"
[(set_attr "type" "arith,multi,arith,multi,multi,arith") [(set_attr "type" "multi,arith")
(set_attr "length" "2,4,2,4,4,2") (set_attr "length" "4,2")
(set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,clobber,set_zn_c0")]) (set_attr "cc" "clobber,set_zn_c0")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=ra,ra")
(plus:HI (match_operand:HI 1 "register_operand" "%0,0")
(match_operand:HI 2 "nonmemory_operand" "i,ra")))]
"TARGET_H8300H"
"@
add.w %T2,%T0
add.w %T2,%T0"
[(set_attr "type" "arith,arith")
(set_attr "length" "4,2")
(set_attr "cc" "set_zn_c0,set_zn_c0")])
(define_expand "addsi3" (define_expand "addsi3"
[(set (match_operand:SI 0 "register_operand" "") [(set (match_operand:SI 0 "register_operand" "")
...@@ -539,8 +627,20 @@ ...@@ -539,8 +627,20 @@
"" ""
"") "")
;; Specialized version using adds/subs. This must come before
;; the more general patterns below.
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=ra")
(plus:SI (match_operand:SI 1 "register_operand" "%0")
(match_operand:SI 2 "adds_subs_operand" "i")))]
"TARGET_H8300H"
"* return output_adds_subs (operands);"
[(set_attr "type" "arith")
(set_attr "length" "4")
(set_attr "cc" "none_0hit")])
(define_insn "addsi_h8300" (define_insn "addsi_h8300"
[(set (match_operand:SI 0 "register_operand" "=r,r,&r") [(set (match_operand:SI 0 "register_operand" "=ra,ra,&ra")
(plus:SI (match_operand:SI 1 "register_operand" "%0,0,r") (plus:SI (match_operand:SI 1 "register_operand" "%0,0,r")
(match_operand:SI 2 "nonmemory_operand" "n,r,r")))] (match_operand:SI 2 "nonmemory_operand" "n,r,r")))]
"TARGET_H8300" "TARGET_H8300"
...@@ -552,25 +652,17 @@ ...@@ -552,25 +652,17 @@
(set_attr "length" "8,6,20") (set_attr "length" "8,6,20")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
;; ??? 4 can be handled in one insn on the 300h.
;; ??? Should the 'n' constraint be 'i' here?
;; ??? We don't handle (reg + symbol_ref) which the 300h can handle.
(define_insn "addsi_h8300h" (define_insn "addsi_h8300h"
[(set (match_operand:SI 0 "register_operand" "=ra,ra,ra,ra,r,ra") [(set (match_operand:SI 0 "register_operand" "=ra,ra")
(plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0") (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "K,M,L,N,n,ra")))] (match_operand:SI 2 "nonmemory_operand" "i,ra")))]
"TARGET_H8300H" "TARGET_H8300H"
"@ "@
adds %S2,%S0
adds #2,%S0\;adds %C2,%S0
subs %M2,%S0
subs #2,%S0\;subs %M2,%S0
add.l %S2,%S0 add.l %S2,%S0
add.l %S2,%S0" add.l %S2,%S0"
[(set_attr "type" "multi,multi,multi,multi,arith,arith") [(set_attr "type" "arith,arith")
(set_attr "length" "2,4,2,4,6,2") (set_attr "length" "6,2")
(set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,set_zn_c0,set_zn_c0")]) (set_attr "cc" "set_zn_c0,set_zn_c0")])
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; SUBTRACT INSTRUCTIONS ;; SUBTRACT INSTRUCTIONS
...@@ -1676,15 +1768,23 @@ ...@@ -1676,15 +1768,23 @@
"" ""
"* "*
{ {
/* The length of this insn includes the bld insn below. We
compute the length of the branch without the bld so we
can easily choose the right branch length. */
int branch_length = get_attr_length (insn);
if (! register_operand (operands[2], QImode))
branch_length -= 2;
output_asm_insn(\"bld %Z3,%Y2\", operands); output_asm_insn(\"bld %Z3,%Y2\", operands);
if (get_attr_length (insn) == 2) if (branch_length == 2)
return \"b%d1 %l0\"; return \"b%d1 %l0\";
else if (get_attr_length (insn) == 4) else if (branch_length == 4)
return \"b%d1 %l0:16\"; return \"b%d1 %l0:16\";
else else
return \"b%g1 %L0\;jmp @%l0\;%L0:\"; return \"b%g1 %L0\;jmp @%l0\;%L0:\";
}" }"
[(set_attr "type" "branch") [(set_attr "type" "bcs")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
(define_insn "bcs_hihi" (define_insn "bcs_hihi"
...@@ -1700,15 +1800,23 @@ ...@@ -1700,15 +1800,23 @@
"" ""
"* "*
{ {
/* The length of this insn includes the bld insn below. We
compute the length of the branch without the bld so we
can easily choose the right branch length. */
int branch_length = get_attr_length (insn);
if (! register_operand (operands[2], QImode))
branch_length -= 2;
output_asm_insn(\"bld %Z3,%Y2\", operands); output_asm_insn(\"bld %Z3,%Y2\", operands);
if (get_attr_length (insn) == 2) if (branch_length == 2)
return \"b%d1 %l0\"; return \"b%d1 %l0\";
else if (get_attr_length (insn) == 4) else if (branch_length == 4)
return \"b%d1 %l0:16\"; return \"b%d1 %l0:16\";
else else
return \"b%g1 %L0\;jmp @%l0\;%L0:\"; return \"b%g1 %L0\;jmp @%l0\;%L0:\";
}" }"
[(set_attr "type" "branch") [(set_attr "type" "bcs")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
(define_insn "bcs_hiqi" (define_insn "bcs_hiqi"
...@@ -1724,15 +1832,23 @@ ...@@ -1724,15 +1832,23 @@
"" ""
"* "*
{ {
/* The length of this insn includes the bld insn below. We
compute the length of the branch without the bld so we
can easily choose the right branch length. */
int branch_length = get_attr_length (insn);
if (! register_operand (operands[2], QImode))
branch_length -= 2;
output_asm_insn(\"bld %Z3,%Y2\", operands); output_asm_insn(\"bld %Z3,%Y2\", operands);
if (get_attr_length (insn) == 2) if (branch_length == 2)
return \"b%d1 %l0\"; return \"b%d1 %l0\";
else if (get_attr_length (insn) == 4) else if (branch_length == 4)
return \"b%d1 %l0:16\"; return \"b%d1 %l0:16\";
else else
return \"b%g1 %L0\;jmp @%l0\;%L0:\"; return \"b%g1 %L0\;jmp @%l0\;%L0:\";
}" }"
[(set_attr "type" "branch") [(set_attr "type" "bcs")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
;; BLD and BST patterns ;; BLD and BST patterns
......
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