1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-22 11:17:19 +00:00

Add full softfloat and hardfloat support for RISC-V.

Hardfloat is now default (use riscv64sf as TARGET_ARCH
for softfloat).

Sponsored by:	DARPA, AFRL
Differential Revision:	https://reviews.freebsd.org/D8529
This commit is contained in:
Ruslan Bukin 2016-11-16 15:21:32 +00:00
parent 33299e3d96
commit 7804dd5212
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=308731
35 changed files with 1000 additions and 182 deletions

View File

@ -239,7 +239,7 @@ _MAKE+= MK_META_MODE=no
_TARGET_ARCH= ${TARGET:S/pc98/i386/:S/arm64/aarch64/}
.elif !defined(TARGET) && defined(TARGET_ARCH) && \
${TARGET_ARCH} != ${MACHINE_ARCH}
_TARGET= ${TARGET_ARCH:C/mips(n32|64)?(el)?(hf)?/mips/:C/arm(v6)?(eb)?/arm/:C/aarch64/arm64/:C/powerpc64/powerpc/:C/powerpcspe/powerpc/:C/riscv64/riscv/}
_TARGET= ${TARGET_ARCH:C/mips(n32|64)?(el)?(hf)?/mips/:C/arm(v6)?(eb)?/arm/:C/aarch64/arm64/:C/powerpc64/powerpc/:C/powerpcspe/powerpc/:C/riscv64(sf)?/riscv/}
.endif
.if defined(TARGET) && !defined(_TARGET)
_TARGET=${TARGET}

View File

@ -364,6 +364,7 @@ KNOWN_ARCHES?= aarch64/arm64 \
powerpc64/powerpc \
powerpcspe/powerpc \
riscv64/riscv \
riscv64sf/riscv \
sparc64
.if ${TARGET} == ${TARGET_ARCH}

View File

@ -4,7 +4,7 @@
# MACHINE_CPUARCH, but there's no easy way to export make functions...
.if defined(TARGET_ARCH)
TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?(hf)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc(64|spe)/powerpc/}
TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?(hf)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc(64|spe)/powerpc/:C/riscv64(sf)?/riscv64/}
.else
TARGET_CPUARCH=${MACHINE_CPUARCH}
.endif

View File

@ -111,7 +111,8 @@ NOASM=
.include "${LIBC_SRCTOP}/xdr/Makefile.inc"
.if (${LIBC_ARCH} == "arm" && \
(${MACHINE_ARCH:Marmv6*} == "" || (defined(CPUTYPE) && ${CPUTYPE:M*soft*}))) || \
(${LIBC_ARCH} == "mips" && ${MACHINE_ARCH:Mmips*hf} == "")
(${LIBC_ARCH} == "mips" && ${MACHINE_ARCH:Mmips*hf} == "") || \
(${LIBC_ARCH} == "riscv" && ${MACHINE_ARCH:Mriscv*sf} != "")
.include "${LIBC_SRCTOP}/softfloat/Makefile.inc"
.endif
.if ${LIBC_ARCH} == "i386" || ${LIBC_ARCH} == "amd64"

View File

@ -3,6 +3,10 @@
# Machine dependent definitions for the RISC-V architecture.
#
.if ${MACHINE_ARCH:Mriscv*sf} != ""
CFLAGS+=-DSOFTFLOAT
.endif
# Long double is quad precision
GDTOASRCS+=strtorQ.c
MDSRCS+=machdep_ldisQ.c

View File

@ -35,4 +35,22 @@ FBSDprivate_1.0 {
_set_tp;
_end;
__makecontext;
/* softfloat */
__addsf3;
__adddf3;
__subsf3;
__subdf3;
__mulsf3;
__muldf3;
__divsf3;
__divdf3;
__floatsisf;
__floatsidf;
__fixsfsi;
__fixdfsi;
__fixunssfsi;
__fixunsdfsi;
__extendsfdf2;
__truncdfsf2;
};

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
@ -61,24 +61,21 @@ ENTRY(_setjmp)
sd ra, (12 * 8)(a0)
addi a0, a0, (13 * 8)
#ifndef _STANDALONE
#if 0
/* RISCVTODO */
/* Store the vfp registers */
fsq fs0, (0 * 16)(a0)
fsq fs1, (1 * 16)(a0)
fsq fs2, (2 * 16)(a0)
fsq fs3, (3 * 16)(a0)
fsq fs4, (4 * 16)(a0)
fsq fs5, (5 * 16)(a0)
fsq fs6, (6 * 16)(a0)
fsq fs7, (7 * 16)(a0)
fsq fs8, (8 * 16)(a0)
fsq fs9, (9 * 16)(a0)
fsq fs10, (10 * 16)(a0)
fsq fs11, (11 * 16)(a0)
#if !defined(_STANDALONE) && !defined(SOFTFLOAT)
/* Store the fpe registers */
fsd fs0, (0 * 16)(a0)
fsd fs1, (1 * 16)(a0)
fsd fs2, (2 * 16)(a0)
fsd fs3, (3 * 16)(a0)
fsd fs4, (4 * 16)(a0)
fsd fs5, (5 * 16)(a0)
fsd fs6, (6 * 16)(a0)
fsd fs7, (7 * 16)(a0)
fsd fs8, (8 * 16)(a0)
fsd fs9, (9 * 16)(a0)
fsd fs10, (10 * 16)(a0)
fsd fs11, (11 * 16)(a0)
addi a0, a0, (12 * 16)
#endif
#endif
/* Return value */
@ -117,24 +114,21 @@ ENTRY(_longjmp)
ld ra, (12 * 8)(a0)
addi a0, a0, (13 * 8)
#ifndef _STANDALONE
#if 0
/* RISCVTODO */
/* Restore the vfp registers */
flq fs0, (0 * 16)(a0)
flq fs1, (1 * 16)(a0)
flq fs2, (2 * 16)(a0)
flq fs3, (3 * 16)(a0)
flq fs4, (4 * 16)(a0)
flq fs5, (5 * 16)(a0)
flq fs6, (6 * 16)(a0)
flq fs7, (7 * 16)(a0)
flq fs8, (8 * 16)(a0)
flq fs9, (9 * 16)(a0)
flq fs10, (10 * 16)(a0)
flq fs11, (11 * 16)(a0)
#if !defined(_STANDALONE) && !defined(SOFTFLOAT)
/* Restore the fpe registers */
fld fs0, (0 * 16)(a0)
fld fs1, (1 * 16)(a0)
fld fs2, (2 * 16)(a0)
fld fs3, (3 * 16)(a0)
fld fs4, (4 * 16)(a0)
fld fs5, (5 * 16)(a0)
fld fs6, (6 * 16)(a0)
fld fs7, (7 * 16)(a0)
fld fs8, (8 * 16)(a0)
fld fs9, (9 * 16)(a0)
fld fs10, (10 * 16)(a0)
fld fs11, (11 * 16)(a0)
addi a0, a0, (12 * 16)
#endif
#endif
/* Load the return value */

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
@ -40,23 +40,24 @@ __FBSDID("$FreeBSD$");
#include <fenv.h>
#include <float.h>
#ifdef SOFTFLOAT
#include "softfloat-for-gcc.h"
#include "milieu.h"
#include "softfloat.h"
#endif
int
__flt_rounds(void)
{
#if 0
uint64_t fcsr;
#endif
int mode;
uint64_t mode;
#if 0
__asm __volatile("csrr %0, fcsr" : "=r" (fcsr));
mode = (fcsr & _ROUND_MASK);
#ifdef SOFTFLOAT
mode = __softfloat_float_rounding_mode;
#else
__asm __volatile("csrr %0, fcsr" : "=r" (mode));
#endif
/* RISCVTODO */
mode = FE_TOWARDZERO; /* softfloat rounding mode */
switch (mode) {
switch (mode & _ROUND_MASK) {
case FE_TOWARDZERO:
return (0);
case FE_TONEAREST:

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
@ -75,21 +75,20 @@ ENTRY(setjmp)
sd ra, (12 * 8)(a0)
addi a0, a0, (13 * 8)
#if 0
/* RISCVTODO */
/* Store the vfp registers */
fsq fs0, (0 * 16)(a0)
fsq fs1, (1 * 16)(a0)
fsq fs2, (2 * 16)(a0)
fsq fs3, (3 * 16)(a0)
fsq fs4, (4 * 16)(a0)
fsq fs5, (5 * 16)(a0)
fsq fs6, (6 * 16)(a0)
fsq fs7, (7 * 16)(a0)
fsq fs8, (8 * 16)(a0)
fsq fs9, (9 * 16)(a0)
fsq fs10, (10 * 16)(a0)
fsq fs11, (11 * 16)(a0)
#ifndef SOFTFLOAT
/* Store the fpe registers */
fsd fs0, (0 * 16)(a0)
fsd fs1, (1 * 16)(a0)
fsd fs2, (2 * 16)(a0)
fsd fs3, (3 * 16)(a0)
fsd fs4, (4 * 16)(a0)
fsd fs5, (5 * 16)(a0)
fsd fs6, (6 * 16)(a0)
fsd fs7, (7 * 16)(a0)
fsd fs8, (8 * 16)(a0)
fsd fs9, (9 * 16)(a0)
fsd fs10, (10 * 16)(a0)
fsd fs11, (11 * 16)(a0)
addi a0, a0, (12 * 16)
#endif
@ -145,21 +144,20 @@ ENTRY(longjmp)
ld ra, (12 * 8)(a0)
addi a0, a0, (13 * 8)
#if 0
/* RISCVTODO */
/* Restore the vfp registers */
flq fs0, (0 * 16)(a0)
flq fs1, (1 * 16)(a0)
flq fs2, (2 * 16)(a0)
flq fs3, (3 * 16)(a0)
flq fs4, (4 * 16)(a0)
flq fs5, (5 * 16)(a0)
flq fs6, (6 * 16)(a0)
flq fs7, (7 * 16)(a0)
flq fs8, (8 * 16)(a0)
flq fs9, (9 * 16)(a0)
flq fs10, (10 * 16)(a0)
flq fs11, (11 * 16)(a0)
#ifndef SOFTFLOAT
/* Restore the fpe registers */
fld fs0, (0 * 16)(a0)
fld fs1, (1 * 16)(a0)
fld fs2, (2 * 16)(a0)
fld fs3, (3 * 16)(a0)
fld fs4, (4 * 16)(a0)
fld fs5, (5 * 16)(a0)
fld fs6, (6 * 16)(a0)
fld fs7, (7 * 16)(a0)
fld fs8, (8 * 16)(a0)
fld fs9, (9 * 16)(a0)
fld fs10, (10 * 16)(a0)
fld fs11, (11 * 16)(a0)
addi a0, a0, (12 * 16)
#endif

View File

@ -0,0 +1,48 @@
/* $FreeBSD$ */
/*
===============================================================================
This C header file is part of the SoftFloat IEC/IEEE Floating-point
Arithmetic Package, Release 2a.
Written by John R. Hauser. This work was made possible in part by the
International Computer Science Institute, located at Suite 600, 1947 Center
Street, Berkeley, California 94704. Funding was partially provided by the
National Science Foundation under grant MIP-9311980. The original version
of this code was written as part of a project to build a fixed-point vector
processor in collaboration with the University of California at Berkeley,
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
arithmetic/SoftFloat.html'.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
Derivative works are acceptable, even for commercial purposes, so long as
(1) they include prominent notice that the work is derivative, and (2) they
include prominent notice akin to these four paragraphs for those parts of
this code that are retained.
===============================================================================
*/
/*
-------------------------------------------------------------------------------
Include common integer types and flags.
-------------------------------------------------------------------------------
*/
#include "riscv-gcc.h"
/*
-------------------------------------------------------------------------------
Symbolic Boolean literals.
-------------------------------------------------------------------------------
*/
enum {
FALSE = 0,
TRUE = 1
};

View File

@ -0,0 +1,86 @@
/* $NetBSD: arm-gcc.h,v 1.2 2001/02/21 18:09:25 bjh21 Exp $ */
/* $FreeBSD$ */
/*
-------------------------------------------------------------------------------
One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined.
-------------------------------------------------------------------------------
*/
#define LITTLEENDIAN
/*
-------------------------------------------------------------------------------
The macro `BITS64' can be defined to indicate that 64-bit integer types are
supported by the compiler.
-------------------------------------------------------------------------------
*/
#define BITS64
/*
-------------------------------------------------------------------------------
Each of the following `typedef's defines the most convenient type that holds
integers of at least as many bits as specified. For example, `uint8' should
be the most convenient type that can hold unsigned integers of as many as
8 bits. The `flag' type must be able to hold either a 0 or 1. For most
implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed
to the same as `int'.
-------------------------------------------------------------------------------
*/
typedef int flag;
typedef int uint8;
typedef int int8;
typedef int uint16;
typedef int int16;
typedef unsigned int uint32;
typedef signed int int32;
#ifdef BITS64
typedef unsigned long long int uint64;
typedef signed long long int int64;
#endif
/*
-------------------------------------------------------------------------------
Each of the following `typedef's defines a type that holds integers
of _exactly_ the number of bits specified. For instance, for most
implementation of C, `bits16' and `sbits16' should be `typedef'ed to
`unsigned short int' and `signed short int' (or `short int'), respectively.
-------------------------------------------------------------------------------
*/
typedef unsigned char bits8;
typedef signed char sbits8;
typedef unsigned short int bits16;
typedef signed short int sbits16;
typedef unsigned int bits32;
typedef signed int sbits32;
#ifdef BITS64
typedef unsigned long long int bits64;
typedef signed long long int sbits64;
#endif
#ifdef BITS64
/*
-------------------------------------------------------------------------------
The `LIT64' macro takes as its argument a textual integer literal and
if necessary ``marks'' the literal as having a 64-bit integer type.
For example, the GNU C Compiler (`gcc') requires that 64-bit literals be
appended with the letters `LL' standing for `long long', which is `gcc's
name for the 64-bit integer type. Some compilers may allow `LIT64' to be
defined as the identity macro: `#define LIT64( a ) a'.
-------------------------------------------------------------------------------
*/
#define LIT64( a ) a##LL
#endif
/*
-------------------------------------------------------------------------------
The macro `INLINE' can be used before functions that should be inlined. If
a compiler does not support explicit inlining, this macro should be defined
to be `static'.
-------------------------------------------------------------------------------
*/
#define INLINE static __inline
#if defined(SOFTFLOAT_FOR_GCC)
#define FLOAT64_DEMANGLE(a) (a)
#define FLOAT64_MANGLE(a) (a)
#endif

View File

@ -0,0 +1,315 @@
/* $NetBSD: softfloat.h,v 1.6 2002/05/12 13:12:46 bjh21 Exp $ */
/* $FreeBSD$ */
/* This is a derivative work. */
/*
===============================================================================
This C header file is part of the SoftFloat IEC/IEEE Floating-point
Arithmetic Package, Release 2a.
Written by John R. Hauser. This work was made possible in part by the
International Computer Science Institute, located at Suite 600, 1947 Center
Street, Berkeley, California 94704. Funding was partially provided by the
National Science Foundation under grant MIP-9311980. The original version
of this code was written as part of a project to build a fixed-point vector
processor in collaboration with the University of California at Berkeley,
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
arithmetic/SoftFloat.html'.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
Derivative works are acceptable, even for commercial purposes, so long as
(1) they include prominent notice that the work is derivative, and (2) they
include prominent notice akin to these four paragraphs for those parts of
this code that are retained.
===============================================================================
*/
/*
-------------------------------------------------------------------------------
The macro `FLOATX80' must be defined to enable the extended double-precision
floating-point format `floatx80'. If this macro is not defined, the
`floatx80' type will not be defined, and none of the functions that either
input or output the `floatx80' type will be defined. The same applies to
the `FLOAT128' macro and the quadruple-precision format `float128'.
-------------------------------------------------------------------------------
*/
/* #define FLOATX80 */
/* #define FLOAT128 */
#include <fenv.h>
/*
-------------------------------------------------------------------------------
Software IEC/IEEE floating-point types.
-------------------------------------------------------------------------------
*/
typedef unsigned int float32;
typedef unsigned long long float64;
#ifdef FLOATX80
typedef struct {
unsigned short high;
unsigned long long low;
} floatx80;
#endif
#ifdef FLOAT128
typedef struct {
unsigned long long high, low;
} float128;
#endif
/*
-------------------------------------------------------------------------------
Software IEC/IEEE floating-point underflow tininess-detection mode.
-------------------------------------------------------------------------------
*/
#ifndef SOFTFLOAT_FOR_GCC
extern int float_detect_tininess;
#endif
enum {
float_tininess_after_rounding = 0,
float_tininess_before_rounding = 1
};
/*
-------------------------------------------------------------------------------
Software IEC/IEEE floating-point rounding mode.
-------------------------------------------------------------------------------
*/
extern int float_rounding_mode;
enum {
float_round_nearest_even = FE_TONEAREST,
float_round_to_zero = FE_TOWARDZERO,
float_round_down = FE_DOWNWARD,
float_round_up = FE_UPWARD
};
/*
-------------------------------------------------------------------------------
Software IEC/IEEE floating-point exception flags.
-------------------------------------------------------------------------------
*/
extern int float_exception_flags;
extern int float_exception_mask;
enum {
float_flag_inexact = FE_INEXACT,
float_flag_underflow = FE_UNDERFLOW,
float_flag_overflow = FE_OVERFLOW,
float_flag_divbyzero = FE_DIVBYZERO,
float_flag_invalid = FE_INVALID
};
/*
-------------------------------------------------------------------------------
Routine to raise any or all of the software IEC/IEEE floating-point
exception flags.
-------------------------------------------------------------------------------
*/
void float_raise( int );
/*
-------------------------------------------------------------------------------
Software IEC/IEEE integer-to-floating-point conversion routines.
-------------------------------------------------------------------------------
*/
float32 int32_to_float32( int );
float64 int32_to_float64( int );
#ifdef FLOATX80
floatx80 int32_to_floatx80( int );
#endif
#ifdef FLOAT128
float128 int32_to_float128( int );
#endif
#ifndef SOFTFLOAT_FOR_GCC /* __floatdi?f is in libgcc2.c */
float32 int64_to_float32( long long );
float64 int64_to_float64( long long );
#ifdef FLOATX80
floatx80 int64_to_floatx80( long long );
#endif
#ifdef FLOAT128
float128 int64_to_float128( long long );
#endif
#endif
/*
-------------------------------------------------------------------------------
Software IEC/IEEE single-precision conversion routines.
-------------------------------------------------------------------------------
*/
int float32_to_int32( float32 );
int float32_to_int32_round_to_zero( float32 );
#if defined(SOFTFLOAT_FOR_GCC) && defined(SOFTFLOAT_NEED_FIXUNS)
unsigned int float32_to_uint32_round_to_zero( float32 );
#endif
#ifndef SOFTFLOAT_FOR_GCC /* __fix?fdi provided by libgcc2.c */
long long float32_to_int64( float32 );
long long float32_to_int64_round_to_zero( float32 );
#endif
float64 float32_to_float64( float32 );
#ifdef FLOATX80
floatx80 float32_to_floatx80( float32 );
#endif
#ifdef FLOAT128
float128 float32_to_float128( float32 );
#endif
/*
-------------------------------------------------------------------------------
Software IEC/IEEE single-precision operations.
-------------------------------------------------------------------------------
*/
float32 float32_round_to_int( float32 );
float32 float32_add( float32, float32 );
float32 float32_sub( float32, float32 );
float32 float32_mul( float32, float32 );
float32 float32_div( float32, float32 );
float32 float32_rem( float32, float32 );
float32 float32_sqrt( float32 );
int float32_eq( float32, float32 );
int float32_le( float32, float32 );
int float32_lt( float32, float32 );
int float32_eq_signaling( float32, float32 );
int float32_le_quiet( float32, float32 );
int float32_lt_quiet( float32, float32 );
#ifndef SOFTFLOAT_FOR_GCC
int float32_is_signaling_nan( float32 );
#endif
/*
-------------------------------------------------------------------------------
Software IEC/IEEE double-precision conversion routines.
-------------------------------------------------------------------------------
*/
int float64_to_int32( float64 );
int float64_to_int32_round_to_zero( float64 );
#if defined(SOFTFLOAT_FOR_GCC) && defined(SOFTFLOAT_NEED_FIXUNS)
unsigned int float64_to_uint32_round_to_zero( float64 );
#endif
#ifndef SOFTFLOAT_FOR_GCC /* __fix?fdi provided by libgcc2.c */
long long float64_to_int64( float64 );
long long float64_to_int64_round_to_zero( float64 );
#endif
float32 float64_to_float32( float64 );
#ifdef FLOATX80
floatx80 float64_to_floatx80( float64 );
#endif
#ifdef FLOAT128
float128 float64_to_float128( float64 );
#endif
/*
-------------------------------------------------------------------------------
Software IEC/IEEE double-precision operations.
-------------------------------------------------------------------------------
*/
float64 float64_round_to_int( float64 );
float64 float64_add( float64, float64 );
float64 float64_sub( float64, float64 );
float64 float64_mul( float64, float64 );
float64 float64_div( float64, float64 );
float64 float64_rem( float64, float64 );
float64 float64_sqrt( float64 );
int float64_eq( float64, float64 );
int float64_le( float64, float64 );
int float64_lt( float64, float64 );
int float64_eq_signaling( float64, float64 );
int float64_le_quiet( float64, float64 );
int float64_lt_quiet( float64, float64 );
#ifndef SOFTFLOAT_FOR_GCC
int float64_is_signaling_nan( float64 );
#endif
#ifdef FLOATX80
/*
-------------------------------------------------------------------------------
Software IEC/IEEE extended double-precision conversion routines.
-------------------------------------------------------------------------------
*/
int floatx80_to_int32( floatx80 );
int floatx80_to_int32_round_to_zero( floatx80 );
long long floatx80_to_int64( floatx80 );
long long floatx80_to_int64_round_to_zero( floatx80 );
float32 floatx80_to_float32( floatx80 );
float64 floatx80_to_float64( floatx80 );
#ifdef FLOAT128
float128 floatx80_to_float128( floatx80 );
#endif
/*
-------------------------------------------------------------------------------
Software IEC/IEEE extended double-precision rounding precision. Valid
values are 32, 64, and 80.
-------------------------------------------------------------------------------
*/
extern int floatx80_rounding_precision;
/*
-------------------------------------------------------------------------------
Software IEC/IEEE extended double-precision operations.
-------------------------------------------------------------------------------
*/
floatx80 floatx80_round_to_int( floatx80 );
floatx80 floatx80_add( floatx80, floatx80 );
floatx80 floatx80_sub( floatx80, floatx80 );
floatx80 floatx80_mul( floatx80, floatx80 );
floatx80 floatx80_div( floatx80, floatx80 );
floatx80 floatx80_rem( floatx80, floatx80 );
floatx80 floatx80_sqrt( floatx80 );
int floatx80_eq( floatx80, floatx80 );
int floatx80_le( floatx80, floatx80 );
int floatx80_lt( floatx80, floatx80 );
int floatx80_eq_signaling( floatx80, floatx80 );
int floatx80_le_quiet( floatx80, floatx80 );
int floatx80_lt_quiet( floatx80, floatx80 );
int floatx80_is_signaling_nan( floatx80 );
#endif
#ifdef FLOAT128
/*
-------------------------------------------------------------------------------
Software IEC/IEEE quadruple-precision conversion routines.
-------------------------------------------------------------------------------
*/
int float128_to_int32( float128 );
int float128_to_int32_round_to_zero( float128 );
long long float128_to_int64( float128 );
long long float128_to_int64_round_to_zero( float128 );
float32 float128_to_float32( float128 );
float64 float128_to_float64( float128 );
#ifdef FLOATX80
floatx80 float128_to_floatx80( float128 );
#endif
/*
-------------------------------------------------------------------------------
Software IEC/IEEE quadruple-precision operations.
-------------------------------------------------------------------------------
*/
float128 float128_round_to_int( float128 );
float128 float128_add( float128, float128 );
float128 float128_sub( float128, float128 );
float128 float128_mul( float128, float128 );
float128 float128_div( float128, float128 );
float128 float128_rem( float128, float128 );
float128 float128_sqrt( float128 );
int float128_eq( float128, float128 );
int float128_le( float128, float128 );
int float128_lt( float128, float128 );
int float128_eq_signaling( float128, float128 );
int float128_le_quiet( float128, float128 );
int float128_lt_quiet( float128, float128 );
int float128_is_signaling_nan( float128 );
#endif

View File

@ -12,8 +12,11 @@ CFLAGS+= -DSOFTFLOAT_FOR_GCC
SRCS+= softfloat.c
# Deprecated FPU control interface
.if ${LIBC_ARCH} != "riscv"
SRCS+= fpgetround.c fpsetround.c fpgetmask.c fpsetmask.c \
fpgetsticky.c
.endif
SRCS+= eqsf2.c nesf2.c gtsf2.c gesf2.c ltsf2.c lesf2.c negsf2.c \
eqdf2.c nedf2.c gtdf2.c gedf2.c ltdf2.c ledf2.c negdf2.c \

View File

@ -125,7 +125,7 @@ SRCF+= umodti3
#
# 128-bit quad precision long double support,
# only used on arm64 and riscv.
# only used on some architectures.
#
.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "riscv"
SRCF+= addtf3
@ -146,8 +146,9 @@ SRCF+= trunctfdf2
SRCF+= trunctfsf2
.endif
# These are already shipped by libc.a on arm and mips
.if ${MACHINE_CPUARCH} != "arm" && ${MACHINE_CPUARCH} != "mips"
# These are already shipped by libc.a on some architectures.
.if ${MACHINE_CPUARCH} != "arm" && ${MACHINE_CPUARCH} != "mips" && \
${MACHINE_CPUARCH} != "riscv"
SRCF+= adddf3
SRCF+= addsf3
SRCF+= divdf3

View File

@ -1,3 +1,8 @@
# $FreeBSD$
.if ${MACHINE_ARCH:Mriscv*sf} != ""
CFLAGS+=-DSOFTFLOAT
.endif
LDBL_PREC = 113
SYM_MAPS += ${.CURDIR}/riscv/Symbol.map

21
lib/msun/riscv/Symbol.map Normal file
View File

@ -0,0 +1,21 @@
/*
* $FreeBSD$
*/
FBSD_1.0 {
};
FBSD_1.3 {
feclearexcept;
fegetexceptflag;
fesetexceptflag;
feraiseexcept;
fetestexcept;
fegetround;
fesetround;
fegetenv;
feholdexcept;
feupdateenv;
feenableexcept;
fedisableexcept;
fegetexcept;
};

View File

@ -39,6 +39,14 @@
*/
const fenv_t __fe_dfl_env = 0;
#ifdef SOFTFLOAT
#define __set_env(env, flags, mask, rnd) env = ((flags) | (rnd) << 5)
#define __env_flags(env) ((env) & FE_ALL_EXCEPT)
#define __env_mask(env) (0) /* No exception traps. */
#define __env_round(env) (((env) >> 5) & _ROUND_MASK)
#include "fenv-softfloat.h"
#endif
extern inline int feclearexcept(int __excepts);
extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts);
extern inline int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
@ -50,3 +58,6 @@ extern inline int fegetenv(fenv_t *__envp);
extern inline int feholdexcept(fenv_t *__envp);
extern inline int fesetenv(const fenv_t *__envp);
extern inline int feupdateenv(const fenv_t *__envp);
extern inline int feenableexcept(int __mask);
extern inline int fedisableexcept(int __mask);
extern inline int fegetexcept(void);

View File

@ -1,6 +1,6 @@
/*-
* Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
@ -59,11 +59,11 @@ typedef __uint64_t fexcept_t;
/*
* RISC-V Rounding modes
*/
#define FE_TONEAREST (0x00 << 5)
#define FE_TOWARDZERO (0x01 << 5)
#define FE_DOWNWARD (0x02 << 5)
#define FE_UPWARD (0x03 << 5)
#define _ROUND_SHIFT 5
#define FE_TONEAREST (0x00 << _ROUND_SHIFT)
#define FE_TOWARDZERO (0x01 << _ROUND_SHIFT)
#define FE_DOWNWARD (0x02 << _ROUND_SHIFT)
#define FE_UPWARD (0x03 << _ROUND_SHIFT)
#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
FE_UPWARD | FE_TOWARDZERO)
@ -73,96 +73,117 @@ __BEGIN_DECLS
extern const fenv_t __fe_dfl_env;
#define FE_DFL_ENV (&__fe_dfl_env)
/* We need to be able to map status flag positions to mask flag positions */
#define _FPUSW_SHIFT 0
#define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT)
#define __rfs(__fpsr) __asm __volatile("csrr %0, fcsr" : "=r" (*(__fpsr)))
#define __wfs(__fpsr) __asm __volatile("csrw fcsr, %0" :: "r" (__fpsr))
#ifndef SOFTFLOAT
#define __rfs(__fcsr) __asm __volatile("csrr %0, fcsr" : "=r" (__fcsr))
#define __wfs(__fcsr) __asm __volatile("csrw fcsr, %0" :: "r" (__fcsr))
#endif
#ifdef SOFTFLOAT
int feclearexcept(int __excepts);
int fegetexceptflag(fexcept_t *__flagp, int __excepts);
int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
int feraiseexcept(int __excepts);
int fetestexcept(int __excepts);
int fegetround(void);
int fesetround(int __round);
int fegetenv(fenv_t *__envp);
int feholdexcept(fenv_t *__envp);
int fesetenv(const fenv_t *__envp);
int feupdateenv(const fenv_t *__envp);
#else
__fenv_static inline int
feclearexcept(int __excepts)
{
fexcept_t __fpsr;
__rfs(&__fpsr);
__fpsr &= ~__excepts;
__wfs(__fpsr);
__asm __volatile("csrc fflags, %0" :: "r"(__excepts));
return (0);
}
__fenv_static inline int
fegetexceptflag(fexcept_t *__flagp, int __excepts)
{
fexcept_t __fpsr;
fexcept_t __fcsr;
__rfs(__fcsr);
*__flagp = __fcsr & __excepts;
__rfs(&__fpsr);
*__flagp = __fpsr & __excepts;
return (0);
}
__fenv_static inline int
fesetexceptflag(const fexcept_t *__flagp, int __excepts)
{
fexcept_t __fpsr;
fexcept_t __fcsr;
__fcsr = *__flagp;
__asm __volatile("csrc fflags, %0" :: "r"(__excepts));
__asm __volatile("csrs fflags, %0" :: "r"(__fcsr & __excepts));
__rfs(&__fpsr);
__fpsr &= ~__excepts;
__fpsr |= *__flagp & __excepts;
__wfs(__fpsr);
return (0);
}
__fenv_static inline int
feraiseexcept(int __excepts)
{
fexcept_t __ex = __excepts;
fesetexceptflag(&__ex, __excepts); /* XXX */
__asm __volatile("csrs fflags, %0" :: "r"(__excepts));
return (0);
}
__fenv_static inline int
fetestexcept(int __excepts)
{
fexcept_t __fpsr;
fexcept_t __fcsr;
__rfs(&__fpsr);
return (__fpsr & __excepts);
__rfs(__fcsr);
return (__fcsr & __excepts);
}
__fenv_static inline int
fegetround(void)
{
fexcept_t __fcsr;
return (-1);
__rfs(__fcsr);
return (__fcsr & _ROUND_MASK);
}
__fenv_static inline int
fesetround(int __round)
{
fexcept_t __fcsr;
return (-1);
if (__round & ~_ROUND_MASK)
return (-1);
__rfs(__fcsr);
__fcsr &= ~_ROUND_MASK;
__fcsr |= __round;
__wfs(__fcsr);
return (0);
}
__fenv_static inline int
fegetenv(fenv_t *__envp)
{
__rfs(__envp);
__rfs(*__envp);
return (0);
}
__fenv_static inline int
feholdexcept(fenv_t *__envp)
{
fenv_t __env;
__rfs(&__env);
*__envp = __env;
__env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
__wfs(__env);
return (0);
/* No exception traps. */
return (-1);
}
__fenv_static inline int
@ -170,56 +191,59 @@ fesetenv(const fenv_t *__envp)
{
__wfs(*__envp);
return (0);
}
__fenv_static inline int
feupdateenv(const fenv_t *__envp)
{
fexcept_t __fpsr;
fexcept_t __fcsr;
__rfs(&__fpsr);
__rfs(__fcsr);
__wfs(*__envp);
feraiseexcept(__fpsr & FE_ALL_EXCEPT);
feraiseexcept(__fcsr & FE_ALL_EXCEPT);
return (0);
}
#endif /* !SOFTFLOAT */
#if __BSD_VISIBLE
/* We currently provide no external definitions of the functions below. */
#ifdef SOFTFLOAT
int feenableexcept(int __mask);
int fedisableexcept(int __mask);
int fegetexcept(void);
#else
static inline int
feenableexcept(int __mask)
{
fenv_t __old_fpsr;
fenv_t __new_fpsr;
__rfs(&__old_fpsr);
__new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT;
__wfs(__new_fpsr);
return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
/* No exception traps. */
return (-1);
}
static inline int
fedisableexcept(int __mask)
{
fenv_t __old_fpsr;
fenv_t __new_fpsr;
__rfs(&__old_fpsr);
__new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT);
__wfs(__new_fpsr);
return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
/* No exception traps. */
return (0);
}
static inline int
fegetexcept(void)
{
fenv_t __fpsr;
__rfs(&__fpsr);
return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT);
/* No exception traps. */
return (0);
}
#endif /* !SOFTFLOAT */
#endif /* __BSD_VISIBLE */

View File

@ -155,8 +155,6 @@ _CPUCFLAGS = -march=${CPUTYPE}
# sb1, xlp, xlr
_CPUCFLAGS = -march=${CPUTYPE:S/^mips//}
. endif
. elif ${MACHINE_CPUARCH} == "riscv"
_CPUCFLAGS = -mno-float -march="IMAFD"
. elif ${MACHINE_ARCH} == "sparc64"
. if ${CPUTYPE} == "v9"
_CPUCFLAGS = -mcpu=v9
@ -350,9 +348,11 @@ CFLAGS += -mcpu=8540 -Wa,-me500 -mspe=yes -mabi=spe -mfloat-gprs=double
.endif
.if ${MACHINE_CPUARCH} == "riscv"
.if ${TARGET_ARCH:Mriscv*sf}
CFLAGS += -mno-float
ACFLAGS += -mno-float
.endif
.endif
# NB: COPTFLAGS is handled in /usr/src/sys/conf/kern.pre.mk

View File

@ -48,7 +48,7 @@ TARGET_ARCHES_arm64?= aarch64
TARGET_ARCHES_mips?= mipsel mips mips64el mips64 mipsn32 mipsn32el
TARGET_ARCHES_powerpc?= powerpc powerpc64 powerpcspe
TARGET_ARCHES_pc98?= i386
TARGET_ARCHES_riscv?= riscv64
TARGET_ARCHES_riscv?= riscv64 riscv64sf
# some corner cases
BOOT_MACHINE_DIR.amd64 = boot/i386

View File

@ -236,16 +236,16 @@ __DEFAULT_YES_OPTIONS+=GCC GCC_BOOTSTRAP GNUCXX
__DEFAULT_NO_OPTIONS+=CLANG CLANG_BOOTSTRAP CLANG_FULL CLANG_IS_CC
.endif
# In-tree binutils/gcc are older versions without modern architecture support.
.if ${__T} == "aarch64" || ${__T} == "riscv64"
.if ${__T} == "aarch64" || ${__T:Mriscv*} != ""
BROKEN_OPTIONS+=BINUTILS BINUTILS_BOOTSTRAP GCC GCC_BOOTSTRAP GDB
.endif
.if ${__T} == "riscv64"
.if ${__T:Mriscv*} != ""
BROKEN_OPTIONS+=PROFILE # "sorry, unimplemented: profiler support for RISC-V"
BROKEN_OPTIONS+=TESTS # "undefined reference to `_Unwind_Resume'"
BROKEN_OPTIONS+=CXX # "libcxxrt.so: undefined reference to `_Unwind_Resume_or_Rethrow'"
.endif
.if ${__T} == "aarch64" || ${__T} == "amd64" || ${__T} == "i386" || \
${__T} == "riscv64"
${__T:Mriscv*} != ""
__DEFAULT_YES_OPTIONS+=LLVM_LIBUNWIND
.else
__DEFAULT_NO_OPTIONS+=LLVM_LIBUNWIND

View File

@ -13,7 +13,7 @@ unix ?= We run FreeBSD, not UNIX.
# and/or endian. This is called MACHINE_CPU in NetBSD, but that's used
# for something different in FreeBSD.
#
MACHINE_CPUARCH=${MACHINE_ARCH:C/mips(n32|64)?(el)?(hf)?/mips/:C/arm(v6)?(eb|hf)?/arm/:C/powerpc(64|spe)/powerpc/:C/riscv64/riscv/}
MACHINE_CPUARCH=${MACHINE_ARCH:C/mips(n32|64)?(el)?(hf)?/mips/:C/arm(v6)?(eb|hf)?/arm/:C/powerpc(64|spe)/powerpc/:C/riscv64(sf)?/riscv/}
.endif

View File

@ -1,4 +1,4 @@
# $FreeBSD$
RISCV opt_global.h
VFP opt_global.h
FPE opt_global.h

View File

@ -60,7 +60,11 @@ assym.o: assym.s
.if ${MACHINE_CPUARCH} == "riscv"
assym.o: assym.s
.if ${TARGET_ARCH:Mriscv*sf}
${AS} -mfloat-abi=soft -o assym.o assym.s
.else
${AS} -mfloat-abi=double -o assym.o assym.s
.endif
.endif
.include <bsd.kmod.mk>

View File

@ -69,7 +69,7 @@ options CAPABILITIES # Capsicum capabilities
options MAC # TrustedBSD MAC Framework
options KDTRACE_FRAME # Ensure frames are compiled in
options KDTRACE_HOOKS # Kernel DTrace hooks
# options VFP # Floating-point support
options FPE # Floating-point extension support
options RACCT # Resource accounting framework
options RACCT_DEFAULT_TO_DISABLED # Set kern.racct.enable=0 by default
options RCTL # Resource limits

38
sys/riscv/include/fpe.h Normal file
View File

@ -0,0 +1,38 @@
/*-
* Copyright (c) 2016 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by SRI International and the University of
* Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
* ("CTSRD"), as part of the DARPA CRASH research programme.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
#ifndef _MACHINE_FPE_H_
#define _MACHINE_FPE_H_
void fpe_state_save(struct thread *td);
#endif /* !_MACHINE_FPE_H_ */

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
@ -42,16 +42,21 @@
struct trapframe;
struct pcb {
uint64_t pcb_ra;
uint64_t pcb_sp;
uint64_t pcb_gp;
uint64_t pcb_tp;
uint64_t pcb_t[7];
uint64_t pcb_s[12];
uint64_t pcb_a[8];
uint64_t pcb_sepc;
uint64_t pcb_ra; /* Return address */
uint64_t pcb_sp; /* Stack pointer */
uint64_t pcb_gp; /* Global pointer */
uint64_t pcb_tp; /* Thread pointer */
uint64_t pcb_t[7]; /* Temporary registers */
uint64_t pcb_s[12]; /* Saved registers */
uint64_t pcb_a[8]; /* Argument registers */
uint64_t pcb_x[32][2]; /* Floating point registers */
uint64_t pcb_fcsr; /* Floating point control reg */
uint64_t pcb_fpflags; /* Floating point flags */
#define PCB_FP_STARTED 0x1
#define PCB_FP_USERMASK 0x1
uint64_t pcb_sepc; /* Supervisor exception pc */
vm_offset_t pcb_l1addr; /* L1 page tables base address */
vm_offset_t pcb_onfault;
vm_offset_t pcb_onfault; /* Copyinout fault handler */
};
#ifdef _KERNEL

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
@ -50,7 +50,8 @@ struct reg {
};
struct fpreg {
int dummy;
uint64_t fp_x[32][2]; /* Floating point registers */
uint64_t fp_fcsr; /* Floating point control reg */
};
struct dbreg {

View File

@ -60,10 +60,14 @@
#define SSTATUS_SPIE_SHIFT 5
#define SSTATUS_SPP (1 << 8)
#define SSTATUS_SPP_SHIFT 8
#define SSTATUS_FS_MASK 0x3
#define SSTATUS_FS_SHIFT 13
#define SSTATUS_XS_MASK 0x3
#define SSTATUS_FS_OFF (0x0 << SSTATUS_FS_SHIFT)
#define SSTATUS_FS_INITIAL (0x1 << SSTATUS_FS_SHIFT)
#define SSTATUS_FS_CLEAN (0x2 << SSTATUS_FS_SHIFT)
#define SSTATUS_FS_DIRTY (0x3 << SSTATUS_FS_SHIFT)
#define SSTATUS_FS_MASK (0x3 << SSTATUS_FS_SHIFT)
#define SSTATUS_XS_SHIFT 15
#define SSTATUS_XS_MASK (0x3 << SSTATUS_XS_SHIFT)
#define SSTATUS_PUM (1 << 18)
#define SSTATUS32_SD (1 << 63)
#define SSTATUS64_SD (1 << 31)

View File

@ -72,6 +72,8 @@ ASSYM(PCB_TP, offsetof(struct pcb, pcb_tp));
ASSYM(PCB_T, offsetof(struct pcb, pcb_t));
ASSYM(PCB_S, offsetof(struct pcb, pcb_s));
ASSYM(PCB_A, offsetof(struct pcb, pcb_a));
ASSYM(PCB_X, offsetof(struct pcb, pcb_x));
ASSYM(PCB_FCSR, offsetof(struct pcb, pcb_fcsr));
ASSYM(SF_UC, offsetof(struct sigframe, sf_uc));

View File

@ -84,8 +84,8 @@ __FBSDID("$FreeBSD$");
#include <machine/asm.h>
#ifdef VFP
#include <machine/vfp.h>
#ifdef FPE
#include <machine/fpe.h>
#endif
#ifdef FDT
@ -203,17 +203,39 @@ set_regs(struct thread *td, struct reg *regs)
int
fill_fpregs(struct thread *td, struct fpreg *regs)
{
#ifdef FPE
struct pcb *pcb;
pcb = td->td_pcb;
if ((pcb->pcb_fpflags & PCB_FP_STARTED) != 0) {
/*
* If we have just been running FPE instructions we will
* need to save the state to memcpy it below.
*/
fpe_state_save(td);
memcpy(regs->fp_x, pcb->pcb_x, sizeof(regs->fp_x));
regs->fp_fcsr = pcb->pcb_fcsr;
} else
#endif
memset(regs->fp_x, 0, sizeof(regs->fp_x));
/* TODO */
bzero(regs, sizeof(*regs));
return (0);
}
int
set_fpregs(struct thread *td, struct fpreg *regs)
{
#ifdef FPE
struct pcb *pcb;
pcb = td->td_pcb;
memcpy(pcb->pcb_x, regs->fp_x, sizeof(regs->fp_x));
pcb->pcb_fcsr = regs->fp_fcsr;
#endif
/* TODO */
return (0);
}
@ -259,8 +281,10 @@ void
exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
{
struct trapframe *tf;
struct pcb *pcb;
tf = td->td_frame;
pcb = td->td_pcb;
memset(tf, 0, sizeof(struct trapframe));
@ -273,6 +297,8 @@ exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
tf->tf_sp = STACKALIGN(stack);
tf->tf_ra = imgp->entry_addr;
tf->tf_sepc = imgp->entry_addr;
pcb->pcb_fpflags &= ~PCB_FP_STARTED;
}
/* Sanity check these are the same size, they will be memcpy'd to and fro */
@ -337,13 +363,54 @@ set_mcontext(struct thread *td, mcontext_t *mcp)
static void
get_fpcontext(struct thread *td, mcontext_t *mcp)
{
/* TODO */
#ifdef FPE
struct pcb *curpcb;
critical_enter();
curpcb = curthread->td_pcb;
KASSERT(td->td_pcb == curpcb, ("Invalid fpe pcb"));
if ((curpcb->pcb_fpflags & PCB_FP_STARTED) != 0) {
/*
* If we have just been running FPE instructions we will
* need to save the state to memcpy it below.
*/
fpe_state_save(td);
KASSERT((curpcb->pcb_fpflags & ~PCB_FP_USERMASK) == 0,
("Non-userspace FPE flags set in get_fpcontext"));
memcpy(mcp->mc_fpregs.fp_x, curpcb->pcb_x,
sizeof(mcp->mc_fpregs));
mcp->mc_fpregs.fp_fcsr = curpcb->pcb_fcsr;
mcp->mc_fpregs.fp_flags = curpcb->pcb_fpflags;
mcp->mc_flags |= _MC_FP_VALID;
}
critical_exit();
#endif
}
static void
set_fpcontext(struct thread *td, mcontext_t *mcp)
{
/* TODO */
#ifdef FPE
struct pcb *curpcb;
critical_enter();
if ((mcp->mc_flags & _MC_FP_VALID) != 0) {
curpcb = curthread->td_pcb;
/* FPE usage is enabled, override registers. */
memcpy(curpcb->pcb_x, mcp->mc_fpregs.fp_x,
sizeof(mcp->mc_fpregs));
curpcb->pcb_fcsr = mcp->mc_fpregs.fp_fcsr;
curpcb->pcb_fpflags = mcp->mc_fpregs.fp_flags & PCB_FP_USERMASK;
}
critical_exit();
#endif
}
void
@ -572,6 +639,7 @@ init_proc0(vm_offset_t kstack)
proc_linkup0(&proc0, &thread0);
thread0.td_kstack = kstack;
thread0.td_pcb = (struct pcb *)(thread0.td_kstack) - 1;
thread0.td_pcb->pcb_fpflags = 0;
thread0.td_frame = &proc0_tf;
pcpup->pc_curpcb = thread0.td_pcb;
}

View File

@ -62,9 +62,6 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
#include <machine/smp.h>
#include <machine/sbi.h>
#ifdef VFP
#include <machine/vfp.h>
#endif
#ifdef FDT
#include <dev/ofw/openfirm.h>
@ -242,10 +239,6 @@ init_secondary(uint64_t cpu)
/* Start per-CPU event timers. */
cpu_initclocks_ap();
#ifdef VFP
/* TODO: init FPU */
#endif
/* Enable interrupts */
intr_enable();

View File

@ -42,6 +42,117 @@
__FBSDID("$FreeBSD$");
#ifdef FPE
.macro __fpe_state_save p
/*
* Enable FPE usage in supervisor mode,
* so we can access registers.
*/
li t0, SSTATUS_FS_INITIAL
csrs sstatus, t0
/* Store registers */
frcsr t0
sd t0, (PCB_FCSR)(\p)
fsd f0, (PCB_X + 0 * 16)(\p)
fsd f1, (PCB_X + 1 * 16)(\p)
fsd f2, (PCB_X + 2 * 16)(\p)
fsd f3, (PCB_X + 3 * 16)(\p)
fsd f4, (PCB_X + 4 * 16)(\p)
fsd f5, (PCB_X + 5 * 16)(\p)
fsd f6, (PCB_X + 6 * 16)(\p)
fsd f7, (PCB_X + 7 * 16)(\p)
fsd f8, (PCB_X + 8 * 16)(\p)
fsd f9, (PCB_X + 9 * 16)(\p)
fsd f10, (PCB_X + 10 * 16)(\p)
fsd f11, (PCB_X + 11 * 16)(\p)
fsd f12, (PCB_X + 12 * 16)(\p)
fsd f13, (PCB_X + 13 * 16)(\p)
fsd f14, (PCB_X + 14 * 16)(\p)
fsd f15, (PCB_X + 15 * 16)(\p)
fsd f16, (PCB_X + 16 * 16)(\p)
fsd f17, (PCB_X + 17 * 16)(\p)
fsd f18, (PCB_X + 18 * 16)(\p)
fsd f19, (PCB_X + 19 * 16)(\p)
fsd f20, (PCB_X + 20 * 16)(\p)
fsd f21, (PCB_X + 21 * 16)(\p)
fsd f22, (PCB_X + 22 * 16)(\p)
fsd f23, (PCB_X + 23 * 16)(\p)
fsd f24, (PCB_X + 24 * 16)(\p)
fsd f25, (PCB_X + 25 * 16)(\p)
fsd f26, (PCB_X + 26 * 16)(\p)
fsd f27, (PCB_X + 27 * 16)(\p)
fsd f28, (PCB_X + 28 * 16)(\p)
fsd f29, (PCB_X + 29 * 16)(\p)
fsd f30, (PCB_X + 30 * 16)(\p)
fsd f31, (PCB_X + 31 * 16)(\p)
/* Disable FPE usage in supervisor mode. */
li t0, SSTATUS_FS_MASK
csrc sstatus, t0
.endm
.macro __fpe_state_load p
/*
* Enable FPE usage in supervisor mode,
* so we can access registers.
*/
li t0, SSTATUS_FS_INITIAL
csrs sstatus, t0
/* Restore registers */
ld t0, (PCB_FCSR)(\p)
fscsr t0
fld f0, (PCB_X + 0 * 16)(\p)
fld f1, (PCB_X + 1 * 16)(\p)
fld f2, (PCB_X + 2 * 16)(\p)
fld f3, (PCB_X + 3 * 16)(\p)
fld f4, (PCB_X + 4 * 16)(\p)
fld f5, (PCB_X + 5 * 16)(\p)
fld f6, (PCB_X + 6 * 16)(\p)
fld f7, (PCB_X + 7 * 16)(\p)
fld f8, (PCB_X + 8 * 16)(\p)
fld f9, (PCB_X + 9 * 16)(\p)
fld f10, (PCB_X + 10 * 16)(\p)
fld f11, (PCB_X + 11 * 16)(\p)
fld f12, (PCB_X + 12 * 16)(\p)
fld f13, (PCB_X + 13 * 16)(\p)
fld f14, (PCB_X + 14 * 16)(\p)
fld f15, (PCB_X + 15 * 16)(\p)
fld f16, (PCB_X + 16 * 16)(\p)
fld f17, (PCB_X + 17 * 16)(\p)
fld f18, (PCB_X + 18 * 16)(\p)
fld f19, (PCB_X + 19 * 16)(\p)
fld f20, (PCB_X + 20 * 16)(\p)
fld f21, (PCB_X + 21 * 16)(\p)
fld f22, (PCB_X + 22 * 16)(\p)
fld f23, (PCB_X + 23 * 16)(\p)
fld f24, (PCB_X + 24 * 16)(\p)
fld f25, (PCB_X + 25 * 16)(\p)
fld f26, (PCB_X + 26 * 16)(\p)
fld f27, (PCB_X + 27 * 16)(\p)
fld f28, (PCB_X + 28 * 16)(\p)
fld f29, (PCB_X + 29 * 16)(\p)
fld f30, (PCB_X + 30 * 16)(\p)
fld f31, (PCB_X + 31 * 16)(\p)
/* Disable FPE usage in supervisor mode. */
li t0, SSTATUS_FS_MASK
csrc sstatus, t0
.endm
/*
* void
* fpe_state_save(struct thread *td)
*/
ENTRY(fpe_state_save)
/* Get pointer to PCB */
ld a0, TD_PCB(a0)
__fpe_state_save a0
ret
END(fpe_state_save)
#endif /* FPE */
/*
* void cpu_throw(struct thread *old, struct thread *new)
*/
@ -81,8 +192,20 @@ ENTRY(cpu_throw)
ld s10, (PCB_S + 10 * 8)(x13)
ld s11, (PCB_S + 11 * 8)(x13)
ret
#ifdef FPE
/* Is FPE enabled for new thread? */
ld t0, TD_FRAME(a1)
ld t1, (TF_SSTATUS)(t0)
li t2, SSTATUS_FS_MASK
and t3, t1, t2
beqz t3, 1f /* No, skip. */
/* Restore registers. */
__fpe_state_load x13
1:
#endif
ret
.Lcpu_throw_panic_str:
.asciz "cpu_throw: %p\0"
END(cpu_throw)
@ -123,6 +246,29 @@ ENTRY(cpu_switch)
sd s10, (PCB_S + 10 * 8)(x13)
sd s11, (PCB_S + 11 * 8)(x13)
#ifdef FPE
/*
* Is FPE enabled and is it in dirty state
* for the old thread?
*/
ld t0, TD_FRAME(a0)
ld t1, (TF_SSTATUS)(t0)
li t2, SSTATUS_FS_MASK
and t3, t1, t2
li t2, SSTATUS_FS_DIRTY
bne t3, t2, 1f /* No, skip. */
/* Yes, mark FPE state clean and save registers. */
li t2, ~SSTATUS_FS_MASK
and t3, t1, t2
li t2, SSTATUS_FS_CLEAN
or t3, t3, t2
sd t3, (TF_SSTATUS)(t0)
__fpe_state_save x13
1:
#endif
/*
* Restore the saved context.
*/
@ -171,6 +317,20 @@ ENTRY(cpu_switch)
ld s9, (PCB_S + 9 * 8)(x13)
ld s10, (PCB_S + 10 * 8)(x13)
ld s11, (PCB_S + 11 * 8)(x13)
#ifdef FPE
/* Is FPE enabled for new thread? */
ld t0, TD_FRAME(a1)
ld t1, (TF_SSTATUS)(t0)
li t2, SSTATUS_FS_MASK
and t3, t1, t2
beqz t3, 1f /* No, skip. */
/* Restore registers. */
__fpe_state_load x13
1:
#endif
ret
.Lcpu_switch_panic_str:
.asciz "cpu_switch: %p\0"
@ -269,9 +429,8 @@ ENTRY(savectx)
sd s10, (PCB_S + 10 * 8)(a0)
sd s11, (PCB_S + 11 * 8)(a0)
/* Store the VFP registers */
#ifdef VFP
/* TODO */
#ifdef FPE
__fpe_state_save a0
#endif
ret
END(savectx)

View File

@ -328,9 +328,11 @@ do_trap_user(struct trapframe *frame)
uint64_t exception;
struct thread *td;
uint64_t sstatus;
struct pcb *pcb;
td = curthread;
td->td_frame = frame;
pcb = td->td_pcb;
/* Ensure we came from usermode, interrupts disabled */
__asm __volatile("csrr %0, sstatus" : "=&r" (sstatus));
@ -358,6 +360,17 @@ do_trap_user(struct trapframe *frame)
svc_handler(frame);
break;
case EXCP_ILLEGAL_INSTRUCTION:
#ifdef FPE
if ((pcb->pcb_fpflags & PCB_FP_STARTED) == 0) {
/*
* May be a FPE trap. Enable FPE usage
* for this thread and try again.
*/
frame->tf_sstatus |= SSTATUS_FS_INITIAL;
pcb->pcb_fpflags |= PCB_FP_STARTED;
break;
}
#endif
call_trapsignal(td, SIGILL, ILL_ILLTRP, (void *)frame->tf_sepc);
userret(td, frame);
break;

View File

@ -87,8 +87,8 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
/* Arguments for child */
tf->tf_a[0] = 0;
tf->tf_a[1] = 0;
tf->tf_sstatus = (SSTATUS_SPIE);
tf->tf_sstatus |= (MSTATUS_PRV_U << MSTATUS_SPP_SHIFT);
tf->tf_sstatus |= (SSTATUS_SPIE); /* Enable interrupts. */
tf->tf_sstatus &= ~(SSTATUS_SPP); /* User mode. */
td2->td_frame = tf;