42
42
16 2 frame pointer (r29:r28)
43
43
18 2 stack pointer (SPH:SPL)
44
44
20 1 status register (SREG)
45
21 3 return address (PC) (2 bytes used for <=128K flash)
45
21 2/3 return address (PC) (2 bytes used for <=128Kw flash)
47
All multibytes are stored as little-endian.
48
int setjmp(jmp_buf __jmpb);
49
void longjmp(jmp_buf __jmpb, int __val) __attribute__((noreturn));
49
int setjmp(jmp_buf __jmpb);
50
void longjmp(jmp_buf __jmpb, int __val) __attribute__((noreturn));
52
56
#include "macros.inc"
55
/* the same library is used for 2313 and 8515 for now -
56
I hope writing 0 to non-existent SPH doesn't hurt... */
58
/* ???: What was a reason to use aliases for common registers?
59
Check the address: is it a port number (value for IN/OUT)? */
60
#if AVR_STACK_POINTER_LO_ADDR != 0x3D \
61
|| AVR_STATUS_ADDR != 0x3F
62
# error "Strange address of common registers SPL, SREG"
66
#define ret_lo rP1 /* r24 */
67
#define ret_hi rP0 /* r25 */
76
.type _U(setjmp), @function
76
in r26, AVR_STACK_POINTER_LO_ADDR
80
; save call-saved registers and frame pointer
81
.irp .L_regno, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,28,29
85
#if defined(__AVR_3_BYTE_PC__) && __AVR_3_BYTE_PC__
86
pop __tmp_reg__ ; used below
90
; save stack pointer (after poping)
91
in ret_lo, AVR_STACK_POINTER_LO_ADDR
77
93
#ifdef _HAVE_AVR_STACK_POINTER_HI
78
in r27, AVR_STACK_POINTER_HI_ADDR
94
in ret_lo, AVR_STACK_POINTER_HI_ADDR
82
/* save program counter (return address) */
83
/* return address on stack (pushed by "call") is big endian! */
84
/* SP is post-decremented by "call" */
86
#ifdef AVR_EXTENDED_INDIRECT_REG /* devices with >128K bytes of flash */
94
/* save stack pointer (SP value before calling this function) */
97
/* save status register (I flag) */
98
in __tmp_reg__, AVR_STATUS_ADDR
100
/* save call-saved registers */
117
/* save frame pointer */
99
; save status register (I flag)
100
in ret_lo, AVR_STATUS_ADDR
102
; save return address
108
#if defined(__AVR_3_BYTE_PC__) && __AVR_3_BYTE_PC__
114
.size _U(setjmp), . - _U(setjmp)
117
.type _U(longjmp), @function
126
120
X_movw XL, jmpb_lo
128
122
X_movw ret_lo, val_lo
129
/* if zero, change to 1 */
123
; if zero, change to 1
131
125
cpc ret_hi, __zero_reg__
132
126
adc ret_lo, __zero_reg__
133
/* restore call-saved registers */
150
/* restore frame pointer */
153
/* restore stack pointer (SP value before the setjmp() call) */
127
; restore call-saved registers and frame pointer
128
.irp .L_regno, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,28,29
131
; restore stack pointer (SP value before the setjmp() call) and SREG
156
134
ld __tmp_reg__, X+
135
#ifdef _HAVE_AVR_STACK_POINTER_HI
157
136
/* interrupts disabled for shortest possible time (3 cycles) */
159
#ifdef _HAVE_AVR_STACK_POINTER_HI
160
out AVR_STACK_POINTER_HI_ADDR, r31
138
out AVR_STACK_POINTER_HI_ADDR, ZH
162
140
/* Restore status register (including the interrupt enable flag).
163
141
Interrupts are re-enabled only after the next instruction. */
164
142
out AVR_STATUS_ADDR, __tmp_reg__
165
out AVR_STACK_POINTER_LO_ADDR, r30
166
/* restore return address */
169
#ifdef AVR_EXTENDED_INDIRECT_REG
143
out AVR_STACK_POINTER_LO_ADDR, ZL
144
; get return address and jump
147
#if defined(__AVR_3_BYTE_PC__) && __AVR_3_BYTE_PC__
171
150
out AVR_EXTENDED_INDIRECT_ADDR, __tmp_reg__
155
.size _U(longjmp), . - _U(longjmp)
157
#endif /* !__DOXYGEN__ */