MicroAPRS/bertos/cpu/avr/hw/switch_ctx_avr.S

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