Author SHA1 Message Date
alex 6f08f4010c Silences build warning 2025-07-22 09:04:07 +02:00
eyck c9c47673d9 implements csr mem as std::array 2025-07-13 14:40:29 +02:00
eyck c1aed64a41 removes use of exceptions to report bus errors 2025-07-06 15:11:11 +02:00
eyck d5d195845c fixes FW load handling in SysC wrapper, reports now na error if failed 2025-07-02 13:52:23 +02:00
alex 9fcbeb478b adds functionality for all Zvk Instructions 2025-07-01 20:36:46 +02:00
alex a768bde7f2 adds all arithmetic Zvk extensions 2025-06-30 10:53:48 +02:00
alex cd866fd74d cleans up agnostic behaviour for softvector 2025-06-30 09:04:46 +02:00
eyck 67f364049c adds some message if disass will be in the trace file 2025-05-23 20:28:01 +02:00
eyck 047e2e12b0 fixes include issue in LLVM vm_base
vm_base.h needs to be included before gdb_session.h as termios.h (via
boost and gdb_server) has a define which clashes with a variable name in
ConstantRange.h (via iss/llvm/vm_base.h)
2025-05-09 20:14:09 +02:00
alex fe3ed49519 updates asmjit template, removes lots of comments from IR 2025-04-28 15:04:18 +02:00
alex 1afd77a942 changes aes box functions to extern linkage 2025-04-28 15:02:05 +02:00
alex cdf5038e59 corrects fp functions for llvm 2025-04-03 09:59:22 +02:00
alex 651897e1e4 corrects another oversight in tcc template wrt floating point 2025-04-03 09:19:02 +02:00
alex a1803c61c1 even more corrections to tcc template 2025-04-02 13:01:25 +02:00
alex bfa2182f8e corrects mistakes wrt tcc template 2025-04-02 12:20:42 +02:00
alex b01c9b27e5 corrects tcc template when using floating point 2025-04-02 12:18:45 +02:00
alex 07f394d5ff corrects tcc template when using floating point 2025-04-02 11:53:55 +02:00
alex 7e97329e78 adds UserProvidedFunctions for NaNBoxing, updates generated files, adapts to new fp API 2025-04-02 10:19:11 +02:00
alex 8f5d666b7d corrects mistake from rebasing, adds newly generated templates 2025-03-31 12:50:05 +02:00
alex cc123939ce configures logger in main 2025-03-31 10:19:16 +02:00
alex a2e5405e25 small changes regarding vector template 2025-03-31 10:19:16 +02:00
alex cd3ec0b79d removes conversion functions in favor of more explicit conversions 2025-03-31 10:19:16 +02:00
alex 0e35a2a8c9 adds complete Zfh support, small rework regarding floating point interface 2025-03-31 10:19:16 +02:00
alex 8220c00a3d small correction for floating point h 2025-03-31 10:19:16 +02:00
alex ec5fb1e87e increases verbosity for file loading errors 2025-03-31 10:19:16 +02:00
alex 453407568c removes carry_t, moves functionality to own functions 2025-03-31 10:19:16 +02:00
alex 0fe9e6ebc8 corrects error for narrowing fp dispatch 2025-03-31 10:19:16 +02:00
alex 484d9dbe08 removes rounding mode lookup as it is not needes 2025-03-31 10:19:15 +02:00
alex 7a7035f267 adds support for half precision float 2025-03-31 10:19:15 +02:00
alex d9f1e5d31b small refactor 2025-03-31 10:19:15 +02:00
alex 7b35f45a48 changes to make correct oversighst for XLEN=64 in Vector functions 2025-03-31 10:19:15 +02:00
alex ece6f7290f small bugfixes, adds some half point functionality 2025-03-31 10:19:15 +02:00
alex 2166a6d81e makes widenning function types more explicit 2025-03-31 10:19:15 +02:00
alex fe9f2a5455 corrects vectorslide, changes all loop index type 2025-03-31 10:19:15 +02:00
alex 42bf6ee380 corrects errors w.r.t. floating point dispatch 2025-03-31 10:19:15 +02:00
alex f0b582df6c corrects ambiguity in frsqrt 2025-03-31 10:19:15 +02:00
alex 6fcb3dbb66 adds missing floating point instructions 2025-03-31 10:19:15 +02:00
alex c01eb39a76 reworks merge instrs, adds fp comparisons 2025-03-31 10:19:15 +02:00
alex 08280a094f allows assigning to mask_view elements 2025-03-31 10:19:15 +02:00
alex ae90adc854 adds most fp functions 2025-03-31 10:19:15 +02:00
alex cd358198ad expands floating point functions 2025-03-31 10:19:14 +02:00
alex 8746003d3e adds floating point reduction instrs, widening are untested 2025-03-31 10:19:14 +02:00
alex 60d2b45a81 adds floating point Permutation Instructions 2025-03-31 10:19:14 +02:00
alex 0264c5d66f small cleanup 2025-03-31 10:19:14 +02:00
alex 528c2536af removes unused declarations 2025-03-31 10:19:14 +02:00
alex 19e38ec898 corrects bug 2025-03-31 10:19:14 +02:00
alex fd11ce18c4 changes order of arguments to reflect assembly 2025-03-31 10:19:14 +02:00
alex 9b7a9fa273 updates indexed load to use vreg_views 2025-03-31 10:19:14 +02:00
alex e24c1874c4 Changes load_store to use vreg_views aswell 2025-03-31 10:19:14 +02:00
alex 221d2ee38c adds whole register moves 2025-03-31 10:19:14 +02:00
alex 877cad27ba adds gather instructions 2025-03-31 10:19:14 +02:00
alex a26505cb5c adds more functions, up to slide 2025-03-31 10:19:13 +02:00
alex c1277b6528 adds mask_mask logical instructions 2025-03-31 10:19:13 +02:00
alex 63889b02e7 adds widening reductions 2025-03-31 10:19:13 +02:00
alex f049d8cbb3 adds Integer Reduction Instructions 2025-03-31 10:19:13 +02:00
alex 28ac169cfe adds narrowing fixed point instructions 2025-03-31 10:19:13 +02:00
alex a6f24db83a adds vssrl and vssra 2025-03-31 10:19:13 +02:00
alex e1911bc450 adds vsmul, widens functions parameters for sat_vector operations 2025-03-31 10:19:13 +02:00
alex 75d96bf18d small cleanup, adds first fixed point instrs 2025-03-31 10:19:13 +02:00
alex e59458aa0e adds the missing vector csrs to the architectural state 2025-03-31 10:18:51 +02:00
alex 77807fec01 adds merge and move instructions 2025-03-31 10:18:10 +02:00
alex 6852d1d299 adds Vector Widening Integer Multiply-Add Instructions 2025-03-31 10:18:10 +02:00
alex ac1322d66b changes to ternary functions for Multiply-Add Instructions 2025-03-31 10:18:10 +02:00
alex 9ba9d2432c adds Vector Widening Integer Multiply Instructions 2025-03-31 10:18:10 +02:00
alex c9b7962cd3 adds Vector Integer Divide Instructions 2025-03-31 10:18:10 +02:00
alex ab31fd27c9 adds single width integer instructins, also small cleanup 2025-03-31 10:18:10 +02:00
alex b3f189145f adds funct3 to vector functions 2025-03-31 10:18:10 +02:00
alex dd4416ab15 adds min/max instructions 2025-03-31 10:18:10 +02:00
alex 0027946f90 renames mask operations to distinguish from vector integer compare instructions 2025-03-31 10:18:09 +02:00
alex feaff8c4a5 adds support for narrowing shifts 2025-03-31 10:18:09 +02:00
alex af3e76cc98 adds integer extension and add/substract with carry vector instructions 2025-03-31 10:18:09 +02:00
alex b1ceac2c2a small correction for vector_functions 2025-03-31 10:18:09 +02:00
alex b5862039e7 changes order of operands to more closely resemble assembly 2025-03-31 10:18:09 +02:00
alex 51f3802394 adds vector_imm instructions to vector_functions, makes size of all involved registers a template parameter 2025-03-31 10:18:09 +02:00
alex 6ce0d97e81 general improvements to vector_functions, adds functions to process arithmetic instructions (working add) 2025-03-31 10:18:09 +02:00
alex 69c8fda5d2 corrects oversight in vector_functions 2025-03-31 10:18:09 +02:00
alex c1f9328528 corrects vector_functions 2025-03-31 10:18:09 +02:00
alex 2b85748279 adds load_store_index to vector_functions 2025-03-31 10:18:09 +02:00
alex f7aa51b12e adds small optimization, clarifies variables in vector_functions 2025-03-31 10:18:09 +02:00
alex 3428745a00 small corrections in vector functions 2025-03-31 10:18:09 +02:00
alex 512b79a3e7 makes elem_count an explicit parameter for the softvector functions rather than calculating it from vtype 2025-03-31 10:18:08 +02:00
alex 7a048f8b93 changes wording of returned index to better reflect what it means, cleans up a bit 2025-03-31 10:18:08 +02:00
alex 6f4daf91ed adds explicit RFS to assertions 2025-03-31 10:18:08 +02:00
alex 947d353bbf adds working vector (unit) stride (segmented) loads and stores 2025-03-31 10:18:08 +02:00
alex b95f518c91 updates templates for interp to make extension specific includes conditonal 2025-03-31 10:18:08 +02:00
alex 4cef0f57c1 updates templates and adds newly generated files 2025-03-31 10:18:05 +02:00
alex 28af695592 adds vector support to m and mu priv wrapper 2025-03-31 10:16:01 +02:00
alex f6cdd9d07c adds vector csr to riscv_common 2025-03-31 09:54:26 +02:00
alex 9e390971d4 corrects include guard comment for fp_functions 2025-03-31 09:54:26 +02:00
alex 2bb2e56310 adds dependencies for K ISA (Cryptography) 2025-03-31 09:54:26 +02:00
alex a0eeae7dd6 corrects template for new arch_if changes 2025-03-30 19:12:22 +02:00
eyck 8f491ef36b adds superflous exception throwing 2025-03-21 20:28:37 +01:00
eyck cbe4c2d62f adds comment to indicate purpose of arch state members 2025-03-19 12:03:12 +01:00
eyck 31c6bb55f4 applies clang format 2025-03-16 14:38:45 +01:00
eyck 63d0162119 adds license header 2025-03-16 13:33:01 +01:00
eyck 3b294d9da0 fixes sc_core_adapter wrt refactored memory hierarchy 2025-03-16 12:29:03 +01:00
eyck 54233b448d moves mmu related code into mmu unit 2025-03-16 08:50:01 +01:00
eyck e238369e18 cleansup htif call 2025-03-15 06:54:21 +01:00
eyck cfc980a069 Merge branch 'feature/privilege_refactor' into develop 2025-03-14 20:00:07 +01:00
eyck 71260a3ef4 Merge remote-tracking branch 'origin/feature/htif' into develop 2025-03-14 11:32:36 +01:00
hongyu aaebeaf023 changes the io_buf 2025-03-11 12:00:31 +01:00
42 changed files with 6487 additions and 1425 deletions

No files matched your search

+2 -1
View File
@@ -18,9 +18,10 @@ add_subdirectory(softfloat)
set(LIB_SOURCES set(LIB_SOURCES
src/iss/plugin/instruction_count.cpp src/iss/plugin/instruction_count.cpp
src/iss/arch/tgc5c.cpp src/iss/arch/tgc5c.cpp
src/iss/mmio/memory_if.cpp src/iss/mem/memory_if.cpp
src/vm/interp/vm_tgc5c.cpp src/vm/interp/vm_tgc5c.cpp
src/vm/fp_functions.cpp src/vm/fp_functions.cpp
src/vm/vector_functions.cpp
src/iss/debugger/csr_names.cpp src/iss/debugger/csr_names.cpp
src/iss/semihosting/semihosting.cpp src/iss/semihosting/semihosting.cpp
) )
+1 -1
View File
@@ -20,7 +20,7 @@ RVI:
mask: 0b00000000000000000000000001111111 mask: 0b00000000000000000000000001111111
size: 32 size: 32
branch: true branch: true
delay: 1 delay: [1,1]
JALR: JALR:
index: 3 index: 3
encoding: 0b00000000000000000000000001100111 encoding: 0b00000000000000000000000001100111
+50 -17
View File
@@ -30,11 +30,21 @@
* *
*******************************************************************************/ *******************************************************************************/
<% <%
def nativeTypeSize(int size){ def nativeSize(int size){
if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64; if(size<=8) return 8;
if(size<=16) return 16;
if(size<=32) return 32;
if(size<=64) return 64;
if(size<=128) return 128;
if(size<=256) return 256;
if(size<=512) return 512;
if(size<=1024) return 1024;
if(size<=2048) return 2048;
if(size<=4096) return 4096;
throw new IllegalArgumentException("Unsupported size in nativeSize in CORENAME.h.gtl");
} }
def getRegisterSizes(){ def getRegisterSizes(){
def regs = registers.collect{nativeTypeSize(it.size)} def regs = registers.collect{nativeSize(it.size)}
regs+=[32,32, 64, 64, 64, 32, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH regs+=[32,32, 64, 64, 64, 32, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH
return regs return regs
} }
@@ -47,13 +57,7 @@ def getRegisterOffsets(){
} }
return offsets return offsets
} }
def byteSize(int size){
if(size<=8) return 8;
if(size<=16) return 16;
if(size<=32) return 32;
if(size<=64) return 64;
return 128;
}
def getCString(def val){ def getCString(def val){
return val.toString()+'ULL' return val.toString()+'ULL'
} }
@@ -84,6 +88,8 @@ template <> struct traits<${coreDef.name.toLowerCase()}> {
enum constants {${constants.collect{c -> c.name+"="+getCString(c.value)}.join(', ')}}; enum constants {${constants.collect{c -> c.name+"="+getCString(c.value)}.join(', ')}};
constexpr static unsigned FP_REGS_SIZE = ${constants.find {it.name=='FLEN'}?.value?:0}; constexpr static unsigned FP_REGS_SIZE = ${constants.find {it.name=='FLEN'}?.value?:0};
constexpr static unsigned V_REGS_SIZE = ${constants.find {it.name=='VLEN'}?.value?:0};
enum reg_e { enum reg_e {
${registers.collect{it.name}.join(', ')}, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH ${registers.collect{it.name}.join(', ')}, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH
@@ -142,15 +148,17 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
#pragma pack(push, 1) #pragma pack(push, 1)
struct ${coreDef.name}_regs {<% struct ${coreDef.name}_regs {<%
registers.each { reg -> if(reg.size>0) {%> registers.each { reg -> if(reg.size>64) {%>
uint${byteSize(reg.size)}_t ${reg.name} = 0;<% uint8_t ${reg.name}[${reg.size/8}] = {0};<%
}else if(reg.size>0) {%>
uint${nativeSize(reg.size)}_t ${reg.name} = 0;<%
}}%> }}%>
uint32_t trap_state = 0, pending_trap = 0; uint32_t trap_state = 0, pending_trap = 0;
uint64_t icount = 0; uint64_t icount = 0; // counts number of instructions undisturbed
uint64_t cycle = 0; uint64_t cycle = 0; // counts number of cycles, in functional mode equals icount
uint64_t instret = 0; uint64_t instret = 0; // counts number of instructions, can be reset via CSR write
uint32_t instruction = 0; uint32_t instruction = 0; // holds op code of currently executed instruction
uint32_t last_branch = 0; uint32_t last_branch = 0; // indicates if last branch was taken
} reg; } reg;
#pragma pack(pop) #pragma pack(pop)
std::array<address_type, 4> addr_mode; std::array<address_type, 4> addr_mode;
@@ -164,6 +172,31 @@ if(fcsr != null) {%>
<%} else { %> <%} else { %>
uint32_t get_fcsr(){return 0;} uint32_t get_fcsr(){return 0;}
void set_fcsr(uint32_t val){} void set_fcsr(uint32_t val){}
<%}
def vstart = registers.find {it.name=='vstart'}
def vl = registers.find {it.name=='vl'}
def vtype = registers.find {it.name=='vtype'}
def vxsat = registers.find {it.name=='vxsat'}
def vxrm = registers.find {it.name=='vxrm'}
if(vtype != null) {%>
uint${vstart.size}_t get_vstart(){return reg.vstart;}
void set_vstart(uint${vstart.size}_t val){reg.vstart = val;}
uint${vl.size}_t get_vl(){return reg.vl;}
uint${vtype.size}_t get_vtype(){return reg.vtype;}
uint${vxsat.size}_t get_vxsat(){return reg.vxsat;}
void set_vxsat(uint${vxsat.size}_t val){reg.vxsat = val;}
uint${vxrm.size}_t get_vxrm(){return reg.vxrm;}
void set_vxrm(uint${vxrm.size}_t val){reg.vxrm = val;}
<%} else { %>
uint32_t get_vstart(){return 0;}
void set_vstart(uint32_t val){}
uint32_t get_vl(){return 0;}
uint32_t get_vtype(){return 0;}
uint32_t get_vxsat(){return 0;}
void set_vxsat(uint32_t val){}
uint32_t get_vxrm(){return 0;}
void set_vxrm(uint32_t val){}
<%}%> <%}%>
}; };
+33 -13
View File
@@ -40,7 +40,11 @@
#include <iss/instruction_decoder.h> #include <iss/instruction_decoder.h>
<%def fcsr = registers.find {it.name=='FCSR'} <%def fcsr = registers.find {it.name=='FCSR'}
if(fcsr != null) {%> if(fcsr != null) {%>
#include <vm/fp_functions.h><%}%> #include <vm/fp_functions.h><%}
def aes = functions.find { it.contains('aes') }
if(aes != null) {%>
#include <vm/aes_sbox.h>
<%}%>
#ifndef FMT_HEADER_ONLY #ifndef FMT_HEADER_ONLY
#define FMT_HEADER_ONLY #define FMT_HEADER_ONLY
#endif #endif
@@ -49,6 +53,22 @@ if(fcsr != null) {%>
#include <array> #include <array>
#include <iss/debugger/riscv_target_adapter.h> #include <iss/debugger/riscv_target_adapter.h>
#ifndef _MSC_VER
using int128_t = __int128;
using uint128_t = unsigned __int128;
namespace std {
template <> struct make_unsigned<__int128> { typedef unsigned __int128 type; };
template <> class __make_unsigned_selector<__int128 unsigned, false, false> {
public:
typedef unsigned __int128 __type;
};
template <> struct is_signed<int128_t> { static constexpr bool value = true; };
template <> struct is_signed<uint128_t> { static constexpr bool value = false; };
template <> struct is_unsigned<int128_t> { static constexpr bool value = false; };
template <> struct is_unsigned<uint128_t> { static constexpr bool value = true; };
} // namespace std
#endif
namespace iss { namespace iss {
namespace asmjit { namespace asmjit {
@@ -116,9 +136,14 @@ protected:
auto sign_mask = 1ULL<<(W-1); auto sign_mask = 1ULL<<(W-1);
return (from & mask) | ((from & sign_mask) ? ~mask : 0); return (from & mask) | ((from & sign_mask) ? ~mask : 0);
} }
inline void raise(uint16_t trap_id, uint16_t cause){
auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id;
this->core.reg.trap_state = trap_val;
}
<%functions.each{ it.eachLine { %> <%functions.each{ it.eachLine { %>
${it}<%}%> ${it}<%}
<%}%> }%>
private: private:
/**************************************************************************** /****************************************************************************
* start opcode definitions * start opcode definitions
@@ -166,7 +191,6 @@ private:
mov(cc, jh.next_pc, pc.val); mov(cc, jh.next_pc, pc.val);
gen_instr_prologue(jh); gen_instr_prologue(jh);
cc.comment("//behavior:");
/*generate behavior*/ /*generate behavior*/
<%instr.behavior.eachLine{%>${it} <%instr.behavior.eachLine{%>${it}
<%}%> <%}%>
@@ -197,7 +221,6 @@ private:
pc = pc + ((instr & 3) == 3 ? 4 : 2); pc = pc + ((instr & 3) == 3 ? 4 : 2);
mov(cc, jh.next_pc, pc.val); mov(cc, jh.next_pc, pc.val);
gen_instr_prologue(jh); gen_instr_prologue(jh);
cc.comment("//behavior:");
gen_raise(jh, 0, 2); gen_raise(jh, 0, 2);
gen_sync(jh, POST_SYNC, instr_descr.size()); gen_sync(jh, POST_SYNC, instr_descr.size());
gen_instr_epilogue(jh); gen_instr_epilogue(jh);
@@ -226,8 +249,6 @@ continuation_e vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, jit_hold
code_word_t instr = 0; code_word_t instr = 0;
phys_addr_t paddr(pc); phys_addr_t paddr(pc);
auto *const data = (uint8_t *)&instr; auto *const data = (uint8_t *)&instr;
if(this->core.has_mmu())
paddr = this->core.virt2phys(pc);
auto res = this->core.read(paddr, 4, data); auto res = this->core.read(paddr, 4, data);
if (res != iss::Ok) if (res != iss::Ok)
return ILLEGAL_FETCH; return ILLEGAL_FETCH;
@@ -245,24 +266,25 @@ template <typename ARCH>
void vm_impl<ARCH>::gen_instr_prologue(jit_holder& jh) { void vm_impl<ARCH>::gen_instr_prologue(jit_holder& jh) {
auto& cc = jh.cc; auto& cc = jh.cc;
cc.comment("//gen_instr_prologue");
x86_reg_t current_trap_state = get_reg_for(cc, traits::TRAP_STATE); x86_reg_t current_trap_state = get_reg_for(cc, traits::TRAP_STATE);
mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE)); mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE));
mov(cc, get_ptr_for(jh, traits::PENDING_TRAP), current_trap_state); mov(cc, get_ptr_for(jh, traits::PENDING_TRAP), current_trap_state);
cc.comment("//Instruction prologue end");
} }
template <typename ARCH> template <typename ARCH>
void vm_impl<ARCH>::gen_instr_epilogue(jit_holder& jh) { void vm_impl<ARCH>::gen_instr_epilogue(jit_holder& jh) {
auto& cc = jh.cc; auto& cc = jh.cc;
cc.comment("//gen_instr_epilogue"); cc.comment("//Instruction epilogue begin");
x86_reg_t current_trap_state = get_reg_for(cc, traits::TRAP_STATE); x86_reg_t current_trap_state = get_reg_for(cc, traits::TRAP_STATE);
mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE)); mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE));
cmp(cc, current_trap_state, 0); cmp(cc, current_trap_state, 0);
cc.jne(jh.trap_entry); cc.jne(jh.trap_entry);
cc.inc(get_ptr_for(jh, traits::ICOUNT)); cc.inc(get_ptr_for(jh, traits::ICOUNT));
cc.inc(get_ptr_for(jh, traits::CYCLE)); cc.inc(get_ptr_for(jh, traits::CYCLE));
cc.comment("//Instruction epilogue end");
} }
template <typename ARCH> template <typename ARCH>
void vm_impl<ARCH>::gen_block_prologue(jit_holder& jh){ void vm_impl<ARCH>::gen_block_prologue(jit_holder& jh){
@@ -274,7 +296,7 @@ void vm_impl<ARCH>::gen_block_prologue(jit_holder& jh){
template <typename ARCH> template <typename ARCH>
void vm_impl<ARCH>::gen_block_epilogue(jit_holder& jh){ void vm_impl<ARCH>::gen_block_epilogue(jit_holder& jh){
x86::Compiler& cc = jh.cc; x86::Compiler& cc = jh.cc;
cc.comment("//gen_block_epilogue"); cc.comment("//block epilogue begin");
cc.ret(jh.next_pc); cc.ret(jh.next_pc);
cc.bind(jh.trap_entry); cc.bind(jh.trap_entry);
@@ -286,7 +308,6 @@ void vm_impl<ARCH>::gen_block_epilogue(jit_holder& jh){
x86::Gp current_pc = get_reg_for_Gp(cc, traits::PC); x86::Gp current_pc = get_reg_for_Gp(cc, traits::PC);
mov(cc, current_pc, get_ptr_for(jh, traits::PC)); mov(cc, current_pc, get_ptr_for(jh, traits::PC));
cc.comment("//enter trap call;");
InvokeNode* call_enter_trap; InvokeNode* call_enter_trap;
cc.invoke(&call_enter_trap, &enter_trap, FuncSignature::build<uint64_t, void*, uint64_t, uint64_t, uint64_t>()); cc.invoke(&call_enter_trap, &enter_trap, FuncSignature::build<uint64_t, void*, uint64_t, uint64_t, uint64_t>());
call_enter_trap->setArg(0, jh.arch_if_ptr); call_enter_trap->setArg(0, jh.arch_if_ptr);
@@ -304,7 +325,6 @@ void vm_impl<ARCH>::gen_block_epilogue(jit_holder& jh){
template <typename ARCH> template <typename ARCH>
inline void vm_impl<ARCH>::gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause) { inline void vm_impl<ARCH>::gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause) {
auto& cc = jh.cc; auto& cc = jh.cc;
cc.comment("//gen_raise");
auto tmp1 = get_reg_for(cc, traits::TRAP_STATE); auto tmp1 = get_reg_for(cc, traits::TRAP_STATE);
mov(cc, tmp1, 0x80ULL << 24 | (cause << 16) | trap_id); mov(cc, tmp1, 0x80ULL << 24 | (cause << 16) | trap_id);
mov(cc, get_ptr_for(jh, traits::TRAP_STATE), tmp1); mov(cc, get_ptr_for(jh, traits::TRAP_STATE), tmp1);
+855 -20
View File
@@ -30,6 +30,9 @@
* *
*******************************************************************************/ *******************************************************************************/
<% <%
def floating_point = registers.find {it.name=='FCSR'}
def vector = registers.find {it.name=='vtype'}
def aes = functions.find { it.contains('aes') }
def nativeTypeSize(int size){ def nativeTypeSize(int size){
if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64; if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64;
} }
@@ -41,7 +44,16 @@ def nativeTypeSize(int size){
#include <iss/debugger/server.h> #include <iss/debugger/server.h>
#include <iss/iss.h> #include <iss/iss.h>
#include <iss/interp/vm_base.h> #include <iss/interp/vm_base.h>
<%
if(floating_point != null) {%>
#include <vm/fp_functions.h> #include <vm/fp_functions.h>
<%}
if(vector != null) {%>
#include <vm/vector_functions.h>
<%}
if(aes != null) {%>
#include <vm/aes_sbox.h>
<%}%>
#include <util/logging.h> #include <util/logging.h>
#include <boost/coroutine2/all.hpp> #include <boost/coroutine2/all.hpp>
#include <functional> #include <functional>
@@ -102,9 +114,47 @@ protected:
inline const char *name(size_t index){return traits::reg_aliases.at(index);} inline const char *name(size_t index){return traits::reg_aliases.at(index);}
<% <%
def fcsr = registers.find {it.name=='FCSR'} if(floating_point != null) {%>
if(fcsr != null) {%>
inline const char *fname(size_t index){return index < 32?name(index+traits::F0):"illegal";} inline const char *fname(size_t index){return index < 32?name(index+traits::F0):"illegal";}
<%}
if(vector != null) {%>
inline const char* vname(size_t index) { return index < 32 ? name(index + traits::V0) : "illegal"; }
inline const char* sew_name(size_t bits) {
switch(bits) {
case 0b000:
return "e8";
case 0b001:
return "e16";
case 0b010:
return "e32";
case 0b011:
return "e64";
default:
return "illegal";
}
}
inline const char* lmul_name(size_t bits) {
switch(bits) {
case 0b101:
return "mf8";
case 0b110:
return "mf4";
case 0b111:
return "mf2";
case 0b000:
return "m1";
case 0b001:
return "m2";
case 0b010:
return "m4";
case 0b011:
return "m8";
default:
return "illegal";
}
}
inline const char* ma_name(bool ma) { return ma ? "ma" : "mu"; }
inline const char* ta_name(bool ta) { return ta ? "ta" : "tu"; }
<%}%> <%}%>
virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override; virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override;
@@ -127,7 +177,806 @@ if(fcsr != null) {%>
inline void set_tval(uint64_t new_tval){ inline void set_tval(uint64_t new_tval){
tval = new_tval; tval = new_tval;
} }
<%if(vector != null) {
def xlen = constants.find { it.name == 'XLEN' }?.value ?: 0
def vlen = constants.find { it.name == 'VLEN' }?.value ?: 0 %>
inline void lower(){
this->core.reg.trap_state = 0;
}
uint64_t vlseg(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint64_t rs1_val, uint8_t width_val, uint8_t segment_size){
switch(width_val){
case 0b000:
return softvector::vector_load_store<${vlen}, uint8_t>(this->get_arch(), softvector::softvec_read, V, vl, vstart, vtype, vm, vd, rs1_val, segment_size);
case 0b101:
return softvector::vector_load_store<${vlen}, uint16_t>(this->get_arch(), softvector::softvec_read, V, vl, vstart, vtype, vm, vd, rs1_val, segment_size);
case 0b110:
return softvector::vector_load_store<${vlen}, uint32_t>(this->get_arch(), softvector::softvec_read, V, vl, vstart, vtype, vm, vd, rs1_val, segment_size);
case 0b111:
return softvector::vector_load_store<${vlen}, uint64_t>(this->get_arch(), softvector::softvec_read, V, vl, vstart, vtype, vm, vd, rs1_val, segment_size);
default:
throw new std::runtime_error("Unsupported width bit value");
}
}
uint64_t vsseg(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint64_t rs1_val, uint8_t width_val, uint8_t segment_size){
switch(width_val){
case 0b000:
return softvector::vector_load_store<${vlen}, uint8_t>(this->get_arch(), softvector::softvec_write, V, vl, vstart, vtype, vm, vd, rs1_val, segment_size);
case 0b101:
return softvector::vector_load_store<${vlen}, uint16_t>(this->get_arch(), softvector::softvec_write, V, vl, vstart, vtype, vm, vd, rs1_val, segment_size);
case 0b110:
return softvector::vector_load_store<${vlen}, uint32_t>(this->get_arch(), softvector::softvec_write, V, vl, vstart, vtype, vm, vd, rs1_val, segment_size);
case 0b111:
return softvector::vector_load_store<${vlen}, uint64_t>(this->get_arch(), softvector::softvec_write, V, vl, vstart, vtype, vm, vd, rs1_val, segment_size);
default:
throw new std::runtime_error("Unsupported width bit value");
}
}
uint64_t vlsseg(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint64_t rs1_val, uint8_t width_val, uint8_t segment_size, int64_t stride){
switch(width_val){
case 0b000:
return softvector::vector_load_store<${vlen}, uint8_t>(this->get_arch(), softvector::softvec_read, V, vl, vstart, vtype, vm, vd, rs1_val, segment_size, stride, true);
case 0b101:
return softvector::vector_load_store<${vlen}, uint16_t>(this->get_arch(), softvector::softvec_read, V, vl, vstart, vtype, vm, vd, rs1_val, segment_size, stride, true);
case 0b110:
return softvector::vector_load_store<${vlen}, uint32_t>(this->get_arch(), softvector::softvec_read, V, vl, vstart, vtype, vm, vd, rs1_val, segment_size, stride, true);
case 0b111:
return softvector::vector_load_store<${vlen}, uint64_t>(this->get_arch(), softvector::softvec_read, V, vl, vstart, vtype, vm, vd, rs1_val, segment_size, stride, true);
default:
throw new std::runtime_error("Unsupported width bit value");
}
}
uint64_t vssseg(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint64_t rs1_val, uint8_t width_val, uint8_t segment_size, int64_t stride){
switch(width_val){
case 0b000:
return softvector::vector_load_store<${vlen}, uint8_t>(this->get_arch(), softvector::softvec_write, V, vl, vstart, vtype, vm, vd, rs1_val, segment_size, stride, true);
case 0b101:
return softvector::vector_load_store<${vlen}, uint16_t>(this->get_arch(), softvector::softvec_write, V, vl, vstart, vtype, vm, vd, rs1_val, segment_size, stride, true);
case 0b110:
return softvector::vector_load_store<${vlen}, uint32_t>(this->get_arch(), softvector::softvec_write, V, vl, vstart, vtype, vm, vd, rs1_val, segment_size, stride, true);
case 0b111:
return softvector::vector_load_store<${vlen}, uint64_t>(this->get_arch(), softvector::softvec_write, V, vl, vstart, vtype, vm, vd, rs1_val, segment_size, stride, true);
default:
throw new std::runtime_error("Unsupported width bit value");
}
}
using indexed_load_store_t = std::function<uint64_t(void*, std::function<bool(void*, uint64_t, uint64_t, uint8_t*)>, uint8_t*, uint64_t, uint64_t, softvector::vtype_t, bool, uint8_t, uint64_t, uint8_t, uint8_t)>;
template <typename T1, typename T2> indexed_load_store_t getFunction() {
return [this](void* core, std::function<uint64_t(void*, uint64_t, uint64_t, uint8_t*)> load_store_fn, uint8_t* V, uint64_t vl,
uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint64_t rs1, uint8_t vs2, uint8_t segment_size) {
return softvector::vector_load_store_index<${xlen}, ${vlen}, T1, T2>(core, load_store_fn, V, vl, vstart, vtype, vm, vd, rs1, vs2, segment_size);
};
}
const std::array<std::array<indexed_load_store_t, 4>, 4> functionTable = {{
{getFunction<uint8_t, uint8_t>(), getFunction<uint8_t, uint16_t>(), getFunction<uint8_t, uint32_t>(), getFunction<uint8_t, uint64_t>()},
{getFunction<uint16_t, uint8_t>(), getFunction<uint16_t, uint16_t>(), getFunction<uint16_t, uint32_t>(), getFunction<uint16_t, uint64_t>()},
{getFunction<uint32_t, uint8_t>(), getFunction<uint32_t, uint16_t>(), getFunction<uint32_t, uint32_t>(), getFunction<uint32_t, uint64_t>()},
{getFunction<uint64_t, uint8_t>(), getFunction<uint64_t, uint16_t>(), getFunction<uint64_t, uint32_t>(), getFunction<uint64_t, uint64_t>()}
}};
const size_t map_index_size[9] = { 0, 0, 1, 0, 2, 0, 0, 0, 3 }; // translate number of bytes to index in functionTable
uint64_t vlxseg(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint64_t rs1_val, uint8_t vs2, uint8_t segment_size, uint8_t index_byte_size, uint8_t data_byte_size, bool ordered){
return functionTable[map_index_size[index_byte_size]][data_byte_size](this->get_arch(), softvector::softvec_read, V, vl, vstart, vtype, vm, vd, rs1_val, vs2, segment_size);
}
uint64_t vsxseg(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vs3, uint64_t rs1_val, uint8_t vs2, uint8_t segment_size, uint8_t index_byte_size, uint8_t data_byte_size, bool ordered){
return functionTable[map_index_size[index_byte_size]][data_byte_size](this->get_arch(), softvector::softvec_write, V, vl, vstart, vtype, vm, vs3, rs1_val, vs2, segment_size);
}
void vector_vector_op(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::vector_vector_op<${vlen}, uint8_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b001:
return softvector::vector_vector_op<${vlen}, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b010:
return softvector::vector_vector_op<${vlen}, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b011:
return softvector::vector_vector_op<${vlen}, uint64_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_imm_op(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, int64_t imm, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::vector_imm_op<${vlen}, uint8_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b001:
return softvector::vector_imm_op<${vlen}, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b010:
return softvector::vector_imm_op<${vlen}, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b011:
return softvector::vector_imm_op<${vlen}, uint64_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_vector_wv(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::vector_vector_op<${vlen}, uint16_t, uint8_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b001:
return softvector::vector_vector_op<${vlen}, uint32_t, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b010:
return softvector::vector_vector_op<${vlen}, uint64_t, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b011: // would widen to 128 bits
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_imm_wv(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, int64_t imm, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::vector_imm_op<${vlen}, uint16_t, uint8_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b001:
return softvector::vector_imm_op<${vlen}, uint32_t, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b010:
return softvector::vector_imm_op<${vlen}, uint64_t, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b011: // would widen to 128 bits
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_vector_ww(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::vector_vector_op<${vlen}, uint16_t, uint16_t, uint8_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b001:
return softvector::vector_vector_op<${vlen}, uint32_t, uint32_t, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b010:
return softvector::vector_vector_op<${vlen}, uint64_t, uint64_t, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b011: // would widen to 128 bits
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_imm_ww(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, int64_t imm, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::vector_imm_op<${vlen}, uint16_t, uint16_t, uint8_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b001:
return softvector::vector_imm_op<${vlen}, uint32_t, uint32_t, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b010:
return softvector::vector_imm_op<${vlen}, uint64_t, uint64_t, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b011: // would widen to 128 bits
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_extend(uint8_t* V, uint8_t unary_op, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t target_sew_pow, uint8_t frac_pow){
switch(target_sew_pow){
case 4: // uint16_t target
if(frac_pow != 1) throw new std::runtime_error("Unsupported frac_pow");
return softvector::vector_unary_op<${vlen}, uint16_t, uint8_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
case 5: // uint32_t target
switch(frac_pow){
case 1:
return softvector::vector_unary_op<${vlen}, uint32_t, uint16_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
case 2:
return softvector::vector_unary_op<${vlen}, uint32_t, uint8_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
default:
throw new std::runtime_error("Unsupported frac_pow");
}
case 6: // uint64_t target
switch(frac_pow){
case 1:
return softvector::vector_unary_op<${vlen}, uint64_t, uint32_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
case 2:
return softvector::vector_unary_op<${vlen}, uint64_t, uint16_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
case 3:
return softvector::vector_unary_op<${vlen}, uint64_t, uint8_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
default:
throw new std::runtime_error("Unsupported frac_pow");
}
default:
throw new std::runtime_error("Unsupported target_sew_pow");
}
}
void vector_vector_carry(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t sew_val, int8_t carry){
switch(sew_val){
case 0b000:
return softvector::vector_vector_carry<${vlen}, uint8_t>(V, funct6, funct3, vl, vstart, vtype, vd, vs2, vs1, carry);
case 0b001:
return softvector::vector_vector_carry<${vlen}, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vd, vs2, vs1, carry);
case 0b010:
return softvector::vector_vector_carry<${vlen}, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vd, vs2, vs1, carry);
case 0b011:
return softvector::vector_vector_carry<${vlen}, uint64_t>(V, funct6, funct3, vl, vstart, vtype, vd, vs2, vs1, carry);
default:
throw new std::runtime_error("Unsupported sew bit value");
} }
void vector_imm_carry(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, uint8_t vd, uint8_t vs2, int64_t imm, uint8_t sew_val, int8_t carry){
switch(sew_val){
case 0b000:
return softvector::vector_imm_carry<${vlen}, uint8_t>(V, funct6, funct3, vl, vstart, vtype, vd, vs2, imm, carry);
case 0b001:
return softvector::vector_imm_carry<${vlen}, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vd, vs2, imm, carry);
case 0b010:
return softvector::vector_imm_carry<${vlen}, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vd, vs2, imm, carry);
case 0b011:
return softvector::vector_imm_carry<${vlen}, uint64_t>(V, funct6, funct3, vl, vstart, vtype, vd, vs2, imm, carry);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void carry_vector_vector_op(uint8_t* V, unsigned funct6, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, unsigned vd, unsigned vs2, unsigned vs1, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::carry_vector_vector_op<${vlen}, uint8_t>(V, funct6, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b001:
return softvector::carry_vector_vector_op<${vlen}, uint16_t>(V, funct6, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b010:
return softvector::carry_vector_vector_op<${vlen}, uint32_t>(V, funct6, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b011:
return softvector::carry_vector_vector_op<${vlen}, uint64_t>(V, funct6, vl, vstart, vtype, vm, vd, vs2, vs1);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void carry_vector_imm_op(uint8_t* V, unsigned funct6, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, unsigned vd, unsigned vs2, int64_t imm, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::carry_vector_imm_op<${vlen}, uint8_t>(V, funct6, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b001:
return softvector::carry_vector_imm_op<${vlen}, uint16_t>(V, funct6, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b010:
return softvector::carry_vector_imm_op<${vlen}, uint32_t>(V, funct6, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b011:
return softvector::carry_vector_imm_op<${vlen}, uint64_t>(V, funct6, vl, vstart, vtype, vm, vd, vs2, imm);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void mask_vector_vector_op(uint8_t* V, unsigned funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, unsigned vd, unsigned vs2, unsigned vs1, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::mask_vector_vector_op<${vlen}, uint8_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b001:
return softvector::mask_vector_vector_op<${vlen}, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b010:
return softvector::mask_vector_vector_op<${vlen}, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b011:
return softvector::mask_vector_vector_op<${vlen}, uint64_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void mask_vector_imm_op(uint8_t* V, unsigned funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, unsigned vd, unsigned vs2, int64_t imm, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::mask_vector_imm_op<${vlen}, uint8_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b001:
return softvector::mask_vector_imm_op<${vlen}, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b010:
return softvector::mask_vector_imm_op<${vlen}, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b011:
return softvector::mask_vector_imm_op<${vlen}, uint64_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_vector_vw(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::vector_vector_op<${vlen}, uint8_t, uint16_t, uint8_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b001:
return softvector::vector_vector_op<${vlen}, uint16_t, uint32_t, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b010:
return softvector::vector_vector_op<${vlen}, uint32_t, uint64_t, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b011: // would require 128 bits vs2 value
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_imm_vw(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, int64_t imm, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::vector_imm_op<${vlen}, uint8_t, uint16_t, uint8_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b001:
return softvector::vector_imm_op<${vlen}, uint16_t, uint32_t, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b010:
return softvector::vector_imm_op<${vlen}, uint32_t, uint64_t, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b011: // would require 128 bits vs2 value
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_vector_merge(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::vector_vector_merge<${vlen}, uint8_t>(V, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b001:
return softvector::vector_vector_merge<${vlen}, uint16_t>(V, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b010:
return softvector::vector_vector_merge<${vlen}, uint32_t>(V, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b011:
return softvector::vector_vector_merge<${vlen}, uint64_t>(V, vl, vstart, vtype, vm, vd, vs2, vs1);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_imm_merge(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, int64_t imm, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::vector_imm_merge<${vlen}, uint8_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b001:
return softvector::vector_imm_merge<${vlen}, uint16_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b010:
return softvector::vector_imm_merge<${vlen}, uint32_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b011:
return softvector::vector_imm_merge<${vlen}, uint64_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
bool sat_vector_vector_op(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, uint64_t vxrm, bool vm, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::sat_vector_vector_op<${vlen}, uint8_t>(V, funct6, funct3, vl, vstart, vtype, vxrm, vm, vd, vs2, vs1);
case 0b001:
return softvector::sat_vector_vector_op<${vlen}, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vxrm, vm, vd, vs2, vs1);
case 0b010:
return softvector::sat_vector_vector_op<${vlen}, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vxrm, vm, vd, vs2, vs1);
case 0b011:
return softvector::sat_vector_vector_op<${vlen}, uint64_t>(V, funct6, funct3, vl, vstart, vtype, vxrm, vm, vd, vs2, vs1);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
bool sat_vector_imm_op(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, uint64_t vxrm, bool vm, uint8_t vd, uint8_t vs2, int64_t imm, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::sat_vector_imm_op<${vlen}, uint8_t>(V, funct6, funct3, vl, vstart, vtype, vxrm, vm, vd, vs2, imm);
case 0b001:
return softvector::sat_vector_imm_op<${vlen}, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vxrm, vm, vd, vs2, imm);
case 0b010:
return softvector::sat_vector_imm_op<${vlen}, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vxrm, vm, vd, vs2, imm);
case 0b011:
return softvector::sat_vector_imm_op<${vlen}, uint64_t>(V, funct6, funct3, vl, vstart, vtype, vxrm, vm, vd, vs2, imm);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
bool sat_vector_vector_vw(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, uint64_t vxrm, bool vm, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::sat_vector_vector_op<${vlen}, uint8_t, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vxrm, vm, vd, vs2, vs1);
case 0b001:
return softvector::sat_vector_vector_op<${vlen}, uint16_t, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vxrm, vm, vd, vs2, vs1);
case 0b010:
return softvector::sat_vector_vector_op<${vlen}, uint32_t, uint64_t>(V, funct6, funct3, vl, vstart, vtype, vxrm, vm, vd, vs2, vs1);
case 0b011: // would require 128 bits vs2 value
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
bool sat_vector_imm_vw(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, uint64_t vxrm, bool vm, uint8_t vd, uint8_t vs2, int64_t imm, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::sat_vector_imm_op<${vlen}, uint8_t, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vxrm, vm, vd, vs2, imm);
case 0b001:
return softvector::sat_vector_imm_op<${vlen}, uint16_t, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vxrm, vm, vd, vs2, imm);
case 0b010:
return softvector::sat_vector_imm_op<${vlen}, uint32_t, uint64_t>(V, funct6, funct3, vl, vstart, vtype, vxrm, vm, vd, vs2, imm);
case 0b011: // would require 128 bits vs2 value
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_red_op(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::vector_red_op<${vlen}, uint8_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b001:
return softvector::vector_red_op<${vlen}, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b010:
return softvector::vector_red_op<${vlen}, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b011:
return softvector::vector_red_op<${vlen}, uint64_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_red_wv(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::vector_red_op<${vlen}, uint16_t, uint8_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b001:
return softvector::vector_red_op<${vlen}, uint32_t, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b010:
return softvector::vector_red_op<${vlen}, uint64_t, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b011: // would require 128 bits vs2 value
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void mask_mask_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, unsigned vd, unsigned vs2, unsigned vs1){
return softvector::mask_mask_op<${vlen}>(V, funct6, funct3, vl, vstart, vd, vs2, vs1);
}
uint64_t vcpop(uint8_t* V, uint64_t vl, uint64_t vstart, bool vm, unsigned vs2){
return softvector::vcpop<${vlen}>(V, vl, vstart, vm, vs2);
}
int64_t vfirst(uint8_t* V, uint64_t vl, uint64_t vstart, bool vm, unsigned vs2){
return softvector::vfirst<${vlen}>(V, vl, vstart, vm, vs2);
}
void mask_set_op(uint8_t* V, unsigned enc, uint64_t vl, uint64_t vstart, bool vm, unsigned vd, unsigned vs2){
return softvector::mask_set_op<${vlen}>(V, enc, vl, vstart, vm, vd, vs2);
}
void viota(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::viota<${vlen}, uint8_t>(V, vl, vstart, vtype, vm, vd, vs2);
case 0b001:
return softvector::viota<${vlen}, uint16_t>(V, vl, vstart, vtype, vm, vd, vs2);
case 0b010:
return softvector::viota<${vlen}, uint32_t>(V, vl, vstart, vtype, vm, vd, vs2);
case 0b011:
return softvector::viota<${vlen}, uint64_t>(V, vl, vstart, vtype, vm, vd, vs2);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vid(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::vid<${vlen}, uint8_t>(V, vl, vstart, vtype, vm, vd);
case 0b001:
return softvector::vid<${vlen}, uint16_t>(V, vl, vstart, vtype, vm, vd);
case 0b010:
return softvector::vid<${vlen}, uint32_t>(V, vl, vstart, vtype, vm, vd);
case 0b011:
return softvector::vid<${vlen}, uint64_t>(V, vl, vstart, vtype, vm, vd);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void scalar_to_vector(uint8_t* V, softvector::vtype_t vtype, unsigned vd, uint64_t val, uint8_t sew_val){
switch(sew_val){
case 0b000:
softvector::scalar_move<${vlen}, uint8_t>(V, vtype, vd, val, true);
break;
case 0b001:
softvector::scalar_move<${vlen}, uint16_t>(V, vtype, vd, val, true);
break;
case 0b010:
softvector::scalar_move<${vlen}, uint32_t>(V, vtype, vd, val, true);
break;
case 0b011:
softvector::scalar_move<${vlen}, uint64_t>(V, vtype, vd, val, true);
break;
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
uint64_t scalar_from_vector(uint8_t* V, softvector::vtype_t vtype, unsigned vd, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::scalar_move<${vlen}, uint8_t>(V, vtype, vd, 0, false);
case 0b001:
return softvector::scalar_move<${vlen}, uint16_t>(V, vtype, vd, 0, false);
case 0b010:
return softvector::scalar_move<${vlen}, uint32_t>(V, vtype, vd, 0, false);
case 0b011:
return softvector::scalar_move<${vlen}, uint64_t>(V, vtype, vd, 0, false);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_slideup(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, unsigned vd, unsigned vs2, uint64_t imm, uint8_t sew_val) {
switch(sew_val){
case 0b000:
return softvector::vector_slideup<${vlen}, uint8_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b001:
return softvector::vector_slideup<${vlen}, uint16_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b010:
return softvector::vector_slideup<${vlen}, uint32_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b011:
return softvector::vector_slideup<${vlen}, uint64_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_slidedown(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, unsigned vd, unsigned vs2, uint64_t imm, uint8_t sew_val) {
switch(sew_val){
case 0b000:
return softvector::vector_slidedown<${vlen}, uint8_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b001:
return softvector::vector_slidedown<${vlen}, uint16_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b010:
return softvector::vector_slidedown<${vlen}, uint32_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b011:
return softvector::vector_slidedown<${vlen}, uint64_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_slide1up(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, unsigned vd, unsigned vs2, uint64_t imm, uint8_t sew_val) {
switch(sew_val){
case 0b000:
return softvector::vector_slide1up<${vlen}, uint8_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b001:
return softvector::vector_slide1up<${vlen}, uint16_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b010:
return softvector::vector_slide1up<${vlen}, uint32_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b011:
return softvector::vector_slide1up<${vlen}, uint64_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_slide1down(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, unsigned vd, unsigned vs2, uint64_t imm, uint8_t sew_val) {
switch(sew_val){
case 0b000:
return softvector::vector_slide1down<${vlen}, uint8_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b001:
return softvector::vector_slide1down<${vlen}, uint16_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b010:
return softvector::vector_slide1down<${vlen}, uint32_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b011:
return softvector::vector_slide1down<${vlen}, uint64_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_vector_gather(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::vector_vector_gather<${vlen}, uint8_t>(V, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b001:
return softvector::vector_vector_gather<${vlen}, uint16_t>(V, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b010:
return softvector::vector_vector_gather<${vlen}, uint32_t>(V, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b011:
return softvector::vector_vector_gather<${vlen}, uint64_t>(V, vl, vstart, vtype, vm, vd, vs2, vs1);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_vector_gatherei16(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::vector_vector_gather<${vlen}, uint8_t, uint16_t>(V, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b001:
return softvector::vector_vector_gather<${vlen}, uint16_t, uint16_t>(V, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b010:
return softvector::vector_vector_gather<${vlen}, uint32_t, uint16_t>(V, vl, vstart, vtype, vm, vd, vs2, vs1);
case 0b011:
return softvector::vector_vector_gather<${vlen}, uint64_t, uint16_t>(V, vl, vstart, vtype, vm, vd, vs2, vs1);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_imm_gather(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint64_t imm, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::vector_imm_gather<${vlen}, uint8_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b001:
return softvector::vector_imm_gather<${vlen}, uint16_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b010:
return softvector::vector_imm_gather<${vlen}, uint32_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
case 0b011:
return softvector::vector_imm_gather<${vlen}, uint64_t>(V, vl, vstart, vtype, vm, vd, vs2, imm);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_compress(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::vector_compress<${vlen}, uint8_t>(V, vl, vstart, vtype, vd, vs2, vs1);
case 0b001:
return softvector::vector_compress<${vlen}, uint16_t>(V, vl, vstart, vtype, vd, vs2, vs1);
case 0b010:
return softvector::vector_compress<${vlen}, uint32_t>(V, vl, vstart, vtype, vd, vs2, vs1);
case 0b011:
return softvector::vector_compress<${vlen}, uint64_t>(V, vl, vstart, vtype, vd, vs2, vs1);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_whole_move(uint8_t* V, uint8_t vd, uint8_t vs2, uint8_t count){
return softvector::vector_whole_move<${vlen}>(V, vd, vs2, count);
}
uint64_t fp_scalar_from_vector(uint8_t* V, softvector::vtype_t vtype, unsigned vd, uint8_t sew_val){
return scalar_from_vector(V, vtype, vd, sew_val);
}
void fp_vector_slide1up(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, unsigned vd, unsigned vs2, uint64_t imm, uint8_t sew_val) {
return vector_slide1up(V, vl, vstart, vtype, vm, vd, vs2, imm, sew_val);
}
void fp_vector_slide1down(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, unsigned vd, unsigned vs2, uint64_t imm, uint8_t sew_val) {
return vector_slide1down(V, vl, vstart, vtype, vm, vd, vs2, imm, sew_val);
}
void fp_vector_red_op(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t rm, uint8_t sew_val){
switch(sew_val){
case 0b000:
throw new std::runtime_error("Unsupported sew bit value");
case 0b001:
return softvector::fp_vector_red_op<${vlen}, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1, rm);
case 0b010:
return softvector::fp_vector_red_op<${vlen}, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1, rm);
case 0b011:
return softvector::fp_vector_red_op<${vlen}, uint64_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1, rm);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void fp_vector_red_wv(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t rm, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::fp_vector_red_op<${vlen}, uint16_t, uint8_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1, rm);
case 0b001:
return softvector::fp_vector_red_op<${vlen}, uint32_t, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1, rm);
case 0b010:
return softvector::fp_vector_red_op<${vlen}, uint64_t, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1, rm);
case 0b011: // would require 128 bits vs2 value
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void fp_vector_vector_op(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t rm, uint8_t sew_val){
switch(sew_val){
case 0b000:
throw new std::runtime_error("Unsupported sew bit value");
case 0b001:
return softvector::fp_vector_vector_op<${vlen}, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1, rm);
case 0b010:
return softvector::fp_vector_vector_op<${vlen}, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1, rm);
case 0b011:
return softvector::fp_vector_vector_op<${vlen}, uint64_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1, rm);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void fp_vector_imm_op(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint64_t imm, uint8_t rm, uint8_t sew_val){
switch(sew_val){
case 0b000:
throw new std::runtime_error("Unsupported sew bit value");
case 0b001:
return softvector::fp_vector_imm_op<${vlen}, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm, rm);
case 0b010:
return softvector::fp_vector_imm_op<${vlen}, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm, rm);
case 0b011:
return softvector::fp_vector_imm_op<${vlen}, uint64_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm, rm);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void fp_vector_vector_wv(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t rm, uint8_t sew_val){
switch(sew_val){
case 0b000:
throw new std::runtime_error("Unsupported sew bit value");
case 0b001:
return softvector::fp_vector_vector_op<${vlen}, uint32_t, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1, rm);
case 0b010:
return softvector::fp_vector_vector_op<${vlen}, uint64_t, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1, rm);
case 0b011: // would widen to 128 bits
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void fp_vector_imm_wv(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint64_t imm, uint8_t rm, uint8_t sew_val){
switch(sew_val){
case 0b000:
throw new std::runtime_error("Unsupported sew bit value");
case 0b001:
return softvector::fp_vector_imm_op<${vlen}, uint32_t, uint16_t, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm, rm);
case 0b010:
return softvector::fp_vector_imm_op<${vlen}, uint64_t, uint32_t, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm, rm);
case 0b011: // would widen to 128 bits
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void fp_vector_vector_ww(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t rm, uint8_t sew_val){
switch(sew_val){
case 0b000:
throw new std::runtime_error("Unsupported sew bit value");
case 0b001:
return softvector::fp_vector_vector_op<${vlen}, uint32_t, uint32_t, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1, rm);
case 0b010:
return softvector::fp_vector_vector_op<${vlen}, uint64_t, uint64_t, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1, rm);
case 0b011: // would widen to 128 bits
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void fp_vector_imm_ww(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint64_t imm, uint8_t rm, uint8_t sew_val){
switch(sew_val){
case 0b000:
throw new std::runtime_error("Unsupported sew bit value");
case 0b001:
return softvector::fp_vector_imm_op<${vlen}, uint32_t, uint32_t, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm, rm);
case 0b010:
return softvector::fp_vector_imm_op<${vlen}, uint64_t, uint64_t, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, imm, rm);
case 0b011: // would widen to 128 bits
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void fp_vector_unary_op(uint8_t* V, uint8_t encoding_space, uint8_t unary_op, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t rm, uint8_t sew_val){
switch(sew_val){
case 0b000:
throw new std::runtime_error("Unsupported sew bit value");
case 0b001:
return softvector::fp_vector_unary_op<${vlen}, uint16_t>(V, encoding_space, unary_op, vl, vstart, vtype, vm, vd, vs2, rm);
case 0b010:
return softvector::fp_vector_unary_op<${vlen}, uint32_t>(V, encoding_space, unary_op, vl, vstart, vtype, vm, vd, vs2, rm);
case 0b011:
return softvector::fp_vector_unary_op<${vlen}, uint64_t>(V, encoding_space, unary_op, vl, vstart, vtype, vm, vd, vs2, rm);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void mask_fp_vector_vector_op(uint8_t* V, uint8_t funct6, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t rm, uint8_t sew_val){
switch(sew_val){
case 0b000:
throw new std::runtime_error("Unsupported sew bit value");
case 0b001:
return softvector::mask_fp_vector_vector_op<${vlen}, uint16_t>(V, funct6, vl, vstart, vtype, vm, vd, vs2, vs1, rm);
case 0b010:
return softvector::mask_fp_vector_vector_op<${vlen}, uint32_t>(V, funct6, vl, vstart, vtype, vm, vd, vs2, vs1, rm);
case 0b011:
return softvector::mask_fp_vector_vector_op<${vlen}, uint64_t>(V, funct6, vl, vstart, vtype, vm, vd, vs2, vs1, rm);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void mask_fp_vector_imm_op(uint8_t* V, uint8_t funct6, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint64_t imm, uint8_t rm, uint8_t sew_val){
switch(sew_val){
case 0b000:
throw new std::runtime_error("Unsupported sew bit value");
case 0b001:
return softvector::mask_fp_vector_imm_op<${vlen}, uint16_t>(V, funct6, vl, vstart, vtype, vm, vd, vs2, imm, rm);
case 0b010:
return softvector::mask_fp_vector_imm_op<${vlen}, uint32_t>(V, funct6, vl, vstart, vtype, vm, vd, vs2, imm, rm);
case 0b011:
return softvector::mask_fp_vector_imm_op<${vlen}, uint64_t>(V, funct6, vl, vstart, vtype, vm, vd, vs2, imm, rm);
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void fp_vector_imm_merge(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint64_t imm, uint8_t sew_val){
vector_imm_merge(V, vl, vstart, vtype, vm, vd, vs2, imm, sew_val);
}
void fp_vector_unary_w(uint8_t* V, uint8_t unary_op, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t rm, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::fp_vector_unary_w<${vlen}, uint16_t, uint8_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2, rm);
case 0b001:
return softvector::fp_vector_unary_w<${vlen}, uint32_t, uint16_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2, rm);
case 0b010:
return softvector::fp_vector_unary_w<${vlen}, uint64_t, uint32_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2, rm);
case 0b011: // would widen to 128 bits
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void fp_vector_unary_n(uint8_t* V, uint8_t unary_op, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t rm, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::fp_vector_unary_n<${vlen}, uint8_t, uint16_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2, rm);
case 0b001:
return softvector::fp_vector_unary_n<${vlen}, uint16_t, uint32_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2, rm);
case 0b010:
return softvector::fp_vector_unary_n<${vlen}, uint32_t, uint64_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2, rm);
case 0b011: // would require 128 bit value to narrow
default:
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_unary_op(uint8_t* V, uint8_t unary_op, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::vector_unary_op<${vlen}, uint8_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
case 0b001:
return softvector::vector_unary_op<${vlen}, uint16_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
case 0b010:
return softvector::vector_unary_op<${vlen}, uint32_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
case 0b011:
return softvector::vector_unary_op<${vlen}, uint64_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
default:
throw new std::runtime_error("Unsupported sew_val");
}
}
<%}%>
uint64_t fetch_count{0}; uint64_t fetch_count{0};
uint64_t tval{0}; uint64_t tval{0};
@@ -175,22 +1024,8 @@ private:
decoder instr_decoder; decoder instr_decoder;
iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ iss::status fetch_ins(virt_addr_t pc, uint8_t * data){
if(this->core.has_mmu()) { if (this->core.read(iss::address_type::PHYSICAL, pc.access, pc.space, pc.val, 4, data) != iss::Ok)
auto phys_pc = this->core.virt2phys(pc); return iss::Err;
// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
// if (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err;
// if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction
// if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok)
// return iss::Err;
// } else {
if (this->core.read(phys_pc, 4, data) != iss::Ok)
return iss::Err;
// }
} else {
if (this->core.read(phys_addr_t(pc.access, pc.space, pc.val), 4, data) != iss::Ok)
return iss::Err;
}
return iss::Ok; return iss::Ok;
} }
}; };
@@ -285,8 +1120,8 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
// used registers<%instr.usedVariables.each{ k,v-> // used registers<%instr.usedVariables.each{ k,v->
if(v.isArray) {%> if(v.isArray) {%>
auto* ${k} = reinterpret_cast<uint${nativeTypeSize(v.type.size)}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::${k}0]);<% }else{ %> auto* ${k} = reinterpret_cast<uint${nativeTypeSize(v.type.size)}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::${k}0]);<% }else{ %>
auto* ${k} = reinterpret_cast<uint${nativeTypeSize(v.type.size)}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::${k}]); auto* ${k} = reinterpret_cast<uint${nativeTypeSize(v.type.size)}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::${k}]);<%}}%>
<%}}%>// calculate next pc value // calculate next pc value
*NEXT_PC = *PC + ${instr.length/8}; *NEXT_PC = *PC + ${instr.length/8};
// execute instruction<%instr.behavior.eachLine{%> // execute instruction<%instr.behavior.eachLine{%>
${it}<%}%> ${it}<%}%>
+27 -6
View File
@@ -31,12 +31,14 @@
*******************************************************************************/ *******************************************************************************/
// clang-format off // clang-format off
#include <iss/arch/${coreDef.name.toLowerCase()}.h> #include <iss/arch/${coreDef.name.toLowerCase()}.h>
// vm_base needs to be included before gdb_session as termios.h (via boost and gdb_server) has a define which clashes with a variable
// name in ConstantRange.h
#include <iss/llvm/vm_base.h>
#include <iss/iss.h>
#include <iss/debugger/gdb_session.h> #include <iss/debugger/gdb_session.h>
#include <iss/debugger/server.h> #include <iss/debugger/server.h>
#include <iss/iss.h>
#include <iss/llvm/vm_base.h>
#include <util/logging.h>
#include <iss/instruction_decoder.h> #include <iss/instruction_decoder.h>
#include <util/logging.h>
<%def fcsr = registers.find {it.name=='FCSR'} <%def fcsr = registers.find {it.name=='FCSR'}
if(fcsr != null) {%> if(fcsr != null) {%>
#include <vm/fp_functions.h><%}%> #include <vm/fp_functions.h><%}%>
@@ -136,7 +138,28 @@ protected:
return (from & mask) | ((from & sign_mask) ? ~mask : 0); return (from & mask) | ((from & sign_mask) ? ~mask : 0);
} }
<%functions.each{ it.eachLine { %> <%functions.each{ it.eachLine { %>
${it}<%}%> ${it}<%}
}
if(fcsr != null) {%>
Value* NaNBox16(BasicBlock* bb, Value* NaNBox16_val){
if(static_cast<uint32_t>(traits::FLEN) == 16)
return this->gen_ext(NaNBox16_val, traits::FLEN, false);
auto box = this->builder.CreateNot((this->gen_ext(0, 32, false)));
return this->gen_ext((this->builder.CreateOr(this->builder.CreateShl(this->gen_ext(box, traits::FLEN), 16), this->gen_ext(NaNBox16_val, traits::FLEN))), traits::FLEN, false);
}
Value* NaNBox32(BasicBlock* bb, Value* NaNBox32_val){
if(static_cast<uint32_t>(traits::FLEN) == 32)
return this->gen_ext(NaNBox32_val, traits::FLEN, false);
auto box = this->builder.CreateNot((this->gen_ext(0, 64, false)));
return this->gen_ext((this->builder.CreateOr(this->builder.CreateShl(this->gen_ext(box, traits::FLEN), 32), this->gen_ext(NaNBox32_val, traits::FLEN))), traits::FLEN, false);
}
Value* NaNBox64(BasicBlock* bb, Value* NaNBox64_val){
if(static_cast<uint32_t>(traits::FLEN) == 64)
return this->gen_ext(NaNBox64_val, traits::FLEN, false);
auto box = this->builder.CreateNot((this->gen_ext(0, 128, false)));
return this->gen_ext((this->builder.CreateOr(this->builder.CreateShl(this->gen_ext(box, traits::FLEN), 64), this->gen_ext(NaNBox64_val, traits::FLEN))), traits::FLEN, false);
}
<%}%> <%}%>
private: private:
/**************************************************************************** /****************************************************************************
@@ -251,8 +274,6 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, BasicBlock *this_block)
// const typename traits::addr_t upper_bits = ~traits::PGMASK; // const typename traits::addr_t upper_bits = ~traits::PGMASK;
phys_addr_t paddr(pc); phys_addr_t paddr(pc);
auto *const data = (uint8_t *)&instr; auto *const data = (uint8_t *)&instr;
if(this->core.has_mmu())
paddr = this->core.virt2phys(pc);
auto res = this->core.read(paddr, 4, data); auto res = this->core.read(paddr, 4, data);
if (res != iss::Ok) if (res != iss::Ok)
return std::make_tuple(ILLEGAL_FETCH, nullptr); return std::make_tuple(ILLEGAL_FETCH, nullptr);
+80 -12
View File
@@ -139,7 +139,34 @@ if(fcsr != null) {%>
} }
<%functions.each{ it.eachLine { %> <%functions.each{ it.eachLine { %>
${it}<%}%> ${it}<%}
}
if(fcsr != null) {%>
value NaNBox16(tu_builder& tu, value NaNBox16_val){
if(static_cast<uint32_t>(traits::FLEN) == 16)
return tu.ext(NaNBox16_val, traits::FLEN, false);
else {
auto box = tu.assignment(tu.logical_neg((tu.ext(0, 32, false))), traits::FLEN) ;
return tu.ext((tu.bitwise_or(tu.shl(box, 16), NaNBox16_val)), traits::FLEN, false);
}
}
value NaNBox32(tu_builder& tu, value NaNBox32_val){
if(static_cast<uint32_t>(traits::FLEN) == 32)
return tu.ext(NaNBox32_val, traits::FLEN, false);
else {
auto box = tu.assignment(tu.logical_neg((tu.ext(0, 64, false))), traits::FLEN) ;
return tu.ext((tu.bitwise_or(tu.shl(box, 32), NaNBox32_val)), traits::FLEN, false);
}
}
value NaNBox64(tu_builder& tu, value NaNBox64_val){
if(static_cast<uint32_t>(traits::FLEN) == 64)
return tu.ext(NaNBox64_val, traits::FLEN, false);
else {
throw new std::runtime_error("tcc does not support Registers wider than 64 bits");
auto box = tu.assignment(tu.logical_neg((tu.ext(0, 128, false))), traits::FLEN) ;
return tu.ext((tu.bitwise_or(tu.shl(box, 64), NaNBox64_val)), traits::FLEN, false);
}
}
<%}%> <%}%>
private: private:
/**************************************************************************** /****************************************************************************
@@ -181,6 +208,8 @@ private:
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
<%instr.behavior.eachLine{%>${it} <%instr.behavior.eachLine{%>${it}
<%}%> <%}%>
tu("(*icount)++;");
tu("(*instret)++;");
tu.close_scope(); tu.close_scope();
vm_base<ARCH>::gen_sync(tu, POST_SYNC,${idx}); vm_base<ARCH>::gen_sync(tu, POST_SYNC,${idx});
gen_trap_check(tu); gen_trap_check(tu);
@@ -232,8 +261,6 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, tu_builder& tu) {
enum {TRAP_ID=1<<16}; enum {TRAP_ID=1<<16};
code_word_t instr = 0; code_word_t instr = 0;
phys_addr_t paddr(pc); phys_addr_t paddr(pc);
if(this->core.has_mmu())
paddr = this->core.virt2phys(pc);
auto res = this->core.read(paddr, 4, reinterpret_cast<uint8_t*>(&instr)); auto res = this->core.read(paddr, 4, reinterpret_cast<uint8_t*>(&instr));
if (res != iss::Ok) if (res != iss::Ok)
return ILLEGAL_FETCH; return ILLEGAL_FETCH;
@@ -278,34 +305,75 @@ template <typename ARCH> void vm_impl<ARCH>::add_prologue(tu_builder& tu){
os << tu.add_reg_ptr("trap_state", arch::traits<ARCH>::TRAP_STATE, this->regs_base_ptr); os << tu.add_reg_ptr("trap_state", arch::traits<ARCH>::TRAP_STATE, this->regs_base_ptr);
os << tu.add_reg_ptr("pending_trap", arch::traits<ARCH>::PENDING_TRAP, this->regs_base_ptr); os << tu.add_reg_ptr("pending_trap", arch::traits<ARCH>::PENDING_TRAP, this->regs_base_ptr);
os << tu.add_reg_ptr("cycle", arch::traits<ARCH>::CYCLE, this->regs_base_ptr); os << tu.add_reg_ptr("cycle", arch::traits<ARCH>::CYCLE, this->regs_base_ptr);
<%if(fcsr != null) {%> <%if(fcsr != null) {
def flen = constants.find { it.name == 'FLEN' }?.value ?: 0
%>
os << "uint32_t (*fget_flags)()=" << (uintptr_t)&fget_flags << ";\\n"; os << "uint32_t (*fget_flags)()=" << (uintptr_t)&fget_flags << ";\\n";
os << "uint16_t (*fadd_h)(uint16_t v1, uint16_t v2, uint8_t mode)=" << (uintptr_t)&fadd_h << ";\\n";
os << "uint16_t (*fsub_h)(uint16_t v1, uint16_t v2, uint8_t mode)=" << (uintptr_t)&fsub_h << ";\\n";
os << "uint16_t (*fmul_h)(uint16_t v1, uint16_t v2, uint8_t mode)=" << (uintptr_t)&fmul_h << ";\\n";
os << "uint16_t (*fdiv_h)(uint16_t v1, uint16_t v2, uint8_t mode)=" << (uintptr_t)&fdiv_h << ";\\n";
os << "uint16_t (*fsqrt_h)(uint16_t v1, uint8_t mode)=" << (uintptr_t)&fsqrt_h << ";\\n";
os << "uint16_t (*fcmp_h)(uint16_t v1, uint16_t v2, uint16_t op)=" << (uintptr_t)&fcmp_h << ";\\n";
os << "uint16_t (*fmadd_h)(uint16_t v1, uint16_t v2, uint16_t v3, uint16_t op, uint8_t mode)=" << (uintptr_t)&fmadd_h << ";\\n";
os << "uint16_t (*fsel_h)(uint16_t v1, uint16_t v2, uint16_t op)=" << (uintptr_t)&fsel_h << ";\\n";
os << "uint16_t (*fclass_h)(uint16_t v1)=" << (uintptr_t)&fclass_h << ";\\n";
os << "uint16_t (*unbox_h)(uint8_t FLEN, uint64_t v)=" << (uintptr_t)&unbox_h << ";\\n";
os << "uint32_t (*f16toi32)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f16toi32 << ";\\n";
os << "uint32_t (*f16toui32)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f16toui32 << ";\\n";
os << "uint16_t (*i32tof16)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&i32tof16 << ";\\n";
os << "uint16_t (*ui32tof16)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&ui32tof16 << ";\\n";
os << "uint64_t (*f16toi64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f16toi64 <<";\\n";
os << "uint64_t (*f16toui64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f16toui64 <<";\\n";
os << "uint16_t (*i64tof16)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&i64tof16 <<";\\n";
os << "uint16_t (*ui64tof16)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&ui64tof16 <<";\\n";
os << "uint32_t (*fadd_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fadd_s << ";\\n"; os << "uint32_t (*fadd_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fadd_s << ";\\n";
os << "uint32_t (*fsub_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fsub_s << ";\\n"; os << "uint32_t (*fsub_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fsub_s << ";\\n";
os << "uint32_t (*fmul_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fmul_s << ";\\n"; os << "uint32_t (*fmul_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fmul_s << ";\\n";
os << "uint32_t (*fdiv_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fdiv_s << ";\\n"; os << "uint32_t (*fdiv_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fdiv_s << ";\\n";
os << "uint32_t (*fsqrt_s)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&fsqrt_s << ";\\n"; os << "uint32_t (*fsqrt_s)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&fsqrt_s << ";\\n";
os << "uint32_t (*fcmp_s)(uint32_t v1, uint32_t v2, uint32_t op)=" << (uintptr_t)&fcmp_s << ";\\n"; os << "uint32_t (*fcmp_s)(uint32_t v1, uint32_t v2, uint32_t op)=" << (uintptr_t)&fcmp_s << ";\\n";
os << "uint32_t (*fcvt_s)(uint32_t v1, uint32_t op, uint8_t mode)=" << (uintptr_t)&fcvt_s << ";\\n";
os << "uint32_t (*fmadd_s)(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mode)=" << (uintptr_t)&fmadd_s << ";\\n"; os << "uint32_t (*fmadd_s)(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mode)=" << (uintptr_t)&fmadd_s << ";\\n";
os << "uint32_t (*fsel_s)(uint32_t v1, uint32_t v2, uint32_t op)=" << (uintptr_t)&fsel_s << ";\\n"; os << "uint32_t (*fsel_s)(uint32_t v1, uint32_t v2, uint32_t op)=" << (uintptr_t)&fsel_s << ";\\n";
os << "uint32_t (*fclass_s)( uint32_t v1 )=" << (uintptr_t)&fclass_s << ";\\n"; os << "uint32_t (*fclass_s)( uint32_t v1 )=" << (uintptr_t)&fclass_s << ";\\n";
os << "uint32_t (*fconv_d2f)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&fconv_d2f << ";\\n"; os << "uint32_t (*unbox_s)(uint8_t FLEN, uint64_t v)=" << (uintptr_t)&unbox_s << ";\\n";
os << "uint64_t (*fconv_f2d)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&fconv_f2d << ";\\n";
os << "uint32_t (*f32toi32)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f32toi32 << ";\\n";
os << "uint32_t (*f32toui32)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f32toui32 << ";\\n";
os << "uint32_t (*i32tof32)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&i32tof32 << ";\\n";
os << "uint32_t (*ui32tof32)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&ui32tof32 << ";\\n";
os << "uint64_t (*f32toi64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f32toi64 <<";\\n";
os << "uint64_t (*f32toui64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f32toui64 <<";\\n";
os << "uint32_t (*i64tof32)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&i64tof32 <<";\\n";
os << "uint32_t (*ui64tof32)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&ui64tof32 <<";\\n";
<%if(flen > 32) {%>
os << "uint64_t (*fadd_d)(uint64_t v1, uint64_t v2, uint8_t mode)=" << (uintptr_t)&fadd_d << ";\\n"; os << "uint64_t (*fadd_d)(uint64_t v1, uint64_t v2, uint8_t mode)=" << (uintptr_t)&fadd_d << ";\\n";
os << "uint64_t (*fsub_d)(uint64_t v1, uint64_t v2, uint8_t mode)=" << (uintptr_t)&fsub_d << ";\\n"; os << "uint64_t (*fsub_d)(uint64_t v1, uint64_t v2, uint8_t mode)=" << (uintptr_t)&fsub_d << ";\\n";
os << "uint64_t (*fmul_d)(uint64_t v1, uint64_t v2, uint8_t mode)=" << (uintptr_t)&fmul_d << ";\\n"; os << "uint64_t (*fmul_d)(uint64_t v1, uint64_t v2, uint8_t mode)=" << (uintptr_t)&fmul_d << ";\\n";
os << "uint64_t (*fdiv_d)(uint64_t v1, uint64_t v2, uint8_t mode)=" << (uintptr_t)&fdiv_d << ";\\n"; os << "uint64_t (*fdiv_d)(uint64_t v1, uint64_t v2, uint8_t mode)=" << (uintptr_t)&fdiv_d << ";\\n";
os << "uint64_t (*fsqrt_d)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&fsqrt_d << ";\\n"; os << "uint64_t (*fsqrt_d)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&fsqrt_d << ";\\n";
os << "uint64_t (*fcmp_d)(uint64_t v1, uint64_t v2, uint32_t op)=" << (uintptr_t)&fcmp_d << ";\\n"; os << "uint64_t (*fcmp_d)(uint64_t v1, uint64_t v2, uint32_t op)=" << (uintptr_t)&fcmp_d << ";\\n";
os << "uint64_t (*fcvt_d)(uint64_t v1, uint32_t op, uint8_t mode)=" << (uintptr_t)&fcvt_d << ";\\n";
os << "uint64_t (*fmadd_d)(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode)=" << (uintptr_t)&fmadd_d << ";\\n"; os << "uint64_t (*fmadd_d)(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode)=" << (uintptr_t)&fmadd_d << ";\\n";
os << "uint64_t (*fsel_d)(uint64_t v1, uint64_t v2, uint32_t op)=" << (uintptr_t)&fsel_d << ";\\n"; os << "uint64_t (*fsel_d)(uint64_t v1, uint64_t v2, uint32_t op)=" << (uintptr_t)&fsel_d << ";\\n";
os << "uint64_t (*fclass_d)(uint64_t v1 )=" << (uintptr_t)&fclass_d << ";\\n"; os << "uint64_t (*fclass_d)(uint64_t v1 )=" << (uintptr_t)&fclass_d << ";\\n";
os << "uint64_t (*fcvt_32_64)(uint32_t v1, uint32_t op, uint8_t mode)=" << (uintptr_t)&fcvt_32_64 << ";\\n"; os << "uint64_t (*unbox_d)(uint8_t FLEN, uint64_t v)=" << (uintptr_t)&unbox_d << ";\\n";
os << "uint32_t (*fcvt_64_32)(uint64_t v1, uint32_t op, uint8_t mode)=" << (uintptr_t)&fcvt_64_32 << ";\\n";
os << "uint32_t (*unbox_s)(uint64_t v)=" << (uintptr_t)&unbox_s << ";\\n"; os << "uint32_t (*f64tof32)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&f64tof32 << ";\\n";
<%}%> os << "uint64_t (*f32tof64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f32tof64 << ";\\n";
os << "uint64_t (*f64toi64)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&f64toi64 <<";\\n";
os << "uint64_t (*f64toui64)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&f64toui64 <<";\\n";
os << "uint64_t (*i64tof64)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&i64tof64 <<";\\n";
os << "uint64_t (*ui64tof64)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&ui64tof64 <<";\\n";
os << "uint64_t (*i32tof64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&i32tof64 <<";\\n";
os << "uint64_t (*ui32tof64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&ui32tof64 <<";\\n";
os << "uint32_t (*f64toi32)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&f64toi32 <<";\\n";
os << "uint32_t (*f64toui32)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&f64toui32 <<";\\n";
<%}
}%>
tu.add_prologue(os.str()); tu.add_prologue(os.str());
} }
+34
View File
@@ -1,3 +1,37 @@
/*******************************************************************************
* Copyright (C) 2024 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* eyck@minres.com - initial implementation
******************************************************************************/
#ifdef _MSC_VER #ifdef _MSC_VER
#define _SCL_SECURE_NO_WARNINGS #define _SCL_SECURE_NO_WARNINGS
#define ELFIO_NO_INTTYPES #define ELFIO_NO_INTTYPES
+127 -75
View File
@@ -35,19 +35,18 @@
#ifndef _RISCV_HART_COMMON #ifndef _RISCV_HART_COMMON
#define _RISCV_HART_COMMON #define _RISCV_HART_COMMON
#include "iss/arch/traits.h"
#include "iss/log_categories.h"
#include "iss/mmio/memory_if.h"
#include "iss/vm_types.h"
#include "mstatus.h" #include "mstatus.h"
#include "util/delegate.h" #include "util/delegate.h"
#include <array> #include <array>
#include <cstdint> #include <cstdint>
#include <elfio/elfio.hpp> #include <elfio/elfio.hpp>
#include <fmt/format.h> #include <fmt/format.h>
#include <iss/arch/traits.h>
#include <iss/arch_if.h> #include <iss/arch_if.h>
#include <iss/log_categories.h> #include <iss/log_categories.h>
#include <iss/mem/memory_if.h>
#include <iss/semihosting/semihosting.h> #include <iss/semihosting/semihosting.h>
#include <iss/vm_types.h>
#include <limits> #include <limits>
#include <sstream> #include <sstream>
#include <string> #include <string>
@@ -195,26 +194,19 @@ enum riscv_csr {
dcsr = 0x7B0, dcsr = 0x7B0,
dpc = 0x7B1, dpc = 0x7B1,
dscratch0 = 0x7B2, dscratch0 = 0x7B2,
dscratch1 = 0x7B3 dscratch1 = 0x7B3,
// vector CSR
// URW
vstart = 0x008,
vxsat = 0x009,
vxrm = 0x00A,
vcsr = 0x00F,
// URO
vl = 0xC20,
vtype = 0xC21,
vlenb = 0xC22,
}; };
enum {
PGSHIFT = 12,
PTE_PPN_SHIFT = 10,
// page table entry (PTE) fields
PTE_V = 0x001, // Valid
PTE_R = 0x002, // Read
PTE_W = 0x004, // Write
PTE_X = 0x008, // Execute
PTE_U = 0x010, // User
PTE_G = 0x020, // Global
PTE_A = 0x040, // Accessed
PTE_D = 0x080, // Dirty
PTE_SOFT = 0x300 // Reserved for Software
};
template <typename T> inline bool PTE_TABLE(T PTE) { return (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V); }
enum { PRIV_U = 0, PRIV_S = 1, PRIV_M = 3, PRIV_D = 4 }; enum { PRIV_U = 0, PRIV_S = 1, PRIV_M = 3, PRIV_D = 4 };
enum { enum {
@@ -233,31 +225,11 @@ enum {
ISA_U = 1 << 20 ISA_U = 1 << 20
}; };
struct vm_info {
int levels;
int idxbits;
int ptesize;
uint64_t ptbase;
bool is_active() { return levels; }
};
struct feature_config {
uint64_t tcm_base{0x10000000};
uint64_t tcm_size{0x8000};
uint64_t io_address{0xf0000000};
uint64_t io_addr_mask{0xf0000000};
};
class trap_load_access_fault : public trap_access { class trap_load_access_fault : public trap_access {
public: public:
trap_load_access_fault(uint64_t badaddr) trap_load_access_fault(uint64_t badaddr)
: trap_access(5 << 16, badaddr) {} : trap_access(5 << 16, badaddr) {}
}; };
class illegal_instruction_fault : public trap_access {
public:
illegal_instruction_fault(uint64_t badaddr)
: trap_access(2 << 16, badaddr) {}
};
class trap_instruction_page_fault : public trap_access { class trap_instruction_page_fault : public trap_access {
public: public:
trap_instruction_page_fault(uint64_t badaddr) trap_instruction_page_fault(uint64_t badaddr)
@@ -281,15 +253,18 @@ template <typename WORD_TYPE> struct priv_if {
std::function<iss::status(unsigned, WORD_TYPE&)> read_csr; std::function<iss::status(unsigned, WORD_TYPE&)> read_csr;
std::function<iss::status(unsigned, WORD_TYPE)> write_csr; std::function<iss::status(unsigned, WORD_TYPE)> write_csr;
std::function<iss::status(uint8_t const*)> exec_htif; std::function<iss::status(uint8_t const*)> exec_htif;
std::function<void(uint16_t, uint16_t, WORD_TYPE)> raise_trap; // trap_id, cause, fault_data
std::unordered_map<unsigned, rd_csr_f>& csr_rd_cb; std::unordered_map<unsigned, rd_csr_f>& csr_rd_cb;
std::unordered_map<unsigned, wr_csr_f>& csr_wr_cb; std::unordered_map<unsigned, wr_csr_f>& csr_wr_cb;
hart_state<WORD_TYPE>& mstatus; hart_state<WORD_TYPE>& state;
uint8_t& PRIV;
WORD_TYPE& PC;
uint64_t& tohost; uint64_t& tohost;
uint64_t& fromhost; uint64_t& fromhost;
unsigned& mcause_max_irq; unsigned& max_irq;
}; };
template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_common : public BASE, public mmio::memory_elem { template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_common : public BASE, public mem::memory_elem {
const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}}; const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
const std::array<const char*, 16> trap_str = {{"" const std::array<const char*, 16> trap_str = {{""
"Instruction address misaligned", // 0 "Instruction address misaligned", // 0
@@ -343,6 +318,19 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
csr_rd_cb[frm] = MK_CSR_RD_CB(read_fcsr); csr_rd_cb[frm] = MK_CSR_RD_CB(read_fcsr);
csr_wr_cb[frm] = MK_CSR_WR_CB(write_fcsr); csr_wr_cb[frm] = MK_CSR_WR_CB(write_fcsr);
} }
if(traits<BASE>::V_REGS_SIZE > 0) {
csr_rd_cb[vstart] = MK_CSR_RD_CB(read_vstart);
csr_wr_cb[vstart] = MK_CSR_WR_CB(write_vstart);
csr_rd_cb[vxsat] = MK_CSR_RD_CB(read_vxsat);
csr_wr_cb[vxsat] = MK_CSR_WR_CB(write_vxsat);
csr_rd_cb[vxrm] = MK_CSR_RD_CB(read_vxrm);
csr_wr_cb[vxrm] = MK_CSR_WR_CB(write_vxrm);
csr_rd_cb[vcsr] = MK_CSR_RD_CB(read_vcsr);
csr_wr_cb[vcsr] = MK_CSR_WR_CB(write_vcsr);
csr_rd_cb[vl] = MK_CSR_RD_CB(read_vl);
csr_rd_cb[vtype] = MK_CSR_RD_CB(read_vtype);
csr_rd_cb[vlenb] = MK_CSR_RD_CB(read_vlenb);
}
for(unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr) { for(unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr) {
csr_rd_cb[addr] = MK_CSR_RD_CB(read_null); csr_rd_cb[addr] = MK_CSR_RD_CB(read_null);
csr_wr_cb[addr] = MK_CSR_WR_CB(write_plain); csr_wr_cb[addr] = MK_CSR_WR_CB(write_plain);
@@ -394,11 +382,13 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
csr_wr_cb[minstreth] = MK_CSR_WR_CB(write_instret); csr_wr_cb[minstreth] = MK_CSR_WR_CB(write_instret);
csr_rd_cb[mhartid] = MK_CSR_RD_CB(read_hartid); csr_rd_cb[mhartid] = MK_CSR_RD_CB(read_hartid);
}; };
~riscv_hart_common() { ~riscv_hart_common() {
if(io_buf.str().length()) { if(io_buf.str().length()) {
CPPLOG(INFO) << "tohost send '" << io_buf.str() << "'"; CPPLOG(INFO) << "tohost send '" << io_buf.str() << "'";
} }
} }
std::unordered_map<std::string, uint64_t> symbol_table; std::unordered_map<std::string, uint64_t> symbol_table;
uint64_t entry_address{0}; uint64_t entry_address{0};
uint64_t tohost = std::numeric_limits<uint64_t>::max(); uint64_t tohost = std::numeric_limits<uint64_t>::max();
@@ -417,8 +407,10 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
// Load ELF data // Load ELF data
if(reader.load(name)) { if(reader.load(name)) {
// check elf properties // check elf properties
if(reader.get_class() != expected_elf_class) if(reader.get_class() != expected_elf_class) {
CPPLOG(ERR) << "ISA missmatch, selected XLEN does not match supplied file ";
return false; return false;
}
if(reader.get_type() != ELFIO::ET_EXEC) if(reader.get_type() != ELFIO::ET_EXEC)
return false; return false;
if(reader.get_machine() != ELFIO::EM_RISCV) if(reader.get_machine() != ELFIO::EM_RISCV)
@@ -455,14 +447,12 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
#endif #endif
} }
} }
try { auto to_it = symbol_table.find("tohost");
tohost = symbol_table.at("tohost"); if(to_it != std::end(symbol_table))
} catch(std::out_of_range& e) { tohost = to_it->second;
} auto from_it = symbol_table.find("tohost");
try { if(from_it != std::end(symbol_table))
fromhost = symbol_table.at("fromhost"); tohost = from_it->second;
} catch(std::out_of_range& e) {
}
} }
return true; return true;
} }
@@ -528,10 +518,10 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
return iss::Err; return iss::Err;
auto req_priv_lvl = (addr >> 8) & 0x3; auto req_priv_lvl = (addr >> 8) & 0x3;
if(this->reg.PRIV < req_priv_lvl) // not having required privileges if(this->reg.PRIV < req_priv_lvl) // not having required privileges
throw illegal_instruction_fault(this->fault_data); return iss::Err;
auto it = csr_rd_cb.find(addr); auto it = csr_rd_cb.find(addr);
if(it == csr_rd_cb.end() || !it->second) // non existent register if(it == csr_rd_cb.end() || !it->second) // non existent register
throw illegal_instruction_fault(this->fault_data); return iss::Err;
return it->second(addr, val); return it->second(addr, val);
} }
@@ -540,12 +530,12 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
return iss::Err; return iss::Err;
auto req_priv_lvl = (addr >> 8) & 0x3; auto req_priv_lvl = (addr >> 8) & 0x3;
if(this->reg.PRIV < req_priv_lvl) // not having required privileges if(this->reg.PRIV < req_priv_lvl) // not having required privileges
throw illegal_instruction_fault(this->fault_data); return iss::Err;
if((addr & 0xc00) == 0xc00) // writing to read-only region if((addr & 0xc00) == 0xc00) // writing to read-only region
throw illegal_instruction_fault(this->fault_data); return iss::Err;
auto it = csr_wr_cb.find(addr); auto it = csr_wr_cb.find(addr);
if(it == csr_wr_cb.end() || !it->second) // non existent register if(it == csr_wr_cb.end() || !it->second) // non existent register
throw illegal_instruction_fault(this->fault_data); return iss::Err;
return it->second(addr, val); return it->second(addr, val);
} }
@@ -642,7 +632,7 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
iss::status write_dcsr(unsigned addr, reg_t val) { iss::status write_dcsr(unsigned addr, reg_t val) {
if(!debug_mode_active()) if(!debug_mode_active())
throw illegal_instruction_fault(this->fault_data); return iss::Err;
// +-------------- ebreakm // +-------------- ebreakm
// | +---------- stepi // | +---------- stepi
// | | +++----- cause // | | +++----- cause
@@ -653,28 +643,28 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
iss::status read_debug(unsigned addr, reg_t& val) { iss::status read_debug(unsigned addr, reg_t& val) {
if(!debug_mode_active()) if(!debug_mode_active())
throw illegal_instruction_fault(this->fault_data); return iss::Err;
val = csr[addr]; val = csr[addr];
return iss::Ok; return iss::Ok;
} }
iss::status write_dscratch(unsigned addr, reg_t val) { iss::status write_dscratch(unsigned addr, reg_t val) {
if(!debug_mode_active()) if(!debug_mode_active())
throw illegal_instruction_fault(this->fault_data); return iss::Err;
csr[addr] = val; csr[addr] = val;
return iss::Ok; return iss::Ok;
} }
iss::status read_dpc(unsigned addr, reg_t& val) { iss::status read_dpc(unsigned addr, reg_t& val) {
if(!debug_mode_active()) if(!debug_mode_active())
throw illegal_instruction_fault(this->fault_data); return iss::Err;
val = this->reg.DPC; val = this->reg.DPC;
return iss::Ok; return iss::Ok;
} }
iss::status write_dpc(unsigned addr, reg_t val) { iss::status write_dpc(unsigned addr, reg_t val) {
if(!debug_mode_active()) if(!debug_mode_active())
throw illegal_instruction_fault(this->fault_data); return iss::Err;
this->reg.DPC = val; this->reg.DPC = val;
return iss::Ok; return iss::Ok;
} }
@@ -713,16 +703,80 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
return iss::Ok; return iss::Ok;
} }
iss::status read_vstart(unsigned addr, reg_t& val) {
val = this->get_vstart();
return iss::Ok;
}
iss::status write_vstart(unsigned addr, reg_t val) {
this->set_vstart(val);
return iss::Ok;
}
iss::status read_vxsat(unsigned addr, reg_t& val) {
val = this->get_vxsat();
return iss::Ok;
}
iss::status write_vxsat(unsigned addr, reg_t val) {
this->set_vxsat(val & 1);
csr[vcsr] = (~1ULL & csr[vcsr]) | (val & 1);
return iss::Ok;
}
iss::status read_vxrm(unsigned addr, reg_t& val) {
val = this->get_vxrm();
return iss::Ok;
}
iss::status write_vxrm(unsigned addr, reg_t val) {
this->set_vxrm(val & 0b11);
csr[vcsr] = (~0b110ULL & csr[vcsr]) | ((val & 0b11) << 1);
return iss::Ok;
}
iss::status read_vcsr(unsigned addr, reg_t& val) {
val = csr[vcsr];
return iss::Ok;
}
iss::status write_vcsr(unsigned addr, reg_t val) {
csr[vcsr] = val;
return iss::Ok;
}
iss::status read_vl(unsigned addr, reg_t& val) {
val = this->get_vl();
return iss::Ok;
}
iss::status read_vtype(unsigned addr, reg_t& val) {
val = this->get_vtype();
return iss::Ok;
}
iss::status read_vlenb(unsigned addr, reg_t& val) {
val = csr[vlenb];
return iss::Ok;
}
priv_if<reg_t> get_priv_if() { priv_if<reg_t> get_priv_if() {
return priv_if<reg_t>{.read_csr = [this](unsigned addr, reg_t& val) -> iss::status { return read_csr(addr, val); }, return priv_if<reg_t>{.read_csr = [this](unsigned addr, reg_t& val) -> iss::status { return read_csr(addr, val); },
.write_csr = [this](unsigned addr, reg_t val) -> iss::status { return write_csr(addr, val); }, .write_csr = [this](unsigned addr, reg_t val) -> iss::status { return write_csr(addr, val); },
.exec_htif = [this](uint8_t const* data) -> iss::status { return execute_htif(data); }, .exec_htif = [this](uint8_t const* data) -> iss::status { return execute_htif(data); },
.raise_trap =
[this](uint16_t trap_id, uint16_t cause, reg_t fault_data) {
this->reg.trap_state = 0x80ULL << 24 | (cause << 16) | trap_id;
this->fault_data = fault_data;
},
.csr_rd_cb{this->csr_rd_cb}, .csr_rd_cb{this->csr_rd_cb},
.csr_wr_cb{csr_wr_cb}, .csr_wr_cb{csr_wr_cb},
.mstatus{this->state}, .state{this->state},
.PRIV{this->reg.PRIV},
.PC{this->reg.PC},
.tohost{this->tohost}, .tohost{this->tohost},
.fromhost{this->fromhost}, .fromhost{this->fromhost},
.mcause_max_irq{mcause_max_irq}}; .max_irq{mcause_max_irq}};
} }
iss::status execute_htif(uint8_t const* data) { iss::status execute_htif(uint8_t const* data) {
@@ -762,14 +816,14 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
} }
} }
mmio::memory_hierarchy memories; mem::memory_hierarchy memories;
virtual mmio::memory_if get_mem_if() override { mem::memory_if get_mem_if() override {
assert(false || "This function should nevver be called"); assert(false || "This function should never be called");
return mmio::memory_if{}; return mem::memory_if{};
} }
virtual void set_next(mmio::memory_if mem_if) { memory = mem_if; }; void set_next(mem::memory_if mem_if) override { memory = mem_if; };
void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); } void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
@@ -788,7 +842,7 @@ protected:
} }
} }
mmio::memory_if memory; mem::memory_if memory;
struct riscv_instrumentation_if : public iss::instrumentation_if { struct riscv_instrumentation_if : public iss::instrumentation_if {
riscv_instrumentation_if(riscv_hart_common<BASE, LOGCAT>& arch) riscv_instrumentation_if(riscv_hart_common<BASE, LOGCAT>& arch)
@@ -830,8 +884,7 @@ protected:
instrumentation_if* get_instrumentation_if() override { return &instr_if; }; instrumentation_if* get_instrumentation_if() override { return &instr_if; };
using csr_type = util::sparse_array<typename traits<BASE>::reg_t, 1ULL << 12, 12>; using csr_type = std::array<typename traits<BASE>::reg_t, 1ULL << 12>;
using csr_page_type = typename csr_type::page_type;
csr_type csr; csr_type csr;
std::unordered_map<unsigned, rd_csr_f> csr_rd_cb; std::unordered_map<unsigned, rd_csr_f> csr_rd_cb;
@@ -845,7 +898,6 @@ protected:
int64_t cycle_offset{0}; int64_t cycle_offset{0};
int64_t instret_offset{0}; int64_t instret_offset{0};
semihosting_cb_t<reg_t> semihosting_cb; semihosting_cb_t<reg_t> semihosting_cb;
std::array<vm_info, 2> vm;
unsigned mcause_max_irq{16U}; unsigned mcause_max_irq{16U};
}; };
+11 -19
View File
@@ -48,7 +48,7 @@
#include <array> #include <array>
#include <elfio/elfio.hpp> #include <elfio/elfio.hpp>
#include <fmt/format.h> #include <fmt/format.h>
#include <iss/mmio/memory_with_htif.h> #include <iss/mem/memory_with_htif.h>
#include <unordered_map> #include <unordered_map>
namespace iss { namespace iss {
@@ -111,7 +111,7 @@ public:
return 0b100010001000; // only machine mode is supported return 0b100010001000; // only machine mode is supported
} }
riscv_hart_m_p(feature_config cfg = feature_config{}); riscv_hart_m_p();
virtual ~riscv_hart_m_p() = default; virtual ~riscv_hart_m_p() = default;
@@ -128,15 +128,12 @@ public:
void set_csr(unsigned addr, reg_t val) { this->csr[addr & this->csr.page_addr_mask] = val; } void set_csr(unsigned addr, reg_t val) { this->csr[addr & this->csr.page_addr_mask] = val; }
void set_num_of_irq(unsigned i) { this->mcause_max_irq = 1 << util::ilog2(i); }
protected: protected:
using mem_read_f = iss::status(phys_addr_t addr, unsigned, uint8_t* const); using mem_read_f = iss::status(phys_addr_t addr, unsigned, uint8_t* const);
using mem_write_f = iss::status(phys_addr_t addr, unsigned, uint8_t const* const); using mem_write_f = iss::status(phys_addr_t addr, unsigned, uint8_t const* const);
hart_state<reg_t> state; hart_state<reg_t> state;
std::unordered_map<reg_t, uint64_t> ptw;
std::unordered_map<uint64_t, uint8_t> atomic_reservation; std::unordered_map<uint64_t, uint8_t> atomic_reservation;
iss::status read_status(unsigned addr, reg_t& val); iss::status read_status(unsigned addr, reg_t& val);
@@ -154,18 +151,15 @@ protected:
iss::status write_dpc(unsigned addr, reg_t val); iss::status write_dpc(unsigned addr, reg_t val);
void check_interrupt(); void check_interrupt();
feature_config cfg; mem::memory_with_htif<reg_t> default_mem;
mmio::memory_with_htif<reg_t> default_mem;
}; };
template <typename BASE, features_e FEAT, typename LOGCAT> template <typename BASE, features_e FEAT, typename LOGCAT>
riscv_hart_m_p<BASE, FEAT, LOGCAT>::riscv_hart_m_p(feature_config cfg) riscv_hart_m_p<BASE, FEAT, LOGCAT>::riscv_hart_m_p()
: cfg(cfg) : default_mem(base::get_priv_if()) {
, default_mem(base::get_priv_if()) {
const std::array<unsigned, 4> rwaddrs{{mepc, mtvec, mscratch, mtval}}; const std::array<unsigned, 4> rwaddrs{{mepc, mtvec, mscratch, mtval}};
for(auto addr : rwaddrs) { for(auto addr : rwaddrs) {
this->csr_rd_cb[addr] = MK_CSR_RD_CB(read_plain); this->csr_rd_cb[addr] = MK_CSR_RD_CB(read_plain);
// MK_CSR_RD_CB(read_plain(a,r);};
this->csr_wr_cb[addr] = MK_CSR_WR_CB(write_plain); this->csr_wr_cb[addr] = MK_CSR_WR_CB(write_plain);
} }
this->csr_rd_cb[mstatus] = MK_CSR_RD_CB(read_status); this->csr_rd_cb[mstatus] = MK_CSR_RD_CB(read_status);
@@ -195,7 +189,7 @@ riscv_hart_m_p<BASE, FEAT, LOGCAT>::riscv_hart_m_p(feature_config cfg)
} }
this->rd_func = util::delegate<arch_if::rd_func_sig>::from<this_class, &this_class::read>(this); this->rd_func = util::delegate<arch_if::rd_func_sig>::from<this_class, &this_class::read>(this);
this->wr_func = util::delegate<arch_if::wr_func_sig>::from<this_class, &this_class::write>(this); this->wr_func = util::delegate<arch_if::wr_func_sig>::from<this_class, &this_class::write>(this);
this->memories.prepend(*this); this->memories.root(*this);
this->memories.append(default_mem); this->memories.append(default_mem);
} }
@@ -300,7 +294,7 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write(const address_type type, c
try { try {
switch(space) { switch(space) {
case traits<BASE>::MEM: { case traits<BASE>::MEM: {
if(unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { if(unlikely(is_fetch(access) && (addr & 0x1) == 1)) {
this->fault_data = addr; this->fault_data = addr;
if(access && iss::access_type::DEBUG) if(access && iss::access_type::DEBUG)
throw trap_access(0, addr); throw trap_access(0, addr);
@@ -403,15 +397,13 @@ template <typename BASE, features_e FEAT, typename LOGCAT> inline void riscv_har
} }
template <typename BASE, features_e FEAT, typename LOGCAT> void riscv_hart_m_p<BASE, FEAT, LOGCAT>::check_interrupt() { template <typename BASE, features_e FEAT, typename LOGCAT> void riscv_hart_m_p<BASE, FEAT, LOGCAT>::check_interrupt() {
// TODO: Implement CLIC functionality
// auto ideleg = csr[mideleg];
// Multiple simultaneous interrupts and traps at the same privilege level are // Multiple simultaneous interrupts and traps at the same privilege level are
// handled in the following decreasing priority order: // handled in the following decreasing priority order:
// external interrupts, software interrupts, timer interrupts, then finally // external interrupts, software interrupts, timer interrupts, then finally
// any synchronous traps. // any synchronous traps.
auto ena_irq = this->csr[mip] & this->csr[mie]; auto ena_irq = this->csr[mip] & this->csr[mie];
bool mstatus_mie = this->state.mstatus.MIE; bool mstatus_mie = state.mstatus.MIE;
auto m_enabled = this->reg.PRIV < PRIV_M || mstatus_mie; auto m_enabled = this->reg.PRIV < PRIV_M || mstatus_mie;
auto enabled_interrupts = m_enabled ? ena_irq : 0; auto enabled_interrupts = m_enabled ? ena_irq : 0;
@@ -525,9 +517,6 @@ uint64_t riscv_hart_m_p<BASE, FEAT, LOGCAT>::enter_trap(uint64_t flags, uint64_t
if((xtvec & 0x1) == 1 && trap_id != 0) if((xtvec & 0x1) == 1 && trap_id != 0)
this->reg.NEXT_PC += 4 * cause; this->reg.NEXT_PC += 4 * cause;
} }
// reset trap state
this->reg.PRIV = new_priv;
this->reg.trap_state = 0;
std::array<char, 32> buffer; std::array<char, 32> buffer;
#if defined(_MSC_VER) #if defined(_MSC_VER)
sprintf(buffer.data(), "0x%016llx", addr); sprintf(buffer.data(), "0x%016llx", addr);
@@ -538,6 +527,9 @@ uint64_t riscv_hart_m_p<BASE, FEAT, LOGCAT>::enter_trap(uint64_t flags, uint64_t
NSCLOG(INFO, LOGCAT) << (trap_id ? "Interrupt" : "Trap") << " with cause '" NSCLOG(INFO, LOGCAT) << (trap_id ? "Interrupt" : "Trap") << " with cause '"
<< (trap_id ? this->irq_str[cause] : this->trap_str[cause]) << "' (" << cause << ")" << (trap_id ? this->irq_str[cause] : this->trap_str[cause]) << "' (" << cause << ")"
<< " at address " << buffer.data() << " occurred"; << " at address " << buffer.data() << " occurred";
// reset trap state
this->reg.PRIV = new_priv;
this->reg.trap_state = 0;
return this->reg.NEXT_PC; return this->reg.NEXT_PC;
} }
+147 -392
View File
@@ -40,23 +40,25 @@
#include "riscv_hart_common.h" #include "riscv_hart_common.h"
#include "util/logging.h" #include "util/logging.h"
#include <algorithm> #include <algorithm>
#include <array>
#include <cstdint> #include <cstdint>
#include <elfio/elf_types.hpp> #include <elfio/elf_types.hpp>
#include <elfio/elfio.hpp>
#include <limits> #include <limits>
#ifndef FMT_HEADER_ONLY #ifndef FMT_HEADER_ONLY
#define FMT_HEADER_ONLY #define FMT_HEADER_ONLY
#endif #endif
#include <array> #include <iss/mem/memory_with_htif.h>
#include <elfio/elfio.hpp> #include <iss/mem/mmu.h>
#include <fmt/format.h> #include <fmt/format.h>
#include <type_traits> #include <type_traits>
#include <unordered_map> #include <unordered_map>
#include <util/bit_field.h>
namespace iss { namespace iss {
namespace arch { namespace arch {
template <typename BASE> class riscv_hart_msu_vp : public riscv_hart_common<BASE> { template <typename BASE, features_e FEAT = FEAT_NONE, typename LOGCAT = logging::disass>
class riscv_hart_msu_vp : public riscv_hart_common<BASE> {
public: public:
using core = BASE; using core = BASE;
using base = riscv_hart_common<BASE>; using base = riscv_hart_common<BASE>;
@@ -65,10 +67,6 @@ public:
using reg_t = typename core::reg_t; using reg_t = typename core::reg_t;
using addr_t = typename core::addr_t; using addr_t = typename core::addr_t;
static constexpr reg_t get_misa() {
return (sizeof(reg_t) == 4 ? (1UL << 30) : (2ULL << 62)) | ISA_I | ISA_M | ISA_A | ISA_U | ISA_S | ISA_M;
}
static constexpr reg_t get_mstatus_mask(unsigned priv_lvl) { static constexpr reg_t get_mstatus_mask(unsigned priv_lvl) {
if(sizeof(reg_t) == 4) { if(sizeof(reg_t) == 4) {
#if __cplusplus < 201402L #if __cplusplus < 201402L
@@ -76,21 +74,21 @@ public:
#else #else
switch(priv_lvl) { switch(priv_lvl) {
case PRIV_U: case PRIV_U:
return 0x80000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001 return 0x80000000UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001
case PRIV_S: case PRIV_S:
return 0x800de133UL; // 0b1000 0000 0000 1101 1110 0001 0011 0011 return 0x800de122UL; // 0b1000 0000 0000 1101 1110 0001 0011 0011
default: default:
return 0x807ff9ddUL; // 0b1000 0000 0111 1111 1111 1001 1011 1011 return 0x807ff9aaUL; // 0b1000 0000 0111 1111 1111 1001 1011 1011
} }
#endif #endif
} else if(sizeof(reg_t) == 8) { } else if(sizeof(reg_t) == 8) {
switch(priv_lvl) { switch(priv_lvl) {
case PRIV_U: case PRIV_U:
return 0x8000000f00000011ULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 return 0x8000000f00000000ULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011
case PRIV_S: case PRIV_S:
return 0x8000000f000de133ULL; // 0b1...0 0011 0000 0000 0000 1101 1110 0001 0011 0011 return 0x8000000f000de122ULL; // 0b1...0 0011 0000 0000 0000 1101 1110 0001 0011 0011
default: default:
return 0x8000000f007ff9ddULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 return 0x8000000f007ff9aaULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011
} }
} else } else
assert(false && "Unsupported XLEN value"); assert(false && "Unsupported XLEN value");
@@ -117,48 +115,6 @@ public:
} }
this->state.mstatus = new_val; this->state.mstatus = new_val;
} }
reg_t satp;
static inline vm_info decode_vm_info(uint32_t state, uint32_t sptbr) {
if(state == PRIV_M)
return {0, 0, 0, 0};
if(state <= PRIV_S)
switch(bit_sub<31, 1>(sptbr)) {
case 0:
return {0, 0, 0, 0}; // off
case 1:
return {2, 10, 4, bit_sub<0, 22>(sptbr) << PGSHIFT}; // SV32
default:
abort();
}
abort();
return {0, 0, 0, 0}; // dummy
}
static inline vm_info decode_vm_info(uint32_t state, uint64_t sptbr) {
if(state == PRIV_M)
return {0, 0, 0, 0};
if(state <= PRIV_S)
switch(bit_sub<60, 4>(sptbr)) {
case 0:
return {0, 0, 0, 0}; // off
case 8:
return {3, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV39
case 9:
return {4, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV48
case 10:
return {5, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV57
case 11:
return {6, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV64
default:
abort();
}
abort();
return {0, 0, 0, 0}; // dummy
}
const typename core::reg_t PGSIZE = 1 << PGSHIFT;
const typename core::reg_t PGMASK = PGSIZE - 1;
constexpr reg_t get_irq_mask(size_t mode) { constexpr reg_t get_irq_mask(size_t mode) {
std::array<const reg_t, 4> m = {{ std::array<const reg_t, 4> m = {{
@@ -176,8 +132,6 @@ public:
void reset(uint64_t address) override; void reset(uint64_t address) override;
phys_addr_t virt2phys(const iss::addr_t& addr) override;
iss::status read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, iss::status read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length,
uint8_t* const data); uint8_t* const data);
iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length,
@@ -190,22 +144,14 @@ public:
void set_csr(unsigned addr, reg_t val) { this->csr[addr & this->csr.page_addr_mask] = val; } void set_csr(unsigned addr, reg_t val) { this->csr[addr & this->csr.page_addr_mask] = val; }
void set_irq_num(unsigned i) { this->mcause_max_irq = 1 << util::ilog2(i); }
protected: protected:
virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t* const data); using mem_read_f = iss::status(phys_addr_t addr, unsigned, uint8_t* const);
virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t* const data); using mem_write_f = iss::status(phys_addr_t addr, unsigned, uint8_t const* const);
hart_state<reg_t> state; hart_state<reg_t> state;
using mem_type = util::sparse_array<uint8_t, 1ULL << 32>;
mem_type mem;
void update_vm_info();
std::unordered_map<reg_t, uint64_t> ptw;
std::unordered_map<uint64_t, uint8_t> atomic_reservation; std::unordered_map<uint64_t, uint8_t> atomic_reservation;
std::vector<uint8_t> tcm;
iss::status read_status(unsigned addr, reg_t& val); iss::status read_status(unsigned addr, reg_t& val);
iss::status write_status(unsigned addr, reg_t val); iss::status write_status(unsigned addr, reg_t val);
iss::status write_cause(unsigned addr, reg_t val); iss::status write_cause(unsigned addr, reg_t val);
@@ -214,26 +160,17 @@ protected:
iss::status read_ip(unsigned addr, reg_t& val); iss::status read_ip(unsigned addr, reg_t& val);
iss::status write_ideleg(unsigned addr, reg_t val); iss::status write_ideleg(unsigned addr, reg_t val);
iss::status write_edeleg(unsigned addr, reg_t val); iss::status write_edeleg(unsigned addr, reg_t val);
iss::status read_satp(unsigned addr, reg_t& val);
iss::status write_satp(unsigned addr, reg_t val);
virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; };
virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; };
void register_custom_csr_rd(unsigned addr) { this->csr_rd_cb[addr] = MK_CSR_RD_CB(read_custom_csr_reg); }
void register_custom_csr_wr(unsigned addr) { this->csr_wr_cb[addr] = MK_CSR_WR_CB(write_custom_csr_reg); }
reg_t mhartid_reg{0x0};
void check_interrupt(); void check_interrupt();
mem::mmu<reg_t> mmu;
mem::memory_with_htif<reg_t> default_mem;
}; };
template <typename BASE> template <typename BASE, features_e FEAT, typename LOGCAT>
riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp() riscv_hart_msu_vp<BASE, FEAT, LOGCAT>::riscv_hart_msu_vp()
: state() { : state()
this->mmu = true; , mmu(base::get_priv_if())
this->rd_func = util::delegate<arch_if::rd_func_sig>::from<this_class, &this_class::read>(this); , default_mem(base::get_priv_if()) {
this->rd_func = util::delegate<arch_if::wr_func_sig>::from<this_class, &this_class::write>(this);
// common regs // common regs
const std::array<unsigned, 17> rwaddrs{{mepc, mtvec, mscratch, mtval, mscratch, sepc, stvec, sscratch, scause, stval, sscratch, uepc, const std::array<unsigned, 17> rwaddrs{{mepc, mtvec, mscratch, mtval, mscratch, sepc, stvec, sscratch, scause, stval, sscratch, uepc,
utvec, uscratch, ucause, utval, uscratch}}; utvec, uscratch, ucause, utval, uscratch}};
@@ -272,17 +209,32 @@ riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp()
this->csr_wr_cb[mvendorid] = MK_CSR_WR_CB(write_null); this->csr_wr_cb[mvendorid] = MK_CSR_WR_CB(write_null);
this->csr_wr_cb[marchid] = MK_CSR_WR_CB(write_null); this->csr_wr_cb[marchid] = MK_CSR_WR_CB(write_null);
this->csr_wr_cb[mimpid] = MK_CSR_WR_CB(write_null); this->csr_wr_cb[mimpid] = MK_CSR_WR_CB(write_null);
this->csr_rd_cb[satp] = MK_CSR_RD_CB(read_satp); this->rd_func = util::delegate<arch_if::rd_func_sig>::from<this_class, &this_class::read>(this);
this->csr_wr_cb[satp] = MK_CSR_WR_CB(write_satp); this->wr_func = util::delegate<arch_if::wr_func_sig>::from<this_class, &this_class::write>(this);
if(FEAT & FEAT_DEBUG) {
this->csr_wr_cb[dscratch0] = MK_CSR_WR_CB(write_dscratch);
this->csr_rd_cb[dscratch0] = MK_CSR_RD_CB(read_debug);
this->csr_wr_cb[dscratch1] = MK_CSR_WR_CB(write_dscratch);
this->csr_rd_cb[dscratch1] = MK_CSR_RD_CB(read_debug);
this->csr_wr_cb[dpc] = MK_CSR_WR_CB(write_dpc);
this->csr_rd_cb[dpc] = MK_CSR_RD_CB(read_dpc);
this->csr_wr_cb[dcsr] = MK_CSR_WR_CB(write_dcsr);
this->csr_rd_cb[dcsr] = MK_CSR_RD_CB(read_debug);
}
this->rd_func = util::delegate<arch_if::rd_func_sig>::from<this_class, &this_class::read>(this);
this->wr_func = util::delegate<arch_if::wr_func_sig>::from<this_class, &this_class::write>(this);
this->set_next(mmu.get_mem_if());
this->memories.root(mmu);
this->memories.append(default_mem);
} }
template <typename BASE> template <typename BASE, features_e FEAT, typename LOGCAT>
iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, iss::status riscv_hart_msu_vp<BASE, FEAT, LOGCAT>::read(const address_type type, const access_type access, const uint32_t space,
const unsigned length, uint8_t* const data) { const uint64_t addr, const unsigned length, uint8_t* const data) {
#ifndef NDEBUG #ifndef NDEBUG
if(access && iss::access_type::DEBUG) { if(access && iss::access_type::DEBUG) {
CPPLOG(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(is_fetch(access)) {
CPPLOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr; CPPLOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr;
} else { } else {
CPPLOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr; CPPLOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr;
@@ -294,31 +246,20 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
auto alignment = is_fetch(access) ? (this->has_compressed() ? 2 : 4) : std::min<unsigned>(length, sizeof(reg_t)); auto alignment = is_fetch(access) ? (this->has_compressed() ? 2 : 4) : std::min<unsigned>(length, sizeof(reg_t));
if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) { if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) {
this->fault_data = addr; this->fault_data = addr;
if(access && iss::access_type::DEBUG) if(is_debug(access))
throw trap_access(0, addr); throw trap_access(0, addr);
this->reg.trap_state = (1 << 31); // issue trap 0 this->reg.trap_state = (1UL << 31); // issue trap 0
return iss::Err; return iss::Err;
} }
try { try {
if(!is_debug(access) && (addr & (alignment - 1))) { if(!is_debug(access) && (addr & (alignment - 1))) {
this->reg.trap_state = 1 << 31 | 4 << 16; this->reg.trap_state = (1UL << 31) | 4 << 16;
this->fault_data = addr; this->fault_data = addr;
return iss::Err; return iss::Err;
} }
if(unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary auto res = this->memory.rd_mem(access, addr, length, data);
vm_info vm = decode_vm_info(this->reg.PRIV, satp);
if(vm.levels != 0) { // VM is active
auto split_addr = (addr + length) & ~PGMASK;
auto len1 = split_addr - addr;
auto res = read(type, access, space, addr, len1, data);
if(res == iss::Ok)
res = read(type, access, space, split_addr, length - len1, data + len1);
return res;
}
}
auto res = read_mem(virt2phys(iss::addr_t{access, type, space, 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 = (1 << 31) | (5 << 16); // issue trap 5 (load access fault this->reg.trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault
this->fault_data = addr; this->fault_data = addr;
} }
return res; return res;
@@ -336,8 +277,6 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
return this->read_csr(addr, *reinterpret_cast<reg_t* const>(data)); return this->read_csr(addr, *reinterpret_cast<reg_t* const>(data));
} break; } break;
case traits<BASE>::FENCE: { case traits<BASE>::FENCE: {
if((addr + length) > mem.size())
return iss::Err;
switch(addr) { switch(addr) {
case 2: // SFENCE:VMA lower case 2: // SFENCE:VMA lower
case 3: { // SFENCE:VMA upper case 3: { // SFENCE:VMA upper
@@ -372,9 +311,9 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
} }
} }
template <typename BASE> template <typename BASE, features_e FEAT, typename LOGCAT>
iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, iss::status riscv_hart_msu_vp<BASE, FEAT, LOGCAT>::write(const address_type type, const access_type access, const uint32_t space,
const unsigned length, const uint8_t* const data) { const uint64_t addr, const unsigned length, const uint8_t* const data) {
#ifndef NDEBUG #ifndef NDEBUG
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
switch(length) { switch(length) {
@@ -401,29 +340,22 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
try { try {
switch(space) { switch(space) {
case traits<BASE>::MEM: { case traits<BASE>::MEM: {
if(unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { if(unlikely(is_fetch(access) && (addr & 0x1) == 1)) {
this->fault_data = addr; this->fault_data = addr;
if(access && iss::access_type::DEBUG) if(access && iss::access_type::DEBUG)
throw trap_access(0, addr); throw trap_access(0, addr);
this->reg.trap_state = (1 << 31); // issue trap 0 this->reg.trap_state = (1UL << 31); // issue trap 0
return iss::Err; return iss::Err;
} }
phys_addr_t paddr = virt2phys(iss::addr_t{access, type, space, addr});
try { try {
// TODO: There is no check for alignment auto alignment = std::min<unsigned>(length, sizeof(reg_t));
if(unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary if(length > 1 && (addr & (alignment - 1)) && !is_debug(access)) {
vm_info vm = decode_vm_info(this->reg.PRIV, satp); this->reg.trap_state = (1UL << 31) | 6 << 16;
if(vm.levels != 0) { // VM is active this->fault_data = addr;
auto split_addr = (addr + length) & ~PGMASK; return iss::Err;
auto len1 = split_addr - addr;
auto res = write(type, access, space, addr, len1, data);
if(res == iss::Ok)
res = write(type, access, space, split_addr, length - len1, data + len1);
return res;
}
} }
auto res = write_mem(paddr, length, data); auto res = this->memory.wr_mem(access, addr, length, data);
if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) { if(unlikely(res != iss::Ok && !is_debug(access))) {
this->reg.trap_state = (1UL << 31) | (7UL << 16); // issue trap 7 (Store/AMO access fault) this->reg.trap_state = (1UL << 31) | (7UL << 16); // issue trap 7 (Store/AMO access fault)
this->fault_data = addr; this->fault_data = addr;
} }
@@ -440,12 +372,9 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
return this->write_csr(addr, *reinterpret_cast<const reg_t*>(data)); return this->write_csr(addr, *reinterpret_cast<const reg_t*>(data));
} break; } break;
case traits<BASE>::FENCE: { case traits<BASE>::FENCE: {
if((addr + length) > mem.size())
return iss::Err;
switch(addr) { switch(addr) {
case 2: case 2:
case 3: { case 3: {
ptw.clear();
auto tvm = state.mstatus.TVM; auto tvm = state.mstatus.TVM;
if(this->reg.PRIV == PRIV_S & tvm != 0) { if(this->reg.PRIV == PRIV_S & tvm != 0) {
this->reg.trap_state = (1 << 31) | (2 << 16); this->reg.trap_state = (1 << 31) | (2 << 16);
@@ -472,26 +401,29 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
} }
} }
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_status(unsigned addr, reg_t& val) { template <typename BASE, features_e FEAT, typename LOGCAT>
iss::status riscv_hart_msu_vp<BASE, FEAT, LOGCAT>::read_status(unsigned addr, reg_t& val) {
auto req_priv_lvl = (addr >> 8) & 0x3; auto req_priv_lvl = (addr >> 8) & 0x3;
val = state.mstatus & get_mstatus_mask(req_priv_lvl); val = state.mstatus & get_mstatus_mask(req_priv_lvl);
return iss::Ok; return iss::Ok;
} }
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_status(unsigned addr, reg_t val) { template <typename BASE, features_e FEAT, typename LOGCAT>
iss::status riscv_hart_msu_vp<BASE, FEAT, LOGCAT>::write_status(unsigned addr, reg_t val) {
auto req_priv_lvl = (addr >> 8) & 0x3; auto req_priv_lvl = (addr >> 8) & 0x3;
write_mstatus(val, req_priv_lvl); write_mstatus(val, req_priv_lvl);
check_interrupt(); check_interrupt();
update_vm_info();
return iss::Ok; return iss::Ok;
} }
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_cause(unsigned addr, reg_t val) { template <typename BASE, features_e FEAT, typename LOGCAT>
iss::status riscv_hart_msu_vp<BASE, FEAT, LOGCAT>::write_cause(unsigned addr, reg_t val) {
this->csr[addr] = val & ((1UL << (traits<BASE>::XLEN - 1)) | 0xf); // TODO: make exception code size configurable this->csr[addr] = val & ((1UL << (traits<BASE>::XLEN - 1)) | 0xf); // TODO: make exception code size configurable
return iss::Ok; return iss::Ok;
} }
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_ie(unsigned addr, reg_t& val) { template <typename BASE, features_e FEAT, typename LOGCAT>
iss::status riscv_hart_msu_vp<BASE, FEAT, LOGCAT>::read_ie(unsigned addr, reg_t& val) {
val = this->csr[mie]; val = this->csr[mie];
if(addr < mie) if(addr < mie)
val &= this->csr[mideleg]; val &= this->csr[mideleg];
@@ -500,7 +432,8 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_ie(unsigned a
return iss::Ok; return iss::Ok;
} }
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_ie(unsigned addr, reg_t val) { template <typename BASE, features_e FEAT, typename LOGCAT>
iss::status riscv_hart_msu_vp<BASE, FEAT, LOGCAT>::write_ie(unsigned addr, reg_t val) {
auto req_priv_lvl = (addr >> 8) & 0x3; auto req_priv_lvl = (addr >> 8) & 0x3;
auto mask = get_irq_mask(req_priv_lvl); auto mask = get_irq_mask(req_priv_lvl);
this->csr[mie] = (this->csr[mie] & ~mask) | (val & mask); this->csr[mie] = (this->csr[mie] & ~mask) | (val & mask);
@@ -508,7 +441,8 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_ie(unsigned
return iss::Ok; return iss::Ok;
} }
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_ip(unsigned addr, reg_t& val) { template <typename BASE, features_e FEAT, typename LOGCAT>
iss::status riscv_hart_msu_vp<BASE, FEAT, LOGCAT>::read_ip(unsigned addr, reg_t& val) {
val = this->csr[mip]; val = this->csr[mip];
if(addr < mip) if(addr < mip)
val &= this->csr[mideleg]; val &= this->csr[mideleg];
@@ -517,111 +451,12 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_ip(unsigned a
return iss::Ok; return iss::Ok;
} }
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_satp(unsigned addr, reg_t& val) { template <typename BASE, features_e FEAT, typename LOGCAT> inline void riscv_hart_msu_vp<BASE, FEAT, LOGCAT>::reset(uint64_t address) {
reg_t tvm = state.mstatus.TVM;
if(this->reg.PRIV == PRIV_S & tvm != 0) {
this->reg.trap_state = (1 << 31) | (2 << 16);
this->fault_data = this->reg.PC;
return iss::Err;
}
val = satp;
return iss::Ok;
}
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_satp(unsigned addr, reg_t val) {
reg_t tvm = state.mstatus.TVM;
if(this->reg.PRIV == PRIV_S & tvm != 0) {
this->reg.trap_state = (1 << 31) | (2 << 16);
this->fault_data = this->reg.PC;
return iss::Err;
}
satp = val;
update_vm_info();
return iss::Ok;
}
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length, uint8_t* const data) {
switch(paddr.val) {
default: {
for(auto offs = 0U; offs < length; ++offs) {
*(data + offs) = mem[(paddr.val + offs) % mem.size()];
}
}
}
return iss::Ok;
}
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) {
mem_type::page_type& p = mem(paddr.val / mem.page_size);
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
// tohost handling in case of riscv-test
// according to https://github.com/riscv-software-src/riscv-isa-sim/issues/364#issuecomment-607657754:
if(paddr.access && iss::access_type::FUNC) {
if(paddr.val == this->tohost) {
reg_t cur_data = *reinterpret_cast<const reg_t*>(data);
// Extract Device (bits 63:56)
uint8_t device = traits<BASE>::XLEN == 32
? *reinterpret_cast<uint32_t*>(p.data() + ((this->tohost + 4) & mem.page_addr_mask)) >> 24
: (cur_data >> 56) & 0xFF;
// Extract Command (bits 55:48)
uint8_t command = traits<BASE>::XLEN == 32
? *reinterpret_cast<uint32_t*>(p.data() + ((this->tohost + 4) & mem.page_addr_mask)) >> 16
: (cur_data >> 48) & 0xFF;
// Extract payload (bits 47:0)
uint64_t payload_addr = cur_data & 0xFFFFFFFFFFFFULL;
if(payload_addr & 1) {
CPPLOG(FATAL) << "tohost value is 0x" << std::hex << payload_addr << std::dec << " (" << payload_addr
<< "), stopping simulation";
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
this->interrupt_sim = payload_addr;
return iss::Ok;
} else if(device == 0 && command == 0) {
std::array<uint64_t, 8> loaded_payload;
if(read(address_type::PHYSICAL, access_type::DEBUG_READ, traits<BASE>::MEM, payload_addr, 8 * sizeof(uint64_t),
reinterpret_cast<uint8_t*>(loaded_payload.data())) == iss::Err)
CPPLOG(ERR) << "Syscall read went wrong";
uint64_t syscall_num = loaded_payload.at(0);
if(syscall_num == 64) { // SYS_WRITE
return this->execute_sys_write(this, loaded_payload, traits<BASE>::MEM);
} else {
CPPLOG(ERR) << "tohost syscall with number 0x" << std::hex << syscall_num << std::dec << " (" << syscall_num
<< ") not implemented";
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
this->interrupt_sim = payload_addr;
return iss::Ok;
}
} else {
CPPLOG(ERR) << "tohost functionality not implemented for device " << device << " and command " << command;
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
this->interrupt_sim = payload_addr;
return iss::Ok;
}
}
if((traits<BASE>::XLEN == 32 && paddr.val == this->fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == this->fromhost)) {
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (this->fromhost & mem.page_addr_mask));
*reinterpret_cast<uint64_t*>(p.data() + (this->tohost & mem.page_addr_mask)) = fhostvar;
}
}
return iss::Ok;
}
template <typename BASE> inline void riscv_hart_msu_vp<BASE>::reset(uint64_t address) {
BASE::reset(address); BASE::reset(address);
state.mstatus = hart_state<reg_t>::mstatus_reset_val; state.mstatus = hart_state<reg_t>::mstatus_reset_val;
update_vm_info();
} }
template <typename BASE> inline void riscv_hart_msu_vp<BASE>::update_vm_info() { template <typename BASE, features_e FEAT, typename LOGCAT> void riscv_hart_msu_vp<BASE, FEAT, LOGCAT>::check_interrupt() {
this->vm[1] = decode_vm_info(this->reg.PRIV, satp);
BASE::addr_mode[3] = BASE::addr_mode[2] = this->vm[1].is_active() ? iss::address_type::VIRTUAL : iss::address_type::PHYSICAL;
if(state.mstatus.MPRV)
this->vm[0] = decode_vm_info(state.mstatus.MPP, satp);
else
this->vm[0] = this->vm[1];
BASE::addr_mode[1] = BASE::addr_mode[0] = this->vm[0].is_active() ? iss::address_type::VIRTUAL : iss::address_type::PHYSICAL;
ptw.clear();
}
template <typename BASE> void riscv_hart_msu_vp<BASE>::check_interrupt() {
auto status = state.mstatus; auto status = state.mstatus;
auto ip = this->csr[mip]; auto ip = this->csr[mip];
auto ie = this->csr[mie]; auto ie = this->csr[mie];
@@ -649,101 +484,8 @@ template <typename BASE> void riscv_hart_msu_vp<BASE>::check_interrupt() {
} }
} }
template <typename BASE> typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys(const iss::addr_t& addr) { template <typename BASE, features_e FEAT, typename LOGCAT>
const auto type = addr.access & iss::access_type::FUNC; uint64_t riscv_hart_msu_vp<BASE, FEAT, LOGCAT>::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) {
auto it = ptw.find(addr.val >> PGSHIFT);
if(it != ptw.end()) {
const reg_t pte = it->second;
const reg_t ad = PTE_A | (type == iss::access_type::WRITE) * PTE_D;
#ifdef RISCV_ENABLE_DIRTY
// set accessed and possibly dirty bits.
*(uint32_t*)ppte |= ad;
return {addr.getAccessType(), addr.space, (pte & (~PGMASK)) | (addr.val & PGMASK)};
#else
// take exception if access or possibly dirty bit is not set.
if((pte & ad) == ad)
return {addr.access, addr.space, (pte & (~PGMASK)) | (addr.val & PGMASK)};
else
ptw.erase(it); // throw an exception
#endif
} else {
uint32_t mode = type != iss::access_type::FETCH && state.mstatus.MPRV ? // MPRV
state.mstatus.MPP
: this->reg.PRIV;
const vm_info& vm = this->vm[static_cast<uint16_t>(type) / 2];
const bool s_mode = mode == PRIV_S;
const bool sum = state.mstatus.SUM;
const bool mxr = state.mstatus.MXR;
// verify bits xlen-1:va_bits-1 are all equal
const int va_bits = PGSHIFT + vm.levels * vm.idxbits;
const reg_t mask = (reg_t(1) << (traits<BASE>::XLEN > -(va_bits - 1))) - 1;
const reg_t masked_msbs = (addr.val >> (va_bits - 1)) & mask;
const int levels = (masked_msbs != 0 && masked_msbs != mask) ? 0 : vm.levels;
reg_t base = vm.ptbase;
for(int i = levels - 1; i >= 0; i--) {
const int ptshift = i * vm.idxbits;
const reg_t idx = (addr.val >> (PGSHIFT + ptshift)) & ((1 << vm.idxbits) - 1);
// check that physical address of PTE is legal
reg_t pte = 0;
const uint8_t res = this->read(iss::address_type::PHYSICAL, addr.access, traits<BASE>::MEM, base + idx * vm.ptesize, vm.ptesize,
(uint8_t*)&pte);
if(res != 0)
throw trap_load_access_fault(addr.val);
const reg_t ppn = pte >> PTE_PPN_SHIFT;
if(PTE_TABLE(pte)) { // next level of page table
base = ppn << PGSHIFT;
} else if((pte & PTE_U) ? s_mode && (type == iss::access_type::FETCH || !sum) : !s_mode) {
break;
} else if(!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) {
break;
} else if(type == (type == iss::access_type::FETCH ? !(pte & PTE_X)
: type == iss::access_type::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X))
: !((pte & PTE_R) && (pte & PTE_W)))) {
break;
} else if((ppn & ((reg_t(1) << ptshift) - 1)) != 0) {
break;
} else {
const reg_t ad = PTE_A | ((type == iss::access_type::WRITE) * PTE_D);
#ifdef RISCV_ENABLE_DIRTY
// set accessed and possibly dirty bits.
*(uint32_t*)ppte |= ad;
#else
// take exception if access or possibly dirty bit is not set.
if((pte & ad) != ad)
break;
#endif
// for superpage mappings, make a fake leaf PTE for the TLB's benefit.
const reg_t vpn = addr.val >> PGSHIFT;
const reg_t value = (ppn | (vpn & ((reg_t(1) << ptshift) - 1))) << PGSHIFT;
const reg_t offset = addr.val & PGMASK;
ptw[vpn] = value | (pte & 0xff);
return {addr.access, addr.space, value | offset};
}
}
}
switch(type) {
case access_type::FETCH:
this->fault_data = addr.val;
throw trap_instruction_page_fault(addr.val);
case access_type::READ:
this->fault_data = addr.val;
throw trap_load_page_fault(addr.val);
case access_type::WRITE:
this->fault_data = addr.val;
throw trap_store_page_fault(addr.val);
default:
abort();
}
}
template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) {
auto cur_priv = this->reg.PRIV;
// flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0]
// calculate and write mcause val // calculate and write mcause val
if(flags == std::numeric_limits<uint64_t>::max()) if(flags == std::numeric_limits<uint64_t>::max())
@@ -751,11 +493,11 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
auto trap_id = bit_sub<0, 16>(flags); auto trap_id = bit_sub<0, 16>(flags);
auto cause = bit_sub<16, 15>(flags); auto cause = bit_sub<16, 15>(flags);
if(trap_id == 0 && cause == 11) if(trap_id == 0 && cause == 11)
cause = 0x8 + cur_priv; // adjust environment call cause cause = 0x8 + this->reg.PRIV; // adjust environment call cause
// calculate effective privilege level // calculate effective privilege level
auto new_priv = PRIV_M; unsigned new_priv = PRIV_M;
if(trap_id == 0) { // exception if(trap_id == 0) { // exception
if(cur_priv != PRIV_M && ((this->csr[medeleg] >> cause) & 0x1) != 0) if(this->reg.PRIV != PRIV_M && ((this->csr[medeleg] >> cause) & 0x1) != 0)
new_priv = (this->csr[sedeleg] >> cause) & 0x1 ? PRIV_U : PRIV_S; new_priv = (this->csr[sedeleg] >> cause) & 0x1 ? PRIV_U : PRIV_S;
// store ret addr in xepc register // store ret addr in xepc register
this->csr[uepc | (new_priv << 8)] = static_cast<reg_t>(addr); // store actual address instruction of exception this->csr[uepc | (new_priv << 8)] = static_cast<reg_t>(addr); // store actual address instruction of exception
@@ -771,21 +513,23 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
this->csr[utval | (new_priv << 8)] = static_cast<reg_t>(addr); this->csr[utval | (new_priv << 8)] = static_cast<reg_t>(addr);
break; break;
case 2: case 2:
this->csr[utval | (new_priv << 8)] = (instr & 0x3) == 3 ? instr : instr & 0xffff; this->csr[utval | (new_priv << 8)] = (!this->has_compressed() || (instr & 0x3) == 3) ? instr : instr & 0xffff;
break; break;
case 3: case 3:
// TODO: implement debug mode behavior if((FEAT & FEAT_DEBUG) && (this->csr[dcsr] & 0x8000)) {
// csr[dpc] = addr; this->reg.DPC = addr;
// csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi) this->csr[dcsr] = (this->csr[dcsr] & ~0x1c3) | (1 << 6) | PRIV_M; // FIXME: cause should not be 4 (stepi)
this->csr[utval | (new_priv << 8)] = addr; new_priv = this->reg.PRIV | PRIV_D;
} else {
this->csr[utval | (new_priv << 8)] = addr;
}
if(this->semihosting_cb) { if(this->semihosting_cb) {
// Check for semihosting call // Check for semihosting call
phys_addr_t p_addr(access_type::DEBUG_READ, traits<BASE>::MEM, addr - 4);
std::array<uint8_t, 8> data; std::array<uint8_t, 8> data;
// check for SLLI_X0_X0_0X1F and SRAI_X0_X0_0X07 // check for SLLI_X0_X0_0X1F and SRAI_X0_X0_0X07
this->read_mem(p_addr, 4, data.data()); this->memory.rd_mem(iss::access_type::DEBUG_READ, addr - 4, 4, data.data());
p_addr.val += 8; addr += 8;
this->read_mem(p_addr, 4, data.data() + 4); this->memory.rd_mem(iss::access_type::DEBUG_READ, addr - 4, 4, data.data() + 4);
const std::array<uint8_t, 8> ref_data = {0x13, 0x10, 0xf0, 0x01, 0x13, 0x50, 0x70, 0x40}; const std::array<uint8_t, 8> ref_data = {0x13, 0x10, 0xf0, 0x01, 0x13, 0x50, 0x70, 0x40};
if(data == ref_data) { if(data == ref_data) {
@@ -797,7 +541,7 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
#else #else
sprintf(buffer.data(), "0x%016lx", addr); sprintf(buffer.data(), "0x%016lx", addr);
#endif #endif
CLOG(INFO, disass) << "Semihosting call at address " << buffer.data() << " occurred "; NSCLOG(INFO, LOGCAT) << "Semihosting call at address " << buffer.data() << " occurred ";
this->semihosting_cb(this, &(this->reg.X10) /*a0*/, &(this->reg.X11) /*a1*/); this->semihosting_cb(this, &(this->reg.X10) /*a0*/, &(this->reg.X11) /*a1*/);
return this->reg.NEXT_PC; return this->reg.NEXT_PC;
@@ -814,7 +558,7 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
} }
this->fault_data = 0; this->fault_data = 0;
} else { } else {
if(cur_priv != PRIV_M && ((this->csr[mideleg] >> cause) & 0x1) != 0) if(this->reg.PRIV != PRIV_M && ((this->csr[mideleg] >> cause) & 0x1) != 0)
new_priv = (this->csr[sideleg] >> cause) & 0x1 ? PRIV_U : PRIV_S; new_priv = (this->csr[sideleg] >> cause) & 0x1 ? PRIV_U : PRIV_S;
this->csr[uepc | (new_priv << 8)] = this->reg.NEXT_PC; // store next address if interrupt this->csr[uepc | (new_priv << 8)] = this->reg.NEXT_PC; // store next address if interrupt
this->reg.pending_trap = 0; this->reg.pending_trap = 0;
@@ -830,12 +574,12 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
// store the actual privilege level in yPP and store interrupt enable flags // store the actual privilege level in yPP and store interrupt enable flags
switch(new_priv) { switch(new_priv) {
case PRIV_M: case PRIV_M:
state.mstatus.MPP = cur_priv; state.mstatus.MPP = this->reg.PRIV;
state.mstatus.MPIE = state.mstatus.MIE; state.mstatus.MPIE = state.mstatus.MIE;
state.mstatus.MIE = false; state.mstatus.MIE = false;
break; break;
case PRIV_S: case PRIV_S:
state.mstatus.SPP = cur_priv; state.mstatus.SPP = this->reg.PRIV;
state.mstatus.SPIE = state.mstatus.SIE; state.mstatus.SPIE = state.mstatus.SIE;
state.mstatus.SIE = false; state.mstatus.SIE = false;
break; break;
@@ -848,71 +592,82 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
} }
// get trap vector // get trap vector
auto ivec = this->csr[utvec | (new_priv << 8)]; auto xtvec = this->csr[utvec | (new_priv << 8)];
// calculate addr// set NEXT_PC to trap addressess to jump to based on MODE // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE
// bits in mtvec // bits in mtvec
this->reg.NEXT_PC = ivec & ~0x3UL; this->reg.NEXT_PC = xtvec & ~0x3UL;
if((ivec & 0x1) == 1 && trap_id != 0) if(trap_id != 0) {
this->reg.NEXT_PC += 4 * cause; if((xtvec & 0x3UL) == 3UL) {
reg_t data;
auto ret = read(address_type::LOGICAL, access_type::READ, 0, this->csr[mtvt], sizeof(reg_t), reinterpret_cast<uint8_t*>(&data));
if(ret == iss::Err)
return this->reg.PC;
this->reg.NEXT_PC = data;
} else if((xtvec & 0x3UL) == 1UL)
this->reg.NEXT_PC += 4 * cause;
}
std::array<char, 32> buffer; std::array<char, 32> buffer;
#if defined(_MSC_VER)
sprintf(buffer.data(), "0x%016llx", addr);
#else
sprintf(buffer.data(), "0x%016lx", addr); sprintf(buffer.data(), "0x%016lx", addr);
#endif
if((flags & 0xffffffff) != 0xffffffff) if((flags & 0xffffffff) != 0xffffffff)
CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" NSCLOG(INFO, LOGCAT) << (trap_id ? "Interrupt" : "Trap") << " with cause '"
<< (trap_id ? this->irq_str[cause] : this->trap_str[cause]) << "' (" << cause << ")" << (trap_id ? this->irq_str[cause] : this->trap_str[cause]) << "' (" << cause << ")"
<< " at address " << buffer.data() << " occurred, changing privilege level from " << this->lvl[cur_priv] << " at address " << buffer.data() << " occurred, changing privilege level from " << this->lvl[this->reg.PRIV]
<< " to " << this->lvl[new_priv]; << " to " << this->lvl[new_priv];
// reset trap state // reset trap state
this->reg.PRIV = new_priv; this->reg.PRIV = new_priv;
this->reg.trap_state = 0; this->reg.trap_state = 0;
update_vm_info();
return this->reg.NEXT_PC; return this->reg.NEXT_PC;
} }
template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::leave_trap(uint64_t flags) { template <typename BASE, features_e FEAT, typename LOGCAT> uint64_t riscv_hart_msu_vp<BASE, FEAT, LOGCAT>::leave_trap(uint64_t flags) {
auto cur_priv = this->reg.PRIV; auto cur_priv = this->reg.PRIV;
auto inst_priv = flags & 0x3; auto inst_priv = flags & 0x3;
auto status = state.mstatus;
auto tsr = state.mstatus.TSR; auto tsr = state.mstatus.TSR;
if(cur_priv == PRIV_S && inst_priv == PRIV_S && tsr != 0) { if(cur_priv == PRIV_S && inst_priv == PRIV_S && tsr != 0) {
this->reg.trap_state = (1 << 31) | (2 << 16); this->reg.trap_state = 0x80ULL << 24 | (2 << 16); // illegal instruction
this->fault_data = this->reg.PC; this->reg.NEXT_PC = std::numeric_limits<uint32_t>::max();
return this->reg.PC; } else {
auto status = state.mstatus;
// pop the relevant lower-privilege interrupt enable and privilege mode stack
// clear respective yIE
switch(inst_priv) {
case PRIV_M:
this->reg.PRIV = state.mstatus.MPP;
state.mstatus.MPP = 0; // clear mpp to U mode
state.mstatus.MIE = state.mstatus.MPIE;
state.mstatus.MPIE = 1;
break;
case PRIV_S:
this->reg.PRIV = state.mstatus.SPP;
state.mstatus.SPP = 0; // clear spp to U mode
state.mstatus.SIE = state.mstatus.SPIE;
state.mstatus.SPIE = 1;
break;
case PRIV_U:
this->reg.PRIV = 0;
state.mstatus.UIE = state.mstatus.UPIE;
state.mstatus.UPIE = 1;
break;
}
// sets the pc to the value stored in the x epc register.
this->reg.NEXT_PC = this->csr[uepc | inst_priv << 8];
NSCLOG(INFO, LOGCAT) << "Executing xRET , changing privilege level from " << this->lvl[cur_priv] << " to "
<< this->lvl[this->reg.PRIV];
check_interrupt();
} }
this->reg.trap_state = this->reg.pending_trap;
// pop the relevant lower-privilege interrupt enable and privilege mode stack
// clear respective yIE
switch(inst_priv) {
case PRIV_M:
this->reg.PRIV = state.mstatus.MPP;
state.mstatus.MPP = 0; // clear mpp to U mode
state.mstatus.MIE = state.mstatus.MPIE;
state.mstatus.MPIE = 1;
break;
case PRIV_S:
this->reg.PRIV = state.mstatus.SPP;
state.mstatus.SPP = 0; // clear spp to U mode
state.mstatus.SIE = state.mstatus.SPIE;
state.mstatus.SPIE = 1;
break;
case PRIV_U:
this->reg.PRIV = 0;
state.mstatus.UIE = state.mstatus.UPIE;
state.mstatus.UPIE = 1;
break;
}
// sets the pc to the value stored in the x epc register.
this->reg.NEXT_PC = this->csr[uepc | inst_priv << 8];
CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << this->lvl[cur_priv] << " to " << this->lvl[this->reg.PRIV];
update_vm_info();
check_interrupt();
return this->reg.NEXT_PC; return this->reg.NEXT_PC;
} }
template <typename BASE> void riscv_hart_msu_vp<BASE>::wait_until(uint64_t flags) { template <typename BASE, features_e FEAT, typename LOGCAT> void riscv_hart_msu_vp<BASE, FEAT, LOGCAT>::wait_until(uint64_t flags) {
auto status = state.mstatus; auto status = state.mstatus;
auto tw = status.TW; auto tw = status.TW;
if(this->reg.PRIV == PRIV_S && tw != 0) { if(this->reg.PRIV < PRIV_M && tw != 0) {
this->reg.trap_state = (1 << 31) | (2 << 16); this->reg.trap_state = (1 << 31) | (2 << 16);
this->fault_data = this->reg.PC; this->fault_data = this->reg.PC;
} }
+57 -61
View File
@@ -40,15 +40,15 @@
#include "riscv_hart_common.h" #include "riscv_hart_common.h"
#include "util/logging.h" #include "util/logging.h"
#include <algorithm> #include <algorithm>
#include <array>
#include <cstdint> #include <cstdint>
#include <elfio/elf_types.hpp> #include <elfio/elf_types.hpp>
#include <elfio/elfio.hpp>
#ifndef FMT_HEADER_ONLY #ifndef FMT_HEADER_ONLY
#define FMT_HEADER_ONLY #define FMT_HEADER_ONLY
#endif #endif
#include <array>
#include <elfio/elfio.hpp>
#include <fmt/format.h> #include <fmt/format.h>
#include <iss/mmio/memory_with_htif.h> #include <iss/mem/memory_with_htif.h>
#include <unordered_map> #include <unordered_map>
namespace iss { namespace iss {
@@ -71,7 +71,7 @@ public:
#else #else
switch(priv_lvl) { switch(priv_lvl) {
case PRIV_U: case PRIV_U:
return 0x00000011UL; // 0b1...0 0001 0001 return FEAT & features_e::FEAT_EXT_N ? 0x00000011UL : 0UL; // 0b1...0 0001 0001
default: default:
// +-SD // +-SD
// | +-TSR // | +-TSR
@@ -88,7 +88,7 @@ public:
// | |||||| | | | || +-UPIE // | |||||| | | | || +-UPIE
// | ||||||/|/|/| || |+-MIE // | ||||||/|/|/| || |+-MIE
// | ||||||/|/|/| || || +-UIE // | ||||||/|/|/| || || +-UIE
return 0b00000000000000000001100010011001; return 0b10000000001000000001100010011001;
} }
#endif #endif
} else if(sizeof(reg_t) == 8) { } else if(sizeof(reg_t) == 8) {
@@ -97,24 +97,23 @@ public:
#else #else
switch(priv_lvl) { switch(priv_lvl) {
case PRIV_U: case PRIV_U:
return 0x00000011UL; // 0b1...0 0001 0001 return FEAT & features_e::FEAT_EXT_N ? 0x8000000000000011ULL : 0ULL; // 0b1...0 0001 0001
default: default:
// +-SD // +-TSR
// | +-TSR // |+-TW
// | |+-TW // ||+-TVM
// | ||+-TVM // |||+-MXR
// | |||+-MXR // ||||+-SUM
// | ||||+-SUM // |||||+-MPRV
// | |||||+-MPRV // |||||| +-XS
// | |||||| +-XS // |||||| | +-FS
// | |||||| | +-FS // |||||| | | +-MPP
// | |||||| | | +-MPP // |||||| | | | +-SPP
// | |||||| | | | +-SPP // |||||| | | | |+-MPIE
// | |||||| | | | |+-MPIE // |||||| | | | || +-UPIE
// | |||||| | | | || +-UPIE // ||||||/|/|/| || |+-MIE
// | ||||||/|/|/| || |+-MIE // ||||||/|/|/| || || +-UIE
// | ||||||/|/|/| || || +-UIE return 0b00000000001000000001100010011001 | 0x8000000000000000ULL;
return 0b00000000000000000001100010011001;
} }
#endif #endif
} else } else
@@ -137,7 +136,7 @@ public:
return m[mode]; return m[mode];
} }
riscv_hart_mu_p(feature_config cfg = feature_config{}); riscv_hart_mu_p();
virtual ~riscv_hart_mu_p() = default; virtual ~riscv_hart_mu_p() = default;
@@ -151,6 +150,7 @@ public:
uint64_t enter_trap(uint64_t flags) override { return riscv_hart_mu_p::enter_trap(flags, this->fault_data, this->fault_data); } uint64_t enter_trap(uint64_t flags) override { return riscv_hart_mu_p::enter_trap(flags, this->fault_data, this->fault_data); }
uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override;
uint64_t leave_trap(uint64_t flags) override; uint64_t leave_trap(uint64_t flags) override;
void wait_until(uint64_t flags) override;
void set_csr(unsigned addr, reg_t val) { this->csr[addr & this->csr.page_addr_mask] = val; } void set_csr(unsigned addr, reg_t val) { this->csr[addr & this->csr.page_addr_mask] = val; }
@@ -160,7 +160,6 @@ protected:
hart_state<reg_t> state; hart_state<reg_t> state;
std::unordered_map<reg_t, uint64_t> ptw;
std::unordered_map<uint64_t, uint8_t> atomic_reservation; std::unordered_map<uint64_t, uint8_t> atomic_reservation;
iss::status read_status(unsigned addr, reg_t& val); iss::status read_status(unsigned addr, reg_t& val);
@@ -180,14 +179,12 @@ protected:
iss::status write_edeleg(unsigned addr, reg_t val); iss::status write_edeleg(unsigned addr, reg_t val);
void check_interrupt(); void check_interrupt();
feature_config cfg; mem::memory_with_htif<reg_t> default_mem;
mmio::memory_with_htif<reg_t> default_mem;
}; };
template <typename BASE, features_e FEAT, typename LOGCAT> template <typename BASE, features_e FEAT, typename LOGCAT>
riscv_hart_mu_p<BASE, FEAT, LOGCAT>::riscv_hart_mu_p(feature_config cfg) riscv_hart_mu_p<BASE, FEAT, LOGCAT>::riscv_hart_mu_p()
: state() : state()
, cfg(cfg)
, default_mem(base::get_priv_if()) { , default_mem(base::get_priv_if()) {
const std::array<unsigned, 8> rwaddrs{{ const std::array<unsigned, 8> rwaddrs{{
mepc, mepc,
@@ -248,7 +245,7 @@ riscv_hart_mu_p<BASE, FEAT, LOGCAT>::riscv_hart_mu_p(feature_config cfg)
} }
this->rd_func = util::delegate<arch_if::rd_func_sig>::from<this_class, &this_class::read>(this); this->rd_func = util::delegate<arch_if::rd_func_sig>::from<this_class, &this_class::read>(this);
this->wr_func = util::delegate<arch_if::wr_func_sig>::from<this_class, &this_class::write>(this); this->wr_func = util::delegate<arch_if::wr_func_sig>::from<this_class, &this_class::write>(this);
this->memories.prepend(*this); this->memories.root(*this);
this->memories.append(default_mem); this->memories.append(default_mem);
} }
@@ -384,16 +381,8 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write(const address_type type,
return iss::Err; return iss::Err;
return this->write_csr(addr, *reinterpret_cast<const reg_t*>(data)); return this->write_csr(addr, *reinterpret_cast<const reg_t*>(data));
} break; } break;
case traits<BASE>::FENCE: { case traits<BASE>::FENCE:
switch(addr) { break;
case 2:
case 3: {
ptw.clear();
auto tvm = state.mstatus.TVM;
return iss::Ok;
}
}
} break;
case traits<BASE>::RES: { case traits<BASE>::RES: {
atomic_reservation[addr] = data[0]; atomic_reservation[addr] = data[0];
} break; } break;
@@ -505,12 +494,12 @@ template <typename BASE, features_e FEAT, typename LOGCAT> void riscv_hart_mu_p<
} }
template <typename BASE, features_e FEAT, typename LOGCAT> template <typename BASE, features_e FEAT, typename LOGCAT>
uint64_t riscv_hart_mu_p<BASE, FEAT, LOGCAT>::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) { uint64_t riscv_hart_mu_p<BASE, FEAT, LOGCAT>::enter_trap(uint64_t flags, uint64_t addr, uint64_t tval) {
// flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0]
// calculate and write mcause val // calculate and write mcause val
if(flags == std::numeric_limits<uint64_t>::max()) if(flags == std::numeric_limits<uint64_t>::max())
flags = this->reg.trap_state; flags = this->reg.trap_state;
auto trap_id = bit_sub<0, 16>(flags); auto const trap_id = bit_sub<0, 16>(flags);
auto cause = bit_sub<16, 15>(flags); auto cause = bit_sub<16, 15>(flags);
if(trap_id == 0 && cause == 11) if(trap_id == 0 && cause == 11)
cause = 0x8 + this->reg.PRIV; // adjust environment call cause cause = 0x8 + this->reg.PRIV; // adjust environment call cause
@@ -533,7 +522,7 @@ uint64_t riscv_hart_mu_p<BASE, FEAT, LOGCAT>::enter_trap(uint64_t flags, uint64_
this->csr[utval | (new_priv << 8)] = static_cast<reg_t>(addr); this->csr[utval | (new_priv << 8)] = static_cast<reg_t>(addr);
break; break;
case 2: case 2:
this->csr[utval | (new_priv << 8)] = (!this->has_compressed() || (instr & 0x3) == 3) ? instr : instr & 0xffff; this->csr[utval | (new_priv << 8)] = (!this->has_compressed() || (tval & 0x3) == 3) ? tval : tval & 0xffff;
break; break;
case 3: case 3:
if((FEAT & FEAT_DEBUG) && (this->csr[dcsr] & 0x8000)) { if((FEAT & FEAT_DEBUG) && (this->csr[dcsr] & 0x8000)) {
@@ -545,7 +534,6 @@ uint64_t riscv_hart_mu_p<BASE, FEAT, LOGCAT>::enter_trap(uint64_t flags, uint64_
} }
if(this->semihosting_cb) { if(this->semihosting_cb) {
// Check for semihosting call // Check for semihosting call
phys_addr_t p_addr(access_type::DEBUG_READ, traits<BASE>::MEM, addr - 4);
std::array<uint8_t, 8> data; std::array<uint8_t, 8> data;
// check for SLLI_X0_X0_0X1F and SRAI_X0_X0_0X07 // check for SLLI_X0_X0_0X1F and SRAI_X0_X0_0X07
this->memory.rd_mem(iss::access_type::DEBUG_READ, addr - 4, 4, data.data()); this->memory.rd_mem(iss::access_type::DEBUG_READ, addr - 4, 4, data.data());
@@ -562,7 +550,7 @@ uint64_t riscv_hart_mu_p<BASE, FEAT, LOGCAT>::enter_trap(uint64_t flags, uint64_
#else #else
sprintf(buffer.data(), "0x%016lx", addr); sprintf(buffer.data(), "0x%016lx", addr);
#endif #endif
CLOG(INFO, disass) << "Semihosting call at address " << buffer.data() << " occurred "; NSCLOG(INFO, LOGCAT) << "Semihosting call at address " << buffer.data() << " occurred ";
this->semihosting_cb(this, &(this->reg.X10) /*a0*/, &(this->reg.X11) /*a1*/); this->semihosting_cb(this, &(this->reg.X10) /*a0*/, &(this->reg.X11) /*a1*/);
return this->reg.NEXT_PC; return this->reg.NEXT_PC;
@@ -611,15 +599,15 @@ uint64_t riscv_hart_mu_p<BASE, FEAT, LOGCAT>::enter_trap(uint64_t flags, uint64_
auto xtvec = this->csr[utvec | (new_priv << 8)]; auto xtvec = this->csr[utvec | (new_priv << 8)];
// calculate addr// set NEXT_PC to trap addressess to jump to based on MODE // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE
// bits in mtvec // bits in mtvec
if(trap_id != 0 && (xtvec & 0x3UL) == 3UL) { this->reg.NEXT_PC = xtvec & ~0x3UL;
reg_t data; if(trap_id != 0) {
auto ret = read(address_type::LOGICAL, access_type::READ, 0, this->csr[mtvt], sizeof(reg_t), reinterpret_cast<uint8_t*>(&data)); if((xtvec & 0x3UL) == 3UL) {
if(ret == iss::Err) reg_t data;
return this->reg.PC; auto ret = read(address_type::LOGICAL, access_type::READ, 0, this->csr[mtvt], sizeof(reg_t), reinterpret_cast<uint8_t*>(&data));
this->reg.NEXT_PC = data; if(ret == iss::Err)
} else { return this->reg.PC;
this->reg.NEXT_PC = xtvec & ~0x3UL; this->reg.NEXT_PC = data;
if((xtvec & 0x1) == 1 && trap_id != 0) } else if((xtvec & 0x3UL) == 1UL)
this->reg.NEXT_PC += 4 * cause; this->reg.NEXT_PC += 4 * cause;
} }
std::array<char, 32> buffer; std::array<char, 32> buffer;
@@ -629,10 +617,10 @@ uint64_t riscv_hart_mu_p<BASE, FEAT, LOGCAT>::enter_trap(uint64_t flags, uint64_
sprintf(buffer.data(), "0x%016lx", addr); sprintf(buffer.data(), "0x%016lx", addr);
#endif #endif
if((flags & 0xffffffff) != 0xffffffff) if((flags & 0xffffffff) != 0xffffffff)
CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" NSCLOG(INFO, LOGCAT) << (trap_id ? "Interrupt" : "Trap") << " with cause '"
<< (trap_id ? this->irq_str[cause] : this->trap_str[cause]) << "' (" << cause << ")" << (trap_id ? this->irq_str[cause] : this->trap_str[cause]) << "' (" << cause << ")"
<< " at address " << buffer.data() << " occurred, changing privilege level from " << this->lvl[this->reg.PRIV] << " at address " << buffer.data() << " occurred, changing privilege level from " << this->lvl[this->reg.PRIV]
<< " to " << this->lvl[new_priv]; << " to " << this->lvl[new_priv];
// reset trap state // reset trap state
this->reg.PRIV = new_priv; this->reg.PRIV = new_priv;
this->reg.trap_state = 0; this->reg.trap_state = 0;
@@ -643,8 +631,7 @@ template <typename BASE, features_e FEAT, typename LOGCAT> uint64_t riscv_hart_m
auto cur_priv = this->reg.PRIV; auto cur_priv = this->reg.PRIV;
auto inst_priv = (flags & 0x3) ? 3 : 0; auto inst_priv = (flags & 0x3) ? 3 : 0;
if(inst_priv > cur_priv) { if(inst_priv > cur_priv) {
auto trap_val = 0x80ULL << 24 | (2 << 16); // illegal instruction this->reg.trap_state = 0x80ULL << 24 | (2 << 16); // illegal instruction
this->reg.trap_state = trap_val;
this->reg.NEXT_PC = std::numeric_limits<uint32_t>::max(); this->reg.NEXT_PC = std::numeric_limits<uint32_t>::max();
} else { } else {
auto status = state.mstatus; auto status = state.mstatus;
@@ -665,13 +652,22 @@ template <typename BASE, features_e FEAT, typename LOGCAT> uint64_t riscv_hart_m
} }
// sets the pc to the value stored in the x epc register. // sets the pc to the value stored in the x epc register.
this->reg.NEXT_PC = this->csr[uepc | inst_priv << 8]; this->reg.NEXT_PC = this->csr[uepc | inst_priv << 8];
CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << this->lvl[cur_priv] << " to " NSCLOG(INFO, LOGCAT) << "Executing xRET , changing privilege level from " << this->lvl[cur_priv] << " to "
<< this->lvl[this->reg.PRIV]; << this->lvl[this->reg.PRIV];
check_interrupt(); check_interrupt();
} }
this->reg.trap_state = this->reg.pending_trap;
return this->reg.NEXT_PC; return this->reg.NEXT_PC;
} }
template <typename BASE, features_e FEAT, typename LOGCAT> void riscv_hart_mu_p<BASE, FEAT, LOGCAT>::wait_until(uint64_t flags) {
auto status = state.mstatus;
auto tw = status.TW;
if(this->reg.PRIV == PRIV_S && tw != 0) {
this->reg.trap_state = (1 << 31) | (2 << 16);
this->fault_data = this->reg.PC;
}
}
} // namespace arch } // namespace arch
} // namespace iss } // namespace iss
+17 -6
View File
@@ -53,9 +53,11 @@ template <> struct traits<tgc5c> {
static constexpr std::array<const char*, 36> reg_aliases{ static constexpr std::array<const char*, 36> reg_aliases{
{"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "next_pc", "priv", "dpc"}}; {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "next_pc", "priv", "dpc"}};
enum constants {RV_CSR_FFLAGS=1ULL, RV_CSR_FRM=2ULL, RV_CSR_FCSR=3ULL, RV_CSR_UTVT=7ULL, RV_CSR_VSTART=8ULL, RV_CSR_VXSAT=9ULL, RV_CSR_VXRM=10ULL, RV_CSR_VCSR=15ULL, RV_CSR_SEED=21ULL, RV_CSR_UNXTI=69ULL, RV_CSR_UINTSTATUS=70ULL, RV_CSR_USCRATCHCSW=72ULL, RV_CSR_USCRATCHCSWL=73ULL, RV_CSR_SSTATUS=256ULL, RV_CSR_SEDELEG=258ULL, RV_CSR_SIDELEG=259ULL, RV_CSR_SIE=260ULL, RV_CSR_STVEC=261ULL, RV_CSR_SCOUNTEREN=262ULL, RV_CSR_STVT=263ULL, RV_CSR_SENVCFG=266ULL, RV_CSR_SSTATEEN0=268ULL, RV_CSR_SSTATEEN1=269ULL, RV_CSR_SSTATEEN2=270ULL, RV_CSR_SSTATEEN3=271ULL, RV_CSR_SSCRATCH=320ULL, RV_CSR_SEPC=321ULL, RV_CSR_SCAUSE=322ULL, RV_CSR_STVAL=323ULL, RV_CSR_SIP=324ULL, RV_CSR_SNXTI=325ULL, RV_CSR_SINTSTATUS=326ULL, RV_CSR_SSCRATCHCSW=328ULL, RV_CSR_SSCRATCHCSWL=329ULL, RV_CSR_STIMECMP=333ULL, RV_CSR_STIMECMPH=349ULL, RV_CSR_SATP=384ULL, RV_CSR_VSSTATUS=512ULL, RV_CSR_VSIE=516ULL, RV_CSR_VSTVEC=517ULL, RV_CSR_VSSCRATCH=576ULL, RV_CSR_VSEPC=577ULL, RV_CSR_VSCAUSE=578ULL, RV_CSR_VSTVAL=579ULL, RV_CSR_VSIP=580ULL, RV_CSR_VSTIMECMP=589ULL, RV_CSR_VSTIMECMPH=605ULL, RV_CSR_VSATP=640ULL, RV_CSR_MSTATUS=768ULL, RV_CSR_MISA=769ULL, RV_CSR_MEDELEG=770ULL, RV_CSR_MIDELEG=771ULL, RV_CSR_MIE=772ULL, RV_CSR_MTVEC=773ULL, RV_CSR_MCOUNTEREN=774ULL, RV_CSR_MTVT=775ULL, RV_CSR_MENVCFG=778ULL, RV_CSR_MSTATEEN0=780ULL, RV_CSR_MSTATEEN1=781ULL, RV_CSR_MSTATEEN2=782ULL, RV_CSR_MSTATEEN3=783ULL, RV_CSR_MSTATUSH=784ULL, RV_CSR_MENVCFGH=794ULL, RV_CSR_MSTATEEN0H=796ULL, RV_CSR_MSTATEEN1H=797ULL, RV_CSR_MSTATEEN2H=798ULL, RV_CSR_MSTATEEN3H=799ULL, RV_CSR_MCOUNTINHIBIT=800ULL, RV_CSR_MHPMEVENT3=803ULL, RV_CSR_MHPMEVENT4=804ULL, RV_CSR_MHPMEVENT5=805ULL, RV_CSR_MHPMEVENT6=806ULL, RV_CSR_MHPMEVENT7=807ULL, RV_CSR_MHPMEVENT8=808ULL, RV_CSR_MHPMEVENT9=809ULL, RV_CSR_MHPMEVENT10=810ULL, RV_CSR_MHPMEVENT11=811ULL, RV_CSR_MHPMEVENT12=812ULL, RV_CSR_MHPMEVENT13=813ULL, RV_CSR_MHPMEVENT14=814ULL, RV_CSR_MHPMEVENT15=815ULL, RV_CSR_MHPMEVENT16=816ULL, RV_CSR_MHPMEVENT17=817ULL, RV_CSR_MHPMEVENT18=818ULL, RV_CSR_MHPMEVENT19=819ULL, RV_CSR_MHPMEVENT20=820ULL, RV_CSR_MHPMEVENT21=821ULL, RV_CSR_MHPMEVENT22=822ULL, RV_CSR_MHPMEVENT23=823ULL, RV_CSR_MHPMEVENT24=824ULL, RV_CSR_MHPMEVENT25=825ULL, RV_CSR_MHPMEVENT26=826ULL, RV_CSR_MHPMEVENT27=827ULL, RV_CSR_MHPMEVENT28=828ULL, RV_CSR_MHPMEVENT29=829ULL, RV_CSR_MHPMEVENT30=830ULL, RV_CSR_MHPMEVENT31=831ULL, RV_CSR_MSCRATCH=832ULL, RV_CSR_MEPC=833ULL, RV_CSR_MCAUSE=834ULL, RV_CSR_MTVAL=835ULL, RV_CSR_MIP=836ULL, RV_CSR_MNXTI=837ULL, RV_CSR_MINTSTATUS=838ULL, RV_CSR_MSCRATCHCSW=840ULL, RV_CSR_MSCRATCHCSWL=841ULL, RV_CSR_MTINST=842ULL, RV_CSR_MTVAL2=843ULL, RV_CSR_PMPCFG0=928ULL, RV_CSR_PMPCFG1=929ULL, RV_CSR_PMPCFG2=930ULL, RV_CSR_PMPCFG3=931ULL, RV_CSR_PMPCFG4=932ULL, RV_CSR_PMPCFG5=933ULL, RV_CSR_PMPCFG6=934ULL, RV_CSR_PMPCFG7=935ULL, RV_CSR_PMPCFG8=936ULL, RV_CSR_PMPCFG9=937ULL, RV_CSR_PMPCFG10=938ULL, RV_CSR_PMPCFG11=939ULL, RV_CSR_PMPCFG12=940ULL, RV_CSR_PMPCFG13=941ULL, RV_CSR_PMPCFG14=942ULL, RV_CSR_PMPCFG15=943ULL, RV_CSR_PMPADDR0=944ULL, RV_CSR_PMPADDR1=945ULL, RV_CSR_PMPADDR2=946ULL, RV_CSR_PMPADDR3=947ULL, RV_CSR_PMPADDR4=948ULL, RV_CSR_PMPADDR5=949ULL, RV_CSR_PMPADDR6=950ULL, RV_CSR_PMPADDR7=951ULL, RV_CSR_PMPADDR8=952ULL, RV_CSR_PMPADDR9=953ULL, RV_CSR_PMPADDR10=954ULL, RV_CSR_PMPADDR11=955ULL, RV_CSR_PMPADDR12=956ULL, RV_CSR_PMPADDR13=957ULL, RV_CSR_PMPADDR14=958ULL, RV_CSR_PMPADDR15=959ULL, RV_CSR_PMPADDR16=960ULL, RV_CSR_PMPADDR17=961ULL, RV_CSR_PMPADDR18=962ULL, RV_CSR_PMPADDR19=963ULL, RV_CSR_PMPADDR20=964ULL, RV_CSR_PMPADDR21=965ULL, RV_CSR_PMPADDR22=966ULL, RV_CSR_PMPADDR23=967ULL, RV_CSR_PMPADDR24=968ULL, RV_CSR_PMPADDR25=969ULL, RV_CSR_PMPADDR26=970ULL, RV_CSR_PMPADDR27=971ULL, RV_CSR_PMPADDR28=972ULL, RV_CSR_PMPADDR29=973ULL, RV_CSR_PMPADDR30=974ULL, RV_CSR_PMPADDR31=975ULL, RV_CSR_PMPADDR32=976ULL, RV_CSR_PMPADDR33=977ULL, RV_CSR_PMPADDR34=978ULL, RV_CSR_PMPADDR35=979ULL, RV_CSR_PMPADDR36=980ULL, RV_CSR_PMPADDR37=981ULL, RV_CSR_PMPADDR38=982ULL, RV_CSR_PMPADDR39=983ULL, RV_CSR_PMPADDR40=984ULL, RV_CSR_PMPADDR41=985ULL, RV_CSR_PMPADDR42=986ULL, RV_CSR_PMPADDR43=987ULL, RV_CSR_PMPADDR44=988ULL, RV_CSR_PMPADDR45=989ULL, RV_CSR_PMPADDR46=990ULL, RV_CSR_PMPADDR47=991ULL, RV_CSR_PMPADDR48=992ULL, RV_CSR_PMPADDR49=993ULL, RV_CSR_PMPADDR50=994ULL, RV_CSR_PMPADDR51=995ULL, RV_CSR_PMPADDR52=996ULL, RV_CSR_PMPADDR53=997ULL, RV_CSR_PMPADDR54=998ULL, RV_CSR_PMPADDR55=999ULL, RV_CSR_PMPADDR56=1000ULL, RV_CSR_PMPADDR57=1001ULL, RV_CSR_PMPADDR58=1002ULL, RV_CSR_PMPADDR59=1003ULL, RV_CSR_PMPADDR60=1004ULL, RV_CSR_PMPADDR61=1005ULL, RV_CSR_PMPADDR62=1006ULL, RV_CSR_PMPADDR63=1007ULL, RV_CSR_SCONTEXT=1448ULL, RV_CSR_HSTATUS=1536ULL, RV_CSR_HEDELEG=1538ULL, RV_CSR_HIDELEG=1539ULL, RV_CSR_HIE=1540ULL, RV_CSR_HTIMEDELTA=1541ULL, RV_CSR_HCOUNTEREN=1542ULL, RV_CSR_HGEIE=1543ULL, RV_CSR_HENVCFG=1546ULL, RV_CSR_HSTATEEN0=1548ULL, RV_CSR_HSTATEEN1=1549ULL, RV_CSR_HSTATEEN2=1550ULL, RV_CSR_HSTATEEN3=1551ULL, RV_CSR_HTIMEDELTAH=1557ULL, RV_CSR_HENVCFGH=1562ULL, RV_CSR_HSTATEEN0H=1564ULL, RV_CSR_HSTATEEN1H=1565ULL, RLine truncated enum constants {MISA_VAL=1073746180ULL, MARCHID_VAL=2147483651ULL, CLIC_NUM_IRQ=0ULL, XLEN=32ULL, FLEN=0ULL, INSTR_ALIGNMENT=2ULL, RFS=32ULL, fence=0ULL, fencei=1ULL, fencevmal=2ULL, fencevmau=3ULL, RV_CSR_FFLAGS=1ULL, RV_CSR_FRM=2ULL, RV_CSR_FCSR=3ULL, RV_CSR_UTVT=7ULL, RV_CSR_VSTART=8ULL, RV_CSR_VXSAT=9ULL, RV_CSR_VXRM=10ULL, RV_CSR_VCSR=15ULL, RV_CSR_SEED=21ULL, RV_CSR_UNXTI=69ULL, RV_CSR_UINTSTATUS=70ULL, RV_CSR_USCRATCHCSW=72ULL, RV_CSR_USCRATCHCSWL=73ULL, RV_CSR_SSTATUS=256ULL, RV_CSR_SEDELEG=258ULL, RV_CSR_SIDELEG=259ULL, RV_CSR_SIE=260ULL, RV_CSR_STVEC=261ULL, RV_CSR_SCOUNTEREN=262ULL, RV_CSR_STVT=263ULL, RV_CSR_SENVCFG=266ULL, RV_CSR_SSTATEEN0=268ULL, RV_CSR_SSTATEEN1=269ULL, RV_CSR_SSTATEEN2=270ULL, RV_CSR_SSTATEEN3=271ULL, RV_CSR_SSCRATCH=320ULL, RV_CSR_SEPC=321ULL, RV_CSR_SCAUSE=322ULL, RV_CSR_STVAL=323ULL, RV_CSR_SIP=324ULL, RV_CSR_SNXTI=325ULL, RV_CSR_SINTSTATUS=326ULL, RV_CSR_SSCRATCHCSW=328ULL, RV_CSR_SSCRATCHCSWL=329ULL, RV_CSR_STIMECMP=333ULL, RV_CSR_STIMECMPH=349ULL, RV_CSR_SATP=384ULL, RV_CSR_VSSTATUS=512ULL, RV_CSR_VSIE=516ULL, RV_CSR_VSTVEC=517ULL, RV_CSR_VSSCRATCH=576ULL, RV_CSR_VSEPC=577ULL, RV_CSR_VSCAUSE=578ULL, RV_CSR_VSTVAL=579ULL, RV_CSR_VSIP=580ULL, RV_CSR_VSTIMECMP=589ULL, RV_CSR_VSTIMECMPH=605ULL, RV_CSR_VSATP=640ULL, RV_CSR_MSTATUS=768ULL, RV_CSR_MISA=769ULL, RV_CSR_MEDELEG=770ULL, RV_CSR_MIDELEG=771ULL, RV_CSR_MIE=772ULL, RV_CSR_MTVEC=773ULL, RV_CSR_MCOUNTEREN=774ULL, RV_CSR_MTVT=775ULL, RV_CSR_MENVCFG=778ULL, RV_CSR_MSTATEEN0=780ULL, RV_CSR_MSTATEEN1=781ULL, RV_CSR_MSTATEEN2=782ULL, RV_CSR_MSTATEEN3=783ULL, RV_CSR_MSTATUSH=784ULL, RV_CSR_MENVCFGH=794ULL, RV_CSR_MSTATEEN0H=796ULL, RV_CSR_MSTATEEN1H=797ULL, RV_CSR_MSTATEEN2H=798ULL, RV_CSR_MSTATEEN3H=799ULL, RV_CSR_MCOUNTINHIBIT=800ULL, RV_CSR_MHPMEVENT3=803ULL, RV_CSR_MHPMEVENT4=804ULL, RV_CSR_MHPMEVENT5=805ULL, RV_CSR_MHPMEVENT6=806ULL, RV_CSR_MHPMEVENT7=807ULL, RV_CSR_MHPMEVENT8=808ULL, RV_CSR_MHPMEVENT9=809ULL, RV_CSR_MHPMEVENT10=810ULL, RV_CSR_MHPMEVENT11=811ULL, RV_CSR_MHPMEVENT12=812ULL, RV_CSR_MHPMEVENT13=813ULL, RV_CSR_MHPMEVENT14=814ULL, RV_CSR_MHPMEVENT15=815ULL, RV_CSR_MHPMEVENT16=816ULL, RV_CSR_MHPMEVENT17=817ULL, RV_CSR_MHPMEVENT18=818ULL, RV_CSR_MHPMEVENT19=819ULL, RV_CSR_MHPMEVENT20=820ULL, RV_CSR_MHPMEVENT21=821ULL, RV_CSR_MHPMEVENT22=822ULL, RV_CSR_MHPMEVENT23=823ULL, RV_CSR_MHPMEVENT24=824ULL, RV_CSR_MHPMEVENT25=825ULL, RV_CSR_MHPMEVENT26=826ULL, RV_CSR_MHPMEVENT27=827ULL, RV_CSR_MHPMEVENT28=828ULL, RV_CSR_MHPMEVENT29=829ULL, RV_CSR_MHPMEVENT30=830ULL, RV_CSR_MHPMEVENT31=831ULL, RV_CSR_MSCRATCH=832ULL, RV_CSR_MEPC=833ULL, RV_CSR_MCAUSE=834ULL, RV_CSR_MTVAL=835ULL, RV_CSR_MIP=836ULL, RV_CSR_MNXTI=837ULL, RV_CSR_MINTSTATUS=838ULL, RV_CSR_MSCRATCHCSW=840ULL, RV_CSR_MSCRATCHCSWL=841ULL, RV_CSR_MTINST=842ULL, RV_CSR_MTVAL2=843ULL, RV_CSR_PMPCFG0=928ULL, RV_CSR_PMPCFG1=929ULL, RV_CSR_PMPCFG2=930ULL, RV_CSR_PMPCFG3=931ULL, RV_CSR_PMPCFG4=932ULL, RV_CSR_PMPCFG5=933ULL, RV_CSR_PMPCFG6=934ULL, RV_CSR_PMPCFG7=935ULL, RV_CSR_PMPCFG8=936ULL, RV_CSR_PMPCFG9=937ULL, RV_CSR_PMPCFG10=938ULL, RV_CSR_PMPCFG11=939ULL, RV_CSR_PMPCFG12=940ULL, RV_CSR_PMPCFG13=941ULL, RV_CSR_PMPCFG14=942ULL, RV_CSR_PMPCFG15=943ULL, RV_CSR_PMPADDR0=944ULL, RV_CSR_PMPADDR1=945ULL, RV_CSR_PMPADDR2=946ULL, RV_CSR_PMPADDR3=947ULL, RV_CSR_PMPADDR4=948ULL, RV_CSR_PMPADDR5=949ULL, RV_CSR_PMPADDR6=950ULL, RV_CSR_PMPADDR7=951ULL, RV_CSR_PMPADDR8=952ULL, RV_CSR_PMPADDR9=953ULL, RV_CSR_PMPADDR10=954ULL, RV_CSR_PMPADDR11=955ULL, RV_CSR_PMPADDR12=956ULL, RV_CSR_PMPADDR13=957ULL, RV_CSR_PMPADDR14=958ULL, RV_CSR_PMPADDR15=959ULL, RV_CSR_PMPADDR16=960ULL, RV_CSR_PMPADDR17=961ULL, RV_CSR_PMPADDR18=962ULL, RV_CSR_PMPADDR19=963ULL, RV_CSR_PMPADDR20=964ULL, RV_CSR_PMPADDR21=965ULL, RV_CSR_PMPADDR22=966ULL, RV_CSR_PMPADDR23=967ULL, RV_CSR_PMPADDR24=968ULL, RV_CSR_PMPADDR25=969ULL, RV_CSR_PMPADDR26=970ULL, RV_CSR_PMPADDR27=971ULL, RV_CSR_PMPADDR28=972ULL, RV_CSR_PMPADDR29=973ULL, RV_CSR_PMPADDR30=974ULL, RV_CSR_PMPADDR31=975ULL, RV_CSR_PMPADDR32=976ULL, RV_CSR_PMPADDR33=977ULL, RV_CSR_PMPADDR34=978ULL, RV_CSR_PMPADDR35=979ULL, RV_CSR_PMPADDR36=980ULL, RV_CSR_PMPADDR37=981ULL, RV_CSR_PMPADDR38=982ULL, RV_CSR_PMPADDR39=983ULL, RV_CSR_PMPADDR40=984ULL, RV_CSR_PMPADDR41=985ULL, RV_CSR_PMPADDR42=986ULL, RV_CSR_PMPADDR43=987ULL, RV_CSR_PMPADDR44=988ULL, RV_CSR_PMPADDR45=989ULL, RV_CSR_PMPADDR46=990ULL, RV_CSR_PMPADDR47=991ULL, RV_CSR_PMPADDR48=992ULL, RV_CSR_PMPADDR49=993ULL, RV_CSR_PMPADDR50=994ULL, RV_CSR_PMPADDR51=995ULL, RV_CSR_PMPADDR52=996ULL, RV_CSR_PMPADDR53=997ULL, RV_CSR_PMPADDR54=998ULL, RV_CSR_PMPADDR55=999ULL, RV_CSR_PMPADDR56=1000ULL, RV_CSR_PMPADDR57=1001ULL, RV_CSR_PMPADDR58=1002ULL, RV_CSR_PMPADDR59=1003ULL, RV_CSR_PMPADDR60=1004ULL, RV_CSR_PMPADDR61=1005ULL, RV_CSR_PMPADDR62=1006ULL, RV_CSR_PMPADDR63=1007ULL, RV_CSR_SCONTEXT=1448ULL, RV_CSR_HSTATUS=1536ULL, RV_CSR_HEDELEG=1538ULL, RV_CSR_HIDELEG=1539ULL, RV_CSR_HIE=1540ULL, RV_CSR_HTIMEDELTA=1541ULL, RV_CSR_HCOUNTEREN=1542ULL, RV_CSR_HGEIE=1543ULL, RV_CSR_HENVCFG=1546ULL, RV_CSR_HSTATEEN0=1548ULL, RV_Line truncated
constexpr static unsigned FP_REGS_SIZE = 0; constexpr static unsigned FP_REGS_SIZE = 0;
constexpr static unsigned V_REGS_SIZE = 0;
enum reg_e { enum reg_e {
X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, PC, NEXT_PC, PRIV, DPC, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, PC, NEXT_PC, PRIV, DPC, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH
@@ -237,11 +239,11 @@ struct tgc5c: public arch_if {
uint8_t PRIV = 0; uint8_t PRIV = 0;
uint32_t DPC = 0; uint32_t DPC = 0;
uint32_t trap_state = 0, pending_trap = 0; uint32_t trap_state = 0, pending_trap = 0;
uint64_t icount = 0; uint64_t icount = 0; // counts number of instructions undisturbed
uint64_t cycle = 0; uint64_t cycle = 0; // counts number of cycles, in functional mode equals icount
uint64_t instret = 0; uint64_t instret = 0; // counts number of instructions, can be reset via CSR write
uint32_t instruction = 0; uint32_t instruction = 0; // holds op code of currently executed instruction
uint32_t last_branch = 0; uint32_t last_branch = 0; // indicates if last branch was taken
} reg; } reg;
#pragma pack(pop) #pragma pack(pop)
std::array<address_type, 4> addr_mode; std::array<address_type, 4> addr_mode;
@@ -251,6 +253,15 @@ struct tgc5c: public arch_if {
uint32_t get_fcsr(){return 0;} uint32_t get_fcsr(){return 0;}
void set_fcsr(uint32_t val){} void set_fcsr(uint32_t val){}
uint32_t get_vstart(){return 0;}
void set_vstart(uint32_t val){}
uint32_t get_vl(){return 0;}
uint32_t get_vtype(){return 0;}
uint32_t get_vxsat(){return 0;}
void set_vxsat(uint32_t val){}
uint32_t get_vxrm(){return 0;}
void set_vxrm(uint32_t val){}
}; };
} }
+39 -11
View File
@@ -1,3 +1,37 @@
/*******************************************************************************
* Copyright (C) 2023 - 2025 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* eyck@minres.com - initial implementation
******************************************************************************/
#ifndef _ISS_ARCH_TGC_MAPPER_H #ifndef _ISS_ARCH_TGC_MAPPER_H
#define _ISS_ARCH_TGC_MAPPER_H #define _ISS_ARCH_TGC_MAPPER_H
@@ -23,35 +57,29 @@ using tgc5c_xrb_nn_plat_type = iss::arch::hwl<iss::arch::riscv_hart_m_p<iss::arc
#ifdef CORE_TGC5D #ifdef CORE_TGC5D
#include "riscv_hart_mu_p.h" #include "riscv_hart_mu_p.h"
#include <iss/arch/tgc5d.h> #include <iss/arch/tgc5d.h>
using tgc5d_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5d, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | using tgc5d_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5d, (iss::arch::features_e)(iss::arch::FEAT_EXT_N)>;
iss::arch::FEAT_EXT_N)>;
#endif #endif
#ifdef CORE_TGC5D_XRB_MAC #ifdef CORE_TGC5D_XRB_MAC
#include "riscv_hart_mu_p.h" #include "riscv_hart_mu_p.h"
#include <iss/arch/tgc5d_xrb_mac.h> #include <iss/arch/tgc5d_xrb_mac.h>
using tgc5d_xrb_mac_plat_type = using tgc5d_xrb_mac_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5d_xrb_mac(iss::arch::features_e)(iss::arch::FEAT_EXT_N)>;
iss::arch::riscv_hart_mu_p<iss::arch::tgc5d_xrb_mac,
(iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>;
#endif #endif
#ifdef CORE_TGC5D_XRB_NN #ifdef CORE_TGC5D_XRB_NN
#include "hwl.h" #include "hwl.h"
#include "riscv_hart_mu_p.h" #include "riscv_hart_mu_p.h"
#include <iss/arch/tgc5d_xrb_nn.h> #include <iss/arch/tgc5d_xrb_nn.h>
using tgc5d_xrb_nn_plat_type = using tgc5d_xrb_nn_plat_type =
iss::arch::hwl<iss::arch::riscv_hart_mu_p<iss::arch::tgc5d_xrb_nn, iss::arch::hwl<iss::arch::riscv_hart_mu_p<iss::arch::tgc5d_xrb_nn, (iss::arch::features_e)(iss::arch::FEAT_EXT_N)>>;
(iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>>;
#endif #endif
#ifdef CORE_TGC5E #ifdef CORE_TGC5E
#include "riscv_hart_mu_p.h" #include "riscv_hart_mu_p.h"
#include <iss/arch/tgc5e.h> #include <iss/arch/tgc5e.h>
using tgc5e_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5e, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | using tgc5e_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5e, (iss::arch::features_e)(iss::arch::FEAT_EXT_N)>;
iss::arch::FEAT_EXT_N)>;
#endif #endif
#ifdef CORE_TGC5X #ifdef CORE_TGC5X
#include "riscv_hart_mu_p.h" #include "riscv_hart_mu_p.h"
#include <iss/arch/tgc5x.h> #include <iss/arch/tgc5x.h>
using tgc5x_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5x, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | using tgc5x_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5x, (iss::arch::features_e)(iss::arch::FEAT_EXT_N)>;
iss::arch::FEAT_EXT_N | iss::arch::FEAT_TCM)>;
#endif #endif
#endif #endif
+34
View File
@@ -1,3 +1,37 @@
/*******************************************************************************
* Copyright (C) 2025 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* eyck@minres.com - initial implementation
******************************************************************************/
#include <array> #include <array>
// generated from: // generated from:
// * /scratch/eyck/workarea/Other/riscv-opcodes/csrs.csv // * /scratch/eyck/workarea/Other/riscv-opcodes/csrs.csv
-1
View File
@@ -39,7 +39,6 @@
#include <iss/iss.h> #include <iss/iss.h>
#include <array> #include <array>
#include <memory>
#ifndef FMT_HEADER_ONLY #ifndef FMT_HEADER_ONLY
#define FMT_HEADER_ONLY #define FMT_HEADER_ONLY
#endif #endif
+42 -9
View File
@@ -1,11 +1,44 @@
/*******************************************************************************
* Copyright (C) 2025 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* eyck@minres.com - initial implementation
******************************************************************************/
#include "memory_if.h"
#include "iss/arch/riscv_hart_common.h" #include "iss/arch/riscv_hart_common.h"
#include "iss/vm_types.h" #include "iss/vm_types.h"
#include "memory_if.h"
#include <util/logging.h> #include <util/logging.h>
namespace iss { namespace iss {
namespace mmio { namespace mem {
struct clic_config { struct clic_config {
uint64_t clic_base{0xc0000000}; uint64_t clic_base{0xc0000000};
unsigned clic_int_ctl_bits{4}; unsigned clic_int_ctl_bits{4};
@@ -199,12 +232,12 @@ template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::read_cause(unsigned a
switch(mode) { switch(mode) {
case 0: case 0:
val |= clic_uprev_lvl << 16; val |= clic_uprev_lvl << 16;
val |= hart_if.mstatus.UPIE << 27; val |= hart_if.state.mstatus.UPIE << 27;
break; break;
default: default:
val |= clic_mprev_lvl << 16; val |= clic_mprev_lvl << 16;
val |= hart_if.mstatus.MPIE << 27; val |= hart_if.state.mstatus.MPIE << 27;
val |= hart_if.mstatus.MPP << 28; val |= hart_if.state.mstatus.MPP << 28;
break; break;
} }
} else } else
@@ -220,12 +253,12 @@ template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::write_cause(unsigned
switch(mode) { switch(mode) {
case 0: case 0:
clic_uprev_lvl = ((val >> 16) & 0xff) | (1 << (8 - cfg.clic_int_ctl_bits)) - 1; clic_uprev_lvl = ((val >> 16) & 0xff) | (1 << (8 - cfg.clic_int_ctl_bits)) - 1;
hart_if.mstatus.UPIE = (val >> 27) & 0x1; hart_if.state.mstatus.UPIE = (val >> 27) & 0x1;
break; break;
default: default:
clic_mprev_lvl = ((val >> 16) & 0xff) | (1 << (8 - cfg.clic_int_ctl_bits)) - 1; clic_mprev_lvl = ((val >> 16) & 0xff) | (1 << (8 - cfg.clic_int_ctl_bits)) - 1;
hart_if.mstatus.MPIE = (val >> 27) & 0x1; hart_if.state.mstatus.MPIE = (val >> 27) & 0x1;
hart_if.mstatus.MPP = (val >> 28) & 0x3; hart_if.state.mstatus.MPP = (val >> 28) & 0x3;
break; break;
} }
} else { } else {
@@ -248,5 +281,5 @@ template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::write_intthresh(unsig
return iss::Ok; return iss::Ok;
} }
} // namespace mmio } // namespace mem
} // namespace iss } // namespace iss
+101
View File
@@ -0,0 +1,101 @@
/*******************************************************************************
* Copyright (C) 2025 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* eyck@minres.com - initial implementation
******************************************************************************/
#include "memory_if.h"
#include <algorithm>
namespace iss {
namespace mem {
void memory_hierarchy::root(memory_elem& e) {
hierarchy.push_front(&e);
root_set = true;
update_chain();
}
void memory_hierarchy::prepend(memory_elem& e) {
if(root_set)
hierarchy.insert(hierarchy.begin() + 1, &e);
else
hierarchy.push_front(&e);
update_chain();
}
void memory_hierarchy::append(memory_elem& e) {
hierarchy.push_back(&e);
update_chain();
}
void memory_hierarchy::insert_before(memory_elem&) {}
void memory_hierarchy::insert_after(memory_elem&) {}
void memory_hierarchy::replace_last(memory_elem& e) {
auto old = hierarchy.back();
auto it = std::find_if(std::begin(owned_elems), std::end(owned_elems),
[old](std::unique_ptr<memory_elem> const& p) { return p.get() == old; });
hierarchy.pop_back();
if(it != std::end(owned_elems))
owned_elems.erase(it);
hierarchy.push_back(&e);
update_chain();
}
void memory_hierarchy::update_chain() {
bool tail = false;
for(size_t i = 1; i < hierarchy.size(); ++i) {
hierarchy[i - 1]->set_next(hierarchy[i]->get_mem_if());
}
}
void memory_hierarchy::prepend(std::unique_ptr<memory_elem>&& p) {
prepend(*p);
owned_elems.push_back(std::move(p));
}
void memory_hierarchy::append(std::unique_ptr<memory_elem>&& p) {
append(*p);
owned_elems.push_back(std::move(p));
}
void memory_hierarchy::insert_before(std::unique_ptr<memory_elem>&& p) {
insert_before(*p);
owned_elems.push_back(std::move(p));
}
void memory_hierarchy::insert_after(std::unique_ptr<memory_elem>&& p) {
insert_after(*p);
owned_elems.push_back(std::move(p));
}
void memory_hierarchy::replace_last(std::unique_ptr<memory_elem>&& p) {
replace_last(*p);
owned_elems.push_back(std::move(p));
}
} // namespace mem
} // namespace iss
@@ -39,10 +39,12 @@
#include <deque> #include <deque>
#include <functional> #include <functional>
#include <limits> #include <limits>
#include <memory>
#include <util/delegate.h> #include <util/delegate.h>
#include <vector>
namespace iss { namespace iss {
namespace mmio { namespace mem {
using rd_mem_func_sig = iss::status(iss::access_type, uint64_t, unsigned, uint8_t*); using rd_mem_func_sig = iss::status(iss::access_type, uint64_t, unsigned, uint8_t*);
using wr_mem_func_sig = iss::status(iss::access_type, uint64_t, unsigned, uint8_t const*); using wr_mem_func_sig = iss::status(iss::access_type, uint64_t, unsigned, uint8_t const*);
@@ -53,24 +55,32 @@ struct memory_if {
}; };
struct memory_elem { struct memory_elem {
virtual ~memory_elem() = default;
virtual memory_if get_mem_if() = 0; virtual memory_if get_mem_if() = 0;
virtual void set_next(memory_if) = 0; virtual void set_next(memory_if) = 0;
virtual void register_csrs() {}
virtual std::tuple<uint64_t, uint64_t> get_range() { return {0, std::numeric_limits<uint64_t>::max()}; } virtual std::tuple<uint64_t, uint64_t> get_range() { return {0, std::numeric_limits<uint64_t>::max()}; }
}; };
struct memory_hierarchy { struct memory_hierarchy {
void root(memory_elem&);
void prepend(memory_elem&); void prepend(memory_elem&);
void append(memory_elem&); void append(memory_elem&);
void insert_before(memory_elem&); void insert_before(memory_elem&);
void insert_after(memory_elem&); void insert_after(memory_elem&);
void replace_last(memory_elem&); void replace_last(memory_elem&);
void prepend(std::unique_ptr<memory_elem>&&);
void append(std::unique_ptr<memory_elem>&&);
void insert_before(std::unique_ptr<memory_elem>&&);
void insert_after(std::unique_ptr<memory_elem>&&);
void replace_last(std::unique_ptr<memory_elem>&&);
protected: protected:
void update_chain(); void update_chain();
std::deque<std::reference_wrapper<memory_elem>> hierarchy; std::deque<memory_elem*> hierarchy;
std::vector<std::unique_ptr<memory_elem>> owned_elems;
bool root_set{false};
}; };
} // namespace mmio } // namespace mem
} // namespace iss } // namespace iss
#endif #endif
+90
View File
@@ -0,0 +1,90 @@
/*******************************************************************************
* Copyright (C) 2025 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* eyck@minres.com - initial implementation
******************************************************************************/
#ifndef _MEMORY_WITH_HTIF_
#define _MEMORY_WITH_HTIF_
#include "memory_if.h"
#include "iss/arch/riscv_hart_common.h"
#include "iss/vm_types.h"
#include <util/logging.h>
#include <util/sparse_array.h>
namespace iss {
namespace mem {
template <typename WORD_TYPE> struct memory_with_htif : public memory_elem {
using this_class = memory_with_htif<WORD_TYPE>;
constexpr static unsigned WORD_LEN = sizeof(WORD_TYPE) * 8;
memory_with_htif(arch::priv_if<WORD_TYPE> hart_if)
: hart_if(hart_if) {}
~memory_with_htif() = default;
memory_if get_mem_if() override {
return memory_if{.rd_mem{util::delegate<rd_mem_func_sig>::from<this_class, &this_class::read_mem>(this)},
.wr_mem{util::delegate<wr_mem_func_sig>::from<this_class, &this_class::write_mem>(this)}};
}
void set_next(memory_if) override {
// intenrionally left empty, leaf element
}
private:
iss::status read_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t* data) {
for(auto offs = 0U; offs < length; ++offs) {
*(data + offs) = mem[(addr + offs) % mem.size()];
}
return iss::Ok;
}
iss::status write_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t const* data) {
mem_type::page_type& p = mem(addr / mem.page_size);
std::copy(data, data + length, p.data() + (addr & mem.page_addr_mask));
// this->tohost handling in case of riscv-test
// according to https://github.com/riscv-software-src/riscv-isa-sim/issues/364#issuecomment-607657754:
if(access && iss::access_type::FUNC && addr == hart_if.tohost) {
return hart_if.exec_htif(data);
}
return iss::Ok;
}
protected:
using mem_type = util::sparse_array<uint8_t, 1ULL << 32>;
mem_type mem;
arch::priv_if<WORD_TYPE> hart_if;
};
} // namespace mem
} // namespace iss
#endif // _MEMORY_WITH_HTIF_
+353
View File
@@ -0,0 +1,353 @@
/*******************************************************************************
* Copyright (C) 2025 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* eyck@minres.com - initial implementation
******************************************************************************/
#include "memory_if.h"
#include "iss/arch/riscv_hart_common.h"
#include "iss/vm_types.h"
#include <util/logging.h>
namespace iss {
namespace mem {
enum {
PGSHIFT = 12,
PTE_PPN_SHIFT = 10,
// page table entry (PTE) fields
PTE_V = 0x001, // Valid
PTE_R = 0x002, // Read
PTE_W = 0x004, // Write
PTE_X = 0x008, // Execute
PTE_U = 0x010, // User
PTE_G = 0x020, // Global
PTE_A = 0x040, // Accessed
PTE_D = 0x080, // Dirty
PTE_SOFT = 0x300 // Reserved for Software
};
template <typename T> inline bool PTE_TABLE(T PTE) { return (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V); }
struct vm_info {
int levels;
int idxbits;
int ptesize;
uint64_t ptbase;
bool is_active() { return levels; }
};
inline void read_reg_with_offset(uint32_t reg, uint8_t offs, uint8_t* const data, unsigned length) {
auto reg_ptr = reinterpret_cast<uint8_t*>(&reg);
switch(offs) {
default:
for(auto i = 0U; i < length; ++i)
*(data + i) = *(reg_ptr + i);
break;
case 1:
for(auto i = 0U; i < length; ++i)
*(data + i) = *(reg_ptr + 1 + i);
break;
case 2:
for(auto i = 0U; i < length; ++i)
*(data + i) = *(reg_ptr + 2 + i);
break;
case 3:
*data = *(reg_ptr + 3);
break;
}
}
inline void write_reg_with_offset(uint32_t& reg, uint8_t offs, const uint8_t* const data, unsigned length) {
auto reg_ptr = reinterpret_cast<uint8_t*>(&reg);
switch(offs) {
default:
for(auto i = 0U; i < length; ++i)
*(reg_ptr + i) = *(data + i);
break;
case 1:
for(auto i = 0U; i < length; ++i)
*(reg_ptr + 1 + i) = *(data + i);
break;
case 2:
for(auto i = 0U; i < length; ++i)
*(reg_ptr + 2 + i) = *(data + i);
break;
case 3:
*(reg_ptr + 3) = *data;
break;
}
}
// TODO: update vminfo on trap enter and leave as well as mstatus write, reset
template <typename WORD_TYPE> struct mmu : public memory_elem {
using this_class = mmu<WORD_TYPE>;
using reg_t = WORD_TYPE;
constexpr static unsigned WORD_LEN = sizeof(WORD_TYPE) * 8;
constexpr static reg_t PGSIZE = 1 << PGSHIFT;
constexpr static reg_t PGMASK = PGSIZE - 1;
mmu(arch::priv_if<WORD_TYPE> hart_if)
: hart_if(hart_if) {
hart_if.csr_rd_cb[satp] = MK_CSR_RD_CB(read_satp);
hart_if.csr_wr_cb[satp] = MK_CSR_WR_CB(write_satp);
}
virtual ~mmu() = default;
memory_if get_mem_if() override {
return memory_if{.rd_mem{util::delegate<rd_mem_func_sig>::from<this_class, &this_class::read_mem>(this)},
.wr_mem{util::delegate<wr_mem_func_sig>::from<this_class, &this_class::write_mem>(this)}};
}
void set_next(memory_if mem) override { down_stream_mem = mem; }
private:
iss::status read_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t* data) {
if(unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary
vm_info vm = decode_vm_info(hart_if.PRIV, satp);
if(vm.levels != 0) { // VM is active
auto split_addr = (addr + length) & ~PGMASK;
auto len1 = split_addr - addr;
auto res = down_stream_mem.rd_mem(access, addr, len1, data);
if(res == iss::Ok)
res = down_stream_mem.rd_mem(access, split_addr, length - len1, data + len1);
return res;
}
}
return down_stream_mem.rd_mem(access, addr, length, data);
}
iss::status write_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t const* data) {
if(unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary
vm_info vm = decode_vm_info(hart_if.PRIV, satp);
if(vm.levels != 0) { // VM is active
auto split_addr = (addr + length) & ~PGMASK;
auto len1 = split_addr - addr;
auto res = down_stream_mem.wr_mem(access, addr, len1, data);
if(res == iss::Ok)
res = down_stream_mem.wr_mem(access, split_addr, length - len1, data + len1);
return res;
}
}
return down_stream_mem.wr_mem(access, virt2phys(access, addr), length, data);
}
void update_vm_info();
iss::status read_plain(unsigned addr, reg_t& val) {
val = hart_if.csr[addr];
return iss::Ok;
}
iss::status write_plain(unsigned addr, reg_t const& val) {
hart_if.csr[addr] = val;
return iss::Ok;
}
iss::status read_satp(unsigned addr, reg_t& val) {
auto tvm = bit_sub<20, 1>(hart_if.state.mstatus());
if(hart_if.PRIV == arch::PRIV_S & tvm != 0) {
hart_if.raise_trap(2, 0, hart_if.PC);
// hart_if.reg.trap_state = (1 << 31) | (2 << 16);
// hart_if.fault_data = hart_if.reg.PC;
return iss::Err;
}
val = satp;
return iss::Ok;
}
iss::status write_satp(unsigned addr, reg_t val) {
reg_t tvm = hart_if.state.mstatus.TVM;
if(hart_if.PRIV == arch::PRIV_S & tvm != 0) {
hart_if.raise_trap(2, 0, hart_if.PC);
// hart_if.reg.trap_state = (1 << 31) | (2 << 16);
// hart_if.fault_data = hart_if.reg.PC;
return iss::Err;
}
satp = val;
update_vm_info();
return iss::Ok;
}
uint64_t virt2phys(iss::access_type access, uint64_t addr);
static inline vm_info decode_vm_info(uint32_t state, uint32_t sptbr) {
if(state == arch::PRIV_M)
return {0, 0, 0, 0};
if(state <= arch::PRIV_S)
switch(bit_sub<31, 1>(sptbr)) {
case 0:
return {0, 0, 0, 0}; // off
case 1:
return {2, 10, 4, bit_sub<0, 22>(sptbr) << PGSHIFT}; // SV32
default:
abort();
}
abort();
return {0, 0, 0, 0}; // dummy
}
static inline vm_info decode_vm_info(uint32_t state, uint64_t sptbr) {
if(state == arch::PRIV_M)
return {0, 0, 0, 0};
if(state <= arch::PRIV_S)
switch(bit_sub<60, 4>(sptbr)) {
case 0:
return {0, 0, 0, 0}; // off
case 8:
return {3, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV39
case 9:
return {4, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV48
case 10:
return {5, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV57
case 11:
return {6, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV64
default:
abort();
}
abort();
return {0, 0, 0, 0}; // dummy
}
protected:
reg_t satp;
std::unordered_map<reg_t, uint64_t> ptw;
std::array<vm_info, 2> vmt;
std::array<address_type, 4> addr_mode;
arch::priv_if<WORD_TYPE> hart_if;
memory_if down_stream_mem;
};
template <typename WORD_TYPE> uint64_t mmu<WORD_TYPE>::virt2phys(iss::access_type access, uint64_t addr) {
const auto type = access & iss::access_type::FUNC;
auto it = ptw.find(addr >> PGSHIFT);
if(it != ptw.end()) {
const reg_t pte = it->second;
const reg_t ad = PTE_A | (type == iss::access_type::WRITE) * PTE_D;
#ifdef RISCV_ENABLE_DIRTY
// set accessed and possibly dirty bits.
*(uint32_t*)ppte |= ad;
return {addr.getAccessType(), addr.space, (pte & (~PGMASK)) | (addr.val & PGMASK)};
#else
// take exception if access or possibly dirty bit is not set.
if((pte & ad) == ad)
return {(pte & (~PGMASK)) | (addr & PGMASK)};
else
ptw.erase(it); // throw an exception
#endif
} else {
uint32_t mode = type != iss::access_type::FETCH && hart_if.state.mstatus.MPRV ? // MPRV
hart_if.state.mstatus.MPP
: hart_if.PRIV;
const vm_info& vm = vmt[static_cast<uint16_t>(type) / 2];
const bool s_mode = mode == arch::PRIV_S;
const bool sum = hart_if.state.mstatus.SUM;
const bool mxr = hart_if.state.mstatus.MXR;
// verify bits xlen-1:va_bits-1 are all equal
const int va_bits = PGSHIFT + vm.levels * vm.idxbits;
const reg_t mask = (reg_t(1) << (sizeof(reg_t) * 8 - (va_bits - 1))) - 1;
const reg_t masked_msbs = (addr >> (va_bits - 1)) & mask;
const int levels = (masked_msbs != 0 && masked_msbs != mask) ? 0 : vm.levels;
reg_t base = vm.ptbase;
for(int i = levels - 1; i >= 0; i--) {
const int ptshift = i * vm.idxbits;
const reg_t idx = (addr >> (PGSHIFT + ptshift)) & ((1 << vm.idxbits) - 1);
// check that physical address of PTE is legal
reg_t pte = 0;
const uint8_t res = down_stream_mem.rd_mem(iss::access_type::READ, base + idx * vm.ptesize, vm.ptesize, (uint8_t*)&pte);
if(res != 0)
throw arch::trap_load_access_fault(addr);
const reg_t ppn = pte >> PTE_PPN_SHIFT;
if(PTE_TABLE(pte)) { // next level of page table
base = ppn << PGSHIFT;
} else if((pte & PTE_U) ? s_mode && (type == iss::access_type::FETCH || !sum) : !s_mode) {
break;
} else if(!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) {
break;
} else if(type == (type == iss::access_type::FETCH ? !(pte & PTE_X)
: type == iss::access_type::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X))
: !((pte & PTE_R) && (pte & PTE_W)))) {
break;
} else if((ppn & ((reg_t(1) << ptshift) - 1)) != 0) {
break;
} else {
const reg_t ad = PTE_A | ((type == iss::access_type::WRITE) * PTE_D);
#ifdef RISCV_ENABLE_DIRTY
// set accessed and possibly dirty bits.
*(uint32_t*)ppte |= ad;
#else
// take exception if access or possibly dirty bit is not set.
if((pte & ad) != ad)
break;
#endif
// for superpage mappings, make a fake leaf PTE for the TLB's benefit.
const reg_t vpn = addr >> PGSHIFT;
const reg_t value = (ppn | (vpn & ((reg_t(1) << ptshift) - 1))) << PGSHIFT;
const reg_t offset = addr & PGMASK;
ptw[vpn] = value | (pte & 0xff);
return value | offset;
}
}
}
switch(type) {
case access_type::FETCH:
hart_if.raise_trap(12, 0, addr);
throw arch::trap_instruction_page_fault(addr);
case access_type::READ:
hart_if.raise_trap(13, 0, addr);
throw arch::trap_load_page_fault(addr);
case access_type::WRITE:
hart_if.raise_trap(15, 0, addr);
throw arch::trap_store_page_fault(addr);
default:
abort();
}
}
template <typename WORD_TYPE> inline void mmu<WORD_TYPE>::update_vm_info() {
vmt[1] = decode_vm_info(hart_if.PRIV, satp);
addr_mode[3] = addr_mode[2] = vmt[1].is_active() ? iss::address_type::VIRTUAL : iss::address_type::PHYSICAL;
if(hart_if.state.mstatus.MPRV)
vmt[0] = decode_vm_info(hart_if.state.mstatus.MPP, satp);
else
vmt[0] = vmt[1];
addr_mode[1] = addr_mode[0] = vmt[0].is_active() ? iss::address_type::VIRTUAL : iss::address_type::PHYSICAL;
ptw.clear();
}
} // namespace mem
} // namespace iss
+39 -7
View File
@@ -1,11 +1,44 @@
/*******************************************************************************
* Copyright (C) 2025 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* eyck@minres.com - initial implementation
******************************************************************************/
#include "memory_if.h"
#include "iss/arch/riscv_hart_common.h" #include "iss/arch/riscv_hart_common.h"
#include "iss/vm_types.h" #include "iss/vm_types.h"
#include "memory_if.h"
#include <util/logging.h> #include <util/logging.h>
namespace iss { namespace iss {
namespace mmio { namespace mem {
struct clic_config { struct clic_config {
uint64_t clic_base{0xc0000000}; uint64_t clic_base{0xc0000000};
unsigned clic_int_ctl_bits{4}; unsigned clic_int_ctl_bits{4};
@@ -61,9 +94,8 @@ template <typename WORD_TYPE> struct pmp : public memory_elem {
using reg_t = WORD_TYPE; using reg_t = WORD_TYPE;
constexpr static unsigned WORD_LEN = sizeof(WORD_TYPE) * 8; constexpr static unsigned WORD_LEN = sizeof(WORD_TYPE) * 8;
pmp(arch::priv_if<WORD_TYPE> hart_if, clic_config cfg) pmp(arch::priv_if<WORD_TYPE> hart_if)
: hart_if(hart_if) : hart_if(hart_if) {
, cfg(cfg) {
for(size_t i = arch::pmpaddr0; i <= arch::pmpaddr15; ++i) { for(size_t i = arch::pmpaddr0; i <= arch::pmpaddr15; ++i) {
hart_if.csr_rd_cb[i] = MK_CSR_RD_CB(read_plain); hart_if.csr_rd_cb[i] = MK_CSR_RD_CB(read_plain);
hart_if.csr_wr_cb[i] = MK_CSR_WR_CB(write_plain); hart_if.csr_wr_cb[i] = MK_CSR_WR_CB(write_plain);
@@ -74,7 +106,7 @@ template <typename WORD_TYPE> struct pmp : public memory_elem {
} }
} }
~pmp() = default; virtual ~pmp() = default;
memory_if get_mem_if() override { memory_if get_mem_if() override {
return memory_if{.rd_mem{util::delegate<rd_mem_func_sig>::from<this_class, &this_class::read_mem>(this)}, return memory_if{.rd_mem{util::delegate<rd_mem_func_sig>::from<this_class, &this_class::read_mem>(this)},
@@ -208,5 +240,5 @@ template <typename WORD_TYPE> bool pmp<WORD_TYPE>::pmp_check(const access_type t
return !any_active || hart_if.reg.PRIV == arch::PRIV_M; return !any_active || hart_if.reg.PRIV == arch::PRIV_M;
} }
} // namespace mmio } // namespace mem
} // namespace iss } // namespace iss
-26
View File
@@ -1,26 +0,0 @@
#include "memory_if.h"
namespace iss {
namespace mmio {
void memory_hierarchy::prepend(memory_elem& e) {
hierarchy.push_front(e);
update_chain();
}
void memory_hierarchy::append(memory_elem& e) {
hierarchy.push_back(e);
update_chain();
}
void memory_hierarchy::insert_before(memory_elem&) {}
void memory_hierarchy::insert_after(memory_elem&) {}
void memory_hierarchy::replace_last(memory_elem&) {}
void memory_hierarchy::update_chain() {
bool tail = false;
for(size_t i = 0; i < hierarchy.size(); ++i) {
hierarchy[i].get().register_csrs();
if(i)
hierarchy[i - 1].get().set_next(hierarchy[i].get().get_mem_if());
}
}
} // namespace mmio
} // namespace iss
-62
View File
@@ -1,62 +0,0 @@
#ifndef _MEMORY_WITH_HTIF_
#define _MEMORY_WITH_HTIF_
#include "iss/arch/riscv_hart_common.h"
#include "iss/vm_types.h"
#include "memory_if.h"
#include <util/logging.h>
#include <util/sparse_array.h>
namespace iss {
namespace mmio {
template <typename WORD_TYPE> struct memory_with_htif : public memory_elem {
using this_class = memory_with_htif<WORD_TYPE>;
constexpr static unsigned WORD_LEN = sizeof(WORD_TYPE) * 8;
memory_with_htif(arch::priv_if<WORD_TYPE> hart_if)
: hart_if(hart_if) {}
~memory_with_htif() = default;
memory_if get_mem_if() override {
return memory_if{.rd_mem{util::delegate<rd_mem_func_sig>::from<this_class, &this_class::read_mem>(this)},
.wr_mem{util::delegate<wr_mem_func_sig>::from<this_class, &this_class::write_mem>(this)}};
}
void set_next(memory_if) override {
// intenrionally left empty, leaf element
}
private:
iss::status read_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t* data) {
for(auto offs = 0U; offs < length; ++offs) {
*(data + offs) = mem[(addr + offs) % mem.size()];
}
return iss::Ok;
}
iss::status write_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t const* data) {
mem_type::page_type& p = mem(addr / mem.page_size);
std::copy(data, data + length, p.data() + (addr & mem.page_addr_mask));
// this->tohost handling in case of riscv-test
// according to https://github.com/riscv-software-src/riscv-isa-sim/issues/364#issuecomment-607657754:
if(access && iss::access_type::FUNC) {
if(addr == hart_if.tohost) {
return hart_if.exec_htif(data);
}
if((WORD_LEN == 32 && addr == hart_if.fromhost + 4) || (WORD_LEN == 64 && addr == hart_if.fromhost)) {
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (hart_if.fromhost & mem.page_addr_mask));
*reinterpret_cast<uint64_t*>(p.data() + (hart_if.tohost & mem.page_addr_mask)) = fhostvar;
}
}
return iss::Ok;
}
protected:
using mem_type = util::sparse_array<uint8_t, 1ULL << 32>;
mem_type mem;
arch::priv_if<WORD_TYPE> hart_if;
};
} // namespace mmio
} // namespace iss
#endif // _MEMORY_WITH_HTIF_
+35 -1
View File
@@ -1,3 +1,37 @@
/*******************************************************************************
* Copyright (C) 2025 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* eyck@minres.com - initial implementation
******************************************************************************/
#include "semihosting.h" #include "semihosting.h"
#include <chrono> #include <chrono>
#include <cstdint> #include <cstdint>
@@ -216,7 +250,7 @@ template <typename T> void semihosting_callback<T>::operator()(iss::arch_if* arc
T cmd_addr = sh_read_field<T>(arch_if_ptr, *parameter); T cmd_addr = sh_read_field<T>(arch_if_ptr, *parameter);
T cmd_len = sh_read_field<T>(arch_if_ptr, (*parameter) + 1); T cmd_len = sh_read_field<T>(arch_if_ptr, (*parameter) + 1);
std::string cmd = sh_read_string<T>(arch_if_ptr, cmd_addr, cmd_len); std::string cmd = sh_read_string<T>(arch_if_ptr, cmd_addr, cmd_len);
system(cmd.c_str()); auto val = system(cmd.c_str());
break; break;
} }
case semihosting_syscalls::SYS_TICKFREQ: { case semihosting_syscalls::SYS_TICKFREQ: {
+34
View File
@@ -1,3 +1,37 @@
/*******************************************************************************
* Copyright (C) 2025 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* eyck@minres.com - initial implementation
******************************************************************************/
#ifndef _SEMIHOSTING_H_ #ifndef _SEMIHOSTING_H_
#define _SEMIHOSTING_H_ #define _SEMIHOSTING_H_
#include <chrono> #include <chrono>
+2
View File
@@ -40,6 +40,7 @@
#include <vector> #include <vector>
#include "iss/arch/tgc_mapper.h" #include "iss/arch/tgc_mapper.h"
#include "util/logging.h"
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#ifdef WITH_LLVM #ifdef WITH_LLVM
@@ -258,6 +259,7 @@ int main(int argc, char* argv[]) {
LOG(ERR) << "Error opening file " << filename << std::endl; LOG(ERR) << "Error opening file " << filename << std::endl;
return 1; return 1;
} }
LOGGER(DEFAULT)::reporting_level() = logging::ERR;
for(auto addr = start_addr; addr < end_addr; addr += data.size()) { 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(), 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 data.data()); // FIXME: get space from iss::arch::traits<ARCH>::mem_type_e::MEM
+18 -13
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (C) 2017, 2018 MINRES Technologies GmbH * Copyright (C) 2017 - 2025 MINRES Technologies GmbH
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -45,11 +45,10 @@
#include <scc/report.h> #include <scc/report.h>
#include <util/ities.h> #include <util/ities.h>
#include <iostream> #include <iostream>
#include <sstream>
#include <array> #include <array>
#include <numeric>
#include <iss/plugin/cycle_estimate.h> #include <iss/plugin/cycle_estimate.h>
#include <iss/plugin/instruction_count.h> #include <iss/plugin/instruction_count.h>
#include <util/ities.h>
// clang-format on // clang-format on
@@ -267,7 +266,10 @@ template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::before_end_of_elab
cpu = new core_wrapper(this); cpu = new core_wrapper(this);
cpu->create_cpu(GET_PROP_VALUE(core_type), GET_PROP_VALUE(backend), GET_PROP_VALUE(gdb_server_port), GET_PROP_VALUE(mhartid)); cpu->create_cpu(GET_PROP_VALUE(core_type), GET_PROP_VALUE(backend), GET_PROP_VALUE(gdb_server_port), GET_PROP_VALUE(mhartid));
sc_assert(cpu->vm != nullptr); sc_assert(cpu->vm != nullptr);
cpu->vm->setDisassEnabled(GET_PROP_VALUE(enable_disass) || trc->m_db != nullptr); auto disass = GET_PROP_VALUE(enable_disass);
if(disass && trc->m_db)
SCCINFO(SCMOD) << "Disasssembly will only be in transaction trace database!";
cpu->vm->setDisassEnabled(disass || trc->m_db != nullptr);
if(GET_PROP_VALUE(plugins).length()) { if(GET_PROP_VALUE(plugins).length()) {
auto p = util::split(GET_PROP_VALUE(plugins), ';'); auto p = util::split(GET_PROP_VALUE(plugins), ';');
for(std::string const& opt_val : p) { for(std::string const& opt_val : p) {
@@ -305,17 +307,20 @@ template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::before_end_of_elab
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::start_of_simulation() { template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::start_of_simulation() {
// quantum_keeper.reset(); // quantum_keeper.reset();
if(GET_PROP_VALUE(elf_file).size() > 0) { if(GET_PROP_VALUE(elf_file).size() > 0) {
istringstream is(GET_PROP_VALUE(elf_file)); auto file_names = util::split(GET_PROP_VALUE(elf_file), ',');
string s; for(auto& s : file_names) {
while(getline(is, s, ',')) { std::pair<uint64_t, bool> load_result = cpu->load_file(s);
std::pair<uint64_t, bool> start_addr = cpu->load_file(s); if(!std::get<1>(load_result)) {
SCCWARN(SCMOD) << "Could not load FW file " << s;
} else {
#ifndef CWR_SYSTEMC #ifndef CWR_SYSTEMC
if(reset_address.is_default_value() && start_addr.second == true) if(reset_address.is_default_value())
reset_address.set_value(start_addr.first); reset_address.set_value(load_result.first);
#else #else
if(start_addr.second == true) if(start_addr.second == true)
reset_address = start_addr.first; reset_address = start_addr.first;
#endif #endif
}
} }
} }
if(trc->m_db != nullptr && trc->stream_handle == nullptr) { if(trc->m_db != nullptr && trc->stream_handle == nullptr) {
@@ -419,7 +424,7 @@ template <unsigned int BUSWIDTH> bool core_complex<BUSWIDTH>::read_mem(uint64_t
gp.set_extension(preExt); gp.set_extension(preExt);
} }
auto pre_delay = delay; auto pre_delay = delay;
dbus->b_transport(gp, delay); sckt->b_transport(gp, delay);
if(pre_delay > delay) { if(pre_delay > delay) {
quantum_keeper.reset(); quantum_keeper.reset();
} else { } else {
+1 -1
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (C) 2017-2021 MINRES Technologies GmbH * Copyright (C) 2017 - 2025 MINRES Technologies GmbH
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
+64 -40
View File
@@ -1,9 +1,36 @@
/* /*******************************************************************************
* sc_core_adapter.h * Copyright (C) 2023 - 2025 MINRES Technologies GmbH
* All rights reserved.
* *
* Created on: Jul 5, 2023 * Redistribution and use in source and binary forms, with or without
* Author: eyck * modification, are permitted provided that the following conditions are met:
*/ *
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* eyck@minres.com - initial implementation
******************************************************************************/
#ifndef _SYSC_SC_CORE_ADAPTER_H_ #ifndef _SYSC_SC_CORE_ADAPTER_H_
#define _SYSC_SC_CORE_ADAPTER_H_ #define _SYSC_SC_CORE_ADAPTER_H_
@@ -11,6 +38,7 @@
#include "sc_core_adapter_if.h" #include "sc_core_adapter_if.h"
#include <iostream> #include <iostream>
#include <iss/iss.h> #include <iss/iss.h>
#include <iss/mem/memory_if.h>
#include <iss/vm_types.h> #include <iss/vm_types.h>
#include <scc/report.h> #include <scc/report.h>
#include <util/ities.h> #include <util/ities.h>
@@ -18,11 +46,16 @@
namespace sysc { namespace sysc {
template <typename PLAT> class sc_core_adapter : public PLAT, public sc_core_adapter_if { template <typename PLAT> class sc_core_adapter : public PLAT, public sc_core_adapter_if {
public: public:
using this_class = sc_core_adapter<PLAT>;
using reg_t = typename iss::arch::traits<typename PLAT::core>::reg_t; using reg_t = typename iss::arch::traits<typename PLAT::core>::reg_t;
using phys_addr_t = typename iss::arch::traits<typename PLAT::core>::phys_addr_t; using phys_addr_t = typename iss::arch::traits<typename PLAT::core>::phys_addr_t;
using heart_state_t = typename PLAT::hart_state_type;
sc_core_adapter(sysc::tgfs::core_complex_if* owner) sc_core_adapter(sysc::tgfs::core_complex_if* owner)
: owner(owner) {} : owner(owner) {
this->csr_rd_cb[iss::arch::time] = MK_CSR_RD_CB(read_time);
if(sizeof(reg_t) == 4)
this->csr_rd_cb[iss::arch::timeh] = MK_CSR_RD_CB(read_time);
this->memories.replace_last(*this);
}
iss::arch_if* get_arch_if() override { return this; } iss::arch_if* get_arch_if() override { return this; }
@@ -60,18 +93,23 @@ public:
} }
}; };
iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t* const data) override { iss::mem::memory_if get_mem_if() override {
if(addr.access && iss::access_type::DEBUG) return iss::mem::memory_if{.rd_mem{util::delegate<iss::mem::rd_mem_func_sig>::from<this_class, &this_class::read_mem>(this)},
return owner->read_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err; .wr_mem{util::delegate<iss::mem::wr_mem_func_sig>::from<this_class, &this_class::write_mem>(this)}};
}
iss::status read_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t* data) {
if(access && iss::access_type::DEBUG)
return owner->read_mem_dbg(addr, length, data) ? iss::Ok : iss::Err;
else { else {
return owner->read_mem(addr.val, length, data, is_fetch(addr.access)) ? iss::Ok : iss::Err; return owner->read_mem(addr, length, data, is_fetch(access)) ? iss::Ok : iss::Err;
} }
} }
iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t* const data) override { iss::status write_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t const* data) {
if(addr.access && iss::access_type::DEBUG) if(access && iss::access_type::DEBUG)
return owner->write_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err; return owner->write_mem_dbg(addr, length, data) ? iss::Ok : iss::Err;
if(addr.val == this->tohost) { if(addr == this->tohost) {
reg_t cur_data = *reinterpret_cast<const reg_t*>(data); reg_t cur_data = *reinterpret_cast<const reg_t*>(data);
// Extract Device (bits 63:56) // Extract Device (bits 63:56)
uint8_t device = sizeof(reg_t) == 4 ? 0 : (cur_data >> 56) & 0xFF; uint8_t device = sizeof(reg_t) == 4 ? 0 : (cur_data >> 56) & 0xFF;
@@ -89,9 +127,6 @@ public:
} }
this->reg.trap_state = std::numeric_limits<uint32_t>::max(); this->reg.trap_state = std::numeric_limits<uint32_t>::max();
this->interrupt_sim = payload_addr; this->interrupt_sim = payload_addr;
#ifndef WITH_TCC
throw(iss::simulation_stopped(payload_addr));
#endif
return iss::Ok; return iss::Ok;
} }
if(device == 0 && command == 0) { if(device == 0 && command == 0) {
@@ -117,39 +152,28 @@ public:
this->interrupt_sim = payload_addr; this->interrupt_sim = payload_addr;
return iss::Ok; return iss::Ok;
} }
auto res = owner->write_mem(addr.val, length, data) ? iss::Ok : iss::Err; auto res = owner->write_mem(addr, length, data) ? iss::Ok : iss::Err;
// clear MTIP on mtimecmp write
if(addr.val == 0x2004000) {
reg_t val;
this->read_csr(iss::arch::mip, val);
if(val & (1ULL << 7))
this->write_csr(iss::arch::mip, val & ~(1ULL << 7));
}
return res; return res;
} }
iss::status read_csr(unsigned addr, reg_t& val) override { iss::status read_time(unsigned addr, reg_t& val) {
if((addr == iss::arch::time || addr == iss::arch::timeh)) { uint64_t time_val = owner->mtime_i.get_interface() ? owner->mtime_i.read() : 0;
uint64_t time_val = owner->mtime_i.get_interface() ? owner->mtime_i.read() : 0; if(addr == iss::arch::time) {
if(addr == iss::arch::time) { val = static_cast<reg_t>(time_val);
val = static_cast<reg_t>(time_val); } else if(addr == iss::arch::timeh) {
} else if(addr == iss::arch::timeh) { if(sizeof(reg_t) != 4)
if(sizeof(reg_t) != 4) return iss::Err;
return iss::Err; val = static_cast<reg_t>(time_val >> 32);
val = static_cast<reg_t>(time_val >> 32);
}
return iss::Ok;
} else {
return PLAT::read_csr(addr, val);
} }
return iss::Ok;
} }
void wait_until(uint64_t flags) override { void wait_until(uint64_t flags) override {
SCCDEBUG(owner->hier_name()) << "Sleeping until interrupt"; SCCDEBUG(owner->hier_name()) << "Sleeping until interrupt";
PLAT::wait_until(flags);
while(this->reg.pending_trap == 0 && (this->csr[iss::arch::mip] & this->csr[iss::arch::mie]) == 0) { while(this->reg.pending_trap == 0 && (this->csr[iss::arch::mip] & this->csr[iss::arch::mie]) == 0) {
sc_core::wait(wfi_evt); sc_core::wait(wfi_evt);
} }
PLAT::wait_until(flags);
} }
void local_irq(short id, bool value) override { void local_irq(short id, bool value) override {
+32 -5
View File
@@ -1,9 +1,36 @@
/* /*******************************************************************************
* sc_core_adapter.h * Copyright (C) 2023 MINRES Technologies GmbH
* All rights reserved.
* *
* Created on: Jul 5, 2023 * Redistribution and use in source and binary forms, with or without
* Author: eyck * modification, are permitted provided that the following conditions are met:
*/ *
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* eyck@minres.com - initial implementation
******************************************************************************/
#ifndef _SYSC_SC_CORE_ADAPTER_IF_H_ #ifndef _SYSC_SC_CORE_ADAPTER_IF_H_
#define _SYSC_SC_CORE_ADAPTER_IF_H_ #define _SYSC_SC_CORE_ADAPTER_IF_H_
+70
View File
@@ -0,0 +1,70 @@
////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2025, MINRES Technologies GmbH
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Contributors:
// ales@minres.com - initial API and implementation
////////////////////////////////////////////////////////////////////////////////
#ifndef _VM_AES_SBOX_H_
#define _VM_AES_SBOX_H_
#include <cstdint>
extern "C" {
const uint8_t AES_ENC_SBOX[] = {
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59,
0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1,
0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83,
0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C,
0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC,
0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE,
0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6,
0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9,
0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1,
0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16};
uint8_t inline aes_sbox_fwd(uint8_t index) { return AES_ENC_SBOX[index]; }
const uint8_t AES_DEC_SBOX[] = {
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F,
0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B,
0x42, 0xFA, 0xC3, 0x4E, 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8,
0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3,
0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41,
0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9,
0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07,
0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F,
0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2B,
0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D};
uint8_t inline aes_sbox_inv(uint8_t index) { return AES_DEC_SBOX[index]; }
}
#endif /* _VM_AES_SBOX_H_ */
+133 -204
View File
File diff suppressed because it is too large. Load diff
+617 -126
View File
@@ -33,7 +33,9 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#include "fp_functions.h" #include "fp_functions.h"
#include "softfloat_types.h"
#include <array> #include <array>
#include <cstdint>
extern "C" { extern "C" {
#include "internals.h" #include "internals.h"
@@ -44,21 +46,375 @@ extern "C" {
#include <limits> #include <limits>
using this_t = uint8_t*; using this_t = uint8_t*;
// this does not inlcude any reserved rm or the DYN rm, as DYN rm should be taken care of in the vm_impl template <typename T> T constexpr defaultNaN();
const std::array<uint8_t, 5> rmm_map = { template <> uint16_t constexpr defaultNaN<uint16_t>() { return defaultNaNF16UI; }
softfloat_round_near_even /*RNE*/, softfloat_round_minMag /*RTZ*/, softfloat_round_min /*RDN*/, softfloat_round_max /*RUP?*/, template <> uint32_t constexpr defaultNaN<uint32_t>() { return defaultNaNF32UI; }
softfloat_round_near_maxMag /*RMM*/ template <> uint64_t constexpr defaultNaN<uint64_t>() { return defaultNaNF64UI; }
}; template <typename T> T constexpr posInf();
template <> uint16_t constexpr posInf<uint16_t>() { return 0x7C00; }
template <> uint32_t constexpr posInf<uint32_t>() { return 0x7F800000; }
template <> uint64_t constexpr posInf<uint64_t>() { return 0x7FF0000000000000; }
template <typename T> T constexpr negInf();
template <> uint16_t constexpr negInf<uint16_t>() { return 0xFC00; }
template <> uint32_t constexpr negInf<uint32_t>() { return 0xFF800000; }
template <> uint64_t constexpr negInf<uint64_t>() { return 0xFFF0000000000000; }
template <typename T> T constexpr negZero();
template <> uint16_t constexpr negZero<uint16_t>() { return 0x8000; }
template <> uint32_t constexpr negZero<uint32_t>() { return 0x80000000; }
template <> uint64_t constexpr negZero<uint64_t>() { return 0x8000000000000000; }
const uint32_t quiet_nan32 = 0x7fC00000; template <typename T> bool rsqrt_check(T fclass_val, bool& subnormal, T& ret_val) {
softfloat_exceptionFlags = 0;
switch(fclass_val) {
case 0x0001: {
softfloat_exceptionFlags |= softfloat_flag_invalid;
ret_val = defaultNaN<T>();
return true;
}
case 0x0002: {
softfloat_exceptionFlags |= softfloat_flag_invalid;
ret_val = defaultNaN<T>();
return true;
}
case 0x0004: {
softfloat_exceptionFlags |= softfloat_flag_invalid;
ret_val = defaultNaN<T>();
return true;
}
case 0x0100: {
softfloat_exceptionFlags |= softfloat_flag_invalid;
ret_val = defaultNaN<T>();
return true;
}
case 0x0200: {
ret_val = defaultNaN<T>();
return true;
}
case 0x0008: {
softfloat_exceptionFlags |= softfloat_flag_infinite;
ret_val = negInf<T>();
return true;
}
case 0x0010: {
softfloat_exceptionFlags |= softfloat_flag_infinite;
ret_val = posInf<T>();
return true;
}
case 0x0080: {
ret_val = 0;
return true;
}
case 0x0020: {
subnormal = true;
}
default:
return false;
}
}
static constexpr std::array<std::array<uint64_t, 64>, 2> rsqrt_table{
{{
52, 51, 50, 48, 47, 46, 44, 43, 42, 41, 40, 39, 38, 36, 35, 34, 33, 32, 31, 30, 30, 29, 28, 27, 26, 25, 24, 23, 23, 22, 21, 20,
19, 19, 18, 17, 16, 16, 15, 14, 14, 13, 12, 12, 11, 10, 10, 9, 9, 8, 7, 7, 6, 6, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0,
},
{127, 125, 123, 121, 119, 118, 116, 114, 113, 111, 109, 108, 106, 105, 103, 102, 100, 99, 97, 96, 95, 93,
92, 91, 90, 88, 87, 86, 85, 84, 83, 82, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 70,
69, 68, 67, 66, 65, 64, 63, 63, 62, 61, 60, 59, 59, 58, 57, 56, 56, 55, 54, 53}}};
uint64_t constexpr frsqrt7_general(const unsigned s, const unsigned e, const uint64_t sign, const int64_t exp, const uint64_t sig,
const bool subnormal) {
int64_t normalized_exp = exp;
uint64_t normalized_sig = sig;
if(subnormal) {
signed nr_leadingzeros = __builtin_clzll(sig) - (64 - s);
normalized_exp = -nr_leadingzeros;
normalized_sig = (sig << (1 + nr_leadingzeros)) & ((1ULL << s) - 1);
}
unsigned exp_idx = normalized_exp & 1;
unsigned sig_idx = (normalized_sig >> (s - 6)) & 0x3f;
// The output of the table becomes the seven high bits of the result significand (after the leading one); the remainder of the
// result significand is zero.
uint64_t out_sig = rsqrt_table[exp_idx][sig_idx] << (s - 7);
// The output exponent equals floor((3*B - 1 - the normalized input exponent) / 2), where B is the exponent bias.
unsigned bias = (1UL << (e - 1)) - 1;
uint64_t out_exp = (3 * bias - 1 - normalized_exp) / 2;
// The output sign equals the input sign.
return (sign << (s + e)) | (out_exp << s) | out_sig;
}
template <typename T> bool recip_check(T fclass_val, bool& subnormal, uint64_t& ret_val) {
softfloat_exceptionFlags = 0;
switch(fclass_val) {
case 0x0001: {
ret_val = negZero<T>();
return true;
}
case 0x0080: {
ret_val = 0;
return true;
}
case 0x0008: {
softfloat_exceptionFlags |= softfloat_flag_infinite;
ret_val = negInf<T>();
return true;
}
case 0x0010: {
softfloat_exceptionFlags |= softfloat_flag_infinite;
ret_val = posInf<T>();
return true;
}
case 0x0100: {
softfloat_exceptionFlags |= softfloat_flag_invalid;
ret_val = defaultNaN<T>();
return true;
}
case 0x0200: {
ret_val = defaultNaN<T>();
return true;
}
case 0x0004: {
subnormal = true;
return false;
}
case 0x0020: {
subnormal = true;
return false;
}
default: {
subnormal = false;
return false;
}
}
}
static constexpr std::array<uint64_t, 128> rec_table{
{127, 125, 123, 121, 119, 117, 116, 114, 112, 110, 109, 107, 105, 104, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85,
84, 83, 81, 80, 79, 77, 76, 75, 74, 72, 71, 70, 69, 68, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55,
54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 40, 39, 38, 37, 36, 35, 35, 34, 33, 32, 31,
31, 30, 29, 28, 28, 27, 26, 25, 25, 24, 23, 23, 22, 21, 21, 20, 19, 19, 18, 17, 17, 16, 15, 15, 14, 14,
13, 12, 12, 11, 11, 10, 9, 9, 8, 8, 7, 7, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0}};
bool frec_general(uint64_t& res, const unsigned s, const unsigned e, const uint64_t sign, const int64_t exp, const uint64_t sig,
const bool subnormal, uint8_t mode) {
int nr_leadingzeros = __builtin_clzll(sig) - (64 - s);
int64_t normalized_exp = subnormal ? -nr_leadingzeros : exp;
uint64_t normalized_sig = subnormal ? ((sig << (1 + nr_leadingzeros)) & ((1ULL << s) - 1)) : sig;
unsigned idx = (normalized_sig >> (s - 7)) & 0x7f;
unsigned bias = (1UL << (e - 1)) - 1;
uint64_t mid_exp = 2 * (bias)-1 - normalized_exp;
uint64_t mid_sig = rec_table[idx] << (s - 7);
uint64_t out_exp = mid_exp;
uint64_t out_sig = mid_sig;
if(mid_exp == 0) {
out_exp = mid_exp;
out_sig = (mid_sig >> 1) | (1ULL << (s - 1));
} else if(mid_exp == (1ULL << e) - 1) {
out_exp = 0;
out_sig = (mid_sig >> 2) | (1ULL << (s - 2));
}
if(subnormal && nr_leadingzeros > 1) {
if((mode == 0b001) || (mode == 0b010 && sign == 0b0) || (mode == 0b011 && sign == 0b1)) {
res = (sign << (s + e)) | ((1ULL << (e - 1)) - 1) << s | ((1ULL << s) - 1);
return true;
} else {
res = (sign << (s + e)) | ((1ULL << e) - 1) << s;
return true;
}
}
res = (sign << (s + e)) | (out_exp << s) | out_sig;
return false;
}
extern "C" { extern "C" {
uint32_t fget_flags() { return softfloat_exceptionFlags & 0x1f; } uint32_t fget_flags() { return softfloat_exceptionFlags & 0x1f; }
uint16_t fadd_h(uint16_t v1, uint16_t v2, uint8_t mode) {
float16_t v1f{v1}, v2f{v2};
softfloat_roundingMode = mode;
softfloat_exceptionFlags = 0;
float16_t r = f16_add(v1f, v2f);
return r.v;
}
uint16_t fsub_h(uint16_t v1, uint16_t v2, uint8_t mode) {
float16_t v1f{v1}, v2f{v2};
softfloat_roundingMode = mode;
softfloat_exceptionFlags = 0;
float16_t r = f16_sub(v1f, v2f);
return r.v;
}
uint16_t fmul_h(uint16_t v1, uint16_t v2, uint8_t mode) {
float16_t v1f{v1}, v2f{v2};
softfloat_roundingMode = mode;
softfloat_exceptionFlags = 0;
float16_t r = f16_mul(v1f, v2f);
return r.v;
}
uint16_t fdiv_h(uint16_t v1, uint16_t v2, uint8_t mode) {
float16_t v1f{v1}, v2f{v2};
softfloat_roundingMode = mode;
softfloat_exceptionFlags = 0;
float16_t r = f16_div(v1f, v2f);
return r.v;
}
uint16_t fsqrt_h(uint16_t v1, uint8_t mode) {
float16_t v1f{v1};
softfloat_roundingMode = mode;
softfloat_exceptionFlags = 0;
float16_t r = f16_sqrt(v1f);
return r.v;
}
uint16_t fcmp_h(uint16_t v1, uint16_t v2, uint16_t op) {
float16_t v1f{v1}, v2f{v2};
softfloat_exceptionFlags = 0;
bool nan = v1 == defaultNaNF16UI || v2 & defaultNaNF16UI;
bool snan = softfloat_isSigNaNF16UI(v1) || softfloat_isSigNaNF16UI(v2);
switch(op) {
case 0:
if(nan | snan) {
if(snan)
softfloat_raiseFlags(softfloat_flag_invalid);
return 0;
} else
return f16_eq(v1f, v2f) ? 1 : 0;
case 1:
if(nan | snan) {
softfloat_raiseFlags(softfloat_flag_invalid);
return 0;
} else
return f16_le(v1f, v2f) ? 1 : 0;
case 2:
if(nan | snan) {
softfloat_raiseFlags(softfloat_flag_invalid);
return 0;
} else
return f16_lt(v1f, v2f) ? 1 : 0;
default:
break;
}
return -1;
}
uint16_t fmadd_h(uint16_t v1, uint16_t v2, uint16_t v3, uint16_t op, uint8_t mode) {
uint16_t F16_SIGN = 1UL << 15;
switch(op) {
case 0: // FMADD_S
break;
case 1: // FMSUB_S
v3 ^= F16_SIGN;
break;
case 2: // FNMADD_S
v1 ^= F16_SIGN;
v3 ^= F16_SIGN;
break;
case 3: // FNMSUB_S
v1 ^= F16_SIGN;
break;
}
softfloat_roundingMode = mode;
softfloat_exceptionFlags = 0;
float16_t res = softfloat_mulAddF16(v1, v2, v3, 0);
return res.v;
}
uint16_t fsel_h(uint16_t v1, uint16_t v2, uint16_t op) {
softfloat_exceptionFlags = 0;
bool v1_nan = (v1 & defaultNaNF16UI) == defaultNaNF16UI;
bool v2_nan = (v2 & defaultNaNF16UI) == defaultNaNF16UI;
bool v1_snan = softfloat_isSigNaNF16UI(v1);
bool v2_snan = softfloat_isSigNaNF16UI(v2);
if(v1_snan || v2_snan)
softfloat_raiseFlags(softfloat_flag_invalid);
if(v1_nan || v1_snan)
return (v2_nan || v2_snan) ? defaultNaNF16UI : v2;
else if(v2_nan || v2_snan)
return v1;
else {
if((v1 & 0x7fff) == 0 && (v2 & 0x7fff) == 0) {
return op == 0 ? ((v1 & 0x8000) ? v1 : v2) : ((v1 & 0x8000) ? v2 : v1);
} else {
float16_t v1f{v1}, v2f{v2};
return op == 0 ? (f16_lt(v1f, v2f) ? v1 : v2) : (f16_lt(v1f, v2f) ? v2 : v1);
}
}
}
uint16_t fclass_h(uint16_t v1) {
float16_t a{v1};
union ui16_f16 uA;
uint_fast16_t uiA;
uA.f = a;
uiA = uA.ui;
bool infOrNaN = expF16UI(uiA) == 0x1F;
bool subnormalOrZero = expF16UI(uiA) == 0;
bool sign = signF16UI(uiA);
bool fracZero = fracF16UI(uiA) == 0;
bool isNaN = isNaNF16UI(uiA);
bool isSNaN = softfloat_isSigNaNF16UI(uiA);
return (sign && infOrNaN && fracZero) << 0 | (sign && !infOrNaN && !subnormalOrZero) << 1 |
(sign && subnormalOrZero && !fracZero) << 2 | (sign && subnormalOrZero && fracZero) << 3 | (!sign && infOrNaN && fracZero) << 7 |
(!sign && !infOrNaN && !subnormalOrZero) << 6 | (!sign && subnormalOrZero && !fracZero) << 5 |
(!sign && subnormalOrZero && fracZero) << 4 | (isNaN && isSNaN) << 8 | (isNaN && !isSNaN) << 9;
}
uint16_t frsqrt7_h(uint16_t v) {
bool subnormal = false;
uint16_t ret_val = 0;
if(rsqrt_check(fclass_h(v), subnormal, ret_val)) {
return ret_val;
}
uint16_t sig = fracF64UI(v);
int16_t exp = expF64UI(v);
uint16_t sign = signF64UI(v);
unsigned constexpr e = 5;
unsigned constexpr s = 10;
return frsqrt7_general(s, e, sign, exp, sig, subnormal);
}
uint16_t frec7_h(uint16_t v, uint8_t mode) {
bool subnormal = false;
uint64_t ret_val = 0;
if(recip_check(fclass_h(v), subnormal, ret_val)) {
return ret_val;
}
uint16_t sig = fracF16UI(v);
int exp = expF16UI(v);
uint16_t sign = signF16UI(v);
unsigned constexpr e = 5;
unsigned constexpr s = 10;
if(frec_general(ret_val, s, e, sign, exp, sig, subnormal, mode))
softfloat_exceptionFlags |= (softfloat_flag_inexact | softfloat_flag_overflow);
return ret_val;
}
uint16_t unbox_h(uint8_t FLEN, uint64_t v) {
uint64_t mask = 0;
switch(FLEN) {
case 32: {
mask = std::numeric_limits<uint32_t>::max() & ~((uint64_t)std::numeric_limits<uint16_t>::max());
break;
}
case 64: {
mask = std::numeric_limits<uint64_t>::max() & ~((uint64_t)std::numeric_limits<uint16_t>::max());
break;
}
default:
break;
}
if((v & mask) != mask)
return defaultNaNF16UI;
else
return v & std::numeric_limits<uint32_t>::max();
}
uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode) { uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode) {
float32_t v1f{v1}, v2f{v2}; float32_t v1f{v1}, v2f{v2};
softfloat_roundingMode = rmm_map.at(mode); softfloat_roundingMode = mode;
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float32_t r = f32_add(v1f, v2f); float32_t r = f32_add(v1f, v2f);
return r.v; return r.v;
@@ -66,7 +422,7 @@ uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode) {
uint32_t fsub_s(uint32_t v1, uint32_t v2, uint8_t mode) { uint32_t fsub_s(uint32_t v1, uint32_t v2, uint8_t mode) {
float32_t v1f{v1}, v2f{v2}; float32_t v1f{v1}, v2f{v2};
softfloat_roundingMode = rmm_map.at(mode); softfloat_roundingMode = mode;
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float32_t r = f32_sub(v1f, v2f); float32_t r = f32_sub(v1f, v2f);
return r.v; return r.v;
@@ -74,7 +430,7 @@ uint32_t fsub_s(uint32_t v1, uint32_t v2, uint8_t mode) {
uint32_t fmul_s(uint32_t v1, uint32_t v2, uint8_t mode) { uint32_t fmul_s(uint32_t v1, uint32_t v2, uint8_t mode) {
float32_t v1f{v1}, v2f{v2}; float32_t v1f{v1}, v2f{v2};
softfloat_roundingMode = rmm_map.at(mode); softfloat_roundingMode = mode;
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float32_t r = f32_mul(v1f, v2f); float32_t r = f32_mul(v1f, v2f);
return r.v; return r.v;
@@ -82,7 +438,7 @@ uint32_t fmul_s(uint32_t v1, uint32_t v2, uint8_t mode) {
uint32_t fdiv_s(uint32_t v1, uint32_t v2, uint8_t mode) { uint32_t fdiv_s(uint32_t v1, uint32_t v2, uint8_t mode) {
float32_t v1f{v1}, v2f{v2}; float32_t v1f{v1}, v2f{v2};
softfloat_roundingMode = rmm_map.at(mode); softfloat_roundingMode = mode;
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float32_t r = f32_div(v1f, v2f); float32_t r = f32_div(v1f, v2f);
return r.v; return r.v;
@@ -90,7 +446,7 @@ uint32_t fdiv_s(uint32_t v1, uint32_t v2, uint8_t mode) {
uint32_t fsqrt_s(uint32_t v1, uint8_t mode) { uint32_t fsqrt_s(uint32_t v1, uint8_t mode) {
float32_t v1f{v1}; float32_t v1f{v1};
softfloat_roundingMode = rmm_map.at(mode); softfloat_roundingMode = mode;
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float32_t r = f32_sqrt(v1f); float32_t r = f32_sqrt(v1f);
return r.v; return r.v;
@@ -99,7 +455,7 @@ uint32_t fsqrt_s(uint32_t v1, uint8_t mode) {
uint32_t fcmp_s(uint32_t v1, uint32_t v2, uint32_t op) { uint32_t fcmp_s(uint32_t v1, uint32_t v2, uint32_t op) {
float32_t v1f{v1}, v2f{v2}; float32_t v1f{v1}, v2f{v2};
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
bool nan = (v1 & defaultNaNF32UI) == quiet_nan32 || (v2 & defaultNaNF32UI) == quiet_nan32; bool nan = v1 == defaultNaNF32UI || v2 == defaultNaNF32UI;
bool snan = softfloat_isSigNaNF32UI(v1) || softfloat_isSigNaNF32UI(v2); bool snan = softfloat_isSigNaNF32UI(v1) || softfloat_isSigNaNF32UI(v2);
switch(op) { switch(op) {
case 0: case 0:
@@ -127,29 +483,6 @@ uint32_t fcmp_s(uint32_t v1, uint32_t v2, uint32_t op) {
return -1; return -1;
} }
uint32_t fcvt_s(uint32_t v1, uint32_t op, uint8_t mode) {
float32_t v1f{v1};
softfloat_exceptionFlags = 0;
float32_t r;
switch(op) {
case 0: { // FCVT__W__S
uint_fast32_t res = f32_to_i32(v1f, rmm_map.at(mode), true);
return (uint32_t)res;
}
case 1: { // FCVT__WU__S
uint_fast32_t res = f32_to_ui32(v1f, rmm_map.at(mode), true);
return (uint32_t)res;
}
case 2: // FCVT__S__W
r = i32_to_f32((int32_t)v1);
return r.v;
case 3: // FCVT__S__WU
r = ui32_to_f32(v1);
return r.v;
}
return 0;
}
uint32_t fmadd_s(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mode) { uint32_t fmadd_s(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mode) {
uint32_t F32_SIGN = 1UL << 31; uint32_t F32_SIGN = 1UL << 31;
switch(op) { switch(op) {
@@ -166,7 +499,7 @@ uint32_t fmadd_s(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mod
v1 ^= F32_SIGN; v1 ^= F32_SIGN;
break; break;
} }
softfloat_roundingMode = rmm_map.at(mode); softfloat_roundingMode = mode;
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float32_t res = softfloat_mulAddF32(v1, v2, v3, 0); float32_t res = softfloat_mulAddF32(v1, v2, v3, 0);
return res.v; return res.v;
@@ -216,37 +549,60 @@ uint32_t fclass_s(uint32_t v1) {
(!sign && subnormalOrZero && fracZero) << 4 | (isNaN && isSNaN) << 8 | (isNaN && !isSNaN) << 9; (!sign && subnormalOrZero && fracZero) << 4 | (isNaN && isSNaN) << 8 | (isNaN && !isSNaN) << 9;
} }
uint32_t fconv_d2f(uint64_t v1, uint8_t mode) { uint32_t frsqrt7_s(uint32_t v) {
bool isNan = isNaNF64UI(v1); bool subnormal = false;
bool isSNaN = softfloat_isSigNaNF64UI(v1); uint32_t ret_val = 0;
softfloat_roundingMode = rmm_map.at(mode); if(rsqrt_check(fclass_s(v), subnormal, ret_val)) {
softfloat_exceptionFlags = 0; return ret_val;
if(isNan) {
if(isSNaN)
softfloat_raiseFlags(softfloat_flag_invalid);
return defaultNaNF32UI;
} else {
float32_t res = f64_to_f32(float64_t{v1});
return res.v;
} }
uint32_t sig = fracF32UI(v);
int exp = expF32UI(v);
uint32_t sign = signF32UI(v);
unsigned constexpr e = 8;
unsigned constexpr s = 23;
return frsqrt7_general(s, e, sign, exp, sig, subnormal);
} }
uint64_t fconv_f2d(uint32_t v1, uint8_t mode) { uint32_t frec7_s(uint32_t v, uint8_t mode) {
bool infOrNaN = expF32UI(v1) == 0xFF; bool subnormal = false;
bool subnormalOrZero = expF32UI(v1) == 0; uint64_t ret_val = 0;
if(infOrNaN || subnormalOrZero) { if(recip_check(fclass_s(v), subnormal, ret_val)) {
return defaultNaNF64UI; return ret_val;
} else {
float64_t res = f32_to_f64(float32_t{v1});
return res.v;
} }
uint32_t sig = fracF32UI(v);
int exp = expF32UI(v);
uint32_t sign = signF32UI(v);
unsigned constexpr e = 8;
unsigned constexpr s = 23;
if(frec_general(ret_val, s, e, sign, exp, sig, subnormal, mode))
softfloat_exceptionFlags |= (softfloat_flag_inexact | softfloat_flag_overflow);
return ret_val;
}
uint32_t unbox_s(uint8_t FLEN, uint64_t v) {
uint64_t mask = 0;
switch(FLEN) {
case 32: {
return v;
}
case 64: {
mask = std::numeric_limits<uint64_t>::max() & ~((uint64_t)std::numeric_limits<uint32_t>::max());
break;
}
default:
break;
}
if((v & mask) != mask)
return defaultNaNF32UI;
else
return v & std::numeric_limits<uint32_t>::max();
} }
uint64_t fadd_d(uint64_t v1, uint64_t v2, uint8_t mode) { uint64_t fadd_d(uint64_t v1, uint64_t v2, uint8_t mode) {
bool nan = (v1 & defaultNaNF32UI) == quiet_nan32; bool nan = v1 == defaultNaNF32UI;
bool snan = softfloat_isSigNaNF32UI(v1); bool snan = softfloat_isSigNaNF32UI(v1);
float64_t v1f{v1}, v2f{v2}; float64_t v1f{v1}, v2f{v2};
softfloat_roundingMode = rmm_map.at(mode); softfloat_roundingMode = mode;
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float64_t r = f64_add(v1f, v2f); float64_t r = f64_add(v1f, v2f);
return r.v; return r.v;
@@ -254,7 +610,7 @@ uint64_t fadd_d(uint64_t v1, uint64_t v2, uint8_t mode) {
uint64_t fsub_d(uint64_t v1, uint64_t v2, uint8_t mode) { uint64_t fsub_d(uint64_t v1, uint64_t v2, uint8_t mode) {
float64_t v1f{v1}, v2f{v2}; float64_t v1f{v1}, v2f{v2};
softfloat_roundingMode = rmm_map.at(mode); softfloat_roundingMode = mode;
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float64_t r = f64_sub(v1f, v2f); float64_t r = f64_sub(v1f, v2f);
return r.v; return r.v;
@@ -262,7 +618,7 @@ uint64_t fsub_d(uint64_t v1, uint64_t v2, uint8_t mode) {
uint64_t fmul_d(uint64_t v1, uint64_t v2, uint8_t mode) { uint64_t fmul_d(uint64_t v1, uint64_t v2, uint8_t mode) {
float64_t v1f{v1}, v2f{v2}; float64_t v1f{v1}, v2f{v2};
softfloat_roundingMode = rmm_map.at(mode); softfloat_roundingMode = mode;
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float64_t r = f64_mul(v1f, v2f); float64_t r = f64_mul(v1f, v2f);
return r.v; return r.v;
@@ -270,7 +626,7 @@ uint64_t fmul_d(uint64_t v1, uint64_t v2, uint8_t mode) {
uint64_t fdiv_d(uint64_t v1, uint64_t v2, uint8_t mode) { uint64_t fdiv_d(uint64_t v1, uint64_t v2, uint8_t mode) {
float64_t v1f{v1}, v2f{v2}; float64_t v1f{v1}, v2f{v2};
softfloat_roundingMode = rmm_map.at(mode); softfloat_roundingMode = mode;
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float64_t r = f64_div(v1f, v2f); float64_t r = f64_div(v1f, v2f);
return r.v; return r.v;
@@ -278,7 +634,7 @@ uint64_t fdiv_d(uint64_t v1, uint64_t v2, uint8_t mode) {
uint64_t fsqrt_d(uint64_t v1, uint8_t mode) { uint64_t fsqrt_d(uint64_t v1, uint8_t mode) {
float64_t v1f{v1}; float64_t v1f{v1};
softfloat_roundingMode = rmm_map.at(mode); softfloat_roundingMode = mode;
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float64_t r = f64_sqrt(v1f); float64_t r = f64_sqrt(v1f);
return r.v; return r.v;
@@ -287,7 +643,7 @@ uint64_t fsqrt_d(uint64_t v1, uint8_t mode) {
uint64_t fcmp_d(uint64_t v1, uint64_t v2, uint32_t op) { uint64_t fcmp_d(uint64_t v1, uint64_t v2, uint32_t op) {
float64_t v1f{v1}, v2f{v2}; float64_t v1f{v1}, v2f{v2};
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
bool nan = (v1 & defaultNaNF64UI) == quiet_nan32 || (v2 & defaultNaNF64UI) == quiet_nan32; bool nan = v1 == defaultNaNF64UI || v2 == defaultNaNF64UI;
bool snan = softfloat_isSigNaNF64UI(v1) || softfloat_isSigNaNF64UI(v2); bool snan = softfloat_isSigNaNF64UI(v1) || softfloat_isSigNaNF64UI(v2);
switch(op) { switch(op) {
case 0: case 0:
@@ -315,30 +671,6 @@ uint64_t fcmp_d(uint64_t v1, uint64_t v2, uint32_t op) {
return -1; return -1;
} }
uint64_t fcvt_d(uint64_t v1, uint32_t op, uint8_t mode) {
float64_t v1f{v1};
softfloat_exceptionFlags = 0;
float64_t r;
switch(op) {
case 0: { // l from d
int64_t res = f64_to_i64(v1f, rmm_map.at(mode), true);
return (uint64_t)res;
}
case 1: { // lu from d
uint64_t res = f64_to_ui64(v1f, rmm_map.at(mode), true);
return res;
}
case 2: // d from l
r = i64_to_f64(v1);
return r.v;
case 3: // d from lu
r = ui64_to_f64(v1);
return r.v;
}
return 0;
}
uint64_t fmadd_d(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode) { uint64_t fmadd_d(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode) {
uint64_t F64_SIGN = 1ULL << 63; uint64_t F64_SIGN = 1ULL << 63;
switch(op) { switch(op) {
@@ -355,7 +687,7 @@ uint64_t fmadd_d(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mod
v1 ^= F64_SIGN; v1 ^= F64_SIGN;
break; break;
} }
softfloat_roundingMode = rmm_map.at(mode); softfloat_roundingMode = mode;
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float64_t res = softfloat_mulAddF64(v1, v2, v3, 0); float64_t res = softfloat_mulAddF64(v1, v2, v3, 0);
return res.v; return res.v;
@@ -406,52 +738,211 @@ uint64_t fclass_d(uint64_t v1) {
(!sign && subnormalOrZero && fracZero) << 4 | (isNaN && isSNaN) << 8 | (isNaN && !isSNaN) << 9; (!sign && subnormalOrZero && fracZero) << 4 | (isNaN && isSNaN) << 8 | (isNaN && !isSNaN) << 9;
} }
uint64_t fcvt_32_64(uint32_t v1, uint32_t op, uint8_t mode) { uint64_t frsqrt7_d(uint64_t v) {
float32_t v1f{v1}; bool subnormal = false;
softfloat_exceptionFlags = 0; uint64_t ret_val = 0;
float64_t r; if(rsqrt_check(fclass_d(v), subnormal, ret_val)) {
switch(op) { return ret_val;
case 0: // l->s, fp to int32
return f32_to_i64(v1f, rmm_map.at(mode), true);
case 1: // wu->s
return f32_to_ui64(v1f, rmm_map.at(mode), true);
case 2: // s->w
r = i32_to_f64(v1);
return r.v;
case 3: // s->wu
r = ui32_to_f64(v1);
return r.v;
} }
return 0; uint64_t sig = fracF64UI(v);
int exp = expF64UI(v);
uint64_t sign = signF64UI(v);
unsigned constexpr e = 11;
unsigned constexpr s = 52;
return frsqrt7_general(s, e, sign, exp, sig, subnormal);
} }
uint32_t fcvt_64_32(uint64_t v1, uint32_t op, uint8_t mode) { uint64_t frec7_d(uint64_t v, uint8_t mode) {
softfloat_exceptionFlags = 0; bool subnormal = false;
float32_t r; uint64_t ret_val = 0;
switch(op) { if(recip_check(fclass_d(v), subnormal, ret_val)) {
case 0: { // wu->s return ret_val;
int32_t r = f64_to_i32(float64_t{v1}, rmm_map.at(mode), true);
return r;
} }
case 1: { // wu->s uint64_t sig = fracF64UI(v);
uint32_t r = f64_to_ui32(float64_t{v1}, rmm_map.at(mode), true); int exp = expF64UI(v);
return r; uint64_t sign = signF64UI(v);
} unsigned constexpr e = 11;
case 2: // l->s, fp to int32 unsigned constexpr s = 52;
r = i64_to_f32(v1); if(frec_general(ret_val, s, e, sign, exp, sig, subnormal, mode))
return r.v; softfloat_exceptionFlags |= (softfloat_flag_inexact | softfloat_flag_overflow);
case 3: // wu->s return ret_val;
r = ui64_to_f32(v1);
return r.v;
}
return 0;
} }
uint32_t unbox_s(uint64_t v) { uint64_t unbox_d(uint8_t FLEN, uint64_t v) {
constexpr uint64_t mask = std::numeric_limits<uint64_t>::max() & ~((uint64_t)std::numeric_limits<uint32_t>::max()); uint64_t mask = 0;
switch(FLEN) {
case 64: {
return v;
break;
}
default:
break;
}
if((v & mask) != mask) if((v & mask) != mask)
return 0x7fc00000; return defaultNaNF64UI;
else else
return v & std::numeric_limits<uint32_t>::max(); return v & std::numeric_limits<uint32_t>::max();
} }
// conversion: float to float
uint32_t f16tof32(uint16_t val, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return f16_to_f32(float16_t{val}).v;
}
uint64_t f16tof64(uint16_t val, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return f16_to_f64(float16_t{val}).v;
}
uint16_t f32tof16(uint32_t val, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return f32_to_f16(float32_t{val}).v;
}
uint64_t f32tof64(uint32_t val, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return f32_to_f64(float32_t{val}).v;
}
uint16_t f64tof16(uint64_t val, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return f64_to_f16(float64_t{val}).v;
}
uint32_t f64tof32(uint64_t val, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return f64_to_f32(float64_t{val}).v;
}
// conversions: float to unsigned
uint32_t f16toui32(uint16_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return f16_to_ui32(float16_t{v}, rm, true);
}
uint64_t f16toui64(uint16_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return f16_to_ui64(float16_t{v}, rm, true);
}
uint32_t f32toui32(uint32_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return f32_to_ui32(float32_t{v}, rm, true);
}
uint64_t f32toui64(uint32_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return f32_to_ui64(float32_t{v}, rm, true);
}
uint32_t f64toui32(uint64_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return f64_to_ui32(float64_t{v}, rm, true);
}
uint64_t f64toui64(uint64_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return f64_to_ui64(float64_t{v}, rm, true);
}
// conversions: float to signed
uint32_t f16toi32(uint16_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return f16_to_i32(float16_t{v}, rm, true);
}
uint64_t f16toi64(uint16_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return f16_to_i64(float16_t{v}, rm, true);
}
uint32_t f32toi32(uint32_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return f32_to_i32(float32_t{v}, rm, true);
}
uint64_t f32toi64(uint32_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return f32_to_i64(float32_t{v}, rm, true);
}
uint32_t f64toi32(uint64_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return f64_to_i32(float64_t{v}, rm, true);
}
uint64_t f64toi64(uint64_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return f64_to_i64(float64_t{v}, rm, true);
}
// conversions: unsigned to float
uint16_t ui32tof16(uint32_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return ui32_to_f16(v).v;
}
uint16_t ui64tof16(uint64_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return ui64_to_f16(v).v;
}
uint32_t ui32tof32(uint32_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return ui32_to_f32(v).v;
}
uint32_t ui64tof32(uint64_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return ui64_to_f32(v).v;
}
uint64_t ui32tof64(uint32_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return ui32_to_f64(v).v;
}
uint64_t ui64tof64(uint64_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return ui64_to_f64(v).v;
}
// conversions: signed to float
uint16_t i32tof16(uint32_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return i32_to_f16(v).v;
}
uint16_t i64tof16(uint64_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return i64_to_f16(v).v;
}
uint32_t i32tof32(uint32_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return i32_to_f32(v).v;
}
uint32_t i64tof32(uint64_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return i64_to_f32(v).v;
}
uint64_t i32tof64(uint32_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return i32_to_f64(v).v;
}
uint64_t i64tof64(uint64_t v, uint8_t rm) {
softfloat_exceptionFlags = 0;
softfloat_roundingMode = rm;
return i64_to_f64(v).v;
}
} }
+65 -8
View File
@@ -39,30 +39,87 @@
extern "C" { extern "C" {
uint32_t fget_flags(); uint32_t fget_flags();
// half precision
uint16_t fadd_h(uint16_t v1, uint16_t v2, uint8_t mode);
uint16_t fsub_h(uint16_t v1, uint16_t v2, uint8_t mode);
uint16_t fmul_h(uint16_t v1, uint16_t v2, uint8_t mode);
uint16_t fdiv_h(uint16_t v1, uint16_t v2, uint8_t mode);
uint16_t fsqrt_h(uint16_t v1, uint8_t mode);
uint16_t fcmp_h(uint16_t v1, uint16_t v2, uint16_t op);
uint16_t fmadd_h(uint16_t v1, uint16_t v2, uint16_t v3, uint16_t op, uint8_t mode);
uint16_t fsel_h(uint16_t v1, uint16_t v2, uint16_t op);
uint16_t fclass_h(uint16_t v1);
uint16_t frsqrt7_h(uint16_t v);
uint16_t frec7_h(uint16_t v, uint8_t mode);
uint16_t unbox_h(uint8_t FLEN, uint64_t v);
// single precision
uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode); uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode);
uint32_t fsub_s(uint32_t v1, uint32_t v2, uint8_t mode); uint32_t fsub_s(uint32_t v1, uint32_t v2, uint8_t mode);
uint32_t fmul_s(uint32_t v1, uint32_t v2, uint8_t mode); uint32_t fmul_s(uint32_t v1, uint32_t v2, uint8_t mode);
uint32_t fdiv_s(uint32_t v1, uint32_t v2, uint8_t mode); uint32_t fdiv_s(uint32_t v1, uint32_t v2, uint8_t mode);
uint32_t fsqrt_s(uint32_t v1, uint8_t mode); uint32_t fsqrt_s(uint32_t v1, uint8_t mode);
uint32_t fcmp_s(uint32_t v1, uint32_t v2, uint32_t op); uint32_t fcmp_s(uint32_t v1, uint32_t v2, uint32_t op);
uint32_t fcvt_s(uint32_t v1, uint32_t op, uint8_t mode);
uint32_t fmadd_s(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mode); uint32_t fmadd_s(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mode);
uint32_t fsel_s(uint32_t v1, uint32_t v2, uint32_t op); uint32_t fsel_s(uint32_t v1, uint32_t v2, uint32_t op);
uint32_t fclass_s(uint32_t v1); uint32_t fclass_s(uint32_t v1);
uint32_t fconv_d2f(uint64_t v1, uint8_t mode); uint32_t frsqrt7_s(uint32_t v);
uint64_t fconv_f2d(uint32_t v1, uint8_t mode); uint32_t frec7_s(uint32_t v, uint8_t mode);
uint32_t unbox_s(uint8_t FLEN, uint64_t v);
// double precision
uint64_t fadd_d(uint64_t v1, uint64_t v2, uint8_t mode); uint64_t fadd_d(uint64_t v1, uint64_t v2, uint8_t mode);
uint64_t fsub_d(uint64_t v1, uint64_t v2, uint8_t mode); uint64_t fsub_d(uint64_t v1, uint64_t v2, uint8_t mode);
uint64_t fmul_d(uint64_t v1, uint64_t v2, uint8_t mode); uint64_t fmul_d(uint64_t v1, uint64_t v2, uint8_t mode);
uint64_t fdiv_d(uint64_t v1, uint64_t v2, uint8_t mode); uint64_t fdiv_d(uint64_t v1, uint64_t v2, uint8_t mode);
uint64_t fsqrt_d(uint64_t v1, uint8_t mode); uint64_t fsqrt_d(uint64_t v1, uint8_t mode);
uint64_t fcmp_d(uint64_t v1, uint64_t v2, uint32_t op); uint64_t fcmp_d(uint64_t v1, uint64_t v2, uint32_t op);
uint64_t fcvt_d(uint64_t v1, uint32_t op, uint8_t mode);
uint64_t fmadd_d(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode); uint64_t fmadd_d(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode);
uint64_t fsel_d(uint64_t v1, uint64_t v2, uint32_t op); uint64_t fsel_d(uint64_t v1, uint64_t v2, uint32_t op);
uint64_t fclass_d(uint64_t v1); uint64_t fclass_d(uint64_t v1);
uint64_t fcvt_32_64(uint32_t v1, uint32_t op, uint8_t mode); uint64_t frsqrt7_d(uint64_t v);
uint32_t fcvt_64_32(uint64_t v1, uint32_t op, uint8_t mode); uint64_t frec7_d(uint64_t v, uint8_t mode);
uint32_t unbox_s(uint64_t v); uint64_t unbox_d(uint8_t FLEN, uint64_t v);
// conversion: float to float
uint32_t f16tof32(uint16_t val, uint8_t rm);
uint64_t f16tof64(uint16_t val, uint8_t rm);
uint16_t f32tof16(uint32_t val, uint8_t rm);
uint64_t f32tof64(uint32_t val, uint8_t rm);
uint16_t f64tof16(uint64_t val, uint8_t rm);
uint32_t f64tof32(uint64_t val, uint8_t rm);
// conversions: float to unsigned
uint32_t f16toui32(uint16_t v, uint8_t rm);
uint64_t f16toui64(uint16_t v, uint8_t rm);
uint32_t f32toui32(uint32_t v, uint8_t rm);
uint64_t f32toui64(uint32_t v, uint8_t rm);
uint32_t f64toui32(uint64_t v, uint8_t rm);
uint64_t f64toui64(uint64_t v, uint8_t rm);
// conversions: float to signed
uint32_t f16toi32(uint16_t v, uint8_t rm);
uint64_t f16toi64(uint16_t v, uint8_t rm);
uint32_t f32toi32(uint32_t v, uint8_t rm);
uint64_t f32toi64(uint32_t v, uint8_t rm);
uint32_t f64toi32(uint64_t v, uint8_t rm);
uint64_t f64toi64(uint64_t v, uint8_t rm);
// conversions: unsigned to float
uint16_t ui32tof16(uint32_t v, uint8_t rm);
uint16_t ui64tof16(uint64_t v, uint8_t rm);
uint32_t ui32tof32(uint32_t v, uint8_t rm);
uint32_t ui64tof32(uint64_t v, uint8_t rm);
uint64_t ui32tof64(uint32_t v, uint8_t rm);
uint64_t ui64tof64(uint64_t v, uint8_t rm);
// conversions: signed to float
uint16_t i32tof16(uint32_t v, uint8_t rm);
uint16_t i64tof16(uint64_t v, uint8_t rm);
uint32_t i32tof32(uint32_t v, uint8_t rm);
uint32_t i64tof32(uint64_t v, uint8_t rm);
uint64_t i32tof64(uint32_t v, uint8_t rm);
uint64_t i64tof64(uint64_t v, uint8_t rm);
} }
#endif /* RISCV_SRC_VM_FP_FUNCTIONS_H_ */ #endif /* _VM_FP_FUNCTIONS_H_ */
+204 -142
View File
File diff suppressed because it is too large. Load diff
+45 -7
View File
@@ -72,32 +72,70 @@ using namespace ::llvm;
void add_fp_functions_2_module(Module* mod, uint32_t flen, uint32_t xlen) { void add_fp_functions_2_module(Module* mod, uint32_t flen, uint32_t xlen) {
if(flen) { if(flen) {
FDECL(fget_flags, INT_TYPE(32)); FDECL(fget_flags, INT_TYPE(32));
FDECL(fadd_h, INT_TYPE(16), INT_TYPE(16), INT_TYPE(16), INT_TYPE(8));
FDECL(fsub_h, INT_TYPE(16), INT_TYPE(16), INT_TYPE(16), INT_TYPE(8));
FDECL(fmul_h, INT_TYPE(16), INT_TYPE(16), INT_TYPE(16), INT_TYPE(8));
FDECL(fdiv_h, INT_TYPE(16), INT_TYPE(16), INT_TYPE(16), INT_TYPE(8));
FDECL(fsqrt_h, INT_TYPE(16), INT_TYPE(16), INT_TYPE(8));
FDECL(fcmp_h, INT_TYPE(16), INT_TYPE(16), INT_TYPE(16), INT_TYPE(16));
FDECL(fmadd_h, INT_TYPE(16), INT_TYPE(16), INT_TYPE(16), INT_TYPE(16), INT_TYPE(16), INT_TYPE(8));
FDECL(fsel_h, INT_TYPE(16), INT_TYPE(16), INT_TYPE(16), INT_TYPE(16));
FDECL(fclass_h, INT_TYPE(16), INT_TYPE(16));
FDECL(unbox_h, INT_TYPE(16), INT_TYPE(32), INT_TYPE(64)); // technically the first arg is only 8 bits
FDECL(f16toi32, INT_TYPE(32), INT_TYPE(32), INT_TYPE(8))
FDECL(f16toui32, INT_TYPE(32), INT_TYPE(32), INT_TYPE(8))
FDECL(i32tof16, INT_TYPE(16), INT_TYPE(32), INT_TYPE(8))
FDECL(ui32tof16, INT_TYPE(16), INT_TYPE(32), INT_TYPE(8))
FDECL(f16toi64, INT_TYPE(64), INT_TYPE(32), INT_TYPE(8))
FDECL(f16toui64, INT_TYPE(64), INT_TYPE(32), INT_TYPE(8))
FDECL(i64tof16, INT_TYPE(16), INT_TYPE(64), INT_TYPE(8))
FDECL(ui64tof16, INT_TYPE(16), INT_TYPE(64), INT_TYPE(8))
FDECL(fadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); FDECL(fadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(fsub_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); FDECL(fsub_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(fmul_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); FDECL(fmul_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(fdiv_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); FDECL(fdiv_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(fsqrt_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); FDECL(fsqrt_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(fcmp_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32)); FDECL(fcmp_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32));
FDECL(fcvt_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(fmadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); FDECL(fmadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(fsel_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32)); FDECL(fsel_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32));
FDECL(fclass_s, INT_TYPE(32), INT_TYPE(32)); FDECL(fclass_s, INT_TYPE(32), INT_TYPE(32));
FDECL(fcvt_32_64, INT_TYPE(64), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); FDECL(unbox_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(64)); // technically the first arg is only 8 bits
FDECL(fcvt_64_32, INT_TYPE(32), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8));
FDECL(f32toi32, INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(f32toui32, INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(i32tof32, INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(ui32tof32, INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(f32toi64, INT_TYPE(64), INT_TYPE(32), INT_TYPE(8));
FDECL(f32toui64, INT_TYPE(64), INT_TYPE(32), INT_TYPE(8));
FDECL(i64tof32, INT_TYPE(32), INT_TYPE(64), INT_TYPE(8));
FDECL(ui64tof32, INT_TYPE(32), INT_TYPE(64), INT_TYPE(8));
if(flen > 32) { if(flen > 32) {
FDECL(fconv_d2f, INT_TYPE(32), INT_TYPE(64), INT_TYPE(8));
FDECL(fconv_f2d, INT_TYPE(64), INT_TYPE(32), INT_TYPE(8));
FDECL(fadd_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); FDECL(fadd_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
FDECL(fsub_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); FDECL(fsub_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
FDECL(fmul_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); FDECL(fmul_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
FDECL(fdiv_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); FDECL(fdiv_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
FDECL(fsqrt_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); FDECL(fsqrt_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
FDECL(fcmp_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32)); FDECL(fcmp_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32));
FDECL(fcvt_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8));
FDECL(fmadd_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8)); FDECL(fmadd_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8));
FDECL(fsel_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32)); FDECL(fsel_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32));
FDECL(fclass_d, INT_TYPE(64), INT_TYPE(64)); FDECL(fclass_d, INT_TYPE(64), INT_TYPE(64));
FDECL(unbox_s, INT_TYPE(32), INT_TYPE(64));
FDECL(f64tof32, INT_TYPE(32), INT_TYPE(64), INT_TYPE(8));
FDECL(f32tof64, INT_TYPE(64), INT_TYPE(32), INT_TYPE(8));
FDECL(f64toi64, INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
FDECL(f64toui64, INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
FDECL(i64tof64, INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
FDECL(ui64tof64, INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
FDECL(i32tof64, INT_TYPE(64), INT_TYPE(32), INT_TYPE(8));
FDECL(ui32tof64, INT_TYPE(64), INT_TYPE(32), INT_TYPE(8));
FDECL(f64toi32, INT_TYPE(32), INT_TYPE(64), INT_TYPE(8));
FDECL(f64toui32, INT_TYPE(32), INT_TYPE(64), INT_TYPE(8));
FDECL(unbox_d, INT_TYPE(64), INT_TYPE(32), INT_TYPE(64)); // technically the first arg is only 8 bits
} }
} }
} }
+69 -69
View File
@@ -31,10 +31,12 @@
*******************************************************************************/ *******************************************************************************/
// clang-format off // clang-format off
#include <iss/arch/tgc5c.h> #include <iss/arch/tgc5c.h>
// vm_base needs to be included before gdb_session as termios.h (via boost and gdb_server) has a define which clashes with a variable
// name in ConstantRange.h
#include <iss/llvm/vm_base.h>
#include <iss/debugger/gdb_session.h> #include <iss/debugger/gdb_session.h>
#include <iss/debugger/server.h> #include <iss/debugger/server.h>
#include <iss/iss.h> #include <iss/iss.h>
#include <iss/llvm/vm_base.h>
#include <util/logging.h> #include <util/logging.h>
#include <iss/instruction_decoder.h> #include <iss/instruction_decoder.h>
@@ -353,7 +355,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -399,7 +401,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -446,7 +448,7 @@ private:
/*generate behavior*/ /*generate behavior*/
this->builder.CreateStore(this->gen_const(32U, static_cast<int>(NO_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false); this->builder.CreateStore(this->gen_const(32U, static_cast<int>(NO_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false);
if(rd>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto new_pc =(uint32_t)(PC+(int32_t)sext<21>(imm)); auto new_pc =(uint32_t)(PC+(int32_t)sext<21>(imm));
@@ -503,7 +505,7 @@ private:
/*generate behavior*/ /*generate behavior*/
this->builder.CreateStore(this->gen_const(32U, static_cast<int>(NO_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false); this->builder.CreateStore(this->gen_const(32U, static_cast<int>(NO_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false);
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto addr_mask =(uint32_t)- 2; auto addr_mask =(uint32_t)- 2;
@@ -584,7 +586,7 @@ private:
/*generate behavior*/ /*generate behavior*/
this->builder.CreateStore(this->gen_const(32U, static_cast<int>(NO_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false); this->builder.CreateStore(this->gen_const(32U, static_cast<int>(NO_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false);
if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
{ {
@@ -649,7 +651,7 @@ private:
/*generate behavior*/ /*generate behavior*/
this->builder.CreateStore(this->gen_const(32U, static_cast<int>(NO_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false); this->builder.CreateStore(this->gen_const(32U, static_cast<int>(NO_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false);
if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
{ {
@@ -714,7 +716,7 @@ private:
/*generate behavior*/ /*generate behavior*/
this->builder.CreateStore(this->gen_const(32U, static_cast<int>(NO_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false); this->builder.CreateStore(this->gen_const(32U, static_cast<int>(NO_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false);
if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
{ {
@@ -783,7 +785,7 @@ private:
/*generate behavior*/ /*generate behavior*/
this->builder.CreateStore(this->gen_const(32U, static_cast<int>(NO_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false); this->builder.CreateStore(this->gen_const(32U, static_cast<int>(NO_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false);
if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
{ {
@@ -852,7 +854,7 @@ private:
/*generate behavior*/ /*generate behavior*/
this->builder.CreateStore(this->gen_const(32U, static_cast<int>(NO_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false); this->builder.CreateStore(this->gen_const(32U, static_cast<int>(NO_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false);
if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
{ {
@@ -917,7 +919,7 @@ private:
/*generate behavior*/ /*generate behavior*/
this->builder.CreateStore(this->gen_const(32U, static_cast<int>(NO_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false); this->builder.CreateStore(this->gen_const(32U, static_cast<int>(NO_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false);
if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
{ {
@@ -981,7 +983,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto load_address =this->gen_ext( auto load_address =this->gen_ext(
@@ -1039,7 +1041,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto load_address =this->gen_ext( auto load_address =this->gen_ext(
@@ -1097,7 +1099,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto load_address =this->gen_ext( auto load_address =this->gen_ext(
@@ -1155,7 +1157,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto load_address =this->gen_ext( auto load_address =this->gen_ext(
@@ -1211,7 +1213,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto load_address =this->gen_ext( auto load_address =this->gen_ext(
@@ -1267,7 +1269,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto store_address =this->gen_ext( auto store_address =this->gen_ext(
@@ -1320,7 +1322,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto store_address =this->gen_ext( auto store_address =this->gen_ext(
@@ -1373,7 +1375,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto store_address =this->gen_ext( auto store_address =this->gen_ext(
@@ -1426,7 +1428,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1478,7 +1480,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1532,7 +1534,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1585,7 +1587,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1635,7 +1637,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1685,7 +1687,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1735,7 +1737,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1785,7 +1787,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1835,7 +1837,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1887,7 +1889,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1939,7 +1941,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1991,7 +1993,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -2044,7 +2046,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -2099,7 +2101,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -2152,7 +2154,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -2202,7 +2204,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -2255,7 +2257,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -2311,7 +2313,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -2361,7 +2363,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -2553,10 +2555,10 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
std::vector<Value*> wait_231_args{ std::vector<Value*> wait_57_args{
this->gen_ext(this->gen_const(8,1), 32) this->gen_ext(this->gen_const(8,1), 32)
}; };
this->builder.CreateCall(this->mod->getFunction("wait"), wait_231_args); this->builder.CreateCall(this->mod->getFunction("wait"), wait_57_args);
bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk);
auto returnValue = std::make_tuple(CONT,bb); auto returnValue = std::make_tuple(CONT,bb);
@@ -2595,7 +2597,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto xrs1 =this->gen_reg_load(traits::X0+ rs1); auto xrs1 =this->gen_reg_load(traits::X0+ rs1);
@@ -2651,7 +2653,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto xrd =this->gen_read_mem(traits::CSR, csr, 4); auto xrd =this->gen_read_mem(traits::CSR, csr, 4);
@@ -2708,7 +2710,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto xrd =this->gen_read_mem(traits::CSR, csr, 4); auto xrd =this->gen_read_mem(traits::CSR, csr, 4);
@@ -2765,7 +2767,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto xrd =this->gen_read_mem(traits::CSR, csr, 4); auto xrd =this->gen_read_mem(traits::CSR, csr, 4);
@@ -2816,7 +2818,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto xrd =this->gen_read_mem(traits::CSR, csr, 4); auto xrd =this->gen_read_mem(traits::CSR, csr, 4);
@@ -2872,7 +2874,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto xrd =this->gen_read_mem(traits::CSR, csr, 4); auto xrd =this->gen_read_mem(traits::CSR, csr, 4);
@@ -2968,7 +2970,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto res =this->builder.CreateMul( auto res =this->builder.CreateMul(
@@ -3023,7 +3025,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto res =this->builder.CreateMul( auto res =this->builder.CreateMul(
@@ -3081,7 +3083,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto res =this->builder.CreateMul( auto res =this->builder.CreateMul(
@@ -3138,7 +3140,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto res =this->builder.CreateMul( auto res =this->builder.CreateMul(
@@ -3194,7 +3196,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto dividend =this->gen_ext( auto dividend =this->gen_ext(
@@ -3298,7 +3300,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
{ {
@@ -3371,7 +3373,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
{ {
@@ -3479,7 +3481,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
{ {
@@ -3561,7 +3563,7 @@ private:
get_reg_ptr(rd+8 + traits::X0), false); get_reg_ptr(rd+8 + traits::X0), false);
} }
else{ else{
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk);
auto returnValue = std::make_tuple(CONT,bb); auto returnValue = std::make_tuple(CONT,bb);
@@ -3698,7 +3700,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rs1>=static_cast<uint32_t>(traits::RFS)) { if(rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rs1!=0) { if(rs1!=0) {
@@ -3825,7 +3827,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -3871,7 +3873,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(imm==0||rd>=static_cast<uint32_t>(traits::RFS)) { if(imm==0||rd>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
if(rd!=0) { if(rd!=0) {
this->builder.CreateStore( this->builder.CreateStore(
@@ -3924,7 +3926,7 @@ private:
get_reg_ptr(2 + traits::X0), false); get_reg_ptr(2 + traits::X0), false);
} }
else{ else{
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk);
auto returnValue = std::make_tuple(CONT,bb); auto returnValue = std::make_tuple(CONT,bb);
@@ -3960,7 +3962,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk);
auto returnValue = std::make_tuple(CONT,bb); auto returnValue = std::make_tuple(CONT,bb);
@@ -4459,7 +4461,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rs1>=static_cast<uint32_t>(traits::RFS)) { if(rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rs1!=0) { if(rs1!=0) {
@@ -4508,7 +4510,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)||rd==0) { if(rd>=static_cast<uint32_t>(traits::RFS)||rd==0) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto offs =this->gen_ext( auto offs =this->gen_ext(
@@ -4562,7 +4564,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -4689,7 +4691,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rd>=static_cast<uint32_t>(traits::RFS)) { if(rd>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -4740,7 +4742,7 @@ private:
/*generate behavior*/ /*generate behavior*/
this->builder.CreateStore(this->gen_const(32U, static_cast<int>(NO_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false); this->builder.CreateStore(this->gen_const(32U, static_cast<int>(NO_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false);
if(rs1>=static_cast<uint32_t>(traits::RFS)) { if(rs1>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto addr_mask =(uint32_t)- 2; auto addr_mask =(uint32_t)- 2;
@@ -4826,7 +4828,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
if(rs2>=static_cast<uint32_t>(traits::RFS)) { if(rs2>=static_cast<uint32_t>(traits::RFS)) {
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto offs =this->gen_ext( auto offs =this->gen_ext(
@@ -4874,7 +4876,7 @@ private:
this->gen_instr_prologue(); this->gen_instr_prologue();
/*generate behavior*/ /*generate behavior*/
this->gen_raise_trap(0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk);
auto returnValue = std::make_tuple(CONT,bb); auto returnValue = std::make_tuple(CONT,bb);
@@ -4944,8 +4946,6 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, BasicBlock *this_block)
// const typename traits::addr_t upper_bits = ~traits::PGMASK; // const typename traits::addr_t upper_bits = ~traits::PGMASK;
phys_addr_t paddr(pc); phys_addr_t paddr(pc);
auto *const data = (uint8_t *)&instr; auto *const data = (uint8_t *)&instr;
if(this->core.has_mmu())
paddr = this->core.virt2phys(pc);
auto res = this->core.read(paddr, 4, data); auto res = this->core.read(paddr, 4, data);
if (res != iss::Ok) if (res != iss::Ok)
return std::make_tuple(ILLEGAL_FETCH, nullptr); return std::make_tuple(ILLEGAL_FETCH, nullptr);
+64 -66
View File
@@ -348,7 +348,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -384,7 +384,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -421,7 +421,7 @@ private:
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32)); tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32));
if(rd>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto new_pc = (uint32_t)(PC+(int32_t)sext<21>(imm)); auto new_pc = (uint32_t)(PC+(int32_t)sext<21>(imm));
@@ -468,7 +468,7 @@ private:
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32)); tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32));
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto addr_mask = (uint32_t)- 2; auto addr_mask = (uint32_t)- 2;
@@ -526,7 +526,7 @@ private:
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32)); tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32));
if(rs2>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rs2>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
tu.open_if(tu.icmp(ICmpInst::ICMP_EQ, tu.open_if(tu.icmp(ICmpInst::ICMP_EQ,
@@ -576,7 +576,7 @@ private:
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32)); tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32));
if(rs2>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rs2>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
tu.open_if(tu.icmp(ICmpInst::ICMP_NE, tu.open_if(tu.icmp(ICmpInst::ICMP_NE,
@@ -626,7 +626,7 @@ private:
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32)); tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32));
if(rs2>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rs2>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
tu.open_if(tu.icmp(ICmpInst::ICMP_SLT, tu.open_if(tu.icmp(ICmpInst::ICMP_SLT,
@@ -676,7 +676,7 @@ private:
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32)); tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32));
if(rs2>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rs2>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
tu.open_if(tu.icmp(ICmpInst::ICMP_SGE, tu.open_if(tu.icmp(ICmpInst::ICMP_SGE,
@@ -726,7 +726,7 @@ private:
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32)); tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32));
if(rs2>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rs2>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
tu.open_if(tu.icmp(ICmpInst::ICMP_ULT, tu.open_if(tu.icmp(ICmpInst::ICMP_ULT,
@@ -776,7 +776,7 @@ private:
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32)); tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32));
if(rs2>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rs2>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
tu.open_if(tu.icmp(ICmpInst::ICMP_UGE, tu.open_if(tu.icmp(ICmpInst::ICMP_UGE,
@@ -825,7 +825,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto load_address = tu.assignment(tu.ext((tu.add( auto load_address = tu.assignment(tu.ext((tu.add(
@@ -866,7 +866,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto load_address = tu.assignment(tu.ext((tu.add( auto load_address = tu.assignment(tu.ext((tu.add(
@@ -907,7 +907,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto load_address = tu.assignment(tu.ext((tu.add( auto load_address = tu.assignment(tu.ext((tu.add(
@@ -948,7 +948,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto load_address = tu.assignment(tu.ext((tu.add( auto load_address = tu.assignment(tu.ext((tu.add(
@@ -989,7 +989,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto load_address = tu.assignment(tu.ext((tu.add( auto load_address = tu.assignment(tu.ext((tu.add(
@@ -1030,7 +1030,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rs2>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rs2>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto store_address = tu.assignment(tu.ext((tu.add( auto store_address = tu.assignment(tu.ext((tu.add(
@@ -1068,7 +1068,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rs2>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rs2>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto store_address = tu.assignment(tu.ext((tu.add( auto store_address = tu.assignment(tu.ext((tu.add(
@@ -1106,7 +1106,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rs2>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rs2>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto store_address = tu.assignment(tu.ext((tu.add( auto store_address = tu.assignment(tu.ext((tu.add(
@@ -1144,7 +1144,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1183,7 +1183,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1222,7 +1222,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1261,7 +1261,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1300,7 +1300,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1339,7 +1339,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1378,7 +1378,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1417,7 +1417,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1456,7 +1456,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1495,7 +1495,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1534,7 +1534,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1573,7 +1573,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1614,7 +1614,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1653,7 +1653,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1692,7 +1692,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1731,7 +1731,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1772,7 +1772,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1813,7 +1813,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -1852,7 +1852,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -2030,7 +2030,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto xrs1 = tu.assignment(tu.load(rs1 + traits::X0, 0),32); auto xrs1 = tu.assignment(tu.load(rs1 + traits::X0, 0),32);
@@ -2072,7 +2072,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32);
@@ -2116,7 +2116,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32);
@@ -2160,7 +2160,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32);
@@ -2199,7 +2199,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32);
@@ -2242,7 +2242,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32);
@@ -2315,7 +2315,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto res = tu.assignment(tu.mul( auto res = tu.assignment(tu.mul(
@@ -2355,7 +2355,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto res = tu.assignment(tu.mul( auto res = tu.assignment(tu.mul(
@@ -2397,7 +2397,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto res = tu.assignment(tu.mul( auto res = tu.assignment(tu.mul(
@@ -2439,7 +2439,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto res = tu.assignment(tu.mul( auto res = tu.assignment(tu.mul(
@@ -2481,7 +2481,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto dividend = tu.assignment(tu.ext(tu.load(rs1 + traits::X0, 0),32,true),32); auto dividend = tu.assignment(tu.ext(tu.load(rs1 + traits::X0, 0),32,true),32);
@@ -2546,7 +2546,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
tu.open_if(tu.icmp(ICmpInst::ICMP_NE, tu.open_if(tu.icmp(ICmpInst::ICMP_NE,
@@ -2597,7 +2597,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
tu.open_if(tu.icmp(ICmpInst::ICMP_NE, tu.open_if(tu.icmp(ICmpInst::ICMP_NE,
@@ -2665,7 +2665,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rs1>=static_cast<uint32_t>(traits:: RFS)||rs2>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
tu.open_if(tu.icmp(ICmpInst::ICMP_NE, tu.open_if(tu.icmp(ICmpInst::ICMP_NE,
@@ -2720,7 +2720,7 @@ private:
tu.constant(imm,16))),32,false)); tu.constant(imm,16))),32,false));
} }
else{ else{
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
auto returnValue = CONT; auto returnValue = CONT;
@@ -2817,7 +2817,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rs1!=0) { if(rs1!=0) {
@@ -2913,7 +2913,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -2949,7 +2949,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(imm==0||rd>=static_cast<uint32_t>(traits:: RFS)) { if(imm==0||rd>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
if(rd!=0) { if(rd!=0) {
tu.store(rd + traits::X0, tu.constant((uint32_t)((int32_t)sext<18>(imm)),32)); tu.store(rd + traits::X0, tu.constant((uint32_t)((int32_t)sext<18>(imm)),32));
@@ -2987,7 +2987,7 @@ private:
tu.constant((int16_t)sext<10>(nzimm),16))),32,false)); tu.constant((int16_t)sext<10>(nzimm),16))),32,false));
} }
else{ else{
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
auto returnValue = CONT; auto returnValue = CONT;
@@ -3015,7 +3015,7 @@ private:
tu("(*cycle)++;"); tu("(*cycle)++;");
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
auto returnValue = CONT; auto returnValue = CONT;
tu.close_scope(); tu.close_scope();
@@ -3376,7 +3376,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rs1!=0) { if(rs1!=0) {
@@ -3414,7 +3414,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)||rd==0) { if(rd>=static_cast<uint32_t>(traits:: RFS)||rd==0) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto offs = tu.assignment(tu.ext((tu.add( auto offs = tu.assignment(tu.ext((tu.add(
@@ -3451,7 +3451,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -3551,7 +3551,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rd>=static_cast<uint32_t>(traits:: RFS)) { if(rd>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
if(rd!=0) { if(rd!=0) {
@@ -3589,7 +3589,7 @@ private:
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32)); tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32));
if(rs1>=static_cast<uint32_t>(traits:: RFS)) { if(rs1>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto addr_mask = (uint32_t)- 2; auto addr_mask = (uint32_t)- 2;
@@ -3656,7 +3656,7 @@ private:
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
if(rs2>=static_cast<uint32_t>(traits:: RFS)) { if(rs2>=static_cast<uint32_t>(traits:: RFS)) {
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
} }
else{ else{
auto offs = tu.assignment(tu.ext((tu.add( auto offs = tu.assignment(tu.ext((tu.add(
@@ -3689,7 +3689,7 @@ private:
tu("(*cycle)++;"); tu("(*cycle)++;");
tu.open_scope(); tu.open_scope();
this->gen_set_tval(tu, instr); this->gen_set_tval(tu, instr);
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION)); this->gen_raise_trap(tu, 0, static_cast<uint32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
auto returnValue = CONT; auto returnValue = CONT;
tu.close_scope(); tu.close_scope();
@@ -3743,8 +3743,6 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, tu_builder& tu) {
enum {TRAP_ID=1<<16}; enum {TRAP_ID=1<<16};
code_word_t instr = 0; code_word_t instr = 0;
phys_addr_t paddr(pc); phys_addr_t paddr(pc);
if(this->core.has_mmu())
paddr = this->core.virt2phys(pc);
auto res = this->core.read(paddr, 4, reinterpret_cast<uint8_t*>(&instr)); auto res = this->core.read(paddr, 4, reinterpret_cast<uint8_t*>(&instr));
if (res != iss::Ok) if (res != iss::Ok)
return ILLEGAL_FETCH; return ILLEGAL_FETCH;
+407
View File
@@ -0,0 +1,407 @@
////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2025, MINRES Technologies GmbH
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Contributors:
// alex@minres.com - initial API and implementation
////////////////////////////////////////////////////////////////////////////////
#include "vector_functions.h"
#include "iss/vm_types.h"
#include "vm/aes_sbox.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <limits>
#include <math.h>
#include <stdexcept>
#include <vector>
namespace softvector {
bool softvec_read(void* core, uint64_t addr, uint64_t length, uint8_t* data) {
// Read length bytes from addr into *data
iss::status status = static_cast<iss::arch_if*>(core)->read(iss::address_type::PHYSICAL, iss::access_type::READ,
0 /*traits<ARCH>::MEM*/, addr, length, data);
return status == iss::Ok;
}
bool softvec_write(void* core, uint64_t addr, uint64_t length, uint8_t* data) {
// Write length bytes from addr into *data
iss::status status = static_cast<iss::arch_if*>(core)->write(iss::address_type::PHYSICAL, iss::access_type::READ,
0 /*traits<ARCH>::MEM*/, addr, length, data);
return status == iss::Ok;
}
vtype_t::vtype_t(uint32_t vtype_val) { underlying = (vtype_val & 0x8000) << 32 | (vtype_val & ~0x8000); }
vtype_t::vtype_t(uint64_t vtype_val) { underlying = vtype_val; }
bool vtype_t::vill() { return underlying >> 63; }
bool vtype_t::vma() { return (underlying >> 7) & 1; }
bool vtype_t::vta() { return (underlying >> 6) & 1; }
unsigned vtype_t::sew() {
uint8_t vsew = (underlying >> 3) & 0b111;
// pow(2, 3 + vsew);
return 1 << (3 + vsew);
}
double vtype_t::lmul() {
uint8_t vlmul = underlying & 0b111;
assert(vlmul != 0b100); // reserved encoding
int8_t signed_vlmul = (vlmul >> 2) ? 0b11111000 | vlmul : vlmul;
return pow(2, signed_vlmul);
}
mask_bit_reference& mask_bit_reference::operator=(const bool new_value) {
*start = *start & ~(1U << pos) | static_cast<unsigned>(new_value) << pos;
return *this;
}
mask_bit_reference::mask_bit_reference(uint8_t* start, uint8_t pos)
: start(start)
, pos(pos) {
assert(pos < 8 && "Bit reference can only be initialized for bytes");
};
mask_bit_reference::operator bool() const { return *(start) & (1U << (pos)); }
mask_bit_reference vmask_view::operator[](size_t idx) const {
assert(idx < elem_count);
return {start + idx / 8, static_cast<uint8_t>(idx % 8)};
}
vmask_view read_vmask(uint8_t* V, uint16_t VLEN, uint16_t elem_count, uint8_t reg_idx) {
uint8_t* mask_start = V + VLEN / 8 * reg_idx;
assert(mask_start + elem_count / 8 <= V + VLEN * RFS / 8);
return {mask_start, elem_count};
}
uint8_t xt2(uint8_t x) { return (x << 1) ^ (bit_sub<7, 1>(x) ? 27 : 0); }
uint8_t xt3(uint8_t x) { return x ^ xt2(x); }
uint8_t gfmul(uint8_t x, uint8_t y) {
return (bit_sub<0, 1>(y) ? x : 0) ^ (bit_sub<1, 1>(y) ? xt2(x) : 0) ^ (bit_sub<2, 1>(y) ? xt2(xt2(x)) : 0) ^
(bit_sub<3, 1>(y) ? xt2(xt2(xt2(x))) : 0);
}
uint32_t aes_mixcolumn_byte_fwd(uint8_t so) {
return ((uint32_t)gfmul(so, 3) << 24) | ((uint32_t)so << 16) | ((uint32_t)so << 8) | gfmul(so, 2);
}
uint32_t aes_mixcolumn_byte_inv(uint8_t so) {
return ((uint32_t)gfmul(so, 11) << 24) | ((uint32_t)gfmul(so, 13) << 16) | ((uint32_t)gfmul(so, 9) << 8) | gfmul(so, 14);
}
uint32_t aes_mixcolumn_fwd(uint32_t x) {
uint8_t s0 = bit_sub<0, 7 - 0 + 1>(x);
uint8_t s1 = bit_sub<8, 15 - 8 + 1>(x);
uint8_t s2 = bit_sub<16, 23 - 16 + 1>(x);
uint8_t s3 = bit_sub<24, 31 - 24 + 1>(x);
uint8_t b0 = xt2(s0) ^ xt3(s1) ^ (s2) ^ (s3);
uint8_t b1 = (s0) ^ xt2(s1) ^ xt3(s2) ^ (s3);
uint8_t b2 = (s0) ^ (s1) ^ xt2(s2) ^ xt3(s3);
uint8_t b3 = xt3(s0) ^ (s1) ^ (s2) ^ xt2(s3);
return ((uint32_t)b3 << 24) | ((uint32_t)b2 << 16) | ((uint32_t)b1 << 8) | b0;
}
uint32_t aes_mixcolumn_inv(uint32_t x) {
uint8_t s0 = bit_sub<0, 7 - 0 + 1>(x);
uint8_t s1 = bit_sub<8, 15 - 8 + 1>(x);
uint8_t s2 = bit_sub<16, 23 - 16 + 1>(x);
uint8_t s3 = bit_sub<24, 31 - 24 + 1>(x);
uint8_t b0 = gfmul(s0, 14) ^ gfmul(s1, 11) ^ gfmul(s2, 13) ^ gfmul(s3, 9);
uint8_t b1 = gfmul(s0, 9) ^ gfmul(s1, 14) ^ gfmul(s2, 11) ^ gfmul(s3, 13);
uint8_t b2 = gfmul(s0, 13) ^ gfmul(s1, 9) ^ gfmul(s2, 14) ^ gfmul(s3, 11);
uint8_t b3 = gfmul(s0, 11) ^ gfmul(s1, 13) ^ gfmul(s2, 9) ^ gfmul(s3, 14);
return ((uint32_t)b3 << 24) | ((uint32_t)b2 << 16) | ((uint32_t)b1 << 8) | b0;
}
uint32_t aes_decode_rcon(uint8_t r) {
switch(r) {
case 0:
return 1;
case 1:
return 2;
case 2:
return 4;
case 3:
return 8;
case 4:
return 16;
case 5:
return 32;
case 6:
return 64;
case 7:
return 128;
case 8:
return 27;
case 9:
return 54;
}
return 0;
}
uint32_t aes_subword_fwd(uint32_t x) {
return ((uint32_t)aes_sbox_fwd(bit_sub<24, 31 - 24 + 1>(x)) << 24) | ((uint32_t)aes_sbox_fwd(bit_sub<16, 23 - 16 + 1>(x)) << 16) |
((uint32_t)aes_sbox_fwd(bit_sub<8, 15 - 8 + 1>(x)) << 8) | aes_sbox_fwd(bit_sub<0, 7 - 0 + 1>(x));
}
uint32_t aes_subword_inv(uint32_t x) {
return ((uint32_t)aes_sbox_inv(bit_sub<24, 31 - 24 + 1>(x)) << 24) | ((uint32_t)aes_sbox_inv(bit_sub<16, 23 - 16 + 1>(x)) << 16) |
((uint32_t)aes_sbox_inv(bit_sub<8, 15 - 8 + 1>(x)) << 8) | aes_sbox_inv(bit_sub<0, 7 - 0 + 1>(x));
}
uint32_t aes_get_column(__uint128_t state, unsigned c) {
assert(c < 4);
return static_cast<uint32_t>(state >> (32 * c));
};
uint64_t aes_apply_fwd_sbox_to_each_byte(uint64_t x) {
return ((uint64_t)aes_sbox_fwd(bit_sub<56, 63 - 56 + 1>(x)) << 56) | ((uint64_t)aes_sbox_fwd(bit_sub<48, 55 - 48 + 1>(x)) << 48) |
((uint64_t)aes_sbox_fwd(bit_sub<40, 47 - 40 + 1>(x)) << 40) | ((uint64_t)aes_sbox_fwd(bit_sub<32, 39 - 32 + 1>(x)) << 32) |
((uint64_t)aes_sbox_fwd(bit_sub<24, 31 - 24 + 1>(x)) << 24) | ((uint64_t)aes_sbox_fwd(bit_sub<16, 23 - 16 + 1>(x)) << 16) |
((uint64_t)aes_sbox_fwd(bit_sub<8, 15 - 8 + 1>(x)) << 8) | aes_sbox_fwd(bit_sub<0, 7 - 0 + 1>(x));
}
uint64_t aes_apply_inv_sbox_to_each_byte(uint64_t x) {
return ((uint64_t)aes_sbox_inv(bit_sub<56, 63 - 56 + 1>(x)) << 56) | ((uint64_t)aes_sbox_inv(bit_sub<48, 55 - 48 + 1>(x)) << 48) |
((uint64_t)aes_sbox_inv(bit_sub<40, 47 - 40 + 1>(x)) << 40) | ((uint64_t)aes_sbox_inv(bit_sub<32, 39 - 32 + 1>(x)) << 32) |
((uint64_t)aes_sbox_inv(bit_sub<24, 31 - 24 + 1>(x)) << 24) | ((uint64_t)aes_sbox_inv(bit_sub<16, 23 - 16 + 1>(x)) << 16) |
((uint64_t)aes_sbox_inv(bit_sub<8, 15 - 8 + 1>(x)) << 8) | aes_sbox_inv(bit_sub<0, 7 - 0 + 1>(x));
}
uint64_t aes_rv64_shiftrows_fwd(uint64_t rs2, uint64_t rs1) {
return ((uint64_t)bit_sub<24, 31 - 24 + 1>(rs1) << 56) | ((uint64_t)bit_sub<48, 55 - 48 + 1>(rs2) << 48) |
((uint64_t)bit_sub<8, 15 - 8 + 1>(rs2) << 40) | ((uint64_t)bit_sub<32, 39 - 32 + 1>(rs1) << 32) |
((uint64_t)bit_sub<56, 63 - 56 + 1>(rs2) << 24) | ((uint64_t)bit_sub<16, 23 - 16 + 1>(rs2) << 16) |
((uint64_t)bit_sub<40, 47 - 40 + 1>(rs1) << 8) | bit_sub<0, 7 - 0 + 1>(rs1);
}
uint64_t aes_rv64_shiftrows_inv(uint64_t rs2, uint64_t rs1) {
return ((uint64_t)bit_sub<24, 31 - 24 + 1>(rs2) << 56) | ((uint64_t)bit_sub<48, 55 - 48 + 1>(rs2) << 48) |
((uint64_t)bit_sub<8, 15 - 8 + 1>(rs1) << 40) | ((uint64_t)bit_sub<32, 39 - 32 + 1>(rs1) << 32) |
((uint64_t)bit_sub<56, 63 - 56 + 1>(rs1) << 24) | ((uint64_t)bit_sub<16, 23 - 16 + 1>(rs2) << 16) |
((uint64_t)bit_sub<40, 47 - 40 + 1>(rs2) << 8) | bit_sub<0, 7 - 0 + 1>(rs1);
}
uint128_t aes_shift_rows_fwd(uint128_t x) {
uint32_t ic3 = aes_get_column(x, 3);
uint32_t ic2 = aes_get_column(x, 2);
uint32_t ic1 = aes_get_column(x, 1);
uint32_t ic0 = aes_get_column(x, 0);
uint32_t oc0 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic3) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic2) << 16) |
((uint32_t)bit_sub<8, 15 - 8 + 1>(ic1) << 8) | bit_sub<0, 7 - 0 + 1>(ic0);
uint32_t oc1 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic0) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic3) << 16) |
((uint32_t)bit_sub<8, 15 - 8 + 1>(ic2) << 8) | bit_sub<0, 7 - 0 + 1>(ic1);
uint32_t oc2 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic1) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic0) << 16) |
((uint32_t)bit_sub<8, 15 - 8 + 1>(ic3) << 8) | bit_sub<0, 7 - 0 + 1>(ic2);
uint32_t oc3 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic2) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic1) << 16) |
((uint32_t)bit_sub<8, 15 - 8 + 1>(ic0) << 8) | bit_sub<0, 7 - 0 + 1>(ic3);
return ((uint128_t)oc3 << 96) | ((uint128_t)oc2 << 64) | ((uint128_t)oc1 << 32) | oc0;
}
uint128_t aes_shift_rows_inv(uint128_t x) {
uint32_t ic3 = aes_get_column(x, 3);
uint32_t ic2 = aes_get_column(x, 2);
uint32_t ic1 = aes_get_column(x, 1);
uint32_t ic0 = aes_get_column(x, 0);
uint32_t oc0 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic1) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic2) << 16) |
((uint32_t)bit_sub<8, 15 - 8 + 1>(ic3) << 8) | bit_sub<0, 7 - 0 + 1>(ic0);
uint32_t oc1 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic2) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic3) << 16) |
((uint32_t)bit_sub<8, 15 - 8 + 1>(ic0) << 8) | bit_sub<0, 7 - 0 + 1>(ic1);
uint32_t oc2 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic3) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic0) << 16) |
((uint32_t)bit_sub<8, 15 - 8 + 1>(ic1) << 8) | bit_sub<0, 7 - 0 + 1>(ic2);
uint32_t oc3 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic0) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic1) << 16) |
((uint32_t)bit_sub<8, 15 - 8 + 1>(ic2) << 8) | bit_sub<0, 7 - 0 + 1>(ic3);
return ((uint128_t)oc3 << 96) | ((uint128_t)oc2 << 64) | ((uint128_t)oc1 << 32) | oc0;
}
uint128_t aes_subbytes_fwd(uint128_t x) {
uint32_t oc0 = aes_subword_fwd(aes_get_column(x, 0));
uint32_t oc1 = aes_subword_fwd(aes_get_column(x, 1));
uint32_t oc2 = aes_subword_fwd(aes_get_column(x, 2));
uint32_t oc3 = aes_subword_fwd(aes_get_column(x, 3));
return ((uint128_t)oc3 << 96) | ((uint128_t)oc2 << 64) | ((uint128_t)oc1 << 32) | oc0;
}
uint128_t aes_subbytes_inv(uint128_t x) {
uint32_t oc0 = aes_subword_inv(aes_get_column(x, 0));
uint32_t oc1 = aes_subword_inv(aes_get_column(x, 1));
uint32_t oc2 = aes_subword_inv(aes_get_column(x, 2));
uint32_t oc3 = aes_subword_inv(aes_get_column(x, 3));
return ((uint128_t)oc3 << 96) | ((uint128_t)oc2 << 64) | ((uint128_t)oc1 << 32) | oc0;
}
uint128_t aes_mixcolumns_fwd(uint128_t x) {
uint32_t oc0 = aes_mixcolumn_fwd(aes_get_column(x, 0));
uint32_t oc1 = aes_mixcolumn_fwd(aes_get_column(x, 1));
uint32_t oc2 = aes_mixcolumn_fwd(aes_get_column(x, 2));
uint32_t oc3 = aes_mixcolumn_fwd(aes_get_column(x, 3));
return ((uint128_t)oc3 << 96) | ((uint128_t)oc2 << 64) | ((uint128_t)oc1 << 32) | oc0;
}
uint128_t aes_mixcolumns_inv(uint128_t x) {
uint32_t oc0 = aes_mixcolumn_inv(aes_get_column(x, 0));
uint32_t oc1 = aes_mixcolumn_inv(aes_get_column(x, 1));
uint32_t oc2 = aes_mixcolumn_inv(aes_get_column(x, 2));
uint32_t oc3 = aes_mixcolumn_inv(aes_get_column(x, 3));
return ((uint128_t)oc3 << 96) | ((uint128_t)oc2 << 64) | ((uint128_t)oc1 << 32) | oc0;
}
uint32_t aes_rotword(uint32_t x) {
uint8_t a0 = bit_sub<0, 7 - 0 + 1>(x);
uint8_t a1 = bit_sub<8, 15 - 8 + 1>(x);
uint8_t a2 = bit_sub<16, 23 - 16 + 1>(x);
uint8_t a3 = bit_sub<24, 31 - 24 + 1>(x);
return ((uint32_t)a0 << 24) | ((uint32_t)a3 << 16) | ((uint32_t)a2 << 8) | a1;
}
std::function<uint128_t(uint128_t, uint128_t, uint128_t)> get_crypto_funct(unsigned funct6, unsigned vs1) {
switch(funct6) {
case 0b101000: // VAES.VV
case 0b101001: // VAES.VS
switch(vs1) {
case 0b00000: // VAESDM
return [](uint128_t state, uint128_t rkey, uint128_t) {
uint128_t sr = aes_shift_rows_inv(state);
uint128_t sb = aes_subbytes_inv(sr);
uint128_t ark = sb ^ rkey;
uint128_t mix = aes_mixcolumns_inv(ark);
return mix;
};
case 0b00001: // VAESDF
return [](uint128_t state, uint128_t rkey, uint128_t) {
uint128_t sr = aes_shift_rows_inv(state);
uint128_t sb = aes_subbytes_inv(sr);
uint128_t ark = sb ^ rkey;
return ark;
};
case 0b00010: // VAESEM
return [](uint128_t state, uint128_t rkey, uint128_t) {
uint128_t sb = aes_subbytes_fwd(state);
uint128_t sr = aes_shift_rows_fwd(sb);
uint128_t mix = aes_mixcolumns_fwd(sr);
uint128_t ark = mix ^ rkey;
return ark;
};
case 0b00011: // VAESEF
return [](uint128_t state, uint128_t rkey, uint128_t) {
uint128_t sb = aes_subbytes_fwd(state);
uint128_t sr = aes_shift_rows_fwd(sb);
uint128_t ark = sr ^ rkey;
return ark;
};
case 0b00111: // VAESZ
return [](uint128_t state, uint128_t rkey, uint128_t) {
uint128_t ark = state ^ rkey;
return ark;
};
case 0b10000: // VSM4R
throw new std::runtime_error("Unsupported operation in get_crypto_funct");
case 0b10001: // VGMUL
return [](uint128_t vd, uint128_t vs2, uint128_t) {
uint128_t Y = brev8<uint128_t>(vd);
uint128_t H = brev8<uint128_t>(vs2);
uint128_t Z = 0;
for(size_t bit = 0; bit < 128; bit++) {
if((Y >> bit) & 1)
Z ^= H;
bool reduce = (H >> 127) & 1;
H = H << 1;
if(reduce)
H ^= 0x87;
}
uint128_t result = brev8<uint128_t>(Z);
return result;
};
default:
throw new std::runtime_error("Unsupported operation in get_crypto_funct");
}
case 0b100000: // VSM3ME
case 0b100001: // VSM4K
throw new std::runtime_error("Unsupported operation in get_crypto_funct");
case 0b100010: // VAESKF1
return [](uint128_t vd, uint128_t vs2, uint128_t r) {
auto extract_word = [](const uint128_t& value, int index) -> uint32_t {
return static_cast<uint32_t>((value >> (32 * index)) & std::numeric_limits<uint32_t>::max());
};
uint32_t k0 = (vs2 >> 32 * 0) & std::numeric_limits<uint32_t>::max();
uint32_t k1 = (vs2 >> 32 * 1) & std::numeric_limits<uint32_t>::max();
uint32_t k2 = (vs2 >> 32 * 2) & std::numeric_limits<uint32_t>::max();
uint32_t k3 = (vs2 >> 32 * 3) & std::numeric_limits<uint32_t>::max();
uint32_t w0 = aes_subword_fwd(aes_rotword(k3)) ^ aes_decode_rcon(r) ^ k0;
uint32_t w1 = w0 ^ k1;
uint32_t w2 = w1 ^ k2;
uint32_t w3 = w2 ^ k3;
uint128_t result = (uint128_t(w3) << 96) | (uint128_t(w2) << 64) | (uint128_t(w1) << 32) | (uint128_t(w0));
return result;
};
case 0b101010: // VAESKF2
return [](uint128_t vd, uint128_t vs2, uint128_t r) {
uint32_t k0 = (vs2 >> 32 * 0) & std::numeric_limits<uint32_t>::max();
uint32_t k1 = (vs2 >> 32 * 1) & std::numeric_limits<uint32_t>::max();
uint32_t k2 = (vs2 >> 32 * 2) & std::numeric_limits<uint32_t>::max();
uint32_t k3 = (vs2 >> 32 * 3) & std::numeric_limits<uint32_t>::max();
uint32_t rkb0 = (vd >> 32 * 0) & std::numeric_limits<uint32_t>::max();
uint32_t rkb1 = (vd >> 32 * 1) & std::numeric_limits<uint32_t>::max();
uint32_t rkb2 = (vd >> 32 * 2) & std::numeric_limits<uint32_t>::max();
uint32_t rkb3 = (vd >> 32 * 3) & std::numeric_limits<uint32_t>::max();
uint32_t w0 = r & 1 ? aes_subword_fwd(k3) ^ rkb0 : aes_subword_fwd(aes_rotword(k3)) ^ aes_decode_rcon((r >> 1) - 1) ^ rkb0;
uint32_t w1 = w0 ^ rkb1;
uint32_t w2 = w1 ^ rkb2;
uint32_t w3 = w2 ^ rkb3;
uint128_t result = (uint128_t(w3) << 96) | (uint128_t(w2) << 64) | (uint128_t(w1) << 32) | (uint128_t(w0));
return result;
};
case 0b101011: // VSM3C
throw new std::runtime_error("Unsupported operation in get_crypto_funct");
case 0b101100: // VGHSH
return [](uint128_t Y, uint128_t vs2, uint128_t X) {
auto H = brev8<uint128_t>(vs2);
uint128_t Z = 0;
uint128_t S = brev8<uint128_t>(Y ^ X);
for(size_t bit = 0; bit < 128; bit++) {
if((S >> bit) & 1)
Z ^= H;
bool reduce = (H >> 127) & 1;
H = H << 1;
if(reduce)
H ^= 0x87;
}
uint128_t result = brev8<uint128_t>(Z);
return result;
};
case 0b101101: // VSHA2MS
case 0b101110: // VSHA2CH
case 0b101111: // VSHA2CL
default:
throw new std::runtime_error("Unknown funct6 in get_crypto_funct");
}
}
} // namespace softvector
+192
View File
@@ -0,0 +1,192 @@
////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2025, MINRES Technologies GmbH
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Contributors:
// alex@minres.com - initial API and implementation
////////////////////////////////////////////////////////////////////////////////
#ifndef _VM_VECTOR_FUNCTIONS_H_
#define _VM_VECTOR_FUNCTIONS_H_
#include "iss/arch_if.h"
#include "iss/vm_types.h"
#include <cstdint>
#include <functional>
#include <stdint.h>
namespace softvector {
#ifndef _MSC_VER
using int128_t = __int128;
using uint128_t = unsigned __int128;
#endif
const unsigned RFS = 32;
struct vtype_t {
uint64_t underlying;
vtype_t(uint32_t vtype_val);
vtype_t(uint64_t vtype_val);
unsigned sew();
double lmul();
bool vill();
bool vma();
bool vta();
};
class mask_bit_reference {
uint8_t* start;
uint8_t pos;
public:
mask_bit_reference& operator=(const bool new_value);
mask_bit_reference(uint8_t* start, uint8_t pos);
operator bool() const;
};
struct vmask_view {
uint8_t* start;
size_t elem_count;
mask_bit_reference operator[](size_t) const;
};
vmask_view read_vmask(uint8_t* V, uint16_t VLEN, uint16_t elem_count, uint8_t reg_idx = 0);
template <unsigned VLEN> vmask_view read_vmask(uint8_t* V, uint16_t elem_count, uint8_t reg_idx = 0);
std::function<uint128_t(uint128_t, uint128_t, uint128_t)> get_crypto_funct(unsigned funct6, unsigned vs1);
template <typename dest_elem_t, typename src_elem_t = dest_elem_t> dest_elem_t brev(src_elem_t vs2);
template <typename dest_elem_t, typename src_elem_t = dest_elem_t> dest_elem_t brev8(src_elem_t vs2);
bool softvec_read(void* core, uint64_t addr, uint64_t length, uint8_t* data);
bool softvec_write(void* core, uint64_t addr, uint64_t length, uint8_t* data);
template <unsigned VLEN, typename eew_t>
uint64_t vector_load_store(void* core, std::function<bool(void*, uint64_t, uint64_t, uint8_t*)> load_store_fn, uint8_t* V, uint64_t vl,
uint64_t vstart, vtype_t vtype, bool vm, uint8_t vd, uint64_t rs1, uint8_t segment_size, int64_t stride = 0,
bool use_stride = false);
template <unsigned XLEN, unsigned VLEN, typename eew_t, typename sew_t>
uint64_t vector_load_store_index(void* core, std::function<bool(void*, uint64_t, uint64_t, uint8_t*)> load_store_fn, uint8_t* V,
uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, uint8_t vd, uint64_t rs1, uint8_t vs2,
uint8_t segment_size);
template <unsigned VLEN, typename dest_elem_t, typename src2_elem_t = dest_elem_t, typename src1_elem_t = src2_elem_t>
void vector_vector_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd,
unsigned vs2, unsigned vs1);
template <unsigned VLEN, typename dest_elem_t, typename src2_elem_t = dest_elem_t, typename src1_elem_t = src2_elem_t>
void vector_imm_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd,
unsigned vs2, typename std::make_signed<src1_elem_t>::type imm);
template <unsigned VLEN, typename elem_t>
void vector_vector_carry(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, unsigned vd,
unsigned vs2, unsigned vs1, signed carry);
template <unsigned VLEN, typename elem_t>
void vector_imm_carry(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, unsigned vd, unsigned vs2,
typename std::make_signed<elem_t>::type imm, signed carry);
template <unsigned VLEN, typename scr_elem_t>
void vector_vector_merge(uint8_t* V, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2, unsigned vs1);
template <unsigned VLEN, typename scr_elem_t>
void vector_imm_merge(uint8_t* V, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2, uint64_t imm);
template <unsigned VLEN, typename dest_elem_t, typename src2_elem_t = dest_elem_t>
void vector_unary_op(uint8_t* V, unsigned unary_op, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2);
template <unsigned VLEN, typename elem_t>
void mask_vector_vector_op(uint8_t* V, unsigned funct, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd,
unsigned vs2, unsigned vs1);
template <unsigned VLEN, typename elem_t>
void mask_vector_imm_op(uint8_t* V, unsigned funct, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd,
unsigned vs2, typename std::make_signed<elem_t>::type imm);
void carry_vector_vector_op(uint8_t* V, unsigned funct, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2,
unsigned vs1);
template <unsigned VLEN, typename elem_t>
void carry_vector_imm_op(uint8_t* V, unsigned funct, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2,
typename std::make_signed<elem_t>::type imm);
template <unsigned VLEN, typename dest_elem_t, typename src2_elem_t = dest_elem_t, typename src1_elem_t = dest_elem_t>
bool sat_vector_vector_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, int64_t vxrm, bool vm,
unsigned vd, unsigned vs2, unsigned vs1);
template <unsigned VLEN, typename dest_elem_t, typename src2_elem_t = dest_elem_t, typename src1_elem_t = dest_elem_t>
bool sat_vector_imm_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, int64_t vxrm, bool vm,
unsigned vd, unsigned vs2, typename std::make_signed<src1_elem_t>::type imm);
template <unsigned VLEN, typename dest_elem_t, typename src_elem_t = dest_elem_t>
void vector_red_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd,
unsigned vs2, unsigned vs1);
template <unsigned VLEN>
void mask_mask_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, unsigned vd, unsigned vs2, unsigned vs1);
template <unsigned VLEN> uint64_t vcpop(uint8_t* V, uint64_t vl, uint64_t vstart, bool vm, unsigned vs2);
template <unsigned VLEN> uint64_t vfirst(uint8_t* V, uint64_t vl, uint64_t vstart, bool vm, unsigned vs2);
template <unsigned VLEN> void mask_set_op(uint8_t* V, unsigned enc, uint64_t vl, uint64_t vstart, bool vm, unsigned vd, unsigned vs2);
template <unsigned VLEN, typename src_elem_t>
void viota(uint8_t* V, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2);
template <unsigned VLEN, typename src_elem_t> void vid(uint8_t* V, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd);
template <unsigned VLEN, typename src_elem_t> uint64_t scalar_move(uint8_t* V, vtype_t vtype, unsigned vd, uint64_t val, bool to_vector);
template <unsigned VLEN, typename src_elem_t>
void vector_slideup(uint8_t* V, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2, uint64_t imm);
template <unsigned VLEN, typename src_elem_t>
void vector_slidedown(uint8_t* V, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2, uint64_t imm);
template <unsigned VLEN, typename src_elem_t>
void vector_slide1up(uint8_t* V, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2, uint64_t imm);
template <unsigned VLEN, typename src_elem_t>
void vector_slide1down(uint8_t* V, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2, uint64_t imm);
template <unsigned VLEN, typename dest_elem_t, typename scr_elem_t = dest_elem_t>
void vector_vector_gather(uint8_t* V, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2, unsigned vs1);
template <unsigned VLEN, typename scr_elem_t>
void vector_imm_gather(uint8_t* V, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2, uint64_t imm);
template <unsigned VLEN, typename scr_elem_t>
void vector_compress(uint8_t* V, uint64_t vl, uint64_t vstart, vtype_t vtype, unsigned vd, unsigned vs2, unsigned vs1);
template <unsigned VLEN> void vector_whole_move(uint8_t* V, unsigned vd, unsigned vs2, unsigned count);
template <unsigned VLEN, typename dest_elem_t, typename src_elem_t = dest_elem_t>
void fp_vector_red_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd,
unsigned vs2, unsigned vs1, uint8_t rm);
template <unsigned VLEN, typename dest_elem_t, typename src2_elem_t = dest_elem_t, typename src1_elem_t = src2_elem_t>
void fp_vector_vector_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd,
unsigned vs2, unsigned vs1, uint8_t rm);
template <unsigned VLEN, typename dest_elem_t, typename src2_elem_t = dest_elem_t, typename src1_elem_t = src2_elem_t>
void fp_vector_imm_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd,
unsigned vs2, src1_elem_t imm, uint8_t rm);
template <unsigned VLEN, typename elem_t>
void fp_vector_unary_op(uint8_t* V, unsigned encoding_space, unsigned unary_op, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm,
unsigned vd, unsigned vs2, uint8_t rm);
template <unsigned VLEN, typename dest_elem_t, typename src_elem_t>
void fp_vector_unary_w(uint8_t* V, unsigned unary_op, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2,
uint8_t rm);
template <unsigned VLEN, typename dest_elem_t, typename src_elem_t>
void fp_vector_unary_n(uint8_t* V, unsigned unary_op, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2,
uint8_t rm);
template <unsigned VLEN, typename elem_t>
void mask_fp_vector_vector_op(uint8_t* V, unsigned funct6, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2,
unsigned vs1, uint8_t rm);
template <unsigned VLEN, typename elem_t>
void mask_fp_vector_imm_op(uint8_t* V, unsigned funct6, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2,
elem_t imm, uint8_t rm);
template <unsigned VLEN, unsigned EGS>
void vector_vector_crypto(uint8_t* V, unsigned funct6, uint64_t eg_len, uint64_t eg_start, vtype_t vtype, unsigned vd, unsigned vs2,
unsigned vs1);
template <unsigned VLEN, unsigned EGS>
void vector_scalar_crypto(uint8_t* V, unsigned funct6, uint64_t eg_len, uint64_t eg_start, vtype_t vtype, unsigned vd, unsigned vs2,
unsigned vs1);
template <unsigned VLEN, unsigned EGS>
void vector_imm_crypto(uint8_t* V, unsigned funct6, uint64_t eg_len, uint64_t eg_start, vtype_t vtype, unsigned vd, unsigned vs2,
uint8_t imm);
template <unsigned VLEN, unsigned EGS, typename elem_type_t>
void vector_crypto(uint8_t* V, unsigned funct6, uint64_t eg_len, uint64_t eg_start, vtype_t vtype, unsigned vd, unsigned vs2, unsigned vs1);
} // namespace softvector
#include "vm/vector_functions.hpp"
#endif /* _VM_VECTOR_FUNCTIONS_H_ */
File diff suppressed because it is too large. Load diff