Commit dea44e56 by Paul Koning Committed by Paul Koning

pdp11.md (movmemhi, movmemhi1): Correct constraints.

* config/pdp11/pdp11.md (movmemhi, movmemhi1): Correct
constraints. 
* config/pdp11/pdp11.c (output_block_move): Rewrite.

From-SVN: r168338
parent fd3ce292
2010-12-30 Paul Koning <ni1d@arrl.net>
* config/pdp11/pdp11.md (movmemhi, movmemhi1): Correct
constraints.
* config/pdp11/pdp11.c (output_block_move): Rewrite.
2010-12-30 Jakub Jelinek <jakub@redhat.com> 2010-12-30 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/47060 PR tree-optimization/47060
...@@ -1167,234 +1167,155 @@ output_block_move(rtx *operands) ...@@ -1167,234 +1167,155 @@ output_block_move(rtx *operands)
{ {
static int count = 0; static int count = 0;
char buf[200]; char buf[200];
int unroll;
int lastbyte = 0;
if (GET_CODE(operands[2]) == CONST_INT /* Move of zero bytes is a NOP. */
&& ! optimize_size) if (operands[2] == const0_rtx)
return "";
/* Look for moves by small constant byte counts, those we'll
expand to straight line code. */
if (CONSTANT_P (operands[2]))
{ {
if (INTVAL(operands[2]) < 16 if (INTVAL (operands[2]) < 16
&& INTVAL(operands[3]) == 1) && (!optimize_size || INTVAL (operands[2]) < 5)
&& INTVAL (operands[3]) == 1)
{ {
register int i; register int i;
for (i = 1; i <= INTVAL(operands[2]); i++) for (i = 1; i <= INTVAL (operands[2]); i++)
output_asm_insn("movb (%1)+, (%0)+", operands); output_asm_insn("movb (%1)+, (%0)+", operands);
return ""; return "";
} }
else if (INTVAL(operands[2]) < 32) else if (INTVAL(operands[2]) < 32
&& (!optimize_size || INTVAL (operands[2]) < 9)
&& INTVAL (operands[3]) >= 2)
{ {
register int i; register int i;
for (i = 1; i <= INTVAL(operands[2])/2; i++) for (i = 1; i <= INTVAL (operands[2]) / 2; i++)
output_asm_insn("mov (%1)+, (%0)+", operands); output_asm_insn ("mov (%1)+, (%0)+", operands);
if (INTVAL (operands[2]) & 1)
/* may I assume that moved quantity is output_asm_insn ("movb (%1), (%0)", operands);
multiple of alignment ???
I HOPE SO !
*/
return ""; return "";
} }
/* can do other clever things, maybe... */
} }
if (CONSTANT_P(operands[2]) ) /* Ideally we'd look for moves that are multiples of 4 or 8
bytes and handle those by unrolling the move loop. That
makes for a lot of code if done at run time, but it's ok
for constant counts. Also, for variable counts we have
to worry about odd byte count with even aligned pointers.
On 11/40 and up we handle that case; on older machines
we don't and just use byte-wise moves all the time. */
if (CONSTANT_P (operands[2]) )
{ {
/* just move count to scratch */ if (INTVAL (operands[3]) < 2)
output_asm_insn("mov %2, %4", operands); unroll = 0;
}
else else
{ {
/* just clobber the register */ lastbyte = INTVAL (operands[2]) & 1;
operands[4] = operands[2];
}
/* switch over alignment */ if (optimize_size || INTVAL (operands[2]) & 2)
switch (INTVAL(operands[3])) unroll = 1;
{ else if (INTVAL (operands[2]) & 4)
case 1: unroll = 2;
/*
x:
movb (%1)+, (%0)+
if (TARGET_45)
sob %4,x
else else
dec %4 unroll = 3;
bgt x
*/
sprintf(buf, "\nmovestrhi%d:", count);
output_asm_insn(buf, NULL);
output_asm_insn("movb (%1)+, (%0)+", operands);
if (TARGET_45)
{
sprintf(buf, "sob %%4, movestrhi%d", count);
output_asm_insn(buf, operands);
} }
else
{
output_asm_insn("dec %4", operands);
sprintf(buf, "bgt movestrhi%d", count); /* Loop count is byte count scaled by unroll. */
output_asm_insn(buf, NULL); operands[2] = GEN_INT (INTVAL (operands[2]) >> unroll);
output_asm_insn ("mov %2, %4", operands);
} }
count ++;
break;
case 2:
/*
asr %4
x:
mov (%1)+, (%0)+
if (TARGET_45)
sob %4, x
else else
dec %4 {
bgt x /* Variable byte count; use the input register
*/ as the scratch. */
operands[4] = operands[2];
generate_compact_code:
output_asm_insn("asr %4", operands);
sprintf(buf, "\nmovestrhi%d:", count);
output_asm_insn(buf, NULL);
output_asm_insn("mov (%1)+, (%0)+", operands);
if (TARGET_45) /* Decide whether to move by words, and check
the byte count for zero. */
if (TARGET_40_PLUS && INTVAL (operands[3]) > 1)
{ {
sprintf(buf, "sob %%4, movestrhi%d", count); unroll = 1;
output_asm_insn(buf, operands); output_asm_insn ("asr %4", operands);
} }
else else
{ {
output_asm_insn("dec %4", operands); unroll = 0;
output_asm_insn ("tst %4", operands);
sprintf(buf, "bgt movestrhi%d", count); }
output_asm_insn(buf, NULL); sprintf (buf, "beq movestrhi%d", count + 1);
output_asm_insn (buf, NULL);
} }
count ++; /* Output the loop label. */
break; sprintf (buf, "\nmovestrhi%d:", count);
output_asm_insn (buf, NULL);
case 4:
/*
asr %4
asr %4
x:
mov (%1)+, (%0)+
mov (%1)+, (%0)+
if (TARGET_45)
sob %4, x
else
dec %4
bgt x
*/
if (optimize_size)
goto generate_compact_code;
output_asm_insn("asr %4", operands);
output_asm_insn("asr %4", operands);
sprintf(buf, "\nmovestrhi%d:", count);
output_asm_insn(buf, NULL);
output_asm_insn("mov (%1)+, (%0)+", operands);
output_asm_insn("mov (%1)+, (%0)+", operands);
if (TARGET_45) /* Output the appropriate move instructions. */
{ switch (unroll)
sprintf(buf, "sob %%4, movestrhi%d", count);
output_asm_insn(buf, operands);
}
else
{ {
output_asm_insn("dec %4", operands); case 0:
output_asm_insn ("movb (%1)+, (%0)+", operands);
break;
sprintf(buf, "bgt movestrhi%d", count); case 1:
output_asm_insn(buf, NULL); output_asm_insn ("mov (%1)+, (%0)+", operands);
} break;
count ++; case 2:
output_asm_insn ("mov (%1)+, (%0)+", operands);
output_asm_insn ("mov (%1)+, (%0)+", operands);
break; break;
default: default:
output_asm_insn ("mov (%1)+, (%0)+", operands);
output_asm_insn ("mov (%1)+, (%0)+", operands);
output_asm_insn ("mov (%1)+, (%0)+", operands);
output_asm_insn ("mov (%1)+, (%0)+", operands);
break;
}
/* /* Output the decrement and test. */
if (TARGET_40_PLUS)
asr %4
asr %4
asr %4
x:
mov (%1)+, (%0)+
mov (%1)+, (%0)+
mov (%1)+, (%0)+
mov (%1)+, (%0)+
if (TARGET_45)
sob %4, x
else
dec %4
bgt x
*/
if (optimize_size)
goto generate_compact_code;
output_asm_insn("asr %4", operands);
output_asm_insn("asr %4", operands);
output_asm_insn("asr %4", operands);
sprintf(buf, "\nmovestrhi%d:", count);
output_asm_insn(buf, NULL);
output_asm_insn("mov (%1)+, (%0)+", operands);
output_asm_insn("mov (%1)+, (%0)+", operands);
output_asm_insn("mov (%1)+, (%0)+", operands);
output_asm_insn("mov (%1)+, (%0)+", operands);
if (TARGET_45)
{ {
sprintf(buf, "sob %%4, movestrhi%d", count); sprintf (buf, "sob %%4, movestrhi%d", count);
output_asm_insn(buf, operands); output_asm_insn (buf, operands);
} }
else else
{ {
output_asm_insn("dec %4", operands); output_asm_insn ("dec %4", operands);
sprintf (buf, "bgt movestrhi%d", count);
sprintf(buf, "bgt movestrhi%d", count); output_asm_insn (buf, NULL);
output_asm_insn(buf, NULL);
} }
count ++; count ++;
break;
; /* If constant odd byte count, move the last byte. */
if (lastbyte)
output_asm_insn ("movb (%1), (%0)", operands);
else if (!CONSTANT_P (operands[2]))
{
/* Output the destination label for the zero byte count check. */
sprintf (buf, "\nmovestrhi%d:", count);
output_asm_insn (buf, NULL);
count++;
/* If we did word moves, check for trailing last byte. */
if (unroll)
{
sprintf (buf, "bcc movestrhi%d", count);
output_asm_insn (buf, NULL);
output_asm_insn ("movb (%1), (%0)", operands);
sprintf (buf, "\nmovestrhi%d:", count);
output_asm_insn (buf, NULL);
count++;
}
} }
return ""; return "";
......
...@@ -321,7 +321,7 @@ ...@@ -321,7 +321,7 @@
(define_expand "movmemhi" (define_expand "movmemhi"
[(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g") [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
(match_operand:BLK 1 "general_operand" "g,g")) (match_operand:BLK 1 "general_operand" "g,g"))
(use (match_operand:HI 2 "general_operand" "n,&mr")) (use (match_operand:HI 2 "general_operand" "n,mr"))
(use (match_operand:HI 3 "immediate_operand" "i,i")) (use (match_operand:HI 3 "immediate_operand" "i,i"))
(clobber (match_scratch:HI 4 "=&r,X")) (clobber (match_scratch:HI 4 "=&r,X"))
(clobber (match_dup 5)) (clobber (match_dup 5))
...@@ -342,10 +342,10 @@ ...@@ -342,10 +342,10 @@
}") }")
(define_insn "" ; "movmemhi" (define_insn "movmemhi1"
[(set (mem:BLK (match_operand 0 "pmode_register_operand" "+r,r")) [(set (mem:BLK (match_operand:HI 0 "register_operand" "r,r"))
(mem:BLK (match_operand 1 "pmode_register_operand" "+r,r"))) (mem:BLK (match_operand:HI 1 "register_operand" "r,r")))
(use (match_operand:HI 2 "general_operand" "+n,&r")) (use (match_operand:HI 2 "general_operand" "n,r"))
(use (match_operand:HI 3 "immediate_operand" "i,i")) (use (match_operand:HI 3 "immediate_operand" "i,i"))
(clobber (match_scratch:HI 4 "=&r,X")) (clobber (match_scratch:HI 4 "=&r,X"))
(clobber (match_dup 0)) (clobber (match_dup 0))
......
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