Commit c4b9be8e by Michael Meissner

*** empty log message ***

From-SVN: r756
parent b7d3fabe
...@@ -1937,13 +1937,20 @@ expand_block_move (operands) ...@@ -1937,13 +1937,20 @@ expand_block_move (operands)
operands[3] is the alignment. operands[3] is the alignment.
operands[4] is a temp register. operands[4] is a temp register.
operands[5] is a temp register. operands[5] is a temp register.
... */ ...
operands[3+num_regs] is the last temp register.
The block move type can be one of the following:
BLOCK_MOVE_NORMAL Do all of the block move.
BLOCK_MOVE_NOT_LAST Do all but the last store.
BLOCK_MOVE_LAST Do just the last store. */
char * char *
output_block_move (insn, operands, num_regs) output_block_move (insn, operands, num_regs, move_type)
rtx insn; rtx insn;
rtx operands[]; rtx operands[];
int num_regs; int num_regs;
enum block_move_type move_type;
{ {
rtx dest_reg = XEXP (operands[0], 0); rtx dest_reg = XEXP (operands[0], 0);
rtx src_reg = XEXP (operands[1], 0); rtx src_reg = XEXP (operands[1], 0);
...@@ -1961,22 +1968,21 @@ output_block_move (insn, operands, num_regs) ...@@ -1961,22 +1968,21 @@ output_block_move (insn, operands, num_regs)
char *load; /* load insn without nop */ char *load; /* load insn without nop */
char *load_nop; /* load insn with trailing nop */ char *load_nop; /* load insn with trailing nop */
char *store; /* store insn */ char *store; /* store insn */
char *final; /* if last_store used: NULL or swr */
char *last_store; /* last store instruction */
int offset; /* current offset */ int offset; /* current offset */
enum machine_mode mode; /* mode to use on (MEM) */ enum machine_mode mode; /* mode to use on (MEM) */
} load_store[4]; } load_store[4];
/* Work around a bug in GCC, where it can give us a register /* Detect a bug in GCC, where it can give us a register
the same as one of the addressing registers. */ the same as one of the addressing registers. */
for (i = 4; i < last_operand; i++) for (i = 4; i < last_operand; i++)
{ {
if (reg_mentioned_p (operands[i], operands[0]) if (reg_mentioned_p (operands[i], operands[0])
|| reg_mentioned_p (operands[i], operands[1])) || reg_mentioned_p (operands[i], operands[1]))
{ {
/* register passed as address and temp register to block move */ error ("register $%d passed as address and temp register to block move",
/* To have a correct compiler, either this function REGNO (operands[i]));
has to handle the case, or something else has to make
sure the case won't arise. */
abort ();
for (j = i+1; j < last_operand; j++) for (j = i+1; j < last_operand; j++)
operands[j-1] = operands[j]; operands[j-1] = operands[j];
...@@ -1990,28 +1996,36 @@ output_block_move (insn, operands, num_regs) ...@@ -1990,28 +1996,36 @@ output_block_move (insn, operands, num_regs)
/* If we are given global or static addresses, and we would be /* If we are given global or static addresses, and we would be
emitting a few instructions, try to save time by using a emitting a few instructions, try to save time by using a
temporary register for the pointer. */ temporary register for the pointer. */
if (bytes > 2*align) if (bytes > 2*align || move_type != BLOCK_MOVE_NORMAL)
{ {
if (CONSTANT_P (src_reg)) if (CONSTANT_P (src_reg))
{ {
if (TARGET_STATS) if (TARGET_STATS)
mips_count_memory_refs (operands[1], 1); mips_count_memory_refs (operands[1], 1);
src_reg = operands[ 3 + num_regs-- ];
if (move_type != BLOCK_MOVE_LAST)
{
xoperands[1] = operands[1]; xoperands[1] = operands[1];
xoperands[0] = src_reg = operands[ 3 + num_regs-- ]; xoperands[0] = src_reg;
output_asm_insn ("la\t%0,%1", xoperands); output_asm_insn ("la\t%0,%1", xoperands);
} }
}
if (CONSTANT_P (dest_reg)) if (CONSTANT_P (dest_reg))
{ {
if (TARGET_STATS) if (TARGET_STATS)
mips_count_memory_refs (operands[0], 1); mips_count_memory_refs (operands[0], 1);
dest_reg = operands[ 3 + num_regs-- ];
if (move_type != BLOCK_MOVE_LAST)
{
xoperands[1] = operands[0]; xoperands[1] = operands[0];
xoperands[0] = dest_reg = operands[ 3 + num_regs-- ]; xoperands[0] = dest_reg;
output_asm_insn ("la\t%0,%1", xoperands); output_asm_insn ("la\t%0,%1", xoperands);
} }
} }
}
if (num_regs > (sizeof (load_store) / sizeof (load_store[0]))) if (num_regs > (sizeof (load_store) / sizeof (load_store[0])))
num_regs = (sizeof (load_store) / sizeof (load_store[0])); num_regs = (sizeof (load_store) / sizeof (load_store[0]));
...@@ -2019,35 +2033,39 @@ output_block_move (insn, operands, num_regs) ...@@ -2019,35 +2033,39 @@ output_block_move (insn, operands, num_regs)
else if (num_regs < 1) else if (num_regs < 1)
abort (); abort ();
if (TARGET_GAS && set_noreorder++ == 0) if (TARGET_GAS && move_type != BLOCK_MOVE_LAST && set_noreorder++ == 0)
output_asm_insn (".set\tnoreorder", operands); output_asm_insn (".set\tnoreorder", operands);
while (bytes > 0) while (bytes > 0)
{ {
load_store[num].offset = offset; load_store[num].offset = offset;
dslots_load_total++;
dslots_load_filled++;
if (bytes >= UNITS_PER_WORD && align >= UNITS_PER_WORD) if (bytes >= UNITS_PER_WORD && align >= UNITS_PER_WORD)
{ {
load_store[num].load = "lw\t%0,%1"; load_store[num].load = "lw\t%0,%1";
load_store[num].load_nop = "lw\t%0,%1%#"; load_store[num].load_nop = "lw\t%0,%1%#";
load_store[num].store = "sw\t%0,%1"; load_store[num].store = "sw\t%0,%1";
load_store[num].last_store = "sw\t%0,%1";
load_store[num].final = (char *)0;
load_store[num].mode = SImode; load_store[num].mode = SImode;
offset += UNITS_PER_WORD; offset += UNITS_PER_WORD;
bytes -= UNITS_PER_WORD; bytes -= UNITS_PER_WORD;
} }
else if (bytes >= UNITS_PER_WORD && TARGET_GAS) else if (bytes >= UNITS_PER_WORD)
{ {
#if BYTES_BIG_ENDIAN #if BYTES_BIG_ENDIAN
load_store[num].load = "lwl\t%0,%1\n\tlwr\t%0,%2"; load_store[num].load = "lwl\t%0,%1\n\tlwr\t%0,%2";
load_store[num].load_nop = "lwl\t%0,%1\n\tlwr\t%0,%2%#"; load_store[num].load_nop = "lwl\t%0,%1\n\tlwr\t%0,%2%#";
load_store[num].store = "swl\t%0,%1\n\tswr\t%0,%2"; load_store[num].store = "swl\t%0,%1\n\tswr\t%0,%2";
load_store[num].last_store = "swr\t%0,%2";
load_store[num].final = "swl\t%0,%1";
#else #else
load_store[num].load = "lwl\t%0,%2\n\tlwr\t%0,%1"; load_store[num].load = "lwl\t%0,%2\n\tlwr\t%0,%1";
load_store[num].load_nop = "lwl\t%0,%2\n\tlwr\t%0,%1%#"; load_store[num].load_nop = "lwl\t%0,%2\n\tlwr\t%0,%1%#";
load_store[num].store = "swl\t%0,%2\n\tswr\t%0,%1"; load_store[num].store = "swl\t%0,%2\n\tswr\t%0,%1";
load_store[num].last_store = "swr\t%0,%1";
load_store[num].final = "swl\t%0,%2";
#endif #endif
load_store[num].mode = SImode; load_store[num].mode = SImode;
offset += UNITS_PER_WORD; offset += UNITS_PER_WORD;
...@@ -2055,21 +2073,13 @@ output_block_move (insn, operands, num_regs) ...@@ -2055,21 +2073,13 @@ output_block_move (insn, operands, num_regs)
use_lwl_lwr = TRUE; use_lwl_lwr = TRUE;
} }
else if (bytes >= UNITS_PER_WORD)
{
load_store[num].load = "ulw\t%0,%1";
load_store[num].load_nop = "ulw\t%0,%1%#";
load_store[num].store = "usw\t%0,%1";
load_store[num].mode = SImode;
offset += UNITS_PER_WORD;
bytes -= UNITS_PER_WORD;
}
else if (bytes >= UNITS_PER_SHORT && align >= UNITS_PER_SHORT) else if (bytes >= UNITS_PER_SHORT && align >= UNITS_PER_SHORT)
{ {
load_store[num].load = "lh\t%0,%1"; load_store[num].load = "lh\t%0,%1";
load_store[num].load_nop = "lh\t%0,%1%#"; load_store[num].load_nop = "lh\t%0,%1%#";
load_store[num].store = "sh\t%0,%1"; load_store[num].store = "sh\t%0,%1";
load_store[num].last_store = "sh\t%0,%1";
load_store[num].final = (char *)0;
load_store[num].offset = offset; load_store[num].offset = offset;
load_store[num].mode = HImode; load_store[num].mode = HImode;
offset += UNITS_PER_SHORT; offset += UNITS_PER_SHORT;
...@@ -2081,13 +2091,18 @@ output_block_move (insn, operands, num_regs) ...@@ -2081,13 +2091,18 @@ output_block_move (insn, operands, num_regs)
load_store[num].load = "lb\t%0,%1"; load_store[num].load = "lb\t%0,%1";
load_store[num].load_nop = "lb\t%0,%1%#"; load_store[num].load_nop = "lb\t%0,%1%#";
load_store[num].store = "sb\t%0,%1"; load_store[num].store = "sb\t%0,%1";
load_store[num].last_store = "sb\t%0,%1";
load_store[num].final = (char *)0;
load_store[num].mode = QImode; load_store[num].mode = QImode;
offset++; offset++;
bytes--; bytes--;
} }
if (TARGET_STATS) if (TARGET_STATS && move_type != BLOCK_MOVE_LAST)
{ {
dslots_load_total++;
dslots_load_filled++;
if (CONSTANT_P (src_reg)) if (CONSTANT_P (src_reg))
mips_count_memory_refs (src_reg, 1); mips_count_memory_refs (src_reg, 1);
...@@ -2104,9 +2119,12 @@ output_block_move (insn, operands, num_regs) ...@@ -2104,9 +2119,12 @@ output_block_move (insn, operands, num_regs)
if (num == 1) if (num == 1)
{ {
load_store[0].load = load_store[0].load_nop; load_store[0].load = load_store[0].load_nop;
if (TARGET_STATS && move_type != BLOCK_MOVE_LAST)
dslots_load_filled--; dslots_load_filled--;
} }
if (move_type != BLOCK_MOVE_LAST)
{
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
{ {
int offset; int offset;
...@@ -2128,10 +2146,13 @@ output_block_move (insn, operands, num_regs) ...@@ -2128,10 +2146,13 @@ output_block_move (insn, operands, num_regs)
output_asm_insn (load_store[i].load, xoperands); output_asm_insn (load_store[i].load, xoperands);
} }
}
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
{ {
int last_p = (i == num-1 && bytes == 0);
int offset = load_store[i].offset; int offset = load_store[i].offset;
xoperands[0] = operands[i+4]; xoperands[0] = operands[i+4];
xoperands[1] = gen_rtx (MEM, load_store[i].mode, xoperands[1] = gen_rtx (MEM, load_store[i].mode,
plus_constant (dest_reg, offset)); plus_constant (dest_reg, offset));
...@@ -2141,7 +2162,20 @@ output_block_move (insn, operands, num_regs) ...@@ -2141,7 +2162,20 @@ output_block_move (insn, operands, num_regs)
xoperands[2] = gen_rtx (MEM, load_store[i].mode, xoperands[2] = gen_rtx (MEM, load_store[i].mode,
plus_constant (dest_reg, UNITS_PER_WORD-1+offset)); plus_constant (dest_reg, UNITS_PER_WORD-1+offset));
if (move_type == BLOCK_MOVE_NORMAL)
output_asm_insn (load_store[i].store, xoperands);
else if (move_type == BLOCK_MOVE_NOT_LAST)
{
if (!last_p)
output_asm_insn (load_store[i].store, xoperands); output_asm_insn (load_store[i].store, xoperands);
else if (load_store[i].final != (char *)0)
output_asm_insn (load_store[i].final, xoperands);
}
else if (last_p)
output_asm_insn (load_store[i].last_store, xoperands);
} }
num = 0; /* reset load_store */ num = 0; /* reset load_store */
...@@ -2149,7 +2183,7 @@ output_block_move (insn, operands, num_regs) ...@@ -2149,7 +2183,7 @@ output_block_move (insn, operands, num_regs)
} }
} }
if (TARGET_GAS && --set_noreorder == 0) if (TARGET_GAS && move_type != BLOCK_MOVE_LAST && --set_noreorder == 0)
output_asm_insn (".set\treorder", operands); output_asm_insn (".set\treorder", operands);
return ""; return "";
......
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