You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/04/14 18:53:25 UTC

[incubator-nuttx] 05/06: Add fpu support.

This is an automated email from the ASF dual-hosted git repository.

gnutt pushed a commit to branch pr789
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 934fccc2ffd225a98c42fa508e21d56d7c0db0b9
Author: zhongan <zh...@xiaomi.com>
AuthorDate: Thu Apr 2 11:20:20 2020 +0800

    Add fpu support.
    
    Change-Id: I1220a58a635546cc954ff04cfacca356923b4b51
    Signed-off-by: zhongan <zh...@xiaomi.com>
---
 arch/risc-v/include/rv32im/irq.h     | 129 +++++++++++++++++-
 arch/risc-v/src/common/up_internal.h |   8 ++
 arch/risc-v/src/rv32im/up_fpu.S      | 251 +++++++++++++++++++++++++++++++++++
 3 files changed, 386 insertions(+), 2 deletions(-)

diff --git a/arch/risc-v/include/rv32im/irq.h b/arch/risc-v/include/rv32im/irq.h
index 3944d9d..567a75c 100644
--- a/arch/risc-v/include/rv32im/irq.h
+++ b/arch/risc-v/include/rv32im/irq.h
@@ -132,11 +132,63 @@
 #ifdef CONFIG_ARCH_CHIP_GAP8
 /* 31 registers, ePC, plus 6 loop registers */
 
-#  define XCPTCONTEXT_REGS  (32 + 6)
+#  define INT_XCPT_REGS     (32 + 6)
 #else
-#  define XCPTCONTEXT_REGS  33
+#  define INT_XCPT_REGS     33
 #endif
 
+#define INT_XCPT_SIZE       (4 * INT_XCPT_REGS)
+
+#ifdef CONFIG_ARCH_FPU
+
+#if defined(CONFIG_ARCH_DPFPU)
+#  define FPU_REG_SIZE      2
+#elif defined(CONFIG_ARCH_QPFPU)
+#  define FPU_REG_SIZE      4
+#else
+#  define FPU_REG_SIZE      1
+#endif
+
+#  define REG_F0_NDX        (INT_XCPT_REGS + FPU_REG_SIZE * 0)
+#  define REG_F1_NDX        (INT_XCPT_REGS + FPU_REG_SIZE * 1)
+#  define REG_F2_NDX        (INT_XCPT_REGS + FPU_REG_SIZE * 2)
+#  define REG_F3_NDX        (INT_XCPT_REGS + FPU_REG_SIZE * 3)
+#  define REG_F4_NDX        (INT_XCPT_REGS + FPU_REG_SIZE * 4)
+#  define REG_F5_NDX        (INT_XCPT_REGS + FPU_REG_SIZE * 5)
+#  define REG_F6_NDX        (INT_XCPT_REGS + FPU_REG_SIZE * 6)
+#  define REG_F7_NDX        (INT_XCPT_REGS + FPU_REG_SIZE * 7)
+#  define REG_F8_NDX        (INT_XCPT_REGS + FPU_REG_SIZE * 8)
+#  define REG_F9_NDX        (INT_XCPT_REGS + FPU_REG_SIZE * 9)
+#  define REG_F10_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 10)
+#  define REG_F11_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 11)
+#  define REG_F12_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 12)
+#  define REG_F13_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 13)
+#  define REG_F14_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 14)
+#  define REG_F15_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 15)
+#  define REG_F16_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 16)
+#  define REG_F17_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 17)
+#  define REG_F18_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 18)
+#  define REG_F19_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 19)
+#  define REG_F20_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 20)
+#  define REG_F21_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 21)
+#  define REG_F22_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 22)
+#  define REG_F23_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 23)
+#  define REG_F24_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 24)
+#  define REG_F25_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 25)
+#  define REG_F26_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 26)
+#  define REG_F27_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 27)
+#  define REG_F28_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 28)
+#  define REG_F29_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 29)
+#  define REG_F30_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 30)
+#  define REG_F31_NDX       (INT_XCPT_REGS + FPU_REG_SIZE * 31)
+#  define REG_FCSR_NDX      (INT_XCPT_REGS + FPU_REG_SIZE * 32)
+
+#  define FPU_XCPT_REGS     (FPU_REG_SIZE * 33)
+#else
+#  define FPU_XCPT_REGS     0
+#endif
+
+#define XCPTCONTEXT_REGS    (INT_XCPT_REGS + FPU_XCPT_REGS)
 #define XCPTCONTEXT_SIZE    (4 * XCPTCONTEXT_REGS)
 
 /* In assembly language, values have to be referenced as byte address
@@ -178,6 +230,42 @@
 #  define REG_X30           (4*REG_X30_NDX)
 #  define REG_X31           (4*REG_X31_NDX)
 #  define REG_INT_CTX       (4*REG_INT_CTX_NDX)
+#ifdef CONFIG_ARCH_FPU
+#  define REG_F0            (4*REG_F0_NDX)
+#  define REG_F1            (4*REG_F1_NDX)
+#  define REG_F2            (4*REG_F2_NDX)
+#  define REG_F3            (4*REG_F3_NDX)
+#  define REG_F4            (4*REG_F4_NDX)
+#  define REG_F5            (4*REG_F5_NDX)
+#  define REG_F6            (4*REG_F6_NDX)
+#  define REG_F7            (4*REG_F7_NDX)
+#  define REG_F8            (4*REG_F8_NDX)
+#  define REG_F9            (4*REG_F9_NDX)
+#  define REG_F10           (4*REG_F10_NDX)
+#  define REG_F11           (4*REG_F11_NDX)
+#  define REG_F12           (4*REG_F12_NDX)
+#  define REG_F13           (4*REG_F13_NDX)
+#  define REG_F14           (4*REG_F14_NDX)
+#  define REG_F15           (4*REG_F15_NDX)
+#  define REG_F16           (4*REG_F16_NDX)
+#  define REG_F17           (4*REG_F17_NDX)
+#  define REG_F18           (4*REG_F18_NDX)
+#  define REG_F19           (4*REG_F19_NDX)
+#  define REG_F20           (4*REG_F20_NDX)
+#  define REG_F21           (4*REG_F21_NDX)
+#  define REG_F22           (4*REG_F22_NDX)
+#  define REG_F23           (4*REG_F23_NDX)
+#  define REG_F24           (4*REG_F24_NDX)
+#  define REG_F25           (4*REG_F25_NDX)
+#  define REG_F26           (4*REG_F26_NDX)
+#  define REG_F27           (4*REG_F27_NDX)
+#  define REG_F28           (4*REG_F28_NDX)
+#  define REG_F29           (4*REG_F29_NDX)
+#  define REG_F30           (4*REG_F30_NDX)
+#  define REG_F31           (4*REG_F31_NDX)
+#  define REG_FCSR          (4*REG_FCSR_NDX)
+#endif
+
 #else
 #  define REG_EPC           REG_EPC_NDX
 #  define REG_X1            REG_X1_NDX
@@ -212,6 +300,43 @@
 #  define REG_X30           REG_X30_NDX
 #  define REG_X31           REG_X31_NDX
 #  define REG_INT_CTX       REG_INT_CTX_NDX
+
+#ifdef CONFIG_ARCH_FPU
+#  define REG_F0            REG_F0_NDX
+#  define REG_F1            REG_F1_NDX
+#  define REG_F2            REG_F2_NDX
+#  define REG_F3            REG_F3_NDX
+#  define REG_F4            REG_F4_NDX
+#  define REG_F5            REG_F5_NDX
+#  define REG_F6            REG_F6_NDX
+#  define REG_F7            REG_F7_NDX
+#  define REG_F8            REG_F8_NDX
+#  define REG_F9            REG_F9_NDX
+#  define REG_F10           REG_F10_NDX
+#  define REG_F11           REG_F11_NDX
+#  define REG_F12           REG_F12_NDX
+#  define REG_F13           REG_F13_NDX
+#  define REG_F14           REG_F14_NDX
+#  define REG_F15           REG_F15_NDX
+#  define REG_F16           REG_F16_NDX
+#  define REG_F17           REG_F17_NDX
+#  define REG_F18           REG_F18_NDX
+#  define REG_F19           REG_F19_NDX
+#  define REG_F20           REG_F20_NDX
+#  define REG_F21           REG_F21_NDX
+#  define REG_F22           REG_F22_NDX
+#  define REG_F23           REG_F23_NDX
+#  define REG_F24           REG_F24_NDX
+#  define REG_F25           REG_F25_NDX
+#  define REG_F26           REG_F26_NDX
+#  define REG_F27           REG_F27_NDX
+#  define REG_F28           REG_F28_NDX
+#  define REG_F29           REG_F29_NDX
+#  define REG_F30           REG_F30_NDX
+#  define REG_F31           REG_F31_NDX
+#  define REG_FCSR          REG_FCSR_NDX
+#endif
+
 #endif
 
 /* Now define more user friendly alternative name that can be used either
diff --git a/arch/risc-v/src/common/up_internal.h b/arch/risc-v/src/common/up_internal.h
index ef9a9b2..068d05f 100644
--- a/arch/risc-v/src/common/up_internal.h
+++ b/arch/risc-v/src/common/up_internal.h
@@ -193,6 +193,14 @@ void up_sigdeliver(void);
 int up_swint(int irq, FAR void *context, FAR void *arg);
 uint32_t up_get_newintctx(void);
 
+#ifdef CONFIG_ARCH_FPU
+void up_savefpu(uint32_t *regs);
+void up_restorefpu(const uint32_t *regs);
+#else
+#  define up_savefpu(regs)
+#  define up_restorefpu(regs)
+#endif
+
 /* Low level serial output **************************************************/
 
 void up_lowputc(char ch);
diff --git a/arch/risc-v/src/rv32im/up_fpu.S b/arch/risc-v/src/rv32im/up_fpu.S
new file mode 100644
index 0000000..f24c867
--- /dev/null
+++ b/arch/risc-v/src/rv32im/up_fpu.S
@@ -0,0 +1,251 @@
+/************************************************************************************
+ * arch/risc-v/src/rv32im/up_fpu.S
+ *
+ *   Copyright (C) 2018 Pinecone Inc. All rights reserved.
+ *   Author: Zhang Xiaoqin <zh...@pinecone.net>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include <arch/rv32im/irq.h>
+
+#ifdef CONFIG_ARCH_FPU
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Symbols
+ ************************************************************************************/
+
+	.globl		up_fpuconfig
+	.globl		up_savefpu
+	.globl		up_restorefpu
+
+	.file		"up_fpu.S"
+
+#define FS_MASK		0x6000
+#define FS_OFF		0x0000
+#define FS_INITIAL	0x2000
+#define FS_CLEAN	0x4000
+#define FS_DIRTY	0x6000
+
+#if defined(CONFIG_ARCH_DPFPU)
+#  define FLOAD		fld
+#  define FSTORE	fsd
+#elif defined(CONFIG_ARCH_QPFPU)
+#  define FLOAD		flq
+#  define FSTORE	fsq
+#else
+#  define FLOAD		flw
+#  define FSTORE	fsw
+#endif
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: up_fpuconfig
+ *
+ * Description:
+ *   init fpu
+ *
+ * C Function Prototype:
+ *   void up_fpuconfig(void);
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   This function does not return anything explicitly.
+ *
+ ************************************************************************************/
+
+	.type		up_fpuconfig, function
+
+up_fpuconfig:
+	li		a0, FS_INITIAL
+	csrs		mstatus, a0
+	csrwi		fcsr, 0
+	ret
+
+/************************************************************************************
+ * Name: up_savefpu
+ *
+ * Description:
+ *   Given the pointer to a register save area (in A0), save the state of the
+ *   floating point registers.
+ *
+ * C Function Prototype:
+ *   void up_savefpu(uint32_t *regs);
+ *
+ * Input Parameters:
+ *   regs - A pointer to the register save area in which to save the floating point
+ *     registers
+ *
+ * Returned Value:
+ *   None
+ *
+ ************************************************************************************/
+
+	.type		up_savefpu, function
+
+up_savefpu:
+	lw		t0, REG_INT_CTX(a0)
+	li		t1, FS_MASK
+	and		t2, t0, t1
+	li		t1, FS_DIRTY
+	bne		t2, t1, 1f
+	li		t1, ~FS_MASK
+	and		t0, t0, t1
+	li		t1, FS_CLEAN
+	or		t0, t0, t1
+	sw		t0, REG_INT_CTX(a0)
+
+	/* Store all floating point registers */
+
+	FSTORE		f0,  REG_F0(a0)
+	FSTORE		f1,  REG_F1(a0)
+	FSTORE		f2,  REG_F2(a0)
+	FSTORE		f3,  REG_F3(a0)
+	FSTORE		f4,  REG_F4(a0)
+	FSTORE		f5,  REG_F5(a0)
+	FSTORE		f6,  REG_F6(a0)
+	FSTORE		f7,  REG_F7(a0)
+	FSTORE		f8,  REG_F8(a0)
+	FSTORE		f9,  REG_F9(a0)
+	FSTORE		f10, REG_F10(a0)
+	FSTORE		f11, REG_F11(a0)
+	FSTORE		f12, REG_F12(a0)
+	FSTORE		f13, REG_F13(a0)
+	FSTORE		f14, REG_F14(a0)
+	FSTORE		f15, REG_F15(a0)
+	FSTORE		f16, REG_F16(a0)
+	FSTORE		f17, REG_F17(a0)
+	FSTORE		f18, REG_F18(a0)
+	FSTORE		f19, REG_F19(a0)
+	FSTORE		f20, REG_F20(a0)
+	FSTORE		f21, REG_F21(a0)
+	FSTORE		f22, REG_F22(a0)
+	FSTORE		f23, REG_F23(a0)
+	FSTORE		f24, REG_F24(a0)
+	FSTORE		f25, REG_F25(a0)
+	FSTORE		f26, REG_F26(a0)
+	FSTORE		f27, REG_F27(a0)
+	FSTORE		f28, REG_F28(a0)
+	FSTORE		f29, REG_F29(a0)
+	FSTORE		f30, REG_F30(a0)
+	FSTORE		f31, REG_F31(a0)
+
+	frcsr		t0
+	sw		t0, REG_FCSR(a0)
+
+1:
+	ret
+
+/************************************************************************************
+ * Name: up_restorefpu
+ *
+ * Description:
+ *   Given the pointer to a register save area (in A0), restore the state of the
+ *   floating point registers.
+ *
+ * C Function Prototype:
+ *   void up_restorefpu(const uint32_t *regs);
+ *
+ * Input Parameters:
+ *   regs - A pointer to the register save area containing the floating point
+ *     registers.
+ *
+ * Returned Value:
+ *   This function does not return anything explicitly.  However, it is called from
+ *   interrupt level assembly logic that assumes that r0 is preserved.
+ *
+ ************************************************************************************/
+
+	.type		up_restorefpu, function
+
+up_restorefpu:
+	lw		t0, REG_INT_CTX(a0)
+	li		t1, FS_MASK
+	and		t2, t0, t1
+	li		t1, FS_INITIAL
+	ble		t2, t1, 1f
+
+	/* Load all floating point registers */
+
+	FLOAD		f0, REG_F0(a0)
+	FLOAD		f1, REG_F1(a0)
+	FLOAD		f2, REG_F2(a0)
+	FLOAD		f3, REG_F3(a0)
+	FLOAD		f4, REG_F4(a0)
+	FLOAD		f5, REG_F5(a0)
+	FLOAD		f6, REG_F6(a0)
+	FLOAD		f7, REG_F7(a0)
+	FLOAD		f8, REG_F8(a0)
+	FLOAD		f9, REG_F9(a0)
+	FLOAD		f10, REG_F10(a0)
+	FLOAD		f11, REG_F11(a0)
+	FLOAD		f12, REG_F12(a0)
+	FLOAD		f13, REG_F13(a0)
+	FLOAD		f14, REG_F14(a0)
+	FLOAD		f15, REG_F15(a0)
+	FLOAD		f16, REG_F16(a0)
+	FLOAD		f17, REG_F17(a0)
+	FLOAD		f18, REG_F18(a0)
+	FLOAD		f19, REG_F19(a0)
+	FLOAD		f20, REG_F20(a0)
+	FLOAD		f21, REG_F21(a0)
+	FLOAD		f22, REG_F22(a0)
+	FLOAD		f23, REG_F23(a0)
+	FLOAD		f24, REG_F24(a0)
+	FLOAD		f25, REG_F25(a0)
+	FLOAD		f26, REG_F26(a0)
+	FLOAD		f27, REG_F27(a0)
+	FLOAD		f28, REG_F28(a0)
+	FLOAD		f29, REG_F29(a0)
+	FLOAD		f30, REG_F30(a0)
+	FLOAD		f31, REG_F31(a0)
+
+	/* Store the floating point control and status register */
+
+	lw		t0, REG_FCSR(a0)
+	fscsr		t0
+
+1:
+	ret
+
+#endif /* CONFIG_ARCH_FPU */