From dbe9dfdd501cea13034c7b809330e82a54883b1e Mon Sep 17 00:00:00 2001 From: Georg-Johann Lay Date: Wed, 20 Jul 2016 14:46:57 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 10 ++ gcc/config/avr/avr.c | 136 ++++++++++-------- gcc/testsuite/ChangeLog | 5 + .../gcc.target/avr/torture/get-mem.c | 52 +++++++ .../gcc.target/avr/torture/set-mem.c | 55 +++++++ 5 files changed, 199 insertions(+), 59 deletions(-) create mode 100644 gcc/testsuite/gcc.target/avr/torture/get-mem.c create mode 100644 gcc/testsuite/gcc.target/avr/torture/set-mem.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 167c46a1ca2..36c13358443 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2016-07-20 Georg-Johann Lay + + * 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 Implement attribute progmem on reduced Tiny cores by adding diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 95f691c7ac7..8beda9f1103 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))) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 952513711ca..7e801c00a44 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-07-20 Georg-Johann Lay + + * gcc.target/avr/torture/get-mem.c: New test. + * gcc.target/avr/torture/set-mem.c: New test. + 2016-07-20 Georg-Johann Lay PR target/71948 diff --git a/gcc/testsuite/gcc.target/avr/torture/get-mem.c b/gcc/testsuite/gcc.target/avr/torture/get-mem.c new file mode 100644 index 00000000000..46f47f10429 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/get-mem.c @@ -0,0 +1,52 @@ +/* { 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; +} diff --git a/gcc/testsuite/gcc.target/avr/torture/set-mem.c b/gcc/testsuite/gcc.target/avr/torture/set-mem.c new file mode 100644 index 00000000000..60ded19d4b6 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/set-mem.c @@ -0,0 +1,55 @@ +/* { 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; +} -- 2.30.2