summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/riscv/decoder.cc48
-rw-r--r--src/arch/riscv/decoder.hh12
-rw-r--r--src/arch/riscv/faults.cc7
-rw-r--r--src/arch/riscv/faults.hh13
-rw-r--r--src/arch/riscv/isa/decoder.isa10
-rw-r--r--src/arch/riscv/isa/formats/fp.isa8
-rw-r--r--src/arch/riscv/utility.hh20
7 files changed, 90 insertions, 28 deletions
diff --git a/src/arch/riscv/decoder.cc b/src/arch/riscv/decoder.cc
index 36504f4f8..020c5e34e 100644
--- a/src/arch/riscv/decoder.cc
+++ b/src/arch/riscv/decoder.cc
@@ -37,29 +37,45 @@
namespace RiscvISA
{
+static const MachInst LowerBitMask = (1 << sizeof(MachInst) * 4) - 1;
+static const MachInst UpperBitMask = LowerBitMask << sizeof(MachInst) * 4;
+
+void Decoder::reset()
+{
+ aligned = true;
+ mid = false;
+ more = true;
+ emi = NoopMachInst;
+ instDone = false;
+}
+
void
Decoder::moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
{
- DPRINTF(Decode, "Getting bytes 0x%08x from address %#x\n",
- inst, pc.pc());
+ DPRINTF(Decode, "Requesting bytes 0x%08x from address %#x\n", inst,
+ fetchPC);
bool aligned = pc.pc() % sizeof(MachInst) == 0;
- if (mid) {
- assert(!aligned);
- emi |= (inst & 0xFFFF) << 16;
+ if (aligned) {
+ emi = inst;
+ if (compressed(emi))
+ emi &= LowerBitMask;
+ more = !compressed(emi);
instDone = true;
} else {
- MachInst instChunk = aligned ? inst & 0xFFFF :
- (inst & 0xFFFF0000) >> 16;
- if (aligned) {
- emi = (inst & 0x3) < 0x3 ? instChunk : inst;
+ if (mid) {
+ assert((emi & UpperBitMask) == 0);
+ emi |= (inst & LowerBitMask) << sizeof(MachInst)*4;
+ mid = false;
+ more = false;
instDone = true;
} else {
- emi = instChunk;
- instDone = (instChunk & 0x3) < 0x3;
+ emi = (inst & UpperBitMask) >> sizeof(MachInst)*4;
+ mid = !compressed(emi);
+ more = true;
+ instDone = compressed(emi);
}
}
- mid = !instDone;
}
StaticInstPtr
@@ -83,12 +99,10 @@ Decoder::decode(RiscvISA::PCState &nextPC)
return nullptr;
instDone = false;
- if ((emi & 0x3) < 0x3) {
- nextPC.compressed(true);
- nextPC.npc(nextPC.pc() + sizeof(MachInst)/2);
+ if (compressed(emi)) {
+ nextPC.npc(nextPC.instAddr() + sizeof(MachInst) / 2);
} else {
- nextPC.compressed(false);
- nextPC.npc(nextPC.pc() + sizeof(MachInst));
+ nextPC.npc(nextPC.instAddr() + sizeof(MachInst));
}
return decode(emi, nextPC.instAddr());
diff --git a/src/arch/riscv/decoder.hh b/src/arch/riscv/decoder.hh
index ef644fa13..c1d68bf06 100644
--- a/src/arch/riscv/decoder.hh
+++ b/src/arch/riscv/decoder.hh
@@ -49,7 +49,9 @@ class Decoder
{
private:
DecodeCache::InstMap instMap;
+ bool aligned;
bool mid;
+ bool more;
protected:
//The extended machine instruction being generated
@@ -57,18 +59,18 @@ class Decoder
bool instDone;
public:
- Decoder(ISA* isa=nullptr)
- : mid(false), emi(NoopMachInst), instDone(false)
- {}
+ Decoder(ISA* isa=nullptr) { reset(); }
void process() {}
- void reset() { instDone = false; }
+ void reset();
+
+ inline bool compressed(ExtMachInst inst) { return (inst & 0x3) < 0x3; }
//Use this to give data to the decoder. This should be used
//when there is control flow.
void moreBytes(const PCState &pc, Addr fetchPC, MachInst inst);
- bool needMoreBytes() { return true; }
+ bool needMoreBytes() { return more; }
bool instReady() { return instDone; }
void takeOverFrom(Decoder *old) {}
diff --git a/src/arch/riscv/faults.cc b/src/arch/riscv/faults.cc
index 58baa4e32..4e44d43f0 100644
--- a/src/arch/riscv/faults.cc
+++ b/src/arch/riscv/faults.cc
@@ -64,6 +64,13 @@ UnknownInstFault::invoke_se(ThreadContext *tc, const StaticInstPtr &inst)
}
void
+IllegalInstFault::invoke_se(ThreadContext *tc, const StaticInstPtr &inst)
+{
+ panic("Illegal instruction 0x%08x at pc 0x%016llx: %s", inst->machInst,
+ tc->pcState().pc(), reason.c_str());
+}
+
+void
UnimplementedFault::invoke_se(ThreadContext *tc,
const StaticInstPtr &inst)
{
diff --git a/src/arch/riscv/faults.hh b/src/arch/riscv/faults.hh
index d0d7988c5..1e33b648f 100644
--- a/src/arch/riscv/faults.hh
+++ b/src/arch/riscv/faults.hh
@@ -116,6 +116,19 @@ class UnknownInstFault : public RiscvFault
invoke_se(ThreadContext *tc, const StaticInstPtr &inst);
};
+class IllegalInstFault : public RiscvFault
+{
+ private:
+ const std::string reason;
+ public:
+ IllegalInstFault(std::string r)
+ : RiscvFault("Illegal instruction", INST_ILLEGAL, SOFTWARE),
+ reason(r)
+ {}
+
+ void invoke_se(ThreadContext *tc, const StaticInstPtr &inst);
+};
+
class UnimplementedFault : public RiscvFault
{
private:
diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa
index 4f4ef7636..0e5567ac3 100644
--- a/src/arch/riscv/isa/decoder.isa
+++ b/src/arch/riscv/isa/decoder.isa
@@ -42,7 +42,8 @@ decode QUADRANT default Unknown::unknown() {
CIMM8<7:6> << 4 |
CIMM8<5:2> << 6;
}}, {{
- assert(imm != 0);
+ if (machInst == 0)
+ fault = make_shared<IllegalInstFault>("zero instruction");
Rp2 = sp + imm;
}});
format CompressedLoad {
@@ -103,7 +104,12 @@ decode QUADRANT default Unknown::unknown() {
if (CIMM1 > 0)
imm |= ~((uint64_t)0x1F);
}}, {{
- assert((RC1 == 0) == (imm == 0));
+ if ((RC1 == 0) != (imm == 0)) {
+ if (RC1 == 0) {
+ fault = make_shared<IllegalInstFault>("source reg x0");
+ } else // imm == 0
+ fault = make_shared<IllegalInstFault>("immediate = 0");
+ }
Rc1_sd = Rc1_sd + imm;
}});
0x1: c_addiw({{
diff --git a/src/arch/riscv/isa/formats/fp.isa b/src/arch/riscv/isa/formats/fp.isa
index 1f60b9b70..3de0bb2ff 100644
--- a/src/arch/riscv/isa/formats/fp.isa
+++ b/src/arch/riscv/isa/formats/fp.isa
@@ -56,8 +56,8 @@ def template FloatExecute {{
std::fesetround(FE_UPWARD);
break;
case 0x4:
- panic("Round to nearest, "
- "ties to max magnitude not implemented.");
+ // Round to nearest, ties to max magnitude not implemented
+ fault = make_shared<IllegalFrmFault>(ROUND_MODE);
break;
case 0x7: {
uint8_t frm = xc->readMiscReg(MISCREG_FRM);
@@ -75,8 +75,8 @@ def template FloatExecute {{
std::fesetround(FE_UPWARD);
break;
case 0x4:
- panic("Round to nearest,"
- " ties to max magnitude not implemented.");
+ // Round to nearest, ties to max magnitude not implemented
+ fault = make_shared<IllegalFrmFault>(ROUND_MODE);
break;
default:
fault = std::make_shared<IllegalFrmFault>(frm);
diff --git a/src/arch/riscv/utility.hh b/src/arch/riscv/utility.hh
index 38109a208..78e9b91a9 100644
--- a/src/arch/riscv/utility.hh
+++ b/src/arch/riscv/utility.hh
@@ -48,6 +48,7 @@
#include <cmath>
#include <cstdint>
+#include <sstream>
#include <string>
#include "arch/riscv/registers.hh"
@@ -133,8 +134,27 @@ inline std::string
registerName(RegId reg)
{
if (reg.isIntReg()) {
+ if (reg.index() >= NumIntArchRegs) {
+ /*
+ * This should only happen if a instruction is being speculatively
+ * executed along a not-taken branch, and if that instruction's
+ * width was incorrectly predecoded (i.e., it was predecoded as a
+ * full instruction rather than a compressed one or vice versa).
+ * It also should only happen if a debug flag is on that prints
+ * disassembly information, so rather than panic the incorrect
+ * value is printed for debugging help.
+ */
+ std::stringstream str;
+ str << "?? (x" << reg.index() << ')';
+ return str.str();
+ }
return IntRegNames[reg.index()];
} else {
+ if (reg.index() >= NumFloatRegs) {
+ std::stringstream str;
+ str << "?? (f" << reg.index() << ')';
+ return str.str();
+ }
return FloatRegNames[reg.index()];
}
}