avr-gcc puts jump tables in section .progmem.gcc_sw_table and assumes that .text starts at 0, i.e. LPM is on order to read table entries.

This is no more the case if .text starts ata higher address like typically used with boot loaders.

This patch adds the few instructions to set RAMPZ and make casesi and __tablejump2__ more generic. __tablejump__ and __tablejump_elpm__ are no more needed. Moreover, using gs() for a jump table is odd because the linker should never generate a stub for this; thus use pm_lo8 etc. instead of gs() for >128k devices.

Ok for trunk?

Johann


gcc/
        * config/avr/avr.md (*tablejump.3byte-pc): New insn.
        (*tablejump): Restrict to !AVR_HAVE_EIJMP_EICALL.  Add void clobber.
        (casesi): Expand to *tablejump.3byte-pc if AVR_HAVE_EIJMP_EICALL.
libgcc/
        * config/avr/libgcc.S (__tablejump2__): Rewrite to use RAMPZ, ELPM
        and R24 as needed.  Make work for all devices and .text locations.
        (__do_global_ctors, __do_global_dtors): Use word addresses.
        (__tablejump__, __tablejump_elpm__): Remove functions.
        * t-avr (LIB1ASMFUNCS): Remove _tablejump, _tablejump_elpm.
        Add _tablejump2.
        (XICALL, XIJMP): New macros.
Index: gcc/config/avr/avr.md
===================================================================
--- gcc/config/avr/avr.md	(revision 214897)
+++ gcc/config/avr/avr.md	(working copy)
@@ -4931,8 +4931,9 @@ (define_insn "*tablejump"
         (unspec:HI [(match_operand:HI 0 "register_operand" "!z,*r,z")]
                    UNSPEC_INDEX_JMP))
    (use (label_ref (match_operand 1 "" "")))
-   (clobber (match_dup 0))]
-  ""
+   (clobber (match_dup 0))
+   (clobber (const_int 0))]
+  "!AVR_HAVE_EIJMP_EICALL"
   "@
 	ijmp
 	push %A0\;push %B0\;ret
@@ -4941,6 +4942,19 @@ (define_insn "*tablejump"
    (set_attr "isa" "rjmp,rjmp,jmp")
    (set_attr "cc" "none,none,clobber")])
 
+(define_insn "*tablejump.3byte-pc"
+  [(set (pc)
+        (unspec:HI [(reg:HI REG_Z)]
+                   UNSPEC_INDEX_JMP))
+   (use (label_ref (match_operand 0 "" "")))
+   (clobber (reg:HI REG_Z))
+   (clobber (reg:QI 24))]
+  "AVR_HAVE_EIJMP_EICALL"
+  "clr r24\;subi r30,pm_lo8(-(%0))\;sbci r31,pm_hi8(-(%0))\;sbci r24,pm_hh8(-(%0))\;jmp __tablejump2__"
+  [(set_attr "length" "6")
+   (set_attr "isa" "eijmp")
+   (set_attr "cc" "clobber")])
+
 
 (define_expand "casesi"
   [(parallel [(set (match_dup 6)
@@ -4958,15 +4972,31 @@ (define_expand "casesi"
                       (label_ref (match_operand 4 "" ""))
                       (pc)))
 
-   (set (match_dup 6)
-        (plus:HI (match_dup 6) (label_ref (match_operand:HI 3 "" ""))))
+   (set (match_dup 10)
+        (match_dup 7))
 
-   (parallel [(set (pc) (unspec:HI [(match_dup 6)] UNSPEC_INDEX_JMP))
+   (parallel [(set (pc)
+                   (unspec:HI [(match_dup 10)] UNSPEC_INDEX_JMP))
               (use (label_ref (match_dup 3)))
-              (clobber (match_dup 6))])]
+              (clobber (match_dup 10))
+              (clobber (match_dup 8))])]
   ""
   {
     operands[6] = gen_reg_rtx (HImode);
+
+    if (AVR_HAVE_EIJMP_EICALL)
+      {
+        operands[7] = operands[6];
+        operands[8] = all_regs_rtx[24];
+        operands[10] = gen_rtx_REG (HImode, REG_Z);
+      }
+    else
+      {
+        operands[7] = gen_rtx_PLUS (HImode, operands[6], 
+                                    gen_rtx_LABEL_REF (VOIDmode, operands[3]));
+        operands[8] = const0_rtx;
+        operands[10] = operands[6];
+      }
   })
 
 
Index: libgcc/config/avr/lib1funcs.S
===================================================================
--- libgcc/config/avr/lib1funcs.S	(revision 214897)
+++ libgcc/config/avr/lib1funcs.S	(working copy)
@@ -46,6 +46,10 @@ see the files COPYING3 and COPYING.RUNTI
            input sections together are small enough to reach every
            location with a RCALL/RJMP instruction.  */
 
+#if defined (__AVR_HAVE_EIJMP_EICALL__) && !defined (__AVR_HAVE_ELPMX__)
+#error device not supported
+#endif
+
 	.macro	mov_l  r_dest, r_src
 #if defined (__AVR_HAVE_MOVW__)
 	movw	\r_dest, \r_src
@@ -79,6 +83,14 @@ .macro	wmov  r_dest, r_src
 #define XJMP  rjmp
 #endif
 
+#if defined (__AVR_HAVE_EIJMP_EICALL__)
+#define XICALL eicall
+#define XIJMP  eijmp
+#else
+#define XICALL icall
+#define XIJMP  ijmp
+#endif
+
 ;; Prologue stuff
 
 .macro do_prologue_saves n_pushed n_frame=0
@@ -2127,11 +2139,7 @@ DEFUN __prologue_saves__
 	out	__SP_L__,r28
 #endif /* #SP = 8/16 */
 
-#if defined (__AVR_HAVE_EIJMP_EICALL__)
-	eijmp
-#else
-	ijmp
-#endif
+	XIJMP
 
 ENDF __prologue_saves__
 #endif /* defined (L_prologue) */
@@ -2213,38 +2221,54 @@ _cleanup:
 
 .section .text.libgcc, "ax", @progbits
 
-#ifdef L_tablejump
+#ifdef L_tablejump2
 DEFUN __tablejump2__
-	lsl	r30
-	rol	r31
-    ;; FALLTHRU
-ENDF __tablejump2__
-
-DEFUN __tablejump__
-#if defined (__AVR_HAVE_LPMX__)
-	lpm __tmp_reg__, Z+
-	lpm r31, Z
-	mov r30, __tmp_reg__
+    lsl     r30
+    rol     r31
 #if defined (__AVR_HAVE_EIJMP_EICALL__)
-	eijmp
-#else
-	ijmp
+    ;; Word address of gs() jumptable entry in R24:Z
+    rol     r24
+    out     __RAMPZ__, r24
+#elif defined (__AVR_HAVE_ELPM__)
+    ;; Word address of jumptable entry in Z
+    clr     __tmp_reg__
+    rol     __tmp_reg__
+    out     __RAMPZ__, __tmp_reg__
 #endif
 
-#else /* !HAVE_LPMX */
-	lpm
-	adiw r30, 1
-	push r0
-	lpm
-	push r0
-#if defined (__AVR_HAVE_EIJMP_EICALL__)
-	in   __tmp_reg__, __EIND__
-	push __tmp_reg__
+	;; Read word address from jumptable and jump
+
+#if defined (__AVR_HAVE_ELPMX__)
+    elpm    __tmp_reg__, Z+
+    elpm    r31, Z
+    mov     r30, __tmp_reg__
+#ifdef __AVR_HAVE_RAMPD__
+    ;; Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM
+    out     __RAMPZ__, __zero_reg__
+#endif /* RAMPD */
+    XIJMP
+#elif defined (__AVR_HAVE_ELPM__)
+    elpm
+    push    r0
+    adiw    r30, 1
+    elpm
+    push    r0
+    ret
+#elif defined (__AVR_HAVE_LPMX__)
+    lpm     __tmp_reg__, Z+
+    lpm     r31, Z
+    mov     r30, __tmp_reg__
+    ijmp
+#else
+    lpm
+    push    r0
+    adiw    r30, 1
+    lpm
+    push    r0
+    ret
 #endif
-	ret
-#endif /* !HAVE_LPMX */
-ENDF __tablejump__
-#endif /* defined (L_tablejump) */
+ENDF __tablejump2__
+#endif /* L_tablejump2 */
 
 #ifdef L_copy_data
 	.section .init4,"ax",@progbits
@@ -2336,116 +2360,65 @@ ENDF __do_clear_bss
 #ifdef L_ctors
 	.section .init6,"ax",@progbits
 DEFUN __do_global_ctors
-#if defined(__AVR_HAVE_ELPM__)
-	ldi	r17, hi8(__ctors_start)
-	ldi	r28, lo8(__ctors_end)
-	ldi	r29, hi8(__ctors_end)
-	ldi	r16, hh8(__ctors_end)
-	rjmp	.L__do_global_ctors_start
+	ldi     r17, pm_hi8(__ctors_start)
+	ldi     r28, pm_lo8(__ctors_end)
+	ldi     r29, pm_hi8(__ctors_end)
+#ifdef __AVR_HAVE_EIJMP_EICALL__
+	ldi     r16, pm_hh8(__ctors_end)
+#endif /* HAVE_EIJMP */
+	rjmp    .L__do_global_ctors_start
 .L__do_global_ctors_loop:
-	sbiw	r28, 2
+	sbiw    r28, 1
+#ifdef __AVR_HAVE_EIJMP_EICALL__
 	sbc     r16, __zero_reg__
+	mov     r24, r16
+#endif /* HAVE_EIJMP */
 	mov_h	r31, r29
 	mov_l	r30, r28
-	out     __RAMPZ__, r16
-	XCALL	__tablejump_elpm__
-.L__do_global_ctors_start:
-	cpi	r28, lo8(__ctors_start)
-	cpc	r29, r17
-	ldi	r24, hh8(__ctors_start)
-	cpc	r16, r24
-	brne	.L__do_global_ctors_loop
-#else
-	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__
+	XCALL	__tablejump2__
 .L__do_global_ctors_start:
-	cpi	r28, lo8(__ctors_start)
-	cpc	r29, r17
+	cpi     r28, pm_lo8(__ctors_start)
+	cpc     r29, r17
+#ifdef __AVR_HAVE_EIJMP_EICALL__
+	ldi     r24, pm_hh8(__ctors_start)
+	cpc     r16, r24
+#endif /* HAVE_EIJMP */
 	brne	.L__do_global_ctors_loop
-#endif /* defined(__AVR_HAVE_ELPM__) */
 ENDF __do_global_ctors
 #endif /* L_ctors */
 
 #ifdef L_dtors
 	.section .fini6,"ax",@progbits
 DEFUN __do_global_dtors
-#if defined(__AVR_HAVE_ELPM__)
-	ldi	r17, hi8(__dtors_end)
-	ldi	r28, lo8(__dtors_start)
-	ldi	r29, hi8(__dtors_start)
-	ldi	r16, hh8(__dtors_start)
-	rjmp	.L__do_global_dtors_start
+    ldi     r17, pm_hi8(__dtors_end)
+    ldi     r28, pm_lo8(__dtors_start)
+    ldi     r29, pm_hi8(__dtors_start)
+#ifdef __AVR_HAVE_EIJMP_EICALL__
+    ldi     r16, pm_hh8(__dtors_start)
+#endif /* HAVE_EIJMP */
+    rjmp    .L__do_global_dtors_start
 .L__do_global_dtors_loop:
-	sbiw	r28, 2
-	sbc     r16, __zero_reg__
-	mov_h	r31, r29
-	mov_l	r30, r28
-	out     __RAMPZ__, r16
-	XCALL	__tablejump_elpm__
+    sbiw    r28, 1
+#ifdef __AVR_HAVE_EIJMP_EICALL__
+    sbc     r16, __zero_reg__
+    mov     r24, r16
+#endif /* HAVE_EIJMP */
+    mov_h   r31, r29
+    mov_l   r30, r28
+    XCALL   __tablejump2__
 .L__do_global_dtors_start:
-	cpi	r28, lo8(__dtors_end)
-	cpc	r29, r17
-	ldi	r24, hh8(__dtors_end)
-	cpc	r16, r24
-	brne	.L__do_global_dtors_loop
-#else
-	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
-.L__do_global_dtors_start:
-	cpi	r28, lo8(__dtors_end)
-	cpc	r29, r17
-	brne	.L__do_global_dtors_loop
-#endif /* defined(__AVR_HAVE_ELPM__) */
+    cpi     r28, pm_lo8(__dtors_end)
+    cpc     r29, r17
+#ifdef __AVR_HAVE_EIJMP_EICALL__
+    ldi     r24, pm_hh8(__dtors_end)
+    cpc     r16, r24
+#endif /* HAVE_EIJMP */
+    brne    .L__do_global_dtors_loop
 ENDF __do_global_dtors
 #endif /* L_dtors */
 
 .section .text.libgcc, "ax", @progbits
 
-#ifdef L_tablejump_elpm
-DEFUN __tablejump_elpm__
-#if defined (__AVR_HAVE_ELPMX__)
-	elpm	__tmp_reg__, Z+
-	elpm	r31, Z
-	mov	r30, __tmp_reg__
-#if defined (__AVR_HAVE_RAMPD__)
-	;; Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM
-	out	__RAMPZ__, __zero_reg__
-#endif /* RAMPD */
-#if defined (__AVR_HAVE_EIJMP_EICALL__)
-	eijmp
-#else
-	ijmp
-#endif
-
-#elif defined (__AVR_HAVE_ELPM__)
-	elpm
-	adiw	r30, 1
-	push	r0
-	elpm
-	push	r0
-#if defined (__AVR_HAVE_EIJMP_EICALL__)
-	in      __tmp_reg__, __EIND__
-	push    __tmp_reg__
-#endif
-	ret
-#endif
-ENDF __tablejump_elpm__
-#endif /* defined (L_tablejump_elpm) */
-
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Loading n bytes from Flash; n = 3,4
 ;; R22... = Flash[Z]
Index: libgcc/config/avr/t-avr
===================================================================
--- libgcc/config/avr/t-avr	(revision 214897)
+++ libgcc/config/avr/t-avr	(working copy)
@@ -26,8 +26,7 @@ LIB1ASMFUNCS = \
 	_epilogue \
 	_exit \
 	_cleanup \
-	_tablejump \
-	_tablejump_elpm \
+	_tablejump2 \
 	_load_3 _load_4 \
 	_xload_1 _xload_2 _xload_3 _xload_4 \
 	_movmemx \

Reply via email to