aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorGeorg-Johann Lay <avr@gjlay.de>2016-07-20 14:46:57 +0000
committerGeorg-Johann Lay <gjl@gcc.gnu.org>2016-07-20 14:46:57 +0000
commitdbe9dfdd501cea13034c7b809330e82a54883b1e (patch)
tree340de8a19b1645bf355f6f2a045baa9284cc9bc4 /gcc/config
parentc25e1d82bf149151af72a8a38db2160b1ca46002 (diff)
downloadgcc-dbe9dfdd501cea13034c7b809330e82a54883b1e.zip
gcc-dbe9dfdd501cea13034c7b809330e82a54883b1e.tar.gz
gcc-dbe9dfdd501cea13034c7b809330e82a54883b1e.tar.bz2
avr.c (avr_legitimize_address): Force constant addresses outside [0,0xc0] into a register.
gcc/ * gcc/config/avr.c (avr_legitimize_address) [AVR_TINY]: Force constant addresses outside [0,0xc0] into a register. (avr_out_movhi_r_mr_reg_no_disp_tiny): Pass insn. And handle cases where the base address register is unused after. (avr_out_movhi_r_mr_reg_disp_tiny): Same. (avr_out_movhi_mr_r_reg_disp_tiny): Same. (avr_out_store_psi_reg_disp_tiny): Same. gcc/testsuite/ * gcc.target/avr/torture/get-mem.c: New test. * gcc.target/avr/torture/set-mem.c: New test. From-SVN: r238528
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/avr/avr.c136
1 files changed, 77 insertions, 59 deletions
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 95f691c..8beda9f 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -1926,6 +1926,16 @@ avr_legitimize_address (rtx x, rtx oldx, machine_mode mode)
x = oldx;
+ if (AVR_TINY)
+ {
+ if (CONSTANT_ADDRESS_P (x)
+ && !(CONST_INT_P (x)
+ && IN_RANGE (INTVAL (x), 0, 0xc0 - GET_MODE_SIZE (mode))))
+ {
+ x = force_reg (Pmode, x);
+ }
+ }
+
if (GET_CODE (oldx) == PLUS
&& REG_P (XEXP (oldx, 0)))
{
@@ -3537,7 +3547,7 @@ out_movqi_r_mr (rtx_insn *insn, rtx op[], int *plen)
/* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
static const char*
-avr_out_movhi_r_mr_reg_no_disp_tiny (rtx op[], int *plen)
+avr_out_movhi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
{
rtx dest = op[0];
rtx src = op[1];
@@ -3551,17 +3561,20 @@ avr_out_movhi_r_mr_reg_no_disp_tiny (rtx op[], int *plen)
"ld %B0,%1" CR_TAB
"mov %A0,__tmp_reg__", op, plen, -3);
- return avr_asm_len ("ld %A0,%1" CR_TAB
- TINY_ADIW (%E1, %F1, 1) CR_TAB
- "ld %B0,%1" CR_TAB
- TINY_SBIW (%E1, %F1, 1), op, plen, -6);
+ avr_asm_len ("ld %A0,%1+" CR_TAB
+ "ld %B0,%1", op, plen, -2);
+
+ if (!reg_unused_after (insn, base))
+ avr_asm_len (TINY_SBIW (%E1, %F1, 1), op, plen, 2);
+
+ return "";
}
/* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
static const char*
-avr_out_movhi_r_mr_reg_disp_tiny (rtx op[], int *plen)
+avr_out_movhi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
{
rtx dest = op[0];
rtx src = op[1];
@@ -3579,10 +3592,14 @@ avr_out_movhi_r_mr_reg_disp_tiny (rtx op[], int *plen)
}
else
{
- return avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
- "ld %A0,%b1+" CR_TAB
- "ld %B0,%b1" CR_TAB
- TINY_SBIW (%I1, %J1, %o1+1), op, plen, -6);
+ avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
+ "ld %A0,%b1+" CR_TAB
+ "ld %B0,%b1", op, plen, -4);
+
+ if (!reg_unused_after (insn, XEXP (base, 0)))
+ avr_asm_len (TINY_SBIW (%I1, %J1, %o1+1), op, plen, 2);
+
+ return "";
}
}
@@ -3630,7 +3647,7 @@ out_movhi_r_mr (rtx_insn *insn, rtx op[], int *plen)
if (reg_base > 0)
{
if (AVR_TINY)
- return avr_out_movhi_r_mr_reg_no_disp_tiny (op, plen);
+ return avr_out_movhi_r_mr_reg_no_disp_tiny (insn, op, plen);
if (reg_dest == reg_base) /* R = (R) */
return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
@@ -3655,7 +3672,7 @@ out_movhi_r_mr (rtx_insn *insn, rtx op[], int *plen)
int reg_base = true_regnum (XEXP (base, 0));
if (AVR_TINY)
- return avr_out_movhi_r_mr_reg_disp_tiny (op, plen);
+ return avr_out_movhi_r_mr_reg_disp_tiny (insn, op, plen);
if (disp > MAX_LD_OFFSET (GET_MODE (src)))
{
@@ -4404,8 +4421,8 @@ avr_out_load_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
"ld %B0,%1+" CR_TAB
"ld %C0,%1", op, plen, -3);
- if (reg_dest != reg_base - 2 &&
- !reg_unused_after (insn, base))
+ if (reg_dest != reg_base - 2
+ && !reg_unused_after (insn, base))
{
avr_asm_len (TINY_SBIW (%E1, %F1, 2), op, plen, 2);
}
@@ -4435,13 +4452,13 @@ avr_out_load_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
else
{
avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
- "ld %A0,%b1+" CR_TAB
- "ld %B0,%b1+" CR_TAB
- "ld %C0,%b1", op, plen, -5);
+ "ld %A0,%b1+" CR_TAB
+ "ld %B0,%b1+" CR_TAB
+ "ld %C0,%b1", op, plen, -5);
- if (reg_dest != (reg_base - 2)
+ if (reg_dest != reg_base - 2
&& !reg_unused_after (insn, XEXP (base, 0)))
- avr_asm_len (TINY_SBIW (%I1, %J1, %o1+2), op, plen, 2);
+ avr_asm_len (TINY_SBIW (%I1, %J1, %o1+2), op, plen, 2);
return "";
}
@@ -4626,7 +4643,7 @@ avr_out_store_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
}
static const char*
-avr_out_store_psi_reg_disp_tiny (rtx *op, int *plen)
+avr_out_store_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
{
rtx dest = op[0];
rtx src = op[1];
@@ -4635,31 +4652,29 @@ avr_out_store_psi_reg_disp_tiny (rtx *op, int *plen)
int reg_src = true_regnum (src);
if (reg_src == reg_base)
- {
- return avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
- "mov __zero_reg__,%B1" CR_TAB
- TINY_ADIW (%I0, %J0, %o0) CR_TAB
- "st %b0+,__tmp_reg__" CR_TAB
- "st %b0+,__zero_reg__" CR_TAB
- "st %b0,%C1" CR_TAB
- "clr __zero_reg__" CR_TAB
- TINY_SBIW (%I0, %J0, %o0+2), op, plen, -10);
- }
+ avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
+ "mov __zero_reg__,%B1" CR_TAB
+ TINY_ADIW (%I0, %J0, %o0) CR_TAB
+ "st %b0+,__tmp_reg__" CR_TAB
+ "st %b0+,__zero_reg__" CR_TAB
+ "st %b0,%C1" CR_TAB
+ "clr __zero_reg__", op, plen, -8);
else if (reg_src == reg_base - 2)
- {
- return avr_asm_len ("mov __tmp_reg__,%C1" CR_TAB
- TINY_ADIW (%I0, %J0, %o0) CR_TAB
- "st %b0+,%A1" CR_TAB
- "st %b0+,%B1" CR_TAB
- "st %b0,__tmp_reg__" CR_TAB
- TINY_SBIW (%I0, %J0, %o0+2), op, plen, -8);
- }
+ avr_asm_len ("mov __tmp_reg__,%C1" CR_TAB
+ TINY_ADIW (%I0, %J0, %o0) CR_TAB
+ "st %b0+,%A1" CR_TAB
+ "st %b0+,%B1" CR_TAB
+ "st %b0,__tmp_reg__", op, plen, -6);
+ else
+ avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
+ "st %b0+,%A1" CR_TAB
+ "st %b0+,%B1" CR_TAB
+ "st %b0,%C1", op, plen, -5);
- return avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
- "st %b0+,%A1" CR_TAB
- "st %b0+,%B1" CR_TAB
- "st %b0,%C1" CR_TAB
- TINY_SBIW (%I0, %J0, %o0+2), op, plen, -7);
+ if (!reg_unused_after (insn, XEXP (base, 0)))
+ avr_asm_len (TINY_SBIW (%I0, %J0, %o0+2), op, plen, 2);
+
+ return "";
}
/* Handle store of 24-bit type from register or zero to memory. */
@@ -4708,7 +4723,7 @@ avr_out_store_psi (rtx_insn *insn, rtx *op, int *plen)
int disp = INTVAL (XEXP (base, 1));
if (AVR_TINY)
- return avr_out_store_psi_reg_disp_tiny (op, plen);
+ return avr_out_store_psi_reg_disp_tiny (insn, op, plen);
reg_base = REGNO (XEXP (base, 0));
@@ -4842,7 +4857,7 @@ avr_out_movqi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
else
{
avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
- "st %b0,%1" , op, plen, -3);
+ "st %b0,%1", op, plen, -3);
}
if (!reg_unused_after (insn, XEXP (x,0)))
@@ -5066,7 +5081,7 @@ avr_out_movhi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
}
static const char*
-avr_out_movhi_mr_r_reg_disp_tiny (rtx op[], int *plen)
+avr_out_movhi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
{
rtx dest = op[0];
rtx src = op[1];
@@ -5074,19 +5089,22 @@ avr_out_movhi_mr_r_reg_disp_tiny (rtx op[], int *plen)
int reg_base = REGNO (XEXP (base, 0));
int reg_src = true_regnum (src);
- return reg_src == reg_base
- ? avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
- "mov __zero_reg__,%B1" CR_TAB
- TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
- "st %b0,__zero_reg__" CR_TAB
- "st -%b0,__tmp_reg__" CR_TAB
- "clr __zero_reg__" CR_TAB
- TINY_SBIW (%I0, %J0, %o0), op, plen, -9)
+ if (reg_src == reg_base)
+ avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
+ "mov __zero_reg__,%B1" CR_TAB
+ TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
+ "st %b0,__zero_reg__" CR_TAB
+ "st -%b0,__tmp_reg__" CR_TAB
+ "clr __zero_reg__", op, plen, -7);
+ else
+ avr_asm_len (TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
+ "st %b0,%B1" CR_TAB
+ "st -%b0,%A1", op, plen, -4);
+
+ if (!reg_unused_after (insn, XEXP (base, 0)))
+ avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
- : avr_asm_len (TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
- "st %b0,%B1" CR_TAB
- "st -%b0,%A1" CR_TAB
- TINY_SBIW (%I0, %J0, %o0), op, plen, -6);
+ return "";
}
static const char*
@@ -5163,7 +5181,7 @@ out_movhi_mr_r (rtx_insn *insn, rtx op[], int *plen)
int disp = INTVAL (XEXP (base, 1));
if (AVR_TINY)
- return avr_out_movhi_mr_r_reg_disp_tiny (op, plen);
+ return avr_out_movhi_mr_r_reg_disp_tiny (insn, op, plen);
reg_base = REGNO (XEXP (base, 0));
if (disp > MAX_LD_OFFSET (GET_MODE (dest)))