File: setjmp.S

package info (click to toggle)
avr-libc 20020203-2
  • links: PTS
  • area: main
  • in suites: woody
  • size: 1,448 kB
  • ctags: 6,562
  • sloc: ansic: 7,631; asm: 4,424; sh: 2,703; makefile: 338; pascal: 289
file content (151 lines) | stat: -rw-r--r-- 3,184 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
   setjmp.S

   Contributors:
     Created by Marek Michalkiewicz <marekm@linux.org.pl>

   THIS SOFTWARE IS NOT COPYRIGHTED

   This source code is offered for use in the public domain.  You may
   use, modify or distribute it freely.

   This code is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY.  ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
   DISCLAIMED.  This includes but is not limited to warranties of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */

/*
   jmp_buf:
	offset	size	description
	 0	16	call-saved registers (r2-r17)
	16	 2	frame pointer (r29:r28)
	18	 2	stack pointer (SPH:SPL)
	20	 1	status register (SREG)
	21	 3	return address (PC) (2 bytes used for <=128K flash)
	24 = total size

int setjmp(jmp_buf __jmpb);
void longjmp(jmp_buf __jmpb, int __val) __attribute__((noreturn));
 */

#include "macros.inc"
#include "ctoasm.inc"

/* the same library is used for 2313 and 8515 for now -
   I hope writing 0 to non-existent SPH doesn't hurt... */
#ifndef SPH
#define SPH (SPL+1)
#endif

#define jmpb_hi	rP0
#define jmpb_lo	rP1
#define val_hi	rP2
#define val_lo	rP3

#define ret_lo rP1  /* r24 */
#define ret_hi rP0  /* r25 */

	.section .text

	.global _U(setjmp)
	.global _U(longjmp)

_U(setjmp):
	LOAD_Z(jmpb_lo, jmpb_hi)
	in	XL, SPL
	in	XH, SPH
	/* save program counter (return address) */
	/* return address on stack (pushed by "call") is big endian! */
	/* SP is post-decremented by "call" */
	adiw	XL, 1
#ifdef EIND  /* devices with >128K bytes of flash - none yet */
	ld	__tmp_reg__, X+
	std	Z+23, __tmp_reg__
#endif
	ld	__tmp_reg__, X+
	std	Z+22, __tmp_reg__
	ld	__tmp_reg__, X
	std	Z+21, __tmp_reg__
	/* save stack pointer (SP value before calling this function) */
	std	Z+18, XL
	std	Z+19, XH
	/* save status register (I flag) */
	in	__tmp_reg__, SREG
	std	Z+20, __tmp_reg__
	/* save call-saved registers */
	st	Z, r2
	std	Z+1, r3
	std	Z+2, r4
	std	Z+3, r5
	std	Z+4, r6
	std	Z+5, r7
	std	Z+6, r8
	std	Z+7, r9
	std	Z+8, r10
	std	Z+9, r11
	std	Z+10, r12
	std	Z+11, r13
	std	Z+12, r14
	std	Z+13, r15
	std	Z+14, r16
	std	Z+15, r17
	/* save frame pointer */
	std	Z+16, YL
	std	Z+17, YH
	/* return zero */
	clr	ret_lo
	clr	ret_hi
	ret

_U(longjmp):
	LOAD_X(jmpb_lo, jmpb_hi)
	/* return value */
	mov	ret_lo, val_lo
	mov	ret_hi, val_hi
	/* if zero, change to 1 */
	cpi	ret_lo, 1
	cpc	ret_hi, __zero_reg__
	adc	ret_lo, __zero_reg__
	/* restore call-saved registers */
	ld	r2, X+
	ld	r3, X+
	ld	r4, X+
	ld	r5, X+
	ld	r6, X+
	ld	r7, X+
	ld	r8, X+
	ld	r9, X+
	ld	r10, X+
	ld	r11, X+
	ld	r12, X+
	ld	r13, X+
	ld	r14, X+
	ld	r15, X+
	ld	r16, X+
	ld	r17, X+
	/* restore frame pointer */
	ld	YL, X+
	ld	YH, X+
	/* restore stack pointer (SP value before the setjmp() call) */
	ld	ZL, X+
	ld	ZH, X+
	ld	__tmp_reg__, X+
	/* interrupts disabled for shortest possible time (3 cycles) */
	cli
	out	SPH, ZH
	/* Restore status register (including the interrupt enable flag).
	   Interrupts are re-enabled only after the next instruction.  */
	out	SREG, __tmp_reg__
	out	SPL, ZL
	/* restore return address */
	ld	ZL, X+
	ld	ZH, X+
#ifdef EIND
	ld	__tmp_reg__, X
	out	EIND, __tmp_reg__
	.word	0x9419  /* eijmp */
#else
	ijmp
#endif