diff --git a/gen_input/CoreDSL-Instruction-Set-Description b/gen_input/CoreDSL-Instruction-Set-Description index 5f78c1f..3cfac1d 160000 --- a/gen_input/CoreDSL-Instruction-Set-Description +++ b/gen_input/CoreDSL-Instruction-Set-Description @@ -1 +1 @@ -Subproject commit 5f78c1fd8965170d418afc55605a94dc0ef4dd75 +Subproject commit 3cfac1d86f6532140a04cdfc1501f1b8f3729632 diff --git a/gen_input/templates/interp/CORENAME.h.gtl b/gen_input/templates/interp/CORENAME.h.gtl index 67d4714..69699b9 100644 --- a/gen_input/templates/interp/CORENAME.h.gtl +++ b/gen_input/templates/interp/CORENAME.h.gtl @@ -31,21 +31,28 @@ *******************************************************************************/ <% def getRegisterSizes(){ - def regs = registers.collect{it.size} - regs[-1]=pc.size // correct for NEXT_PC - regs+=[32, 32, 32, 32, 64] // append TRAP_STATE, PENDING_TRAP, MACHINE_STATE, LAST_BRANCH, ICOUNT + def regs = registers.collect{it.size} + regs[-1]=pc.size // correct for NEXT_PC + regs+=[32, 32, 32, 32, 64] // append TRAP_STATE, PENDING_TRAP, MACHINE_STATE, LAST_BRANCH, ICOUNT return regs } def getRegisterOffsets(){ - def regs = registers.collect{it.offset} - def offs= regs[-1] - // append TRAP_STATE, PENDING_TRAP, MACHINE_STATE, LAST_BRANCH, ICOUNT offsets starting with NEXT_PC size - [pc.size/8, 4, 4, 4, 4].each{ sz -> - regs+=offs+sz - offs+=sz - } + def regs = registers.collect{it.offset} + def offs= regs[-1] + // append TRAP_STATE, PENDING_TRAP, MACHINE_STATE, LAST_BRANCH, ICOUNT offsets starting with NEXT_PC size + [pc.size/8, 4, 4, 4, 4].each{ sz -> + regs+=offs+sz + offs+=sz + } return regs } +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; +} %> #ifndef _${coreDef.name.toUpperCase()}_H_ #define _${coreDef.name.toUpperCase()}_H_ @@ -62,20 +69,20 @@ struct ${coreDef.name.toLowerCase()}; template <> struct traits<${coreDef.name.toLowerCase()}> { - constexpr static char const* const core_type = "${coreDef.name}"; + constexpr static char const* const core_type = "${coreDef.name}"; - static constexpr std::array reg_names{ - {"${registers.collect{it.name}.join('", "')}"}}; + static constexpr std::array reg_names{ + {"${registers.collect{it.name}.join('", "')}"}}; - static constexpr std::array reg_aliases{ - {"${registers.collect{it.alias}.join('", "')}"}}; + static constexpr std::array reg_aliases{ + {"${registers.collect{it.alias}.join('", "')}"}}; enum constants {${constants.collect{c -> c.name+"="+c.value}.join(', ')}}; constexpr static unsigned FP_REGS_SIZE = ${constants.find {it.name=='FLEN'}?.value?:0}; enum reg_e {<% - registers.each { reg -> %> + registers.each { reg -> %> ${reg.name},<% }%> NEXT_${pc.name}=NUM_REGS, @@ -96,17 +103,22 @@ template <> struct traits<${coreDef.name.toLowerCase()}> { using phys_addr_t = iss::typed_addr_t; - static constexpr std::array reg_bit_widths{ - {${getRegisterSizes().join(',')}}}; + static constexpr std::array reg_bit_widths{ + {${getRegisterSizes().join(',')}}}; static constexpr std::array reg_byte_offsets{ - {${getRegisterOffsets().join(',')}}}; + {${getRegisterOffsets().join(',')}}}; static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); enum sreg_flag_e { FLAGS }; enum mem_type_e { ${spaces.collect{it.name}.join(', ')} }; + + enum class opcode_e : unsigned short {<%instructions.eachWithIndex{instr, index -> %> + ${instr.instruction.name} = ${index},<%}%> + MAX_OPCODE + }; }; struct ${coreDef.name.toLowerCase()}: public arch_if { @@ -153,10 +165,10 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { protected: struct ${coreDef.name}_regs {<% - registers.each { reg -> if(reg.size>0) {%> - uint${reg.size}_t ${reg.name} = 0;<% + registers.each { reg -> if(reg.size>0) {%> + uint${byteSize(reg.size)}_t ${reg.name} = 0;<% }}%> - uint${pc.size}_t NEXT_${pc.name} = 0; + uint${byteSize(pc.size)}_t NEXT_${pc.name} = 0; uint32_t trap_state = 0, pending_trap = 0, machine_state = 0, last_branch = 0; uint64_t icount = 0; } reg; @@ -167,11 +179,11 @@ protected: <% def fcsr = registers.find {it.name=='FCSR'} if(fcsr != null) {%> - uint${fcsr.size}_t get_fcsr(){return reg.FCSR;} - void set_fcsr(uint${fcsr.size}_t val){reg.FCSR = val;} + uint${fcsr.size}_t get_fcsr(){return reg.FCSR;} + void set_fcsr(uint${fcsr.size}_t val){reg.FCSR = val;} <%} else { %> - uint32_t get_fcsr(){return 0;} - void set_fcsr(uint32_t val){} + uint32_t get_fcsr(){return 0;} + void set_fcsr(uint32_t val){} <%}%> }; diff --git a/incl/iss/arch/tgf_b.h b/incl/iss/arch/tgf_b.h index eeaba8d..d47e9cb 100644 --- a/incl/iss/arch/tgf_b.h +++ b/incl/iss/arch/tgf_b.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2017, 2018 MINRES Technologies GmbH + * Copyright (C) 2017 - 2020 MINRES Technologies GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,7 +30,6 @@ * *******************************************************************************/ - #ifndef _TGF_B_H_ #define _TGF_B_H_ @@ -46,15 +45,15 @@ struct tgf_b; template <> struct traits { - constexpr static char const* const core_type = "TGF_B"; + constexpr static char const* const core_type = "TGF_B"; - static constexpr std::array reg_names{ - {"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"}}; + static constexpr std::array reg_names{ + {"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", "PRIV", "NUM_REGS"}}; - static constexpr std::array 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"}}; + static constexpr std::array reg_aliases{ + {"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", "PRIV", "NUM_REGS"}}; - enum constants {XLEN=32, PCLEN=32, MISA_VAL=0b1000000000000000000000100000000, PGSIZE=0x1000, PGMASK=0xfff}; + enum constants {XLEN=32, PCLEN=32, MISA_VAL=0b1000000000000000000000100000000, PGSIZE=0x1000, PGMASK=0xfff, CSR_SIZE=4096, fence=0, fencei=1, fencevmal=2, fencevmau=3}; constexpr static unsigned FP_REGS_SIZE = 0; @@ -92,45 +91,14 @@ template <> struct traits { X30, X31, PC, + PRIV, NUM_REGS, NEXT_PC=NUM_REGS, TRAP_STATE, PENDING_TRAP, MACHINE_STATE, LAST_BRANCH, - ICOUNT, - ZERO = X0, - RA = X1, - SP = X2, - GP = X3, - TP = X4, - T0 = X5, - T1 = X6, - T2 = X7, - S0 = X8, - S1 = X9, - A0 = X10, - A1 = X11, - A2 = X12, - A3 = X13, - A4 = X14, - A5 = X15, - A6 = X16, - A7 = X17, - S2 = X18, - S3 = X19, - S4 = X20, - S5 = X21, - S6 = X22, - S7 = X23, - S8 = X24, - S9 = X25, - S10 = X26, - S11 = X27, - T3 = X28, - T4 = X29, - T5 = X30, - T6 = X31 + ICOUNT }; using reg_t = uint32_t; @@ -143,17 +111,73 @@ template <> struct traits { using phys_addr_t = iss::typed_addr_t; - static constexpr std::array reg_bit_widths{ - {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64}}; + static constexpr std::array reg_bit_widths{ + {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,2,32,32,32,32,32,64}}; static constexpr std::array reg_byte_offsets{ - {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,160}}; + {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,133,137,141,145,149,153}}; static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); enum sreg_flag_e { FLAGS }; enum mem_type_e { MEM, CSR, FENCE, RES }; + + enum class opcode_e : unsigned short { + LUI = 0, + AUIPC = 1, + JAL = 2, + JALR = 3, + BEQ = 4, + BNE = 5, + BLT = 6, + BGE = 7, + BLTU = 8, + BGEU = 9, + LB = 10, + LH = 11, + LW = 12, + LBU = 13, + LHU = 14, + SB = 15, + SH = 16, + SW = 17, + ADDI = 18, + SLTI = 19, + SLTIU = 20, + XORI = 21, + ORI = 22, + ANDI = 23, + SLLI = 24, + SRLI = 25, + SRAI = 26, + ADD = 27, + SUB = 28, + SLL = 29, + SLT = 30, + SLTU = 31, + XOR = 32, + SRL = 33, + SRA = 34, + OR = 35, + AND = 36, + FENCE = 37, + FENCE_I = 38, + ECALL = 39, + EBREAK = 40, + URET = 41, + SRET = 42, + MRET = 43, + WFI = 44, + SFENCE_VMA = 45, + CSRRW = 46, + CSRRS = 47, + CSRRC = 48, + CSRRWI = 49, + CSRRSI = 50, + CSRRCI = 51, + MAX_OPCODE + }; }; struct tgf_b: public arch_if { @@ -199,40 +223,41 @@ struct tgf_b: public arch_if { inline uint32_t get_last_branch() { return reg.last_branch; } protected: - struct TGF_B_regs { - uint32_t X0 = 0; - uint32_t X1 = 0; - uint32_t X2 = 0; - uint32_t X3 = 0; - uint32_t X4 = 0; - uint32_t X5 = 0; - uint32_t X6 = 0; - uint32_t X7 = 0; - uint32_t X8 = 0; - uint32_t X9 = 0; - uint32_t X10 = 0; - uint32_t X11 = 0; - uint32_t X12 = 0; - uint32_t X13 = 0; - uint32_t X14 = 0; - uint32_t X15 = 0; - uint32_t X16 = 0; - uint32_t X17 = 0; - uint32_t X18 = 0; - uint32_t X19 = 0; - uint32_t X20 = 0; - uint32_t X21 = 0; - uint32_t X22 = 0; - uint32_t X23 = 0; - uint32_t X24 = 0; - uint32_t X25 = 0; - uint32_t X26 = 0; - uint32_t X27 = 0; - uint32_t X28 = 0; - uint32_t X29 = 0; - uint32_t X30 = 0; - uint32_t X31 = 0; - uint32_t PC = 0; + struct TGF_B_regs { + uint32_t X0 = 0; + uint32_t X1 = 0; + uint32_t X2 = 0; + uint32_t X3 = 0; + uint32_t X4 = 0; + uint32_t X5 = 0; + uint32_t X6 = 0; + uint32_t X7 = 0; + uint32_t X8 = 0; + uint32_t X9 = 0; + uint32_t X10 = 0; + uint32_t X11 = 0; + uint32_t X12 = 0; + uint32_t X13 = 0; + uint32_t X14 = 0; + uint32_t X15 = 0; + uint32_t X16 = 0; + uint32_t X17 = 0; + uint32_t X18 = 0; + uint32_t X19 = 0; + uint32_t X20 = 0; + uint32_t X21 = 0; + uint32_t X22 = 0; + uint32_t X23 = 0; + uint32_t X24 = 0; + uint32_t X25 = 0; + uint32_t X26 = 0; + uint32_t X27 = 0; + uint32_t X28 = 0; + uint32_t X29 = 0; + uint32_t X30 = 0; + uint32_t X31 = 0; + uint32_t PC = 0; + uint8_t PRIV = 0; uint32_t NEXT_PC = 0; uint32_t trap_state = 0, pending_trap = 0, machine_state = 0, last_branch = 0; uint64_t icount = 0; @@ -242,8 +267,8 @@ protected: uint64_t interrupt_sim=0; - uint32_t get_fcsr(){return 0;} - void set_fcsr(uint32_t val){} + uint32_t get_fcsr(){return 0;} + void set_fcsr(uint32_t val){} }; diff --git a/incl/iss/arch/tgf_c.h b/incl/iss/arch/tgf_c.h index 7978836..cee60b2 100644 --- a/incl/iss/arch/tgf_c.h +++ b/incl/iss/arch/tgf_c.h @@ -45,13 +45,13 @@ struct tgf_c; template <> struct traits { - constexpr static char const* const core_type = "TGF_C"; + constexpr static char const* const core_type = "TGF_C"; - static constexpr std::array reg_names{ - {"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", "PRIV", "NUM_REGS"}}; + static constexpr std::array reg_names{ + {"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", "PRIV", "NUM_REGS"}}; - static constexpr std::array reg_aliases{ - {"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", "PRIV", "NUM_REGS"}}; + static constexpr std::array reg_aliases{ + {"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", "PRIV", "NUM_REGS"}}; enum constants {XLEN=32, PCLEN=32, MISA_VAL=0b1000000000000000001000100000100, PGSIZE=0x1000, PGMASK=0xfff, CSR_SIZE=4096, fence=0, fencei=1, fencevmal=2, fencevmau=3, MUL_LEN=64}; @@ -111,17 +111,109 @@ template <> struct traits { using phys_addr_t = iss::typed_addr_t; - static constexpr std::array reg_bit_widths{ - {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,2,32,32,32,32,32,64}}; + static constexpr std::array reg_bit_widths{ + {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,2,32,32,32,32,32,64}}; static constexpr std::array reg_byte_offsets{ - {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,133,137,141,145,149,153}}; + {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,133,137,141,145,149,153}}; static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); enum sreg_flag_e { FLAGS }; enum mem_type_e { MEM, CSR, FENCE, RES }; + + enum class opcode_e : unsigned short { + LUI = 0, + AUIPC = 1, + JAL = 2, + JALR = 3, + BEQ = 4, + BNE = 5, + BLT = 6, + BGE = 7, + BLTU = 8, + BGEU = 9, + LB = 10, + LH = 11, + LW = 12, + LBU = 13, + LHU = 14, + SB = 15, + SH = 16, + SW = 17, + ADDI = 18, + SLTI = 19, + SLTIU = 20, + XORI = 21, + ORI = 22, + ANDI = 23, + SLLI = 24, + SRLI = 25, + SRAI = 26, + ADD = 27, + SUB = 28, + SLL = 29, + SLT = 30, + SLTU = 31, + XOR = 32, + SRL = 33, + SRA = 34, + OR = 35, + AND = 36, + FENCE = 37, + FENCE_I = 38, + ECALL = 39, + EBREAK = 40, + URET = 41, + SRET = 42, + MRET = 43, + WFI = 44, + SFENCE_VMA = 45, + CSRRW = 46, + CSRRS = 47, + CSRRC = 48, + CSRRWI = 49, + CSRRSI = 50, + CSRRCI = 51, + MUL = 52, + MULH = 53, + MULHSU = 54, + MULHU = 55, + DIV = 56, + DIVU = 57, + REM = 58, + REMU = 59, + CADDI4SPN = 60, + CLW = 61, + CSW = 62, + CADDI = 63, + CNOP = 64, + CJAL = 65, + CLI = 66, + CLUI = 67, + CADDI16SP = 68, + CSRLI = 69, + CSRAI = 70, + CANDI = 71, + CSUB = 72, + CXOR = 73, + COR = 74, + CAND = 75, + CJ = 76, + CBEQZ = 77, + CBNEZ = 78, + CSLLI = 79, + CLWSP = 80, + CMV = 81, + CJR = 82, + CADD = 83, + CJALR = 84, + CEBREAK = 85, + CSWSP = 86, + DII = 87, + MAX_OPCODE + }; }; struct tgf_c: public arch_if { @@ -211,8 +303,8 @@ protected: uint64_t interrupt_sim=0; - uint32_t get_fcsr(){return 0;} - void set_fcsr(uint32_t val){} + uint32_t get_fcsr(){return 0;} + void set_fcsr(uint32_t val){} }; diff --git a/src/iss/tgf_b.cpp b/src/iss/tgf_b.cpp index f757e84..17ad356 100644 --- a/src/iss/tgf_b.cpp +++ b/src/iss/tgf_b.cpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2017, 2018 MINRES Technologies GmbH + * Copyright (C) 2017 - 2020 MINRES Technologies GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. * *******************************************************************************/ - + #include "util/ities.h" #include #include @@ -39,9 +39,9 @@ using namespace iss::arch; -constexpr std::array iss::arch::traits::reg_names; -constexpr std::array iss::arch::traits::reg_aliases; -constexpr std::array iss::arch::traits::reg_bit_widths; +constexpr std::array iss::arch::traits::reg_names; +constexpr std::array iss::arch::traits::reg_aliases; +constexpr std::array iss::arch::traits::reg_bit_widths; constexpr std::array iss::arch::traits::reg_byte_offsets; tgf_b::tgf_b() { diff --git a/src/vm/interp/vm_tgf_b.cpp b/src/vm/interp/vm_tgf_b.cpp index 7b0987a..b0057b9 100644 --- a/src/vm/interp/vm_tgf_b.cpp +++ b/src/vm/interp/vm_tgf_b.cpp @@ -56,13 +56,14 @@ using namespace iss::debugger; template class vm_impl : public iss::interp::vm_base { public: - using super = typename iss::interp::vm_base; + using traits = arch::traits; + using super = typename iss::interp::vm_base; using virt_addr_t = typename super::virt_addr_t; using phys_addr_t = typename super::phys_addr_t; using code_word_t = typename super::code_word_t; - using addr_t = typename super::addr_t; - using reg_t = typename traits::reg_t; - using iss::interp::vm_base::get_reg; + using addr_t = typename super::addr_t; + using reg_t = typename traits::reg_t; + using mem_type_e = typename traits::mem_type_e; vm_impl(); @@ -82,7 +83,7 @@ protected: using compile_ret_t = virt_addr_t; using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr); - 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);} virt_addr_t execute_inst(virt_addr_t start, std::function pred) override; @@ -138,23 +139,31 @@ protected: return lut_val; } - void raise_trap(uint16_t trap_id, uint16_t cause){ + void raise(uint16_t trap_id, uint16_t cause){ auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; - this->template get_reg(arch::traits::TRAP_STATE) = trap_val; - this->template get_reg(arch::traits::NEXT_PC) = std::numeric_limits::max(); + this->template get_reg(traits::TRAP_STATE) = trap_val; + this->template get_reg(traits::NEXT_PC) = std::numeric_limits::max(); } - void leave_trap(unsigned lvl){ + void leave(unsigned lvl){ this->core.leave_trap(lvl); - auto pc_val = super::template read_mem(traits::CSR, (lvl << 8) + 0x41); - this->template get_reg(arch::traits::NEXT_PC) = pc_val; - this->template get_reg(arch::traits::LAST_BRANCH) = std::numeric_limits::max(); + auto pc_val = super::template read_mem(traits::CSR, (lvl << 8) + 0x41); + this->template get_reg(traits::NEXT_PC) = pc_val; + this->template get_reg(traits::LAST_BRANCH) = std::numeric_limits::max(); } void wait(unsigned type){ this->core.wait_until(type); } + inline uint8_t readSpace1(typename super::mem_type_e space, uint64_t addr){return super::template read_mem(space, addr);} + inline uint16_t readSpace2(typename super::mem_type_e space, uint64_t addr){return super::template read_mem(space, addr);} + inline uint32_t readSpace4(typename super::mem_type_e space, uint64_t addr){return super::template read_mem(space, addr);} + inline uint64_t readSpace8(typename super::mem_type_e space, uint64_t addr){return super::template read_mem(space, addr);} + inline void writeSpace1(typename super::mem_type_e space, uint64_t addr, uint8_t data){super::write_mem(space, addr, data);} + inline void writeSpace2(typename super::mem_type_e space, uint64_t addr, uint16_t data){super::write_mem(space, addr, data);} + inline void writeSpace4(typename super::mem_type_e space, uint64_t addr, uint32_t data){super::write_mem(space, addr, data);} + inline void writeSpace8(typename super::mem_type_e space, uint64_t addr, uint64_t data){super::write_mem(space, addr, data);} private: /**************************************************************************** @@ -259,7 +268,7 @@ private: {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, /* instruction WFI */ {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, - /* instruction SFENCE.VMA */ + /* instruction SFENCE_VMA */ {32, 0b00010010000000000000000001110011, 0b11111110000000000111111111111111, &this_class::__sfence_vma}, /* instruction CSRRW */ {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, @@ -278,31 +287,32 @@ private: /* instruction definitions */ /* instruction 0: LUI */ compile_ret_t __lui(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 0); - uint8_t rd = ((bit_sub<7,5>(instr))); int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (imm); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 0); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = imm; + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 0); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -310,31 +320,32 @@ private: /* instruction 1: AUIPC */ compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 1); - uint8_t rd = ((bit_sub<7,5>(instr))); int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(cur_pc_val) + (imm)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 1); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = *PC + imm; + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 1); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -342,35 +353,35 @@ private: /* instruction 2: JAL */ compile_ret_t __jal(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 2); - uint8_t rd = ((bit_sub<7,5>(instr))); int32_t imm = signextend((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (cur_pc_val + 4); - super::template get_reg(rd + traits::X0)=Xtmp0_val; + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + { + if(rd != 0) *(X+rd) = *PC + 4; + *PC = *PC + imm; } - auto PC_val = (static_cast(cur_pc_val) + (imm)); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 2); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = super::template get_reg(arch::traits::PC); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 2); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -378,8 +389,8 @@ private: /* instruction 3: JALR */ compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 3); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); int16_t imm = signextend((bit_sub<20,12>(instr))); @@ -387,35 +398,34 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto new_pc_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto align_val = (new_pc_val & 0x2); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction { - if((align_val != 0)) { - raise_trap(0, 0); - } - else { - if(rd != 0){ - auto Xtmp0_val = (cur_pc_val + 4); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto PC_val = (new_pc_val & ~(0x1)); - super::template get_reg(traits::NEXT_PC) = PC_val; - super::template get_reg(traits::LAST_BRANCH) = std::numeric_limits::max(); - } + int32_t new_pc = *(X+rs1) + imm; + int32_t align = new_pc & 0x2; + if(align != 0) { + raise(0, 0); + } + else { + if(rd != 0) *(X+rd) = *PC + 4; + *PC = new_pc & ~ 0x1; + } } - this->do_sync(POST_SYNC, 3); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = super::template get_reg(arch::traits::PC); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 3); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -423,8 +433,8 @@ private: /* instruction 4: BEQ */ compile_ret_t __beq(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 4); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -432,25 +442,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (super::template get_reg(rs1 + traits::X0) == super::template get_reg(rs2 + traits::X0))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 4); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(*(X+rs1) == *(X+rs2)) *PC = *PC + imm; + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = super::template get_reg(arch::traits::PC); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 4); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -458,8 +467,8 @@ private: /* instruction 5: BNE */ compile_ret_t __bne(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 5); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -467,25 +476,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (super::template get_reg(rs1 + traits::X0) != super::template get_reg(rs2 + traits::X0))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 5); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(*(X+rs1) != *(X+rs2)) *PC = *PC + imm; + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = super::template get_reg(arch::traits::PC); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 5); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -493,8 +501,8 @@ private: /* instruction 6: BLT */ compile_ret_t __blt(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 6); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -502,25 +510,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < static_cast(super::template get_reg(rs2 + traits::X0)))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 6); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(*(X+rs1) < *(X+rs2)) *PC = *PC + imm; + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = super::template get_reg(arch::traits::PC); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 6); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -528,8 +535,8 @@ private: /* instruction 7: BGE */ compile_ret_t __bge(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 7); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -537,25 +544,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (static_cast(super::template get_reg(rs1 + traits::X0)) >= static_cast(super::template get_reg(rs2 + traits::X0)))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 7); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(*(X+rs1) >= *(X+rs2)) *PC = *PC + imm; + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = super::template get_reg(arch::traits::PC); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 7); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -563,8 +569,8 @@ private: /* instruction 8: BLTU */ compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 8); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -572,25 +578,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (super::template get_reg(rs1 + traits::X0) < super::template get_reg(rs2 + traits::X0))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 8); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(*(X+rs1) < *(X+rs2)) *PC = *PC + imm; + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = super::template get_reg(arch::traits::PC); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 8); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -598,8 +603,8 @@ private: /* instruction 9: BGEU */ compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 9); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -607,25 +612,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (super::template get_reg(rs1 + traits::X0) >= super::template get_reg(rs2 + traits::X0))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 9); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(*(X+rs1) >= *(X+rs2)) *PC = *PC + imm; + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = super::template get_reg(arch::traits::PC); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 9); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -633,8 +637,8 @@ private: /* instruction 10: LB */ compile_ret_t __lb(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 10); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); int16_t imm = signextend((bit_sub<20,12>(instr))); @@ -642,24 +646,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 10); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = readSpace1(traits::MEM, *(X+rs1) + imm); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 10); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -667,8 +671,8 @@ private: /* instruction 11: LH */ compile_ret_t __lh(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 11); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); int16_t imm = signextend((bit_sub<20,12>(instr))); @@ -676,24 +680,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 11); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = (int16_t)readSpace2(traits::MEM, *(X+rs1) + imm); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 11); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -701,8 +705,8 @@ private: /* instruction 12: LW */ compile_ret_t __lw(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 12); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); int16_t imm = signextend((bit_sub<20,12>(instr))); @@ -710,24 +714,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 12); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = (uint32_t)readSpace4(traits::MEM, *(X+rs1) + imm); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 12); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -735,8 +739,8 @@ private: /* instruction 13: LBU */ compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 13); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); int16_t imm = signextend((bit_sub<20,12>(instr))); @@ -744,24 +748,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template zext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 13); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = (uint8_t)readSpace1(traits::MEM, *(X+rs1) + imm); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 13); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -769,8 +773,8 @@ private: /* instruction 14: LHU */ compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 14); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); int16_t imm = signextend((bit_sub<20,12>(instr))); @@ -778,24 +782,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template zext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 14); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = (uint16_t)readSpace2(traits::MEM, *(X+rs1) + imm); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 14); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -803,8 +807,8 @@ private: /* instruction 15: SB */ compile_ret_t __sb(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 15); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -812,22 +816,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 15); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + writeSpace1(traits::MEM, *(X+rs1) + imm, (int8_t)*(X+rs2)); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 15); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -835,8 +841,8 @@ private: /* instruction 16: SH */ compile_ret_t __sh(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 16); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -844,22 +850,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 16); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + writeSpace2(traits::MEM, *(X+rs1) + imm, (int16_t)*(X+rs2)); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 16); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -867,8 +875,8 @@ private: /* instruction 17: SW */ compile_ret_t __sw(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 17); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -876,22 +884,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 17); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + writeSpace4(traits::MEM, *(X+rs1) + imm, *(X+rs2)); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 17); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -899,8 +909,8 @@ private: /* instruction 18: ADDI */ compile_ret_t __addi(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 18); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); int16_t imm = signextend((bit_sub<20,12>(instr))); @@ -908,23 +918,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 18); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = *(X+rs1) + imm; + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 18); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -932,8 +943,8 @@ private: /* instruction 19: SLTI */ compile_ret_t __slti(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 19); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); int16_t imm = signextend((bit_sub<20,12>(instr))); @@ -941,25 +952,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < (imm))? - 1: - 0; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 19); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = *(X+rs1) < imm? 1 : 0; + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 19); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -967,8 +977,8 @@ private: /* instruction 20: SLTIU */ compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 20); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); int16_t imm = signextend((bit_sub<20,12>(instr))); @@ -976,26 +986,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - int32_t full_imm_val = imm; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) < full_imm_val)? - 1: - 0; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 20); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = (uint8_t)*(X+rs1) < (uint8_t)(int32_t)imm? 1 : 0; + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 20); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1003,8 +1011,8 @@ private: /* instruction 21: XORI */ compile_ret_t __xori(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 21); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); int16_t imm = signextend((bit_sub<20,12>(instr))); @@ -1012,23 +1020,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) ^ (imm)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 21); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = *(X+rs1) ^ imm; + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 21); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1036,8 +1045,8 @@ private: /* instruction 22: ORI */ compile_ret_t __ori(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 22); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); int16_t imm = signextend((bit_sub<20,12>(instr))); @@ -1045,23 +1054,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) | (imm)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 22); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = *(X+rs1) | imm; + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 22); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1069,8 +1079,8 @@ private: /* instruction 23: ANDI */ compile_ret_t __andi(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 23); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); int16_t imm = signextend((bit_sub<20,12>(instr))); @@ -1078,23 +1088,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) & (imm)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 23); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = *(X+rs1) & imm; + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 23); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1102,8 +1113,8 @@ private: /* instruction 24: SLLI */ compile_ret_t __slli(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 24); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t shamt = ((bit_sub<20,5>(instr))); @@ -1111,27 +1122,29 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(shamt > 31){ - raise_trap(0, 0); - } else { - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0)<<(shamt)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(shamt > 31) { + raise(0, 0); } - this->do_sync(POST_SYNC, 24); + else { + if(rd != 0) *(X+rd) = *(X+rs1) << shamt; + } + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 24); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1139,8 +1152,8 @@ private: /* instruction 25: SRLI */ compile_ret_t __srli(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 25); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t shamt = ((bit_sub<20,5>(instr))); @@ -1148,27 +1161,29 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(shamt > 31){ - raise_trap(0, 0); - } else { - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(shamt)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(shamt > 31) { + raise(0, 0); } - this->do_sync(POST_SYNC, 25); + else { + if(rd != 0) *(X+rd) = ((uint8_t)*(X+rs1)) >> shamt; + } + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 25); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1176,8 +1191,8 @@ private: /* instruction 26: SRAI */ compile_ret_t __srai(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 26); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t shamt = ((bit_sub<20,5>(instr))); @@ -1185,27 +1200,29 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(shamt > 31){ - raise_trap(0, 0); - } else { - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(shamt)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(shamt > 31) { + raise(0, 0); } - this->do_sync(POST_SYNC, 26); + else { + if(rd != 0) *(X+rd) = *(X+rs1) >> shamt; + } + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 26); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1213,8 +1230,8 @@ private: /* instruction 27: ADD */ compile_ret_t __add(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 27); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1222,23 +1239,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) + super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 27); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = *(X+rs1) + *(X+rs2); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 27); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1246,8 +1264,8 @@ private: /* instruction 28: SUB */ compile_ret_t __sub(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 28); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1255,23 +1273,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) - super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 28); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = *(X+rs1) - *(X+rs2); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 28); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1279,8 +1298,8 @@ private: /* instruction 29: SLL */ compile_ret_t __sll(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 29); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1288,23 +1307,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0)<<(super::template get_reg(rs2 + traits::X0) & ((32) - 1))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 29); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = *(X+rs1) << (*(X+rs2) & (traits::XLEN - 1)); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 29); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1312,8 +1332,8 @@ private: /* instruction 30: SLT */ compile_ret_t __slt(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 30); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1321,25 +1341,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < static_cast(super::template get_reg(rs2 + traits::X0)))? - 1: - 0; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 30); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = *(X+rs1) < *(X+rs2)? 1 : 0; + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 30); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1347,8 +1366,8 @@ private: /* instruction 31: SLTU */ compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 31); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1356,25 +1375,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template zext(super::template get_reg(rs1 + traits::X0)) < super::template zext(super::template get_reg(rs2 + traits::X0)))? - 1: - 0; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 31); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = (uint32_t)*(X+rs1) < (uint32_t)*(X+rs2)? 1 : 0; + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 31); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1382,8 +1400,8 @@ private: /* instruction 32: XOR */ compile_ret_t __xor(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 32); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1391,23 +1409,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) ^ super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 32); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = *(X+rs1) ^ *(X+rs2); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 32); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1415,8 +1434,8 @@ private: /* instruction 33: SRL */ compile_ret_t __srl(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 33); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1424,23 +1443,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(super::template get_reg(rs2 + traits::X0) & ((32) - 1))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 33); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = *(X+rs1) << (*(X+rs2) & (traits::XLEN - 1)); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 33); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1448,8 +1468,8 @@ private: /* instruction 34: SRA */ compile_ret_t __sra(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 34); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1457,23 +1477,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(super::template get_reg(rs2 + traits::X0) & ((32) - 1))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 34); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = *(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1)); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 34); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1481,8 +1502,8 @@ private: /* instruction 35: OR */ compile_ret_t __or(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 35); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1490,23 +1511,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) | super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 35); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = *(X+rs1) | *(X+rs2); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 35); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1514,8 +1536,8 @@ private: /* instruction 36: AND */ compile_ret_t __and(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 36); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1523,23 +1545,24 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) & super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 36); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + if(rd != 0) *(X+rd) = *(X+rs1) & *(X+rs2); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 36); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1547,28 +1570,34 @@ private: /* instruction 37: FENCE */ compile_ret_t __fence(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 37); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t succ = ((bit_sub<20,4>(instr))); uint8_t pred = ((bit_sub<24,4>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ - this->core.disass_output(pc.val, "fence"); + auto mnemonic = fmt::format( + "{mnemonic:10} {pred}, {succ}, {rs1}, {rd}", fmt::arg("mnemonic", "fence"), + fmt::arg("pred", name(pred)), fmt::arg("succ", name(succ)), fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd))); + this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto FENCEtmp0_val = (((pred) << 4) | (succ)); - super::write_mem(traits::FENCE, (0), static_cast(FENCEtmp0_val)); - this->do_sync(POST_SYNC, 37); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + writeSpace1(traits::FENCE, traits::fence, pred << 4 | succ); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 37); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1576,27 +1605,33 @@ private: /* instruction 38: FENCE_I */ compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 38); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ - this->core.disass_output(pc.val, "fence_i"); + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rd}, {imm}", fmt::arg("mnemonic", "fence_i"), + fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd)), fmt::arg("imm", name(imm))); + this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto FENCEtmp0_val = (imm); - super::write_mem(traits::FENCE, (1), static_cast(FENCEtmp0_val)); - this->do_sync(POST_SYNC, 38); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + writeSpace2(traits::FENCE, traits::fencei, imm); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 38); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1604,23 +1639,27 @@ private: /* instruction 39: ECALL */ compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 39); - if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "ecall"); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - raise_trap(0, 11); - this->do_sync(POST_SYNC, 39); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + raise(0, 11); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 39); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1628,23 +1667,27 @@ private: /* instruction 40: EBREAK */ compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 40); - if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "ebreak"); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - raise_trap(0, 3); - this->do_sync(POST_SYNC, 40); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + raise(0, 3); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 40); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1652,23 +1695,27 @@ private: /* instruction 41: URET */ compile_ret_t __uret(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 41); - if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "uret"); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - leave_trap(0); - this->do_sync(POST_SYNC, 41); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + leave(0); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 41); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1676,23 +1723,27 @@ private: /* instruction 42: SRET */ compile_ret_t __sret(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 42); - if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "sret"); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - leave_trap(1); - this->do_sync(POST_SYNC, 42); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + leave(1); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 42); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1700,23 +1751,27 @@ private: /* instruction 43: MRET */ compile_ret_t __mret(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 43); - if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "mret"); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - leave_trap(3); - this->do_sync(POST_SYNC, 43); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + leave(3); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 43); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1724,52 +1779,63 @@ private: /* instruction 44: WFI */ compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 44); - if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "wfi"); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction wait(1); - this->do_sync(POST_SYNC, 44); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 44); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; } - /* instruction 45: SFENCE.VMA */ + /* instruction 45: SFENCE_VMA */ compile_ret_t __sfence_vma(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 45); - uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ - this->core.disass_output(pc.val, "sfence.vma"); + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {rs1}", fmt::arg("mnemonic", "sfence_vma"), + fmt::arg("rs2", name(rs2)), fmt::arg("rs1", rs1)); + this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto FENCEtmp0_val = (rs1); - super::write_mem(traits::FENCE, (2), static_cast(FENCEtmp0_val)); - auto FENCEtmp1_val = (rs2); - super::write_mem(traits::FENCE, (3), static_cast(FENCEtmp1_val)); - this->do_sync(POST_SYNC, 45); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + { + writeSpace1(traits::FENCE, traits::fencevmal, (uint8_t)rs1); + writeSpace1(traits::FENCE, traits::fencevmau, (uint8_t)rs2); + } + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 45); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1777,8 +1843,8 @@ private: /* instruction 46: CSRRW */ compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 46); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1786,30 +1852,34 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto rs_val_val = super::template get_reg(rs1 + traits::X0); - if(rd != 0){ - auto csr_val_val = super::template read_mem(traits::CSR, (csr)); - auto CSRtmp0_val = rs_val_val; - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp0_val)); - auto Xtmp1_val = csr_val_val; - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } else { - auto CSRtmp2_val = rs_val_val; - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp2_val)); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + { + uint32_t rs_val = *(X+rs1); + if(rd != 0) { + uint32_t csr_val = readSpace4(traits::CSR, csr); + writeSpace4(traits::CSR, csr, rs_val); + *(X+rd) = csr_val; + } + else { + writeSpace4(traits::CSR, csr, rs_val); + } } - this->do_sync(POST_SYNC, 46); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 46); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1817,8 +1887,8 @@ private: /* instruction 47: CSRRS */ compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 47); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1826,29 +1896,29 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto xrd_val = super::template read_mem(traits::CSR, (csr)); - auto xrs1_val = super::template get_reg(rs1 + traits::X0); - if(rd != 0){ - auto Xtmp0_val = xrd_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + { + uint32_t xrd = readSpace4(traits::CSR, csr); + uint32_t xrs1 = *(X+rs1); + if(rd != 0) *(X+rd) = xrd; + if(rs1 != 0) writeSpace4(traits::CSR, csr, xrd | xrs1); } - if(rs1 != 0){ - auto CSRtmp1_val = (xrd_val | xrs1_val); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); - } - this->do_sync(POST_SYNC, 47); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 47); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1856,8 +1926,8 @@ private: /* instruction 48: CSRRC */ compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 48); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1865,29 +1935,29 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto xrd_val = super::template read_mem(traits::CSR, (csr)); - auto xrs1_val = super::template get_reg(rs1 + traits::X0); - if(rd != 0){ - auto Xtmp0_val = xrd_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + { + uint32_t xrd = readSpace4(traits::CSR, csr); + uint32_t xrs1 = *(X+rs1); + if(rd != 0) *(X+rd) = xrd; + if(rs1 != 0) writeSpace4(traits::CSR, csr, xrd & ~ xrs1); } - if(rs1 != 0){ - auto CSRtmp1_val = (xrd_val & ~(xrs1_val)); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); - } - this->do_sync(POST_SYNC, 48); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 48); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1895,8 +1965,8 @@ private: /* instruction 49: CSRRWI */ compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 49); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1904,25 +1974,27 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = super::template read_mem(traits::CSR, (csr)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + { + if(rd != 0) *(X+rd) = readSpace4(traits::CSR, csr); + writeSpace4(traits::CSR, csr, (uint32_t)zimm); } - auto CSRtmp1_val = super::template zext((zimm)); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); - this->do_sync(POST_SYNC, 49); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 49); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1930,8 +2002,8 @@ private: /* instruction 50: CSRRSI */ compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 50); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1939,28 +2011,28 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = super::template read_mem(traits::CSR, (csr)); - if(zimm != 0){ - auto CSRtmp0_val = (res_val | super::template zext((zimm))); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp0_val)); + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + { + uint32_t res = readSpace4(traits::CSR, csr); + if(zimm != 0) writeSpace4(traits::CSR, csr, res | (uint32_t)zimm); + if(rd != 0) *(X+rd) = res; } - if(rd != 0){ - auto Xtmp1_val = res_val; - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - this->do_sync(POST_SYNC, 50); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 50); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -1968,8 +2040,8 @@ private: /* instruction 51: CSRRCI */ compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff this->do_sync(PRE_SYNC, 51); - uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1977,28 +2049,28 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); this->core.disass_output(pc.val, mnemonic); + } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = super::template read_mem(traits::CSR, (csr)); - if(rd != 0){ - auto Xtmp0_val = res_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; + // prepare execution + uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + // execute instruction + { + uint32_t res = readSpace4(traits::CSR, csr); + if(rd != 0) *(X+rd) = res; + if(zimm != 0) writeSpace4(traits::CSR, csr, res & ~ ((uint32_t)zimm)); } - if(zimm != 0){ - auto CSRtmp1_val = (res_val & ~(super::template zext((zimm)))); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); - } - this->do_sync(POST_SYNC, 51); + // post execution stuff + super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 51); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); + super::core.enter_trap(trap_state, pc.val); } pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; @@ -2037,7 +2109,7 @@ template typename vm_base::virt_addr_t vm_impl::execute_inst(virt_addr_t start, std::function pred) { // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; - const typename traits::addr_t upper_bits = ~traits::PGMASK; + const typename traits::addr_t upper_bits = ~traits::PGMASK; code_word_t insn = 0; auto *const data = (uint8_t *)&insn; auto pc=start; diff --git a/src/vm/interp/vm_tgf_c.cpp b/src/vm/interp/vm_tgf_c.cpp index e7dad44..a9ff8e6 100644 --- a/src/vm/interp/vm_tgf_c.cpp +++ b/src/vm/interp/vm_tgf_c.cpp @@ -516,7 +516,7 @@ private: uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); // execute instruction - *PC = *(X+rs1) == *(X+rs2)? *PC + imm : *PC + 4; + if(*(X+rs1) == *(X+rs2)) *PC = *PC + imm; // post execution stuff super::template get_reg(arch::traits::NEXT_PC) = super::template get_reg(arch::traits::PC); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 4); @@ -550,7 +550,7 @@ private: uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); // execute instruction - *PC = *(X+rs1) != *(X+rs2)? *PC + imm : *PC + 4; + if(*(X+rs1) != *(X+rs2)) *PC = *PC + imm; // post execution stuff super::template get_reg(arch::traits::NEXT_PC) = super::template get_reg(arch::traits::PC); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 5); @@ -584,7 +584,7 @@ private: uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); // execute instruction - *PC = *(X+rs1) < *(X+rs2)? *PC + imm : *PC + 4; + if(*(X+rs1) < *(X+rs2)) *PC = *PC + imm; // post execution stuff super::template get_reg(arch::traits::NEXT_PC) = super::template get_reg(arch::traits::PC); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 6); @@ -618,7 +618,7 @@ private: uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); // execute instruction - *PC = *(X+rs1) >= *(X+rs2)? *PC + imm : *PC + 4; + if(*(X+rs1) >= *(X+rs2)) *PC = *PC + imm; // post execution stuff super::template get_reg(arch::traits::NEXT_PC) = super::template get_reg(arch::traits::PC); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 7); @@ -652,7 +652,7 @@ private: uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); // execute instruction - *PC = *(X+rs1) < *(X+rs2)? *PC + imm : *PC + 4; + if(*(X+rs1) < *(X+rs2)) *PC = *PC + imm; // post execution stuff super::template get_reg(arch::traits::NEXT_PC) = super::template get_reg(arch::traits::PC); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 8); @@ -686,7 +686,7 @@ private: uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); // execute instruction - *PC = *(X+rs1) >= *(X+rs2)? *PC + imm : *PC + 4; + if(*(X+rs1) >= *(X+rs2)) *PC = *PC + imm; // post execution stuff super::template get_reg(arch::traits::NEXT_PC) = super::template get_reg(arch::traits::PC); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 9); @@ -788,7 +788,7 @@ private: uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); // execute instruction - if(rd != 0) *(X+rd) = (int32_t)readSpace4(traits::MEM, *(X+rs1) + imm); + if(rd != 0) *(X+rd) = (uint32_t)readSpace4(traits::MEM, *(X+rs1) + imm); // post execution stuff super::template get_reg(arch::traits::NEXT_PC) = pc.val + 4; if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 12); @@ -3076,7 +3076,7 @@ private: uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); // execute instruction - *PC = *(X+(rs1 + 8)) == 0? (int8_t)*PC + imm : *PC + 2; + if(*(X+(rs1 + 8)) == 0) *PC = (int8_t)*PC + imm; // post execution stuff super::template get_reg(arch::traits::NEXT_PC) = super::template get_reg(arch::traits::PC); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 77); @@ -3109,7 +3109,7 @@ private: uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); // execute instruction - *PC = *(X+(rs1 + 8)) != 0? (int8_t)*PC + imm : *PC + 2; + if(*(X+(rs1 + 8)) != 0) *PC = (int8_t)*PC + imm; // post execution stuff super::template get_reg(arch::traits::NEXT_PC) = super::template get_reg(arch::traits::PC); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 78);