mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-06 09:17:02 +08:00
mcore-protos.h (mcore_r15_operand_p): Declare.
* 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. From-SVN: r71330
This commit is contained in:
parent
70b160738b
commit
f0f4da3220
@ -1,3 +1,26 @@
|
||||
2003-09-12 Richard Sandiford <rsandifo@redhat.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2003-09-11 Mike Stump <mrs@apple.com>
|
||||
|
||||
* c-lex.c (fe_file_change): Don't transform to_line with SOURCE_LINE.
|
||||
|
@ -65,6 +65,8 @@ extern void mcore_print_operand_address PARAMS ((FILE *, rtx));
|
||||
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));
|
||||
@ -72,7 +74,6 @@ extern int mcore_arith_S_operand PARAMS ((rtx));
|
||||
#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));
|
||||
|
@ -1270,7 +1270,17 @@ mcore_output_move (insn, operands, mode)
|
||||
if (GET_CODE (XEXP (src, 0)) == LABEL_REF)
|
||||
return "lrw\t%0,[%1]"; /* a-R */
|
||||
else
|
||||
return "ldw\t%0,%1"; /* r-m */
|
||||
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)
|
||||
{
|
||||
@ -1291,100 +1301,21 @@ mcore_output_move (insn, operands, mode)
|
||||
return "lrw\t%0, %1"; /* Into the literal pool. */
|
||||
}
|
||||
else if (GET_CODE (dst) == MEM) /* m-r */
|
||||
return "stw\t%1,%0";
|
||||
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 ();
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
@ -3064,36 +2995,53 @@ mcore_reorg ()
|
||||
}
|
||||
|
||||
|
||||
/* 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 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. */
|
||||
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;
|
||||
{
|
||||
enum reg_class new_class;
|
||||
if (reg_class_subset_p (LRW_REGS, class) && !mcore_r15_operand_p (x))
|
||||
return LRW_REGS;
|
||||
|
||||
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;
|
||||
return class;
|
||||
}
|
||||
|
||||
/* Tell me if a pair of reg/subreg rtx's actually refer to the same
|
||||
|
@ -603,7 +603,8 @@ extern const enum reg_class reg_class_from_letter[];
|
||||
/* 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
|
||||
#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.
|
||||
|
@ -1226,101 +1226,20 @@
|
||||
{
|
||||
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"))]
|
||||
[(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))
|
||||
&& ! (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))"
|
||||
|| register_operand (operands[1], SImode))"
|
||||
"* return mcore_output_move (insn, operands, SImode);"
|
||||
[(set_attr "type" "move,move,move,move,move,move,load,load,store")])
|
||||
[(set_attr "type" "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" ""))]
|
||||
@ -1338,73 +1257,17 @@
|
||||
{
|
||||
rtx reg = gen_reg_rtx (SImode);
|
||||
emit_insn (gen_movsi (reg, operands[1]));
|
||||
operands[1] = gen_rtx (SUBREG, HImode, reg, 0);
|
||||
operands[1] = gen_lowpart (HImode, reg);
|
||||
}
|
||||
}")
|
||||
|
||||
(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"))]
|
||||
[(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))
|
||||
&& (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")])
|
||||
|| register_operand (operands[1], HImode))"
|
||||
"* return mcore_output_move (insn, operands, HImode);"
|
||||
[(set_attr "type" "move,move,move,move,load,store")])
|
||||
|
||||
;;
|
||||
;; QImode
|
||||
@ -1427,67 +1290,18 @@
|
||||
{
|
||||
rtx reg = gen_reg_rtx (SImode);
|
||||
emit_insn (gen_movsi (reg, operands[1]));
|
||||
operands[1] = gen_rtx (SUBREG, QImode, reg, 0);
|
||||
operands[1] = gen_lowpart (QImode, reg);
|
||||
}
|
||||
}")
|
||||
|
||||
(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"))]
|
||||
[(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))
|
||||
&& (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")])
|
||||
|| register_operand (operands[1], QImode))"
|
||||
"* return mcore_output_move (insn, operands, QImode);"
|
||||
[(set_attr "type" "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
|
||||
|
||||
@ -1502,15 +1316,12 @@
|
||||
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)
|
||||
&& ! CONST_OK_FOR_N (INTVAL (operands[1])))
|
||||
{
|
||||
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));
|
||||
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;
|
||||
}
|
||||
}")
|
||||
|
Loading…
Reference in New Issue
Block a user