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>
* 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
flash offset 0x4000 to respective symbols.
......
......@@ -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)))
......
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
* 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