Move the ARM, Ltd. floating point emulator to arch/arm.

This commit is contained in:
thorpej 2001-11-24 01:26:23 +00:00
parent 598f003e0a
commit 87fe867c21
8 changed files with 8427 additions and 12 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: process_machdep.c,v 1.8 2001/11/22 17:59:59 thorpej Exp $ */
/* $NetBSD: process_machdep.c,v 1.9 2001/11/24 01:26:23 thorpej Exp $ */
/*
* Copyright (c) 1995 Frank Lancaster. All rights reserved.
@ -70,7 +70,7 @@
#include <sys/param.h>
__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.8 2001/11/22 17:59:59 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.9 2001/11/24 01:26:23 thorpej Exp $");
#include <sys/proc.h>
#include <sys/ptrace.h>
@ -84,8 +84,8 @@ __KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.8 2001/11/22 17:59:59 thorpej
#include <arm/armreg.h>
#ifdef ARMFPE
#include <arm32/fpe-arm/armfpe.h>
#endif /* ARMFPE */
#include <arm/fpe-arm/armfpe.h>
#endif
static __inline struct trapframe *
process_frame(struct proc *p)

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.c,v 1.10 2001/11/23 21:18:30 thorpej Exp $ */
/* $NetBSD: cpu.c,v 1.11 2001/11/24 01:26:24 thorpej Exp $ */
/*
* Copyright (c) 1995 Mark Brinicombe.
@ -58,8 +58,8 @@
#ifdef ARMFPE
#include <machine/bootconfig.h> /* For boot args */
#include <arm32/fpe-arm/armfpe.h>
#endif /* ARMFPE */
#include <arm/fpe-arm/armfpe.h>
#endif
cpu_t cpus[MAX_CPUS];

View File

@ -1,4 +1,4 @@
/* $NetBSD: vm_machdep.c,v 1.9 2001/11/19 20:38:58 chris Exp $ */
/* $NetBSD: vm_machdep.c,v 1.10 2001/11/24 01:26:24 thorpej Exp $ */
/*
* Copyright (c) 1994-1998 Mark Brinicombe.
@ -64,7 +64,7 @@
#include <machine/vmparam.h>
#ifdef ARMFPE
#include <arm32/fpe-arm/armfpe.h>
#include <arm/fpe-arm/armfpe.h>
#endif
extern pv_addr_t systempage;

View File

@ -1,16 +1,19 @@
# $NetBSD: files.arm,v 1.42 2001/11/22 17:59:59 thorpej Exp $
# $NetBSD: files.arm,v 1.43 2001/11/24 01:26:24 thorpej Exp $
# temporary define to allow easy moving to ../arch/arm/arm32
defopt ARM32
# CPU types
defopt opt_cputypes.h CPU_ARM2 CPU_ARM250 CPU_ARM3 : PROG26
defopt opt_cputypes.h CPU_ARM2 CPU_ARM250 CPU_ARM3
defopt opt_cputypes.h CPU_ARM6 CPU_ARM7 CPU_ARM7TDMI CPU_ARM8
CPU_ARM9 CPU_SA110 CPU_SA1100 CPU_SA1110
CPU_XSCALE : PROG32
CPU_XSCALE
# Floating point emulator
defopt ARMFPE
file arch/arm/fpe-arm/armfpe_glue.S armfpe
file arch/arm/fpe-arm/armfpe_init.c armfpe
file arch/arm/fpe-arm/armfpe.s armfpe
# PMAP_DEBUG (heavily abused option)
defopt PMAP_DEBUG

View File

@ -0,0 +1,140 @@
/* $NetBSD: armfpe.h,v 1.1 2001/11/24 01:26:24 thorpej Exp $ */
/*
* Copyright (c) 1995 Neil A Carson.
* 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 Brini.
* 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
*
* armfpe.h
*
* Details of functions and structures needed for ARM FP cor
* support in RiscBSD
*
* Created : 04/01/96
*/
#ifndef _ARMFPE_H_
#define _ARMFPE_H_
#include <arm/cpus.h>
#include <machine/fp.h>
#include <machine/ieeefp.h>
#include <machine/reg.h>
#ifdef _KERNEL
/*
* Type for a saved FP context, if we want to translate the context to a
* user-readable form
*/
typedef struct fp_context_frame {
u_int32_t fpsr;
fp_extended_precision_t regs[8];
} fp_context_frame_t;
/* Define a structure that overlays the start of the core */
typedef struct {
/*
* Addresses of procedures/functions
*/
u_int32_t core_abort_addr;
u_int32_t core_initws_addr;
u_int32_t core_initcontext_addr;
u_int32_t core_changecontext_addr;
u_int32_t core_shutdown_addr;
u_int32_t core_activatecontext_addr;
u_int32_t core_deactivatecontext_addr;
u_int32_t core_savecontext_addr;
u_int32_t core_loadcontext_addr;
u_int32_t core_disable_addr;
u_int32_t core_enable_addr;
/*
* Addresses of things that need to be filled in by the kernel on startup
*/
u_int32_t *main_ws_ptr_addr;
u_int32_t *local_handler_ptr_addr;
u_int32_t *old_handler_ptr_addr;
u_int32_t *exc_handler_ptr_addr;
u_int32_t *fp_post_proc_addr;
/*
* Constants that the kernel needs
*/
u_int32_t workspacelength;
u_int32_t contextlength;
/*
* Data pointers for extra information
*/
u_char *core_identity_addr;
} arm_fpe_mod_hdr_t;
/* macro to return the FP context for a process */
#define FP_CONTEXT(p) ((u_int)(((u_char *)(p)->p_addr) + sizeof(struct user)))
/* Prototypes */
int arm_fpe_boot __P((cpu_t *cpu));
int initialise_arm_fpe __P((cpu_t *cpu));
void arm_fpe_postproc __P((u_int fpframe, struct trapframe *frame));
void arm_fpe_exception __P((int exception, u_int fpframe, struct trapframe *frame));
void arm_fpe_core_disable __P((void));
void arm_fpe_core_enable __P((void));
u_int arm_fpe_core_initws __P((u_int workspace, int handler1, int handler2));
u_int arm_fpe_core_abort __P((u_int context, int r12, int pc));
void arm_fpe_core_initcontext __P((u_int context));
u_int arm_fpe_core_changecontext __P((u_int context));
void arm_fpe_core_shutdown __P((void));
void arm_fpe_core_activatecontext __P((u_int context));
u_int arm_fpe_core_deactivatecontext __P((void));
u_int arm_fpe_core_savecontext __P((u_int context, fp_context_frame_t *savearea, int pc));
void arm_fpe_core_loadcontext __P((u_int context, fp_context_frame_t *loadarea));
void arm_fpe_copycontext __P((u_int c1, u_int c2));
void arm_fpe_getcontext __P((struct proc *p, struct fpreg *fpregs));
void arm_fpe_setcontext __P((struct proc *p, struct fpreg *fpregs));
void arm_fpe_exception_glue __P((int exception));
void arm_fpe_panic __P((void));
void undefined_entry __P((void));
void arm_fpe_post_proc_glue __P((void));
void arm_fpe_set_exception_mask __P((fp_except));
#endif /* _KERNEL */
#endif /* _ARMFPE_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,475 @@
/* $NetBSD: armfpe_glue.S,v 1.1 2001/11/24 01:26:24 thorpej 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
*/
#define CHECK_BEFORE_USERRET
#include "assym.h"
#include <machine/asm.h>
#include <machine/cpu.h>
/*
* Glue for calling the core entry points
*/
ENTRY_NP(arm_fpe_core_disable)
stmfd sp!, {r0-r7, lr}
bl _fpe_arm_core_disable
ldmfd sp!, {r0-r7, pc}
ENTRY_NP(arm_fpe_core_enable)
stmfd sp!, {r0-r7, lr}
bl _fpe_arm_core_enable
ldmfd sp!, {r0-r7, pc}
ENTRY_NP(arm_fpe_core_initws)
stmfd sp!, {r10, lr}
mov r10, r0
bl _fpe_arm_core_initws
ldmfd sp!, {r10, pc}
ENTRY_NP(arm_fpe_core_abort)
stmfd sp!, {r1-r7, r10, lr}
mov r10, r0
mov r0, r1
mov r1, r2
bl _fpe_arm_core_abort
ldmfd sp!, {r1-r7, r10, pc}
/* Only needs to preserve r10 */
ENTRY_NP(arm_fpe_core_initcontext)
stmfd sp!, {r0-r7, r10, lr}
mov r10, r0
bl _fpe_arm_core_initcontext
ldmfd sp!, {r0-r7, r10, pc}
/* Only needs to preserve r10 */
ENTRY_NP(arm_fpe_core_changecontext)
stmfd sp!, {r1-r7, r10, lr}
mov r10, r0
bl _fpe_arm_core_changecontext
ldmfd sp!, {r1-r7, r10, pc}
/* All regs preserved */
ENTRY_NP(arm_fpe_core_shutdown)
stmfd sp!, {r0-r7, r10, lr}
bl _fpe_arm_core_shutdown
ldmfd sp!, {r0-r7, r10, pc}
/* Preserve r10 */
ENTRY_NP(arm_fpe_core_savecontext)
stmfd sp!, {r1-r7, r10, lr}
mov r10, r0
mov r0, r1
mov r1, r2
bl _fpe_arm_core_savecontext
ldmfd sp!, {r1-r7, r10, pc}
/* Preserve r10 */
ENTRY_NP(arm_fpe_core_loadcontext)
stmfd sp!, {r0-r7, r10, lr}
mov r10, r0
mov r0, r1
bl _fpe_arm_core_loadcontext
ldmfd sp!, {r0-r7, r10, pc}
/* Only needs to preserve r10 */
ENTRY_NP(arm_fpe_core_activatecontext)
stmfd sp!, {r0-r7, r10, lr}
mov r10, r0
bl _fpe_arm_core_activatecontext
ldmfd sp!, {r0-r7, r10, pc}
/* Only needs to preserve r10 */
ENTRY_NP(arm_fpe_core_deactivatecontext)
stmfd sp!, {r1-r7, r10, lr}
bl _fpe_arm_core_deactivatecontext
ldmfd sp!, {r1-r7, r10, pc}
/*
* Call back functions from the core
*/
ENTRY_NP(arm_fpe_newhandler)
stmfd sp!, {r0, lr}
ldr r0, Llocal_handler_addr
str r1, [r0]
ldmfd sp!, {r0, pc}
Llocal_handler_addr:
.word _undefined_handler_address
ENTRY_NP(arm_fpe_restorehandler)
stmfd sp!, {r0-r1, lr}
ldr r0, Llocal_handler_addr
ldr r1, Lold_handler_addr
ldr r1, [r1]
str r1, [r0]
ldmfd sp!, {r0-r1, pc}
Lold_handler_addr:
.word _arm_fpe_old_handler_address
ENTRY_NP(arm_fpe_handle_exception)
b _arm_fpe_exception_glue
ENTRY_NP(arm_fpe_get_ws)
sub sp, sp, #8
str r0, [sp]
ldr r0, Larm_fpe_core_workspace
ldr r0, [r0]
str r0, [sp, #4]
ldr r0, [sp], #4
mov pc, lr
Larm_fpe_core_workspace:
.word _arm_fpe_core_workspace
ENTRY_NP(arm_fpe_post_proc)
b _arm_fpe_post_proc_glue
/* Simple call back function that panics */
ENTRY_NP(arm_fpe_panic)
adr r0, Lfpe_panic_text
b _C_LABEL(panic)
Lfpe_panic_text:
.asciz "armfpe: we are panicing"
.align 0
/*
* Call back routine from FPE on completion of an instruction
*/
#ifdef CHECK_BEFORE_USERRET
.global _userret_count0
.global _userret_count1
.data
_userret_count0:
.word 0
_userret_count1:
.word 0
.text
Luserret_count0:
.word _userret_count0
Luserret_count1:
.word _userret_count1
Lwant_resched:
.word _want_resched
Lcurproc:
.word _curproc
Lcurpriority:
.word _cpu_info_store
#endif
ENTRY_NP(arm_fpe_post_proc_glue)
stmfd sp!, {r0-r3, lr}
#ifdef CHECK_BEFORE_USERRET
/* Call userret if we need a reschedule */
/* Debugging */
ldr r0, Luserret_count0
ldr r1, [r0]
add r1, r1, #1
str r1, [r0]
/* Do we need a reschedule */
ldr r0, Lwant_resched
ldr r0, [r0]
teq r0, #0x00000000
bne Lwe_need_userret
/* All other userret requirement conditions come from curproc */
ldr r0, Lcurproc
ldr r0, [r0]
/* Remember the flags field */
ldr r3, [r0, #(P_FLAG)]
/* Get the signal list */
ldr r1, [r0, #(P_SIGLIST)]
teq r1, #0x00000000
beq Lno_signals_pending
tst r3, #(P_TRACED)
bne Lwe_need_userret
ldr r1, [r0, #(P_SIGLIST)]
ldr r2, [r0, #(P_SIGMASK)]
bic r1, r1, r2
teq r1, #0x00000000
bne Lwe_need_userret
Lno_signals_pending:
/* Are we profiling ? */
tst r3, #(P_PROFIL)
bne Lwe_need_userret
/* Update the current priority */
ldrb r1, [r0, #(P_USRPRI)]
strb r1, [r0, #(P_PRIORITY)]
ldr r0, Lcurpriority
strb r1, [r0, #(CI_CURPRIORITY)]
/* Fast return */
ldmfd sp!, {r0-r3, pc}
Lwe_need_userret:
/* Ok we need to call userret() */
stmfd sp!, {r4-r6, r10-r12}
/* Debugging */
ldr r0, Luserret_count1
ldr r1, [r0]
add r1, r1, #1
str r1, [r0]
#endif
/* 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], #0x0004
ldmia r0!, {r2, r3, r5, r6} /* copy r0-r5 */
stmia r1!, {r2, r3, r5, r6}
ldmia r0!, {r2, r3, r5, r6} /* copy r6-r11 */
stmia r1!, {r2, r3, r5, r6}
ldmia r0!, {r2, r3, r5, r6} /* copy r6-r11 */
stmia r1!, {r2, r3, r5, r6}
ldmia r0!, {r2, r3, r5, r6} /* copy r12, r13, r14, r15 */
stmia r1!, {r2, r3, r5, r14}
str r6, [r1, #0x0000]
mov r0, r12
mov r1, sp
/*
* 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 an assembly version of userret() */
bl _arm_fpe_postproc
/* Release the trapframe on the SVC stack */
mov r14, r5
mov r0, sp
ldr r2, [r0], #0x0004 /* Copy spsr */
str r2, [r6, #-0x0008]
ldmia r0!, {r1, r2, r3, r5, r10, r11} /* copy r0-r5 */
stmia r6!, {r1, r2, r3, r5, r10, r11}
ldmia r0!, {r1, r2, r3, r5, r10, r11} /* copy r6-r11 */
stmia r6!, {r1, r2, r3, r5, r10, r11}
ldmia r0!, {r1, r2, r3} /* copy r12, r13, r14 */
stmia r6!, {r1, r2, r3}
ldr r1, [r0, #0x0004]
str r1, [r6]
add sp, sp, #(TRAPFRAMESIZE)
msr cpsr_all, r4
ldmfd sp!, {r4-r6, r10-r12}
ldmfd sp!, {r0-r3, pc}
/*
* Call back routine from FPE when the an exception occurs
*/
ENTRY_NP(arm_fpe_exception_glue)
stmfd sp!, {r0-r6, r10-r12, lr}
mov r10, r0
/* 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], #0x0004
ldmia r0!, {r2, r3, r5, r6} /* copy r0-r5 */
stmia r1!, {r2, r3, r5, r6}
ldmia r0!, {r2, r3, r5, r6} /* copy r6-r11 */
stmia r1!, {r2, r3, r5, r6}
ldmia r0!, {r2, r3, r5, r6} /* copy r6-r11 */
stmia r1!, {r2, r3, r5, r6}
ldmia r0!, {r2, r3, r5, r6} /* copy r12, r13, r14, r15 */
stmia r1!, {r2, r3, r5, r14}
str r6, [r1, #0x0000]
mov r0, r10 /* exception */
mov r1, r12 /* fpframe */
mov r2, sp /* trapframe */
/*
* 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 an assembly version of userret() */
bl _arm_fpe_exception
/* Release the trapframe on the SVC stack */
mov r14, r5
mov r0, sp
ldr r2, [r0], #0x0004 /* Copy spsr */
str r2, [r6, #-0x0008]
ldmia r0!, {r1, r2, r3, r5, r10, r11} /* copy r0-r5 */
stmia r6!, {r1, r2, r3, r5, r10, r11}
ldmia r0!, {r1, r2, r3, r5, r10, r11} /* copy r6-r11 */
stmia r6!, {r1, r2, r3, r5, r10, r11}
ldmia r0!, {r1, r2, r3} /* copy r12, r13, r14 */
stmia r6!, {r1, r2, r3}
ldr r1, [r0, #0x0004]
str r1, [r6]
add sp, sp, #(TRAPFRAMESIZE)
msr cpsr_all, r4
ldmfd sp!, {r0-r6, 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}^
ENTRY_NP(arm_fpe_set_exception_mask)
rfs r1 /* Get FP status */
bic r1, r1, #0x001f0000 /* Zero exception mask */
and r0, r0, #0x0000001f /* Mask new bits */
orr r0, r1, r0, lsl #16 /* Merge */
wfs r0 /* Set status */
mov r0, r1, lsr #16 /* Return old mask */
mov pc, lr /* return */
.global _fpe_nexthandler
_fpe_nexthandler:
.word _undefinedinstruction_bounce

View File

@ -0,0 +1,277 @@
/* $NetBSD: armfpe_init.c,v 1.1 2001/11/24 01:26:25 thorpej Exp $ */
/*
* Copyright (C) 1996 Mark Brinicombe
* Copyright (C) 1995 Neil A Carson.
* 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.c
*
* Stuff needed to interface the ARM floating point emulator module to RiscBSD.
*
* Created : 22/10/95
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/user.h>
#include <sys/malloc.h>
#include <sys/acct.h>
#include <uvm/uvm_extern.h>
#include <machine/cpu.h>
#include <arm/cpus.h>
#include <arm/arm32/katelib.h>
#include <machine/frame.h>
#include <arm/fpe-arm/armfpe.h>
extern int want_resched;
extern u_int fpe_nexthandler;
extern u_int fpe_arm_start[];
extern arm_fpe_mod_hdr_t fpe_arm_header;
extern u_int undefined_handler_address;
u_int arm_fpe_old_handler_address;
u_int arm_fpe_core_workspace;
/*
* Error messages for the various exceptions, numbered 0-5
*/
static const char *exception_errors[] = {
"invalid operation",
"division by zero (0)",
"overflow",
"underflow",
"operation inexact",
"major faliure... core fault trapped... not good!"
};
/*
* Initialisation point. The kernel calls this during the configuration of
* the cpu in order to install the FPE.
* The FPE specification needs to be filled in the specified cpu_t structure
* and the FPE needs to be installed on the CPU undefined instruction vector.
*/
int
initialise_arm_fpe(cpu)
cpu_t *cpu;
{
int error;
cpu->fpu_class = FPU_CLASS_FPE;
cpu->fpu_type = FPU_TYPE_ARMLTD_FPE;
strcpy(cpu->fpu_model, fpe_arm_header.core_identity_addr);
error = arm_fpe_boot(cpu);
if (error != 0) {
strcat(cpu->fpu_model, " - boot failed");
return(1);
}
return(0);
}
/*
* The actual FPE boot routine.
* This has to do a number of things :
* 1. Relocate the FPE - Note this requires write access to the kernel text area
* 2. Allocated memory for the FPE
* 3. Initialise the FPE
*/
int
arm_fpe_boot(cpu)
cpu_t *cpu;
{
u_int workspace;
int id;
#ifdef DEBUG
/* Print a bit of debugging info */
printf("FPE: base=%08x\n", (u_int)fpe_arm_start);
printf("FPE: global workspace size = %d bytes, context size = %d bytes\n",
fpe_arm_header.workspacelength, fpe_arm_header.contextlength);
#endif
/* Now we must do some memory allocation */
workspace = (u_int)malloc(fpe_arm_header.workspacelength, M_DEVBUF, M_NOWAIT);
if (!workspace)
return(ENOMEM);
arm_fpe_core_workspace = workspace;
arm_fpe_old_handler_address = undefined_handler_address;
/* Initialise out gloable workspace */
id = arm_fpe_core_initws(workspace, (u_int)&fpe_nexthandler,
(u_int)&fpe_nexthandler);
if (id == FPU_TYPE_FPA11) {
cpu->fpu_class = FPU_CLASS_FPA;
cpu->fpu_type = FPU_TYPE_FPA11;
}
#ifdef DEBUG
printf("fpe id=%08x\n", id);
#endif
/* Initialise proc0's FPE context and select it */
arm_fpe_core_initcontext(FP_CONTEXT(&proc0));
arm_fpe_core_changecontext(FP_CONTEXT(&proc0));
/*
* Set the default excpection mask. This will be inherited on
* a fork when the context is copied.
*
* XXX - The is done with FP instructions - the only ones in
* the kernel
*/
arm_fpe_set_exception_mask(FP_X_DZ | FP_X_OFL);
return(0);
}
/*
* Callback routine from the FPE when instruction emulation completes
*/
void
arm_fpe_postproc(fpframe, frame)
u_int fpframe;
struct trapframe *frame;
{
register int sig;
register struct proc *p;
p = curproc;
p->p_addr->u_pcb.pcb_tf = frame;
/* take pending signals */
while ((sig = (CURSIG(p))) != 0) {
postsig(sig);
}
p->p_priority = p->p_usrpri;
if (want_resched) {
/*
* We are being preempted.
*/
preempt(NULL);
while ((sig = (CURSIG(p))) != 0) {
postsig(sig);
}
}
/* Profiling. */
if (p->p_flag & P_PROFIL) {
extern int psratio;
u_int pc;
pc = ReadWord(fpframe + 15*4);
#ifdef DIAGNOSTIC
if (pc < 0x1000 || pc > 0xefc00000)
panic("armfpe_postproc: pc=%08x\n", pc);
#endif
addupc_task(p, pc, (int)(p->p_sticks - p->p_sticks) * psratio);
}
curcpu()->ci_schedstate.spc_curpriority = p->p_priority;
}
/*
* Callback routine from the FPE when an exception occurs.
*/
void
arm_fpe_exception(exception, fpframe, frame)
int exception;
u_int fpframe;
struct trapframe *frame;
{
if (exception >= 0 && exception < 6)
printf("fpe exception: %s (%d)\n",
exception_errors[exception], exception);
else
printf("fpe exception: unknown (%d)\n", exception);
trapsignal(curproc, SIGFPE, exception << 8);
userret(curproc);
}
void
arm_fpe_copycontext(c1, c2)
u_int c1;
u_int c2;
{
fp_context_frame_t fpcontext;
arm_fpe_core_savecontext(c1, &fpcontext, 0);
arm_fpe_core_loadcontext(c2, &fpcontext);
}
/*
* Warning the arm_fpe_getcontext() and arm_fpe_setcontext() functions
* rely on the fact that the fp_context_frame_t type is structurally the
* same as struct fpreg and thus can just cast the pointer.
* If a change is made to either then a tempoary buffer will be needed
* and the structure members copied indiviually.
*/
void arm_fpe_getcontext(p, fpregs)
struct proc *p;
struct fpreg *fpregs;
{
arm_fpe_core_savecontext(FP_CONTEXT(p), (fp_context_frame_t *)fpregs, 0);
}
void arm_fpe_setcontext(p, fpregs)
struct proc *p;
struct fpreg *fpregs;
{
arm_fpe_core_loadcontext(FP_CONTEXT(p), (fp_context_frame_t *)fpregs);
}
/* End of armfpe_init.c */