applies clang-format changes

This commit is contained in:
Eyck Jentzsch 2023-10-29 17:06:56 +01:00
parent 2115e9ceae
commit 759061b569
51 changed files with 11493 additions and 12673 deletions

View File

@ -1,4 +1,3 @@
---
Language: Cpp Language: Cpp
# BasedOnStyle: LLVM # BasedOnStyle: LLVM
# should be in line with IndentWidth # should be in line with IndentWidth
@ -13,8 +12,8 @@ AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: true AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: true AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false AlwaysBreakBeforeMultilineStrings: false
@ -39,8 +38,8 @@ BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: true BreakConstructorInitializersBeforeComma: true
BreakAfterJavaFieldAnnotations: false BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true BreakStringLiterals: true
ColumnLimit: 120 ColumnLimit: 140
CommentPragmas: '^ IWYU pragma:' CommentPragmas: '^( IWYU pragma:| @suppress)'
ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 0 ConstructorInitializerIndentWidth: 0
ContinuationIndentWidth: 4 ContinuationIndentWidth: 4
@ -76,13 +75,13 @@ PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000 PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000 PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60 PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right PointerAlignment: Left
ReflowComments: true ReflowComments: true
SortIncludes: true SortIncludes: true
SpaceAfterCStyleCast: false SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements SpaceBeforeParens: Never
SpaceInEmptyParentheses: false SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1 SpacesBeforeTrailingComments: 1
SpacesInAngles: false SpacesInAngles: false

View File

@ -50,4 +50,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define SOFTFLOAT_BUILTIN_CLZ 1 #define SOFTFLOAT_BUILTIN_CLZ 1
#include "opts-GCC.h" #include "opts-GCC.h"

View File

@ -50,4 +50,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define SOFTFLOAT_BUILTIN_CLZ 1 #define SOFTFLOAT_BUILTIN_CLZ 1
#include "opts-GCC.h" #include "opts-GCC.h"

View File

@ -50,4 +50,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define SOFTFLOAT_BUILTIN_CLZ 1 #define SOFTFLOAT_BUILTIN_CLZ 1
#include "opts-GCC.h" #include "opts-GCC.h"

View File

@ -54,4 +54,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define SOFTFLOAT_INTRINSIC_INT128 1 #define SOFTFLOAT_INTRINSIC_INT128 1
#endif #endif
#include "opts-GCC.h" #include "opts-GCC.h"

View File

@ -50,4 +50,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define SOFTFLOAT_BUILTIN_CLZ 1 #define SOFTFLOAT_BUILTIN_CLZ 1
#include "opts-GCC.h" #include "opts-GCC.h"

View File

@ -50,4 +50,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define SOFTFLOAT_BUILTIN_CLZ 1 #define SOFTFLOAT_BUILTIN_CLZ 1
#include "opts-GCC.h" #include "opts-GCC.h"

View File

@ -51,4 +51,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define SOFTFLOAT_BUILTIN_CLZ 1 #define SOFTFLOAT_BUILTIN_CLZ 1
#define SOFTFLOAT_INTRINSIC_INT128 1 #define SOFTFLOAT_INTRINSIC_INT128 1
#include "opts-GCC.h" #include "opts-GCC.h"

View File

@ -47,4 +47,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
== > #define THREAD_LOCAL _Thread_local == > #define THREAD_LOCAL _Thread_local

View File

@ -47,4 +47,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
== > #define THREAD_LOCAL _Thread_local == > #define THREAD_LOCAL _Thread_local

View File

@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef specialize_h #ifndef specialize_h
#define specialize_h 1 #define specialize_h 1
#include <stdbool.h>
#include <stdint.h>
#include "primitiveTypes.h" #include "primitiveTypes.h"
#include "softfloat.h" #include "softfloat.h"
#include <stdbool.h>
#include <stdint.h>
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Default value for 'softfloat_detectTininess'. | Default value for 'softfloat_detectTininess'.
@ -114,8 +114,7 @@ uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised. | signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
uint_fast16_t uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 32-bit floating-point NaN. | The bit pattern for a default generated 32-bit floating-point NaN.
@ -149,8 +148,7 @@ uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised. | signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
uint_fast32_t uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 64-bit floating-point NaN. | The bit pattern for a default generated 64-bit floating-point NaN.
@ -162,7 +160,8 @@ uint_fast32_t
| 64-bit floating-point signaling NaN. | 64-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once. | Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF ))) #define softfloat_isSigNaNF64UI(uiA) \
((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF)))
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts | Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts
@ -184,8 +183,7 @@ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised. | signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
uint_fast64_t uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 80-bit extended floating-point NaN. | The bit pattern for a default generated 80-bit extended floating-point NaN.
@ -199,7 +197,8 @@ uint_fast64_t
| floating-point signaling NaN. | floating-point signaling NaN.
| Note: This macro evaluates its arguments more than once. | Note: This macro evaluates its arguments more than once.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF ))) #define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \
((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF)))
#ifdef SOFTFLOAT_FAST_INT64 #ifdef SOFTFLOAT_FAST_INT64
@ -215,9 +214,7 @@ uint_fast64_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised. | exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
softfloat_extF80UIToCommonNaN(
uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
@ -235,13 +232,7 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
| result. If either original floating-point value is a signaling NaN, the | result. If either original floating-point value is a signaling NaN, the
| invalid exception is raised. | invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
struct uint128 struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0);
softfloat_propagateNaNExtF80UI(
uint_fast16_t uiA64,
uint_fast64_t uiA0,
uint_fast16_t uiB64,
uint_fast64_t uiB0
);
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 128-bit floating-point NaN. | The bit pattern for a default generated 128-bit floating-point NaN.
@ -255,7 +246,8 @@ struct uint128
| point signaling NaN. | point signaling NaN.
| Note: This macro evaluates its arguments more than once. | Note: This macro evaluates its arguments more than once.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF )))) #define softfloat_isSigNaNF128UI(uiA64, uiA0) \
((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF))))
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' | Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
@ -264,9 +256,7 @@ struct uint128
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception | pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
| is raised. | is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
softfloat_f128UIToCommonNaN(
uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
@ -283,13 +273,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
| If either original floating-point value is a signaling NaN, the invalid | If either original floating-point value is a signaling NaN, the invalid
| exception is raised. | exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
struct uint128 struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0);
softfloat_propagateNaNF128UI(
uint_fast64_t uiA64,
uint_fast64_t uiA0,
uint_fast64_t uiB64,
uint_fast64_t uiB0
);
#else #else
@ -304,18 +288,14 @@ struct uint128
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling | common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
| NaN, the invalid exception is raised. | NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr);
softfloat_extF80MToCommonNaN(
const struct extFloat80M *aSPtr, struct commonNaN *zPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
| floating-point NaN, and stores this NaN at the location pointed to by | floating-point NaN, and stores this NaN at the location pointed to by
| 'zSPtr'. | 'zSPtr'.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
softfloat_commonNaNToExtF80M(
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Assuming at least one of the two 80-bit extended floating-point values | Assuming at least one of the two 80-bit extended floating-point values
@ -323,12 +303,7 @@ void
| at the location pointed to by 'zSPtr'. If either original floating-point | at the location pointed to by 'zSPtr'. If either original floating-point
| value is a signaling NaN, the invalid exception is raised. | value is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr);
softfloat_propagateNaNExtF80M(
const struct extFloat80M *aSPtr,
const struct extFloat80M *bSPtr,
struct extFloat80M *zSPtr
);
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 128-bit floating-point NaN. | The bit pattern for a default generated 128-bit floating-point NaN.
@ -346,8 +321,7 @@ void
| four 32-bit elements that concatenate in the platform's normal endian order | four 32-bit elements that concatenate in the platform's normal endian order
| to form a 128-bit floating-point value. | to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr);
softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
@ -355,8 +329,7 @@ void
| 'zWPtr' points to an array of four 32-bit elements that concatenate in the | 'zWPtr' points to an array of four 32-bit elements that concatenate in the
| platform's normal endian order to form a 128-bit floating-point value. | platform's normal endian order to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Assuming at least one of the two 128-bit floating-point values pointed to by | Assuming at least one of the two 128-bit floating-point values pointed to by
@ -366,11 +339,8 @@ void
| and 'zWPtr' points to an array of four 32-bit elements that concatenate in | and 'zWPtr' points to an array of four 32-bit elements that concatenate in
| the platform's normal endian order to form a 128-bit floating-point value. | the platform's normal endian order to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr);
softfloat_propagateNaNF128M(
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
#endif #endif
#endif #endif

View File

@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef specialize_h #ifndef specialize_h
#define specialize_h 1 #define specialize_h 1
#include <stdbool.h>
#include <stdint.h>
#include "primitiveTypes.h" #include "primitiveTypes.h"
#include "softfloat.h" #include "softfloat.h"
#include <stdbool.h>
#include <stdint.h>
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Default value for 'softfloat_detectTininess'. | Default value for 'softfloat_detectTininess'.
@ -114,8 +114,7 @@ uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised. | signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
uint_fast16_t uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 32-bit floating-point NaN. | The bit pattern for a default generated 32-bit floating-point NaN.
@ -149,8 +148,7 @@ uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised. | signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
uint_fast32_t uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 64-bit floating-point NaN. | The bit pattern for a default generated 64-bit floating-point NaN.
@ -162,7 +160,8 @@ uint_fast32_t
| 64-bit floating-point signaling NaN. | 64-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once. | Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF ))) #define softfloat_isSigNaNF64UI(uiA) \
((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF)))
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts | Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts
@ -184,8 +183,7 @@ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised. | signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
uint_fast64_t uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 80-bit extended floating-point NaN. | The bit pattern for a default generated 80-bit extended floating-point NaN.
@ -199,7 +197,8 @@ uint_fast64_t
| floating-point signaling NaN. | floating-point signaling NaN.
| Note: This macro evaluates its arguments more than once. | Note: This macro evaluates its arguments more than once.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF ))) #define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \
((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF)))
#ifdef SOFTFLOAT_FAST_INT64 #ifdef SOFTFLOAT_FAST_INT64
@ -215,9 +214,7 @@ uint_fast64_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised. | exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
softfloat_extF80UIToCommonNaN(
uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
@ -235,13 +232,7 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
| result. If either original floating-point value is a signaling NaN, the | result. If either original floating-point value is a signaling NaN, the
| invalid exception is raised. | invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
struct uint128 struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0);
softfloat_propagateNaNExtF80UI(
uint_fast16_t uiA64,
uint_fast64_t uiA0,
uint_fast16_t uiB64,
uint_fast64_t uiB0
);
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 128-bit floating-point NaN. | The bit pattern for a default generated 128-bit floating-point NaN.
@ -255,7 +246,8 @@ struct uint128
| point signaling NaN. | point signaling NaN.
| Note: This macro evaluates its arguments more than once. | Note: This macro evaluates its arguments more than once.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF )))) #define softfloat_isSigNaNF128UI(uiA64, uiA0) \
((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF))))
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' | Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
@ -264,9 +256,7 @@ struct uint128
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception | pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
| is raised. | is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
softfloat_f128UIToCommonNaN(
uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
@ -283,13 +273,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
| If either original floating-point value is a signaling NaN, the invalid | If either original floating-point value is a signaling NaN, the invalid
| exception is raised. | exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
struct uint128 struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0);
softfloat_propagateNaNF128UI(
uint_fast64_t uiA64,
uint_fast64_t uiA0,
uint_fast64_t uiB64,
uint_fast64_t uiB0
);
#else #else
@ -304,18 +288,14 @@ struct uint128
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling | common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
| NaN, the invalid exception is raised. | NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr);
softfloat_extF80MToCommonNaN(
const struct extFloat80M *aSPtr, struct commonNaN *zPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
| floating-point NaN, and stores this NaN at the location pointed to by | floating-point NaN, and stores this NaN at the location pointed to by
| 'zSPtr'. | 'zSPtr'.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
softfloat_commonNaNToExtF80M(
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Assuming at least one of the two 80-bit extended floating-point values | Assuming at least one of the two 80-bit extended floating-point values
@ -323,12 +303,7 @@ void
| at the location pointed to by 'zSPtr'. If either original floating-point | at the location pointed to by 'zSPtr'. If either original floating-point
| value is a signaling NaN, the invalid exception is raised. | value is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr);
softfloat_propagateNaNExtF80M(
const struct extFloat80M *aSPtr,
const struct extFloat80M *bSPtr,
struct extFloat80M *zSPtr
);
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 128-bit floating-point NaN. | The bit pattern for a default generated 128-bit floating-point NaN.
@ -346,8 +321,7 @@ void
| four 32-bit elements that concatenate in the platform's normal endian order | four 32-bit elements that concatenate in the platform's normal endian order
| to form a 128-bit floating-point value. | to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr);
softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
@ -355,8 +329,7 @@ void
| 'zWPtr' points to an array of four 32-bit elements that concatenate in the | 'zWPtr' points to an array of four 32-bit elements that concatenate in the
| platform's normal endian order to form a 128-bit floating-point value. | platform's normal endian order to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Assuming at least one of the two 128-bit floating-point values pointed to by | Assuming at least one of the two 128-bit floating-point values pointed to by
@ -366,11 +339,8 @@ void
| and 'zWPtr' points to an array of four 32-bit elements that concatenate in | and 'zWPtr' points to an array of four 32-bit elements that concatenate in
| the platform's normal endian order to form a 128-bit floating-point value. | the platform's normal endian order to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr);
softfloat_propagateNaNF128M(
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
#endif #endif
#endif #endif

View File

@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef specialize_h #ifndef specialize_h
#define specialize_h 1 #define specialize_h 1
#include <stdbool.h>
#include <stdint.h>
#include "primitiveTypes.h" #include "primitiveTypes.h"
#include "softfloat.h" #include "softfloat.h"
#include <stdbool.h>
#include <stdint.h>
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Default value for 'softfloat_detectTininess'. | Default value for 'softfloat_detectTininess'.
@ -73,7 +73,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
| "Common NaN" structure, used to transfer NaN representations from one format | "Common NaN" structure, used to transfer NaN representations from one format
| to another. | to another.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
struct commonNaN { char _unused; }; struct commonNaN {
char _unused;
};
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 16-bit floating-point NaN. | The bit pattern for a default generated 16-bit floating-point NaN.
@ -93,7 +95,9 @@ struct commonNaN { char _unused; };
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised. | exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_f16UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & 0x0200) ) softfloat_raiseFlags( softfloat_flag_invalid ) #define softfloat_f16UIToCommonNaN(uiA, zPtr) \
if(!((uiA)&0x0200)) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point | Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point
@ -107,8 +111,7 @@ struct commonNaN { char _unused; };
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised. | signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
uint_fast16_t uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 32-bit floating-point NaN. | The bit pattern for a default generated 32-bit floating-point NaN.
@ -128,7 +131,9 @@ uint_fast16_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised. | exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_f32UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & 0x00400000) ) softfloat_raiseFlags( softfloat_flag_invalid ) #define softfloat_f32UIToCommonNaN(uiA, zPtr) \
if(!((uiA)&0x00400000)) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point | Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point
@ -142,8 +147,7 @@ uint_fast16_t
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised. | signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
uint_fast32_t uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 64-bit floating-point NaN. | The bit pattern for a default generated 64-bit floating-point NaN.
@ -155,7 +159,8 @@ uint_fast32_t
| 64-bit floating-point signaling NaN. | 64-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once. | Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF ))) #define softfloat_isSigNaNF64UI(uiA) \
((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF)))
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts | Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts
@ -163,7 +168,9 @@ uint_fast32_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised. | exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_f64UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & UINT64_C( 0x0008000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid ) #define softfloat_f64UIToCommonNaN(uiA, zPtr) \
if(!((uiA)&UINT64_C(0x0008000000000000))) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point | Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point
@ -177,8 +184,7 @@ uint_fast32_t
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised. | signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
uint_fast64_t uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 80-bit extended floating-point NaN. | The bit pattern for a default generated 80-bit extended floating-point NaN.
@ -192,7 +198,8 @@ uint_fast64_t
| floating-point signaling NaN. | floating-point signaling NaN.
| Note: This macro evaluates its arguments more than once. | Note: This macro evaluates its arguments more than once.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF ))) #define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \
((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF)))
#ifdef SOFTFLOAT_FAST_INT64 #ifdef SOFTFLOAT_FAST_INT64
@ -208,7 +215,9 @@ uint_fast64_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised. | exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_extF80UIToCommonNaN( uiA64, uiA0, zPtr ) if ( ! ((uiA0) & UINT64_C( 0x4000000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid ) #define softfloat_extF80UIToCommonNaN(uiA64, uiA0, zPtr) \
if(!((uiA0)&UINT64_C(0x4000000000000000))) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
@ -217,8 +226,7 @@ uint_fast64_t
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE && !defined softfloat_commonNaNToExtF80UI #if defined INLINE && !defined softfloat_commonNaNToExtF80UI
INLINE INLINE
struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ) struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr) {
{
struct uint128 uiZ; struct uint128 uiZ;
uiZ.v64 = defaultNaNExtF80UI64; uiZ.v64 = defaultNaNExtF80UI64;
uiZ.v0 = defaultNaNExtF80UI0; uiZ.v0 = defaultNaNExtF80UI0;
@ -237,13 +245,7 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
| result. If either original floating-point value is a signaling NaN, the | result. If either original floating-point value is a signaling NaN, the
| invalid exception is raised. | invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
struct uint128 struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0);
softfloat_propagateNaNExtF80UI(
uint_fast16_t uiA64,
uint_fast64_t uiA0,
uint_fast16_t uiB64,
uint_fast64_t uiB0
);
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 128-bit floating-point NaN. | The bit pattern for a default generated 128-bit floating-point NaN.
@ -257,7 +259,8 @@ struct uint128
| point signaling NaN. | point signaling NaN.
| Note: This macro evaluates its arguments more than once. | Note: This macro evaluates its arguments more than once.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF )))) #define softfloat_isSigNaNF128UI(uiA64, uiA0) \
((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF))))
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' | Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
@ -266,7 +269,9 @@ struct uint128
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception | pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
| is raised. | is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_f128UIToCommonNaN( uiA64, uiA0, zPtr ) if ( ! ((uiA64) & UINT64_C( 0x0000800000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid ) #define softfloat_f128UIToCommonNaN(uiA64, uiA0, zPtr) \
if(!((uiA64)&UINT64_C(0x0000800000000000))) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
@ -274,8 +279,7 @@ struct uint128
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE && !defined softfloat_commonNaNToF128UI #if defined INLINE && !defined softfloat_commonNaNToF128UI
INLINE INLINE
struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr ) struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN* aPtr) {
{
struct uint128 uiZ; struct uint128 uiZ;
uiZ.v64 = defaultNaNF128UI64; uiZ.v64 = defaultNaNF128UI64;
uiZ.v0 = defaultNaNF128UI0; uiZ.v0 = defaultNaNF128UI0;
@ -294,13 +298,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
| If either original floating-point value is a signaling NaN, the invalid | If either original floating-point value is a signaling NaN, the invalid
| exception is raised. | exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
struct uint128 struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0);
softfloat_propagateNaNF128UI(
uint_fast64_t uiA64,
uint_fast64_t uiA0,
uint_fast64_t uiB64,
uint_fast64_t uiB0
);
#else #else
@ -315,7 +313,9 @@ struct uint128
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling | common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
| NaN, the invalid exception is raised. | NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_extF80MToCommonNaN( aSPtr, zPtr ) if ( ! ((aSPtr)->signif & UINT64_C( 0x4000000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid ) #define softfloat_extF80MToCommonNaN(aSPtr, zPtr) \
if(!((aSPtr)->signif & UINT64_C(0x4000000000000000))) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
@ -324,17 +324,12 @@ struct uint128
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE && !defined softfloat_commonNaNToExtF80M #if defined INLINE && !defined softfloat_commonNaNToExtF80M
INLINE INLINE
void void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr) {
softfloat_commonNaNToExtF80M(
const struct commonNaN *aPtr, struct extFloat80M *zSPtr )
{
zSPtr->signExp = defaultNaNExtF80UI64; zSPtr->signExp = defaultNaNExtF80UI64;
zSPtr->signif = defaultNaNExtF80UI0; zSPtr->signif = defaultNaNExtF80UI0;
} }
#else #else
void void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
softfloat_commonNaNToExtF80M(
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
#endif #endif
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
@ -343,12 +338,7 @@ void
| at the location pointed to by 'zSPtr'. If either original floating-point | at the location pointed to by 'zSPtr'. If either original floating-point
| value is a signaling NaN, the invalid exception is raised. | value is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr);
softfloat_propagateNaNExtF80M(
const struct extFloat80M *aSPtr,
const struct extFloat80M *bSPtr,
struct extFloat80M *zSPtr
);
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 128-bit floating-point NaN. | The bit pattern for a default generated 128-bit floating-point NaN.
@ -366,7 +356,9 @@ void
| four 32-bit elements that concatenate in the platform's normal endian order | four 32-bit elements that concatenate in the platform's normal endian order
| to form a 128-bit floating-point value. | to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_f128MToCommonNaN( aWPtr, zPtr ) if ( ! ((aWPtr)[indexWordHi( 4 )] & UINT64_C( 0x0000800000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid ) #define softfloat_f128MToCommonNaN(aWPtr, zPtr) \
if(!((aWPtr)[indexWordHi(4)] & UINT64_C(0x0000800000000000))) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
@ -376,17 +368,14 @@ void
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE && !defined softfloat_commonNaNToF128M #if defined INLINE && !defined softfloat_commonNaNToF128M
INLINE INLINE
void void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr) {
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr )
{
zWPtr[indexWord(4, 3)] = defaultNaNF128UI96; zWPtr[indexWord(4, 3)] = defaultNaNF128UI96;
zWPtr[indexWord(4, 2)] = defaultNaNF128UI64; zWPtr[indexWord(4, 2)] = defaultNaNF128UI64;
zWPtr[indexWord(4, 1)] = defaultNaNF128UI32; zWPtr[indexWord(4, 1)] = defaultNaNF128UI32;
zWPtr[indexWord(4, 0)] = defaultNaNF128UI0; zWPtr[indexWord(4, 0)] = defaultNaNF128UI0;
} }
#else #else
void void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
#endif #endif
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
@ -397,11 +386,8 @@ void
| and 'zWPtr' points to an array of four 32-bit elements that concatenate in | and 'zWPtr' points to an array of four 32-bit elements that concatenate in
| the platform's normal endian order to form a 128-bit floating-point value. | the platform's normal endian order to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr);
softfloat_propagateNaNF128M(
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
#endif #endif
#endif #endif

View File

@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef specialize_h #ifndef specialize_h
#define specialize_h 1 #define specialize_h 1
#include <stdbool.h>
#include <stdint.h>
#include "primitiveTypes.h" #include "primitiveTypes.h"
#include "softfloat.h" #include "softfloat.h"
#include <stdbool.h>
#include <stdint.h>
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Default value for 'softfloat_detectTininess'. | Default value for 'softfloat_detectTininess'.
@ -114,8 +114,7 @@ uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised. | signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
uint_fast16_t uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 32-bit floating-point NaN. | The bit pattern for a default generated 32-bit floating-point NaN.
@ -149,8 +148,7 @@ uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised. | signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
uint_fast32_t uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 64-bit floating-point NaN. | The bit pattern for a default generated 64-bit floating-point NaN.
@ -162,7 +160,8 @@ uint_fast32_t
| 64-bit floating-point signaling NaN. | 64-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once. | Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF ))) #define softfloat_isSigNaNF64UI(uiA) \
((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF)))
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts | Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts
@ -184,8 +183,7 @@ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised. | signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
uint_fast64_t uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 80-bit extended floating-point NaN. | The bit pattern for a default generated 80-bit extended floating-point NaN.
@ -199,7 +197,8 @@ uint_fast64_t
| floating-point signaling NaN. | floating-point signaling NaN.
| Note: This macro evaluates its arguments more than once. | Note: This macro evaluates its arguments more than once.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF ))) #define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \
((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF)))
#ifdef SOFTFLOAT_FAST_INT64 #ifdef SOFTFLOAT_FAST_INT64
@ -215,9 +214,7 @@ uint_fast64_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised. | exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
softfloat_extF80UIToCommonNaN(
uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
@ -235,13 +232,7 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
| result. If either original floating-point value is a signaling NaN, the | result. If either original floating-point value is a signaling NaN, the
| invalid exception is raised. | invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
struct uint128 struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0);
softfloat_propagateNaNExtF80UI(
uint_fast16_t uiA64,
uint_fast64_t uiA0,
uint_fast16_t uiB64,
uint_fast64_t uiB0
);
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 128-bit floating-point NaN. | The bit pattern for a default generated 128-bit floating-point NaN.
@ -255,7 +246,8 @@ struct uint128
| point signaling NaN. | point signaling NaN.
| Note: This macro evaluates its arguments more than once. | Note: This macro evaluates its arguments more than once.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF )))) #define softfloat_isSigNaNF128UI(uiA64, uiA0) \
((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF))))
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' | Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
@ -264,9 +256,7 @@ struct uint128
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception | pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
| is raised. | is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
softfloat_f128UIToCommonNaN(
uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
@ -283,13 +273,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
| If either original floating-point value is a signaling NaN, the invalid | If either original floating-point value is a signaling NaN, the invalid
| exception is raised. | exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
struct uint128 struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0);
softfloat_propagateNaNF128UI(
uint_fast64_t uiA64,
uint_fast64_t uiA0,
uint_fast64_t uiB64,
uint_fast64_t uiB0
);
#else #else
@ -304,18 +288,14 @@ struct uint128
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling | common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
| NaN, the invalid exception is raised. | NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr);
softfloat_extF80MToCommonNaN(
const struct extFloat80M *aSPtr, struct commonNaN *zPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
| floating-point NaN, and stores this NaN at the location pointed to by | floating-point NaN, and stores this NaN at the location pointed to by
| 'zSPtr'. | 'zSPtr'.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
softfloat_commonNaNToExtF80M(
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Assuming at least one of the two 80-bit extended floating-point values | Assuming at least one of the two 80-bit extended floating-point values
@ -323,12 +303,7 @@ void
| at the location pointed to by 'zSPtr'. If either original floating-point | at the location pointed to by 'zSPtr'. If either original floating-point
| value is a signaling NaN, the invalid exception is raised. | value is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr);
softfloat_propagateNaNExtF80M(
const struct extFloat80M *aSPtr,
const struct extFloat80M *bSPtr,
struct extFloat80M *zSPtr
);
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 128-bit floating-point NaN. | The bit pattern for a default generated 128-bit floating-point NaN.
@ -346,8 +321,7 @@ void
| four 32-bit elements that concatenate in the platform's normal endian order | four 32-bit elements that concatenate in the platform's normal endian order
| to form a 128-bit floating-point value. | to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr);
softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
@ -355,8 +329,7 @@ void
| 'zWPtr' points to an array of four 32-bit elements that concatenate in the | 'zWPtr' points to an array of four 32-bit elements that concatenate in the
| platform's normal endian order to form a 128-bit floating-point value. | platform's normal endian order to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Assuming at least one of the two 128-bit floating-point values pointed to by | Assuming at least one of the two 128-bit floating-point values pointed to by
@ -366,11 +339,8 @@ void
| and 'zWPtr' points to an array of four 32-bit elements that concatenate in | and 'zWPtr' points to an array of four 32-bit elements that concatenate in
| the platform's normal endian order to form a 128-bit floating-point value. | the platform's normal endian order to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr);
softfloat_propagateNaNF128M(
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
#endif #endif
#endif #endif

View File

@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef specialize_h #ifndef specialize_h
#define specialize_h 1 #define specialize_h 1
#include <stdbool.h>
#include <stdint.h>
#include "primitiveTypes.h" #include "primitiveTypes.h"
#include "softfloat.h" #include "softfloat.h"
#include <stdbool.h>
#include <stdint.h>
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Default value for 'softfloat_detectTininess'. | Default value for 'softfloat_detectTininess'.
@ -114,8 +114,7 @@ uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised. | signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
uint_fast16_t uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 32-bit floating-point NaN. | The bit pattern for a default generated 32-bit floating-point NaN.
@ -149,8 +148,7 @@ uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised. | signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
uint_fast32_t uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 64-bit floating-point NaN. | The bit pattern for a default generated 64-bit floating-point NaN.
@ -162,7 +160,8 @@ uint_fast32_t
| 64-bit floating-point signaling NaN. | 64-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once. | Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF ))) #define softfloat_isSigNaNF64UI(uiA) \
((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF)))
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts | Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts
@ -184,8 +183,7 @@ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised. | signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
uint_fast64_t uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 80-bit extended floating-point NaN. | The bit pattern for a default generated 80-bit extended floating-point NaN.
@ -199,7 +197,8 @@ uint_fast64_t
| floating-point signaling NaN. | floating-point signaling NaN.
| Note: This macro evaluates its arguments more than once. | Note: This macro evaluates its arguments more than once.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF ))) #define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \
((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF)))
#ifdef SOFTFLOAT_FAST_INT64 #ifdef SOFTFLOAT_FAST_INT64
@ -215,9 +214,7 @@ uint_fast64_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised. | exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
softfloat_extF80UIToCommonNaN(
uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
@ -235,13 +232,7 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
| result. If either original floating-point value is a signaling NaN, the | result. If either original floating-point value is a signaling NaN, the
| invalid exception is raised. | invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
struct uint128 struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0);
softfloat_propagateNaNExtF80UI(
uint_fast16_t uiA64,
uint_fast64_t uiA0,
uint_fast16_t uiB64,
uint_fast64_t uiB0
);
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 128-bit floating-point NaN. | The bit pattern for a default generated 128-bit floating-point NaN.
@ -255,7 +246,8 @@ struct uint128
| point signaling NaN. | point signaling NaN.
| Note: This macro evaluates its arguments more than once. | Note: This macro evaluates its arguments more than once.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF )))) #define softfloat_isSigNaNF128UI(uiA64, uiA0) \
((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF))))
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' | Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
@ -264,9 +256,7 @@ struct uint128
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception | pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
| is raised. | is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
softfloat_f128UIToCommonNaN(
uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
@ -283,13 +273,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
| If either original floating-point value is a signaling NaN, the invalid | If either original floating-point value is a signaling NaN, the invalid
| exception is raised. | exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
struct uint128 struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0);
softfloat_propagateNaNF128UI(
uint_fast64_t uiA64,
uint_fast64_t uiA0,
uint_fast64_t uiB64,
uint_fast64_t uiB0
);
#else #else
@ -304,18 +288,14 @@ struct uint128
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling | common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
| NaN, the invalid exception is raised. | NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr);
softfloat_extF80MToCommonNaN(
const struct extFloat80M *aSPtr, struct commonNaN *zPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
| floating-point NaN, and stores this NaN at the location pointed to by | floating-point NaN, and stores this NaN at the location pointed to by
| 'zSPtr'. | 'zSPtr'.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
softfloat_commonNaNToExtF80M(
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Assuming at least one of the two 80-bit extended floating-point values | Assuming at least one of the two 80-bit extended floating-point values
@ -323,12 +303,7 @@ void
| at the location pointed to by 'zSPtr'. If either original floating-point | at the location pointed to by 'zSPtr'. If either original floating-point
| value is a signaling NaN, the invalid exception is raised. | value is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr);
softfloat_propagateNaNExtF80M(
const struct extFloat80M *aSPtr,
const struct extFloat80M *bSPtr,
struct extFloat80M *zSPtr
);
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 128-bit floating-point NaN. | The bit pattern for a default generated 128-bit floating-point NaN.
@ -346,8 +321,7 @@ void
| four 32-bit elements that concatenate in the platform's normal endian order | four 32-bit elements that concatenate in the platform's normal endian order
| to form a 128-bit floating-point value. | to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr);
softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
@ -355,8 +329,7 @@ void
| 'zWPtr' points to an array of four 32-bit elements that concatenate in the | 'zWPtr' points to an array of four 32-bit elements that concatenate in the
| platform's normal endian order to form a 128-bit floating-point value. | platform's normal endian order to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Assuming at least one of the two 128-bit floating-point values pointed to by | Assuming at least one of the two 128-bit floating-point values pointed to by
@ -366,11 +339,8 @@ void
| and 'zWPtr' points to an array of four 32-bit elements that concatenate in | and 'zWPtr' points to an array of four 32-bit elements that concatenate in
| the platform's normal endian order to form a 128-bit floating-point value. | the platform's normal endian order to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr);
softfloat_propagateNaNF128M(
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
#endif #endif
#endif #endif

View File

@ -37,33 +37,43 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef internals_h #ifndef internals_h
#define internals_h 1 #define internals_h 1
#include <stdbool.h>
#include <stdint.h>
#include "primitives.h" #include "primitives.h"
#include "softfloat_types.h" #include "softfloat_types.h"
#include <stdbool.h>
#include <stdint.h>
union ui16_f16 { uint16_t ui; float16_t f; }; union ui16_f16 {
union ui32_f32 { uint32_t ui; float32_t f; }; uint16_t ui;
union ui64_f64 { uint64_t ui; float64_t f; }; float16_t f;
};
union ui32_f32 {
uint32_t ui;
float32_t f;
};
union ui64_f64 {
uint64_t ui;
float64_t f;
};
#ifdef SOFTFLOAT_FAST_INT64 #ifdef SOFTFLOAT_FAST_INT64
union extF80M_extF80 { struct extFloat80M fM; extFloat80_t f; }; union extF80M_extF80 {
union ui128_f128 { struct uint128 ui; float128_t f; }; struct extFloat80M fM;
extFloat80_t f;
};
union ui128_f128 {
struct uint128 ui;
float128_t f;
};
#endif #endif
enum { enum { softfloat_mulAdd_subC = 1, softfloat_mulAdd_subProd = 2 };
softfloat_mulAdd_subC = 1,
softfloat_mulAdd_subProd = 2
};
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
uint_fast32_t softfloat_roundToUI32(bool, uint_fast64_t, uint_fast8_t, bool); uint_fast32_t softfloat_roundToUI32(bool, uint_fast64_t, uint_fast8_t, bool);
#ifdef SOFTFLOAT_FAST_INT64 #ifdef SOFTFLOAT_FAST_INT64
uint_fast64_t uint_fast64_t softfloat_roundToUI64(bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool);
softfloat_roundToUI64(
bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool );
#else #else
uint_fast64_t softfloat_roundMToUI64(bool, uint32_t*, uint_fast8_t, bool); uint_fast64_t softfloat_roundMToUI64(bool, uint32_t*, uint_fast8_t, bool);
#endif #endif
@ -71,9 +81,7 @@ uint_fast64_t softfloat_roundMToUI64( bool, uint32_t *, uint_fast8_t, bool );
int_fast32_t softfloat_roundToI32(bool, uint_fast64_t, uint_fast8_t, bool); int_fast32_t softfloat_roundToI32(bool, uint_fast64_t, uint_fast8_t, bool);
#ifdef SOFTFLOAT_FAST_INT64 #ifdef SOFTFLOAT_FAST_INT64
int_fast64_t int_fast64_t softfloat_roundToI64(bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool);
softfloat_roundToI64(
bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool );
#else #else
int_fast64_t softfloat_roundMToI64(bool, uint32_t*, uint_fast8_t, bool); int_fast64_t softfloat_roundMToI64(bool, uint32_t*, uint_fast8_t, bool);
#endif #endif
@ -87,7 +95,10 @@ int_fast64_t softfloat_roundMToI64( bool, uint32_t *, uint_fast8_t, bool );
#define isNaNF16UI(a) (((~(a)&0x7C00) == 0) && ((a)&0x03FF)) #define isNaNF16UI(a) (((~(a)&0x7C00) == 0) && ((a)&0x03FF))
struct exp8_sig16 { int_fast8_t exp; uint_fast16_t sig; }; struct exp8_sig16 {
int_fast8_t exp;
uint_fast16_t sig;
};
struct exp8_sig16 softfloat_normSubnormalF16Sig(uint_fast16_t); struct exp8_sig16 softfloat_normSubnormalF16Sig(uint_fast16_t);
float16_t softfloat_roundPackToF16(bool, int_fast16_t, uint_fast16_t); float16_t softfloat_roundPackToF16(bool, int_fast16_t, uint_fast16_t);
@ -95,9 +106,7 @@ float16_t softfloat_normRoundPackToF16( bool, int_fast16_t, uint_fast16_t );
float16_t softfloat_addMagsF16(uint_fast16_t, uint_fast16_t); float16_t softfloat_addMagsF16(uint_fast16_t, uint_fast16_t);
float16_t softfloat_subMagsF16(uint_fast16_t, uint_fast16_t); float16_t softfloat_subMagsF16(uint_fast16_t, uint_fast16_t);
float16_t float16_t softfloat_mulAddF16(uint_fast16_t, uint_fast16_t, uint_fast16_t, uint_fast8_t);
softfloat_mulAddF16(
uint_fast16_t, uint_fast16_t, uint_fast16_t, uint_fast8_t );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
@ -108,7 +117,10 @@ float16_t
#define isNaNF32UI(a) (((~(a)&0x7F800000) == 0) && ((a)&0x007FFFFF)) #define isNaNF32UI(a) (((~(a)&0x7F800000) == 0) && ((a)&0x007FFFFF))
struct exp16_sig32 { int_fast16_t exp; uint_fast32_t sig; }; struct exp16_sig32 {
int_fast16_t exp;
uint_fast32_t sig;
};
struct exp16_sig32 softfloat_normSubnormalF32Sig(uint_fast32_t); struct exp16_sig32 softfloat_normSubnormalF32Sig(uint_fast32_t);
float32_t softfloat_roundPackToF32(bool, int_fast16_t, uint_fast32_t); float32_t softfloat_roundPackToF32(bool, int_fast16_t, uint_fast32_t);
@ -116,9 +128,7 @@ float32_t softfloat_normRoundPackToF32( bool, int_fast16_t, uint_fast32_t );
float32_t softfloat_addMagsF32(uint_fast32_t, uint_fast32_t); float32_t softfloat_addMagsF32(uint_fast32_t, uint_fast32_t);
float32_t softfloat_subMagsF32(uint_fast32_t, uint_fast32_t); float32_t softfloat_subMagsF32(uint_fast32_t, uint_fast32_t);
float32_t float32_t softfloat_mulAddF32(uint_fast32_t, uint_fast32_t, uint_fast32_t, uint_fast8_t);
softfloat_mulAddF32(
uint_fast32_t, uint_fast32_t, uint_fast32_t, uint_fast8_t );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
@ -129,7 +139,10 @@ float32_t
#define isNaNF64UI(a) (((~(a)&UINT64_C(0x7FF0000000000000)) == 0) && ((a)&UINT64_C(0x000FFFFFFFFFFFFF))) #define isNaNF64UI(a) (((~(a)&UINT64_C(0x7FF0000000000000)) == 0) && ((a)&UINT64_C(0x000FFFFFFFFFFFFF)))
struct exp16_sig64 { int_fast16_t exp; uint_fast64_t sig; }; struct exp16_sig64 {
int_fast16_t exp;
uint_fast64_t sig;
};
struct exp16_sig64 softfloat_normSubnormalF64Sig(uint_fast64_t); struct exp16_sig64 softfloat_normSubnormalF64Sig(uint_fast64_t);
float64_t softfloat_roundPackToF64(bool, int_fast16_t, uint_fast64_t); float64_t softfloat_roundPackToF64(bool, int_fast16_t, uint_fast64_t);
@ -137,9 +150,7 @@ float64_t softfloat_normRoundPackToF64( bool, int_fast16_t, uint_fast64_t );
float64_t softfloat_addMagsF64(uint_fast64_t, uint_fast64_t, bool); float64_t softfloat_addMagsF64(uint_fast64_t, uint_fast64_t, bool);
float64_t softfloat_subMagsF64(uint_fast64_t, uint_fast64_t, bool); float64_t softfloat_subMagsF64(uint_fast64_t, uint_fast64_t, bool);
float64_t float64_t softfloat_mulAddF64(uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_t);
softfloat_mulAddF64(
uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_t );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
@ -154,22 +165,17 @@ float64_t
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
struct exp32_sig64 { int_fast32_t exp; uint64_t sig; }; struct exp32_sig64 {
int_fast32_t exp;
uint64_t sig;
};
struct exp32_sig64 softfloat_normSubnormalExtF80Sig(uint_fast64_t); struct exp32_sig64 softfloat_normSubnormalExtF80Sig(uint_fast64_t);
extFloat80_t extFloat80_t softfloat_roundPackToExtF80(bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t);
softfloat_roundPackToExtF80( extFloat80_t softfloat_normRoundPackToExtF80(bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t);
bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t );
extFloat80_t
softfloat_normRoundPackToExtF80(
bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t );
extFloat80_t extFloat80_t softfloat_addMagsExtF80(uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool);
softfloat_addMagsExtF80( extFloat80_t softfloat_subMagsExtF80(uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool);
uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool );
extFloat80_t
softfloat_subMagsExtF80(
uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
@ -180,67 +186,35 @@ extFloat80_t
#define isNaNF128UI(a64, a0) (((~(a64)&UINT64_C(0x7FFF000000000000)) == 0) && (a0 || ((a64)&UINT64_C(0x0000FFFFFFFFFFFF)))) #define isNaNF128UI(a64, a0) (((~(a64)&UINT64_C(0x7FFF000000000000)) == 0) && (a0 || ((a64)&UINT64_C(0x0000FFFFFFFFFFFF))))
struct exp32_sig128 { int_fast32_t exp; struct uint128 sig; }; struct exp32_sig128 {
struct exp32_sig128 int_fast32_t exp;
softfloat_normSubnormalF128Sig( uint_fast64_t, uint_fast64_t ); struct uint128 sig;
};
struct exp32_sig128 softfloat_normSubnormalF128Sig(uint_fast64_t, uint_fast64_t);
float128_t float128_t softfloat_roundPackToF128(bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast64_t);
softfloat_roundPackToF128( float128_t softfloat_normRoundPackToF128(bool, int_fast32_t, uint_fast64_t, uint_fast64_t);
bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast64_t );
float128_t
softfloat_normRoundPackToF128(
bool, int_fast32_t, uint_fast64_t, uint_fast64_t );
float128_t float128_t softfloat_addMagsF128(uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool);
softfloat_addMagsF128( float128_t softfloat_subMagsF128(uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool);
uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); float128_t softfloat_mulAddF128(uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_t);
float128_t
softfloat_subMagsF128(
uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
float128_t
softfloat_mulAddF128(
uint_fast64_t,
uint_fast64_t,
uint_fast64_t,
uint_fast64_t,
uint_fast64_t,
uint_fast64_t,
uint_fast8_t
);
#else #else
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
bool bool softfloat_tryPropagateNaNExtF80M(const struct extFloat80M*, const struct extFloat80M*, struct extFloat80M*);
softfloat_tryPropagateNaNExtF80M(
const struct extFloat80M *,
const struct extFloat80M *,
struct extFloat80M *
);
void softfloat_invalidExtF80M(struct extFloat80M*); void softfloat_invalidExtF80M(struct extFloat80M*);
int softfloat_normExtF80SigM(uint64_t*); int softfloat_normExtF80SigM(uint64_t*);
void void softfloat_roundPackMToExtF80M(bool, int32_t, uint32_t*, uint_fast8_t, struct extFloat80M*);
softfloat_roundPackMToExtF80M( void softfloat_normRoundPackMToExtF80M(bool, int32_t, uint32_t*, uint_fast8_t, struct extFloat80M*);
bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * );
void
softfloat_normRoundPackMToExtF80M(
bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * );
void void softfloat_addExtF80M(const struct extFloat80M*, const struct extFloat80M*, struct extFloat80M*, bool);
softfloat_addExtF80M(
const struct extFloat80M *,
const struct extFloat80M *,
struct extFloat80M *,
bool
);
int int softfloat_compareNonnormExtF80M(const struct extFloat80M*, const struct extFloat80M*);
softfloat_compareNonnormExtF80M(
const struct extFloat80M *, const struct extFloat80M * );
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
@ -251,9 +225,7 @@ int
bool softfloat_isNaNF128M(const uint32_t*); bool softfloat_isNaNF128M(const uint32_t*);
bool bool softfloat_tryPropagateNaNF128M(const uint32_t*, const uint32_t*, uint32_t*);
softfloat_tryPropagateNaNF128M(
const uint32_t *, const uint32_t *, uint32_t * );
void softfloat_invalidF128M(uint32_t*); void softfloat_invalidF128M(uint32_t*);
int softfloat_shiftNormSigF128M(const uint32_t*, uint_fast8_t, uint32_t*); int softfloat_shiftNormSigF128M(const uint32_t*, uint_fast8_t, uint32_t*);
@ -261,18 +233,9 @@ int softfloat_shiftNormSigF128M( const uint32_t *, uint_fast8_t, uint32_t * );
void softfloat_roundPackMToF128M(bool, int32_t, uint32_t*, uint32_t*); void softfloat_roundPackMToF128M(bool, int32_t, uint32_t*, uint32_t*);
void softfloat_normRoundPackMToF128M(bool, int32_t, uint32_t*, uint32_t*); void softfloat_normRoundPackMToF128M(bool, int32_t, uint32_t*, uint32_t*);
void void softfloat_addF128M(const uint32_t*, const uint32_t*, uint32_t*, bool);
softfloat_addF128M( const uint32_t *, const uint32_t *, uint32_t *, bool ); void softfloat_mulAddF128M(const uint32_t*, const uint32_t*, const uint32_t*, uint32_t*, uint_fast8_t);
void
softfloat_mulAddF128M(
const uint32_t *,
const uint32_t *,
const uint32_t *,
uint32_t *,
uint_fast8_t
);
#endif #endif
#endif #endif

View File

@ -39,57 +39,57 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef INLINE #ifdef INLINE
#include <stdint.h>
#include "primitiveTypes.h" #include "primitiveTypes.h"
#include <stdint.h>
#ifdef SOFTFLOAT_BUILTIN_CLZ #ifdef SOFTFLOAT_BUILTIN_CLZ
INLINE uint_fast8_t softfloat_countLeadingZeros16( uint16_t a ) INLINE uint_fast8_t softfloat_countLeadingZeros16(uint16_t a) { return a ? __builtin_clz(a) - 16 : 16; }
{ return a ? __builtin_clz( a ) - 16 : 16; }
#define softfloat_countLeadingZeros16 softfloat_countLeadingZeros16 #define softfloat_countLeadingZeros16 softfloat_countLeadingZeros16
INLINE uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ) INLINE uint_fast8_t softfloat_countLeadingZeros32(uint32_t a) { return a ? __builtin_clz(a) : 32; }
{ return a ? __builtin_clz( a ) : 32; }
#define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32 #define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32
INLINE uint_fast8_t softfloat_countLeadingZeros64( uint64_t a ) INLINE uint_fast8_t softfloat_countLeadingZeros64(uint64_t a) { return a ? __builtin_clzll(a) : 64; }
{ return a ? __builtin_clzll( a ) : 64; }
#define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64 #define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64
#endif #endif
#ifdef SOFTFLOAT_INTRINSIC_INT128 #ifdef SOFTFLOAT_INTRINSIC_INT128
INLINE struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b ) INLINE struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b) {
{ union {
union { unsigned __int128 ui; struct uint128 s; } uZ; unsigned __int128 ui;
struct uint128 s;
} uZ;
uZ.ui = (unsigned __int128)a * ((uint_fast64_t)b << 32); uZ.ui = (unsigned __int128)a * ((uint_fast64_t)b << 32);
return uZ.s; return uZ.s;
} }
#define softfloat_mul64ByShifted32To128 softfloat_mul64ByShifted32To128 #define softfloat_mul64ByShifted32To128 softfloat_mul64ByShifted32To128
INLINE struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b ) INLINE struct uint128 softfloat_mul64To128(uint64_t a, uint64_t b) {
{ union {
union { unsigned __int128 ui; struct uint128 s; } uZ; unsigned __int128 ui;
struct uint128 s;
} uZ;
uZ.ui = (unsigned __int128)a * b; uZ.ui = (unsigned __int128)a * b;
return uZ.s; return uZ.s;
} }
#define softfloat_mul64To128 softfloat_mul64To128 #define softfloat_mul64To128 softfloat_mul64To128
INLINE INLINE
struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b ) struct uint128 softfloat_mul128By32(uint64_t a64, uint64_t a0, uint32_t b) {
{ union {
union { unsigned __int128 ui; struct uint128 s; } uZ; unsigned __int128 ui;
struct uint128 s;
} uZ;
uZ.ui = ((unsigned __int128)a64 << 64 | a0) * b; uZ.ui = ((unsigned __int128)a64 << 64 | a0) * b;
return uZ.s; return uZ.s;
} }
#define softfloat_mul128By32 softfloat_mul128By32 #define softfloat_mul128By32 softfloat_mul128By32
INLINE INLINE
void void softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t* zPtr) {
softfloat_mul128To256M(
uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr )
{
unsigned __int128 z0, mid1, mid, z128; unsigned __int128 z0, mid1, mid, z128;
z0 = (unsigned __int128)a0 * b0; z0 = (unsigned __int128)a0 * b0;
mid1 = (unsigned __int128)a64 * b0; mid1 = (unsigned __int128)a64 * b0;
@ -111,4 +111,3 @@ void
#endif #endif
#endif #endif

View File

@ -42,13 +42,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef SOFTFLOAT_FAST_INT64 #ifdef SOFTFLOAT_FAST_INT64
#ifdef LITTLEENDIAN #ifdef LITTLEENDIAN
struct uint128 { uint64_t v0, v64; }; struct uint128 {
struct uint64_extra { uint64_t extra, v; }; uint64_t v0, v64;
struct uint128_extra { uint64_t extra; struct uint128 v; }; };
struct uint64_extra {
uint64_t extra, v;
};
struct uint128_extra {
uint64_t extra;
struct uint128 v;
};
#else #else
struct uint128 { uint64_t v64, v0; }; struct uint128 {
struct uint64_extra { uint64_t v, extra; }; uint64_t v64, v0;
struct uint128_extra { struct uint128 v; uint64_t extra; }; };
struct uint64_extra {
uint64_t v, extra;
};
struct uint128_extra {
struct uint128 v;
uint64_t extra;
};
#endif #endif
#endif #endif
@ -67,7 +81,8 @@ struct uint128_extra { struct uint128 v; uint64_t extra; };
#define indexMultiwordLo(total, n) 0 #define indexMultiwordLo(total, n) 0
#define indexMultiwordHiBut(total, n) (n) #define indexMultiwordHiBut(total, n) (n)
#define indexMultiwordLoBut(total, n) 0 #define indexMultiwordLoBut(total, n) 0
#define INIT_UINTM4( v3, v2, v1, v0 ) { v0, v1, v2, v3 } #define INIT_UINTM4(v3, v2, v1, v0) \
{ v0, v1, v2, v3 }
#else #else
#define wordIncr -1 #define wordIncr -1
#define indexWord(total, n) ((total)-1 - (n)) #define indexWord(total, n) ((total)-1 - (n))
@ -78,8 +93,8 @@ struct uint128_extra { struct uint128 v; uint64_t extra; };
#define indexMultiwordLo(total, n) ((total) - (n)) #define indexMultiwordLo(total, n) ((total) - (n))
#define indexMultiwordHiBut(total, n) 0 #define indexMultiwordHiBut(total, n) 0
#define indexMultiwordLoBut(total, n) (n) #define indexMultiwordLoBut(total, n) (n)
#define INIT_UINTM4( v3, v2, v1, v0 ) { v3, v2, v1, v0 } #define INIT_UINTM4(v3, v2, v1, v0) \
{ v3, v2, v1, v0 }
#endif #endif
#endif #endif

View File

@ -37,9 +37,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef primitives_h #ifndef primitives_h
#define primitives_h 1 #define primitives_h 1
#include "primitiveTypes.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "primitiveTypes.h"
#ifndef softfloat_shortShiftRightJam64 #ifndef softfloat_shortShiftRightJam64
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
@ -50,8 +50,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE INLINE
uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist ) uint64_t softfloat_shortShiftRightJam64(uint64_t a, uint_fast8_t dist) { return a >> dist | ((a & (((uint_fast64_t)1 << dist) - 1)) != 0); }
{ return a>>dist | ((a & (((uint_fast64_t) 1<<dist) - 1)) != 0); }
#else #else
uint64_t softfloat_shortShiftRightJam64(uint64_t a, uint_fast8_t dist); uint64_t softfloat_shortShiftRightJam64(uint64_t a, uint_fast8_t dist);
#endif #endif
@ -68,10 +67,8 @@ uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist );
| is zero or nonzero. | is zero or nonzero.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist ) INLINE uint32_t softfloat_shiftRightJam32(uint32_t a, uint_fast16_t dist) {
{ return (dist < 31) ? a >> dist | ((uint32_t)(a << (-dist & 31)) != 0) : (a != 0);
return
(dist < 31) ? a>>dist | ((uint32_t) (a<<(-dist & 31)) != 0) : (a != 0);
} }
#else #else
uint32_t softfloat_shiftRightJam32(uint32_t a, uint_fast16_t dist); uint32_t softfloat_shiftRightJam32(uint32_t a, uint_fast16_t dist);
@ -89,10 +86,8 @@ uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist );
| is zero or nonzero. | is zero or nonzero.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) #if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
INLINE uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist ) INLINE uint64_t softfloat_shiftRightJam64(uint64_t a, uint_fast32_t dist) {
{ return (dist < 63) ? a >> dist | ((uint64_t)(a << (-dist & 63)) != 0) : (a != 0);
return
(dist < 63) ? a>>dist | ((uint64_t) (a<<(-dist & 63)) != 0) : (a != 0);
} }
#else #else
uint64_t softfloat_shiftRightJam64(uint64_t a, uint_fast32_t dist); uint64_t softfloat_shiftRightJam64(uint64_t a, uint_fast32_t dist);
@ -112,8 +107,7 @@ extern const uint_least8_t softfloat_countLeadingZeros8[256];
| 'a'. If 'a' is zero, 16 is returned. | 'a'. If 'a' is zero, 16 is returned.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE uint_fast8_t softfloat_countLeadingZeros16( uint16_t a ) INLINE uint_fast8_t softfloat_countLeadingZeros16(uint16_t a) {
{
uint_fast8_t count = 8; uint_fast8_t count = 8;
if(0x100 <= a) { if(0x100 <= a) {
count = 0; count = 0;
@ -133,8 +127,7 @@ uint_fast8_t softfloat_countLeadingZeros16( uint16_t a );
| 'a'. If 'a' is zero, 32 is returned. | 'a'. If 'a' is zero, 32 is returned.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) #if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
INLINE uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ) INLINE uint_fast8_t softfloat_countLeadingZeros32(uint32_t a) {
{
uint_fast8_t count = 0; uint_fast8_t count = 0;
if(a < 0x10000) { if(a < 0x10000) {
count = 16; count = 16;
@ -222,8 +215,7 @@ uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a );
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (1 <= INLINE_LEVEL) #if defined INLINE_LEVEL && (1 <= INLINE_LEVEL)
INLINE INLINE
bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) bool softfloat_eq128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) { return (a64 == b64) && (a0 == b0); }
{ return (a64 == b64) && (a0 == b0); }
#else #else
bool softfloat_eq128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0); bool softfloat_eq128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0);
#endif #endif
@ -237,8 +229,7 @@ bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE INLINE
bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) bool softfloat_le128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) { return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); }
{ return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); }
#else #else
bool softfloat_le128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0); bool softfloat_le128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0);
#endif #endif
@ -252,8 +243,7 @@ bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE INLINE
bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) bool softfloat_lt128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) { return (a64 < b64) || ((a64 == b64) && (a0 < b0)); }
{ return (a64 < b64) || ((a64 == b64) && (a0 < b0)); }
#else #else
bool softfloat_lt128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0); bool softfloat_lt128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0);
#endif #endif
@ -266,17 +256,14 @@ bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE INLINE
struct uint128 struct uint128 softfloat_shortShiftLeft128(uint64_t a64, uint64_t a0, uint_fast8_t dist) {
softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist )
{
struct uint128 z; struct uint128 z;
z.v64 = a64 << dist | a0 >> (-dist & 63); z.v64 = a64 << dist | a0 >> (-dist & 63);
z.v0 = a0 << dist; z.v0 = a0 << dist;
return z; return z;
} }
#else #else
struct uint128 struct uint128 softfloat_shortShiftLeft128(uint64_t a64, uint64_t a0, uint_fast8_t dist);
softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist );
#endif #endif
#endif #endif
@ -287,17 +274,14 @@ struct uint128
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE INLINE
struct uint128 struct uint128 softfloat_shortShiftRight128(uint64_t a64, uint64_t a0, uint_fast8_t dist) {
softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist )
{
struct uint128 z; struct uint128 z;
z.v64 = a64 >> dist; z.v64 = a64 >> dist;
z.v0 = a64 << (-dist & 63) | a0 >> dist; z.v0 = a64 << (-dist & 63) | a0 >> dist;
return z; return z;
} }
#else #else
struct uint128 struct uint128 softfloat_shortShiftRight128(uint64_t a64, uint64_t a0, uint_fast8_t dist);
softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist );
#endif #endif
#endif #endif
@ -308,19 +292,14 @@ struct uint128
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE INLINE
struct uint64_extra struct uint64_extra softfloat_shortShiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast8_t dist) {
softfloat_shortShiftRightJam64Extra(
uint64_t a, uint64_t extra, uint_fast8_t dist )
{
struct uint64_extra z; struct uint64_extra z;
z.v = a >> dist; z.v = a >> dist;
z.extra = a << (-dist & 63) | (extra != 0); z.extra = a << (-dist & 63) | (extra != 0);
return z; return z;
} }
#else #else
struct uint64_extra struct uint64_extra softfloat_shortShiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast8_t dist);
softfloat_shortShiftRightJam64Extra(
uint64_t a, uint64_t extra, uint_fast8_t dist );
#endif #endif
#endif #endif
@ -334,22 +313,15 @@ struct uint64_extra
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) #if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
INLINE INLINE
struct uint128 struct uint128 softfloat_shortShiftRightJam128(uint64_t a64, uint64_t a0, uint_fast8_t dist) {
softfloat_shortShiftRightJam128(
uint64_t a64, uint64_t a0, uint_fast8_t dist )
{
uint_fast8_t negDist = -dist; uint_fast8_t negDist = -dist;
struct uint128 z; struct uint128 z;
z.v64 = a64 >> dist; z.v64 = a64 >> dist;
z.v0 = z.v0 = a64 << (negDist & 63) | a0 >> dist | ((uint64_t)(a0 << (negDist & 63)) != 0);
a64<<(negDist & 63) | a0>>dist
| ((uint64_t) (a0<<(negDist & 63)) != 0);
return z; return z;
} }
#else #else
struct uint128 struct uint128 softfloat_shortShiftRightJam128(uint64_t a64, uint64_t a0, uint_fast8_t dist);
softfloat_shortShiftRightJam128(
uint64_t a64, uint64_t a0, uint_fast8_t dist );
#endif #endif
#endif #endif
@ -360,10 +332,7 @@ struct uint128
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) #if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
INLINE INLINE
struct uint128_extra struct uint128_extra softfloat_shortShiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist) {
softfloat_shortShiftRightJam128Extra(
uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist )
{
uint_fast8_t negDist = -dist; uint_fast8_t negDist = -dist;
struct uint128_extra z; struct uint128_extra z;
z.v.v64 = a64 >> dist; z.v.v64 = a64 >> dist;
@ -372,9 +341,7 @@ struct uint128_extra
return z; return z;
} }
#else #else
struct uint128_extra struct uint128_extra softfloat_shortShiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist);
softfloat_shortShiftRightJam128Extra(
uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist );
#endif #endif
#endif #endif
@ -397,10 +364,7 @@ struct uint128_extra
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (4 <= INLINE_LEVEL) #if defined INLINE_LEVEL && (4 <= INLINE_LEVEL)
INLINE INLINE
struct uint64_extra struct uint64_extra softfloat_shiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast32_t dist) {
softfloat_shiftRightJam64Extra(
uint64_t a, uint64_t extra, uint_fast32_t dist )
{
struct uint64_extra z; struct uint64_extra z;
if(dist < 64) { if(dist < 64) {
z.v = a >> dist; z.v = a >> dist;
@ -413,9 +377,7 @@ struct uint64_extra
return z; return z;
} }
#else #else
struct uint64_extra struct uint64_extra softfloat_shiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast32_t dist);
softfloat_shiftRightJam64Extra(
uint64_t a, uint64_t extra, uint_fast32_t dist );
#endif #endif
#endif #endif
@ -430,8 +392,7 @@ struct uint64_extra
| greater than 128, the result will be either 0 or 1, depending on whether the | greater than 128, the result will be either 0 or 1, depending on whether the
| original 128 bits are all zeros. | original 128 bits are all zeros.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
struct uint128 struct uint128 softfloat_shiftRightJam128(uint64_t a64, uint64_t a0, uint_fast32_t dist);
softfloat_shiftRightJam128( uint64_t a64, uint64_t a0, uint_fast32_t dist );
#endif #endif
#ifndef softfloat_shiftRightJam128Extra #ifndef softfloat_shiftRightJam128Extra
@ -452,9 +413,7 @@ struct uint128
| is modified as described above and returned in the 'extra' field of the | is modified as described above and returned in the 'extra' field of the
| result.) | result.)
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
struct uint128_extra struct uint128_extra softfloat_shiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t dist);
softfloat_shiftRightJam128Extra(
uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t dist );
#endif #endif
#ifndef softfloat_shiftRightJam256M #ifndef softfloat_shiftRightJam256M
@ -470,9 +429,7 @@ struct uint128_extra
| is greater than 256, the stored result will be either 0 or 1, depending on | is greater than 256, the stored result will be either 0 or 1, depending on
| whether the original 256 bits are all zeros. | whether the original 256 bits are all zeros.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_shiftRightJam256M(const uint64_t* aPtr, uint_fast32_t dist, uint64_t* zPtr);
softfloat_shiftRightJam256M(
const uint64_t *aPtr, uint_fast32_t dist, uint64_t *zPtr );
#endif #endif
#ifndef softfloat_add128 #ifndef softfloat_add128
@ -483,17 +440,14 @@ void
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE INLINE
struct uint128 struct uint128 softfloat_add128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) {
softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
{
struct uint128 z; struct uint128 z;
z.v0 = a0 + b0; z.v0 = a0 + b0;
z.v64 = a64 + b64 + (z.v0 < a0); z.v64 = a64 + b64 + (z.v0 < a0);
return z; return z;
} }
#else #else
struct uint128 struct uint128 softfloat_add128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0);
softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
#endif #endif
#endif #endif
@ -505,9 +459,7 @@ struct uint128
| an array of four 64-bit elements that concatenate in the platform's normal | an array of four 64-bit elements that concatenate in the platform's normal
| endian order to form a 256-bit integer. | endian order to form a 256-bit integer.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_add256M(const uint64_t* aPtr, const uint64_t* bPtr, uint64_t* zPtr);
softfloat_add256M(
const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr );
#endif #endif
#ifndef softfloat_sub128 #ifndef softfloat_sub128
@ -518,9 +470,7 @@ void
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE INLINE
struct uint128 struct uint128 softfloat_sub128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) {
softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
{
struct uint128 z; struct uint128 z;
z.v0 = a0 - b0; z.v0 = a0 - b0;
z.v64 = a64 - b64; z.v64 = a64 - b64;
@ -528,8 +478,7 @@ struct uint128
return z; return z;
} }
#else #else
struct uint128 struct uint128 softfloat_sub128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0);
softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
#endif #endif
#endif #endif
@ -542,9 +491,7 @@ struct uint128
| 64-bit elements that concatenate in the platform's normal endian order to | 64-bit elements that concatenate in the platform's normal endian order to
| form a 256-bit integer. | form a 256-bit integer.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_sub256M(const uint64_t* aPtr, const uint64_t* bPtr, uint64_t* zPtr);
softfloat_sub256M(
const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr );
#endif #endif
#ifndef softfloat_mul64ByShifted32To128 #ifndef softfloat_mul64ByShifted32To128
@ -552,8 +499,7 @@ void
| Returns the 128-bit product of 'a', 'b', and 2^32. | Returns the 128-bit product of 'a', 'b', and 2^32.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) #if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
INLINE struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b ) INLINE struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b) {
{
uint_fast64_t mid; uint_fast64_t mid;
struct uint128 z; struct uint128 z;
mid = (uint_fast64_t)(uint32_t)a * b; mid = (uint_fast64_t)(uint32_t)a * b;
@ -581,8 +527,7 @@ struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b );
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (4 <= INLINE_LEVEL) #if defined INLINE_LEVEL && (4 <= INLINE_LEVEL)
INLINE INLINE
struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b ) struct uint128 softfloat_mul128By32(uint64_t a64, uint64_t a0, uint32_t b) {
{
struct uint128 z; struct uint128 z;
uint_fast64_t mid; uint_fast64_t mid;
uint_fast32_t carry; uint_fast32_t carry;
@ -605,9 +550,7 @@ struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b );
| Argument 'zPtr' points to an array of four 64-bit elements that concatenate | Argument 'zPtr' points to an array of four 64-bit elements that concatenate
| in the platform's normal endian order to form a 256-bit integer. | in the platform's normal endian order to form a 256-bit integer.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t* zPtr);
softfloat_mul128To256M(
uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr );
#endif #endif
#else #else
@ -638,8 +581,7 @@ int_fast8_t softfloat_compare96M( const uint32_t *aPtr, const uint32_t *bPtr );
| Each of 'aPtr' and 'bPtr' points to an array of four 32-bit elements that | Each of 'aPtr' and 'bPtr' points to an array of four 32-bit elements that
| concatenate in the platform's normal endian order to form a 128-bit integer. | concatenate in the platform's normal endian order to form a 128-bit integer.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
int_fast8_t int_fast8_t softfloat_compare128M(const uint32_t* aPtr, const uint32_t* bPtr);
softfloat_compare128M( const uint32_t *aPtr, const uint32_t *bPtr );
#endif #endif
#ifndef softfloat_shortShiftLeft64To96M #ifndef softfloat_shortShiftLeft64To96M
@ -652,19 +594,14 @@ int_fast8_t
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE INLINE
void void softfloat_shortShiftLeft64To96M(uint64_t a, uint_fast8_t dist, uint32_t* zPtr) {
softfloat_shortShiftLeft64To96M(
uint64_t a, uint_fast8_t dist, uint32_t *zPtr )
{
zPtr[indexWord(3, 0)] = (uint32_t)a << dist; zPtr[indexWord(3, 0)] = (uint32_t)a << dist;
a >>= 32 - dist; a >>= 32 - dist;
zPtr[indexWord(3, 2)] = a >> 32; zPtr[indexWord(3, 2)] = a >> 32;
zPtr[indexWord(3, 1)] = a; zPtr[indexWord(3, 1)] = a;
} }
#else #else
void void softfloat_shortShiftLeft64To96M(uint64_t a, uint_fast8_t dist, uint32_t* zPtr);
softfloat_shortShiftLeft64To96M(
uint64_t a, uint_fast8_t dist, uint32_t *zPtr );
#endif #endif
#endif #endif
@ -678,13 +615,7 @@ void
| that concatenate in the platform's normal endian order to form an N-bit | that concatenate in the platform's normal endian order to form an N-bit
| integer. | integer.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_shortShiftLeftM(uint_fast8_t size_words, const uint32_t* aPtr, uint_fast8_t dist, uint32_t* zPtr);
softfloat_shortShiftLeftM(
uint_fast8_t size_words,
const uint32_t *aPtr,
uint_fast8_t dist,
uint32_t *zPtr
);
#endif #endif
#ifndef softfloat_shortShiftLeft96M #ifndef softfloat_shortShiftLeft96M
@ -722,13 +653,7 @@ void
| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is | The value of 'dist' can be arbitrarily large. In particular, if 'dist' is
| greater than N, the stored result will be 0. | greater than N, the stored result will be 0.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_shiftLeftM(uint_fast8_t size_words, const uint32_t* aPtr, uint32_t dist, uint32_t* zPtr);
softfloat_shiftLeftM(
uint_fast8_t size_words,
const uint32_t *aPtr,
uint32_t dist,
uint32_t *zPtr
);
#endif #endif
#ifndef softfloat_shiftLeft96M #ifndef softfloat_shiftLeft96M
@ -765,13 +690,7 @@ void
| that concatenate in the platform's normal endian order to form an N-bit | that concatenate in the platform's normal endian order to form an N-bit
| integer. | integer.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_shortShiftRightM(uint_fast8_t size_words, const uint32_t* aPtr, uint_fast8_t dist, uint32_t* zPtr);
softfloat_shortShiftRightM(
uint_fast8_t size_words,
const uint32_t *aPtr,
uint_fast8_t dist,
uint32_t *zPtr
);
#endif #endif
#ifndef softfloat_shortShiftRight128M #ifndef softfloat_shortShiftRight128M
@ -801,9 +720,7 @@ void
| to a 'size_words'-long array of 32-bit elements that concatenate in the | to a 'size_words'-long array of 32-bit elements that concatenate in the
| platform's normal endian order to form an N-bit integer. | platform's normal endian order to form an N-bit integer.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_shortShiftRightJamM(uint_fast8_t, const uint32_t*, uint_fast8_t, uint32_t*);
softfloat_shortShiftRightJamM(
uint_fast8_t, const uint32_t *, uint_fast8_t, uint32_t * );
#endif #endif
#ifndef softfloat_shortShiftRightJam160M #ifndef softfloat_shortShiftRightJam160M
@ -825,13 +742,7 @@ void
| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is | The value of 'dist' can be arbitrarily large. In particular, if 'dist' is
| greater than N, the stored result will be 0. | greater than N, the stored result will be 0.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_shiftRightM(uint_fast8_t size_words, const uint32_t* aPtr, uint32_t dist, uint32_t* zPtr);
softfloat_shiftRightM(
uint_fast8_t size_words,
const uint32_t *aPtr,
uint32_t dist,
uint32_t *zPtr
);
#endif #endif
#ifndef softfloat_shiftRight96M #ifndef softfloat_shiftRight96M
@ -856,13 +767,7 @@ void
| is greater than N, the stored result will be either 0 or 1, depending on | is greater than N, the stored result will be either 0 or 1, depending on
| whether the original N bits are all zeros. | whether the original N bits are all zeros.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_shiftRightJamM(uint_fast8_t size_words, const uint32_t* aPtr, uint32_t dist, uint32_t* zPtr);
softfloat_shiftRightJamM(
uint_fast8_t size_words,
const uint32_t *aPtr,
uint32_t dist,
uint32_t *zPtr
);
#endif #endif
#ifndef softfloat_shiftRightJam96M #ifndef softfloat_shiftRightJam96M
@ -898,13 +803,7 @@ void
| elements that concatenate in the platform's normal endian order to form an | elements that concatenate in the platform's normal endian order to form an
| N-bit integer. | N-bit integer.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_addM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint32_t* zPtr);
softfloat_addM(
uint_fast8_t size_words,
const uint32_t *aPtr,
const uint32_t *bPtr,
uint32_t *zPtr
);
#endif #endif
#ifndef softfloat_add96M #ifndef softfloat_add96M
@ -940,14 +839,7 @@ void
| points to a 'size_words'-long array of 32-bit elements that concatenate in | points to a 'size_words'-long array of 32-bit elements that concatenate in
| the platform's normal endian order to form an N-bit integer. | the platform's normal endian order to form an N-bit integer.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
uint_fast8_t uint_fast8_t softfloat_addCarryM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint_fast8_t carry, uint32_t* zPtr);
softfloat_addCarryM(
uint_fast8_t size_words,
const uint32_t *aPtr,
const uint32_t *bPtr,
uint_fast8_t carry,
uint32_t *zPtr
);
#endif #endif
#ifndef softfloat_addComplCarryM #ifndef softfloat_addComplCarryM
@ -956,14 +848,8 @@ uint_fast8_t
| the value of the unsigned integer pointed to by 'bPtr' is bit-wise completed | the value of the unsigned integer pointed to by 'bPtr' is bit-wise completed
| before the addition. | before the addition.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
uint_fast8_t uint_fast8_t softfloat_addComplCarryM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint_fast8_t carry,
softfloat_addComplCarryM( uint32_t* zPtr);
uint_fast8_t size_words,
const uint32_t *aPtr,
const uint32_t *bPtr,
uint_fast8_t carry,
uint32_t *zPtr
);
#endif #endif
#ifndef softfloat_addComplCarry96M #ifndef softfloat_addComplCarry96M
@ -1052,13 +938,7 @@ void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr );
| array of 32-bit elements that concatenate in the platform's normal endian | array of 32-bit elements that concatenate in the platform's normal endian
| order to form an N-bit integer. | order to form an N-bit integer.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_subM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint32_t* zPtr);
softfloat_subM(
uint_fast8_t size_words,
const uint32_t *aPtr,
const uint32_t *bPtr,
uint32_t *zPtr
);
#endif #endif
#ifndef softfloat_sub96M #ifndef softfloat_sub96M
@ -1104,9 +984,7 @@ void softfloat_mul64To128M( uint64_t a, uint64_t b, uint32_t *zPtr );
| Argument 'zPtr' points to an array of eight 32-bit elements that concatenate | Argument 'zPtr' points to an array of eight 32-bit elements that concatenate
| to form a 256-bit integer. | to form a 256-bit integer.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_mul128MTo256M(const uint32_t* aPtr, const uint32_t* bPtr, uint32_t* zPtr);
softfloat_mul128MTo256M(
const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr );
#endif #endif
#ifndef softfloat_remStepMBy32 #ifndef softfloat_remStepMBy32
@ -1119,15 +997,8 @@ void
| to a 'size_words'-long array of 32-bit elements that concatenate in the | to a 'size_words'-long array of 32-bit elements that concatenate in the
| platform's normal endian order to form an N-bit integer. | platform's normal endian order to form an N-bit integer.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void softfloat_remStepMBy32(uint_fast8_t size_words, const uint32_t* remPtr, uint_fast8_t dist, const uint32_t* bPtr, uint32_t q,
softfloat_remStepMBy32( uint32_t* zPtr);
uint_fast8_t size_words,
const uint32_t *remPtr,
uint_fast8_t dist,
const uint32_t *bPtr,
uint32_t q,
uint32_t *zPtr
);
#endif #endif
#ifndef softfloat_remStep96MBy32 #ifndef softfloat_remStep96MBy32
@ -1157,4 +1028,3 @@ void
#endif #endif
#endif #endif

View File

@ -34,7 +34,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/ =============================================================================*/
/*============================================================================ /*============================================================================
| Note: If SoftFloat is made available as a general library for programs to | Note: If SoftFloat is made available as a general library for programs to
| use, it is strongly recommended that a platform-specific version of this | use, it is strongly recommended that a platform-specific version of this
@ -42,13 +41,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
| eliminates all dependencies on compile-time macros. | eliminates all dependencies on compile-time macros.
*============================================================================*/ *============================================================================*/
#ifndef softfloat_h #ifndef softfloat_h
#define softfloat_h 1 #define softfloat_h 1
#include "softfloat_types.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "softfloat_types.h"
#ifndef THREAD_LOCAL #ifndef THREAD_LOCAL
#define THREAD_LOCAL #define THREAD_LOCAL
@ -58,10 +56,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
| Software floating-point underflow tininess-detection mode. | Software floating-point underflow tininess-detection mode.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
extern THREAD_LOCAL uint_fast8_t softfloat_detectTininess; extern THREAD_LOCAL uint_fast8_t softfloat_detectTininess;
enum { enum { softfloat_tininess_beforeRounding = 0, softfloat_tininess_afterRounding = 1 };
softfloat_tininess_beforeRounding = 0,
softfloat_tininess_afterRounding = 1
};
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Software floating-point rounding mode. (Mode "odd" is supported only if | Software floating-point rounding mode. (Mode "odd" is supported only if
@ -288,9 +283,7 @@ float16_t extF80M_to_f16( const extFloat80_t * );
float32_t extF80M_to_f32(const extFloat80_t*); float32_t extF80M_to_f32(const extFloat80_t*);
float64_t extF80M_to_f64(const extFloat80_t*); float64_t extF80M_to_f64(const extFloat80_t*);
void extF80M_to_f128M(const extFloat80_t*, float128_t*); void extF80M_to_f128M(const extFloat80_t*, float128_t*);
void void extF80M_roundToInt(const extFloat80_t*, uint_fast8_t, bool, extFloat80_t*);
extF80M_roundToInt(
const extFloat80_t *, uint_fast8_t, bool, extFloat80_t * );
void extF80M_add(const extFloat80_t*, const extFloat80_t*, extFloat80_t*); void extF80M_add(const extFloat80_t*, const extFloat80_t*, extFloat80_t*);
void extF80M_sub(const extFloat80_t*, const extFloat80_t*, extFloat80_t*); void extF80M_sub(const extFloat80_t*, const extFloat80_t*, extFloat80_t*);
void extF80M_mul(const extFloat80_t*, const extFloat80_t*, extFloat80_t*); void extF80M_mul(const extFloat80_t*, const extFloat80_t*, extFloat80_t*);
@ -353,10 +346,7 @@ void f128M_roundToInt( const float128_t *, uint_fast8_t, bool, float128_t * );
void f128M_add(const float128_t*, const float128_t*, float128_t*); void f128M_add(const float128_t*, const float128_t*, float128_t*);
void f128M_sub(const float128_t*, const float128_t*, float128_t*); void f128M_sub(const float128_t*, const float128_t*, float128_t*);
void f128M_mul(const float128_t*, const float128_t*, float128_t*); void f128M_mul(const float128_t*, const float128_t*, float128_t*);
void void f128M_mulAdd(const float128_t*, const float128_t*, const float128_t*, float128_t*);
f128M_mulAdd(
const float128_t *, const float128_t *, const float128_t *, float128_t *
);
void f128M_div(const float128_t*, const float128_t*, float128_t*); void f128M_div(const float128_t*, const float128_t*, float128_t*);
void f128M_rem(const float128_t*, const float128_t*, float128_t*); void f128M_rem(const float128_t*, const float128_t*, float128_t*);
void f128M_sqrt(const float128_t*, float128_t*); void f128M_sqrt(const float128_t*, float128_t*);
@ -369,4 +359,3 @@ bool f128M_lt_quiet( const float128_t *, const float128_t * );
bool f128M_isSignalingNaN(const float128_t*); bool f128M_isSignalingNaN(const float128_t*);
#endif #endif

View File

@ -47,10 +47,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
| the types below may, if desired, be defined as aliases for the native types | the types below may, if desired, be defined as aliases for the native types
| (typically 'float' and 'double', and possibly 'long double'). | (typically 'float' and 'double', and possibly 'long double').
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
typedef struct { uint16_t v; } float16_t; typedef struct {
typedef struct { uint32_t v; } float32_t; uint16_t v;
typedef struct { uint64_t v; } float64_t; } float16_t;
typedef struct { uint64_t v[2]; } float128_t; typedef struct {
uint32_t v;
} float32_t;
typedef struct {
uint64_t v;
} float64_t;
typedef struct {
uint64_t v[2];
} float128_t;
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The format of an 80-bit extended floating-point number in memory. This | The format of an 80-bit extended floating-point number in memory. This
@ -58,9 +66,15 @@ typedef struct { uint64_t v[2]; } float128_t;
| named 'signif'. | named 'signif'.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#ifdef LITTLEENDIAN #ifdef LITTLEENDIAN
struct extFloat80M { uint64_t signif; uint16_t signExp; }; struct extFloat80M {
uint64_t signif;
uint16_t signExp;
};
#else #else
struct extFloat80M { uint16_t signExp; uint64_t signif; }; struct extFloat80M {
uint16_t signExp;
uint64_t signif;
};
#endif #endif
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
@ -78,4 +92,3 @@ struct extFloat80M { uint16_t signExp; uint64_t signif; };
typedef struct extFloat80M extFloat80_t; typedef struct extFloat80M extFloat80_t;
#endif #endif

View File

@ -54,9 +54,9 @@ protected:
iss::status write_custom_csr_reg(unsigned addr, reg_t val) override; iss::status write_custom_csr_reg(unsigned addr, reg_t val) override;
}; };
template <typename BASE> template <typename BASE>
inline hwl<BASE>::hwl(feature_config cfg): BASE(cfg) { inline hwl<BASE>::hwl(feature_config cfg)
: BASE(cfg) {
for(unsigned addr = 0x800; addr < 0x803; ++addr) { for(unsigned addr = 0x800; addr < 0x803; ++addr) {
this->register_custom_csr_rd(addr); this->register_custom_csr_rd(addr);
this->register_custom_csr_wr(addr); this->register_custom_csr_wr(addr);
@ -67,28 +67,50 @@ inline hwl<BASE>::hwl(feature_config cfg): BASE(cfg) {
} }
} }
template<typename BASE> template <typename BASE> inline iss::status iss::arch::hwl<BASE>::read_custom_csr_reg(unsigned addr, reg_t& val) {
inline iss::status iss::arch::hwl<BASE>::read_custom_csr_reg(unsigned addr, reg_t &val) {
switch(addr) { switch(addr) {
case 0x800: val = this->reg.lpstart0; break; case 0x800:
case 0x801: val = this->reg.lpend0; break; val = this->reg.lpstart0;
case 0x802: val = this->reg.lpcount0; break; break;
case 0x804: val = this->reg.lpstart1; break; case 0x801:
case 0x805: val = this->reg.lpend1; break; val = this->reg.lpend0;
case 0x806: val = this->reg.lpcount1; break; break;
case 0x802:
val = this->reg.lpcount0;
break;
case 0x804:
val = this->reg.lpstart1;
break;
case 0x805:
val = this->reg.lpend1;
break;
case 0x806:
val = this->reg.lpcount1;
break;
} }
return iss::Ok; return iss::Ok;
} }
template<typename BASE> template <typename BASE> inline iss::status iss::arch::hwl<BASE>::write_custom_csr_reg(unsigned addr, reg_t val) {
inline iss::status iss::arch::hwl<BASE>::write_custom_csr_reg(unsigned addr, reg_t val) {
switch(addr) { switch(addr) {
case 0x800: this->reg.lpstart0 = val; break; case 0x800:
case 0x801: this->reg.lpend0 = val; break; this->reg.lpstart0 = val;
case 0x802: this->reg.lpcount0 = val; break; break;
case 0x804: this->reg.lpstart1 = val; break; case 0x801:
case 0x805: this->reg.lpend1 = val; break; this->reg.lpend0 = val;
case 0x806: this->reg.lpcount1 = val; break; break;
case 0x802:
this->reg.lpcount0 = val;
break;
case 0x804:
this->reg.lpstart1 = val;
break;
case 0x805:
this->reg.lpend1 = val;
break;
case 0x806:
this->reg.lpcount1 = val;
break;
} }
return iss::Ok; return iss::Ok;
} }
@ -96,5 +118,4 @@ inline iss::status iss::arch::hwl<BASE>::write_custom_csr_reg(unsigned addr, reg
} // namespace arch } // namespace arch
} // namespace iss } // namespace iss
#endif /* _RISCV_HART_M_P_H */ #endif /* _RISCV_HART_M_P_H */

View File

@ -175,7 +175,6 @@ enum riscv_csr {
dscratch1 = 0x7B3 dscratch1 = 0x7B3
}; };
enum { enum {
PGSHIFT = 12, PGSHIFT = 12,
PTE_PPN_SHIFT = 10, PTE_PPN_SHIFT = 10,
@ -298,7 +297,7 @@ inline void write_reg_uint32(uint64_t offs, uint32_t& reg, const uint8_t *const
} }
} }
} } // namespace arch
} } // namespace iss
#endif #endif

View File

@ -35,22 +35,22 @@
#ifndef _RISCV_HART_M_P_H #ifndef _RISCV_HART_M_P_H
#define _RISCV_HART_M_P_H #define _RISCV_HART_M_P_H
#include "riscv_hart_common.h"
#include "iss/arch/traits.h" #include "iss/arch/traits.h"
#include "iss/instrumentation_if.h" #include "iss/instrumentation_if.h"
#include "iss/log_categories.h" #include "iss/log_categories.h"
#include "iss/vm_if.h" #include "iss/vm_if.h"
#include "riscv_hart_common.h"
#ifndef FMT_HEADER_ONLY #ifndef FMT_HEADER_ONLY
#define FMT_HEADER_ONLY #define FMT_HEADER_ONLY
#endif #endif
#include <array> #include <array>
#include <elfio/elfio.hpp> #include <elfio/elfio.hpp>
#include <fmt/format.h> #include <fmt/format.h>
#include <functional>
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include <type_traits> #include <type_traits>
#include <unordered_map> #include <unordered_map>
#include <functional>
#include <util/bit_field.h> #include <util/bit_field.h>
#include <util/ities.h> #include <util/ities.h>
#include <util/sparse_array.h> #include <util/sparse_array.h>
@ -86,10 +86,11 @@ protected:
"Load page fault", // d "Load page fault", // d
"Reserved", // e "Reserved", // e
"Store/AMO page fault"}}; "Store/AMO page fault"}};
const std::array<const char *, 12> irq_str = { const std::array<const char*, 12> irq_str = {{"User software interrupt", "Supervisor software interrupt", "Reserved",
{"User software interrupt", "Supervisor software interrupt", "Reserved", "Machine software interrupt", "Machine software interrupt", "User timer interrupt", "Supervisor timer interrupt",
"User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt", "Reserved", "Machine timer interrupt", "User external interrupt",
"User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; "Supervisor external interrupt", "Reserved", "Machine external interrupt"}};
public: public:
using core = BASE; using core = BASE;
using this_class = riscv_hart_m_p<BASE, FEAT>; using this_class = riscv_hart_m_p<BASE, FEAT>;
@ -108,7 +109,8 @@ public:
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint32_t>::value>::type> { template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint32_t>::value>::type> {
public: public:
BEGIN_BF_DECL(mstatus_t, T); BEGIN_BF_DECL(mstatus_t, T);
// SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11))) // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR
// XS==11)))
BF_FIELD(SD, 31, 1); BF_FIELD(SD, 31, 1);
// Trap SRET // Trap SRET
BF_FIELD(TSR, 22, 1); BF_FIELD(TSR, 22, 1);
@ -122,7 +124,8 @@ public:
BF_FIELD(SUM, 18, 1); BF_FIELD(SUM, 18, 1);
// Modify PRiVilege // Modify PRiVilege
BF_FIELD(MPRV, 17, 1); BF_FIELD(MPRV, 17, 1);
// status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None
// dirty, some clean/Some dirty
BF_FIELD(XS, 15, 2); BF_FIELD(XS, 15, 2);
// floating-point unit status Off/Initial/Clean/Dirty // floating-point unit status Off/Initial/Clean/Dirty
BF_FIELD(FS, 13, 2); BF_FIELD(FS, 13, 2);
@ -177,7 +180,8 @@ public:
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint64_t>::value>::type> { template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint64_t>::value>::type> {
public: public:
BEGIN_BF_DECL(mstatus_t, T); BEGIN_BF_DECL(mstatus_t, T);
// SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11))) // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR
// XS==11)))
BF_FIELD(SD, 63, 1); BF_FIELD(SD, 63, 1);
// value of XLEN for S-mode // value of XLEN for S-mode
BF_FIELD(SXL, 34, 2); BF_FIELD(SXL, 34, 2);
@ -195,7 +199,8 @@ public:
BF_FIELD(SUM, 18, 1); BF_FIELD(SUM, 18, 1);
// Modify PRiVilege // Modify PRiVilege
BF_FIELD(MPRV, 17, 1); BF_FIELD(MPRV, 17, 1);
// status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None
// dirty, some clean/Some dirty
BF_FIELD(XS, 15, 2); BF_FIELD(XS, 15, 2);
// floating-point unit status Off/Initial/Clean/Dirty // floating-point unit status Off/Initial/Clean/Dirty
BF_FIELD(FS, 13, 2); BF_FIELD(FS, 13, 2);
@ -252,12 +257,8 @@ public:
return 0b100010001000; // only machine mode is supported return 0b100010001000; // only machine mode is supported
} }
constexpr bool has_compressed() { constexpr bool has_compressed() { return traits<BASE>::MISA_VAL & 0b0100; }
return traits<BASE>::MISA_VAL&0b0100; constexpr reg_t get_pc_mask() { return has_compressed() ? (reg_t)~1 : (reg_t)~3; }
}
constexpr reg_t get_pc_mask() {
return has_compressed()?(reg_t)~1:(reg_t)~3;
}
riscv_hart_m_p(feature_config cfg = feature_config{}); riscv_hart_m_p(feature_config cfg = feature_config{});
virtual ~riscv_hart_m_p() = default; virtual ~riscv_hart_m_p() = default;
@ -266,10 +267,10 @@ public:
std::pair<uint64_t, bool> load_file(std::string name, int type = -1) override; std::pair<uint64_t, bool> load_file(std::string name, int type = -1) override;
iss::status read(const address_type type, const access_type access, const uint32_t space, iss::status read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length,
const uint64_t addr, const unsigned length, uint8_t *const data) override; uint8_t* const data) override;
iss::status write(const address_type type, const access_type access, const uint32_t space, iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length,
const uint64_t addr, const unsigned length, const uint8_t *const data) override; const uint8_t* const data) override;
uint64_t enter_trap(uint64_t flags) override { return riscv_hart_m_p::enter_trap(flags, fault_data, fault_data); } uint64_t enter_trap(uint64_t flags) override { return riscv_hart_m_p::enter_trap(flags, fault_data, fault_data); }
uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override;
@ -279,19 +280,16 @@ public:
void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; }; void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; };
void disass_output(uint64_t pc, const std::string instr) override { void disass_output(uint64_t pc, const std::string instr) override {
CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [s:0x{:x};c:{}]", CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [s:0x{:x};c:{}]", pc, instr, (reg_t)state.mstatus,
pc, instr, (reg_t)state.mstatus, this->reg.icount + cycle_offset); this->reg.icount + cycle_offset);
}; };
iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; } iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; }
void set_csr(unsigned addr, reg_t val){ void set_csr(unsigned addr, reg_t val) { csr[addr & csr.page_addr_mask] = val; }
csr[addr & csr.page_addr_mask] = val;
} void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
void set_irq_num(unsigned i) {
mcause_max_irq=1<<util::ilog2(i);
}
protected: protected:
struct riscv_instrumentation_if : public iss::instrumentation_if { struct riscv_instrumentation_if : public iss::instrumentation_if {
@ -405,12 +403,8 @@ protected:
virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; }; virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; };
virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; }; virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; };
void register_custom_csr_rd(unsigned addr){ void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr_reg; }
csr_rd_cb[addr] = &this_class::read_custom_csr_reg; void register_custom_csr_wr(unsigned addr) { csr_wr_cb[addr] = &this_class::write_custom_csr_reg; }
}
void register_custom_csr_wr(unsigned addr){
csr_wr_cb[addr] = &this_class::write_custom_csr_reg;
}
reg_t mhartid_reg{0x0}; reg_t mhartid_reg{0x0};
@ -423,8 +417,8 @@ protected:
feature_config cfg; feature_config cfg;
uint64_t mcause_max_irq{(FEAT & features_e::FEAT_CLIC) ? 4096 : 16}; uint64_t mcause_max_irq{(FEAT & features_e::FEAT_CLIC) ? 4096 : 16};
inline bool debug_mode_active() { return this->reg.PRIV & 0x4; } inline bool debug_mode_active() { return this->reg.PRIV & 0x4; }
std::pair<std::function<mem_read_f>, std::function<mem_write_f>> std::pair<std::function<mem_read_f>, std::function<mem_write_f>> replace_mem_access(std::function<mem_read_f> rd,
replace_mem_access(std::function<mem_read_f> rd, std::function<mem_write_f> wr){ std::function<mem_write_f> wr) {
std::pair<std::function<mem_read_f>, std::function<mem_write_f>> ret{hart_mem_rd_delegate, hart_mem_wr_delegate}; std::pair<std::function<mem_read_f>, std::function<mem_write_f>> ret{hart_mem_rd_delegate, hart_mem_wr_delegate};
hart_mem_rd_delegate = rd; hart_mem_rd_delegate = rd;
hart_mem_wr_delegate = wr; hart_mem_wr_delegate = wr;
@ -450,7 +444,8 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p(feature_config cfg)
csr_rd_cb[addr] = &this_class::read_null; csr_rd_cb[addr] = &this_class::read_null;
csr_wr_cb[addr] = &this_class::write_csr_reg; csr_wr_cb[addr] = &this_class::write_csr_reg;
} }
if(traits<BASE>::XLEN==32) for (unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr){ if(traits<BASE>::XLEN == 32)
for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) {
csr_rd_cb[addr] = &this_class::read_null; csr_rd_cb[addr] = &this_class::read_null;
csr_wr_cb[addr] = &this_class::write_csr_reg; csr_wr_cb[addr] = &this_class::write_csr_reg;
} }
@ -461,7 +456,8 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p(feature_config cfg)
for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) { for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) {
csr_rd_cb[addr] = &this_class::read_null; csr_rd_cb[addr] = &this_class::read_null;
} }
if(traits<BASE>::XLEN==32) for (unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr){ if(traits<BASE>::XLEN == 32)
for(unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr) {
csr_rd_cb[addr] = &this_class::read_null; csr_rd_cb[addr] = &this_class::read_null;
// csr_wr_cb[addr] = &this_class::write_csr_reg; // csr_wr_cb[addr] = &this_class::write_csr_reg;
} }
@ -478,20 +474,27 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p(feature_config cfg)
} }
// special handling & overrides // special handling & overrides
csr_rd_cb[time] = &this_class::read_time; csr_rd_cb[time] = &this_class::read_time;
if(traits<BASE>::XLEN==32) csr_rd_cb[timeh] = &this_class::read_time; if(traits<BASE>::XLEN == 32)
csr_rd_cb[timeh] = &this_class::read_time;
csr_rd_cb[cycle] = &this_class::read_cycle; csr_rd_cb[cycle] = &this_class::read_cycle;
if(traits<BASE>::XLEN==32) csr_rd_cb[cycleh] = &this_class::read_cycle; if(traits<BASE>::XLEN == 32)
csr_rd_cb[cycleh] = &this_class::read_cycle;
csr_rd_cb[instret] = &this_class::read_instret; csr_rd_cb[instret] = &this_class::read_instret;
if(traits<BASE>::XLEN==32) csr_rd_cb[instreth] = &this_class::read_instret; if(traits<BASE>::XLEN == 32)
csr_rd_cb[instreth] = &this_class::read_instret;
csr_rd_cb[mcycle] = &this_class::read_cycle; csr_rd_cb[mcycle] = &this_class::read_cycle;
csr_wr_cb[mcycle] = &this_class::write_cycle; csr_wr_cb[mcycle] = &this_class::write_cycle;
if(traits<BASE>::XLEN==32) csr_rd_cb[mcycleh] = &this_class::read_cycle; if(traits<BASE>::XLEN == 32)
if(traits<BASE>::XLEN==32) csr_wr_cb[mcycleh] = &this_class::write_cycle; csr_rd_cb[mcycleh] = &this_class::read_cycle;
if(traits<BASE>::XLEN == 32)
csr_wr_cb[mcycleh] = &this_class::write_cycle;
csr_rd_cb[minstret] = &this_class::read_instret; csr_rd_cb[minstret] = &this_class::read_instret;
csr_wr_cb[minstret] = &this_class::write_instret; csr_wr_cb[minstret] = &this_class::write_instret;
if(traits<BASE>::XLEN==32) csr_rd_cb[minstreth] = &this_class::read_instret; if(traits<BASE>::XLEN == 32)
if(traits<BASE>::XLEN==32) csr_wr_cb[minstreth] = &this_class::write_instret; csr_rd_cb[minstreth] = &this_class::read_instret;
if(traits<BASE>::XLEN == 32)
csr_wr_cb[minstreth] = &this_class::write_instret;
csr_rd_cb[mstatus] = &this_class::read_status; csr_rd_cb[mstatus] = &this_class::read_status;
csr_wr_cb[mstatus] = &this_class::write_status; csr_wr_cb[mstatus] = &this_class::write_status;
csr_rd_cb[mcause] = &this_class::read_cause; csr_rd_cb[mcause] = &this_class::read_cause;
@ -524,7 +527,8 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p(feature_config cfg)
clic_cfg_reg = 0x20; clic_cfg_reg = 0x20;
clic_mact_lvl = clic_mprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1; clic_mact_lvl = clic_mprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1;
csr[mintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1; csr[mintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1;
insert_mem_range(cfg.clic_base, 0x5000UL, insert_mem_range(
cfg.clic_base, 0x5000UL,
[this](phys_addr_t addr, unsigned length, uint8_t* const data) { return read_clic(addr.val, length, data); }, [this](phys_addr_t addr, unsigned length, uint8_t* const data) { return read_clic(addr.val, length, data); },
[this](phys_addr_t addr, unsigned length, uint8_t const* const data) { return write_clic(addr.val, length, data); }); [this](phys_addr_t addr, unsigned length, uint8_t const* const data) { return write_clic(addr.val, length, data); });
} }
@ -552,12 +556,8 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p(feature_config cfg)
csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr; csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr;
csr_rd_cb[dcsr] = &this_class::read_dcsr_reg; csr_rd_cb[dcsr] = &this_class::read_dcsr_reg;
} }
hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return this->read_mem(a, l, d); };
return this->read_mem(a, l, d); hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return this->write_mem(a, l, d); };
};
hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status {
return this->write_mem(a, l, d);
};
} }
template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m_p<BASE, FEAT>::load_file(std::string name, int type) { template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m_p<BASE, FEAT>::load_file(std::string name, int type) {
@ -566,35 +566,37 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
std::array<char, 5> buf; std::array<char, 5> buf;
auto n = fread(buf.data(), 1, 4, fp); auto n = fread(buf.data(), 1, 4, fp);
fclose(fp); fclose(fp);
if (n != 4) throw std::runtime_error("input file has insufficient size"); if(n != 4)
throw std::runtime_error("input file has insufficient size");
buf[4] = 0; buf[4] = 0;
if(strcmp(buf.data() + 1, "ELF") == 0) { if(strcmp(buf.data() + 1, "ELF") == 0) {
// Create elfio reader // Create elfio reader
ELFIO::elfio reader; ELFIO::elfio reader;
// Load ELF data // Load ELF data
if (!reader.load(name)) throw std::runtime_error("could not process elf file"); if(!reader.load(name))
throw std::runtime_error("could not process elf file");
// check elf properties // check elf properties
if(reader.get_class() != ELFCLASS32) if(reader.get_class() != ELFCLASS32)
if (sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file"); if(sizeof(reg_t) == 4)
if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file"); throw std::runtime_error("wrong elf class in file");
if (reader.get_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file"); if(reader.get_type() != ET_EXEC)
throw std::runtime_error("wrong elf type in file");
if(reader.get_machine() != EM_RISCV)
throw std::runtime_error("wrong elf machine in file");
auto entry = reader.get_entry(); auto entry = reader.get_entry();
for(const auto pseg : reader.segments) { for(const auto pseg : reader.segments) {
const auto fsize = pseg->get_file_size(); // 0x42c/0x0 const auto fsize = pseg->get_file_size(); // 0x42c/0x0
const auto seg_data = pseg->get_data(); const auto seg_data = pseg->get_data();
if(fsize > 0) { if(fsize > 0) {
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM,
traits<BASE>::MEM, pseg->get_physical_address(), pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data));
fsize, reinterpret_cast<const uint8_t *const>(seg_data));
if(res != iss::Ok) if(res != iss::Ok)
LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address();
<< pseg->get_physical_address();
} }
} }
for(const auto sec : reader.sections) { for(const auto sec : reader.sections) {
if(sec->get_name() == ".symtab") { if(sec->get_name() == ".symtab") {
if ( SHT_SYMTAB == sec->get_type() || if(SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type()) {
SHT_DYNSYM == sec->get_type() ) {
ELFIO::symbol_section_accessor symbols(reader, sec); ELFIO::symbol_section_accessor symbols(reader, sec);
auto sym_no = symbols.get_symbols_num(); auto sym_no = symbols.get_symbols_num();
std::string name; std::string name;
@ -617,7 +619,6 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
tohost = sec->get_address(); tohost = sec->get_address();
fromhost = tohost + 0x40; fromhost = tohost + 0x40;
} }
} }
return std::make_pair(entry, true); return std::make_pair(entry, true);
} }
@ -630,10 +631,9 @@ template<typename BASE, features_e FEAT>
inline void riscv_hart_m_p<BASE, FEAT>::insert_mem_range(uint64_t base, uint64_t size, std::function<mem_read_f> rd_f, inline void riscv_hart_m_p<BASE, FEAT>::insert_mem_range(uint64_t base, uint64_t size, std::function<mem_read_f> rd_f,
std::function<mem_write_f> wr_fn) { std::function<mem_write_f> wr_fn) {
std::tuple<uint64_t, uint64_t> entry{base, size}; std::tuple<uint64_t, uint64_t> entry{base, size};
auto it = std::upper_bound( memfn_range.begin(), memfn_range.end(), entry, auto it = std::upper_bound(
[](std::tuple<uint64_t, uint64_t> const& a, std::tuple<uint64_t, uint64_t> const& b){ memfn_range.begin(), memfn_range.end(), entry,
return std::get<0>(a)<std::get<0>(b); [](std::tuple<uint64_t, uint64_t> const& a, std::tuple<uint64_t, uint64_t> const& b) { return std::get<0>(a) < std::get<0>(b); });
});
auto idx = std::distance(memfn_range.begin(), it); auto idx = std::distance(memfn_range.begin(), it);
memfn_range.insert(it, entry); memfn_range.insert(it, entry);
memfn_read.insert(std::begin(memfn_read) + idx, rd_f); memfn_read.insert(std::begin(memfn_read) + idx, rd_f);
@ -641,8 +641,8 @@ inline void riscv_hart_m_p<BASE, FEAT>::insert_mem_range(uint64_t base, uint64_t
} }
template <typename BASE, features_e FEAT> template <typename BASE, features_e FEAT>
iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const access_type access, const uint32_t space, iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr,
const uint64_t addr, const unsigned length, uint8_t *const data) { const unsigned length, uint8_t* const data) {
#ifndef NDEBUG #ifndef NDEBUG
if(access && iss::access_type::DEBUG) { if(access && iss::access_type::DEBUG) {
LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr; LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr;
@ -658,7 +658,8 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce
auto alignment = is_fetch(access) ? (has_compressed() ? 2 : 4) : length; auto alignment = is_fetch(access) ? (has_compressed() ? 2 : 4) : length;
if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) { if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) {
fault_data = addr; fault_data = addr;
if (is_debug(access)) throw trap_access(0, addr); if(is_debug(access))
throw trap_access(0, addr);
this->reg.trap_state = (1UL << 31); // issue trap 0 this->reg.trap_state = (1UL << 31); // issue trap 0
return iss::Err; return iss::Err;
} }
@ -671,7 +672,8 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce
phys_addr_t phys_addr{access, space, addr}; phys_addr_t phys_addr{access, space, addr};
auto res = iss::Err; auto res = iss::Err;
if(access != access_type::FETCH && memfn_range.size()) { if(access != access_type::FETCH && memfn_range.size()) {
auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a){ auto it =
std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a) {
return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val; return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val;
}); });
if(it != std::end(memfn_range)) { if(it != std::end(memfn_range)) {
@ -694,11 +696,13 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce
} }
} break; } break;
case traits<BASE>::CSR: { case traits<BASE>::CSR: {
if (length != sizeof(reg_t)) return iss::Err; if(length != sizeof(reg_t))
return iss::Err;
return read_csr(addr, *reinterpret_cast<reg_t* const>(data)); return read_csr(addr, *reinterpret_cast<reg_t* const>(data));
} break; } break;
case traits<BASE>::FENCE: { case traits<BASE>::FENCE: {
if ((addr + length) > mem.size()) return iss::Err; if((addr + length) > mem.size())
return iss::Err;
return iss::Ok; return iss::Ok;
} break; } break;
case traits<BASE>::RES: { case traits<BASE>::RES: {
@ -721,26 +725,26 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce
} }
template <typename BASE, features_e FEAT> template <typename BASE, features_e FEAT>
iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const access_type access, const uint32_t space, iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr,
const uint64_t addr, const unsigned length, const uint8_t *const data) { const unsigned length, const uint8_t* const data) {
#ifndef NDEBUG #ifndef NDEBUG
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
switch(length) { switch(length) {
case 8: case 8:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x"
<< ") @addr 0x" << std::hex << addr; << std::hex << addr;
break; break;
case 4: case 4:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t *)&data[0] << std::dec LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x"
<< ") @addr 0x" << std::hex << addr; << std::hex << addr;
break; break;
case 2: case 2:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t *)&data[0] << std::dec LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x"
<< ") @addr 0x" << std::hex << addr; << std::hex << addr;
break; break;
case 1: case 1:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x"
<< ") @addr 0x" << std::hex << addr; << std::hex << addr;
break; break;
default: default:
LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr; LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr;
@ -751,7 +755,8 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
case traits<BASE>::MEM: { case traits<BASE>::MEM: {
if(unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { if(unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) {
fault_data = addr; fault_data = addr;
if (access && iss::access_type::DEBUG) throw trap_access(0, addr); if(access && iss::access_type::DEBUG)
throw trap_access(0, addr);
this->reg.trap_state = (1UL << 31); // issue trap 0 this->reg.trap_state = (1UL << 31); // issue trap 0
return iss::Err; return iss::Err;
} }
@ -764,7 +769,8 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
phys_addr_t phys_addr{access, space, addr}; phys_addr_t phys_addr{access, space, addr};
auto res = iss::Err; auto res = iss::Err;
if(access != access_type::FETCH && memfn_range.size()) { if(access != access_type::FETCH && memfn_range.size()) {
auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a){ auto it =
std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a) {
return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val; return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val;
}); });
if(it != std::end(memfn_range)) { if(it != std::end(memfn_range)) {
@ -786,7 +792,8 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
return iss::Err; return iss::Err;
} }
if ((addr + length) > mem.size()) return iss::Err; if((addr + length) > mem.size())
return iss::Err;
switch(addr) { switch(addr) {
case 0x10013000: // UART0 base, TXFIFO reg case 0x10013000: // UART0 base, TXFIFO reg
case 0x10023000: // UART1 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg
@ -803,7 +810,8 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
auto offs = addr & mem.page_addr_mask; auto offs = addr & mem.page_addr_mask;
std::copy(data, data + length, p.data() + offs); std::copy(data, data + length, p.data() + offs);
auto& x = *(p.data() + offs + 3); auto& x = *(p.data() + offs + 3);
if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1 if(x & 0x40)
x |= 0x80; // hfroscrdy = 1 if hfroscen==1
return iss::Ok; return iss::Ok;
} }
case 0x10008008: { // HFROSC base, pllcfg reg case 0x10008008: { // HFROSC base, pllcfg reg
@ -818,11 +826,13 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
} }
} break; } break;
case traits<BASE>::CSR: { case traits<BASE>::CSR: {
if (length != sizeof(reg_t)) return iss::Err; if(length != sizeof(reg_t))
return iss::Err;
return write_csr(addr, *reinterpret_cast<const reg_t*>(data)); return write_csr(addr, *reinterpret_cast<const reg_t*>(data));
} break; } break;
case traits<BASE>::FENCE: { case traits<BASE>::FENCE: {
if ((addr + length) > mem.size()) return iss::Err; if((addr + length) > mem.size())
return iss::Err;
switch(addr) { switch(addr) {
case 2: case 2:
case 3: { case 3: {
@ -847,7 +857,8 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
} }
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_csr(unsigned addr, reg_t& val) { template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_csr(unsigned addr, reg_t& val) {
if (addr >= csr.size()) return iss::Err; if(addr >= csr.size())
return iss::Err;
auto req_priv_lvl = (addr >> 8) & 0x3; auto req_priv_lvl = (addr >> 8) & 0x3;
if(this->reg.PRIV < req_priv_lvl) // not having required privileges if(this->reg.PRIV < req_priv_lvl) // not having required privileges
throw illegal_instruction_fault(this->fault_data); throw illegal_instruction_fault(this->fault_data);
@ -858,7 +869,8 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
} }
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_csr(unsigned addr, reg_t val) { template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_csr(unsigned addr, reg_t val) {
if (addr >= csr.size()) return iss::Err; if(addr >= csr.size())
return iss::Err;
auto req_priv_lvl = (addr >> 8) & 0x3; auto req_priv_lvl = (addr >> 8) & 0x3;
if(this->reg.PRIV < req_priv_lvl) // not having required privileges if(this->reg.PRIV < req_priv_lvl) // not having required privileges
throw illegal_instruction_fault(this->fault_data); throw illegal_instruction_fault(this->fault_data);
@ -937,7 +949,8 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
if(addr == time) { if(addr == time) {
val = static_cast<reg_t>(time_val); val = static_cast<reg_t>(time_val);
} else if(addr == timeh) { } else if(addr == timeh) {
if (sizeof(typename traits<BASE>::reg_t) != 4) return iss::Err; if(sizeof(typename traits<BASE>::reg_t) != 4)
return iss::Err;
val = static_cast<reg_t>(time_val >> 32); val = static_cast<reg_t>(time_val >> 32);
} }
return iss::Ok; return iss::Ok;
@ -1052,20 +1065,17 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
return iss::Ok; return iss::Ok;
} }
template<typename BASE, features_e FEAT> template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_intstatus(unsigned addr, reg_t& val) {
iss::status riscv_hart_m_p<BASE, FEAT>::read_intstatus(unsigned addr, reg_t& val) {
val = (clic_mact_lvl & 0xff) << 24; val = (clic_mact_lvl & 0xff) << 24;
return iss::Ok; return iss::Ok;
} }
template<typename BASE, features_e FEAT> template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_intthresh(unsigned addr, reg_t val) {
iss::status riscv_hart_m_p<BASE, FEAT>::write_intthresh(unsigned addr, reg_t val) {
csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1; csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1;
return iss::Ok; return iss::Ok;
} }
template<typename BASE, features_e FEAT> template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_xtvt(unsigned addr, reg_t val) {
iss::status riscv_hart_m_p<BASE, FEAT>::write_xtvt(unsigned addr, reg_t val) {
csr[addr] = val & ~0x3fULL; csr[addr] = val & ~0x3fULL;
return iss::Ok; return iss::Ok;
} }
@ -1097,10 +1107,9 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned le
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask)); std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
// tohost handling in case of riscv-test // tohost handling in case of riscv-test
if(paddr.access && iss::access_type::FUNC) { if(paddr.access && iss::access_type::FUNC) {
auto tohost_upper = (traits<BASE>::XLEN == 32 && paddr.val == (tohost + 4)) || auto tohost_upper =
(traits<BASE>::XLEN == 64 && paddr.val == tohost); (traits<BASE>::XLEN == 32 && paddr.val == (tohost + 4)) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
auto tohost_lower = auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
(traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
if(tohost_lower || tohost_upper) { if(tohost_lower || tohost_upper) {
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)); uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) {
@ -1133,8 +1142,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned le
} }
} else if(tohost_lower) } else if(tohost_lower)
to_host_wr_cnt++; to_host_wr_cnt++;
} else if ((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || } else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
(traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask)); uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
} }
@ -1148,15 +1156,18 @@ template<typename BASE, features_e FEAT>
iss::status riscv_hart_m_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned length, uint8_t* const data) { iss::status riscv_hart_m_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned length, uint8_t* const data) {
if(addr == cfg.clic_base) { // cliccfg if(addr == cfg.clic_base) { // cliccfg
*data = clic_cfg_reg; *data = clic_cfg_reg;
for(auto i=1; i<length; ++i) *(data+i)=0; for(auto i = 1; i < length; ++i)
*(data + i) = 0;
} else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig } else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig
auto offset = ((addr & 0x7fff) - 0x40) / 4; auto offset = ((addr & 0x7fff) - 0x40) / 4;
read_reg_uint32(addr, clic_inttrig_reg[offset], data, length); read_reg_uint32(addr, clic_inttrig_reg[offset], data, length);
} else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl } else if(addr >= (cfg.clic_base + 0x1000) &&
(addr + length) <= (cfg.clic_base + 0x1000 + cfg.clic_num_irq * 4)) { // clicintip/clicintie/clicintattr/clicintctl
auto offset = ((addr & 0x7fff) - 0x1000) / 4; auto offset = ((addr & 0x7fff) - 0x1000) / 4;
read_reg_uint32(addr, clic_int_reg[offset].raw, data, length); read_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
} else { } else {
for(auto i = 0U; i<length; ++i) *(data+i)=0; for(auto i = 0U; i < length; ++i)
*(data + i) = 0;
} }
return iss::Ok; return iss::Ok;
} }
@ -1168,7 +1179,8 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_clic(uint64_t addr, unsigned lengt
} else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig } else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig
auto offset = ((addr & 0x7fff) - 0x40) / 4; auto offset = ((addr & 0x7fff) - 0x40) / 4;
write_reg_uint32(addr, clic_inttrig_reg[offset], data, length); write_reg_uint32(addr, clic_inttrig_reg[offset], data, length);
} else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl } else if(addr >= (cfg.clic_base + 0x1000) &&
(addr + length) <= (cfg.clic_base + 0x1000 + cfg.clic_num_irq * 4)) { // clicintip/clicintie/clicintattr/clicintctl
auto offset = ((addr & 0x7fff) - 0x1000) / 4; auto offset = ((addr & 0x7fff) - 0x1000) / 4;
write_reg_uint32(addr, clic_int_reg[offset].raw, data, length); write_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
clic_int_reg[offset].raw &= 0xf0c70101; // clicIntCtlBits->0xf0, clicintattr->0xc7, clicintie->0x1, clicintip->0x1 clic_int_reg[offset].raw &= 0xf0c70101; // clicIntCtlBits->0xf0, clicintattr->0xc7, clicintie->0x1, clicintip->0x1
@ -1212,7 +1224,8 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::e
// calculate effective privilege level // calculate effective privilege level
unsigned new_priv = PRIV_M; unsigned new_priv = PRIV_M;
if(trap_id == 0) { // exception if(trap_id == 0) { // exception
if (cause == 11) cause = 0x8 + PRIV_M; // adjust environment call cause if(cause == 11)
cause = 0x8 + PRIV_M; // adjust environment call cause
// store ret addr in xepc register // store ret addr in xepc register
csr[mepc] = static_cast<reg_t>(addr) & get_pc_mask(); // store actual address instruction of exception csr[mepc] = static_cast<reg_t>(addr) & get_pc_mask(); // store actual address instruction of exception
/* /*
@ -1274,7 +1287,8 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::e
} else { } else {
// bits in mtvec // bits in mtvec
this->reg.NEXT_PC = xtvec & ~0x3UL; this->reg.NEXT_PC = xtvec & ~0x3UL;
if ((xtvec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; if((xtvec & 0x1) == 1 && trap_id != 0)
this->reg.NEXT_PC += 4 * cause;
} }
// reset trap state // reset trap state
this->reg.PRIV = new_priv; this->reg.PRIV = new_priv;
@ -1286,8 +1300,8 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::e
sprintf(buffer.data(), "0x%016lx", addr); sprintf(buffer.data(), "0x%016lx", addr);
#endif #endif
if((flags & 0xffffffff) != 0xffffffff) if((flags & 0xffffffff) != 0xffffffff)
CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause]) << "' ("
<< (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")" << cause << ")"
<< " at address " << buffer.data() << " occurred"; << " at address " << buffer.data() << " occurred";
return this->reg.NEXT_PC; return this->reg.NEXT_PC;
} }

View File

@ -35,22 +35,22 @@
#ifndef _RISCV_HART_MSU_VP_H #ifndef _RISCV_HART_MSU_VP_H
#define _RISCV_HART_MSU_VP_H #define _RISCV_HART_MSU_VP_H
#include "riscv_hart_common.h"
#include "iss/arch/traits.h" #include "iss/arch/traits.h"
#include "iss/instrumentation_if.h" #include "iss/instrumentation_if.h"
#include "iss/log_categories.h" #include "iss/log_categories.h"
#include "iss/vm_if.h" #include "iss/vm_if.h"
#include "riscv_hart_common.h"
#ifndef FMT_HEADER_ONLY #ifndef FMT_HEADER_ONLY
#define FMT_HEADER_ONLY #define FMT_HEADER_ONLY
#endif #endif
#include <array> #include <array>
#include <elfio/elfio.hpp> #include <elfio/elfio.hpp>
#include <fmt/format.h> #include <fmt/format.h>
#include <functional>
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include <type_traits> #include <type_traits>
#include <unordered_map> #include <unordered_map>
#include <functional>
#include <util/bit_field.h> #include <util/bit_field.h>
#include <util/ities.h> #include <util/ities.h>
#include <util/sparse_array.h> #include <util/sparse_array.h>
@ -86,10 +86,11 @@ protected:
"Load page fault", // d "Load page fault", // d
"Reserved", // e "Reserved", // e
"Store/AMO page fault"}}; "Store/AMO page fault"}};
const std::array<const char *, 12> irq_str = { const std::array<const char*, 12> irq_str = {{"User software interrupt", "Supervisor software interrupt", "Reserved",
{"User software interrupt", "Supervisor software interrupt", "Reserved", "Machine software interrupt", "Machine software interrupt", "User timer interrupt", "Supervisor timer interrupt",
"User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt", "Reserved", "Machine timer interrupt", "User external interrupt",
"User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; "Supervisor external interrupt", "Reserved", "Machine external interrupt"}};
public: public:
using core = BASE; using core = BASE;
using this_class = riscv_hart_msu_vp<BASE>; using this_class = riscv_hart_msu_vp<BASE>;
@ -107,7 +108,8 @@ public:
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint32_t>::value>::type> { template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint32_t>::value>::type> {
public: public:
BEGIN_BF_DECL(mstatus_t, T); BEGIN_BF_DECL(mstatus_t, T);
// SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11))) // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR
// XS==11)))
BF_FIELD(SD, 31, 1); BF_FIELD(SD, 31, 1);
// Trap SRET // Trap SRET
BF_FIELD(TSR, 22, 1); BF_FIELD(TSR, 22, 1);
@ -121,7 +123,8 @@ public:
BF_FIELD(SUM, 18, 1); BF_FIELD(SUM, 18, 1);
// Modify PRiVilege // Modify PRiVilege
BF_FIELD(MPRV, 17, 1); BF_FIELD(MPRV, 17, 1);
// status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None
// dirty, some clean/Some dirty
BF_FIELD(XS, 15, 2); BF_FIELD(XS, 15, 2);
// floating-point unit status Off/Initial/Clean/Dirty // floating-point unit status Off/Initial/Clean/Dirty
BF_FIELD(FS, 13, 2); BF_FIELD(FS, 13, 2);
@ -162,20 +165,27 @@ public:
return priv_lvl == PRIV_U ? 0x80000011UL : priv_lvl == PRIV_S ? 0x800de133UL : 0x807ff9ddUL; return priv_lvl == PRIV_U ? 0x80000011UL : priv_lvl == PRIV_S ? 0x800de133UL : 0x807ff9ddUL;
#else #else
switch(priv_lvl) { switch(priv_lvl) {
case PRIV_U: return 0x80000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001 case PRIV_U:
case PRIV_S: return 0x800de133UL; // 0b1000 0000 0000 1101 1110 0001 0011 0011 return 0x80000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001
default: return 0x807ff9ddUL; // 0b1000 0000 0111 1111 1111 1001 1011 1011 case PRIV_S:
return 0x800de133UL; // 0b1000 0000 0000 1101 1110 0001 0011 0011
default:
return 0x807ff9ddUL; // 0b1000 0000 0111 1111 1111 1001 1011 1011
} }
#endif #endif
} }
static inline vm_info decode_vm_info(uint32_t state, T sptbr) { static inline vm_info decode_vm_info(uint32_t state, T sptbr) {
if (state == PRIV_M) return {0, 0, 0, 0}; if(state == PRIV_M)
return {0, 0, 0, 0};
if(state <= PRIV_S) if(state <= PRIV_S)
switch(bit_sub<31, 1>(sptbr)) { switch(bit_sub<31, 1>(sptbr)) {
case 0: return {0, 0, 0, 0}; // off case 0:
case 1: return {2, 10, 4, bit_sub<0, 22>(sptbr) << PGSHIFT}; // SV32 return {0, 0, 0, 0}; // off
default: abort(); case 1:
return {2, 10, 4, bit_sub<0, 22>(sptbr) << PGSHIFT}; // SV32
default:
abort();
} }
abort(); abort();
return {0, 0, 0, 0}; // dummy return {0, 0, 0, 0}; // dummy
@ -185,7 +195,8 @@ public:
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint64_t>::value>::type> { template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint64_t>::value>::type> {
public: public:
BEGIN_BF_DECL(mstatus_t, T); BEGIN_BF_DECL(mstatus_t, T);
// SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11))) // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR
// XS==11)))
BF_FIELD(SD, 63, 1); BF_FIELD(SD, 63, 1);
// value of XLEN for S-mode // value of XLEN for S-mode
BF_FIELD(SXL, 34, 2); BF_FIELD(SXL, 34, 2);
@ -203,7 +214,8 @@ public:
BF_FIELD(SUM, 18, 1); BF_FIELD(SUM, 18, 1);
// Modify PRiVilege // Modify PRiVilege
BF_FIELD(MPRV, 17, 1); BF_FIELD(MPRV, 17, 1);
// status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None
// dirty, some clean/Some dirty
BF_FIELD(XS, 15, 2); BF_FIELD(XS, 15, 2);
// floating-point unit status Off/Initial/Clean/Dirty // floating-point unit status Off/Initial/Clean/Dirty
BF_FIELD(FS, 13, 2); BF_FIELD(FS, 13, 2);
@ -249,23 +261,36 @@ public:
static constexpr T get_mask(unsigned priv_lvl) { static constexpr T get_mask(unsigned priv_lvl) {
uint64_t ret; uint64_t ret;
switch(priv_lvl) { switch(priv_lvl) {
case PRIV_U: ret = 0x8000000f00000011ULL;break; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 case PRIV_U:
case PRIV_S: ret = 0x8000000f000de133ULL;break; // 0b1...0 0011 0000 0000 0000 1101 1110 0001 0011 0011 ret = 0x8000000f00000011ULL;
default: ret = 0x8000000f007ff9ddULL;break; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 break; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011
case PRIV_S:
ret = 0x8000000f000de133ULL;
break; // 0b1...0 0011 0000 0000 0000 1101 1110 0001 0011 0011
default:
ret = 0x8000000f007ff9ddULL;
break; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011
} }
return ret; return ret;
} }
static inline vm_info decode_vm_info(uint32_t state, T sptbr) { static inline vm_info decode_vm_info(uint32_t state, T sptbr) {
if (state == PRIV_M) return {0, 0, 0, 0}; if(state == PRIV_M)
return {0, 0, 0, 0};
if(state <= PRIV_S) if(state <= PRIV_S)
switch(bit_sub<60, 4>(sptbr)) { switch(bit_sub<60, 4>(sptbr)) {
case 0: return {0, 0, 0, 0}; // off case 0:
case 8: return {3, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV39 return {0, 0, 0, 0}; // off
case 9: return {4, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV48 case 8:
case 10: return {5, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV57 return {3, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV39
case 11: return {6, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV64 case 9:
default: abort(); return {4, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV48
case 10:
return {5, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV57
case 11:
return {6, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV64
default:
abort();
} }
abort(); abort();
return {0, 0, 0, 0}; // dummy return {0, 0, 0, 0}; // dummy
@ -295,10 +320,10 @@ public:
phys_addr_t virt2phys(const iss::addr_t& addr) override; phys_addr_t virt2phys(const iss::addr_t& addr) override;
iss::status read(const address_type type, const access_type access, const uint32_t space, iss::status read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length,
const uint64_t addr, const unsigned length, uint8_t *const data) override; uint8_t* const data) override;
iss::status write(const address_type type, const access_type access, const uint32_t space, iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length,
const uint64_t addr, const unsigned length, const uint8_t *const data) override; const uint8_t* const data) override;
uint64_t enter_trap(uint64_t flags) override { return riscv_hart_msu_vp::enter_trap(flags, fault_data, fault_data); } uint64_t enter_trap(uint64_t flags) override { return riscv_hart_msu_vp::enter_trap(flags, fault_data, fault_data); }
uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override;
@ -306,19 +331,16 @@ public:
void wait_until(uint64_t flags) override; void wait_until(uint64_t flags) override;
void disass_output(uint64_t pc, const std::string instr) override { void disass_output(uint64_t pc, const std::string instr) override {
CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus,
pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount + cycle_offset); this->reg.icount + cycle_offset);
}; };
iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; } iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; }
void set_csr(unsigned addr, reg_t val){ void set_csr(unsigned addr, reg_t val) { csr[addr & csr.page_addr_mask] = val; }
csr[addr & csr.page_addr_mask] = val;
} void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
void set_irq_num(unsigned i) {
mcause_max_irq=1<<util::ilog2(i);
}
protected: protected:
struct riscv_instrumentation_if : public iss::instrumentation_if { struct riscv_instrumentation_if : public iss::instrumentation_if {
@ -416,12 +438,8 @@ protected:
virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; }; virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; };
virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; }; virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; };
void register_custom_csr_rd(unsigned addr){ void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr_reg; }
csr_rd_cb[addr] = &this_class::read_custom_csr_reg; void register_custom_csr_wr(unsigned addr) { csr_wr_cb[addr] = &this_class::write_custom_csr_reg; }
}
void register_custom_csr_wr(unsigned addr){
csr_wr_cb[addr] = &this_class::write_custom_csr_reg;
}
reg_t mhartid_reg{0x0}; reg_t mhartid_reg{0x0};
@ -460,32 +478,36 @@ riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp()
// csr_wr_cb[addr] = &this_class::write_csr_reg; // csr_wr_cb[addr] = &this_class::write_csr_reg;
} }
// common regs // common regs
const std::array<unsigned, 22> addrs{{ const std::array<unsigned, 22> addrs{{misa, mvendorid, marchid, mimpid, mepc, mtvec, mscratch, mcause,
misa, mvendorid, marchid, mimpid, mtval, mscratch, sepc, stvec, sscratch, scause, stval, sscratch,
mepc, mtvec, mscratch, mcause, mtval, mscratch, uepc, utvec, uscratch, ucause, utval, uscratch}};
sepc, stvec, sscratch, scause, stval, sscratch,
uepc, utvec, uscratch, ucause, utval, uscratch
}};
for(auto addr : addrs) { for(auto addr : addrs) {
csr_rd_cb[addr] = &this_class::read_csr_reg; csr_rd_cb[addr] = &this_class::read_csr_reg;
csr_wr_cb[addr] = &this_class::write_csr_reg; csr_wr_cb[addr] = &this_class::write_csr_reg;
} }
// special handling & overrides // special handling & overrides
csr_rd_cb[time] = &this_class::read_time; csr_rd_cb[time] = &this_class::read_time;
if(traits<BASE>::XLEN==32) csr_rd_cb[timeh] = &this_class::read_time; if(traits<BASE>::XLEN == 32)
csr_rd_cb[timeh] = &this_class::read_time;
csr_rd_cb[cycle] = &this_class::read_cycle; csr_rd_cb[cycle] = &this_class::read_cycle;
if(traits<BASE>::XLEN==32) csr_rd_cb[cycleh] = &this_class::read_cycle; if(traits<BASE>::XLEN == 32)
csr_rd_cb[cycleh] = &this_class::read_cycle;
csr_rd_cb[instret] = &this_class::read_instret; csr_rd_cb[instret] = &this_class::read_instret;
if(traits<BASE>::XLEN==32) csr_rd_cb[instreth] = &this_class::read_instret; if(traits<BASE>::XLEN == 32)
csr_rd_cb[instreth] = &this_class::read_instret;
csr_rd_cb[mcycle] = &this_class::read_cycle; csr_rd_cb[mcycle] = &this_class::read_cycle;
csr_wr_cb[mcycle] = &this_class::write_cycle; csr_wr_cb[mcycle] = &this_class::write_cycle;
if(traits<BASE>::XLEN==32) csr_rd_cb[mcycleh] = &this_class::read_cycle; if(traits<BASE>::XLEN == 32)
if(traits<BASE>::XLEN==32) csr_wr_cb[mcycleh] = &this_class::write_cycle; csr_rd_cb[mcycleh] = &this_class::read_cycle;
if(traits<BASE>::XLEN == 32)
csr_wr_cb[mcycleh] = &this_class::write_cycle;
csr_rd_cb[minstret] = &this_class::read_instret; csr_rd_cb[minstret] = &this_class::read_instret;
csr_wr_cb[minstret] = &this_class::write_instret; csr_wr_cb[minstret] = &this_class::write_instret;
if(traits<BASE>::XLEN==32) csr_rd_cb[minstreth] = &this_class::read_instret; if(traits<BASE>::XLEN == 32)
if(traits<BASE>::XLEN==32) csr_wr_cb[minstreth] = &this_class::write_instret; csr_rd_cb[minstreth] = &this_class::read_instret;
if(traits<BASE>::XLEN == 32)
csr_wr_cb[minstreth] = &this_class::write_instret;
csr_rd_cb[mstatus] = &this_class::read_status; csr_rd_cb[mstatus] = &this_class::read_status;
csr_wr_cb[mstatus] = &this_class::write_status; csr_wr_cb[mstatus] = &this_class::write_status;
csr_wr_cb[mcause] = &this_class::write_cause; csr_wr_cb[mcause] = &this_class::write_cause;
@ -536,35 +558,37 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load
std::array<char, 5> buf; std::array<char, 5> buf;
auto n = fread(buf.data(), 1, 4, fp); auto n = fread(buf.data(), 1, 4, fp);
fclose(fp); fclose(fp);
if (n != 4) throw std::runtime_error("input file has insufficient size"); if(n != 4)
throw std::runtime_error("input file has insufficient size");
buf[4] = 0; buf[4] = 0;
if(strcmp(buf.data() + 1, "ELF") == 0) { if(strcmp(buf.data() + 1, "ELF") == 0) {
// Create elfio reader // Create elfio reader
ELFIO::elfio reader; ELFIO::elfio reader;
// Load ELF data // Load ELF data
if (!reader.load(name)) throw std::runtime_error("could not process elf file"); if(!reader.load(name))
throw std::runtime_error("could not process elf file");
// check elf properties // check elf properties
if(reader.get_class() != ELFCLASS32) if(reader.get_class() != ELFCLASS32)
if (sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file"); if(sizeof(reg_t) == 4)
if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file"); throw std::runtime_error("wrong elf class in file");
if (reader.get_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file"); if(reader.get_type() != ET_EXEC)
throw std::runtime_error("wrong elf type in file");
if(reader.get_machine() != EM_RISCV)
throw std::runtime_error("wrong elf machine in file");
auto entry = reader.get_entry(); auto entry = reader.get_entry();
for(const auto pseg : reader.segments) { for(const auto pseg : reader.segments) {
const auto fsize = pseg->get_file_size(); // 0x42c/0x0 const auto fsize = pseg->get_file_size(); // 0x42c/0x0
const auto seg_data = pseg->get_data(); const auto seg_data = pseg->get_data();
if(fsize > 0) { if(fsize > 0) {
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM,
traits<BASE>::MEM, pseg->get_physical_address(), pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data));
fsize, reinterpret_cast<const uint8_t *const>(seg_data));
if(res != iss::Ok) if(res != iss::Ok)
LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address();
<< pseg->get_physical_address();
} }
} }
for(const auto sec : reader.sections) { for(const auto sec : reader.sections) {
if(sec->get_name() == ".symtab") { if(sec->get_name() == ".symtab") {
if ( SHT_SYMTAB == sec->get_type() || if(SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type()) {
SHT_DYNSYM == sec->get_type() ) {
ELFIO::symbol_section_accessor symbols(reader, sec); ELFIO::symbol_section_accessor symbols(reader, sec);
auto sym_no = symbols.get_symbols_num(); auto sym_no = symbols.get_symbols_num();
std::string name; std::string name;
@ -587,7 +611,6 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load
tohost = sec->get_address(); tohost = sec->get_address();
fromhost = tohost + 0x40; fromhost = tohost + 0x40;
} }
} }
return std::make_pair(entry, true); return std::make_pair(entry, true);
} }
@ -597,8 +620,8 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load
} }
template <typename BASE> template <typename BASE>
iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_type access, const uint32_t space, iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr,
const uint64_t addr, const unsigned length, uint8_t *const data) { const unsigned length, uint8_t* const data) {
#ifndef NDEBUG #ifndef NDEBUG
if(access && iss::access_type::DEBUG) { if(access && iss::access_type::DEBUG) {
LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr; LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr;
@ -614,7 +637,8 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
auto alignment = is_fetch(access) ? (traits<BASE>::MISA_VAL & 0x100 ? 2 : 4) : length; auto alignment = is_fetch(access) ? (traits<BASE>::MISA_VAL & 0x100 ? 2 : 4) : length;
if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) { if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) {
fault_data = addr; fault_data = addr;
if (access && iss::access_type::DEBUG) throw trap_access(0, addr); if(access && iss::access_type::DEBUG)
throw trap_access(0, addr);
this->reg.trap_state = (1 << 31); // issue trap 0 this->reg.trap_state = (1 << 31); // issue trap 0
return iss::Err; return iss::Err;
} }
@ -648,11 +672,13 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
} }
} break; } break;
case traits<BASE>::CSR: { case traits<BASE>::CSR: {
if (length != sizeof(reg_t)) return iss::Err; if(length != sizeof(reg_t))
return iss::Err;
return read_csr(addr, *reinterpret_cast<reg_t* const>(data)); return read_csr(addr, *reinterpret_cast<reg_t* const>(data));
} break; } break;
case traits<BASE>::FENCE: { case traits<BASE>::FENCE: {
if ((addr + length) > mem.size()) return iss::Err; if((addr + length) > mem.size())
return iss::Err;
switch(addr) { switch(addr) {
case 2: // SFENCE:VMA lower case 2: // SFENCE:VMA lower
case 3: { // SFENCE:VMA upper case 3: { // SFENCE:VMA upper
@ -686,26 +712,26 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
} }
template <typename BASE> template <typename BASE>
iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access_type access, const uint32_t space, iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr,
const uint64_t addr, const unsigned length, const uint8_t *const data) { const unsigned length, const uint8_t* const data) {
#ifndef NDEBUG #ifndef NDEBUG
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
switch(length) { switch(length) {
case 8: case 8:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x"
<< ") @addr 0x" << std::hex << addr; << std::hex << addr;
break; break;
case 4: case 4:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t *)&data[0] << std::dec LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x"
<< ") @addr 0x" << std::hex << addr; << std::hex << addr;
break; break;
case 2: case 2:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t *)&data[0] << std::dec LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x"
<< ") @addr 0x" << std::hex << addr; << std::hex << addr;
break; break;
case 1: case 1:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x"
<< ") @addr 0x" << std::hex << addr; << std::hex << addr;
break; break;
default: default:
LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr; LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr;
@ -716,7 +742,8 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
case traits<BASE>::MEM: { case traits<BASE>::MEM: {
if(unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { if(unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) {
fault_data = addr; fault_data = addr;
if (access && iss::access_type::DEBUG) throw trap_access(0, addr); if(access && iss::access_type::DEBUG)
throw trap_access(0, addr);
this->reg.trap_state = (1 << 31); // issue trap 0 this->reg.trap_state = (1 << 31); // issue trap 0
return iss::Err; return iss::Err;
} }
@ -745,7 +772,8 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
return iss::Err; return iss::Err;
} }
if ((paddr.val + length) > mem.size()) return iss::Err; if((paddr.val + length) > mem.size())
return iss::Err;
switch(paddr.val) { switch(paddr.val) {
case 0x10013000: // UART0 base, TXFIFO reg case 0x10013000: // UART0 base, TXFIFO reg
case 0x10023000: // UART1 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg
@ -762,7 +790,8 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
auto offs = paddr.val & mem.page_addr_mask; auto offs = paddr.val & mem.page_addr_mask;
std::copy(data, data + length, p.data() + offs); std::copy(data, data + length, p.data() + offs);
auto& x = *(p.data() + offs + 3); auto& x = *(p.data() + offs + 3);
if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1 if(x & 0x40)
x |= 0x80; // hfroscrdy = 1 if hfroscen==1
return iss::Ok; return iss::Ok;
} }
case 0x10008008: { // HFROSC base, pllcfg reg case 0x10008008: { // HFROSC base, pllcfg reg
@ -777,11 +806,13 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
} }
} break; } break;
case traits<BASE>::CSR: { case traits<BASE>::CSR: {
if (length != sizeof(reg_t)) return iss::Err; if(length != sizeof(reg_t))
return iss::Err;
return write_csr(addr, *reinterpret_cast<const reg_t*>(data)); return write_csr(addr, *reinterpret_cast<const reg_t*>(data));
} break; } break;
case traits<BASE>::FENCE: { case traits<BASE>::FENCE: {
if ((addr + length) > mem.size()) return iss::Err; if((addr + length) > mem.size())
return iss::Err;
switch(addr) { switch(addr) {
case 2: case 2:
case 3: { case 3: {
@ -811,7 +842,8 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
} }
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_csr(unsigned addr, reg_t& val) { template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_csr(unsigned addr, reg_t& val) {
if (addr >= csr.size()) return iss::Err; if(addr >= csr.size())
return iss::Err;
auto req_priv_lvl = (addr >> 8) & 0x3; auto req_priv_lvl = (addr >> 8) & 0x3;
if(this->reg.PRIV < req_priv_lvl) // not having required privileges if(this->reg.PRIV < req_priv_lvl) // not having required privileges
throw illegal_instruction_fault(this->fault_data); throw illegal_instruction_fault(this->fault_data);
@ -822,7 +854,8 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_csr(unsigned
} }
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_csr(unsigned addr, reg_t val) { template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_csr(unsigned addr, reg_t val) {
if (addr >= csr.size()) return iss::Err; if(addr >= csr.size())
return iss::Err;
auto req_priv_lvl = (addr >> 8) & 0x3; auto req_priv_lvl = (addr >> 8) & 0x3;
if(this->reg.PRIV < req_priv_lvl) // not having required privileges if(this->reg.PRIV < req_priv_lvl) // not having required privileges
throw illegal_instruction_fault(this->fault_data); throw illegal_instruction_fault(this->fault_data);
@ -854,7 +887,8 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_cycle(unsigne
if(addr == mcycle) { if(addr == mcycle) {
val = static_cast<reg_t>(cycle_val); val = static_cast<reg_t>(cycle_val);
} else if(addr == mcycleh) { } else if(addr == mcycleh) {
if (sizeof(typename traits<BASE>::reg_t) != 4) return iss::Err; if(sizeof(typename traits<BASE>::reg_t) != 4)
return iss::Err;
val = static_cast<reg_t>(cycle_val >> 32); val = static_cast<reg_t>(cycle_val >> 32);
} }
return iss::Ok; return iss::Ok;
@ -902,7 +936,8 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_time(unsigned
if(addr == time) { if(addr == time) {
val = static_cast<reg_t>(time_val); val = static_cast<reg_t>(time_val);
} else if(addr == timeh) { } else if(addr == timeh) {
if (sizeof(typename traits<BASE>::reg_t) != 4) return iss::Err; if(sizeof(typename traits<BASE>::reg_t) != 4)
return iss::Err;
val = static_cast<reg_t>(time_val >> 32); val = static_cast<reg_t>(time_val >> 32);
} }
return iss::Ok; return iss::Ok;
@ -934,8 +969,10 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_cause(unsign
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_ie(unsigned addr, reg_t& val) { template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_ie(unsigned addr, reg_t& val) {
val = csr[mie]; val = csr[mie];
if (addr < mie) val &= csr[mideleg]; if(addr < mie)
if (addr < sie) val &= csr[sideleg]; val &= csr[mideleg];
if(addr < sie)
val &= csr[sideleg];
return iss::Ok; return iss::Ok;
} }
@ -954,8 +991,10 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_ie(unsigned
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_ip(unsigned addr, reg_t& val) { template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_ip(unsigned addr, reg_t& val) {
val = csr[mip]; val = csr[mip];
if (addr < mip) val &= csr[mideleg]; if(addr < mip)
if (addr < sip) val &= csr[sideleg]; val &= csr[mideleg];
if(addr < sip)
val &= csr[sideleg];
return iss::Ok; return iss::Ok;
} }
@ -1020,8 +1059,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_fcsr(unsigne
return iss::Ok; return iss::Ok;
} }
template <typename BASE> template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length, uint8_t* const data) {
iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) {
switch(paddr.val) { switch(paddr.val) {
default: { default: {
for(auto offs = 0U; offs < length; ++offs) { for(auto offs = 0U; offs < length; ++offs) {
@ -1032,8 +1070,7 @@ iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length
return iss::Ok; return iss::Ok;
} }
template <typename BASE> template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) {
iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) {
switch(paddr.val) { switch(paddr.val) {
case 0xFFFF0000: // UART0 base, TXFIFO reg case 0xFFFF0000: // UART0 base, TXFIFO reg
if(((char)data[0]) == '\n' || data[0] == 0) { if(((char)data[0]) == '\n' || data[0] == 0) {
@ -1047,10 +1084,9 @@ iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned lengt
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask)); std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
// tohost handling in case of riscv-test // tohost handling in case of riscv-test
if(paddr.access && iss::access_type::FUNC) { if(paddr.access && iss::access_type::FUNC) {
auto tohost_upper = (traits<BASE>::XLEN == 32 && paddr.val == (tohost + 4)) || auto tohost_upper =
(traits<BASE>::XLEN == 64 && paddr.val == tohost); (traits<BASE>::XLEN == 32 && paddr.val == (tohost + 4)) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
auto tohost_lower = auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
(traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
if(tohost_lower || tohost_upper) { if(tohost_lower || tohost_upper) {
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)); uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) {
@ -1081,8 +1117,7 @@ iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned lengt
} }
} else if(tohost_lower) } else if(tohost_lower)
to_host_wr_cnt++; to_host_wr_cnt++;
} else if ((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || } else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
(traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask)); uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
} }
@ -1131,13 +1166,13 @@ template <typename BASE> void riscv_hart_msu_vp<BASE>::check_interrupt() {
} }
if(enabled_interrupts != 0) { if(enabled_interrupts != 0) {
int res = 0; int res = 0;
while ((enabled_interrupts & 1) == 0) enabled_interrupts >>= 1, res++; while((enabled_interrupts & 1) == 0)
enabled_interrupts >>= 1, res++;
this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id
} }
} }
template <typename BASE> template <typename BASE> typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys(const iss::addr_t& addr) {
typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys(const iss::addr_t &addr) {
const auto type = addr.access & iss::access_type::FUNC; const auto type = addr.access & iss::access_type::FUNC;
auto it = ptw.find(addr.val >> PGSHIFT); auto it = ptw.find(addr.val >> PGSHIFT);
if(it != ptw.end()) { if(it != ptw.end()) {
@ -1156,8 +1191,8 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys
#endif #endif
} else { } else {
uint32_t mode = type != iss::access_type::FETCH && state.mstatus.MPRV ? // MPRV uint32_t mode = type != iss::access_type::FETCH && state.mstatus.MPRV ? // MPRV
state.mstatus.MPP : state.mstatus.MPP
this->reg.PRIV; : this->reg.PRIV;
const vm_info& vm = this->vm[static_cast<uint16_t>(type) / 2]; const vm_info& vm = this->vm[static_cast<uint16_t>(type) / 2];
@ -1178,9 +1213,10 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys
// check that physical address of PTE is legal // check that physical address of PTE is legal
reg_t pte = 0; reg_t pte = 0;
const uint8_t res = this->read(iss::address_type::PHYSICAL, addr.access, const uint8_t res = this->read(iss::address_type::PHYSICAL, addr.access, traits<BASE>::MEM, base + idx * vm.ptesize, vm.ptesize,
traits<BASE>::MEM, base + idx * vm.ptesize, vm.ptesize, (uint8_t *)&pte); (uint8_t*)&pte);
if (res != 0) throw trap_load_access_fault(addr.val); if(res != 0)
throw trap_load_access_fault(addr.val);
const reg_t ppn = pte >> PTE_PPN_SHIFT; const reg_t ppn = pte >> PTE_PPN_SHIFT;
if(PTE_TABLE(pte)) { // next level of page table if(PTE_TABLE(pte)) { // next level of page table
@ -1189,8 +1225,7 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys
break; break;
} else if(!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) { } else if(!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) {
break; break;
} else if (type == iss::access_type::FETCH } else if(type == iss::access_type::FETCH ? !(pte & PTE_X)
? !(pte & PTE_X)
: type == iss::access_type::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X)) : type == iss::access_type::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X))
: !((pte & PTE_R) && (pte & PTE_W))) { : !((pte & PTE_R) && (pte & PTE_W))) {
break; break;
@ -1203,7 +1238,8 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys
*(uint32_t*)ppte |= ad; *(uint32_t*)ppte |= ad;
#else #else
// take exception if access or possibly dirty bit is not set. // take exception if access or possibly dirty bit is not set.
if ((pte & ad) != ad) break; if((pte & ad) != ad)
break;
#endif #endif
// for superpage mappings, make a fake leaf PTE for the TLB's benefit. // for superpage mappings, make a fake leaf PTE for the TLB's benefit.
const reg_t vpn = addr.val >> PGSHIFT; const reg_t vpn = addr.val >> PGSHIFT;
@ -1233,10 +1269,12 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
auto cur_priv = this->reg.PRIV; auto cur_priv = this->reg.PRIV;
// flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0]
// calculate and write mcause val // calculate and write mcause val
if(flags==std::numeric_limits<uint64_t>::max()) flags=this->reg.trap_state; if(flags == std::numeric_limits<uint64_t>::max())
flags = this->reg.trap_state;
auto trap_id = bit_sub<0, 16>(flags); auto trap_id = bit_sub<0, 16>(flags);
auto cause = bit_sub<16, 15>(flags); auto cause = bit_sub<16, 15>(flags);
if (trap_id == 0 && cause == 11) cause = 0x8 + cur_priv; // adjust environment call cause if(trap_id == 0 && cause == 11)
cause = 0x8 + cur_priv; // adjust environment call cause
// calculate effective privilege level // calculate effective privilege level
auto new_priv = PRIV_M; auto new_priv = PRIV_M;
if(trap_id == 0) { // exception if(trap_id == 0) { // exception
@ -1312,14 +1350,15 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
// calculate addr// set NEXT_PC to trap addressess to jump to based on MODE // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE
// bits in mtvec // bits in mtvec
this->reg.NEXT_PC = ivec & ~0x3UL; this->reg.NEXT_PC = ivec & ~0x3UL;
if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; if((ivec & 0x1) == 1 && trap_id != 0)
this->reg.NEXT_PC += 4 * cause;
std::array<char, 32> buffer; std::array<char, 32> buffer;
sprintf(buffer.data(), "0x%016lx", addr); sprintf(buffer.data(), "0x%016lx", addr);
if((flags & 0xffffffff) != 0xffffffff) if((flags & 0xffffffff) != 0xffffffff)
CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause]) << "' ("
<< (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")" << cause << ")"
<< " at address " << buffer.data() << " occurred, changing privilege level from " << " at address " << buffer.data() << " occurred, changing privilege level from " << lvl[cur_priv] << " to "
<< lvl[cur_priv] << " to " << lvl[new_priv]; << lvl[new_priv];
// reset trap state // reset trap state
this->reg.PRIV = new_priv; this->reg.PRIV = new_priv;
this->reg.trap_state = 0; this->reg.trap_state = 0;
@ -1362,8 +1401,7 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::leave_trap(uint64_t f
} }
// sets the pc to the value stored in the x epc register. // sets the pc to the value stored in the x epc register.
this->reg.NEXT_PC = csr[uepc | inst_priv << 8]; this->reg.NEXT_PC = csr[uepc | inst_priv << 8];
CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " << lvl[this->reg.PRIV];
<< lvl[this->reg.PRIV];
update_vm_info(); update_vm_info();
check_interrupt(); check_interrupt();
return this->reg.NEXT_PC; return this->reg.NEXT_PC;
@ -1377,7 +1415,7 @@ template <typename BASE> void riscv_hart_msu_vp<BASE>::wait_until(uint64_t flags
this->fault_data = this->reg.PC; this->fault_data = this->reg.PC;
} }
} }
} } // namespace arch
} } // namespace iss
#endif /* _RISCV_HART_MSU_VP_H */ #endif /* _RISCV_HART_MSU_VP_H */

View File

@ -35,22 +35,22 @@
#ifndef _RISCV_HART_MU_P_H #ifndef _RISCV_HART_MU_P_H
#define _RISCV_HART_MU_P_H #define _RISCV_HART_MU_P_H
#include "riscv_hart_common.h"
#include "iss/arch/traits.h" #include "iss/arch/traits.h"
#include "iss/instrumentation_if.h" #include "iss/instrumentation_if.h"
#include "iss/log_categories.h" #include "iss/log_categories.h"
#include "iss/vm_if.h" #include "iss/vm_if.h"
#include "riscv_hart_common.h"
#ifndef FMT_HEADER_ONLY #ifndef FMT_HEADER_ONLY
#define FMT_HEADER_ONLY #define FMT_HEADER_ONLY
#endif #endif
#include <array> #include <array>
#include <elfio/elfio.hpp> #include <elfio/elfio.hpp>
#include <fmt/format.h> #include <fmt/format.h>
#include <functional>
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include <type_traits> #include <type_traits>
#include <unordered_map> #include <unordered_map>
#include <functional>
#include <util/bit_field.h> #include <util/bit_field.h>
#include <util/ities.h> #include <util/ities.h>
#include <util/sparse_array.h> #include <util/sparse_array.h>
@ -86,10 +86,11 @@ protected:
"Load page fault", // d "Load page fault", // d
"Reserved", // e "Reserved", // e
"Store/AMO page fault"}}; "Store/AMO page fault"}};
const std::array<const char *, 12> irq_str = { const std::array<const char*, 12> irq_str = {{"User software interrupt", "Supervisor software interrupt", "Reserved",
{"User software interrupt", "Supervisor software interrupt", "Reserved", "Machine software interrupt", "Machine software interrupt", "User timer interrupt", "Supervisor timer interrupt",
"User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt", "Reserved", "Machine timer interrupt", "User external interrupt",
"User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; "Supervisor external interrupt", "Reserved", "Machine external interrupt"}};
public: public:
using core = BASE; using core = BASE;
using this_class = riscv_hart_mu_p<BASE, FEAT>; using this_class = riscv_hart_mu_p<BASE, FEAT>;
@ -108,7 +109,8 @@ public:
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint32_t>::value>::type> { template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint32_t>::value>::type> {
public: public:
BEGIN_BF_DECL(mstatus_t, T); BEGIN_BF_DECL(mstatus_t, T);
// SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11))) // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR
// XS==11)))
BF_FIELD(SD, 31, 1); BF_FIELD(SD, 31, 1);
// Trap SRET // Trap SRET
BF_FIELD(TSR, 22, 1); BF_FIELD(TSR, 22, 1);
@ -122,7 +124,8 @@ public:
BF_FIELD(SUM, 18, 1); BF_FIELD(SUM, 18, 1);
// Modify PRiVilege // Modify PRiVilege
BF_FIELD(MPRV, 17, 1); BF_FIELD(MPRV, 17, 1);
// status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None
// dirty, some clean/Some dirty
BF_FIELD(XS, 15, 2); BF_FIELD(XS, 15, 2);
// floating-point unit status Off/Initial/Clean/Dirty // floating-point unit status Off/Initial/Clean/Dirty
BF_FIELD(FS, 13, 2); BF_FIELD(FS, 13, 2);
@ -159,7 +162,8 @@ public:
return priv_lvl == PRIV_U ? 0x80000011UL : priv_lvl == PRIV_S ? 0x800de133UL : 0x807ff9ddUL; return priv_lvl == PRIV_U ? 0x80000011UL : priv_lvl == PRIV_S ? 0x800de133UL : 0x807ff9ddUL;
#else #else
switch(priv_lvl) { switch(priv_lvl) {
case PRIV_U: return 0x00000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001 case PRIV_U:
return 0x00000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001
default: default:
// +-SD // +-SD
// | +-TSR // | +-TSR
@ -186,7 +190,8 @@ public:
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint64_t>::value>::type> { template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint64_t>::value>::type> {
public: public:
BEGIN_BF_DECL(mstatus_t, T); BEGIN_BF_DECL(mstatus_t, T);
// SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11))) // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR
// XS==11)))
BF_FIELD(SD, 63, 1); BF_FIELD(SD, 63, 1);
// value of XLEN for S-mode // value of XLEN for S-mode
BF_FIELD(SXL, 34, 2); BF_FIELD(SXL, 34, 2);
@ -204,7 +209,8 @@ public:
BF_FIELD(SUM, 18, 1); BF_FIELD(SUM, 18, 1);
// Modify PRiVilege // Modify PRiVilege
BF_FIELD(MPRV, 17, 1); BF_FIELD(MPRV, 17, 1);
// status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None
// dirty, some clean/Some dirty
BF_FIELD(XS, 15, 2); BF_FIELD(XS, 15, 2);
// floating-point unit status Off/Initial/Clean/Dirty // floating-point unit status Off/Initial/Clean/Dirty
BF_FIELD(FS, 13, 2); BF_FIELD(FS, 13, 2);
@ -241,7 +247,8 @@ public:
return priv_lvl == PRIV_U ? 0x011ULL : priv_lvl == PRIV_S ? 0x000de133ULL : 0x007ff9ddULL; return priv_lvl == PRIV_U ? 0x011ULL : priv_lvl == PRIV_S ? 0x000de133ULL : 0x007ff9ddULL;
#else #else
switch(priv_lvl) { switch(priv_lvl) {
case PRIV_U: return 0x00000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001 case PRIV_U:
return 0x00000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001
default: default:
// +-SD // +-SD
// | +-TSR // | +-TSR
@ -276,12 +283,8 @@ public:
return m[mode]; return m[mode];
} }
constexpr bool has_compressed() { constexpr bool has_compressed() { return traits<BASE>::MISA_VAL & 0b0100; }
return traits<BASE>::MISA_VAL&0b0100; constexpr reg_t get_pc_mask() { return has_compressed() ? ~1 : ~3; }
}
constexpr reg_t get_pc_mask() {
return has_compressed()?~1:~3;
}
riscv_hart_mu_p(feature_config cfg = feature_config{}); riscv_hart_mu_p(feature_config cfg = feature_config{});
@ -291,10 +294,10 @@ public:
std::pair<uint64_t, bool> load_file(std::string name, int type = -1) override; std::pair<uint64_t, bool> load_file(std::string name, int type = -1) override;
iss::status read(const address_type type, const access_type access, const uint32_t space, iss::status read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length,
const uint64_t addr, const unsigned length, uint8_t *const data) override; uint8_t* const data) override;
iss::status write(const address_type type, const access_type access, const uint32_t space, iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length,
const uint64_t addr, const unsigned length, const uint8_t *const data) override; const uint8_t* const data) override;
uint64_t enter_trap(uint64_t flags) override { return riscv_hart_mu_p::enter_trap(flags, fault_data, fault_data); } uint64_t enter_trap(uint64_t flags) override { return riscv_hart_mu_p::enter_trap(flags, fault_data, fault_data); }
uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override;
@ -304,19 +307,16 @@ public:
void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; }; void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; };
void disass_output(uint64_t pc, const std::string instr) override { void disass_output(uint64_t pc, const std::string instr) override {
CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus,
pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount + cycle_offset); this->reg.icount + cycle_offset);
}; };
iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; } iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; }
void set_csr(unsigned addr, reg_t val){ void set_csr(unsigned addr, reg_t val) { csr[addr & csr.page_addr_mask] = val; }
csr[addr & csr.page_addr_mask] = val;
} void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
void set_irq_num(unsigned i) {
mcause_max_irq=1<<util::ilog2(i);
}
protected: protected:
struct riscv_instrumentation_if : public iss::instrumentation_if { struct riscv_instrumentation_if : public iss::instrumentation_if {
@ -433,12 +433,8 @@ protected:
virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; }; virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; };
virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; }; virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; };
void register_custom_csr_rd(unsigned addr){ void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr_reg; }
csr_rd_cb[addr] = &this_class::read_custom_csr_reg; void register_custom_csr_wr(unsigned addr) { csr_wr_cb[addr] = &this_class::write_custom_csr_reg; }
}
void register_custom_csr_wr(unsigned addr){
csr_wr_cb[addr] = &this_class::write_custom_csr_reg;
}
reg_t mhartid_reg{0x0}; reg_t mhartid_reg{0x0};
@ -452,8 +448,8 @@ protected:
uint64_t mcause_max_irq{(FEAT & features_e::FEAT_CLIC) ? 4096 : 16}; uint64_t mcause_max_irq{(FEAT & features_e::FEAT_CLIC) ? 4096 : 16};
inline bool debug_mode_active() { return this->reg.PRIV & 0x4; } inline bool debug_mode_active() { return this->reg.PRIV & 0x4; }
std::pair<std::function<mem_read_f>, std::function<mem_write_f>> std::pair<std::function<mem_read_f>, std::function<mem_write_f>> replace_mem_access(std::function<mem_read_f> rd,
replace_mem_access(std::function<mem_read_f> rd, std::function<mem_write_f> wr){ std::function<mem_write_f> wr) {
std::pair<std::function<mem_read_f>, std::function<mem_write_f>> ret{hart_mem_rd_delegate, hart_mem_wr_delegate}; std::pair<std::function<mem_read_f>, std::function<mem_write_f>> ret{hart_mem_rd_delegate, hart_mem_wr_delegate};
hart_mem_rd_delegate = rd; hart_mem_rd_delegate = rd;
hart_mem_wr_delegate = wr; hart_mem_wr_delegate = wr;
@ -479,7 +475,8 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg)
csr_rd_cb[addr] = &this_class::read_null; csr_rd_cb[addr] = &this_class::read_null;
csr_wr_cb[addr] = &this_class::write_csr_reg; csr_wr_cb[addr] = &this_class::write_csr_reg;
} }
if(traits<BASE>::XLEN==32) for (unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr){ if(traits<BASE>::XLEN == 32)
for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) {
csr_rd_cb[addr] = &this_class::read_null; csr_rd_cb[addr] = &this_class::read_null;
csr_wr_cb[addr] = &this_class::write_csr_reg; csr_wr_cb[addr] = &this_class::write_csr_reg;
} }
@ -490,7 +487,8 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg)
for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) { for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) {
csr_rd_cb[addr] = &this_class::read_null; csr_rd_cb[addr] = &this_class::read_null;
} }
if(traits<BASE>::XLEN==32) for (unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr){ if(traits<BASE>::XLEN == 32)
for(unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr) {
csr_rd_cb[addr] = &this_class::read_null; csr_rd_cb[addr] = &this_class::read_null;
// csr_wr_cb[addr] = &this_class::write_csr_reg; // csr_wr_cb[addr] = &this_class::write_csr_reg;
} }
@ -501,8 +499,14 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg)
csr_wr_cb[addr] = &this_class::write_null; csr_wr_cb[addr] = &this_class::write_null;
} }
const std::array<unsigned, 8> rwaddrs{{ const std::array<unsigned, 8> rwaddrs{{
mepc, mtvec, mscratch, mtval, mepc,
uepc, utvec, uscratch, utval, mtvec,
mscratch,
mtval,
uepc,
utvec,
uscratch,
utval,
}}; }};
for(auto addr : rwaddrs) { for(auto addr : rwaddrs) {
csr_rd_cb[addr] = &this_class::read_csr_reg; csr_rd_cb[addr] = &this_class::read_csr_reg;
@ -510,20 +514,27 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg)
} }
// special handling & overrides // special handling & overrides
csr_rd_cb[time] = &this_class::read_time; csr_rd_cb[time] = &this_class::read_time;
if(traits<BASE>::XLEN==32) csr_rd_cb[timeh] = &this_class::read_time; if(traits<BASE>::XLEN == 32)
csr_rd_cb[timeh] = &this_class::read_time;
csr_rd_cb[cycle] = &this_class::read_cycle; csr_rd_cb[cycle] = &this_class::read_cycle;
if(traits<BASE>::XLEN==32) csr_rd_cb[cycleh] = &this_class::read_cycle; if(traits<BASE>::XLEN == 32)
csr_rd_cb[cycleh] = &this_class::read_cycle;
csr_rd_cb[instret] = &this_class::read_instret; csr_rd_cb[instret] = &this_class::read_instret;
if(traits<BASE>::XLEN==32) csr_rd_cb[instreth] = &this_class::read_instret; if(traits<BASE>::XLEN == 32)
csr_rd_cb[instreth] = &this_class::read_instret;
csr_rd_cb[mcycle] = &this_class::read_cycle; csr_rd_cb[mcycle] = &this_class::read_cycle;
csr_wr_cb[mcycle] = &this_class::write_cycle; csr_wr_cb[mcycle] = &this_class::write_cycle;
if(traits<BASE>::XLEN==32) csr_rd_cb[mcycleh] = &this_class::read_cycle; if(traits<BASE>::XLEN == 32)
if(traits<BASE>::XLEN==32) csr_wr_cb[mcycleh] = &this_class::write_cycle; csr_rd_cb[mcycleh] = &this_class::read_cycle;
if(traits<BASE>::XLEN == 32)
csr_wr_cb[mcycleh] = &this_class::write_cycle;
csr_rd_cb[minstret] = &this_class::read_instret; csr_rd_cb[minstret] = &this_class::read_instret;
csr_wr_cb[minstret] = &this_class::write_instret; csr_wr_cb[minstret] = &this_class::write_instret;
if(traits<BASE>::XLEN==32) csr_rd_cb[minstreth] = &this_class::read_instret; if(traits<BASE>::XLEN == 32)
if(traits<BASE>::XLEN==32) csr_wr_cb[minstreth] = &this_class::write_instret; csr_rd_cb[minstreth] = &this_class::read_instret;
if(traits<BASE>::XLEN == 32)
csr_wr_cb[minstreth] = &this_class::write_instret;
csr_rd_cb[mstatus] = &this_class::read_status; csr_rd_cb[mstatus] = &this_class::read_status;
csr_wr_cb[mstatus] = &this_class::write_status; csr_wr_cb[mstatus] = &this_class::write_status;
csr_rd_cb[mcause] = &this_class::read_cause; csr_rd_cb[mcause] = &this_class::read_cause;
@ -595,7 +606,8 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg)
clic_uact_lvl = clic_uprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1; clic_uact_lvl = clic_uprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1;
csr[mintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1; csr[mintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1;
csr[uintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1; csr[uintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1;
insert_mem_range(cfg.clic_base, 0x5000UL, insert_mem_range(
cfg.clic_base, 0x5000UL,
[this](phys_addr_t addr, unsigned length, uint8_t* const data) { return read_clic(addr.val, length, data); }, [this](phys_addr_t addr, unsigned length, uint8_t* const data) { return read_clic(addr.val, length, data); },
[this](phys_addr_t addr, unsigned length, uint8_t const* const data) { return write_clic(addr.val, length, data); }); [this](phys_addr_t addr, unsigned length, uint8_t const* const data) { return write_clic(addr.val, length, data); });
} }
@ -623,12 +635,8 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg)
csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr; csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr;
csr_rd_cb[dcsr] = &this_class::read_dcsr_reg; csr_rd_cb[dcsr] = &this_class::read_dcsr_reg;
} }
hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return this->read_mem(a, l, d); };
return this->read_mem(a, l, d); hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return this->write_mem(a, l, d); };
};
hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status {
return this->write_mem(a, l, d);
};
} }
template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_mu_p<BASE, FEAT>::load_file(std::string name, int type) { template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_mu_p<BASE, FEAT>::load_file(std::string name, int type) {
@ -637,35 +645,37 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
std::array<char, 5> buf; std::array<char, 5> buf;
auto n = fread(buf.data(), 1, 4, fp); auto n = fread(buf.data(), 1, 4, fp);
fclose(fp); fclose(fp);
if (n != 4) throw std::runtime_error("input file has insufficient size"); if(n != 4)
throw std::runtime_error("input file has insufficient size");
buf[4] = 0; buf[4] = 0;
if(strcmp(buf.data() + 1, "ELF") == 0) { if(strcmp(buf.data() + 1, "ELF") == 0) {
// Create elfio reader // Create elfio reader
ELFIO::elfio reader; ELFIO::elfio reader;
// Load ELF data // Load ELF data
if (!reader.load(name)) throw std::runtime_error("could not process elf file"); if(!reader.load(name))
throw std::runtime_error("could not process elf file");
// check elf properties // check elf properties
if(reader.get_class() != ELFCLASS32) if(reader.get_class() != ELFCLASS32)
if (sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file"); if(sizeof(reg_t) == 4)
if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file"); throw std::runtime_error("wrong elf class in file");
if (reader.get_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file"); if(reader.get_type() != ET_EXEC)
throw std::runtime_error("wrong elf type in file");
if(reader.get_machine() != EM_RISCV)
throw std::runtime_error("wrong elf machine in file");
auto entry = reader.get_entry(); auto entry = reader.get_entry();
for(const auto pseg : reader.segments) { for(const auto pseg : reader.segments) {
const auto fsize = pseg->get_file_size(); // 0x42c/0x0 const auto fsize = pseg->get_file_size(); // 0x42c/0x0
const auto seg_data = pseg->get_data(); const auto seg_data = pseg->get_data();
if(fsize > 0) { if(fsize > 0) {
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM,
traits<BASE>::MEM, pseg->get_physical_address(), pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data));
fsize, reinterpret_cast<const uint8_t *const>(seg_data));
if(res != iss::Ok) if(res != iss::Ok)
LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address();
<< pseg->get_physical_address();
} }
} }
for(const auto sec : reader.sections) { for(const auto sec : reader.sections) {
if(sec->get_name() == ".symtab") { if(sec->get_name() == ".symtab") {
if ( SHT_SYMTAB == sec->get_type() || if(SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type()) {
SHT_DYNSYM == sec->get_type() ) {
ELFIO::symbol_section_accessor symbols(reader, sec); ELFIO::symbol_section_accessor symbols(reader, sec);
auto sym_no = symbols.get_symbols_num(); auto sym_no = symbols.get_symbols_num();
std::string name; std::string name;
@ -688,7 +698,6 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
tohost = sec->get_address(); tohost = sec->get_address();
fromhost = tohost + 0x40; fromhost = tohost + 0x40;
} }
} }
return std::make_pair(entry, true); return std::make_pair(entry, true);
} }
@ -701,23 +710,22 @@ template<typename BASE, features_e FEAT>
inline void riscv_hart_mu_p<BASE, FEAT>::insert_mem_range(uint64_t base, uint64_t size, std::function<mem_read_f> rd_f, inline void riscv_hart_mu_p<BASE, FEAT>::insert_mem_range(uint64_t base, uint64_t size, std::function<mem_read_f> rd_f,
std::function<mem_write_f> wr_fn) { std::function<mem_write_f> wr_fn) {
std::tuple<uint64_t, uint64_t> entry{base, size}; std::tuple<uint64_t, uint64_t> entry{base, size};
auto it = std::upper_bound( memfn_range.begin(), memfn_range.end(), entry, auto it = std::upper_bound(
[](std::tuple<uint64_t, uint64_t> const& a, std::tuple<uint64_t, uint64_t> const& b){ memfn_range.begin(), memfn_range.end(), entry,
return std::get<0>(a)<std::get<0>(b); [](std::tuple<uint64_t, uint64_t> const& a, std::tuple<uint64_t, uint64_t> const& b) { return std::get<0>(a) < std::get<0>(b); });
});
auto idx = std::distance(memfn_range.begin(), it); auto idx = std::distance(memfn_range.begin(), it);
memfn_range.insert(it, entry); memfn_range.insert(it, entry);
memfn_read.insert(std::begin(memfn_read) + idx, rd_f); memfn_read.insert(std::begin(memfn_read) + idx, rd_f);
memfn_write.insert(std::begin(memfn_write) + idx, wr_fn); memfn_write.insert(std::begin(memfn_write) + idx, wr_fn);
} }
template<typename BASE, features_e FEAT> template <typename BASE, features_e FEAT> inline iss::status riscv_hart_mu_p<BASE, FEAT>::write_pmpcfg_reg(unsigned addr, reg_t val) {
inline iss::status riscv_hart_mu_p<BASE, FEAT>::write_pmpcfg_reg(unsigned addr, reg_t val) {
csr[addr] = val & 0x9f9f9f9f; csr[addr] = val & 0x9f9f9f9f;
return iss::Ok; return iss::Ok;
} }
template <typename BASE, features_e FEAT> bool riscv_hart_mu_p<BASE, FEAT>::pmp_check(const access_type type, const uint64_t addr, const unsigned len) { template <typename BASE, features_e FEAT>
bool riscv_hart_mu_p<BASE, FEAT>::pmp_check(const access_type type, const uint64_t addr, const unsigned len) {
constexpr auto PMP_SHIFT = 2U; constexpr auto PMP_SHIFT = 2U;
constexpr auto PMP_R = 0x1U; constexpr auto PMP_R = 0x1U;
constexpr auto PMP_W = 0x2U; constexpr auto PMP_W = 0x2U;
@ -757,10 +765,8 @@ template <typename BASE, features_e FEAT> bool riscv_hart_mu_p<BASE, FEAT>::pmp_
// If the PMP matches only a strict subset of the access, fail it // If the PMP matches only a strict subset of the access, fail it
if(!all_match) if(!all_match)
return false; return false;
return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) || return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) || (type == access_type::READ && (cfg & PMP_R)) ||
(type == access_type::READ && (cfg & PMP_R)) || (type == access_type::WRITE && (cfg & PMP_W)) || (type == access_type::FETCH && (cfg & PMP_X));
(type == access_type::WRITE && (cfg & PMP_W)) ||
(type == access_type::FETCH && (cfg & PMP_X));
} }
} }
base = tor; base = tor;
@ -799,10 +805,9 @@ template <typename BASE, features_e FEAT> bool riscv_hart_mu_p<BASE, FEAT>::pmp_
return !any_active || this->reg.PRIV == PRIV_M; return !any_active || this->reg.PRIV == PRIV_M;
} }
template <typename BASE, features_e FEAT> template <typename BASE, features_e FEAT>
iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const access_type access, const uint32_t space, iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr,
const uint64_t addr, const unsigned length, uint8_t *const data) { const unsigned length, uint8_t* const data) {
#ifndef NDEBUG #ifndef NDEBUG
if(access && iss::access_type::DEBUG) { if(access && iss::access_type::DEBUG) {
LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr; LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr;
@ -818,7 +823,8 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
if(FEAT & FEAT_PMP) { if(FEAT & FEAT_PMP) {
if(!pmp_check(access, addr, length) && !is_debug(access)) { if(!pmp_check(access, addr, length) && !is_debug(access)) {
fault_data = addr; fault_data = addr;
if (is_debug(access)) throw trap_access(0, addr); if(is_debug(access))
throw trap_access(0, addr);
this->reg.trap_state = (1UL << 31) | ((access == access_type::FETCH ? 1 : 5) << 16); // issue trap 1 this->reg.trap_state = (1UL << 31) | ((access == access_type::FETCH ? 1 : 5) << 16); // issue trap 1
return iss::Err; return iss::Err;
} }
@ -826,7 +832,8 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
auto alignment = is_fetch(access) ? (has_compressed() ? 2 : 4) : length; auto alignment = is_fetch(access) ? (has_compressed() ? 2 : 4) : length;
if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) { if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) {
fault_data = addr; fault_data = addr;
if (is_debug(access)) throw trap_access(0, addr); if(is_debug(access))
throw trap_access(0, addr);
this->reg.trap_state = (1UL << 31); // issue trap 0 this->reg.trap_state = (1UL << 31); // issue trap 0
return iss::Err; return iss::Err;
} }
@ -839,7 +846,8 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
phys_addr_t phys_addr{access, space, addr}; phys_addr_t phys_addr{access, space, addr};
auto res = iss::Err; auto res = iss::Err;
if(!is_fetch(access) && memfn_range.size()) { if(!is_fetch(access) && memfn_range.size()) {
auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a){ auto it =
std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a) {
return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val; return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val;
}); });
if(it != std::end(memfn_range)) { if(it != std::end(memfn_range)) {
@ -862,11 +870,13 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
} }
} break; } break;
case traits<BASE>::CSR: { case traits<BASE>::CSR: {
if (length != sizeof(reg_t)) return iss::Err; if(length != sizeof(reg_t))
return iss::Err;
return read_csr(addr, *reinterpret_cast<reg_t* const>(data)); return read_csr(addr, *reinterpret_cast<reg_t* const>(data));
} break; } break;
case traits<BASE>::FENCE: { case traits<BASE>::FENCE: {
if ((addr + length) > mem.size()) return iss::Err; if((addr + length) > mem.size())
return iss::Err;
return iss::Ok; return iss::Ok;
} break; } break;
case traits<BASE>::RES: { case traits<BASE>::RES: {
@ -889,26 +899,26 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
} }
template <typename BASE, features_e FEAT> template <typename BASE, features_e FEAT>
iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const access_type access, const uint32_t space, iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr,
const uint64_t addr, const unsigned length, const uint8_t *const data) { const unsigned length, const uint8_t* const data) {
#ifndef NDEBUG #ifndef NDEBUG
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
switch(length) { switch(length) {
case 8: case 8:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x"
<< ") @addr 0x" << std::hex << addr; << std::hex << addr;
break; break;
case 4: case 4:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t *)&data[0] << std::dec LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x"
<< ") @addr 0x" << std::hex << addr; << std::hex << addr;
break; break;
case 2: case 2:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t *)&data[0] << std::dec LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x"
<< ") @addr 0x" << std::hex << addr; << std::hex << addr;
break; break;
case 1: case 1:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x"
<< ") @addr 0x" << std::hex << addr; << std::hex << addr;
break; break;
default: default:
LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr; LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr;
@ -920,14 +930,16 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
if(FEAT & FEAT_PMP) { if(FEAT & FEAT_PMP) {
if(!pmp_check(access, addr, length) && (access & access_type::DEBUG) != access_type::DEBUG) { if(!pmp_check(access, addr, length) && (access & access_type::DEBUG) != access_type::DEBUG) {
fault_data = addr; fault_data = addr;
if (access && iss::access_type::DEBUG) throw trap_access(0, addr); if(access && iss::access_type::DEBUG)
throw trap_access(0, addr);
this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 1 this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 1
return iss::Err; return iss::Err;
} }
} }
if(unlikely(is_fetch(access) && (addr & 0x1) == 1)) { if(unlikely(is_fetch(access) && (addr & 0x1) == 1)) {
fault_data = addr; fault_data = addr;
if (access && iss::access_type::DEBUG) throw trap_access(0, addr); if(access && iss::access_type::DEBUG)
throw trap_access(0, addr);
this->reg.trap_state = (1UL << 31); // issue trap 0 this->reg.trap_state = (1UL << 31); // issue trap 0
return iss::Err; return iss::Err;
} }
@ -940,7 +952,8 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
phys_addr_t phys_addr{access, space, addr}; phys_addr_t phys_addr{access, space, addr};
auto res = iss::Err; auto res = iss::Err;
if(!is_fetch(access) && memfn_range.size()) { if(!is_fetch(access) && memfn_range.size()) {
auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a){ auto it =
std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a) {
return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val; return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val;
}); });
if(it != std::end(memfn_range)) { if(it != std::end(memfn_range)) {
@ -962,7 +975,8 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
return iss::Err; return iss::Err;
} }
if ((addr + length) > mem.size()) return iss::Err; if((addr + length) > mem.size())
return iss::Err;
switch(addr) { switch(addr) {
case 0x10013000: // UART0 base, TXFIFO reg case 0x10013000: // UART0 base, TXFIFO reg
case 0x10023000: // UART1 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg
@ -979,7 +993,8 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
auto offs = addr & mem.page_addr_mask; auto offs = addr & mem.page_addr_mask;
std::copy(data, data + length, p.data() + offs); std::copy(data, data + length, p.data() + offs);
auto& x = *(p.data() + offs + 3); auto& x = *(p.data() + offs + 3);
if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1 if(x & 0x40)
x |= 0x80; // hfroscrdy = 1 if hfroscen==1
return iss::Ok; return iss::Ok;
} }
case 0x10008008: { // HFROSC base, pllcfg reg case 0x10008008: { // HFROSC base, pllcfg reg
@ -994,11 +1009,13 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
} }
} break; } break;
case traits<BASE>::CSR: { case traits<BASE>::CSR: {
if (length != sizeof(reg_t)) return iss::Err; if(length != sizeof(reg_t))
return iss::Err;
return write_csr(addr, *reinterpret_cast<const reg_t*>(data)); return write_csr(addr, *reinterpret_cast<const reg_t*>(data));
} break; } break;
case traits<BASE>::FENCE: { case traits<BASE>::FENCE: {
if ((addr + length) > mem.size()) return iss::Err; if((addr + length) > mem.size())
return iss::Err;
switch(addr) { switch(addr) {
case 2: case 2:
case 3: { case 3: {
@ -1023,7 +1040,8 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
} }
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_csr(unsigned addr, reg_t& val) { template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_csr(unsigned addr, reg_t& val) {
if (addr >= csr.size()) return iss::Err; if(addr >= csr.size())
return iss::Err;
auto req_priv_lvl = (addr >> 8) & 0x3; auto req_priv_lvl = (addr >> 8) & 0x3;
if(this->reg.PRIV < req_priv_lvl) // not having required privileges if(this->reg.PRIV < req_priv_lvl) // not having required privileges
throw illegal_instruction_fault(this->fault_data); throw illegal_instruction_fault(this->fault_data);
@ -1034,7 +1052,8 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
} }
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_csr(unsigned addr, reg_t val) { template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_csr(unsigned addr, reg_t val) {
if (addr >= csr.size()) return iss::Err; if(addr >= csr.size())
return iss::Err;
auto req_priv_lvl = (addr >> 8) & 0x3; auto req_priv_lvl = (addr >> 8) & 0x3;
if(this->reg.PRIV < req_priv_lvl) // not having required privileges if(this->reg.PRIV < req_priv_lvl) // not having required privileges
throw illegal_instruction_fault(this->fault_data); throw illegal_instruction_fault(this->fault_data);
@ -1113,7 +1132,8 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
if(addr == time) { if(addr == time) {
val = static_cast<reg_t>(time_val); val = static_cast<reg_t>(time_val);
} else if(addr == timeh) { } else if(addr == timeh) {
if (sizeof(typename traits<BASE>::reg_t) != 4) return iss::Err; if(sizeof(typename traits<BASE>::reg_t) != 4)
return iss::Err;
val = static_cast<reg_t>(time_val >> 32); val = static_cast<reg_t>(time_val >> 32);
} }
return iss::Ok; return iss::Ok;
@ -1261,8 +1281,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
return iss::Ok; return iss::Ok;
} }
template<typename BASE, features_e FEAT> template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_intstatus(unsigned addr, reg_t& val) {
iss::status riscv_hart_mu_p<BASE, FEAT>::read_intstatus(unsigned addr, reg_t& val) {
auto mode = (addr >> 8) & 0x3; auto mode = (addr >> 8) & 0x3;
val = clic_uact_lvl & 0xff; val = clic_uact_lvl & 0xff;
if(mode == 0x3) if(mode == 0x3)
@ -1270,14 +1289,12 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read_intstatus(unsigned addr, reg_t& va
return iss::Ok; return iss::Ok;
} }
template<typename BASE, features_e FEAT> template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_intthresh(unsigned addr, reg_t val) {
iss::status riscv_hart_mu_p<BASE, FEAT>::write_intthresh(unsigned addr, reg_t val) {
csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1; csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1;
return iss::Ok; return iss::Ok;
} }
template<typename BASE, features_e FEAT> template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_xtvt(unsigned addr, reg_t val) {
iss::status riscv_hart_mu_p<BASE, FEAT>::write_xtvt(unsigned addr, reg_t val) {
csr[addr] = val & ~0x3fULL; csr[addr] = val & ~0x3fULL;
return iss::Ok; return iss::Ok;
} }
@ -1309,10 +1326,9 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned l
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask)); std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
// tohost handling in case of riscv-test // tohost handling in case of riscv-test
if(paddr.access && iss::access_type::FUNC) { if(paddr.access && iss::access_type::FUNC) {
auto tohost_upper = (traits<BASE>::XLEN == 32 && paddr.val == (tohost + 4)) || auto tohost_upper =
(traits<BASE>::XLEN == 64 && paddr.val == tohost); (traits<BASE>::XLEN == 32 && paddr.val == (tohost + 4)) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
auto tohost_lower = auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
(traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
if(tohost_lower || tohost_upper) { if(tohost_lower || tohost_upper) {
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)); uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) {
@ -1343,8 +1359,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned l
} }
} else if(tohost_lower) } else if(tohost_lower)
to_host_wr_cnt++; to_host_wr_cnt++;
} else if ((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || } else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
(traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask)); uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
} }
@ -1358,15 +1373,18 @@ template<typename BASE, features_e FEAT>
iss::status riscv_hart_mu_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned length, uint8_t* const data) { iss::status riscv_hart_mu_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned length, uint8_t* const data) {
if(addr == cfg.clic_base) { // cliccfg if(addr == cfg.clic_base) { // cliccfg
*data = clic_cfg_reg; *data = clic_cfg_reg;
for(auto i=1; i<length; ++i) *(data+i)=0; for(auto i = 1; i < length; ++i)
*(data + i) = 0;
} else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig } else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig
auto offset = ((addr & 0x7fff) - 0x40) / 4; auto offset = ((addr & 0x7fff) - 0x40) / 4;
read_reg_uint32(addr, clic_inttrig_reg[offset], data, length); read_reg_uint32(addr, clic_inttrig_reg[offset], data, length);
} else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl } else if(addr >= (cfg.clic_base + 0x1000) &&
(addr + length) <= (cfg.clic_base + 0x1000 + cfg.clic_num_irq * 4)) { // clicintip/clicintie/clicintattr/clicintctl
auto offset = ((addr & 0x7fff) - 0x1000) / 4; auto offset = ((addr & 0x7fff) - 0x1000) / 4;
read_reg_uint32(addr, clic_int_reg[offset].raw, data, length); read_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
} else { } else {
for(auto i = 0U; i<length; ++i) *(data+i)=0; for(auto i = 0U; i < length; ++i)
*(data + i) = 0;
} }
return iss::Ok; return iss::Ok;
} }
@ -1378,7 +1396,8 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_clic(uint64_t addr, unsigned leng
} else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig } else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig
auto offset = ((addr & 0x7fff) - 0x40) / 4; auto offset = ((addr & 0x7fff) - 0x40) / 4;
write_reg_uint32(addr, clic_inttrig_reg[offset], data, length); write_reg_uint32(addr, clic_inttrig_reg[offset], data, length);
} else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl } else if(addr >= (cfg.clic_base + 0x1000) &&
(addr + length) <= (cfg.clic_base + 0x1000 + cfg.clic_num_irq * 4)) { // clicintip/clicintie/clicintattr/clicintctl
auto offset = ((addr & 0x7fff) - 0x1000) / 4; auto offset = ((addr & 0x7fff) - 0x1000) / 4;
write_reg_uint32(addr, clic_int_reg[offset].raw, data, length); write_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
clic_int_reg[offset].raw &= 0xf0c70101; // clicIntCtlBits->0xf0, clicintattr->0xc7, clicintie->0x1, clicintip->0x1 clic_int_reg[offset].raw &= 0xf0c70101; // clicIntCtlBits->0xf0, clicintattr->0xc7, clicintie->0x1, clicintip->0x1
@ -1417,10 +1436,12 @@ template <typename BASE, features_e FEAT> void riscv_hart_mu_p<BASE, FEAT>::chec
template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) { template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) {
// flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0]
// calculate and write mcause val // calculate and write mcause val
if(flags==std::numeric_limits<uint64_t>::max()) flags=this->reg.trap_state; if(flags == std::numeric_limits<uint64_t>::max())
flags = this->reg.trap_state;
auto trap_id = bit_sub<0, 16>(flags); auto trap_id = bit_sub<0, 16>(flags);
auto cause = bit_sub<16, 15>(flags); auto cause = bit_sub<16, 15>(flags);
if (trap_id == 0 && cause == 11) cause = 0x8 + this->reg.PRIV; // adjust environment call cause if(trap_id == 0 && cause == 11)
cause = 0x8 + this->reg.PRIV; // adjust environment call cause
// calculate effective privilege level // calculate effective privilege level
unsigned new_priv = PRIV_M; unsigned new_priv = PRIV_M;
if(trap_id == 0) { // exception if(trap_id == 0) { // exception
@ -1511,10 +1532,10 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::
sprintf(buffer.data(), "0x%016lx", addr); sprintf(buffer.data(), "0x%016lx", addr);
#endif #endif
if((flags & 0xffffffff) != 0xffffffff) if((flags & 0xffffffff) != 0xffffffff)
CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause]) << "' ("
<< (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")" << cause << ")"
<< " at address " << buffer.data() << " occurred, changing privilege level from " << " at address " << buffer.data() << " occurred, changing privilege level from " << lvl[this->reg.PRIV]
<< lvl[this->reg.PRIV] << " to " << lvl[new_priv]; << " to " << lvl[new_priv];
// reset trap state // reset trap state
this->reg.PRIV = new_priv; this->reg.PRIV = new_priv;
this->reg.trap_state = 0; this->reg.trap_state = 0;
@ -1547,8 +1568,7 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::
} }
// sets the pc to the value stored in the x epc register. // sets the pc to the value stored in the x epc register.
this->reg.NEXT_PC = csr[uepc | inst_priv << 8]; this->reg.NEXT_PC = csr[uepc | inst_priv << 8];
CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " << lvl[this->reg.PRIV];
<< lvl[this->reg.PRIV];
check_interrupt(); check_interrupt();
} }
return this->reg.NEXT_PC; return this->reg.NEXT_PC;

View File

@ -32,10 +32,10 @@
#include "tgc5c.h" #include "tgc5c.h"
#include "util/ities.h" #include "util/ities.h"
#include <util/logging.h>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <fstream> #include <fstream>
#include <util/logging.h>
using namespace iss::arch; using namespace iss::arch;
@ -59,11 +59,8 @@ void tgc5c::reset(uint64_t address) {
reg.icount = 0; reg.icount = 0;
} }
uint8_t *tgc5c::get_regs_base_ptr() { uint8_t* tgc5c::get_regs_base_ptr() { return reinterpret_cast<uint8_t*>(&reg); }
return reinterpret_cast<uint8_t*>(&reg);
}
tgc5c::phys_addr_t tgc5c::virt2phys(const iss::addr_t& addr) { tgc5c::phys_addr_t tgc5c::virt2phys(const iss::addr_t& addr) {
return phys_addr_t(addr.access, addr.space, addr.val & traits<tgc5c>::addr_mask); return phys_addr_t(addr.access, addr.space, addr.val & traits<tgc5c>::addr_mask);
} }

View File

@ -47,18 +47,76 @@ template <> struct traits<tgc5c> {
constexpr static char const* const core_type = "TGC5C"; constexpr static char const* const core_type = "TGC5C";
static constexpr std::array<const char*, 36> reg_names{ static constexpr std::array<const char*, 36> reg_names{{"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8",
{"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", "pc", "next_pc", "priv", "dpc"}}; "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17",
"x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26",
"x27", "x28", "x29", "x30", "x31", "pc", "next_pc", "priv", "dpc"}};
static constexpr std::array<const char*, 36> reg_aliases{ static constexpr std::array<const char*, 36> reg_aliases{
{"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "next_pc", "priv", "dpc"}}; {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
"s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "next_pc", "priv", "dpc"}};
enum constants {MISA_VAL=1073746180ULL, MARCHID_VAL=2147483651ULL, XLEN=32ULL, INSTR_ALIGNMENT=2ULL, RFS=32ULL, fence=0ULL, fencei=1ULL, fencevmal=2ULL, fencevmau=3ULL, CSR_SIZE=4096ULL, MUL_LEN=64ULL}; enum constants {
MISA_VAL = 1073746180ULL,
MARCHID_VAL = 2147483651ULL,
XLEN = 32ULL,
INSTR_ALIGNMENT = 2ULL,
RFS = 32ULL,
fence = 0ULL,
fencei = 1ULL,
fencevmal = 2ULL,
fencevmau = 3ULL,
CSR_SIZE = 4096ULL,
MUL_LEN = 64ULL
};
constexpr static unsigned FP_REGS_SIZE = 0; constexpr static unsigned FP_REGS_SIZE = 0;
enum reg_e { enum reg_e {
X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, PC, NEXT_PC, PRIV, DPC, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH X0,
X1,
X2,
X3,
X4,
X5,
X6,
X7,
X8,
X9,
X10,
X11,
X12,
X13,
X14,
X15,
X16,
X17,
X18,
X19,
X20,
X21,
X22,
X23,
X24,
X25,
X26,
X27,
X28,
X29,
X30,
X31,
PC,
NEXT_PC,
PRIV,
DPC,
NUM_REGS,
TRAP_STATE = NUM_REGS,
PENDING_TRAP,
ICOUNT,
CYCLE,
INSTRET,
INSTRUCTION,
LAST_BRANCH
}; };
using reg_t = uint32_t; using reg_t = uint32_t;
@ -71,11 +129,13 @@ template <> struct traits<tgc5c> {
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>; using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
static constexpr std::array<const uint32_t, 43> reg_bit_widths{ static constexpr std::array<const uint32_t, 43> reg_bit_widths{{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
{32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32,32,32,64,64,64,32,32}}; 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 8, 32, 32, 32, 64, 64, 64, 32, 32}};
static constexpr std::array<const uint32_t, 43> reg_byte_offsets{ static constexpr std::array<const uint32_t, 43> reg_byte_offsets{
{0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137,141,145,149,157,165,173,177}}; {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84,
88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 137, 141, 145, 149, 157, 165, 173, 177}};
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
@ -201,7 +261,6 @@ struct tgc5c: public arch_if {
inline uint32_t get_last_branch() { return reg.last_branch; } inline uint32_t get_last_branch() { return reg.last_branch; }
#pragma pack(push, 1) #pragma pack(push, 1)
struct TGC5C_regs { struct TGC5C_regs {
uint32_t X0 = 0; uint32_t X0 = 0;
@ -254,9 +313,8 @@ struct tgc5c: public arch_if {
uint32_t get_fcsr() { return 0; } uint32_t get_fcsr() { return 0; }
void set_fcsr(uint32_t val) {} void set_fcsr(uint32_t val) {}
}; };
} } // namespace arch
} } // namespace iss
#endif /* _TGC5C_H_ */ #endif /* _TGC5C_H_ */

View File

@ -15,36 +15,43 @@ using tgc5a_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc5a>;
using tgc5b_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc5b>; using tgc5b_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc5b>;
#endif #endif
#ifdef CORE_TGC5C_XRB_NN #ifdef CORE_TGC5C_XRB_NN
#include "riscv_hart_m_p.h"
#include "hwl.h" #include "hwl.h"
#include "riscv_hart_m_p.h"
#include <iss/arch/tgc5c_xrb_nn.h> #include <iss/arch/tgc5c_xrb_nn.h>
using tgc5c_xrb_nn_plat_type = iss::arch::hwl<iss::arch::riscv_hart_m_p<iss::arch::tgc5c_xrb_nn>>; using tgc5c_xrb_nn_plat_type = iss::arch::hwl<iss::arch::riscv_hart_m_p<iss::arch::tgc5c_xrb_nn>>;
#endif #endif
#ifdef CORE_TGC5D #ifdef CORE_TGC5D
#include "riscv_hart_mu_p.h" #include "riscv_hart_mu_p.h"
#include <iss/arch/tgc5d.h> #include <iss/arch/tgc5d.h>
using tgc5d_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5d, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>; using tgc5d_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5d, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC |
iss::arch::FEAT_EXT_N)>;
#endif #endif
#ifdef CORE_TGC5D_XRB_MAC #ifdef CORE_TGC5D_XRB_MAC
#include "riscv_hart_mu_p.h" #include "riscv_hart_mu_p.h"
#include <iss/arch/tgc5d_xrb_mac.h> #include <iss/arch/tgc5d_xrb_mac.h>
using tgc5d_xrb_mac_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5d_xrb_mac, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>; using tgc5d_xrb_mac_plat_type =
iss::arch::riscv_hart_mu_p<iss::arch::tgc5d_xrb_mac,
(iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>;
#endif #endif
#ifdef CORE_TGC5D_XRB_NN #ifdef CORE_TGC5D_XRB_NN
#include "riscv_hart_mu_p.h"
#include "hwl.h" #include "hwl.h"
#include "riscv_hart_mu_p.h"
#include <iss/arch/tgc5d_xrb_nn.h> #include <iss/arch/tgc5d_xrb_nn.h>
using tgc5d_xrb_nn_plat_type = iss::arch::hwl<iss::arch::riscv_hart_mu_p<iss::arch::tgc5d_xrb_nn, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>>; using tgc5d_xrb_nn_plat_type =
iss::arch::hwl<iss::arch::riscv_hart_mu_p<iss::arch::tgc5d_xrb_nn,
(iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>>;
#endif #endif
#ifdef CORE_TGC5E #ifdef CORE_TGC5E
#include "riscv_hart_mu_p.h" #include "riscv_hart_mu_p.h"
#include <iss/arch/tgc5e.h> #include <iss/arch/tgc5e.h>
using tgc5e_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5e, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>; using tgc5e_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5e, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC |
iss::arch::FEAT_EXT_N)>;
#endif #endif
#ifdef CORE_TGC5X #ifdef CORE_TGC5X
#include "riscv_hart_mu_p.h" #include "riscv_hart_mu_p.h"
#include <iss/arch/tgc5x.h> #include <iss/arch/tgc5x.h>
using tgc5x_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5x, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N | iss::arch::FEAT_TCM)>; using tgc5x_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5x, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC |
iss::arch::FEAT_EXT_N | iss::arch::FEAT_TCM)>;
#endif #endif
#endif #endif

View File

@ -36,10 +36,10 @@
#define _RISCV_HART_M_P_WT_CACHE_H #define _RISCV_HART_M_P_WT_CACHE_H
#include <iss/vm_types.h> #include <iss/vm_types.h>
#include <util/ities.h>
#include <vector>
#include <map> #include <map>
#include <memory> #include <memory>
#include <util/ities.h>
#include <vector>
namespace iss { namespace iss {
namespace arch { namespace arch {
@ -50,11 +50,13 @@ struct line {
uint64_t tag_addr{0}; uint64_t tag_addr{0};
state st{state::INVALID}; state st{state::INVALID};
std::vector<uint8_t> data; std::vector<uint8_t> data;
line(unsigned line_sz): data(line_sz) {} line(unsigned line_sz)
: data(line_sz) {}
}; };
struct set { struct set {
std::vector<line> ways; std::vector<line> ways;
set(unsigned ways_count, line const& l): ways(ways_count, l) {} set(unsigned ways_count, line const& l)
: ways(ways_count, l) {}
}; };
struct cache { struct cache {
std::vector<set> sets; std::vector<set> sets;
@ -69,7 +71,7 @@ struct cache {
struct wt_policy { struct wt_policy {
bool is_cacheline_hit(cache& c); bool is_cacheline_hit(cache& c);
}; };
} } // namespace cache
// write thru, allocate on read, direct mapped or set-associative with round-robin replacement policy // write thru, allocate on read, direct mapped or set-associative with round-robin replacement policy
template <typename BASE> class wt_cache : public BASE { template <typename BASE> class wt_cache : public BASE {
@ -89,6 +91,7 @@ public:
unsigned ways{1}; unsigned ways{1};
uint64_t io_address{0xf0000000}; uint64_t io_address{0xf0000000};
uint64_t io_addr_mask{0xf0000000}; uint64_t io_addr_mask{0xf0000000};
protected: protected:
iss::status read_cache(phys_addr_t addr, unsigned, uint8_t* const); iss::status read_cache(phys_addr_t addr, unsigned, uint8_t* const);
iss::status write_cache(phys_addr_t addr, unsigned, uint8_t const* const); iss::status write_cache(phys_addr_t addr, unsigned, uint8_t const* const);
@ -96,18 +99,14 @@ protected:
std::function<mem_write_f> cache_mem_wr_delegate; std::function<mem_write_f> cache_mem_wr_delegate;
std::unique_ptr<cache::cache> dcache_ptr; std::unique_ptr<cache::cache> dcache_ptr;
std::unique_ptr<cache::cache> icache_ptr; std::unique_ptr<cache::cache> icache_ptr;
size_t get_way_select() { size_t get_way_select() { return 0; }
return 0;
}
}; };
template <typename BASE> template <typename BASE>
inline wt_cache<BASE>::wt_cache(feature_config cfg) inline wt_cache<BASE>::wt_cache(feature_config cfg)
: BASE(cfg) : BASE(cfg)
, io_address{cfg.io_address} , io_address{cfg.io_address}
, io_addr_mask{cfg.io_addr_mask} , io_addr_mask{cfg.io_addr_mask} {
{
auto cb = base_class::replace_mem_access( auto cb = base_class::replace_mem_access(
[this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return read_cache(a, l, d); }, [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return read_cache(a, l, d); },
[this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return write_cache(a, l, d); }); [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return write_cache(a, l, d); });
@ -115,8 +114,7 @@ inline wt_cache<BASE>::wt_cache(feature_config cfg)
cache_mem_wr_delegate = cb.second; cache_mem_wr_delegate = cb.second;
} }
template<typename BASE> template <typename BASE> iss::status iss::arch::wt_cache<BASE>::read_cache(phys_addr_t a, unsigned l, uint8_t* const d) {
iss::status iss::arch::wt_cache<BASE>::read_cache(phys_addr_t a, unsigned l, uint8_t* const d) {
if(!icache_ptr) { if(!icache_ptr) {
icache_ptr.reset(new cache::cache(size, line_sz, ways)); icache_ptr.reset(new cache::cache(size, line_sz, ways));
dcache_ptr.reset(new cache::cache(size, line_sz, ways)); dcache_ptr.reset(new cache::cache(size, line_sz, ways));
@ -147,8 +145,7 @@ iss::status iss::arch::wt_cache<BASE>::read_cache(phys_addr_t a, unsigned l, uin
return cache_mem_rd_delegate(a, l, d); return cache_mem_rd_delegate(a, l, d);
} }
template<typename BASE> template <typename BASE> iss::status iss::arch::wt_cache<BASE>::write_cache(phys_addr_t a, unsigned l, const uint8_t* const d) {
iss::status iss::arch::wt_cache<BASE>::write_cache(phys_addr_t a, unsigned l, const uint8_t* const d) {
if(!dcache_ptr) if(!dcache_ptr)
dcache_ptr.reset(new cache::cache(size, line_sz, ways)); dcache_ptr.reset(new cache::cache(size, line_sz, ways));
auto res = cache_mem_wr_delegate(a, l, d); auto res = cache_mem_wr_delegate(a, l, d);
@ -168,8 +165,6 @@ iss::status iss::arch::wt_cache<BASE>::write_cache(phys_addr_t a, unsigned l, co
return res; return res;
} }
} // namespace arch } // namespace arch
} // namespace iss } // namespace iss

View File

@ -84,8 +84,7 @@ public:
target byte order. If register is not available target byte order. If register is not available
corresponding bytes in avail_buf are 0, otherwise corresponding bytes in avail_buf are 0, otherwise
avail buf is 1 */ avail buf is 1 */
status read_single_register(unsigned int reg_no, std::vector<uint8_t> &buf, status read_single_register(unsigned int reg_no, std::vector<uint8_t>& buf, std::vector<uint8_t>& avail_buf) override;
std::vector<uint8_t> &avail_buf) override;
/* Write one register. buf is 4-byte aligned and it is in target byte /* Write one register. buf is 4-byte aligned and it is in target byte
order */ order */
@ -103,8 +102,8 @@ public:
status process_query(unsigned int& mask, const rp_thread_ref& arg, rp_thread_info& info) override; status process_query(unsigned int& mask, const rp_thread_ref& arg, rp_thread_info& info) override;
status thread_list_query(int first, const rp_thread_ref &arg, std::vector<rp_thread_ref> &result, size_t max_num, status thread_list_query(int first, const rp_thread_ref& arg, std::vector<rp_thread_ref>& result, size_t max_num, size_t& num,
size_t &num, bool &done) override; bool& done) override;
status current_thread_query(rp_thread_ref& thread) override; status current_thread_query(rp_thread_ref& thread) override;
@ -124,8 +123,7 @@ public:
status remove_break(break_type type, uint64_t addr, unsigned int length) override; status remove_break(break_type type, uint64_t addr, unsigned int length) override;
status resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread, status resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread, std::function<void(unsigned)> stop_callback) override;
std::function<void(unsigned)> stop_callback) override;
status target_xml_query(std::string& out_buf) override; status target_xml_query(std::string& out_buf) override;
@ -158,9 +156,8 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::is_thread_alive(rp_t
* set if all threads are processed. * set if all threads are processed.
*/ */
template <typename ARCH> template <typename ARCH>
status riscv_target_adapter<ARCH>::thread_list_query(int first, const rp_thread_ref &arg, status riscv_target_adapter<ARCH>::thread_list_query(int first, const rp_thread_ref& arg, std::vector<rp_thread_ref>& result,
std::vector<rp_thread_ref> &result, size_t max_num, size_t &num, size_t max_num, size_t& num, bool& done) {
bool &done) {
if(first == 0) { if(first == 0) {
result.clear(); result.clear();
result.push_back(thread_idx); result.push_back(thread_idx);
@ -176,8 +173,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::current_thread_query
return Ok; return Ok;
} }
template <typename ARCH> template <typename ARCH> status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t> &data, std::vector<uint8_t> &avail) {
LOG(TRACE) << "reading target registers"; LOG(TRACE) << "reading target registers";
// return idx<0?:; // return idx<0?:;
data.clear(); data.clear();
@ -239,8 +235,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::write_registers(cons
} }
template <typename ARCH> template <typename ARCH>
status riscv_target_adapter<ARCH>::read_single_register(unsigned int reg_no, std::vector<uint8_t> &data, status riscv_target_adapter<ARCH>::read_single_register(unsigned int reg_no, std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
std::vector<uint8_t> &avail) {
if(reg_no < 65) { if(reg_no < 65) {
// auto reg_size = arch::traits<ARCH>::reg_bit_width(static_cast<typename // auto reg_size = arch::traits<ARCH>::reg_bit_width(static_cast<typename
// arch::traits<ARCH>::reg_e>(reg_no))/8; // arch::traits<ARCH>::reg_e>(reg_no))/8;
@ -261,8 +256,7 @@ status riscv_target_adapter<ARCH>::read_single_register(unsigned int reg_no, std
return data.size() > 0 ? Ok : Err; return data.size() > 0 ? Ok : Err;
} }
template <typename ARCH> template <typename ARCH> status riscv_target_adapter<ARCH>::write_single_register(unsigned int reg_no, const std::vector<uint8_t>& data) {
status riscv_target_adapter<ARCH>::write_single_register(unsigned int reg_no, const std::vector<uint8_t> &data) {
if(reg_no < 65) { if(reg_no < 65) {
auto* reg_base = core->get_regs_base_ptr(); auto* reg_base = core->get_regs_base_ptr();
auto reg_width = arch::traits<ARCH>::reg_bit_widths[static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)] / 8; auto reg_width = arch::traits<ARCH>::reg_bit_widths[static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)] / 8;
@ -292,21 +286,16 @@ status riscv_target_adapter<ARCH>::process_query(unsigned int &mask, const rp_th
return NotSupported; return NotSupported;
} }
template <typename ARCH> template <typename ARCH> status riscv_target_adapter<ARCH>::offsets_query(uint64_t& text, uint64_t& data, uint64_t& bss) {
status riscv_target_adapter<ARCH>::offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) {
text = 0; text = 0;
data = 0; data = 0;
bss = 0; bss = 0;
return Ok; return Ok;
} }
template <typename ARCH> status riscv_target_adapter<ARCH>::crc_query(uint64_t addr, size_t len, uint32_t &val) { template <typename ARCH> status riscv_target_adapter<ARCH>::crc_query(uint64_t addr, size_t len, uint32_t& val) { return NotSupported; }
return NotSupported;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::raw_query(std::string in_buf, std::string &out_buf) { template <typename ARCH> status riscv_target_adapter<ARCH>::raw_query(std::string in_buf, std::string& out_buf) { return NotSupported; }
return NotSupported;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::threadinfo_query(int first, std::string& out_buf) { template <typename ARCH> status riscv_target_adapter<ARCH>::threadinfo_query(int first, std::string& out_buf) {
if(first) { if(first) {
@ -317,8 +306,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::threadinfo_query(int
return Ok; return Ok;
} }
template <typename ARCH> template <typename ARCH> status riscv_target_adapter<ARCH>::threadextrainfo_query(const rp_thread_ref& thread, std::string& out_buf) {
status riscv_target_adapter<ARCH>::threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) {
std::array<char, 20> buf; std::array<char, 20> buf;
memset(buf.data(), 0, 20); memset(buf.data(), 0, 20);
sprintf(buf.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x", 'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0); sprintf(buf.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x", 'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0);
@ -340,8 +328,8 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::add_break(break_type
auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr}); auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr});
auto eaddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr + length}); auto eaddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr + length});
target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val); target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val);
LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex << saddr.val
<< saddr.val << std::dec; << std::dec;
LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
return Ok; return Ok;
} }
@ -357,8 +345,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::remove_break(break_t
auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr}); auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr});
unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val); unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val);
if(handle) { if(handle) {
LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val << std::dec;
<< std::dec;
// TODO: check length of addr range // TODO: check length of addr range
target_adapter_base::bp_lut.removeEntry(handle); target_adapter_base::bp_lut.removeEntry(handle);
LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
@ -468,7 +455,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::target_xml_query(std
</target> </target>
*/ */
} } // namespace debugger
} } // namespace iss
#endif /* _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_ */ #endif /* _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_ */

View File

@ -33,12 +33,12 @@
#ifndef _ISS_FACTORY_H_ #ifndef _ISS_FACTORY_H_
#define _ISS_FACTORY_H_ #define _ISS_FACTORY_H_
#include <algorithm>
#include <functional>
#include <iss/iss.h> #include <iss/iss.h>
#include <memory> #include <memory>
#include <unordered_map>
#include <functional>
#include <string> #include <string>
#include <algorithm> #include <unordered_map>
#include <vector> #include <vector>
namespace iss { namespace iss {
@ -46,8 +46,7 @@ namespace iss {
using cpu_ptr = std::unique_ptr<iss::arch_if>; using cpu_ptr = std::unique_ptr<iss::arch_if>;
using vm_ptr = std::unique_ptr<iss::vm_if>; using vm_ptr = std::unique_ptr<iss::vm_if>;
template<typename PLAT> template <typename PLAT> std::tuple<cpu_ptr, vm_ptr> create_cpu(std::string const& backend, unsigned gdb_port) {
std::tuple<cpu_ptr, vm_ptr> create_cpu(std::string const& backend, unsigned gdb_port){
using core_type = typename PLAT::core; using core_type = typename PLAT::core;
core_type* lcpu = new PLAT(); core_type* lcpu = new PLAT();
if(backend == "interp") if(backend == "interp")
@ -63,7 +62,6 @@ std::tuple<cpu_ptr, vm_ptr> create_cpu(std::string const& backend, unsigned gdb_
return {nullptr, nullptr}; return {nullptr, nullptr};
} }
class core_factory { class core_factory {
using cpu_ptr = std::unique_ptr<iss::arch_if>; using cpu_ptr = std::unique_ptr<iss::arch_if>;
using vm_ptr = std::unique_ptr<iss::vm_if>; using vm_ptr = std::unique_ptr<iss::vm_if>;
@ -78,7 +76,10 @@ class core_factory {
core_factory& operator=(const core_factory&) = delete; core_factory& operator=(const core_factory&) = delete;
public: public:
static core_factory & instance() { static core_factory bf; return bf; } static core_factory& instance() {
static core_factory bf;
return bf;
}
bool register_creator(const std::string& className, create_fn const& fn) { bool register_creator(const std::string& className, create_fn const& fn) {
registry[className] = fn; registry[className] = fn;
@ -94,13 +95,12 @@ public:
std::vector<std::string> get_names() { std::vector<std::string> get_names() {
std::vector<std::string> keys{registry.size()}; std::vector<std::string> keys{registry.size()};
std::transform(std::begin(registry), std::end(registry), std::begin(keys), [](std::pair<std::string, create_fn> const& p){ std::transform(std::begin(registry), std::end(registry), std::begin(keys),
return p.first; [](std::pair<std::string, create_fn> const& p) { return p.first; });
});
return keys; return keys;
} }
}; };
} } // namespace iss
#endif /* _ISS_FACTORY_H_ */ #endif /* _ISS_FACTORY_H_ */

View File

@ -36,17 +36,15 @@
#include <iss/plugin/calculator.h> #include <iss/plugin/calculator.h>
#include <yaml-cpp/yaml.h> #include <yaml-cpp/yaml.h>
#include <fstream>
#include <iss/arch_if.h> #include <iss/arch_if.h>
#include <util/logging.h> #include <util/logging.h>
#include <fstream>
using namespace std; using namespace std;
iss::plugin::cycle_estimate::cycle_estimate(string const& config_file_name) iss::plugin::cycle_estimate::cycle_estimate(string const& config_file_name)
: instr_if(nullptr) : instr_if(nullptr)
, config_file_name(config_file_name) , config_file_name(config_file_name) {}
{
}
iss::plugin::cycle_estimate::~cycle_estimate() = default; iss::plugin::cycle_estimate::~cycle_estimate() = default;
@ -54,7 +52,8 @@ bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if&
instr_if = vm.get_arch()->get_instrumentation_if(); instr_if = vm.get_arch()->get_instrumentation_if();
assert(instr_if && "No instrumentation interface available but callback executed"); assert(instr_if && "No instrumentation interface available but callback executed");
reg_base_ptr = reinterpret_cast<uint32_t*>(vm.get_arch()->get_regs_base_ptr()); reg_base_ptr = reinterpret_cast<uint32_t*>(vm.get_arch()->get_regs_base_ptr());
if(!instr_if) return false; if(!instr_if)
return false;
const string core_name = instr_if->core_type_name(); const string core_name = instr_if->core_type_name();
if(config_file_name.length() > 0) { if(config_file_name.length() > 0) {
std::ifstream is(config_file_name); std::ifstream is(config_file_name);

View File

@ -37,10 +37,10 @@
#include "iss/instrumentation_if.h" #include "iss/instrumentation_if.h"
#include "iss/vm_plugin.h" #include "iss/vm_plugin.h"
#include <functional>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include <functional>
namespace iss { namespace iss {
@ -91,7 +91,7 @@ private:
std::unordered_map<std::pair<uint64_t, uint64_t>, uint64_t, pair_hash> blocks; std::unordered_map<std::pair<uint64_t, uint64_t>, uint64_t, pair_hash> blocks;
std::string config_file_name; std::string config_file_name;
}; };
} } // namespace plugin
} } // namespace iss
#endif /* _ISS_PLUGIN_CYCLE_ESTIMATE_H_ */ #endif /* _ISS_PLUGIN_CYCLE_ESTIMATE_H_ */

View File

@ -36,9 +36,9 @@
#include <iss/instrumentation_if.h> #include <iss/instrumentation_if.h>
#include <yaml-cpp/yaml.h> #include <yaml-cpp/yaml.h>
#include <fstream>
#include <iss/arch_if.h> #include <iss/arch_if.h>
#include <util/logging.h> #include <util/logging.h>
#include <fstream>
iss::plugin::instruction_count::instruction_count(std::string config_file_name) { iss::plugin::instruction_count::instruction_count(std::string config_file_name) {
if(config_file_name.length() > 0) { if(config_file_name.length() > 0) {
@ -88,10 +88,9 @@ iss::plugin::instruction_count::~instruction_count() {
bool iss::plugin::instruction_count::registration(const char* const version, vm_if& vm) { bool iss::plugin::instruction_count::registration(const char* const version, vm_if& vm) {
auto instr_if = vm.get_arch()->get_instrumentation_if(); auto instr_if = vm.get_arch()->get_instrumentation_if();
if(!instr_if) return false; if(!instr_if)
return false;
return true; return true;
} }
void iss::plugin::instruction_count::callback(instr_info_t instr_info) { void iss::plugin::instruction_count::callback(instr_info_t instr_info) { rep_counts[instr_info.instr_id]++; }
rep_counts[instr_info.instr_id]++;
}

View File

@ -75,7 +75,7 @@ private:
std::vector<instr_delay> delays; std::vector<instr_delay> delays;
std::vector<uint64_t> rep_counts; std::vector<uint64_t> rep_counts;
}; };
} } // namespace plugin
} } // namespace iss
#endif /* _ISS_PLUGIN_INSTRUCTION_COUNTER_H_ */ #endif /* _ISS_PLUGIN_INSTRUCTION_COUNTER_H_ */

View File

@ -30,20 +30,20 @@
* *
*******************************************************************************/ *******************************************************************************/
#include <iostream>
#include <vector>
#include <array> #include <array>
#include <iostream>
#include <iss/factory.h> #include <iss/factory.h>
#include <vector>
#include "iss/arch/tgc_mapper.h"
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include "iss/arch/tgc_mapper.h"
#ifdef WITH_LLVM #ifdef WITH_LLVM
#include <iss/llvm/jit_init.h> #include <iss/llvm/jit_init.h>
#endif #endif
#include <iss/log_categories.h>
#include "iss/plugin/cycle_estimate.h" #include "iss/plugin/cycle_estimate.h"
#include "iss/plugin/instruction_count.h" #include "iss/plugin/instruction_count.h"
#include <iss/log_categories.h>
#ifndef WIN32 #ifndef WIN32
#include <iss/plugin/loader.h> #include <iss/plugin/loader.h>
#endif #endif
@ -196,11 +196,13 @@ int main(int argc, char *argv[]) {
if(clim.count("elf")) if(clim.count("elf"))
for(std::string input : clim["elf"].as<std::vector<std::string>>()) { for(std::string input : clim["elf"].as<std::vector<std::string>>()) {
auto start_addr = vm->get_arch()->load_file(input); auto start_addr = vm->get_arch()->load_file(input);
if (start_addr.second) start_address = start_addr.first; if(start_addr.second)
start_address = start_addr.first;
} }
for(std::string input : args) { for(std::string input : args) {
auto start_addr = vm->get_arch()->load_file(input); // treat remaining arguments as elf files auto start_addr = vm->get_arch()->load_file(input); // treat remaining arguments as elf files
if (start_addr.second) start_address = start_addr.first; if(start_addr.second)
start_address = start_addr.first;
} }
if(clim.count("reset")) { if(clim.count("reset")) {
auto str = clim["reset"].as<std::string>(); auto str = clim["reset"].as<std::string>();
@ -210,8 +212,7 @@ int main(int argc, char *argv[]) {
auto cycles = clim["instructions"].as<uint64_t>(); auto cycles = clim["instructions"].as<uint64_t>();
res = vm->start(cycles, dump); res = vm->start(cycles, dump);
} catch(std::exception& e) { } catch(std::exception& e) {
LOG(ERR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" LOG(ERR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" << std::endl;
<< std::endl;
res = 2; res = 2;
} }
// cleanup to let plugins report of needed // cleanup to let plugins report of needed

View File

@ -56,7 +56,9 @@
#define STR(X) #X #define STR(X) #X
#define CREATE_CORE(CN) \ #define CREATE_CORE(CN) \
if (type == STR(CN)) { std::tie(cpu, vm) = create_core<CN ## _plat_type>(backend, gdb_port, hart_id); } else if(type == STR(CN)) { \
std::tie(cpu, vm) = create_core<CN##_plat_type>(backend, gdb_port, hart_id); \
} else
#ifdef HAS_SCV #ifdef HAS_SCV
#include <scv.h> #include <scv.h>
@ -87,10 +89,9 @@ using namespace sc_core;
namespace { namespace {
iss::debugger::encoder_decoder encdec; iss::debugger::encoder_decoder encdec;
std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}}; std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
} } // namespace
int cmd_sysc(int argc, char *argv[], debugger::out_func of, debugger::data_func df, int cmd_sysc(int argc, char* argv[], debugger::out_func of, debugger::data_func df, debugger::target_adapter_if* tgt_adapter) {
debugger::target_adapter_if *tgt_adapter) {
if(argc > 1) { if(argc > 1) {
if(strcasecmp(argv[1], "print_time") == 0) { if(strcasecmp(argv[1], "print_time") == 0) {
std::string t = sc_time_stamp().to_string(); std::string t = sc_time_stamp().to_string();
@ -124,13 +125,15 @@ using vm_ptr= std::unique_ptr<iss::vm_if>;
class core_wrapper { class core_wrapper {
public: public:
core_wrapper(core_complex *owner) : owner(owner) { } core_wrapper(core_complex* owner)
: owner(owner) {}
void reset(uint64_t addr) { vm->reset(addr); } void reset(uint64_t addr) { vm->reset(addr); }
inline void start(bool dump = false) { vm->start(std::numeric_limits<uint64_t>::max(), dump); } inline void start(bool dump = false) { vm->start(std::numeric_limits<uint64_t>::max(), dump); }
inline std::pair<uint64_t, bool> load_file(std::string const& name) { inline std::pair<uint64_t, bool> load_file(std::string const& name) {
iss::arch_if* cc = cpu->get_arch_if(); iss::arch_if* cc = cpu->get_arch_if();
return cc->load_file(name);}; return cc->load_file(name);
};
std::function<unsigned(void)> get_mode; std::function<unsigned(void)> get_mode;
std::function<uint64_t(void)> get_state; std::function<uint64_t(void)> get_state;
@ -168,13 +171,14 @@ public:
local_irq = [sc_cpu_if](short s, bool b) { return sc_cpu_if->local_irq(s, b); }; local_irq = [sc_cpu_if](short s, bool b) { return sc_cpu_if->local_irq(s, b); };
auto* srv = debugger::server<debugger::gdb_session>::get(); auto* srv = debugger::server<debugger::gdb_session>::get();
if (srv) tgt_adapter = srv->get_target(); if(srv)
tgt_adapter = srv->get_target();
if(tgt_adapter) if(tgt_adapter)
tgt_adapter->add_custom_command( tgt_adapter->add_custom_command({"sysc",
{"sysc", [this](int argc, char *argv[], debugger::out_func of, [this](int argc, char* argv[], debugger::out_func of, debugger::data_func df) -> int {
debugger::data_func df) -> int { return cmd_sysc(argc, argv, of, df, tgt_adapter); }, return cmd_sysc(argc, argv, of, df, tgt_adapter);
},
"SystemC sub-commands: break <time>, print_time"}); "SystemC sub-commands: break <time>, print_time"});
} }
core_complex* const owner; core_complex* const owner;
@ -199,8 +203,7 @@ core_complex::core_complex(sc_module_name const& name)
: sc_module(name) : sc_module(name)
, fetch_lut(tlm_dmi_ext()) , fetch_lut(tlm_dmi_ext())
, read_lut(tlm_dmi_ext()) , read_lut(tlm_dmi_ext())
, write_lut(tlm_dmi_ext()) , write_lut(tlm_dmi_ext()) {
{
init(); init();
} }
#endif #endif
@ -297,7 +300,6 @@ void core_complex::before_end_of_elaboration() {
} }
} }
} }
} }
void core_complex::start_of_simulation() { void core_complex::start_of_simulation() {
@ -324,8 +326,10 @@ void core_complex::start_of_simulation() {
} }
bool core_complex::disass_output(uint64_t pc, const std::string instr_str) { bool core_complex::disass_output(uint64_t pc, const std::string instr_str) {
if (trc->m_db == nullptr) return false; if(trc->m_db == nullptr)
if (trc->tr_handle.is_active()) trc->tr_handle.end_transaction(); return false;
if(trc->tr_handle.is_active())
trc->tr_handle.end_transaction();
trc->tr_handle = trc->instr_tr_handle->begin_transaction(); trc->tr_handle = trc->instr_tr_handle->begin_transaction();
trc->tr_handle.record_attribute("PC", pc); trc->tr_handle.record_attribute("PC", pc);
trc->tr_handle.record_attribute("INSTR", instr_str); trc->tr_handle.record_attribute("INSTR", instr_str);
@ -346,11 +350,13 @@ void core_complex::forward() {
void core_complex::set_clock_period(sc_core::sc_time period) { void core_complex::set_clock_period(sc_core::sc_time period) {
curr_clk = period; curr_clk = period;
if (period == SC_ZERO_TIME) cpu->set_interrupt_execution(true); if(period == SC_ZERO_TIME)
cpu->set_interrupt_execution(true);
} }
void core_complex::rst_cb() { void core_complex::rst_cb() {
if (rst_i.read()) cpu->set_interrupt_execution(true); if(rst_i.read())
cpu->set_interrupt_execution(true);
} }
void core_complex::sw_irq_cb() { cpu->local_irq(3, sw_irq_i.read()); } void core_complex::sw_irq_cb() { cpu->local_irq(3, sw_irq_i.read()); }
@ -423,7 +429,8 @@ bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data,
else else
dbus_inc += incr; dbus_inc += incr;
} }
SCCTRACE(this->name()) << "[local time: "<<delay<<"]: finish read_mem(0x" << std::hex << addr << ") : 0x" << (length==4?*(uint32_t*)data:length==2?*(uint16_t*)data:(unsigned)*data); SCCTRACE(this->name()) << "[local time: " << delay << "]: finish read_mem(0x" << std::hex << addr << ") : 0x"
<< (length == 4 ? *(uint32_t*)data : length == 2 ? *(uint16_t*)data : (unsigned)*data);
if(gp.get_response_status() != tlm::TLM_OK_RESPONSE) { if(gp.get_response_status() != tlm::TLM_OK_RESPONSE) {
return false; return false;
} }
@ -433,8 +440,7 @@ bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data,
tlm_dmi_ext dmi_data; tlm_dmi_ext dmi_data;
if(sckt->get_direct_mem_ptr(gp, dmi_data)) { if(sckt->get_direct_mem_ptr(gp, dmi_data)) {
if(dmi_data.is_read_allowed()) if(dmi_data.is_read_allowed())
dmi_lut.addEntry(dmi_data, dmi_data.get_start_address(), dmi_lut.addEntry(dmi_data, dmi_data.get_start_address(), dmi_data.get_end_address() - dmi_data.get_start_address() + 1);
dmi_data.get_end_address() - dmi_data.get_start_address() + 1);
} }
} }
return true; return true;
@ -443,8 +449,7 @@ bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data,
bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t* const data) { bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t* const data) {
auto lut_entry = write_lut.getEntry(addr); auto lut_entry = write_lut.getEntry(addr);
if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && if(lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && addr + length <= lut_entry.get_end_address() + 1) {
addr + length <= lut_entry.get_end_address() + 1) {
auto offset = addr - lut_entry.get_start_address(); auto offset = addr - lut_entry.get_start_address();
std::copy(data, data + length, lut_entry.get_dmi_ptr() + offset); std::copy(data, data + length, lut_entry.get_dmi_ptr() + offset);
dbus_inc += lut_entry.get_write_latency() / curr_clk; dbus_inc += lut_entry.get_write_latency() / curr_clk;
@ -469,7 +474,8 @@ bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t *cons
quantum_keeper.reset(); quantum_keeper.reset();
else else
dbus_inc += (delay - quantum_keeper.get_local_time()) / curr_clk; dbus_inc += (delay - quantum_keeper.get_local_time()) / curr_clk;
SCCTRACE() << "[local time: "<<delay<<"]: finish write_mem(0x" << std::hex << addr << ") : 0x" << (length==4?*(uint32_t*)data:length==2?*(uint16_t*)data:(unsigned)*data); SCCTRACE() << "[local time: " << delay << "]: finish write_mem(0x" << std::hex << addr << ") : 0x"
<< (length == 4 ? *(uint32_t*)data : length == 2 ? *(uint16_t*)data : (unsigned)*data);
if(gp.get_response_status() != tlm::TLM_OK_RESPONSE) { if(gp.get_response_status() != tlm::TLM_OK_RESPONSE) {
return false; return false;
} }

View File

@ -33,10 +33,10 @@
#ifndef _SYSC_CORE_COMPLEX_H_ #ifndef _SYSC_CORE_COMPLEX_H_
#define _SYSC_CORE_COMPLEX_H_ #define _SYSC_CORE_COMPLEX_H_
#include <tlm/scc/initiator_mixin.h>
#include <scc/traceable.h>
#include <scc/tick2time.h> #include <scc/tick2time.h>
#include <scc/traceable.h>
#include <scc/utilities.h> #include <scc/utilities.h>
#include <tlm/scc/initiator_mixin.h>
#include <tlm/scc/scv/tlm_rec_initiator_socket.h> #include <tlm/scc/scv/tlm_rec_initiator_socket.h>
#ifdef CWR_SYSTEMC #ifdef CWR_SYSTEMC
#include <scmlinc/scml_property.h> #include <scmlinc/scml_property.h>
@ -45,10 +45,10 @@
#include <cci_configuration> #include <cci_configuration>
#define SOCKET_WIDTH scc::LT #define SOCKET_WIDTH scc::LT
#endif #endif
#include <memory>
#include <tlm> #include <tlm>
#include <tlm_utils/tlm_quantumkeeper.h> #include <tlm_utils/tlm_quantumkeeper.h>
#include <util/range_lut.h> #include <util/range_lut.h>
#include <memory>
namespace iss { namespace iss {
class vm_plugin; class vm_plugin;
@ -58,8 +58,8 @@ namespace sysc {
class tlm_dmi_ext : public tlm::tlm_dmi { class tlm_dmi_ext : public tlm::tlm_dmi {
public: public:
bool operator==(const tlm_dmi_ext& o) const { bool operator==(const tlm_dmi_ext& o) const {
return this->get_granted_access() == o.get_granted_access() && return this->get_granted_access() == o.get_granted_access() && this->get_start_address() == o.get_start_address() &&
this->get_start_address() == o.get_start_address() && this->get_end_address() == o.get_end_address(); this->get_end_address() == o.get_end_address();
} }
bool operator!=(const tlm_dmi_ext& o) const { return !operator==(o); } bool operator!=(const tlm_dmi_ext& o) const { return !operator==(o); }
@ -151,8 +151,7 @@ public:
, plugins{"plugins", ""} , plugins{"plugins", ""}
, fetch_lut(tlm_dmi_ext()) , fetch_lut(tlm_dmi_ext())
, read_lut(tlm_dmi_ext()) , read_lut(tlm_dmi_ext())
, write_lut(tlm_dmi_ext()) , write_lut(tlm_dmi_ext()) {
{
init(); init();
} }
@ -160,7 +159,6 @@ public:
~core_complex(); ~core_complex();
inline unsigned get_last_bus_cycles() { inline unsigned get_last_bus_cycles() {
auto mem_incr = std::max(ibus_inc, dbus_inc); auto mem_incr = std::max(ibus_inc, dbus_inc);
ibus_inc = dbus_inc = 0; ibus_inc = dbus_inc = 0;
@ -190,6 +188,7 @@ public:
bool disass_output(uint64_t pc, const std::string instr); bool disass_output(uint64_t pc, const std::string instr);
void set_clock_period(sc_core::sc_time period); void set_clock_period(sc_core::sc_time period);
protected: protected:
void before_end_of_elaboration() override; void before_end_of_elaboration() override;
void start_of_simulation() override; void start_of_simulation() override;
@ -209,10 +208,10 @@ protected:
uint64_t ibus_inc{0}, dbus_inc{0}; uint64_t ibus_inc{0}, dbus_inc{0};
core_trace* trc{nullptr}; core_trace* trc{nullptr};
std::unique_ptr<scc::tick2time> t2t; std::unique_ptr<scc::tick2time> t2t;
private: private:
void init(); void init();
std::vector<iss::vm_plugin*> plugin_list; std::vector<iss::vm_plugin*> plugin_list;
}; };
} /* namespace tgfs */ } /* namespace tgfs */
} /* namespace sysc */ } /* namespace sysc */

View File

@ -33,13 +33,13 @@
#ifndef _ISS_FACTORY_H_ #ifndef _ISS_FACTORY_H_
#define _ISS_FACTORY_H_ #define _ISS_FACTORY_H_
#include <iss/iss.h>
#include "sc_core_adapter_if.h" #include "sc_core_adapter_if.h"
#include <memory>
#include <unordered_map>
#include <functional>
#include <string>
#include <algorithm> #include <algorithm>
#include <functional>
#include <iss/iss.h>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector> #include <vector>
namespace sysc { namespace sysc {
@ -57,7 +57,10 @@ public:
iss_factory(const iss_factory&) = delete; iss_factory(const iss_factory&) = delete;
iss_factory& operator=(const iss_factory&) = delete; iss_factory& operator=(const iss_factory&) = delete;
static iss_factory & instance() { static iss_factory bf; return bf; } static iss_factory& instance() {
static iss_factory bf;
return bf;
}
bool register_creator(const std::string& className, create_fn const& fn) { bool register_creator(const std::string& className, create_fn const& fn) {
registry[className] = fn; registry[className] = fn;
@ -73,16 +76,15 @@ public:
std::vector<std::string> get_names() { std::vector<std::string> get_names() {
std::vector<std::string> keys{registry.size()}; std::vector<std::string> keys{registry.size()};
std::transform(std::begin(registry), std::end(registry), std::begin(keys), [](std::pair<std::string, create_fn> const& p){ std::transform(std::begin(registry), std::end(registry), std::begin(keys),
return p.first; [](std::pair<std::string, create_fn> const& p) { return p.first; });
});
return keys; return keys;
} }
private: private:
registry_t registry; registry_t registry;
}; };
} } // namespace sysc
#endif /* _ISS_FACTORY_H_ */ #endif /* _ISS_FACTORY_H_ */

View File

@ -30,19 +30,20 @@
* *
*******************************************************************************/ *******************************************************************************/
#include "core_complex.h"
#include "iss_factory.h" #include "iss_factory.h"
#include <iss/arch/tgc5c.h> #include "sc_core_adapter.h"
#include <array>
#include <iss/arch/riscv_hart_m_p.h> #include <iss/arch/riscv_hart_m_p.h>
#include <iss/arch/riscv_hart_mu_p.h> #include <iss/arch/riscv_hart_mu_p.h>
#include "sc_core_adapter.h" #include <iss/arch/tgc5c.h>
#include "core_complex.h"
#include <array>
namespace iss { namespace iss {
namespace interp { namespace interp {
using namespace sysc; using namespace sysc;
volatile std::array<bool, 2> tgc_init = { volatile std::array<bool, 2> tgc_init = {
iss_factory::instance().register_creator("tgc5c|m_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t { iss_factory::instance().register_creator("tgc5c|m_p|interp",
[](unsigned gdb_port, void* data) -> iss_factory::base_t {
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data); auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc); auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}}; return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
@ -51,14 +52,14 @@ volatile std::array<bool, 2> tgc_init = {
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data); auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc); auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}}; return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
}) })};
}; } // namespace interp
}
#if defined(WITH_LLVM) #if defined(WITH_LLVM)
namespace llvm { namespace llvm {
using namespace sysc; using namespace sysc;
volatile std::array<bool, 2> tgc_init = { volatile std::array<bool, 2> tgc_init = {
iss_factory::instance().register_creator("tgc5c|m_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t { iss_factory::instance().register_creator("tgc5c|m_p|llvm",
[](unsigned gdb_port, void* data) -> iss_factory::base_t {
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data); auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc); auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}}; return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
@ -67,15 +68,15 @@ volatile std::array<bool, 2> tgc_init = {
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data); auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc); auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}}; return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
}) })};
}; } // namespace llvm
}
#endif #endif
#if defined(WITH_TCC) #if defined(WITH_TCC)
namespace tcc { namespace tcc {
using namespace sysc; using namespace sysc;
volatile std::array<bool, 2> tgc_init = { volatile std::array<bool, 2> tgc_init = {
iss_factory::instance().register_creator("tgc5c|m_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t { iss_factory::instance().register_creator("tgc5c|m_p|tcc",
[](unsigned gdb_port, void* data) -> iss_factory::base_t {
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data); auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc); auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}}; return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
@ -84,15 +85,15 @@ volatile std::array<bool, 2> tgc_init = {
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data); auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc); auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}}; return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
}) })};
}; } // namespace tcc
}
#endif #endif
#if defined(WITH_ASMJIT) #if defined(WITH_ASMJIT)
namespace asmjit { namespace asmjit {
using namespace sysc; using namespace sysc;
volatile std::array<bool, 2> tgc_init = { volatile std::array<bool, 2> tgc_init = {
iss_factory::instance().register_creator("tgc5c|m_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t { iss_factory::instance().register_creator("tgc5c|m_p|asmjit",
[](unsigned gdb_port, void* data) -> iss_factory::base_t {
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data); auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc); auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}}; return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
@ -101,8 +102,7 @@ volatile std::array<bool, 2> tgc_init = {
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data); auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc); auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}}; return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
}) })};
}; } // namespace asmjit
}
#endif #endif
} } // namespace iss

View File

@ -8,17 +8,15 @@
#ifndef _SYSC_SC_CORE_ADAPTER_H_ #ifndef _SYSC_SC_CORE_ADAPTER_H_
#define _SYSC_SC_CORE_ADAPTER_H_ #define _SYSC_SC_CORE_ADAPTER_H_
#include <scc/report.h>
#include <util/ities.h>
#include "sc_core_adapter_if.h" #include "sc_core_adapter_if.h"
#include <iostream>
#include <iss/iss.h> #include <iss/iss.h>
#include <iss/vm_types.h> #include <iss/vm_types.h>
#include <iostream> #include <scc/report.h>
#include <util/ities.h>
namespace sysc { namespace sysc {
template<typename PLAT> template <typename PLAT> class sc_core_adapter : public PLAT, public sc_core_adapter_if {
class sc_core_adapter : public PLAT, public sc_core_adapter_if {
public: public:
using reg_t = typename iss::arch::traits<typename PLAT::core>::reg_t; using reg_t = typename iss::arch::traits<typename PLAT::core>::reg_t;
using phys_addr_t = typename iss::arch::traits<typename PLAT::core>::phys_addr_t; using phys_addr_t = typename iss::arch::traits<typename PLAT::core>::phys_addr_t;
@ -54,9 +52,8 @@ public:
static constexpr std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}}; static constexpr std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
if(!owner->disass_output(pc, instr)) { if(!owner->disass_output(pc, instr)) {
std::stringstream s; std::stringstream s;
s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0') s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0') << std::setw(sizeof(reg_t) * 2)
<< std::setw(sizeof(reg_t) * 2) << (reg_t)this->state.mstatus << std::dec << ";c:" << (reg_t)this->state.mstatus << std::dec << ";c:" << this->reg.icount + this->cycle_offset << "]";
<< this->reg.icount + this->cycle_offset << "]";
SCCDEBUG(owner->name()) << "disass: " SCCDEBUG(owner->name()) << "disass: "
<< "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40) << "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40)
<< std::setfill(' ') << std::left << instr << s.str(); << std::setfill(' ') << std::left << instr << s.str();
@ -75,20 +72,18 @@ public:
if(addr.access && iss::access_type::DEBUG) if(addr.access && iss::access_type::DEBUG)
return owner->write_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err; return owner->write_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err;
else { else {
auto tohost_upper = (sizeof(reg_t) == 4 && addr.val == (this->tohost + 4)) || auto tohost_upper = (sizeof(reg_t) == 4 && addr.val == (this->tohost + 4)) || (sizeof(reg_t) == 8 && addr.val == this->tohost);
(sizeof(reg_t) == 8 && addr.val == this->tohost); auto tohost_lower = (sizeof(reg_t) == 4 && addr.val == this->tohost) || (sizeof(reg_t) == 64 && addr.val == this->tohost);
auto tohost_lower = (sizeof(reg_t) == 4 && addr.val == this->tohost) ||
(sizeof(reg_t)== 64 && addr.val == this->tohost);
if(tohost_lower || tohost_upper) { if(tohost_lower || tohost_upper) {
if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) {
switch(hostvar >> 48) { switch(hostvar >> 48) {
case 0: case 0:
if(hostvar != 0x1) { if(hostvar != 0x1) {
SCCINFO(owner->name()) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar SCCINFO(owner->name())
<< "), stopping simulation"; << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation";
} else { } else {
SCCINFO(owner->name()) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar SCCINFO(owner->name())
<< "), stopping simulation"; << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation";
} }
this->reg.trap_state = std::numeric_limits<uint32_t>::max(); this->reg.trap_state = std::numeric_limits<uint32_t>::max();
this->interrupt_sim = hostvar; this->interrupt_sim = hostvar;
@ -108,7 +103,8 @@ public:
if(addr.val == 0x2004000) { if(addr.val == 0x2004000) {
reg_t val; reg_t val;
this->read_csr(iss::arch::mip, val); this->read_csr(iss::arch::mip, val);
if (val & (1ULL << 7)) this->write_csr(iss::arch::mip, val & ~(1ULL << 7)); if(val & (1ULL << 7))
this->write_csr(iss::arch::mip, val & ~(1ULL << 7));
} }
return res; return res;
} }
@ -123,7 +119,8 @@ public:
if(addr == iss::arch::time) { if(addr == iss::arch::time) {
val = static_cast<reg_t>(time_val); val = static_cast<reg_t>(time_val);
} else if(addr == iss::arch::timeh) { } else if(addr == iss::arch::timeh) {
if (sizeof(reg_t) != 4) return iss::Err; if(sizeof(reg_t) != 4)
return iss::Err;
val = static_cast<reg_t>(time_val >> 32); val = static_cast<reg_t>(time_val >> 32);
} }
return ret ? iss::Ok : iss::Err; return ret ? iss::Ok : iss::Err;
@ -133,7 +130,8 @@ public:
if(addr == iss::arch::time) { if(addr == iss::arch::time) {
val = static_cast<reg_t>(time_val); val = static_cast<reg_t>(time_val);
} else if(addr == iss::arch::timeh) { } else if(addr == iss::arch::timeh) {
if (sizeof(reg_t) != 4) return iss::Err; if(sizeof(reg_t) != 4)
return iss::Err;
val = static_cast<reg_t>(time_val >> 32); val = static_cast<reg_t>(time_val >> 32);
} }
return iss::Ok; return iss::Ok;
@ -164,7 +162,8 @@ public:
mask = 1 << 11; mask = 1 << 11;
break; break;
default: default:
if(id>15) mask = 1 << id; if(id > 15)
mask = 1 << id;
break; break;
} }
if(value) { if(value) {
@ -184,5 +183,5 @@ private:
unsigned to_host_wr_cnt = 0; unsigned to_host_wr_cnt = 0;
bool first{true}; bool first{true};
}; };
} } // namespace sysc
#endif /* _SYSC_SC_CORE_ADAPTER_H_ */ #endif /* _SYSC_SC_CORE_ADAPTER_H_ */

View File

@ -8,13 +8,12 @@
#ifndef _SYSC_SC_CORE_ADAPTER_IF_H_ #ifndef _SYSC_SC_CORE_ADAPTER_IF_H_
#define _SYSC_SC_CORE_ADAPTER_IF_H_ #define _SYSC_SC_CORE_ADAPTER_IF_H_
#include <scc/report.h>
#include <util/ities.h>
#include "core_complex.h" #include "core_complex.h"
#include <iostream>
#include <iss/iss.h> #include <iss/iss.h>
#include <iss/vm_types.h> #include <iss/vm_types.h>
#include <iostream> #include <scc/report.h>
#include <util/ities.h>
namespace sysc { namespace sysc {
struct sc_core_adapter_if { struct sc_core_adapter_if {
@ -27,5 +26,5 @@ struct sc_core_adapter_if {
virtual void local_irq(short id, bool value) = 0; virtual void local_irq(short id, bool value) = 0;
virtual ~sc_core_adapter_if() = default; virtual ~sc_core_adapter_if() = default;
}; };
} } // namespace sysc
#endif /* _SYSC_SC_CORE_ADAPTER_IF_H_ */ #endif /* _SYSC_SC_CORE_ADAPTER_IF_H_ */

View File

@ -86,7 +86,6 @@ void gen_instr_prologue(jit_holder& jh, addr_t pc){
cc.comment("\n//increment *next_pc"); cc.comment("\n//increment *next_pc");
cc.mov(jh.next_pc, pc); cc.mov(jh.next_pc, pc);
} }
void gen_instr_epilogue(jit_holder& jh) { void gen_instr_epilogue(jit_holder& jh) {
auto& cc = jh.cc; auto& cc = jh.cc;
@ -100,8 +99,6 @@ void gen_instr_epilogue(jit_holder& jh){
write_reg_to_mem(jh, jh.pc, traits::PC); write_reg_to_mem(jh, jh.pc, traits::PC);
write_reg_to_mem(jh, jh.next_pc, traits::NEXT_PC); write_reg_to_mem(jh, jh.next_pc, traits::NEXT_PC);
write_reg_to_mem(jh, jh.trap_state, traits::TRAP_STATE); write_reg_to_mem(jh, jh.trap_state, traits::TRAP_STATE);
} }
void gen_block_prologue(jit_holder& jh) override { void gen_block_prologue(jit_holder& jh) override {
@ -135,19 +132,12 @@ void gen_block_epilogue(jit_holder& jh) override{
cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), std::numeric_limits<uint32_t>::max()); cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), std::numeric_limits<uint32_t>::max());
cc.comment("\n//return *next_pc;"); cc.comment("\n//return *next_pc;");
cc.ret(jh.next_pc); cc.ret(jh.next_pc);
} }
// TODO implement // TODO implement
void gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause) { void gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause) { jh.cc.comment("//gen_raise"); }
jh.cc.comment("//gen_raise"); void gen_wait(jit_holder& jh, unsigned type) { jh.cc.comment("//gen_wait"); }
} void gen_leave(jit_holder& jh, unsigned lvl) { jh.cc.comment("//gen_leave"); }
void gen_wait(jit_holder& jh, unsigned type) {
jh.cc.comment("//gen_wait");
}
void gen_leave(jit_holder& jh, unsigned lvl){
jh.cc.comment("//gen_leave");
}
enum operation { add, sub, band, bor, bxor, shl, sar, shr }; enum operation { add, sub, band, bor, bxor, shl, sar, shr };
@ -155,15 +145,40 @@ template <typename T, typename = std::enable_if_t<std::is_integral<T>::value ||
x86::Gp gen_operation(jit_holder& jh, operation op, x86::Gp a, T b) { x86::Gp gen_operation(jit_holder& jh, operation op, x86::Gp a, T b) {
x86::Compiler& cc = jh.cc; x86::Compiler& cc = jh.cc;
switch(op) { switch(op) {
case add: { cc.add(a, b); break; } case add: {
case sub: { cc.sub(a, b); break; } cc.add(a, b);
case band: { cc.and_(a, b); break; } break;
case bor: { cc.or_(a, b); break; } }
case bxor: { cc.xor_(a, b); break; } case sub: {
case shl: { cc.shl(a, b); break; } cc.sub(a, b);
case sar: { cc.sar(a, b); break; } break;
case shr: { cc.shr(a, b); break; } }
default: throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (operation)", op)); case band: {
cc.and_(a, b);
break;
}
case bor: {
cc.or_(a, b);
break;
}
case bxor: {
cc.xor_(a, b);
break;
}
case shl: {
cc.shl(a, b);
break;
}
case sar: {
cc.sar(a, b);
break;
}
case shr: {
cc.shr(a, b);
break;
}
default:
throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (operation)", op));
} }
return a; return a;
} }
@ -212,7 +227,8 @@ x86::Gp gen_operation(jit_holder& jh, three_operand_operation op, x86::Gp a, x86
return rem; return rem;
} }
default: throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (three_operand)", op)); default:
throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (three_operand)", op));
} }
return a; return a;
} }
@ -239,16 +255,36 @@ x86::Gp gen_operation(jit_holder& jh, comparison_operation op, x86::Gp a, T b){
Label label_then = cc.newLabel(); Label label_then = cc.newLabel();
cc.cmp(a, b); cc.cmp(a, b);
switch(op) { switch(op) {
case eq: cc.je(label_then); break; case eq:
case ne: cc.jne(label_then); break; cc.je(label_then);
case lt: cc.jl(label_then); break; break;
case ltu: cc.jb(label_then); break; case ne:
case gt: cc.jg(label_then); break; cc.jne(label_then);
case gtu: cc.ja(label_then); break; break;
case lte: cc.jle(label_then); break; case lt:
case lteu: cc.jbe(label_then); break; cc.jl(label_then);
case gte: cc.jge(label_then); break; break;
case gteu: cc.jae(label_then); break; case ltu:
cc.jb(label_then);
break;
case gt:
cc.jg(label_then);
break;
case gtu:
cc.ja(label_then);
break;
case lte:
cc.jle(label_then);
break;
case lteu:
cc.jbe(label_then);
break;
case gte:
cc.jge(label_then);
break;
case gteu:
cc.jae(label_then);
break;
case land: { case land: {
Label label_false = cc.newLabel(); Label label_false = cc.newLabel();
cc.cmp(a, 0); cc.cmp(a, 0);
@ -270,7 +306,8 @@ x86::Gp gen_operation(jit_holder& jh, comparison_operation op, x86::Gp a, T b){
cc.jne(label_then); cc.jne(label_then);
break; break;
} }
default: throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (comparison)", op)); default:
throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (comparison)", op));
} }
cc.mov(tmp, 0); cc.mov(tmp, 0);
cc.bind(label_then); cc.bind(label_then);
@ -281,34 +318,40 @@ enum binary_operation{lnot, inc, dec, bnot, neg};
x86::Gp gen_operation(jit_holder& jh, binary_operation op, x86::Gp a) { x86::Gp gen_operation(jit_holder& jh, binary_operation op, x86::Gp a) {
x86::Compiler& cc = jh.cc; x86::Compiler& cc = jh.cc;
switch(op) { switch(op) {
case lnot: throw std::runtime_error("Current operation not supported in gen_operation(lnot)"); case lnot:
case inc: { cc.inc(a); break; } throw std::runtime_error("Current operation not supported in gen_operation(lnot)");
case dec: { cc.dec(a); break; } case inc: {
case bnot: { cc.not_(a); break; } cc.inc(a);
case neg: { cc.neg(a); break; } break;
default: throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (unary)", op)); }
case dec: {
cc.dec(a);
break;
}
case bnot: {
cc.not_(a);
break;
}
case neg: {
cc.neg(a);
break;
}
default:
throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (unary)", op));
} }
return a; return a;
} }
/* template <typename T> /* template <typename T>
inline typename std::enable_if_t<std::is_unsigned<T>::value, x86::Gp> gen_ext(jit_holder& jh, T val, unsigned size, bool is_signed) const { inline typename std::enable_if_t<std::is_unsigned<T>::value, x86::Gp> gen_ext(jit_holder& jh, T val, unsigned size, bool
auto val_reg = get_reg_for(jh, sizeof(val)*8); is_signed) const { auto val_reg = get_reg_for(jh, sizeof(val)*8); auto tmp = get_reg_for(jh, size); jh.cc.mov(val_reg,
auto tmp = get_reg_for(jh, size); val); if(is_signed) jh.cc.movsx(tmp, val_reg); else jh.cc.movzx(tmp,val_reg); return tmp;
jh.cc.mov(val_reg, val);
if(is_signed) jh.cc.movsx(tmp, val_reg);
else jh.cc.movzx(tmp,val_reg);
return tmp;
} }
template <typename T> template <typename T>
inline typename std::enable_if_t<std::is_signed<T>::value, x86::Gp> gen_ext(jit_holder& jh, T val, unsigned size, bool is_signed) const { inline typename std::enable_if_t<std::is_signed<T>::value, x86::Gp> gen_ext(jit_holder& jh, T val, unsigned size, bool
auto val_reg = get_reg_for(jh, sizeof(val)*8); is_signed) const { auto val_reg = get_reg_for(jh, sizeof(val)*8); auto tmp = get_reg_for(jh, size); jh.cc.mov(val_reg,
auto tmp = get_reg_for(jh, size); val); if(is_signed) jh.cc.movsx(tmp, val_reg); else jh.cc.movzx(tmp,val_reg); return tmp;
jh.cc.mov(val_reg, val);
if(is_signed) jh.cc.movsx(tmp, val_reg);
else jh.cc.movzx(tmp,val_reg);
return tmp;
} */ } */
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>> template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
inline x86::Gp gen_ext(jit_holder& jh, T val, unsigned size, bool is_signed) { inline x86::Gp gen_ext(jit_holder& jh, T val, unsigned size, bool is_signed) {
@ -321,20 +364,38 @@ inline x86::Gp gen_ext(jit_holder& jh, x86::Gp val, unsigned size, bool is_signe
auto& cc = jh.cc; auto& cc = jh.cc;
if(is_signed) { if(is_signed) {
switch(val.size()) { switch(val.size()) {
case 1: cc.cbw(val); break; case 1:
case 2: cc.cwde(val); break; cc.cbw(val);
case 4: cc.cdqe(val); break; break;
case 8: break; case 2:
default: throw std::runtime_error("Invalid register size in gen_ext"); cc.cwde(val);
break;
case 4:
cc.cdqe(val);
break;
case 8:
break;
default:
throw std::runtime_error("Invalid register size in gen_ext");
} }
} }
switch(size) { switch(size) {
case 8: cc.and_(val,std::numeric_limits<uint8_t>::max()); return val.r8(); case 8:
case 16: cc.and_(val,std::numeric_limits<uint16_t>::max()); return val.r16(); cc.and_(val, std::numeric_limits<uint8_t>::max());
case 32: cc.and_(val,std::numeric_limits<uint32_t>::max()); return val.r32(); return val.r8();
case 64: cc.and_(val,std::numeric_limits<uint64_t>::max()); return val.r64(); case 16:
case 128: return val.r64(); cc.and_(val, std::numeric_limits<uint16_t>::max());
default: throw std::runtime_error("Invalid size in gen_ext"); return val.r16();
case 32:
cc.and_(val, std::numeric_limits<uint32_t>::max());
return val.r32();
case 64:
cc.and_(val, std::numeric_limits<uint64_t>::max());
return val.r64();
case 128:
return val.r64();
default:
throw std::runtime_error("Invalid size in gen_ext");
} }
} }
@ -376,7 +437,8 @@ inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, uint3
mask = std::numeric_limits<uint64_t>::max(); mask = std::numeric_limits<uint64_t>::max();
break; break;
} }
default: throw std::runtime_error(fmt::format("Invalid length ({}) in gen_read_mem",length)); default:
throw std::runtime_error(fmt::format("Invalid length ({}) in gen_read_mem", length));
} }
invokeNode->setRet(0, ret_reg); invokeNode->setRet(0, ret_reg);
@ -421,7 +483,6 @@ inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, int64_t
auto val_reg = jh.cc.newInt64(); auto val_reg = jh.cc.newInt64();
jh.cc.mov(val_reg, val); jh.cc.mov(val_reg, val);
gen_write_mem(jh, type, addr, val_reg); gen_write_mem(jh, type, addr, val_reg);
} }
inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp val) { inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp val) {
x86::Compiler& cc = jh.cc; x86::Compiler& cc = jh.cc;
@ -435,17 +496,14 @@ inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp
if(val.isGpb()) { if(val.isGpb()) {
cc.invoke(&invokeNode, &write_mem1, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint8_t>()); cc.invoke(&invokeNode, &write_mem1, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint8_t>());
} } else if(val.isGpw()) {
else if(val.isGpw()){
cc.invoke(&invokeNode, &write_mem2, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint16_t>()); cc.invoke(&invokeNode, &write_mem2, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint16_t>());
} } else if(val.isGpd()) {
else if(val.isGpd()){
cc.invoke(&invokeNode, &write_mem4, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint32_t>()); cc.invoke(&invokeNode, &write_mem4, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint32_t>());
} } else if(val.isGpq()) {
else if(val.isGpq()){
cc.invoke(&invokeNode, &write_mem8, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint64_t>()); cc.invoke(&invokeNode, &write_mem8, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint64_t>());
} } else
else throw std::runtime_error("Invalid register size in gen_write_mem"); throw std::runtime_error("Invalid register size in gen_write_mem");
invokeNode->setRet(0, ret_reg); invokeNode->setRet(0, ret_reg);
invokeNode->setArg(0, jh.arch_if_ptr); invokeNode->setArg(0, jh.arch_if_ptr);
@ -456,7 +514,6 @@ inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp
cc.cmp(ret_reg, 0); cc.cmp(ret_reg, 0);
cc.jne(jh.trap_entry); cc.jne(jh.trap_entry);
} }
inline void gen_write_mem(jit_holder& jh, mem_type_e type, uint64_t addr, x86::Gp val) { inline void gen_write_mem(jit_holder& jh, mem_type_e type, uint64_t addr, x86::Gp val) {
auto addr_reg = jh.cc.newInt64(); auto addr_reg = jh.cc.newInt64();
@ -470,5 +527,4 @@ inline void gen_write_mem(jit_holder& jh, mem_type_e type, uint64_t addr, int64_
auto addr_reg = jh.cc.newInt64(); auto addr_reg = jh.cc.newInt64();
jh.cc.mov(addr_reg, addr); jh.cc.mov(addr_reg, addr);
gen_write_mem(jh, type, addr_reg, val_reg); gen_write_mem(jh, type, addr_reg, val_reg);
} }

File diff suppressed because it is too large Load Diff

View File

@ -35,32 +35,24 @@
#include "fp_functions.h" #include "fp_functions.h"
extern "C" { extern "C" {
#include <softfloat.h>
#include "internals.h" #include "internals.h"
#include "specialize.h" #include "specialize.h"
#include <softfloat.h>
} }
#include <limits> #include <limits>
using this_t = uint8_t*; using this_t = uint8_t*;
const uint8_t rmm_map[] = { const uint8_t rmm_map[] = {
softfloat_round_near_even /*RNE*/, softfloat_round_near_even /*RNE*/, softfloat_round_minMag /*RTZ*/, softfloat_round_min /*RDN*/, softfloat_round_max /*RUP?*/,
softfloat_round_minMag/*RTZ*/, softfloat_round_near_maxMag /*RMM*/, softfloat_round_max /*RTZ*/, softfloat_round_max /*RTZ*/, softfloat_round_max /*RTZ*/,
softfloat_round_min/*RDN*/,
softfloat_round_max/*RUP?*/,
softfloat_round_near_maxMag /*RMM*/,
softfloat_round_max/*RTZ*/,
softfloat_round_max/*RTZ*/,
softfloat_round_max/*RTZ*/,
}; };
const uint32_t quiet_nan32 = 0x7fC00000; const uint32_t quiet_nan32 = 0x7fC00000;
extern "C" { extern "C" {
uint32_t fget_flags(){ uint32_t fget_flags() { return softfloat_exceptionFlags & 0x1f; }
return softfloat_exceptionFlags&0x1f;
}
uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode) { uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode) {
float32_t v1f{v1}, v2f{v2}; float32_t v1f{v1}, v2f{v2};
@ -110,7 +102,8 @@ uint32_t fcmp_s(uint32_t v1, uint32_t v2, uint32_t op) {
switch(op) { switch(op) {
case 0: case 0:
if(nan | snan) { if(nan | snan) {
if(snan) softfloat_raiseFlags(softfloat_flag_invalid); if(snan)
softfloat_raiseFlags(softfloat_flag_invalid);
return 0; return 0;
} else } else
return f32_eq(v1f, v2f) ? 1 : 0; return f32_eq(v1f, v2f) ? 1 : 0;
@ -160,7 +153,8 @@ uint32_t fmadd_s(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mod
softfloat_roundingMode = rmm_map[mode & 0x7]; softfloat_roundingMode = rmm_map[mode & 0x7];
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float32_t res = softfloat_mulAddF32(v1, v2, v3, op & 0x1); float32_t res = softfloat_mulAddF32(v1, v2, v3, op & 0x1);
if(op>1) res.v ^= 1ULL<<31; if(op > 1)
res.v ^= 1ULL << 31;
return res.v; return res.v;
} }
@ -170,11 +164,11 @@ uint32_t fsel_s(uint32_t v1, uint32_t v2, uint32_t op) {
bool v2_nan = (v2 & defaultNaNF32UI) == defaultNaNF32UI; bool v2_nan = (v2 & defaultNaNF32UI) == defaultNaNF32UI;
bool v1_snan = softfloat_isSigNaNF32UI(v1); bool v1_snan = softfloat_isSigNaNF32UI(v1);
bool v2_snan = softfloat_isSigNaNF32UI(v2); bool v2_snan = softfloat_isSigNaNF32UI(v2);
if (v1_snan || v2_snan) softfloat_raiseFlags(softfloat_flag_invalid); if(v1_snan || v2_snan)
softfloat_raiseFlags(softfloat_flag_invalid);
if(v1_nan || v1_snan) if(v1_nan || v1_snan)
return (v2_nan || v2_snan) ? defaultNaNF32UI : v2; return (v2_nan || v2_snan) ? defaultNaNF32UI : v2;
else else if(v2_nan || v2_snan)
if (v2_nan || v2_snan)
return v1; return v1;
else { else {
if((v1 & 0x7fffffff) == 0 && (v2 & 0x7fffffff) == 0) { if((v1 & 0x7fffffff) == 0 && (v2 & 0x7fffffff) == 0) {
@ -202,17 +196,10 @@ uint32_t fclass_s( uint32_t v1 ){
bool isNaN = isNaNF32UI(uiA); bool isNaN = isNaNF32UI(uiA);
bool isSNaN = softfloat_isSigNaNF32UI(uiA); bool isSNaN = softfloat_isSigNaNF32UI(uiA);
return return (sign && infOrNaN && fracZero) << 0 | (sign && !infOrNaN && !subnormalOrZero) << 1 |
( sign && infOrNaN && fracZero ) << 0 | (sign && subnormalOrZero && !fracZero) << 2 | (sign && subnormalOrZero && fracZero) << 3 | (!sign && infOrNaN && fracZero) << 7 |
( sign && !infOrNaN && !subnormalOrZero ) << 1 | (!sign && !infOrNaN && !subnormalOrZero) << 6 | (!sign && subnormalOrZero && !fracZero) << 5 |
( sign && subnormalOrZero && !fracZero ) << 2 | (!sign && subnormalOrZero && fracZero) << 4 | (isNaN && isSNaN) << 8 | (isNaN && !isSNaN) << 9;
( sign && subnormalOrZero && fracZero ) << 3 |
( !sign && infOrNaN && fracZero ) << 7 |
( !sign && !infOrNaN && !subnormalOrZero ) << 6 |
( !sign && subnormalOrZero && !fracZero ) << 5 |
( !sign && subnormalOrZero && fracZero ) << 4 |
( isNaN && isSNaN ) << 8 |
( isNaN && !isSNaN ) << 9;
} }
uint32_t fconv_d2f(uint64_t v1, uint8_t mode) { uint32_t fconv_d2f(uint64_t v1, uint8_t mode) {
@ -287,7 +274,8 @@ uint64_t fcmp_d(uint64_t v1, uint64_t v2, uint32_t op) {
switch(op) { switch(op) {
case 0: case 0:
if(nan | snan) { if(nan | snan) {
if(snan) softfloat_raiseFlags(softfloat_flag_invalid); if(snan)
softfloat_raiseFlags(softfloat_flag_invalid);
return 0; return 0;
} else } else
return f64_eq(v1f, v2f) ? 1 : 0; return f64_eq(v1f, v2f) ? 1 : 0;
@ -337,7 +325,8 @@ uint64_t fmadd_d(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mod
softfloat_roundingMode = rmm_map[mode & 0x7]; softfloat_roundingMode = rmm_map[mode & 0x7];
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float64_t res = softfloat_mulAddF64(v1, v2, v3, op & 0x1); float64_t res = softfloat_mulAddF64(v1, v2, v3, op & 0x1);
if(op>1) res.v ^= 1ULL<<63; if(op > 1)
res.v ^= 1ULL << 63;
return res.v; return res.v;
} }
@ -347,22 +336,19 @@ uint64_t fsel_d(uint64_t v1, uint64_t v2, uint32_t op) {
bool v2_nan = (v2 & defaultNaNF64UI) == defaultNaNF64UI; bool v2_nan = (v2 & defaultNaNF64UI) == defaultNaNF64UI;
bool v1_snan = softfloat_isSigNaNF64UI(v1); bool v1_snan = softfloat_isSigNaNF64UI(v1);
bool v2_snan = softfloat_isSigNaNF64UI(v2); bool v2_snan = softfloat_isSigNaNF64UI(v2);
if (v1_snan || v2_snan) softfloat_raiseFlags(softfloat_flag_invalid); if(v1_snan || v2_snan)
softfloat_raiseFlags(softfloat_flag_invalid);
if(v1_nan || v1_snan) if(v1_nan || v1_snan)
return (v2_nan || v2_snan) ? defaultNaNF64UI : v2; return (v2_nan || v2_snan) ? defaultNaNF64UI : v2;
else else if(v2_nan || v2_snan)
if (v2_nan || v2_snan)
return v1; return v1;
else { else {
if((v1 & std::numeric_limits<int64_t>::max()) == 0 && (v2 & std::numeric_limits<int64_t>::max()) == 0) { if((v1 & std::numeric_limits<int64_t>::max()) == 0 && (v2 & std::numeric_limits<int64_t>::max()) == 0) {
return op == 0 ? return op == 0 ? ((v1 & std::numeric_limits<int64_t>::min()) ? v1 : v2)
((v1 & std::numeric_limits<int64_t>::min()) ? v1 : v2) : : ((v1 & std::numeric_limits<int64_t>::min()) ? v2 : v1);
((v1 & std::numeric_limits<int64_t>::min()) ? v2 : v1);
} else { } else {
float64_t v1f{v1}, v2f{v2}; float64_t v1f{v1}, v2f{v2};
return op == 0 ? return op == 0 ? (f64_lt(v1f, v2f) ? v1 : v2) : (f64_lt(v1f, v2f) ? v2 : v1);
(f64_lt(v1f, v2f) ? v1 : v2) :
(f64_lt(v1f, v2f) ? v2 : v1);
} }
} }
} }
@ -383,17 +369,10 @@ uint64_t fclass_d(uint64_t v1 ){
bool isNaN = isNaNF64UI(uiA); bool isNaN = isNaNF64UI(uiA);
bool isSNaN = softfloat_isSigNaNF64UI(uiA); bool isSNaN = softfloat_isSigNaNF64UI(uiA);
return return (sign && infOrNaN && fracZero) << 0 | (sign && !infOrNaN && !subnormalOrZero) << 1 |
( sign && infOrNaN && fracZero ) << 0 | (sign && subnormalOrZero && !fracZero) << 2 | (sign && subnormalOrZero && fracZero) << 3 | (!sign && infOrNaN && fracZero) << 7 |
( sign && !infOrNaN && !subnormalOrZero ) << 1 | (!sign && !infOrNaN && !subnormalOrZero) << 6 | (!sign && subnormalOrZero && !fracZero) << 5 |
( sign && subnormalOrZero && !fracZero ) << 2 | (!sign && subnormalOrZero && fracZero) << 4 | (isNaN && isSNaN) << 8 | (isNaN && !isSNaN) << 9;
( sign && subnormalOrZero && fracZero ) << 3 |
( !sign && infOrNaN && fracZero ) << 7 |
( !sign && !infOrNaN && !subnormalOrZero ) << 6 |
( !sign && subnormalOrZero && !fracZero ) << 5 |
( !sign && subnormalOrZero && fracZero ) << 4 |
( isNaN && isSNaN ) << 8 |
( isNaN && !isSNaN ) << 9;
} }
uint64_t fcvt_32_64(uint32_t v1, uint32_t op, uint8_t mode) { uint64_t fcvt_32_64(uint32_t v1, uint32_t op, uint8_t mode) {
@ -445,4 +424,3 @@ uint32_t unbox_s(uint64_t v){
return v & std::numeric_limits<uint32_t>::max(); return v & std::numeric_limits<uint32_t>::max();
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -36,9 +36,9 @@
#include <iss/llvm/vm_base.h> #include <iss/llvm/vm_base.h>
extern "C" { extern "C" {
#include <softfloat.h>
#include "internals.h" #include "internals.h"
#include "specialize.h" #include "specialize.h"
#include <softfloat.h>
} }
#include <limits> #include <limits>
@ -69,7 +69,6 @@ using namespace ::llvm;
FunctionType* NAME##_type = FunctionType::get(RET, NAME##_args, false); \ FunctionType* NAME##_type = FunctionType::get(RET, NAME##_args, false); \
mod->getOrInsertFunction(#NAME, NAME##_type); mod->getOrInsertFunction(#NAME, NAME##_type);
void add_fp_functions_2_module(Module* mod, uint32_t flen, uint32_t xlen) { void add_fp_functions_2_module(Module* mod, uint32_t flen, uint32_t xlen) {
if(flen) { if(flen) {
FDECL(fget_flags, INT_TYPE(32)); FDECL(fget_flags, INT_TYPE(32));
@ -99,11 +98,10 @@ void add_fp_functions_2_module(Module *mod, uint32_t flen, uint32_t xlen) {
FDECL(fsel_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32)); FDECL(fsel_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32));
FDECL(fclass_d, INT_TYPE(64), INT_TYPE(64)); FDECL(fclass_d, INT_TYPE(64), INT_TYPE(64));
FDECL(unbox_s, INT_TYPE(32), INT_TYPE(64)); FDECL(unbox_s, INT_TYPE(32), INT_TYPE(64));
} }
} }
} }
} } // namespace fp_impl
} } // namespace llvm
} } // namespace iss

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff