arch: arc: optimize the float support
* enable float support * implement z_arch_float_disable * add arc support in fp_sharing test Signed-off-by: Wayne Ren <wei.ren@synopsys.com>
This commit is contained in:
parent
98a3399138
commit
8b04c7de13
|
@ -455,7 +455,7 @@ config MPU_REQUIRES_NON_OVERLAPPING_REGIONS
|
|||
menuconfig FLOAT
|
||||
bool "Floating point"
|
||||
depends on CPU_HAS_FPU
|
||||
depends on ARM || X86
|
||||
depends on ARM || X86 || ARC
|
||||
help
|
||||
This option allows threads to use the floating point registers.
|
||||
By default, only a single thread may use the registers.
|
||||
|
|
|
@ -269,3 +269,21 @@ FUNC_NORETURN void z_arch_user_mode_enter(k_thread_entry_t user_entry,
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_FLOAT) && defined(CONFIG_FP_SHARING)
|
||||
int z_arch_float_disable(struct k_thread *thread)
|
||||
{
|
||||
unsigned int key;
|
||||
|
||||
/* Ensure a preemptive context switch does not occur */
|
||||
|
||||
key = irq_lock();
|
||||
|
||||
/* Disable all floating point capabilities for the thread */
|
||||
thread->base.user_options &= ~K_FP_REGS;
|
||||
|
||||
irq_unlock(key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_FLOAT && CONFIG_FP_SHARING */
|
||||
|
|
|
@ -56,6 +56,9 @@ extern "C" {
|
|||
st r30, [sp, ___callee_saved_stack_t_r30_OFFSET]
|
||||
|
||||
#ifdef CONFIG_FP_SHARING
|
||||
ld r13, [r2, ___thread_base_t_user_options_OFFSET]
|
||||
/* K_FP_REGS is bit 1 */
|
||||
bbit0 r13, 1, 1f
|
||||
st r58, [sp, ___callee_saved_stack_t_r58_OFFSET]
|
||||
st r59, [sp, ___callee_saved_stack_t_r59_OFFSET]
|
||||
lr r13, [_ARC_V2_FPU_STATUS]
|
||||
|
@ -73,7 +76,7 @@ extern "C" {
|
|||
lr r13, [_ARC_V2_FPU_DPFP2H]
|
||||
st_s r13, [sp, ___callee_saved_stack_t_dpfp2h_OFFSET]
|
||||
#endif
|
||||
|
||||
1 :
|
||||
#endif
|
||||
|
||||
/* save stack pointer in struct k_thread */
|
||||
|
@ -86,6 +89,9 @@ extern "C" {
|
|||
ld sp, [r2, _thread_offset_to_sp]
|
||||
|
||||
#ifdef CONFIG_FP_SHARING
|
||||
ld r13, [r2, ___thread_base_t_user_options_OFFSET]
|
||||
/* K_FP_REGS is bit 1 */
|
||||
bbit0 r13, 1, 2f
|
||||
ld r58, [sp, ___callee_saved_stack_t_r58_OFFSET]
|
||||
ld r59, [sp, ___callee_saved_stack_t_r59_OFFSET]
|
||||
|
||||
|
@ -104,7 +110,7 @@ extern "C" {
|
|||
ld_s r13, [sp, ___callee_saved_stack_t_dpfp2h_OFFSET]
|
||||
sr r13, [_ARC_V2_FPU_DPFP2H]
|
||||
#endif
|
||||
|
||||
2 :
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
|
|
|
@ -36,6 +36,9 @@ config ARC_FIRQ
|
|||
config CACHE_FLUSHING
|
||||
default y
|
||||
|
||||
config FP_FPU_DA
|
||||
def_bool y
|
||||
|
||||
if (ARC_MPU_VER = 2)
|
||||
|
||||
config MAIN_STACK_SIZE
|
||||
|
|
|
@ -88,6 +88,24 @@ struct fp_non_volatile_register_set {
|
|||
#define SIZEOF_FP_NON_VOLATILE_REGISTER_SET \
|
||||
sizeof(struct fp_non_volatile_register_set)
|
||||
|
||||
#elif defined(CONFIG_CPU_ARCV2)
|
||||
|
||||
struct fp_volatile_register_set {
|
||||
#ifdef CONFIG_FP_FPU_DA
|
||||
u32_t dpfp2h;
|
||||
u32_t dpfp2l;
|
||||
u32_t dpfp1h;
|
||||
u32_t dpfp1l;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct fp_non_volatile_register_set {
|
||||
/* No non-volatile floating point registers */
|
||||
};
|
||||
|
||||
#define SIZEOF_FP_VOLATILE_REGISTER_SET sizeof(struct fp_volatile_register_set)
|
||||
#define SIZEOF_FP_NON_VOLATILE_REGISTER_SET 0
|
||||
|
||||
#else
|
||||
|
||||
#error "Architecture must provide the following definitions:\n"
|
||||
|
|
114
tests/kernel/fp_sharing/generic/src/float_regs_arc_gcc.h
Normal file
114
tests/kernel/fp_sharing/generic/src/float_regs_arc_gcc.h
Normal file
|
@ -0,0 +1,114 @@
|
|||
/**
|
||||
* @file
|
||||
* @brief ARC GCC specific floating point register macros
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019, Synopsys.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _FLOAT_REGS_ARC_GCC_H
|
||||
#define _FLOAT_REGS_ARC_GCC_H
|
||||
|
||||
#if !defined(__GNUC__) || !defined(CONFIG_CPU_ARCV2)
|
||||
#error __FILE__ goes only with ARC GCC
|
||||
#endif
|
||||
|
||||
#include <toolchain.h>
|
||||
#include "float_context.h"
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Load all floating point registers
|
||||
*
|
||||
* This function loads ALL floating point registers pointed to by @a regs.
|
||||
* It is expected that a subsequent call to _store_all_float_registers()
|
||||
* will be issued to dump the floating point registers to memory.
|
||||
*
|
||||
* The format/organization of 'struct fp_register_set'; the generic C test
|
||||
* code (main.c) merely treat the register set as an array of bytes.
|
||||
*
|
||||
* The only requirement is that the arch specific implementations of
|
||||
* _load_all_float_registers() and _store_all_float_registers() agree
|
||||
* on the format.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static inline void _load_all_float_registers(struct fp_register_set *regs)
|
||||
{
|
||||
u32_t temp = 0;
|
||||
|
||||
#ifdef CONFIG_FP_FPU_DA
|
||||
__asm__ volatile (
|
||||
"ld.ab %1, [%0, 4];\n\t"
|
||||
"sr %1, [%2];\n\t"
|
||||
"ld.ab %1, [%0, 4];\n\t"
|
||||
"sr %1, [%3];\n\t"
|
||||
"ld.ab %1, [%0, 4];\n\t"
|
||||
"sr %1, [%4];\n\t"
|
||||
"ld.ab %1, [%0, 4];\n\t"
|
||||
"sr %1, [%5];\n\t"
|
||||
: : "r" (regs), "r" (temp),
|
||||
"i"(_ARC_V2_FPU_DPFP1L), "i"(_ARC_V2_FPU_DPFP1H),
|
||||
"i"(_ARC_V2_FPU_DPFP2L), "i"(_ARC_V2_FPU_DPFP2H)
|
||||
: "memory"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Dump all floating point registers to memory
|
||||
*
|
||||
* This function stores ALL floating point registers to the memory buffer
|
||||
* specified by @a regs. It is expected that a previous invocation of
|
||||
* _load_all_float_registers() occurred to load all the floating point
|
||||
* registers from a memory buffer.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
static inline void _store_all_float_registers(struct fp_register_set *regs)
|
||||
{
|
||||
u32_t temp = 0;
|
||||
|
||||
#ifdef CONFIG_FP_FPU_DA
|
||||
__asm__ volatile (
|
||||
"lr %1, [%2];\n\t"
|
||||
"st.ab %1, [%0, 4];\n\t"
|
||||
"lr %1, [%3];\n\t"
|
||||
"st.ab %1, [%0, 4];\n\t"
|
||||
"lr %1, [%4];\n\t"
|
||||
"st.ab %1, [%0, 4];\n\t"
|
||||
"lr %1, [%5];\n\t"
|
||||
"st.ab %1, [%0, 4];\n\t"
|
||||
: : "r" (regs), "r" (temp),
|
||||
"i"(_ARC_V2_FPU_DPFP1L), "i"(_ARC_V2_FPU_DPFP1H),
|
||||
"i"(_ARC_V2_FPU_DPFP2L), "i"(_ARC_V2_FPU_DPFP2H)
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Load then dump all float registers to memory
|
||||
*
|
||||
* This function loads ALL floating point registers from the memory buffer
|
||||
* specified by @a regs, and then stores them back to that buffer.
|
||||
*
|
||||
* This routine is called by a high priority thread prior to calling a primitive
|
||||
* that pends and triggers a co-operative context switch to a low priority
|
||||
* thread.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
static inline void _load_then_store_all_float_registers(struct fp_register_set
|
||||
*regs)
|
||||
{
|
||||
_load_all_float_registers(regs);
|
||||
_store_all_float_registers(regs);
|
||||
}
|
||||
#endif /* _FLOAT_REGS_ARC_GCC_H */
|
|
@ -63,6 +63,12 @@
|
|||
#else
|
||||
#include "float_regs_arm_other.h"
|
||||
#endif /* __GNUC__ */
|
||||
#elif defined(CONFIG_CPU_ARCV2)
|
||||
#if defined(__GNUC__)
|
||||
#include "float_regs_arc_gcc.h"
|
||||
#else
|
||||
#include "float_regs_arc_other.h"
|
||||
#endif /* __GNUC__ */
|
||||
#endif
|
||||
|
||||
#include <tc_util.h>
|
||||
|
|
|
@ -12,3 +12,10 @@ tests:
|
|||
slow: true
|
||||
tags: kernel
|
||||
timeout: 600
|
||||
kernel.fp_sharing.arc:
|
||||
extra_args: PI_NUM_ITERATIONS=500
|
||||
filter: CONFIG_CPU_ARCV2 and CONFIG_CPU_HAS_FPU
|
||||
slow: true
|
||||
tags: kernel
|
||||
timeout: 600
|
||||
min_ram: 16
|
||||
|
|
Loading…
Reference in a new issue