diff options
Diffstat (limited to 'arch/alpha/faults.cc')
-rw-r--r-- | arch/alpha/faults.cc | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/arch/alpha/faults.cc b/arch/alpha/faults.cc index e0918da21..0083aa9f3 100644 --- a/arch/alpha/faults.cc +++ b/arch/alpha/faults.cc @@ -30,6 +30,9 @@ #include "cpu/exec_context.hh" #include "cpu/base.hh" #include "base/trace.hh" +#if FULL_SYSTEM +#include "arch/alpha/ev5.hh" +#endif namespace AlphaISA { @@ -70,6 +73,10 @@ FaultName DtbAcvFault::_name = "dfault"; FaultVect DtbAcvFault::_vect = 0x0381; FaultStat DtbAcvFault::_count; +FaultName DtbAlignmentFault::_name = "unalign"; +FaultVect DtbAlignmentFault::_vect = 0x0301; +FaultStat DtbAlignmentFault::_count; + FaultName ItbMissFault::_name = "itbmiss"; FaultVect ItbMissFault::_vect = 0x0181; FaultStat ItbMissFault::_count; @@ -125,6 +132,44 @@ void ArithmeticFault::invoke(ExecContext * xc) panic("Arithmetic traps are unimplemented!"); } +void DtbFault::invoke(ExecContext * xc) +{ + // Set fault address and flags. Even though we're modeling an + // EV5, we use the EV6 technique of not latching fault registers + // on VPTE loads (instead of locking the registers until IPR_VA is + // read, like the EV5). The EV6 approach is cleaner and seems to + // work with EV5 PAL code, but not the other way around. + if (!xc->misspeculating() + && !(reqFlags & VPTE) && !(reqFlags & NO_FAULT)) { + // set VA register with faulting address + xc->setMiscReg(AlphaISA::IPR_VA, vaddr); + + // set MM_STAT register flags + xc->setMiscReg(AlphaISA::IPR_MM_STAT, + (((EV5::Opcode(xc->getInst()) & 0x3f) << 11) + | ((EV5::Ra(xc->getInst()) & 0x1f) << 6) + | (flags & 0x3f))); + + // set VA_FORM register with faulting formatted address + xc->setMiscReg(AlphaISA::IPR_VA_FORM, + xc->readMiscReg(AlphaISA::IPR_MVPTBR) | (vaddr.vpn() << 3)); + } + + AlphaFault::invoke(xc); +} + +void ItbFault::invoke(ExecContext * xc) +{ + if (!xc->misspeculating()) { + xc->setMiscReg(AlphaISA::IPR_ITB_TAG, pc); + xc->setMiscReg(AlphaISA::IPR_IFAULT_VA_FORM, + xc->readMiscReg(AlphaISA::IPR_IVPTBR) | + (AlphaISA::VAddr(pc).vpn() << 3)); + } + + AlphaFault::invoke(xc); +} + #endif } // namespace AlphaISA |