Commit dbe9dfdd by Georg-Johann Lay Committed by Georg-Johann Lay

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
parent c25e1d82
2016-07-20 Georg-Johann Lay <avr@gjlay.de> 2016-07-20 Georg-Johann Lay <avr@gjlay.de>
* 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.
2016-07-20 Georg-Johann Lay <avr@gjlay.de>
Implement attribute progmem on reduced Tiny cores by adding Implement attribute progmem on reduced Tiny cores by adding
flash offset 0x4000 to respective symbols. flash offset 0x4000 to respective symbols.
......
...@@ -1926,6 +1926,16 @@ avr_legitimize_address (rtx x, rtx oldx, machine_mode mode) ...@@ -1926,6 +1926,16 @@ avr_legitimize_address (rtx x, rtx oldx, machine_mode mode)
x = oldx; 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 if (GET_CODE (oldx) == PLUS
&& REG_P (XEXP (oldx, 0))) && REG_P (XEXP (oldx, 0)))
{ {
...@@ -3537,7 +3547,7 @@ out_movqi_r_mr (rtx_insn *insn, rtx op[], int *plen) ...@@ -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 */ /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
static const char* 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 dest = op[0];
rtx src = op[1]; rtx src = op[1];
...@@ -3551,17 +3561,20 @@ avr_out_movhi_r_mr_reg_no_disp_tiny (rtx op[], int *plen) ...@@ -3551,17 +3561,20 @@ avr_out_movhi_r_mr_reg_no_disp_tiny (rtx op[], int *plen)
"ld %B0,%1" CR_TAB "ld %B0,%1" CR_TAB
"mov %A0,__tmp_reg__", op, plen, -3); "mov %A0,__tmp_reg__", op, plen, -3);
return avr_asm_len ("ld %A0,%1" CR_TAB avr_asm_len ("ld %A0,%1+" CR_TAB
TINY_ADIW (%E1, %F1, 1) CR_TAB "ld %B0,%1", op, plen, -2);
"ld %B0,%1" CR_TAB
TINY_SBIW (%E1, %F1, 1), op, plen, -6); 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 */ /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
static const char* 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 dest = op[0];
rtx src = op[1]; rtx src = op[1];
...@@ -3579,10 +3592,14 @@ avr_out_movhi_r_mr_reg_disp_tiny (rtx op[], int *plen) ...@@ -3579,10 +3592,14 @@ avr_out_movhi_r_mr_reg_disp_tiny (rtx op[], int *plen)
} }
else else
{ {
return avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
"ld %A0,%b1+" CR_TAB "ld %A0,%b1+" CR_TAB
"ld %B0,%b1" CR_TAB "ld %B0,%b1", op, plen, -4);
TINY_SBIW (%I1, %J1, %o1+1), op, plen, -6);
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) ...@@ -3630,7 +3647,7 @@ out_movhi_r_mr (rtx_insn *insn, rtx op[], int *plen)
if (reg_base > 0) if (reg_base > 0)
{ {
if (AVR_TINY) 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) */ if (reg_dest == reg_base) /* R = (R) */
return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB 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) ...@@ -3655,7 +3672,7 @@ out_movhi_r_mr (rtx_insn *insn, rtx op[], int *plen)
int reg_base = true_regnum (XEXP (base, 0)); int reg_base = true_regnum (XEXP (base, 0));
if (AVR_TINY) 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))) 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) ...@@ -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 %B0,%1+" CR_TAB
"ld %C0,%1", op, plen, -3); "ld %C0,%1", op, plen, -3);
if (reg_dest != reg_base - 2 && if (reg_dest != reg_base - 2
!reg_unused_after (insn, base)) && !reg_unused_after (insn, base))
{ {
avr_asm_len (TINY_SBIW (%E1, %F1, 2), op, plen, 2); avr_asm_len (TINY_SBIW (%E1, %F1, 2), op, plen, 2);
} }
...@@ -4439,7 +4456,7 @@ avr_out_load_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen) ...@@ -4439,7 +4456,7 @@ avr_out_load_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
"ld %B0,%b1+" CR_TAB "ld %B0,%b1+" CR_TAB
"ld %C0,%b1", op, plen, -5); "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))) && !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);
...@@ -4626,7 +4643,7 @@ avr_out_store_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen) ...@@ -4626,7 +4643,7 @@ avr_out_store_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
} }
static const char* 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 dest = op[0];
rtx src = op[1]; rtx src = op[1];
...@@ -4635,31 +4652,29 @@ avr_out_store_psi_reg_disp_tiny (rtx *op, int *plen) ...@@ -4635,31 +4652,29 @@ avr_out_store_psi_reg_disp_tiny (rtx *op, int *plen)
int reg_src = true_regnum (src); int reg_src = true_regnum (src);
if (reg_src == reg_base) if (reg_src == reg_base)
{ avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
return avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
"mov __zero_reg__,%B1" CR_TAB "mov __zero_reg__,%B1" CR_TAB
TINY_ADIW (%I0, %J0, %o0) CR_TAB TINY_ADIW (%I0, %J0, %o0) CR_TAB
"st %b0+,__tmp_reg__" CR_TAB "st %b0+,__tmp_reg__" CR_TAB
"st %b0+,__zero_reg__" CR_TAB "st %b0+,__zero_reg__" CR_TAB
"st %b0,%C1" CR_TAB "st %b0,%C1" CR_TAB
"clr __zero_reg__" CR_TAB "clr __zero_reg__", op, plen, -8);
TINY_SBIW (%I0, %J0, %o0+2), op, plen, -10);
}
else if (reg_src == reg_base - 2) else if (reg_src == reg_base - 2)
{ avr_asm_len ("mov __tmp_reg__,%C1" CR_TAB
return avr_asm_len ("mov __tmp_reg__,%C1" CR_TAB
TINY_ADIW (%I0, %J0, %o0) CR_TAB TINY_ADIW (%I0, %J0, %o0) CR_TAB
"st %b0+,%A1" CR_TAB "st %b0+,%A1" CR_TAB
"st %b0+,%B1" CR_TAB "st %b0+,%B1" CR_TAB
"st %b0,__tmp_reg__" CR_TAB "st %b0,__tmp_reg__", op, plen, -6);
TINY_SBIW (%I0, %J0, %o0+2), op, plen, -8); else
} avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
return avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
"st %b0+,%A1" CR_TAB "st %b0+,%A1" CR_TAB
"st %b0+,%B1" CR_TAB "st %b0+,%B1" CR_TAB
"st %b0,%C1" CR_TAB "st %b0,%C1", op, plen, -5);
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. */ /* 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) ...@@ -4708,7 +4723,7 @@ avr_out_store_psi (rtx_insn *insn, rtx *op, int *plen)
int disp = INTVAL (XEXP (base, 1)); int disp = INTVAL (XEXP (base, 1));
if (AVR_TINY) 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)); 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) ...@@ -4842,7 +4857,7 @@ avr_out_movqi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
else else
{ {
avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB 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))) 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) ...@@ -5066,7 +5081,7 @@ avr_out_movhi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
} }
static const char* 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 dest = op[0];
rtx src = op[1]; rtx src = op[1];
...@@ -5074,19 +5089,22 @@ avr_out_movhi_mr_r_reg_disp_tiny (rtx op[], int *plen) ...@@ -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_base = REGNO (XEXP (base, 0));
int reg_src = true_regnum (src); int reg_src = true_regnum (src);
return reg_src == reg_base if (reg_src == reg_base)
? avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
"mov __zero_reg__,%B1" CR_TAB "mov __zero_reg__,%B1" CR_TAB
TINY_ADIW (%I0, %J0, %o0+1) CR_TAB TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
"st %b0,__zero_reg__" CR_TAB "st %b0,__zero_reg__" CR_TAB
"st -%b0,__tmp_reg__" CR_TAB "st -%b0,__tmp_reg__" CR_TAB
"clr __zero_reg__" CR_TAB "clr __zero_reg__", op, plen, -7);
TINY_SBIW (%I0, %J0, %o0), op, plen, -9) else
avr_asm_len (TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
: avr_asm_len (TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
"st %b0,%B1" CR_TAB "st %b0,%B1" CR_TAB
"st -%b0,%A1" CR_TAB "st -%b0,%A1", op, plen, -4);
TINY_SBIW (%I0, %J0, %o0), op, plen, -6);
if (!reg_unused_after (insn, XEXP (base, 0)))
avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
return "";
} }
static const char* static const char*
...@@ -5163,7 +5181,7 @@ out_movhi_mr_r (rtx_insn *insn, rtx op[], int *plen) ...@@ -5163,7 +5181,7 @@ out_movhi_mr_r (rtx_insn *insn, rtx op[], int *plen)
int disp = INTVAL (XEXP (base, 1)); int disp = INTVAL (XEXP (base, 1));
if (AVR_TINY) 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)); reg_base = REGNO (XEXP (base, 0));
if (disp > MAX_LD_OFFSET (GET_MODE (dest))) if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
......
2016-07-20 Georg-Johann Lay <avr@gjlay.de> 2016-07-20 Georg-Johann Lay <avr@gjlay.de>
* gcc.target/avr/torture/get-mem.c: New test.
* gcc.target/avr/torture/set-mem.c: New test.
2016-07-20 Georg-Johann Lay <avr@gjlay.de>
PR target/71948 PR target/71948
* gcc.target/avr/torture/tiny-progmem.c: New test. * gcc.target/avr/torture/tiny-progmem.c: New test.
......
/* { dg-do run } */
#define NI __attribute__((noinline, noclone))
typedef __INT8_TYPE__ s8;
typedef __INT16_TYPE__ s16;
typedef __int24 s24;
typedef __INT32_TYPE__ s32;
static const s8 arr8[] = { 12, 23, 34 };
static const s16 arr16[] = { 123, 234, 345 };
static const s24 arr24[] = { 1234, 2345, 3456 };
static const s32 arr32[] = { 12345, 23456, 34567 };
NI s8 add8 (const s8 *p) { return p[0] + p[1] + p[2]; }
NI s16 add16 (const s16 *p) { return p[0] + p[1] + p[2]; }
NI s24 add24 (const s24 *p) { return p[0] + p[1] + p[2]; }
NI s32 add32 (const s32 *p) { return p[0] + p[1] + p[2]; }
void test8 (void)
{
if (add8 (arr8) != arr8[0] + arr8[1] + arr8[2])
__builtin_abort();
}
void test16 (void)
{
if (add16 (arr16) != arr16[0] + arr16[1] + arr16[2])
__builtin_abort();
}
void test24 (void)
{
if (add24 (arr24) != arr24[0] + arr24[1] + arr24[2])
__builtin_abort();
}
void test32 (void)
{
if (add32 (arr32) != arr32[0] + arr32[1] + arr32[2])
__builtin_abort();
}
int main (void)
{
test8();
test16();
test24();
test32();
return 0;
}
/* { dg-do run } */
#define NI __attribute__((noinline, noclone))
typedef __INT8_TYPE__ s8;
typedef __INT16_TYPE__ s16;
typedef __int24 s24;
typedef __INT32_TYPE__ s32;
static s8 arr8[3];
static s16 arr16[3];
static s24 arr24[3];
static s32 arr32[3];
NI void set8 (s8 *p) { p[0] = -123; p[1] = -23; p[2] = -34; }
NI void set16 (s16 *p) { p[0] = -123; p[1] = -234; p[2] = -345; }
NI void set24 (s24 *p) { p[0] = -123; p[1] = -234; p[2] = -345; }
NI void set32 (s32 *p) { p[0] = -123; p[1] = -234; p[2] = -345; }
void test8 (void)
{
set8 (arr8);
if (arr8[0] != -123 || arr8[1] != -23 || arr8[2] != -34)
__builtin_abort();
}
void test16 (void)
{
set16 (arr16);
if (arr16[0] != -123 || arr16[1] != -234 || arr16[2] != -345)
__builtin_abort();
}
void test24 (void)
{
set24 (arr24);
if (arr24[0] != -123 || arr24[1] != -234 || arr24[2] != -345)
__builtin_abort();
}
void test32 (void)
{
set32 (arr32);
if (arr32[0] != -123 || arr32[1] != -234 || arr32[2] != -345)
__builtin_abort();
}
int main (void)
{
test8();
test16();
test24();
test32();
return 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