blob: a582d41fa051a666f99ad405665578f145e0599f [file] [log] [blame]
/**
* @file
* @brief ARM64 GCC specific floating point register macros
*/
/*
* Copyright (c) 2021 BayLibre SAS
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _FLOAT_REGS_ARM64_GCC_H
#define _FLOAT_REGS_ARM64_GCC_H
#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.
*
*/
static inline void _load_all_float_registers(struct fp_register_set *regs)
{
__asm__ volatile (
"ldp q0, q1, [x0, #(16 * 0)]\n\t"
"ldp q2, q3, [x0, #(16 * 2)]\n\t"
"ldp q4, q5, [x0, #(16 * 4)]\n\t"
"ldp q6, q7, [x0, #(16 * 6)]\n\t"
"ldp q8, q9, [x0, #(16 * 8)]\n\t"
"ldp q10, q11, [x0, #(16 * 10)]\n\t"
"ldp q12, q13, [x0, #(16 * 12)]\n\t"
"ldp q14, q15, [x0, #(16 * 14)]\n\t"
"ldp q16, q17, [x0, #(16 * 16)]\n\t"
"ldp q18, q19, [x0, #(16 * 18)]\n\t"
"ldp q20, q21, [x0, #(16 * 20)]\n\t"
"ldp q22, q23, [x0, #(16 * 22)]\n\t"
"ldp q24, q25, [x0, #(16 * 24)]\n\t"
"ldp q26, q27, [x0, #(16 * 26)]\n\t"
"ldp q28, q29, [x0, #(16 * 28)]\n\t"
"ldp q30, q31, [x0, #(16 * 30)]"
:
: "r" (regs)
);
}
/**
*
* @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 (
"stp q0, q1, [x0, #(16 * 0)]\n\t"
"stp q2, q3, [x0, #(16 * 2)]\n\t"
"stp q4, q5, [x0, #(16 * 4)]\n\t"
"stp q6, q7, [x0, #(16 * 6)]\n\t"
"stp q8, q9, [x0, #(16 * 8)]\n\t"
"stp q10, q11, [x0, #(16 * 10)]\n\t"
"stp q12, q13, [x0, #(16 * 12)]\n\t"
"stp q14, q15, [x0, #(16 * 14)]\n\t"
"stp q16, q17, [x0, #(16 * 16)]\n\t"
"stp q18, q19, [x0, #(16 * 18)]\n\t"
"stp q20, q21, [x0, #(16 * 20)]\n\t"
"stp q22, q23, [x0, #(16 * 22)]\n\t"
"stp q24, q25, [x0, #(16 * 24)]\n\t"
"stp q26, q27, [x0, #(16 * 26)]\n\t"
"stp q28, q29, [x0, #(16 * 28)]\n\t"
"stp q30, q31, [x0, #(16 * 30)]"
:
: "r" (regs)
: "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_ARM64_GCC_H */