aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPaul Koning <ni1d@arrl.net>2010-12-30 06:50:40 -0500
committerPaul Koning <pkoning@gcc.gnu.org>2010-12-30 06:50:40 -0500
commitdea44e569da296dab34c6f76b259c0844083a919 (patch)
treebfe07c93e4066d897c0ea26f36be593cf45a4349 /gcc
parentfd3ce292ae5796e7da960d332d50e34b6ab0fe91 (diff)
downloadgcc-dea44e569da296dab34c6f76b259c0844083a919.zip
gcc-dea44e569da296dab34c6f76b259c0844083a919.tar.gz
gcc-dea44e569da296dab34c6f76b259c0844083a919.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/pdp11/pdp11.c311
-rw-r--r--gcc/config/pdp11/pdp11.md10
3 files changed, 127 insertions, 200 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 067ed75..a3e7fae 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+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>
PR tree-optimization/47060
diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c
index 9c7b476..3a7f9d6 100644
--- a/gcc/config/pdp11/pdp11.c
+++ b/gcc/config/pdp11/pdp11.c
@@ -1167,236 +1167,157 @@ output_block_move(rtx *operands)
{
static int count = 0;
char buf[200];
+ int unroll;
+ int lastbyte = 0;
- if (GET_CODE(operands[2]) == CONST_INT
- && ! optimize_size)
+ /* Move of zero bytes is a NOP. */
+ 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
- && INTVAL(operands[3]) == 1)
+ if (INTVAL (operands[2]) < 16
+ && (!optimize_size || INTVAL (operands[2]) < 5)
+ && INTVAL (operands[3]) == 1)
{
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);
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;
- for (i = 1; i <= INTVAL(operands[2])/2; i++)
- output_asm_insn("mov (%1)+, (%0)+", operands);
+ for (i = 1; i <= INTVAL (operands[2]) / 2; i++)
+ output_asm_insn ("mov (%1)+, (%0)+", operands);
+ if (INTVAL (operands[2]) & 1)
+ output_asm_insn ("movb (%1), (%0)", operands);
- /* may I assume that moved quantity is
- multiple of alignment ???
-
- I HOPE SO !
- */
-
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 */
- output_asm_insn("mov %2, %4", operands);
+ if (INTVAL (operands[3]) < 2)
+ unroll = 0;
+ else
+ {
+ lastbyte = INTVAL (operands[2]) & 1;
+
+ if (optimize_size || INTVAL (operands[2]) & 2)
+ unroll = 1;
+ else if (INTVAL (operands[2]) & 4)
+ unroll = 2;
+ else
+ unroll = 3;
+ }
+
+ /* Loop count is byte count scaled by unroll. */
+ operands[2] = GEN_INT (INTVAL (operands[2]) >> unroll);
+ output_asm_insn ("mov %2, %4", operands);
}
else
{
- /* just clobber the register */
+ /* Variable byte count; use the input register
+ as the scratch. */
operands[4] = operands[2];
- }
-
- /* switch over alignment */
- switch (INTVAL(operands[3]))
- {
- case 1:
-
- /*
- x:
- movb (%1)+, (%0)+
-
- if (TARGET_45)
- sob %4,x
- else
- dec %4
- bgt x
+ /* Decide whether to move by words, and check
+ the byte count for zero. */
+ if (TARGET_40_PLUS && INTVAL (operands[3]) > 1)
+ {
+ unroll = 1;
+ output_asm_insn ("asr %4", operands);
+ }
+ else
+ {
+ unroll = 0;
+ output_asm_insn ("tst %4", operands);
+ }
+ sprintf (buf, "beq movestrhi%d", count + 1);
+ output_asm_insn (buf, NULL);
+ }
- */
+ /* Output the loop label. */
+ sprintf (buf, "\nmovestrhi%d:", count);
+ output_asm_insn (buf, NULL);
- 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);
- output_asm_insn(buf, NULL);
- }
+ /* Output the appropriate move instructions. */
+ switch (unroll)
+ {
+ case 0:
+ output_asm_insn ("movb (%1)+, (%0)+", operands);
+ break;
- count ++;
+ case 1:
+ output_asm_insn ("mov (%1)+, (%0)+", operands);
break;
case 2:
-
- /*
- asr %4
-
- x:
-
- mov (%1)+, (%0)+
-
- if (TARGET_45)
- sob %4, x
- else
- dec %4
- bgt x
- */
-
- 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)
- {
- 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);
- output_asm_insn(buf, NULL);
- }
-
- count ++;
+ output_asm_insn ("mov (%1)+, (%0)+", operands);
+ output_asm_insn ("mov (%1)+, (%0)+", operands);
break;
-
- 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)
- {
- 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);
- output_asm_insn(buf, NULL);
- }
-
- count ++;
- break;
-
default:
-
- /*
-
- 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);
- output_asm_insn(buf, operands);
- }
- else
- {
- output_asm_insn("dec %4", operands);
-
- sprintf(buf, "bgt movestrhi%d", count);
- output_asm_insn(buf, NULL);
- }
-
- count ++;
+ 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)
+ {
+ 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);
+ output_asm_insn (buf, NULL);
+ }
+ count ++;
+
+ /* 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 "";
}
diff --git a/gcc/config/pdp11/pdp11.md b/gcc/config/pdp11/pdp11.md
index 0566d9a..aa7512b 100644
--- a/gcc/config/pdp11/pdp11.md
+++ b/gcc/config/pdp11/pdp11.md
@@ -321,7 +321,7 @@
(define_expand "movmemhi"
[(parallel [(set (match_operand:BLK 0 "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"))
(clobber (match_scratch:HI 4 "=&r,X"))
(clobber (match_dup 5))
@@ -342,10 +342,10 @@
}")
-(define_insn "" ; "movmemhi"
- [(set (mem:BLK (match_operand 0 "pmode_register_operand" "+r,r"))
- (mem:BLK (match_operand 1 "pmode_register_operand" "+r,r")))
- (use (match_operand:HI 2 "general_operand" "+n,&r"))
+(define_insn "movmemhi1"
+ [(set (mem:BLK (match_operand:HI 0 "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 3 "immediate_operand" "i,i"))
(clobber (match_scratch:HI 4 "=&r,X"))
(clobber (match_dup 0))