diff options
-rw-r--r-- | arch/alpha/alpha_memory.cc | 8 | ||||
-rw-r--r-- | arch/alpha/ev5.cc | 10 | ||||
-rw-r--r-- | arch/alpha/isa_desc | 50 |
3 files changed, 44 insertions, 24 deletions
diff --git a/arch/alpha/alpha_memory.cc b/arch/alpha/alpha_memory.cc index c79b821d0..d934299b8 100644 --- a/arch/alpha/alpha_memory.cc +++ b/arch/alpha/alpha_memory.cc @@ -436,12 +436,12 @@ AlphaDtb::translate(MemReqPtr req, bool write) const else read_accesses++; - AlphaISA::md_mode_type mode = - (AlphaISA::md_mode_type)DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]); + AlphaISA::mode_type mode = + (AlphaISA::mode_type)DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]); if (PC_PAL(pc)) { - mode = (req->flags & ALTMODE) ? (AlphaISA::md_mode_type) - (ALT_MODE_AM(ipr[AlphaISA::IPR_ALT_MODE])) + mode = (req->flags & ALTMODE) ? + (AlphaISA::mode_type)ALT_MODE_AM(ipr[AlphaISA::IPR_ALT_MODE]) : AlphaISA::mode_kernel; } diff --git a/arch/alpha/ev5.cc b/arch/alpha/ev5.cc index 6759fdbf9..8494ee9f6 100644 --- a/arch/alpha/ev5.cc +++ b/arch/alpha/ev5.cc @@ -551,16 +551,14 @@ ExecContext::simPalCheck(int palFunc) switch (palFunc) { case PAL::halt: - if (!misspeculating()) { - halt(); - if (--System::numSystemsRunning == 0) - new SimExitEvent("all cpus halted"); - } + halt(); + if (--System::numSystemsRunning == 0) + new SimExitEvent("all cpus halted"); break; case PAL::bpt: case PAL::bugchk: - if (!misspeculating() && system->breakpoint()) + if (system->breakpoint()) return false; break; } diff --git a/arch/alpha/isa_desc b/arch/alpha/isa_desc index aef9135d3..293b0fcf6 100644 --- a/arch/alpha/isa_desc +++ b/arch/alpha/isa_desc @@ -1399,6 +1399,7 @@ declare {{ protected: int palFunc; ///< Function code part of instruction int palOffset; ///< Target PC, offset from IPR_PAL_BASE + bool palValid; ///< is the function code valid? bool palPriv; ///< is this call privileged? /// Constructor. @@ -1407,9 +1408,22 @@ declare {{ : AlphaStaticInst(mnem, _machInst, __opClass), palFunc(PALFUNC) { - palPriv = ((machInst & 0x80) != 0); - int shortPalFunc = (machInst & 0x3f); - palOffset = 0x2001 + (palPriv << 12) + (shortPalFunc << 6); + // From the 21164 HRM (paraphrased): + // Bit 7 of the function code (mask 0x80) indicates + // whether the call is privileged (bit 7 == 0) or + // unprivileged (bit 7 == 1). The privileged call table + // starts at 0x2000, the unprivielged call table starts at + // 0x3000. Bits 5-0 (mask 0x3f) are used to calculate the + // offset. + const int palPrivMask = 0x80; + const int palOffsetMask = 0x3f; + + // Pal call is invalid unless all other bits are 0 + palValid = ((machInst & ~(palPrivMask | palOffsetMask)) == 0); + palPriv = ((machInst & palPrivMask) == 0); + int shortPalFunc = (machInst & palOffsetMask); + // Add 1 to base to set pal-mode bit + palOffset = (palPriv ? 0x2001 : 0x3001) + (shortPalFunc << 6); } std::string generateDisassembly(Addr pc, const SymbolTable *symtab) @@ -2353,25 +2367,33 @@ decode OPCODE default Unknown::unknown() { #ifdef FULL_SYSTEM 0x00: CallPal::call_pal({{ - if (palPriv && !PC_PAL(xc->regs.pc)) { - // attempt to do privileged PAL call in non-PAL mode + using namespace AlphaISA; + + if (!palValid || + (palPriv && xc->readIpr(IPR_ICM, fault) != mode_kernel)) { + // invalid pal function code, or attempt to do privileged + // PAL call in non-kernel mode fault = Unimplemented_Opcode_Fault; } else { - // check to see if simulator wants to do something special - // on this PAL call (including maybe suppress it) - bool dopal = xc->simPalCheck(palFunc); - if (!xc->misspeculating()) { + // check to see if simulator wants to do something special + // on this PAL call (including maybe suppress it) + bool dopal = xc->simPalCheck(palFunc); + Annotate::Callpal(xc, palFunc); + + if (dopal) { + swap_palshadow(&xc->regs, true); + xc->setIpr(IPR_EXC_ADDR, NPC); + } } + // if we're misspeculating, it's still safe (if + // unrealistic) to set NPC, as the control-flow change + // won't get committed. if (dopal) { - if (!xc->misspeculating()) { - AlphaISA::swap_palshadow(&xc->regs, true); - } - xc->setIpr(AlphaISA::IPR_EXC_ADDR, NPC); - NPC = xc->readIpr(AlphaISA::IPR_PAL_BASE, fault) + palOffset; + NPC = xc->readIpr(IPR_PAL_BASE, fault) + palOffset; } } }}); |