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
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());
{
private:
DecodeCache::InstMap instMap;
+ bool aligned;
bool mid;
+ bool more;
protected:
//The extended machine instruction being generated
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) {}
tc->pcState().pc());
}
+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)
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:
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 {
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({{
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);
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);
#include <cmath>
#include <cstdint>
+#include <sstream>
#include <string>
#include "arch/riscv/registers.hh"
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()];
}
}