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);
@ -449,8 +449,8 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rd != 0) *(X+rd) = *PC + 4; if(rd != 0) *(X+rd) = *PC + 4;
pc_assign(*NEXT_PC) = *PC + (int32_t)sext<21>(imm); pc_assign(*NEXT_PC) = *PC + (int32_t)sext<21>(imm);
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 2); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 2);
@ -485,9 +485,9 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// 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
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 3); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 3);
@ -720,8 +720,8 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
int8_t res = (int8_t)readSpace1(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm)); int8_t res = (int8_t)readSpace1(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm));
if(rd != 0) *(X+rd) = res; if(rd != 0) *(X+rd) = res;
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 10); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 10);
@ -756,12 +756,12 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm);
if(traits::eei_aligned_addresses && (load_address & 0x1)) raise(0, 4); if(traits::eei_aligned_addresses && (load_address & 0x1)) raise(0, 4);
else { else {
int16_t res = (int16_t)readSpace2(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm)); int16_t res = (int16_t)readSpace2(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm));
if(rd != 0) *(X+rd) = res; if(rd != 0) *(X+rd) = res;
} }
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 11); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 11);
@ -796,12 +796,12 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm);
if(traits::eei_aligned_addresses && (load_address & 0x3)) raise(0, 4); if(traits::eei_aligned_addresses && (load_address & 0x3)) raise(0, 4);
else { else {
int32_t res = (int32_t)readSpace4(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm)); int32_t res = (int32_t)readSpace4(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm));
if(rd != 0) *(X+rd) = (uint32_t)res; if(rd != 0) *(X+rd) = (uint32_t)res;
} }
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 12); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 12);
@ -836,8 +836,8 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
uint8_t res = (uint8_t)readSpace1(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm)); uint8_t res = (uint8_t)readSpace1(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm));
if(rd != 0) *(X+rd) = res; if(rd != 0) *(X+rd) = res;
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 13); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 13);
@ -872,12 +872,12 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm);
if(traits::eei_aligned_addresses && (load_address & 0x1)) raise(0, 4); if(traits::eei_aligned_addresses && (load_address & 0x1)) raise(0, 4);
else { else {
uint16_t res = (uint16_t)readSpace2(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm)); uint16_t res = (uint16_t)readSpace2(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm));
if(rd != 0) *(X+rd) = res; if(rd != 0) *(X+rd) = res;
} }
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 14); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 14);
@ -945,9 +945,9 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm); uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm);
if(traits::eei_aligned_addresses && (store_address & 0x1)) raise(0, 6); if(traits::eei_aligned_addresses && (store_address & 0x1)) raise(0, 6);
else writeSpace2(traits::MEM, store_address, (int16_t)*(X+rs2)); else writeSpace2(traits::MEM, store_address, (int16_t)*(X+rs2));
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 16); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 16);
@ -982,9 +982,9 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm); uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm);
if(traits::eei_aligned_addresses && (store_address & 0x3)) raise(0, 6); if(traits::eei_aligned_addresses && (store_address & 0x3)) raise(0, 6);
else writeSpace4(traits::MEM, store_address, *(X+rs2)); else writeSpace4(traits::MEM, store_address, *(X+rs2));
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 17); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 17);
@ -1217,10 +1217,10 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
if(shamt > 31) { if(shamt > 31) {
raise(0, 0); raise(0, 0);
} }
else { else {
if(rd != 0) *(X+rd) = *(X+rs1) << shamt; if(rd != 0) *(X+rd) = *(X+rs1) << shamt;
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 24); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 24);
@ -1255,10 +1255,10 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
if(shamt > 31) { if(shamt > 31) {
raise(0, 0); raise(0, 0);
} }
else { else {
if(rd != 0) *(X+rd) = *(X+rs1) >> shamt; if(rd != 0) *(X+rd) = *(X+rs1) >> shamt;
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 25); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 25);
@ -1293,10 +1293,10 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
if(shamt > 31) { if(shamt > 31) {
raise(0, 0); raise(0, 0);
} }
else { else {
if(rd != 0) *(X+rd) = (int32_t)*(X+rs1) >> shamt; if(rd != 0) *(X+rd) = (int32_t)*(X+rs1) >> shamt;
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 26); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 26);
@ -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);
@ -1925,15 +1925,15 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
uint32_t rs_val = *(X+rs1); uint32_t rs_val = *(X+rs1);
if(rd != 0) { if(rd != 0) {
uint32_t csr_val = readSpace4(traits::CSR, csr); uint32_t csr_val = readSpace4(traits::CSR, csr);
writeSpace4(traits::CSR, csr, rs_val); writeSpace4(traits::CSR, csr, rs_val);
*(X+rd) = csr_val; *(X+rd) = csr_val;
} }
else { else {
writeSpace4(traits::CSR, csr, rs_val); writeSpace4(traits::CSR, csr, rs_val);
} }
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 46); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 46);
@ -1968,10 +1968,10 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
uint32_t xrd = readSpace4(traits::CSR, csr); uint32_t xrd = readSpace4(traits::CSR, csr);
uint32_t xrs1 = *(X+rs1); uint32_t xrs1 = *(X+rs1);
if(rd != 0) *(X+rd) = xrd; if(rd != 0) *(X+rd) = xrd;
if(rs1 != 0) writeSpace4(traits::CSR, csr, xrd | xrs1); if(rs1 != 0) writeSpace4(traits::CSR, csr, xrd | xrs1);
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 47); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 47);
@ -2006,10 +2006,10 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
uint32_t xrd = readSpace4(traits::CSR, csr); uint32_t xrd = readSpace4(traits::CSR, csr);
uint32_t xrs1 = *(X+rs1); uint32_t xrs1 = *(X+rs1);
if(rd != 0) *(X+rd) = xrd; if(rd != 0) *(X+rd) = xrd;
if(rs1 != 0) writeSpace4(traits::CSR, csr, xrd & ~ xrs1); if(rs1 != 0) writeSpace4(traits::CSR, csr, xrd & ~ xrs1);
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 48); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 48);
@ -2044,8 +2044,8 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rd != 0) *(X+rd) = readSpace4(traits::CSR, csr); if(rd != 0) *(X+rd) = readSpace4(traits::CSR, csr);
writeSpace4(traits::CSR, csr, (uint32_t)zimm); writeSpace4(traits::CSR, csr, (uint32_t)zimm);
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 49); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 49);
@ -2080,9 +2080,9 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
uint32_t res = readSpace4(traits::CSR, csr); uint32_t res = readSpace4(traits::CSR, csr);
if(zimm != 0) writeSpace4(traits::CSR, csr, res | (uint32_t)zimm); if(zimm != 0) writeSpace4(traits::CSR, csr, res | (uint32_t)zimm);
if(rd != 0) *(X+rd) = res; if(rd != 0) *(X+rd) = res;
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 50); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 50);
@ -2117,9 +2117,9 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
uint32_t res = readSpace4(traits::CSR, csr); uint32_t res = readSpace4(traits::CSR, csr);
if(rd != 0) *(X+rd) = res; if(rd != 0) *(X+rd) = res;
if(zimm != 0) writeSpace4(traits::CSR, csr, res & ~ ((uint32_t)zimm)); if(zimm != 0) writeSpace4(traits::CSR, csr, res & ~ ((uint32_t)zimm));
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 51); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 51);
@ -2154,10 +2154,10 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// 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;
} }
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 52); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 52);
@ -2192,10 +2192,10 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// 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);
} }
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 53); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 53);
@ -2230,10 +2230,10 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// 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;
} }
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 54); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 54);
@ -2268,10 +2268,10 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// 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;
} }
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 55); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 55);
@ -2306,14 +2306,14 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
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;
} }
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 56); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 56);
@ -2348,10 +2348,10 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rd != 0) { if(rd != 0) {
if(*(X+rs2) != 0) *(X+rd) = *(X+rs1) / *(X+rs2); if(*(X+rs2) != 0) *(X+rd) = *(X+rs1) / *(X+rs2);
else *(X+rd) = - 1; else *(X+rd) = - 1;
} }
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 57); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 57);
@ -2386,14 +2386,14 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
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);
} }
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 58); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 58);
@ -2428,10 +2428,10 @@ private:
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rd != 0) { if(rd != 0) {
if(*(X+rs2) != 0) *(X+rd) = *(X+rs1) % *(X+rs2); if(*(X+rs2) != 0) *(X+rd) = *(X+rs1) % *(X+rs2);
else *(X+rd) = *(X+rs1); else *(X+rd) = *(X+rs1);
} }
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 59); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 59);
@ -2465,8 +2465,8 @@ private:
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
{ {
if(imm == 0) raise(0, 2); if(imm == 0) raise(0, 2);
*(X+(rd + 8)) = *(X+2) + imm; *(X+(rd + 8)) = *(X+2) + imm;
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 60); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 60);
@ -2501,9 +2501,9 @@ private:
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
{ {
uint32_t load_address = *(X+(rs1 + 8)) + uimm; uint32_t load_address = *(X+(rs1 + 8)) + uimm;
if(traits::eei_aligned_addresses && (load_address & 0x3)) raise(0, 4); if(traits::eei_aligned_addresses && (load_address & 0x3)) raise(0, 4);
else *(X+(rd + 8)) = (int32_t)readSpace4(traits::MEM, load_address); else *(X+(rd + 8)) = (int32_t)readSpace4(traits::MEM, load_address);
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 61); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 61);
@ -2538,9 +2538,9 @@ private:
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
{ {
uint32_t load_address = *(X+(rs1 + 8)) + uimm; uint32_t load_address = *(X+(rs1 + 8)) + uimm;
if(traits::eei_aligned_addresses && (load_address & 0x3)) raise(0, 6); if(traits::eei_aligned_addresses && (load_address & 0x3)) raise(0, 6);
else writeSpace4(traits::MEM, load_address, *(X+(rs2 + 8))); else writeSpace4(traits::MEM, load_address, *(X+(rs2 + 8)));
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 62); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 62);
@ -2634,8 +2634,8 @@ private:
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
{ {
*(X+1) = *PC + 2; *(X+1) = *PC + 2;
pc_assign(*NEXT_PC) = *PC + (int16_t)sext<12>(imm); pc_assign(*NEXT_PC) = *PC + (int16_t)sext<12>(imm);
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 65); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 65);
@ -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);
@ -2703,9 +2703,9 @@ private:
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
{ {
if(rd == 0) raise(0, 2); if(rd == 0) raise(0, 2);
if(imm == 0) raise(0, 2); if(imm == 0) raise(0, 2);
*(X+rd) = (int32_t)sext<18>(imm); *(X+rd) = (int32_t)sext<18>(imm);
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 67); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 67);
@ -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,12 +2806,12 @@ 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
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 70); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 70);
@ -2846,8 +2845,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) & (int8_t)sext<6>(imm); *(X+rs1_idx) = *(X+rs1_idx) & (int8_t)sext<6>(imm);
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 71); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 71);
@ -2881,8 +2880,8 @@ 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
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 72); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 72);
@ -2916,8 +2915,8 @@ 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
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 73); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 73);
@ -2951,8 +2950,8 @@ 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
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 74); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 74);
@ -2986,8 +2985,8 @@ 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
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 75); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 75);
@ -3148,8 +3147,8 @@ private:
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
if(rd) { if(rd) {
uint32_t offs = *(X+2) + uimm; uint32_t offs = *(X+2) + uimm;
*(X+rd) = (int32_t)readSpace4(traits::MEM, offs); *(X+rd) = (int32_t)readSpace4(traits::MEM, offs);
} }
else raise(0, 2); else raise(0, 2);
// post execution stuff // post execution stuff
@ -3279,8 +3278,8 @@ private:
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
{ {
*(X+1) = *PC + 2; *(X+1) = *PC + 2;
pc_assign(*NEXT_PC) = *(X+rs1); pc_assign(*NEXT_PC) = *(X+rs1);
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 84); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 84);
@ -3341,8 +3340,8 @@ private:
*NEXT_PC = *PC + 2; *NEXT_PC = *PC + 2;
// execute instruction // execute instruction
{ {
uint32_t offs = *(X+2) + uimm; uint32_t offs = *(X+2) + uimm;
writeSpace4(traits::MEM, offs, (uint32_t)*(X+rs2)); writeSpace4(traits::MEM, offs, (uint32_t)*(X+rs2));
} }
// post execution stuff // post execution stuff
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 86); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 86);
@ -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;
} }
}; };