From 5d508740fd34e01028b311b4eae7678fc933d642 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 18 Nov 2017 00:42:33 +0100 Subject: [PATCH] Fixed 64bit integer base instruction set --- README.md | 6 +- dbt-core | 2 +- riscv/gen_input/RV64IBase.core_desc | 117 ++++++++++-------- riscv/incl/iss/arch/riscv_hart_msu_vp.h | 157 ++++++++++++++---------- riscv/incl/iss/arch/rv32imac.h | 4 +- riscv/incl/iss/arch/rv64ia.h | 2 +- riscv/src/internal/vm_rv64ia.cpp | 128 +++++++++++++------ riscv/src/iss/rv32imac.cpp | 4 +- riscv/src/iss/rv64ia.cpp | 6 +- 9 files changed, 267 insertions(+), 159 deletions(-) diff --git a/README.md b/README.md index 994f4c0..f872fa4 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,9 @@ DBT-RISE-RiscV uses libGIS (https://github.com/vsergeev/libGIS) as well as ELFIO **Planned features** -* add platform peripherals to resemble E300 platform - * PLIC - * gpio +* add platform peripherals beyond programmers view to resemble E300 platform + * QSPI + * PWM * ... * and more diff --git a/dbt-core b/dbt-core index 29a6988..53d78d9 160000 --- a/dbt-core +++ b/dbt-core @@ -1 +1 @@ -Subproject commit 29a69884d2fcfb29f7a5f5a927e93e35f05fdd7e +Subproject commit 53d78d993a8d3310a8b73fec0b601457b3c0ef75 diff --git a/riscv/gen_input/RV64IBase.core_desc b/riscv/gen_input/RV64IBase.core_desc index 5508bb9..68ca175 100644 --- a/riscv/gen_input/RV64IBase.core_desc +++ b/riscv/gen_input/RV64IBase.core_desc @@ -2,97 +2,114 @@ import "RV32IBase.core_desc" InsructionSet RV64IBase extends RV32IBase { instructions{ - LWU { - encoding: imm[11:0]s | rs1[4:0] | b010 | rd[4:0] | b0000011; - args_disass:"x%rd$d, %imm%(x%rs1$d)"; - val offs[XLEN] <= X[rs1]+imm; - if(rd!=0) X[rd]<=zext(MEM[offs]{32}); + LWU { // 80000104: 0000ef03 lwu t5,0(ra) + encoding: imm[11:0]s | rs1[4:0] | b110 | rd[4:0] | b0000011; + args_disass:"x%rd$d, %imm%(x%rs1$d)"; + val offs[XLEN] <= X[rs1]+imm; + if(rd!=0) X[rd]<=zext(MEM[offs]{32}); } LD{ encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0000011; - args_disass:"x%rd$d, %imm%(x%rs1$d)"; - val offs[XLEN] <= X[rs1]+imm; - if(rd!=0) X[rd]<=sext(MEM[offs]{64}); + args_disass:"x%rd$d, %imm%(x%rs1$d)"; + val offs[XLEN] <= X[rs1]+imm; + if(rd!=0) X[rd]<=sext(MEM[offs]{64}); } SD{ - encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b011 | imm[4:0] | b0100011; - args_disass:"x%rs2$d, %imm%(x%rs1$d)"; - val offs[XLEN] <= X[rs1] + sext(imm, XLEN); - MEM[offs]{64} <= X[rs2]; + encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b011 | imm[4:0]s | b0100011; + args_disass:"x%rs2$d, %imm%(x%rs1$d)"; + val offs[XLEN] <= X[rs1] + imm; + MEM[offs]{64} <= X[rs2]; } SLLI { encoding: b000000 | shamt[5:0] | rs1[4:0] | b001 | rd[4:0] | b0010011; - args_disass:"x%rd$d, x%rs1$d, %shamt%"; - if(rd != 0) X[rd] <= shll(X[rs1], shamt); + args_disass:"x%rd$d, x%rs1$d, %shamt%"; + if(rd != 0) X[rd] <= shll(X[rs1], shamt); } SRLI { encoding: b000000 | shamt[5:0] | rs1[4:0] | b101 | rd[4:0] | b0010011; - args_disass:"x%rd$d, x%rs1$d, %shamt%"; - if(rd != 0) X[rd] <= shrl(X[rs1], shamt); + args_disass:"x%rd$d, x%rs1$d, %shamt%"; + if(rd != 0) X[rd] <= shrl(X[rs1], shamt); } SRAI { encoding: b010000 | shamt[5:0] | rs1[4:0] | b101 | rd[4:0] | b0010011; - args_disass:"x%rd$d, x%rs1$d, %shamt%"; - if(rd != 0) X[rd] <= shra(X[rs1], shamt); + args_disass:"x%rd$d, x%rs1$d, %shamt%"; + if(rd != 0) X[rd] <= shra(X[rs1], shamt); } ADDIW { encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b0011011; - args_disass:"x%rd$d, x%rs1$d, %imm%"; - if(rd != 0) X[rd] <= sext(X[rs1]{32}, XLEN) + sext(imm, XLEN); + args_disass:"x%rd$d, x%rs1$d, %imm%"; + if(rd != 0){ + val res[32] <= X[rs1]{32} + imm{32}; + X[rd] <= sext(res); + } } SLLIW { encoding: b0000000 | shamt[4:0] | rs1[4:0] | b001 | rd[4:0] | b0011011; - args_disass:"x%rd$d, x%rs1$d, %shamt%"; - if(rd != 0){ - val sh_val[32] <= shll(X[rs1]{32}, shamt); - X[rd] <= sext(sh_val, XLEN); - } + args_disass:"x%rd$d, x%rs1$d, %shamt%"; + if(rd != 0){ + val sh_val[32] <= shll(X[rs1]{32}, shamt); + X[rd] <= sext(sh_val); + } } SRLIW { encoding: b0000000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0011011; - args_disass:"x%rd$d, x%rs1$d, %shamt%"; - if(rd != 0){ - val sh_val[32] <= shrl(X[rs1], shamt); - X[rd] <= sext(sh_val, XLEN); - } + args_disass:"x%rd$d, x%rs1$d, %shamt%"; + if(rd != 0){ + val sh_val[32] <= shrl(X[rs1]{32}, shamt); + X[rd] <= sext(sh_val); + } } SRAIW { encoding: b0100000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0011011; - args_disass:"x%rd$d, x%rs1$d, %shamt%"; - if(rd != 0){ - val sh_val[32] <= shra(X[rs1], shamt); - X[rd] <= sext(sh_val, XLEN); - } + args_disass:"x%rd$d, x%rs1$d, %shamt%"; + if(rd != 0){ + val sh_val[32] <= shra(X[rs1]{32}, shamt); + X[rd] <= sext(sh_val); + } } ADDW { encoding: b0000000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0111011; + if(rd != 0){ + val res[32] <= X[rs1]{32} + X[rs2]{32}; + X[rd] <= sext(res); + } } SUBW { encoding: b0100000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0111011; + if(rd != 0){ + val res[32] <= X[rs1]{32} - X[rs2]{32}; + X[rd] <= sext(res); + } } SLLW { encoding: b0000000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0111011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; - if(rd != 0){ - val sh_val[32] <= shll(X[rs1], X[rs2]&0x1f); - X[rd] <= sext(sh_val, XLEN); - } + args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; + if(rd != 0){ + val mask[32] <= 0x1f; + val count[32] <= X[rs2]{32} & mask; + val sh_val[32] <= shll(X[rs1]{32}, count); + X[rd] <= sext(sh_val); + } } SRLW { encoding: b0000000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0111011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; - if(rd != 0){ - val sh_val[32] <= shrl(X[rs1], X[rs2]&0x1f); - X[rd] <= sext(sh_val, XLEN); - } + args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; + if(rd != 0){ + val mask[32] <= 0x1f; + val count[32] <= X[rs2]{32} & mask; + val sh_val[32] <= shrl(X[rs1]{32}, count); + X[rd] <= sext(sh_val); + } } SRAW { encoding: b0100000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0111011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; - if(rd != 0){ - val sh_val[32] <= shra(X[rs1], X[rs2]&0x1f); - X[rd] <= sext(sh_val, XLEN); - } + args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; + if(rd != 0){ + val mask[32] <= 0x1f; + val count[32] <= X[rs2]{32} & mask; + val sh_val[32] <= shra(X[rs1]{32}, count); + X[rd] <= sext(sh_val); + } } } } diff --git a/riscv/incl/iss/arch/riscv_hart_msu_vp.h b/riscv/incl/iss/arch/riscv_hart_msu_vp.h index 51cd7c4..15a7ecb 100644 --- a/riscv/incl/iss/arch/riscv_hart_msu_vp.h +++ b/riscv/incl/iss/arch/riscv_hart_msu_vp.h @@ -308,6 +308,14 @@ public: mstatus_t mstatus; + static const reg_t mstatus_reset_val = 0; + + void write_mstatus(T val, unsigned priv_lvl){ + auto mask = get_mask(priv_lvl); + auto new_val = (mstatus & ~mask) | (val & mask); + mstatus=new_val; + } + T satp; static constexpr T get_misa() { return (1UL << 30) | ISA_I | ISA_M | ISA_A | ISA_U | ISA_S | ISA_M; } @@ -379,14 +387,29 @@ public: mstatus_t mstatus; + static const reg_t mstatus_reset_val = 0xa00000000; + + void write_mstatus(T val, unsigned priv_lvl){ + T old_val = mstatus; + auto mask = get_mask(priv_lvl); + auto new_val = (old_val & ~mask) | (val & mask); + if((new_val&mstatus.SXL.Mask)==0){ + new_val |= old_val&mstatus.SXL.Mask; + } + if((new_val&mstatus.UXL.Mask)==0){ + new_val |= old_val&mstatus.UXL.Mask; + } + mstatus=new_val; + } + T satp; static constexpr T get_misa() { return (2ULL << 62) | ISA_I | ISA_M | ISA_A | ISA_U | ISA_S | ISA_M; } static constexpr T get_mask(unsigned priv_lvl) { switch (priv_lvl) { - case PRIV_U: return 0x8000000000000011ULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 - case PRIV_S: return 0x80000003000de133ULL; // 0b1...0 0011 0000 0000 0000 1101 1110 0001 0011 0011 + case PRIV_U: return 0x8000000f00000011ULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 + case PRIV_S: return 0x8000000f000de133ULL; // 0b1...0 0011 0000 0000 0000 1101 1110 0001 0011 0011 default: return 0x8000000f007ff9ddULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 } } @@ -423,6 +446,8 @@ public: riscv_hart_msu_vp(); virtual ~riscv_hart_msu_vp() = default; + void reset(uint64_t address) override; + void load_file(std::string name, int type = -1) override; virtual phys_addr_t v2p(const iss::addr_t &addr); @@ -573,66 +598,71 @@ iss::status riscv_hart_msu_vp::read(const iss::addr_t &addr, unsigned leng LOG(DEBUG) << "read of " << length << " bytes @addr " << addr; } #endif - switch (addr.space) { - case traits::MEM: { - if ((addr.type & (iss::ACCESS_TYPE - iss::DEBUG)) == iss::FETCH && (addr.val & 0x1) == 1) { - fault_data = addr.val; - if ((addr.type & iss::DEBUG)) throw trap_access(0, addr.val); - this->reg.trap_state = (1 << 31); // issue trap 0 - return iss::Err; - } - try { - if ((addr.val & ~PGMASK) != ((addr.val + length - 1) & ~PGMASK)) { // we may cross a page boundary - vm_info vm = hart_state::decode_vm_info(this->reg.machine_state, state.satp); - if (vm.levels != 0) { // VM is active - auto split_addr = (addr.val + length) & ~PGMASK; - auto len1 = split_addr - addr.val; - auto res = read(addr, len1, data); - if (res == iss::Ok) - res = read(iss::addr_t{addr.type, addr.space, split_addr}, length - len1, data + len1); - return res; - } - } - phys_addr_t paddr = (addr.type & iss::ADDRESS_TYPE) == iss::PHYSICAL ? addr : v2p(addr); - auto res = read_mem(paddr, length, data); - if (res != iss::Ok) this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault - return res; - } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; - return iss::Err; - } - } break; - case traits::CSR: { - if (length != sizeof(reg_t)) return iss::Err; - return read_csr(addr.val, *reinterpret_cast(data)); - } break; - case traits::FENCE: { - if ((addr.val + length) > mem.size()) return iss::Err; - switch (addr.val) { - case 2: // SFENCE:VMA lower - case 3: { // SFENCE:VMA upper - auto tvm = state.mstatus.TVM; - if (this->reg.machine_state == PRIV_S & tvm != 0) { - this->reg.trap_state = (1 << 31) | (2 << 16); - this->fault_data = this->reg.PC; + try { + switch (addr.space) { + case traits::MEM: { + if ((addr.type & (iss::ACCESS_TYPE - iss::DEBUG)) == iss::FETCH && (addr.val & 0x1) == 1) { + fault_data = addr.val; + if ((addr.type & iss::DEBUG)) throw trap_access(0, addr.val); + this->reg.trap_state = (1 << 31); // issue trap 0 return iss::Err; } - return iss::Ok; + try { + if ((addr.val & ~PGMASK) != ((addr.val + length - 1) & ~PGMASK)) { // we may cross a page boundary + vm_info vm = hart_state::decode_vm_info(this->reg.machine_state, state.satp); + if (vm.levels != 0) { // VM is active + auto split_addr = (addr.val + length) & ~PGMASK; + auto len1 = split_addr - addr.val; + auto res = read(addr, len1, data); + if (res == iss::Ok) + res = read(iss::addr_t{addr.type, addr.space, split_addr}, length - len1, data + len1); + return res; + } + } + phys_addr_t paddr = (addr.type & iss::ADDRESS_TYPE) == iss::PHYSICAL ? addr : v2p(addr); + auto res = read_mem(paddr, length, data); + if (res != iss::Ok) this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault + return res; + } catch (trap_access &ta) { + this->reg.trap_state = (1 << 31) | ta.id; + return iss::Err; + } + } break; + case traits::CSR: { + if (length != sizeof(reg_t)) return iss::Err; + return read_csr(addr.val, *reinterpret_cast(data)); + } break; + case traits::FENCE: { + if ((addr.val + length) > mem.size()) return iss::Err; + switch (addr.val) { + case 2: // SFENCE:VMA lower + case 3: { // SFENCE:VMA upper + auto tvm = state.mstatus.TVM; + if (this->reg.machine_state == PRIV_S & tvm != 0) { + this->reg.trap_state = (1 << 31) | (2 << 16); + this->fault_data = this->reg.PC; + return iss::Err; + } + return iss::Ok; + } + } + } break; + case traits::RES: { + auto it = atomic_reservation.find(addr.val); + if (it != atomic_reservation.end() && (*it).second != 0) { + memset(data, 0xff, length); + atomic_reservation.erase(addr.val); + } else + memset(data, 0, length); + } break; + default: + return iss::Err; // assert("Not supported"); } - } - } break; - case traits::RES: { - auto it = atomic_reservation.find(addr.val); - if (it != atomic_reservation.end() && (*it).second != 0) { - memset(data, 0xff, length); - atomic_reservation.erase(addr.val); - } else - memset(data, 0, length); - } break; - default: - return iss::Err; // assert("Not supported"); + return iss::Ok; + } catch (trap_access &ta) { + this->reg.trap_state = (1 << 31) | ta.id; + return iss::Err; } - return iss::Ok; } template @@ -810,10 +840,7 @@ template iss::status riscv_hart_msu_vp::read_status(unsign template iss::status riscv_hart_msu_vp::write_status(unsigned addr, reg_t val) { auto req_priv_lvl = addr >> 8; if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data); - auto mask = hart_state::get_mask(req_priv_lvl); - auto old_val = state.mstatus; - auto new_val = (old_val & ~mask) | (val & mask); - state.mstatus = new_val; + state.write_mstatus(val, req_priv_lvl); check_interrupt(); return iss::Ok; } @@ -980,6 +1007,12 @@ inline void riscv_hart_msu_vp::notify_phase(iss::arch_if::exec_phase phase BASE::notify_phase(phase); } +template +inline void riscv_hart_msu_vp::reset(uint64_t address) { + BASE::reset(address); + state.mstatus = hart_state::mstatus_reset_val; +} + template void riscv_hart_msu_vp::check_interrupt() { auto status = state.mstatus; auto ip = csr[mip]; diff --git a/riscv/incl/iss/arch/rv32imac.h b/riscv/incl/iss/arch/rv32imac.h index 39bdd5c..5dc4bf4 100644 --- a/riscv/incl/iss/arch/rv32imac.h +++ b/riscv/incl/iss/arch/rv32imac.h @@ -28,7 +28,7 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // -// Created on: Wed Oct 18 11:42:36 CEST 2017 +// Created on: Fri Nov 17 20:34:49 CET 2017 // * rv32imac.h Author: // //////////////////////////////////////////////////////////////////////////////// @@ -126,7 +126,7 @@ struct rv32imac: public arch_if { using addr_t = typename traits::addr_t; rv32imac(); - ~rv32imac() = default; + ~rv32imac(); void reset(uint64_t address=0) override; diff --git a/riscv/incl/iss/arch/rv64ia.h b/riscv/incl/iss/arch/rv64ia.h index 18f4ced..2bfbd96 100644 --- a/riscv/incl/iss/arch/rv64ia.h +++ b/riscv/incl/iss/arch/rv64ia.h @@ -28,7 +28,7 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // -// Created on: Wed Oct 18 11:42:36 CEST 2017 +// Created on: Fri Nov 17 20:34:49 CET 2017 // * rv64ia.h Author: // //////////////////////////////////////////////////////////////////////////////// diff --git a/riscv/src/internal/vm_rv64ia.cpp b/riscv/src/internal/vm_rv64ia.cpp index 026e198..fbd5aa8 100644 --- a/riscv/src/internal/vm_rv64ia.cpp +++ b/riscv/src/internal/vm_rv64ia.cpp @@ -148,7 +148,8 @@ protected: } // some compile time constants - enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; + // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; + enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; @@ -217,7 +218,7 @@ private: const InstructionDesriptor instr_descr[75] = { /* entries are: valid value, valid mask, function ptr */ /* instruction LWU */ - {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lwu}, + {32, 0b00000000000000000110000000000011, 0b00000000000000000111000001111111, &this_class::__lwu}, /* instruction LD */ {32, 0b00000000000000000011000000000011, 0b00000000000000000111000001111111, &this_class::__ld}, /* instruction SD */ @@ -451,7 +452,7 @@ private: this->gen_sync(iss::PRE_SYNC); - uint16_t fld_imm_val = 0 | (bit_sub<7,5>(instr)) | (signed_bit_sub<25,7>(instr) << 5); + int16_t fld_imm_val = 0 | (bit_sub<7,5>(instr)) | (signed_bit_sub<25,7>(instr) << 5); uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); if(this->disass_enabled){ @@ -469,10 +470,7 @@ private: Value* offs_val = this->builder->CreateAdd( this->gen_reg_load(fld_rs1_val, 0), - this->gen_ext( - this->gen_const(64U, fld_imm_val), - 64, - true)); + this->gen_const(64U, fld_imm_val)); Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); this->gen_write_mem( traits::MEM, @@ -613,18 +611,16 @@ private: pc=pc+4; if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateAdd( - this->gen_ext( - this->builder->CreateTrunc( - this->gen_reg_load(fld_rs1_val, 0), - this-> get_type(32) - ), - 64, - true), - this->gen_ext( - this->gen_const(64U, fld_imm_val), - 64, - true)); + Value* res_val = this->builder->CreateAdd( + this->builder->CreateTrunc( + this->gen_reg_load(fld_rs1_val, 0), + this-> get_type(32) + ), + this->gen_const(32U, fld_imm_val)); + Value* X_rd_val = this->gen_ext( + res_val, + 64, + true); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); @@ -700,7 +696,10 @@ private: if(fld_rd_val != 0){ Value* sh_val_val = this->builder->CreateLShr( - this->gen_reg_load(fld_rs1_val, 0), + this->builder->CreateTrunc( + this->gen_reg_load(fld_rs1_val, 0), + this-> get_type(32) + ), this->gen_const(32U, fld_shamt_val)); Value* X_rd_val = this->gen_ext( sh_val_val, @@ -739,7 +738,10 @@ private: if(fld_rd_val != 0){ Value* sh_val_val = this->builder->CreateAShr( - this->gen_reg_load(fld_rs1_val, 0), + this->builder->CreateTrunc( + this->gen_reg_load(fld_rs1_val, 0), + this-> get_type(32) + ), this->gen_const(32U, fld_shamt_val)); Value* X_rd_val = this->gen_ext( sh_val_val, @@ -774,7 +776,22 @@ private: } pc=pc+4; - /* TODO: describe operations for ADDW ! */ + if(fld_rd_val != 0){ + Value* res_val = this->builder->CreateAdd( + this->builder->CreateTrunc( + this->gen_reg_load(fld_rs1_val, 0), + this-> get_type(32) + ), + this->builder->CreateTrunc( + this->gen_reg_load(fld_rs2_val, 0), + this-> get_type(32) + )); + Value* X_rd_val = this->gen_ext( + res_val, + 64, + true); + this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -802,7 +819,22 @@ private: } pc=pc+4; - /* TODO: describe operations for SUBW ! */ + if(fld_rd_val != 0){ + Value* res_val = this->builder->CreateSub( + this->builder->CreateTrunc( + this->gen_reg_load(fld_rs1_val, 0), + this-> get_type(32) + ), + this->builder->CreateTrunc( + this->gen_reg_load(fld_rs2_val, 0), + this-> get_type(32) + )); + Value* X_rd_val = this->gen_ext( + res_val, + 64, + true); + this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -833,11 +865,19 @@ private: pc=pc+4; if(fld_rd_val != 0){ - Value* sh_val_val = this->builder->CreateShl( - this->gen_reg_load(fld_rs1_val, 0), - this->builder->CreateAnd( + Value* mask_val = this->gen_const(32U, 31); + Value* count_val = this->builder->CreateAnd( + this->builder->CreateTrunc( this->gen_reg_load(fld_rs2_val, 0), - this->gen_const(32U, 31))); + this-> get_type(32) + ), + mask_val); + Value* sh_val_val = this->builder->CreateShl( + this->builder->CreateTrunc( + this->gen_reg_load(fld_rs1_val, 0), + this-> get_type(32) + ), + count_val); Value* X_rd_val = this->gen_ext( sh_val_val, 64, @@ -874,11 +914,19 @@ private: pc=pc+4; if(fld_rd_val != 0){ - Value* sh_val_val = this->builder->CreateLShr( - this->gen_reg_load(fld_rs1_val, 0), - this->builder->CreateAnd( + Value* mask_val = this->gen_const(32U, 31); + Value* count_val = this->builder->CreateAnd( + this->builder->CreateTrunc( this->gen_reg_load(fld_rs2_val, 0), - this->gen_const(32U, 31))); + this-> get_type(32) + ), + mask_val); + Value* sh_val_val = this->builder->CreateLShr( + this->builder->CreateTrunc( + this->gen_reg_load(fld_rs1_val, 0), + this-> get_type(32) + ), + count_val); Value* X_rd_val = this->gen_ext( sh_val_val, 64, @@ -915,11 +963,19 @@ private: pc=pc+4; if(fld_rd_val != 0){ - Value* sh_val_val = this->builder->CreateAShr( - this->gen_reg_load(fld_rs1_val, 0), - this->builder->CreateAnd( + Value* mask_val = this->gen_const(32U, 31); + Value* count_val = this->builder->CreateAnd( + this->builder->CreateTrunc( this->gen_reg_load(fld_rs2_val, 0), - this->gen_const(32U, 31))); + this-> get_type(32) + ), + mask_val); + Value* sh_val_val = this->builder->CreateAShr( + this->builder->CreateTrunc( + this->gen_reg_load(fld_rs1_val, 0), + this-> get_type(32) + ), + count_val); Value* X_rd_val = this->gen_ext( sh_val_val, 64, @@ -3384,7 +3440,7 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, } catch (trap_access &ta) { throw trap_access(ta.id, pc.val); } - if (insn == 0x0000006f) throw simulation_stopped(0); + if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack typename vm_impl::processing_pc_entry addr(*this, pc, paddr); ++inst_cnt; diff --git a/riscv/src/iss/rv32imac.cpp b/riscv/src/iss/rv32imac.cpp index 677b4f4..7cb43af 100644 --- a/riscv/src/iss/rv32imac.cpp +++ b/riscv/src/iss/rv32imac.cpp @@ -52,7 +52,9 @@ extern "C" { using namespace iss::arch; -rv32imac::rv32imac() { reg.icount = 0; } +rv32imac::rv32imac() { reg.icount = 0; reg.machine_state = 0x3;} + +rv32imac::~rv32imac(){} void rv32imac::reset(uint64_t address) { for (size_t i = 0; i < traits::NUM_REGS; ++i) diff --git a/riscv/src/iss/rv64ia.cpp b/riscv/src/iss/rv64ia.cpp index 9b80eb2..7542a04 100644 --- a/riscv/src/iss/rv64ia.cpp +++ b/riscv/src/iss/rv64ia.cpp @@ -52,9 +52,9 @@ extern "C" { using namespace iss::arch; -rv64ia::rv64ia() { reg.icount = 0; } +rv64ia::rv64ia() { reg.icount = 0; reg.machine_state = 0x3;} -rv64ia::~rv64ia() {} +rv64ia::~rv64ia(){} void rv64ia::reset(uint64_t address) { for (size_t i = 0; i < traits::NUM_REGS; ++i) @@ -62,7 +62,7 @@ void rv64ia::reset(uint64_t address) { reg.PC = address; reg.NEXT_PC = reg.PC; reg.trap_state = 0; - reg.machine_state = 0x0; + reg.machine_state = 0x3; } uint8_t *rv64ia::get_regs_base_ptr() { return reinterpret_cast(®); }