264 lines
8.2 KiB
ArmAsm
264 lines
8.2 KiB
ArmAsm
/* $NetBSD: _context_u.S,v 1.4 2003/03/26 22:33:56 scw Exp $ */
|
|
|
|
/*
|
|
* Copyright 2003 Wasabi Systems, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* Written by Steve C. Woodford for Wasabi Systems, Inc.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed for the NetBSD Project by
|
|
* Wasabi Systems, Inc.
|
|
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
|
|
* or promote products derived from this software without specific prior
|
|
* written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <machine/asm.h>
|
|
#include "assym.h"
|
|
|
|
/*
|
|
* Save the current context into the ucontext_t structure pointed to r2.
|
|
*
|
|
* We only need to save the `callee' saved registers.
|
|
* Assumes the PC value to save is in r18.
|
|
*
|
|
* Clobbers r0, r1 and r3
|
|
*
|
|
* XXX: Will need to be revisited in order to support FPU-less cores.
|
|
*/
|
|
#define GETC \
|
|
st.q r2, UC_REGS_PC, r18 ;\
|
|
st.q r2, UC_REGS_R2, r63 ;\
|
|
st.q r2, UC_REGS_R10, r10 ;\
|
|
st.q r2, UC_REGS_R11, r11 ;\
|
|
st.q r2, UC_REGS_R12, r12 ;\
|
|
st.q r2, UC_REGS_R13, r13 ;\
|
|
st.q r2, UC_REGS_R14, r14 ;\
|
|
st.q r2, UC_REGS_SP, r15 ;\
|
|
st.q r2, UC_REGS_R18, r18 ;\
|
|
st.q r2, UC_REGS_R26, r26 ;\
|
|
st.q r2, UC_REGS_R27, r27 ;\
|
|
st.q r2, UC_REGS_R28, r28 ;\
|
|
st.q r2, UC_REGS_R29, r29 ;\
|
|
st.q r2, UC_REGS_R30, r30 ;\
|
|
st.q r2, UC_REGS_R31, r31 ;\
|
|
st.q r2, UC_REGS_R32, r32 ;\
|
|
st.q r2, UC_REGS_R33, r33 ;\
|
|
st.q r2, UC_REGS_R34, r34 ;\
|
|
st.q r2, UC_REGS_R35, r35 ;\
|
|
st.q r2, UC_REGS_R44, r44 ;\
|
|
st.q r2, UC_REGS_R45, r45 ;\
|
|
st.q r2, UC_REGS_R46, r46 ;\
|
|
st.q r2, UC_REGS_R47, r47 ;\
|
|
st.q r2, UC_REGS_R48, r48 ;\
|
|
st.q r2, UC_REGS_R49, r49 ;\
|
|
st.q r2, UC_REGS_R50, r50 ;\
|
|
st.q r2, UC_REGS_R51, r51 ;\
|
|
st.q r2, UC_REGS_R52, r52 ;\
|
|
st.q r2, UC_REGS_R53, r53 ;\
|
|
st.q r2, UC_REGS_R54, r54 ;\
|
|
st.q r2, UC_REGS_R55, r55 ;\
|
|
st.q r2, UC_REGS_R56, r56 ;\
|
|
st.q r2, UC_REGS_R57, r57 ;\
|
|
st.q r2, UC_REGS_R58, r58 ;\
|
|
st.q r2, UC_REGS_R59, r59 ;\
|
|
getcon usr, r1 ;\
|
|
gettr tr5, r0 ;\
|
|
st.q r2, UC_REGS_TR5, r0 ;\
|
|
gettr tr6, r0 ;\
|
|
st.q r2, UC_REGS_TR6, r0 ;\
|
|
gettr tr7, r0 ;\
|
|
st.q r2, UC_REGS_TR7, r0 ;\
|
|
pta/l 4f, tr0 ;\
|
|
st.q r2, UC_REGS_USR, r1 ;\
|
|
fgetscr fr0 ;\
|
|
shlri r1, SH5_CONREG_USR_FPRS_SHIFT, r1 ;\
|
|
LDC32((_UC_CPU | _UC_USER), r3) ;\
|
|
andi r1, SH5_CONREG_USR_FPRS_MASK, r0 ;\
|
|
fst.s r2, UC_FPREGS_FPSCR, fr0 ;\
|
|
beq/l r0, r63, tr0 ;\
|
|
fst.d r2, UC_FPREGS_DR12, dr12 ;\
|
|
fst.d r2, UC_FPREGS_DR14, dr14 ;\
|
|
fst.d r2, UC_FPREGS_DR36, dr36 ;\
|
|
fst.d r2, UC_FPREGS_DR38, dr38 ;\
|
|
pta/l 1f, tr0 ;\
|
|
andi r1, 0x20, r0 ;\
|
|
beq/l r0, r63, tr0 ;\
|
|
fst.d r2, UC_FPREGS_DR40, dr40 ;\
|
|
fst.d r2, UC_FPREGS_DR42, dr42 ;\
|
|
fst.d r2, UC_FPREGS_DR44, dr44 ;\
|
|
fst.d r2, UC_FPREGS_DR46, dr46 ;\
|
|
1: pta/l 2f, tr0 ;\
|
|
andi r1, 0x40, r0 ;\
|
|
beq/l r0, r63, tr0 ;\
|
|
fst.d r2, UC_FPREGS_DR48, dr48 ;\
|
|
fst.d r2, UC_FPREGS_DR50, dr50 ;\
|
|
fst.d r2, UC_FPREGS_DR52, dr52 ;\
|
|
fst.d r2, UC_FPREGS_DR54, dr54 ;\
|
|
2: pta/l 3f, tr0 ;\
|
|
andi r1, 0x80, r0 ;\
|
|
beq/l r0, r63, tr0 ;\
|
|
fst.d r2, UC_FPREGS_DR56, dr56 ;\
|
|
fst.d r2, UC_FPREGS_DR58, dr58 ;\
|
|
fst.d r2, UC_FPREGS_DR60, dr60 ;\
|
|
fst.d r2, UC_FPREGS_DR62, dr62 ;\
|
|
3: ori r3, _UC_FPU, r3 ;\
|
|
4: ld.q r2, UC_REGS_USR, r1 ;\
|
|
st.l r2, UC_FLAGS, r3 ;\
|
|
putcon r1, usr
|
|
|
|
/*
|
|
* Restore the context pointed to by r2
|
|
*/
|
|
#define SETC \
|
|
/* \
|
|
* If _UC_USER is set, we only need to restore \
|
|
* the callee-saved set. If not, we have no \
|
|
* choice but to defer to the setcontext(2) \
|
|
* system call as we can't do it ourselves. \
|
|
* (Actually, we can restore everything except \
|
|
* for the branch target register we use to \
|
|
* jump to the new context. Which just isn't \
|
|
* quite good enough. Sigh.) \
|
|
*/ \
|
|
ld.l r2, UC_FLAGS, r3 ;\
|
|
ld.q r2, UC_REGS_R10, r10 ;\
|
|
shlri r3, _UC_USER_BIT, r0 ;\
|
|
ld.q r2, UC_REGS_R11, r11 ;\
|
|
andi r0, 1, r0 ;\
|
|
pta/u 4f, tr0 ;\
|
|
ld.q r2, UC_REGS_R12, r12 ;\
|
|
beq/u r0, r63, tr0 ;\
|
|
ld.q r2, UC_REGS_R13, r13 ;\
|
|
ld.q r2, UC_REGS_R14, r14 ;\
|
|
ld.q r2, UC_REGS_R18, r18 ;\
|
|
ld.q r2, UC_REGS_R26, r26 ;\
|
|
ld.q r2, UC_REGS_R27, r27 ;\
|
|
ld.q r2, UC_REGS_R28, r28 ;\
|
|
ld.q r2, UC_REGS_R29, r29 ;\
|
|
ld.q r2, UC_REGS_R30, r30 ;\
|
|
ld.q r2, UC_REGS_R31, r31 ;\
|
|
ld.q r2, UC_REGS_R32, r32 ;\
|
|
ld.q r2, UC_REGS_R33, r33 ;\
|
|
ld.q r2, UC_REGS_R34, r34 ;\
|
|
ld.q r2, UC_REGS_R35, r35 ;\
|
|
ld.q r2, UC_REGS_R44, r44 ;\
|
|
ld.q r2, UC_REGS_R45, r45 ;\
|
|
ld.q r2, UC_REGS_R46, r46 ;\
|
|
ld.q r2, UC_REGS_R47, r47 ;\
|
|
ld.q r2, UC_REGS_R48, r48 ;\
|
|
ld.q r2, UC_REGS_R49, r49 ;\
|
|
ld.q r2, UC_REGS_R50, r50 ;\
|
|
ld.q r2, UC_REGS_R51, r51 ;\
|
|
ld.q r2, UC_REGS_R52, r52 ;\
|
|
ld.q r2, UC_REGS_R53, r53 ;\
|
|
ld.q r2, UC_REGS_R54, r54 ;\
|
|
ld.q r2, UC_REGS_R55, r55 ;\
|
|
ld.q r2, UC_REGS_R56, r56 ;\
|
|
ld.q r2, UC_REGS_R57, r57 ;\
|
|
ld.q r2, UC_REGS_R58, r58 ;\
|
|
ld.q r2, UC_REGS_R59, r59 ;\
|
|
ld.q r2, UC_REGS_TR5, r0 ;\
|
|
ptabs/u r0, tr5 ;\
|
|
ld.q r2, UC_REGS_TR6, r0 ;\
|
|
ptabs/u r0, tr6 ;\
|
|
ld.q r2, UC_REGS_TR7, r0 ;\
|
|
pta/l 3f, tr0 ;\
|
|
ptabs/u r0, tr7 ;\
|
|
andi r3, _UC_FPU, r0 ;\
|
|
ld.q r2, UC_REGS_USR, r3 ;\
|
|
beq/l r0, r63, tr0 ;\
|
|
shlri r3, SH5_CONREG_USR_FPRS_SHIFT, r1 ;\
|
|
fld.d r2, UC_FPREGS_DR12, dr12 ;\
|
|
fld.d r2, UC_FPREGS_DR14, dr14 ;\
|
|
fld.d r2, UC_FPREGS_DR36, dr36 ;\
|
|
fld.d r2, UC_FPREGS_DR38, dr38 ;\
|
|
pta/l 1f, tr0 ;\
|
|
andi r1, 0x20, r0 ;\
|
|
beq/l r0, r63, tr0 ;\
|
|
fld.d r2, UC_FPREGS_DR40, dr40 ;\
|
|
fld.d r2, UC_FPREGS_DR42, dr42 ;\
|
|
fld.d r2, UC_FPREGS_DR44, dr44 ;\
|
|
fld.d r2, UC_FPREGS_DR46, dr46 ;\
|
|
1: pta/l 2f, tr0 ;\
|
|
andi r1, 0x40, r0 ;\
|
|
beq/l r0, r63, tr0 ;\
|
|
fld.d r2, UC_FPREGS_DR48, dr48 ;\
|
|
fld.d r2, UC_FPREGS_DR50, dr50 ;\
|
|
fld.d r2, UC_FPREGS_DR52, dr52 ;\
|
|
fld.d r2, UC_FPREGS_DR54, dr54 ;\
|
|
2: pta/l 3f, tr0 ;\
|
|
andi r1, 0x80, r0 ;\
|
|
beq/l r0, r63, tr0 ;\
|
|
fld.d r2, UC_FPREGS_DR56, dr56 ;\
|
|
fld.d r2, UC_FPREGS_DR58, dr58 ;\
|
|
fld.d r2, UC_FPREGS_DR60, dr60 ;\
|
|
fld.d r2, UC_FPREGS_DR62, dr62 ;\
|
|
3: fld.s r2, UC_FPREGS_FPSCR, fr0 ;\
|
|
ld.q r2, UC_REGS_PC, r0 ;\
|
|
ld.q r2, UC_REGS_SP, r15 ;\
|
|
ptabs/l r0, tr0 ;\
|
|
fputscr fr0 ;\
|
|
putcon r3, usr ;\
|
|
blink tr0, r63 ;\
|
|
\
|
|
/* ! _UC_USER case. Restore full context */ \
|
|
\
|
|
4: PIC_GET_GOT(tr0) ;\
|
|
PIC_PTAL(_C_LABEL(setcontext), r0, tr0) ;\
|
|
blink tr0, r18 ;\
|
|
brk /* Catch setcontext() failure */
|
|
|
|
|
|
/*
|
|
* int _getcontext_u(ucontext_t *ctx)
|
|
* Store the current context in the provided ctx structure.
|
|
*/
|
|
ENTRY_NOPROFILE(_getcontext_u)
|
|
GETC
|
|
ptabs/l r18, tr0
|
|
movi 0, r2
|
|
blink tr0, r63
|
|
|
|
/*
|
|
* int _setcontext_u(const ucontext_t *ctx)
|
|
* Make the context stored in ctx current.
|
|
*/
|
|
ENTRY_NOPROFILE(_setcontext_u)
|
|
SETC
|
|
/* NOTREACHED */
|
|
|
|
/*
|
|
* int _swapcontext_u(ucontext_t *from, const ucontext_t *to)
|
|
* Save the current context in `from' before switching to the
|
|
* new context in `to'.
|
|
*/
|
|
ENTRY_NOPROFILE(_swapcontext_u)
|
|
or r3, r63, r5 /* Save 'to' in a safe place */
|
|
GETC
|
|
or r5, r63, r2 /* Restore 'to' */
|
|
SETC
|
|
/* NOTREACHED */
|