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:
Wayne Ren 2019-06-17 18:53:06 +08:00 committed by Andrew Boie
parent 98a3399138
commit 8b04c7de13
8 changed files with 175 additions and 3 deletions

View file

@ -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.

View file

@ -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 */

View file

@ -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

View file

@ -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

View file

@ -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"

View 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 */

View file

@ -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>

View file

@ -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