Hi, Here are some patches. Please take a look and tell me if what I did with setjmp makes any sense. I don't really use longjmp so it's not fully tested, and it is only to handle a case which is very difficult to create.
I have tested the gcc patch and my program is working very well now. There is still a major issue of what to do in bootloaders. It appears that the trampolines do not get generated for bootloaders.. and how can they? For bootloaders the compiler should use eijmp and eicall and set EIND to the bootloader segment at startup. But what if longjmp is used and what if application code is called? I'm not sure what the best solution is here, but currently I'm just glad my bootloader doesn't need indirect jumps. Sean
Index: gcc/config/avr/libgcc.S =================================================================== --- gcc/config/avr/libgcc.S (revision 147314) +++ gcc/config/avr/libgcc.S (working copy) @@ -590,11 +642,7 @@ __prologue_saves__: out __SP_H__,r29 out __SREG__,__tmp_reg__ out __SP_L__,r28 -#if defined (__AVR_HAVE_EIJMP_EICALL__) - eijmp -#else ijmp -#endif .endfunc #endif /* defined (L_prologue) */ @@ -675,12 +723,7 @@ __tablejump__: lpm __tmp_reg__, Z+ lpm r31, Z mov r30, __tmp_reg__ - -#if defined (__AVR_HAVE_EIJMP_EICALL__) - eijmp -#else ijmp -#endif #else lpm @@ -688,7 +731,7 @@ __tablejump__: push r0 lpm push r0 -#if defined (__AVR_HAVE_EIJMP_EICALL__) +#if defined (__AVR_3_BYTE_PC__) push __zero_reg__ #endif ret @@ -876,19 +919,14 @@ __tablejump_elpm__: elpm __tmp_reg__, Z+ elpm r31, Z mov r30, __tmp_reg__ -#if defined (__AVR_HAVE_EIJMP_EICALL__) - eijmp -#else ijmp -#endif - #else elpm adiw r30, 1 push r0 elpm push r0 -#if defined (__AVR_HAVE_EIJMP_EICALL__) +#if defined (__AVR_3_BYTE_PC__) push __zero_reg__ #endif ret Index: gcc/config/avr/avr.md =================================================================== --- gcc/config/avr/avr.md (revision 147314) +++ gcc/config/avr/avr.md (working copy) @@ -2741,22 +2823,22 @@ (define_insn "call_insn" "(register_operand (operands[0], HImode) || CONSTANT_P (operands[0]))" "*{ if (which_alternative==0) - return \"%!icall\"; + return \"icall\"; else if (which_alternative==1) { if (AVR_HAVE_MOVW) return (AS2 (movw, r30, %0) CR_TAB - \"%!icall\"); + \"icall\"); else return (AS2 (mov, r30, %A0) CR_TAB AS2 (mov, r31, %B0) CR_TAB - \"%!icall\"); + \"icall\"); } else if (which_alternative==2) return AS1(%~call,%c0); return (AS2 (ldi,r30,lo8(%0)) CR_TAB AS2 (ldi,r31,hi8(%0)) CR_TAB - \"%!icall\"); + \"icall\"); }" [(set_attr "cc" "clobber,clobber,clobber,clobber") (set_attr_alternative "length" @@ -2778,22 +2860,22 @@ (define_insn "call_value_insn" "(register_operand (operands[0], VOIDmode) || CONSTANT_P (operands[0]))" "*{ if (which_alternative==0) - return \"%!icall\"; + return \"icall\"; else if (which_alternative==1) { if (AVR_HAVE_MOVW) return (AS2 (movw, r30, %1) CR_TAB - \"%!icall\"); + \"icall\"); else return (AS2 (mov, r30, %A1) CR_TAB AS2 (mov, r31, %B1) CR_TAB - \"%!icall\"); + \"icall\"); } else if (which_alternative==2) return AS1(%~call,%c1); return (AS2 (ldi, r30, lo8(%1)) CR_TAB AS2 (ldi, r31, hi8(%1)) CR_TAB - \"%!icall\"); + \"icall\"); }" [(set_attr "cc" "clobber,clobber,clobber,clobber") (set_attr_alternative "length" @@ -2816,20 +2898,13 @@ (define_insn "nop" ; indirect jump (define_insn "indirect_jump" [(set (pc) (match_operand:HI 0 "register_operand" "!z,*r"))] - "!AVR_HAVE_EIJMP_EICALL" + "" "@ ijmp push %A0\;push %B0\;ret" [(set_attr "length" "1,3") (set_attr "cc" "none,none")]) -(define_insn "*indirect_jump_avr6" - [(set (pc) (match_operand:HI 0 "register_operand" "z"))] - "AVR_HAVE_EIJMP_EICALL" - "eijmp" - [(set_attr "length" "1") - (set_attr "cc" "none")]) - ;; table jump ;; Table made from "rjmp" instructions for <=8K devices. @@ -2867,7 +2942,7 @@ (define_insn "*tablejump_enh" lpm __tmp_reg__,Z+ lpm r31,Z mov r30,__tmp_reg__ - %!ijmp" + ijmp" [(set_attr "length" "6") (set_attr "cc" "clobber")])
Index: libc/stdlib/setjmp.S =================================================================== RCS file: /sources/avr-libc/avr-libc/libc/stdlib/setjmp.S,v retrieving revision 1.7 diff -u -r1.7 setjmp.S --- libc/stdlib/setjmp.S 1 Apr 2009 23:11:00 -0000 1.7 +++ libc/stdlib/setjmp.S 10 May 2009 05:36:28 -0000 @@ -155,6 +155,12 @@ #if defined(__AVR_3_BYTE_PC__) && __AVR_3_BYTE_PC__ ld __tmp_reg__, X+ .L_eijmp: + brid .L_eijmp_nointerrupt + cli + out AVR_EXTENDED_INDIRECT_ADDR, __tmp_reg__ + sei + eijmp +.L_eijmp_nointerrupt: out AVR_EXTENDED_INDIRECT_ADDR, __tmp_reg__ eijmp #else
_______________________________________________ AVR-GCC-list mailing list AVR-GCC-list@nongnu.org http://lists.nongnu.org/mailman/listinfo/avr-gcc-list