diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 21c58ec6f1d010df03d391abda5dcb040d7925f0..e3ccd7948275ced78b78d817786bc6fc2bf23042 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 a63b26aa50629fbc8dad0db33e260c06e00f586b..14bd1d37a5085c809f8343fffdd088072a041325 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 410a70589acc3d467eeb22e316c6b7da61c6bcd2..cbb47817d6dd10b2d068b4243b2fc266a0fda484 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 \