Skip to content

Commit

Permalink
test_fp_sharing: clean up test code
Browse files Browse the repository at this point in the history
Clean up test code in preparation for adding Cortex-M4 support.

Change-Id: I64a32e8aa2808b4e0348601e2fc0f7f39cdb413c
Signed-off-by: Peter Mitsis <[email protected]>
  • Loading branch information
wrsPeterMitsis committed Jul 1, 2016
1 parent 005925e commit 3490627
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 248 deletions.
2 changes: 1 addition & 1 deletion tests/kernel/test_fp_sharing/microkernel/src/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ccflags-y += -I${ZEPHYR_BASE}/tests/include

obj-y += main.o
obj-y += pi.o
obj-$(CONFIG_MICROKERNEL) += pi.o
91 changes: 50 additions & 41 deletions tests/kernel/test_fp_sharing/microkernel/src/float_context.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
/* float_context.h - common definitions for the FPU sharing test application */
/**
* @file
* @brief common definitions for the FPU sharing test application
*/

/*
* Copyright (c) 2011-2014 Wind River Systems, Inc.
Expand All @@ -20,10 +23,21 @@
#define _FLOATCONTEXT_H

/*
* Each architecture must define the FP_REG_SET and FP_NONVOLATILE_REG_SET
* structures, and tailor the architecture specific implementations of
* _LoadAllFloatRegisters(), _StoreAllFloatRegisters(), and
* _StoreNonVolatileFloatRegisters() to read/write from these structures.
* Each architecture must define the following structures (which may be empty):
* 'struct fp_volatile_register_set'
* 'struct fp_non_volatile_register_set'
*
* Each architecture must also define the following macros:
* SIZEOF_FP_VOLATILE_REGISTER_SET
* SIZEOF_FP_NON_VOLATILE_REGISTER_SET
* Those macros are used as sizeof(<an empty structure>) is compiler specific;
* that is, it may evaluate to a non-zero value.
*
* Each architecture shall also have custom implementations of:
* _load_all_float_registers()
* _load_then_store_all_float_registers()
* _store_all_float_registers()
* _store_non_volatile_float_registers()
*/

#if defined(CONFIG_ISA_IA32)
Expand All @@ -32,57 +46,52 @@

/*
* In the future, the struct definitions may need to be refined based on the
* specific IA-32 processor, but for now only the Pentium4 is supported.
* specific IA-32 processor, but for now only the Pentium4 is supported:
*
* There exists 8 x 80 bit floating point registers (ST[0] -> ST[7]) and
* 8 * 128 bit XMM registers (XMM[0] -> XMM[7]). All of these registers are
* considered volatile across a function invocation.
* 8 x 80 bit floating point registers (ST[0] -> ST[7])
* 8 x 128 bit XMM registers (XMM[0] -> XMM[7])
*
* All these registers are considered volatile across a function invocation.
*/

/* a single x87 FPU register in double extended format (80 bits) */

typedef struct fpReg {
struct fp_register {
unsigned char reg[10];
} FP_REG;
};

/* a single XMM register (128 bits) */

typedef struct xmmReg {
struct xmm_register {
unsigned char reg[16];
} XMM_REG;

/* the set of volatile floating point registers */

typedef struct fpVolatileRegSet {
XMM_REG xmmRegs[8]; /* XMM[0] -> XMM[7] */
FP_REG fpRegs[8]; /* ST[0] -> ST[7] */
} FP_VOLATILE_REG_SET;

/* the set of non-volatile floating point registers */
};

typedef struct fpNonVolatileRegSet {
/* this structure has been intentionally left blank */
} FP_NONVOLATILE_REG_SET;
struct fp_volatile_register_set {
struct xmm_register xmm[8]; /* XMM[0] -> XMM[7] */
struct fp_register st[8]; /* ST[0] -> ST[7] */
};

#define SIZEOF_FP_VOLATILE_REG_SET sizeof(FP_VOLATILE_REG_SET)
#define SIZEOF_FP_NONVOLATILE_REG_SET 0
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 /* ! CONFIG_ISA_IA32 */

#error Architecture needs to provide a definition for 'struct fpRegSet' \
and 'struct fpNonVolatileRegSet'
#error "Architecture must provide the following definitions:\n" \
"\t'struct fp_volatile_registers'\n" \
"\t'struct fp_non_volatile_registers'\n" \
"\t'SIZEOF_FP_VOLATILE_REGISTER_SET'\n" \
"\t'SIZEOF_FP_NON_VOLATILE_REGISTER_SET'\n"
#endif /* CONFIG_ISA_IA32 */

/* the set of ALL floating point registers */

typedef struct fpRegSet {
FP_VOLATILE_REG_SET fpVolRegSet;
FP_NONVOLATILE_REG_SET fpNonVolRegSet;
} FP_REG_SET;
struct fp_register_set {
struct fp_volatile_register_set fp_volatile;
struct fp_non_volatile_register_set fp_non_volatile;
};

#define SIZEOF_FP_REG_SET \
(SIZEOF_FP_VOLATILE_REG_SET + SIZEOF_FP_NONVOLATILE_REG_SET)
#define SIZEOF_FP_REGISTER_SET \
(SIZEOF_FP_VOLATILE_REGISTER_SET + SIZEOF_FP_NON_VOLATILE_REGISTER_SET)

/*
* The following constants define the initial byte value used by the background
Expand All @@ -92,8 +101,8 @@ typedef struct fpRegSet {
#define MAIN_FLOAT_REG_CHECK_BYTE (unsigned char)0xe5
#define FIBER_FLOAT_REG_CHECK_BYTE (unsigned char)0xf9

void _StoreNonVolatileFloatRegisters(FP_NONVOLATILE_REG_SET *pToBuffer);
void _store_non_volatile_float_registers(struct fp_non_volatile_register_set *regs);

extern int fpu_sharing_error;

#endif /* _FLOATRCONTEXT_H */
#endif /* _FLOATCONTEXT_H */
87 changes: 22 additions & 65 deletions tests/kernel/test_fp_sharing/microkernel/src/float_regs_x86_gcc.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
/* Intel x86 GCC specific floating point register macros */
/**
* @file
* @brief Intel x86 GCC specific floating point register macros
*/

/*
* Copyright (c) 2015, Wind River Systems, Inc.
Expand All @@ -20,7 +23,7 @@
#define _FLOAT_REGS_X86_GCC_H

#if !defined(__GNUC__) || !defined(CONFIG_ISA_IA32)
#error test_asm_inline_gcc.h goes only with x86 GCC
#error __FILE__ goes only with x86 GCC
#endif

#include <toolchain.h>
Expand All @@ -30,47 +33,22 @@
*
* @brief Load all floating point registers
*
* This function loads ALL floating point registers from the memory buffer
* specified by <pFromBuffer>. It is expected that a subsequent call to
* _StoreAllFloatRegisters() will be issued to dump the floating point registers
* to memory.
* 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 the FP_REG_SET structure is not important; the
* generic C test code (main.c and fiber.c) merely treat the FP_REG_SET
* (and FP_NONVOLATILE_REG_SET) as an array of bytes.
* 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
* _LoadAllFloatRegisters(), _StoreAllFloatRegisters(), and
* _LoadThenStoreAllFloatRegisters agree on the format.
* _load_all_float_registers(), _store_all_float_registers() and
* _load_then_store_all_float_registers() agree on the format.
*
* @return N/A
*/

static inline void _LoadAllFloatRegisters(FP_REG_SET *pFromBuffer)
static inline void _load_all_float_registers(struct fp_register_set *regs)
{
/*
* The 'movdqu' is the "move double quad unaligned" instruction: Move
* a double quadword (16 bytes) between memory and an XMM register (or
* between a pair of XMM registers). The memory destination/source operand
* may be unaligned on a 16-byte boundary without causing an exception.
*
* The 'fldt' is the "load floating point value" instruction: Push an 80-bit
* (double extended-precision) onto the FPU register stack.
*
* A note about operand size specification in the AT&T assembler syntax:
*
* Instructions are generally suffixed with the a letter or a pair of
* letters to specify the operand size:
*
* b = byte (8 bit)
* s = short (16 bit integer) or single (32-bit floating point)
* w = word (16 bit)
* l = long (32 bit integer or 64-bit floating point)
* q = quad (64 bit)
* t = ten bytes (80-bit floating point)
* dq = double quad (128 bit)
*/

__asm__ volatile (
"movdqu 0(%0), %%xmm0\n\t;"
"movdqu 16(%0), %%xmm1\n\t;"
Expand All @@ -90,7 +68,7 @@ static inline void _LoadAllFloatRegisters(FP_REG_SET *pFromBuffer)
"fldt 188(%0)\n\t;"
"fldt 198(%0)\n\t;"

:: "r" (pFromBuffer)
:: "r" (regs)
);
}

Expand All @@ -100,7 +78,7 @@ static inline void _LoadAllFloatRegisters(FP_REG_SET *pFromBuffer)
* @brief Load then dump all float registers to memory
*
* This function loads ALL floating point registers from the memory buffer
* specified by <pFromToBuffer>, and then stores them back to that 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
Expand All @@ -113,7 +91,7 @@ static inline void _LoadAllFloatRegisters(FP_REG_SET *pFromBuffer)
* @return N/A
*/

static inline void _LoadThenStoreAllFloatRegisters(FP_REG_SET *pFromToBuffer)
static inline void _load_then_store_all_float_registers(struct fp_register_set *regs)
{
__asm__ volatile (
"movdqu 0(%0), %%xmm0\n\t;"
Expand Down Expand Up @@ -145,7 +123,7 @@ static inline void _LoadThenStoreAllFloatRegisters(FP_REG_SET *pFromToBuffer)
"fstpt 138(%0)\n\t;"
"fstpt 128(%0)\n\t;"

:: "r" (pFromToBuffer)
:: "r" (regs)
);
}

Expand All @@ -155,14 +133,14 @@ static inline void _LoadThenStoreAllFloatRegisters(FP_REG_SET *pFromToBuffer)
* @brief Dump all floating point registers to memory
*
* This function stores ALL floating point registers to the memory buffer
* specified by <pToBuffer>. It is expected that a previous invocation of
* _LoadAllFloatRegisters() occurred to load all the floating point registers
* from a 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 _StoreAllFloatRegisters(FP_REG_SET *pToBuffer)
static inline void _store_all_float_registers(struct fp_register_set *regs)
{
__asm__ volatile (
"movdqu %%xmm0, 0(%0)\n\t;"
Expand All @@ -183,28 +161,7 @@ static inline void _StoreAllFloatRegisters(FP_REG_SET *pToBuffer)
"fstpt 138(%0)\n\t;"
"fstpt 128(%0)\n\t;"

:: "r" (pToBuffer) : "memory"
:: "r" (regs) : "memory"
);
}

/**
*
* @brief Dump non-volatile FP registers to memory
*
* This routine is called by a high priority thread after resuming execution
* from calling a primitive that will pend and thus result in a co-operative
* context switch to a low priority thread.
*
* Only the non-volatile floating point registers are expected to survive across
* a function call, regardless of whether the call results in the thread being
* pended.
*
* @return N/A
*/

void _StoreNonVolatileFloatRegisters(FP_NONVOLATILE_REG_SET *pToBuffer)
{
ARG_UNUSED(pToBuffer);
/* do nothing; there are no non-volatile floating point registers */
}
#endif /* _FLOAT_REGS_X86_GCC_H */
Loading

0 comments on commit 3490627

Please sign in to comment.