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
This commit is contained in:
Georg-Johann Lay 2014-09-11 08:08:17 +00:00 committed by Georg-Johann Lay
parent c883e5fb6a
commit ea3f2b240f
5 changed files with 156 additions and 136 deletions

View 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>

View File

@ -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];
}
})

View 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>

View 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:
.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
;; 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
;; 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
ijmp
lpm
push r0
adiw r30, 1
lpm
push r0
ret
#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__
#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]

View 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 \