blob: 60d46f9f57c8b6ecdb0b0db64a026af41ccdabae [file] [log] [blame]
/**
* @file
* @brief RISCV GCC specific floating point register macros
*/
/*
* Copyright (c) 2019, Huang Qi <757509347@qq.com>.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _FLOAT_REGS_RISCV_GCC_H
#define _FLOAT_REGS_RISCV_GCC_H
#if !defined(__GNUC__) || !defined(CONFIG_RISCV)
#error __FILE__ goes only with RISCV GCC
#endif
#include <zephyr/toolchain.h>
#include "float_context.h"
#ifdef CONFIG_CPU_HAS_FPU_DOUBLE_PRECISION
#define RV_FPREG_WIDTH 8
#define RV_FPREG_SAVE "fsd "
#define RV_FPREG_LOAD "fld "
#else
#define RV_FPREG_WIDTH 4
#define RV_FPREG_SAVE "fsw "
#define RV_FPREG_LOAD "flw "
#endif
/**
*
* @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__(
"mv t0, %0\n"
"mv t1, %1\n"
RV_FPREG_LOAD "f0, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f1, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f2, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f3, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f4, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f5, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f6, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f7, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f8, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f9, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f10, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f11, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f12, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f13, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f14, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f15, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f16, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f17, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f18, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f19, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f20, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f21, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f22, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f23, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f24, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f25, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f26, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f27, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f28, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f29, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f30, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_LOAD "f31, 0(t0)\n"
:
: "r"(regs), "r"(RV_FPREG_WIDTH)
: "t0", "t1"
);
}
/**
*
* @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(
"mv t0, %0\n\t"
"mv t1, %1\n\t"
RV_FPREG_SAVE "f0, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f1, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f2, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f3, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f4, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f5, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f6, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f7, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f8, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f9, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f10, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f11, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f12, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f13, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f14, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f15, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f16, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f17, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f18, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f19, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f20, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f21, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f22, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f23, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f24, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f25, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f26, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f27, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f28, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f29, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f30, 0(t0)\n"
"add t0, t0, t1\n"
RV_FPREG_SAVE "f31, 0(t0)\n"
:
: "r"(regs), "r"(RV_FPREG_WIDTH)
: "t0", "t1", "memory"
);
}
/**
*
* @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_ARC_GCC_H */