Merge branch "preempt" in "trunk".
[bertos.git] / bertos / cpu / avr / hw / switch_ctx_avr.S
1 /*!
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2004, 2008 Develer S.r.l. (http://www.develer.com/)
30  * Copyright 1999, 2000, 2001 Bernie Innocenti <bernie@codewiz.org>
31  * -->
32  *
33  * \version $Id$
34  * \author Bernie Innocenti <bernie@codewiz.org>
35  * \author Stefano Fedrigo <aleph@develer.com>
36  *
37  * \brief AVR context switch
38  *
39  */
40
41 #include <avr/io.h>
42
43 /* void asm_switch_context(void **new_sp [r24:r25], void **save_sp [r22:r23]) */
44 .globl asm_switch_context
45 asm_switch_context:
46
47 ;       r0 is the TEMP REG and can be used freely.
48 ;       r1 is the ZERO REG and must always contain 0.
49 ;
50 ;       Stack frame is 18 byte, remember to update
51 ;       CPU_SAVED_REGS_CNT if you change pushed regs.
52
53         push    r2
54         push    r3
55         push    r4
56         push    r5
57         push    r6
58         push    r7
59         push    r8
60         push    r9
61         push    r10
62         push    r11
63         push    r12
64         push    r13
65         push    r14
66         push    r15
67         push    r16
68         push    r17
69
70         push    r28
71         push    r29
72
73         in      r18,SPL-__SFR_OFFSET    ; r18:r19 = SP
74         in      r19,SPH-__SFR_OFFSET
75         movw    r26,r22                 ; X = save_sp
76         st      X+,r18                  ; *save_sp = SP
77         st      X,r19
78         movw    r26,r24                 ; X = new_sp
79         ld      r18,X+
80         ld      r19,X
81
82 ;       Set new stack pointer.
83 ;       AVR is an 8 bit processor so
84 ;       care must be taken when updating
85 ;       SP that is a 16 bit reg.
86 ;       Two instructions are required to update SP
87 ;       so an IRQ can sneak in between them.
88 ;       So IRQ *MUST* be disabled and then restored.
89         in      r0, SREG-__SFR_OFFSET
90         cli                             ; Disable interrupt
91         out     SPL-__SFR_OFFSET,r18    ; SP = *new_sp
92         out     SPH-__SFR_OFFSET,r19
93         out     SREG-__SFR_OFFSET,r0    ; Restore previous IRQ state
94
95         pop     r29
96         pop     r28
97
98         pop     r17
99         pop     r16
100         pop     r15
101         pop     r14
102         pop     r13
103         pop     r12
104         pop     r11
105         pop     r10
106         pop     r9
107         pop     r8
108         pop     r7
109         pop     r6
110         pop     r5
111         pop     r4
112         pop     r3
113         pop     r2
114
115         ret