fix RVC description bugs, remove paged fetch

This commit is contained in:
Eyck Jentzsch 2021-03-13 10:19:30 +00:00
parent a5186ff88d
commit 80057eef32
3 changed files with 162 additions and 163 deletions

@ -1 +1 @@
Subproject commit d51b3e30f5c4b9863411fbecad6ec7e5793f865e Subproject commit eab89af46bd1d6485e150111db1612ce8dca984b

View File

@ -165,8 +165,8 @@ protected:
inline void writeSpace2(typename super::mem_type_e space, uint64_t addr, uint16_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 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);} inline void writeSpace8(typename super::mem_type_e space, uint64_t addr, uint64_t data){super::write_mem(space, addr, data);}
template<unsigned W, typename T> template<unsigned W, typename U, typename S = typename std::make_signed<U>::type>
inline T sext(T from) { inline S sext(U from) {
auto mask = (1ULL<<W) - 1; auto mask = (1ULL<<W) - 1;
auto sign_mask = 1ULL<<(W-1); auto sign_mask = 1ULL<<(W-1);
return (from & mask) | ((from & sign_mask) ? ~mask : 0); return (from & mask) | ((from & sign_mask) ? ~mask : 0);
@ -241,13 +241,13 @@ private:
static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK; static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK;
iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ iss::status fetch_ins(virt_addr_t pc, uint8_t * data){
auto phys_pc = this->core.v2p(pc); auto phys_pc = this->core.v2p(pc);
if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary //if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
if (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err; // if (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err;
if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction // if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction
if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) return iss::Err; // if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) return iss::Err;
} else { //} else {
if (this->core.read(phys_pc, 4, data) != iss::Ok) return iss::Err; if (this->core.read(phys_pc, 4, data) != iss::Ok) return iss::Err;
} //}
return iss::Ok; return iss::Ok;
} }
}; };

View File

@ -165,8 +165,8 @@ protected:
inline void writeSpace2(typename super::mem_type_e space, uint64_t addr, uint16_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 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);} inline void writeSpace8(typename super::mem_type_e space, uint64_t addr, uint64_t data){super::write_mem(space, addr, data);}
template<unsigned W, typename T> template<unsigned W, typename U, typename S = typename std::make_signed<U>::type>
inline T sext(T from) { inline S sext(U from) {
auto mask = (1ULL<<W) - 1; auto mask = (1ULL<<W) - 1;
auto sign_mask = 1ULL<<(W-1); auto sign_mask = 1ULL<<(W-1);
return (from & mask) | ((from & sign_mask) ? ~mask : 0); return (from & mask) | ((from & sign_mask) ? ~mask : 0);
@ -486,7 +486,7 @@ private:
// execute instruction // execute instruction
{ {
int32_t new_pc = *(X+rs1) + (int16_t)sext<12>(imm); int32_t new_pc = *(X+rs1) + (int16_t)sext<12>(imm);
if(rd != 0) *(X+rd) = *PC + 4; if(rd != 0) *(X+rd) = *PC + 2;
pc_assign(*NEXT_PC) = new_pc & ~ 0x1; pc_assign(*NEXT_PC) = new_pc & ~ 0x1;
} }
// post execution stuff // post execution stuff
@ -1889,8 +1889,8 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
writeSpace1(traits::FENCE, traits::fencevmal, (uint8_t)rs1); writeSpace4(traits::FENCE, traits::fencevmal, (uint32_t)rs1);
writeSpace1(traits::FENCE, traits::fencevmau, (uint8_t)rs2); writeSpace4(traits::FENCE, traits::fencevmau, (uint32_t)rs2);
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 45); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 45);
@ -2155,7 +2155,7 @@ private:
// execute instruction // execute instruction
{ {
if(rd != 0) { if(rd != 0) {
int64_t res = (int64_t)*(X+rs1) * (int64_t)*(X+rs2); int64_t res = (int32_t)*(X+rs1) * (int32_t)*(X+rs2);
*(X+rd) = (uint32_t)res; *(X+rd) = (uint32_t)res;
} }
} }
@ -2193,7 +2193,7 @@ private:
// execute instruction // execute instruction
{ {
if(rd != 0) { if(rd != 0) {
int64_t res = (int64_t)*(X+rs1) * (int64_t)*(X+rs2); int64_t res = (int32_t)*(X+rs1) * (int32_t)*(X+rs2);
*(X+rd) = (uint32_t)(res >> traits::XLEN); *(X+rd) = (uint32_t)(res >> traits::XLEN);
} }
} }
@ -2231,7 +2231,7 @@ private:
// execute instruction // execute instruction
{ {
if(rd != 0) { if(rd != 0) {
int64_t res = (int64_t)*(X+rs1) * (uint64_t)*(X+rs2); int64_t res = (int32_t)*(X+rs1) * (uint32_t)*(X+rs2);
*(X+rd) = (uint32_t)res; *(X+rd) = (uint32_t)res;
} }
} }
@ -2269,7 +2269,7 @@ private:
// execute instruction // execute instruction
{ {
if(rd != 0) { if(rd != 0) {
uint64_t res = (uint64_t)*(X+rs1) * (uint64_t)*(X+rs2); uint64_t res = (uint32_t)*(X+rs1) * (uint32_t)*(X+rs2);
*(X+rd) = (uint32_t)res; *(X+rd) = (uint32_t)res;
} }
} }
@ -2309,8 +2309,8 @@ private:
if(rd != 0) { if(rd != 0) {
if(*(X+rs2) != 0) { if(*(X+rs2) != 0) {
uint32_t MMIN = 1 << (traits::XLEN - 1); uint32_t MMIN = 1 << (traits::XLEN - 1);
if(*(X+rs1) == MMIN && (int8_t)*(X+rs2) == - 1) *(X+rd) = MMIN; if(*(X+rs1) == MMIN && (int32_t)*(X+rs2) == - 1) *(X+rd) = MMIN;
else *(X+rd) = (int8_t)*(X+rs1) / (int8_t)*(X+rs2); else *(X+rd) = (int32_t)*(X+rs1) / (int32_t)*(X+rs2);
} }
else *(X+rd) = - 1; else *(X+rd) = - 1;
} }
@ -2389,8 +2389,8 @@ private:
if(rd != 0) { if(rd != 0) {
if(*(X+rs2) != 0) { if(*(X+rs2) != 0) {
uint32_t MMIN = 1 << (traits::XLEN - 1); uint32_t MMIN = 1 << (traits::XLEN - 1);
if(*(X+rs1) == MMIN && *(X+rs2) == - 1) *(X+rd) = 0; if(*(X+rs1) == MMIN && (int32_t)*(X+rs2) == - 1) *(X+rd) = 0;
else *(X+rd) = (int8_t)*(X+rs1) % (int8_t)*(X+rs2); else *(X+rd) = (int32_t)*(X+rs1) % (int32_t)*(X+rs2);
} }
else *(X+rd) = *(X+rs1); else *(X+rd) = *(X+rs1);
} }
@ -2669,7 +2669,7 @@ private:
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
{ {
if(rd == 0) *(X+rd) = (int8_t)sext<6>(imm); if(rd != 0) *(X+rd) = (uint32_t)(int32_t)sext<6>(imm);
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 66); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 66);
@ -2722,13 +2722,12 @@ private:
compile_ret_t __caddi16sp(virt_addr_t& pc, code_word_t instr){ compile_ret_t __caddi16sp(virt_addr_t& pc, code_word_t instr){
// pre execution stuff // pre execution stuff
this->do_sync(PRE_SYNC, 68); this->do_sync(PRE_SYNC, 68);
uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4)); uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9));
uint16_t imm = ((bit_sub<12,1>(instr) << 9));
if(this->disass_enabled){ if(this->disass_enabled){
/* generate console output when executing the command */ /* generate console output when executing the command */
auto mnemonic = fmt::format( auto mnemonic = fmt::format(
"{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "caddi16sp"), "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "caddi16sp"),
fmt::arg("imm", nzimm)); fmt::arg("nzimm", nzimm));
this->core.disass_output(pc.val, mnemonic); this->core.disass_output(pc.val, mnemonic);
} }
@ -2772,8 +2771,8 @@ private:
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
{ {
uint8_t rs1_idx = rs1 + 8; uint32_t rs1_idx = rs1 + 8;
*(X+rs1_idx) = *(X+rs1_idx) << shamt; *(X+rs1_idx) = *(X+rs1_idx) >> shamt;
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 69); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 69);
@ -2807,11 +2806,11 @@ private:
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
if(shamt) { if(shamt) {
uint8_t rs1_idx = rs1 + 8; uint32_t rs1_idx = rs1 + 8;
*(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> shamt; *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> shamt;
} }
else if(traits::XLEN == 128) { else if(traits::XLEN == 128) {
uint8_t rs1_idx = rs1 + 8; uint32_t rs1_idx = rs1 + 8;
*(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> 64; *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> 64;
} }
// post execution stuff // post execution stuff
@ -2846,7 +2845,7 @@ private:
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
{ {
uint8_t rs1_idx = rs1 + 8; uint32_t rs1_idx = rs1 + 8;
*(X+rs1_idx) = *(X+rs1_idx) & (int8_t)sext<6>(imm); *(X+rs1_idx) = *(X+rs1_idx) & (int8_t)sext<6>(imm);
} }
// post execution stuff // post execution stuff
@ -2881,7 +2880,7 @@ private:
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
{ {
uint8_t rd_idx = rd + 8; uint32_t rd_idx = rd + 8;
*(X+rd_idx) = *(X+rd_idx) - *(X+(rs2 + 8)); *(X+rd_idx) = *(X+rd_idx) - *(X+(rs2 + 8));
} }
// post execution stuff // post execution stuff
@ -2916,7 +2915,7 @@ private:
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
{ {
uint8_t rd_idx = rd + 8; uint32_t rd_idx = rd + 8;
*(X+rd_idx) = *(X+rd_idx) ^ *(X+(rs2 + 8)); *(X+rd_idx) = *(X+rd_idx) ^ *(X+(rs2 + 8));
} }
// post execution stuff // post execution stuff
@ -2951,7 +2950,7 @@ private:
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
{ {
uint8_t rd_idx = rd + 8; uint32_t rd_idx = rd + 8;
*(X+rd_idx) = *(X+rd_idx) | *(X+(rs2 + 8)); *(X+rd_idx) = *(X+rd_idx) | *(X+(rs2 + 8));
} }
// post execution stuff // post execution stuff
@ -2986,7 +2985,7 @@ private:
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
{ {
uint8_t rd_idx = rd + 8; uint32_t rd_idx = rd + 8;
*(X+rd_idx) = *(X+rd_idx) & *(X+(rs2 + 8)); *(X+rd_idx) = *(X+rd_idx) & *(X+(rs2 + 8));
} }
// post execution stuff // post execution stuff
@ -3405,13 +3404,13 @@ private:
static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK; static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK;
iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ iss::status fetch_ins(virt_addr_t pc, uint8_t * data){
auto phys_pc = this->core.v2p(pc); auto phys_pc = this->core.v2p(pc);
if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary //if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
if (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err; // if (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err;
if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction // if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction
if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) return iss::Err; // if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) return iss::Err;
} else { //} else {
if (this->core.read(phys_pc, 4, data) != iss::Ok) return iss::Err; if (this->core.read(phys_pc, 4, data) != iss::Ok) return iss::Err;
} //}
return iss::Ok; return iss::Ok;
} }
}; };