From ea3f2b240febca348d795e19ba908a34f78b206d Mon Sep 17 00:00:00 2001 From: Georg-Johann Lay Date: Thu, 11 Sep 2014 08:08:17 +0000 Subject: [PATCH] re PR target/63223 ([avr] Make jumptables work with -Wl,--section-start,.text=) 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 | 7 ++ gcc/config/avr/avr.md | 42 ++++++- libgcc/ChangeLog | 11 ++ libgcc/config/avr/lib1funcs.S | 227 +++++++++++++++------------------- libgcc/config/avr/t-avr | 3 +- 5 files changed, 155 insertions(+), 135 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 747dbfcb28a..014014a8c14 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2014-09-11 Georg-Johann Lay + + 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 Maxim Kuznetsov Anna Tikhonova diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index a959b9bb7fa..ecedbbd96b0 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -4932,8 +4932,9 @@ (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 @@ -4942,6 +4943,19 @@ (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) @@ -4959,15 +4973,31 @@ (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]; + } }) diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 317dc29b985..a63f08e7ba6 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,14 @@ +2014-09-11 Georg-Johann Lay + + 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 Ramana Radhakrishnan diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S index 6f1c77edbe3..080e250cd61 100644 --- a/libgcc/config/avr/lib1funcs.S +++ b/libgcc/config/avr/lib1funcs.S @@ -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: .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] diff --git a/libgcc/config/avr/t-avr b/libgcc/config/avr/t-avr index 461304706d9..1f7356968aa 100644 --- a/libgcc/config/avr/t-avr +++ b/libgcc/config/avr/t-avr @@ -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 \ -- 2.30.2