aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMarek Michalkiewicz <marekm@linux.org.pl>2000-12-20 19:49:22 +0100
committerDenis Chertykov <denisc@gcc.gnu.org>2000-12-20 21:49:22 +0300
commitdfaf5abf0f831d2ed94eedf13ba2dd7d647b0ad7 (patch)
treec2ad61ef0ffd7d5c7ea3e7d51f64340708ff3314 /gcc
parent64094f6a65becc338e39fe3bc72d83d812c50d4d (diff)
downloadgcc-dfaf5abf0f831d2ed94eedf13ba2dd7d647b0ad7.zip
gcc-dfaf5abf0f831d2ed94eedf13ba2dd7d647b0ad7.tar.gz
gcc-dfaf5abf0f831d2ed94eedf13ba2dd7d647b0ad7.tar.bz2
avr.c (out_movsi_r_mr, [...]): Do not output undefined opcodes where source or destination register overlaps...
* config/avr/avr.c (out_movsi_r_mr, out_movsi_mr_r, out_movhi_mr_r): Do not output undefined opcodes where source or destination register overlaps with modified pointer register. Handle (X + d) addresses. * config/avr/avr.md (*movhi, *movsi, *movsf): Correct insn length in alternatives with memory operand. From-SVN: r38405
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/avr/avr.c150
-rw-r--r--gcc/config/avr/avr.md6
3 files changed, 135 insertions, 29 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6eca585..72dd495 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2000-12-20 Marek Michalkiewicz <marekm@linux.org.pl>
+
+ * config/avr/avr.c (out_movsi_r_mr, out_movsi_mr_r, out_movhi_mr_r):
+ Do not output undefined opcodes where source or destination register
+ overlaps with modified pointer register. Handle (X + d) addresses.
+ * config/avr/avr.md (*movhi, *movsi, *movsf): Correct insn length
+ in alternatives with memory operand.
+
2000-12-20 Richard Henderson <rth@redhat.com>
* c-typeck.c (build_asm_stmt): New, broken out from ...
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 2903509..72c3523 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -1995,12 +1995,14 @@ out_movsi_r_mr (insn, op, l)
if (reg_base == REG_X) /* (R26) */
{
if (reg_dest == REG_X)
- return *l=6, (AS2 (adiw,r26,3) CR_TAB
- AS2 (ld,%D0,X) CR_TAB
- AS2 (ld,%C0,-X) CR_TAB
- AS2 (ld,__tmp_reg__,-X) CR_TAB
- AS2 (ld,%A0,-X) CR_TAB
- AS2 (mov,%B0,__tmp_reg__));
+ /* "ld r26,-X" is undefined */
+ return *l=7, (AS2 (adiw,r26,3) CR_TAB
+ AS2 (ld,r29,X) CR_TAB
+ AS2 (ld,r28,-X) CR_TAB
+ AS2 (ld,__tmp_reg__,-X) CR_TAB
+ AS2 (sbiw,r26,1) CR_TAB
+ AS2 (ld,r26,X) CR_TAB
+ AS2 (mov,r27,__tmp_reg__));
else if (reg_dest == REG_X - 2)
return *l=5, (AS2 (ld,%A0,X+) CR_TAB
AS2 (ld,%B0,X+) CR_TAB
@@ -2073,6 +2075,37 @@ out_movsi_r_mr (insn, op, l)
}
reg_base = true_regnum (XEXP (base, 0));
+ if (reg_base == REG_X)
+ {
+ /* R = (X + d) */
+ if (reg_dest == REG_X)
+ {
+ *l = 7;
+ /* "ld r26,-X" is undefined */
+ return (AS2 (adiw,r26,%o1+3) CR_TAB
+ AS2 (ld,r29,X) CR_TAB
+ AS2 (ld,r28,-X) CR_TAB
+ AS2 (ld,__tmp_reg__,-X) CR_TAB
+ AS2 (sbiw,r26,1) CR_TAB
+ AS2 (ld,r26,X) CR_TAB
+ AS2 (mov,r27,__tmp_reg__));
+ }
+ *l = 6;
+ if (reg_dest == REG_X - 2)
+ return (AS2 (adiw,r26,%o1) CR_TAB
+ AS2 (ld,r24,X+) CR_TAB
+ AS2 (ld,r25,X+) CR_TAB
+ AS2 (ld,__tmp_reg__,X+) CR_TAB
+ AS2 (ld,r27,X) CR_TAB
+ AS2 (mov,r26,__tmp_reg__));
+
+ return (AS2 (adiw,r26,%o1) CR_TAB
+ AS2 (ld,%A0,X+) CR_TAB
+ AS2 (ld,%B0,X+) CR_TAB
+ AS2 (ld,%C0,X+) CR_TAB
+ AS2 (ld,%D0,X) CR_TAB
+ AS2 (sbiw,r26,%o1+3));
+ }
if (reg_dest == reg_base)
return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
AS2 (ldd,%C0,%C1) CR_TAB
@@ -2137,19 +2170,22 @@ out_movsi_mr_r (insn, op, l)
{
if (reg_src == REG_X)
{
+ /* "st X+,r26" is undefined */
if (reg_unused_after (insn, base))
- return *l=5, (AS2 (mov,__tmp_reg__,%B1) CR_TAB
- AS2 (st,%0+,%A1) CR_TAB
- AS2 (st,%0+,__tmp_reg__) CR_TAB
- AS2 (st,%0+,%C1) CR_TAB
- AS2 (st,%0,%D1));
+ return *l=6, (AS2 (mov,__tmp_reg__,r27) CR_TAB
+ AS2 (st,X,r26) CR_TAB
+ AS2 (adiw,r26,1) CR_TAB
+ AS2 (st,X+,__tmp_reg__) CR_TAB
+ AS2 (st,X+,r28) CR_TAB
+ AS2 (st,X,r29));
else
- return *l=6, (AS2 (mov,__tmp_reg__,%B1) CR_TAB
- AS2 (st,%0+,%A1) CR_TAB
- AS2 (st,%0+,__tmp_reg__) CR_TAB
- AS2 (st,%0+,%C1) CR_TAB
- AS2 (st,%0,%D1) CR_TAB
- AS2 (sbiw,r26,3));
+ return *l=7, (AS2 (mov,__tmp_reg__,r27) CR_TAB
+ AS2 (st,X,r26) CR_TAB
+ AS2 (adiw,r26,1) CR_TAB
+ AS2 (st,X+,__tmp_reg__) CR_TAB
+ AS2 (st,X+,r28) CR_TAB
+ AS2 (st,X,r29) CR_TAB
+ AS2 (sbiw,r26,3));
}
else if (reg_base == reg_src + 2)
{
@@ -2186,9 +2222,10 @@ out_movsi_mr_r (insn, op, l)
else if (GET_CODE (base) == PLUS) /* (R + i) */
{
int disp = INTVAL (XEXP (base, 1));
+ reg_base = REGNO (XEXP (base, 0));
if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
{
- if (REGNO (XEXP (base, 0)) != REG_Y)
+ if (reg_base != REG_Y)
fatal_insn ("Incorrect insn:",insn);
if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
{
@@ -2213,6 +2250,43 @@ out_movsi_mr_r (insn, op, l)
AS2 (sbci, r29, hi8(%4)));
}
}
+ if (reg_base == REG_X)
+ {
+ /* (X + d) = R */
+ if (reg_src == REG_X)
+ {
+ *l = 9;
+ return (AS2 (mov,__tmp_reg__,r26) CR_TAB
+ AS2 (mov,__zero_reg__,r27) CR_TAB
+ AS2 (adiw,r26,%o0) CR_TAB
+ AS2 (st,X+,__tmp_reg__) CR_TAB
+ AS2 (st,X+,__zero_reg__) CR_TAB
+ AS2 (st,X+,r28) CR_TAB
+ AS2 (st,X,r29) CR_TAB
+ AS1 (clr,__zero_reg__) CR_TAB
+ AS2 (sbiw,r26,%o0+3));
+ }
+ else if (reg_src == REG_X - 2)
+ {
+ *l = 9;
+ return (AS2 (mov,__tmp_reg__,r26) CR_TAB
+ AS2 (mov,__zero_reg__,r27) CR_TAB
+ AS2 (adiw,r26,%o0) CR_TAB
+ AS2 (st,X+,r24) CR_TAB
+ AS2 (st,X+,r25) CR_TAB
+ AS2 (st,X+,__tmp_reg__) CR_TAB
+ AS2 (st,X,__zero_reg__) CR_TAB
+ AS1 (clr,__zero_reg__) CR_TAB
+ AS2 (sbiw,r26,%o0+3));
+ }
+ *l = 6;
+ return (AS2 (adiw,r26,%o0) CR_TAB
+ AS2 (st,X+,%A1) CR_TAB
+ AS2 (st,X+,%B1) CR_TAB
+ AS2 (st,X+,%C1) CR_TAB
+ AS2 (st,X,%D1) CR_TAB
+ AS2 (sbiw,r26,%o0+3));
+ }
return *l=4, (AS2 (std,%A0,%A1) CR_TAB
AS2 (std,%B0,%B1) CR_TAB
AS2 (std,%C0,%C1) CR_TAB
@@ -2545,15 +2619,18 @@ out_movhi_mr_r (insn, op, l)
{
if (reg_src == REG_X)
{
+ /* "st X+,r26" is undefined */
if (reg_unused_after (insn, src))
- return *l=3, (AS2 (mov,__tmp_reg__,r27) CR_TAB
- AS2 (st ,X+,r26) CR_TAB
- AS2 (st ,X,__tmp_reg__));
+ return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
+ AS2 (st,X,r26) CR_TAB
+ AS2 (adiw,r26,1) CR_TAB
+ AS2 (st,X,__tmp_reg__));
else
- return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
- AS2 (st ,X+,r26) CR_TAB
- AS2 (st ,X,__tmp_reg__) CR_TAB
- AS2 (sbiw,r26,1));
+ return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
+ AS2 (st,X,r26) CR_TAB
+ AS2 (adiw,r26,1) CR_TAB
+ AS2 (st,X,__tmp_reg__) CR_TAB
+ AS2 (sbiw,r26,1));
}
else
{
@@ -2573,9 +2650,10 @@ out_movhi_mr_r (insn, op, l)
else if (GET_CODE (base) == PLUS)
{
int disp = INTVAL (XEXP (base, 1));
+ reg_base = REGNO (XEXP (base, 0));
if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
{
- if (REGNO (XEXP (base, 0)) != REG_Y)
+ if (reg_base != REG_Y)
fatal_insn ("Incorrect insn:",insn);
if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
{
@@ -2596,6 +2674,26 @@ out_movhi_mr_r (insn, op, l)
AS2 (sbci, r29, hi8(%4)));
}
}
+ if (reg_base == REG_X)
+ {
+ /* (X + d) = R */
+ if (reg_src == REG_X)
+ {
+ *l = 7;
+ return (AS2 (mov,__tmp_reg__,r26) CR_TAB
+ AS2 (mov,__zero_reg__,r27) CR_TAB
+ AS2 (adiw,r26,%o0) CR_TAB
+ AS2 (st,X+,__tmp_reg__) CR_TAB
+ AS2 (st,X,__zero_reg__) CR_TAB
+ AS1 (clr,__zero_reg__) CR_TAB
+ AS2 (sbiw,r26,%o0+1));
+ }
+ *l = 4;
+ return (AS2 (adiw,r26,%o0) CR_TAB
+ AS2 (st,X+,%A1) CR_TAB
+ AS2 (st,X,%B1) CR_TAB
+ AS2 (sbiw,r26,%o0+1));
+ }
return *l=2, (AS2 (std,%A0,%A1) CR_TAB
AS2 (std,%B0,%B1));
}
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index c49b72d..c3a5e37 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -246,7 +246,7 @@
"(register_operand (operands[0],HImode)
|| register_operand (operands[1],HImode) || const0_rtx == operands[1])"
"* return output_movhi (insn, operands, NULL);"
- [(set_attr "length" "2,4,4,2,6,5,2")
+ [(set_attr "length" "2,6,7,2,6,5,2")
(set_attr "cc" "none,clobber,clobber,none,clobber,none,none")])
;;==========================================================================
@@ -295,7 +295,7 @@
"(register_operand (operands[0],SImode)
|| register_operand (operands[1],SImode) || const0_rtx == operands[1])"
"* return output_movsisf (insn, operands, NULL);"
- [(set_attr "length" "4,4,8,8,4,10")
+ [(set_attr "length" "4,4,8,9,4,10")
(set_attr "cc" "none,set_zn,clobber,clobber,none,clobber")])
;; fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
@@ -321,7 +321,7 @@
"register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode)"
"* return output_movsisf (insn, operands, NULL);"
- [(set_attr "length" "4,4,8,8,4,10")
+ [(set_attr "length" "4,4,8,9,4,10")
(set_attr "cc" "none,set_zn,clobber,clobber,none,clobber")])
;;=========================================================================