117 lines
2.9 KiB
ArmAsm
117 lines
2.9 KiB
ArmAsm
/*!
|
|
* \file
|
|
* <!--
|
|
* This file is part of BeRTOS.
|
|
*
|
|
* Bertos is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
* As a special exception, you may use this file as part of a free software
|
|
* library without restriction. Specifically, if other files instantiate
|
|
* templates or use macros or inline functions from this file, or you compile
|
|
* this file and link it with other files to produce an executable, this
|
|
* file does not by itself cause the resulting executable to be covered by
|
|
* the GNU General Public License. This exception does not however
|
|
* invalidate any other reasons why the executable file might be covered by
|
|
* the GNU General Public License.
|
|
*
|
|
* Copyright 2004, 2008 Develer S.r.l. (http://www.develer.com/)
|
|
* Copyright 1999, 2000, 2001 Bernie Innocenti <bernie@codewiz.org>
|
|
* -->
|
|
*
|
|
* \author Bernie Innocenti <bernie@codewiz.org>
|
|
* \author Stefano Fedrigo <aleph@develer.com>
|
|
*
|
|
* \brief AVR context switch
|
|
*
|
|
*/
|
|
|
|
#include <avr/io.h>
|
|
|
|
/* void asm_switch_context(void **new_sp [r24:r25], void **save_sp [r22:r23]) */
|
|
.globl asm_switch_context
|
|
asm_switch_context:
|
|
|
|
; r0 is the TEMP REG and can be used freely.
|
|
; r1 is the ZERO REG and must always contain 0.
|
|
;
|
|
; Stack frame is 18 byte, remember to update
|
|
; CPU_SAVED_REGS_CNT if you change pushed regs.
|
|
|
|
push r2
|
|
push r3
|
|
push r4
|
|
push r5
|
|
push r6
|
|
push r7
|
|
push r8
|
|
push r9
|
|
push r10
|
|
push r11
|
|
push r12
|
|
push r13
|
|
push r14
|
|
push r15
|
|
push r16
|
|
push r17
|
|
|
|
push r28
|
|
push r29
|
|
|
|
in r18,SPL-__SFR_OFFSET ; r18:r19 = SP
|
|
in r19,SPH-__SFR_OFFSET
|
|
movw r26,r22 ; X = save_sp
|
|
st X+,r18 ; *save_sp = SP
|
|
st X,r19
|
|
movw r26,r24 ; X = new_sp
|
|
ld r18,X+
|
|
ld r19,X
|
|
|
|
;FIXME: We probably need to safe the RAMP registers for some XMEGA devices / setups
|
|
|
|
; Set new stack pointer.
|
|
; AVR is an 8 bit processor so
|
|
; care must be taken when updating
|
|
; SP that is a 16 bit reg.
|
|
; Two instructions are required to update SP
|
|
; so an IRQ can sneak in between them.
|
|
; So IRQ *MUST* be disabled and then restored.
|
|
in r0, SREG-__SFR_OFFSET
|
|
cli ; Disable interrupt
|
|
out SPL-__SFR_OFFSET,r18 ; SP = *new_sp
|
|
out SPH-__SFR_OFFSET,r19
|
|
out SREG-__SFR_OFFSET,r0 ; Restore previous IRQ state
|
|
|
|
pop r29
|
|
pop r28
|
|
|
|
pop r17
|
|
pop r16
|
|
pop r15
|
|
pop r14
|
|
pop r13
|
|
pop r12
|
|
pop r11
|
|
pop r10
|
|
pop r9
|
|
pop r8
|
|
pop r7
|
|
pop r6
|
|
pop r5
|
|
pop r4
|
|
pop r3
|
|
pop r2
|
|
|
|
ret
|