InitReg(MISCREG_PMXEVCNTR_EL0).mapsTo(MISCREG_PMXEVCNTR);
InitReg(MISCREG_PMXEVTYPER_EL0).mapsTo(MISCREG_PMXEVTYPER);
+ InitReg(MISCREG_SCR).res0(0xff40) // [31:16], [6]
+ .res1(0x0030); // [5:4]
+
// from ARM DDI 0487A.i, template text
// "AArch64 System register ___ can be mapped to
// AArch32 System register ___, but this is not
{
assert(misc_reg < NumMiscRegs);
- auto regs = getMiscIndices(misc_reg);
- int lower = regs.first, upper = regs.second;
- return !upper ? miscRegs[lower] : ((miscRegs[lower] & mask(32))
- |(miscRegs[upper] << 32));
+ const auto ® = lookUpMiscReg[misc_reg]; // bit masks
+ const auto &map = getMiscIndices(misc_reg);
+ int lower = map.first, upper = map.second;
+ // NB!: apply architectural masks according to desired register,
+ // despite possibly getting value from different (mapped) register.
+ auto val = !upper ? miscRegs[lower] : ((miscRegs[lower] & mask(32))
+ |(miscRegs[upper] << 32));
+ if (val & reg.res0()) {
+ DPRINTF(MiscRegs, "Reading MiscReg %s with set res0 bits: %#x\n",
+ miscRegName[misc_reg], val & reg.res0());
+ }
+ if ((val & reg.res1()) != reg.res1()) {
+ DPRINTF(MiscRegs, "Reading MiscReg %s with clear res1 bits: %#x\n",
+ miscRegName[misc_reg], (val & reg.res1()) ^ reg.res1());
+ }
+ return (val & ~reg.raz()) | reg.rao(); // enforce raz/rao
}
{
assert(misc_reg < NumMiscRegs);
- auto regs = getMiscIndices(misc_reg);
- int lower = regs.first, upper = regs.second;
+ const auto ® = lookUpMiscReg[misc_reg]; // bit masks
+ const auto &map = getMiscIndices(misc_reg);
+ int lower = map.first, upper = map.second;
+
+ auto v = (val & ~reg.wi()) | reg.rao();
if (upper > 0) {
- miscRegs[lower] = bits(val, 31, 0);
- miscRegs[upper] = bits(val, 63, 32);
+ miscRegs[lower] = bits(v, 31, 0);
+ miscRegs[upper] = bits(v, 63, 32);
DPRINTF(MiscRegs, "Writing to misc reg %d (%d:%d) : %#x\n",
- misc_reg, lower, upper, val);
+ misc_reg, lower, upper, v);
} else {
- miscRegs[lower] = val;
+ miscRegs[lower] = v;
DPRINTF(MiscRegs, "Writing to misc reg %d (%d) : %#x\n",
- misc_reg, lower, val);
+ misc_reg, lower, v);
}
}
bool haveLargeAsid64;
uint8_t physAddrRange64;
- /** Register translation entry used in lookUpMiscReg */
+ /** MiscReg metadata **/
struct MiscRegLUTEntry {
uint32_t lower; // Lower half mapped to this register
uint32_t upper; // Upper half mapped to this register
+ uint64_t _reset; // value taken on reset (i.e. initialization)
+ uint64_t _res0; // reserved
+ uint64_t _res1; // reserved
+ uint64_t _raz; // read as zero (fixed at 0)
+ uint64_t _rao; // read as one (fixed at 1)
+ public:
+ MiscRegLUTEntry() :
+ lower(0), upper(0),
+ _reset(0), _res0(0), _res1(0), _raz(0), _rao(0) {}
+ uint64_t reset() const { return _reset; }
+ uint64_t res0() const { return _res0; }
+ uint64_t res1() const { return _res1; }
+ uint64_t raz() const { return _raz; }
+ uint64_t rao() const { return _rao; }
+ // raz/rao implies writes ignored
+ uint64_t wi() const { return _raz | _rao; }
};
/** Metadata table accessible via the value of the register */
entry.upper = u;
return *this;
}
+ chain res0(uint64_t mask) const {
+ entry._res0 = mask;
+ return *this;
+ }
+ chain res1(uint64_t mask) const {
+ entry._res1 = mask;
+ return *this;
+ }
+ chain raz(uint64_t mask) const {
+ entry._raz = mask;
+ return *this;
+ }
+ chain rao(uint64_t mask) const {
+ entry._rao = mask;
+ return *this;
+ }
MiscRegLUTEntryInitializer(struct MiscRegLUTEntry &e)
: entry(e)
{}