re PR target/63223 ([avr] Make jumptables work with -Wl,--section-start,.text=)
authorGeorg-Johann Lay <avr@gjlay.de>
Thu, 11 Sep 2014 08:08:17 +0000 (08:08 +0000)
committerGeorg-Johann Lay <gjl@gcc.gnu.org>
Thu, 11 Sep 2014 08:08:17 +0000 (08:08 +0000)
gcc/
PR target/63223
* 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/
PR target/63223
* 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.

From-SVN: r215152

gcc/ChangeLog
gcc/config/avr/avr.md
libgcc/ChangeLog
libgcc/config/avr/lib1funcs.S
libgcc/config/avr/t-avr

index 747dbfcb28abcb06ba165569dfaa7346eb93de5c..014014a8c148663f21b9b16476a40dd301fd355c 100644 (file)
@@ -1,3 +1,10 @@
+2014-09-11  Georg-Johann Lay  <avr@gjlay.de>
+
+       PR target/63223
+       * 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.
+
 2014-09-11  Alexander Ivchenko  <alexander.ivchenko@intel.com>
            Maxim Kuznetsov  <maxim.kuznetsov@intel.com>
            Anna Tikhonova  <anna.tikhonova@intel.com>
index a959b9bb7fa74ee7bb03027d4de3e4f1ca96bc21..ecedbbd96b0f35a2afa98c478e9b9cbe19e2584c 100644 (file)
         (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
    (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)
                       (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 317dc29b98519873ca37bf9ab8d22e2d4676ace7..a63f08e7ba6d6fb175b269fbeb448856b6766a17 100644 (file)
@@ -1,3 +1,14 @@
+2014-09-11  Georg-Johann Lay  <avr@gjlay.de>
+
+       PR target/63223
+       * 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.
+
 2014-09-09  Marcus Shawcroft  <marcus.shawcroft@arm.com>
        Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
 
index 6f1c77edbe30d30d1e6b25dbd2815439fbaa10ab..080e250cd616318549388ac24e2a0a9a18bcac80 100644 (file)
@@ -46,6 +46,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
            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 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #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:
 \f
 .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
-       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_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__
-.L__do_global_ctors_start:
-       cpi     r28, lo8(__ctors_start)
-       cpc     r29, r17
-       brne    .L__do_global_ctors_loop
-#endif /* defined(__AVR_HAVE_ELPM__) */
+    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
 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_start)
+    ldi     r28, pm_lo8(__dtors_end)
+    ldi     r29, pm_hi8(__dtors_end)
+#ifdef __AVR_HAVE_EIJMP_EICALL__
+    ldi     r16, pm_hh8(__dtors_end)
+#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_start)
+    cpc     r29, r17
+#ifdef __AVR_HAVE_EIJMP_EICALL__
+    ldi     r24, pm_hh8(__dtors_start)
+    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 461304706d948475e00f27b99c51324354de6651..1f7356968aacb4993b33882ee13a2c914a34d553 100644 (file)
@@ -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 \