From 33faafca375f8c5c4113b4f0628c69add6971ee6 Mon Sep 17 00:00:00 2001
From: Anatoly Sokolov <aesok@post.ru>
Date: Mon, 12 Jan 2009 23:41:57 +0300
Subject: [PATCH] re PR target/29141 (static constructors beyond 64k fail)

	PR target/29141
	* config/avr/t-avr (LIB1ASMFUNCS): Add _tablejump_elpm.
	* config/avr/libgcc.S (__do_global_ctors, __do_global_dtors): Add
	variant for devices with 3-byte PC.
	(__tablejump_elpm__) : New.

From-SVN: r143306
---
 gcc/ChangeLog           |  8 ++++
 gcc/config/avr/libgcc.S | 92 +++++++++++++++++++++++++++++++++++++----
 gcc/config/avr/t-avr    |  1 +
 3 files changed, 92 insertions(+), 9 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 21c58ec6f1d0..e3ccd7948275 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2009-01-03  Anatoly Sokolov  <aesok@post.ru>
+
+	PR target/29141
+	* config/avr/t-avr (LIB1ASMFUNCS): Add _tablejump_elpm.
+	* config/avr/libgcc.S (__do_global_ctors, __do_global_dtors): Add
+	variant for devices with 3-byte PC.
+	(__tablejump_elpm__) : New.
+
 2009-01-12  Jakub Jelinek  <jakub@redhat.com>
 
 	PR c/32041
diff --git a/gcc/config/avr/libgcc.S b/gcc/config/avr/libgcc.S
index a63b26aa5062..14bd1d37a508 100644
--- a/gcc/config/avr/libgcc.S
+++ b/gcc/config/avr/libgcc.S
@@ -1,5 +1,5 @@
 /*  -*- Mode: Asm -*-  */
-/* Copyright (C) 1998, 1999, 2000, 2007, 2008 
+/* Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Contributed by Denis Chertykov <denisc@overta.ru>
 
@@ -793,38 +793,112 @@ __do_clear_bss:
 #ifdef L_ctors
 	.section .init6,"ax",@progbits
 	.global	__do_global_ctors
+#if defined(__AVR_HAVE_RAMPZ__)
 __do_global_ctors:
 	ldi	r17, hi8(__ctors_start)
+	ldi	r16, hh8(__ctors_start)
 	ldi	r28, lo8(__ctors_end)
 	ldi	r29, hi8(__ctors_end)
-	rjmp	.do_global_ctors_start
-.do_global_ctors_loop:
+	ldi	r20, hh8(__ctors_end)
+	rjmp	.L__do_global_ctors_start
+.L__do_global_ctors_loop:
+	sbiw	r28, 2
+	sbc     r20, __zero_reg__
+	mov_h	r31, r29
+	mov_l	r30, r28
+	out     __RAMPZ__, r20
+	XCALL	__tablejump_elpm__
+.L__do_global_ctors_start:
+	cpi	r28, lo8(__ctors_start)
+	cpc	r29, r17
+	cpc	r20, r16
+	brne	.L__do_global_ctors_loop
+#else
+__do_global_ctors:
+	ldi	r17, hi8(__ctors_start)
+	ldi	r28, lo8(__ctors_end)
+	ldi	r29, hi8(__ctors_end)
+	rjmp	.L__do_global_ctors_start
+.L__do_global_ctors_loop:
 	sbiw	r28, 2
 	mov_h	r31, r29
 	mov_l	r30, r28
 	XCALL	__tablejump__
-.do_global_ctors_start:
+.L__do_global_ctors_start:
 	cpi	r28, lo8(__ctors_start)
 	cpc	r29, r17
-	brne	.do_global_ctors_loop
+	brne	.L__do_global_ctors_loop
+#endif /* defined(__AVR_HAVE_RAMPZ__) */
 #endif /* L_ctors */
 
 #ifdef L_dtors
 	.section .fini6,"ax",@progbits
 	.global	__do_global_dtors
+#if defined(__AVR_HAVE_RAMPZ__)
 __do_global_dtors:
 	ldi	r17, hi8(__dtors_end)
+	ldi	r16, hh8(__dtors_end)
 	ldi	r28, lo8(__dtors_start)
 	ldi	r29, hi8(__dtors_start)
-	rjmp	.do_global_dtors_start
-.do_global_dtors_loop:
+	ldi	r20, hh8(__dtors_start)
+	rjmp	.L__do_global_dtors_start
+.L__do_global_dtors_loop:
+	sbiw	r28, 2
+	sbc     r20, __zero_reg__
+	mov_h	r31, r29
+	mov_l	r30, r28
+	out     __RAMPZ__, r20
+	XCALL	__tablejump_elpm__
+.L__do_global_dtors_start:
+	cpi	r28, lo8(__dtors_end)
+	cpc	r29, r17
+	cpc	r20, r16
+	brne	.L__do_global_dtors_loop
+#else
+__do_global_dtors:
+	ldi	r17, hi8(__dtors_end)
+	ldi	r28, lo8(__dtors_start)
+	ldi	r29, hi8(__dtors_start)
+	rjmp	.L__do_global_dtors_start
+.L__do_global_dtors_loop:
 	mov_h	r31, r29
 	mov_l	r30, r28
 	XCALL	__tablejump__
 	adiw	r28, 2
-.do_global_dtors_start:
+.L__do_global_dtors_start:
 	cpi	r28, lo8(__dtors_end)
 	cpc	r29, r17
-	brne	.do_global_dtors_loop
+	brne	.L__do_global_dtors_loop
+#endif /* defined(__AVR_HAVE_RAMPZ__) */
 #endif /* L_dtors */
 
+#ifdef L_tablejump_elpm
+	.global __tablejump_elpm__
+	.func	__tablejump_elpm__
+__tablejump_elpm__:
+#if defined (__AVR_HAVE_ELPM__)
+#if defined (__AVR_HAVE_LPMX__)
+	elpm	__tmp_reg__, Z+
+	elpm	r31, Z
+	mov	r30, __tmp_reg__
+#if defined (__AVR_HAVE_EIJMP_EICALL__)
+	eijmp
+#else
+	ijmp
+#endif
+
+#else
+	elpm
+	adiw	r30, 1
+	push	r0
+	elpm
+	push	r0
+#if defined (__AVR_HAVE_EIJMP_EICALL__)
+        push    __zero_reg__
+#endif
+	ret
+#endif
+#endif /* defined (__AVR_HAVE_ELPM__) */
+	.endfunc
+#endif /* defined (L_tablejump_elpm) */
+
diff --git a/gcc/config/avr/t-avr b/gcc/config/avr/t-avr
index 410a70589acc..cbb47817d6dd 100644
--- a/gcc/config/avr/t-avr
+++ b/gcc/config/avr/t-avr
@@ -14,6 +14,7 @@ LIB1ASMFUNCS = \
 	_exit \
 	_cleanup \
 	_tablejump \
+	_tablejump_elpm \
 	_copy_data \
 	_clear_bss \
 	_ctors \
-- 
GitLab