NetBSD/lib/libpthread/arch/sh3/_context_u.S

152 lines
4.7 KiB
ArmAsm

/* $NetBSD: _context_u.S,v 1.1 2003/06/23 19:34:43 uwe Exp $ */
/*
* Copyright (c) 2003 Christian P. Groessler
* All rights reserved.
*
* 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. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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"
/*
* Only save/restore registers that are callee saved, i.e for which
* gcc has call_used_regs[reg] == 0.
*/
#define GETC(uc) \
mov.l .L_uc_gregs_offset, r1 ; \
sts pr, r0 ; \
add uc, r1 /* uc->uc_mcontext.__gregs */ ; \
mov.l r0, @((_REG_PC * 4), r1) ; \
mov.l r0, @((_REG_PR * 4), r1) ; \
\
mov.l r8, @((_REG_R8 * 4), r1) ; \
mov.l r9, @((_REG_R9 * 4), r1) ; \
mov.l r10, @((_REG_R10 * 4), r1) ; \
mov.l r11, @((_REG_R11 * 4), r1) ; \
mov.l r12, @((_REG_R12 * 4), r1) ; \
mov.l r13, @((_REG_R13 * 4), r1) ; \
mov.l r14, @((_REG_R14 * 4), r1) ; \
/* _REG_R15 is too far to use @(disp, Rn) */ \
\
/* in Hitachi calling convention mac regs are callee saved */ \
sts mach, r0 ; \
mov.l r0, @((_REG_MACH * 4), r1) ; \
sts macl, r0 ; \
mov.l r0, @((_REG_MACL * 4), r1) ; \
\
mov.l .L_uc_flags, r0 ; \
\
add #(_REG_R15 * 4), r1 ; \
mov.l r15, @r1 ; \
\
/* XXX: FP registers fr12..fr15? */ \
\
mov.l r0, @(UC_FLAGS, uc)
#define SETC(uc) \
mov.l @(UC_FLAGS, uc), r1 ; \
mov.l .L_uc_user, r0 ; \
tst r0, r1 /* ands and sets T if zero(!) */ ; \
bt/s 1f ; \
/* .empty */ \
\
/* a _UC_USER context */ \
mov.l .L_uc_gregs_offset, r1 ; \
add uc, r1 /* uc->uc_mcontext.__gregs */ ; \
\
mov.l @((_REG_R8 * 4), r1), r8 ; \
mov.l @((_REG_R9 * 4), r1), r9 ; \
mov.l @((_REG_R10 * 4), r1), r10 ; \
mov.l @((_REG_R11 * 4), r1), r11 ; \
mov.l @((_REG_R12 * 4), r1), r12 ; \
mov.l @((_REG_R13 * 4), r1), r13 ; \
mov.l @((_REG_R14 * 4), r1), r14 ; \
/* _REG_R15 is too far to use @(disp, Rn) */ \
\
/* in Hitachi calling convention mac regs are callee saved */ \
mov.l @((_REG_MACH * 4), r1), r0 ; \
mov.l @((_REG_MACL * 4), r1), r2 ; \
lds r0, mach ; \
lds r2, macl ; \
\
/* XXX: FP registers fr12..fr15? */ \
\
mov.l @((_REG_PR * 4), r1), r0 ; \
mov.l @((_REG_PC * 4), r1), r2 ; \
lds r0, pr ; \
add #(_REG_R15 * 4), r1 ; \
jmp @r2 ; \
mov.l @r1, r15 ; \
/* NOTREACHED */ \
\
1: /* not a _UC_USER context, pass to setcontext(2) */ \
mov.l .L_setcontext, r1 ; \
jsr @r1 ; \
.ifc "uc","r4" ; \
nop ; \
.else ; \
mov uc, r4 ; \
.endif ; \
/* NOTREACHED */
/*
* int _getcontext_u(ucontext_t *ctx)
* Store the current context in the provided ctx structure.
*/
NENTRY(_getcontext_u)
GETC(r4) /* r4 - ctx */
rts
mov #0, r0
/*
* int _swapcontext_u(ucontext_t *from, const ucontext_t *to)
* Save the current context in `from' before switching to the
* new context in `to'.
*/
NENTRY(_swapcontext_u)
GETC(r4) /* r4 - from */
mov r5, r4 /* r5 - to */
/* FALLTHROUGH */
/*
* int _setcontext_u(const ucontext_t *ctx)
* Make the context stored in ctx current.
*/
NENTRY(_setcontext_u)
SETC(r4) /* r4 - ctx */
/* NOTREACHED */
.align 4
.L_uc_gregs_offset: .long UC_REGS
.L_uc_flags: .long _UC_USER | _UC_CPU
.L_uc_user: .long _UC_USER
.L_setcontext: .long _C_LABEL(setcontext)