Compare commits

...

16 Commits

Author SHA1 Message Date
Eyck Jentzsch 6cb76fc256 updates tgc5c according to latest CoreDSL 2024-04-16 13:09:14 +02:00
Stanislaw Kaushanski fbcd389580 fix log macro 2024-04-15 13:03:47 +02:00
Stanislaw Kaushanski b25b7848c6 fix formatting 2024-03-19 11:47:12 +01:00
Eyck-Alexander Jentzsch 6c986d38d8 Merge branch 'develop' of https://git.minres.com/DBT-RISE/DBT-RISE-TGC into develop 2024-03-19 11:02:17 +01:00
Eyck-Alexander Jentzsch a1ebd83d2a adds riscv_hart_common and signature output 2024-03-19 11:02:03 +01:00
Stanislaw Kaushanski 8aed551813 Add a new LOG macro in SCC to avoid conflicts with other libraries. 2024-03-14 09:43:08 +01:00
Eyck-Alexander Jentzsch 1e6a0086e9 adds disass functionality 2024-03-07 13:58:08 +01:00
Eyck Jentzsch 119d4a8b43 adds generation if IMEM space 2024-02-21 07:08:24 +01:00
Eyck Jentzsch 9841b16122 fixes clang-format failures 2024-01-12 11:49:11 +01:00
Eyck-Alexander Jentzsch fbda1424f3 Merge branch 'develop' of https://git.minres.com/DBT-RISE/DBT-RISE-TGC into develop 2024-01-10 16:22:31 +01:00
Eyck-Alexander Jentzsch fe2d5cb2f9 adds semihosting to all backends 2024-01-10 11:47:12 +01:00
Eyck-Alexander Jentzsch 3ff59ba45d small refactor, adds baisc functionality 2024-01-10 10:15:05 +01:00
Eyck Jentzsch db5765b342 makes softfloat always a static library 2024-01-10 09:36:52 +01:00
Eyck-Alexander Jentzsch 075e04249a adds semihosting skeleton 2024-01-09 12:50:41 +01:00
Eyck-Alexander Jentzsch 207f778ee6 adds initial semihosting host capabilities 2024-01-08 17:17:59 +01:00
Eyck Jentzsch f4f90c5e65 backports clang-format changes to template 2023-12-02 17:42:57 +01:00
24 changed files with 6747 additions and 4659 deletions

View File

@ -1,8 +1,9 @@
cmake_minimum_required(VERSION 3.12) cmake_minimum_required(VERSION 3.12)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
###############################################################################
# ##############################################################################
# #
############################################################################### # ##############################################################################
project(dbt-rise-tgc VERSION 1.0.0) project(dbt-rise-tgc VERSION 1.0.0)
include(GNUInstallDirs) include(GNUInstallDirs)
@ -14,59 +15,69 @@ find_package(Boost COMPONENTS coroutine 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/vm/interp/vm_tgc5c.cpp src/vm/interp/vm_tgc5c.cpp
src/vm/fp_functions.cpp src/vm/fp_functions.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()
if(WITH_ASMJIT)
list(APPEND LIB_SOURCES
src/vm/asmjit/vm_tgc5c.cpp
) )
endif() endif()
if(WITH_ASMJIT)
list(APPEND LIB_SOURCES
src/vm/asmjit/vm_tgc5c.cpp
)
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)
FILE(GLOB LLVM_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/llvm/vm_*.cpp) FILE(GLOB LLVM_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/llvm/vm_*.cpp)
list(APPEND LIB_SOURCES ${LLVM_GEN_SOURCES}) list(APPEND LIB_SOURCES ${LLVM_GEN_SOURCES})
endif() endif()
if(WITH_TCC) 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,60 +86,67 @@ 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))
target_compile_definitions(${PROJECT_NAME} INTERFACE ${DBT_CORE_DEFS}) if(NOT(DBT_CORE_DEFS STREQUAL DBT_CORE_DEFS-NOTFOUND))
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)
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) if(WITH_LLVM)
find_package(LLVM) find_package(LLVM)
target_compile_definitions(${PROJECT_NAME} PUBLIC ${LLVM_DEFINITIONS}) target_compile_definitions(${PROJECT_NAME} PUBLIC ${LLVM_DEFINITIONS})
target_include_directories(${PROJECT_NAME} PUBLIC ${LLVM_INCLUDE_DIRS}) target_include_directories(${PROJECT_NAME} PUBLIC ${LLVM_INCLUDE_DIRS})
if(BUILD_SHARED_LIBS)
target_link_libraries( ${PROJECT_NAME} PUBLIC ${LLVM_LIBRARIES}) if(BUILD_SHARED_LIBS)
endif() target_link_libraries(${PROJECT_NAME} PUBLIC ${LLVM_LIBRARIES})
endif()
endif() endif()
set_target_properties(${PROJECT_NAME} PROPERTIES set_target_properties(${PROJECT_NAME} PROPERTIES
VERSION ${PROJECT_VERSION} VERSION ${PROJECT_VERSION}
FRAMEWORK FALSE FRAMEWORK FALSE
) )
install(TARGETS ${PROJECT_NAME} COMPONENT ${PROJECT_NAME} install(TARGETS ${PROJECT_NAME} COMPONENT ${PROJECT_NAME}
EXPORT ${PROJECT_NAME}Targets # for downstream dependencies EXPORT ${PROJECT_NAME}Targets # for downstream dependencies
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # static lib ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # static lib
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # binaries RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # binaries
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # shared lib LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # shared lib
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} # for mac FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} # for mac
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} # headers for mac (note the different component -> different package) PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} # headers for mac (note the different component -> different package)
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers
) )
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/incl/iss COMPONENT ${PROJECT_NAME} install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/incl/iss COMPONENT ${PROJECT_NAME}
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # target directory DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # target directory
FILES_MATCHING # install only matched files FILES_MATCHING # install only matched files
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)
###############################################################################
# ##############################################################################
# #
############################################################################### # ##############################################################################
set(CMAKE_INSTALL_RPATH $ORIGIN/../${CMAKE_INSTALL_LIBDIR}) set(CMAKE_INSTALL_RPATH $ORIGIN/../${CMAKE_INSTALL_LIBDIR})
project(tgc-sim) 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()
@ -140,21 +158,20 @@ else()
endif() endif()
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})
string(TOUPPER ${CORE_NAME_LC} CORE_NAME) string(TOUPPER ${CORE_NAME_LC} CORE_NAME)
target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME})
endif() endif()
endforeach() endforeach()
#if(WITH_LLVM) # if(WITH_LLVM)
# target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_LLVM) # target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_LLVM)
# #target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) # #target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
#endif() # endif()
#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,78 +179,85 @@ 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)
install(TARGETS tgc-sim install(TARGETS tgc-sim
EXPORT ${PROJECT_NAME}Targets # for downstream dependencies EXPORT ${PROJECT_NAME}Targets # for downstream dependencies
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # static lib ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # static lib
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # binaries RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # binaries
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # shared lib LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # shared lib
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} # for mac FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} # for mac
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} # headers for mac (note the different component -> different package) PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} # headers for mac (note the different component -> different package)
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers
) )
if(BUILD_TESTING) 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)
add_test(NAME tgc-sim-tcc if(WITH_TCC)
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend tcc) add_test(NAME tgc-sim-tcc
endif() COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend tcc)
if(WITH_LLVM) endif()
add_test(NAME tgc-sim-llvm
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend llvm) if(WITH_LLVM)
endif() add_test(NAME tgc-sim-llvm
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend llvm)
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()
###############################################################################
# ##############################################################################
# #
############################################################################### # ##############################################################################
if(TARGET scc-sysc) if(TARGET scc-sysc)
project(dbt-rise-tgc_sc VERSION 1.0.0) project(dbt-rise-tgc_sc VERSION 1.0.0)
set(LIB_SOURCES set(LIB_SOURCES
src/sysc/core_complex.cpp src/sysc/core_complex.cpp
src/sysc/register_tgc_c.cpp src/sysc/register_tgc_c.cpp
) )
FILE(GLOB GEN_SC_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/sysc/register_*.cpp) FILE(GLOB GEN_SC_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/sysc/register_*.cpp)
list(APPEND LIB_SOURCES ${GEN_SC_SOURCES}) list(APPEND LIB_SOURCES ${GEN_SC_SOURCES})
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})
string(TOUPPER ${CORE_NAME_LC} CORE_NAME) string(TOUPPER ${CORE_NAME_LC} CORE_NAME)
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)
# target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) # if(WITH_LLVM)
# endif() # target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
# 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}
FRAMEWORK FALSE FRAMEWORK FALSE
PUBLIC_HEADER "${LIB_HEADERS}" # specify the public headers PUBLIC_HEADER "${LIB_HEADERS}" # specify the public headers
) )
install(TARGETS ${PROJECT_NAME} COMPONENT ${PROJECT_NAME} install(TARGETS ${PROJECT_NAME} COMPONENT ${PROJECT_NAME}
EXPORT ${PROJECT_NAME}Targets # for downstream dependencies EXPORT ${PROJECT_NAME}Targets # for downstream dependencies
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # static lib ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # static lib
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # binaries RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # binaries
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # shared lib LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # shared lib
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} # for mac FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} # for mac
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sysc # headers for mac (note the different component -> different package) PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sysc # headers for mac (note the different component -> different package)
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers
) )
endif() endif()

View File

@ -349,7 +349,7 @@ 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

View File

@ -109,7 +109,7 @@ template <> struct traits<${coreDef.name.toLowerCase()}> {
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},<%}%>

View File

@ -127,10 +127,18 @@ 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, FuncSignatureT<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.mov(jh.pc,PC);
cc.comment(fmt::format("\\n${instr.name}_{:#x}:",pc.val).c_str()); cc.comment(fmt::format("\\n${instr.name}_{:#x}:",pc.val).c_str());
this->gen_sync(jh, PRE_SYNC, ${idx}); this->gen_sync(jh, PRE_SYNC, ${idx});
pc=pc+ ${instr.length/8}; pc=pc+ ${instr.length/8};
@ -263,16 +271,24 @@ std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreD
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<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|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<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}};
}) })
}; };

View File

@ -357,22 +357,30 @@ std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreD
} // namespace interp } // namespace interp
} // 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|interp", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{ core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](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 interp::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false); auto vm = new interp::${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|interp", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{ core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|interp", [](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 interp::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false); auto vm = new interp::${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}};
}) })
}; };

View File

@ -359,22 +359,30 @@ 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}};
}) })
}; };

View File

@ -323,22 +323,30 @@ 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<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|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<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}};
}) })
}; };

View File

@ -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)

View File

@ -35,8 +35,14 @@
#ifndef _RISCV_HART_COMMON #ifndef _RISCV_HART_COMMON
#define _RISCV_HART_COMMON #define _RISCV_HART_COMMON
#include "iss/arch_if.h"
#include <cstdint> #include <cstdint>
#include <elfio/elfio.hpp>
#include <fmt/format.h>
#include <iss/arch_if.h>
#include <iss/log_categories.h>
#include <string>
#include <unordered_map>
#include <util/logging.h>
namespace iss { namespace iss {
namespace arch { namespace arch {
@ -296,6 +302,61 @@ inline void write_reg_uint32(uint64_t offs, uint32_t& reg, const uint8_t* const
break; break;
} }
} }
struct riscv_hart_common {
riscv_hart_common(){};
~riscv_hart_common(){};
std::unordered_map<std::string, uint64_t> symbol_table;
std::unordered_map<std::string, uint64_t> get_sym_table(std::string name) {
if(!symbol_table.empty())
return symbol_table;
FILE* fp = fopen(name.c_str(), "r");
if(fp) {
std::array<char, 5> buf;
auto n = fread(buf.data(), 1, 4, fp);
fclose(fp);
if(n != 4)
throw std::runtime_error("input file has insufficient size");
buf[4] = 0;
if(strcmp(buf.data() + 1, "ELF") == 0) {
// Create elfio reader
ELFIO::elfio reader;
// Load ELF data
if(!reader.load(name))
throw std::runtime_error("could not process elf file");
// check elf properties
if(reader.get_type() != ET_EXEC)
throw std::runtime_error("wrong elf type in file");
if(reader.get_machine() != EM_RISCV)
throw std::runtime_error("wrong elf machine in file");
const auto sym_sec = reader.sections[".symtab"];
if(SHT_SYMTAB == sym_sec->get_type() || 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
}
}
}
return symbol_table;
}
throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file", name));
} else
throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name));
};
};
} // namespace arch } // namespace arch
} // namespace iss } // namespace iss

View File

@ -40,6 +40,7 @@
#include "iss/log_categories.h" #include "iss/log_categories.h"
#include "iss/vm_if.h" #include "iss/vm_if.h"
#include "riscv_hart_common.h" #include "riscv_hart_common.h"
#include <stdexcept>
#ifndef FMT_HEADER_ONLY #ifndef FMT_HEADER_ONLY
#define FMT_HEADER_ONLY #define FMT_HEADER_ONLY
#endif #endif
@ -55,6 +56,8 @@
#include <util/ities.h> #include <util/ities.h>
#include <util/sparse_array.h> #include <util/sparse_array.h>
#include <iss/semihosting/semihosting.h>
#if defined(__GNUC__) #if defined(__GNUC__)
#define likely(x) __builtin_expect(!!(x), 1) #define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0) #define unlikely(x) __builtin_expect(!!(x), 0)
@ -66,7 +69,7 @@
namespace iss { namespace iss {
namespace arch { namespace arch {
template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_m_p : public BASE { template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_m_p : public BASE, public riscv_hart_common {
protected: protected:
const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}}; const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
const std::array<const char*, 16> trap_str = {{"" const std::array<const char*, 16> trap_str = {{""
@ -290,6 +293,8 @@ public:
void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); } void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
void set_semihosting_callback(std::function<void(arch_if*, reg_t, reg_t)>& cb) { semihosting_cb = cb; };
protected: protected:
struct riscv_instrumentation_if : public iss::instrumentation_if { struct riscv_instrumentation_if : public iss::instrumentation_if {
@ -322,6 +327,8 @@ protected:
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; } unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
std::unordered_map<std::string, uint64_t> get_symbol_table(std::string name) override { return arch.get_sym_table(name); }
riscv_hart_m_p<BASE, FEAT>& arch; riscv_hart_m_p<BASE, FEAT>& arch;
}; };
@ -344,9 +351,11 @@ protected:
reg_t fault_data; reg_t fault_data;
uint64_t tohost = tohost_dflt; uint64_t tohost = tohost_dflt;
uint64_t fromhost = fromhost_dflt; uint64_t fromhost = fromhost_dflt;
unsigned to_host_wr_cnt = 0; bool tohost_lower_written = false;
riscv_instrumentation_if instr_if; riscv_instrumentation_if instr_if;
std::function<void(arch_if*, reg_t, reg_t)> semihosting_cb;
using mem_type = util::sparse_array<uint8_t, 1ULL << 32>; using mem_type = util::sparse_array<uint8_t, 1ULL << 32>;
using csr_type = util::sparse_array<typename traits<BASE>::reg_t, 1ULL << 12, 12>; using csr_type = util::sparse_array<typename traits<BASE>::reg_t, 1ULL << 12, 12>;
using csr_page_type = typename csr_type::page_type; using csr_page_type = typename csr_type::page_type;
@ -419,6 +428,7 @@ protected:
feature_config cfg; feature_config cfg;
unsigned mcause_max_irq{(FEAT & features_e::FEAT_CLIC) ? std::max(16U, static_cast<unsigned>(traits<BASE>::CLIC_NUM_IRQ)) : 16U}; unsigned mcause_max_irq{(FEAT & features_e::FEAT_CLIC) ? std::max(16U, static_cast<unsigned>(traits<BASE>::CLIC_NUM_IRQ)) : 16U};
inline bool debug_mode_active() { return this->reg.PRIV & 0x4; } inline bool debug_mode_active() { return this->reg.PRIV & 0x4; }
std::pair<std::function<mem_read_f>, std::function<mem_write_f>> replace_mem_access(std::function<mem_read_f> rd, std::pair<std::function<mem_read_f>, std::function<mem_write_f>> replace_mem_access(std::function<mem_read_f> rd,
std::function<mem_write_f> wr) { std::function<mem_write_f> wr) {
std::pair<std::function<mem_read_f>, std::function<mem_write_f>> ret{hart_mem_rd_delegate, hart_mem_wr_delegate}; std::pair<std::function<mem_read_f>, std::function<mem_write_f>> ret{hart_mem_rd_delegate, hart_mem_wr_delegate};
@ -563,6 +573,12 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p(feature_config cfg)
} }
template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m_p<BASE, FEAT>::load_file(std::string name, int type) { template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m_p<BASE, FEAT>::load_file(std::string name, int type) {
get_sym_table(name);
try {
tohost = symbol_table.at("tohost");
fromhost = symbol_table.at("fromhost");
} catch(std::out_of_range& e) {
}
FILE* fp = fopen(name.c_str(), "r"); FILE* fp = fopen(name.c_str(), "r");
if(fp) { if(fp) {
std::array<char, 5> buf; std::array<char, 5> buf;
@ -593,31 +609,11 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM, 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)); pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data));
if(res != iss::Ok) if(res != iss::Ok)
LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address(); CPPLOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address();
} }
} }
for(const auto sec : reader.sections) { for(const auto sec : reader.sections) {
if(sec->get_name() == ".symtab") { if(sec->get_name() == ".tohost") {
if(SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type()) {
ELFIO::symbol_section_accessor symbols(reader, 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 == "tohost") {
tohost = value;
} else if(name == "fromhost") {
fromhost = value;
}
}
}
} else if(sec->get_name() == ".tohost") {
tohost = sec->get_address(); tohost = sec->get_address();
fromhost = tohost + 0x40; fromhost = tohost + 0x40;
} }
@ -647,11 +643,11 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce
const unsigned length, uint8_t* const data) { const unsigned length, uint8_t* const data) {
#ifndef NDEBUG #ifndef NDEBUG
if(access && iss::access_type::DEBUG) { if(access && iss::access_type::DEBUG) {
LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr; CPPLOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr;
} else if(access && iss::access_type::FETCH) { } else if(access && iss::access_type::FETCH) {
LOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr; CPPLOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr;
} else { } else {
LOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr; CPPLOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr;
} }
#endif #endif
try { try {
@ -733,23 +729,23 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
switch(length) { switch(length) {
case 8: case 8:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
case 4: case 4:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
case 2: case 2:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
case 1: case 1:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
default: default:
LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr; CPPLOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr;
} }
#endif #endif
try { try {
@ -784,7 +780,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
res = write_mem(phys_addr, length, data); res = write_mem(phys_addr, length, data);
} }
if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) { if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) {
this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) this->reg.trap_state = (1UL << 31) | (7UL << 16); // issue trap 7 (Store/AMO access fault)
fault_data = addr; fault_data = addr;
} }
return res; return res;
@ -801,7 +797,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
case 0x10023000: // UART1 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg
uart_buf << (char)data[0]; uart_buf << (char)data[0];
if(((char)data[0]) == '\n' || data[0] == 0) { if(((char)data[0]) == '\n' || data[0] == 0) {
// LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send // CPPLOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send
// '"<<uart_buf.str()<<"'"; // '"<<uart_buf.str()<<"'";
std::cout << uart_buf.str(); std::cout << uart_buf.str();
uart_buf.str(""); uart_buf.str("");
@ -1098,9 +1094,10 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned len
template <typename BASE, features_e FEAT> template <typename BASE, features_e FEAT>
iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) { iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) {
switch(paddr.val) { switch(paddr.val) {
// TODO remove UART, Peripherals should not be part of the ISS
case 0xFFFF0000: // UART0 base, TXFIFO reg case 0xFFFF0000: // UART0 base, TXFIFO reg
if(((char)data[0]) == '\n' || data[0] == 0) { if(((char)data[0]) == '\n' || data[0] == 0) {
LOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'"; CPPLOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'";
uart_buf.str(""); uart_buf.str("");
} else if(((char)data[0]) != '\r') } else if(((char)data[0]) != '\r')
uart_buf << (char)data[0]; uart_buf << (char)data[0];
@ -1115,15 +1112,16 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned le
auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost); auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
if(tohost_lower || tohost_upper) { if(tohost_lower || tohost_upper) {
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)); uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { // in case of 32 bit system, two writes to tohost are needed, only evaluate on the second (high) write
if(tohost_upper && (tohost_lower || tohost_lower_written)) {
switch(hostvar >> 48) { switch(hostvar >> 48) {
case 0: case 0:
if(hostvar != 0x1) { if(hostvar != 0x1) {
LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar CPPLOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
<< "), stopping simulation"; << "), stopping simulation";
} else { } else {
LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar CPPLOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
<< "), stopping simulation"; << "), stopping simulation";
} }
this->reg.trap_state = std::numeric_limits<uint32_t>::max(); this->reg.trap_state = std::numeric_limits<uint32_t>::max();
this->interrupt_sim = hostvar; this->interrupt_sim = hostvar;
@ -1134,17 +1132,17 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned le
case 0x0101: { case 0x0101: {
char c = static_cast<char>(hostvar & 0xff); char c = static_cast<char>(hostvar & 0xff);
if(c == '\n' || c == 0) { if(c == '\n' || c == 0) {
LOG(INFO) << "tohost send '" << uart_buf.str() << "'"; CPPLOG(INFO) << "tohost send '" << uart_buf.str() << "'";
uart_buf.str(""); uart_buf.str("");
} else } else
uart_buf << c; uart_buf << c;
to_host_wr_cnt = 0;
} break; } break;
default: default:
break; break;
} }
tohost_lower_written = false;
} else if(tohost_lower) } else if(tohost_lower)
to_host_wr_cnt++; tohost_lower_written = true;
} else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) { } else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask)); uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
@ -1253,6 +1251,31 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::e
} else { } else {
csr[mtval] = addr; csr[mtval] = addr;
} }
if(semihosting_cb) {
// Check for semihosting call
phys_addr_t p_addr(access_type::DEBUG_READ, traits<BASE>::MEM, addr - 4);
std::array<uint8_t, 8> data;
// check for SLLI_X0_X0_0X1F and SRAI_X0_X0_0X07
this->read_mem(p_addr, 4, data.data());
p_addr.val += 8;
this->read_mem(p_addr, 4, data.data() + 4);
const std::array<uint8_t, 8> ref_data = {0x13, 0x10, 0xf0, 0x01, 0x13, 0x50, 0x70, 0x40};
if(data == ref_data) {
this->reg.NEXT_PC = addr + 8;
std::array<char, 32> buffer;
#if defined(_MSC_VER)
sprintf(buffer.data(), "0x%016llx", addr);
#else
sprintf(buffer.data(), "0x%016lx", addr);
#endif
CLOG(INFO, disass) << "Semihosting call at address " << buffer.data() << " occurred ";
semihosting_callback(this, this->reg.X10 /*a0*/, this->reg.X11 /*a1*/);
return this->reg.NEXT_PC;
}
}
break; break;
case 4: case 4:
case 6: case 6:

View File

@ -55,6 +55,8 @@
#include <util/ities.h> #include <util/ities.h>
#include <util/sparse_array.h> #include <util/sparse_array.h>
#include <iss/semihosting/semihosting.h>
#if defined(__GNUC__) #if defined(__GNUC__)
#define likely(x) __builtin_expect(!!(x), 1) #define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0) #define unlikely(x) __builtin_expect(!!(x), 0)
@ -66,7 +68,7 @@
namespace iss { namespace iss {
namespace arch { namespace arch {
template <typename BASE> class riscv_hart_msu_vp : public BASE { template <typename BASE> class riscv_hart_msu_vp : public BASE, public riscv_hart_common {
protected: protected:
const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}}; const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
const std::array<const char*, 16> trap_str = {{"" const std::array<const char*, 16> trap_str = {{""
@ -341,6 +343,8 @@ public:
void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); } void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
void set_semihosting_callback(std::function<void(arch_if*, reg_t, reg_t)>& cb) { semihosting_cb = cb; };
protected: protected:
struct riscv_instrumentation_if : public iss::instrumentation_if { struct riscv_instrumentation_if : public iss::instrumentation_if {
@ -373,6 +377,8 @@ protected:
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; } unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
std::unordered_map<std::string, uint64_t> get_symbol_table(std::string name) override { return arch.get_sym_table(name); }
riscv_hart_msu_vp<BASE>& arch; riscv_hart_msu_vp<BASE>& arch;
}; };
@ -395,9 +401,11 @@ protected:
std::array<vm_info, 2> vm; std::array<vm_info, 2> vm;
uint64_t tohost = tohost_dflt; uint64_t tohost = tohost_dflt;
uint64_t fromhost = fromhost_dflt; uint64_t fromhost = fromhost_dflt;
unsigned to_host_wr_cnt = 0; bool tohost_lower_written = false;
riscv_instrumentation_if instr_if; riscv_instrumentation_if instr_if;
std::function<void(arch_if*, reg_t, reg_t)> semihosting_cb;
using mem_type = util::sparse_array<uint8_t, 1ULL << 32>; using mem_type = util::sparse_array<uint8_t, 1ULL << 32>;
using csr_type = util::sparse_array<typename traits<BASE>::reg_t, 1ULL << 12, 12>; using csr_type = util::sparse_array<typename traits<BASE>::reg_t, 1ULL << 12, 12>;
using csr_page_type = typename csr_type::page_type; using csr_page_type = typename csr_type::page_type;
@ -585,7 +593,7 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM, 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)); pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data));
if(res != iss::Ok) if(res != iss::Ok)
LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address(); CPPLOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address();
} }
} }
for(const auto sec : reader.sections) { for(const auto sec : reader.sections) {
@ -626,11 +634,11 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
const unsigned length, uint8_t* const data) { const unsigned length, uint8_t* const data) {
#ifndef NDEBUG #ifndef NDEBUG
if(access && iss::access_type::DEBUG) { if(access && iss::access_type::DEBUG) {
LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr; CPPLOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr;
} else if(access && iss::access_type::FETCH) { } else if(access && iss::access_type::FETCH) {
LOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr; CPPLOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr;
} else { } else {
LOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr; CPPLOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr;
} }
#endif #endif
try { try {
@ -720,23 +728,23 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
switch(length) { switch(length) {
case 8: case 8:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
case 4: case 4:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
case 2: case 2:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
case 1: case 1:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
default: default:
LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr; CPPLOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr;
} }
#endif #endif
try { try {
@ -781,7 +789,7 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
case 0x10023000: // UART1 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg
uart_buf << (char)data[0]; uart_buf << (char)data[0];
if(((char)data[0]) == '\n' || data[0] == 0) { if(((char)data[0]) == '\n' || data[0] == 0) {
// LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send // CPPLOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send
// '"<<uart_buf.str()<<"'"; // '"<<uart_buf.str()<<"'";
std::cout << uart_buf.str(); std::cout << uart_buf.str();
uart_buf.str(""); uart_buf.str("");
@ -1077,7 +1085,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_add
switch(paddr.val) { switch(paddr.val) {
case 0xFFFF0000: // UART0 base, TXFIFO reg case 0xFFFF0000: // UART0 base, TXFIFO reg
if(((char)data[0]) == '\n' || data[0] == 0) { if(((char)data[0]) == '\n' || data[0] == 0) {
LOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'"; CPPLOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'";
uart_buf.str(""); uart_buf.str("");
} else if(((char)data[0]) != '\r') } else if(((char)data[0]) != '\r')
uart_buf << (char)data[0]; uart_buf << (char)data[0];
@ -1092,34 +1100,37 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_add
auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost); auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
if(tohost_lower || tohost_upper) { if(tohost_lower || tohost_upper) {
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)); uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { // in case of 32 bit system, two writes to tohost are needed, only evaluate on the second (high) write
if(tohost_upper && (tohost_lower || tohost_lower_written)) {
switch(hostvar >> 48) { switch(hostvar >> 48) {
case 0: case 0:
if(hostvar != 0x1) { if(hostvar != 0x1) {
LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar CPPLOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
<< "), stopping simulation"; << "), stopping simulation";
} else { } else {
LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar CPPLOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
<< "), stopping simulation"; << "), stopping simulation";
} }
this->reg.trap_state = std::numeric_limits<uint32_t>::max(); this->reg.trap_state = std::numeric_limits<uint32_t>::max();
this->interrupt_sim = hostvar; this->interrupt_sim = hostvar;
#ifndef WITH_TCC
throw(iss::simulation_stopped(hostvar));
#endif
break; break;
// throw(iss::simulation_stopped(hostvar));
case 0x0101: { case 0x0101: {
char c = static_cast<char>(hostvar & 0xff); char c = static_cast<char>(hostvar & 0xff);
if(c == '\n' || c == 0) { if(c == '\n' || c == 0) {
LOG(INFO) << "tohost send '" << uart_buf.str() << "'"; CPPLOG(INFO) << "tohost send '" << uart_buf.str() << "'";
uart_buf.str(""); uart_buf.str("");
} else } else
uart_buf << c; uart_buf << c;
to_host_wr_cnt = 0;
} break; } break;
default: default:
break; break;
} }
tohost_lower_written = false;
} else if(tohost_lower) } else if(tohost_lower)
to_host_wr_cnt++; tohost_lower_written = true;
} else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) { } else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask)); uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
@ -1304,6 +1315,31 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
// csr[dpc] = addr; // csr[dpc] = addr;
// csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi) // csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi)
csr[utval | (new_priv << 8)] = addr; csr[utval | (new_priv << 8)] = addr;
if(semihosting_cb) {
// Check for semihosting call
phys_addr_t p_addr(access_type::DEBUG_READ, traits<BASE>::MEM, addr - 4);
std::array<uint8_t, 8> data;
// check for SLLI_X0_X0_0X1F and SRAI_X0_X0_0X07
this->read_mem(p_addr, 4, data.data());
p_addr.val += 8;
this->read_mem(p_addr, 4, data.data() + 4);
const std::array<uint8_t, 8> ref_data = {0x13, 0x10, 0xf0, 0x01, 0x13, 0x50, 0x70, 0x40};
if(data == ref_data) {
this->reg.NEXT_PC = addr + 8;
std::array<char, 32> buffer;
#if defined(_MSC_VER)
sprintf(buffer.data(), "0x%016llx", addr);
#else
sprintf(buffer.data(), "0x%016lx", addr);
#endif
CLOG(INFO, disass) << "Semihosting call at address " << buffer.data() << " occurred ";
semihosting_callback(this, this->reg.X10 /*a0*/, this->reg.X11 /*a1*/);
return this->reg.NEXT_PC;
}
}
break; break;
case 4: case 4:
case 6: case 6:
@ -1321,7 +1357,7 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
this->reg.pending_trap = 0; this->reg.pending_trap = 0;
} }
size_t adr = ucause | (new_priv << 8); size_t adr = ucause | (new_priv << 8);
csr[adr] = (trap_id << 31) + cause; csr[adr] = (trap_id << (traits<BASE>::XLEN - 1)) + cause;
// update mstatus // update mstatus
// xPP field of mstatus is written with the active privilege mode at the time // xPP field of mstatus is written with the active privilege mode at the time
// of the trap; the x PIE field of mstatus // of the trap; the x PIE field of mstatus

View File

@ -55,6 +55,8 @@
#include <util/ities.h> #include <util/ities.h>
#include <util/sparse_array.h> #include <util/sparse_array.h>
#include <iss/semihosting/semihosting.h>
#if defined(__GNUC__) #if defined(__GNUC__)
#define likely(x) __builtin_expect(!!(x), 1) #define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0) #define unlikely(x) __builtin_expect(!!(x), 0)
@ -66,7 +68,7 @@
namespace iss { namespace iss {
namespace arch { namespace arch {
template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_mu_p : public BASE { template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_mu_p : public BASE, public riscv_hart_common {
protected: protected:
const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}}; const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
const std::array<const char*, 16> trap_str = {{"" const std::array<const char*, 16> trap_str = {{""
@ -317,6 +319,8 @@ public:
void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); } void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
void set_semihosting_callback(std::function<void(arch_if*, reg_t, reg_t)>& cb) { semihosting_cb = cb; };
protected: protected:
struct riscv_instrumentation_if : public iss::instrumentation_if { struct riscv_instrumentation_if : public iss::instrumentation_if {
@ -349,6 +353,8 @@ protected:
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; } unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
std::unordered_map<std::string, uint64_t> get_symbol_table(std::string name) override { return arch.get_sym_table(name); }
riscv_hart_mu_p<BASE, FEAT>& arch; riscv_hart_mu_p<BASE, FEAT>& arch;
}; };
@ -371,9 +377,11 @@ protected:
reg_t fault_data; reg_t fault_data;
uint64_t tohost = tohost_dflt; uint64_t tohost = tohost_dflt;
uint64_t fromhost = fromhost_dflt; uint64_t fromhost = fromhost_dflt;
unsigned to_host_wr_cnt = 0; bool tohost_lower_written = false;
riscv_instrumentation_if instr_if; riscv_instrumentation_if instr_if;
std::function<void(arch_if*, reg_t, reg_t)> semihosting_cb;
using mem_type = util::sparse_array<uint8_t, 1ULL << 32>; using mem_type = util::sparse_array<uint8_t, 1ULL << 32>;
using csr_type = util::sparse_array<typename traits<BASE>::reg_t, 1ULL << 12, 12>; using csr_type = util::sparse_array<typename traits<BASE>::reg_t, 1ULL << 12, 12>;
using csr_page_type = typename csr_type::page_type; using csr_page_type = typename csr_type::page_type;
@ -672,7 +680,7 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM, 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)); pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data));
if(res != iss::Ok) if(res != iss::Ok)
LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address(); CPPLOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address();
} }
} }
for(const auto sec : reader.sections) { for(const auto sec : reader.sections) {
@ -812,11 +820,11 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
const unsigned length, uint8_t* const data) { const unsigned length, uint8_t* const data) {
#ifndef NDEBUG #ifndef NDEBUG
if(access && iss::access_type::DEBUG) { if(access && iss::access_type::DEBUG) {
LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr; CPPLOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr;
} else if(is_fetch(access)) { } else if(is_fetch(access)) {
LOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr; CPPLOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr;
} else { } else {
LOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr; CPPLOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr;
} }
#endif #endif
try { try {
@ -907,23 +915,23 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
switch(length) { switch(length) {
case 8: case 8:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
case 4: case 4:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
case 2: case 2:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
case 1: case 1:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
default: default:
LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr; CPPLOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr;
} }
#endif #endif
try { try {
@ -984,7 +992,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
case 0x10023000: // UART1 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg
uart_buf << (char)data[0]; uart_buf << (char)data[0];
if(((char)data[0]) == '\n' || data[0] == 0) { if(((char)data[0]) == '\n' || data[0] == 0) {
// LOG(INFO)<<"UART"<<((addr>>16)&0x3)<<" send // CPPLOG(INFO)<<"UART"<<((addr>>16)&0x3)<<" send
// '"<<uart_buf.str()<<"'"; // '"<<uart_buf.str()<<"'";
std::cout << uart_buf.str(); std::cout << uart_buf.str();
uart_buf.str(""); uart_buf.str("");
@ -1317,9 +1325,10 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned le
template <typename BASE, features_e FEAT> template <typename BASE, features_e FEAT>
iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) { iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) {
switch(paddr.val) { switch(paddr.val) {
// TODO remove UART, Peripherals should not be part of the ISS
case 0xFFFF0000: // UART0 base, TXFIFO reg case 0xFFFF0000: // UART0 base, TXFIFO reg
if(((char)data[0]) == '\n' || data[0] == 0) { if(((char)data[0]) == '\n' || data[0] == 0) {
LOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'"; CPPLOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'";
uart_buf.str(""); uart_buf.str("");
} else if(((char)data[0]) != '\r') } else if(((char)data[0]) != '\r')
uart_buf << (char)data[0]; uart_buf << (char)data[0];
@ -1334,34 +1343,37 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned l
auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost); auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
if(tohost_lower || tohost_upper) { if(tohost_lower || tohost_upper) {
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)); uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { // in case of 32 bit system, two writes to tohost are needed, only evaluate on the second (high) write
if(tohost_upper && (tohost_lower || tohost_lower_written)) {
switch(hostvar >> 48) { switch(hostvar >> 48) {
case 0: case 0:
if(hostvar != 0x1) { if(hostvar != 0x1) {
LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar CPPLOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
<< "), stopping simulation"; << "), stopping simulation";
} else { } else {
LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar CPPLOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
<< "), stopping simulation"; << "), stopping simulation";
} }
this->reg.trap_state = std::numeric_limits<uint32_t>::max(); this->reg.trap_state = std::numeric_limits<uint32_t>::max();
this->interrupt_sim = hostvar; this->interrupt_sim = hostvar;
#ifndef WITH_TCC
throw(iss::simulation_stopped(hostvar));
#endif
break; break;
// throw(iss::simulation_stopped(hostvar));
case 0x0101: { case 0x0101: {
char c = static_cast<char>(hostvar & 0xff); char c = static_cast<char>(hostvar & 0xff);
if(c == '\n' || c == 0) { if(c == '\n' || c == 0) {
LOG(INFO) << "tohost send '" << uart_buf.str() << "'"; CPPLOG(INFO) << "tohost send '" << uart_buf.str() << "'";
uart_buf.str(""); uart_buf.str("");
} else } else
uart_buf << c; uart_buf << c;
to_host_wr_cnt = 0;
} break; } break;
default: default:
break; break;
} }
tohost_lower_written = false;
} else if(tohost_lower) } else if(tohost_lower)
to_host_wr_cnt++; tohost_lower_written = true;
} else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) { } else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask)); uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
@ -1474,6 +1486,31 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::
} else { } else {
csr[utval | (new_priv << 8)] = addr; csr[utval | (new_priv << 8)] = addr;
} }
if(semihosting_cb) {
// Check for semihosting call
phys_addr_t p_addr(access_type::DEBUG_READ, traits<BASE>::MEM, addr - 4);
std::array<uint8_t, 8> data;
// check for SLLI_X0_X0_0X1F and SRAI_X0_X0_0X07
this->read_mem(p_addr, 4, data.data());
p_addr.val += 8;
this->read_mem(p_addr, 4, data.data() + 4);
const std::array<uint8_t, 8> ref_data = {0x13, 0x10, 0xf0, 0x01, 0x13, 0x50, 0x70, 0x40};
if(data == ref_data) {
this->reg.NEXT_PC = addr + 8;
std::array<char, 32> buffer;
#if defined(_MSC_VER)
sprintf(buffer.data(), "0x%016llx", addr);
#else
sprintf(buffer.data(), "0x%016lx", addr);
#endif
CLOG(INFO, disass) << "Semihosting call at address " << buffer.data() << " occurred ";
semihosting_callback(this, this->reg.X10 /*a0*/, this->reg.X11 /*a1*/);
return this->reg.NEXT_PC;
}
}
break; break;
case 4: case 4:
case 6: case 6:

View File

@ -81,7 +81,7 @@ template <> struct traits<tgc5c> {
enum sreg_flag_e { FLAGS }; enum sreg_flag_e { FLAGS };
enum mem_type_e { MEM, FENCE, RES, CSR }; enum mem_type_e { MEM, FENCE, RES, CSR, IMEM = MEM };
enum class opcode_e { enum class opcode_e {
LUI = 0, LUI = 0,

View File

@ -174,7 +174,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::current_thread_query
} }
template <typename ARCH> status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t>& data, std::vector<uint8_t>& avail) { template <typename ARCH> status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
LOG(TRACE) << "reading target registers"; CPPLOG(TRACE) << "reading target registers";
// return idx<0?:; // return idx<0?:;
data.clear(); data.clear();
avail.clear(); avail.clear();
@ -328,9 +328,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 << saddr.val CPPLOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex << 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;
} }
} }
@ -345,13 +345,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 << std::dec; CPPLOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val << 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;
} }
} }

View File

@ -61,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;
@ -87,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;
} }
} }

View File

@ -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,7 +81,7 @@ 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++;
} }
} }

View File

@ -0,0 +1,132 @@
#include "semihosting.h"
#include <cstdint>
#include <iss/vm_types.h>
#include <stdexcept>
// explanation of syscalls can be found at https://github.com/SpinalHDL/openocd_riscv/blob/riscv_spinal/src/target/semihosting_common.h
template <typename T> void semihosting_callback(iss::arch_if* arch_if_ptr, T call_number, T parameter) {
switch(static_cast<semihosting_syscalls>(call_number)) {
case semihosting_syscalls::SYS_CLOCK: {
throw std::runtime_error("Semihosting Call not Implemented");
break;
}
case semihosting_syscalls::SYS_CLOSE: {
throw std::runtime_error("Semihosting Call not Implemented");
break;
}
case semihosting_syscalls::SYS_ELAPSED: {
throw std::runtime_error("Semihosting Call not Implemented");
break;
}
case semihosting_syscalls::SYS_ERRNO: {
throw std::runtime_error("Semihosting Call not Implemented");
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: {
throw std::runtime_error("Semihosting Call not Implemented");
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: {
throw std::runtime_error("Semihosting Call not Implemented");
break;
}
case semihosting_syscalls::SYS_ISTTY: {
throw std::runtime_error("Semihosting Call not Implemented");
break;
}
case semihosting_syscalls::SYS_OPEN: {
throw std::runtime_error("Semihosting Call not Implemented");
break;
}
case semihosting_syscalls::SYS_READ: {
throw std::runtime_error("Semihosting Call not Implemented");
break;
}
case semihosting_syscalls::SYS_READC: {
throw std::runtime_error("Semihosting Call not Implemented");
break;
}
case semihosting_syscalls::SYS_REMOVE: {
throw std::runtime_error("Semihosting Call not Implemented");
break;
}
case semihosting_syscalls::SYS_RENAME: {
throw std::runtime_error("Semihosting Call not Implemented");
break;
}
case semihosting_syscalls::SYS_SEEK: {
throw std::runtime_error("Semihosting Call not Implemented");
break;
}
case semihosting_syscalls::SYS_SYSTEM: {
throw std::runtime_error("Semihosting Call not Implemented");
break;
}
case semihosting_syscalls::SYS_TICKFREQ: {
throw std::runtime_error("Semihosting Call not Implemented");
break;
}
case semihosting_syscalls::SYS_TIME: {
throw std::runtime_error("Semihosting Call not Implemented");
break;
}
case semihosting_syscalls::SYS_TMPNAM: {
throw std::runtime_error("Semihosting Call not Implemented");
break;
}
case semihosting_syscalls::SYS_WRITE: {
throw std::runtime_error("Semihosting Call not Implemented");
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 void semihosting_callback<uint32_t>(iss::arch_if* arch_if_ptr, uint32_t call_number, uint32_t parameter);
template void semihosting_callback<uint64_t>(iss::arch_if* arch_if_ptr, uint64_t call_number, uint64_t parameter);

View File

@ -0,0 +1,53 @@
#ifndef _SEMIHOSTING_H_
#define _SEMIHOSTING_H_
#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> void semihosting_callback(iss::arch_if* arch_if_ptr, T call_number, T parameter);
#endif

View File

@ -31,8 +31,12 @@
*******************************************************************************/ *******************************************************************************/
#include <array> #include <array>
#include <cstdint>
#include <iostream> #include <iostream>
#include <iss/factory.h> #include <iss/factory.h>
#include <iss/semihosting/semihosting.h>
#include <string>
#include <unordered_map>
#include <vector> #include <vector>
#include "iss/arch/tgc_mapper.h" #include "iss/arch/tgc_mapper.h"
@ -52,7 +56,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
@ -116,6 +119,7 @@ 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};
std::function<void(iss::arch_if*, uint32_t, uint32_t)> semihosting_cb = &semihosting_callback<uint32_t>;
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 +127,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 +136,14 @@ 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; CPPLOG(ERR) << "Could not create cpu for isa " << isa_opt << " and backend " << clim["backend"].as<std::string>() << 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 +179,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,12 +201,12 @@ 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) if(start_addr.second) // FIXME: this always evaluates to true as load file always returns <sth, true>
start_address = start_addr.first; start_address = start_addr.first;
} }
for(std::string input : args) { for(std::string input : args) {
auto start_addr = vm->get_arch()->load_file(input); // treat remaining arguments as elf files auto start_addr = vm->get_arch()->load_file(input); // treat remaining arguments as elf files
if(start_addr.second) if(start_addr.second) // FIXME: this always evaluates to true as load file always returns <sth, true>
start_address = start_addr.first; start_address = start_addr.first;
} }
if(clim.count("reset")) { if(clim.count("reset")) {
@ -211,11 +216,42 @@ int main(int argc, char* argv[]) {
vm->reset(start_address); vm->reset(start_address);
auto cycles = clim["instructions"].as<uint64_t>(); auto cycles = clim["instructions"].as<uint64_t>();
res = vm->start(cycles, dump); res = vm->start(cycles, dump);
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;
}
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" << std::endl; CPPLOG(ERR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" << 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;
} }

View File

@ -1,4 +1,5 @@
#include <asmjit/asmjit.h>
#include <iss/asmjit/jit_helper.h>
x86::Mem get_reg_ptr(jit_holder& jh, unsigned idx) { x86::Mem get_reg_ptr(jit_holder& jh, unsigned idx) {
@ -74,6 +75,7 @@ inline void write_reg_to_mem(jit_holder& jh, x86::Gp reg, unsigned idx) {
void gen_instr_prologue(jit_holder& jh, addr_t pc) { void gen_instr_prologue(jit_holder& jh, addr_t pc) {
auto& cc = jh.cc; auto& cc = jh.cc;
cc.mov(jh.pc, pc);
cc.comment("\n//(*icount)++;"); cc.comment("\n//(*icount)++;");
cc.inc(get_reg_ptr(jh, traits::ICOUNT)); cc.inc(get_reg_ptr(jh, traits::ICOUNT));
@ -534,4 +536,4 @@ inline void gen_write_mem(jit_holder& jh, mem_type_e type, uint64_t addr, int64_
auto addr_reg = jh.cc.newUInt64(); auto addr_reg = jh.cc.newUInt64();
jh.cc.mov(addr_reg, addr); jh.cc.mov(addr_reg, addr);
gen_write_mem(jh, type, addr_reg, val_reg, length); gen_write_mem(jh, type, addr_reg, val_reg, length);
} }

File diff suppressed because it is too large Load Diff

View File

@ -429,7 +429,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
else { else {
if(rd != 0) { if(rd != 0) {
*(X+rd) = (uint32_t)(*PC + (int32_t)imm); *(X+rd) = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int32_t)imm ));
} }
} }
} }
@ -459,9 +459,9 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
else { else {
if(rd != 0) { if(rd != 0) {
*(X+rd) = (uint32_t)(*PC + 4); *(X+rd) = (uint32_t)((uint64_t)(*PC ) + (uint64_t)( 4 ));
} }
*NEXT_PC = (uint32_t)(*PC + (int32_t)sext<21>(imm)); *NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int32_t)sext<21>(imm) ));
this->core.reg.last_branch = 1; this->core.reg.last_branch = 1;
} }
} }
@ -489,13 +489,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
else { else {
uint32_t addr_mask = (uint32_t)- 2; uint32_t addr_mask = (uint32_t)- 2;
uint32_t new_pc = (uint32_t)((*(X+rs1) + (int16_t)sext<12>(imm)) & addr_mask); uint32_t new_pc = (uint32_t)(((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) )) & (int64_t)(addr_mask ));
if(new_pc % traits::INSTR_ALIGNMENT) { if(new_pc % traits::INSTR_ALIGNMENT) {
raise(0, 0); raise(0, 0);
} }
else { else {
if(rd != 0) { if(rd != 0) {
*(X+rd) = (uint32_t)(*PC + 4); *(X+rd) = (uint32_t)((uint64_t)(*PC ) + (uint64_t)( 4 ));
} }
*NEXT_PC = new_pc; *NEXT_PC = new_pc;
this->core.reg.last_branch = 1; this->core.reg.last_branch = 1;
@ -525,11 +525,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
else { else {
if(*(X+rs1) == *(X+rs2)) { if(*(X+rs1) == *(X+rs2)) {
if(imm % traits::INSTR_ALIGNMENT) { if((uint32_t)(imm ) % traits::INSTR_ALIGNMENT) {
raise(0, 0); raise(0, 0);
} }
else { else {
*NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); *NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) ));
this->core.reg.last_branch = 1; this->core.reg.last_branch = 1;
} }
} }
@ -558,11 +558,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
else { else {
if(*(X+rs1) != *(X+rs2)) { if(*(X+rs1) != *(X+rs2)) {
if(imm % traits::INSTR_ALIGNMENT) { if((uint32_t)(imm ) % traits::INSTR_ALIGNMENT) {
raise(0, 0); raise(0, 0);
} }
else { else {
*NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); *NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) ));
this->core.reg.last_branch = 1; this->core.reg.last_branch = 1;
} }
} }
@ -591,11 +591,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
else { else {
if((int32_t)*(X+rs1) < (int32_t)*(X+rs2)) { if((int32_t)*(X+rs1) < (int32_t)*(X+rs2)) {
if(imm % traits::INSTR_ALIGNMENT) { if((uint32_t)(imm ) % traits::INSTR_ALIGNMENT) {
raise(0, 0); raise(0, 0);
} }
else { else {
*NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); *NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) ));
this->core.reg.last_branch = 1; this->core.reg.last_branch = 1;
} }
} }
@ -624,11 +624,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
else { else {
if((int32_t)*(X+rs1) >= (int32_t)*(X+rs2)) { if((int32_t)*(X+rs1) >= (int32_t)*(X+rs2)) {
if(imm % traits::INSTR_ALIGNMENT) { if((uint32_t)(imm ) % traits::INSTR_ALIGNMENT) {
raise(0, 0); raise(0, 0);
} }
else { else {
*NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); *NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) ));
this->core.reg.last_branch = 1; this->core.reg.last_branch = 1;
} }
} }
@ -657,11 +657,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
else { else {
if(*(X+rs1) < *(X+rs2)) { if(*(X+rs1) < *(X+rs2)) {
if(imm % traits::INSTR_ALIGNMENT) { if((uint32_t)(imm ) % traits::INSTR_ALIGNMENT) {
raise(0, 0); raise(0, 0);
} }
else { else {
*NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); *NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) ));
this->core.reg.last_branch = 1; this->core.reg.last_branch = 1;
} }
} }
@ -690,11 +690,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
else { else {
if(*(X+rs1) >= *(X+rs2)) { if(*(X+rs1) >= *(X+rs2)) {
if(imm % traits::INSTR_ALIGNMENT) { if((uint32_t)(imm ) % traits::INSTR_ALIGNMENT) {
raise(0, 0); raise(0, 0);
} }
else { else {
*NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); *NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) ));
this->core.reg.last_branch = 1; this->core.reg.last_branch = 1;
} }
} }
@ -722,7 +722,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2); raise(0, 2);
} }
else { else {
uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); uint32_t load_address = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) ));
int8_t res_27 = super::template read_mem<int8_t>(traits::MEM, load_address); int8_t res_27 = super::template read_mem<int8_t>(traits::MEM, load_address);
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
int8_t res = (int8_t)res_27; int8_t res = (int8_t)res_27;
@ -753,7 +753,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2); raise(0, 2);
} }
else { else {
uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); uint32_t load_address = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) ));
int16_t res_28 = super::template read_mem<int16_t>(traits::MEM, load_address); int16_t res_28 = super::template read_mem<int16_t>(traits::MEM, load_address);
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
int16_t res = (int16_t)res_28; int16_t res = (int16_t)res_28;
@ -784,7 +784,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2); raise(0, 2);
} }
else { else {
uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); uint32_t load_address = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) ));
int32_t res_29 = super::template read_mem<int32_t>(traits::MEM, load_address); int32_t res_29 = super::template read_mem<int32_t>(traits::MEM, load_address);
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
int32_t res = (int32_t)res_29; int32_t res = (int32_t)res_29;
@ -815,7 +815,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2); raise(0, 2);
} }
else { else {
uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); uint32_t load_address = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) ));
uint8_t res_30 = super::template read_mem<uint8_t>(traits::MEM, load_address); uint8_t res_30 = super::template read_mem<uint8_t>(traits::MEM, load_address);
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
uint8_t res = res_30; uint8_t res = res_30;
@ -846,7 +846,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2); raise(0, 2);
} }
else { else {
uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); uint32_t load_address = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) ));
uint16_t res_31 = super::template read_mem<uint16_t>(traits::MEM, load_address); uint16_t res_31 = super::template read_mem<uint16_t>(traits::MEM, load_address);
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
uint16_t res = res_31; uint16_t res = res_31;
@ -877,7 +877,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2); raise(0, 2);
} }
else { else {
uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); uint32_t store_address = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) ));
super::template write_mem<uint8_t>(traits::MEM, store_address, (uint8_t)*(X+rs2)); super::template write_mem<uint8_t>(traits::MEM, store_address, (uint8_t)*(X+rs2));
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
} }
@ -904,7 +904,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2); raise(0, 2);
} }
else { else {
uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); uint32_t store_address = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) ));
super::template write_mem<uint16_t>(traits::MEM, store_address, (uint16_t)*(X+rs2)); super::template write_mem<uint16_t>(traits::MEM, store_address, (uint16_t)*(X+rs2));
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
} }
@ -931,7 +931,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2); raise(0, 2);
} }
else { else {
uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); uint32_t store_address = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) ));
super::template write_mem<uint32_t>(traits::MEM, store_address, (uint32_t)*(X+rs2)); super::template write_mem<uint32_t>(traits::MEM, store_address, (uint32_t)*(X+rs2));
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
} }
@ -959,7 +959,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
else { else {
if(rd != 0) { if(rd != 0) {
*(X+rd) = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); *(X+rd) = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) ));
} }
} }
} }
@ -1202,7 +1202,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
else { else {
if(rd != 0) { if(rd != 0) {
*(X+rd) = (uint32_t)(*(X+rs1) + *(X+rs2)); *(X+rd) = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)(*(X+rs2) ));
} }
} }
} }
@ -1229,7 +1229,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
else { else {
if(rd != 0) { if(rd != 0) {
*(X+rd) = (uint32_t)(*(X+rs1) - *(X+rs2)); *(X+rd) = (uint32_t)((uint64_t)(*(X+rs1) ) - (uint64_t)(*(X+rs2) ));
} }
} }
} }
@ -1256,7 +1256,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
else { else {
if(rd != 0) { if(rd != 0) {
*(X+rd) = *(X+rs1) << (*(X+rs2) & (traits::XLEN - 1)); *(X+rd) = *(X+rs1) << ((uint64_t)(*(X+rs2) ) & ((uint64_t)(traits::XLEN ) - (uint64_t)( 1 )));
} }
} }
} }
@ -1364,7 +1364,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
else { else {
if(rd != 0) { if(rd != 0) {
*(X+rd) = *(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1)); *(X+rd) = *(X+rs1) >> ((uint64_t)(*(X+rs2) ) & ((uint64_t)(traits::XLEN ) - (uint64_t)( 1 )));
} }
} }
} }
@ -1391,7 +1391,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
else { else {
if(rd != 0) { if(rd != 0) {
*(X+rd) = (uint32_t)((int32_t)*(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1))); *(X+rd) = (uint32_t)((int32_t)*(X+rs1) >> ((uint64_t)(*(X+rs2) ) & ((uint64_t)(traits::XLEN ) - (uint64_t)( 1 ))));
} }
} }
} }
@ -1772,7 +1772,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2); raise(0, 2);
} }
else { else {
int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2)); int64_t res = (int64_t)((int32_t)*(X+rs1) ) * (int64_t)((int32_t)*(X+rs2) );
if(rd != 0) { if(rd != 0) {
*(X+rd) = (uint32_t)res; *(X+rd) = (uint32_t)res;
} }
@ -1800,7 +1800,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2); raise(0, 2);
} }
else { else {
int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2)); int64_t res = (int64_t)((int32_t)*(X+rs1) ) * (int64_t)((int32_t)*(X+rs2) );
if(rd != 0) { if(rd != 0) {
*(X+rd) = (uint32_t)(res >> traits::XLEN); *(X+rd) = (uint32_t)(res >> traits::XLEN);
} }
@ -1828,7 +1828,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2); raise(0, 2);
} }
else { else {
int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (uint64_t)*(X+rs2)); int64_t res = (int64_t)((int32_t)*(X+rs1) ) * (int64_t)(*(X+rs2) );
if(rd != 0) { if(rd != 0) {
*(X+rd) = (uint32_t)(res >> traits::XLEN); *(X+rd) = (uint32_t)(res >> traits::XLEN);
} }
@ -1856,7 +1856,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2); raise(0, 2);
} }
else { else {
uint64_t res = (uint64_t)((uint64_t)*(X+rs1) * (uint64_t)*(X+rs2)); uint64_t res = (uint64_t)(*(X+rs1) ) * (uint64_t)(*(X+rs2) );
if(rd != 0) { if(rd != 0) {
*(X+rd) = (uint32_t)(res >> traits::XLEN); *(X+rd) = (uint32_t)(res >> traits::XLEN);
} }
@ -1888,7 +1888,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
int32_t divisor = (int32_t)*(X+rs2); int32_t divisor = (int32_t)*(X+rs2);
if(rd != 0) { if(rd != 0) {
if(divisor != 0) { if(divisor != 0) {
uint32_t MMIN = ((uint32_t)1) << (traits::XLEN - 1); uint32_t MMIN = ((uint32_t)1) << ((uint64_t)(traits::XLEN ) - (uint64_t)(1 ));
if(*(X+rs1) == MMIN && divisor == - 1) { if(*(X+rs1) == MMIN && divisor == - 1) {
*(X+rd) = MMIN; *(X+rd) = MMIN;
} }
@ -1926,7 +1926,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
else { else {
if(*(X+rs2) != 0) { if(*(X+rs2) != 0) {
if(rd != 0) { if(rd != 0) {
*(X+rd) = (uint32_t)(*(X+rs1) / *(X+rs2)); *(X+rd) = *(X+rs1) / *(X+rs2);
} }
} }
else { else {
@ -1959,7 +1959,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
else { else {
if(*(X+rs2) != 0) { if(*(X+rs2) != 0) {
uint32_t MMIN = (uint32_t)1 << (traits::XLEN - 1); uint32_t MMIN = (uint32_t)1 << ((uint64_t)(traits::XLEN ) - (uint64_t)(1 ));
if(*(X+rs1) == MMIN && (int32_t)*(X+rs2) == - 1) { if(*(X+rs1) == MMIN && (int32_t)*(X+rs2) == - 1) {
if(rd != 0) { if(rd != 0) {
*(X+rd) = 0; *(X+rd) = 0;
@ -1967,7 +1967,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
else { else {
if(rd != 0) { if(rd != 0) {
*(X+rd) = (uint32_t)((int32_t)*(X+rs1) % (int32_t)*(X+rs2)); *(X+rd) = ((uint32_t)((int32_t)*(X+rs1) % (int32_t)*(X+rs2)));
} }
} }
} }
@ -2030,7 +2030,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
// execute instruction // execute instruction
{ {
if(imm) { if(imm) {
*(X+rd + 8) = (uint32_t)(*(X+2) + imm); *(X+rd + 8) = (uint32_t)((uint64_t)(*(X+2) ) + (uint64_t)(imm ));
} }
else { else {
raise(0, 2); raise(0, 2);
@ -2054,7 +2054,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
{ {
uint32_t offs = (uint32_t)(*(X+rs1 + 8) + uimm); uint32_t offs = (uint32_t)((uint64_t)(*(X+rs1 + 8) ) + (uint64_t)(uimm ));
int32_t res_38 = super::template read_mem<int32_t>(traits::MEM, offs); int32_t res_38 = super::template read_mem<int32_t>(traits::MEM, offs);
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
*(X+rd + 8) = (uint32_t)(int32_t)res_38; *(X+rd + 8) = (uint32_t)(int32_t)res_38;
@ -2077,7 +2077,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
{ {
uint32_t offs = (uint32_t)(*(X+rs1 + 8) + uimm); uint32_t offs = (uint32_t)((uint64_t)(*(X+rs1 + 8) ) + (uint64_t)(uimm ));
super::template write_mem<uint32_t>(traits::MEM, offs, (uint32_t)*(X+rs2 + 8)); super::template write_mem<uint32_t>(traits::MEM, offs, (uint32_t)*(X+rs2 + 8));
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
} }
@ -2103,7 +2103,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
else { else {
if(rs1 != 0) { if(rs1 != 0) {
*(X+rs1) = (uint32_t)(*(X+rs1) + (int8_t)sext<6>(imm)); *(X+rs1) = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)((int8_t)sext<6>(imm) ));
} }
} }
} }
@ -2136,8 +2136,8 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
{ {
*(X+1) = (uint32_t)(*PC + 2); *(X+1) = (uint32_t)((uint64_t)(*PC ) + (uint64_t)( 2 ));
*NEXT_PC = (uint32_t)(*PC + (int16_t)sext<12>(imm)); *NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<12>(imm) ));
this->core.reg.last_branch = 1; this->core.reg.last_branch = 1;
} }
break; break;
@ -2207,7 +2207,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
// execute instruction // execute instruction
{ {
if(nzimm) { if(nzimm) {
*(X+2) = (uint32_t)(*(X+2) + (int16_t)sext<10>(nzimm)); *(X+2) = (uint32_t)((uint64_t)(*(X+2) ) + (uint64_t)((int16_t)sext<10>(nzimm) ));
} }
else { else {
raise(0, 2); raise(0, 2);
@ -2289,7 +2289,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
{ {
*(X+rs1 + 8) = (uint32_t)(*(X+rs1 + 8) & (int8_t)sext<6>(imm)); *(X+rs1 + 8) = (uint32_t)(*(X+rs1 + 8) & (uint32_t)((int8_t)sext<6>(imm) ));
} }
break; break;
}// @suppress("No break at end of case") }// @suppress("No break at end of case")
@ -2308,7 +2308,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
{ {
*(X+rd + 8) = (uint32_t)(*(X+rd + 8) - *(X+rs2 + 8)); *(X+rd + 8) = (uint32_t)((uint64_t)(*(X+rd + 8) ) - (uint64_t)(*(X+rs2 + 8) ));
} }
break; break;
}// @suppress("No break at end of case") }// @suppress("No break at end of case")
@ -2382,7 +2382,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
{ {
*NEXT_PC = (uint32_t)(*PC + (int16_t)sext<12>(imm)); *NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<12>(imm) ));
this->core.reg.last_branch = 1; this->core.reg.last_branch = 1;
} }
break; break;
@ -2403,7 +2403,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
// execute instruction // execute instruction
{ {
if(*(X+rs1 + 8) == 0) { if(*(X+rs1 + 8) == 0) {
*NEXT_PC = (uint32_t)(*PC + (int16_t)sext<9>(imm)); *NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<9>(imm) ));
this->core.reg.last_branch = 1; this->core.reg.last_branch = 1;
} }
} }
@ -2425,7 +2425,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
// execute instruction // execute instruction
{ {
if(*(X+rs1 + 8) != 0) { if(*(X+rs1 + 8) != 0) {
*NEXT_PC = (uint32_t)(*PC + (int16_t)sext<9>(imm)); *NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<9>(imm) ));
this->core.reg.last_branch = 1; this->core.reg.last_branch = 1;
} }
} }
@ -2476,7 +2476,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2); raise(0, 2);
} }
else { else {
uint32_t offs = (uint32_t)(*(X+2) + uimm); uint32_t offs = (uint32_t)((uint64_t)(*(X+2) ) + (uint64_t)(uimm ));
int32_t res_39 = super::template read_mem<int32_t>(traits::MEM, offs); int32_t res_39 = super::template read_mem<int32_t>(traits::MEM, offs);
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
*(X+rd) = (uint32_t)(int32_t)res_39; *(X+rd) = (uint32_t)(int32_t)res_39;
@ -2525,7 +2525,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
// execute instruction // execute instruction
{ {
if(rs1 && rs1 < traits::RFS) { if(rs1 && rs1 < traits::RFS) {
*NEXT_PC = *(X+rs1 % traits::RFS) & ~ 0x1; *NEXT_PC = *(X+(uint32_t)(rs1 ) % traits::RFS) & (uint32_t)(~ 0x1 );
this->core.reg.last_branch = 1; this->core.reg.last_branch = 1;
} }
else { else {
@ -2567,7 +2567,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
else { else {
if(rd != 0) { if(rd != 0) {
*(X+rd) = (uint32_t)(*(X+rd) + *(X+rs2)); *(X+rd) = (uint32_t)((uint64_t)(*(X+rd) ) + (uint64_t)(*(X+rs2) ));
} }
} }
} }
@ -2592,8 +2592,8 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
else { else {
uint32_t new_pc = *(X+rs1); uint32_t new_pc = *(X+rs1);
*(X+1) = (uint32_t)(*PC + 2); *(X+1) = (uint32_t)((uint64_t)(*PC ) + (uint64_t)( 2 ));
*NEXT_PC = new_pc & ~ 0x1; *NEXT_PC = new_pc & (uint32_t)(~ 0x1 );
this->core.reg.last_branch = 1; this->core.reg.last_branch = 1;
} }
} }
@ -2631,7 +2631,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2); raise(0, 2);
} }
else { else {
uint32_t offs = (uint32_t)(*(X+2) + uimm); uint32_t offs = (uint32_t)((uint64_t)(*(X+2) ) + (uint64_t)(uimm ));
super::template write_mem<uint32_t>(traits::MEM, offs, (uint32_t)*(X+rs2)); super::template write_mem<uint32_t>(traits::MEM, offs, (uint32_t)*(X+rs2));
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
} }
@ -2695,16 +2695,24 @@ std::unique_ptr<vm_if> create<arch::tgc5c>(arch::tgc5c *core, unsigned short por
namespace iss { namespace iss {
namespace { namespace {
volatile std::array<bool, 2> dummy = { volatile std::array<bool, 2> dummy = {
core_factory::instance().register_creator("tgc5c|m_p|interp", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{ core_factory::instance().register_creator("tgc5c|m_p|interp", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::tgc5c>(); auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::tgc5c>();
auto vm = new interp::tgc5c::vm_impl<arch::tgc5c>(*cpu, false); auto vm = new interp::tgc5c::vm_impl<arch::tgc5c>(*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::tgc5c>::reg_t, arch::traits<arch::tgc5c>::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("tgc5c|mu_p|interp", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{ core_factory::instance().register_creator("tgc5c|mu_p|interp", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::tgc5c>(); auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::tgc5c>();
auto vm = new interp::tgc5c::vm_impl<arch::tgc5c>(*cpu, false); auto vm = new interp::tgc5c::vm_impl<arch::tgc5c>(*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::tgc5c>::reg_t, arch::traits<arch::tgc5c>::reg_t)>*>(init_data);
cpu->set_semihosting_callback(*cb);
}
return {cpu_ptr{cpu}, vm_ptr{vm}}; return {cpu_ptr{cpu}, vm_ptr{vm}};
}) })
}; };

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff