Mercurial > ecos
diff packages/hal/cortexm/arch/current/src/context.S @ 3208:614e724c4b7a
Add: hardware floating point support for Cortex-M4F [ Bugzilla 1001607 ]
| author | vae |
|---|---|
| date | Sat, 09 Mar 2013 17:13:06 +0000 |
| parents | abf5be1b8582 |
| children |
line wrap: on
line diff
--- a/packages/hal/cortexm/arch/current/src/context.S +++ b/packages/hal/cortexm/arch/current/src/context.S @@ -8,7 +8,7 @@ // ####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 2008 Free Software Foundation, Inc. +// Copyright (C) 2008, 2012 Free Software Foundation, Inc. // // eCos 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 @@ -39,9 +39,10 @@ //========================================================================== //#####DESCRIPTIONBEGIN#### // -// Author(s): nickg -// Date: 2008-07-30 -// Description: This file contains thread context switch code. +// Author(s): nickg, ilijak (FPU support) +// Contributor(s): +// Date: 2008-07-30 +// Description: This file contains thread context switch code. // //####DESCRIPTIONEND#### // @@ -55,6 +56,12 @@ #include <pkgconf/kernel.h> #endif +#ifdef CYGHWR_HAL_CORTEXM_FPU +#include <cyg/hal/hal_arch.h> +#include <cyg/hal/cortexm_fpu.h> // Optional Floating Point Unit + +#endif + //========================================================================== .syntax unified @@ -67,6 +74,132 @@ // R0 contains a pointer to the SP of the thread to load, R1 contains // a pointer to the SP of the current thread. +#ifdef CYGHWR_HAL_CORTEXM_FPU_SWITCH_LAZY +//========================================================================== +// LAZY Context switch +// +// Save the FPU registers only for threads that use FPU. +// + + .globl hal_thread_switch_context + .thumb + .thumb_func + .type hal_thread_switch_context, %function +hal_thread_switch_context: + + push {r0-r12,lr} // Push all savable register + ldr r7,=CYGARC_REG_FPU_CPACR // + ldr r6,[r7] + tst r6,#CYGARC_REG_FPU_CPACR_ENABLE // Is FPU enabled? + beq lazy_float_push // N: Be lazy. + vmrs r5,fpscr // Y: Save FPU context + vpush.f64 {d0-d15} // Push FPU registers + push {r5} // together with FPSCR + mov r2,#HAL_SAVEDREGISTERS_THREAD_FPU // Set state type: thread with FPU + b float_push_join + lazy_float_push: + mov r2,#HAL_SAVEDREGISTERS_THREAD + sub sp,#HAL_SAVEDREGISTERS_FPU_THREAD_CONTEXT_SIZE + float_push_join: + mrs r3,basepri // Get priority base register + mov r4,sp // Get SP (for info only) + push {r2-r4} // Push them + str sp,[r1] // Save SP + // Fall through + +//-------------------------------------------------------------------------- +// Load context +// +// This is used to load a thread context, abandoning the current one. Following +// function part is the second half of hal_thread_switch_context. + + + .globl hal_thread_load_context + .thumb + .thumb_func + .type hal_thread_load_context, %function +hal_thread_load_context_common: + + ldr sp,[r0] // Load SP + pop {r2-r4} // Pop type, basepri, SP(discarded) and FPSCR + msr basepri,r3 // Set BASEPRI + cmp r2,#HAL_SAVEDREGISTERS_THREAD_FPU // Is state type a FP thread? + beq real_float_pop // Y: + // N: Be lazy + and r6,#~CYGARC_REG_FPU_CPACR_ENABLE + add sp,#HAL_SAVEDREGISTERS_FPU_THREAD_CONTEXT_SIZE + str r6,[r7] + pop {r0-r12,pc} // Pop all registers and return to an non-FP thread + + real_float_pop: // Restore floating point context for FP thread. + orr r6,#CYGARC_REG_FPU_CPACR_ENABLE + pop {r5} // Retrieve FPU status register + str r6,[r7] + dsb + isb + vpop.f64 {d0-d15} // Pestore FPU registers + vmsr fpscr,r5 // Restore FPU status register + pop {r0-r12,pc} // Pop all registers and return to a FP thread. + +// Load context entry point +// Load context initially needs CPACR register, so it is provided here. +hal_thread_load_context: + ldr r7,=CYGARC_REG_FPU_CPACR + ldr r6,[r7] + b hal_thread_load_context_common + +#elif defined CYGHWR_HAL_CORTEXM_FPU_SWITCH_ALL + +//========================================================================== +// ALL Context switch +// +// Save the FPU registers for all threads. +// + + .globl hal_thread_switch_context + .thumb + .thumb_func + .type hal_thread_switch_context, %function +hal_thread_switch_context: + + push {r0-r12,lr} // Push all savable register + vmrs r5,fpscr + mov r2,#HAL_SAVEDREGISTERS_THREAD_FPU // Set state type == thread + vpush.f64 {d0-d15} // Push FPU registers + sub r4,sp,#4 // Get SP (for info only) + mrs r3,basepri // Get priority base register + push {r2-r5} // Push them + str sp,[r1] // Save SP + // Fall through + +//-------------------------------------------------------------------------- +// Load context +// +// This is used to load a thread context, abandoning the current one. This +// function is also the second half of hal_thread_switch_context. + + + .globl hal_thread_load_context + .thumb + .thumb_func + .type hal_thread_load_context, %function +hal_thread_load_context: + + ldr sp,[r0] // Load SP + pop {r2-r5} // Pop type, basepri,SP(discarded) and FPSCR + msr basepri,r3 // Set BASEPRI + vpop.f64 {d0-d15} // Pop FPU registers + vmsr fpscr,r5 // and FPU status register + pop {r0-r12,pc} // Pop all register and return + +#else + +//========================================================================== +// NONE Context switch +// +// No FPU or NONE context saving scheme. Do not save FPU registers. +// + .globl hal_thread_switch_context .thumb .thumb_func @@ -100,6 +233,8 @@ hal_thread_load_context: msr basepri,r3 // Set BASEPRI pop {r0-r12,pc} // Pop all register and return +#endif + //========================================================================== // HAL longjmp, setjmp implementations //
