Fixed handling of compressed ISA

This commit is contained in:
Eyck Jentzsch 2017-10-25 22:05:31 +02:00
parent 9970303fa4
commit b0dcb3b60e
7 changed files with 219 additions and 218 deletions

@ -1 +1 @@
Subproject commit 55b281a010a7cedc7ba23c3856a551a9ee314eb4
Subproject commit 29a69884d2fcfb29f7a5f5a927e93e35f05fdd7e

View File

@ -97,14 +97,14 @@ public:
void notify_phase(iss::arch_if::exec_phase phase);
void disass_output(uint64_t pc, const std::string instr) override {
#ifndef WITH_SCV
if (logging::INFO <= logging::Log<logging::Output2FILE<logging::disass>>::reporting_level() && logging::Output2FILE<logging::disass>::stream()){
std::stringstream s;
s << "[p:" << lvl[this->reg.machine_state] << ";s:0x" << std::hex << std::setfill('0')
<< std::setw(sizeof(reg_t) * 2) << (reg_t)state.mstatus << std::dec << ";c:" << this->reg.icount << "]";
CLOG(INFO, disass) << "0x"<<std::setw(16)<<std::setfill('0')<<std::hex<<pc<<"\t\t"<<instr<<"\t"<<s.str();
#else
scc::Log<logging::Output2FILE<logging::disass>>().get(logging::INFO, "disass")
<< "0x"<<std::setw(16)<<std::setfill('0')<<std::hex<<pc<<"\t\t"<<std::setw(40)<<std::setfill(' ')<<std::left<<instr<<s.str();
}
owner->disass_output(pc,instr);
#endif
};
iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data) {
@ -221,7 +221,7 @@ void core_complex::start_of_simulation() {
quantum_keeper.reset();
if (elf_file.value.size() > 0) cpu->load_file(elf_file.value);
#ifdef WITH_SCV
if (stream_handle == NULL) {
if (m_db!=nullptr && stream_handle == nullptr) {
string basename(this->name());
stream_handle = new scv_tr_stream((basename + ".instr").c_str(), "TRANSACTOR", m_db);
instr_tr_handle = new scv_tr_generator<>("execute", *stream_handle);
@ -232,6 +232,7 @@ void core_complex::start_of_simulation() {
void core_complex::disass_output(uint64_t pc, const std::string instr_str) {
#ifdef WITH_SCV
if (m_db==nullptr) return;
if(tr_handle.is_active()) tr_handle.end_transaction();
tr_handle = instr_tr_handle->begin_transaction();
tr_handle.record_attribute("PC", pc);
@ -270,7 +271,7 @@ bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data,
gp.set_streaming_width(4);
auto delay{quantum_keeper.get_local_time()};
#ifdef WITH_SCV
if(tr_handle.is_valid()){
if(m_db!=nullptr && tr_handle.is_valid()){
if(is_fetch && tr_handle.is_active()) tr_handle.end_transaction();
auto preExt = new scv4tlm::tlm_recording_extension(tr_handle, this);
gp.set_extension(preExt);

View File

@ -12,42 +12,37 @@ InsructionSet RV32CI {
PC[XLEN](is_pc)
}
instructions{
C.ADDI4SPN { //(RES, nzuimm=0)
encoding: b000 | nzuimm[5:4] | nzuimm[9:6] | nzuimm[2:2] | nzuimm[3:3] | rd[2:0] | b00;
args_disass: "x%rd$d, 0x%nzuimm$05x";
if(nzuimm == 0)
raise(0, 2);
C.ADDI4SPN { //(RES, imm=0)
encoding: b000 | imm[5:4] | imm[9:6] | imm[2:2] | imm[3:3] | rd[2:0] | b00;
args_disass: "x%rd$d, 0x%imm$05x";
if(imm == 0) raise(0, 2);
val rd_idx[5] <= rd+8;
val x2_idx[5] <= 2;
X[rd_idx] <= X[x2_idx] + nzuimm;
X[rd_idx] <= X[x2_idx] + imm;
}
C.LW { // (RV32)
encoding: b010 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rd[2:0] | b00;
args_disass: "x(8+%rd$d), x(8+%rs1$d), 0x%uimm$05x";
val rs1_idx[5] <= rs1+8;
val adr[XLEN] <= X[rs1_idx]+uimm;
val rd_idx[5] <= rd+8;
X[rd_idx] <= MEM[adr]{32};
val offs[XLEN] <= X[rs1_idx]+uimm;
X[rd_idx] <= MEM[offs]{32};
}
C.SW {//(RV32)
encoding: b110 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rs2[2:0] | b00;
args_disass: "x(8+%rs1$d), x(8+%rs2$d), 0x%uimm$05x";
val rs1_idx[5] <= rs1+8;
val adr[XLEN] <= X[rs1_idx]+uimm;
val rs2_idx[5] <= rs2+8;
MEM[adr]{32} <= X[rs2_idx];
}
C.NOP {//(RV32)
encoding: b000 | b0 | b00000 | b00000 | b01; //TODO
args_disass: "";
val offs[XLEN] <= X[rs1_idx]+uimm;
MEM[offs]{32} <= X[rs2_idx];
}
C.ADDI {//(RV32)
encoding:b000 | nzimm[5:5]s | rs1[4:0] | nzimm[4:0]s | b01;
args_disass: "x%rs1$d, 0x%nzimm$05x";
if(nzimm == 0)
raise(0, 2);
X[rs1] <= X[rs1] + nzimm;
encoding:b000 | imm[5:5]s | rs1[4:0] | imm[4:0]s | b01;
args_disass: "x%rs1$d, 0x%imm$05x";
X[rs1] <= X[rs1] + imm;
}
C.NOP {
encoding:b000 | b0 | b00000 | b00000 | b01;
}
// C.JAL will be overwritten by C.ADDIW for RV64/128
C.JAL(no_cont) {//(RV32)
@ -60,35 +55,32 @@ InsructionSet RV32CI {
C.LI {//(RV32)
encoding:b010 | imm[5:5]s | rd[4:0] | imm[4:0]s | b01;
args_disass: "x%rd$d, 0x%imm$05x";
if(rd == 0) raise(0, 2);
if(rd == 0) raise(0, 2); //TODO: should it be handled as trap?
X[rd] <= imm;
}
// order matters here as C.ADDI16SP overwrites C.LUI vor rd==2
C.LUI {//(RV32)
encoding:b011 | nzimm[17:17]s | rd[4:0] | nzimm[16:12]s | b01;
args_disass: "x%rd$d, 0x%nzimm$05x";
if(rd == 0) raise(0, 2);
if(rd == 2) raise(0, 2);
if(nzimm == 0) raise(0, 2);
X[rd] <= nzimm;
encoding:b011 | imm[17:17]s | rd[4:0] | imm[16:12]s | b01;
args_disass: "x%rd$d, 0x%imm$05x";
if(rd == 0) raise(0, 2); //TODO: should it be handled as trap?
if(imm == 0) raise(0, 2); //TODO: should it be handled as trap?
X[rd] <= imm;
}
C.ADDI16SP {//(RV32)
encoding:b011 | nzimm[9:9]s | b00010 | nzimm[4:4]s |nzimm[6:6]s | nzimm[8:7]s | nzimm[5:5]s | b01;
args_disass: "0x%nzimm$05x";
encoding:b011 | imm[9:9]s | b00010 | imm[4:4]s | imm[6:6]s | imm[8:7]s | imm[5:5]s | b01;
args_disass: "0x%imm$05x";
val x2_idx[5] <= 2;
X[x2_idx] <= X[x2_idx]s + nzimm;
X[x2_idx] <= X[x2_idx]s + imm;
}
C.SRLI {//(RV32 nse)
encoding:b100 | shamt[5:5] | b00 | rs1[2:0] | shamt[4:0] | b01;
encoding:b100 | b0 | b00 | rs1[2:0] | shamt[4:0] | b01;
args_disass: "x(8+%rs1$d), %shamt$d";
if(shamt > 31) raise(0, 2);
val rs1_idx[5] <= rs1+8;
X[rs1_idx] <= shrl(X[rs1_idx], shamt);
}
C.SRAI {//(RV32)
encoding:b100 | shamt[5:5] | b01 | rs1[2:0] | shamt[4:0] | b01;
encoding:b100 | b0 | b01 | rs1[2:0] | shamt[4:0] | b01;
args_disass: "x(8+%rs1$d), %shamt$d";
if(shamt > 31) raise(0, 2);
val rs1_idx[5] <= rs1+8;
X[rs1_idx] <= shra(X[rs1_idx], shamt);
}
@ -132,27 +124,23 @@ InsructionSet RV32CI {
PC<=PC+imm;
}
C.BEQZ(no_cont) {//(RV32)
encoding:b110 | imm[8:8]s | imm[4:3]s | rs1d[2:0] | imm[7:6]s |imm[2:1]s | imm[5:5]s | b01;
args_disass: "x(8+%rs1d$d), 0x%imm$05x";
val rs1[5] <= rs1d+8;
PC<=choose(X[rs1]==0, PC+imm, PC+2);
encoding:b110 | imm[8:8]s | imm[4:3]s | rs1[2:0] | imm[7:6]s |imm[2:1]s | imm[5:5]s | b01;
args_disass: "x(8+%rs1$d), 0x%imm$05x";
val rs1_idx[5] <= rs1+8;
PC<=choose(X[rs1_idx]==0, PC+imm, PC+2);
}
C.BNEZ(no_cont) {//(RV32)
encoding:b111 | imm[8:8] | imm[4:3] | rs1d[2:0] | imm[7:6] | imm[2:1] | imm[5:5] | b01;
args_disass: "x(8+%rs1d$d),, 0x%imm$05x";
val rs1[5] <= rs1d+8;
PC<=choose(X[rs1]!=0, PC+imm, PC+2);
encoding:b111 | imm[8:8]s | imm[4:3]s | rs1[2:0] | imm[7:6]s | imm[2:1]s | imm[5:5]s | b01;
args_disass: "x(8+%rs1$d), 0x%imm$05x";
val rs1_idx[5] <= rs1+8;
PC<=choose(X[rs1_idx]!=0, PC+imm, PC+2);
}
C.SLLI {//(RV32)
encoding:b000 | shamt[5:5] | rs1[4:0] | shamt[4:0] | b10;
encoding:b000 | b0 | rs1[4:0] | shamt[4:0] | b10;
args_disass: "x%rs1$d, %shamt$d";
if(rs1 == 0) raise(0, 2);
if(shamt > 31) raise(0, 2);
X[rs1] <= shll(X[rs1], shamt);
}
C.LQSP {//(RV128)
encoding:b001 | uimm[5:5] | rd[4:0] | uimm[4:4] | uimm[9:6] | b10;
}
C.LWSP {//
encoding:b010 | uimm[5:5] | rd[4:0] | uimm[4:2] | uimm[7:6] | b10;
args_disass: "x%rd$d, sp, 0x%uimm$05x";
@ -160,7 +148,7 @@ InsructionSet RV32CI {
val offs[XLEN] <= X[x2_idx] + uimm;
X[rd] <= MEM[offs]{32};
}
// order matters as C.JR is a special case of C.JR
// order matters as C.JR is a special case of C.MV
C.MV {//(RV32)
encoding:b100 | b0 | rd[4:0] | rs2[4:0] | b10;
args_disass: "x%rd$d, x%rs2$d";
@ -171,11 +159,7 @@ InsructionSet RV32CI {
args_disass: "x%rs1$d";
PC <= X[rs1];
}
C.EBREAK(no_cont) {//(RV32)
encoding:b100 | b1 | b00000 | b00000 | b10;
raise(0, 3);
}
// order matters as C.JALR is a special case of C.ADD
// order matters as C.EBREAK is a special case of C.JALR which is a special case of C.ADD
C.ADD {//(RV32)
encoding:b100 | b1 | rd[4:0] | rs2[4:0] | b10;
args_disass: "x%rd$d, x%rs2$d";
@ -184,10 +168,14 @@ InsructionSet RV32CI {
C.JALR(no_cont) {//(RV32)
encoding:b100 | b1 | rs1[4:0] | b00000 | b10;
args_disass: "x%rs1$d";
val rd[5] <= 1;
X[rd] <= PC+2;
val r_idx[5] <= 1;
X[r_idx] <= PC+2;
PC<=X[rs1];
}
C.EBREAK(no_cont) {//(RV32)
encoding:b100 | b1 | b00000 | b00000 | b10;
raise(0, 3);
}
C.SWSP {//
encoding:b110 | uimm[5:2] | uimm[7:6] | rs2[4:0] | b10;
args_disass: "x2+0x%uimm$05x, x%rs2$d";
@ -195,6 +183,10 @@ InsructionSet RV32CI {
val offs[XLEN] <= X[x2_idx] + uimm;
MEM[offs]{32} <= X[rs2];
}
DII {
encoding:b000 | b0 | b00000 | b00000 | b00;
raise(0, 2);
}
}
}

View File

@ -435,6 +435,8 @@ public:
virtual uint64_t leave_trap(uint64_t flags) override;
void wait_until(uint64_t flags) override;
void notify_phase(iss::arch_if::exec_phase phase);
void disass_output(uint64_t pc, const std::string instr) override {
std::stringstream s;
s << "[p:" << lvl[this->reg.machine_state] << ";s:0x" << std::hex << std::setfill('0')
@ -468,6 +470,7 @@ protected:
private:
iss::status read_cycle(unsigned addr, reg_t &val);
iss::status read_time(unsigned addr, reg_t &val);
iss::status read_status(unsigned addr, reg_t &val);
iss::status write_status(unsigned addr, reg_t val);
iss::status read_ie(unsigned addr, reg_t &val);
@ -489,6 +492,10 @@ riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp()
for (unsigned addr = mcycle; addr <= hpmcounter31; ++addr) csr_wr_cb[addr] = nullptr;
for (unsigned addr = mcycleh; addr <= hpmcounter31h; ++addr) csr_wr_cb[addr] = nullptr;
// special handling
csr_rd_cb[time] = &riscv_hart_msu_vp<BASE>::read_time;
csr_wr_cb[time] = nullptr;
csr_rd_cb[timeh] = &riscv_hart_msu_vp<BASE>::read_time;
csr_wr_cb[timeh] = nullptr;
csr_rd_cb[mcycle] = &riscv_hart_msu_vp<BASE>::read_cycle;
csr_rd_cb[mcycleh] = &riscv_hart_msu_vp<BASE>::read_cycle;
csr_rd_cb[minstret] = &riscv_hart_msu_vp<BASE>::read_cycle;
@ -781,6 +788,17 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_cycle(unsigne
return iss::Ok;
}
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_time(unsigned addr, reg_t &val) {
uint64_t time_val=this->reg.icount>>12;
if (addr == time) {
val = static_cast<reg_t>(time_val);
} else if (addr == timeh) {
if (sizeof(typename traits<BASE>::reg_t) != 4) return iss::Err;
val = static_cast<reg_t>(time_val >> 32);
}
return iss::Ok;
}
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_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);
@ -862,8 +880,9 @@ iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length
if ((paddr.val + length) > mem.size()) return iss::Err;
switch (paddr.val) {
case 0x0200BFF8: { // CLINT base, mtime reg
uint64_t mtime = this->reg.icount >> 12 /*12*/;
std::copy((uint8_t *)&mtime, ((uint8_t *)&mtime) + length, data);
if(sizeof(reg_t)<length) return iss::Err;
reg_t time_val=this->csr[time];
std::copy((uint8_t *)&time_val, ((uint8_t *)&time_val) + length, data);
} break;
case 0x10008000: {
const mem_type::page_type &p = mem(paddr.val / mem.page_size);
@ -954,6 +973,11 @@ iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned lengt
return iss::Ok;
}
template<typename BASE>
inline void riscv_hart_msu_vp<BASE>::notify_phase(iss::arch_if::exec_phase phase) {
BASE::notify_phase(phase);
}
template <typename BASE> void riscv_hart_msu_vp<BASE>::check_interrupt() {
auto status = state.mstatus;
auto ip = csr[mip];

View File

@ -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) };
@ -281,7 +282,7 @@ vm_impl<ARCH>::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<ARCH>::processing_pc_entry addr(*this, pc, paddr);
++inst_cnt;

View File

@ -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) };
@ -364,10 +365,10 @@ private:
{16, 0b0100000000000000, 0b1110000000000011, &this_class::__c_lw},
/* instruction C.SW */
{16, 0b1100000000000000, 0b1110000000000011, &this_class::__c_sw},
/* instruction C.NOP */
{16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop},
/* instruction C.ADDI */
{16, 0b0000000000000001, 0b1110000000000011, &this_class::__c_addi},
/* instruction C.NOP */
{16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop},
/* instruction C.JAL */
{16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_jal},
/* instruction C.LI */
@ -377,9 +378,9 @@ private:
/* instruction C.ADDI16SP */
{16, 0b0110000100000001, 0b1110111110000011, &this_class::__c_addi16sp},
/* instruction C.SRLI */
{16, 0b1000000000000001, 0b1110110000000011, &this_class::__c_srli},
{16, 0b1000000000000001, 0b1111110000000011, &this_class::__c_srli},
/* instruction C.SRAI */
{16, 0b1000010000000001, 0b1110110000000011, &this_class::__c_srai},
{16, 0b1000010000000001, 0b1111110000000011, &this_class::__c_srai},
/* instruction C.ANDI */
{16, 0b1000100000000001, 0b1110110000000011, &this_class::__c_andi},
/* instruction C.SUB */
@ -397,23 +398,23 @@ private:
/* instruction C.BNEZ */
{16, 0b1110000000000001, 0b1110000000000011, &this_class::__c_bnez},
/* instruction C.SLLI */
{16, 0b0000000000000010, 0b1110000000000011, &this_class::__c_slli},
/* instruction C.LQSP */
{16, 0b0010000000000010, 0b1110000000000011, &this_class::__c_lqsp},
{16, 0b0000000000000010, 0b1111000000000011, &this_class::__c_slli},
/* instruction C.LWSP */
{16, 0b0100000000000010, 0b1110000000000011, &this_class::__c_lwsp},
/* instruction C.MV */
{16, 0b1000000000000010, 0b1111000000000011, &this_class::__c_mv},
/* instruction C.JR */
{16, 0b1000000000000010, 0b1111000001111111, &this_class::__c_jr},
/* instruction C.EBREAK */
{16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak},
/* instruction C.ADD */
{16, 0b1001000000000010, 0b1111000000000011, &this_class::__c_add},
/* instruction C.JALR */
{16, 0b1001000000000010, 0b1111000001111111, &this_class::__c_jalr},
/* instruction C.EBREAK */
{16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak},
/* instruction C.SWSP */
{16, 0b1100000000000010, 0b1110000000000011, &this_class::__c_swsp},
/* instruction DII */
{16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii},
};
// instruction LUI
std::tuple<vm::continuation_e, llvm::BasicBlock*> __lui(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){
@ -3353,11 +3354,11 @@ private:
this->gen_sync(iss::PRE_SYNC);
uint8_t fld_rd_val = 0 | (bit_sub<2,3>(instr));
uint16_t fld_nzuimm_val = 0 | (bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4);
uint16_t fld_imm_val = 0 | (bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4);
if(this->disass_enabled){
/* generate console output when executing the command */
boost::format ins_fmter("C.ADDI4SPN x%1$d, 0x%2$05x");
ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_nzuimm_val;
ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_imm_val;
std::vector<llvm::Value*> args {
this->core_ptr,
this->gen_const(64, pc.val),
@ -3367,14 +3368,14 @@ private:
}
pc=pc+2;
if(fld_nzuimm_val == 0){
if(fld_imm_val == 0){
this->gen_raise_trap(0, 2);
}
uint8_t rd_idx_val = (fld_rd_val + 8);
uint8_t x2_idx_val = 2;
Value* X_rd_idx_val = this->builder->CreateAdd(
this->gen_reg_load(x2_idx_val, 0),
this->gen_const(32U, fld_nzuimm_val));
this->gen_const(32U, fld_imm_val));
this->builder->CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val), false);
this->gen_set_pc(pc, traits<ARCH>::NEXT_PC);
this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */
@ -3406,11 +3407,11 @@ private:
pc=pc+2;
uint8_t rs1_idx_val = (fld_rs1_val + 8);
Value* adr_val = this->builder->CreateAdd(
uint8_t rd_idx_val = (fld_rd_val + 8);
Value* offs_val = this->builder->CreateAdd(
this->gen_reg_load(rs1_idx_val, 0),
this->gen_const(32U, fld_uimm_val));
uint8_t rd_idx_val = (fld_rd_val + 8);
Value* X_rd_idx_val = this->gen_read_mem(traits<ARCH>::MEM, adr_val, 32/8);
Value* X_rd_idx_val = this->gen_read_mem(traits<ARCH>::MEM, offs_val, 32/8);
this->builder->CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val), false);
this->gen_set_pc(pc, traits<ARCH>::NEXT_PC);
this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */
@ -3442,15 +3443,47 @@ private:
pc=pc+2;
uint8_t rs1_idx_val = (fld_rs1_val + 8);
Value* adr_val = this->builder->CreateAdd(
uint8_t rs2_idx_val = (fld_rs2_val + 8);
Value* offs_val = this->builder->CreateAdd(
this->gen_reg_load(rs1_idx_val, 0),
this->gen_const(32U, fld_uimm_val));
uint8_t rs2_idx_val = (fld_rs2_val + 8);
Value* MEM_adr_val = this->gen_reg_load(rs2_idx_val, 0);
Value* MEM_offs_val = this->gen_reg_load(rs2_idx_val, 0);
this->gen_write_mem(
traits<ARCH>::MEM,
adr_val,
this->builder->CreateZExtOrTrunc(MEM_adr_val,this->get_type(32)));
offs_val,
this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32)));
this->gen_set_pc(pc, traits<ARCH>::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 */
this->gen_trap_check(bb);
return std::make_tuple(vm::CONT, bb);
}
// instruction C.ADDI
std::tuple<vm::continuation_e, llvm::BasicBlock*> __c_addi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){
bb->setName("C.ADDI");
this->gen_sync(iss::PRE_SYNC);
int8_t fld_imm_val = 0 | (bit_sub<2,5>(instr)) | (signed_bit_sub<12,1>(instr) << 5);
uint8_t fld_rs1_val = 0 | (bit_sub<7,5>(instr));
if(this->disass_enabled){
/* generate console output when executing the command */
boost::format ins_fmter("C.ADDI x%1$d, 0x%2$05x");
ins_fmter % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val;
std::vector<llvm::Value*> args {
this->core_ptr,
this->gen_const(64, pc.val),
this->builder->CreateGlobalStringPtr(ins_fmter.str()),
};
this->builder->CreateCall(this->mod->getFunction("print_disass"), args);
}
pc=pc+2;
Value* X_rs1_val = this->builder->CreateAdd(
this->gen_reg_load(fld_rs1_val, 0),
this->gen_const(32U, fld_imm_val));
this->builder->CreateStore(X_rs1_val, get_reg_ptr(fld_rs1_val), false);
this->gen_set_pc(pc, traits<ARCH>::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 */
@ -3467,12 +3500,10 @@ private:
;
if(this->disass_enabled){
/* generate console output when executing the command */
boost::format ins_fmter("C.NOP ");
ins_fmter ;
std::vector<llvm::Value*> args {
this->core_ptr,
this->gen_const(64, pc.val),
this->builder->CreateGlobalStringPtr(ins_fmter.str()),
this->builder->CreateGlobalStringPtr("C.NOP"),
};
this->builder->CreateCall(this->mod->getFunction("print_disass"), args);
}
@ -3486,41 +3517,6 @@ private:
return std::make_tuple(vm::CONT, bb);
}
// instruction C.ADDI
std::tuple<vm::continuation_e, llvm::BasicBlock*> __c_addi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){
bb->setName("C.ADDI");
this->gen_sync(iss::PRE_SYNC);
int8_t fld_nzimm_val = 0 | (bit_sub<2,5>(instr)) | (signed_bit_sub<12,1>(instr) << 5);
uint8_t fld_rs1_val = 0 | (bit_sub<7,5>(instr));
if(this->disass_enabled){
/* generate console output when executing the command */
boost::format ins_fmter("C.ADDI x%1$d, 0x%2$05x");
ins_fmter % (uint64_t)fld_rs1_val % (int64_t)fld_nzimm_val;
std::vector<llvm::Value*> args {
this->core_ptr,
this->gen_const(64, pc.val),
this->builder->CreateGlobalStringPtr(ins_fmter.str()),
};
this->builder->CreateCall(this->mod->getFunction("print_disass"), args);
}
pc=pc+2;
if(fld_nzimm_val == 0){
this->gen_raise_trap(0, 2);
}
Value* X_rs1_val = this->builder->CreateAdd(
this->gen_reg_load(fld_rs1_val, 0),
this->gen_const(32U, fld_nzimm_val));
this->builder->CreateStore(X_rs1_val, get_reg_ptr(fld_rs1_val), false);
this->gen_set_pc(pc, traits<ARCH>::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 */
this->gen_trap_check(bb);
return std::make_tuple(vm::CONT, bb);
}
// instruction C.JAL
std::tuple<vm::continuation_e, llvm::BasicBlock*> __c_jal(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){
bb->setName("C.JAL");
@ -3594,12 +3590,12 @@ private:
this->gen_sync(iss::PRE_SYNC);
int32_t fld_nzimm_val = 0 | (bit_sub<2,5>(instr) << 12) | (signed_bit_sub<12,1>(instr) << 17);
int32_t fld_imm_val = 0 | (bit_sub<2,5>(instr) << 12) | (signed_bit_sub<12,1>(instr) << 17);
uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr));
if(this->disass_enabled){
/* generate console output when executing the command */
boost::format ins_fmter("C.LUI x%1$d, 0x%2$05x");
ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_nzimm_val;
ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val;
std::vector<llvm::Value*> args {
this->core_ptr,
this->gen_const(64, pc.val),
@ -3612,13 +3608,10 @@ private:
if(fld_rd_val == 0){
this->gen_raise_trap(0, 2);
}
if(fld_rd_val == 2){
if(fld_imm_val == 0){
this->gen_raise_trap(0, 2);
}
if(fld_nzimm_val == 0){
this->gen_raise_trap(0, 2);
}
Value* X_rd_val = this->gen_const(32U, fld_nzimm_val);
Value* X_rd_val = this->gen_const(32U, fld_imm_val);
this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false);
this->gen_set_pc(pc, traits<ARCH>::NEXT_PC);
this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */
@ -3633,11 +3626,11 @@ private:
this->gen_sync(iss::PRE_SYNC);
int16_t fld_nzimm_val = 0 | (bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (signed_bit_sub<12,1>(instr) << 9);
int16_t fld_imm_val = 0 | (bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (signed_bit_sub<12,1>(instr) << 9);
if(this->disass_enabled){
/* generate console output when executing the command */
boost::format ins_fmter("C.ADDI16SP 0x%1$05x");
ins_fmter % (int64_t)fld_nzimm_val;
ins_fmter % (int64_t)fld_imm_val;
std::vector<llvm::Value*> args {
this->core_ptr,
this->gen_const(64, pc.val),
@ -3652,7 +3645,7 @@ private:
this->gen_ext(
this->gen_reg_load(x2_idx_val, 0),
32, true),
this->gen_const(32U, fld_nzimm_val));
this->gen_const(32U, fld_imm_val));
this->builder->CreateStore(X_x2_idx_val, get_reg_ptr(x2_idx_val), false);
this->gen_set_pc(pc, traits<ARCH>::NEXT_PC);
this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */
@ -3667,7 +3660,7 @@ private:
this->gen_sync(iss::PRE_SYNC);
uint8_t fld_shamt_val = 0 | (bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5);
uint8_t fld_shamt_val = 0 | (bit_sub<2,5>(instr));
uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr));
if(this->disass_enabled){
/* generate console output when executing the command */
@ -3682,9 +3675,6 @@ private:
}
pc=pc+2;
if(fld_shamt_val > 31){
this->gen_raise_trap(0, 2);
}
uint8_t rs1_idx_val = (fld_rs1_val + 8);
Value* X_rs1_idx_val = this->builder->CreateLShr(
this->gen_reg_load(rs1_idx_val, 0),
@ -3703,7 +3693,7 @@ private:
this->gen_sync(iss::PRE_SYNC);
uint8_t fld_shamt_val = 0 | (bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5);
uint8_t fld_shamt_val = 0 | (bit_sub<2,5>(instr));
uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr));
if(this->disass_enabled){
/* generate console output when executing the command */
@ -3718,9 +3708,6 @@ private:
}
pc=pc+2;
if(fld_shamt_val > 31){
this->gen_raise_trap(0, 2);
}
uint8_t rs1_idx_val = (fld_rs1_val + 8);
Value* X_rs1_idx_val = this->builder->CreateAShr(
this->gen_reg_load(rs1_idx_val, 0),
@ -3938,11 +3925,11 @@ private:
this->gen_sync(iss::PRE_SYNC);
int16_t fld_imm_val = 0 | (bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (signed_bit_sub<12,1>(instr) << 8);
uint8_t fld_rs1d_val = 0 | (bit_sub<7,3>(instr));
uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr));
if(this->disass_enabled){
/* generate console output when executing the command */
boost::format ins_fmter("C.BEQZ x(8+%1$d), 0x%2$05x");
ins_fmter % (uint64_t)fld_rs1d_val % (int64_t)fld_imm_val;
ins_fmter % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val;
std::vector<llvm::Value*> args {
this->core_ptr,
this->gen_const(64, pc.val),
@ -3952,11 +3939,11 @@ private:
}
pc=pc+2;
uint8_t rs1_val = (fld_rs1d_val + 8);
uint8_t rs1_idx_val = (fld_rs1_val + 8);
Value* PC_val = this->gen_choose(
this->builder->CreateICmp(
ICmpInst::ICMP_EQ,
this->gen_reg_load(rs1_val, 0),
this->gen_reg_load(rs1_idx_val, 0),
this->gen_const(32U, 0)),
this->builder->CreateAdd(
this->gen_reg_load(traits<ARCH>::PC, 0),
@ -3977,12 +3964,12 @@ private:
this->gen_sync(iss::PRE_SYNC);
uint16_t fld_imm_val = 0 | (bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8);
uint8_t fld_rs1d_val = 0 | (bit_sub<7,3>(instr));
int16_t fld_imm_val = 0 | (bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (signed_bit_sub<12,1>(instr) << 8);
uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr));
if(this->disass_enabled){
/* generate console output when executing the command */
boost::format ins_fmter("C.BNEZ x(8+%1$d),, 0x%2$05x");
ins_fmter % (uint64_t)fld_rs1d_val % (uint64_t)fld_imm_val;
boost::format ins_fmter("C.BNEZ x(8+%1$d), 0x%2$05x");
ins_fmter % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val;
std::vector<llvm::Value*> args {
this->core_ptr,
this->gen_const(64, pc.val),
@ -3992,11 +3979,11 @@ private:
}
pc=pc+2;
uint8_t rs1_val = (fld_rs1d_val + 8);
uint8_t rs1_idx_val = (fld_rs1_val + 8);
Value* PC_val = this->gen_choose(
this->builder->CreateICmp(
ICmpInst::ICMP_NE,
this->gen_reg_load(rs1_val, 0),
this->gen_reg_load(rs1_idx_val, 0),
this->gen_const(32U, 0)),
this->builder->CreateAdd(
this->gen_reg_load(traits<ARCH>::PC, 0),
@ -4017,7 +4004,7 @@ private:
this->gen_sync(iss::PRE_SYNC);
uint8_t fld_shamt_val = 0 | (bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5);
uint8_t fld_shamt_val = 0 | (bit_sub<2,5>(instr));
uint8_t fld_rs1_val = 0 | (bit_sub<7,5>(instr));
if(this->disass_enabled){
/* generate console output when executing the command */
@ -4035,9 +4022,6 @@ private:
if(fld_rs1_val == 0){
this->gen_raise_trap(0, 2);
}
if(fld_shamt_val > 31){
this->gen_raise_trap(0, 2);
}
Value* X_rs1_val = this->builder->CreateShl(
this->gen_reg_load(fld_rs1_val, 0),
this->gen_const(32U, fld_shamt_val));
@ -4049,33 +4033,6 @@ private:
return std::make_tuple(vm::CONT, bb);
}
// instruction C.LQSP
std::tuple<vm::continuation_e, llvm::BasicBlock*> __c_lqsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){
bb->setName("C.LQSP");
this->gen_sync(iss::PRE_SYNC);
uint16_t fld_uimm_val = 0 | (bit_sub<2,4>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 5);
uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr));
if(this->disass_enabled){
/* generate console output when executing the command */
std::vector<llvm::Value*> args {
this->core_ptr,
this->gen_const(64, pc.val),
this->builder->CreateGlobalStringPtr("C.LQSP"),
};
this->builder->CreateCall(this->mod->getFunction("print_disass"), args);
}
pc=pc+2;
/* TODO: describe operations for C.LQSP ! */
this->gen_set_pc(pc, traits<ARCH>::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 */
this->gen_trap_check(bb);
return std::make_tuple(vm::CONT, bb);
}
// instruction C.LWSP
std::tuple<vm::continuation_e, llvm::BasicBlock*> __c_lwsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){
bb->setName("C.LWSP");
@ -4167,30 +4124,6 @@ private:
return std::make_tuple(iss::vm::BRANCH, nullptr);
}
// instruction C.EBREAK
std::tuple<vm::continuation_e, llvm::BasicBlock*> __c_ebreak(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){
bb->setName("C.EBREAK");
this->gen_sync(iss::PRE_SYNC);
;
if(this->disass_enabled){
/* generate console output when executing the command */
std::vector<llvm::Value*> args {
this->core_ptr,
this->gen_const(64, pc.val),
this->builder->CreateGlobalStringPtr("C.EBREAK"),
};
this->builder->CreateCall(this->mod->getFunction("print_disass"), args);
}
pc=pc+2;
this->gen_raise_trap(0, 3);
this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */
this->gen_trap_check(this->leave_blk);
return std::make_tuple(iss::vm::BRANCH, nullptr);
}
// instruction C.ADD
std::tuple<vm::continuation_e, llvm::BasicBlock*> __c_add(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){
bb->setName("C.ADD");
@ -4243,11 +4176,11 @@ private:
}
pc=pc+2;
uint8_t rd_val = 1;
Value* X_rd_val = this->builder->CreateAdd(
uint8_t r_idx_val = 1;
Value* X_r_idx_val = this->builder->CreateAdd(
this->gen_reg_load(traits<ARCH>::PC, 0),
this->gen_const(32U, 2));
this->builder->CreateStore(X_rd_val, get_reg_ptr(rd_val), false);
this->builder->CreateStore(X_r_idx_val, get_reg_ptr(r_idx_val), false);
Value* PC_val = this->gen_reg_load(fld_rs1_val, 0);
this->builder->CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false);
this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */
@ -4255,6 +4188,30 @@ private:
return std::make_tuple(iss::vm::BRANCH, nullptr);
}
// instruction C.EBREAK
std::tuple<vm::continuation_e, llvm::BasicBlock*> __c_ebreak(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){
bb->setName("C.EBREAK");
this->gen_sync(iss::PRE_SYNC);
;
if(this->disass_enabled){
/* generate console output when executing the command */
std::vector<llvm::Value*> args {
this->core_ptr,
this->gen_const(64, pc.val),
this->builder->CreateGlobalStringPtr("C.EBREAK"),
};
this->builder->CreateCall(this->mod->getFunction("print_disass"), args);
}
pc=pc+2;
this->gen_raise_trap(0, 3);
this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */
this->gen_trap_check(this->leave_blk);
return std::make_tuple(iss::vm::BRANCH, nullptr);
}
// instruction C.SWSP
std::tuple<vm::continuation_e, llvm::BasicBlock*> __c_swsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){
bb->setName("C.SWSP");
@ -4292,6 +4249,32 @@ private:
return std::make_tuple(vm::CONT, bb);
}
// instruction DII
std::tuple<vm::continuation_e, llvm::BasicBlock*> __dii(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){
bb->setName("DII");
this->gen_sync(iss::PRE_SYNC);
;
if(this->disass_enabled){
/* generate console output when executing the command */
std::vector<llvm::Value*> args {
this->core_ptr,
this->gen_const(64, pc.val),
this->builder->CreateGlobalStringPtr("DII"),
};
this->builder->CreateCall(this->mod->getFunction("print_disass"), args);
}
pc=pc+2;
this->gen_raise_trap(0, 2);
this->gen_set_pc(pc, traits<ARCH>::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 */
this->gen_trap_check(bb);
return std::make_tuple(vm::CONT, bb);
}
/* end generated code */
/****************************************************************************
* end opcode definitions
@ -4358,7 +4341,7 @@ vm_impl<ARCH>::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<ARCH>::processing_pc_entry addr(*this, pc, paddr);
++inst_cnt;

@ -1 +1 @@
Subproject commit fbd3247649d3b12d0e752c92a5d856572641445c
Subproject commit ba65d9f172246d6735a40fd6259ec13467e43419