Commit 633e4eb4 by Bob Wilson Committed by Bob Wilson

xtensa-protos.h (smalloffset_double_mem_p): Delete.

        * config/xtensa/xtensa-protos.h (smalloffset_double_mem_p): Delete.
        (xtensa_split_operand_pair): New proto.
        * config/xtensa/xtensa.c (move_operand): Handle DFmode and DImode.
        (smalloffset_double_mem_p): Delete.
        (gen_float_relational, printx, print_operand, xtensa_va_arg):
        Fix whitespace.
        (xtensa_split_operand_pair): New.
        (xtensa_dbx_register_number): Fix formatting.
        * config/xtensa/xtensa.h (EXTRA_CONSTRAINT): Remove 'S' constraint.
        * config/xtensa/xtensa.md (movdi, movdf): Force constants to memory
        instead of splitting them into single-word moves.  Remove unnecessary
        checks for reload_in_progress and reload_completed.
        (movdi_internal, movdf_internal): Change to post-reload split patterns.
        Add constraints to allow constant operands.
        (movsf_internal): Allow CONST_INT operands.

From-SVN: r67215
parent 358bdeee
2003-05-28 Bob Wilson <bob.wilson@acm.org>
* config/xtensa/xtensa-protos.h (smalloffset_double_mem_p): Delete.
(xtensa_split_operand_pair): New proto.
* config/xtensa/xtensa.c (move_operand): Handle DFmode and DImode.
(smalloffset_double_mem_p): Delete.
(gen_float_relational, printx, print_operand, xtensa_va_arg):
Fix whitespace.
(xtensa_split_operand_pair): New.
(xtensa_dbx_register_number): Fix formatting.
* config/xtensa/xtensa.h (EXTRA_CONSTRAINT): Remove 'S' constraint.
* config/xtensa/xtensa.md (movdi, movdf): Force constants to memory
instead of splitting them into single-word moves. Remove unnecessary
checks for reload_in_progress and reload_completed.
(movdi_internal, movdf_internal): Change to post-reload split patterns.
Add constraints to allow constant operands.
(movsf_internal): Allow CONST_INT operands.
2003-05-27 Danny Smith <dannysmith@users.sourceforge.net>
* config.gcc (i[34567]86-*-mingw32*): Add host makefile
......
......@@ -54,7 +54,6 @@ extern int ubranch_operand PARAMS ((rtx, enum machine_mode));
extern int call_insn_operand PARAMS ((rtx, enum machine_mode));
extern int move_operand PARAMS ((rtx, enum machine_mode));
extern int smalloffset_mem_p PARAMS ((rtx));
extern int smalloffset_double_mem_p PARAMS ((rtx));
extern int constantpool_address_p PARAMS ((rtx));
extern int constantpool_mem_p PARAMS ((rtx));
extern int const_float_1_operand PARAMS ((rtx, enum machine_mode));
......@@ -67,6 +66,7 @@ extern void xtensa_expand_conditional_branch PARAMS ((rtx *, enum rtx_code));
extern int xtensa_expand_conditional_move PARAMS ((rtx *, int));
extern int xtensa_expand_scc PARAMS ((rtx *));
extern int xtensa_expand_block_move PARAMS ((rtx *));
extern void xtensa_split_operand_pair PARAMS ((rtx *, enum machine_mode));
extern int xtensa_emit_move_sequence PARAMS ((rtx *, enum machine_mode));
extern bool xtensa_copy_incoming_a7 PARAMS ((rtx *, enum machine_mode));
extern void xtensa_emit_block_move PARAMS ((rtx *, rtx *, int));
......
......@@ -599,9 +599,20 @@ move_operand (op, mode)
|| memory_operand (op, mode))
return TRUE;
if (mode == SFmode)
switch (mode)
{
case DFmode:
case SFmode:
return TARGET_CONST16 && CONSTANT_P (op);
case DImode:
case SImode:
if (TARGET_CONST16)
return CONSTANT_P (op);
/* fall through */
case HImode:
case QImode:
/* Accept CONSTANT_P_RTX, since it will be gone by CSE1 and
result in 0/1. */
if (GET_CODE (op) == CONSTANT_P_RTX)
......@@ -609,9 +620,11 @@ move_operand (op, mode)
if (GET_CODE (op) == CONST_INT && xtensa_simm12b (INTVAL (op)))
return TRUE;
break;
if (mode == SImode)
return TARGET_CONST16 && CONSTANT_P (op);
default:
break;
}
return FALSE;
}
......@@ -641,16 +654,6 @@ smalloffset_mem_p (op)
int
smalloffset_double_mem_p (op)
rtx op;
{
if (!smalloffset_mem_p (op))
return FALSE;
return smalloffset_mem_p (adjust_address (op, GET_MODE (op), 4));
}
int
constantpool_address_p (addr)
rtx addr;
{
......@@ -1207,6 +1210,53 @@ xtensa_expand_scc (operands)
}
/* Split OP[1] into OP[2,3] and likewise for OP[0] into OP[0,1]. MODE is
for the output, i.e., the input operands are twice as big as MODE. */
void
xtensa_split_operand_pair (operands, mode)
rtx operands[4];
enum machine_mode mode;
{
switch (GET_CODE (operands[1]))
{
case REG:
operands[3] = gen_rtx_REG (mode, REGNO (operands[1]) + 1);
operands[2] = gen_rtx_REG (mode, REGNO (operands[1]));
break;
case MEM:
operands[3] = adjust_address (operands[1], mode, GET_MODE_SIZE (mode));
operands[2] = adjust_address (operands[1], mode, 0);
break;
case CONST_INT:
case CONST_DOUBLE:
split_double (operands[1], &operands[2], &operands[3]);
break;
default:
abort ();
}
switch (GET_CODE (operands[0]))
{
case REG:
operands[1] = gen_rtx_REG (mode, REGNO (operands[0]) + 1);
operands[0] = gen_rtx_REG (mode, REGNO (operands[0]));
break;
case MEM:
operands[1] = adjust_address (operands[0], mode, GET_MODE_SIZE (mode));
operands[0] = adjust_address (operands[0], mode, 0);
break;
default:
abort ();
}
}
/* Emit insns to move operands[1] into operands[0].
Return 1 if we have written out everything that needs to be done to
do the move. Otherwise, return 0 and the caller will emit the move
......@@ -1659,15 +1709,18 @@ xtensa_dbx_register_number (regno)
{
int first = -1;
if (GP_REG_P (regno)) {
if (GP_REG_P (regno))
{
regno -= GP_REG_FIRST;
first = 0;
}
else if (BR_REG_P (regno)) {
else if (BR_REG_P (regno))
{
regno -= BR_REG_FIRST;
first = 16;
}
else if (FP_REG_P (regno)) {
else if (FP_REG_P (regno))
{
regno -= FP_REG_FIRST;
/* The current numbering convention is that TIE registers are
numbered in libcc order beginning with 256. We can't guarantee
......
......@@ -691,7 +691,6 @@ extern enum reg_class xtensa_char_to_class[256];
operand types.
R = memory that can be accessed with a 4-bit unsigned offset
S = memory where the second word can be addressed with a 4-bit offset
T = memory in a constant pool (addressable with a pc-relative load)
U = memory *NOT* in a constant pool
......@@ -713,7 +712,6 @@ extern enum reg_class xtensa_char_to_class[256];
&& reload_in_progress && GET_CODE (OP) == REG \
&& REGNO (OP) >= FIRST_PSEUDO_REGISTER) \
: ((CODE) == 'R') ? smalloffset_mem_p (OP) \
: ((CODE) == 'S') ? smalloffset_double_mem_p (OP) \
: ((CODE) == 'T') ? !TARGET_CONST16 && constantpool_mem_p (OP) \
: ((CODE) == 'U') ? !constantpool_mem_p (OP) \
: FALSE)
......
......@@ -922,83 +922,35 @@
""
"
{
if (CONSTANT_P (operands[1])
&& register_operand (operands[0], DImode))
{
rtx src0, src1, dst0, dst1;
dst0 = operand_subword (operands[0], 0, 1, DImode);
src0 = operand_subword (operands[1], 0, 1, DImode);
dst1 = operand_subword (operands[0], 1, 1, DImode);
src1 = operand_subword (operands[1], 1, 1, DImode);
if (!dst0 || !src0 || !dst1 || !src1)
abort ();
emit_insn (gen_movsi (dst0, src0));
emit_insn (gen_movsi (dst1, src1));
DONE;
}
if (CONSTANT_P (operands[1]) && !TARGET_CONST16)
operands[1] = force_const_mem (DImode, operands[1]);
if (!(reload_in_progress | reload_completed))
{
if (!register_operand (operands[0], DImode)
&& !register_operand (operands[1], DImode))
operands[1] = force_reg (DImode, operands[1]);
if (xtensa_copy_incoming_a7 (operands, DImode))
DONE;
}
}")
(define_insn "movdi_internal"
[(set (match_operand:DI 0 "nonimmed_operand" "=D,D,S,a,a,U")
(match_operand:DI 1 "nonimmed_operand" "d,S,d,r,U,r"))]
(define_insn_and_split "movdi_internal"
[(set (match_operand:DI 0 "nonimmed_operand" "=a,W,a,a,U")
(match_operand:DI 1 "move_operand" "r,i,T,U,r"))]
"register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode)"
"*
"#"
"reload_completed"
[(set (match_dup 0) (match_dup 2))
(set (match_dup 1) (match_dup 3))]
{
rtx dstreg;
switch (which_alternative)
{
case 0: return \"mov.n\\t%0, %1\;mov.n\\t%D0, %D1\";
case 2: return \"%v0s32i.n\\t%1, %0\;s32i.n\\t%D1, %N0\";
case 3: return \"mov\\t%0, %1\;mov\\t%D0, %D1\";
case 5: return \"%v0s32i\\t%1, %0\;s32i\\t%D1, %N0\";
case 1:
case 4:
/* Check if the first half of the destination register is used
in the source address. If so, reverse the order of the loads
so that the source address doesn't get clobbered until it is
no longer needed. */
dstreg = operands[0];
if (GET_CODE (dstreg) == SUBREG)
dstreg = SUBREG_REG (dstreg);
if (GET_CODE (dstreg) != REG)
abort();
if (reg_mentioned_p (dstreg, operands[1]))
{
switch (which_alternative)
{
case 1: return \"%v1l32i.n\\t%D0, %N1\;l32i.n\\t%0, %1\";
case 4: return \"%v1l32i\\t%D0, %N1\;l32i\\t%0, %1\";
}
}
else
{
switch (which_alternative)
xtensa_split_operand_pair (operands, SImode);
if (reg_overlap_mentioned_p (operands[0], operands[3]))
{
case 1: return \"%v1l32i.n\\t%0, %1\;l32i.n\\t%D0, %N1\";
case 4: return \"%v1l32i\\t%0, %1\;l32i\\t%D0, %N1\";
rtx tmp;
tmp = operands[0], operands[0] = operands[1], operands[1] = tmp;
tmp = operands[2], operands[2] = operands[3], operands[3] = tmp;
}
}
}
abort ();
return \"\";
}"
[(set_attr "type" "move,load,store,move,load,store")
(set_attr "mode" "DI")
(set_attr "length" "4,4,4,6,6,6")])
})
;; 32-bit Integer moves
......@@ -1122,7 +1074,7 @@
(define_insn "movsf_internal"
[(set (match_operand:SF 0 "nonimmed_operand" "=f,f,U,D,D,R,a,f,a,W,a,a,U")
(match_operand:SF 1 "move_operand" "f,U,f,d,R,d,r,r,f,F,T,U,r"))]
(match_operand:SF 1 "move_operand" "f,U,f,d,R,d,r,r,f,iF,T,U,r"))]
"((register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode))
&& !(FP_REG_P (xt_true_regnum (operands[0]))
......@@ -1187,82 +1139,36 @@
""
"
{
if (CONSTANT_P (operands[1]))
{
rtx src0, src1, dst0, dst1;
dst0 = operand_subword (operands[0], 0, 1, DFmode);
src0 = operand_subword (operands[1], 0, 1, DFmode);
dst1 = operand_subword (operands[0], 1, 1, DFmode);
src1 = operand_subword (operands[1], 1, 1, DFmode);
if (!dst0 || !src0 || !dst1 || !src1)
abort ();
emit_insn (gen_movsi (dst0, src0));
emit_insn (gen_movsi (dst1, src1));
DONE;
}
if (CONSTANT_P (operands[1]) && !TARGET_CONST16)
operands[1] = force_const_mem (DFmode, operands[1]);
if (!(reload_in_progress | reload_completed))
{
if (!register_operand (operands[0], DFmode)
&& !register_operand (operands[1], DFmode))
operands[1] = force_reg (DFmode, operands[1]);
if (xtensa_copy_incoming_a7 (operands, DFmode))
DONE;
}
}")
(define_insn "movdf_internal"
[(set (match_operand:DF 0 "nonimmed_operand" "=D,D,S,a,a,U")
(match_operand:DF 1 "nonimmed_operand" "d,S,d,r,U,r"))]
(define_insn_and_split "movdf_internal"
[(set (match_operand:DF 0 "nonimmed_operand" "=a,W,a,a,U")
(match_operand:DF 1 "move_operand" "r,iF,T,U,r"))]
"register_operand (operands[0], DFmode)
|| register_operand (operands[1], DFmode)"
"*
"#"
"reload_completed"
[(set (match_dup 0) (match_dup 2))
(set (match_dup 1) (match_dup 3))]
{
rtx dstreg;
switch (which_alternative)
xtensa_split_operand_pair (operands, SFmode);
if (reg_overlap_mentioned_p (operands[0], operands[3]))
{
case 0: return \"mov.n\\t%0, %1\;mov.n\\t%D0, %D1\";
case 2: return \"%v0s32i.n\\t%1, %0\;s32i.n\\t%D1, %N0\";
case 3: return \"mov\\t%0, %1\;mov\\t%D0, %D1\";
case 5: return \"%v0s32i\\t%1, %0\;s32i\\t%D1, %N0\";
case 1:
case 4:
/* Check if the first half of the destination register is used
in the source address. If so, reverse the order of the loads
so that the source address doesn't get clobbered until it is
no longer needed. */
dstreg = operands[0];
if (GET_CODE (dstreg) == SUBREG)
dstreg = SUBREG_REG (dstreg);
if (GET_CODE (dstreg) != REG)
abort ();
if (reg_mentioned_p (dstreg, operands[1]))
{
switch (which_alternative)
{
case 1: return \"%v1l32i.n\\t%D0, %N1\;l32i.n\\t%0, %1\";
case 4: return \"%v1l32i\\t%D0, %N1\;l32i\\t%0, %1\";
}
}
else
{
switch (which_alternative)
{
case 1: return \"%v1l32i.n\\t%0, %1\;l32i.n\\t%D0, %N1\";
case 4: return \"%v1l32i\\t%0, %1\;l32i\\t%D0, %N1\";
rtx tmp;
tmp = operands[0], operands[0] = operands[1], operands[1] = tmp;
tmp = operands[2], operands[2] = operands[3], operands[3] = tmp;
}
}
}
abort ();
return \"\";
}"
[(set_attr "type" "move,load,store,move,load,store")
(set_attr "mode" "DF")
(set_attr "length" "4,4,4,6,6,6")])
})
;; Block moves
......
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