NetBSD/sys/arch/arm32/fpe-arm/armfpe_glue.S

412 lines
9.2 KiB
ArmAsm

/* $NetBSD: armfpe_glue.S,v 1.6 1996/03/18 19:54:59 mark Exp $ */
/*
* Copyright (c) 1996 Mark Brinicombe
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Mark Brinicombe.
* 4. The name of the company nor the name of the author may 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 OR CONTRIBUTORS 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.
*
* RiscBSD kernel project
*
* arm_fpe_glue.S
*
* Glue code for calling the ARM FPE core code
*
* Created : 21/12/95
*/
#include "assym.h"
#include <machine/cpu.h>
sp .req r13
lr .req r14
pc .req r15
/* Offsets into fpe core for function addresses */
#define ARM_FPE_CORE_ABORT 0
#define ARM_FPE_CORE_INITWS 4
#define ARM_FPE_CORE_INITCONTEXT 8
#define ARM_FPE_CORE_CHANGECONTEXT 12
#define ARM_FPE_CORE_SHUTDOWN 16
#define ARM_FPE_CORE_ACTIVATECONTEXT 20
#define ARM_FPE_CORE_DEACTIVATECONTEXT 24
#define ARM_FPE_CORE_SAVECONTEXT 28
#define ARM_FPE_CORE_LOADCONTEXT 32
#define ARM_FPE_CORE_DISABLE 36
#define ARM_FPE_CORE_ENABLE 40
/*
* Ok Lots of little stubs for calling the fpe core
* routines from C
*/
.text
.align
arm_fpe_header:
.word _arm_fpe_mod
.global _arm_fpe_core_disable
_arm_fpe_core_disable:
stmfd sp!, {r0-r7, lr}
ldr r0, [pc, #arm_fpe_header - . - 8]
ldr r0, [r0, #ARM_FPE_CORE_DISABLE]
add lr, pc, #L1 - . - 8
mov pc, r0
L1:
ldmfd sp!, {r0-r7, pc}
.global _arm_fpe_core_enable
_arm_fpe_core_enable:
stmfd sp!, {r0-r7, lr}
ldr r0, [pc, #arm_fpe_header - . - 8]
ldr r0, [r0, #ARM_FPE_CORE_ENABLE]
add lr, pc, #L2 - . - 8
mov pc, r0
L2:
ldmfd sp!, {r0-r7, pc}
.global _arm_fpe_core_initws
_arm_fpe_core_initws:
stmfd sp!, {r10, lr}
mov r10, r0
ldr r3, [pc, #arm_fpe_header - . - 8]
ldr r3, [r3, #ARM_FPE_CORE_INITWS]
add lr, pc, #L3 - . - 8
mov pc, r3
L3:
ldmfd sp!, {r10, pc}
.global _arm_fpe_core_abort
_arm_fpe_core_abort:
stmfd sp!, {r1-r7, r10, lr}
mov r10, r0
mov r0, r1
mov r1, r2
ldr r3, [pc, #arm_fpe_header - . - 8]
ldr r3, [r3, #ARM_FPE_CORE_ABORT]
add lr, pc, #L4 - . - 8
mov pc, r3
L4:
ldmfd sp!, {r1-r7, r10, pc}
/* Only needs to preserve r10 */
.global _arm_fpe_core_initcontext
_arm_fpe_core_initcontext:
stmfd sp!, {r0-r7, r10, lr}
mov r10, r0
ldr r3, [pc, #arm_fpe_header - . - 8]
ldr r3, [r3, #ARM_FPE_CORE_INITCONTEXT]
add lr, pc, #L5 - . - 8
mov pc, r3
L5:
ldmfd sp!, {r0-r7, r10, pc}
/* Only needs to preserve r10 */
.global _arm_fpe_core_changecontext
_arm_fpe_core_changecontext:
stmfd sp!, {r1-r7, r10, lr}
mov r10, r0
ldr r3, [pc, #arm_fpe_header - . - 8]
ldr r3, [r3, #ARM_FPE_CORE_CHANGECONTEXT]
add lr, pc, #L6 - . - 8
mov pc, r3
L6:
ldmfd sp!, {r1-r7, r10, pc}
/* All regs preerved */
.global _arm_fpe_core_shutdown
_arm_fpe_core_shutdown:
stmfd sp!, {r0-r7, r10, lr}
ldr r3, [pc, #arm_fpe_header - . - 8]
ldr r3, [r3, #ARM_FPE_CORE_SHUTDOWN]
add lr, pc, #L7 - . - 8
mov pc, r3
L7:
ldmfd sp!, {r0-r7, r10, pc}
/* Preserve r10 */
.global _arm_fpe_core_savecontext
_arm_fpe_core_savecontext:
stmfd sp!, {r1-r7, r10, lr}
mov r10, r0
mov r0, r1
mov r1, r2
ldr r3, [pc, #arm_fpe_header - . - 8]
ldr r3, [r3, #ARM_FPE_CORE_SAVECONTEXT]
add lr, pc, #L8 - . - 8
mov pc, r3
L8:
ldmfd sp!, {r1-r7, r10, pc}
/* Preserve r10 */
.global _arm_fpe_core_loadcontext
_arm_fpe_core_loadcontext:
stmfd sp!, {r0-r7, r10, lr}
mov r10, r0
mov r0, r1
ldr r3, [pc, #arm_fpe_header - . - 8]
ldr r3, [r3, #ARM_FPE_CORE_LOADCONTEXT]
add lr, pc, #L9 - . - 8
mov pc, r3
L9:
ldmfd sp!, {r0-r7, r10, pc}
/* Only needs to preserve r10 */
.global _arm_fpe_core_activatecontext
_arm_fpe_core_activatecontext:
stmfd sp!, {r0-r7, r10, lr}
mov r10, r0
ldr r3, [pc, #arm_fpe_header - . - 8]
ldr r3, [r3, #ARM_FPE_CORE_ACTIVATECONTEXT]
add lr, pc, #L10 - . - 8
mov pc, r3
L10:
ldmfd sp!, {r0-r7, r10, pc}
/* Only needs to preserve r10 */
.global _arm_fpe_core_deactivatecontext
_arm_fpe_core_deactivatecontext:
stmfd sp!, {r1-r7, r10, lr}
ldr r3, [pc, #arm_fpe_header - . - 8]
ldr r3, [r3, #ARM_FPE_CORE_DEACTIVATECONTEXT]
add lr, pc, #L11 - . - 8
mov pc, r3
L11:
ldmfd sp!, {r1-r7, r10, pc}
/* Simple call back function that panics */
.global _arm_fpe_panic
_arm_fpe_panic:
adr r0, fpe_panic_text
b _panic
fpe_panic_text:
.asciz "armfpe: we are panicing"
.align 0
/*
* Call back routine from FPE on completion of an instruction
*/
.global _arm_fpe_post_proc_glue
_arm_fpe_post_proc_glue:
stmfd sp!, {r0-r6, r10-r12, lr}
/* This could be optimised as we are going from UND32->SVC32 mode */
mrs r4, cpsr_all
bic r3, r4, #(PSR_MODE)
orr r3, r3, #(PSR_SVC32_MODE)
msr cpsr_all, r3
mov r0, r12
/* Reserve a trapframe on the SVC stack */
sub sp, sp, #(TRAPFRAMESIZE)
mov r1, sp
ldr r2, [r0, #-0x0008] /* Copy spsr */
str r2, [r1, #0x0000]
ldr r2, [r0, #0x0000] /* Copy r0 */
str r2, [r1, #0x0004]
ldr r2, [r0, #0x0004]
str r2, [r1, #0x0008]
ldr r2, [r0, #0x0008]
str r2, [r1, #0x000c]
ldr r2, [r0, #0x000c]
str r2, [r1, #0x0010]
ldr r2, [r0, #0x0010]
str r2, [r1, #0x0014]
ldr r2, [r0, #0x0014]
str r2, [r1, #0x0018]
ldr r2, [r0, #0x0018]
str r2, [r1, #0x001c]
ldr r2, [r0, #0x001c]
str r2, [r1, #0x0020]
ldr r2, [r0, #0x0020]
str r2, [r1, #0x0024]
ldr r2, [r0, #0x0024]
str r2, [r1, #0x0028]
ldr r2, [r0, #0x0028]
str r2, [r1, #0x002c]
ldr r2, [r0, #0x002c]
str r2, [r1, #0x0030]
ldr r2, [r0, #0x0030] /* Copy r12 */
str r2, [r1, #0x0034]
ldr r2, [r0, #0x0034] /* Copy usr r13 */
str r2, [r1, #0x0038]
ldr r2, [r0, #0x0038] /* Copy usr r14 */
str r2, [r1, #0x003c]
ldr r2, [r0, #0x003c] /* Copy old pc */
str r2, [r1, #0x0044]
str r14, [r1, #0x0040] /* SVC r14 */
/*
* OK Question Time ...
*
* Do I need to save SVC r14 ?
* It only needs saving if this routine can interrupt something already
* running in SVC mode. Since FP is only valid from USR32 mode this
* should not happen.
*/
mov r5, r14
mov r6, r12
/* More optimisation ... Need to code a assembly version of userret() */
bl _arm_fpe_postproc
/* Release the trapframe on the SVC stack */
ldr r2, [sp, #0x0000] /* Copy spsr */
str r2, [r6, #-0x0008]
ldr r2, [sp, #0x0004] /* Copy r0 */
str r2, [r6, #0x0000]
ldr r2, [sp, #0x0008] /* Copy r1 */
str r2, [r6, #0x0004]
ldr r2, [sp, #0x000c] /* Copy r2 */
str r2, [r6, #0x0008]
ldr r2, [sp, #0x0010] /* Copy r3 */
str r2, [r6, #0x000c]
ldr r2, [sp, #0x0014] /* Copy r4 */
str r2, [r6, #0x0010]
ldr r2, [sp, #0x0018] /* Copy r5 */
str r2, [r6, #0x0014]
ldr r2, [sp, #0x001c] /* Copy r6 */
str r2, [r6, #0x0018]
ldr r2, [sp, #0x0020] /* Copy r7 */
str r2, [r6, #0x001c]
ldr r2, [sp, #0x0024] /* Copy r8 */
str r2, [r6, #0x0020]
ldr r2, [sp, #0x0028] /* Copy r9 */
str r2, [r6, #0x0024]
ldr r2, [sp, #0x002c] /* Copy r10 */
str r2, [r6, #0x0028]
ldr r2, [sp, #0x0030] /* Copy r11 */
str r2, [r6, #0x002c]
ldr r2, [sp, #0x0034] /* Copy r12 */
str r2, [r6, #0x0030]
ldr r2, [sp, #0x0038] /* Copy usr r13 */
str r2, [r6, #0x0034]
ldr r2, [sp, #0x003c] /* Copy usr r14 */
str r2, [r6, #0x0038]
ldr r2, [sp, #0x0044] /* Copy pc */
str r2, [r6, #0x003c]
add sp, sp, #(TRAPFRAMESIZE)
mov r14, r5
msr cpsr_all, r4
ldmfd sp!, {r0-r6, r10-r12, pc}
/*
* Call back routine from FPE when the an exception occurs
*/
.global _arm_fpe_exception_glue
_arm_fpe_exception_glue:
stmfd sp!, {r0-r5, r10-r12, lr}
/* This could be optimised as we are going from UND32->SVC32 mode */
mrs r4, cpsr_all
bic r3, r4, #(PSR_MODE)
orr r3, r3, #(PSR_SVC32_MODE)
msr cpsr_all, r3
ldr r1, [r12, #15*4]
mov r2, r12
mov r5, r14
bl _arm_fpe_exception
mov r14, r5
msr cpsr_all, r4
ldmfd sp!, {r0-r5, r10-r12, lr}
/* Now pull the original trapframe that the FPE pushed off the stack */
ldmdb r12, {r0, r1}
msr cpsr_all, r1
msr spsr_all, r0
mov sp, r12
ldmia sp, {r0-r14}^
mov r0, r0
add sp, sp, #15*4
ldmfd sp!, {pc}^
.global _fpe_nexthandler
_fpe_nexthandler:
.word _undefinedinstruction_bounce