From a5515d43a51c1ba7a0fe6bbe4fd1432e036bc1fe Mon Sep 17 00:00:00 2001 From: Lucas Tamborrino Date: Tue, 11 Oct 2022 14:32:05 -0300 Subject: [PATCH] tests: kernel: fpu_sharing: add xtensa arch Add xtensa arch to Shared Floating Point Support test. Signed-off-by: Lucas Tamborrino --- .../fpu_sharing/generic/src/float_context.h | 13 +++ .../generic/src/float_regs_xtensa.h | 103 ++++++++++++++++++ .../fpu_sharing/generic/src/load_store.c | 2 + 3 files changed, 118 insertions(+) create mode 100644 tests/kernel/fpu_sharing/generic/src/float_regs_xtensa.h diff --git a/tests/kernel/fpu_sharing/generic/src/float_context.h b/tests/kernel/fpu_sharing/generic/src/float_context.h index 6cebde58bff..12051ae770d 100644 --- a/tests/kernel/fpu_sharing/generic/src/float_context.h +++ b/tests/kernel/fpu_sharing/generic/src/float_context.h @@ -150,6 +150,19 @@ struct fp_non_volatile_register_set { #define SIZEOF_FP_VOLATILE_REGISTER_SET sizeof(struct fp_volatile_register_set) #define SIZEOF_FP_NON_VOLATILE_REGISTER_SET 0 +#elif defined(CONFIG_XTENSA) + +struct fp_volatile_register_set { + /* No volatile floating point registers */ +}; + +struct fp_non_volatile_register_set { + uint32_t reg[18]; /* FR register file consists of 18 registers of 32 bits */ +}; + +#define SIZEOF_FP_VOLATILE_REGISTER_SET 0 +#define SIZEOF_FP_NON_VOLATILE_REGISTER_SET sizeof(struct fp_non_volatile_register_set) + #else #error "Architecture must provide the following definitions:\n" diff --git a/tests/kernel/fpu_sharing/generic/src/float_regs_xtensa.h b/tests/kernel/fpu_sharing/generic/src/float_regs_xtensa.h new file mode 100644 index 00000000000..8296e125fa6 --- /dev/null +++ b/tests/kernel/fpu_sharing/generic/src/float_regs_xtensa.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _FLOAT_REGS_XTENSA_H +#define _FLOAT_REGS_XTENSA_H + +#include +#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. + * + */ +static inline void _load_all_float_registers(struct fp_register_set *regs) +{ + __asm__ volatile("wfr f0, %0\n" :: "r"(regs->fp_non_volatile.reg[0])); + __asm__ volatile("wfr f1, %0\n" :: "r"(regs->fp_non_volatile.reg[1])); + __asm__ volatile("wfr f2, %0\n" :: "r"(regs->fp_non_volatile.reg[2])); + __asm__ volatile("wfr f3, %0\n" :: "r"(regs->fp_non_volatile.reg[3])); + __asm__ volatile("wfr f4, %0\n" :: "r"(regs->fp_non_volatile.reg[4])); + __asm__ volatile("wfr f5, %0\n" :: "r"(regs->fp_non_volatile.reg[5])); + __asm__ volatile("wfr f6, %0\n" :: "r"(regs->fp_non_volatile.reg[6])); + __asm__ volatile("wfr f7, %0\n" :: "r"(regs->fp_non_volatile.reg[7])); + __asm__ volatile("wfr f8, %0\n" :: "r"(regs->fp_non_volatile.reg[8])); + __asm__ volatile("wfr f9, %0\n" :: "r"(regs->fp_non_volatile.reg[9])); + __asm__ volatile("wfr f10, %0\n" :: "r"(regs->fp_non_volatile.reg[10])); + __asm__ volatile("wfr f11, %0\n" :: "r"(regs->fp_non_volatile.reg[11])); + __asm__ volatile("wfr f12, %0\n" :: "r"(regs->fp_non_volatile.reg[12])); + __asm__ volatile("wfr f13, %0\n" :: "r"(regs->fp_non_volatile.reg[13])); + __asm__ volatile("wfr f14, %0\n" :: "r"(regs->fp_non_volatile.reg[14])); + __asm__ volatile("wfr f15, %0\n" :: "r"(regs->fp_non_volatile.reg[15])); + __asm__ volatile("wur.fsr %0\n" :: "r"(regs->fp_non_volatile.reg[16])); + __asm__ volatile("wur.fcr %0\n" :: "r"(regs->fp_non_volatile.reg[17])); +} + +/** + * + * @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. + * + */ + +static inline void _store_all_float_registers(struct fp_register_set *regs) +{ + __asm__ volatile("rfr %0, f0\n" : "=r"(regs->fp_non_volatile.reg[0])); + __asm__ volatile("rfr %0, f1\n" : "=r"(regs->fp_non_volatile.reg[1])); + __asm__ volatile("rfr %0, f2\n" : "=r"(regs->fp_non_volatile.reg[2])); + __asm__ volatile("rfr %0, f3\n" : "=r"(regs->fp_non_volatile.reg[3])); + __asm__ volatile("rfr %0, f4\n" : "=r"(regs->fp_non_volatile.reg[4])); + __asm__ volatile("rfr %0, f5\n" : "=r"(regs->fp_non_volatile.reg[5])); + __asm__ volatile("rfr %0, f6\n" : "=r"(regs->fp_non_volatile.reg[6])); + __asm__ volatile("rfr %0, f7\n" : "=r"(regs->fp_non_volatile.reg[7])); + __asm__ volatile("rfr %0, f8\n" : "=r"(regs->fp_non_volatile.reg[8])); + __asm__ volatile("rfr %0, f9\n" : "=r"(regs->fp_non_volatile.reg[9])); + __asm__ volatile("rfr %0, f10\n" : "=r"(regs->fp_non_volatile.reg[10])); + __asm__ volatile("rfr %0, f11\n" : "=r"(regs->fp_non_volatile.reg[11])); + __asm__ volatile("rfr %0, f12\n" : "=r"(regs->fp_non_volatile.reg[12])); + __asm__ volatile("rfr %0, f13\n" : "=r"(regs->fp_non_volatile.reg[13])); + __asm__ volatile("rfr %0, f14\n" : "=r"(regs->fp_non_volatile.reg[14])); + __asm__ volatile("rfr %0, f15\n" : "=r"(regs->fp_non_volatile.reg[15])); + __asm__ volatile("rur.fsr %0\n" : "=r"(regs->fp_non_volatile.reg[16])); + __asm__ volatile("rur.fcr %0\n" : "=r"(regs->fp_non_volatile.reg[17])); +} + +/** + * + * @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. + * + */ +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_XTENSA_H */ diff --git a/tests/kernel/fpu_sharing/generic/src/load_store.c b/tests/kernel/fpu_sharing/generic/src/load_store.c index d1ff353f46c..204b334bfaf 100644 --- a/tests/kernel/fpu_sharing/generic/src/load_store.c +++ b/tests/kernel/fpu_sharing/generic/src/load_store.c @@ -70,6 +70,8 @@ #endif /* __GNUC__ */ #elif defined(CONFIG_SPARC) #include "float_regs_sparc.h" +#elif defined(CONFIG_XTENSA) +#include "float_regs_xtensa.h" #endif #include "float_context.h"