Compare commits
265 Commits
2115e9ceae
...
featture/i
Author | SHA1 | Date | |
---|---|---|---|
071cb4fdac | |||
dd937710a7 | |||
047e2e12b0 | |||
fe3ed49519 | |||
1afd77a942 | |||
cdf5038e59 | |||
651897e1e4 | |||
a1803c61c1 | |||
bfa2182f8e | |||
b01c9b27e5 | |||
07f394d5ff | |||
7e97329e78 | |||
8f5d666b7d | |||
cc123939ce | |||
a2e5405e25 | |||
cd3ec0b79d | |||
0e35a2a8c9 | |||
8220c00a3d | |||
ec5fb1e87e | |||
453407568c | |||
0fe9e6ebc8 | |||
484d9dbe08 | |||
7a7035f267 | |||
d9f1e5d31b | |||
7b35f45a48 | |||
ece6f7290f | |||
2166a6d81e | |||
fe9f2a5455 | |||
42bf6ee380 | |||
f0b582df6c | |||
6fcb3dbb66 | |||
c01eb39a76 | |||
08280a094f | |||
ae90adc854 | |||
cd358198ad | |||
8746003d3e | |||
60d2b45a81 | |||
0264c5d66f | |||
528c2536af | |||
19e38ec898 | |||
fd11ce18c4 | |||
9b7a9fa273 | |||
e24c1874c4 | |||
221d2ee38c | |||
877cad27ba | |||
a26505cb5c | |||
c1277b6528 | |||
63889b02e7 | |||
f049d8cbb3 | |||
28ac169cfe | |||
a6f24db83a | |||
e1911bc450 | |||
75d96bf18d | |||
e59458aa0e | |||
77807fec01 | |||
6852d1d299 | |||
ac1322d66b | |||
9ba9d2432c | |||
c9b7962cd3 | |||
ab31fd27c9 | |||
b3f189145f | |||
dd4416ab15 | |||
0027946f90 | |||
feaff8c4a5 | |||
af3e76cc98 | |||
b1ceac2c2a | |||
b5862039e7 | |||
51f3802394 | |||
6ce0d97e81 | |||
69c8fda5d2 | |||
c1f9328528 | |||
2b85748279 | |||
f7aa51b12e | |||
3428745a00 | |||
512b79a3e7 | |||
7a048f8b93 | |||
6f4daf91ed | |||
947d353bbf | |||
b95f518c91 | |||
4cef0f57c1 | |||
28af695592 | |||
f6cdd9d07c | |||
9e390971d4 | |||
2bb2e56310 | |||
a0eeae7dd6 | |||
8f491ef36b | |||
cbe4c2d62f | |||
31c6bb55f4 | |||
63d0162119 | |||
3b294d9da0 | |||
54233b448d | |||
e238369e18 | |||
cfc980a069 | |||
502f3e8df9 | |||
88475bfa55 | |||
71260a3ef4 | |||
23842742a6 | |||
a13b7ac6d3 | |||
aaebeaf023 | |||
fb0f6255e9 | |||
57d5ea92be | |||
383d762abc | |||
03cbd305c6 | |||
9f5326c110 | |||
f4718c6de3 | |||
53de21eef9 | |||
d443c89c87 | |||
9a2df32d57 | |||
be0f783af8 | |||
1089800682 | |||
a6a6f51f0b | |||
21e1f791ad | |||
be6f5791fa | |||
d907dc7f54 | |||
75e81ce236 | |||
82a70efdb8 | |||
978c3db06e | |||
0e88664ff7 | |||
ac818f304d | |||
ad60449073 | |||
b45b3589fa | |||
1fb7e8fcea | |||
5f9d0beafb | |||
4c0d1c75aa | |||
2f3abf2f76 | |||
62768bf81e | |||
f6be8ec006 | |||
a8f56b6e27 | |||
76ea0db25d | |||
ec1b820c18 | |||
64329cf0f6 | |||
9de0aed84d | |||
bb4e2766d1 | |||
0996d15bd4 | |||
6305efa7c2 | |||
de79adc50d | |||
0473aa5344 | |||
a45fcd28db | |||
0f15032210 | |||
efc11d87a5 | |||
4a19e27926 | |||
c15cdb0955 | |||
6609d12582 | |||
b5341700aa | |||
0b5062d21c | |||
fbca690b3b | |||
235a7e6e24 | |||
62d21e1156 | |||
9c51d6eade | |||
2878dca6b5 | |||
c28e8fd00c | |||
b3cc9d2346 | |||
933f08494c | |||
21f8eab432 | |||
6ddb8da07f | |||
edf456c59f | |||
42efced1eb | |||
c376e34b2b | |||
f579ec6e48 | |||
fd20e66f1f | |||
5d69b79232 | |||
2edd68d1bd | |||
7ffa7667b6 | |||
93d89e07ca | |||
17dcba4b90 | |||
39d2518fdd | |||
a365110054 | |||
d2efb23ff7 | |||
04b7a09b19 | |||
72b11beac5 | |||
e87b7d5fd0 | |||
5a2b96ef3e | |||
c6b99cd155 | |||
b1306c3a47 | |||
0d6bf924ed | |||
86de536c8f | |||
051dd5e2d3 | |||
e3942be776 | |||
6ee484a771 | |||
60808c8649 | |||
0432803d82 | |||
4f5d9214ed | |||
d42d2ce533 | |||
236d12d7f5 | |||
e1b6cab890 | |||
8361f88718 | |||
2ec7ea4b41 | |||
b24965d321 | |||
244bf6d2f2 | |||
1a4465a371 | |||
fa82a50824 | |||
6dc17857da | |||
11a30caae8 | |||
ac1a26a10c | |||
7a199e122d | |||
d8c3d2e19c | |||
375755999a | |||
9996fd4833 | |||
149b3136d2 | |||
ac8f8b0539 | |||
b2cbf90d0b | |||
373145478e | |||
55b0cea94f | |||
5b17599aa2 | |||
4cfb15c7cd | |||
63da7f8d57 | |||
fb4012fbd1 | |||
24449f1c0f | |||
fd303c8343 | |||
346b177a87 | |||
d4ec131fa7 | |||
48370a4555 | |||
36b076774e | |||
482a4ec253 | |||
2fb28364c5 | |||
8460f4ab7f | |||
3fd51cc68c | |||
551822916c | |||
37db31fb4b | |||
e2da306eee | |||
41051f8f34 | |||
2a7449fa1e | |||
a6c48ceaac | |||
1e30b68507 | |||
ed793471bb | |||
58fb815f32 | |||
3cc8bd0854 | |||
a27850f841 | |||
fb330cddea | |||
b76c5bf0d6 | |||
001c6349f7 | |||
ee6a11dae6 | |||
2e27b025cc | |||
f0a004be9d | |||
3422c7cd5c | |||
ad79a28705 | |||
9fdbc3ff38 | |||
602bc6e06a | |||
6cb76fc256 | |||
fbcd389580 | |||
b25b7848c6 | |||
6c986d38d8 | |||
a1ebd83d2a | |||
8aed551813 | |||
1e6a0086e9 | |||
119d4a8b43 | |||
9841b16122 | |||
fbda1424f3 | |||
fe2d5cb2f9 | |||
3ff59ba45d | |||
db5765b342 | |||
075e04249a | |||
207f778ee6 | |||
f4f90c5e65 | |||
bc4ea30815 | |||
e921201f7b | |||
e6aa6e5842 | |||
4418fa7e4f | |||
adaa7e1c04 | |||
0eb1db0e7e | |||
e48597b2b7 | |||
458c773e19 | |||
b3f40f9b15 | |||
6419ad471e | |||
759061b569 |
@ -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
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,5 +1,6 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
/*.il
|
/*.il
|
||||||
|
/.settings
|
||||||
/avr-instr.html
|
/avr-instr.html
|
||||||
/blink.S
|
/blink.S
|
||||||
/flash.*
|
/flash.*
|
||||||
@ -14,7 +15,6 @@
|
|||||||
/*.ods
|
/*.ods
|
||||||
/build*/
|
/build*/
|
||||||
/*.logs
|
/*.logs
|
||||||
language.settings.xml
|
|
||||||
/*.gtkw
|
/*.gtkw
|
||||||
/Debug wo LLVM/
|
/Debug wo LLVM/
|
||||||
/*.txdb
|
/*.txdb
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.12)
|
cmake_minimum_required(VERSION 3.18)
|
||||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||||
|
|
||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
#
|
#
|
||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
@ -11,41 +12,52 @@ include(flink)
|
|||||||
find_package(elfio QUIET)
|
find_package(elfio QUIET)
|
||||||
find_package(jsoncpp)
|
find_package(jsoncpp)
|
||||||
find_package(Boost COMPONENTS coroutine REQUIRED)
|
find_package(Boost COMPONENTS coroutine REQUIRED)
|
||||||
|
find_package(absl REQUIRED)
|
||||||
|
|
||||||
add_subdirectory(softfloat)
|
add_subdirectory(softfloat)
|
||||||
|
|
||||||
set(LIB_SOURCES
|
set(LIB_SOURCES
|
||||||
src/iss/plugin/instruction_count.cpp
|
src/iss/plugin/instruction_count.cpp
|
||||||
src/iss/arch/tgc5c.cpp
|
src/iss/arch/tgc5c.cpp
|
||||||
|
src/iss/mem/memory_if.cpp
|
||||||
src/vm/interp/vm_tgc5c.cpp
|
src/vm/interp/vm_tgc5c.cpp
|
||||||
src/vm/fp_functions.cpp
|
src/vm/fp_functions.cpp
|
||||||
|
src/vm/vector_functions.cpp
|
||||||
|
src/iss/debugger/csr_names.cpp
|
||||||
|
src/iss/semihosting/semihosting.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WITH_TCC)
|
if(WITH_TCC)
|
||||||
list(APPEND LIB_SOURCES
|
list(APPEND LIB_SOURCES
|
||||||
src/vm/tcc/vm_tgc5c.cpp
|
src/vm/tcc/vm_tgc5c.cpp
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_LLVM)
|
if(WITH_LLVM)
|
||||||
list(APPEND LIB_SOURCES
|
list(APPEND LIB_SOURCES
|
||||||
src/vm/llvm/vm_tgc5c.cpp
|
src/vm/llvm/vm_tgc5c.cpp
|
||||||
src/vm/llvm/fp_impl.cpp
|
src/vm/llvm/fp_impl.cpp
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_ASMJIT)
|
if(WITH_ASMJIT)
|
||||||
list(APPEND LIB_SOURCES
|
list(APPEND LIB_SOURCES
|
||||||
src/vm/asmjit/vm_tgc5c.cpp
|
src/vm/asmjit/vm_tgc5c.cpp
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# library files
|
# library files
|
||||||
FILE(GLOB GEN_ISS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp)
|
FILE(GLOB GEN_ISS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp)
|
||||||
FILE(GLOB GEN_VM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/interp/vm_*.cpp)
|
FILE(GLOB GEN_VM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/interp/vm_*.cpp)
|
||||||
FILE(GLOB GEN_YAML_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/contrib/instr/*.yaml)
|
FILE(GLOB GEN_YAML_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/contrib/instr/*.yaml)
|
||||||
list(APPEND LIB_SOURCES ${GEN_ISS_SOURCES} ${GEN_VM_SOURCES})
|
list(APPEND LIB_SOURCES ${GEN_ISS_SOURCES} ${GEN_VM_SOURCES})
|
||||||
|
|
||||||
foreach(FILEPATH ${GEN_ISS_SOURCES})
|
foreach(FILEPATH ${GEN_ISS_SOURCES})
|
||||||
get_filename_component(CORE ${FILEPATH} NAME_WE)
|
get_filename_component(CORE ${FILEPATH} NAME_WE)
|
||||||
string(TOUPPER ${CORE} CORE)
|
string(TOUPPER ${CORE} CORE)
|
||||||
list(APPEND LIB_DEFINES CORE_${CORE})
|
list(APPEND LIB_DEFINES CORE_${CORE})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
message(STATUS "Core defines are ${LIB_DEFINES}")
|
message(STATUS "Core defines are ${LIB_DEFINES}")
|
||||||
|
|
||||||
if(WITH_LLVM)
|
if(WITH_LLVM)
|
||||||
@ -57,16 +69,19 @@ if(WITH_TCC)
|
|||||||
FILE(GLOB TCC_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/tcc/vm_*.cpp)
|
FILE(GLOB TCC_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/tcc/vm_*.cpp)
|
||||||
list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES})
|
list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_ASMJIT)
|
if(WITH_ASMJIT)
|
||||||
FILE(GLOB TCC_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/asmjit/vm_*.cpp)
|
FILE(GLOB TCC_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/asmjit/vm_*.cpp)
|
||||||
list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES})
|
list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(TARGET yaml-cpp::yaml-cpp)
|
if(TARGET yaml-cpp::yaml-cpp)
|
||||||
list(APPEND LIB_SOURCES
|
list(APPEND LIB_SOURCES
|
||||||
src/iss/plugin/cycle_estimate.cpp
|
src/iss/plugin/cycle_estimate.cpp
|
||||||
src/iss/plugin/instruction_count.cpp
|
src/iss/plugin/instruction_count.cpp
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Define the library
|
# Define the library
|
||||||
add_library(${PROJECT_NAME} SHARED ${LIB_SOURCES})
|
add_library(${PROJECT_NAME} SHARED ${LIB_SOURCES})
|
||||||
|
|
||||||
@ -75,33 +90,28 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
|||||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
target_compile_options(${PROJECT_NAME} PRIVATE /wd4293)
|
target_compile_options(${PROJECT_NAME} PRIVATE /wd4293)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC src)
|
target_include_directories(${PROJECT_NAME} PUBLIC src)
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC src-gen)
|
target_include_directories(${PROJECT_NAME} PUBLIC src-gen)
|
||||||
|
|
||||||
target_force_link_libraries(${PROJECT_NAME} PRIVATE dbt-rise-core)
|
target_force_link_libraries(${PROJECT_NAME} PRIVATE dbt-rise-core)
|
||||||
|
|
||||||
# only re-export the include paths
|
# only re-export the include paths
|
||||||
get_target_property(DBT_CORE_INCL dbt-rise-core INTERFACE_INCLUDE_DIRECTORIES)
|
get_target_property(DBT_CORE_INCL dbt-rise-core INTERFACE_INCLUDE_DIRECTORIES)
|
||||||
target_include_directories(${PROJECT_NAME} INTERFACE ${DBT_CORE_INCL})
|
target_include_directories(${PROJECT_NAME} INTERFACE ${DBT_CORE_INCL})
|
||||||
get_target_property(DBT_CORE_DEFS dbt-rise-core INTERFACE_COMPILE_DEFINITIONS)
|
get_target_property(DBT_CORE_DEFS dbt-rise-core INTERFACE_COMPILE_DEFINITIONS)
|
||||||
|
|
||||||
if(NOT(DBT_CORE_DEFS STREQUAL DBT_CORE_DEFS-NOTFOUND))
|
if(NOT(DBT_CORE_DEFS STREQUAL DBT_CORE_DEFS-NOTFOUND))
|
||||||
target_compile_definitions(${PROJECT_NAME} INTERFACE ${DBT_CORE_DEFS})
|
target_compile_definitions(${PROJECT_NAME} INTERFACE ${DBT_CORE_DEFS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio softfloat scc-util Boost::coroutine)
|
target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio softfloat scc-util Boost::coroutine abseil::abseil)
|
||||||
|
|
||||||
if(TARGET yaml-cpp::yaml-cpp)
|
if(TARGET yaml-cpp::yaml-cpp)
|
||||||
target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_PLUGINS)
|
target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_PLUGINS)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC yaml-cpp::yaml-cpp)
|
target_link_libraries(${PROJECT_NAME} PUBLIC yaml-cpp::yaml-cpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_LLVM)
|
|
||||||
find_package(LLVM)
|
|
||||||
target_compile_definitions(${PROJECT_NAME} PUBLIC ${LLVM_DEFINITIONS})
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ${LLVM_INCLUDE_DIRS})
|
|
||||||
if(BUILD_SHARED_LIBS)
|
|
||||||
target_link_libraries( ${PROJECT_NAME} PUBLIC ${LLVM_LIBRARIES})
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||||
VERSION ${PROJECT_VERSION}
|
VERSION ${PROJECT_VERSION}
|
||||||
FRAMEWORK FALSE
|
FRAMEWORK FALSE
|
||||||
@ -121,6 +131,7 @@ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/incl/iss COMPONENT ${PROJECT_NAME}
|
|||||||
PATTERN "*.h" # select header files
|
PATTERN "*.h" # select header files
|
||||||
)
|
)
|
||||||
install(FILES ${GEN_YAML_SOURCES} DESTINATION share/tgc-vp)
|
install(FILES ${GEN_YAML_SOURCES} DESTINATION share/tgc-vp)
|
||||||
|
|
||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
#
|
#
|
||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
@ -129,6 +140,7 @@ project(tgc-sim)
|
|||||||
find_package(Boost COMPONENTS program_options thread REQUIRED)
|
find_package(Boost COMPONENTS program_options thread REQUIRED)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} src/main.cpp)
|
add_executable(${PROJECT_NAME} src/main.cpp)
|
||||||
|
|
||||||
if(TARGET ${CORE_NAME}_cpp)
|
if(TARGET ${CORE_NAME}_cpp)
|
||||||
list(APPEND TGC_SOURCES ${${CORE_NAME}_OUTPUT_FILES})
|
list(APPEND TGC_SOURCES ${${CORE_NAME}_OUTPUT_FILES})
|
||||||
else()
|
else()
|
||||||
@ -154,7 +166,6 @@ endforeach()
|
|||||||
# if(WITH_TCC)
|
# if(WITH_TCC)
|
||||||
# target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_TCC)
|
# target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_TCC)
|
||||||
# endif()
|
# endif()
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc fmt::fmt)
|
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc fmt::fmt)
|
||||||
|
|
||||||
if(TARGET Boost::program_options)
|
if(TARGET Boost::program_options)
|
||||||
@ -162,7 +173,9 @@ if(TARGET Boost::program_options)
|
|||||||
else()
|
else()
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${BOOST_program_options_LIBRARY})
|
target_link_libraries(${PROJECT_NAME} PUBLIC ${BOOST_program_options_LIBRARY})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${CMAKE_DL_LIBS})
|
target_link_libraries(${PROJECT_NAME} PUBLIC ${CMAKE_DL_LIBS})
|
||||||
|
|
||||||
if(Tcmalloc_FOUND)
|
if(Tcmalloc_FOUND)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${Tcmalloc_LIBRARIES})
|
target_link_libraries(${PROJECT_NAME} PUBLIC ${Tcmalloc_LIBRARIES})
|
||||||
endif(Tcmalloc_FOUND)
|
endif(Tcmalloc_FOUND)
|
||||||
@ -181,19 +194,23 @@ if(BUILD_TESTING)
|
|||||||
# ... CMake code to create tests ...
|
# ... CMake code to create tests ...
|
||||||
add_test(NAME tgc-sim-interp
|
add_test(NAME tgc-sim-interp
|
||||||
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend interp)
|
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend interp)
|
||||||
|
|
||||||
if(WITH_TCC)
|
if(WITH_TCC)
|
||||||
add_test(NAME tgc-sim-tcc
|
add_test(NAME tgc-sim-tcc
|
||||||
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend tcc)
|
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend tcc)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_LLVM)
|
if(WITH_LLVM)
|
||||||
add_test(NAME tgc-sim-llvm
|
add_test(NAME tgc-sim-llvm
|
||||||
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend llvm)
|
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend llvm)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_ASMJIT)
|
if(WITH_ASMJIT)
|
||||||
add_test(NAME tgc-sim-asmjit
|
add_test(NAME tgc-sim-asmjit
|
||||||
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend asmjit)
|
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend asmjit)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
#
|
#
|
||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
@ -208,6 +225,7 @@ if(TARGET scc-sysc)
|
|||||||
add_library(${PROJECT_NAME} ${LIB_SOURCES})
|
add_library(${PROJECT_NAME} ${LIB_SOURCES})
|
||||||
target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_SYSTEMC)
|
target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_SYSTEMC)
|
||||||
target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME})
|
target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME})
|
||||||
|
|
||||||
foreach(F IN LISTS TGC_SOURCES)
|
foreach(F IN LISTS TGC_SOURCES)
|
||||||
if(${F} MATCHES ".*/arch/([^/]*)\.cpp")
|
if(${F} MATCHES ".*/arch/([^/]*)\.cpp")
|
||||||
string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F})
|
string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F})
|
||||||
@ -215,11 +233,12 @@ if(TARGET scc-sysc)
|
|||||||
target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME})
|
target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME})
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc scc-sysc)
|
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc scc-sysc)
|
||||||
|
|
||||||
# if(WITH_LLVM)
|
# if(WITH_LLVM)
|
||||||
# target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
|
# target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
|
||||||
# endif()
|
# endif()
|
||||||
|
|
||||||
set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/sysc/core_complex.h)
|
set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/sysc/core_complex.h)
|
||||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||||
VERSION ${PROJECT_VERSION}
|
VERSION ${PROJECT_VERSION}
|
||||||
@ -237,3 +256,8 @@ if(TARGET scc-sysc)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
project(elfio-test)
|
||||||
|
find_package(Boost COMPONENTS program_options thread REQUIRED)
|
||||||
|
|
||||||
|
add_executable(${PROJECT_NAME} src/elfio.cpp)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
RV32I:
|
RVI:
|
||||||
LUI:
|
LUI:
|
||||||
index: 0
|
index: 0
|
||||||
encoding: 0b00000000000000000000000000110111
|
encoding: 0b00000000000000000000000000110111
|
||||||
@ -20,91 +20,91 @@ RV32I:
|
|||||||
mask: 0b00000000000000000000000001111111
|
mask: 0b00000000000000000000000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: true
|
branch: true
|
||||||
delay: 1
|
delay: [1,1]
|
||||||
JALR:
|
JALR:
|
||||||
index: 3
|
index: 3
|
||||||
encoding: 0b00000000000000000000000001100111
|
encoding: 0b00000000000000000000000001100111
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: true
|
branch: true
|
||||||
delay: [1,2]
|
delay: [1,1]
|
||||||
BEQ:
|
BEQ:
|
||||||
index: 4
|
index: 4
|
||||||
encoding: 0b00000000000000000000000001100011
|
encoding: 0b00000000000000000000000001100011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: true
|
branch: true
|
||||||
delay: [1,2]
|
delay: [1,1]
|
||||||
BNE:
|
BNE:
|
||||||
index: 5
|
index: 5
|
||||||
encoding: 0b00000000000000000001000001100011
|
encoding: 0b00000000000000000001000001100011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: true
|
branch: true
|
||||||
delay: [1,2]
|
delay: [1,1]
|
||||||
BLT:
|
BLT:
|
||||||
index: 6
|
index: 6
|
||||||
encoding: 0b00000000000000000100000001100011
|
encoding: 0b00000000000000000100000001100011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: true
|
branch: true
|
||||||
delay: [1,2]
|
delay: [1,1]
|
||||||
BGE:
|
BGE:
|
||||||
index: 7
|
index: 7
|
||||||
encoding: 0b00000000000000000101000001100011
|
encoding: 0b00000000000000000101000001100011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: true
|
branch: true
|
||||||
delay: [1,2]
|
delay: [1,1]
|
||||||
BLTU:
|
BLTU:
|
||||||
index: 8
|
index: 8
|
||||||
encoding: 0b00000000000000000110000001100011
|
encoding: 0b00000000000000000110000001100011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: true
|
branch: true
|
||||||
delay: [1,2]
|
delay: [1,1]
|
||||||
BGEU:
|
BGEU:
|
||||||
index: 9
|
index: 9
|
||||||
encoding: 0b00000000000000000111000001100011
|
encoding: 0b00000000000000000111000001100011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: true
|
branch: true
|
||||||
delay: [1,2]
|
delay: [1,1]
|
||||||
LB:
|
LB:
|
||||||
index: 10
|
index: 10
|
||||||
encoding: 0b00000000000000000000000000000011
|
encoding: 0b00000000000000000000000000000011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 2
|
delay: 1
|
||||||
LH:
|
LH:
|
||||||
index: 11
|
index: 11
|
||||||
encoding: 0b00000000000000000001000000000011
|
encoding: 0b00000000000000000001000000000011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 2
|
delay: 1
|
||||||
LW:
|
LW:
|
||||||
index: 12
|
index: 12
|
||||||
encoding: 0b00000000000000000010000000000011
|
encoding: 0b00000000000000000010000000000011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 2
|
delay: 1
|
||||||
LBU:
|
LBU:
|
||||||
index: 13
|
index: 13
|
||||||
encoding: 0b00000000000000000100000000000011
|
encoding: 0b00000000000000000100000000000011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 2
|
delay: 1
|
||||||
LHU:
|
LHU:
|
||||||
index: 14
|
index: 14
|
||||||
encoding: 0b00000000000000000101000000000011
|
encoding: 0b00000000000000000101000000000011
|
||||||
mask: 0b00000000000000000111000001111111
|
mask: 0b00000000000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 2
|
delay: 1
|
||||||
SB:
|
SB:
|
||||||
index: 15
|
index: 15
|
||||||
encoding: 0b00000000000000000000000000100011
|
encoding: 0b00000000000000000000000000100011
|
||||||
@ -349,63 +349,63 @@ Zifencei:
|
|||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 1
|
delay: 1
|
||||||
RV32M:
|
RVM:
|
||||||
MUL:
|
MUL:
|
||||||
index: 49
|
index: 49
|
||||||
encoding: 0b00000010000000000000000000110011
|
encoding: 0b00000010000000000000000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 2
|
delay: 1
|
||||||
MULH:
|
MULH:
|
||||||
index: 50
|
index: 50
|
||||||
encoding: 0b00000010000000000001000000110011
|
encoding: 0b00000010000000000001000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 2
|
delay: 1
|
||||||
MULHSU:
|
MULHSU:
|
||||||
index: 51
|
index: 51
|
||||||
encoding: 0b00000010000000000010000000110011
|
encoding: 0b00000010000000000010000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 2
|
delay: 1
|
||||||
MULHU:
|
MULHU:
|
||||||
index: 52
|
index: 52
|
||||||
encoding: 0b00000010000000000011000000110011
|
encoding: 0b00000010000000000011000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 2
|
delay: 1
|
||||||
DIV:
|
DIV:
|
||||||
index: 53
|
index: 53
|
||||||
encoding: 0b00000010000000000100000000110011
|
encoding: 0b00000010000000000100000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 17
|
delay: 1
|
||||||
DIVU:
|
DIVU:
|
||||||
index: 54
|
index: 54
|
||||||
encoding: 0b00000010000000000101000000110011
|
encoding: 0b00000010000000000101000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 17
|
delay: 1
|
||||||
REM:
|
REM:
|
||||||
index: 55
|
index: 55
|
||||||
encoding: 0b00000010000000000110000000110011
|
encoding: 0b00000010000000000110000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 17
|
delay: 1
|
||||||
REMU:
|
REMU:
|
||||||
index: 56
|
index: 56
|
||||||
encoding: 0b00000010000000000111000000110011
|
encoding: 0b00000010000000000111000000110011
|
||||||
mask: 0b11111110000000000111000001111111
|
mask: 0b11111110000000000111000001111111
|
||||||
size: 32
|
size: 32
|
||||||
branch: false
|
branch: false
|
||||||
delay: 17
|
delay: 1
|
||||||
Zca:
|
Zca:
|
||||||
C__ADDI4SPN:
|
C__ADDI4SPN:
|
||||||
index: 57
|
index: 57
|
||||||
@ -420,7 +420,7 @@ Zca:
|
|||||||
mask: 0b1110000000000011
|
mask: 0b1110000000000011
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 2
|
delay: 1
|
||||||
C__SW:
|
C__SW:
|
||||||
index: 59
|
index: 59
|
||||||
encoding: 0b1100000000000000
|
encoding: 0b1100000000000000
|
||||||
@ -542,14 +542,14 @@ Zca:
|
|||||||
mask: 0b1110000000000011
|
mask: 0b1110000000000011
|
||||||
size: 16
|
size: 16
|
||||||
branch: true
|
branch: true
|
||||||
delay: [1,2]
|
delay: [1,1]
|
||||||
C__BNEZ:
|
C__BNEZ:
|
||||||
index: 76
|
index: 76
|
||||||
encoding: 0b1110000000000001
|
encoding: 0b1110000000000001
|
||||||
mask: 0b1110000000000011
|
mask: 0b1110000000000011
|
||||||
size: 16
|
size: 16
|
||||||
branch: true
|
branch: true
|
||||||
delay: [1,2]
|
delay: [1,1]
|
||||||
C__SLLI:
|
C__SLLI:
|
||||||
index: 77
|
index: 77
|
||||||
encoding: 0b0000000000000010
|
encoding: 0b0000000000000010
|
||||||
@ -564,7 +564,7 @@ Zca:
|
|||||||
mask: 0b1110000000000011
|
mask: 0b1110000000000011
|
||||||
size: 16
|
size: 16
|
||||||
branch: false
|
branch: false
|
||||||
delay: 2
|
delay: 1
|
||||||
C__MV:
|
C__MV:
|
||||||
index: 79
|
index: 79
|
||||||
encoding: 0b1000000000000010
|
encoding: 0b1000000000000010
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (C) 2017 - 2020 MINRES Technologies GmbH
|
* Copyright (C) 2024 MINRES Technologies GmbH
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -37,6 +37,7 @@ def getRegisterSizes(){
|
|||||||
return regs
|
return regs
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
|
// clang-format off
|
||||||
#include "${coreDef.name.toLowerCase()}.h"
|
#include "${coreDef.name.toLowerCase()}.h"
|
||||||
#include "util/ities.h"
|
#include "util/ities.h"
|
||||||
#include <util/logging.h>
|
#include <util/logging.h>
|
||||||
@ -46,10 +47,10 @@ def getRegisterSizes(){
|
|||||||
|
|
||||||
using namespace iss::arch;
|
using namespace iss::arch;
|
||||||
|
|
||||||
constexpr std::array<const char*, ${registers.size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_names;
|
constexpr std::array<const char*, ${registers.size()}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_names;
|
||||||
constexpr std::array<const char*, ${registers.size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_aliases;
|
constexpr std::array<const char*, ${registers.size()}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_aliases;
|
||||||
constexpr std::array<const uint32_t, ${getRegisterSizes().size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_bit_widths;
|
constexpr std::array<const uint32_t, ${getRegisterSizes().size()}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_bit_widths;
|
||||||
constexpr std::array<const uint32_t, ${getRegisterSizes().size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_byte_offsets;
|
constexpr std::array<const uint32_t, ${getRegisterSizes().size()}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_byte_offsets;
|
||||||
|
|
||||||
${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() = default;
|
${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() = default;
|
||||||
|
|
||||||
@ -73,4 +74,4 @@ uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() {
|
|||||||
${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &addr) {
|
${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &addr) {
|
||||||
return phys_addr_t(addr.access, addr.space, addr.val&traits<${coreDef.name.toLowerCase()}>::addr_mask);
|
return phys_addr_t(addr.access, addr.space, addr.val&traits<${coreDef.name.toLowerCase()}>::addr_mask);
|
||||||
}
|
}
|
||||||
|
// clang-format on
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (C) 2017 - 2021 MINRES Technologies GmbH
|
* Copyright (C) 2024 MINRES Technologies GmbH
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -30,11 +30,21 @@
|
|||||||
*
|
*
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
<%
|
<%
|
||||||
def nativeTypeSize(int size){
|
def nativeSize(int size){
|
||||||
if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64;
|
if(size<=8) return 8;
|
||||||
|
if(size<=16) return 16;
|
||||||
|
if(size<=32) return 32;
|
||||||
|
if(size<=64) return 64;
|
||||||
|
if(size<=128) return 128;
|
||||||
|
if(size<=256) return 256;
|
||||||
|
if(size<=512) return 512;
|
||||||
|
if(size<=1024) return 1024;
|
||||||
|
if(size<=2048) return 2048;
|
||||||
|
if(size<=4096) return 4096;
|
||||||
|
throw new IllegalArgumentException("Unsupported size in nativeSize in CORENAME.h.gtl");
|
||||||
}
|
}
|
||||||
def getRegisterSizes(){
|
def getRegisterSizes(){
|
||||||
def regs = registers.collect{nativeTypeSize(it.size)}
|
def regs = registers.collect{nativeSize(it.size)}
|
||||||
regs+=[32,32, 64, 64, 64, 32, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH
|
regs+=[32,32, 64, 64, 64, 32, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH
|
||||||
return regs
|
return regs
|
||||||
}
|
}
|
||||||
@ -47,20 +57,14 @@ def getRegisterOffsets(){
|
|||||||
}
|
}
|
||||||
return offsets
|
return offsets
|
||||||
}
|
}
|
||||||
def byteSize(int size){
|
|
||||||
if(size<=8) return 8;
|
|
||||||
if(size<=16) return 16;
|
|
||||||
if(size<=32) return 32;
|
|
||||||
if(size<=64) return 64;
|
|
||||||
return 128;
|
|
||||||
}
|
|
||||||
def getCString(def val){
|
def getCString(def val){
|
||||||
return val.toString()+'ULL'
|
return val.toString()+'ULL'
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
#ifndef _${coreDef.name.toUpperCase()}_H_
|
#ifndef _${coreDef.name.toUpperCase()}_H_
|
||||||
#define _${coreDef.name.toUpperCase()}_H_
|
#define _${coreDef.name.toUpperCase()}_H_
|
||||||
|
// clang-format off
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <iss/arch/traits.h>
|
#include <iss/arch/traits.h>
|
||||||
#include <iss/arch_if.h>
|
#include <iss/arch_if.h>
|
||||||
@ -75,15 +79,17 @@ template <> struct traits<${coreDef.name.toLowerCase()}> {
|
|||||||
|
|
||||||
constexpr static char const* const core_type = "${coreDef.name}";
|
constexpr static char const* const core_type = "${coreDef.name}";
|
||||||
|
|
||||||
static constexpr std::array<const char*, ${registers.size}> reg_names{
|
static constexpr std::array<const char*, ${registers.size()}> reg_names{
|
||||||
{"${registers.collect{it.name.toLowerCase()}.join('", "')}"}};
|
{"${registers.collect{it.name.toLowerCase()}.join('", "')}"}};
|
||||||
|
|
||||||
static constexpr std::array<const char*, ${registers.size}> reg_aliases{
|
static constexpr std::array<const char*, ${registers.size()}> reg_aliases{
|
||||||
{"${registers.collect{it.alias.toLowerCase()}.join('", "')}"}};
|
{"${registers.collect{it.alias.toLowerCase()}.join('", "')}"}};
|
||||||
|
|
||||||
enum constants {${constants.collect{c -> c.name+"="+getCString(c.value)}.join(', ')}};
|
enum constants {${constants.collect{c -> c.name+"="+getCString(c.value)}.join(', ')}};
|
||||||
|
|
||||||
constexpr static unsigned FP_REGS_SIZE = ${constants.find {it.name=='FLEN'}?.value?:0};
|
constexpr static unsigned FP_REGS_SIZE = ${constants.find {it.name=='FLEN'}?.value?:0};
|
||||||
|
constexpr static unsigned V_REGS_SIZE = ${constants.find {it.name=='VLEN'}?.value?:0};
|
||||||
|
|
||||||
|
|
||||||
enum reg_e {
|
enum reg_e {
|
||||||
${registers.collect{it.name}.join(', ')}, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH
|
${registers.collect{it.name}.join(', ')}, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH
|
||||||
@ -99,17 +105,17 @@ template <> struct traits<${coreDef.name.toLowerCase()}> {
|
|||||||
|
|
||||||
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, ${getRegisterSizes().size}> reg_bit_widths{
|
static constexpr std::array<const uint32_t, ${getRegisterSizes().size()}> reg_bit_widths{
|
||||||
{${getRegisterSizes().join(',')}}};
|
{${getRegisterSizes().join(',')}}};
|
||||||
|
|
||||||
static constexpr std::array<const uint32_t, ${getRegisterOffsets().size}> reg_byte_offsets{
|
static constexpr std::array<const uint32_t, ${getRegisterOffsets().size()}> reg_byte_offsets{
|
||||||
{${getRegisterOffsets().join(',')}}};
|
{${getRegisterOffsets().join(',')}}};
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
enum sreg_flag_e { FLAGS };
|
enum sreg_flag_e { FLAGS };
|
||||||
|
|
||||||
enum mem_type_e { ${spaces.collect{it.name}.join(', ')} };
|
enum mem_type_e { ${spaces.collect{it.name}.join(', ')}, IMEM = MEM };
|
||||||
|
|
||||||
enum class opcode_e {<%instructions.eachWithIndex{instr, index -> %>
|
enum class opcode_e {<%instructions.eachWithIndex{instr, index -> %>
|
||||||
${instr.instruction.name} = ${index},<%}%>
|
${instr.instruction.name} = ${index},<%}%>
|
||||||
@ -131,8 +137,6 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
|
|||||||
|
|
||||||
uint8_t* get_regs_base_ptr() override;
|
uint8_t* get_regs_base_ptr() override;
|
||||||
|
|
||||||
inline uint64_t get_icount() { return reg.icount; }
|
|
||||||
|
|
||||||
inline bool should_stop() { return interrupt_sim; }
|
inline bool should_stop() { return interrupt_sim; }
|
||||||
|
|
||||||
inline uint64_t stop_code() { return interrupt_sim; }
|
inline uint64_t stop_code() { return interrupt_sim; }
|
||||||
@ -141,20 +145,20 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
|
|||||||
|
|
||||||
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
|
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
|
||||||
|
|
||||||
inline uint32_t get_last_branch() { return reg.last_branch; }
|
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct ${coreDef.name}_regs {<%
|
struct ${coreDef.name}_regs {<%
|
||||||
registers.each { reg -> if(reg.size>0) {%>
|
registers.each { reg -> if(reg.size>64) {%>
|
||||||
uint${byteSize(reg.size)}_t ${reg.name} = 0;<%
|
uint8_t ${reg.name}[${reg.size/8}] = {0};<%
|
||||||
|
}else if(reg.size>0) {%>
|
||||||
|
uint${nativeSize(reg.size)}_t ${reg.name} = 0;<%
|
||||||
}}%>
|
}}%>
|
||||||
uint32_t trap_state = 0, pending_trap = 0;
|
uint32_t trap_state = 0, pending_trap = 0;
|
||||||
uint64_t icount = 0;
|
uint64_t icount = 0; // counts number of instructions undisturbed
|
||||||
uint64_t cycle = 0;
|
uint64_t cycle = 0; // counts number of cycles, in functional mode equals icount
|
||||||
uint64_t instret = 0;
|
uint64_t instret = 0; // counts number of instructions, can be reset via CSR write
|
||||||
uint32_t instruction = 0;
|
uint32_t instruction = 0; // holds op code of currently executed instruction
|
||||||
uint32_t last_branch = 0;
|
uint32_t last_branch = 0; // indicates if last branch was taken
|
||||||
} reg;
|
} reg;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
std::array<address_type, 4> addr_mode;
|
std::array<address_type, 4> addr_mode;
|
||||||
@ -168,9 +172,35 @@ if(fcsr != null) {%>
|
|||||||
<%} else { %>
|
<%} else { %>
|
||||||
uint32_t get_fcsr(){return 0;}
|
uint32_t get_fcsr(){return 0;}
|
||||||
void set_fcsr(uint32_t val){}
|
void set_fcsr(uint32_t val){}
|
||||||
|
<%}
|
||||||
|
def vstart = registers.find {it.name=='vstart'}
|
||||||
|
def vl = registers.find {it.name=='vl'}
|
||||||
|
def vtype = registers.find {it.name=='vtype'}
|
||||||
|
def vxsat = registers.find {it.name=='vxsat'}
|
||||||
|
def vxrm = registers.find {it.name=='vxrm'}
|
||||||
|
|
||||||
|
if(vtype != null) {%>
|
||||||
|
uint${vstart.size}_t get_vstart(){return reg.vstart;}
|
||||||
|
void set_vstart(uint${vstart.size}_t val){reg.vstart = val;}
|
||||||
|
uint${vl.size}_t get_vl(){return reg.vl;}
|
||||||
|
uint${vtype.size}_t get_vtype(){return reg.vtype;}
|
||||||
|
uint${vxsat.size}_t get_vxsat(){return reg.vxsat;}
|
||||||
|
void set_vxsat(uint${vxsat.size}_t val){reg.vxsat = val;}
|
||||||
|
uint${vxrm.size}_t get_vxrm(){return reg.vxrm;}
|
||||||
|
void set_vxrm(uint${vxrm.size}_t val){reg.vxrm = val;}
|
||||||
|
<%} else { %>
|
||||||
|
uint32_t get_vstart(){return 0;}
|
||||||
|
void set_vstart(uint32_t val){}
|
||||||
|
uint32_t get_vl(){return 0;}
|
||||||
|
uint32_t get_vtype(){return 0;}
|
||||||
|
uint32_t get_vxsat(){return 0;}
|
||||||
|
void set_vxsat(uint32_t val){}
|
||||||
|
uint32_t get_vxrm(){return 0;}
|
||||||
|
void set_vxrm(uint32_t val){}
|
||||||
<%}%>
|
<%}%>
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* _${coreDef.name.toUpperCase()}_H_ */
|
#endif /* _${coreDef.name.toUpperCase()}_H_ */
|
||||||
|
// clang-format on
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (C) 2023 MINRES Technologies GmbH
|
* Copyright (C) 2024 MINRES Technologies GmbH
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -29,7 +29,7 @@
|
|||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
// clang-format off
|
||||||
#include <sysc/iss_factory.h>
|
#include <sysc/iss_factory.h>
|
||||||
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
||||||
#include <iss/arch/riscv_hart_m_p.h>
|
#include <iss/arch/riscv_hart_m_p.h>
|
||||||
@ -45,17 +45,17 @@ namespace interp {
|
|||||||
using namespace sysc;
|
using namespace sysc;
|
||||||
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|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_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
}),
|
}),
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_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_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
|
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|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_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
})<%}%>
|
})<%}%>
|
||||||
@ -66,17 +66,17 @@ namespace llvm {
|
|||||||
using namespace sysc;
|
using namespace sysc;
|
||||||
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|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_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
}),
|
}),
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_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_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
|
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|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_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
})<%}%>
|
})<%}%>
|
||||||
@ -88,17 +88,17 @@ namespace tcc {
|
|||||||
using namespace sysc;
|
using namespace sysc;
|
||||||
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|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_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
}),
|
}),
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_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_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
|
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|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_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
})<%}%>
|
})<%}%>
|
||||||
@ -110,17 +110,17 @@ namespace asmjit {
|
|||||||
using namespace sysc;
|
using namespace sysc;
|
||||||
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|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_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
}),
|
}),
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_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_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
|
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|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_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
})<%}%>
|
})<%}%>
|
||||||
@ -128,3 +128,4 @@ volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
// clang-format on
|
@ -1,5 +1,5 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (C) 2017, 2023 MINRES Technologies GmbH
|
* Copyright (C) 2017-2024 MINRES Technologies GmbH
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -29,7 +29,7 @@
|
|||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
// clang-format off
|
||||||
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
||||||
#include <iss/debugger/gdb_session.h>
|
#include <iss/debugger/gdb_session.h>
|
||||||
#include <iss/debugger/server.h>
|
#include <iss/debugger/server.h>
|
||||||
@ -37,7 +37,14 @@
|
|||||||
#include <iss/asmjit/vm_base.h>
|
#include <iss/asmjit/vm_base.h>
|
||||||
#include <asmjit/asmjit.h>
|
#include <asmjit/asmjit.h>
|
||||||
#include <util/logging.h>
|
#include <util/logging.h>
|
||||||
#include <fp_functions.h>
|
#include <iss/instruction_decoder.h>
|
||||||
|
<%def fcsr = registers.find {it.name=='FCSR'}
|
||||||
|
if(fcsr != null) {%>
|
||||||
|
#include <vm/fp_functions.h><%}
|
||||||
|
def aes = functions.find { it.contains('aes') }
|
||||||
|
if(aes != null) {%>
|
||||||
|
#include <vm/aes_sbox.h>
|
||||||
|
<%}%>
|
||||||
#ifndef FMT_HEADER_ONLY
|
#ifndef FMT_HEADER_ONLY
|
||||||
#define FMT_HEADER_ONLY
|
#define FMT_HEADER_ONLY
|
||||||
#endif
|
#endif
|
||||||
@ -46,6 +53,22 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <iss/debugger/riscv_target_adapter.h>
|
#include <iss/debugger/riscv_target_adapter.h>
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
using int128_t = __int128;
|
||||||
|
using uint128_t = unsigned __int128;
|
||||||
|
namespace std {
|
||||||
|
template <> struct make_unsigned<__int128> { typedef unsigned __int128 type; };
|
||||||
|
template <> class __make_unsigned_selector<__int128 unsigned, false, false> {
|
||||||
|
public:
|
||||||
|
typedef unsigned __int128 __type;
|
||||||
|
};
|
||||||
|
template <> struct is_signed<int128_t> { static constexpr bool value = true; };
|
||||||
|
template <> struct is_signed<uint128_t> { static constexpr bool value = false; };
|
||||||
|
template <> struct is_unsigned<int128_t> { static constexpr bool value = false; };
|
||||||
|
template <> struct is_unsigned<uint128_t> { static constexpr bool value = true; };
|
||||||
|
} // namespace std
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace iss {
|
namespace iss {
|
||||||
namespace asmjit {
|
namespace asmjit {
|
||||||
|
|
||||||
@ -79,12 +102,33 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using vm_base<ARCH>::get_reg_ptr;
|
using super::get_ptr_for;
|
||||||
|
using super::get_reg_for;
|
||||||
|
using super::get_reg_for_Gp;
|
||||||
|
using super::load_reg_from_mem;
|
||||||
|
using super::load_reg_from_mem_Gp;
|
||||||
|
using super::write_reg_to_mem;
|
||||||
|
using super::gen_read_mem;
|
||||||
|
using super::gen_write_mem;
|
||||||
|
using super::gen_leave;
|
||||||
|
using super::gen_sync;
|
||||||
|
|
||||||
using this_class = vm_impl<ARCH>;
|
using this_class = vm_impl<ARCH>;
|
||||||
using compile_func = continuation_e (this_class::*)(virt_addr_t&, code_word_t, jit_holder&);
|
using compile_func = continuation_e (this_class::*)(virt_addr_t&, code_word_t, jit_holder&);
|
||||||
|
|
||||||
continuation_e gen_single_inst_behavior(virt_addr_t&, unsigned int &, jit_holder&) override;
|
continuation_e gen_single_inst_behavior(virt_addr_t&, jit_holder&) override;
|
||||||
|
enum globals_e {TVAL = 0, GLOBALS_SIZE};
|
||||||
|
void gen_block_prologue(jit_holder& jh) override;
|
||||||
|
void gen_block_epilogue(jit_holder& jh) override;
|
||||||
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
|
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
|
||||||
|
<%if(fcsr != null) {%>
|
||||||
|
inline const char *fname(size_t index){return index < 32?name(index+traits::F0):"illegal";}
|
||||||
|
<%}%>
|
||||||
|
void gen_instr_prologue(jit_holder& jh);
|
||||||
|
void gen_instr_epilogue(jit_holder& jh);
|
||||||
|
inline void gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause);
|
||||||
|
template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type> void gen_set_tval(jit_holder& jh, T new_tval) ;
|
||||||
|
void gen_set_tval(jit_holder& jh, x86_reg_t _new_tval) ;
|
||||||
|
|
||||||
template<unsigned W, typename U, typename S = typename std::make_signed<U>::type>
|
template<unsigned W, typename U, typename S = typename std::make_signed<U>::type>
|
||||||
inline S sext(U from) {
|
inline S sext(U from) {
|
||||||
@ -92,34 +136,34 @@ protected:
|
|||||||
auto sign_mask = 1ULL<<(W-1);
|
auto sign_mask = 1ULL<<(W-1);
|
||||||
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
|
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
|
||||||
}
|
}
|
||||||
#include "helper_func.h"
|
inline void raise(uint16_t trap_id, uint16_t cause){
|
||||||
|
auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id;
|
||||||
|
this->core.reg.trap_state = trap_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
<%functions.each{ it.eachLine { %>
|
||||||
|
${it}<%}
|
||||||
|
}%>
|
||||||
private:
|
private:
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* start opcode definitions
|
* start opcode definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
struct instruction_descriptor {
|
struct instruction_descriptor {
|
||||||
size_t length;
|
uint32_t length;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
compile_func op;
|
compile_func op;
|
||||||
};
|
};
|
||||||
struct decoding_tree_node{
|
|
||||||
std::vector<instruction_descriptor> instrs;
|
|
||||||
std::vector<decoding_tree_node*> children;
|
|
||||||
uint32_t submask = std::numeric_limits<uint32_t>::max();
|
|
||||||
uint32_t value;
|
|
||||||
decoding_tree_node(uint32_t value) : value(value){}
|
|
||||||
};
|
|
||||||
|
|
||||||
decoding_tree_node* root {nullptr};
|
const std::array<instruction_descriptor, ${instructions.size()}> instr_descr = {{
|
||||||
|
|
||||||
const std::array<instruction_descriptor, ${instructions.size}> instr_descr = {{
|
|
||||||
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
|
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
|
||||||
/* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */
|
/* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */
|
||||||
{${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
|
{${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
//needs to be declared after instr_descr
|
||||||
|
decoder instr_decoder;
|
||||||
|
|
||||||
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
|
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
|
||||||
/* instruction ${idx}: ${instr.name} */
|
/* instruction ${idx}: ${instr.name} */
|
||||||
continuation_e __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, jit_holder& jh){
|
continuation_e __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, jit_holder& jh){
|
||||||
@ -127,126 +171,183 @@ private:
|
|||||||
<%instr.fields.eachLine{%>${it}
|
<%instr.fields.eachLine{%>${it}
|
||||||
<%}%>if(this->disass_enabled){
|
<%}%>if(this->disass_enabled){
|
||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
<%instr.disass.eachLine{%>
|
||||||
|
${it}<%}%>
|
||||||
|
InvokeNode* call_print_disass;
|
||||||
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
|
jh.disass_collection.push_back(mnemonic_ptr);
|
||||||
|
jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build<void, void *, uint64_t, char *>());
|
||||||
|
call_print_disass->setArg(0, jh.arch_if_ptr);
|
||||||
|
call_print_disass->setArg(1, pc.val);
|
||||||
|
call_print_disass->setArg(2, mnemonic_ptr);
|
||||||
|
|
||||||
}
|
}
|
||||||
x86::Compiler& cc = jh.cc;
|
x86::Compiler& cc = jh.cc;
|
||||||
//ideally only do this if necessary (someone / plugin needs it)
|
cc.comment(fmt::format("${instr.name}_{:#x}:",pc.val).c_str());
|
||||||
cc.mov(jh.pc,PC);
|
gen_sync(jh, PRE_SYNC, ${idx});
|
||||||
cc.comment(fmt::format("\\n${instr.name}_{:#x}:",pc.val).c_str());
|
mov(cc, jh.pc, pc.val);
|
||||||
this->gen_sync(jh, PRE_SYNC, ${idx});
|
gen_set_tval(jh, instr);
|
||||||
pc = pc+${instr.length/8};
|
pc = pc+${instr.length/8};
|
||||||
|
mov(cc, jh.next_pc, pc.val);
|
||||||
|
|
||||||
gen_instr_prologue(jh, pc.val);
|
gen_instr_prologue(jh);
|
||||||
cc.comment("\\n//behavior:");
|
|
||||||
/*generate behavior*/
|
/*generate behavior*/
|
||||||
<%instr.behavior.eachLine{%>${it}
|
<%instr.behavior.eachLine{%>${it}
|
||||||
<%}%>
|
<%}%>
|
||||||
|
gen_sync(jh, POST_SYNC, ${idx});
|
||||||
gen_instr_epilogue(jh);
|
gen_instr_epilogue(jh);
|
||||||
this->gen_sync(jh, POST_SYNC, ${idx});
|
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
<%}%>
|
<%}%>
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* end opcode definitions
|
* end opcode definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
continuation_e illegal_intruction(virt_addr_t &pc, code_word_t instr, jit_holder& jh ) {
|
continuation_e illegal_instruction(virt_addr_t &pc, code_word_t instr, jit_holder& jh ) {
|
||||||
|
x86::Compiler& cc = jh.cc;
|
||||||
return BRANCH;
|
if(this->disass_enabled){
|
||||||
|
auto mnemonic = std::string("illegal_instruction");
|
||||||
|
InvokeNode* call_print_disass;
|
||||||
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
|
jh.disass_collection.push_back(mnemonic_ptr);
|
||||||
|
jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build<void, void *, uint64_t, char *>());
|
||||||
|
call_print_disass->setArg(0, jh.arch_if_ptr);
|
||||||
|
call_print_disass->setArg(1, pc.val);
|
||||||
|
call_print_disass->setArg(2, mnemonic_ptr);
|
||||||
}
|
}
|
||||||
//decoding functionality
|
cc.comment(fmt::format("illegal_instruction{:#x}:",pc.val).c_str());
|
||||||
|
gen_sync(jh, PRE_SYNC, instr_descr.size());
|
||||||
void populate_decoding_tree(decoding_tree_node* root){
|
mov(cc, jh.pc, pc.val);
|
||||||
//create submask
|
gen_set_tval(jh, instr);
|
||||||
for(auto instr: root->instrs){
|
pc = pc + ((instr & 3) == 3 ? 4 : 2);
|
||||||
root->submask &= instr.mask;
|
mov(cc, jh.next_pc, pc.val);
|
||||||
}
|
gen_instr_prologue(jh);
|
||||||
//put each instr according to submask&encoding into children
|
gen_raise(jh, 0, 2);
|
||||||
for(auto instr: root->instrs){
|
gen_sync(jh, POST_SYNC, instr_descr.size());
|
||||||
bool foundMatch = false;
|
gen_instr_epilogue(jh);
|
||||||
for(auto child: root->children){
|
return ILLEGAL_INSTR;
|
||||||
//use value as identifying trait
|
|
||||||
if(child->value == (instr.value&root->submask)){
|
|
||||||
child->instrs.push_back(instr);
|
|
||||||
foundMatch = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!foundMatch){
|
|
||||||
decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask);
|
|
||||||
child->instrs.push_back(instr);
|
|
||||||
root->children.push_back(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
root->instrs.clear();
|
|
||||||
//call populate_decoding_tree for all children
|
|
||||||
if(root->children.size() >1)
|
|
||||||
for(auto child: root->children){
|
|
||||||
populate_decoding_tree(child);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
//sort instrs by value of the mask, this works bc we want to have the least restrictive one last
|
|
||||||
std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) {
|
|
||||||
return instr1.mask > instr2.mask;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
compile_func decode_instr(decoding_tree_node* node, code_word_t word){
|
|
||||||
if(!node->children.size()){
|
|
||||||
if(node->instrs.size() == 1) return node->instrs[0].op;
|
|
||||||
for(auto instr : node->instrs){
|
|
||||||
if((instr.mask&word) == instr.value) return instr.op;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
for(auto child : node->children){
|
|
||||||
if (child->value == (node->submask&word)){
|
|
||||||
return decode_instr(child, word);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename CODE_WORD> void debug_fn(CODE_WORD instr) {
|
|
||||||
volatile CODE_WORD x = instr;
|
|
||||||
instr = 2 * x;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
|
template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
||||||
: vm_base<ARCH>(core, core_id, cluster_id) {
|
: vm_base<ARCH>(core, core_id, cluster_id)
|
||||||
root = new decoding_tree_node(std::numeric_limits<uint32_t>::max());
|
, instr_decoder([this]() {
|
||||||
for(auto instr: instr_descr){
|
std::vector<generic_instruction_descriptor> g_instr_descr;
|
||||||
root->instrs.push_back(instr);
|
g_instr_descr.reserve(instr_descr.size());
|
||||||
}
|
for (uint32_t i = 0; i < instr_descr.size(); ++i) {
|
||||||
populate_decoding_tree(root);
|
generic_instruction_descriptor new_instr_descr {instr_descr[i].value, instr_descr[i].mask, i};
|
||||||
|
g_instr_descr.push_back(new_instr_descr);
|
||||||
}
|
}
|
||||||
|
return std::move(g_instr_descr);
|
||||||
|
}()) {}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
continuation_e
|
continuation_e vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, jit_holder& jh) {
|
||||||
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, jit_holder& jh) {
|
|
||||||
enum {TRAP_ID=1<<16};
|
enum {TRAP_ID=1<<16};
|
||||||
code_word_t instr = 0;
|
code_word_t instr = 0;
|
||||||
phys_addr_t paddr(pc);
|
phys_addr_t paddr(pc);
|
||||||
auto *const data = (uint8_t *)&instr;
|
auto *const data = (uint8_t *)&instr;
|
||||||
if(this->core.has_mmu())
|
|
||||||
paddr = this->core.virt2phys(pc);
|
|
||||||
auto res = this->core.read(paddr, 4, data);
|
auto res = this->core.read(paddr, 4, data);
|
||||||
if (res != iss::Ok)
|
if (res != iss::Ok)
|
||||||
throw trap_access(TRAP_ID, pc.val);
|
return ILLEGAL_FETCH;
|
||||||
if (instr == 0x0000006f || (instr&0xffff)==0xa001)
|
if (instr == 0x0000006f || (instr&0xffff)==0xa001)
|
||||||
throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
return JUMP_TO_SELF;
|
||||||
++inst_cnt;
|
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
||||||
auto f = decode_instr(root, instr);
|
compile_func f = nullptr;
|
||||||
|
if(inst_index < instr_descr.size())
|
||||||
|
f = instr_descr[inst_index].op;
|
||||||
if (f == nullptr)
|
if (f == nullptr)
|
||||||
f = &this_class::illegal_intruction;
|
f = &this_class::illegal_instruction;
|
||||||
return (this->*f)(pc, instr, jh);
|
return (this->*f)(pc, instr, jh);
|
||||||
}
|
}
|
||||||
|
template <typename ARCH>
|
||||||
|
void vm_impl<ARCH>::gen_instr_prologue(jit_holder& jh) {
|
||||||
|
auto& cc = jh.cc;
|
||||||
|
|
||||||
|
x86_reg_t current_trap_state = get_reg_for(cc, traits::TRAP_STATE);
|
||||||
|
mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE));
|
||||||
|
mov(cc, get_ptr_for(jh, traits::PENDING_TRAP), current_trap_state);
|
||||||
|
cc.comment("//Instruction prologue end");
|
||||||
|
|
||||||
|
}
|
||||||
|
template <typename ARCH>
|
||||||
|
void vm_impl<ARCH>::gen_instr_epilogue(jit_holder& jh) {
|
||||||
|
auto& cc = jh.cc;
|
||||||
|
|
||||||
} // namespace ${coreDef.name.toLowerCase()}
|
cc.comment("//Instruction epilogue begin");
|
||||||
|
x86_reg_t current_trap_state = get_reg_for(cc, traits::TRAP_STATE);
|
||||||
|
mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE));
|
||||||
|
cmp(cc, current_trap_state, 0);
|
||||||
|
cc.jne(jh.trap_entry);
|
||||||
|
cc.inc(get_ptr_for(jh, traits::ICOUNT));
|
||||||
|
cc.inc(get_ptr_for(jh, traits::CYCLE));
|
||||||
|
cc.comment("//Instruction epilogue end");
|
||||||
|
|
||||||
|
}
|
||||||
|
template <typename ARCH>
|
||||||
|
void vm_impl<ARCH>::gen_block_prologue(jit_holder& jh){
|
||||||
|
jh.pc = load_reg_from_mem_Gp(jh, traits::PC);
|
||||||
|
jh.next_pc = load_reg_from_mem_Gp(jh, traits::NEXT_PC);
|
||||||
|
jh.globals.resize(GLOBALS_SIZE);
|
||||||
|
jh.globals[TVAL] = get_reg_Gp(jh.cc, 64, false);
|
||||||
|
}
|
||||||
|
template <typename ARCH>
|
||||||
|
void vm_impl<ARCH>::gen_block_epilogue(jit_holder& jh){
|
||||||
|
x86::Compiler& cc = jh.cc;
|
||||||
|
cc.comment("//block epilogue begin");
|
||||||
|
cc.ret(jh.next_pc);
|
||||||
|
|
||||||
|
cc.bind(jh.trap_entry);
|
||||||
|
this->write_back(jh);
|
||||||
|
|
||||||
|
x86::Gp current_trap_state = get_reg_for_Gp(cc, traits::TRAP_STATE);
|
||||||
|
mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE));
|
||||||
|
|
||||||
|
x86::Gp current_pc = get_reg_for_Gp(cc, traits::PC);
|
||||||
|
mov(cc, current_pc, get_ptr_for(jh, traits::PC));
|
||||||
|
|
||||||
|
InvokeNode* call_enter_trap;
|
||||||
|
cc.invoke(&call_enter_trap, &enter_trap, FuncSignature::build<uint64_t, void*, uint64_t, uint64_t, uint64_t>());
|
||||||
|
call_enter_trap->setArg(0, jh.arch_if_ptr);
|
||||||
|
call_enter_trap->setArg(1, current_trap_state);
|
||||||
|
call_enter_trap->setArg(2, current_pc);
|
||||||
|
call_enter_trap->setArg(3, jh.globals[TVAL]);
|
||||||
|
|
||||||
|
x86_reg_t current_next_pc = get_reg_for(cc, traits::NEXT_PC);
|
||||||
|
mov(cc, current_next_pc, get_ptr_for(jh, traits::NEXT_PC));
|
||||||
|
mov(cc, jh.next_pc, current_next_pc);
|
||||||
|
|
||||||
|
mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(UNKNOWN_JUMP));
|
||||||
|
cc.ret(jh.next_pc);
|
||||||
|
}
|
||||||
|
template <typename ARCH>
|
||||||
|
inline void vm_impl<ARCH>::gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause) {
|
||||||
|
auto& cc = jh.cc;
|
||||||
|
auto tmp1 = get_reg_for(cc, traits::TRAP_STATE);
|
||||||
|
mov(cc, tmp1, 0x80ULL << 24 | (cause << 16) | trap_id);
|
||||||
|
mov(cc, get_ptr_for(jh, traits::TRAP_STATE), tmp1);
|
||||||
|
cc.jmp(jh.trap_entry);
|
||||||
|
}
|
||||||
|
template <typename ARCH>
|
||||||
|
template <typename T, typename>
|
||||||
|
void vm_impl<ARCH>::gen_set_tval(jit_holder& jh, T new_tval) {
|
||||||
|
mov(jh.cc, jh.globals[TVAL], new_tval);
|
||||||
|
}
|
||||||
|
template <typename ARCH>
|
||||||
|
void vm_impl<ARCH>::gen_set_tval(jit_holder& jh, x86_reg_t _new_tval) {
|
||||||
|
if(nonstd::holds_alternative<x86::Gp>(_new_tval)) {
|
||||||
|
x86::Gp new_tval = nonstd::get<x86::Gp>(_new_tval);
|
||||||
|
if(new_tval.size() < 8)
|
||||||
|
new_tval = gen_ext_Gp(jh.cc, new_tval, 64, false);
|
||||||
|
mov(jh.cc, jh.globals[TVAL], new_tval);
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Variant not supported in gen_set_tval");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace tgc5c
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) {
|
std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) {
|
||||||
@ -257,24 +358,33 @@ std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreD
|
|||||||
} // namespace asmjit
|
} // namespace asmjit
|
||||||
} // namespace iss
|
} // namespace iss
|
||||||
|
|
||||||
#include <iss/factory.h>
|
|
||||||
#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 <iss/factory.h>
|
||||||
namespace iss {
|
namespace iss {
|
||||||
namespace {
|
namespace {
|
||||||
volatile std::array<bool, 2> dummy = {
|
volatile std::array<bool, 2> dummy = {
|
||||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|asmjit", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
|
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|asmjit", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
|
||||||
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
||||||
auto* vm = new asmjit::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
auto vm = new asmjit::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
||||||
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
||||||
|
if(init_data){
|
||||||
|
auto* cb = reinterpret_cast<semihosting_cb_t<arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t>*>(init_data);
|
||||||
|
cpu->set_semihosting_callback(*cb);
|
||||||
|
}
|
||||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||||
}),
|
}),
|
||||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|asmjit", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
|
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|asmjit", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
|
||||||
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
||||||
auto* vm = new asmjit::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
auto vm = new asmjit::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
||||||
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
||||||
|
if(init_data){
|
||||||
|
auto* cb = reinterpret_cast<semihosting_cb_t<arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t>*>(init_data);
|
||||||
|
cpu->set_semihosting_callback(*cb);
|
||||||
|
}
|
||||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// clang-format on
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
|
* Copyright (C) 2017-2024 MINRES Technologies GmbH
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -29,14 +29,19 @@
|
|||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
// clang-format off
|
||||||
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
||||||
|
// vm_base needs to be included before gdb_session as termios.h (via boost and gdb_server) has a define which clashes with a variable
|
||||||
|
// name in ConstantRange.h
|
||||||
|
#include <iss/llvm/vm_base.h>
|
||||||
|
#include <iss/iss.h>
|
||||||
#include <iss/debugger/gdb_session.h>
|
#include <iss/debugger/gdb_session.h>
|
||||||
#include <iss/debugger/server.h>
|
#include <iss/debugger/server.h>
|
||||||
#include <iss/iss.h>
|
#include <iss/instruction_decoder.h>
|
||||||
#include <iss/llvm/vm_base.h>
|
|
||||||
#include <util/logging.h>
|
#include <util/logging.h>
|
||||||
|
<%def fcsr = registers.find {it.name=='FCSR'}
|
||||||
|
if(fcsr != null) {%>
|
||||||
|
#include <vm/fp_functions.h><%}%>
|
||||||
#ifndef FMT_HEADER_ONLY
|
#ifndef FMT_HEADER_ONLY
|
||||||
#define FMT_HEADER_ONLY
|
#define FMT_HEADER_ONLY
|
||||||
#endif
|
#endif
|
||||||
@ -82,7 +87,9 @@ protected:
|
|||||||
using vm_base<ARCH>::get_reg_ptr;
|
using vm_base<ARCH>::get_reg_ptr;
|
||||||
|
|
||||||
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
|
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
|
||||||
|
<%if(fcsr != null) {%>
|
||||||
|
inline const char *fname(size_t index){return index < 32?name(index+traits::F0):"illegal";}
|
||||||
|
<%}%>
|
||||||
template <typename T> inline ConstantInt *size(T type) {
|
template <typename T> inline ConstantInt *size(T type) {
|
||||||
return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits()));
|
return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits()));
|
||||||
}
|
}
|
||||||
@ -96,19 +103,17 @@ protected:
|
|||||||
return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size));
|
return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<continuation_e, BasicBlock *> gen_single_inst_behavior(virt_addr_t &, unsigned int &, BasicBlock *) override;
|
std::tuple<continuation_e, BasicBlock *> gen_single_inst_behavior(virt_addr_t &, BasicBlock *) override;
|
||||||
|
|
||||||
void gen_leave_behavior(BasicBlock *leave_blk) override;
|
void gen_leave_behavior(BasicBlock *leave_blk) override;
|
||||||
|
|
||||||
void gen_raise_trap(uint16_t trap_id, uint16_t cause);
|
void gen_raise_trap(uint16_t trap_id, uint16_t cause);
|
||||||
|
|
||||||
void gen_leave_trap(unsigned lvl);
|
void gen_leave_trap(unsigned lvl);
|
||||||
|
|
||||||
void gen_wait(unsigned type);
|
void gen_wait(unsigned type);
|
||||||
|
void set_tval(uint64_t new_tval);
|
||||||
|
void set_tval(Value* new_tval);
|
||||||
void gen_trap_behavior(BasicBlock *) override;
|
void gen_trap_behavior(BasicBlock *) override;
|
||||||
|
void gen_instr_prologue();
|
||||||
void gen_trap_check(BasicBlock *bb);
|
void gen_instr_epilogue(BasicBlock *bb);
|
||||||
|
|
||||||
inline Value *gen_reg_load(unsigned i, unsigned level = 0) {
|
inline Value *gen_reg_load(unsigned i, unsigned level = 0) {
|
||||||
return this->builder.CreateLoad(this->get_typeptr(i), get_reg_ptr(i), false);
|
return this->builder.CreateLoad(this->get_typeptr(i), get_reg_ptr(i), false);
|
||||||
@ -132,51 +137,79 @@ protected:
|
|||||||
auto sign_mask = 1ULL<<(W-1);
|
auto sign_mask = 1ULL<<(W-1);
|
||||||
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
|
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
|
||||||
}
|
}
|
||||||
|
<%functions.each{ it.eachLine { %>
|
||||||
|
${it}<%}
|
||||||
|
}
|
||||||
|
if(fcsr != null) {%>
|
||||||
|
Value* NaNBox16(BasicBlock* bb, Value* NaNBox16_val){
|
||||||
|
if(static_cast<uint32_t>(traits::FLEN) == 16)
|
||||||
|
return this->gen_ext(NaNBox16_val, traits::FLEN, false);
|
||||||
|
auto box = this->builder.CreateNot((this->gen_ext(0, 32, false)));
|
||||||
|
return this->gen_ext((this->builder.CreateOr(this->builder.CreateShl(this->gen_ext(box, traits::FLEN), 16), this->gen_ext(NaNBox16_val, traits::FLEN))), traits::FLEN, false);
|
||||||
|
}
|
||||||
|
Value* NaNBox32(BasicBlock* bb, Value* NaNBox32_val){
|
||||||
|
if(static_cast<uint32_t>(traits::FLEN) == 32)
|
||||||
|
return this->gen_ext(NaNBox32_val, traits::FLEN, false);
|
||||||
|
auto box = this->builder.CreateNot((this->gen_ext(0, 64, false)));
|
||||||
|
return this->gen_ext((this->builder.CreateOr(this->builder.CreateShl(this->gen_ext(box, traits::FLEN), 32), this->gen_ext(NaNBox32_val, traits::FLEN))), traits::FLEN, false);
|
||||||
|
}
|
||||||
|
Value* NaNBox64(BasicBlock* bb, Value* NaNBox64_val){
|
||||||
|
if(static_cast<uint32_t>(traits::FLEN) == 64)
|
||||||
|
return this->gen_ext(NaNBox64_val, traits::FLEN, false);
|
||||||
|
auto box = this->builder.CreateNot((this->gen_ext(0, 128, false)));
|
||||||
|
return this->gen_ext((this->builder.CreateOr(this->builder.CreateShl(this->gen_ext(box, traits::FLEN), 64), this->gen_ext(NaNBox64_val, traits::FLEN))), traits::FLEN, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
<%}%>
|
||||||
private:
|
private:
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* start opcode definitions
|
* start opcode definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
struct instruction_descriptor {
|
struct instruction_descriptor {
|
||||||
size_t length;
|
uint32_t length;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
compile_func op;
|
compile_func op;
|
||||||
};
|
};
|
||||||
struct decoding_tree_node{
|
|
||||||
std::vector<instruction_descriptor> instrs;
|
|
||||||
std::vector<decoding_tree_node*> children;
|
|
||||||
uint32_t submask = std::numeric_limits<uint32_t>::max();
|
|
||||||
uint32_t value;
|
|
||||||
decoding_tree_node(uint32_t value) : value(value){}
|
|
||||||
};
|
|
||||||
|
|
||||||
decoding_tree_node* root {nullptr};
|
const std::array<instruction_descriptor, ${instructions.size()}> instr_descr = {{
|
||||||
|
|
||||||
const std::array<instruction_descriptor, ${instructions.size}> instr_descr = {{
|
|
||||||
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
|
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
|
||||||
/* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */
|
/* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */
|
||||||
{${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
|
{${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
//needs to be declared after instr_descr
|
||||||
|
decoder instr_decoder;
|
||||||
|
|
||||||
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
|
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
|
||||||
/* instruction ${idx}: ${instr.name} */
|
/* instruction ${idx}: ${instr.name} */
|
||||||
std::tuple<continuation_e, BasicBlock*> __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){
|
std::tuple<continuation_e, BasicBlock*> __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){
|
||||||
bb->setName(fmt::format("${instr.name}_0x{:X}",pc.val));
|
|
||||||
this->gen_sync(PRE_SYNC,${idx});
|
|
||||||
uint64_t PC = pc.val;
|
uint64_t PC = pc.val;
|
||||||
<%instr.fields.eachLine{%>${it}
|
<%instr.fields.eachLine{%>${it}
|
||||||
<%}%>if(this->disass_enabled){
|
<%}%>if(this->disass_enabled){
|
||||||
/* generate console output when executing the command */<%instr.disass.eachLine{%>
|
/* generate console output when executing the command */<%instr.disass.eachLine{%>
|
||||||
${it}<%}%>
|
${it}<%}%>
|
||||||
|
std::vector<Value*> args {
|
||||||
|
this->core_ptr,
|
||||||
|
this->gen_const(64, pc.val),
|
||||||
|
this->builder.CreateGlobalStringPtr(mnemonic),
|
||||||
|
};
|
||||||
|
this->builder.CreateCall(this->mod->getFunction("print_disass"), args);
|
||||||
}
|
}
|
||||||
auto cur_pc_val = this->gen_const(32,pc.val);
|
bb->setName(fmt::format("${instr.name}_0x{:X}",pc.val));
|
||||||
|
this->gen_sync(PRE_SYNC,${idx});
|
||||||
|
|
||||||
|
this->gen_set_pc(pc, traits::PC);
|
||||||
|
this->set_tval(instr);
|
||||||
pc=pc+ ${instr.length/8};
|
pc=pc+ ${instr.length/8};
|
||||||
this->gen_set_pc(pc, traits::NEXT_PC);
|
this->gen_set_pc(pc, traits::NEXT_PC);
|
||||||
|
|
||||||
|
this->gen_instr_prologue();
|
||||||
|
/*generate behavior*/
|
||||||
<%instr.behavior.eachLine{%>${it}
|
<%instr.behavior.eachLine{%>${it}
|
||||||
<%}%>
|
<%}%>
|
||||||
this->gen_trap_check(bb);
|
|
||||||
this->gen_sync(POST_SYNC, ${idx});
|
this->gen_sync(POST_SYNC, ${idx});
|
||||||
|
this->gen_instr_epilogue(bb);
|
||||||
this->builder.CreateBr(bb);
|
this->builder.CreateBr(bb);
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
@ -184,7 +217,16 @@ private:
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* end opcode definitions
|
* end opcode definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
std::tuple<continuation_e, BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) {
|
std::tuple<continuation_e, BasicBlock *> illegal_instruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) {
|
||||||
|
if(this->disass_enabled){
|
||||||
|
auto mnemonic = std::string("illegal_instruction");
|
||||||
|
std::vector<Value*> args {
|
||||||
|
this->core_ptr,
|
||||||
|
this->gen_const(64, pc.val),
|
||||||
|
this->builder.CreateGlobalStringPtr(mnemonic),
|
||||||
|
};
|
||||||
|
this->builder.CreateCall(this->mod->getFunction("print_disass"), args);
|
||||||
|
}
|
||||||
this->gen_sync(iss::PRE_SYNC, instr_descr.size());
|
this->gen_sync(iss::PRE_SYNC, instr_descr.size());
|
||||||
this->builder.CreateStore(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), true),
|
this->builder.CreateStore(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), true),
|
||||||
get_reg_ptr(traits::PC), true);
|
get_reg_ptr(traits::PC), true);
|
||||||
@ -193,62 +235,13 @@ private:
|
|||||||
this->gen_const(64U, 1)),
|
this->gen_const(64U, 1)),
|
||||||
get_reg_ptr(traits::ICOUNT), true);
|
get_reg_ptr(traits::ICOUNT), true);
|
||||||
pc = pc + ((instr & 3) == 3 ? 4 : 2);
|
pc = pc + ((instr & 3) == 3 ? 4 : 2);
|
||||||
|
this->set_tval(instr);
|
||||||
this->gen_raise_trap(0, 2); // illegal instruction trap
|
this->gen_raise_trap(0, 2); // illegal instruction trap
|
||||||
this->gen_sync(iss::POST_SYNC, instr_descr.size());
|
this->gen_sync(iss::POST_SYNC, instr_descr.size());
|
||||||
this->gen_trap_check(this->leave_blk);
|
bb = this->leave_blk;
|
||||||
return std::make_tuple(BRANCH, nullptr);
|
this->gen_instr_epilogue(bb);
|
||||||
}
|
this->builder.CreateBr(bb);
|
||||||
//decoding functionality
|
return std::make_tuple(ILLEGAL_INSTR, nullptr);
|
||||||
|
|
||||||
void populate_decoding_tree(decoding_tree_node* root){
|
|
||||||
//create submask
|
|
||||||
for(auto instr: root->instrs){
|
|
||||||
root->submask &= instr.mask;
|
|
||||||
}
|
|
||||||
//put each instr according to submask&encoding into children
|
|
||||||
for(auto instr: root->instrs){
|
|
||||||
bool foundMatch = false;
|
|
||||||
for(auto child: root->children){
|
|
||||||
//use value as identifying trait
|
|
||||||
if(child->value == (instr.value&root->submask)){
|
|
||||||
child->instrs.push_back(instr);
|
|
||||||
foundMatch = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!foundMatch){
|
|
||||||
decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask);
|
|
||||||
child->instrs.push_back(instr);
|
|
||||||
root->children.push_back(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
root->instrs.clear();
|
|
||||||
//call populate_decoding_tree for all children
|
|
||||||
if(root->children.size() >1)
|
|
||||||
for(auto child: root->children){
|
|
||||||
populate_decoding_tree(child);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
//sort instrs by value of the mask, this works bc we want to have the least restrictive one last
|
|
||||||
std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) {
|
|
||||||
return instr1.mask > instr2.mask;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
compile_func decode_instr(decoding_tree_node* node, code_word_t word){
|
|
||||||
if(!node->children.size()){
|
|
||||||
if(node->instrs.size() == 1) return node->instrs[0].op;
|
|
||||||
for(auto instr : node->instrs){
|
|
||||||
if((instr.mask&word) == instr.value) return instr.op;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
for(auto child : node->children){
|
|
||||||
if (child->value == (node->submask&word)){
|
|
||||||
return decode_instr(child, word);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -261,84 +254,103 @@ template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
|
|||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
||||||
: vm_base<ARCH>(core, core_id, cluster_id) {
|
: vm_base<ARCH>(core, core_id, cluster_id)
|
||||||
root = new decoding_tree_node(std::numeric_limits<uint32_t>::max());
|
, instr_decoder([this]() {
|
||||||
for(auto instr:instr_descr){
|
std::vector<generic_instruction_descriptor> g_instr_descr;
|
||||||
root->instrs.push_back(instr);
|
g_instr_descr.reserve(instr_descr.size());
|
||||||
}
|
for (uint32_t i = 0; i < instr_descr.size(); ++i) {
|
||||||
populate_decoding_tree(root);
|
generic_instruction_descriptor new_instr_descr {instr_descr[i].value, instr_descr[i].mask, i};
|
||||||
|
g_instr_descr.push_back(new_instr_descr);
|
||||||
}
|
}
|
||||||
|
return std::move(g_instr_descr);
|
||||||
|
}()) {}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
std::tuple<continuation_e, BasicBlock *>
|
std::tuple<continuation_e, BasicBlock *>
|
||||||
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, BasicBlock *this_block) {
|
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, BasicBlock *this_block) {
|
||||||
// we fetch at max 4 byte, alignment is 2
|
// we fetch at max 4 byte, alignment is 2
|
||||||
enum {TRAP_ID=1<<16};
|
enum {TRAP_ID=1<<16};
|
||||||
code_word_t instr = 0;
|
code_word_t instr = 0;
|
||||||
// const typename traits::addr_t upper_bits = ~traits::PGMASK;
|
// const typename traits::addr_t upper_bits = ~traits::PGMASK;
|
||||||
phys_addr_t paddr(pc);
|
phys_addr_t paddr(pc);
|
||||||
auto *const data = (uint8_t *)&instr;
|
auto *const data = (uint8_t *)&instr;
|
||||||
if(this->core.has_mmu())
|
|
||||||
paddr = this->core.virt2phys(pc);
|
|
||||||
//TODO: re-add page handling
|
|
||||||
// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
|
|
||||||
// auto res = this->core.read(paddr, 2, data);
|
|
||||||
// if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
|
||||||
// if ((instr & 0x3) == 0x3) { // this is a 32bit instruction
|
|
||||||
// res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
auto res = this->core.read(paddr, 4, data);
|
auto res = this->core.read(paddr, 4, data);
|
||||||
if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
if (res != iss::Ok)
|
||||||
// }
|
return std::make_tuple(ILLEGAL_FETCH, nullptr);
|
||||||
if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
if (instr == 0x0000006f || (instr&0xffff)==0xa001){
|
||||||
// curr pc on stack
|
this->builder.CreateBr(this->leave_blk);
|
||||||
++inst_cnt;
|
return std::make_tuple(JUMP_TO_SELF, nullptr);
|
||||||
auto f = decode_instr(root, instr);
|
}
|
||||||
|
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
||||||
|
compile_func f = nullptr;
|
||||||
|
if(inst_index < instr_descr.size())
|
||||||
|
f = instr_descr[inst_index].op;
|
||||||
if (f == nullptr) {
|
if (f == nullptr) {
|
||||||
f = &this_class::illegal_intruction;
|
f = &this_class::illegal_instruction;
|
||||||
}
|
}
|
||||||
return (this->*f)(pc, instr, this_block);
|
return (this->*f)(pc, instr, this_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_leave_behavior(BasicBlock *leave_blk) {
|
template <typename ARCH>
|
||||||
|
void vm_impl<ARCH>::gen_leave_behavior(BasicBlock *leave_blk) {
|
||||||
this->builder.SetInsertPoint(leave_blk);
|
this->builder.SetInsertPoint(leave_blk);
|
||||||
this->builder.CreateRet(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC),get_reg_ptr(traits::NEXT_PC), false));
|
this->builder.CreateRet(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC),get_reg_ptr(traits::NEXT_PC), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) {
|
template <typename ARCH>
|
||||||
|
void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) {
|
||||||
auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id);
|
auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id);
|
||||||
this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true);
|
this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true);
|
||||||
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), get_reg_ptr(traits::LAST_BRANCH), false);
|
this->builder.CreateBr(this->trap_blk);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
|
template <typename ARCH>
|
||||||
|
void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
|
||||||
std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, lvl)) };
|
std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, lvl)) };
|
||||||
this->builder.CreateCall(this->mod->getFunction("leave_trap"), args);
|
this->builder.CreateCall(this->mod->getFunction("leave_trap"), args);
|
||||||
auto *PC_val = this->gen_read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN / 8);
|
this->builder.CreateStore(this->gen_const(32U, static_cast<int>(UNKNOWN_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false);
|
||||||
this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false);
|
|
||||||
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), get_reg_ptr(traits::LAST_BRANCH), false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) {
|
template <typename ARCH>
|
||||||
|
void vm_impl<ARCH>::gen_wait(unsigned type) {
|
||||||
std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, type)) };
|
std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, type)) };
|
||||||
this->builder.CreateCall(this->mod->getFunction("wait"), args);
|
this->builder.CreateCall(this->mod->getFunction("wait"), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(BasicBlock *trap_blk) {
|
template <typename ARCH>
|
||||||
|
inline void vm_impl<ARCH>::set_tval(uint64_t tval) {
|
||||||
|
auto tmp_tval = this->gen_const(64, tval);
|
||||||
|
this->set_tval(tmp_tval);
|
||||||
|
}
|
||||||
|
template <typename ARCH>
|
||||||
|
inline void vm_impl<ARCH>::set_tval(Value* new_tval) {
|
||||||
|
this->builder.CreateStore(this->gen_ext(new_tval, 64, false), this->tval);
|
||||||
|
}
|
||||||
|
template <typename ARCH>
|
||||||
|
void vm_impl<ARCH>::gen_trap_behavior(BasicBlock *trap_blk) {
|
||||||
this->builder.SetInsertPoint(trap_blk);
|
this->builder.SetInsertPoint(trap_blk);
|
||||||
this->gen_sync(POST_SYNC, -1); //TODO get right InstrId
|
|
||||||
auto *trap_state_val = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true);
|
auto *trap_state_val = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true);
|
||||||
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()),
|
auto *cur_pc_val = this->builder.CreateLoad(this->get_typeptr(traits::PC), get_reg_ptr(traits::PC), true);
|
||||||
get_reg_ptr(traits::LAST_BRANCH), false);
|
std::vector<Value *> args{this->core_ptr,
|
||||||
std::vector<Value *> args{this->core_ptr, this->adj_to64(trap_state_val),
|
this->adj_to64(trap_state_val),
|
||||||
this->adj_to64(this->builder.CreateLoad(this->get_typeptr(traits::PC), get_reg_ptr(traits::PC), false))};
|
this->adj_to64(cur_pc_val),
|
||||||
|
this->adj_to64(this->builder.CreateLoad(this->get_type(64),this->tval))};
|
||||||
this->builder.CreateCall(this->mod->getFunction("enter_trap"), args);
|
this->builder.CreateCall(this->mod->getFunction("enter_trap"), args);
|
||||||
|
this->builder.CreateStore(this->gen_const(32U, static_cast<int>(UNKNOWN_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false);
|
||||||
|
|
||||||
auto *trap_addr_val = this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), false);
|
auto *trap_addr_val = this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), false);
|
||||||
this->builder.CreateRet(trap_addr_val);
|
this->builder.CreateRet(trap_addr_val);
|
||||||
}
|
}
|
||||||
|
template <typename ARCH>
|
||||||
|
void vm_impl<ARCH>::gen_instr_prologue() {
|
||||||
|
auto* trap_val =
|
||||||
|
this->builder.CreateLoad(this->get_typeptr(arch::traits<ARCH>::PENDING_TRAP), get_reg_ptr(arch::traits<ARCH>::PENDING_TRAP));
|
||||||
|
this->builder.CreateStore(trap_val, get_reg_ptr(arch::traits<ARCH>::TRAP_STATE), false);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(BasicBlock *bb) {
|
|
||||||
|
template <typename ARCH>
|
||||||
|
void vm_impl<ARCH>::gen_instr_epilogue(BasicBlock *bb) {
|
||||||
auto* target_bb = BasicBlock::Create(this->mod->getContext(), "", this->func, bb);
|
auto* target_bb = BasicBlock::Create(this->mod->getContext(), "", this->func, bb);
|
||||||
auto *v = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true);
|
auto *v = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true);
|
||||||
this->gen_cond_branch(this->builder.CreateICmp(
|
this->gen_cond_branch(this->builder.CreateICmp(
|
||||||
@ -346,6 +358,14 @@ template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(BasicBlock *b
|
|||||||
ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))),
|
ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))),
|
||||||
target_bb, this->trap_blk, 1);
|
target_bb, this->trap_blk, 1);
|
||||||
this->builder.SetInsertPoint(target_bb);
|
this->builder.SetInsertPoint(target_bb);
|
||||||
|
// update icount
|
||||||
|
auto* icount_val = this->builder.CreateAdd(
|
||||||
|
this->builder.CreateLoad(this->get_typeptr(arch::traits<ARCH>::ICOUNT), get_reg_ptr(arch::traits<ARCH>::ICOUNT)), this->gen_const(64U, 1));
|
||||||
|
this->builder.CreateStore(icount_val, get_reg_ptr(arch::traits<ARCH>::ICOUNT), false);
|
||||||
|
//increment cyclecount
|
||||||
|
auto* cycle_val = this->builder.CreateAdd(
|
||||||
|
this->builder.CreateLoad(this->get_typeptr(arch::traits<ARCH>::CYCLE), get_reg_ptr(arch::traits<ARCH>::CYCLE)), this->gen_const(64U, 1));
|
||||||
|
this->builder.CreateStore(cycle_val, get_reg_ptr(arch::traits<ARCH>::CYCLE), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ${coreDef.name.toLowerCase()}
|
} // namespace ${coreDef.name.toLowerCase()}
|
||||||
@ -359,24 +379,33 @@ std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreD
|
|||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
} // namespace iss
|
} // namespace iss
|
||||||
|
|
||||||
#include <iss/factory.h>
|
|
||||||
#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 <iss/factory.h>
|
||||||
namespace iss {
|
namespace iss {
|
||||||
namespace {
|
namespace {
|
||||||
volatile std::array<bool, 2> dummy = {
|
volatile std::array<bool, 2> dummy = {
|
||||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|llvm", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
|
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|llvm", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
|
||||||
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
||||||
auto* vm = new llvm::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
auto vm = new llvm::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
||||||
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
||||||
|
if(init_data){
|
||||||
|
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t*)>*>(init_data);
|
||||||
|
cpu->set_semihosting_callback(*cb);
|
||||||
|
}
|
||||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||||
}),
|
}),
|
||||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|llvm", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
|
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|llvm", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
|
||||||
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
||||||
auto* vm = new llvm::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
auto vm = new llvm::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
||||||
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
||||||
|
if(init_data){
|
||||||
|
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t*)>*>(init_data);
|
||||||
|
cpu->set_semihosting_callback(*cb);
|
||||||
|
}
|
||||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// clang-format on
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (C) 2020 MINRES Technologies GmbH
|
* Copyright (C) 2020-2024 MINRES Technologies GmbH
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -29,7 +29,7 @@
|
|||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
// clang-format off
|
||||||
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
||||||
#include <iss/debugger/gdb_session.h>
|
#include <iss/debugger/gdb_session.h>
|
||||||
#include <iss/debugger/server.h>
|
#include <iss/debugger/server.h>
|
||||||
@ -37,7 +37,10 @@
|
|||||||
#include <iss/tcc/vm_base.h>
|
#include <iss/tcc/vm_base.h>
|
||||||
#include <util/logging.h>
|
#include <util/logging.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <iss/instruction_decoder.h>
|
||||||
|
<%def fcsr = registers.find {it.name=='FCSR'}
|
||||||
|
if(fcsr != null) {%>
|
||||||
|
#include <vm/fp_functions.h><%}%>
|
||||||
#ifndef FMT_HEADER_ONLY
|
#ifndef FMT_HEADER_ONLY
|
||||||
#define FMT_HEADER_ONLY
|
#define FMT_HEADER_ONLY
|
||||||
#endif
|
#endif
|
||||||
@ -80,16 +83,21 @@ protected:
|
|||||||
using vm_base<ARCH>::get_reg_ptr;
|
using vm_base<ARCH>::get_reg_ptr;
|
||||||
|
|
||||||
using this_class = vm_impl<ARCH>;
|
using this_class = vm_impl<ARCH>;
|
||||||
using compile_ret_t = std::tuple<continuation_e>;
|
using compile_ret_t = continuation_e;
|
||||||
using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, tu_builder&);
|
using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, tu_builder&);
|
||||||
|
|
||||||
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
|
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
|
||||||
|
<%
|
||||||
|
if(fcsr != null) {%>
|
||||||
|
inline const char *fname(size_t index){return index < 32?name(index+traits::F0):"illegal";}
|
||||||
|
<%}%>
|
||||||
|
void add_prologue(tu_builder& tu) override;
|
||||||
|
|
||||||
void setup_module(std::string m) override {
|
void setup_module(std::string m) override {
|
||||||
super::setup_module(m);
|
super::setup_module(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
compile_ret_t gen_single_inst_behavior(virt_addr_t &, unsigned int &, tu_builder&) override;
|
compile_ret_t gen_single_inst_behavior(virt_addr_t &, tu_builder&) override;
|
||||||
|
|
||||||
void gen_trap_behavior(tu_builder& tu) override;
|
void gen_trap_behavior(tu_builder& tu) override;
|
||||||
|
|
||||||
@ -97,7 +105,9 @@ protected:
|
|||||||
|
|
||||||
void gen_leave_trap(tu_builder& tu, unsigned lvl);
|
void gen_leave_trap(tu_builder& tu, unsigned lvl);
|
||||||
|
|
||||||
void gen_wait(tu_builder& tu, unsigned type);
|
inline void gen_set_tval(tu_builder& tu, uint64_t new_tval);
|
||||||
|
|
||||||
|
inline void gen_set_tval(tu_builder& tu, value new_tval);
|
||||||
|
|
||||||
inline void gen_trap_check(tu_builder& tu) {
|
inline void gen_trap_check(tu_builder& tu) {
|
||||||
tu("if(*trap_state!=0) goto trap_entry;");
|
tu("if(*trap_state!=0) goto trap_entry;");
|
||||||
@ -128,32 +138,56 @@ protected:
|
|||||||
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
|
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<%functions.each{ it.eachLine { %>
|
||||||
|
${it}<%}
|
||||||
|
}
|
||||||
|
if(fcsr != null) {%>
|
||||||
|
value NaNBox16(tu_builder& tu, value NaNBox16_val){
|
||||||
|
if(static_cast<uint32_t>(traits::FLEN) == 16)
|
||||||
|
return tu.ext(NaNBox16_val, traits::FLEN, false);
|
||||||
|
else {
|
||||||
|
auto box = tu.assignment(tu.logical_neg((tu.ext(0, 32, false))), traits::FLEN) ;
|
||||||
|
return tu.ext((tu.bitwise_or(tu.shl(box, 16), NaNBox16_val)), traits::FLEN, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
value NaNBox32(tu_builder& tu, value NaNBox32_val){
|
||||||
|
if(static_cast<uint32_t>(traits::FLEN) == 32)
|
||||||
|
return tu.ext(NaNBox32_val, traits::FLEN, false);
|
||||||
|
else {
|
||||||
|
auto box = tu.assignment(tu.logical_neg((tu.ext(0, 64, false))), traits::FLEN) ;
|
||||||
|
return tu.ext((tu.bitwise_or(tu.shl(box, 32), NaNBox32_val)), traits::FLEN, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
value NaNBox64(tu_builder& tu, value NaNBox64_val){
|
||||||
|
if(static_cast<uint32_t>(traits::FLEN) == 64)
|
||||||
|
return tu.ext(NaNBox64_val, traits::FLEN, false);
|
||||||
|
else {
|
||||||
|
throw new std::runtime_error("tcc does not support Registers wider than 64 bits");
|
||||||
|
auto box = tu.assignment(tu.logical_neg((tu.ext(0, 128, false))), traits::FLEN) ;
|
||||||
|
return tu.ext((tu.bitwise_or(tu.shl(box, 64), NaNBox64_val)), traits::FLEN, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
<%}%>
|
||||||
private:
|
private:
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* start opcode definitions
|
* start opcode definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
struct instruction_descriptor {
|
struct instruction_descriptor {
|
||||||
size_t length;
|
uint32_t length;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
compile_func op;
|
compile_func op;
|
||||||
};
|
};
|
||||||
struct decoding_tree_node{
|
|
||||||
std::vector<instruction_descriptor> instrs;
|
|
||||||
std::vector<decoding_tree_node*> children;
|
|
||||||
uint32_t submask = std::numeric_limits<uint32_t>::max();
|
|
||||||
uint32_t value;
|
|
||||||
decoding_tree_node(uint32_t value) : value(value){}
|
|
||||||
};
|
|
||||||
|
|
||||||
decoding_tree_node* root {nullptr};
|
const std::array<instruction_descriptor, ${instructions.size()}> instr_descr = {{
|
||||||
|
|
||||||
const std::array<instruction_descriptor, ${instructions.size}> instr_descr = {{
|
|
||||||
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
|
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
|
||||||
/* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */
|
/* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */
|
||||||
{${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
|
{${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
//needs to be declared after instr_descr
|
||||||
|
decoder instr_decoder;
|
||||||
|
|
||||||
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
|
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
|
||||||
/* instruction ${idx}: ${instr.name} */
|
/* instruction ${idx}: ${instr.name} */
|
||||||
compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, tu_builder& tu){
|
compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, tu_builder& tu){
|
||||||
@ -164,82 +198,39 @@ private:
|
|||||||
<%}%>if(this->disass_enabled){
|
<%}%>if(this->disass_enabled){
|
||||||
/* generate console output when executing the command */<%instr.disass.eachLine{%>
|
/* generate console output when executing the command */<%instr.disass.eachLine{%>
|
||||||
${it}<%}%>
|
${it}<%}%>
|
||||||
|
tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic);
|
||||||
}
|
}
|
||||||
auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]);
|
auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]);
|
||||||
pc=pc+ ${instr.length/8};
|
pc=pc+ ${instr.length/8};
|
||||||
gen_set_pc(tu, pc, traits::NEXT_PC);
|
gen_set_pc(tu, pc, traits::NEXT_PC);
|
||||||
|
tu("(*cycle)++;");
|
||||||
tu.open_scope();
|
tu.open_scope();
|
||||||
|
this->gen_set_tval(tu, instr);
|
||||||
<%instr.behavior.eachLine{%>${it}
|
<%instr.behavior.eachLine{%>${it}
|
||||||
<%}%>
|
<%}%>
|
||||||
|
tu("(*icount)++;");
|
||||||
|
tu("(*instret)++;");
|
||||||
tu.close_scope();
|
tu.close_scope();
|
||||||
gen_trap_check(tu);
|
|
||||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,${idx});
|
vm_base<ARCH>::gen_sync(tu, POST_SYNC,${idx});
|
||||||
|
gen_trap_check(tu);
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
<%}%>
|
<%}%>
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* end opcode definitions
|
* end opcode definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr, tu_builder& tu) {
|
compile_ret_t illegal_instruction(virt_addr_t &pc, code_word_t instr, tu_builder& tu) {
|
||||||
vm_impl::gen_sync(tu, iss::PRE_SYNC, instr_descr.size());
|
vm_impl::gen_sync(tu, iss::PRE_SYNC, instr_descr.size());
|
||||||
|
if(this->disass_enabled){
|
||||||
|
/* generate console output when executing the command */
|
||||||
|
tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, std::string("illegal_instruction"));
|
||||||
|
}
|
||||||
pc = pc + ((instr & 3) == 3 ? 4 : 2);
|
pc = pc + ((instr & 3) == 3 ? 4 : 2);
|
||||||
gen_raise_trap(tu, 0, 2); // illegal instruction trap
|
gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
|
||||||
|
this->gen_set_tval(tu, instr);
|
||||||
vm_impl::gen_sync(tu, iss::POST_SYNC, instr_descr.size());
|
vm_impl::gen_sync(tu, iss::POST_SYNC, instr_descr.size());
|
||||||
vm_impl::gen_trap_check(tu);
|
vm_impl::gen_trap_check(tu);
|
||||||
return BRANCH;
|
return ILLEGAL_INSTR;
|
||||||
}
|
|
||||||
|
|
||||||
//decoding functionality
|
|
||||||
|
|
||||||
void populate_decoding_tree(decoding_tree_node* root){
|
|
||||||
//create submask
|
|
||||||
for(auto instr: root->instrs){
|
|
||||||
root->submask &= instr.mask;
|
|
||||||
}
|
|
||||||
//put each instr according to submask&encoding into children
|
|
||||||
for(auto instr: root->instrs){
|
|
||||||
bool foundMatch = false;
|
|
||||||
for(auto child: root->children){
|
|
||||||
//use value as identifying trait
|
|
||||||
if(child->value == (instr.value&root->submask)){
|
|
||||||
child->instrs.push_back(instr);
|
|
||||||
foundMatch = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!foundMatch){
|
|
||||||
decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask);
|
|
||||||
child->instrs.push_back(instr);
|
|
||||||
root->children.push_back(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
root->instrs.clear();
|
|
||||||
//call populate_decoding_tree for all children
|
|
||||||
if(root->children.size() >1)
|
|
||||||
for(auto child: root->children){
|
|
||||||
populate_decoding_tree(child);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
//sort instrs by value of the mask, this works bc we want to have the least restrictive one last
|
|
||||||
std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) {
|
|
||||||
return instr1.mask > instr2.mask;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
compile_func decode_instr(decoding_tree_node* node, code_word_t word){
|
|
||||||
if(!node->children.size()){
|
|
||||||
if(node->instrs.size() == 1) return node->instrs[0].op;
|
|
||||||
for(auto instr : node->instrs){
|
|
||||||
if((instr.mask&word) == instr.value) return instr.op;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
for(auto child : node->children){
|
|
||||||
if (child->value == (node->submask&word)){
|
|
||||||
return decode_instr(child, word);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -252,65 +243,139 @@ template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
|
|||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
||||||
: vm_base<ARCH>(core, core_id, cluster_id) {
|
: vm_base<ARCH>(core, core_id, cluster_id)
|
||||||
root = new decoding_tree_node(std::numeric_limits<uint32_t>::max());
|
, instr_decoder([this]() {
|
||||||
for(auto instr:instr_descr){
|
std::vector<generic_instruction_descriptor> g_instr_descr;
|
||||||
root->instrs.push_back(instr);
|
g_instr_descr.reserve(instr_descr.size());
|
||||||
}
|
for (uint32_t i = 0; i < instr_descr.size(); ++i) {
|
||||||
populate_decoding_tree(root);
|
generic_instruction_descriptor new_instr_descr {instr_descr[i].value, instr_descr[i].mask, i};
|
||||||
|
g_instr_descr.push_back(new_instr_descr);
|
||||||
}
|
}
|
||||||
|
return std::move(g_instr_descr);
|
||||||
|
}()) {}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
std::tuple<continuation_e>
|
continuation_e
|
||||||
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, tu_builder& tu) {
|
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, tu_builder& tu) {
|
||||||
// we fetch at max 4 byte, alignment is 2
|
// we fetch at max 4 byte, alignment is 2
|
||||||
enum {TRAP_ID=1<<16};
|
enum {TRAP_ID=1<<16};
|
||||||
code_word_t instr = 0;
|
code_word_t instr = 0;
|
||||||
phys_addr_t paddr(pc);
|
phys_addr_t paddr(pc);
|
||||||
if(this->core.has_mmu())
|
|
||||||
paddr = this->core.virt2phys(pc);
|
|
||||||
//TODO: re-add page handling
|
|
||||||
// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
|
|
||||||
// auto res = this->core.read(paddr, 2, data);
|
|
||||||
// if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
|
||||||
// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction
|
|
||||||
// res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
auto res = this->core.read(paddr, 4, reinterpret_cast<uint8_t*>(&instr));
|
auto res = this->core.read(paddr, 4, reinterpret_cast<uint8_t*>(&instr));
|
||||||
if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
if (res != iss::Ok)
|
||||||
// }
|
return ILLEGAL_FETCH;
|
||||||
if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
if (instr == 0x0000006f || (instr&0xffff)==0xa001)
|
||||||
// curr pc on stack
|
return JUMP_TO_SELF;
|
||||||
++inst_cnt;
|
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
||||||
auto f = decode_instr(root, instr);
|
compile_func f = nullptr;
|
||||||
|
if(inst_index < instr_descr.size())
|
||||||
|
f = instr_descr[inst_index].op;
|
||||||
if (f == nullptr) {
|
if (f == nullptr) {
|
||||||
f = &this_class::illegal_intruction;
|
f = &this_class::illegal_instruction;
|
||||||
}
|
}
|
||||||
return (this->*f)(pc, instr, tu);
|
return (this->*f)(pc, instr, tu);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) {
|
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) {
|
||||||
tu(" *trap_state = {:#x};", 0x80 << 24 | (cause << 16) | trap_id);
|
tu(" *trap_state = {:#x};", 0x80 << 24 | (cause << 16) | trap_id);
|
||||||
tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits<uint32_t>::max(), 32));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(tu_builder& tu, unsigned lvl) {
|
template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(tu_builder& tu, unsigned lvl) {
|
||||||
tu("leave_trap(core_ptr, {});", lvl);
|
tu("leave_trap(core_ptr, {});", lvl);
|
||||||
tu.store(traits::NEXT_PC, tu.read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN));
|
tu.store(traits::NEXT_PC, tu.read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN));
|
||||||
tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits<uint32_t>::max(), 32));
|
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(UNKNOWN_JUMP), 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_wait(tu_builder& tu, unsigned type) {
|
template <typename ARCH> void vm_impl<ARCH>::gen_set_tval(tu_builder& tu, uint64_t new_tval) {
|
||||||
|
tu(fmt::format("tval = {};", new_tval));
|
||||||
|
}
|
||||||
|
template <typename ARCH> void vm_impl<ARCH>::gen_set_tval(tu_builder& tu, value new_tval) {
|
||||||
|
tu(fmt::format("tval = {};", new_tval.str));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(tu_builder& tu) {
|
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(tu_builder& tu) {
|
||||||
tu("trap_entry:");
|
tu("trap_entry:");
|
||||||
this->gen_sync(tu, POST_SYNC, -1);
|
this->gen_sync(tu, POST_SYNC, -1);
|
||||||
tu("enter_trap(core_ptr, *trap_state, *pc, 0);");
|
tu("enter_trap(core_ptr, *trap_state, *pc, tval);");
|
||||||
tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits<uint32_t>::max(),32));
|
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(UNKNOWN_JUMP),32));
|
||||||
tu("return *next_pc;");
|
tu("return *next_pc;");
|
||||||
}
|
}
|
||||||
|
template <typename ARCH> void vm_impl<ARCH>::add_prologue(tu_builder& tu){
|
||||||
|
std::ostringstream os;
|
||||||
|
os << tu.add_reg_ptr("trap_state", arch::traits<ARCH>::TRAP_STATE, this->regs_base_ptr);
|
||||||
|
os << tu.add_reg_ptr("pending_trap", arch::traits<ARCH>::PENDING_TRAP, this->regs_base_ptr);
|
||||||
|
os << tu.add_reg_ptr("cycle", arch::traits<ARCH>::CYCLE, this->regs_base_ptr);
|
||||||
|
<%if(fcsr != null) {
|
||||||
|
def flen = constants.find { it.name == 'FLEN' }?.value ?: 0
|
||||||
|
%>
|
||||||
|
os << "uint32_t (*fget_flags)()=" << (uintptr_t)&fget_flags << ";\\n";
|
||||||
|
|
||||||
|
os << "uint16_t (*fadd_h)(uint16_t v1, uint16_t v2, uint8_t mode)=" << (uintptr_t)&fadd_h << ";\\n";
|
||||||
|
os << "uint16_t (*fsub_h)(uint16_t v1, uint16_t v2, uint8_t mode)=" << (uintptr_t)&fsub_h << ";\\n";
|
||||||
|
os << "uint16_t (*fmul_h)(uint16_t v1, uint16_t v2, uint8_t mode)=" << (uintptr_t)&fmul_h << ";\\n";
|
||||||
|
os << "uint16_t (*fdiv_h)(uint16_t v1, uint16_t v2, uint8_t mode)=" << (uintptr_t)&fdiv_h << ";\\n";
|
||||||
|
os << "uint16_t (*fsqrt_h)(uint16_t v1, uint8_t mode)=" << (uintptr_t)&fsqrt_h << ";\\n";
|
||||||
|
os << "uint16_t (*fcmp_h)(uint16_t v1, uint16_t v2, uint16_t op)=" << (uintptr_t)&fcmp_h << ";\\n";
|
||||||
|
os << "uint16_t (*fmadd_h)(uint16_t v1, uint16_t v2, uint16_t v3, uint16_t op, uint8_t mode)=" << (uintptr_t)&fmadd_h << ";\\n";
|
||||||
|
os << "uint16_t (*fsel_h)(uint16_t v1, uint16_t v2, uint16_t op)=" << (uintptr_t)&fsel_h << ";\\n";
|
||||||
|
os << "uint16_t (*fclass_h)(uint16_t v1)=" << (uintptr_t)&fclass_h << ";\\n";
|
||||||
|
os << "uint16_t (*unbox_h)(uint8_t FLEN, uint64_t v)=" << (uintptr_t)&unbox_h << ";\\n";
|
||||||
|
|
||||||
|
os << "uint32_t (*f16toi32)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f16toi32 << ";\\n";
|
||||||
|
os << "uint32_t (*f16toui32)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f16toui32 << ";\\n";
|
||||||
|
os << "uint16_t (*i32tof16)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&i32tof16 << ";\\n";
|
||||||
|
os << "uint16_t (*ui32tof16)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&ui32tof16 << ";\\n";
|
||||||
|
os << "uint64_t (*f16toi64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f16toi64 <<";\\n";
|
||||||
|
os << "uint64_t (*f16toui64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f16toui64 <<";\\n";
|
||||||
|
os << "uint16_t (*i64tof16)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&i64tof16 <<";\\n";
|
||||||
|
os << "uint16_t (*ui64tof16)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&ui64tof16 <<";\\n";
|
||||||
|
|
||||||
|
os << "uint32_t (*fadd_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fadd_s << ";\\n";
|
||||||
|
os << "uint32_t (*fsub_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fsub_s << ";\\n";
|
||||||
|
os << "uint32_t (*fmul_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fmul_s << ";\\n";
|
||||||
|
os << "uint32_t (*fdiv_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fdiv_s << ";\\n";
|
||||||
|
os << "uint32_t (*fsqrt_s)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&fsqrt_s << ";\\n";
|
||||||
|
os << "uint32_t (*fcmp_s)(uint32_t v1, uint32_t v2, uint32_t op)=" << (uintptr_t)&fcmp_s << ";\\n";
|
||||||
|
os << "uint32_t (*fmadd_s)(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mode)=" << (uintptr_t)&fmadd_s << ";\\n";
|
||||||
|
os << "uint32_t (*fsel_s)(uint32_t v1, uint32_t v2, uint32_t op)=" << (uintptr_t)&fsel_s << ";\\n";
|
||||||
|
os << "uint32_t (*fclass_s)( uint32_t v1 )=" << (uintptr_t)&fclass_s << ";\\n";
|
||||||
|
os << "uint32_t (*unbox_s)(uint8_t FLEN, uint64_t v)=" << (uintptr_t)&unbox_s << ";\\n";
|
||||||
|
|
||||||
|
os << "uint32_t (*f32toi32)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f32toi32 << ";\\n";
|
||||||
|
os << "uint32_t (*f32toui32)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f32toui32 << ";\\n";
|
||||||
|
os << "uint32_t (*i32tof32)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&i32tof32 << ";\\n";
|
||||||
|
os << "uint32_t (*ui32tof32)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&ui32tof32 << ";\\n";
|
||||||
|
os << "uint64_t (*f32toi64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f32toi64 <<";\\n";
|
||||||
|
os << "uint64_t (*f32toui64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f32toui64 <<";\\n";
|
||||||
|
os << "uint32_t (*i64tof32)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&i64tof32 <<";\\n";
|
||||||
|
os << "uint32_t (*ui64tof32)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&ui64tof32 <<";\\n";
|
||||||
|
<%if(flen > 32) {%>
|
||||||
|
|
||||||
|
os << "uint64_t (*fadd_d)(uint64_t v1, uint64_t v2, uint8_t mode)=" << (uintptr_t)&fadd_d << ";\\n";
|
||||||
|
os << "uint64_t (*fsub_d)(uint64_t v1, uint64_t v2, uint8_t mode)=" << (uintptr_t)&fsub_d << ";\\n";
|
||||||
|
os << "uint64_t (*fmul_d)(uint64_t v1, uint64_t v2, uint8_t mode)=" << (uintptr_t)&fmul_d << ";\\n";
|
||||||
|
os << "uint64_t (*fdiv_d)(uint64_t v1, uint64_t v2, uint8_t mode)=" << (uintptr_t)&fdiv_d << ";\\n";
|
||||||
|
os << "uint64_t (*fsqrt_d)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&fsqrt_d << ";\\n";
|
||||||
|
os << "uint64_t (*fcmp_d)(uint64_t v1, uint64_t v2, uint32_t op)=" << (uintptr_t)&fcmp_d << ";\\n";
|
||||||
|
os << "uint64_t (*fmadd_d)(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode)=" << (uintptr_t)&fmadd_d << ";\\n";
|
||||||
|
os << "uint64_t (*fsel_d)(uint64_t v1, uint64_t v2, uint32_t op)=" << (uintptr_t)&fsel_d << ";\\n";
|
||||||
|
os << "uint64_t (*fclass_d)(uint64_t v1 )=" << (uintptr_t)&fclass_d << ";\\n";
|
||||||
|
os << "uint64_t (*unbox_d)(uint8_t FLEN, uint64_t v)=" << (uintptr_t)&unbox_d << ";\\n";
|
||||||
|
|
||||||
|
os << "uint32_t (*f64tof32)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&f64tof32 << ";\\n";
|
||||||
|
os << "uint64_t (*f32tof64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f32tof64 << ";\\n";
|
||||||
|
os << "uint64_t (*f64toi64)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&f64toi64 <<";\\n";
|
||||||
|
os << "uint64_t (*f64toui64)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&f64toui64 <<";\\n";
|
||||||
|
os << "uint64_t (*i64tof64)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&i64tof64 <<";\\n";
|
||||||
|
os << "uint64_t (*ui64tof64)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&ui64tof64 <<";\\n";
|
||||||
|
os << "uint64_t (*i32tof64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&i32tof64 <<";\\n";
|
||||||
|
os << "uint64_t (*ui32tof64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&ui32tof64 <<";\\n";
|
||||||
|
os << "uint32_t (*f64toi32)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&f64toi32 <<";\\n";
|
||||||
|
os << "uint32_t (*f64toui32)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&f64toui32 <<";\\n";
|
||||||
|
<%}
|
||||||
|
}%>
|
||||||
|
tu.add_prologue(os.str());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ${coreDef.name.toLowerCase()}
|
} // namespace ${coreDef.name.toLowerCase()}
|
||||||
|
|
||||||
@ -323,24 +388,33 @@ std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreD
|
|||||||
} // namesapce tcc
|
} // namesapce tcc
|
||||||
} // namespace iss
|
} // namespace iss
|
||||||
|
|
||||||
#include <iss/factory.h>
|
|
||||||
#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 <iss/factory.h>
|
||||||
namespace iss {
|
namespace iss {
|
||||||
namespace {
|
namespace {
|
||||||
volatile std::array<bool, 2> dummy = {
|
volatile std::array<bool, 2> dummy = {
|
||||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
|
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
|
||||||
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
||||||
auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
||||||
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
||||||
|
if(init_data){
|
||||||
|
auto* cb = reinterpret_cast<semihosting_cb_t<arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t>*>(init_data);
|
||||||
|
cpu->set_semihosting_callback(*cb);
|
||||||
|
}
|
||||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||||
}),
|
}),
|
||||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
|
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
|
||||||
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
||||||
auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
||||||
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
||||||
|
if(init_data){
|
||||||
|
auto* cb = reinterpret_cast<semihosting_cb_t<arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t>*>(init_data);
|
||||||
|
cpu->set_semihosting_callback(*cb);
|
||||||
|
}
|
||||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// clang-format on
|
2
softfloat/.gitignore
vendored
Normal file
2
softfloat/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
build/*/*.o
|
||||||
|
build/*/*.a
|
@ -327,7 +327,7 @@ set(OTHERS
|
|||||||
|
|
||||||
set(LIB_SOURCES ${PRIMITIVES} ${SPECIALIZE} ${OTHERS})
|
set(LIB_SOURCES ${PRIMITIVES} ${SPECIALIZE} ${OTHERS})
|
||||||
|
|
||||||
add_library(softfloat ${LIB_SOURCES})
|
add_library(softfloat STATIC ${LIB_SOURCES})
|
||||||
set_property(TARGET softfloat PROPERTY C_STANDARD 99)
|
set_property(TARGET softfloat PROPERTY C_STANDARD 99)
|
||||||
target_compile_definitions(softfloat PRIVATE
|
target_compile_definitions(softfloat PRIVATE
|
||||||
SOFTFLOAT_ROUND_ODD
|
SOFTFLOAT_ROUND_ODD
|
||||||
@ -347,7 +347,7 @@ set_target_properties(softfloat PROPERTIES
|
|||||||
|
|
||||||
install(TARGETS softfloat
|
install(TARGETS softfloat
|
||||||
EXPORT ${PROJECT_NAME}Targets # for downstream dependencies
|
EXPORT ${PROJECT_NAME}Targets # for downstream dependencies
|
||||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs # static lib
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/static COMPONENT libs # static lib
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs # shared lib
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs # shared lib
|
||||||
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs # for mac
|
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs # for mac
|
||||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT devel # headers for mac (note the different component -> different package)
|
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT devel # headers for mac (note the different component -> different package)
|
||||||
|
24
softfloat/README.md
Normal file
24
softfloat/README.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
Package Overview for Berkeley SoftFloat Release 3e
|
||||||
|
==================================================
|
||||||
|
|
||||||
|
John R. Hauser<br>
|
||||||
|
2018 January 20
|
||||||
|
|
||||||
|
|
||||||
|
Berkeley SoftFloat is a software implementation of binary floating-point
|
||||||
|
that conforms to the IEEE Standard for Floating-Point Arithmetic. SoftFloat
|
||||||
|
is distributed in the form of C source code. Building the SoftFloat sources
|
||||||
|
generates a library file (typically `softfloat.a` or `libsoftfloat.a`)
|
||||||
|
containing the floating-point subroutines.
|
||||||
|
|
||||||
|
|
||||||
|
The SoftFloat package is documented in the following files in the `doc`
|
||||||
|
subdirectory:
|
||||||
|
|
||||||
|
* [SoftFloat.html](http://www.jhauser.us/arithmetic/SoftFloat-3/doc/SoftFloat.html) Documentation for using the SoftFloat functions.
|
||||||
|
* [SoftFloat-source.html](http://www.jhauser.us/arithmetic/SoftFloat-3/doc/SoftFloat-source.html) Documentation for building SoftFloat.
|
||||||
|
* [SoftFloat-history.html](http://www.jhauser.us/arithmetic/SoftFloat-3/doc/SoftFloat-history.html) History of the major changes to SoftFloat.
|
||||||
|
|
||||||
|
Other files in the package comprise the source code for SoftFloat.
|
||||||
|
|
399
softfloat/build/Linux-RISCV64-GCC/Makefile
Normal file
399
softfloat/build/Linux-RISCV64-GCC/Makefile
Normal file
@ -0,0 +1,399 @@
|
|||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
#
|
||||||
|
# This Makefile is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||||
|
# Package, Release 3e, by John R. Hauser.
|
||||||
|
#
|
||||||
|
# Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
|
||||||
|
# University of California. All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
# this list of conditions, and the following disclaimer.
|
||||||
|
#
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions, and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# 3. Neither the name of the University nor the names of its contributors
|
||||||
|
# may be used to endorse or promote products derived from this software
|
||||||
|
# without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||||
|
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||||
|
# DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
#=============================================================================
|
||||||
|
|
||||||
|
SOURCE_DIR ?= ../../source
|
||||||
|
SPECIALIZE_TYPE ?= RISCV
|
||||||
|
MARCH ?= rv64gcv_zfh_zfhmin
|
||||||
|
MABI ?= lp64d
|
||||||
|
|
||||||
|
SOFTFLOAT_OPTS ?= \
|
||||||
|
-DSOFTFLOAT_ROUND_ODD -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV32TO16 \
|
||||||
|
-DSOFTFLOAT_FAST_DIV64TO32
|
||||||
|
|
||||||
|
DELETE = rm -f
|
||||||
|
C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include
|
||||||
|
COMPILE_C = \
|
||||||
|
riscv64-unknown-linux-gnu-gcc -c -march=$(MARCH) -mabi=$(MABI) -Werror-implicit-function-declaration -DSOFTFLOAT_FAST_INT64 \
|
||||||
|
$(SOFTFLOAT_OPTS) $(C_INCLUDES) -O2 -o $@
|
||||||
|
MAKELIB = ar crs $@
|
||||||
|
|
||||||
|
OBJ = .o
|
||||||
|
LIB = .a
|
||||||
|
|
||||||
|
OTHER_HEADERS = $(SOURCE_DIR)/include/opts-GCC.h
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: softfloat$(LIB)
|
||||||
|
|
||||||
|
OBJS_PRIMITIVES = \
|
||||||
|
s_eq128$(OBJ) \
|
||||||
|
s_le128$(OBJ) \
|
||||||
|
s_lt128$(OBJ) \
|
||||||
|
s_shortShiftLeft128$(OBJ) \
|
||||||
|
s_shortShiftRight128$(OBJ) \
|
||||||
|
s_shortShiftRightJam64$(OBJ) \
|
||||||
|
s_shortShiftRightJam64Extra$(OBJ) \
|
||||||
|
s_shortShiftRightJam128$(OBJ) \
|
||||||
|
s_shortShiftRightJam128Extra$(OBJ) \
|
||||||
|
s_shiftRightJam32$(OBJ) \
|
||||||
|
s_shiftRightJam64$(OBJ) \
|
||||||
|
s_shiftRightJam64Extra$(OBJ) \
|
||||||
|
s_shiftRightJam128$(OBJ) \
|
||||||
|
s_shiftRightJam128Extra$(OBJ) \
|
||||||
|
s_shiftRightJam256M$(OBJ) \
|
||||||
|
s_countLeadingZeros8$(OBJ) \
|
||||||
|
s_countLeadingZeros16$(OBJ) \
|
||||||
|
s_countLeadingZeros32$(OBJ) \
|
||||||
|
s_countLeadingZeros64$(OBJ) \
|
||||||
|
s_add128$(OBJ) \
|
||||||
|
s_add256M$(OBJ) \
|
||||||
|
s_sub128$(OBJ) \
|
||||||
|
s_sub256M$(OBJ) \
|
||||||
|
s_mul64ByShifted32To128$(OBJ) \
|
||||||
|
s_mul64To128$(OBJ) \
|
||||||
|
s_mul128By32$(OBJ) \
|
||||||
|
s_mul128To256M$(OBJ) \
|
||||||
|
s_approxRecip_1Ks$(OBJ) \
|
||||||
|
s_approxRecip32_1$(OBJ) \
|
||||||
|
s_approxRecipSqrt_1Ks$(OBJ) \
|
||||||
|
s_approxRecipSqrt32_1$(OBJ) \
|
||||||
|
|
||||||
|
OBJS_SPECIALIZE = \
|
||||||
|
softfloat_raiseFlags$(OBJ) \
|
||||||
|
s_f16UIToCommonNaN$(OBJ) \
|
||||||
|
s_commonNaNToF16UI$(OBJ) \
|
||||||
|
s_propagateNaNF16UI$(OBJ) \
|
||||||
|
s_bf16UIToCommonNaN$(OBJ) \
|
||||||
|
s_commonNaNToBF16UI$(OBJ) \
|
||||||
|
s_f32UIToCommonNaN$(OBJ) \
|
||||||
|
s_commonNaNToF32UI$(OBJ) \
|
||||||
|
s_propagateNaNF32UI$(OBJ) \
|
||||||
|
s_f64UIToCommonNaN$(OBJ) \
|
||||||
|
s_commonNaNToF64UI$(OBJ) \
|
||||||
|
s_propagateNaNF64UI$(OBJ) \
|
||||||
|
extF80M_isSignalingNaN$(OBJ) \
|
||||||
|
s_extF80UIToCommonNaN$(OBJ) \
|
||||||
|
s_commonNaNToExtF80UI$(OBJ) \
|
||||||
|
s_propagateNaNExtF80UI$(OBJ) \
|
||||||
|
f128M_isSignalingNaN$(OBJ) \
|
||||||
|
s_f128UIToCommonNaN$(OBJ) \
|
||||||
|
s_commonNaNToF128UI$(OBJ) \
|
||||||
|
s_propagateNaNF128UI$(OBJ) \
|
||||||
|
|
||||||
|
OBJS_OTHERS = \
|
||||||
|
s_roundToUI32$(OBJ) \
|
||||||
|
s_roundToUI64$(OBJ) \
|
||||||
|
s_roundToI32$(OBJ) \
|
||||||
|
s_roundToI64$(OBJ) \
|
||||||
|
s_normSubnormalBF16Sig$(OBJ) \
|
||||||
|
s_roundPackToBF16$(OBJ) \
|
||||||
|
s_normSubnormalF16Sig$(OBJ) \
|
||||||
|
s_roundPackToF16$(OBJ) \
|
||||||
|
s_normRoundPackToF16$(OBJ) \
|
||||||
|
s_addMagsF16$(OBJ) \
|
||||||
|
s_subMagsF16$(OBJ) \
|
||||||
|
s_mulAddF16$(OBJ) \
|
||||||
|
s_normSubnormalF32Sig$(OBJ) \
|
||||||
|
s_roundPackToF32$(OBJ) \
|
||||||
|
s_normRoundPackToF32$(OBJ) \
|
||||||
|
s_addMagsF32$(OBJ) \
|
||||||
|
s_subMagsF32$(OBJ) \
|
||||||
|
s_mulAddF32$(OBJ) \
|
||||||
|
s_normSubnormalF64Sig$(OBJ) \
|
||||||
|
s_roundPackToF64$(OBJ) \
|
||||||
|
s_normRoundPackToF64$(OBJ) \
|
||||||
|
s_addMagsF64$(OBJ) \
|
||||||
|
s_subMagsF64$(OBJ) \
|
||||||
|
s_mulAddF64$(OBJ) \
|
||||||
|
s_normSubnormalExtF80Sig$(OBJ) \
|
||||||
|
s_roundPackToExtF80$(OBJ) \
|
||||||
|
s_normRoundPackToExtF80$(OBJ) \
|
||||||
|
s_addMagsExtF80$(OBJ) \
|
||||||
|
s_subMagsExtF80$(OBJ) \
|
||||||
|
s_normSubnormalF128Sig$(OBJ) \
|
||||||
|
s_roundPackToF128$(OBJ) \
|
||||||
|
s_normRoundPackToF128$(OBJ) \
|
||||||
|
s_addMagsF128$(OBJ) \
|
||||||
|
s_subMagsF128$(OBJ) \
|
||||||
|
s_mulAddF128$(OBJ) \
|
||||||
|
softfloat_state$(OBJ) \
|
||||||
|
ui32_to_f16$(OBJ) \
|
||||||
|
ui32_to_f32$(OBJ) \
|
||||||
|
ui32_to_f64$(OBJ) \
|
||||||
|
ui32_to_extF80$(OBJ) \
|
||||||
|
ui32_to_extF80M$(OBJ) \
|
||||||
|
ui32_to_f128$(OBJ) \
|
||||||
|
ui32_to_f128M$(OBJ) \
|
||||||
|
ui64_to_f16$(OBJ) \
|
||||||
|
ui64_to_f32$(OBJ) \
|
||||||
|
ui64_to_f64$(OBJ) \
|
||||||
|
ui64_to_extF80$(OBJ) \
|
||||||
|
ui64_to_extF80M$(OBJ) \
|
||||||
|
ui64_to_f128$(OBJ) \
|
||||||
|
ui64_to_f128M$(OBJ) \
|
||||||
|
i32_to_f16$(OBJ) \
|
||||||
|
i32_to_f32$(OBJ) \
|
||||||
|
i32_to_f64$(OBJ) \
|
||||||
|
i32_to_extF80$(OBJ) \
|
||||||
|
i32_to_extF80M$(OBJ) \
|
||||||
|
i32_to_f128$(OBJ) \
|
||||||
|
i32_to_f128M$(OBJ) \
|
||||||
|
i64_to_f16$(OBJ) \
|
||||||
|
i64_to_f32$(OBJ) \
|
||||||
|
i64_to_f64$(OBJ) \
|
||||||
|
i64_to_extF80$(OBJ) \
|
||||||
|
i64_to_extF80M$(OBJ) \
|
||||||
|
i64_to_f128$(OBJ) \
|
||||||
|
i64_to_f128M$(OBJ) \
|
||||||
|
bf16_isSignalingNaN$(OBJ) \
|
||||||
|
bf16_to_f32$(OBJ) \
|
||||||
|
f16_to_ui32$(OBJ) \
|
||||||
|
f16_to_ui64$(OBJ) \
|
||||||
|
f16_to_i32$(OBJ) \
|
||||||
|
f16_to_i64$(OBJ) \
|
||||||
|
f16_to_ui32_r_minMag$(OBJ) \
|
||||||
|
f16_to_ui64_r_minMag$(OBJ) \
|
||||||
|
f16_to_i32_r_minMag$(OBJ) \
|
||||||
|
f16_to_i64_r_minMag$(OBJ) \
|
||||||
|
f16_to_f32$(OBJ) \
|
||||||
|
f16_to_f64$(OBJ) \
|
||||||
|
f16_to_extF80$(OBJ) \
|
||||||
|
f16_to_extF80M$(OBJ) \
|
||||||
|
f16_to_f128$(OBJ) \
|
||||||
|
f16_to_f128M$(OBJ) \
|
||||||
|
f16_roundToInt$(OBJ) \
|
||||||
|
f16_add$(OBJ) \
|
||||||
|
f16_sub$(OBJ) \
|
||||||
|
f16_mul$(OBJ) \
|
||||||
|
f16_mulAdd$(OBJ) \
|
||||||
|
f16_div$(OBJ) \
|
||||||
|
f16_rem$(OBJ) \
|
||||||
|
f16_sqrt$(OBJ) \
|
||||||
|
f16_eq$(OBJ) \
|
||||||
|
f16_le$(OBJ) \
|
||||||
|
f16_lt$(OBJ) \
|
||||||
|
f16_eq_signaling$(OBJ) \
|
||||||
|
f16_le_quiet$(OBJ) \
|
||||||
|
f16_lt_quiet$(OBJ) \
|
||||||
|
f16_isSignalingNaN$(OBJ) \
|
||||||
|
f32_to_ui32$(OBJ) \
|
||||||
|
f32_to_ui64$(OBJ) \
|
||||||
|
f32_to_i32$(OBJ) \
|
||||||
|
f32_to_i64$(OBJ) \
|
||||||
|
f32_to_ui32_r_minMag$(OBJ) \
|
||||||
|
f32_to_ui64_r_minMag$(OBJ) \
|
||||||
|
f32_to_i32_r_minMag$(OBJ) \
|
||||||
|
f32_to_i64_r_minMag$(OBJ) \
|
||||||
|
f32_to_bf16$(OBJ) \
|
||||||
|
f32_to_f16$(OBJ) \
|
||||||
|
f32_to_f64$(OBJ) \
|
||||||
|
f32_to_extF80$(OBJ) \
|
||||||
|
f32_to_extF80M$(OBJ) \
|
||||||
|
f32_to_f128$(OBJ) \
|
||||||
|
f32_to_f128M$(OBJ) \
|
||||||
|
f32_roundToInt$(OBJ) \
|
||||||
|
f32_add$(OBJ) \
|
||||||
|
f32_sub$(OBJ) \
|
||||||
|
f32_mul$(OBJ) \
|
||||||
|
f32_mulAdd$(OBJ) \
|
||||||
|
f32_div$(OBJ) \
|
||||||
|
f32_rem$(OBJ) \
|
||||||
|
f32_sqrt$(OBJ) \
|
||||||
|
f32_eq$(OBJ) \
|
||||||
|
f32_le$(OBJ) \
|
||||||
|
f32_lt$(OBJ) \
|
||||||
|
f32_eq_signaling$(OBJ) \
|
||||||
|
f32_le_quiet$(OBJ) \
|
||||||
|
f32_lt_quiet$(OBJ) \
|
||||||
|
f32_isSignalingNaN$(OBJ) \
|
||||||
|
f64_to_ui32$(OBJ) \
|
||||||
|
f64_to_ui64$(OBJ) \
|
||||||
|
f64_to_i32$(OBJ) \
|
||||||
|
f64_to_i64$(OBJ) \
|
||||||
|
f64_to_ui32_r_minMag$(OBJ) \
|
||||||
|
f64_to_ui64_r_minMag$(OBJ) \
|
||||||
|
f64_to_i32_r_minMag$(OBJ) \
|
||||||
|
f64_to_i64_r_minMag$(OBJ) \
|
||||||
|
f64_to_f16$(OBJ) \
|
||||||
|
f64_to_f32$(OBJ) \
|
||||||
|
f64_to_extF80$(OBJ) \
|
||||||
|
f64_to_extF80M$(OBJ) \
|
||||||
|
f64_to_f128$(OBJ) \
|
||||||
|
f64_to_f128M$(OBJ) \
|
||||||
|
f64_roundToInt$(OBJ) \
|
||||||
|
f64_add$(OBJ) \
|
||||||
|
f64_sub$(OBJ) \
|
||||||
|
f64_mul$(OBJ) \
|
||||||
|
f64_mulAdd$(OBJ) \
|
||||||
|
f64_div$(OBJ) \
|
||||||
|
f64_rem$(OBJ) \
|
||||||
|
f64_sqrt$(OBJ) \
|
||||||
|
f64_eq$(OBJ) \
|
||||||
|
f64_le$(OBJ) \
|
||||||
|
f64_lt$(OBJ) \
|
||||||
|
f64_eq_signaling$(OBJ) \
|
||||||
|
f64_le_quiet$(OBJ) \
|
||||||
|
f64_lt_quiet$(OBJ) \
|
||||||
|
f64_isSignalingNaN$(OBJ) \
|
||||||
|
extF80_to_ui32$(OBJ) \
|
||||||
|
extF80_to_ui64$(OBJ) \
|
||||||
|
extF80_to_i32$(OBJ) \
|
||||||
|
extF80_to_i64$(OBJ) \
|
||||||
|
extF80_to_ui32_r_minMag$(OBJ) \
|
||||||
|
extF80_to_ui64_r_minMag$(OBJ) \
|
||||||
|
extF80_to_i32_r_minMag$(OBJ) \
|
||||||
|
extF80_to_i64_r_minMag$(OBJ) \
|
||||||
|
extF80_to_f16$(OBJ) \
|
||||||
|
extF80_to_f32$(OBJ) \
|
||||||
|
extF80_to_f64$(OBJ) \
|
||||||
|
extF80_to_f128$(OBJ) \
|
||||||
|
extF80_roundToInt$(OBJ) \
|
||||||
|
extF80_add$(OBJ) \
|
||||||
|
extF80_sub$(OBJ) \
|
||||||
|
extF80_mul$(OBJ) \
|
||||||
|
extF80_div$(OBJ) \
|
||||||
|
extF80_rem$(OBJ) \
|
||||||
|
extF80_sqrt$(OBJ) \
|
||||||
|
extF80_eq$(OBJ) \
|
||||||
|
extF80_le$(OBJ) \
|
||||||
|
extF80_lt$(OBJ) \
|
||||||
|
extF80_eq_signaling$(OBJ) \
|
||||||
|
extF80_le_quiet$(OBJ) \
|
||||||
|
extF80_lt_quiet$(OBJ) \
|
||||||
|
extF80_isSignalingNaN$(OBJ) \
|
||||||
|
extF80M_to_ui32$(OBJ) \
|
||||||
|
extF80M_to_ui64$(OBJ) \
|
||||||
|
extF80M_to_i32$(OBJ) \
|
||||||
|
extF80M_to_i64$(OBJ) \
|
||||||
|
extF80M_to_ui32_r_minMag$(OBJ) \
|
||||||
|
extF80M_to_ui64_r_minMag$(OBJ) \
|
||||||
|
extF80M_to_i32_r_minMag$(OBJ) \
|
||||||
|
extF80M_to_i64_r_minMag$(OBJ) \
|
||||||
|
extF80M_to_f16$(OBJ) \
|
||||||
|
extF80M_to_f32$(OBJ) \
|
||||||
|
extF80M_to_f64$(OBJ) \
|
||||||
|
extF80M_to_f128M$(OBJ) \
|
||||||
|
extF80M_roundToInt$(OBJ) \
|
||||||
|
extF80M_add$(OBJ) \
|
||||||
|
extF80M_sub$(OBJ) \
|
||||||
|
extF80M_mul$(OBJ) \
|
||||||
|
extF80M_div$(OBJ) \
|
||||||
|
extF80M_rem$(OBJ) \
|
||||||
|
extF80M_sqrt$(OBJ) \
|
||||||
|
extF80M_eq$(OBJ) \
|
||||||
|
extF80M_le$(OBJ) \
|
||||||
|
extF80M_lt$(OBJ) \
|
||||||
|
extF80M_eq_signaling$(OBJ) \
|
||||||
|
extF80M_le_quiet$(OBJ) \
|
||||||
|
extF80M_lt_quiet$(OBJ) \
|
||||||
|
f128_to_ui32$(OBJ) \
|
||||||
|
f128_to_ui64$(OBJ) \
|
||||||
|
f128_to_i32$(OBJ) \
|
||||||
|
f128_to_i64$(OBJ) \
|
||||||
|
f128_to_ui32_r_minMag$(OBJ) \
|
||||||
|
f128_to_ui64_r_minMag$(OBJ) \
|
||||||
|
f128_to_i32_r_minMag$(OBJ) \
|
||||||
|
f128_to_i64_r_minMag$(OBJ) \
|
||||||
|
f128_to_f16$(OBJ) \
|
||||||
|
f128_to_f32$(OBJ) \
|
||||||
|
f128_to_extF80$(OBJ) \
|
||||||
|
f128_to_f64$(OBJ) \
|
||||||
|
f128_roundToInt$(OBJ) \
|
||||||
|
f128_add$(OBJ) \
|
||||||
|
f128_sub$(OBJ) \
|
||||||
|
f128_mul$(OBJ) \
|
||||||
|
f128_mulAdd$(OBJ) \
|
||||||
|
f128_div$(OBJ) \
|
||||||
|
f128_rem$(OBJ) \
|
||||||
|
f128_sqrt$(OBJ) \
|
||||||
|
f128_eq$(OBJ) \
|
||||||
|
f128_le$(OBJ) \
|
||||||
|
f128_lt$(OBJ) \
|
||||||
|
f128_eq_signaling$(OBJ) \
|
||||||
|
f128_le_quiet$(OBJ) \
|
||||||
|
f128_lt_quiet$(OBJ) \
|
||||||
|
f128_isSignalingNaN$(OBJ) \
|
||||||
|
f128M_to_ui32$(OBJ) \
|
||||||
|
f128M_to_ui64$(OBJ) \
|
||||||
|
f128M_to_i32$(OBJ) \
|
||||||
|
f128M_to_i64$(OBJ) \
|
||||||
|
f128M_to_ui32_r_minMag$(OBJ) \
|
||||||
|
f128M_to_ui64_r_minMag$(OBJ) \
|
||||||
|
f128M_to_i32_r_minMag$(OBJ) \
|
||||||
|
f128M_to_i64_r_minMag$(OBJ) \
|
||||||
|
f128M_to_f16$(OBJ) \
|
||||||
|
f128M_to_f32$(OBJ) \
|
||||||
|
f128M_to_extF80M$(OBJ) \
|
||||||
|
f128M_to_f64$(OBJ) \
|
||||||
|
f128M_roundToInt$(OBJ) \
|
||||||
|
f128M_add$(OBJ) \
|
||||||
|
f128M_sub$(OBJ) \
|
||||||
|
f128M_mul$(OBJ) \
|
||||||
|
f128M_mulAdd$(OBJ) \
|
||||||
|
f128M_div$(OBJ) \
|
||||||
|
f128M_rem$(OBJ) \
|
||||||
|
f128M_sqrt$(OBJ) \
|
||||||
|
f128M_eq$(OBJ) \
|
||||||
|
f128M_le$(OBJ) \
|
||||||
|
f128M_lt$(OBJ) \
|
||||||
|
f128M_eq_signaling$(OBJ) \
|
||||||
|
f128M_le_quiet$(OBJ) \
|
||||||
|
f128M_lt_quiet$(OBJ) \
|
||||||
|
|
||||||
|
OBJS_ALL = $(OBJS_PRIMITIVES) $(OBJS_SPECIALIZE) $(OBJS_OTHERS)
|
||||||
|
|
||||||
|
$(OBJS_ALL): \
|
||||||
|
$(OTHER_HEADERS) platform.h $(SOURCE_DIR)/include/primitiveTypes.h \
|
||||||
|
$(SOURCE_DIR)/include/primitives.h
|
||||||
|
$(OBJS_SPECIALIZE) $(OBJS_OTHERS): \
|
||||||
|
$(SOURCE_DIR)/include/softfloat_types.h $(SOURCE_DIR)/include/internals.h \
|
||||||
|
$(SOURCE_DIR)/$(SPECIALIZE_TYPE)/specialize.h \
|
||||||
|
$(SOURCE_DIR)/include/softfloat.h
|
||||||
|
|
||||||
|
$(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c
|
||||||
|
$(COMPILE_C) $(SOURCE_DIR)/$*.c
|
||||||
|
|
||||||
|
$(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c
|
||||||
|
$(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c
|
||||||
|
|
||||||
|
softfloat$(LIB): $(OBJS_ALL)
|
||||||
|
$(DELETE) $@
|
||||||
|
$(MAKELIB) $^
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
$(DELETE) $(OBJS_ALL) softfloat$(LIB)
|
||||||
|
|
54
softfloat/build/Linux-RISCV64-GCC/platform.h
Normal file
54
softfloat/build/Linux-RISCV64-GCC/platform.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
|
||||||
|
/*============================================================================
|
||||||
|
|
||||||
|
This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||||
|
Package, Release 3e, by John R. Hauser.
|
||||||
|
|
||||||
|
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
|
||||||
|
University of California. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions, and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions, and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the University nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
#define LITTLEENDIAN 1
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
#ifdef __GNUC_STDC_INLINE__
|
||||||
|
#define INLINE inline
|
||||||
|
#else
|
||||||
|
#define INLINE extern inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
#define SOFTFLOAT_BUILTIN_CLZ 1
|
||||||
|
#define SOFTFLOAT_INTRINSIC_INT128 1
|
||||||
|
#include "opts-GCC.h"
|
||||||
|
|
@ -94,6 +94,8 @@ OBJS_SPECIALIZE = \
|
|||||||
s_f16UIToCommonNaN$(OBJ) \
|
s_f16UIToCommonNaN$(OBJ) \
|
||||||
s_commonNaNToF16UI$(OBJ) \
|
s_commonNaNToF16UI$(OBJ) \
|
||||||
s_propagateNaNF16UI$(OBJ) \
|
s_propagateNaNF16UI$(OBJ) \
|
||||||
|
s_bf16UIToCommonNaN$(OBJ) \
|
||||||
|
s_commonNaNToBF16UI$(OBJ) \
|
||||||
s_f32UIToCommonNaN$(OBJ) \
|
s_f32UIToCommonNaN$(OBJ) \
|
||||||
s_commonNaNToF32UI$(OBJ) \
|
s_commonNaNToF32UI$(OBJ) \
|
||||||
s_propagateNaNF32UI$(OBJ) \
|
s_propagateNaNF32UI$(OBJ) \
|
||||||
@ -114,6 +116,8 @@ OBJS_OTHERS = \
|
|||||||
s_roundToUI64$(OBJ) \
|
s_roundToUI64$(OBJ) \
|
||||||
s_roundToI32$(OBJ) \
|
s_roundToI32$(OBJ) \
|
||||||
s_roundToI64$(OBJ) \
|
s_roundToI64$(OBJ) \
|
||||||
|
s_normSubnormalBF16Sig$(OBJ) \
|
||||||
|
s_roundPackToBF16$(OBJ) \
|
||||||
s_normSubnormalF16Sig$(OBJ) \
|
s_normSubnormalF16Sig$(OBJ) \
|
||||||
s_roundPackToF16$(OBJ) \
|
s_roundPackToF16$(OBJ) \
|
||||||
s_normRoundPackToF16$(OBJ) \
|
s_normRoundPackToF16$(OBJ) \
|
||||||
@ -172,6 +176,8 @@ OBJS_OTHERS = \
|
|||||||
i64_to_extF80M$(OBJ) \
|
i64_to_extF80M$(OBJ) \
|
||||||
i64_to_f128$(OBJ) \
|
i64_to_f128$(OBJ) \
|
||||||
i64_to_f128M$(OBJ) \
|
i64_to_f128M$(OBJ) \
|
||||||
|
bf16_isSignalingNaN$(OBJ) \
|
||||||
|
bf16_to_f32$(OBJ) \
|
||||||
f16_to_ui32$(OBJ) \
|
f16_to_ui32$(OBJ) \
|
||||||
f16_to_ui64$(OBJ) \
|
f16_to_ui64$(OBJ) \
|
||||||
f16_to_i32$(OBJ) \
|
f16_to_i32$(OBJ) \
|
||||||
@ -209,6 +215,7 @@ OBJS_OTHERS = \
|
|||||||
f32_to_ui64_r_minMag$(OBJ) \
|
f32_to_ui64_r_minMag$(OBJ) \
|
||||||
f32_to_i32_r_minMag$(OBJ) \
|
f32_to_i32_r_minMag$(OBJ) \
|
||||||
f32_to_i64_r_minMag$(OBJ) \
|
f32_to_i64_r_minMag$(OBJ) \
|
||||||
|
f32_to_bf16$(OBJ) \
|
||||||
f32_to_f16$(OBJ) \
|
f32_to_f16$(OBJ) \
|
||||||
f32_to_f64$(OBJ) \
|
f32_to_f64$(OBJ) \
|
||||||
f32_to_extF80$(OBJ) \
|
f32_to_extF80$(OBJ) \
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
@ -115,6 +115,8 @@ OBJS_OTHERS = \
|
|||||||
s_roundToUI64$(OBJ) \
|
s_roundToUI64$(OBJ) \
|
||||||
s_roundToI32$(OBJ) \
|
s_roundToI32$(OBJ) \
|
||||||
s_roundToI64$(OBJ) \
|
s_roundToI64$(OBJ) \
|
||||||
|
s_normSubnormalBF16Sig$(OBJ) \
|
||||||
|
s_roundPackToBF16$(OBJ) \
|
||||||
s_normSubnormalF16Sig$(OBJ) \
|
s_normSubnormalF16Sig$(OBJ) \
|
||||||
s_roundPackToF16$(OBJ) \
|
s_roundPackToF16$(OBJ) \
|
||||||
s_normRoundPackToF16$(OBJ) \
|
s_normRoundPackToF16$(OBJ) \
|
||||||
@ -173,6 +175,8 @@ OBJS_OTHERS = \
|
|||||||
i64_to_extF80M$(OBJ) \
|
i64_to_extF80M$(OBJ) \
|
||||||
i64_to_f128$(OBJ) \
|
i64_to_f128$(OBJ) \
|
||||||
i64_to_f128M$(OBJ) \
|
i64_to_f128M$(OBJ) \
|
||||||
|
bf16_isSignalingNaN$(OBJ) \
|
||||||
|
bf16_to_f32$(OBJ) \
|
||||||
f16_to_ui32$(OBJ) \
|
f16_to_ui32$(OBJ) \
|
||||||
f16_to_ui64$(OBJ) \
|
f16_to_ui64$(OBJ) \
|
||||||
f16_to_i32$(OBJ) \
|
f16_to_i32$(OBJ) \
|
||||||
@ -210,6 +214,7 @@ OBJS_OTHERS = \
|
|||||||
f32_to_ui64_r_minMag$(OBJ) \
|
f32_to_ui64_r_minMag$(OBJ) \
|
||||||
f32_to_i32_r_minMag$(OBJ) \
|
f32_to_i32_r_minMag$(OBJ) \
|
||||||
f32_to_i64_r_minMag$(OBJ) \
|
f32_to_i64_r_minMag$(OBJ) \
|
||||||
|
f32_to_bf16$(OBJ) \
|
||||||
f32_to_f16$(OBJ) \
|
f32_to_f16$(OBJ) \
|
||||||
f32_to_f64$(OBJ) \
|
f32_to_f64$(OBJ) \
|
||||||
f32_to_extF80$(OBJ) \
|
f32_to_extF80$(OBJ) \
|
||||||
|
@ -508,7 +508,7 @@ significant extra cost.
|
|||||||
On computers where the word size is <NOBR>64 bits</NOBR> or larger, both
|
On computers where the word size is <NOBR>64 bits</NOBR> or larger, both
|
||||||
function versions (<CODE>f128M_add</CODE> and <CODE>f128_add</CODE>) are
|
function versions (<CODE>f128M_add</CODE> and <CODE>f128_add</CODE>) are
|
||||||
provided, because the cost of passing by value is then more reasonable.
|
provided, because the cost of passing by value is then more reasonable.
|
||||||
Applications that must be portable accross both classes of computers must use
|
Applications that must be portable across both classes of computers must use
|
||||||
the pointer-based functions, as these are always implemented.
|
the pointer-based functions, as these are always implemented.
|
||||||
However, if it is known that SoftFloat includes the by-value functions for all
|
However, if it is known that SoftFloat includes the by-value functions for all
|
||||||
platforms of interest, programmers can use whichever version they prefer.
|
platforms of interest, programmers can use whichever version they prefer.
|
||||||
|
59
softfloat/source/8086-SSE/s_bf16UIToCommonNaN.c
Normal file
59
softfloat/source/8086-SSE/s_bf16UIToCommonNaN.c
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
|
||||||
|
/*============================================================================
|
||||||
|
|
||||||
|
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||||
|
Package, Release 3e, by John R. Hauser.
|
||||||
|
|
||||||
|
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions, and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions, and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the University nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "platform.h"
|
||||||
|
#include "specialize.h"
|
||||||
|
#include "softfloat.h"
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
| Assuming `uiA' has the bit pattern of a BF16 NaN, converts
|
||||||
|
| this NaN to the common NaN form, and stores the resulting common NaN at the
|
||||||
|
| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
|
||||||
|
| exception is raised.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
void softfloat_bf16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr )
|
||||||
|
{
|
||||||
|
|
||||||
|
if ( softfloat_isSigNaNBF16UI( uiA ) ) {
|
||||||
|
softfloat_raiseFlags( softfloat_flag_invalid );
|
||||||
|
}
|
||||||
|
zPtr->sign = uiA>>15;
|
||||||
|
zPtr->v64 = (uint_fast64_t) uiA<<56;
|
||||||
|
zPtr->v0 = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
51
softfloat/source/8086-SSE/s_commonNaNToBF16UI.c
Normal file
51
softfloat/source/8086-SSE/s_commonNaNToBF16UI.c
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
|
||||||
|
/*============================================================================
|
||||||
|
|
||||||
|
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||||
|
Package, Release 3e, by John R. Hauser.
|
||||||
|
|
||||||
|
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions, and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions, and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the University nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "platform.h"
|
||||||
|
#include "specialize.h"
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
| Converts the common NaN pointed to by `aPtr' into a BF16 NaN, and
|
||||||
|
| returns the bit pattern of this value as an unsigned integer.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
uint_fast16_t softfloat_commonNaNToBF16UI( const struct commonNaN *aPtr )
|
||||||
|
{
|
||||||
|
|
||||||
|
return (uint_fast16_t) aPtr->sign<<15 | 0x7FC0 | aPtr->v64>>56;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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,28 @@ 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 );
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
| Returns true when 16-bit unsigned integer 'uiA' has the bit pattern of a
|
||||||
|
| 16-bit brain floating-point (BF16) signaling NaN.
|
||||||
|
| Note: This macro evaluates its argument more than once.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
#define softfloat_isSigNaNBF16UI(uiA) ((((uiA)&0x7FC0) == 0x7F80) && ((uiA)&0x003F))
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
| Assuming 'uiA' has the bit pattern of a 16-bit BF16 floating-point NaN, converts
|
||||||
|
| this NaN to the common NaN form, and stores the resulting common NaN at the
|
||||||
|
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||||
|
| exception is raised.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
void softfloat_bf16UIToCommonNaN(uint_fast16_t uiA, struct commonNaN* zPtr);
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
| Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point
|
||||||
|
| NaN, and returns the bit pattern of this value as an unsigned integer.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
uint_fast16_t softfloat_commonNaNToBF16UI(const struct commonNaN* aPtr);
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| 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 +169,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 +181,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 +204,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 +218,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 +235,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 +253,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 +267,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 +277,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 +294,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 +309,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 +324,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 +342,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 +350,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 +360,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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
5
softfloat/source/RISCV/s_bf16UIToCommonNaN.c
Normal file
5
softfloat/source/RISCV/s_bf16UIToCommonNaN.c
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
| This file intentionally contains no code.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
5
softfloat/source/RISCV/s_commonNaNToBF16UI.c
Normal file
5
softfloat/source/RISCV/s_commonNaNToBF16UI.c
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
| This file intentionally contains no code.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
@ -4,8 +4,8 @@
|
|||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||||
Package, Release 3e, by John R. Hauser.
|
Package, Release 3e, by John R. Hauser.
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
|
||||||
All rights reserved.
|
California. All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are met:
|
modification, are permitted provided that the following conditions are met:
|
||||||
@ -34,9 +34,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
=============================================================================*/
|
=============================================================================*/
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "internals.h"
|
#include "softfloat_types.h"
|
||||||
|
|
||||||
|
#define softfloat_commonNaNToExtF80M softfloat_commonNaNToExtF80M
|
||||||
#include "specialize.h"
|
#include "specialize.h"
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
@ -49,8 +50,8 @@ void
|
|||||||
const struct commonNaN *aPtr, struct extFloat80M *zSPtr )
|
const struct commonNaN *aPtr, struct extFloat80M *zSPtr )
|
||||||
{
|
{
|
||||||
|
|
||||||
zSPtr->signExp = packToExtF80UI64( aPtr->sign, 0x7FFF );
|
zSPtr->signExp = defaultNaNExtF80UI64;
|
||||||
zSPtr->signif = UINT64_C( 0xC000000000000000 ) | aPtr->v64>>1;
|
zSPtr->signif = defaultNaNExtF80UI0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||||
Package, Release 3e, by John R. Hauser.
|
Package, Release 3e, by John R. Hauser.
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
|
||||||
All rights reserved.
|
California. All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are met:
|
modification, are permitted provided that the following conditions are met:
|
||||||
@ -34,9 +34,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
=============================================================================*/
|
=============================================================================*/
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "primitives.h"
|
#include "primitiveTypes.h"
|
||||||
|
|
||||||
|
#define softfloat_commonNaNToExtF80UI softfloat_commonNaNToExtF80UI
|
||||||
#include "specialize.h"
|
#include "specialize.h"
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
@ -48,8 +49,8 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr )
|
|||||||
{
|
{
|
||||||
struct uint128 uiZ;
|
struct uint128 uiZ;
|
||||||
|
|
||||||
uiZ.v64 = (uint_fast16_t) aPtr->sign<<15 | 0x7FFF;
|
uiZ.v64 = defaultNaNExtF80UI64;
|
||||||
uiZ.v0 = UINT64_C( 0xC000000000000000 ) | aPtr->v64>>1;
|
uiZ.v0 = defaultNaNExtF80UI0;
|
||||||
return uiZ;
|
return uiZ;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||||
Package, Release 3e, by John R. Hauser.
|
Package, Release 3e, by John R. Hauser.
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
|
||||||
All rights reserved.
|
California. All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are met:
|
modification, are permitted provided that the following conditions are met:
|
||||||
@ -36,7 +36,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "primitives.h"
|
#include "primitiveTypes.h"
|
||||||
|
|
||||||
|
#define softfloat_commonNaNToF128M softfloat_commonNaNToF128M
|
||||||
#include "specialize.h"
|
#include "specialize.h"
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
@ -49,8 +51,10 @@ void
|
|||||||
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr )
|
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr )
|
||||||
{
|
{
|
||||||
|
|
||||||
softfloat_shortShiftRight128M( (const uint32_t *) &aPtr->v0, 16, zWPtr );
|
zWPtr[indexWord( 4, 3 )] = defaultNaNF128UI96;
|
||||||
zWPtr[indexWordHi( 4 )] |= (uint32_t) aPtr->sign<<31 | 0x7FFF8000;
|
zWPtr[indexWord( 4, 2 )] = defaultNaNF128UI64;
|
||||||
|
zWPtr[indexWord( 4, 1 )] = defaultNaNF128UI32;
|
||||||
|
zWPtr[indexWord( 4, 0 )] = defaultNaNF128UI0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||||
Package, Release 3e, by John R. Hauser.
|
Package, Release 3e, by John R. Hauser.
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
|
||||||
All rights reserved.
|
California. All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are met:
|
modification, are permitted provided that the following conditions are met:
|
||||||
@ -34,9 +34,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
=============================================================================*/
|
=============================================================================*/
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "primitives.h"
|
#include "primitiveTypes.h"
|
||||||
|
|
||||||
|
#define softfloat_commonNaNToF128UI softfloat_commonNaNToF128UI
|
||||||
#include "specialize.h"
|
#include "specialize.h"
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
@ -47,8 +48,8 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr )
|
|||||||
{
|
{
|
||||||
struct uint128 uiZ;
|
struct uint128 uiZ;
|
||||||
|
|
||||||
uiZ = softfloat_shortShiftRight128( aPtr->v64, aPtr->v0, 16 );
|
uiZ.v64 = defaultNaNF128UI64;
|
||||||
uiZ.v64 |= (uint_fast64_t) aPtr->sign<<63 | UINT64_C( 0x7FFF800000000000 );
|
uiZ.v0 = defaultNaNF128UI0;
|
||||||
return uiZ;
|
return uiZ;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,51 +1,5 @@
|
|||||||
|
|
||||||
/*============================================================================
|
|
||||||
|
|
||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
|
||||||
Package, Release 3e, by John R. Hauser.
|
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
|
|
||||||
California. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions, and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions, and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of the University nor the names of its contributors may
|
|
||||||
be used to endorse or promote products derived from this software without
|
|
||||||
specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
|
||||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
=============================================================================*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "platform.h"
|
|
||||||
#include "specialize.h"
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Converts the common NaN pointed to by `aPtr' into a 16-bit floating-point
|
| This file intentionally contains no code.
|
||||||
| NaN, and returns the bit pattern of this value as an unsigned integer.
|
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr )
|
|
||||||
{
|
|
||||||
|
|
||||||
return (uint_fast16_t) aPtr->sign<<15 | 0x7E00 | aPtr->v64>>54;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,51 +1,5 @@
|
|||||||
|
|
||||||
/*============================================================================
|
|
||||||
|
|
||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
|
||||||
Package, Release 3e, by John R. Hauser.
|
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions, and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions, and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of the University nor the names of its contributors may
|
|
||||||
be used to endorse or promote products derived from this software without
|
|
||||||
specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
|
||||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
=============================================================================*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "platform.h"
|
|
||||||
#include "specialize.h"
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Converts the common NaN pointed to by `aPtr' into a 32-bit floating-point
|
| This file intentionally contains no code.
|
||||||
| NaN, and returns the bit pattern of this value as an unsigned integer.
|
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr )
|
|
||||||
{
|
|
||||||
|
|
||||||
return (uint_fast32_t) aPtr->sign<<31 | 0x7FC00000 | aPtr->v64>>41;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,53 +1,5 @@
|
|||||||
|
|
||||||
/*============================================================================
|
|
||||||
|
|
||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
|
||||||
Package, Release 3e, by John R. Hauser.
|
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions, and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions, and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of the University nor the names of its contributors may
|
|
||||||
be used to endorse or promote products derived from this software without
|
|
||||||
specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
|
||||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
=============================================================================*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "platform.h"
|
|
||||||
#include "specialize.h"
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Converts the common NaN pointed to by `aPtr' into a 64-bit floating-point
|
| This file intentionally contains no code.
|
||||||
| NaN, and returns the bit pattern of this value as an unsigned integer.
|
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr )
|
|
||||||
{
|
|
||||||
|
|
||||||
return
|
|
||||||
(uint_fast64_t) aPtr->sign<<63 | UINT64_C( 0x7FF8000000000000 )
|
|
||||||
| aPtr->v64>>12;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,62 +1,5 @@
|
|||||||
|
|
||||||
/*============================================================================
|
|
||||||
|
|
||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
|
||||||
Package, Release 3e, by John R. Hauser.
|
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions, and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions, and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of the University nor the names of its contributors may
|
|
||||||
be used to endorse or promote products derived from this software without
|
|
||||||
specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
|
||||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
=============================================================================*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "platform.h"
|
|
||||||
#include "internals.h"
|
|
||||||
#include "specialize.h"
|
|
||||||
#include "softfloat.h"
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Assuming the 80-bit extended floating-point value pointed to by `aSPtr' is
|
| This file intentionally contains no code.
|
||||||
| a NaN, converts this NaN to the common NaN form, and stores the resulting
|
|
||||||
| common NaN at the location pointed to by `zPtr'. If the NaN is a signaling
|
|
||||||
| NaN, the invalid exception is raised.
|
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
|
||||||
softfloat_extF80MToCommonNaN(
|
|
||||||
const struct extFloat80M *aSPtr, struct commonNaN *zPtr )
|
|
||||||
{
|
|
||||||
|
|
||||||
if ( extF80M_isSignalingNaN( (const extFloat80_t *) aSPtr ) ) {
|
|
||||||
softfloat_raiseFlags( softfloat_flag_invalid );
|
|
||||||
}
|
|
||||||
zPtr->sign = signExtF80UI64( aSPtr->signExp );
|
|
||||||
zPtr->v64 = aSPtr->signif<<1;
|
|
||||||
zPtr->v0 = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,62 +1,5 @@
|
|||||||
|
|
||||||
/*============================================================================
|
|
||||||
|
|
||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
|
||||||
Package, Release 3e, by John R. Hauser.
|
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions, and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions, and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of the University nor the names of its contributors may
|
|
||||||
be used to endorse or promote products derived from this software without
|
|
||||||
specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
|
||||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
=============================================================================*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "platform.h"
|
|
||||||
#include "specialize.h"
|
|
||||||
#include "softfloat.h"
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0'
|
| This file intentionally contains no code.
|
||||||
| has the bit pattern of an 80-bit extended floating-point NaN, converts
|
|
||||||
| this NaN to the common NaN form, and stores the resulting common NaN at the
|
|
||||||
| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
|
|
||||||
| exception is raised.
|
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
|
||||||
softfloat_extF80UIToCommonNaN(
|
|
||||||
uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr )
|
|
||||||
{
|
|
||||||
|
|
||||||
if ( softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ) {
|
|
||||||
softfloat_raiseFlags( softfloat_flag_invalid );
|
|
||||||
}
|
|
||||||
zPtr->sign = uiA64>>15;
|
|
||||||
zPtr->v64 = uiA0<<1;
|
|
||||||
zPtr->v0 = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,62 +1,5 @@
|
|||||||
|
|
||||||
/*============================================================================
|
|
||||||
|
|
||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
|
||||||
Package, Release 3e, by John R. Hauser.
|
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions, and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions, and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of the University nor the names of its contributors may
|
|
||||||
be used to endorse or promote products derived from this software without
|
|
||||||
specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
|
||||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
=============================================================================*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "platform.h"
|
|
||||||
#include "primitives.h"
|
|
||||||
#include "specialize.h"
|
|
||||||
#include "softfloat.h"
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Assuming the 128-bit floating-point value pointed to by `aWPtr' is a NaN,
|
| This file intentionally contains no code.
|
||||||
| converts this NaN to the common NaN form, and stores the resulting common
|
|
||||||
| NaN at the location pointed to by `zPtr'. If the NaN is a signaling NaN,
|
|
||||||
| the invalid exception is raised. Argument `aWPtr' 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.
|
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
|
||||||
softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr )
|
|
||||||
{
|
|
||||||
|
|
||||||
if ( f128M_isSignalingNaN( (const float128_t *) aWPtr ) ) {
|
|
||||||
softfloat_raiseFlags( softfloat_flag_invalid );
|
|
||||||
}
|
|
||||||
zPtr->sign = aWPtr[indexWordHi( 4 )]>>31;
|
|
||||||
softfloat_shortShiftLeft128M( aWPtr, 16, (uint32_t *) &zPtr->v0 );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,65 +1,5 @@
|
|||||||
|
|
||||||
/*============================================================================
|
|
||||||
|
|
||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
|
||||||
Package, Release 3e, by John R. Hauser.
|
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions, and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions, and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of the University nor the names of its contributors may
|
|
||||||
be used to endorse or promote products derived from this software without
|
|
||||||
specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
|
||||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
=============================================================================*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "platform.h"
|
|
||||||
#include "primitives.h"
|
|
||||||
#include "specialize.h"
|
|
||||||
#include "softfloat.h"
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0'
|
| This file intentionally contains no code.
|
||||||
| has the bit pattern of a 128-bit floating-point NaN, converts this NaN to
|
|
||||||
| the common NaN form, and stores the resulting common NaN at the location
|
|
||||||
| pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid exception
|
|
||||||
| is raised.
|
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
|
||||||
softfloat_f128UIToCommonNaN(
|
|
||||||
uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr )
|
|
||||||
{
|
|
||||||
struct uint128 NaNSig;
|
|
||||||
|
|
||||||
if ( softfloat_isSigNaNF128UI( uiA64, uiA0 ) ) {
|
|
||||||
softfloat_raiseFlags( softfloat_flag_invalid );
|
|
||||||
}
|
|
||||||
NaNSig = softfloat_shortShiftLeft128( uiA64, uiA0, 16 );
|
|
||||||
zPtr->sign = uiA64>>63;
|
|
||||||
zPtr->v64 = NaNSig.v64;
|
|
||||||
zPtr->v0 = NaNSig.v0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,59 +1,5 @@
|
|||||||
|
|
||||||
/*============================================================================
|
|
||||||
|
|
||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
|
||||||
Package, Release 3e, by John R. Hauser.
|
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
|
|
||||||
California. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions, and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions, and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of the University nor the names of its contributors may
|
|
||||||
be used to endorse or promote products derived from this software without
|
|
||||||
specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
|
||||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
=============================================================================*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "platform.h"
|
|
||||||
#include "specialize.h"
|
|
||||||
#include "softfloat.h"
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Assuming `uiA' has the bit pattern of a 16-bit floating-point NaN, converts
|
| This file intentionally contains no code.
|
||||||
| this NaN to the common NaN form, and stores the resulting common NaN at the
|
|
||||||
| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
|
|
||||||
| exception is raised.
|
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr )
|
|
||||||
{
|
|
||||||
|
|
||||||
if ( softfloat_isSigNaNF16UI( uiA ) ) {
|
|
||||||
softfloat_raiseFlags( softfloat_flag_invalid );
|
|
||||||
}
|
|
||||||
zPtr->sign = uiA>>15;
|
|
||||||
zPtr->v64 = (uint_fast64_t) uiA<<54;
|
|
||||||
zPtr->v0 = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,59 +1,5 @@
|
|||||||
|
|
||||||
/*============================================================================
|
|
||||||
|
|
||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
|
||||||
Package, Release 3e, by John R. Hauser.
|
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions, and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions, and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of the University nor the names of its contributors may
|
|
||||||
be used to endorse or promote products derived from this software without
|
|
||||||
specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
|
||||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
=============================================================================*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "platform.h"
|
|
||||||
#include "specialize.h"
|
|
||||||
#include "softfloat.h"
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Assuming `uiA' has the bit pattern of a 32-bit floating-point NaN, converts
|
| This file intentionally contains no code.
|
||||||
| this NaN to the common NaN form, and stores the resulting common NaN at the
|
|
||||||
| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
|
|
||||||
| exception is raised.
|
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr )
|
|
||||||
{
|
|
||||||
|
|
||||||
if ( softfloat_isSigNaNF32UI( uiA ) ) {
|
|
||||||
softfloat_raiseFlags( softfloat_flag_invalid );
|
|
||||||
}
|
|
||||||
zPtr->sign = uiA>>31;
|
|
||||||
zPtr->v64 = (uint_fast64_t) uiA<<41;
|
|
||||||
zPtr->v0 = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,59 +1,5 @@
|
|||||||
|
|
||||||
/*============================================================================
|
|
||||||
|
|
||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
|
||||||
Package, Release 3e, by John R. Hauser.
|
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions, and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions, and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of the University nor the names of its contributors may
|
|
||||||
be used to endorse or promote products derived from this software without
|
|
||||||
specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
|
||||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
=============================================================================*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "platform.h"
|
|
||||||
#include "specialize.h"
|
|
||||||
#include "softfloat.h"
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Assuming `uiA' has the bit pattern of a 64-bit floating-point NaN, converts
|
| This file intentionally contains no code.
|
||||||
| this NaN to the common NaN form, and stores the resulting common NaN at the
|
|
||||||
| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
|
|
||||||
| exception is raised.
|
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr )
|
|
||||||
{
|
|
||||||
|
|
||||||
if ( softfloat_isSigNaNF64UI( uiA ) ) {
|
|
||||||
softfloat_raiseFlags( softfloat_flag_invalid );
|
|
||||||
}
|
|
||||||
zPtr->sign = uiA>>63;
|
|
||||||
zPtr->v64 = uiA<<12;
|
|
||||||
zPtr->v0 = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||||
Package, Release 3e, by John R. Hauser.
|
Package, Release 3e, by John R. Hauser.
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
|
||||||
All rights reserved.
|
California. All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are met:
|
modification, are permitted provided that the following conditions are met:
|
||||||
@ -34,10 +34,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
=============================================================================*/
|
=============================================================================*/
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "internals.h"
|
#include "primitiveTypes.h"
|
||||||
#include "specialize.h"
|
#include "specialize.h"
|
||||||
#include "softfloat.h"
|
#include "softfloat.h"
|
||||||
|
|
||||||
@ -54,54 +53,22 @@ void
|
|||||||
struct extFloat80M *zSPtr
|
struct extFloat80M *zSPtr
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
bool isSigNaNA;
|
uint_fast16_t ui64;
|
||||||
const struct extFloat80M *sPtr;
|
uint_fast64_t ui0;
|
||||||
bool isSigNaNB;
|
|
||||||
uint_fast16_t uiB64;
|
|
||||||
uint64_t uiB0;
|
|
||||||
uint_fast16_t uiA64;
|
|
||||||
uint64_t uiA0;
|
|
||||||
uint_fast16_t uiMagA64, uiMagB64;
|
|
||||||
|
|
||||||
isSigNaNA = extF80M_isSignalingNaN( (const extFloat80_t *) aSPtr );
|
ui64 = aSPtr->signExp;
|
||||||
sPtr = aSPtr;
|
ui0 = aSPtr->signif;
|
||||||
if ( ! bSPtr ) {
|
if (
|
||||||
if ( isSigNaNA ) softfloat_raiseFlags( softfloat_flag_invalid );
|
softfloat_isSigNaNExtF80UI( ui64, ui0 )
|
||||||
goto copy;
|
|| (bSPtr
|
||||||
}
|
&& (ui64 = bSPtr->signExp,
|
||||||
isSigNaNB = extF80M_isSignalingNaN( (const extFloat80_t *) bSPtr );
|
ui0 = bSPtr->signif,
|
||||||
if ( isSigNaNA | isSigNaNB ) {
|
softfloat_isSigNaNExtF80UI( ui64, ui0 )))
|
||||||
|
) {
|
||||||
softfloat_raiseFlags( softfloat_flag_invalid );
|
softfloat_raiseFlags( softfloat_flag_invalid );
|
||||||
if ( isSigNaNA ) {
|
|
||||||
uiB64 = bSPtr->signExp;
|
|
||||||
if ( isSigNaNB ) goto returnLargerUIMag;
|
|
||||||
uiB0 = bSPtr->signif;
|
|
||||||
if ( isNaNExtF80UI( uiB64, uiB0 ) ) goto copyB;
|
|
||||||
goto copy;
|
|
||||||
} else {
|
|
||||||
uiA64 = aSPtr->signExp;
|
|
||||||
uiA0 = aSPtr->signif;
|
|
||||||
if ( isNaNExtF80UI( uiA64, uiA0 ) ) goto copy;
|
|
||||||
goto copyB;
|
|
||||||
}
|
}
|
||||||
}
|
zSPtr->signExp = defaultNaNExtF80UI64;
|
||||||
uiB64 = bSPtr->signExp;
|
zSPtr->signif = defaultNaNExtF80UI0;
|
||||||
returnLargerUIMag:
|
|
||||||
uiA64 = aSPtr->signExp;
|
|
||||||
uiMagA64 = uiA64 & 0x7FFF;
|
|
||||||
uiMagB64 = uiB64 & 0x7FFF;
|
|
||||||
if ( uiMagA64 < uiMagB64 ) goto copyB;
|
|
||||||
if ( uiMagB64 < uiMagA64 ) goto copy;
|
|
||||||
uiA0 = aSPtr->signif;
|
|
||||||
uiB0 = bSPtr->signif;
|
|
||||||
if ( uiA0 < uiB0 ) goto copyB;
|
|
||||||
if ( uiB0 < uiA0 ) goto copy;
|
|
||||||
if ( uiA64 < uiB64 ) goto copy;
|
|
||||||
copyB:
|
|
||||||
sPtr = bSPtr;
|
|
||||||
copy:
|
|
||||||
zSPtr->signExp = sPtr->signExp;
|
|
||||||
zSPtr->signif = sPtr->signif | UINT64_C( 0xC000000000000000 );
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||||
Package, Release 3e, by John R. Hauser.
|
Package, Release 3e, by John R. Hauser.
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014, 2018 The Regents of the University of
|
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
|
||||||
California. All rights reserved.
|
California. All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@ -34,17 +34,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
=============================================================================*/
|
=============================================================================*/
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "internals.h"
|
#include "primitiveTypes.h"
|
||||||
#include "specialize.h"
|
#include "specialize.h"
|
||||||
#include "softfloat.h"
|
#include "softfloat.h"
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Interpreting the unsigned integer formed from concatenating 'uiA64' and
|
| Interpreting the unsigned integer formed from concatenating `uiA64' and
|
||||||
| 'uiA0' as an 80-bit extended floating-point value, and likewise interpreting
|
| `uiA0' as an 80-bit extended floating-point value, and likewise interpreting
|
||||||
| the unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another
|
| the unsigned integer formed from concatenating `uiB64' and `uiB0' as another
|
||||||
| 80-bit extended floating-point value, and assuming at least on of these
|
| 80-bit extended floating-point value, and assuming at least on of these
|
||||||
| floating-point values is a NaN, returns the bit pattern of the combined NaN
|
| floating-point values is a NaN, returns the bit pattern of the combined NaN
|
||||||
| result. If either original floating-point value is a signaling NaN, the
|
| result. If either original floating-point value is a signaling NaN, the
|
||||||
@ -58,48 +57,16 @@ struct uint128
|
|||||||
uint_fast64_t uiB0
|
uint_fast64_t uiB0
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
bool isSigNaNA, isSigNaNB;
|
|
||||||
uint_fast64_t uiNonsigA0, uiNonsigB0;
|
|
||||||
uint_fast16_t uiMagA64, uiMagB64;
|
|
||||||
struct uint128 uiZ;
|
struct uint128 uiZ;
|
||||||
|
|
||||||
/*------------------------------------------------------------------------
|
if (
|
||||||
*------------------------------------------------------------------------*/
|
softfloat_isSigNaNExtF80UI( uiA64, uiA0 )
|
||||||
isSigNaNA = softfloat_isSigNaNExtF80UI( uiA64, uiA0 );
|
|| softfloat_isSigNaNExtF80UI( uiB64, uiB0 )
|
||||||
isSigNaNB = softfloat_isSigNaNExtF80UI( uiB64, uiB0 );
|
) {
|
||||||
/*------------------------------------------------------------------------
|
|
||||||
| Make NaNs non-signaling.
|
|
||||||
*------------------------------------------------------------------------*/
|
|
||||||
uiNonsigA0 = uiA0 | UINT64_C( 0xC000000000000000 );
|
|
||||||
uiNonsigB0 = uiB0 | UINT64_C( 0xC000000000000000 );
|
|
||||||
/*------------------------------------------------------------------------
|
|
||||||
*------------------------------------------------------------------------*/
|
|
||||||
if ( isSigNaNA | isSigNaNB ) {
|
|
||||||
softfloat_raiseFlags( softfloat_flag_invalid );
|
softfloat_raiseFlags( softfloat_flag_invalid );
|
||||||
if ( isSigNaNA ) {
|
|
||||||
if ( isSigNaNB ) goto returnLargerMag;
|
|
||||||
if ( isNaNExtF80UI( uiB64, uiB0 ) ) goto returnB;
|
|
||||||
goto returnA;
|
|
||||||
} else {
|
|
||||||
if ( isNaNExtF80UI( uiA64, uiA0 ) ) goto returnA;
|
|
||||||
goto returnB;
|
|
||||||
}
|
}
|
||||||
}
|
uiZ.v64 = defaultNaNExtF80UI64;
|
||||||
returnLargerMag:
|
uiZ.v0 = defaultNaNExtF80UI0;
|
||||||
uiMagA64 = uiA64 & 0x7FFF;
|
|
||||||
uiMagB64 = uiB64 & 0x7FFF;
|
|
||||||
if ( uiMagA64 < uiMagB64 ) goto returnB;
|
|
||||||
if ( uiMagB64 < uiMagA64 ) goto returnA;
|
|
||||||
if ( uiA0 < uiB0 ) goto returnB;
|
|
||||||
if ( uiB0 < uiA0 ) goto returnA;
|
|
||||||
if ( uiA64 < uiB64 ) goto returnA;
|
|
||||||
returnB:
|
|
||||||
uiZ.v64 = uiB64;
|
|
||||||
uiZ.v0 = uiNonsigB0;
|
|
||||||
return uiZ;
|
|
||||||
returnA:
|
|
||||||
uiZ.v64 = uiA64;
|
|
||||||
uiZ.v0 = uiNonsigA0;
|
|
||||||
return uiZ;
|
return uiZ;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||||
Package, Release 3e, by John R. Hauser.
|
Package, Release 3e, by John R. Hauser.
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
Copyright 2011, 2012, 2013, 2014, 2015, 2018 The Regents of the University of
|
||||||
All rights reserved.
|
California. All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are met:
|
modification, are permitted provided that the following conditions are met:
|
||||||
@ -34,43 +34,35 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
=============================================================================*/
|
=============================================================================*/
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "internals.h"
|
#include "primitiveTypes.h"
|
||||||
#include "specialize.h"
|
#include "specialize.h"
|
||||||
#include "softfloat.h"
|
#include "softfloat.h"
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| 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
|
||||||
| `aWPtr' and `bWPtr' is a NaN, stores the combined NaN result at the location
|
| 'aWPtr' and 'bWPtr' is a NaN, stores the combined NaN result at the location
|
||||||
| pointed to by `zWPtr'. If either original floating-point value is a
|
| pointed to by 'zWPtr'. If either original floating-point value is a
|
||||||
| signaling NaN, the invalid exception is raised. Each of `aWPtr', `bWPtr',
|
| signaling NaN, the invalid exception is raised. Each of 'aWPtr', 'bWPtr',
|
||||||
| 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(
|
softfloat_propagateNaNF128M(
|
||||||
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr )
|
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr )
|
||||||
{
|
{
|
||||||
bool isSigNaNA;
|
|
||||||
const uint32_t *ptr;
|
|
||||||
|
|
||||||
ptr = aWPtr;
|
|
||||||
isSigNaNA = f128M_isSignalingNaN( (const float128_t *) aWPtr );
|
|
||||||
if (
|
if (
|
||||||
isSigNaNA
|
f128M_isSignalingNaN( (const float128_t *) aWPtr )
|
||||||
|| (bWPtr && f128M_isSignalingNaN( (const float128_t *) bWPtr ))
|
|| (bWPtr && f128M_isSignalingNaN( (const float128_t *) bWPtr ))
|
||||||
) {
|
) {
|
||||||
softfloat_raiseFlags( softfloat_flag_invalid );
|
softfloat_raiseFlags( softfloat_flag_invalid );
|
||||||
if ( isSigNaNA ) goto copy;
|
|
||||||
}
|
}
|
||||||
if ( ! softfloat_isNaNF128M( aWPtr ) ) ptr = bWPtr;
|
zWPtr[indexWord( 4, 3 )] = defaultNaNF128UI96;
|
||||||
copy:
|
zWPtr[indexWord( 4, 2 )] = defaultNaNF128UI64;
|
||||||
zWPtr[indexWordHi( 4 )] = ptr[indexWordHi( 4 )] | 0x00008000;
|
zWPtr[indexWord( 4, 1 )] = defaultNaNF128UI32;
|
||||||
zWPtr[indexWord( 4, 2 )] = ptr[indexWord( 4, 2 )];
|
zWPtr[indexWord( 4, 0 )] = defaultNaNF128UI0;
|
||||||
zWPtr[indexWord( 4, 1 )] = ptr[indexWord( 4, 1 )];
|
|
||||||
zWPtr[indexWord( 4, 0 )] = ptr[indexWord( 4, 0 )];
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||||
Package, Release 3e, by John R. Hauser.
|
Package, Release 3e, by John R. Hauser.
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
|
||||||
All rights reserved.
|
California. All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are met:
|
modification, are permitted provided that the following conditions are met:
|
||||||
@ -34,10 +34,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
=============================================================================*/
|
=============================================================================*/
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "internals.h"
|
#include "primitiveTypes.h"
|
||||||
#include "specialize.h"
|
#include "specialize.h"
|
||||||
#include "softfloat.h"
|
#include "softfloat.h"
|
||||||
|
|
||||||
@ -58,23 +57,16 @@ struct uint128
|
|||||||
uint_fast64_t uiB0
|
uint_fast64_t uiB0
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
bool isSigNaNA;
|
|
||||||
struct uint128 uiZ;
|
struct uint128 uiZ;
|
||||||
|
|
||||||
isSigNaNA = softfloat_isSigNaNF128UI( uiA64, uiA0 );
|
if (
|
||||||
if ( isSigNaNA || softfloat_isSigNaNF128UI( uiB64, uiB0 ) ) {
|
softfloat_isSigNaNF128UI( uiA64, uiA0 )
|
||||||
|
|| softfloat_isSigNaNF128UI( uiB64, uiB0 )
|
||||||
|
) {
|
||||||
softfloat_raiseFlags( softfloat_flag_invalid );
|
softfloat_raiseFlags( softfloat_flag_invalid );
|
||||||
if ( isSigNaNA ) goto returnNonsigA;
|
|
||||||
}
|
}
|
||||||
if ( isNaNF128UI( uiA64, uiA0 ) ) {
|
uiZ.v64 = defaultNaNF128UI64;
|
||||||
returnNonsigA:
|
uiZ.v0 = defaultNaNF128UI0;
|
||||||
uiZ.v64 = uiA64;
|
|
||||||
uiZ.v0 = uiA0;
|
|
||||||
} else {
|
|
||||||
uiZ.v64 = uiB64;
|
|
||||||
uiZ.v0 = uiB0;
|
|
||||||
}
|
|
||||||
uiZ.v64 |= UINT64_C( 0x0000800000000000 );
|
|
||||||
return uiZ;
|
return uiZ;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||||
Package, Release 3e, by John R. Hauser.
|
Package, Release 3e, by John R. Hauser.
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
|
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
|
||||||
California. All rights reserved.
|
California. All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@ -34,10 +34,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
=============================================================================*/
|
=============================================================================*/
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "internals.h"
|
|
||||||
#include "specialize.h"
|
#include "specialize.h"
|
||||||
#include "softfloat.h"
|
#include "softfloat.h"
|
||||||
|
|
||||||
@ -50,14 +48,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
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 )
|
||||||
{
|
{
|
||||||
bool isSigNaNA;
|
|
||||||
|
|
||||||
isSigNaNA = softfloat_isSigNaNF16UI( uiA );
|
if ( softfloat_isSigNaNF16UI( uiA ) || softfloat_isSigNaNF16UI( uiB ) ) {
|
||||||
if ( isSigNaNA || softfloat_isSigNaNF16UI( uiB ) ) {
|
|
||||||
softfloat_raiseFlags( softfloat_flag_invalid );
|
softfloat_raiseFlags( softfloat_flag_invalid );
|
||||||
if ( isSigNaNA ) return uiA | 0x0200;
|
|
||||||
}
|
}
|
||||||
return (isNaNF16UI( uiA ) ? uiA : uiB) | 0x0200;
|
return defaultNaNF16UI;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||||
Package, Release 3e, by John R. Hauser.
|
Package, Release 3e, by John R. Hauser.
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
|
||||||
All rights reserved.
|
California. All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are met:
|
modification, are permitted provided that the following conditions are met:
|
||||||
@ -34,10 +34,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
=============================================================================*/
|
=============================================================================*/
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "internals.h"
|
|
||||||
#include "specialize.h"
|
#include "specialize.h"
|
||||||
#include "softfloat.h"
|
#include "softfloat.h"
|
||||||
|
|
||||||
@ -50,14 +48,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
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 )
|
||||||
{
|
{
|
||||||
bool isSigNaNA;
|
|
||||||
|
|
||||||
isSigNaNA = softfloat_isSigNaNF32UI( uiA );
|
if ( softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) ) {
|
||||||
if ( isSigNaNA || softfloat_isSigNaNF32UI( uiB ) ) {
|
|
||||||
softfloat_raiseFlags( softfloat_flag_invalid );
|
softfloat_raiseFlags( softfloat_flag_invalid );
|
||||||
if ( isSigNaNA ) return uiA | 0x00400000;
|
|
||||||
}
|
}
|
||||||
return (isNaNF32UI( uiA ) ? uiA : uiB) | 0x00400000;
|
return defaultNaNF32UI;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||||
Package, Release 3e, by John R. Hauser.
|
Package, Release 3e, by John R. Hauser.
|
||||||
|
|
||||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
|
||||||
All rights reserved.
|
California. All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are met:
|
modification, are permitted provided that the following conditions are met:
|
||||||
@ -34,10 +34,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
=============================================================================*/
|
=============================================================================*/
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "internals.h"
|
|
||||||
#include "specialize.h"
|
#include "specialize.h"
|
||||||
#include "softfloat.h"
|
#include "softfloat.h"
|
||||||
|
|
||||||
@ -50,14 +48,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
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 )
|
||||||
{
|
{
|
||||||
bool isSigNaNA;
|
|
||||||
|
|
||||||
isSigNaNA = softfloat_isSigNaNF64UI( uiA );
|
if ( softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB ) ) {
|
||||||
if ( isSigNaNA || softfloat_isSigNaNF64UI( uiB ) ) {
|
|
||||||
softfloat_raiseFlags( softfloat_flag_invalid );
|
softfloat_raiseFlags( softfloat_flag_invalid );
|
||||||
if ( isSigNaNA ) return uiA | UINT64_C( 0x0008000000000000 );
|
|
||||||
}
|
}
|
||||||
return (isNaNF64UI( uiA ) ? uiA : uiB) | UINT64_C( 0x0008000000000000 );
|
return defaultNaNF64UI;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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'.
|
||||||
@ -51,19 +51,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
| The values to return on conversions to 32-bit integer formats that raise an
|
| The values to return on conversions to 32-bit integer formats that raise an
|
||||||
| invalid exception.
|
| invalid exception.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#define ui32_fromPosOverflow UINT32_C(0xFFFFFFFF)
|
#define ui32_fromPosOverflow 0xFFFFFFFF
|
||||||
#define ui32_fromNegOverflow UINT32_C(0x0)
|
#define ui32_fromNegOverflow 0
|
||||||
#define ui32_fromNaN UINT32_C(0xFFFFFFFF)
|
#define ui32_fromNaN 0xFFFFFFFF
|
||||||
#define i32_fromPosOverflow INT64_C(0x7FFFFFFF)
|
#define i32_fromPosOverflow 0x7FFFFFFF
|
||||||
#define i32_fromNegOverflow (-INT64_C(0x7FFFFFFF)-1)
|
#define i32_fromNegOverflow (-0x7FFFFFFF - 1)
|
||||||
#define i32_fromNaN INT64_C(0x7FFFFFFF)
|
#define i32_fromNaN 0x7FFFFFFF
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| The values to return on conversions to 64-bit integer formats that raise an
|
| The values to return on conversions to 64-bit integer formats that raise an
|
||||||
| invalid exception.
|
| invalid exception.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#define ui64_fromPosOverflow UINT64_C(0xFFFFFFFFFFFFFFFF)
|
#define ui64_fromPosOverflow UINT64_C(0xFFFFFFFFFFFFFFFF)
|
||||||
#define ui64_fromNegOverflow UINT64_C( 0x0 )
|
#define ui64_fromNegOverflow 0
|
||||||
#define ui64_fromNaN UINT64_C(0xFFFFFFFFFFFFFFFF)
|
#define ui64_fromNaN UINT64_C(0xFFFFFFFFFFFFFFFF)
|
||||||
#define i64_fromPosOverflow INT64_C(0x7FFFFFFFFFFFFFFF)
|
#define i64_fromPosOverflow INT64_C(0x7FFFFFFFFFFFFFFF)
|
||||||
#define i64_fromNegOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1)
|
#define i64_fromNegOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1)
|
||||||
@ -74,18 +74,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
| to another.
|
| to another.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
struct commonNaN {
|
struct commonNaN {
|
||||||
bool sign;
|
char _unused;
|
||||||
#ifdef LITTLEENDIAN
|
|
||||||
uint64_t v0, v64;
|
|
||||||
#else
|
|
||||||
uint64_t v64, v0;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| The bit pattern for a default generated 16-bit floating-point NaN.
|
| The bit pattern for a default generated 16-bit floating-point NaN.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#define defaultNaNF16UI 0xFE00
|
#define defaultNaNF16UI 0x7E00
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Returns true when 16-bit unsigned integer 'uiA' has the bit pattern of a
|
| Returns true when 16-bit unsigned integer 'uiA' has the bit pattern of a
|
||||||
@ -94,19 +89,38 @@ struct commonNaN {
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#define softfloat_isSigNaNF16UI(uiA) ((((uiA)&0x7E00) == 0x7C00) && ((uiA)&0x01FF))
|
#define softfloat_isSigNaNF16UI(uiA) ((((uiA)&0x7E00) == 0x7C00) && ((uiA)&0x01FF))
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
| Returns true when 16-bit unsigned integer 'uiA' has the bit pattern of a
|
||||||
|
| 16-bit brain floating-point (BF16) signaling NaN.
|
||||||
|
| Note: This macro evaluates its argument more than once.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
#define softfloat_isSigNaNBF16UI(uiA) ((((uiA)&0x7FC0) == 0x7F80) && ((uiA)&0x003F))
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts
|
| Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts
|
||||||
| this NaN to the common NaN form, and stores the resulting common NaN at the
|
| this NaN to the common NaN form, and stores the resulting common NaN at the
|
||||||
| 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 softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr );
|
#define softfloat_f16UIToCommonNaN(uiA, zPtr) \
|
||||||
|
if(!((uiA)&0x0200)) \
|
||||||
|
softfloat_raiseFlags(softfloat_flag_invalid)
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
| Assuming 'uiA' has the bit pattern of a 16-bit BF16 floating-point NaN, converts
|
||||||
|
| this NaN to the common NaN form, and stores the resulting common NaN at the
|
||||||
|
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||||
|
| exception is raised.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
#define softfloat_bf16UIToCommonNaN(uiA, zPtr) \
|
||||||
|
if(!((uiA)&0x0040)) \
|
||||||
|
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
|
||||||
| NaN, and returns the bit pattern of this value as an unsigned integer.
|
| NaN, and returns the bit pattern of this value as an unsigned integer.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr );
|
#define softfloat_commonNaNToF16UI(aPtr) ((uint_fast16_t)defaultNaNF16UI)
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating-
|
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating-
|
||||||
@ -114,8 +128,18 @@ 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 16-bit BF16 floating-point NaN.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
#define defaultNaNBF16UI 0x7FC0
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
| Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point
|
||||||
|
| NaN, and returns the bit pattern of this value as an unsigned integer.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
#define softfloat_commonNaNToBF16UI(aPtr) ((uint_fast16_t)defaultNaNBF16UI)
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| The bit pattern for a default generated 32-bit floating-point NaN.
|
| The bit pattern for a default generated 32-bit floating-point NaN.
|
||||||
@ -135,13 +159,15 @@ 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.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr );
|
#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
|
||||||
| NaN, and returns the bit pattern of this value as an unsigned integer.
|
| NaN, and returns the bit pattern of this value as an unsigned integer.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr );
|
#define softfloat_commonNaNToF32UI(aPtr) ((uint_fast32_t)defaultNaNF32UI)
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating-
|
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating-
|
||||||
@ -149,8 +175,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 +187,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
|
||||||
@ -170,13 +196,15 @@ 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.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr );
|
#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
|
||||||
| NaN, and returns the bit pattern of this value as an unsigned integer.
|
| NaN, and returns the bit pattern of this value as an unsigned integer.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr );
|
#define softfloat_commonNaNToF64UI(aPtr) ((uint_fast64_t)defaultNaNF64UI)
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating-
|
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating-
|
||||||
@ -184,13 +212,12 @@ 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.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#define defaultNaNExtF80UI64 0xFFFF
|
#define defaultNaNExtF80UI64 0x7FFF
|
||||||
#define defaultNaNExtF80UI0 UINT64_C(0xC000000000000000)
|
#define defaultNaNExtF80UI0 UINT64_C(0xC000000000000000)
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
@ -199,7 +226,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,16 +243,26 @@ 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
|
#define softfloat_extF80UIToCommonNaN(uiA64, uiA0, zPtr) \
|
||||||
softfloat_extF80UIToCommonNaN(
|
if(!((uiA0)&UINT64_C(0x4000000000000000))) \
|
||||||
uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
|
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
|
||||||
| floating-point NaN, and returns the bit pattern of this value as an unsigned
|
| floating-point NaN, and returns the bit pattern of this value as an unsigned
|
||||||
| integer.
|
| integer.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
|
#if defined INLINE && !defined softfloat_commonNaNToExtF80UI
|
||||||
|
INLINE
|
||||||
|
struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr) {
|
||||||
|
struct uint128 uiZ;
|
||||||
|
uiZ.v64 = defaultNaNExtF80UI64;
|
||||||
|
uiZ.v0 = defaultNaNExtF80UI0;
|
||||||
|
return uiZ;
|
||||||
|
}
|
||||||
|
#else
|
||||||
struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr);
|
struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Interpreting the unsigned integer formed from concatenating 'uiA64' and
|
| Interpreting the unsigned integer formed from concatenating 'uiA64' and
|
||||||
@ -235,18 +273,12 @@ 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.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#define defaultNaNF128UI64 UINT64_C( 0xFFFF800000000000 )
|
#define defaultNaNF128UI64 UINT64_C(0x7FFF800000000000)
|
||||||
#define defaultNaNF128UI0 UINT64_C(0)
|
#define defaultNaNF128UI0 UINT64_C(0)
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
@ -255,7 +287,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,15 +297,25 @@ 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
|
#define softfloat_f128UIToCommonNaN(uiA64, uiA0, zPtr) \
|
||||||
softfloat_f128UIToCommonNaN(
|
if(!((uiA64)&UINT64_C(0x0000800000000000))) \
|
||||||
uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
|
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
|
||||||
| NaN, and returns the bit pattern of this value as an unsigned integer.
|
| NaN, and returns the bit pattern of this value as an unsigned integer.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
|
#if defined INLINE && !defined softfloat_commonNaNToF128UI
|
||||||
|
INLINE
|
||||||
|
struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN* aPtr) {
|
||||||
|
struct uint128 uiZ;
|
||||||
|
uiZ.v64 = defaultNaNF128UI64;
|
||||||
|
uiZ.v0 = defaultNaNF128UI0;
|
||||||
|
return uiZ;
|
||||||
|
}
|
||||||
|
#else
|
||||||
struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN*);
|
struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN*);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Interpreting the unsigned integer formed from concatenating 'uiA64' and
|
| Interpreting the unsigned integer formed from concatenating 'uiA64' and
|
||||||
@ -283,13 +326,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 +341,24 @@ 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
|
#define softfloat_extF80MToCommonNaN(aSPtr, zPtr) \
|
||||||
softfloat_extF80MToCommonNaN(
|
if(!((aSPtr)->signif & UINT64_C(0x4000000000000000))) \
|
||||||
const struct extFloat80M *aSPtr, struct commonNaN *zPtr );
|
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
|
||||||
| 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
|
#if defined INLINE && !defined softfloat_commonNaNToExtF80M
|
||||||
softfloat_commonNaNToExtF80M(
|
INLINE
|
||||||
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
|
void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr) {
|
||||||
|
zSPtr->signExp = defaultNaNExtF80UI64;
|
||||||
|
zSPtr->signif = defaultNaNExtF80UI0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| 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,17 +366,12 @@ 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.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#define defaultNaNF128UI96 0xFFFF8000
|
#define defaultNaNF128UI96 0x7FFF8000
|
||||||
#define defaultNaNF128UI64 0
|
#define defaultNaNF128UI64 0
|
||||||
#define defaultNaNF128UI32 0
|
#define defaultNaNF128UI32 0
|
||||||
#define defaultNaNF128UI0 0
|
#define defaultNaNF128UI0 0
|
||||||
@ -346,8 +384,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.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
#define softfloat_f128MToCommonNaN(aWPtr, zPtr) \
|
||||||
softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *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
|
||||||
@ -355,8 +394,17 @@ 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
|
#if defined INLINE && !defined softfloat_commonNaNToF128M
|
||||||
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
|
INLINE
|
||||||
|
void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr) {
|
||||||
|
zWPtr[indexWord(4, 3)] = defaultNaNF128UI96;
|
||||||
|
zWPtr[indexWord(4, 2)] = defaultNaNF128UI64;
|
||||||
|
zWPtr[indexWord(4, 1)] = defaultNaNF128UI32;
|
||||||
|
zWPtr[indexWord(4, 0)] = defaultNaNF128UI0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| 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 +414,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
|
||||||
|
|
||||||
|
51
softfloat/source/bf16_isSignalingNaN.c
Normal file
51
softfloat/source/bf16_isSignalingNaN.c
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
|
||||||
|
/*============================================================================
|
||||||
|
|
||||||
|
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||||
|
Package, Release 3e, by John R. Hauser.
|
||||||
|
|
||||||
|
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
|
||||||
|
California. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions, and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions, and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the University nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "platform.h"
|
||||||
|
#include "internals.h"
|
||||||
|
#include "specialize.h"
|
||||||
|
#include "softfloat.h"
|
||||||
|
|
||||||
|
bool bf16_isSignalingNaN( bfloat16_t a )
|
||||||
|
{
|
||||||
|
union ui16_bf16 uA;
|
||||||
|
|
||||||
|
uA.f = a;
|
||||||
|
return softfloat_isSigNaNBF16UI( uA.ui );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
90
softfloat/source/bf16_to_f32.c
Normal file
90
softfloat/source/bf16_to_f32.c
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
|
||||||
|
/*============================================================================
|
||||||
|
|
||||||
|
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||||
|
Package, Release 3e, by John R. Hauser.
|
||||||
|
|
||||||
|
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
|
||||||
|
California. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions, and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions, and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the University nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "platform.h"
|
||||||
|
#include "internals.h"
|
||||||
|
#include "specialize.h"
|
||||||
|
#include "softfloat.h"
|
||||||
|
|
||||||
|
float32_t bf16_to_f32( bfloat16_t a )
|
||||||
|
{
|
||||||
|
union ui16_bf16 uA;
|
||||||
|
uint_fast16_t uiA;
|
||||||
|
bool sign;
|
||||||
|
int_fast16_t exp;
|
||||||
|
uint_fast16_t frac;
|
||||||
|
struct commonNaN commonNaN;
|
||||||
|
uint_fast32_t uiZ;
|
||||||
|
struct exp8_sig16 normExpSig;
|
||||||
|
union ui32_f32 uZ;
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
*------------------------------------------------------------------------*/
|
||||||
|
uA.f = a;
|
||||||
|
uiA = uA.ui;
|
||||||
|
sign = signBF16UI( uiA );
|
||||||
|
exp = expBF16UI( uiA );
|
||||||
|
frac = fracBF16UI( uiA );
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
*------------------------------------------------------------------------*/
|
||||||
|
// NaN or Inf
|
||||||
|
if ( exp == 0xFF ) {
|
||||||
|
if ( frac ) {
|
||||||
|
softfloat_bf16UIToCommonNaN( uiA, &commonNaN );
|
||||||
|
uiZ = softfloat_commonNaNToF32UI( &commonNaN );
|
||||||
|
} else {
|
||||||
|
uiZ = packToF32UI( sign, 0xFF, 0 );
|
||||||
|
}
|
||||||
|
goto uiZ;
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
*------------------------------------------------------------------------*/
|
||||||
|
// packToF32UI simply packs bitfields without any numerical change
|
||||||
|
// which means it can be used directly for any BF16 to f32 conversions which
|
||||||
|
// does not require bits manipulation
|
||||||
|
// (that is everything where the 16-bit are just padded right with 16 zeros, including
|
||||||
|
// subnormal numbers)
|
||||||
|
uiZ = packToF32UI( sign, exp, ((uint_fast32_t) frac) <<16 );
|
||||||
|
uiZ:
|
||||||
|
uZ.ui = uiZ;
|
||||||
|
return uZ.f;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
105
softfloat/source/f32_to_bf16.c
Normal file
105
softfloat/source/f32_to_bf16.c
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
|
||||||
|
/*============================================================================
|
||||||
|
|
||||||
|
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||||
|
Package, Release 3e, by John R. Hauser.
|
||||||
|
|
||||||
|
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
|
||||||
|
California. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions, and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions, and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the University nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "platform.h"
|
||||||
|
#include "internals.h"
|
||||||
|
#include "specialize.h"
|
||||||
|
#include "softfloat.h"
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
bfloat16_t f32_to_bf16( float32_t a )
|
||||||
|
{
|
||||||
|
union ui32_f32 uA;
|
||||||
|
uint_fast32_t uiA;
|
||||||
|
bool sign;
|
||||||
|
int_fast16_t exp;
|
||||||
|
uint_fast32_t frac;
|
||||||
|
struct commonNaN commonNaN;
|
||||||
|
uint_fast16_t uiZ, frac16;
|
||||||
|
union ui16_bf16 uZ;
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
*------------------------------------------------------------------------*/
|
||||||
|
uA.f = a;
|
||||||
|
uiA = uA.ui;
|
||||||
|
sign = signF32UI( uiA );
|
||||||
|
exp = expF32UI( uiA );
|
||||||
|
frac = fracF32UI( uiA );
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
*------------------------------------------------------------------------*/
|
||||||
|
// infinity or NaN cases
|
||||||
|
if ( exp == 0xFF ) {
|
||||||
|
if ( frac ) {
|
||||||
|
// NaN case
|
||||||
|
softfloat_f32UIToCommonNaN( uiA, &commonNaN );
|
||||||
|
uiZ = softfloat_commonNaNToBF16UI( &commonNaN );
|
||||||
|
} else {
|
||||||
|
// infinity case
|
||||||
|
uiZ = packToBF16UI( sign, 0xFF, 0 );
|
||||||
|
}
|
||||||
|
goto uiZ;
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
*------------------------------------------------------------------------*/
|
||||||
|
// frac is a 24-bit mantissa, right shifted by 9
|
||||||
|
// In the normal case, (24-9) = 15 are set
|
||||||
|
frac16 = frac>>9 | ((frac & 0x1FF) != 0);
|
||||||
|
if ( ! (exp | frac16) ) {
|
||||||
|
uiZ = packToBF16UI( sign, 0, 0 );
|
||||||
|
goto uiZ;
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
*------------------------------------------------------------------------*/
|
||||||
|
// softfloat_roundPackToBF16 exponent argument (2nd argument)
|
||||||
|
// must correspond to the exponent of fracIn[13] bits
|
||||||
|
// (fracIn is the 3rd and last argument)
|
||||||
|
uint_fast32_t mask = exp ? 0x4000 : 0x0; // implicit one mask added if input is a normal number
|
||||||
|
// exponent for the lowest normal and largest subnormal should be equal
|
||||||
|
// but is not in IEEE encoding so mantissa must be partially normalized
|
||||||
|
// (by one bit) for subnormal numbers. Such that (exp - 1) corresponds
|
||||||
|
// to the exponent of frac16[13]
|
||||||
|
frac16 = frac16 << (exp ? 0 : 1);
|
||||||
|
return softfloat_roundPackToBF16( sign, exp - 1, frac16 | mask );
|
||||||
|
uiZ:
|
||||||
|
uZ.ui = uiZ;
|
||||||
|
return uZ.f;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -72,6 +72,9 @@ float16_t f32_to_f16( float32_t a )
|
|||||||
}
|
}
|
||||||
/*------------------------------------------------------------------------
|
/*------------------------------------------------------------------------
|
||||||
*------------------------------------------------------------------------*/
|
*------------------------------------------------------------------------*/
|
||||||
|
// frac is a 24-bit significand, the bottom 9 bits LSB are extracted and OR-red
|
||||||
|
// into a sticky flag, the top 15 MSBs are extracted, the LSB of this top slice
|
||||||
|
// is OR-red with the sticky
|
||||||
frac16 = frac>>9 | ((frac & 0x1FF) != 0);
|
frac16 = frac>>9 | ((frac & 0x1FF) != 0);
|
||||||
if ( ! (exp | frac16) ) {
|
if ( ! (exp | frac16) ) {
|
||||||
uiZ = packToF16UI( sign, 0, 0 );
|
uiZ = packToF16UI( sign, 0, 0 );
|
||||||
|
@ -37,33 +37,47 @@ 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 ui16_bf16 {
|
||||||
|
uint16_t ui;
|
||||||
|
bfloat16_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 +85,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 +99,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 +110,19 @@ 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 );
|
/*----------------------------------------------------------------------------
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
#define signBF16UI(a) ((bool)((uint16_t)(a) >> 15))
|
||||||
|
#define expBF16UI(a) ((int_fast16_t)((a) >> 7) & 0xFF)
|
||||||
|
#define fracBF16UI(a) ((a)&0x07F)
|
||||||
|
#define packToBF16UI(sign, exp, sig) (((uint16_t)(sign) << 15) + ((uint16_t)(exp) << 7) + (sig))
|
||||||
|
|
||||||
|
#define isNaNBF16UI(a) (((~(a)&0x7FC0) == 0) && ((a)&0x07F))
|
||||||
|
|
||||||
|
bfloat16_t softfloat_roundPackToBF16(bool, int_fast16_t, uint_fast16_t);
|
||||||
|
struct exp8_sig16 softfloat_normSubnormalBF16Sig(uint_fast16_t);
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
@ -108,7 +133,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 +144,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 +155,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 +166,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 +181,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 +202,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 +241,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 +249,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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
@ -81,13 +76,13 @@ enum {
|
|||||||
| Software floating-point exception flags.
|
| Software floating-point exception flags.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
extern THREAD_LOCAL uint_fast8_t softfloat_exceptionFlags;
|
extern THREAD_LOCAL uint_fast8_t softfloat_exceptionFlags;
|
||||||
enum {
|
typedef enum {
|
||||||
softfloat_flag_inexact = 1,
|
softfloat_flag_inexact = 1,
|
||||||
softfloat_flag_underflow = 2,
|
softfloat_flag_underflow = 2,
|
||||||
softfloat_flag_overflow = 4,
|
softfloat_flag_overflow = 4,
|
||||||
softfloat_flag_infinite = 8,
|
softfloat_flag_infinite = 8,
|
||||||
softfloat_flag_invalid = 16
|
softfloat_flag_invalid = 16
|
||||||
};
|
} exceptionFlag_t;
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Routine to raise any or all of the software floating-point exception flags.
|
| Routine to raise any or all of the software floating-point exception flags.
|
||||||
@ -169,6 +164,13 @@ bool f16_le_quiet( float16_t, float16_t );
|
|||||||
bool f16_lt_quiet(float16_t, float16_t);
|
bool f16_lt_quiet(float16_t, float16_t);
|
||||||
bool f16_isSignalingNaN(float16_t);
|
bool f16_isSignalingNaN(float16_t);
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
| 16-bit (brain float 16) floating-point operations.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
float32_t bf16_to_f32(bfloat16_t);
|
||||||
|
bfloat16_t f32_to_bf16(float32_t);
|
||||||
|
bool bf16_isSignalingNaN(bfloat16_t);
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| 32-bit (single-precision) floating-point operations.
|
| 32-bit (single-precision) floating-point operations.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
@ -288,9 +290,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 +353,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 +366,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
|
||||||
|
|
||||||
|
@ -47,10 +47,21 @@ 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 {
|
||||||
|
uint16_t v;
|
||||||
|
} bfloat16_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 +69,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 +95,3 @@ struct extFloat80M { uint16_t signExp; uint64_t signif; };
|
|||||||
typedef struct extFloat80M extFloat80_t;
|
typedef struct extFloat80M extFloat80_t;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -221,4 +221,3 @@ float32_t
|
|||||||
return uZ.f;
|
return uZ.f;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
52
softfloat/source/s_normSubnormalBF16Sig.c
Normal file
52
softfloat/source/s_normSubnormalBF16Sig.c
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
|
||||||
|
/*============================================================================
|
||||||
|
|
||||||
|
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||||
|
Package, Release 3e, by John R. Hauser.
|
||||||
|
|
||||||
|
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
|
||||||
|
California. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions, and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions, and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the University nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "platform.h"
|
||||||
|
#include "internals.h"
|
||||||
|
|
||||||
|
struct exp8_sig16 softfloat_normSubnormalBF16Sig( uint_fast16_t sig )
|
||||||
|
{
|
||||||
|
int_fast8_t shiftDist;
|
||||||
|
struct exp8_sig16 z;
|
||||||
|
|
||||||
|
shiftDist = softfloat_countLeadingZeros16( sig ) - 8;
|
||||||
|
z.exp = 1 - shiftDist;
|
||||||
|
z.sig = sig<<shiftDist;
|
||||||
|
return z;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
114
softfloat/source/s_roundPackToBF16.c
Normal file
114
softfloat/source/s_roundPackToBF16.c
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
|
||||||
|
/*============================================================================
|
||||||
|
|
||||||
|
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||||
|
Package, Release 3e, by John R. Hauser.
|
||||||
|
|
||||||
|
Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
|
||||||
|
California. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions, and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions, and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the University nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "platform.h"
|
||||||
|
#include "internals.h"
|
||||||
|
#include "softfloat.h"
|
||||||
|
|
||||||
|
/** sig last significant bit is sig[7], the 7 LSBs will be used for rounding */
|
||||||
|
bfloat16_t
|
||||||
|
softfloat_roundPackToBF16( bool sign, int_fast16_t exp, uint_fast16_t sig )
|
||||||
|
{
|
||||||
|
uint_fast8_t roundingMode;
|
||||||
|
bool roundNearEven;
|
||||||
|
uint_fast8_t roundIncrement, roundBits;
|
||||||
|
bool isTiny;
|
||||||
|
uint_fast16_t uiZ;
|
||||||
|
union ui16_bf16 uZ;
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
*------------------------------------------------------------------------*/
|
||||||
|
roundingMode = softfloat_roundingMode;
|
||||||
|
roundNearEven = (roundingMode == softfloat_round_near_even);
|
||||||
|
roundIncrement = 0x40;
|
||||||
|
if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
|
||||||
|
roundIncrement =
|
||||||
|
(roundingMode
|
||||||
|
== (sign ? softfloat_round_min : softfloat_round_max))
|
||||||
|
? 0x7F
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
roundBits = sig & 0x7F;
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
*------------------------------------------------------------------------*/
|
||||||
|
if ( 0xFD <= (unsigned int) exp ) {
|
||||||
|
if ( exp < 0 ) {
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
*----------------------------------------------------------------*/
|
||||||
|
isTiny =
|
||||||
|
(softfloat_detectTininess == softfloat_tininess_beforeRounding)
|
||||||
|
|| (exp < -1) || (sig + roundIncrement < 0x8000);
|
||||||
|
sig = softfloat_shiftRightJam32( sig, -exp );
|
||||||
|
exp = 0;
|
||||||
|
roundBits = sig & 0x7F;
|
||||||
|
if ( isTiny && roundBits ) {
|
||||||
|
softfloat_raiseFlags( softfloat_flag_underflow );
|
||||||
|
}
|
||||||
|
} else if ( (0xFD < exp) || (0x8000 <= sig + roundIncrement) ) {
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
*----------------------------------------------------------------*/
|
||||||
|
softfloat_raiseFlags(
|
||||||
|
softfloat_flag_overflow | softfloat_flag_inexact );
|
||||||
|
uiZ = packToBF16UI( sign, 0xFF, 0 ) - ! roundIncrement;
|
||||||
|
goto uiZ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
*------------------------------------------------------------------------*/
|
||||||
|
sig = (sig + roundIncrement)>>7;
|
||||||
|
if ( roundBits ) {
|
||||||
|
softfloat_exceptionFlags |= softfloat_flag_inexact;
|
||||||
|
#ifdef SOFTFLOAT_ROUND_ODD
|
||||||
|
if ( roundingMode == softfloat_round_odd ) {
|
||||||
|
sig |= 1;
|
||||||
|
goto packReturn;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
sig &= ~(uint_fast16_t) (! (roundBits ^ 0x40) & roundNearEven);
|
||||||
|
if ( ! sig ) exp = 0;
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
*------------------------------------------------------------------------*/
|
||||||
|
packReturn:
|
||||||
|
uiZ = packToBF16UI( sign, exp, sig );
|
||||||
|
uiZ:
|
||||||
|
uZ.ui = uiZ;
|
||||||
|
return uZ.f;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
69
src/elfio.cpp
Normal file
69
src/elfio.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (C) 2024 MINRES Technologies GmbH
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* eyck@minres.com - initial implementation
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define _SCL_SECURE_NO_WARNINGS
|
||||||
|
#define ELFIO_NO_INTTYPES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <elfio/elfio_dump.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace ELFIO;
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
if(argc != 2) {
|
||||||
|
printf("Usage: elfdump <file_name>\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
elfio reader;
|
||||||
|
|
||||||
|
if(!reader.load(argv[1])) {
|
||||||
|
printf("File %s is not found or it is not an ELF file\n", argv[1]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dump::header(std::cout, reader);
|
||||||
|
dump::section_headers(std::cout, reader);
|
||||||
|
dump::segment_headers(std::cout, reader);
|
||||||
|
dump::symbol_tables(std::cout, reader);
|
||||||
|
dump::notes(std::cout, reader);
|
||||||
|
dump::modinfo(std::cout, reader);
|
||||||
|
dump::dynamic_tags(std::cout, reader);
|
||||||
|
dump::section_datas(std::cout, reader);
|
||||||
|
dump::segment_datas(std::cout, reader);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -35,6 +35,7 @@
|
|||||||
#ifndef _RISCV_HART_M_P_HWL_H
|
#ifndef _RISCV_HART_M_P_HWL_H
|
||||||
#define _RISCV_HART_M_P_HWL_H
|
#define _RISCV_HART_M_P_HWL_H
|
||||||
|
|
||||||
|
#include "riscv_hart_common.h"
|
||||||
#include <iss/vm_types.h>
|
#include <iss/vm_types.h>
|
||||||
|
|
||||||
namespace iss {
|
namespace iss {
|
||||||
@ -50,13 +51,13 @@ public:
|
|||||||
virtual ~hwl() = default;
|
virtual ~hwl() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
iss::status read_custom_csr_reg(unsigned addr, reg_t &val) override;
|
iss::status read_custom_csr(unsigned addr, reg_t& val) override;
|
||||||
iss::status write_custom_csr_reg(unsigned addr, reg_t val) override;
|
iss::status write_custom_csr(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 +68,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(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(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 +119,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 */
|
||||||
|
233
src/iss/arch/mstatus.h
Normal file
233
src/iss/arch/mstatus.h
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (C) 2025 MINRES Technologies GmbH
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* eyck@minres.com - initial implementation
|
||||||
|
******************************************************************************/
|
||||||
|
#ifndef _MSTATUS_TYPE
|
||||||
|
#define _MSTATUS_TYPE
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <util/bit_field.h>
|
||||||
|
#include <util/ities.h>
|
||||||
|
|
||||||
|
namespace iss {
|
||||||
|
namespace arch {
|
||||||
|
|
||||||
|
template <class T, class Enable = void> struct status {};
|
||||||
|
// specialization 32bit
|
||||||
|
template <typename T> struct status<T, typename std::enable_if<std::is_same<T, uint32_t>::value>::type> {
|
||||||
|
static inline unsigned SD(T v) { return bit_sub<63, 1>(v); }
|
||||||
|
// value of XLEN for S-mode
|
||||||
|
static inline unsigned SXL(T v) { return bit_sub<34, 2>(v); };
|
||||||
|
// value of XLEN for U-mode
|
||||||
|
static inline unsigned UXL(T v) { return bit_sub<32, 2>(v); };
|
||||||
|
// Trap SRET
|
||||||
|
static inline unsigned TSR(T v) { return bit_sub<22, 1>(v); };
|
||||||
|
// Timeout Wait
|
||||||
|
static inline unsigned TW(T v) { return bit_sub<21, 1>(v); };
|
||||||
|
// Trap Virtual Memory
|
||||||
|
static inline unsigned TVM(T v) { return bit_sub<20, 1>(v); };
|
||||||
|
// Make eXecutable Readable
|
||||||
|
static inline unsigned MXR(T v) { return bit_sub<19, 1>(v); };
|
||||||
|
// permit Supervisor User Memory access
|
||||||
|
static inline unsigned SUM(T v) { return bit_sub<18, 1>(v); };
|
||||||
|
// Modify PRiVilege
|
||||||
|
static inline unsigned MPRV(T v) { return bit_sub<17, 1>(v); };
|
||||||
|
// status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None
|
||||||
|
// dirty, some clean/Some dirty
|
||||||
|
static inline unsigned XS(T v) { return bit_sub<15, 2>(v); };
|
||||||
|
// floating-point unit status Off/Initial/Clean/Dirty
|
||||||
|
static inline unsigned FS(T v) { return bit_sub<13, 2>(v); };
|
||||||
|
// machine previous privilege
|
||||||
|
static inline unsigned MPP(T v) { return bit_sub<11, 2>(v); };
|
||||||
|
// supervisor previous privilege
|
||||||
|
static inline unsigned SPP(T v) { return bit_sub<8, 1>(v); };
|
||||||
|
// previous machine interrupt-enable
|
||||||
|
static inline unsigned MPIE(T v) { return bit_sub<7, 1>(v); };
|
||||||
|
// previous supervisor interrupt-enable
|
||||||
|
static inline unsigned SPIE(T v) { return bit_sub<5, 1>(v); };
|
||||||
|
// previous user interrupt-enable
|
||||||
|
static inline unsigned UPIE(T v) { return bit_sub<4, 1>(v); };
|
||||||
|
// machine interrupt-enable
|
||||||
|
static inline unsigned MIE(T v) { return bit_sub<3, 1>(v); };
|
||||||
|
// supervisor interrupt-enable
|
||||||
|
static inline unsigned SIE(T v) { return bit_sub<1, 1>(v); };
|
||||||
|
// user interrupt-enable
|
||||||
|
static inline unsigned UIE(T v) { return bit_sub<0, 1>(v); };
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T> struct status<T, typename std::enable_if<std::is_same<T, uint64_t>::value>::type> {
|
||||||
|
public:
|
||||||
|
// 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)))
|
||||||
|
static inline unsigned SD(T v) { return bit_sub<63, 1>(v); };
|
||||||
|
// value of XLEN for S-mode
|
||||||
|
static inline unsigned SXL(T v) { return bit_sub<34, 2>(v); };
|
||||||
|
// value of XLEN for U-mode
|
||||||
|
static inline unsigned UXL(T v) { return bit_sub<32, 2>(v); };
|
||||||
|
// Trap SRET
|
||||||
|
static inline unsigned TSR(T v) { return bit_sub<22, 1>(v); };
|
||||||
|
// Timeout Wait
|
||||||
|
static inline unsigned TW(T v) { return bit_sub<21, 1>(v); };
|
||||||
|
// Trap Virtual Memory
|
||||||
|
static inline unsigned TVM(T v) { return bit_sub<20, 1>(v); };
|
||||||
|
// Make eXecutable Readable
|
||||||
|
static inline unsigned MXR(T v) { return bit_sub<19, 1>(v); };
|
||||||
|
// permit Supervisor User Memory access
|
||||||
|
static inline unsigned SUM(T v) { return bit_sub<18, 1>(v); };
|
||||||
|
// Modify PRiVilege
|
||||||
|
static inline unsigned MPRV(T v) { return bit_sub<17, 1>(v); };
|
||||||
|
// status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None
|
||||||
|
// dirty, some clean/Some dirty
|
||||||
|
static inline unsigned XS(T v) { return bit_sub<15, 2>(v); };
|
||||||
|
// floating-point unit status Off/Initial/Clean/Dirty
|
||||||
|
static inline unsigned FS(T v) { return bit_sub<13, 2>(v); };
|
||||||
|
// machine previous privilege
|
||||||
|
static inline unsigned MPP(T v) { return bit_sub<11, 2>(v); };
|
||||||
|
// supervisor previous privilege
|
||||||
|
static inline unsigned SPP(T v) { return bit_sub<8, 1>(v); };
|
||||||
|
// previous machine interrupt-enable
|
||||||
|
static inline unsigned MPIE(T v) { return bit_sub<7, 1>(v); };
|
||||||
|
// previous supervisor interrupt-enable
|
||||||
|
static inline unsigned SPIE(T v) { return bit_sub<5, 1>(v); };
|
||||||
|
// previous user interrupt-enable
|
||||||
|
static inline unsigned UPIE(T v) { return bit_sub<4, 1>(v); };
|
||||||
|
// machine interrupt-enable
|
||||||
|
static inline unsigned MIE(T v) { return bit_sub<3, 1>(v); };
|
||||||
|
// supervisor interrupt-enable
|
||||||
|
static inline unsigned SIE(T v) { return bit_sub<1, 1>(v); };
|
||||||
|
// user interrupt-enable
|
||||||
|
static inline unsigned UIE(T v) { return bit_sub<0, 1>(v); };
|
||||||
|
};
|
||||||
|
|
||||||
|
// primary template
|
||||||
|
template <class T, class Enable = void> struct hart_state {};
|
||||||
|
// specialization 32bit
|
||||||
|
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint32_t>::value>::type> {
|
||||||
|
public:
|
||||||
|
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)))
|
||||||
|
BF_FIELD(SD, 31, 1);
|
||||||
|
// Trap SRET
|
||||||
|
BF_FIELD(TSR, 22, 1);
|
||||||
|
// Timeout Wait
|
||||||
|
BF_FIELD(TW, 21, 1);
|
||||||
|
// Trap Virtual Memory
|
||||||
|
BF_FIELD(TVM, 20, 1);
|
||||||
|
// Make eXecutable Readable
|
||||||
|
BF_FIELD(MXR, 19, 1);
|
||||||
|
// permit Supervisor User Memory access
|
||||||
|
BF_FIELD(SUM, 18, 1);
|
||||||
|
// Modify PRiVilege
|
||||||
|
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
|
||||||
|
BF_FIELD(XS, 15, 2);
|
||||||
|
// floating-point unit status Off/Initial/Clean/Dirty
|
||||||
|
BF_FIELD(FS, 13, 2);
|
||||||
|
// machine previous privilege
|
||||||
|
BF_FIELD(MPP, 11, 2);
|
||||||
|
// supervisor previous privilege
|
||||||
|
BF_FIELD(SPP, 8, 1);
|
||||||
|
// previous machine interrupt-enable
|
||||||
|
BF_FIELD(MPIE, 7, 1);
|
||||||
|
// previous supervisor interrupt-enable
|
||||||
|
BF_FIELD(SPIE, 5, 1);
|
||||||
|
// previous user interrupt-enable
|
||||||
|
BF_FIELD(UPIE, 4, 1);
|
||||||
|
// machine interrupt-enable
|
||||||
|
BF_FIELD(MIE, 3, 1);
|
||||||
|
// supervisor interrupt-enable
|
||||||
|
BF_FIELD(SIE, 1, 1);
|
||||||
|
// user interrupt-enable
|
||||||
|
BF_FIELD(UIE, 0, 1);
|
||||||
|
END_BF_DECL();
|
||||||
|
|
||||||
|
mstatus_t mstatus;
|
||||||
|
|
||||||
|
static const T mstatus_reset_val = 0x1800;
|
||||||
|
};
|
||||||
|
|
||||||
|
// specialization 64bit
|
||||||
|
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint64_t>::value>::type> {
|
||||||
|
public:
|
||||||
|
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)))
|
||||||
|
BF_FIELD(SD, 63, 1);
|
||||||
|
// value of XLEN for S-mode
|
||||||
|
BF_FIELD(SXL, 34, 2);
|
||||||
|
// value of XLEN for U-mode
|
||||||
|
BF_FIELD(UXL, 32, 2);
|
||||||
|
// Trap SRET
|
||||||
|
BF_FIELD(TSR, 22, 1);
|
||||||
|
// Timeout Wait
|
||||||
|
BF_FIELD(TW, 21, 1);
|
||||||
|
// Trap Virtual Memory
|
||||||
|
BF_FIELD(TVM, 20, 1);
|
||||||
|
// Make eXecutable Readable
|
||||||
|
BF_FIELD(MXR, 19, 1);
|
||||||
|
// permit Supervisor User Memory access
|
||||||
|
BF_FIELD(SUM, 18, 1);
|
||||||
|
// Modify PRiVilege
|
||||||
|
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
|
||||||
|
BF_FIELD(XS, 15, 2);
|
||||||
|
// floating-point unit status Off/Initial/Clean/Dirty
|
||||||
|
BF_FIELD(FS, 13, 2);
|
||||||
|
// machine previous privilege
|
||||||
|
BF_FIELD(MPP, 11, 2);
|
||||||
|
// supervisor previous privilege
|
||||||
|
BF_FIELD(SPP, 8, 1);
|
||||||
|
// previous machine interrupt-enable
|
||||||
|
BF_FIELD(MPIE, 7, 1);
|
||||||
|
// previous supervisor interrupt-enable
|
||||||
|
BF_FIELD(SPIE, 5, 1);
|
||||||
|
// previous user interrupt-enable
|
||||||
|
BF_FIELD(UPIE, 4, 1);
|
||||||
|
// machine interrupt-enable
|
||||||
|
BF_FIELD(MIE, 3, 1);
|
||||||
|
// supervisor interrupt-enable
|
||||||
|
BF_FIELD(SIE, 1, 1);
|
||||||
|
// user interrupt-enable
|
||||||
|
BF_FIELD(UIE, 0, 1);
|
||||||
|
END_BF_DECL();
|
||||||
|
|
||||||
|
mstatus_t mstatus;
|
||||||
|
|
||||||
|
static const T mstatus_reset_val = 0x1800;
|
||||||
|
};
|
||||||
|
} // namespace arch
|
||||||
|
} // namespace iss
|
||||||
|
#endif // _MSTATUS_TYPE
|
@ -1,5 +1,5 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (C) 2017, 2018, 2021 MINRES Technologies GmbH
|
* Copyright (C) 2017 - 2025 MINRES Technologies GmbH
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -35,15 +35,38 @@
|
|||||||
#ifndef _RISCV_HART_COMMON
|
#ifndef _RISCV_HART_COMMON
|
||||||
#define _RISCV_HART_COMMON
|
#define _RISCV_HART_COMMON
|
||||||
|
|
||||||
#include "iss/arch_if.h"
|
#include "mstatus.h"
|
||||||
|
#include "util/delegate.h"
|
||||||
|
#include <absl/container/flat_hash_map.h>
|
||||||
|
#include <array>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <elfio/elfio.hpp>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#include <iss/arch/traits.h>
|
||||||
|
#include <iss/arch_if.h>
|
||||||
|
#include <iss/log_categories.h>
|
||||||
|
#include <iss/mem/memory_if.h>
|
||||||
|
#include <iss/semihosting/semihosting.h>
|
||||||
|
#include <iss/vm_types.h>
|
||||||
|
#include <limits>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <util/logging.h>
|
||||||
|
#include <util/sparse_array.h>
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#define likely(x) ::__builtin_expect(!!(x), 1)
|
||||||
|
#define unlikely(x) ::__builtin_expect(!!(x), 0)
|
||||||
|
#else
|
||||||
|
#define likely(x) x
|
||||||
|
#define unlikely(x) x
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace iss {
|
namespace iss {
|
||||||
namespace arch {
|
namespace arch {
|
||||||
|
|
||||||
enum { tohost_dflt = 0xF0001000, fromhost_dflt = 0xF0001040 };
|
enum features_e { FEAT_NONE, FEAT_EXT_N = 1, FEAT_DEBUG = 2 };
|
||||||
|
|
||||||
enum features_e{FEAT_NONE, FEAT_PMP=1, FEAT_EXT_N=2, FEAT_CLIC=4, FEAT_DEBUG=8, FEAT_TCM=16};
|
|
||||||
|
|
||||||
enum riscv_csr {
|
enum riscv_csr {
|
||||||
/* user-level CSR */
|
/* user-level CSR */
|
||||||
@ -172,27 +195,19 @@ enum riscv_csr {
|
|||||||
dcsr = 0x7B0,
|
dcsr = 0x7B0,
|
||||||
dpc = 0x7B1,
|
dpc = 0x7B1,
|
||||||
dscratch0 = 0x7B2,
|
dscratch0 = 0x7B2,
|
||||||
dscratch1 = 0x7B3
|
dscratch1 = 0x7B3,
|
||||||
|
// vector CSR
|
||||||
|
// URW
|
||||||
|
vstart = 0x008,
|
||||||
|
vxsat = 0x009,
|
||||||
|
vxrm = 0x00A,
|
||||||
|
vcsr = 0x00F,
|
||||||
|
// URO
|
||||||
|
vl = 0xC20,
|
||||||
|
vtype = 0xC21,
|
||||||
|
vlenb = 0xC22,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
enum {
|
|
||||||
PGSHIFT = 12,
|
|
||||||
PTE_PPN_SHIFT = 10,
|
|
||||||
// page table entry (PTE) fields
|
|
||||||
PTE_V = 0x001, // Valid
|
|
||||||
PTE_R = 0x002, // Read
|
|
||||||
PTE_W = 0x004, // Write
|
|
||||||
PTE_X = 0x008, // Execute
|
|
||||||
PTE_U = 0x010, // User
|
|
||||||
PTE_G = 0x020, // Global
|
|
||||||
PTE_A = 0x040, // Accessed
|
|
||||||
PTE_D = 0x080, // Dirty
|
|
||||||
PTE_SOFT = 0x300 // Reserved for Software
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T> inline bool PTE_TABLE(T PTE) { return (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V); }
|
|
||||||
|
|
||||||
enum { PRIV_U = 0, PRIV_S = 1, PRIV_M = 3, PRIV_D = 4 };
|
enum { PRIV_U = 0, PRIV_S = 1, PRIV_M = 3, PRIV_D = 4 };
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -211,25 +226,6 @@ enum {
|
|||||||
ISA_U = 1 << 20
|
ISA_U = 1 << 20
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vm_info {
|
|
||||||
int levels;
|
|
||||||
int idxbits;
|
|
||||||
int ptesize;
|
|
||||||
uint64_t ptbase;
|
|
||||||
bool is_active() { return levels; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct feature_config {
|
|
||||||
uint64_t clic_base{0xc0000000};
|
|
||||||
unsigned clic_int_ctl_bits{4};
|
|
||||||
unsigned clic_num_irq{16};
|
|
||||||
unsigned clic_num_trigger{0};
|
|
||||||
uint64_t tcm_base{0x10000000};
|
|
||||||
uint64_t tcm_size{0x8000};
|
|
||||||
uint64_t io_address{0xf0000000};
|
|
||||||
uint64_t io_addr_mask{0xf0000000};
|
|
||||||
};
|
|
||||||
|
|
||||||
class trap_load_access_fault : public trap_access {
|
class trap_load_access_fault : public trap_access {
|
||||||
public:
|
public:
|
||||||
trap_load_access_fault(uint64_t badaddr)
|
trap_load_access_fault(uint64_t badaddr)
|
||||||
@ -256,49 +252,663 @@ public:
|
|||||||
: trap_access(15 << 16, badaddr) {}
|
: trap_access(15 << 16, badaddr) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void read_reg_uint32(uint64_t offs, uint32_t& reg, uint8_t *const data, unsigned length) {
|
template <typename WORD_TYPE> struct priv_if {
|
||||||
auto reg_ptr = reinterpret_cast<uint8_t*>(®);
|
using rd_csr_f = std::function<iss::status(unsigned addr, WORD_TYPE&)>;
|
||||||
switch (offs & 0x3) {
|
using wr_csr_f = std::function<iss::status(unsigned addr, WORD_TYPE)>;
|
||||||
case 0:
|
|
||||||
for (auto i = 0U; i < length; ++i)
|
std::function<iss::status(unsigned, WORD_TYPE&)> read_csr;
|
||||||
*(data + i) = *(reg_ptr + i);
|
std::function<iss::status(unsigned, WORD_TYPE)> write_csr;
|
||||||
break;
|
std::function<iss::status(uint8_t const*)> exec_htif;
|
||||||
case 1:
|
std::function<void(uint16_t, uint16_t, WORD_TYPE)> raise_trap; // trap_id, cause, fault_data
|
||||||
for (auto i = 0U; i < length; ++i)
|
absl::flat_hash_map<unsigned, rd_csr_f>& csr_rd_cb;
|
||||||
*(data + i) = *(reg_ptr + 1 + i);
|
absl::flat_hash_map<unsigned, wr_csr_f>& csr_wr_cb;
|
||||||
break;
|
hart_state<WORD_TYPE>& state;
|
||||||
case 2:
|
uint8_t& PRIV;
|
||||||
for (auto i = 0U; i < length; ++i)
|
WORD_TYPE& PC;
|
||||||
*(data + i) = *(reg_ptr + 2 + i);
|
uint64_t& tohost;
|
||||||
break;
|
uint64_t& fromhost;
|
||||||
case 3:
|
unsigned& max_irq;
|
||||||
*data = *(reg_ptr + 3);
|
};
|
||||||
break;
|
|
||||||
|
template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_common : public BASE, public mem::memory_elem {
|
||||||
|
const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
|
||||||
|
const std::array<const char*, 16> trap_str = {{""
|
||||||
|
"Instruction address misaligned", // 0
|
||||||
|
"Instruction access fault", // 1
|
||||||
|
"Illegal instruction", // 2
|
||||||
|
"Breakpoint", // 3
|
||||||
|
"Load address misaligned", // 4
|
||||||
|
"Load access fault", // 5
|
||||||
|
"Store/AMO address misaligned", // 6
|
||||||
|
"Store/AMO access fault", // 7
|
||||||
|
"Environment call from U-mode", // 8
|
||||||
|
"Environment call from S-mode", // 9
|
||||||
|
"Reserved", // a
|
||||||
|
"Environment call from M-mode", // b
|
||||||
|
"Instruction page fault", // c
|
||||||
|
"Load page fault", // d
|
||||||
|
"Reserved", // e
|
||||||
|
"Store/AMO page fault"}};
|
||||||
|
const std::array<const char*, 12> irq_str = {{"User software interrupt", "Supervisor software interrupt", "Reserved",
|
||||||
|
"Machine software interrupt", "User timer interrupt", "Supervisor timer interrupt",
|
||||||
|
"Reserved", "Machine timer interrupt", "User external interrupt",
|
||||||
|
"Supervisor external interrupt", "Reserved", "Machine external interrupt"}};
|
||||||
|
constexpr static unsigned MEM = traits<BASE>::MEM;
|
||||||
|
|
||||||
|
using core = BASE;
|
||||||
|
using this_class = riscv_hart_common<BASE, LOGCAT>;
|
||||||
|
using phys_addr_t = typename core::phys_addr_t;
|
||||||
|
using reg_t = typename core::reg_t;
|
||||||
|
using addr_t = typename core::addr_t;
|
||||||
|
|
||||||
|
using rd_csr_f = std::function<iss::status(unsigned addr, reg_t&)>;
|
||||||
|
using wr_csr_f = std::function<iss::status(unsigned addr, reg_t)>;
|
||||||
|
|
||||||
|
#define MK_CSR_RD_CB(FCT) [this](unsigned a, reg_t& r) -> iss::status { return this->FCT(a, r); };
|
||||||
|
#define MK_CSR_WR_CB(FCT) [this](unsigned a, reg_t r) -> iss::status { return this->FCT(a, r); };
|
||||||
|
|
||||||
|
riscv_hart_common()
|
||||||
|
: state()
|
||||||
|
, instr_if(*this) {
|
||||||
|
// reset values
|
||||||
|
csr[misa] = traits<BASE>::MISA_VAL;
|
||||||
|
csr[mvendorid] = 0x669;
|
||||||
|
csr[marchid] = traits<BASE>::MARCHID_VAL;
|
||||||
|
csr[mimpid] = 1;
|
||||||
|
|
||||||
|
if(traits<BASE>::FLEN > 0) {
|
||||||
|
csr_rd_cb[fcsr] = MK_CSR_RD_CB(read_fcsr);
|
||||||
|
csr_wr_cb[fcsr] = MK_CSR_WR_CB(write_fcsr);
|
||||||
|
csr_rd_cb[fflags] = MK_CSR_RD_CB(read_fcsr);
|
||||||
|
csr_wr_cb[fflags] = MK_CSR_WR_CB(write_fcsr);
|
||||||
|
csr_rd_cb[frm] = MK_CSR_RD_CB(read_fcsr);
|
||||||
|
csr_wr_cb[frm] = MK_CSR_WR_CB(write_fcsr);
|
||||||
|
}
|
||||||
|
if(traits<BASE>::V_REGS_SIZE > 0) {
|
||||||
|
csr_rd_cb[vstart] = MK_CSR_RD_CB(read_vstart);
|
||||||
|
csr_wr_cb[vstart] = MK_CSR_WR_CB(write_vstart);
|
||||||
|
csr_rd_cb[vxsat] = MK_CSR_RD_CB(read_vxsat);
|
||||||
|
csr_wr_cb[vxsat] = MK_CSR_WR_CB(write_vxsat);
|
||||||
|
csr_rd_cb[vxrm] = MK_CSR_RD_CB(read_vxrm);
|
||||||
|
csr_wr_cb[vxrm] = MK_CSR_WR_CB(write_vxrm);
|
||||||
|
csr_rd_cb[vcsr] = MK_CSR_RD_CB(read_vcsr);
|
||||||
|
csr_wr_cb[vcsr] = MK_CSR_WR_CB(write_vcsr);
|
||||||
|
csr_rd_cb[vl] = MK_CSR_RD_CB(read_vl);
|
||||||
|
csr_rd_cb[vtype] = MK_CSR_RD_CB(read_vtype);
|
||||||
|
csr_rd_cb[vlenb] = MK_CSR_RD_CB(read_vlenb);
|
||||||
|
}
|
||||||
|
for(unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr) {
|
||||||
|
csr_rd_cb[addr] = MK_CSR_RD_CB(read_null);
|
||||||
|
csr_wr_cb[addr] = MK_CSR_WR_CB(write_plain);
|
||||||
|
}
|
||||||
|
if(traits<BASE>::XLEN == 32)
|
||||||
|
for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) {
|
||||||
|
csr_rd_cb[addr] = MK_CSR_RD_CB(read_null);
|
||||||
|
csr_wr_cb[addr] = MK_CSR_WR_CB(write_plain);
|
||||||
|
}
|
||||||
|
for(unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr) {
|
||||||
|
csr_rd_cb[addr] = MK_CSR_RD_CB(read_null);
|
||||||
|
csr_wr_cb[addr] = MK_CSR_WR_CB(write_plain);
|
||||||
|
}
|
||||||
|
for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) {
|
||||||
|
csr_rd_cb[addr] = MK_CSR_RD_CB(read_null);
|
||||||
|
}
|
||||||
|
if(traits<BASE>::XLEN == 32)
|
||||||
|
for(unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr) {
|
||||||
|
csr_rd_cb[addr] = MK_CSR_RD_CB(read_null);
|
||||||
|
}
|
||||||
|
// common regs
|
||||||
|
const std::array<unsigned, 4> roaddrs{{misa, mvendorid, marchid, mimpid}};
|
||||||
|
for(auto addr : roaddrs) {
|
||||||
|
csr_rd_cb[addr] = MK_CSR_RD_CB(read_plain);
|
||||||
|
csr_wr_cb[addr] = MK_CSR_WR_CB(write_null);
|
||||||
|
}
|
||||||
|
// special handling & overrides
|
||||||
|
csr_rd_cb[time] = MK_CSR_RD_CB(read_time);
|
||||||
|
if(traits<BASE>::XLEN == 32)
|
||||||
|
csr_rd_cb[timeh] = MK_CSR_RD_CB(read_time);
|
||||||
|
csr_rd_cb[cycle] = MK_CSR_RD_CB(read_cycle);
|
||||||
|
if(traits<BASE>::XLEN == 32)
|
||||||
|
csr_rd_cb[cycleh] = MK_CSR_RD_CB(read_cycle);
|
||||||
|
csr_rd_cb[instret] = MK_CSR_RD_CB(read_instret);
|
||||||
|
if(traits<BASE>::XLEN == 32)
|
||||||
|
csr_rd_cb[instreth] = MK_CSR_RD_CB(read_instret);
|
||||||
|
|
||||||
|
csr_rd_cb[mcycle] = MK_CSR_RD_CB(read_cycle);
|
||||||
|
csr_wr_cb[mcycle] = MK_CSR_WR_CB(write_cycle);
|
||||||
|
if(traits<BASE>::XLEN == 32)
|
||||||
|
csr_rd_cb[mcycleh] = MK_CSR_RD_CB(read_cycle);
|
||||||
|
if(traits<BASE>::XLEN == 32)
|
||||||
|
csr_wr_cb[mcycleh] = MK_CSR_WR_CB(write_cycle);
|
||||||
|
csr_rd_cb[minstret] = MK_CSR_RD_CB(read_instret);
|
||||||
|
csr_wr_cb[minstret] = MK_CSR_WR_CB(write_instret);
|
||||||
|
if(traits<BASE>::XLEN == 32)
|
||||||
|
csr_rd_cb[minstreth] = MK_CSR_RD_CB(read_instret);
|
||||||
|
if(traits<BASE>::XLEN == 32)
|
||||||
|
csr_wr_cb[minstreth] = MK_CSR_WR_CB(write_instret);
|
||||||
|
csr_rd_cb[mhartid] = MK_CSR_RD_CB(read_hartid);
|
||||||
|
};
|
||||||
|
|
||||||
|
~riscv_hart_common() {
|
||||||
|
if(io_buf.str().length()) {
|
||||||
|
CPPLOG(INFO) << "tohost send '" << io_buf.str() << "'";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void write_reg_uint32(uint64_t offs, uint32_t& reg, const uint8_t *const data, unsigned length) {
|
std::unordered_map<std::string, uint64_t> symbol_table;
|
||||||
auto reg_ptr = reinterpret_cast<uint8_t*>(®);
|
uint64_t entry_address{0};
|
||||||
switch (offs & 0x3) {
|
uint64_t tohost = std::numeric_limits<uint64_t>::max();
|
||||||
case 0:
|
uint64_t fromhost = std::numeric_limits<uint64_t>::max();
|
||||||
for (auto i = 0U; i < length; ++i)
|
std::stringstream io_buf;
|
||||||
*(reg_ptr + i) = *(data + i);
|
|
||||||
|
void set_semihosting_callback(semihosting_cb_t<reg_t> cb) { semihosting_cb = cb; };
|
||||||
|
|
||||||
|
std::pair<uint64_t, bool> load_file(std::string name, int type) {
|
||||||
|
return std::make_pair(entry_address, read_elf_file(name, sizeof(reg_t) == 4 ? ELFIO::ELFCLASS32 : ELFIO::ELFCLASS64));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool read_elf_file(std::string name, uint8_t expected_elf_class) {
|
||||||
|
// Create elfio reader
|
||||||
|
ELFIO::elfio reader;
|
||||||
|
// Load ELF data
|
||||||
|
if(reader.load(name)) {
|
||||||
|
// check elf properties
|
||||||
|
if(reader.get_class() != expected_elf_class) {
|
||||||
|
CPPLOG(ERR) << "ISA missmatch, selected XLEN does not match supplied file ";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(reader.get_type() != ELFIO::ET_EXEC)
|
||||||
|
return false;
|
||||||
|
if(reader.get_machine() != ELFIO::EM_RISCV)
|
||||||
|
return false;
|
||||||
|
entry_address = reader.get_entry();
|
||||||
|
for(const auto& pseg : reader.segments) {
|
||||||
|
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
|
||||||
|
const auto seg_data = pseg->get_data();
|
||||||
|
const auto type = pseg->get_type();
|
||||||
|
if(type == ELFIO::PT_LOAD && fsize > 0) {
|
||||||
|
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM,
|
||||||
|
pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data));
|
||||||
|
if(res != iss::Ok)
|
||||||
|
CPPLOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto sym_sec = reader.sections[".symtab"];
|
||||||
|
if(ELFIO::SHT_SYMTAB == sym_sec->get_type() || ELFIO::SHT_DYNSYM == sym_sec->get_type()) {
|
||||||
|
ELFIO::symbol_section_accessor symbols(reader, sym_sec);
|
||||||
|
auto sym_no = symbols.get_symbols_num();
|
||||||
|
std::string name;
|
||||||
|
ELFIO::Elf64_Addr value = 0;
|
||||||
|
ELFIO::Elf_Xword size = 0;
|
||||||
|
unsigned char bind = 0;
|
||||||
|
unsigned char type = 0;
|
||||||
|
ELFIO::Elf_Half section = 0;
|
||||||
|
unsigned char other = 0;
|
||||||
|
for(auto i = 0U; i < sym_no; ++i) {
|
||||||
|
symbols.get_symbol(i, name, value, size, bind, type, section, other);
|
||||||
|
if(name != "") {
|
||||||
|
this->symbol_table[name] = value;
|
||||||
|
#ifndef NDEBUG
|
||||||
|
CPPLOG(DEBUG) << "Found Symbol " << name;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto to_it = symbol_table.find("tohost");
|
||||||
|
if(to_it != std::end(symbol_table))
|
||||||
|
tohost = to_it->second;
|
||||||
|
auto from_it = symbol_table.find("tohost");
|
||||||
|
if(from_it != std::end(symbol_table))
|
||||||
|
tohost = from_it->second;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
iss::status execute_sys_write(arch_if* aif, const std::array<uint64_t, 8>& loaded_payload, unsigned mem_type) {
|
||||||
|
uint64_t fd = loaded_payload[1];
|
||||||
|
uint64_t buf_ptr = loaded_payload[2];
|
||||||
|
uint64_t len = loaded_payload[3];
|
||||||
|
std::vector<char> buf(len);
|
||||||
|
if(aif->read(address_type::PHYSICAL, access_type::DEBUG_READ, mem_type, buf_ptr, len, reinterpret_cast<uint8_t*>(buf.data()))) {
|
||||||
|
CPPLOG(ERR) << "SYS_WRITE buffer read went wrong";
|
||||||
|
return iss::Err;
|
||||||
|
}
|
||||||
|
// we disregard the fd and just log to stdout
|
||||||
|
for(size_t i = 0; i < len; i++) {
|
||||||
|
if(buf[i] == '\n' || buf[i] == '\0') {
|
||||||
|
CPPLOG(INFO) << "tohost send '" << io_buf.str() << "'";
|
||||||
|
io_buf.str("");
|
||||||
|
} else
|
||||||
|
io_buf << buf[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not sure what the correct return value should be
|
||||||
|
uint8_t ret_val = 1;
|
||||||
|
if(fromhost != std::numeric_limits<uint64_t>::max())
|
||||||
|
if(aif->write(address_type::PHYSICAL, access_type::DEBUG_WRITE, mem_type, fromhost, 1, &ret_val)) {
|
||||||
|
CPPLOG(ERR) << "Fromhost write went wrong";
|
||||||
|
return iss::Err;
|
||||||
|
}
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool has_compressed() { return traits<BASE>::MISA_VAL & 0b0100; }
|
||||||
|
|
||||||
|
constexpr reg_t get_pc_mask() { return has_compressed() ? (reg_t)~1 : (reg_t)~3; }
|
||||||
|
|
||||||
|
void disass_output(uint64_t pc, const std::string instr) override {
|
||||||
|
// NSCLOG(INFO, LOGCAT) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", pc, instr, lvl[this->reg.PRIV],
|
||||||
|
// (reg_t)state.mstatus,
|
||||||
|
// this->reg.cycle + cycle_offset);
|
||||||
|
NSCLOG(INFO, LOGCAT) << fmt::format("0x{:016x} {:40} [p:{};c:{}]", pc, instr, lvl[this->reg.PRIV],
|
||||||
|
this->reg.cycle + cycle_offset);
|
||||||
|
};
|
||||||
|
|
||||||
|
void register_csr(unsigned addr, rd_csr_f f) { csr_rd_cb[addr] = f; }
|
||||||
|
void register_csr(unsigned addr, wr_csr_f f) { csr_wr_cb[addr] = f; }
|
||||||
|
void register_csr(unsigned addr, rd_csr_f rdf, wr_csr_f wrf) {
|
||||||
|
csr_rd_cb[addr] = rdf;
|
||||||
|
csr_wr_cb[addr] = wrf;
|
||||||
|
}
|
||||||
|
void unregister_csr_rd(unsigned addr) { csr_rd_cb.erase(addr); }
|
||||||
|
void unregister_csr_wr(unsigned addr) { csr_wr_cb.erase(addr); }
|
||||||
|
|
||||||
|
bool debug_mode_active() { return this->reg.PRIV & 0x4; }
|
||||||
|
|
||||||
|
const reg_t& get_mhartid() const { return mhartid_reg; }
|
||||||
|
void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; };
|
||||||
|
|
||||||
|
iss::status read_csr(unsigned addr, reg_t& val) {
|
||||||
|
if(addr >= csr.size())
|
||||||
|
return iss::Err;
|
||||||
|
auto req_priv_lvl = (addr >> 8) & 0x3;
|
||||||
|
if(this->reg.PRIV < req_priv_lvl) // not having required privileges
|
||||||
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
|
auto it = csr_rd_cb.find(addr);
|
||||||
|
if(it == csr_rd_cb.end() || !it->second) // non existent register
|
||||||
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
|
return it->second(addr, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_csr(unsigned addr, reg_t val) {
|
||||||
|
if(addr >= csr.size())
|
||||||
|
return iss::Err;
|
||||||
|
auto req_priv_lvl = (addr >> 8) & 0x3;
|
||||||
|
if(this->reg.PRIV < req_priv_lvl) // not having required privileges
|
||||||
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
|
if((addr & 0xc00) == 0xc00) // writing to read-only region
|
||||||
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
|
auto it = csr_wr_cb.find(addr);
|
||||||
|
if(it == csr_wr_cb.end() || !it->second) // non existent register
|
||||||
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
|
return it->second(addr, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_null(unsigned addr, reg_t& val) {
|
||||||
|
val = 0;
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; }
|
||||||
|
|
||||||
|
iss::status read_plain(unsigned addr, reg_t& val) {
|
||||||
|
val = csr[addr];
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_plain(unsigned addr, reg_t val) {
|
||||||
|
csr[addr] = val;
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_cycle(unsigned addr, reg_t& val) {
|
||||||
|
auto cycle_val = this->reg.cycle + cycle_offset;
|
||||||
|
if(addr == mcycle) {
|
||||||
|
val = static_cast<reg_t>(cycle_val);
|
||||||
|
} else if(addr == mcycleh) {
|
||||||
|
val = static_cast<reg_t>(cycle_val >> 32);
|
||||||
|
}
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_cycle(unsigned addr, reg_t val) {
|
||||||
|
if(sizeof(typename traits<BASE>::reg_t) != 4) {
|
||||||
|
mcycle_csr = static_cast<uint64_t>(val);
|
||||||
|
} else {
|
||||||
|
if(addr == mcycle) {
|
||||||
|
mcycle_csr = (mcycle_csr & 0xffffffff00000000) + val;
|
||||||
|
} else {
|
||||||
|
mcycle_csr = (static_cast<uint64_t>(val) << 32) + (mcycle_csr & 0xffffffff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cycle_offset = mcycle_csr - this->reg.cycle; // TODO: relying on wrap-around
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_instret(unsigned addr, reg_t& val) {
|
||||||
|
if((addr & 0xff) == (minstret & 0xff)) {
|
||||||
|
val = static_cast<reg_t>(this->reg.instret);
|
||||||
|
} else if((addr & 0xff) == (minstreth & 0xff)) {
|
||||||
|
val = static_cast<reg_t>(this->reg.instret >> 32);
|
||||||
|
}
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_instret(unsigned addr, reg_t val) {
|
||||||
|
if(sizeof(typename traits<BASE>::reg_t) != 4) {
|
||||||
|
this->reg.instret = static_cast<uint64_t>(val);
|
||||||
|
} else {
|
||||||
|
if((addr & 0xff) == (minstret & 0xff)) {
|
||||||
|
this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val;
|
||||||
|
} else {
|
||||||
|
this->reg.instret = (static_cast<uint64_t>(val) << 32) + (this->reg.instret & 0xffffffff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->reg.instret--;
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_time(unsigned addr, reg_t& val) {
|
||||||
|
uint64_t time_val = this->reg.cycle / (100000000 / 32768 - 1); //-> ~3052;
|
||||||
|
if(addr == time) {
|
||||||
|
val = static_cast<reg_t>(time_val);
|
||||||
|
} else if(addr == timeh) {
|
||||||
|
if(sizeof(typename traits<BASE>::reg_t) != 4)
|
||||||
|
return iss::Err;
|
||||||
|
val = static_cast<reg_t>(time_val >> 32);
|
||||||
|
}
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_tvec(unsigned addr, reg_t& val) {
|
||||||
|
val = csr[addr] & ~2;
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_hartid(unsigned addr, reg_t& val) {
|
||||||
|
val = mhartid_reg;
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_epc(unsigned addr, reg_t val) {
|
||||||
|
csr[addr] = val & get_pc_mask();
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_dcsr(unsigned addr, reg_t val) {
|
||||||
|
if(!debug_mode_active())
|
||||||
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
|
// +-------------- ebreakm
|
||||||
|
// | +---------- stepi
|
||||||
|
// | | +++----- cause
|
||||||
|
// | | ||| +- step
|
||||||
|
csr[addr] = val & 0b1000100111000100U;
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_debug(unsigned addr, reg_t& val) {
|
||||||
|
if(!debug_mode_active())
|
||||||
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
|
val = csr[addr];
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_dscratch(unsigned addr, reg_t val) {
|
||||||
|
if(!debug_mode_active())
|
||||||
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
|
csr[addr] = val;
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_dpc(unsigned addr, reg_t& val) {
|
||||||
|
if(!debug_mode_active())
|
||||||
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
|
val = this->reg.DPC;
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_dpc(unsigned addr, reg_t val) {
|
||||||
|
if(!debug_mode_active())
|
||||||
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
|
this->reg.DPC = val;
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_fcsr(unsigned addr, reg_t& val) {
|
||||||
|
switch(addr) {
|
||||||
|
case 1: // fflags, 4:0
|
||||||
|
val = bit_sub<0, 5>(this->get_fcsr());
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 2: // frm, 7:5
|
||||||
for (auto i = 0U; i < length; ++i)
|
val = bit_sub<5, 3>(this->get_fcsr());
|
||||||
*(reg_ptr + 1 + i) = *(data + i);
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 3: // fcsr
|
||||||
for (auto i = 0U; i < length; ++i)
|
val = this->get_fcsr();
|
||||||
*(reg_ptr + 2 + i) = *(data + i);
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
default:
|
||||||
*(reg_ptr + 3) = *data ;
|
return iss::Err;
|
||||||
|
}
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_fcsr(unsigned addr, reg_t val) {
|
||||||
|
switch(addr) {
|
||||||
|
case 1: // fflags, 4:0
|
||||||
|
this->set_fcsr((this->get_fcsr() & 0xffffffe0) | (val & 0x1f));
|
||||||
break;
|
break;
|
||||||
|
case 2: // frm, 7:5
|
||||||
|
this->set_fcsr((this->get_fcsr() & 0xffffff1f) | ((val & 0x7) << 5));
|
||||||
|
break;
|
||||||
|
case 3: // fcsr
|
||||||
|
this->set_fcsr(val & 0xff);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return iss::Err;
|
||||||
|
}
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_vstart(unsigned addr, reg_t& val) {
|
||||||
|
val = this->get_vstart();
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_vstart(unsigned addr, reg_t val) {
|
||||||
|
this->set_vstart(val);
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_vxsat(unsigned addr, reg_t& val) {
|
||||||
|
val = this->get_vxsat();
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_vxsat(unsigned addr, reg_t val) {
|
||||||
|
this->set_vxsat(val & 1);
|
||||||
|
csr[vcsr] = (~1ULL & csr[vcsr]) | (val & 1);
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_vxrm(unsigned addr, reg_t& val) {
|
||||||
|
val = this->get_vxrm();
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_vxrm(unsigned addr, reg_t val) {
|
||||||
|
this->set_vxrm(val & 0b11);
|
||||||
|
csr[vcsr] = (~0b110ULL & csr[vcsr]) | ((val & 0b11) << 1);
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_vcsr(unsigned addr, reg_t& val) {
|
||||||
|
val = csr[vcsr];
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_vcsr(unsigned addr, reg_t val) {
|
||||||
|
csr[vcsr] = val;
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_vl(unsigned addr, reg_t& val) {
|
||||||
|
val = this->get_vl();
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_vtype(unsigned addr, reg_t& val) {
|
||||||
|
val = this->get_vtype();
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_vlenb(unsigned addr, reg_t& val) {
|
||||||
|
val = csr[vlenb];
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv_if<reg_t> get_priv_if() {
|
||||||
|
return priv_if<reg_t>{.read_csr = [this](unsigned addr, reg_t& val) -> iss::status { return read_csr(addr, val); },
|
||||||
|
.write_csr = [this](unsigned addr, reg_t val) -> iss::status { return write_csr(addr, val); },
|
||||||
|
.exec_htif = [this](uint8_t const* data) -> iss::status { return execute_htif(data); },
|
||||||
|
.raise_trap =
|
||||||
|
[this](uint16_t trap_id, uint16_t cause, reg_t fault_data) {
|
||||||
|
this->reg.trap_state = 0x80ULL << 24 | (cause << 16) | trap_id;
|
||||||
|
this->fault_data = fault_data;
|
||||||
|
},
|
||||||
|
.csr_rd_cb{this->csr_rd_cb},
|
||||||
|
.csr_wr_cb{this->csr_wr_cb},
|
||||||
|
.state{this->state},
|
||||||
|
.PRIV{this->reg.PRIV},
|
||||||
|
.PC{this->reg.PC},
|
||||||
|
.tohost{this->tohost},
|
||||||
|
.fromhost{this->fromhost},
|
||||||
|
.max_irq{mcause_max_irq}};
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status execute_htif(uint8_t const* data) {
|
||||||
|
reg_t cur_data = *reinterpret_cast<const reg_t*>(data);
|
||||||
|
// Extract Device (bits 63:56)
|
||||||
|
uint8_t device = traits<BASE>::XLEN == 32 ? 0 : (cur_data >> 56) & 0xFF;
|
||||||
|
// Extract Command (bits 55:48)
|
||||||
|
uint8_t command = traits<BASE>::XLEN == 32 ? 0 : (cur_data >> 48) & 0xFF;
|
||||||
|
// Extract payload (bits 47:0)
|
||||||
|
uint64_t payload_addr = cur_data & 0xFFFFFFFFFFFFULL;
|
||||||
|
if(payload_addr & 1) {
|
||||||
|
CPPLOG(FATAL) << "this->tohost value is 0x" << std::hex << payload_addr << std::dec << " (" << payload_addr
|
||||||
|
<< "), stopping simulation";
|
||||||
|
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||||
|
this->interrupt_sim = payload_addr;
|
||||||
|
return iss::Ok;
|
||||||
|
} else if(device == 0 && command == 0) {
|
||||||
|
std::array<uint64_t, 8> loaded_payload;
|
||||||
|
if(memory.rd_mem(access_type::DEBUG_READ, payload_addr, 8 * sizeof(uint64_t),
|
||||||
|
reinterpret_cast<uint8_t*>(loaded_payload.data())) == iss::Err)
|
||||||
|
CPPLOG(ERR) << "Syscall read went wrong";
|
||||||
|
uint64_t syscall_num = loaded_payload.at(0);
|
||||||
|
if(syscall_num == 64) { // SYS_WRITE
|
||||||
|
return this->execute_sys_write(this, loaded_payload, traits<BASE>::MEM);
|
||||||
|
} else {
|
||||||
|
CPPLOG(ERR) << "this->tohost syscall with number 0x" << std::hex << syscall_num << std::dec << " (" << syscall_num
|
||||||
|
<< ") not implemented";
|
||||||
|
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||||
|
this->interrupt_sim = payload_addr;
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CPPLOG(ERR) << "this->tohost functionality not implemented for device " << device << " and command " << command;
|
||||||
|
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||||
|
this->interrupt_sim = payload_addr;
|
||||||
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mem::memory_hierarchy memories;
|
||||||
|
|
||||||
|
mem::memory_if get_mem_if() override {
|
||||||
|
assert(false || "This function should never be called");
|
||||||
|
return mem::memory_if{};
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_next(mem::memory_if mem_if) override { memory = mem_if; };
|
||||||
|
|
||||||
|
void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
hart_state<reg_t> state;
|
||||||
|
|
||||||
|
static constexpr reg_t get_mstatus_mask_t(unsigned priv_lvl = PRIV_M) {
|
||||||
|
if(sizeof(reg_t) == 4) {
|
||||||
|
return priv_lvl == PRIV_U ? 0x80000011UL : // 0b1...0 0001 0001
|
||||||
|
priv_lvl == PRIV_S ? 0x800de133UL // 0b0...0 0001 1000 1001 1001;
|
||||||
|
: 0x807ff9ddUL;
|
||||||
|
} else {
|
||||||
|
return priv_lvl == PRIV_U ? 0x011ULL : // 0b1...0 0001 0001
|
||||||
|
priv_lvl == PRIV_S ? 0x000de133ULL
|
||||||
|
: 0x007ff9ddULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mem::memory_if memory;
|
||||||
|
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
||||||
|
|
||||||
|
riscv_instrumentation_if(riscv_hart_common<BASE, LOGCAT>& arch)
|
||||||
|
: arch(arch) {}
|
||||||
|
/**
|
||||||
|
* get the name of this architecture
|
||||||
|
*
|
||||||
|
* @return the name of this architecture
|
||||||
|
*/
|
||||||
|
const std::string core_type_name() const override { return traits<BASE>::core_type; }
|
||||||
|
|
||||||
|
uint64_t get_pc() override { return arch.reg.PC; }
|
||||||
|
|
||||||
|
uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }
|
||||||
|
|
||||||
|
uint64_t get_instr_word() override { return arch.reg.instruction; }
|
||||||
|
|
||||||
|
uint64_t get_instr_count() override { return arch.reg.icount; }
|
||||||
|
|
||||||
|
uint64_t get_pendig_traps() override { return arch.reg.trap_state; }
|
||||||
|
|
||||||
|
uint64_t get_total_cycles() override { return arch.reg.cycle + arch.cycle_offset; }
|
||||||
|
|
||||||
|
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }
|
||||||
|
|
||||||
|
bool is_branch_taken() override { return arch.reg.last_branch; }
|
||||||
|
|
||||||
|
unsigned get_reg_num() override { return traits<BASE>::NUM_REGS; }
|
||||||
|
|
||||||
|
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
|
||||||
|
|
||||||
|
std::unordered_map<std::string, uint64_t> const& get_symbol_table(std::string name) override { return arch.symbol_table; }
|
||||||
|
|
||||||
|
riscv_hart_common<BASE, LOGCAT>& arch;
|
||||||
|
};
|
||||||
|
|
||||||
|
friend struct riscv_instrumentation_if;
|
||||||
|
riscv_instrumentation_if instr_if;
|
||||||
|
|
||||||
|
instrumentation_if* get_instrumentation_if() override { return &instr_if; };
|
||||||
|
|
||||||
|
using csr_type = util::sparse_array<typename traits<BASE>::reg_t, 1ULL << 12, 12>;
|
||||||
|
using csr_page_type = typename csr_type::page_type;
|
||||||
|
csr_type csr;
|
||||||
|
|
||||||
|
absl::flat_hash_map<unsigned, rd_csr_f> csr_rd_cb;
|
||||||
|
absl::flat_hash_map<unsigned, wr_csr_f> csr_wr_cb;
|
||||||
|
|
||||||
|
reg_t mhartid_reg{0x0};
|
||||||
|
uint64_t mcycle_csr{0};
|
||||||
|
uint64_t minstret_csr{0};
|
||||||
|
reg_t fault_data;
|
||||||
|
|
||||||
|
int64_t cycle_offset{0};
|
||||||
|
int64_t instret_offset{0};
|
||||||
|
semihosting_cb_t<reg_t> semihosting_cb;
|
||||||
|
unsigned mcause_max_irq{16U};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace arch
|
||||||
|
} // namespace iss
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (C) 2017 - 2020 MINRES Technologies GmbH
|
* Copyright (C) 2024 MINRES Technologies GmbH
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -30,6 +30,7 @@
|
|||||||
*
|
*
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
#include "tgc5c.h"
|
#include "tgc5c.h"
|
||||||
#include "util/ities.h"
|
#include "util/ities.h"
|
||||||
#include <util/logging.h>
|
#include <util/logging.h>
|
||||||
@ -66,4 +67,4 @@ uint8_t *tgc5c::get_regs_base_ptr() {
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
// clang-format on
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1,3 +1,37 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (C) 2023 - 2025 MINRES Technologies GmbH
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* eyck@minres.com - initial implementation
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
#ifndef _ISS_ARCH_TGC_MAPPER_H
|
#ifndef _ISS_ARCH_TGC_MAPPER_H
|
||||||
#define _ISS_ARCH_TGC_MAPPER_H
|
#define _ISS_ARCH_TGC_MAPPER_H
|
||||||
|
|
||||||
@ -15,36 +49,37 @@ 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_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_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_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_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_EXT_N)>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -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 {
|
||||||
@ -85,10 +87,11 @@ public:
|
|||||||
virtual ~wt_cache() = default;
|
virtual ~wt_cache() = default;
|
||||||
|
|
||||||
unsigned size{4096};
|
unsigned size{4096};
|
||||||
unsigned line_sz{32};
|
unsigned line_sz{64};
|
||||||
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,13 +114,12 @@ 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));
|
||||||
}
|
}
|
||||||
if((a.val&io_addr_mask) != io_address) {
|
if((a.access & iss::access_type::FETCH) == iss::access_type::FETCH || (a.val & io_addr_mask) != io_address) {
|
||||||
auto set_addr = (a.val & (size - 1)) >> util::ilog2(line_sz * ways);
|
auto set_addr = (a.val & (size - 1)) >> util::ilog2(line_sz * ways);
|
||||||
auto tag_addr = a.val >> util::ilog2(line_sz);
|
auto tag_addr = a.val >> util::ilog2(line_sz);
|
||||||
auto& set = (is_fetch(a.access) ? icache_ptr : dcache_ptr)->sets[set_addr];
|
auto& set = (is_fetch(a.access) ? icache_ptr : dcache_ptr)->sets[set_addr];
|
||||||
@ -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
|
||||||
|
|
||||||
|
4142
src/iss/debugger/csr_names.cpp
Normal file
4142
src/iss/debugger/csr_names.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -30,8 +30,8 @@
|
|||||||
*
|
*
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_
|
#ifndef _ISS_ARCH_DEBUGGER_RISCV_TARGET_ADAPTER_H_
|
||||||
#define _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_
|
#define _ISS_ARCH_DEBUGGER_RISCV_TARGET_ADAPTER_H_
|
||||||
|
|
||||||
#include "iss/arch_if.h"
|
#include "iss/arch_if.h"
|
||||||
#include <iss/arch/traits.h>
|
#include <iss/arch/traits.h>
|
||||||
@ -48,6 +48,10 @@
|
|||||||
|
|
||||||
namespace iss {
|
namespace iss {
|
||||||
namespace debugger {
|
namespace debugger {
|
||||||
|
|
||||||
|
char const* const get_csr_name(unsigned);
|
||||||
|
constexpr auto csr_offset = 100U;
|
||||||
|
|
||||||
using namespace iss::arch;
|
using namespace iss::arch;
|
||||||
using namespace iss::debugger;
|
using namespace iss::debugger;
|
||||||
|
|
||||||
@ -84,8 +88,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 +106,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,18 +127,23 @@ 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;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static inline constexpr addr_t map_addr(const addr_t& i) { return i; }
|
static inline constexpr addr_t map_addr(const addr_t& i) { return i; }
|
||||||
|
std::string csr_xml;
|
||||||
iss::arch_if* core;
|
iss::arch_if* core;
|
||||||
rp_thread_ref thread_idx;
|
rp_thread_ref thread_idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename ARCH> typename std::enable_if<iss::arch::traits<ARCH>::FLEN != 0, unsigned>::type get_f0_offset() {
|
||||||
|
return iss::arch::traits<ARCH>::F0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ARCH> typename std::enable_if<iss::arch::traits<ARCH>::FLEN == 0, unsigned>::type get_f0_offset() { return 0; }
|
||||||
|
|
||||||
template <typename ARCH> status riscv_target_adapter<ARCH>::set_gen_thread(rp_thread_ref& thread) {
|
template <typename ARCH> status riscv_target_adapter<ARCH>::set_gen_thread(rp_thread_ref& thread) {
|
||||||
thread_idx = thread;
|
thread_idx = thread;
|
||||||
return Ok;
|
return Ok;
|
||||||
@ -158,9 +166,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,15 +183,31 @@ 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) {
|
CPPLOG(TRACE) << "reading target registers";
|
||||||
LOG(TRACE) << "reading target registers";
|
|
||||||
// return idx<0?:;
|
|
||||||
data.clear();
|
data.clear();
|
||||||
avail.clear();
|
avail.clear();
|
||||||
const uint8_t* reg_base = core->get_regs_base_ptr();
|
const uint8_t* reg_base = core->get_regs_base_ptr();
|
||||||
auto start_reg = arch::traits<ARCH>::X0;
|
auto start_reg = arch::traits<ARCH>::X0;
|
||||||
for (size_t reg_no = start_reg; reg_no < start_reg+33/*arch::traits<ARCH>::NUM_REGS*/; ++reg_no) {
|
for(size_t i = 0; i < 33; ++i) {
|
||||||
|
if(i < arch::traits<ARCH>::RFS || i == arch::traits<ARCH>::PC) {
|
||||||
|
auto reg_no = i < 32 ? start_reg + i : arch::traits<ARCH>::PC;
|
||||||
|
unsigned offset = traits<ARCH>::reg_byte_offsets[reg_no];
|
||||||
|
for(size_t j = 0; j < arch::traits<ARCH>::XLEN / 8; ++j) {
|
||||||
|
data.push_back(*(reg_base + offset + j));
|
||||||
|
avail.push_back(0xff);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(size_t j = 0; j < arch::traits<ARCH>::XLEN / 8; ++j) {
|
||||||
|
data.push_back(0);
|
||||||
|
avail.push_back(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(iss::arch::traits<ARCH>::FLEN > 0) {
|
||||||
|
auto fstart_reg = get_f0_offset<ARCH>();
|
||||||
|
for(size_t i = 0; i < 32; ++i) {
|
||||||
|
auto reg_no = fstart_reg + i;
|
||||||
auto reg_width = arch::traits<ARCH>::reg_bit_widths[reg_no] / 8;
|
auto reg_width = arch::traits<ARCH>::reg_bit_widths[reg_no] / 8;
|
||||||
unsigned offset = traits<ARCH>::reg_byte_offsets[reg_no];
|
unsigned offset = traits<ARCH>::reg_byte_offsets[reg_no];
|
||||||
for(size_t j = 0; j < reg_width; ++j) {
|
for(size_t j = 0; j < reg_width; ++j) {
|
||||||
@ -192,21 +215,7 @@ status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t> &data, st
|
|||||||
avail.push_back(0xff);
|
avail.push_back(0xff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// work around fill with F type registers
|
}
|
||||||
// if (arch::traits<ARCH>::NUM_REGS < 65) {
|
|
||||||
// auto reg_width = sizeof(typename arch::traits<ARCH>::reg_t);
|
|
||||||
// for (size_t reg_no = 0; reg_no < 33; ++reg_no) {
|
|
||||||
// for (size_t j = 0; j < reg_width; ++j) {
|
|
||||||
// data.push_back(0x0);
|
|
||||||
// avail.push_back(0x00);
|
|
||||||
// }
|
|
||||||
// // if(arch::traits<ARCH>::XLEN < 64)
|
|
||||||
// // for(unsigned j=0; j<4; ++j){
|
|
||||||
// // data.push_back(0x0);
|
|
||||||
// // avail.push_back(0x00);
|
|
||||||
// // }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,34 +223,33 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::write_registers(cons
|
|||||||
auto start_reg = arch::traits<ARCH>::X0;
|
auto start_reg = arch::traits<ARCH>::X0;
|
||||||
auto* reg_base = core->get_regs_base_ptr();
|
auto* reg_base = core->get_regs_base_ptr();
|
||||||
auto iter = data.data();
|
auto iter = data.data();
|
||||||
bool e_ext = arch::traits<ARCH>::PC<32;
|
auto iter_end = data.data() + data.size();
|
||||||
for (size_t reg_no = 0; reg_no < start_reg+33/*arch::traits<ARCH>::NUM_REGS*/; ++reg_no) {
|
for(size_t i = 0; i < 33 && iter < iter_end; ++i) {
|
||||||
if(e_ext && reg_no>15){
|
auto reg_width = arch::traits<ARCH>::XLEN / 8;
|
||||||
if(reg_no==32){
|
if(i < arch::traits<ARCH>::RFS) {
|
||||||
auto reg_width = arch::traits<ARCH>::reg_bit_widths[arch::traits<ARCH>::PC] / 8;
|
auto offset = traits<ARCH>::reg_byte_offsets[start_reg + i];
|
||||||
|
std::copy(iter, iter + reg_width, reg_base + offset);
|
||||||
|
} else if(i == 32) {
|
||||||
auto offset = traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC];
|
auto offset = traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC];
|
||||||
std::copy(iter, iter + reg_width, reg_base);
|
std::copy(iter, iter + reg_width, reg_base + offset);
|
||||||
} else {
|
|
||||||
const uint64_t zero_val=0;
|
|
||||||
auto reg_width = arch::traits<ARCH>::reg_bit_widths[15] / 8;
|
|
||||||
auto iter = (uint8_t*)&zero_val;
|
|
||||||
std::copy(iter, iter + reg_width, reg_base);
|
|
||||||
}
|
}
|
||||||
} else {
|
iter += reg_width;
|
||||||
auto reg_width = arch::traits<ARCH>::reg_bit_widths[reg_no] / 8;
|
}
|
||||||
auto offset = traits<ARCH>::reg_byte_offsets[reg_no];
|
if(iss::arch::traits<ARCH>::FLEN > 0) {
|
||||||
std::copy(iter, iter + reg_width, reg_base);
|
auto fstart_reg = get_f0_offset<ARCH>();
|
||||||
iter += 4;
|
auto reg_width = arch::traits<ARCH>::FLEN / 8;
|
||||||
reg_base += offset;
|
for(size_t i = 0; i < 32 && iter < iter_end; ++i) {
|
||||||
|
unsigned offset = traits<ARCH>::reg_byte_offsets[fstart_reg + i];
|
||||||
|
std::copy(iter, iter + reg_width, reg_base + offset);
|
||||||
|
iter += reg_width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 < csr_offset) {
|
||||||
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;
|
||||||
auto* reg_base = core->get_regs_base_ptr();
|
auto* reg_base = core->get_regs_base_ptr();
|
||||||
@ -252,24 +260,24 @@ status riscv_target_adapter<ARCH>::read_single_register(unsigned int reg_no, std
|
|||||||
std::copy(reg_base + offset, reg_base + offset + reg_width, data.begin());
|
std::copy(reg_base + offset, reg_base + offset + reg_width, data.begin());
|
||||||
std::fill(avail.begin(), avail.end(), 0xff);
|
std::fill(avail.begin(), avail.end(), 0xff);
|
||||||
} else {
|
} else {
|
||||||
typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_READ, traits<ARCH>::CSR, reg_no - 65);
|
typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_READ, traits<ARCH>::CSR, reg_no - csr_offset);
|
||||||
data.resize(sizeof(typename traits<ARCH>::reg_t));
|
data.resize(sizeof(typename traits<ARCH>::reg_t));
|
||||||
avail.resize(sizeof(typename traits<ARCH>::reg_t));
|
avail.resize(sizeof(typename traits<ARCH>::reg_t));
|
||||||
std::fill(avail.begin(), avail.end(), 0xff);
|
std::fill(avail.begin(), avail.end(), 0xff);
|
||||||
core->read(a, data.size(), data.data());
|
core->read(a, data.size(), data.data());
|
||||||
|
std::fill(avail.begin(), avail.end(), 0xff);
|
||||||
}
|
}
|
||||||
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 < csr_offset) {
|
||||||
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;
|
||||||
auto offset = traits<ARCH>::reg_byte_offsets[reg_no];
|
auto offset = traits<ARCH>::reg_byte_offsets[reg_no];
|
||||||
std::copy(data.begin(), data.begin() + reg_width, reg_base + offset);
|
std::copy(data.begin(), data.begin() + reg_width, reg_base + offset);
|
||||||
} else {
|
} else {
|
||||||
typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_WRITE, traits<ARCH>::CSR, reg_no - 65);
|
typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_WRITE, traits<ARCH>::CSR, reg_no - csr_offset);
|
||||||
core->write(a, data.size(), data.data());
|
core->write(a, data.size(), data.data());
|
||||||
}
|
}
|
||||||
return Ok;
|
return Ok;
|
||||||
@ -282,7 +290,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::read_mem(uint64_t ad
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> status riscv_target_adapter<ARCH>::write_mem(uint64_t addr, const std::vector<uint8_t>& data) {
|
template <typename ARCH> status riscv_target_adapter<ARCH>::write_mem(uint64_t addr, const std::vector<uint8_t>& data) {
|
||||||
auto a = map_addr({iss::access_type::DEBUG_READ, iss::address_type::VIRTUAL, 0, addr});
|
auto a = map_addr({iss::access_type::DEBUG_WRITE, iss::address_type::VIRTUAL, 0, addr});
|
||||||
auto f = [&]() -> status { return core->write(a, data.size(), data.data()); };
|
auto f = [&]() -> status { return core->write(a, data.size(), data.data()); };
|
||||||
return srv->execute_syncronized(f);
|
return srv->execute_syncronized(f);
|
||||||
}
|
}
|
||||||
@ -292,21 +300,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 +320,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,9 +342,9 @@ 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
|
CPPLOG(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";
|
CPPLOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -357,14 +359,13 @@ 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
|
CPPLOG(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";
|
CPPLOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
|
CPPLOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
|
||||||
return Err;
|
return Err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -382,93 +383,57 @@ status riscv_target_adapter<ARCH>::resume_from_addr(bool step, int sig, uint64_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> status riscv_target_adapter<ARCH>::target_xml_query(std::string& out_buf) {
|
template <typename ARCH> status riscv_target_adapter<ARCH>::target_xml_query(std::string& out_buf) {
|
||||||
const std::string res{"<?xml version=\"1.0\"?><!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
|
if(!csr_xml.size()) {
|
||||||
"<target><architecture>riscv:rv32</architecture>"
|
std::ostringstream oss;
|
||||||
//" <feature name=\"org.gnu.gdb.riscv.rv32i\">\n"
|
oss << "<?xml version=\"1.0\"?><!DOCTYPE feature SYSTEM \"gdb-target.dtd\"><target version=\"1.0\">\n";
|
||||||
//" <reg name=\"x0\" bitsize=\"32\" group=\"general\"/>\n"
|
if(iss::arch::traits<ARCH>::XLEN == 32)
|
||||||
//" <reg name=\"x1\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << "<architecture>riscv:rv32</architecture>\n";
|
||||||
//" <reg name=\"x2\" bitsize=\"32\" group=\"general\"/>\n"
|
else if(iss::arch::traits<ARCH>::XLEN == 64)
|
||||||
//" <reg name=\"x3\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " <architectureriscv:rv64</architecture>\n";
|
||||||
//" <reg name=\"x4\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " <feature name=\"org.gnu.gdb.riscv.cpu\">\n";
|
||||||
//" <reg name=\"x5\" bitsize=\"32\" group=\"general\"/>\n"
|
auto reg_base_num = iss::arch::traits<ARCH>::X0;
|
||||||
//" <reg name=\"x6\" bitsize=\"32\" group=\"general\"/>\n"
|
for(auto i = 0U; i < iss::arch::traits<ARCH>::RFS; ++i) {
|
||||||
//" <reg name=\"x7\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " <reg name=\"x" << i << "\" bitsize=\"" << iss::arch::traits<ARCH>::reg_bit_widths[reg_base_num + i]
|
||||||
//" <reg name=\"x8\" bitsize=\"32\" group=\"general\"/>\n"
|
<< "\" type=\"int\" regnum=\"" << i << "\"/>\n";
|
||||||
//" <reg name=\"x9\" bitsize=\"32\" group=\"general\"/>\n"
|
}
|
||||||
//" <reg name=\"x10\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " <reg name=\"pc\" bitsize=\"" << iss::arch::traits<ARCH>::reg_bit_widths[iss::arch::traits<ARCH>::PC]
|
||||||
//" <reg name=\"x11\" bitsize=\"32\" group=\"general\"/>\n"
|
<< "\" type=\"code_ptr\" regnum=\"" << 32U << "\"/>\n";
|
||||||
//" <reg name=\"x12\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " </feature>\n";
|
||||||
//" <reg name=\"x13\" bitsize=\"32\" group=\"general\"/>\n"
|
if(iss::arch::traits<ARCH>::FLEN > 0) {
|
||||||
//" <reg name=\"x14\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " <feature name=\"org.gnu.gdb.riscv.fpu\">\n";
|
||||||
//" <reg name=\"x15\" bitsize=\"32\" group=\"general\"/>\n"
|
auto reg_base_num = get_f0_offset<ARCH>();
|
||||||
//" <reg name=\"x16\" bitsize=\"32\" group=\"general\"/>\n"
|
auto type = iss::arch::traits<ARCH>::FLEN == 32 ? "ieee_single" : "riscv_double";
|
||||||
//" <reg name=\"x17\" bitsize=\"32\" group=\"general\"/>\n"
|
for(auto i = 0U; i < 32; ++i) {
|
||||||
//" <reg name=\"x18\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " <reg name=\"f" << i << "\" bitsize=\"" << iss::arch::traits<ARCH>::reg_bit_widths[reg_base_num + i]
|
||||||
//" <reg name=\"x19\" bitsize=\"32\" group=\"general\"/>\n"
|
<< "\" type=\"" << type << "\" regnum=\"" << i + 33 << "\"/>\n";
|
||||||
//" <reg name=\"x20\" bitsize=\"32\" group=\"general\"/>\n"
|
}
|
||||||
//" <reg name=\"x21\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " <reg name=\"fcsr\" bitsize=\"" << iss::arch::traits<ARCH>::XLEN << "\" regnum=\"103\" type int/>\n";
|
||||||
//" <reg name=\"x22\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " <reg name=\"fflags\" bitsize=\"" << iss::arch::traits<ARCH>::XLEN << "\" regnum=\"101\" type int/>\n";
|
||||||
//" <reg name=\"x23\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " <reg name=\"frm\" bitsize=\"" << iss::arch::traits<ARCH>::XLEN << "\" regnum=\"102\" type int/>\n";
|
||||||
//" <reg name=\"x24\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " </feature>\n";
|
||||||
//" <reg name=\"x25\" bitsize=\"32\" group=\"general\"/>\n"
|
}
|
||||||
//" <reg name=\"x26\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " <feature name=\"org.gnu.gdb.riscv.csr\">\n";
|
||||||
//" <reg name=\"x27\" bitsize=\"32\" group=\"general\"/>\n"
|
std::vector<uint8_t> data;
|
||||||
//" <reg name=\"x28\" bitsize=\"32\" group=\"general\"/>\n"
|
std::vector<uint8_t> avail;
|
||||||
//" <reg name=\"x29\" bitsize=\"32\" group=\"general\"/>\n"
|
data.resize(sizeof(typename traits<ARCH>::reg_t));
|
||||||
//" <reg name=\"x30\" bitsize=\"32\" group=\"general\"/>\n"
|
avail.resize(sizeof(typename traits<ARCH>::reg_t));
|
||||||
//" <reg name=\"x31\" bitsize=\"32\" group=\"general\"/>\n"
|
for(auto i = 0U; i < 4096; ++i) {
|
||||||
//" </feature>\n"
|
typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_READ, traits<ARCH>::CSR, i);
|
||||||
"</target>"};
|
std::fill(avail.begin(), avail.end(), 0xff);
|
||||||
out_buf = res;
|
auto res = core->read(a, data.size(), data.data());
|
||||||
|
if(res == iss::Ok) {
|
||||||
|
oss << " <reg name=\"" << get_csr_name(i) << "\" bitsize=\"" << iss::arch::traits<ARCH>::XLEN
|
||||||
|
<< "\" type=\"int\" regnum=\"" << (i + csr_offset) << "\"/>\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
oss << " </feature>\n";
|
||||||
|
oss << "</target>\n";
|
||||||
|
csr_xml = oss.str();
|
||||||
|
}
|
||||||
|
out_buf = csr_xml;
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
} // namespace debugger
|
||||||
|
} // namespace iss
|
||||||
|
|
||||||
/*
|
#endif /* _ISS_ARCH_DEBUGGER_RISCV_TARGET_ADAPTER_H_ */
|
||||||
*
|
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!DOCTYPE target SYSTEM "gdb-target.dtd">
|
|
||||||
<target>
|
|
||||||
<architecture>riscv:rv32</architecture>
|
|
||||||
|
|
||||||
<feature name="org.gnu.gdb.riscv.rv32i">
|
|
||||||
<reg name="x0" bitsize="32" group="general"/>
|
|
||||||
<reg name="x1" bitsize="32" group="general"/>
|
|
||||||
<reg name="x2" bitsize="32" group="general"/>
|
|
||||||
<reg name="x3" bitsize="32" group="general"/>
|
|
||||||
<reg name="x4" bitsize="32" group="general"/>
|
|
||||||
<reg name="x5" bitsize="32" group="general"/>
|
|
||||||
<reg name="x6" bitsize="32" group="general"/>
|
|
||||||
<reg name="x7" bitsize="32" group="general"/>
|
|
||||||
<reg name="x8" bitsize="32" group="general"/>
|
|
||||||
<reg name="x9" bitsize="32" group="general"/>
|
|
||||||
<reg name="x10" bitsize="32" group="general"/>
|
|
||||||
<reg name="x11" bitsize="32" group="general"/>
|
|
||||||
<reg name="x12" bitsize="32" group="general"/>
|
|
||||||
<reg name="x13" bitsize="32" group="general"/>
|
|
||||||
<reg name="x14" bitsize="32" group="general"/>
|
|
||||||
<reg name="x15" bitsize="32" group="general"/>
|
|
||||||
<reg name="x16" bitsize="32" group="general"/>
|
|
||||||
<reg name="x17" bitsize="32" group="general"/>
|
|
||||||
<reg name="x18" bitsize="32" group="general"/>
|
|
||||||
<reg name="x19" bitsize="32" group="general"/>
|
|
||||||
<reg name="x20" bitsize="32" group="general"/>
|
|
||||||
<reg name="x21" bitsize="32" group="general"/>
|
|
||||||
<reg name="x22" bitsize="32" group="general"/>
|
|
||||||
<reg name="x23" bitsize="32" group="general"/>
|
|
||||||
<reg name="x24" bitsize="32" group="general"/>
|
|
||||||
<reg name="x25" bitsize="32" group="general"/>
|
|
||||||
<reg name="x26" bitsize="32" group="general"/>
|
|
||||||
<reg name="x27" bitsize="32" group="general"/>
|
|
||||||
<reg name="x28" bitsize="32" group="general"/>
|
|
||||||
<reg name="x29" bitsize="32" group="general"/>
|
|
||||||
<reg name="x30" bitsize="32" group="general"/>
|
|
||||||
<reg name="x31" bitsize="32" group="general"/>
|
|
||||||
</feature>
|
|
||||||
|
|
||||||
</target>
|
|
||||||
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_ */
|
|
||||||
|
@ -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_ */
|
||||||
|
285
src/iss/mem/clic.h
Normal file
285
src/iss/mem/clic.h
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (C) 2025 MINRES Technologies GmbH
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* eyck@minres.com - initial implementation
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "memory_if.h"
|
||||||
|
#include "iss/arch/riscv_hart_common.h"
|
||||||
|
#include "iss/vm_types.h"
|
||||||
|
#include <util/logging.h>
|
||||||
|
|
||||||
|
namespace iss {
|
||||||
|
namespace mem {
|
||||||
|
struct clic_config {
|
||||||
|
uint64_t clic_base{0xc0000000};
|
||||||
|
unsigned clic_int_ctl_bits{4};
|
||||||
|
unsigned clic_num_irq{16};
|
||||||
|
unsigned clic_num_trigger{0};
|
||||||
|
bool nmode{false};
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void read_reg_with_offset(uint32_t reg, uint8_t offs, uint8_t* const data, unsigned length) {
|
||||||
|
auto reg_ptr = reinterpret_cast<uint8_t*>(®);
|
||||||
|
switch(offs) {
|
||||||
|
default:
|
||||||
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(data + i) = *(reg_ptr + i);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(data + i) = *(reg_ptr + 1 + i);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(data + i) = *(reg_ptr + 2 + i);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
*data = *(reg_ptr + 3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void write_reg_with_offset(uint32_t& reg, uint8_t offs, const uint8_t* const data, unsigned length) {
|
||||||
|
auto reg_ptr = reinterpret_cast<uint8_t*>(®);
|
||||||
|
switch(offs) {
|
||||||
|
default:
|
||||||
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(reg_ptr + i) = *(data + i);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(reg_ptr + 1 + i) = *(data + i);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(reg_ptr + 2 + i) = *(data + i);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
*(reg_ptr + 3) = *data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename WORD_TYPE> struct clic : public memory_elem {
|
||||||
|
using this_class = clic<WORD_TYPE>;
|
||||||
|
using reg_t = WORD_TYPE;
|
||||||
|
constexpr static unsigned WORD_LEN = sizeof(WORD_TYPE) * 8;
|
||||||
|
|
||||||
|
clic(arch::priv_if<WORD_TYPE> hart_if, clic_config cfg)
|
||||||
|
: hart_if(hart_if)
|
||||||
|
, cfg(cfg) {
|
||||||
|
clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw = 0});
|
||||||
|
clic_cfg_reg = 0x30;
|
||||||
|
clic_mact_lvl = clic_mprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1;
|
||||||
|
clic_uact_lvl = clic_uprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1;
|
||||||
|
hart_if.csr_rd_cb[arch::mtvt] = MK_CSR_RD_CB(read_plain);
|
||||||
|
hart_if.csr_wr_cb[arch::mtvt] = MK_CSR_WR_CB(write_xtvt);
|
||||||
|
// hart_if.csr_rd_cb[mxnti] = MK_CSR_RD_CB(read_plain(a,r);};
|
||||||
|
// hart_if.csr_wr_cb[mxnti] = MK_CSR_WR_CB(write_plain(a,r);};
|
||||||
|
hart_if.csr_rd_cb[arch::mintstatus] = MK_CSR_RD_CB(read_intstatus);
|
||||||
|
hart_if.csr_wr_cb[arch::mintstatus] = MK_CSR_WR_CB(write_null);
|
||||||
|
// hart_if.csr_rd_cb[mscratchcsw] = MK_CSR_RD_CB(read_plain(a,r);};
|
||||||
|
// hart_if.csr_wr_cb[mscratchcsw] = MK_CSR_WR_CB(write_plain(a,r);};
|
||||||
|
// hart_if.csr_rd_cb[mscratchcswl] = MK_CSR_RD_CB(read_plain(a,r);};
|
||||||
|
// hart_if.csr_wr_cb[mscratchcswl] = MK_CSR_WR_CB(write_plain(a,r);};
|
||||||
|
hart_if.csr_rd_cb[arch::mintthresh] = MK_CSR_RD_CB(read_plain);
|
||||||
|
hart_if.csr_wr_cb[arch::mintthresh] = MK_CSR_WR_CB(write_intthresh);
|
||||||
|
if(cfg.nmode) {
|
||||||
|
hart_if.csr_rd_cb[arch::utvt] = MK_CSR_RD_CB(read_plain);
|
||||||
|
hart_if.csr_wr_cb[arch::utvt] = MK_CSR_WR_CB(write_xtvt);
|
||||||
|
hart_if.csr_rd_cb[arch::uintstatus] = MK_CSR_RD_CB(read_intstatus);
|
||||||
|
hart_if.csr_wr_cb[arch::uintstatus] = MK_CSR_WR_CB(write_null);
|
||||||
|
hart_if.csr_rd_cb[arch::uintthresh] = MK_CSR_RD_CB(read_plain);
|
||||||
|
hart_if.csr_wr_cb[arch::uintthresh] = MK_CSR_WR_CB(write_intthresh);
|
||||||
|
}
|
||||||
|
hart_if.csr[arch::mintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1;
|
||||||
|
hart_if.csr[arch::uintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
~clic() = default;
|
||||||
|
|
||||||
|
memory_if get_mem_if() override {
|
||||||
|
return memory_if{.rd_mem{util::delegate<rd_mem_func_sig>::from<this_class, &this_class::read_mem>(this)},
|
||||||
|
.wr_mem{util::delegate<wr_mem_func_sig>::from<this_class, &this_class::write_mem>(this)}};
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_next(memory_if mem) override { down_stream_mem = mem; }
|
||||||
|
|
||||||
|
std::tuple<uint64_t, uint64_t> get_range() override { return {cfg.clic_base, cfg.clic_base + 0x7fff}; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
iss::status read_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t* data) {
|
||||||
|
if(addr >= cfg.clic_base && (addr + length) < (cfg.clic_base + 0x8000))
|
||||||
|
return read_clic(addr, length, data);
|
||||||
|
return down_stream_mem.rd_mem(access, addr, length, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t const* data) {
|
||||||
|
if(addr >= cfg.clic_base && (addr + length) < (cfg.clic_base + 0x8000))
|
||||||
|
return write_clic(addr, length, data);
|
||||||
|
return down_stream_mem.wr_mem(access, addr, length, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_clic(uint64_t addr, unsigned length, uint8_t* data);
|
||||||
|
|
||||||
|
iss::status write_clic(uint64_t addr, unsigned length, uint8_t const* data);
|
||||||
|
|
||||||
|
iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; }
|
||||||
|
|
||||||
|
iss::status read_plain(unsigned addr, reg_t& val) {
|
||||||
|
val = hart_if.csr[addr];
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_xtvt(unsigned addr, reg_t val) {
|
||||||
|
hart_if.csr[addr] = val & ~0x3fULL;
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_cause(unsigned addr, reg_t& val);
|
||||||
|
iss::status write_cause(unsigned addr, reg_t val);
|
||||||
|
|
||||||
|
iss::status read_intstatus(unsigned addr, reg_t& val);
|
||||||
|
iss::status write_intthresh(unsigned addr, reg_t val);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
arch::priv_if<WORD_TYPE> hart_if;
|
||||||
|
memory_if down_stream_mem;
|
||||||
|
clic_config cfg;
|
||||||
|
uint8_t clic_cfg_reg{0};
|
||||||
|
std::array<uint32_t, 32> clic_inttrig_reg;
|
||||||
|
union clic_int_reg_t {
|
||||||
|
struct {
|
||||||
|
uint8_t ip;
|
||||||
|
uint8_t ie;
|
||||||
|
uint8_t attr;
|
||||||
|
uint8_t ctl;
|
||||||
|
};
|
||||||
|
uint32_t raw;
|
||||||
|
};
|
||||||
|
std::vector<clic_int_reg_t> clic_int_reg;
|
||||||
|
uint8_t clic_mprev_lvl{0}, clic_uprev_lvl{0};
|
||||||
|
uint8_t clic_mact_lvl{0}, clic_uact_lvl{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::read_clic(uint64_t addr, unsigned length, uint8_t* const data) {
|
||||||
|
if(addr == cfg.clic_base) { // cliccfg
|
||||||
|
*data = clic_cfg_reg;
|
||||||
|
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
|
||||||
|
auto offset = ((addr & 0x7fff) - 0x40) / 4;
|
||||||
|
read_reg_with_offset(clic_inttrig_reg[offset], addr & 0x3, data, length);
|
||||||
|
} 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;
|
||||||
|
read_reg_with_offset(clic_int_reg[offset].raw, addr & 0x3, data, length);
|
||||||
|
} else {
|
||||||
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(data + i) = 0;
|
||||||
|
}
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::write_clic(uint64_t addr, unsigned length, const uint8_t* const data) {
|
||||||
|
if(addr == cfg.clic_base) { // cliccfg
|
||||||
|
clic_cfg_reg = (clic_cfg_reg & ~0x1e) | (*data & 0x1e);
|
||||||
|
} 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;
|
||||||
|
write_reg_with_offset(clic_inttrig_reg[offset], addr & 0x3, data, length);
|
||||||
|
} 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;
|
||||||
|
write_reg_with_offset(clic_int_reg[offset].raw, addr & 0x3, data, length);
|
||||||
|
clic_int_reg[offset].raw &= 0xf0c70101; // clicIntCtlBits->0xf0, clicintattr->0xc7, clicintie->0x1, clicintip->0x1
|
||||||
|
}
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::read_cause(unsigned addr, reg_t& val) {
|
||||||
|
if((hart_if.csr[arch::mtvec] & 0x3) == 3) {
|
||||||
|
val = hart_if.csr[addr] & (1UL << (sizeof(reg_t) * 8) | (hart_if.mcause_max_irq - 1) | (0xfUL << 16));
|
||||||
|
auto mode = (addr >> 8) & 0x3;
|
||||||
|
switch(mode) {
|
||||||
|
case 0:
|
||||||
|
val |= clic_uprev_lvl << 16;
|
||||||
|
val |= hart_if.state.mstatus.UPIE << 27;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
val |= clic_mprev_lvl << 16;
|
||||||
|
val |= hart_if.state.mstatus.MPIE << 27;
|
||||||
|
val |= hart_if.state.mstatus.MPP << 28;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
val = hart_if.csr[addr] & ((1UL << (sizeof(WORD_TYPE) * 8 - 1)) | (hart_if.mcause_max_irq - 1));
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::write_cause(unsigned addr, reg_t val) {
|
||||||
|
if((hart_if.csr[arch::mtvec] & 0x3) == 3) {
|
||||||
|
auto mask = ((1UL << (sizeof(WORD_TYPE) * 8 - 1)) | (hart_if.mcause_max_irq - 1) | (0xfUL << 16));
|
||||||
|
hart_if.csr[addr] = (val & mask) | (hart_if.csr[addr] & ~mask);
|
||||||
|
auto mode = (addr >> 8) & 0x3;
|
||||||
|
switch(mode) {
|
||||||
|
case 0:
|
||||||
|
clic_uprev_lvl = ((val >> 16) & 0xff) | (1 << (8 - cfg.clic_int_ctl_bits)) - 1;
|
||||||
|
hart_if.state.mstatus.UPIE = (val >> 27) & 0x1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
clic_mprev_lvl = ((val >> 16) & 0xff) | (1 << (8 - cfg.clic_int_ctl_bits)) - 1;
|
||||||
|
hart_if.state.mstatus.MPIE = (val >> 27) & 0x1;
|
||||||
|
hart_if.state.mstatus.MPP = (val >> 28) & 0x3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto mask = ((1UL << (sizeof(WORD_TYPE) * 8 - 1)) | (hart_if.mcause_max_irq - 1));
|
||||||
|
hart_if.csr[addr] = (val & mask) | (hart_if.csr[addr] & ~mask);
|
||||||
|
}
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::read_intstatus(unsigned addr, reg_t& val) {
|
||||||
|
auto mode = (addr >> 8) & 0x3;
|
||||||
|
val = clic_uact_lvl & 0xff;
|
||||||
|
if(mode == 0x3)
|
||||||
|
val += (clic_mact_lvl & 0xff) << 24;
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::write_intthresh(unsigned addr, reg_t val) {
|
||||||
|
hart_if.csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1;
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mem
|
||||||
|
} // namespace iss
|
101
src/iss/mem/memory_if.cpp
Normal file
101
src/iss/mem/memory_if.cpp
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (C) 2025 MINRES Technologies GmbH
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* eyck@minres.com - initial implementation
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "memory_if.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace iss {
|
||||||
|
namespace mem {
|
||||||
|
void memory_hierarchy::root(memory_elem& e) {
|
||||||
|
hierarchy.push_front(&e);
|
||||||
|
root_set = true;
|
||||||
|
update_chain();
|
||||||
|
}
|
||||||
|
void memory_hierarchy::prepend(memory_elem& e) {
|
||||||
|
if(root_set)
|
||||||
|
hierarchy.insert(hierarchy.begin() + 1, &e);
|
||||||
|
else
|
||||||
|
hierarchy.push_front(&e);
|
||||||
|
update_chain();
|
||||||
|
}
|
||||||
|
void memory_hierarchy::append(memory_elem& e) {
|
||||||
|
hierarchy.push_back(&e);
|
||||||
|
update_chain();
|
||||||
|
}
|
||||||
|
void memory_hierarchy::insert_before(memory_elem&) {}
|
||||||
|
void memory_hierarchy::insert_after(memory_elem&) {}
|
||||||
|
void memory_hierarchy::replace_last(memory_elem& e) {
|
||||||
|
auto old = hierarchy.back();
|
||||||
|
auto it = std::find_if(std::begin(owned_elems), std::end(owned_elems),
|
||||||
|
[old](std::unique_ptr<memory_elem> const& p) { return p.get() == old; });
|
||||||
|
hierarchy.pop_back();
|
||||||
|
if(it != std::end(owned_elems))
|
||||||
|
owned_elems.erase(it);
|
||||||
|
hierarchy.push_back(&e);
|
||||||
|
update_chain();
|
||||||
|
}
|
||||||
|
void memory_hierarchy::update_chain() {
|
||||||
|
bool tail = false;
|
||||||
|
for(size_t i = 1; i < hierarchy.size(); ++i) {
|
||||||
|
hierarchy[i - 1]->set_next(hierarchy[i]->get_mem_if());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void memory_hierarchy::prepend(std::unique_ptr<memory_elem>&& p) {
|
||||||
|
prepend(*p);
|
||||||
|
owned_elems.push_back(std::move(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
void memory_hierarchy::append(std::unique_ptr<memory_elem>&& p) {
|
||||||
|
append(*p);
|
||||||
|
owned_elems.push_back(std::move(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
void memory_hierarchy::insert_before(std::unique_ptr<memory_elem>&& p) {
|
||||||
|
insert_before(*p);
|
||||||
|
owned_elems.push_back(std::move(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
void memory_hierarchy::insert_after(std::unique_ptr<memory_elem>&& p) {
|
||||||
|
insert_after(*p);
|
||||||
|
owned_elems.push_back(std::move(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
void memory_hierarchy::replace_last(std::unique_ptr<memory_elem>&& p) {
|
||||||
|
replace_last(*p);
|
||||||
|
owned_elems.push_back(std::move(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mem
|
||||||
|
} // namespace iss
|
86
src/iss/mem/memory_if.h
Normal file
86
src/iss/mem/memory_if.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (C) 2025 MINRES Technologies GmbH
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* eyck@minres.com - initial implementation
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _MEMORY_MEMORY_IF_
|
||||||
|
#define _MEMORY_MEMORY_IF_
|
||||||
|
|
||||||
|
#include "iss/vm_types.h"
|
||||||
|
#include <deque>
|
||||||
|
#include <functional>
|
||||||
|
#include <limits>
|
||||||
|
#include <memory>
|
||||||
|
#include <util/delegate.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace iss {
|
||||||
|
namespace mem {
|
||||||
|
|
||||||
|
using rd_mem_func_sig = iss::status(iss::access_type, uint64_t, unsigned, uint8_t*);
|
||||||
|
using wr_mem_func_sig = iss::status(iss::access_type, uint64_t, unsigned, uint8_t const*);
|
||||||
|
|
||||||
|
struct memory_if {
|
||||||
|
util::delegate<iss::status(access_type, uint64_t, unsigned, uint8_t*)> rd_mem;
|
||||||
|
util::delegate<iss::status(access_type, uint64_t, unsigned, uint8_t const*)> wr_mem;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct memory_elem {
|
||||||
|
virtual ~memory_elem() = default;
|
||||||
|
virtual memory_if get_mem_if() = 0;
|
||||||
|
virtual void set_next(memory_if) = 0;
|
||||||
|
virtual std::tuple<uint64_t, uint64_t> get_range() { return {0, std::numeric_limits<uint64_t>::max()}; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct memory_hierarchy {
|
||||||
|
void root(memory_elem&);
|
||||||
|
void prepend(memory_elem&);
|
||||||
|
void append(memory_elem&);
|
||||||
|
void insert_before(memory_elem&);
|
||||||
|
void insert_after(memory_elem&);
|
||||||
|
void replace_last(memory_elem&);
|
||||||
|
void prepend(std::unique_ptr<memory_elem>&&);
|
||||||
|
void append(std::unique_ptr<memory_elem>&&);
|
||||||
|
void insert_before(std::unique_ptr<memory_elem>&&);
|
||||||
|
void insert_after(std::unique_ptr<memory_elem>&&);
|
||||||
|
void replace_last(std::unique_ptr<memory_elem>&&);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void update_chain();
|
||||||
|
std::deque<memory_elem*> hierarchy;
|
||||||
|
std::vector<std::unique_ptr<memory_elem>> owned_elems;
|
||||||
|
bool root_set{false};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mem
|
||||||
|
} // namespace iss
|
||||||
|
#endif
|
90
src/iss/mem/memory_with_htif.h
Normal file
90
src/iss/mem/memory_with_htif.h
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (C) 2025 MINRES Technologies GmbH
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* eyck@minres.com - initial implementation
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _MEMORY_WITH_HTIF_
|
||||||
|
#define _MEMORY_WITH_HTIF_
|
||||||
|
|
||||||
|
#include "memory_if.h"
|
||||||
|
#include "iss/arch/riscv_hart_common.h"
|
||||||
|
#include "iss/vm_types.h"
|
||||||
|
#include <util/logging.h>
|
||||||
|
#include <util/sparse_array.h>
|
||||||
|
|
||||||
|
namespace iss {
|
||||||
|
namespace mem {
|
||||||
|
template <typename WORD_TYPE> struct memory_with_htif : public memory_elem {
|
||||||
|
using this_class = memory_with_htif<WORD_TYPE>;
|
||||||
|
constexpr static unsigned WORD_LEN = sizeof(WORD_TYPE) * 8;
|
||||||
|
|
||||||
|
memory_with_htif(arch::priv_if<WORD_TYPE> hart_if)
|
||||||
|
: hart_if(hart_if) {}
|
||||||
|
|
||||||
|
~memory_with_htif() = default;
|
||||||
|
|
||||||
|
memory_if get_mem_if() override {
|
||||||
|
return memory_if{.rd_mem{util::delegate<rd_mem_func_sig>::from<this_class, &this_class::read_mem>(this)},
|
||||||
|
.wr_mem{util::delegate<wr_mem_func_sig>::from<this_class, &this_class::write_mem>(this)}};
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_next(memory_if) override {
|
||||||
|
// intenrionally left empty, leaf element
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
iss::status read_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t* data) {
|
||||||
|
for(auto offs = 0U; offs < length; ++offs) {
|
||||||
|
*(data + offs) = mem[(addr + offs) % mem.size()];
|
||||||
|
}
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t const* data) {
|
||||||
|
mem_type::page_type& p = mem(addr / mem.page_size);
|
||||||
|
std::copy(data, data + length, p.data() + (addr & mem.page_addr_mask));
|
||||||
|
// this->tohost handling in case of riscv-test
|
||||||
|
// according to https://github.com/riscv-software-src/riscv-isa-sim/issues/364#issuecomment-607657754:
|
||||||
|
if(access && iss::access_type::FUNC && addr == hart_if.tohost) {
|
||||||
|
return hart_if.exec_htif(data);
|
||||||
|
}
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
using mem_type = util::sparse_array<uint8_t, 1ULL << 32>;
|
||||||
|
mem_type mem;
|
||||||
|
arch::priv_if<WORD_TYPE> hart_if;
|
||||||
|
};
|
||||||
|
} // namespace mem
|
||||||
|
} // namespace iss
|
||||||
|
#endif // _MEMORY_WITH_HTIF_
|
353
src/iss/mem/mmu.h
Normal file
353
src/iss/mem/mmu.h
Normal file
@ -0,0 +1,353 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (C) 2025 MINRES Technologies GmbH
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* eyck@minres.com - initial implementation
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "iss/arch/riscv_hart_common.h"
|
||||||
|
#include "iss/vm_types.h"
|
||||||
|
#include "memory_if.h"
|
||||||
|
#include <util/logging.h>
|
||||||
|
|
||||||
|
namespace iss {
|
||||||
|
namespace mem {
|
||||||
|
enum {
|
||||||
|
PGSHIFT = 12,
|
||||||
|
PTE_PPN_SHIFT = 10,
|
||||||
|
// page table entry (PTE) fields
|
||||||
|
PTE_V = 0x001, // Valid
|
||||||
|
PTE_R = 0x002, // Read
|
||||||
|
PTE_W = 0x004, // Write
|
||||||
|
PTE_X = 0x008, // Execute
|
||||||
|
PTE_U = 0x010, // User
|
||||||
|
PTE_G = 0x020, // Global
|
||||||
|
PTE_A = 0x040, // Accessed
|
||||||
|
PTE_D = 0x080, // Dirty
|
||||||
|
PTE_SOFT = 0x300 // Reserved for Software
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T> inline bool PTE_TABLE(T PTE) { return (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V); }
|
||||||
|
|
||||||
|
struct vm_info {
|
||||||
|
int levels;
|
||||||
|
int idxbits;
|
||||||
|
int ptesize;
|
||||||
|
uint64_t ptbase;
|
||||||
|
bool is_active() { return levels; }
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void read_reg_with_offset(uint32_t reg, uint8_t offs, uint8_t* const data, unsigned length) {
|
||||||
|
auto reg_ptr = reinterpret_cast<uint8_t*>(®);
|
||||||
|
switch(offs) {
|
||||||
|
default:
|
||||||
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(data + i) = *(reg_ptr + i);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(data + i) = *(reg_ptr + 1 + i);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(data + i) = *(reg_ptr + 2 + i);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
*data = *(reg_ptr + 3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void write_reg_with_offset(uint32_t& reg, uint8_t offs, const uint8_t* const data, unsigned length) {
|
||||||
|
auto reg_ptr = reinterpret_cast<uint8_t*>(®);
|
||||||
|
switch(offs) {
|
||||||
|
default:
|
||||||
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(reg_ptr + i) = *(data + i);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(reg_ptr + 1 + i) = *(data + i);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(reg_ptr + 2 + i) = *(data + i);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
*(reg_ptr + 3) = *data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: update vminfo on trap enter and leave as well as mstatus write, reset
|
||||||
|
template <typename WORD_TYPE> struct mmu : public memory_elem {
|
||||||
|
using this_class = mmu<WORD_TYPE>;
|
||||||
|
using reg_t = WORD_TYPE;
|
||||||
|
constexpr static unsigned WORD_LEN = sizeof(WORD_TYPE) * 8;
|
||||||
|
|
||||||
|
constexpr static reg_t PGSIZE = 1 << PGSHIFT;
|
||||||
|
constexpr static reg_t PGMASK = PGSIZE - 1;
|
||||||
|
|
||||||
|
mmu(arch::priv_if<WORD_TYPE> hart_if)
|
||||||
|
: hart_if(hart_if) {
|
||||||
|
hart_if.csr_rd_cb[satp] = MK_CSR_RD_CB(read_satp);
|
||||||
|
hart_if.csr_wr_cb[satp] = MK_CSR_WR_CB(write_satp);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~mmu() = default;
|
||||||
|
|
||||||
|
memory_if get_mem_if() override {
|
||||||
|
return memory_if{.rd_mem{util::delegate<rd_mem_func_sig>::from<this_class, &this_class::read_mem>(this)},
|
||||||
|
.wr_mem{util::delegate<wr_mem_func_sig>::from<this_class, &this_class::write_mem>(this)}};
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_next(memory_if mem) override { down_stream_mem = mem; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
iss::status read_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t* data) {
|
||||||
|
if(unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary
|
||||||
|
vm_info vm = decode_vm_info(hart_if.PRIV, satp);
|
||||||
|
if(vm.levels != 0) { // VM is active
|
||||||
|
auto split_addr = (addr + length) & ~PGMASK;
|
||||||
|
auto len1 = split_addr - addr;
|
||||||
|
auto res = down_stream_mem.rd_mem(access, addr, len1, data);
|
||||||
|
if(res == iss::Ok)
|
||||||
|
res = down_stream_mem.rd_mem(access, split_addr, length - len1, data + len1);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return down_stream_mem.rd_mem(access, addr, length, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t const* data) {
|
||||||
|
if(unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary
|
||||||
|
vm_info vm = decode_vm_info(hart_if.PRIV, satp);
|
||||||
|
if(vm.levels != 0) { // VM is active
|
||||||
|
auto split_addr = (addr + length) & ~PGMASK;
|
||||||
|
auto len1 = split_addr - addr;
|
||||||
|
auto res = down_stream_mem.wr_mem(access, addr, len1, data);
|
||||||
|
if(res == iss::Ok)
|
||||||
|
res = down_stream_mem.wr_mem(access, split_addr, length - len1, data + len1);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return down_stream_mem.wr_mem(access, virt2phys(access, addr), length, data);
|
||||||
|
}
|
||||||
|
void update_vm_info();
|
||||||
|
|
||||||
|
iss::status read_plain(unsigned addr, reg_t& val) {
|
||||||
|
val = hart_if.csr[addr];
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_plain(unsigned addr, reg_t const& val) {
|
||||||
|
hart_if.csr[addr] = val;
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_satp(unsigned addr, reg_t& val) {
|
||||||
|
auto tvm = bit_sub<20, 1>(hart_if.state.mstatus());
|
||||||
|
if(hart_if.PRIV == arch::PRIV_S & tvm != 0) {
|
||||||
|
hart_if.raise_trap(2, 0, hart_if.PC);
|
||||||
|
// hart_if.reg.trap_state = (1 << 31) | (2 << 16);
|
||||||
|
// hart_if.fault_data = hart_if.reg.PC;
|
||||||
|
return iss::Err;
|
||||||
|
}
|
||||||
|
val = satp;
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_satp(unsigned addr, reg_t val) {
|
||||||
|
reg_t tvm = hart_if.state.mstatus.TVM;
|
||||||
|
if(hart_if.PRIV == arch::PRIV_S & tvm != 0) {
|
||||||
|
hart_if.raise_trap(2, 0, hart_if.PC);
|
||||||
|
// hart_if.reg.trap_state = (1 << 31) | (2 << 16);
|
||||||
|
// hart_if.fault_data = hart_if.reg.PC;
|
||||||
|
return iss::Err;
|
||||||
|
}
|
||||||
|
satp = val;
|
||||||
|
update_vm_info();
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t virt2phys(iss::access_type access, uint64_t addr);
|
||||||
|
|
||||||
|
static inline vm_info decode_vm_info(uint32_t state, uint32_t sptbr) {
|
||||||
|
if(state == arch::PRIV_M)
|
||||||
|
return {0, 0, 0, 0};
|
||||||
|
if(state <= arch::PRIV_S)
|
||||||
|
switch(bit_sub<31, 1>(sptbr)) {
|
||||||
|
case 0:
|
||||||
|
return {0, 0, 0, 0}; // off
|
||||||
|
case 1:
|
||||||
|
return {2, 10, 4, bit_sub<0, 22>(sptbr) << PGSHIFT}; // SV32
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
abort();
|
||||||
|
return {0, 0, 0, 0}; // dummy
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline vm_info decode_vm_info(uint32_t state, uint64_t sptbr) {
|
||||||
|
if(state == arch::PRIV_M)
|
||||||
|
return {0, 0, 0, 0};
|
||||||
|
if(state <= arch::PRIV_S)
|
||||||
|
switch(bit_sub<60, 4>(sptbr)) {
|
||||||
|
case 0:
|
||||||
|
return {0, 0, 0, 0}; // off
|
||||||
|
case 8:
|
||||||
|
return {3, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV39
|
||||||
|
case 9:
|
||||||
|
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();
|
||||||
|
return {0, 0, 0, 0}; // dummy
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
reg_t satp;
|
||||||
|
absl::flat_hash_map<reg_t, uint64_t> ptw;
|
||||||
|
std::array<vm_info, 2> vmt;
|
||||||
|
std::array<address_type, 4> addr_mode;
|
||||||
|
|
||||||
|
arch::priv_if<WORD_TYPE> hart_if;
|
||||||
|
memory_if down_stream_mem;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename WORD_TYPE> uint64_t mmu<WORD_TYPE>::virt2phys(iss::access_type access, uint64_t addr) {
|
||||||
|
const auto type = access & iss::access_type::FUNC;
|
||||||
|
auto it = ptw.find(addr >> PGSHIFT);
|
||||||
|
if(it != ptw.end()) {
|
||||||
|
const reg_t pte = it->second;
|
||||||
|
const reg_t ad = PTE_A | (type == iss::access_type::WRITE) * PTE_D;
|
||||||
|
#ifdef RISCV_ENABLE_DIRTY
|
||||||
|
// set accessed and possibly dirty bits.
|
||||||
|
*(uint32_t*)ppte |= ad;
|
||||||
|
return {addr.getAccessType(), addr.space, (pte & (~PGMASK)) | (addr.val & PGMASK)};
|
||||||
|
#else
|
||||||
|
// take exception if access or possibly dirty bit is not set.
|
||||||
|
if((pte & ad) == ad)
|
||||||
|
return {(pte & (~PGMASK)) | (addr & PGMASK)};
|
||||||
|
else
|
||||||
|
ptw.erase(it); // throw an exception
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
uint32_t mode = type != iss::access_type::FETCH && hart_if.state.mstatus.MPRV ? // MPRV
|
||||||
|
hart_if.state.mstatus.MPP
|
||||||
|
: hart_if.PRIV;
|
||||||
|
|
||||||
|
const vm_info& vm = vmt[static_cast<uint16_t>(type) / 2];
|
||||||
|
|
||||||
|
const bool s_mode = mode == arch::PRIV_S;
|
||||||
|
const bool sum = hart_if.state.mstatus.SUM;
|
||||||
|
const bool mxr = hart_if.state.mstatus.MXR;
|
||||||
|
|
||||||
|
// verify bits xlen-1:va_bits-1 are all equal
|
||||||
|
const int va_bits = PGSHIFT + vm.levels * vm.idxbits;
|
||||||
|
const reg_t mask = (reg_t(1) << (sizeof(reg_t) * 8 - (va_bits - 1))) - 1;
|
||||||
|
const reg_t masked_msbs = (addr >> (va_bits - 1)) & mask;
|
||||||
|
const int levels = (masked_msbs != 0 && masked_msbs != mask) ? 0 : vm.levels;
|
||||||
|
|
||||||
|
reg_t base = vm.ptbase;
|
||||||
|
for(int i = levels - 1; i >= 0; i--) {
|
||||||
|
const int ptshift = i * vm.idxbits;
|
||||||
|
const reg_t idx = (addr >> (PGSHIFT + ptshift)) & ((1 << vm.idxbits) - 1);
|
||||||
|
|
||||||
|
// check that physical address of PTE is legal
|
||||||
|
reg_t pte = 0;
|
||||||
|
const uint8_t res = down_stream_mem.rd_mem(iss::access_type::READ, base + idx * vm.ptesize, vm.ptesize, (uint8_t*)&pte);
|
||||||
|
if(res != 0)
|
||||||
|
throw arch::trap_load_access_fault(addr);
|
||||||
|
const reg_t ppn = pte >> PTE_PPN_SHIFT;
|
||||||
|
|
||||||
|
if(PTE_TABLE(pte)) { // next level of page table
|
||||||
|
base = ppn << PGSHIFT;
|
||||||
|
} else if((pte & PTE_U) ? s_mode && (type == iss::access_type::FETCH || !sum) : !s_mode) {
|
||||||
|
break;
|
||||||
|
} else if(!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) {
|
||||||
|
break;
|
||||||
|
} else if(type == (type == iss::access_type::FETCH ? !(pte & PTE_X)
|
||||||
|
: type == iss::access_type::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X))
|
||||||
|
: !((pte & PTE_R) && (pte & PTE_W)))) {
|
||||||
|
break;
|
||||||
|
} else if((ppn & ((reg_t(1) << ptshift) - 1)) != 0) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
const reg_t ad = PTE_A | ((type == iss::access_type::WRITE) * PTE_D);
|
||||||
|
#ifdef RISCV_ENABLE_DIRTY
|
||||||
|
// set accessed and possibly dirty bits.
|
||||||
|
*(uint32_t*)ppte |= ad;
|
||||||
|
#else
|
||||||
|
// take exception if access or possibly dirty bit is not set.
|
||||||
|
if((pte & ad) != ad)
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
// for superpage mappings, make a fake leaf PTE for the TLB's benefit.
|
||||||
|
const reg_t vpn = addr >> PGSHIFT;
|
||||||
|
const reg_t value = (ppn | (vpn & ((reg_t(1) << ptshift) - 1))) << PGSHIFT;
|
||||||
|
const reg_t offset = addr & PGMASK;
|
||||||
|
ptw[vpn] = value | (pte & 0xff);
|
||||||
|
return value | offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch(type) {
|
||||||
|
case access_type::FETCH:
|
||||||
|
hart_if.raise_trap(12, 0, addr);
|
||||||
|
throw arch::trap_instruction_page_fault(addr);
|
||||||
|
case access_type::READ:
|
||||||
|
hart_if.raise_trap(13, 0, addr);
|
||||||
|
throw arch::trap_load_page_fault(addr);
|
||||||
|
case access_type::WRITE:
|
||||||
|
hart_if.raise_trap(15, 0, addr);
|
||||||
|
throw arch::trap_store_page_fault(addr);
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename WORD_TYPE> inline void mmu<WORD_TYPE>::update_vm_info() {
|
||||||
|
vmt[1] = decode_vm_info(hart_if.PRIV, satp);
|
||||||
|
addr_mode[3] = addr_mode[2] = vmt[1].is_active() ? iss::address_type::VIRTUAL : iss::address_type::PHYSICAL;
|
||||||
|
if(hart_if.state.mstatus.MPRV)
|
||||||
|
vmt[0] = decode_vm_info(hart_if.state.mstatus.MPP, satp);
|
||||||
|
else
|
||||||
|
vmt[0] = vmt[1];
|
||||||
|
addr_mode[1] = addr_mode[0] = vmt[0].is_active() ? iss::address_type::VIRTUAL : iss::address_type::PHYSICAL;
|
||||||
|
ptw.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mem
|
||||||
|
} // namespace iss
|
244
src/iss/mem/pmp.h
Normal file
244
src/iss/mem/pmp.h
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (C) 2025 MINRES Technologies GmbH
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* eyck@minres.com - initial implementation
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "memory_if.h"
|
||||||
|
#include "iss/arch/riscv_hart_common.h"
|
||||||
|
#include "iss/vm_types.h"
|
||||||
|
#include <util/logging.h>
|
||||||
|
|
||||||
|
namespace iss {
|
||||||
|
namespace mem {
|
||||||
|
struct clic_config {
|
||||||
|
uint64_t clic_base{0xc0000000};
|
||||||
|
unsigned clic_int_ctl_bits{4};
|
||||||
|
unsigned clic_num_irq{16};
|
||||||
|
unsigned clic_num_trigger{0};
|
||||||
|
bool nmode{false};
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void read_reg_with_offset(uint32_t reg, uint8_t offs, uint8_t* const data, unsigned length) {
|
||||||
|
auto reg_ptr = reinterpret_cast<uint8_t*>(®);
|
||||||
|
switch(offs) {
|
||||||
|
default:
|
||||||
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(data + i) = *(reg_ptr + i);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(data + i) = *(reg_ptr + 1 + i);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(data + i) = *(reg_ptr + 2 + i);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
*data = *(reg_ptr + 3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void write_reg_with_offset(uint32_t& reg, uint8_t offs, const uint8_t* const data, unsigned length) {
|
||||||
|
auto reg_ptr = reinterpret_cast<uint8_t*>(®);
|
||||||
|
switch(offs) {
|
||||||
|
default:
|
||||||
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(reg_ptr + i) = *(data + i);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(reg_ptr + 1 + i) = *(data + i);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
for(auto i = 0U; i < length; ++i)
|
||||||
|
*(reg_ptr + 2 + i) = *(data + i);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
*(reg_ptr + 3) = *data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename WORD_TYPE> struct pmp : public memory_elem {
|
||||||
|
using this_class = pmp<WORD_TYPE>;
|
||||||
|
using reg_t = WORD_TYPE;
|
||||||
|
constexpr static unsigned WORD_LEN = sizeof(WORD_TYPE) * 8;
|
||||||
|
|
||||||
|
pmp(arch::priv_if<WORD_TYPE> hart_if)
|
||||||
|
: hart_if(hart_if) {
|
||||||
|
for(size_t i = arch::pmpaddr0; i <= arch::pmpaddr15; ++i) {
|
||||||
|
hart_if.csr_rd_cb[i] = MK_CSR_RD_CB(read_plain);
|
||||||
|
hart_if.csr_wr_cb[i] = MK_CSR_WR_CB(write_plain);
|
||||||
|
}
|
||||||
|
for(size_t i = arch::pmpcfg0; i < arch::pmpcfg0 + 16 / sizeof(reg_t); ++i) {
|
||||||
|
hart_if.csr_rd_cb[i] = MK_CSR_RD_CB(read_plain);
|
||||||
|
hart_if.csr_wr_cb[i] = MK_CSR_WR_CB(write_pmpcfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~pmp() = default;
|
||||||
|
|
||||||
|
memory_if get_mem_if() override {
|
||||||
|
return memory_if{.rd_mem{util::delegate<rd_mem_func_sig>::from<this_class, &this_class::read_mem>(this)},
|
||||||
|
.wr_mem{util::delegate<wr_mem_func_sig>::from<this_class, &this_class::write_mem>(this)}};
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_next(memory_if mem) override { down_stream_mem = mem; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
iss::status read_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t* data) {
|
||||||
|
if(!pmp_check(access, addr, length) && !is_debug(access)) {
|
||||||
|
hart_if.fault_data = addr;
|
||||||
|
if(is_debug(access))
|
||||||
|
throw trap_access(0, addr);
|
||||||
|
hart_if.reg.trap_state = (1UL << 31) | ((access == access_type::FETCH ? 1 : 5) << 16); // issue trap 1
|
||||||
|
return iss::Err;
|
||||||
|
}
|
||||||
|
return down_stream_mem.rd_mem(access, addr, length, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t const* data) {
|
||||||
|
if(!pmp_check(access, addr, length) && !is_debug(access)) {
|
||||||
|
hart_if.fault_data = addr;
|
||||||
|
if(is_debug(access))
|
||||||
|
throw trap_access(0, addr);
|
||||||
|
hart_if.reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 1
|
||||||
|
return iss::Err;
|
||||||
|
}
|
||||||
|
return down_stream_mem.wr_mem(access, addr, length, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_plain(unsigned addr, reg_t& val) {
|
||||||
|
val = hart_if.csr[addr];
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_plain(unsigned addr, reg_t const& val) {
|
||||||
|
hart_if.csr[addr] = val;
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status write_pmpcfg(unsigned addr, reg_t val) {
|
||||||
|
hart_if.csr[addr] = val & 0x9f9f9f9f;
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pmp_check(const access_type type, const uint64_t addr, const unsigned len);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
arch::priv_if<WORD_TYPE> hart_if;
|
||||||
|
memory_if down_stream_mem;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename WORD_TYPE> bool pmp<WORD_TYPE>::pmp_check(const access_type type, const uint64_t addr, const unsigned len) {
|
||||||
|
constexpr auto PMP_SHIFT = 2U;
|
||||||
|
constexpr auto PMP_R = 0x1U;
|
||||||
|
constexpr auto PMP_W = 0x2U;
|
||||||
|
constexpr auto PMP_X = 0x4U;
|
||||||
|
constexpr auto PMP_A = 0x18U;
|
||||||
|
constexpr auto PMP_L = 0x80U;
|
||||||
|
constexpr auto PMP_TOR = 0x1U;
|
||||||
|
constexpr auto PMP_NA4 = 0x2U;
|
||||||
|
constexpr auto PMP_NAPOT = 0x3U;
|
||||||
|
reg_t base = 0;
|
||||||
|
auto any_active = false;
|
||||||
|
auto const cfg_reg_size = sizeof(reg_t);
|
||||||
|
for(size_t i = 0; i < 16; i++) {
|
||||||
|
reg_t tor = hart_if.csr[arch::pmpaddr0 + i] << PMP_SHIFT;
|
||||||
|
uint8_t cfg = hart_if.csr[arch::pmpcfg0 + (i / cfg_reg_size)] >> (i % cfg_reg_size);
|
||||||
|
if(cfg & PMP_A) {
|
||||||
|
any_active = true;
|
||||||
|
auto pmp_a = (cfg & PMP_A) >> 3;
|
||||||
|
auto is_tor = pmp_a == PMP_TOR;
|
||||||
|
auto is_na4 = pmp_a == PMP_NA4;
|
||||||
|
|
||||||
|
reg_t mask = (hart_if.csr[arch::pmpaddr0 + i] << 1) | (!is_na4);
|
||||||
|
mask = ~(mask & ~(mask + 1)) << PMP_SHIFT;
|
||||||
|
|
||||||
|
// Check each 4-byte sector of the access
|
||||||
|
auto any_match = false;
|
||||||
|
auto all_match = true;
|
||||||
|
for(reg_t offset = 0; offset < len; offset += 1 << PMP_SHIFT) {
|
||||||
|
reg_t cur_addr = addr + offset;
|
||||||
|
auto napot_match = ((cur_addr ^ tor) & mask) == 0;
|
||||||
|
auto tor_match = base <= (cur_addr + len - 1) && cur_addr < tor;
|
||||||
|
auto match = is_tor ? tor_match : napot_match;
|
||||||
|
any_match |= match;
|
||||||
|
all_match &= match;
|
||||||
|
}
|
||||||
|
if(any_match) {
|
||||||
|
// If the PMP matches only a strict subset of the access, fail it
|
||||||
|
if(!all_match)
|
||||||
|
return false;
|
||||||
|
return (hart_if.reg.PRIV == arch::PRIV_M && !(cfg & PMP_L)) || (type == access_type::READ && (cfg & PMP_R)) ||
|
||||||
|
(type == access_type::WRITE && (cfg & PMP_W)) || (type == access_type::FETCH && (cfg & PMP_X));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base = tor;
|
||||||
|
}
|
||||||
|
// constexpr auto pmp_num_regs = 16;
|
||||||
|
// reg_t tor_base = 0;
|
||||||
|
// auto any_active = false;
|
||||||
|
// auto lower_addr = addr >>2;
|
||||||
|
// auto upper_addr = (addr+len-1)>>2;
|
||||||
|
// for (size_t i = 0; i < pmp_num_regs; i++) {
|
||||||
|
// uint8_t cfg = csr[pmpcfg0+(i/4)]>>(i%4);
|
||||||
|
// uint8_t cfg_next = i==(pmp_num_regs-1)? 0 : csr[pmpcfg0+((i+1)/4)]>>((i+1)%4);
|
||||||
|
// auto pmpaddr = csr[pmpaddr0+i];
|
||||||
|
// if (cfg & PMP_A) {
|
||||||
|
// any_active=true;
|
||||||
|
// auto is_tor = bit_sub<3, 2>(cfg) == PMP_TOR;
|
||||||
|
// auto is_napot = bit_sub<4, 1>(cfg) && bit_sub<3, 2>(cfg_next)!= PMP_TOR;
|
||||||
|
// if(is_napot) {
|
||||||
|
// reg_t mask = bit_sub<3, 1>(cfg)?~( pmpaddr & ~(pmpaddr + 1)): 0x3fffffff;
|
||||||
|
// auto mpmpaddr = pmpaddr & mask;
|
||||||
|
// if((lower_addr&mask) == mpmpaddr && (upper_addr&mask)==mpmpaddr)
|
||||||
|
// return (hart_if.reg.PRIV == PRIV_M && !(cfg & PMP_L)) ||
|
||||||
|
// (type == access_type::READ && (cfg & PMP_R)) ||
|
||||||
|
// (type == access_type::WRITE && (cfg & PMP_W)) ||
|
||||||
|
// (type == access_type::FETCH && (cfg & PMP_X));
|
||||||
|
// } else if(is_tor) {
|
||||||
|
// if(lower_addr>=tor_base && upper_addr<=pmpaddr)
|
||||||
|
// return (hart_if.reg.PRIV == PRIV_M && !(cfg & PMP_L)) ||
|
||||||
|
// (type == access_type::READ && (cfg & PMP_R)) ||
|
||||||
|
// (type == access_type::WRITE && (cfg & PMP_W)) ||
|
||||||
|
// (type == access_type::FETCH && (cfg & PMP_X));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// tor_base = pmpaddr;
|
||||||
|
// }
|
||||||
|
return !any_active || hart_if.reg.PRIV == arch::PRIV_M;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mem
|
||||||
|
} // namespace iss
|
@ -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);
|
||||||
@ -62,7 +61,7 @@ bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if&
|
|||||||
try {
|
try {
|
||||||
auto root = YAML::LoadAll(is);
|
auto root = YAML::LoadAll(is);
|
||||||
if(root.size() != 1) {
|
if(root.size() != 1) {
|
||||||
LOG(ERR) << "Too many root nodes in YAML file " << config_file_name;
|
CPPLOG(ERR) << "Too many root nodes in YAML file " << config_file_name;
|
||||||
}
|
}
|
||||||
for(auto p : root[0]) {
|
for(auto p : root[0]) {
|
||||||
auto isa_subset = p.first;
|
auto isa_subset = p.first;
|
||||||
@ -88,11 +87,11 @@ bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(YAML::ParserException& e) {
|
} catch(YAML::ParserException& e) {
|
||||||
LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what();
|
CPPLOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG(ERR) << "Could not open input file " << config_file_name;
|
CPPLOG(ERR) << "Could not open input file " << config_file_name;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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_ */
|
||||||
|
@ -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) {
|
||||||
@ -47,7 +47,7 @@ iss::plugin::instruction_count::instruction_count(std::string config_file_name)
|
|||||||
try {
|
try {
|
||||||
auto root = YAML::LoadAll(is);
|
auto root = YAML::LoadAll(is);
|
||||||
if(root.size() != 1) {
|
if(root.size() != 1) {
|
||||||
LOG(ERR) << "Too many rro nodes in YAML file " << config_file_name;
|
CPPLOG(ERR) << "Too many rro nodes in YAML file " << config_file_name;
|
||||||
}
|
}
|
||||||
for(auto p : root[0]) {
|
for(auto p : root[0]) {
|
||||||
auto isa_subset = p.first;
|
auto isa_subset = p.first;
|
||||||
@ -69,10 +69,10 @@ iss::plugin::instruction_count::instruction_count(std::string config_file_name)
|
|||||||
}
|
}
|
||||||
rep_counts.resize(delays.size());
|
rep_counts.resize(delays.size());
|
||||||
} catch(YAML::ParserException& e) {
|
} catch(YAML::ParserException& e) {
|
||||||
LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what();
|
CPPLOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG(ERR) << "Could not open input file " << config_file_name;
|
CPPLOG(ERR) << "Could not open input file " << config_file_name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,17 +81,16 @@ iss::plugin::instruction_count::~instruction_count() {
|
|||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
for(auto it : delays) {
|
for(auto it : delays) {
|
||||||
if(rep_counts[idx] > 0 && it.instr_name.find("__" != 0))
|
if(rep_counts[idx] > 0 && it.instr_name.find("__" != 0))
|
||||||
LOG(INFO)<<it.instr_name<<";"<<rep_counts[idx];
|
CPPLOG(INFO) << it.instr_name << ";" << rep_counts[idx];
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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]++;
|
|
||||||
}
|
|
||||||
|
@ -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_ */
|
||||||
|
331
src/iss/semihosting/semihosting.cpp
Normal file
331
src/iss/semihosting/semihosting.cpp
Normal file
@ -0,0 +1,331 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (C) 2025 MINRES Technologies GmbH
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* eyck@minres.com - initial implementation
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "semihosting.h"
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iss/vm_types.h>
|
||||||
|
#include <map>
|
||||||
|
#include <stdexcept>
|
||||||
|
// explanation of syscalls can be found at https://github.com/SpinalHDL/openocd_riscv/blob/riscv_spinal/src/target/semihosting_common.h
|
||||||
|
|
||||||
|
const char* SYS_OPEN_MODES_STRS[] = {"r", "rb", "r+", "r+b", "w", "wb", "w+", "w+b", "a", "ab", "a+", "a+b"};
|
||||||
|
|
||||||
|
template <typename T> T sh_read_field(iss::arch_if* arch_if_ptr, T addr, int len = 4) {
|
||||||
|
uint8_t bytes[4];
|
||||||
|
auto res = arch_if_ptr->read(iss::address_type::PHYSICAL, iss::access_type::DEBUG_READ, 0, addr, 4, &bytes[0]);
|
||||||
|
// auto res = arch_if_ptr->read(iss::address_type::PHYSICAL, iss::access_type::DEBUG_READ, 0, *parameter, 1, &character);
|
||||||
|
|
||||||
|
if(res != iss::Ok) {
|
||||||
|
return 0; // TODO THROW ERROR
|
||||||
|
} else
|
||||||
|
return static_cast<T>(bytes[0]) | (static_cast<T>(bytes[1]) << 8) | (static_cast<T>(bytes[2]) << 16) |
|
||||||
|
(static_cast<T>(bytes[3]) << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> std::string sh_read_string(iss::arch_if* arch_if_ptr, T addr, T str_len) {
|
||||||
|
std::vector<uint8_t> buffer(str_len);
|
||||||
|
for(int i = 0; i < str_len; i++) {
|
||||||
|
buffer[i] = sh_read_field(arch_if_ptr, addr + i, 1);
|
||||||
|
}
|
||||||
|
std::string str(buffer.begin(), buffer.end());
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> void semihosting_callback<T>::operator()(iss::arch_if* arch_if_ptr, T* call_number, T* parameter) {
|
||||||
|
static std::map<T, FILE*> openFiles;
|
||||||
|
static T file_count = 3;
|
||||||
|
static T semihostingErrno;
|
||||||
|
|
||||||
|
switch(static_cast<semihosting_syscalls>(*call_number)) {
|
||||||
|
case semihosting_syscalls::SYS_CLOCK: {
|
||||||
|
auto end = std::chrono::high_resolution_clock::now(); // end measurement
|
||||||
|
auto elapsed = end - timeVar;
|
||||||
|
auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
|
||||||
|
*call_number = millis; // TODO get time now
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_CLOSE: {
|
||||||
|
T file_handle = *parameter;
|
||||||
|
if(openFiles.size() <= file_handle && file_handle < 0) {
|
||||||
|
semihostingErrno = EBADF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto file = openFiles[file_handle];
|
||||||
|
openFiles.erase(file_handle);
|
||||||
|
if(!(file == stdin || file == stdout || file == stderr)) {
|
||||||
|
int i = fclose(file);
|
||||||
|
*call_number = i;
|
||||||
|
} else {
|
||||||
|
*call_number = -1;
|
||||||
|
semihostingErrno = EINTR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_ELAPSED: {
|
||||||
|
throw std::runtime_error("Semihosting Call not Implemented");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_ERRNO: {
|
||||||
|
*call_number = semihostingErrno;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_EXIT: {
|
||||||
|
|
||||||
|
throw std::runtime_error("ISS terminated by Semihost: SYS_EXIT");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_EXIT_EXTENDED: {
|
||||||
|
throw std::runtime_error("ISS terminated by Semihost: SYS_EXIT_EXTENDED");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_FLEN: {
|
||||||
|
T file_handle = *parameter;
|
||||||
|
auto file = openFiles[file_handle];
|
||||||
|
|
||||||
|
size_t currentPos = ftell(file);
|
||||||
|
if(currentPos < 0)
|
||||||
|
throw std::runtime_error("SYS_FLEN negative value");
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
size_t length = ftell(file);
|
||||||
|
fseek(file, currentPos, SEEK_SET);
|
||||||
|
*call_number = (T)length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_GET_CMDLINE: {
|
||||||
|
throw std::runtime_error("Semihosting Call not Implemented");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_HEAPINFO: {
|
||||||
|
throw std::runtime_error("Semihosting Call not Implemented");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_ISERROR: {
|
||||||
|
T value = *parameter;
|
||||||
|
*call_number = (value != 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_ISTTY: {
|
||||||
|
T file_handle = *parameter;
|
||||||
|
*call_number = (file_handle == 0 || file_handle == 1 || file_handle == 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_OPEN: {
|
||||||
|
T path_str_addr = sh_read_field<T>(arch_if_ptr, *parameter);
|
||||||
|
T mode = sh_read_field<T>(arch_if_ptr, 4 + (*parameter));
|
||||||
|
T path_len = sh_read_field<T>(arch_if_ptr, 8 + (*parameter));
|
||||||
|
|
||||||
|
std::string path_str = sh_read_string<T>(arch_if_ptr, path_str_addr, path_len);
|
||||||
|
|
||||||
|
// TODO LOG INFO
|
||||||
|
|
||||||
|
if(mode >= 12) {
|
||||||
|
// TODO throw ERROR
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* file = nullptr;
|
||||||
|
if(path_str == ":tt") {
|
||||||
|
if(mode < 4)
|
||||||
|
file = stdin;
|
||||||
|
else if(mode < 8)
|
||||||
|
file = stdout;
|
||||||
|
else
|
||||||
|
file = stderr;
|
||||||
|
} else {
|
||||||
|
file = fopen(path_str.c_str(), SYS_OPEN_MODES_STRS[mode]);
|
||||||
|
if(file == nullptr) {
|
||||||
|
// TODO throw error
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
T file_handle = file_count++;
|
||||||
|
openFiles[file_handle] = file;
|
||||||
|
*call_number = file_handle;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_READ: {
|
||||||
|
T file_handle = sh_read_field<T>(arch_if_ptr, (*parameter) + 4);
|
||||||
|
T addr = sh_read_field<T>(arch_if_ptr, *parameter);
|
||||||
|
T count = sh_read_field<T>(arch_if_ptr, (*parameter) + 8);
|
||||||
|
|
||||||
|
auto file = openFiles[file_handle];
|
||||||
|
|
||||||
|
std::vector<uint8_t> buffer(count);
|
||||||
|
size_t num_read = 0;
|
||||||
|
if(file == stdin) {
|
||||||
|
// when reading from stdin: mimic behaviour from read syscall
|
||||||
|
// and return on newline.
|
||||||
|
while(num_read < count) {
|
||||||
|
char c = fgetc(file);
|
||||||
|
buffer[num_read] = c;
|
||||||
|
num_read++;
|
||||||
|
if(c == '\n')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
num_read = fread(buffer.data(), 1, count, file);
|
||||||
|
}
|
||||||
|
buffer.resize(num_read);
|
||||||
|
for(int i = 0; i < num_read; i++) {
|
||||||
|
auto res = arch_if_ptr->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_READ, 0, addr + i, 1, &buffer[i]);
|
||||||
|
if(res != iss::Ok)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*call_number = count - num_read;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_READC: {
|
||||||
|
uint8_t character = getchar();
|
||||||
|
// character = getchar();
|
||||||
|
/*if(character != iss::Ok)
|
||||||
|
std::cout << "Not OK";
|
||||||
|
return;*/
|
||||||
|
*call_number = character;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_REMOVE: {
|
||||||
|
T path_str_addr = sh_read_field<T>(arch_if_ptr, *parameter);
|
||||||
|
T path_len = sh_read_field<T>(arch_if_ptr, (*parameter) + 4);
|
||||||
|
std::string path_str = sh_read_string<T>(arch_if_ptr, path_str_addr, path_len);
|
||||||
|
|
||||||
|
if(remove(path_str.c_str()) < 0)
|
||||||
|
*call_number = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_RENAME: {
|
||||||
|
T path_str_addr_old = sh_read_field<T>(arch_if_ptr, *parameter);
|
||||||
|
T path_len_old = sh_read_field<T>(arch_if_ptr, (*parameter) + 4);
|
||||||
|
T path_str_addr_new = sh_read_field<T>(arch_if_ptr, (*parameter) + 8);
|
||||||
|
T path_len_new = sh_read_field<T>(arch_if_ptr, (*parameter) + 12);
|
||||||
|
|
||||||
|
std::string path_str_old = sh_read_string<T>(arch_if_ptr, path_str_addr_old, path_len_old);
|
||||||
|
std::string path_str_new = sh_read_string<T>(arch_if_ptr, path_str_addr_new, path_len_new);
|
||||||
|
rename(path_str_old.c_str(), path_str_new.c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_SEEK: {
|
||||||
|
T file_handle = sh_read_field<T>(arch_if_ptr, *parameter);
|
||||||
|
T pos = sh_read_field<T>(arch_if_ptr, (*parameter) + 1);
|
||||||
|
auto file = openFiles[file_handle];
|
||||||
|
|
||||||
|
int retval = fseek(file, pos, SEEK_SET);
|
||||||
|
if(retval < 0)
|
||||||
|
throw std::runtime_error("SYS_SEEK negative return value");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_SYSTEM: {
|
||||||
|
T cmd_addr = sh_read_field<T>(arch_if_ptr, *parameter);
|
||||||
|
T cmd_len = sh_read_field<T>(arch_if_ptr, (*parameter) + 1);
|
||||||
|
std::string cmd = sh_read_string<T>(arch_if_ptr, cmd_addr, cmd_len);
|
||||||
|
system(cmd.c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_TICKFREQ: {
|
||||||
|
throw std::runtime_error("Semihosting Call not Implemented");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_TIME: {
|
||||||
|
// returns time in seconds scince 01.01.1970 00:00
|
||||||
|
*call_number = time(NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_TMPNAM: {
|
||||||
|
T buffer_addr = sh_read_field<T>(arch_if_ptr, *parameter);
|
||||||
|
T identifier = sh_read_field<T>(arch_if_ptr, (*parameter) + 1);
|
||||||
|
T buffer_len = sh_read_field<T>(arch_if_ptr, (*parameter) + 2);
|
||||||
|
|
||||||
|
if(identifier > 255) {
|
||||||
|
*call_number = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "tmp/file-" << std::setfill('0') << std::setw(3) << identifier;
|
||||||
|
std::string filename = ss.str();
|
||||||
|
|
||||||
|
for(int i = 0; i < buffer_len; i++) {
|
||||||
|
uint8_t character = filename[i];
|
||||||
|
auto res = arch_if_ptr->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_READ, 0, (*parameter) + i, 1, &character);
|
||||||
|
if(res != iss::Ok)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_WRITE: {
|
||||||
|
T file_handle = sh_read_field<T>(arch_if_ptr, (*parameter) + 4);
|
||||||
|
T addr = sh_read_field<T>(arch_if_ptr, *parameter);
|
||||||
|
T count = sh_read_field<T>(arch_if_ptr, (*parameter) + 8);
|
||||||
|
|
||||||
|
auto file = openFiles[file_handle];
|
||||||
|
std::string str = sh_read_string<T>(arch_if_ptr, addr, count);
|
||||||
|
fwrite(&str[0], 1, count, file);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_WRITEC: {
|
||||||
|
uint8_t character;
|
||||||
|
auto res = arch_if_ptr->read(iss::address_type::PHYSICAL, iss::access_type::DEBUG_READ, 0, *parameter, 1, &character);
|
||||||
|
if(res != iss::Ok)
|
||||||
|
return;
|
||||||
|
putchar(character);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::SYS_WRITE0: {
|
||||||
|
uint8_t character;
|
||||||
|
while(1) {
|
||||||
|
auto res = arch_if_ptr->read(iss::address_type::PHYSICAL, iss::access_type::DEBUG_READ, 0, *parameter, 1, &character);
|
||||||
|
if(res != iss::Ok)
|
||||||
|
return;
|
||||||
|
if(character == 0)
|
||||||
|
break;
|
||||||
|
putchar(character);
|
||||||
|
(*parameter)++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::USER_CMD_0x100: {
|
||||||
|
throw std::runtime_error("Semihosting Call not Implemented");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case semihosting_syscalls::USER_CMD_0x1FF: {
|
||||||
|
throw std::runtime_error("Semihosting Call not Implemented");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("Semihosting Call not Implemented");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template class semihosting_callback<uint32_t>;
|
||||||
|
template class semihosting_callback<uint64_t>;
|
95
src/iss/semihosting/semihosting.h
Normal file
95
src/iss/semihosting/semihosting.h
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (C) 2025 MINRES Technologies GmbH
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* eyck@minres.com - initial implementation
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _SEMIHOSTING_H_
|
||||||
|
#define _SEMIHOSTING_H_
|
||||||
|
#include <chrono>
|
||||||
|
#include <functional>
|
||||||
|
#include <iss/arch_if.h>
|
||||||
|
/*
|
||||||
|
* According to:
|
||||||
|
* "Semihosting for AArch32 and AArch64, Release 2.0"
|
||||||
|
* https://static.docs.arm.com/100863/0200/semihosting.pdf
|
||||||
|
* from ARM Ltd.
|
||||||
|
*
|
||||||
|
* The available semihosting operation numbers passed in A0 are allocated
|
||||||
|
* as follows:
|
||||||
|
* - 0x00-0x31 Used by ARM.
|
||||||
|
* - 0x32-0xFF Reserved for future use by ARM.
|
||||||
|
* - 0x100-0x1FF Reserved for user applications. These are not used by ARM.
|
||||||
|
* However, if you are writing your own SVC operations, you are advised
|
||||||
|
* to use a different SVC number rather than using the semihosted
|
||||||
|
* SVC number and these operation type numbers.
|
||||||
|
* - 0x200-0xFFFFFFFF Undefined and currently unused. It is recommended
|
||||||
|
* that you do not use these.
|
||||||
|
*/
|
||||||
|
enum class semihosting_syscalls {
|
||||||
|
|
||||||
|
SYS_OPEN = 0x01,
|
||||||
|
SYS_CLOSE = 0x02,
|
||||||
|
SYS_WRITEC = 0x03,
|
||||||
|
SYS_WRITE0 = 0x04,
|
||||||
|
SYS_WRITE = 0x05,
|
||||||
|
SYS_READ = 0x06,
|
||||||
|
SYS_READC = 0x07,
|
||||||
|
SYS_ISERROR = 0x08,
|
||||||
|
SYS_ISTTY = 0x09,
|
||||||
|
SYS_SEEK = 0x0A,
|
||||||
|
SYS_FLEN = 0x0C,
|
||||||
|
SYS_TMPNAM = 0x0D,
|
||||||
|
SYS_REMOVE = 0x0E,
|
||||||
|
SYS_RENAME = 0x0F,
|
||||||
|
SYS_CLOCK = 0x10,
|
||||||
|
SYS_TIME = 0x11,
|
||||||
|
SYS_SYSTEM = 0x12,
|
||||||
|
SYS_ERRNO = 0x13,
|
||||||
|
SYS_GET_CMDLINE = 0x15,
|
||||||
|
SYS_HEAPINFO = 0x16,
|
||||||
|
SYS_EXIT = 0x18,
|
||||||
|
SYS_EXIT_EXTENDED = 0x20,
|
||||||
|
SYS_ELAPSED = 0x30,
|
||||||
|
SYS_TICKFREQ = 0x31,
|
||||||
|
USER_CMD_0x100 = 0x100,
|
||||||
|
USER_CMD_0x1FF = 0x1FF,
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T> struct semihosting_callback {
|
||||||
|
std::chrono::high_resolution_clock::time_point timeVar;
|
||||||
|
semihosting_callback()
|
||||||
|
: timeVar(std::chrono::high_resolution_clock::now()) {}
|
||||||
|
void operator()(iss::arch_if* arch_if_ptr, T* call_number, T* parameter);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T> using semihosting_cb_t = std::function<void(iss::arch_if*, T*, T*)>;
|
||||||
|
#endif
|
97
src/main.cpp
97
src/main.cpp
@ -30,20 +30,25 @@
|
|||||||
*
|
*
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <vector>
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
#include <iss/factory.h>
|
#include <iss/factory.h>
|
||||||
|
#include <iss/semihosting/semihosting.h>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "iss/arch/tgc_mapper.h"
|
||||||
|
#include "util/logging.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
|
||||||
@ -52,7 +57,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
/*
|
/*
|
||||||
* Define and parse the program options
|
* Define and parse the program options
|
||||||
@ -66,13 +70,14 @@ int main(int argc, char *argv[]) {
|
|||||||
("logfile,l", po::value<std::string>(), "Sets default log file.")
|
("logfile,l", po::value<std::string>(), "Sets default log file.")
|
||||||
("disass,d", po::value<std::string>()->implicit_value(""), "Enables disassembly")
|
("disass,d", po::value<std::string>()->implicit_value(""), "Enables disassembly")
|
||||||
("gdb-port,g", po::value<unsigned>()->default_value(0), "enable gdb server and specify port to use")
|
("gdb-port,g", po::value<unsigned>()->default_value(0), "enable gdb server and specify port to use")
|
||||||
("instructions,i", po::value<uint64_t>()->default_value(std::numeric_limits<uint64_t>::max()), "max. number of instructions to simulate")
|
("ilimit,i", po::value<uint64_t>()->default_value(std::numeric_limits<uint64_t>::max()), "max. number of instructions to simulate")
|
||||||
|
("flimit", po::value<uint64_t>()->default_value(std::numeric_limits<uint64_t>::max()), "max. number of fetches to simulate")
|
||||||
("reset,r", po::value<std::string>(), "reset address")
|
("reset,r", po::value<std::string>(), "reset address")
|
||||||
("dump-ir", "dump the intermediate representation")
|
("dump-ir", "dump the intermediate representation")
|
||||||
("elf,f", po::value<std::vector<std::string>>(), "ELF file(s) to load")
|
("elf,f", po::value<std::vector<std::string>>(), "ELF file(s) to load")
|
||||||
("mem,m", po::value<std::string>(), "the memory input file")
|
("mem,m", po::value<std::string>(), "the memory input file")
|
||||||
("plugin,p", po::value<std::vector<std::string>>(), "plugin to activate")
|
("plugin,p", po::value<std::vector<std::string>>(), "plugin to activate")
|
||||||
("backend", po::value<std::string>()->default_value("interp"), "the ISS backend to use, options are: interp, tcc")
|
("backend", po::value<std::string>()->default_value("interp"), "the ISS backend to use, options are: interp, llvm, tcc, asmjit")
|
||||||
("isa", po::value<std::string>()->default_value("tgc5c"), "core or isa name to use for simulation, use '?' to get list");
|
("isa", po::value<std::string>()->default_value("tgc5c"), "core or isa name to use for simulation, use '?' to get list");
|
||||||
// clang-format on
|
// clang-format on
|
||||||
auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
|
auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
|
||||||
@ -116,6 +121,8 @@ int main(int argc, char *argv[]) {
|
|||||||
// instantiate the simulator
|
// instantiate the simulator
|
||||||
iss::vm_ptr vm{nullptr};
|
iss::vm_ptr vm{nullptr};
|
||||||
iss::cpu_ptr cpu{nullptr};
|
iss::cpu_ptr cpu{nullptr};
|
||||||
|
semihosting_callback<uint32_t> cb{};
|
||||||
|
semihosting_cb_t<uint32_t> semihosting_cb = [&cb](iss::arch_if* i, uint32_t* a0, uint32_t* a1) { cb(i, a0, a1); };
|
||||||
std::string isa_opt(clim["isa"].as<std::string>());
|
std::string isa_opt(clim["isa"].as<std::string>());
|
||||||
if(isa_opt.size() == 0 || isa_opt == "?") {
|
if(isa_opt.size() == 0 || isa_opt == "?") {
|
||||||
auto list = f.get_names();
|
auto list = f.get_names();
|
||||||
@ -123,7 +130,8 @@ int main(int argc, char *argv[]) {
|
|||||||
std::cout << "Available implementations (core|platform|backend):\n - " << util::join(list, "\n - ") << std::endl;
|
std::cout << "Available implementations (core|platform|backend):\n - " << util::join(list, "\n - ") << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
} else if(isa_opt.find('|') != std::string::npos) {
|
} else if(isa_opt.find('|') != std::string::npos) {
|
||||||
std::tie(cpu, vm) = f.create(isa_opt+"|"+clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
|
std::tie(cpu, vm) =
|
||||||
|
f.create(isa_opt + "|" + clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>(), &semihosting_cb);
|
||||||
} else {
|
} else {
|
||||||
auto base_isa = isa_opt.substr(0, 5);
|
auto base_isa = isa_opt.substr(0, 5);
|
||||||
if(base_isa == "tgc5d" || base_isa == "tgc5e") {
|
if(base_isa == "tgc5d" || base_isa == "tgc5e") {
|
||||||
@ -131,14 +139,17 @@ int main(int argc, char *argv[]) {
|
|||||||
} else {
|
} else {
|
||||||
isa_opt += "|m_p|" + clim["backend"].as<std::string>();
|
isa_opt += "|m_p|" + clim["backend"].as<std::string>();
|
||||||
}
|
}
|
||||||
std::tie(cpu, vm) = f.create(isa_opt, clim["gdb-port"].as<unsigned>());
|
std::tie(cpu, vm) = f.create(isa_opt, clim["gdb-port"].as<unsigned>(), &semihosting_cb);
|
||||||
}
|
}
|
||||||
if(!cpu) {
|
if(!cpu) {
|
||||||
LOG(ERR) << "Could not create cpu for isa " << isa_opt << " and backend " <<clim["backend"].as<std::string>()<< std::endl;
|
auto list = f.get_names();
|
||||||
|
std::sort(std::begin(list), std::end(list));
|
||||||
|
CPPLOG(ERR) << "Could not create cpu for isa " << isa_opt << " and backend " << clim["backend"].as<std::string>() << "\n"
|
||||||
|
<< "Available implementations (core|platform|backend):\n - " << util::join(list, "\n - ") << std::endl;
|
||||||
return 127;
|
return 127;
|
||||||
}
|
}
|
||||||
if(!vm) {
|
if(!vm) {
|
||||||
LOG(ERR) << "Could not create vm for isa " << isa_opt << " and backend " <<clim["backend"].as<std::string>()<< std::endl;
|
CPPLOG(ERR) << "Could not create vm for isa " << isa_opt << " and backend " << clim["backend"].as<std::string>() << std::endl;
|
||||||
return 127;
|
return 127;
|
||||||
}
|
}
|
||||||
if(clim.count("plugin")) {
|
if(clim.count("plugin")) {
|
||||||
@ -174,7 +185,7 @@ int main(int argc, char *argv[]) {
|
|||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
LOG(ERR) << "Unknown plugin name: " << plugin_name << ", valid names are 'ce', 'ic'" << std::endl;
|
CPPLOG(ERR) << "Unknown plugin name: " << plugin_name << ", valid names are 'ce', 'ic'" << std::endl;
|
||||||
return 127;
|
return 127;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -196,25 +207,73 @@ 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;
|
||||||
|
else {
|
||||||
|
LOG(ERR) << "Error occured while loading file " << input << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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;
|
||||||
|
else {
|
||||||
|
LOG(ERR) << "Error occured while loading file " << input << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(clim.count("reset")) {
|
if(clim.count("reset")) {
|
||||||
auto str = clim["reset"].as<std::string>();
|
auto str = clim["reset"].as<std::string>();
|
||||||
start_address = str.find("0x") == 0 ? std::stoull(str.substr(2), nullptr, 16) : std::stoull(str, nullptr, 10);
|
start_address = str.find("0x") == 0 ? std::stoull(str.substr(2), nullptr, 16) : std::stoull(str, nullptr, 10);
|
||||||
}
|
}
|
||||||
vm->reset(start_address);
|
vm->reset(start_address);
|
||||||
auto cycles = clim["instructions"].as<uint64_t>();
|
auto limit = clim["ilimit"].as<uint64_t>();
|
||||||
res = vm->start(cycles, dump);
|
auto cond = iss::finish_cond_e::JUMP_TO_SELF;
|
||||||
|
if(clim.count("flimit")) {
|
||||||
|
cond = cond | iss::finish_cond_e::FCOUNT_LIMIT;
|
||||||
|
limit = clim["flimit"].as<uint64_t>();
|
||||||
|
} else {
|
||||||
|
cond = cond | iss::finish_cond_e::ICOUNT_LIMIT;
|
||||||
|
}
|
||||||
|
res = vm->start(limit, dump, cond);
|
||||||
|
|
||||||
|
auto instr_if = vm->get_arch()->get_instrumentation_if();
|
||||||
|
// this assumes a single input file
|
||||||
|
std::unordered_map<std::string, uint64_t> sym_table;
|
||||||
|
if(args.empty())
|
||||||
|
sym_table = instr_if->get_symbol_table(clim["elf"].as<std::vector<std::string>>()[0]);
|
||||||
|
else
|
||||||
|
sym_table = instr_if->get_symbol_table(args[0]);
|
||||||
|
if(sym_table.find("begin_signature") != std::end(sym_table) && sym_table.find("end_signature") != std::end(sym_table)) {
|
||||||
|
auto start_addr = sym_table["begin_signature"];
|
||||||
|
auto end_addr = sym_table["end_signature"];
|
||||||
|
std::array<uint8_t, 4> data;
|
||||||
|
std::ofstream file;
|
||||||
|
std::string filename = fmt::format("{}.signature", isa_opt);
|
||||||
|
std::replace(std::begin(filename), std::end(filename), '|', '_');
|
||||||
|
// default riscof requires this filename
|
||||||
|
filename = "DUT-tgc.signature";
|
||||||
|
file.open(filename, std::ios::out);
|
||||||
|
if(!file.is_open()) {
|
||||||
|
LOG(ERR) << "Error opening file " << filename << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
LOGGER(DEFAULT)::reporting_level() = logging::ERR;
|
||||||
|
for(auto addr = start_addr; addr < end_addr; addr += data.size()) {
|
||||||
|
vm->get_arch()->read(iss::address_type::PHYSICAL, iss::access_type::DEBUG_READ, 0 /*MEM*/, addr, data.size(),
|
||||||
|
data.data()); // FIXME: get space from iss::arch::traits<ARCH>::mem_type_e::MEM
|
||||||
|
|
||||||
|
// TODO : obey Target endianess
|
||||||
|
uint32_t to_print = (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0];
|
||||||
|
file << std::hex << fmt::format("{:08x}", to_print) << std::dec << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
LOG(ERR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit"
|
CPPLOG(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 if needed
|
||||||
for(auto* p : plugin_list) {
|
for(auto* p : plugin_list) {
|
||||||
delete p;
|
delete p;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
|
* Copyright (C) 2017 - 2025 MINRES Technologies GmbH
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -42,7 +42,6 @@
|
|||||||
#include <iss/plugin/loader.h>
|
#include <iss/plugin/loader.h>
|
||||||
#endif
|
#endif
|
||||||
#include "sc_core_adapter_if.h"
|
#include "sc_core_adapter_if.h"
|
||||||
#include <iss/arch/tgc_mapper.h>
|
|
||||||
#include <scc/report.h>
|
#include <scc/report.h>
|
||||||
#include <util/ities.h>
|
#include <util/ities.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -56,7 +55,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 +88,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 +124,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_if* 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,16 +170,17 @@ 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_if* const owner;
|
||||||
vm_ptr vm{nullptr};
|
vm_ptr vm{nullptr};
|
||||||
sc_cpu_ptr cpu{nullptr};
|
sc_cpu_ptr cpu{nullptr};
|
||||||
iss::debugger::target_adapter_if* tgt_adapter{nullptr};
|
iss::debugger::target_adapter_if* tgt_adapter{nullptr};
|
||||||
@ -193,19 +196,18 @@ struct core_trace {
|
|||||||
scv_tr_handle tr_handle;
|
scv_tr_handle tr_handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
SC_HAS_PROCESS(core_complex);// NOLINT
|
|
||||||
#ifndef CWR_SYSTEMC
|
#ifndef CWR_SYSTEMC
|
||||||
core_complex::core_complex(sc_module_name const& name)
|
template <unsigned int BUSWIDTH>
|
||||||
|
core_complex<BUSWIDTH>::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
|
||||||
|
|
||||||
void core_complex::init(){
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::init() {
|
||||||
trc = new core_trace();
|
trc = new core_trace();
|
||||||
ibus.register_invalidate_direct_mem_ptr([=](uint64_t start, uint64_t end) -> void {
|
ibus.register_invalidate_direct_mem_ptr([=](uint64_t start, uint64_t end) -> void {
|
||||||
auto lut_entry = fetch_lut.getEntry(start);
|
auto lut_entry = fetch_lut.getEntry(start);
|
||||||
@ -224,6 +226,7 @@ void core_complex::init(){
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
SC_HAS_PROCESS(core_complex<BUSWIDTH>); // NOLINT
|
||||||
SC_THREAD(run);
|
SC_THREAD(run);
|
||||||
SC_METHOD(rst_cb);
|
SC_METHOD(rst_cb);
|
||||||
sensitive << rst_i;
|
sensitive << rst_i;
|
||||||
@ -249,16 +252,16 @@ void core_complex::init(){
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
core_complex::~core_complex(){
|
template <unsigned int BUSWIDTH> core_complex<BUSWIDTH>::~core_complex() {
|
||||||
delete cpu;
|
delete cpu;
|
||||||
delete trc;
|
delete trc;
|
||||||
for(auto* p : plugin_list)
|
for(auto* p : plugin_list)
|
||||||
delete p;
|
delete p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_complex::trace(sc_trace_file *trf) const {}
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::trace(sc_trace_file* trf) const {}
|
||||||
|
|
||||||
void core_complex::before_end_of_elaboration() {
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::before_end_of_elaboration() {
|
||||||
SCCDEBUG(SCMOD) << "instantiating iss::arch::tgf with " << GET_PROP_VALUE(backend) << " backend";
|
SCCDEBUG(SCMOD) << "instantiating iss::arch::tgf with " << GET_PROP_VALUE(backend) << " backend";
|
||||||
// cpu = scc::make_unique<core_wrapper>(this);
|
// cpu = scc::make_unique<core_wrapper>(this);
|
||||||
cpu = new core_wrapper(this);
|
cpu = new core_wrapper(this);
|
||||||
@ -297,10 +300,9 @@ void core_complex::before_end_of_elaboration() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_complex::start_of_simulation() {
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::start_of_simulation() {
|
||||||
// quantum_keeper.reset();
|
// quantum_keeper.reset();
|
||||||
if(GET_PROP_VALUE(elf_file).size() > 0) {
|
if(GET_PROP_VALUE(elf_file).size() > 0) {
|
||||||
istringstream is(GET_PROP_VALUE(elf_file));
|
istringstream is(GET_PROP_VALUE(elf_file));
|
||||||
@ -323,9 +325,11 @@ void core_complex::start_of_simulation() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool core_complex::disass_output(uint64_t pc, const std::string instr_str) {
|
template <unsigned int BUSWIDTH> bool core_complex<BUSWIDTH>::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);
|
||||||
@ -335,7 +339,7 @@ bool core_complex::disass_output(uint64_t pc, const std::string instr_str) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_complex::forward() {
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::forward() {
|
||||||
#ifndef CWR_SYSTEMC
|
#ifndef CWR_SYSTEMC
|
||||||
set_clock_period(clk_i.read());
|
set_clock_period(clk_i.read());
|
||||||
#else
|
#else
|
||||||
@ -344,22 +348,24 @@ void core_complex::forward() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_complex::set_clock_period(sc_core::sc_time period) {
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::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() {
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::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()); }
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::sw_irq_cb() { cpu->local_irq(3, sw_irq_i.read()); }
|
||||||
|
|
||||||
void core_complex::timer_irq_cb() { cpu->local_irq(7, timer_irq_i.read()); }
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::timer_irq_cb() { cpu->local_irq(7, timer_irq_i.read()); }
|
||||||
|
|
||||||
void core_complex::ext_irq_cb() { cpu->local_irq(11, ext_irq_i.read()); }
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::ext_irq_cb() { cpu->local_irq(11, ext_irq_i.read()); }
|
||||||
|
|
||||||
void core_complex::local_irq_cb() {
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::local_irq_cb() {
|
||||||
for(auto i = 0U; i < local_irq_i.size(); ++i) {
|
for(auto i = 0U; i < local_irq_i.size(); ++i) {
|
||||||
if(local_irq_i[i].event()) {
|
if(local_irq_i[i].event()) {
|
||||||
cpu->local_irq(16 + i, local_irq_i[i].read());
|
cpu->local_irq(16 + i, local_irq_i[i].read());
|
||||||
@ -367,7 +373,7 @@ void core_complex::local_irq_cb() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_complex::run() {
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::run() {
|
||||||
wait(SC_ZERO_TIME); // separate from elaboration phase
|
wait(SC_ZERO_TIME); // separate from elaboration phase
|
||||||
do {
|
do {
|
||||||
wait(SC_ZERO_TIME);
|
wait(SC_ZERO_TIME);
|
||||||
@ -381,11 +387,11 @@ void core_complex::run() {
|
|||||||
quantum_keeper.reset();
|
quantum_keeper.reset();
|
||||||
cpu->set_interrupt_execution(false);
|
cpu->set_interrupt_execution(false);
|
||||||
cpu->start(dump_ir);
|
cpu->start(dump_ir);
|
||||||
} while (cpu->get_interrupt_execution());
|
} while(!cpu->get_interrupt_execution());
|
||||||
sc_stop();
|
sc_stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data, bool is_fetch) {
|
template <unsigned int BUSWIDTH> bool core_complex<BUSWIDTH>::read_mem(uint64_t addr, unsigned length, uint8_t* const data, bool is_fetch) {
|
||||||
auto& dmi_lut = is_fetch ? fetch_lut : read_lut;
|
auto& dmi_lut = is_fetch ? fetch_lut : read_lut;
|
||||||
auto lut_entry = dmi_lut.getEntry(addr);
|
auto lut_entry = dmi_lut.getEntry(addr);
|
||||||
if(lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && addr + length <= lut_entry.get_end_address() + 1) {
|
if(lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && addr + length <= lut_entry.get_end_address() + 1) {
|
||||||
@ -413,7 +419,7 @@ bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data,
|
|||||||
gp.set_extension(preExt);
|
gp.set_extension(preExt);
|
||||||
}
|
}
|
||||||
auto pre_delay = delay;
|
auto pre_delay = delay;
|
||||||
dbus->b_transport(gp, delay);
|
sckt->b_transport(gp, delay);
|
||||||
if(pre_delay > delay) {
|
if(pre_delay > delay) {
|
||||||
quantum_keeper.reset();
|
quantum_keeper.reset();
|
||||||
} else {
|
} else {
|
||||||
@ -423,7 +429,10 @@ 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,18 +442,16 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t *const data) {
|
template <unsigned int BUSWIDTH> bool core_complex<BUSWIDTH>::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 +476,10 @@ 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;
|
||||||
}
|
}
|
||||||
@ -487,7 +497,7 @@ bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t *cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool core_complex::read_mem_dbg(uint64_t addr, unsigned length, uint8_t *const data) {
|
template <unsigned int BUSWIDTH> bool core_complex<BUSWIDTH>::read_mem_dbg(uint64_t addr, unsigned length, uint8_t* const data) {
|
||||||
tlm::tlm_generic_payload gp;
|
tlm::tlm_generic_payload gp;
|
||||||
gp.set_command(tlm::TLM_READ_COMMAND);
|
gp.set_command(tlm::TLM_READ_COMMAND);
|
||||||
gp.set_address(addr);
|
gp.set_address(addr);
|
||||||
@ -497,7 +507,7 @@ bool core_complex::read_mem_dbg(uint64_t addr, unsigned length, uint8_t *const d
|
|||||||
return dbus->transport_dbg(gp) == length;
|
return dbus->transport_dbg(gp) == length;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool core_complex::write_mem_dbg(uint64_t addr, unsigned length, const uint8_t *const data) {
|
template <unsigned int BUSWIDTH> bool core_complex<BUSWIDTH>::write_mem_dbg(uint64_t addr, unsigned length, const uint8_t* const data) {
|
||||||
write_buf.resize(length);
|
write_buf.resize(length);
|
||||||
std::copy(data, data + length, write_buf.begin()); // need to copy as TLM does not guarantee data integrity
|
std::copy(data, data + length, write_buf.begin()); // need to copy as TLM does not guarantee data integrity
|
||||||
tlm::tlm_generic_payload gp;
|
tlm::tlm_generic_payload gp;
|
||||||
@ -508,5 +518,10 @@ bool core_complex::write_mem_dbg(uint64_t addr, unsigned length, const uint8_t *
|
|||||||
gp.set_streaming_width(length);
|
gp.set_streaming_width(length);
|
||||||
return dbus->transport_dbg(gp) == length;
|
return dbus->transport_dbg(gp) == length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template class core_complex<scc::LT>;
|
||||||
|
template class core_complex<32>;
|
||||||
|
template class core_complex<64>;
|
||||||
|
|
||||||
} /* namespace tgfs */
|
} /* namespace tgfs */
|
||||||
} /* namespace sysc */
|
} /* namespace sysc */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (C) 2017-2021 MINRES Technologies GmbH
|
* Copyright (C) 2017 - 2025 MINRES Technologies GmbH
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -33,22 +33,21 @@
|
|||||||
#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/signal_opt_ports.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>
|
||||||
#define SOCKET_WIDTH 32
|
|
||||||
#else
|
#else
|
||||||
#include <cci_configuration>
|
#include <cci_configuration>
|
||||||
#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 +57,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); }
|
||||||
@ -68,12 +67,35 @@ public:
|
|||||||
namespace tgfs {
|
namespace tgfs {
|
||||||
class core_wrapper;
|
class core_wrapper;
|
||||||
struct core_trace;
|
struct core_trace;
|
||||||
|
struct core_complex_if {
|
||||||
|
|
||||||
class core_complex : public sc_core::sc_module, public scc::traceable {
|
virtual ~core_complex_if() = default;
|
||||||
|
|
||||||
|
virtual bool read_mem(uint64_t addr, unsigned length, uint8_t* const data, bool is_fetch) = 0;
|
||||||
|
|
||||||
|
virtual bool write_mem(uint64_t addr, unsigned length, const uint8_t* const data) = 0;
|
||||||
|
|
||||||
|
virtual bool read_mem_dbg(uint64_t addr, unsigned length, uint8_t* const data) = 0;
|
||||||
|
|
||||||
|
virtual bool write_mem_dbg(uint64_t addr, unsigned length, const uint8_t* const data) = 0;
|
||||||
|
|
||||||
|
virtual bool disass_output(uint64_t pc, const std::string instr) = 0;
|
||||||
|
|
||||||
|
virtual unsigned get_last_bus_cycles() = 0;
|
||||||
|
|
||||||
|
//! Allow quantum keeper handling
|
||||||
|
virtual void sync(uint64_t) = 0;
|
||||||
|
|
||||||
|
virtual char const* hier_name() = 0;
|
||||||
|
|
||||||
|
scc::sc_in_opt<uint64_t> mtime_i{"mtime_i"};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <unsigned int BUSWIDTH = scc::LT> class core_complex : public sc_core::sc_module, public scc::traceable, public core_complex_if {
|
||||||
public:
|
public:
|
||||||
tlm::scc::initiator_mixin<tlm::tlm_initiator_socket<SOCKET_WIDTH>> ibus{"ibus"};
|
tlm::scc::initiator_mixin<tlm::tlm_initiator_socket<BUSWIDTH>> ibus{"ibus"};
|
||||||
|
|
||||||
tlm::scc::initiator_mixin<tlm::tlm_initiator_socket<SOCKET_WIDTH>> dbus{"dbus"};
|
tlm::scc::initiator_mixin<tlm::tlm_initiator_socket<BUSWIDTH>> dbus{"dbus"};
|
||||||
|
|
||||||
sc_core::sc_in<bool> rst_i{"rst_i"};
|
sc_core::sc_in<bool> rst_i{"rst_i"};
|
||||||
|
|
||||||
@ -88,8 +110,6 @@ public:
|
|||||||
#ifndef CWR_SYSTEMC
|
#ifndef CWR_SYSTEMC
|
||||||
sc_core::sc_in<sc_core::sc_time> clk_i{"clk_i"};
|
sc_core::sc_in<sc_core::sc_time> clk_i{"clk_i"};
|
||||||
|
|
||||||
sc_core::sc_port<tlm::tlm_peek_if<uint64_t>, 1, sc_core::SC_ZERO_OR_MORE_BOUND> mtime_o{"mtime_o"};
|
|
||||||
|
|
||||||
cci::cci_param<std::string> elf_file{"elf_file", ""};
|
cci::cci_param<std::string> elf_file{"elf_file", ""};
|
||||||
|
|
||||||
cci::cci_param<bool> enable_disass{"enable_disass", false};
|
cci::cci_param<bool> enable_disass{"enable_disass", false};
|
||||||
@ -115,8 +135,6 @@ public:
|
|||||||
#else
|
#else
|
||||||
sc_core::sc_in<bool> clk_i{"clk_i"};
|
sc_core::sc_in<bool> clk_i{"clk_i"};
|
||||||
|
|
||||||
sc_core::sc_in<uint64_t> mtime_i{"mtime_i"};
|
|
||||||
|
|
||||||
scml_property<std::string> elf_file{"elf_file", ""};
|
scml_property<std::string> elf_file{"elf_file", ""};
|
||||||
|
|
||||||
scml_property<bool> enable_disass{"enable_disass", false};
|
scml_property<bool> enable_disass{"enable_disass", false};
|
||||||
@ -151,8 +169,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,14 +177,13 @@ public:
|
|||||||
|
|
||||||
~core_complex();
|
~core_complex();
|
||||||
|
|
||||||
|
unsigned get_last_bus_cycles() override {
|
||||||
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;
|
||||||
return mem_incr > 1 ? mem_incr : 1;
|
return mem_incr > 1 ? mem_incr : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sync(uint64_t cycle) {
|
void sync(uint64_t cycle) override {
|
||||||
auto core_inc = curr_clk * (cycle - last_sync_cycle);
|
auto core_inc = curr_clk * (cycle - last_sync_cycle);
|
||||||
quantum_keeper.inc(core_inc);
|
quantum_keeper.inc(core_inc);
|
||||||
if(quantum_keeper.need_sync()) {
|
if(quantum_keeper.need_sync()) {
|
||||||
@ -177,19 +193,22 @@ public:
|
|||||||
last_sync_cycle = cycle;
|
last_sync_cycle = cycle;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_mem(uint64_t addr, unsigned length, uint8_t *const data, bool is_fetch);
|
bool read_mem(uint64_t addr, unsigned length, uint8_t* const data, bool is_fetch) override;
|
||||||
|
|
||||||
bool write_mem(uint64_t addr, unsigned length, const uint8_t *const data);
|
bool write_mem(uint64_t addr, unsigned length, const uint8_t* const data) override;
|
||||||
|
|
||||||
bool read_mem_dbg(uint64_t addr, unsigned length, uint8_t *const data);
|
bool read_mem_dbg(uint64_t addr, unsigned length, uint8_t* const data) override;
|
||||||
|
|
||||||
bool write_mem_dbg(uint64_t addr, unsigned length, const uint8_t *const data);
|
bool write_mem_dbg(uint64_t addr, unsigned length, const uint8_t* const data) override;
|
||||||
|
|
||||||
void trace(sc_core::sc_trace_file* trf) const override;
|
void trace(sc_core::sc_trace_file* trf) const override;
|
||||||
|
|
||||||
bool disass_output(uint64_t pc, const std::string instr);
|
bool disass_output(uint64_t pc, const std::string instr) override;
|
||||||
|
|
||||||
void set_clock_period(sc_core::sc_time period);
|
void set_clock_period(sc_core::sc_time period);
|
||||||
|
|
||||||
|
char const* hier_name() override { return name(); }
|
||||||
|
|
||||||
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 +228,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 */
|
||||||
|
@ -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_ */
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
*
|
*
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
#include "iss_factory.h"
|
#include "iss_factory.h"
|
||||||
#include <iss/arch/tgc5c.h>
|
#include <iss/arch/tgc5c.h>
|
||||||
#include <iss/arch/riscv_hart_m_p.h>
|
#include <iss/arch/riscv_hart_m_p.h>
|
||||||
@ -37,72 +38,73 @@
|
|||||||
#include "sc_core_adapter.h"
|
#include "sc_core_adapter.h"
|
||||||
#include "core_complex.h"
|
#include "core_complex.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
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",
|
||||||
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
[](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
|
auto cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(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)}};
|
||||||
}),
|
}),
|
||||||
iss_factory::instance().register_creator("tgc5c|mu_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("tgc5c|mu_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_if*>(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",
|
||||||
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
[](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
|
auto cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(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)}};
|
||||||
}),
|
}),
|
||||||
iss_factory::instance().register_creator("tgc5c|mu_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("tgc5c|mu_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_if*>(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",
|
||||||
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
[](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
|
auto cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(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)}};
|
||||||
}),
|
}),
|
||||||
iss_factory::instance().register_creator("tgc5c|mu_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("tgc5c|mu_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_if*>(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",
|
||||||
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
[](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
|
auto cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(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)}};
|
||||||
}),
|
}),
|
||||||
iss_factory::instance().register_creator("tgc5c|mu_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("tgc5c|mu_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_if*>(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
|
||||||
|
@ -1,30 +1,61 @@
|
|||||||
/*
|
/*******************************************************************************
|
||||||
* sc_core_adapter.h
|
* Copyright (C) 2023 - 2025 MINRES Technologies GmbH
|
||||||
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Created on: Jul 5, 2023
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* Author: eyck
|
* modification, are permitted provided that the following conditions are met:
|
||||||
*/
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* eyck@minres.com - initial implementation
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
#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 "sc_core_adapter_if.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <iss/iss.h>
|
||||||
|
#include <iss/mem/memory_if.h>
|
||||||
|
#include <iss/vm_types.h>
|
||||||
#include <scc/report.h>
|
#include <scc/report.h>
|
||||||
#include <util/ities.h>
|
#include <util/ities.h>
|
||||||
#include "sc_core_adapter_if.h"
|
|
||||||
#include <iss/iss.h>
|
|
||||||
#include <iss/vm_types.h>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
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 this_class = sc_core_adapter<PLAT>;
|
||||||
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;
|
||||||
using heart_state_t = typename PLAT::hart_state_type;
|
sc_core_adapter(sysc::tgfs::core_complex_if* owner)
|
||||||
sc_core_adapter(sysc::tgfs::core_complex *owner)
|
: owner(owner) {
|
||||||
: owner(owner) { }
|
this->csr_rd_cb[iss::arch::time] = MK_CSR_RD_CB(read_time);
|
||||||
|
if(sizeof(reg_t) == 4)
|
||||||
|
this->csr_rd_cb[iss::arch::timeh] = MK_CSR_RD_CB(read_time);
|
||||||
|
this->memories.replace_last(*this);
|
||||||
|
}
|
||||||
|
|
||||||
iss::arch_if* get_arch_if() override { return this; }
|
iss::arch_if* get_arch_if() override { return this; }
|
||||||
|
|
||||||
@ -54,101 +85,95 @@ 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->hier_name()) << "disass: "
|
||||||
SCCDEBUG(owner->name())<<"disass: "
|
<< "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t"
|
||||||
<< "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40)
|
<< std::setw(40) << std::setfill(' ') << std::left << instr << s.str();
|
||||||
<< std::setfill(' ') << std::left << instr << s.str();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data) override {
|
iss::mem::memory_if get_mem_if() override {
|
||||||
if (addr.access && iss::access_type::DEBUG)
|
return iss::mem::memory_if{.rd_mem{util::delegate<iss::mem::rd_mem_func_sig>::from<this_class, &this_class::read_mem>(this)},
|
||||||
return owner->read_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err;
|
.wr_mem{util::delegate<iss::mem::wr_mem_func_sig>::from<this_class, &this_class::write_mem>(this)}};
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::status read_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t* data) {
|
||||||
|
if(access && iss::access_type::DEBUG)
|
||||||
|
return owner->read_mem_dbg(addr, length, data) ? iss::Ok : iss::Err;
|
||||||
else {
|
else {
|
||||||
return owner->read_mem(addr.val, length, data, is_fetch(addr.access)) ? iss::Ok : iss::Err;
|
return owner->read_mem(addr, length, data, is_fetch(access)) ? iss::Ok : iss::Err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data) override {
|
iss::status write_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t const* data) {
|
||||||
if (addr.access && iss::access_type::DEBUG)
|
if(access && iss::access_type::DEBUG)
|
||||||
return owner->write_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err;
|
return owner->write_mem_dbg(addr, length, data) ? iss::Ok : iss::Err;
|
||||||
else {
|
if(addr == this->tohost) {
|
||||||
auto tohost_upper = (sizeof(reg_t) == 4 && addr.val == (this->tohost + 4)) ||
|
reg_t cur_data = *reinterpret_cast<const reg_t*>(data);
|
||||||
(sizeof(reg_t) == 8 && addr.val == this->tohost);
|
// Extract Device (bits 63:56)
|
||||||
auto tohost_lower = (sizeof(reg_t) == 4 && addr.val == this->tohost) ||
|
uint8_t device = sizeof(reg_t) == 4 ? 0 : (cur_data >> 56) & 0xFF;
|
||||||
(sizeof(reg_t)== 64 && addr.val == this->tohost);
|
// Extract Command (bits 55:48)
|
||||||
if (tohost_lower || tohost_upper) {
|
uint8_t command = sizeof(reg_t) == 4 ? 0 : (cur_data >> 48) & 0xFF;
|
||||||
if (tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) {
|
// Extract payload (bits 47:0)
|
||||||
switch (hostvar >> 48) {
|
uint64_t payload_addr = cur_data & 0xFFFFFFFFFFFFULL; // 24bits
|
||||||
case 0:
|
if(payload_addr & 1) {
|
||||||
if (hostvar != 0x1) {
|
if(payload_addr != 0x1) {
|
||||||
SCCINFO(owner->name()) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
|
SCCERR(owner->hier_name()) << "tohost value is 0x" << std::hex << payload_addr << std::dec << " (" << payload_addr
|
||||||
<< "), stopping simulation";
|
<< "), stopping simulation";
|
||||||
} else {
|
} else {
|
||||||
SCCINFO(owner->name()) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
|
SCCINFO(owner->hier_name())
|
||||||
<< "), stopping simulation";
|
<< "tohost value is 0x" << std::hex << payload_addr << std::dec << " (" << payload_addr << "), 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 = payload_addr;
|
||||||
#ifndef WITH_TCC
|
|
||||||
throw(iss::simulation_stopped(hostvar));
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (tohost_lower)
|
|
||||||
to_host_wr_cnt++;
|
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
} else {
|
|
||||||
auto res = owner->write_mem(addr.val, length, data) ? iss::Ok : iss::Err;
|
|
||||||
// clear MTIP on mtimecmp write
|
|
||||||
if (addr.val == 0x2004000) {
|
|
||||||
reg_t val;
|
|
||||||
this->read_csr(iss::arch::mip, val);
|
|
||||||
if (val & (1ULL << 7)) this->write_csr(iss::arch::mip, val & ~(1ULL << 7));
|
|
||||||
}
|
}
|
||||||
|
if(device == 0 && command == 0) {
|
||||||
|
std::array<uint64_t, 8> loaded_payload;
|
||||||
|
auto res = owner->read_mem(payload_addr, 8 * sizeof(uint64_t), reinterpret_cast<uint8_t*>(loaded_payload.data()), false)
|
||||||
|
? iss::Ok
|
||||||
|
: iss::Err;
|
||||||
|
if(res == iss::Err) {
|
||||||
|
SCCERR(owner->hier_name()) << "Syscall read went wrong";
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
uint64_t syscall_num = loaded_payload.at(0);
|
||||||
|
if(syscall_num == 64) // SYS_WRITE
|
||||||
|
return this->execute_sys_write(this, loaded_payload, PLAT::MEM);
|
||||||
|
SCCERR(owner->hier_name()) << "tohost syscall with number 0x" << std::hex << syscall_num << std::dec << " (" << syscall_num
|
||||||
|
<< ") not implemented";
|
||||||
|
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||||
|
this->interrupt_sim = payload_addr;
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
SCCERR(owner->hier_name()) << "tohost functionality not implemented for device " << device << " and command " << command;
|
||||||
|
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||||
|
this->interrupt_sim = payload_addr;
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
auto res = owner->write_mem(addr, length, data) ? iss::Ok : iss::Err;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iss::status read_csr(unsigned addr, reg_t &val) override {
|
iss::status read_time(unsigned addr, reg_t& val) {
|
||||||
#ifndef CWR_SYSTEMC
|
uint64_t time_val = owner->mtime_i.get_interface() ? owner->mtime_i.read() : 0;
|
||||||
if((addr==iss::arch::time || addr==iss::arch::timeh) && owner->mtime_o.get_interface(0)){
|
|
||||||
uint64_t time_val;
|
|
||||||
bool ret = owner->mtime_o->nb_peek(time_val);
|
|
||||||
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)
|
||||||
val = static_cast<reg_t>(time_val >> 32);
|
return iss::Err;
|
||||||
}
|
|
||||||
return ret?iss::Ok:iss::Err;
|
|
||||||
#else
|
|
||||||
if((addr==iss::arch::time || addr==iss::arch::timeh)){
|
|
||||||
uint64_t time_val = owner->mtime_i.read();
|
|
||||||
if (addr == iss::arch::time) {
|
|
||||||
val = static_cast<reg_t>(time_val);
|
|
||||||
} else if (addr == iss::arch::timeh) {
|
|
||||||
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;
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
return PLAT::read_csr(addr, val);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wait_until(uint64_t flags) override {
|
void wait_until(uint64_t flags) override {
|
||||||
SCCDEBUG(owner->name()) << "Sleeping until interrupt";
|
SCCDEBUG(owner->hier_name()) << "Sleeping until interrupt";
|
||||||
|
PLAT::wait_until(flags);
|
||||||
while(this->reg.pending_trap == 0 && (this->csr[iss::arch::mip] & this->csr[iss::arch::mie]) == 0) {
|
while(this->reg.pending_trap == 0 && (this->csr[iss::arch::mip] & this->csr[iss::arch::mie]) == 0) {
|
||||||
sc_core::wait(wfi_evt);
|
sc_core::wait(wfi_evt);
|
||||||
}
|
}
|
||||||
PLAT::wait_until(flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void local_irq(short id, bool value) override {
|
void local_irq(short id, bool value) override {
|
||||||
@ -164,7 +189,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) {
|
||||||
@ -174,15 +200,14 @@ public:
|
|||||||
this->csr[iss::arch::mip] &= ~mask;
|
this->csr[iss::arch::mip] &= ~mask;
|
||||||
this->check_interrupt();
|
this->check_interrupt();
|
||||||
if(value)
|
if(value)
|
||||||
SCCTRACE(owner->name()) << "Triggering interrupt " << id << " Pending trap: " << this->reg.pending_trap;
|
SCCTRACE(owner->hier_name()) << "Triggering interrupt " << id << " Pending trap: " << this->reg.pending_trap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sysc::tgfs::core_complex *const owner;
|
sysc::tgfs::core_complex_if* const owner{nullptr};
|
||||||
sc_core::sc_event wfi_evt;
|
sc_core::sc_event wfi_evt;
|
||||||
uint64_t hostvar{std::numeric_limits<uint64_t>::max()};
|
|
||||||
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_ */
|
||||||
|
@ -1,20 +1,46 @@
|
|||||||
/*
|
/*******************************************************************************
|
||||||
* sc_core_adapter.h
|
* Copyright (C) 2023 MINRES Technologies GmbH
|
||||||
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Created on: Jul 5, 2023
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* Author: eyck
|
* modification, are permitted provided that the following conditions are met:
|
||||||
*/
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* eyck@minres.com - initial implementation
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
#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 +53,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_ */
|
||||||
|
70
src/vm/aes_sbox.h
Normal file
70
src/vm/aes_sbox.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright (C) 2025, MINRES Technologies GmbH
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
// may be used to endorse or promote products derived from this software
|
||||||
|
// without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Contributors:
|
||||||
|
// ales@minres.com - initial API and implementation
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef _VM_AES_SBOX_H_
|
||||||
|
#define _VM_AES_SBOX_H_
|
||||||
|
#include <cstdint>
|
||||||
|
extern "C" {
|
||||||
|
const uint8_t AES_ENC_SBOX[] = {
|
||||||
|
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59,
|
||||||
|
0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1,
|
||||||
|
0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83,
|
||||||
|
0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
|
||||||
|
0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C,
|
||||||
|
0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC,
|
||||||
|
0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE,
|
||||||
|
0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
|
||||||
|
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6,
|
||||||
|
0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9,
|
||||||
|
0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1,
|
||||||
|
0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16};
|
||||||
|
uint8_t inline aes_sbox_fwd(uint8_t index) { return AES_ENC_SBOX[index]; }
|
||||||
|
|
||||||
|
const uint8_t AES_DEC_SBOX[] = {
|
||||||
|
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F,
|
||||||
|
0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B,
|
||||||
|
0x42, 0xFA, 0xC3, 0x4E, 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8,
|
||||||
|
0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
|
||||||
|
0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3,
|
||||||
|
0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41,
|
||||||
|
0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9,
|
||||||
|
0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
|
||||||
|
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07,
|
||||||
|
0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F,
|
||||||
|
0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2B,
|
||||||
|
0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D};
|
||||||
|
uint8_t inline aes_sbox_inv(uint8_t index) { return AES_DEC_SBOX[index]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _VM_AES_SBOX_H_ */
|
@ -1,474 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
x86::Mem get_reg_ptr(jit_holder& jh, unsigned idx){
|
|
||||||
|
|
||||||
x86::Gp tmp_ptr = jh.cc.newUIntPtr("tmp_ptr");
|
|
||||||
jh.cc.mov(tmp_ptr, jh.regs_base_ptr);
|
|
||||||
jh.cc.add(tmp_ptr, traits::reg_byte_offsets[idx]);
|
|
||||||
switch(traits::reg_bit_widths[idx]){
|
|
||||||
case 8:
|
|
||||||
return x86::ptr_8(tmp_ptr);
|
|
||||||
case 16:
|
|
||||||
return x86::ptr_16(tmp_ptr);
|
|
||||||
case 32:
|
|
||||||
return x86::ptr_32(tmp_ptr);
|
|
||||||
case 64:
|
|
||||||
return x86::ptr_64(tmp_ptr);
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("Invalid reg size in get_reg_ptr");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
x86::Gp get_reg_for(jit_holder& jh, unsigned idx){
|
|
||||||
//can check for regs in jh and return them instead of creating new ones
|
|
||||||
switch(traits::reg_bit_widths[idx]){
|
|
||||||
case 8:
|
|
||||||
return jh.cc.newInt8();
|
|
||||||
case 16:
|
|
||||||
return jh.cc.newInt16();
|
|
||||||
case 32:
|
|
||||||
return jh.cc.newInt32();
|
|
||||||
case 64:
|
|
||||||
return jh.cc.newInt64();
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("Invalid reg size in get_reg_ptr");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
x86::Gp get_reg_for(jit_holder& jh, unsigned size, bool is_signed){
|
|
||||||
if(is_signed)
|
|
||||||
switch(size){
|
|
||||||
case 8:
|
|
||||||
return jh.cc.newInt8();
|
|
||||||
case 16:
|
|
||||||
return jh.cc.newInt16();
|
|
||||||
case 32:
|
|
||||||
return jh.cc.newInt32();
|
|
||||||
case 64:
|
|
||||||
return jh.cc.newInt64();
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("Invalid reg size in get_reg_ptr");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
switch(size){
|
|
||||||
case 8:
|
|
||||||
return jh.cc.newUInt8();
|
|
||||||
case 16:
|
|
||||||
return jh.cc.newUInt16();
|
|
||||||
case 32:
|
|
||||||
return jh.cc.newUInt32();
|
|
||||||
case 64:
|
|
||||||
return jh.cc.newUInt64();
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("Invalid reg size in get_reg_ptr");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inline x86::Gp load_reg_from_mem(jit_holder& jh, unsigned idx){
|
|
||||||
auto ptr = get_reg_ptr(jh, idx);
|
|
||||||
auto reg = get_reg_for(jh, idx);
|
|
||||||
jh.cc.mov(reg, ptr);
|
|
||||||
return reg;
|
|
||||||
}
|
|
||||||
inline void write_reg_to_mem(jit_holder& jh, x86::Gp reg, unsigned idx){
|
|
||||||
auto ptr = get_reg_ptr(jh, idx);
|
|
||||||
jh.cc.mov(ptr, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gen_instr_prologue(jit_holder& jh, addr_t pc){
|
|
||||||
auto& cc = jh.cc;
|
|
||||||
|
|
||||||
cc.comment("\n//(*icount)++;");
|
|
||||||
cc.inc(get_reg_ptr(jh, traits::ICOUNT));
|
|
||||||
|
|
||||||
cc.comment("\n//*pc=*next_pc;");
|
|
||||||
cc.mov(get_reg_ptr(jh, traits::PC), jh.next_pc);
|
|
||||||
|
|
||||||
cc.comment("\n//*trap_state=*pending_trap;");
|
|
||||||
cc.mov(get_reg_ptr(jh, traits::PENDING_TRAP), jh.trap_state);
|
|
||||||
|
|
||||||
cc.comment("\n//increment *next_pc");
|
|
||||||
cc.mov(jh.next_pc, pc);
|
|
||||||
|
|
||||||
}
|
|
||||||
void gen_instr_epilogue(jit_holder& jh){
|
|
||||||
auto& cc = jh.cc;
|
|
||||||
|
|
||||||
cc.comment("\n//if(*trap_state!=0) goto trap_entry;");
|
|
||||||
cc.test(jh.trap_state, jh.trap_state);
|
|
||||||
cc.jnz(jh.trap_entry);
|
|
||||||
|
|
||||||
//Does this need to be done after every single instruction?
|
|
||||||
cc.comment("\n//write back regs to mem");
|
|
||||||
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.trap_state, traits::TRAP_STATE);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
void gen_block_prologue(jit_holder& jh) override{
|
|
||||||
|
|
||||||
jh.pc = load_reg_from_mem(jh, traits::PC);
|
|
||||||
jh.next_pc = load_reg_from_mem(jh, traits::NEXT_PC);
|
|
||||||
jh.trap_state = load_reg_from_mem(jh, traits::TRAP_STATE);
|
|
||||||
}
|
|
||||||
void gen_block_epilogue(jit_holder& jh) override{
|
|
||||||
x86::Compiler& cc = jh.cc;
|
|
||||||
cc.comment("\n//return *next_pc;");
|
|
||||||
cc.ret(jh.next_pc);
|
|
||||||
|
|
||||||
cc.bind(jh.trap_entry);
|
|
||||||
cc.comment("\n//enter_trap(core_ptr, *trap_state, *pc, 0);");
|
|
||||||
|
|
||||||
x86::Gp current_trap_state = get_reg_for(jh, traits::TRAP_STATE);
|
|
||||||
cc.mov(current_trap_state, get_reg_ptr(jh, traits::TRAP_STATE));
|
|
||||||
|
|
||||||
x86::Gp current_pc = get_reg_for(jh, traits::PC);
|
|
||||||
cc.mov(current_pc, get_reg_ptr(jh, traits::PC));
|
|
||||||
|
|
||||||
x86::Gp instr = cc.newInt32("instr");
|
|
||||||
cc.mov(instr, 0);
|
|
||||||
InvokeNode* call_enter_trap;
|
|
||||||
cc.invoke(&call_enter_trap, &enter_trap, FuncSignatureT<uint64_t, void*, uint64_t, uint64_t, uint64_t>());
|
|
||||||
call_enter_trap->setArg(0, jh.arch_if_ptr);
|
|
||||||
call_enter_trap->setArg(1, current_trap_state);
|
|
||||||
call_enter_trap->setArg(2, current_pc);
|
|
||||||
call_enter_trap->setArg(3, instr);
|
|
||||||
cc.comment("\n//*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.ret(jh.next_pc);
|
|
||||||
|
|
||||||
}
|
|
||||||
//TODO implement
|
|
||||||
|
|
||||||
void gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause) {
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
enum operation {add, sub, band, bor, bxor, shl, sar , shr};
|
|
||||||
|
|
||||||
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value || std::is_same<T, x86::Gp>::value>>
|
|
||||||
x86::Gp gen_operation(jit_holder& jh, operation op, x86::Gp a, T b){
|
|
||||||
x86::Compiler& cc = jh.cc;
|
|
||||||
switch (op) {
|
|
||||||
case add: { cc.add(a, b); break; }
|
|
||||||
case sub: { cc.sub(a, b); break; }
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum three_operand_operation{imul, mul, idiv, div, srem, urem};
|
|
||||||
|
|
||||||
x86::Gp gen_operation(jit_holder& jh, three_operand_operation op, x86::Gp a, x86::Gp b){
|
|
||||||
x86::Compiler& cc = jh.cc;
|
|
||||||
switch (op) {
|
|
||||||
case imul: {
|
|
||||||
x86::Gp dummy = cc.newInt64();
|
|
||||||
cc.imul(dummy, a.r64(), b.r64());
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
case mul: {
|
|
||||||
x86::Gp dummy = cc.newInt64();
|
|
||||||
cc.mul(dummy, a.r64(), b.r64());
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
case idiv: {
|
|
||||||
x86::Gp dummy = cc.newInt64();
|
|
||||||
cc.mov(dummy, 0);
|
|
||||||
cc.idiv(dummy, a.r64(), b.r64());
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
case div: {
|
|
||||||
x86::Gp dummy = cc.newInt64();
|
|
||||||
cc.mov(dummy, 0);
|
|
||||||
cc.div(dummy, a.r64(), b.r64());
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
case srem:{
|
|
||||||
x86::Gp rem = cc.newInt32();
|
|
||||||
cc.mov(rem, 0);
|
|
||||||
auto a_reg = cc.newInt32();
|
|
||||||
cc.mov(a_reg, a.r32());
|
|
||||||
cc.idiv(rem, a_reg, b.r32());
|
|
||||||
return rem;
|
|
||||||
}
|
|
||||||
case urem:{
|
|
||||||
x86::Gp rem = cc.newInt32();
|
|
||||||
cc.mov(rem, 0);
|
|
||||||
auto a_reg = cc.newInt32();
|
|
||||||
cc.mov(a_reg, a.r32());
|
|
||||||
cc.div(rem, a_reg, b.r32());
|
|
||||||
return rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (three_operand)", op));
|
|
||||||
}
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
|
|
||||||
x86::Gp gen_operation(jit_holder& jh, three_operand_operation op, x86::Gp a, T b){
|
|
||||||
x86::Gp b_reg = jh.cc.newInt32();
|
|
||||||
/* switch(a.size()){
|
|
||||||
case 1: b_reg = jh.cc.newInt8(); break;
|
|
||||||
case 2: b_reg = jh.cc.newInt16(); break;
|
|
||||||
case 4: b_reg = jh.cc.newInt32(); break;
|
|
||||||
case 8: b_reg = jh.cc.newInt64(); break;
|
|
||||||
default: throw std::runtime_error(fmt::format("Invalid size ({}) in gen operation", a.size()));
|
|
||||||
} */
|
|
||||||
jh.cc.mov(b_reg, b);
|
|
||||||
return gen_operation(jh, op, a, b_reg);
|
|
||||||
}
|
|
||||||
enum comparison_operation{land, lor, eq, ne, lt, ltu, gt, gtu, lte, lteu, gte, gteu};
|
|
||||||
|
|
||||||
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value || std::is_same<T, x86::Gp>::value>>
|
|
||||||
x86::Gp gen_operation(jit_holder& jh, comparison_operation op, x86::Gp a, T b){
|
|
||||||
x86::Compiler& cc = jh.cc;
|
|
||||||
x86::Gp tmp = cc.newInt8();
|
|
||||||
cc.mov(tmp,1);
|
|
||||||
Label label_then = cc.newLabel();
|
|
||||||
cc.cmp(a,b);
|
|
||||||
switch (op) {
|
|
||||||
case eq: cc.je(label_then); break;
|
|
||||||
case ne: cc.jne(label_then); break;
|
|
||||||
case lt: cc.jl(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: {
|
|
||||||
Label label_false = cc.newLabel();
|
|
||||||
cc.cmp(a, 0);
|
|
||||||
cc.je(label_false);
|
|
||||||
auto b_reg = cc.newInt8();
|
|
||||||
cc.mov(b_reg, b);
|
|
||||||
cc.cmp(b_reg, 0);
|
|
||||||
cc.je(label_false);
|
|
||||||
cc.jmp(label_then);
|
|
||||||
cc.bind(label_false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case lor: {
|
|
||||||
cc.cmp(a, 0);
|
|
||||||
cc.jne(label_then);
|
|
||||||
auto b_reg = cc.newInt8();
|
|
||||||
cc.mov(b_reg, b);
|
|
||||||
cc.cmp(b_reg, 0);
|
|
||||||
cc.jne(label_then);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (comparison)", op));
|
|
||||||
}
|
|
||||||
cc.mov(tmp,0);
|
|
||||||
cc.bind(label_then);
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
enum binary_operation{lnot, inc, dec, bnot, neg};
|
|
||||||
|
|
||||||
x86::Gp gen_operation(jit_holder& jh, binary_operation op, x86::Gp a){
|
|
||||||
x86::Compiler& cc = jh.cc;
|
|
||||||
switch (op) {
|
|
||||||
case lnot: throw std::runtime_error("Current operation not supported in gen_operation(lnot)");
|
|
||||||
case inc: { cc.inc(a); break; }
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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 {
|
|
||||||
auto val_reg = get_reg_for(jh, sizeof(val)*8);
|
|
||||||
auto tmp = get_reg_for(jh, size);
|
|
||||||
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>
|
|
||||||
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 {
|
|
||||||
auto val_reg = get_reg_for(jh, sizeof(val)*8);
|
|
||||||
auto tmp = get_reg_for(jh, size);
|
|
||||||
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>>
|
|
||||||
inline x86::Gp gen_ext(jit_holder& jh, T val, unsigned size, bool is_signed) {
|
|
||||||
auto val_reg = get_reg_for(jh, sizeof(val)*8);
|
|
||||||
jh.cc.mov(val_reg, val);
|
|
||||||
return gen_ext(jh, val_reg, size, is_signed);
|
|
||||||
}
|
|
||||||
//explicit Gp size cast
|
|
||||||
inline x86::Gp gen_ext(jit_holder& jh, x86::Gp val, unsigned size, bool is_signed) {
|
|
||||||
auto& cc = jh.cc;
|
|
||||||
if(is_signed){
|
|
||||||
switch(val.size()){
|
|
||||||
case 1: cc.cbw(val); break;
|
|
||||||
case 2: 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){
|
|
||||||
case 8: cc.and_(val,std::numeric_limits<uint8_t>::max()); return val.r8();
|
|
||||||
case 16: cc.and_(val,std::numeric_limits<uint16_t>::max()); 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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, uint32_t length){
|
|
||||||
x86::Compiler& cc = jh.cc;
|
|
||||||
auto ret_reg = cc.newInt32();
|
|
||||||
|
|
||||||
auto mem_type_reg = cc.newInt32();
|
|
||||||
cc.mov(mem_type_reg, type);
|
|
||||||
|
|
||||||
auto space_reg = cc.newInt32();
|
|
||||||
cc.mov(space_reg, static_cast<uint16_t>(iss::address_type::VIRTUAL));
|
|
||||||
|
|
||||||
auto val_ptr = cc.newUIntPtr();
|
|
||||||
cc.mov(val_ptr, read_mem_buf);
|
|
||||||
|
|
||||||
InvokeNode* invokeNode;
|
|
||||||
uint64_t mask = 0;
|
|
||||||
x86::Gp val_reg = cc.newInt64();
|
|
||||||
|
|
||||||
switch(length){
|
|
||||||
case 1:{
|
|
||||||
cc.invoke(&invokeNode, &read_mem1, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uintptr_t>());
|
|
||||||
mask = std::numeric_limits<uint8_t>::max();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2:{
|
|
||||||
cc.invoke(&invokeNode, &read_mem2, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uintptr_t>());
|
|
||||||
mask = std::numeric_limits<uint16_t>::max();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 4:{
|
|
||||||
cc.invoke(&invokeNode, &read_mem4, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uintptr_t>());
|
|
||||||
mask = std::numeric_limits<uint32_t>::max();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 8:{
|
|
||||||
cc.invoke(&invokeNode, &read_mem8, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uintptr_t>());
|
|
||||||
mask = std::numeric_limits<uint64_t>::max();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: throw std::runtime_error(fmt::format("Invalid length ({}) in gen_read_mem",length));
|
|
||||||
}
|
|
||||||
|
|
||||||
invokeNode->setRet(0, ret_reg);
|
|
||||||
invokeNode->setArg(0, jh.arch_if_ptr);
|
|
||||||
invokeNode->setArg(1, space_reg);
|
|
||||||
invokeNode->setArg(2, mem_type_reg);
|
|
||||||
invokeNode->setArg(3, addr);
|
|
||||||
invokeNode->setArg(4, val_ptr);
|
|
||||||
|
|
||||||
cc.mov(val_reg, x86::ptr_64(val_ptr));
|
|
||||||
cc.and_(val_reg, mask);
|
|
||||||
cc.cmp(ret_reg,0);
|
|
||||||
cc.jne(jh.trap_entry);
|
|
||||||
return val_reg;
|
|
||||||
}
|
|
||||||
inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp length){
|
|
||||||
uint32_t length_val = 0;
|
|
||||||
auto length_ptr = jh.cc.newIntPtr();
|
|
||||||
jh.cc.mov(length_ptr, &length_val);
|
|
||||||
jh.cc.mov(x86::ptr_32(length_ptr),length);
|
|
||||||
|
|
||||||
return gen_read_mem(jh, type, addr, length);
|
|
||||||
}
|
|
||||||
inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, uint64_t addr, x86::Gp length){
|
|
||||||
auto addr_reg = jh.cc.newInt64();
|
|
||||||
jh.cc.mov(addr_reg, addr);
|
|
||||||
|
|
||||||
uint32_t length_val = 0;
|
|
||||||
auto length_ptr = jh.cc.newIntPtr();
|
|
||||||
jh.cc.mov(length_ptr, &length_val);
|
|
||||||
jh.cc.mov(x86::ptr_32(length_ptr),length);
|
|
||||||
|
|
||||||
return gen_read_mem(jh, type, addr_reg, length_val);
|
|
||||||
}
|
|
||||||
inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, uint64_t addr, uint32_t length){
|
|
||||||
auto addr_reg = jh.cc.newInt64();
|
|
||||||
jh.cc.mov(addr_reg, addr);
|
|
||||||
|
|
||||||
return gen_read_mem(jh, type, addr_reg, length);
|
|
||||||
}
|
|
||||||
inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, int64_t val){
|
|
||||||
auto val_reg = jh.cc.newInt64();
|
|
||||||
jh.cc.mov(val_reg, val);
|
|
||||||
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){
|
|
||||||
x86::Compiler& cc = jh.cc;
|
|
||||||
|
|
||||||
auto mem_type_reg = cc.newInt32();
|
|
||||||
jh.cc.mov(mem_type_reg, type);
|
|
||||||
auto space_reg = cc.newInt32();
|
|
||||||
jh.cc.mov(space_reg, static_cast<uint16_t>(iss::address_type::VIRTUAL));
|
|
||||||
auto ret_reg = cc.newInt32();
|
|
||||||
InvokeNode* invokeNode;
|
|
||||||
|
|
||||||
if(val.isGpb()){
|
|
||||||
cc.invoke(&invokeNode, &write_mem1, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint8_t>());
|
|
||||||
}
|
|
||||||
else if(val.isGpw()){
|
|
||||||
cc.invoke(&invokeNode, &write_mem2, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint16_t>());
|
|
||||||
}
|
|
||||||
else if(val.isGpd()){
|
|
||||||
cc.invoke(&invokeNode, &write_mem4, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint32_t>());
|
|
||||||
}
|
|
||||||
else if(val.isGpq()){
|
|
||||||
cc.invoke(&invokeNode, &write_mem8, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint64_t>());
|
|
||||||
}
|
|
||||||
else throw std::runtime_error("Invalid register size in gen_write_mem");
|
|
||||||
|
|
||||||
invokeNode->setRet(0,ret_reg);
|
|
||||||
invokeNode->setArg(0, jh.arch_if_ptr);
|
|
||||||
invokeNode->setArg(1, space_reg);
|
|
||||||
invokeNode->setArg(2, mem_type_reg);
|
|
||||||
invokeNode->setArg(3, addr);
|
|
||||||
invokeNode->setArg(4, val);
|
|
||||||
|
|
||||||
cc.cmp(ret_reg,0);
|
|
||||||
cc.jne(jh.trap_entry);
|
|
||||||
|
|
||||||
}
|
|
||||||
inline void gen_write_mem(jit_holder& jh, mem_type_e type, uint64_t addr, x86::Gp val){
|
|
||||||
auto addr_reg = jh.cc.newInt64();
|
|
||||||
jh.cc.mov(addr_reg, addr);
|
|
||||||
gen_write_mem(jh, type, addr_reg, val);
|
|
||||||
}
|
|
||||||
inline void gen_write_mem(jit_holder& jh, mem_type_e type, uint64_t addr, int64_t val){
|
|
||||||
auto val_reg = jh.cc.newInt64();
|
|
||||||
jh.cc.mov(val_reg, val);
|
|
||||||
|
|
||||||
auto addr_reg = jh.cc.newInt64();
|
|
||||||
jh.cc.mov(addr_reg, addr);
|
|
||||||
gen_write_mem(jh, type, addr_reg, val_reg);
|
|
||||||
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user