diff --git a/CMakeLists.txt b/CMakeLists.txt index aec662a..ac3bf7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,7 @@ project(dbt-rise-tgc VERSION 1.0.0) include(GNUInstallDirs) find_package(elfio) +find_package(Boost COMPONENTS coroutine) if(WITH_LLVM) if(DEFINED ENV{LLVM_HOME}) @@ -66,7 +67,7 @@ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") target_compile_options(${PROJECT_NAME} PRIVATE /wd4293) endif() target_include_directories(${PROJECT_NAME} PUBLIC incl) -target_link_libraries(${PROJECT_NAME} PUBLIC softfloat scc-util jsoncpp) +target_link_libraries(${PROJECT_NAME} PUBLIC softfloat scc-util jsoncpp Boost::coroutine) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--whole-archive dbt-core -Wl,--no-whole-archive) else() diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index 2105569..fa69704 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -161,7 +161,7 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { inline uint32_t get_last_branch() { return reg.last_branch; } -protected: + #pragma pack(push, 1) struct ${coreDef.name}_regs {<% registers.each { reg -> if(reg.size>0) {%> diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 7cf5c47..26db3d0 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -45,6 +45,8 @@ def nativeTypeSize(int size){ #include #include #include +#include +#include #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY @@ -59,6 +61,7 @@ namespace interp { namespace ${coreDef.name.toLowerCase()} { using namespace iss::arch; using namespace iss::debugger; +using namespace std::placeholders; template class vm_impl : public iss::interp::vm_base { public: @@ -130,6 +133,10 @@ protected: this->core.wait_until(type); } + using yield_t = boost::coroutines2::coroutine::push_type; + using coro_t = boost::coroutines2::coroutine::pull_type; + std::vector spawn_blocks; + template T& pc_assign(T& val){super::ex_info.branch_taken=true; return val;} inline uint8_t readSpace1(typename super::mem_type_e space, uint64_t addr){ @@ -174,7 +181,9 @@ protected: auto sign_mask = 1ULL<<(W-1); return (from & mask) | ((from & sign_mask) ? ~mask : 0); } - +<%functions.each{ it.eachLine { %> + ${it}<%}%> +<%}%> private: /**************************************************************************** * start opcode definitions @@ -196,11 +205,6 @@ private: /* instruction ${idx}: ${instr.name} */ compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, ${idx}); <%instr.fields.eachLine{%>${it} <%}%>if(this->disass_enabled){ @@ -208,6 +212,9 @@ private: <%instr.disass.eachLine{%>${it} <%}%> } + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // used registers<%instr.usedVariables.each{ k,v-> if(v.isArray) {%> auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}0]);<% }else{ %> @@ -219,6 +226,7 @@ private: <%instr.behavior.eachLine{%>${it} <%}%>} catch(...){} // post execution stuff + for(auto& spawn_block:spawn_blocks) spawn_block(); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, ${idx}); // trap check if(*trap_state!=0){ @@ -335,6 +343,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto f = decode_inst(insn); auto old_pc = pc.val; pc = (this->*f)(pc, insn); + this->core.reg.PC = this->core.reg.NEXT_PC; + this->core.reg.trap_state = this->core.reg.pending_trap; } } return pc;