This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Some mcore fixes
- From: Richard Sandiford <rsandifo at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: 02 Sep 2003 17:20:44 +0100
- Subject: Some mcore fixes
No-one seems to have objected in principle to:
http://gcc.gnu.org/ml/gcc/2003-08/msg01412.html
so I thought I'd get the patch ready for submission. This first
part deals with mcore fallout.
The regressions I mentioned were due to movdi not handling certain
constants during reload. They are fixed with the movdi hunk below.
I noticed there were a few existing failures due to other
move-related issues:
- When the source is a non-inlineable constant, movhi and movqi
use an SImode temporary. As the final step, they move the lowpart
of that temporary into operands[0].
A lot of little-endian failures were due to this code using
gen_rtx (SUBREG, ..., 0) rather than an endian-aware function
like gen_lowpart.
- The move patterns take elaborate countermeasures if reload tries
to move a constant into r15. But these measures only work for
CONST_INTs, not for symbolic constants. It seems simpler to
admit that certain constants can't be reloaded directly into
r15 and define SECONDARY_RELOAD_CLASS accordingly.
(While this doesn't fix an observed failure after the reload
change linked above, it could certainly trigger in principle.)
Also, the move patterns can handle r15 <- P-type constants just fine.
There doesn't seem any need to deal with them differently from other
reg <- P moves.
Patch tested on mcore-elf {-mlittle-endian,-mbig-endian} (without the
reload changedlinked above). Number of check-gcc failures goes down
from 615 to 444. OK to install?
Richard
* config/mcore/mcore-protos.h (mcore_r15_operand_p): Declare.
(mcore_secondary_reload_class): Declare.
(mcore_output_inline_const_forced): Remove.
* config/mcore/mcore.md (movsi): Remove the code that forced
non-inlineable constants into a register if the target was r15
or the stack pointer. Remove constant restrictions from the main
define_insn. Remove r <- I, r <- M and r <- N alternatives in favor
of an r <- P alternative. Remove fallback define_insn for reload.
(movhi, movqi): Use gen_lowpart rather than gen_SUBREG. Remove reload
define_insn. Use mcore_output_move in the remaining define_insn.
Adjust condition and constraints in the way as for movsi.
(movdi): Always split unacceptable constants into two. Use
simplify_gen_subreg instead of operand_subword{,_force}.
* config/mcore/mcore.c (mcore_output_inline_const_forced): Remove.
(mcore_output_move): Support HImode and QImode moves as well.
(mcore_m15_operand_p): New function.
(mcore_reload_class): Use it to detect cases where LRW_REGS are better.
(mcore_secondary_reload_class): New function.
* config/mcore/mcore.h (SECONDARY_RELOAD_CLASS): Redefine in
terms of mcore_secondary_reload_class.
Index: config/mcore/mcore-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mcore/mcore-protos.h,v
retrieving revision 1.12
diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.12 mcore-protos.h
*** config/mcore/mcore-protos.h 14 May 2003 07:29:50 -0000 1.12
--- config/mcore/mcore-protos.h 1 Sep 2003 09:29:46 -0000
*************** extern void mcore_print_operand_
*** 65,70 ****
--- 64,71 ----
extern void mcore_print_operand PARAMS ((FILE *, rtx, int));
extern rtx mcore_gen_compare_reg PARAMS ((RTX_CODE));
extern int mcore_symbolic_address_p PARAMS ((rtx));
+ extern bool mcore_r15_operand_p PARAMS ((rtx));
+ extern enum reg_class mcore_secondary_reload_class PARAMS ((enum reg_class, enum machine_mode, rtx));
extern enum reg_class mcore_reload_class PARAMS ((rtx, enum reg_class));
extern int mcore_is_same_reg PARAMS ((rtx, rtx));
extern int mcore_arith_S_operand PARAMS ((rtx));
*************** extern int mcore_arith_S_operan
*** 72,78 ****
#ifdef HAVE_MACHINE_MODES
extern const char * mcore_output_move PARAMS ((rtx, rtx *, enum machine_mode));
extern const char * mcore_output_movedouble PARAMS ((rtx *, enum machine_mode));
- extern const char * mcore_output_inline_const_forced PARAMS ((rtx, rtx *, enum machine_mode));
extern int mcore_arith_reg_operand PARAMS ((rtx, enum machine_mode));
extern int mcore_general_movsrc_operand PARAMS ((rtx, enum machine_mode));
extern int mcore_general_movdst_operand PARAMS ((rtx, enum machine_mode));
--- 73,78 ----
Index: config/mcore/mcore.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mcore/mcore.md,v
retrieving revision 1.11
diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.11 mcore.md
*** config/mcore/mcore.md 3 Jul 2003 12:34:07 -0000 1.11
--- config/mcore/mcore.md 1 Sep 2003 09:29:47 -0000
*************** (define_expand "movsi"
*** 1226,1326 ****
{
if (GET_CODE (operands[0]) == MEM)
operands[1] = force_reg (SImode, operands[1]);
- else if (CONSTANT_P (operands[1])
- && (GET_CODE (operands[1]) != CONST_INT
- || ( ! CONST_OK_FOR_I (INTVAL (operands[1]))
- && ! CONST_OK_FOR_M (INTVAL (operands[1]))
- && ! CONST_OK_FOR_N (INTVAL (operands[1]))
- && (! TARGET_HARDLIT ||
- ! mcore_const_ok_for_inline (INTVAL (operands[1])))))
- && ! reload_completed
- && ! reload_in_progress
- && GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER
- && (REGNO (operands[0]) == STACK_POINTER_REGNUM
- || REGNO (operands[0]) == LK_REG))
- operands[1] = force_reg (SImode, operands[1]);
}")
- ;;; Must put a/i before r/r so that it will be preferred when the dest is
- ;;; a hard register. Must put a/R before r/m.
- ;;; DO WE NEED a/i ANYMORE?
-
(define_insn ""
! [(set (match_operand:SI 0 "mcore_general_movdst_operand" "=r,r,r,a,r,r,a,r,m")
! (match_operand:SI 1 "mcore_general_movsrc_operand" "I,M,N,i,r,c,R,m,r"))]
"(register_operand (operands[0], SImode)
! || register_operand (operands[1], SImode))
! && ! (CONSTANT_P (operands[1])
! && (GET_CODE (operands[1]) != CONST_INT
! || ( ! CONST_OK_FOR_I (INTVAL (operands[1]))
! && ! CONST_OK_FOR_M (INTVAL (operands[1]))
! && ! CONST_OK_FOR_N (INTVAL (operands[1]))))
! && GET_CODE (operands[0]) == REG
! && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER
! && (REGNO (operands[0]) == STACK_POINTER_REGNUM
! || REGNO (operands[0]) == LK_REG))"
"* return mcore_output_move (insn, operands, SImode);"
! [(set_attr "type" "move,move,move,move,move,move,load,load,store")])
!
! ;; This is to work around a bug in reload.
! (define_insn ""
! [(set (match_operand:SI 0 "register_operand" "=r")
! (match_operand:SI 1 "immediate_operand" "i"))]
! "((reload_in_progress || reload_completed)
! && CONSTANT_P (operands[1])
! && GET_CODE (operands[1]) == CONST_INT
! && ! CONST_OK_FOR_I (INTVAL (operands[1]))
! && ! CONST_OK_FOR_M (INTVAL (operands[1]))
! && ! CONST_OK_FOR_N (INTVAL (operands[1]))
! && GET_CODE (operands[0]) == REG
! && REGNO (operands[0]) == LK_REG)"
! "* return mcore_output_inline_const_forced (insn, operands, SImode);"
! [(set_attr "type" "load")])
- ;; (define_expand "reload_insi"
- ;; [(parallel [(match_operand:SI 0 "register_operand" "=r")
- ;; (match_operand:SI 1 "general_operand" "")
- ;; (match_operand:DI 2 "register_operand" "=&r")])]
- ;; ""
- ;; "
- ;; {
- ;; if (CONSTANT_P (operands[1])
- ;; && GET_CODE (operands[1]) == CONST_INT
- ;; && ! CONST_OK_FOR_I (INTVAL (operands[1]))
- ;; && ! CONST_OK_FOR_M (INTVAL (operands[1]))
- ;; && ! CONST_OK_FOR_N (INTVAL (operands[1]))
- ;; && GET_CODE (operands[0]) == REG
- ;; && (REGNO (operands[0]) == STACK_POINTER_REGNUM
- ;; || REGNO (operands[0]) == LK_REG))
- ;; {
- ;; rtx tmp;
- ;;
- ;; if ( REGNO (operands[2]) == REGNO (operands[0])
- ;; || REGNO (operands[2]) == STACK_POINTER_REGNUM
- ;; || REGNO (operands[2]) == LK_REG)
- ;; tmp = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
- ;; else
- ;; tmp = gen_rtx_REG (SImode, REGNO (operands[2]));
- ;;
- ;; emit_insn (gen_movsi (tmp, operands[1]));
- ;; emit_insn (gen_movsi (operands[0], tmp));
- ;; DONE;
- ;; }
- ;; emit_insn (gen_movsi (operands[0], operands[1]));
- ;; DONE;
- ;; }"
- ;; )
-
-
-
;;
;; HImode
;;
- ;;; ??? This isn't guaranteed to work. It should be more like the SImode
- ;;; patterns.
-
(define_expand "movhi"
[(set (match_operand:HI 0 "general_operand" "")
(match_operand:HI 1 "general_operand" ""))]
--- 1226,1245 ----
{
if (GET_CODE (operands[0]) == MEM)
operands[1] = force_reg (SImode, operands[1]);
}")
(define_insn ""
! [(set (match_operand:SI 0 "mcore_general_movdst_operand" "=r,r,a,r,a,r,m")
! (match_operand:SI 1 "mcore_general_movsrc_operand" "r,P,i,c,R,m,r"))]
"(register_operand (operands[0], SImode)
! || register_operand (operands[1], SImode))"
"* return mcore_output_move (insn, operands, SImode);"
! [(set_attr "type" "move,move,move,move,load,load,store")])
;;
;; HImode
;;
(define_expand "movhi"
[(set (match_operand:HI 0 "general_operand" "")
(match_operand:HI 1 "general_operand" ""))]
*************** (define_expand "movhi"
*** 1338,1410 ****
{
rtx reg = gen_reg_rtx (SImode);
emit_insn (gen_movsi (reg, operands[1]));
! operands[1] = gen_rtx (SUBREG, HImode, reg, 0);
}
}")
(define_insn ""
! [(set (match_operand:HI 0 "mcore_general_movdst_operand" "=r,r,r,r,r,r,m")
! (match_operand:HI 1 "mcore_general_movsrc_operand" "r,I,M,N,c,m,r"))]
"(register_operand (operands[0], HImode)
! || register_operand (operands[1], HImode))
! && (GET_CODE (operands[1]) != CONST_INT
! || CONST_OK_FOR_M (INTVAL (operands[1]))
! || CONST_OK_FOR_N (INTVAL (operands[1]))
! || CONST_OK_FOR_I (INTVAL (operands[1])))"
! "@
! mov %0,%1
! movi %0,%1
! bgeni %0,%P1
! bmaski %0,%N1
! mvc %0
! ld.h %0,%1
! st.h %1,%0"
! [(set_attr "type" "move,move,move,move,move,load,store")])
!
! ;; Like movhi, but the const_int source can't be synthesized in
! ;; a single-instruction. Fall back to the same things that
! ;; are done for movsi in such cases. Presumes that we can
! ;; modify any parts of the register that we wish.
!
! (define_insn ""
! [(set (match_operand:HI 0 "mcore_general_movdst_operand" "=r,a")
! (match_operand:HI 1 "const_int_operand" "P,i"))]
! "GET_CODE (operands[1]) == CONST_INT
! && INTVAL (operands[1]) > 127 && INTVAL (operands[1]) < 65536"
! "*
! {
! if (GET_CODE (operands[0])== REG && REGNO (operands[0]) == 15
! && !mcore_const_ok_for_inline (INTVAL (operands[1])))
! {
! /* mcore_output_move would generate lrw r15 -- a forbidden combo */
! return mcore_output_inline_const_forced (insn, operands, SImode);
! }
! else
! return mcore_output_move (insn, operands, SImode);
! }"
! [(set_attr "type" "move")])
!
!
! ;; if we're still looking around for things to use, here's a last
! ;; ditch effort that just calls the move. We only let this happen
! ;; if we're in the reload pass.
! ;;
! (define_insn ""
! [(set (match_operand:HI 0 "mcore_general_movdst_operand" "=r,a")
! (match_operand:HI 1 "const_int_operand" "P,i"))]
! "reload_in_progress || reload_completed"
! "*
! {
! if (GET_CODE (operands[0])== REG && REGNO (operands[0]) == 15
! && !mcore_const_ok_for_inline (INTVAL (operands[1])))
! {
! /* mcore_output_move would generate lrw r15 -- a forbidden combo */
! return mcore_output_inline_const_forced (insn, operands, SImode);
! }
! else
! return mcore_output_move (insn, operands, HImode);
! }"
! [(set_attr "type" "move")])
;;
;; QImode
--- 1257,1273 ----
{
rtx reg = gen_reg_rtx (SImode);
emit_insn (gen_movsi (reg, operands[1]));
! operands[1] = gen_lowpart (HImode, reg);
}
}")
(define_insn ""
! [(set (match_operand:HI 0 "mcore_general_movdst_operand" "=r,r,a,r,r,m")
! (match_operand:HI 1 "mcore_general_movsrc_operand" "r,P,i,c,m,r"))]
"(register_operand (operands[0], HImode)
! || register_operand (operands[1], HImode))"
! "* return mcore_output_move (insn, operands, HImode);"
! [(set_attr "type" "move,move,move,move,load,store")])
;;
;; QImode
*************** (define_expand "movqi"
*** 1427,1493 ****
{
rtx reg = gen_reg_rtx (SImode);
emit_insn (gen_movsi (reg, operands[1]));
! operands[1] = gen_rtx (SUBREG, QImode, reg, 0);
}
}")
(define_insn ""
! [(set (match_operand:QI 0 "mcore_general_movdst_operand" "=r,r,r,r,r,r,m")
! (match_operand:QI 1 "mcore_general_movsrc_operand" "r,I,M,N,c,m,r"))]
"(register_operand (operands[0], QImode)
! || register_operand (operands[1], QImode))
! && (GET_CODE (operands[1]) != CONST_INT
! || CONST_OK_FOR_M (INTVAL (operands[1]))
! || CONST_OK_FOR_N (INTVAL (operands[1]))
! || CONST_OK_FOR_I (INTVAL (operands[1])))"
! "@
! mov %0,%1
! movi %0,%1
! bgeni %0,%P1
! bmaski %0,%N1
! mvc %0
! ld.b %0,%1
! st.b %1,%0"
! [(set_attr "type" "move,move,move,move,move,load,store")])
- ;; cover the case where the constant is 128..255; this isn't handled
- ;; in the above case. We could if we wanted to mess with adding a
- ;; new constraint class like M,N,I.
- (define_insn ""
- [(set (match_operand:QI 0 "mcore_general_movdst_operand" "=r")
- (match_operand:QI 1 "const_int_operand" ""))]
- "GET_CODE (operands[1]) == CONST_INT
- && INTVAL (operands[1]) > 127 && INTVAL (operands[1]) < 256"
- "*
- {
- /* have a constant in range 128..255; have to do 2 insns; we can
- * do this with a movi followed by a bseti
- */
- operands[2] = GEN_INT (INTVAL (operands[1]) & 0x7f);
- return \"movi\\t%0,%2\;bseti\\t%0,7\";
- }"
- [(set_attr "type" "move")])
-
- ;; if we're still looking around for things to use, here's a last
- ;; ditch effort that just calls the move. We only let this happen
- ;; if we're in the reload pass.
- ;;
- (define_insn ""
- [(set (match_operand:QI 0 "mcore_general_movdst_operand" "=r,a")
- (match_operand:QI 1 "const_int_operand" "P,i"))]
- "(reload_in_progress || reload_completed)"
- "*
- {
- if (GET_CODE (operands[0])== REG && REGNO (operands[0]) == 15
- && ! mcore_const_ok_for_inline (INTVAL (operands[1])))
- {
- /* mcore_output_move would generate lrw r15 -- a forbidden combo */
- return mcore_output_inline_const_forced (insn, operands, SImode);
- }
- else
- return mcore_output_move (insn, operands, QImode);
- }"
- [(set_attr "type" "move")])
;; DImode
--- 1290,1307 ----
{
rtx reg = gen_reg_rtx (SImode);
emit_insn (gen_movsi (reg, operands[1]));
! operands[1] = gen_lowpart (QImode, reg);
}
}")
(define_insn ""
! [(set (match_operand:QI 0 "mcore_general_movdst_operand" "=r,r,a,r,r,m")
! (match_operand:QI 1 "mcore_general_movsrc_operand" "r,P,i,c,m,r"))]
"(register_operand (operands[0], QImode)
! || register_operand (operands[1], QImode))"
! "* return mcore_output_move (insn, operands, QImode);"
! [(set_attr "type" "move,move,move,move,load,store")])
;; DImode
*************** (define_expand "movdi"
*** 1502,1516 ****
else if (GET_CODE (operands[1]) == CONST_INT
&& ! CONST_OK_FOR_I (INTVAL (operands[1]))
&& ! CONST_OK_FOR_M (INTVAL (operands[1]))
! && ! CONST_OK_FOR_N (INTVAL (operands[1]))
! && ! reload_completed
! && ! reload_in_progress
! && GET_CODE (operands[0]) == REG)
{
! emit_move_insn (operand_subword (operands[0], 0, 1, DImode),
! operand_subword_force (operands[1], 0, DImode));
! emit_move_insn (operand_subword (operands[0], 1, 1, DImode),
! operand_subword_force (operands[1], 1, DImode));
DONE;
}
}")
--- 1316,1327 ----
else if (GET_CODE (operands[1]) == CONST_INT
&& ! CONST_OK_FOR_I (INTVAL (operands[1]))
&& ! CONST_OK_FOR_M (INTVAL (operands[1]))
! && ! CONST_OK_FOR_N (INTVAL (operands[1])))
{
! int i;
! for (i = 0; i < UNITS_PER_WORD * 2; i += UNITS_PER_WORD)
! emit_move_insn (simplify_gen_subreg (SImode, operands[0], DImode, i),
! simplify_gen_subreg (SImode, operands[1], DImode, i));
DONE;
}
}")
Index: config/mcore/mcore.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mcore/mcore.c,v
retrieving revision 1.50
diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.50 mcore.c
*** config/mcore/mcore.c 26 Jul 2003 11:27:40 -0000 1.50
--- config/mcore/mcore.c 1 Sep 2003 09:29:48 -0000
*************** mcore_output_move (insn, operands, mode)
*** 1270,1276 ****
if (GET_CODE (XEXP (src, 0)) == LABEL_REF)
return "lrw\t%0,[%1]"; /* a-R */
else
! return "ldw\t%0,%1"; /* r-m */
}
else if (GET_CODE (src) == CONST_INT)
{
--- 1270,1286 ----
if (GET_CODE (XEXP (src, 0)) == LABEL_REF)
return "lrw\t%0,[%1]"; /* a-R */
else
! switch (GET_MODE (src)) /* r-m */
! {
! case SImode:
! return "ldw\t%0,%1";
! case HImode:
! return "ld.h\t%0,%1";
! case QImode:
! return "ld.b\t%0,%1";
! default:
! abort ();
! }
}
else if (GET_CODE (src) == CONST_INT)
{
*************** mcore_output_move (insn, operands, mode)
*** 1291,1390 ****
return "lrw\t%0, %1"; /* Into the literal pool. */
}
else if (GET_CODE (dst) == MEM) /* m-r */
! return "stw\t%1,%0";
abort ();
}
- /* Outputs a constant inline -- regardless of the cost.
- Useful for things where we've gotten into trouble and think we'd
- be doing an lrw into r15 (forbidden). This lets us get out of
- that pickle even after register allocation. */
-
- const char *
- mcore_output_inline_const_forced (insn, operands, mode)
- rtx insn ATTRIBUTE_UNUSED;
- rtx operands[];
- enum machine_mode mode ATTRIBUTE_UNUSED;
- {
- unsigned long value = INTVAL (operands[1]);
- unsigned long ovalue = value;
- struct piece
- {
- int low;
- int shift;
- }
- part[6];
- int i;
-
- if (mcore_const_ok_for_inline (value))
- return output_inline_const (SImode, operands);
-
- for (i = 0; (unsigned) i < ARRAY_SIZE (part); i++)
- {
- part[i].shift = 0;
- part[i].low = (value & 0x1F);
- value -= part[i].low;
-
- if (mcore_const_ok_for_inline (value))
- break;
- else
- {
- value >>= 5;
- part[i].shift = 5;
-
- while ((value & 1) == 0)
- {
- part[i].shift++;
- value >>= 1;
- }
-
- if (mcore_const_ok_for_inline (value))
- break;
- }
- }
-
- /* 5 bits per iteration, a maximum of 5 times == 25 bits and leaves
- 7 bits left in the constant -- which we know we can cover with
- a movi. The final value can't be zero otherwise we'd have stopped
- in the previous iteration. */
- if (value == 0 || ! mcore_const_ok_for_inline (value))
- abort ();
-
- /* Now, work our way backwards emitting the constant. */
-
- /* Emit the value that remains -- it will be nonzero. */
- operands[1] = GEN_INT (value);
- output_asm_insn (output_inline_const (SImode, operands), operands);
-
- while (i >= 0)
- {
- /* Shift anything we've already loaded. */
- if (part[i].shift)
- {
- operands[2] = GEN_INT (part[i].shift);
- output_asm_insn ("lsli %0,%2", operands);
- value <<= part[i].shift;
- }
-
- /* Add anything we need into the low 5 bits. */
- if (part[i].low != 0)
- {
- operands[2] = GEN_INT (part[i].low);
- output_asm_insn ("addi %0,%2", operands);
- value += part[i].low;
- }
-
- i--;
- }
-
- if (value != ovalue) /* sanity */
- abort ();
-
- /* We've output all the instructions. */
- return "";
- }
-
/* Return a sequence of instructions to perform DI or DF move.
Since the MCORE cannot move a DI or DF in one instruction, we have
to take care when we see overlapping source and dest registers. */
--- 1301,1321 ----
return "lrw\t%0, %1"; /* Into the literal pool. */
}
else if (GET_CODE (dst) == MEM) /* m-r */
! switch (GET_MODE (dst))
! {
! case SImode:
! return "stw\t%1,%0";
! case HImode:
! return "st.h\t%1,%0";
! case QImode:
! return "st.b\t%1,%0";
! default:
! abort ();
! }
abort ();
}
/* Return a sequence of instructions to perform DI or DF move.
Since the MCORE cannot move a DI or DF in one instruction, we have
to take care when we see overlapping source and dest registers. */
*************** mcore_reorg ()
*** 3064,3099 ****
}
! /* Return the reg_class to use when reloading the rtx X into the class
! CLASS. */
! /* If the input is (PLUS REG CONSTANT) representing a stack slot address,
! then we want to restrict the class to LRW_REGS since that ensures that
! will be able to safely load the constant.
! If the input is a constant that should be loaded with mvir1, then use
! ONLYR1_REGS.
! ??? We don't handle the case where we have (PLUS REG CONSTANT) and
! the constant should be loaded with mvir1, because that can lead to cases
! where an instruction needs two ONLYR1_REGS reloads. */
enum reg_class
mcore_reload_class (x, class)
rtx x;
enum reg_class class;
{
! enum reg_class new_class;
!
! if (class == GENERAL_REGS && CONSTANT_P (x)
! && (GET_CODE (x) != CONST_INT
! || ( ! CONST_OK_FOR_I (INTVAL (x))
! && ! CONST_OK_FOR_M (INTVAL (x))
! && ! CONST_OK_FOR_N (INTVAL (x)))))
! new_class = LRW_REGS;
! else
! new_class = class;
! return new_class;
}
/* Tell me if a pair of reg/subreg rtx's actually refer to the same
--- 2954,3006 ----
}
! /* Return true if X is something that can be moved directly into r15. */
! bool
! mcore_r15_operand_p (x)
! rtx x;
! {
! switch (GET_CODE (x))
! {
! case CONST_INT:
! return mcore_const_ok_for_inline (INTVAL (x));
! case REG:
! case SUBREG:
! case MEM:
! return 1;
! default:
! return 0;
! }
! }
!
! /* Implement SECONDARY_RELOAD_CLASS. If CLASS contains r15, and we can't
! directly move X into it, use r1-r14 as a temporary. */
! enum reg_class
! mcore_secondary_reload_class (class, mode, x)
! enum reg_class class;
! enum machine_mode mode ATTRIBUTE_UNUSED;
! rtx x;
! {
! if (TEST_HARD_REG_BIT (reg_class_contents[class], 15)
! && !mcore_r15_operand_p (x))
! return LRW_REGS;
! return NO_REGS;
! }
!
! /* Return the reg_class to use when reloading the rtx X into the class
! CLASS. If X is too complex to move directly into r15, prefer to
! use LRW_REGS instead. */
enum reg_class
mcore_reload_class (x, class)
rtx x;
enum reg_class class;
{
! if (reg_class_subset_p (LRW_REGS, class) && !mcore_r15_operand_p (x))
! return LRW_REGS;
! return class;
}
/* Tell me if a pair of reg/subreg rtx's actually refer to the same
Index: config/mcore/mcore.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mcore/mcore.h,v
retrieving revision 1.54
diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.54 mcore.h
*** config/mcore/mcore.h 21 Aug 2003 17:27:24 -0000 1.54
--- config/mcore/mcore.h 1 Sep 2003 09:29:48 -0000
*************** #define PREFERRED_RELOAD_CLASS(X, CLASS)
*** 603,609 ****
/* Return the register class of a scratch register needed to copy IN into
or out of a register in CLASS in MODE. If it can be done directly,
NO_REGS is returned. */
! #define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) NO_REGS
/* Return the maximum number of consecutive registers
needed to represent mode MODE in a register of class CLASS.
--- 603,610 ----
/* Return the register class of a scratch register needed to copy IN into
or out of a register in CLASS in MODE. If it can be done directly,
NO_REGS is returned. */
! #define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) \
! mcore_secondary_reload_class (CLASS, MODE, X)
/* Return the maximum number of consecutive registers
needed to represent mode MODE in a register of class CLASS.