This patch adds support to consistently use EIND. The compiler never sets this SFR but uses it in table jumps and EIJMP/EICALL instructions.
Custom startup code could set EIND to an other value than 0 and the compiler should use EIND consistently given that EIND might not be zero. EIND != 0 will need support of custom linker script to locate jump pads in an other segment, but that's a different story. The patch undoes some changes from r179760 and introduces using EIND the other way round: Not trying to avoid EIND altogether and assume code is supposed to work in the lower segment only, but instead use EIND and not zero-reg when simulating indirect jump by means of RET. With this patch, the application may set EIND to a custom value and invent own linker script to place jump pads. The assertion is that EIND never changes throughout the application and therefore ISR prologue/epilogue need not care. With the gs() magic, code using indirect jumps works fine with that, e.g. - Indirect calls - Computed goto - Jumping to 1: in prologue_saves What does not work as expected is to jump to const_int addresses like int main() { ((void(*)(void))0)(); return 0; } Instead, code must read extern void my_address (void); int main() { my_address(); return 0; } and compiled with, say -Wl,--defsym,my_address=0x20000, so that a jump pad is generated. Patch ok for trunk? Johann * config/avr/libgcc.S (__EIND__): New define to 0x3C. (__tablejump__): Consistently use EIND for indirect jump/call. (__tablejump_elpm__): Ditto. Index: config/avr/libgcc.S =================================================================== --- config/avr/libgcc.S (revision 180262) +++ config/avr/libgcc.S (working copy) @@ -28,6 +28,7 @@ see the files COPYING3 and COPYING.RUNTI #define __SP_H__ 0x3e #define __SP_L__ 0x3d #define __RAMPZ__ 0x3B +#define __EIND__ 0x3C /* Most of the functions here are called directly from avr.md patterns, instead of using the standard libcall mechanisms. @@ -821,17 +822,12 @@ ENDF __tablejump2__ DEFUN __tablejump__ #if defined (__AVR_HAVE_LPMX__) -#if defined (__AVR_HAVE_EIJMP_EICALL__) - lpm __tmp_reg__, Z+ - push __tmp_reg__ - lpm __tmp_reg__, Z - push __tmp_reg__ - push __zero_reg__ - ret -#else lpm __tmp_reg__, Z+ lpm r31, Z mov r30, __tmp_reg__ +#if defined (__AVR_HAVE_EIJMP_EICALL__) + eijmp +#else ijmp #endif @@ -842,7 +838,8 @@ DEFUN __tablejump__ lpm push r0 #if defined (__AVR_HAVE_EIJMP_EICALL__) - push __zero_reg__ + in __tmp_reg__, __EIND__ + push __tmp_reg__ #endif ret #endif /* !HAVE_LPMX */ @@ -1034,7 +1031,8 @@ DEFUN __tablejump_elpm__ elpm push r0 #if defined (__AVR_HAVE_EIJMP_EICALL__) - push __zero_reg__ + in __tmp_reg__, __EIND__ + push __tmp_reg__ #endif ret #endif