@@ -4471,28 +4471,21 @@ avr_out_lpm_no_lpmx (rtx_insn *insn, rtx *xop, int *plen)
gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
&& n_bytes <= 4);
- if (regno_dest == LPM_REGNO)
- avr_asm_len ("%4lpm" CR_TAB
- "adiw %2,1", xop, plen, 2);
- else
- avr_asm_len ("%4lpm" CR_TAB
- "mov %A0,%3" CR_TAB
- "adiw %2,1", xop, plen, 3);
+ for (int i = 0; i < n_bytes; ++i)
+ {
+ rtx reg = simplify_gen_subreg (QImode, dest, GET_MODE (dest), i);
- if (n_bytes >= 2)
- avr_asm_len ("%4lpm" CR_TAB
- "mov %B0,%3" CR_TAB
- "adiw %2,1", xop, plen, 3);
+ if (i > 0)
+ avr_asm_len ("adiw %2,1", xop, plen, 1);
- if (n_bytes >= 3)
- avr_asm_len ("%4lpm" CR_TAB
- "mov %C0,%3" CR_TAB
- "adiw %2,1", xop, plen, 3);
+ avr_asm_len ("%4lpm", xop, plen, 1);
- if (n_bytes >= 4)
- avr_asm_len ("%4lpm" CR_TAB
- "mov %D0,%3" CR_TAB
- "adiw %2,1", xop, plen, 3);
+ if (REGNO (reg) != LPM_REGNO)
+ avr_asm_len ("mov %0,r0", ®, plen, 1);
+ }
+
+ if (! _reg_unused_after (insn, xop[2], false))
+ avr_asm_len ("adiw %2,1", xop, plen, 1);
break; /* POST_INC */
@@ -6685,6 +6678,14 @@ avr_split_tiny_move (rtx_insn * /*insn*/, rtx *xop)
if (REGNO (base) > REG_Z)
return false;
+ if (! AVR_TINY
+ // Only keep base registers that can't do PLUS addressing.
+ && ((REGNO (base) != REG_X
+ && ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (mem)))
+ || avr_load_libgcc_p (mem)
+ || avr_mem_memx_p (mem)))
+ return false;
+
bool volatile_p = MEM_VOLATILE_P (mem);
bool mem_volatile_p = false;
if (frame_pointer_needed
@@ -1035,8 +1035,7 @@ (define_split
[(parallel [(set (match_operand:MOVMODE 0 "nonimmediate_operand")
(match_operand:MOVMODE 1 "general_operand"))
(clobber (reg:CC REG_CC))])]
- "AVR_TINY
- && reload_completed
+ "reload_completed
&& avr_fuse_add > 0
// Only split this for .split2 when we are before
// pass .avr-fuse-add (which runs after proep).
new file mode 100644
@@ -0,0 +1,59 @@
+/* { dg-do run } */
+/* { dg-additional-options "-std=gnu99" } */
+
+typedef __UINT64_TYPE__ uint64_t;
+
+extern const uint64_t aa __asm ("real_aa");
+extern const uint64_t bb __asm ("real_bb");
+
+__attribute__((used)) const uint64_t real_aa = 0x1122334455667788;
+__attribute__((used)) const uint64_t real_bb = 0x0908070605040302;
+
+__attribute__((noinline,noclone))
+uint64_t add1 (const uint64_t *aa, const uint64_t *bb)
+{
+ return *aa + *bb;
+}
+
+#ifdef __FLASH
+extern const __flash uint64_t fa __asm ("real_fa");
+extern const __flash uint64_t fb __asm ("real_fb");
+
+__attribute__((used)) const __flash uint64_t real_fa = 0x1122334455667788;
+__attribute__((used)) const __flash uint64_t real_fb = 0x0908070605040302;
+
+__attribute__((noinline,noclone))
+uint64_t add2 (const __flash uint64_t *aa, const uint64_t *bb)
+{
+ return *aa + *bb;
+}
+
+uint64_t add3 (const uint64_t *aa, const __flash uint64_t *bb)
+{
+ return *aa + *bb;
+}
+
+uint64_t add4 (const __flash uint64_t *aa, const __flash uint64_t *bb)
+{
+ return *aa + *bb;
+}
+#endif /* have __flash */
+
+int main (void)
+{
+ if (add1 (&aa, &bb) != real_aa + real_bb)
+ __builtin_exit (__LINE__);
+
+#ifdef __FLASH
+ if (add2 (&fa, &bb) != real_fa + real_bb)
+ __builtin_exit (__LINE__);
+
+ if (add3 (&aa, &fb) != real_aa + real_fb)
+ __builtin_exit (__LINE__);
+
+ if (add4 (&fa, &fb) != real_fa + real_fb)
+ __builtin_exit (__LINE__);
+#endif
+
+ return 0;
+}