d53c6c168a
Mostly a matter of keeping prefetches to invalid addrs from messing up VM IPRs. Also discovered that wh64s were not being treated as prefetches, when they really should be (for the most part, anyway). arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: - Get rid of intrlock flag for locking VM fault regs (a la EV5); instead, just don't update regs on VPTE loads (a la EV6). - Add NO_FAULT MemReq flag to indicate references that should not cause page faults (i.e., prefetches). arch/alpha/ev5.cc: - Get rid of intrlock flag for locking VM fault regs (a la EV5); instead, just don't update regs on VPTE loads (a la EV6). - Add Fault trace flag. arch/alpha/isa_desc: - Add NO_FAULT MemReq flag to indicate references that should not cause page faults (i.e., prefetches). - Mark wh64 as a "data prefetch" instruction so it gets controlled properly by the FullCPU data prefetch control switch. - Align wh64 EA in decoder so issue stage doesn't need to worry about it. arch/alpha/isa_traits.hh: - Get rid of intrlock flag for locking VM fault regs (a la EV5); instead, just don't update regs on VPTE loads (a la EV6). base/traceflags.py: - Add Fault trace flag. cpu/simple_cpu/simple_cpu.hh: - Pass MemReq flags to writeHint() operation. cpu/static_inst.hh: Update comment re: prefetches. --HG-- extra : convert_revision : 62e466b0f4c0ff9961796270fa2e371ec24bcbb6
651 lines
17 KiB
C++
651 lines
17 KiB
C++
/* $Id$ */
|
|
|
|
#include "arch/alpha/alpha_memory.hh"
|
|
#include "arch/alpha/isa_traits.hh"
|
|
#include "arch/alpha/osfpal.hh"
|
|
#include "base/kgdb.h"
|
|
#include "base/remote_gdb.hh"
|
|
#include "base/stats/events.hh"
|
|
#include "cpu/exec_context.hh"
|
|
#include "cpu/fast_cpu/fast_cpu.hh"
|
|
#include "sim/debug.hh"
|
|
#include "sim/sim_events.hh"
|
|
|
|
#ifdef FULL_SYSTEM
|
|
|
|
#ifndef SYSTEM_EV5
|
|
#error This code is only valid for EV5 systems
|
|
#endif
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
void
|
|
AlphaISA::swap_palshadow(RegFile *regs, bool use_shadow)
|
|
{
|
|
if (regs->pal_shadow == use_shadow)
|
|
panic("swap_palshadow: wrong PAL shadow state");
|
|
|
|
regs->pal_shadow = use_shadow;
|
|
|
|
for (int i = 0; i < NumIntRegs; i++) {
|
|
if (reg_redir[i]) {
|
|
IntReg temp = regs->intRegFile[i];
|
|
regs->intRegFile[i] = regs->palregs[i];
|
|
regs->palregs[i] = temp;
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Machine dependent functions
|
|
//
|
|
void
|
|
AlphaISA::initCPU(RegFile *regs)
|
|
{
|
|
initIPRs(regs);
|
|
// CPU comes up with PAL regs enabled
|
|
swap_palshadow(regs, true);
|
|
|
|
regs->pc = regs->ipr[IPR_PAL_BASE] + fault_addr[Reset_Fault];
|
|
regs->npc = regs->pc + sizeof(MachInst);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// alpha exceptions - value equals trap address, update with MD_FAULT_TYPE
|
|
//
|
|
Addr
|
|
AlphaISA::fault_addr[Num_Faults] = {
|
|
0x0000, /* No_Fault */
|
|
0x0001, /* Reset_Fault */
|
|
0x0401, /* Machine_Check_Fault */
|
|
0x0501, /* Arithmetic_Fault */
|
|
0x0101, /* Interrupt_Fault */
|
|
0x0201, /* Ndtb_Miss_Fault */
|
|
0x0281, /* Pdtb_Miss_Fault */
|
|
0x0301, /* Alignment_Fault */
|
|
0x0381, /* DTB_Fault_Fault */
|
|
0x0381, /* DTB_Acv_Fault */
|
|
0x0181, /* ITB_Miss_Fault */
|
|
0x0181, /* ITB_Fault_Fault */
|
|
0x0081, /* ITB_Acv_Fault */
|
|
0x0481, /* Unimplemented_Opcode_Fault */
|
|
0x0581, /* Fen_Fault */
|
|
0x2001, /* Pal_Fault */
|
|
0x0501, /* Integer_Overflow_Fault: maps to Arithmetic_Fault */
|
|
};
|
|
|
|
const int AlphaISA::reg_redir[AlphaISA::NumIntRegs] = {
|
|
/* 0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 8 */ 1, 1, 1, 1, 1, 1, 1, 0,
|
|
/* 16 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 24 */ 0, 1, 0, 0, 0, 0, 0, 0 };
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
void
|
|
AlphaISA::initIPRs(RegFile *regs)
|
|
{
|
|
uint64_t *ipr = regs->ipr;
|
|
|
|
bzero((char *)ipr, NumInternalProcRegs * sizeof(InternalProcReg));
|
|
ipr[IPR_PAL_BASE] = PAL_BASE;
|
|
ipr[IPR_MCSR] = 0x6;
|
|
}
|
|
|
|
|
|
template <class XC>
|
|
void
|
|
AlphaISA::processInterrupts(XC *xc)
|
|
{
|
|
//Check if there are any outstanding interrupts
|
|
//Handle the interrupts
|
|
int ipl = 0;
|
|
int summary = 0;
|
|
IntReg *ipr = xc->getIprPtr();
|
|
|
|
check_interrupts = 0;
|
|
|
|
if (ipr[IPR_ASTRR])
|
|
panic("asynchronous traps not implemented\n");
|
|
|
|
if (ipr[IPR_SIRR]) {
|
|
for (int i = INTLEVEL_SOFTWARE_MIN;
|
|
i < INTLEVEL_SOFTWARE_MAX; i++) {
|
|
if (ipr[IPR_SIRR] & (ULL(1) << i)) {
|
|
// See table 4-19 of the 21164 hardware reference
|
|
ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
|
|
summary |= (ULL(1) << i);
|
|
}
|
|
}
|
|
}
|
|
|
|
uint64_t interrupts = xc->intr_status();
|
|
|
|
if (interrupts) {
|
|
for (int i = INTLEVEL_EXTERNAL_MIN;
|
|
i < INTLEVEL_EXTERNAL_MAX; i++) {
|
|
if (interrupts & (ULL(1) << i)) {
|
|
// See table 4-19 of the 21164 hardware reference
|
|
ipl = i;
|
|
summary |= (ULL(1) << i);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ipl && ipl > ipr[IPR_IPLR]) {
|
|
ipr[IPR_ISR] = summary;
|
|
ipr[IPR_INTID] = ipl;
|
|
xc->trap(Interrupt_Fault);
|
|
DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
|
|
ipr[IPR_IPLR], ipl, summary);
|
|
}
|
|
|
|
}
|
|
|
|
template <class XC>
|
|
void
|
|
AlphaISA::zeroRegisters(XC *xc)
|
|
{
|
|
// Insure ISA semantics
|
|
// (no longer very clean due to the change in setIntReg() in the
|
|
// cpu model. Consider changing later.)
|
|
xc->xc->setIntReg(ZeroReg, 0);
|
|
xc->xc->setFloatRegDouble(ZeroReg, 0.0);
|
|
}
|
|
|
|
void
|
|
ExecContext::ev5_trap(Fault fault)
|
|
{
|
|
DPRINTF(Fault, "Fault %s\n", FaultName(fault));
|
|
Stats::recordEvent(csprintf("Fault %s", FaultName(fault)));
|
|
|
|
assert(!misspeculating());
|
|
kernelStats.fault(fault);
|
|
|
|
if (fault == Arithmetic_Fault)
|
|
panic("Arithmetic traps are unimplemented!");
|
|
|
|
AlphaISA::InternalProcReg *ipr = regs.ipr;
|
|
|
|
// exception restart address
|
|
if (fault != Interrupt_Fault || !PC_PAL(regs.pc))
|
|
ipr[AlphaISA::IPR_EXC_ADDR] = regs.pc;
|
|
|
|
if (fault == Pal_Fault || fault == Arithmetic_Fault /* ||
|
|
fault == Interrupt_Fault && !PC_PAL(regs.pc) */) {
|
|
// traps... skip faulting instruction
|
|
ipr[AlphaISA::IPR_EXC_ADDR] += 4;
|
|
}
|
|
|
|
if (!PC_PAL(regs.pc))
|
|
AlphaISA::swap_palshadow(®s, true);
|
|
|
|
regs.pc = ipr[AlphaISA::IPR_PAL_BASE] + AlphaISA::fault_addr[fault];
|
|
regs.npc = regs.pc + sizeof(MachInst);
|
|
}
|
|
|
|
|
|
void
|
|
AlphaISA::intr_post(RegFile *regs, Fault fault, Addr pc)
|
|
{
|
|
InternalProcReg *ipr = regs->ipr;
|
|
bool use_pc = (fault == No_Fault);
|
|
|
|
if (fault == Arithmetic_Fault)
|
|
panic("arithmetic faults NYI...");
|
|
|
|
// compute exception restart address
|
|
if (use_pc || fault == Pal_Fault || fault == Arithmetic_Fault) {
|
|
// traps... skip faulting instruction
|
|
ipr[IPR_EXC_ADDR] = regs->pc + 4;
|
|
} else {
|
|
// fault, post fault at excepting instruction
|
|
ipr[IPR_EXC_ADDR] = regs->pc;
|
|
}
|
|
|
|
// jump to expection address (PAL PC bit set here as well...)
|
|
if (!use_pc)
|
|
regs->npc = ipr[IPR_PAL_BASE] + fault_addr[fault];
|
|
else
|
|
regs->npc = ipr[IPR_PAL_BASE] + pc;
|
|
|
|
// that's it! (orders of magnitude less painful than x86)
|
|
}
|
|
|
|
bool AlphaISA::check_interrupts = false;
|
|
|
|
Fault
|
|
ExecContext::hwrei()
|
|
{
|
|
uint64_t *ipr = regs.ipr;
|
|
|
|
if (!PC_PAL(regs.pc))
|
|
return Unimplemented_Opcode_Fault;
|
|
|
|
setNextPC(ipr[AlphaISA::IPR_EXC_ADDR]);
|
|
|
|
if (!misspeculating()) {
|
|
kernelStats.hwrei();
|
|
|
|
if ((ipr[AlphaISA::IPR_EXC_ADDR] & 1) == 0)
|
|
AlphaISA::swap_palshadow(®s, false);
|
|
|
|
AlphaISA::check_interrupts = true;
|
|
}
|
|
|
|
// FIXME: XXX check for interrupts? XXX
|
|
return No_Fault;
|
|
}
|
|
|
|
uint64_t
|
|
ExecContext::readIpr(int idx, Fault &fault)
|
|
{
|
|
uint64_t *ipr = regs.ipr;
|
|
uint64_t retval = 0; // return value, default 0
|
|
|
|
switch (idx) {
|
|
case AlphaISA::IPR_PALtemp0:
|
|
case AlphaISA::IPR_PALtemp1:
|
|
case AlphaISA::IPR_PALtemp2:
|
|
case AlphaISA::IPR_PALtemp3:
|
|
case AlphaISA::IPR_PALtemp4:
|
|
case AlphaISA::IPR_PALtemp5:
|
|
case AlphaISA::IPR_PALtemp6:
|
|
case AlphaISA::IPR_PALtemp7:
|
|
case AlphaISA::IPR_PALtemp8:
|
|
case AlphaISA::IPR_PALtemp9:
|
|
case AlphaISA::IPR_PALtemp10:
|
|
case AlphaISA::IPR_PALtemp11:
|
|
case AlphaISA::IPR_PALtemp12:
|
|
case AlphaISA::IPR_PALtemp13:
|
|
case AlphaISA::IPR_PALtemp14:
|
|
case AlphaISA::IPR_PALtemp15:
|
|
case AlphaISA::IPR_PALtemp16:
|
|
case AlphaISA::IPR_PALtemp17:
|
|
case AlphaISA::IPR_PALtemp18:
|
|
case AlphaISA::IPR_PALtemp19:
|
|
case AlphaISA::IPR_PALtemp20:
|
|
case AlphaISA::IPR_PALtemp21:
|
|
case AlphaISA::IPR_PALtemp22:
|
|
case AlphaISA::IPR_PALtemp23:
|
|
case AlphaISA::IPR_PAL_BASE:
|
|
|
|
case AlphaISA::IPR_IVPTBR:
|
|
case AlphaISA::IPR_DC_MODE:
|
|
case AlphaISA::IPR_MAF_MODE:
|
|
case AlphaISA::IPR_ISR:
|
|
case AlphaISA::IPR_EXC_ADDR:
|
|
case AlphaISA::IPR_IC_PERR_STAT:
|
|
case AlphaISA::IPR_DC_PERR_STAT:
|
|
case AlphaISA::IPR_MCSR:
|
|
case AlphaISA::IPR_ASTRR:
|
|
case AlphaISA::IPR_ASTER:
|
|
case AlphaISA::IPR_SIRR:
|
|
case AlphaISA::IPR_ICSR:
|
|
case AlphaISA::IPR_ICM:
|
|
case AlphaISA::IPR_DTB_CM:
|
|
case AlphaISA::IPR_IPLR:
|
|
case AlphaISA::IPR_INTID:
|
|
case AlphaISA::IPR_PMCTR:
|
|
// no side-effect
|
|
retval = ipr[idx];
|
|
break;
|
|
|
|
case AlphaISA::IPR_CC:
|
|
retval |= ipr[idx] & ULL(0xffffffff00000000);
|
|
retval |= curTick & ULL(0x00000000ffffffff);
|
|
break;
|
|
|
|
case AlphaISA::IPR_VA:
|
|
retval = ipr[idx];
|
|
break;
|
|
|
|
case AlphaISA::IPR_VA_FORM:
|
|
case AlphaISA::IPR_MM_STAT:
|
|
case AlphaISA::IPR_IFAULT_VA_FORM:
|
|
case AlphaISA::IPR_EXC_MASK:
|
|
case AlphaISA::IPR_EXC_SUM:
|
|
retval = ipr[idx];
|
|
break;
|
|
|
|
case AlphaISA::IPR_DTB_PTE:
|
|
{
|
|
AlphaISA::PTE &pte = dtb->index(!misspeculating());
|
|
|
|
retval |= ((u_int64_t)pte.ppn & ULL(0x7ffffff)) << 32;
|
|
retval |= ((u_int64_t)pte.xre & ULL(0xf)) << 8;
|
|
retval |= ((u_int64_t)pte.xwe & ULL(0xf)) << 12;
|
|
retval |= ((u_int64_t)pte.fonr & ULL(0x1)) << 1;
|
|
retval |= ((u_int64_t)pte.fonw & ULL(0x1))<< 2;
|
|
retval |= ((u_int64_t)pte.asma & ULL(0x1)) << 4;
|
|
retval |= ((u_int64_t)pte.asn & ULL(0x7f)) << 57;
|
|
}
|
|
break;
|
|
|
|
// write only registers
|
|
case AlphaISA::IPR_HWINT_CLR:
|
|
case AlphaISA::IPR_SL_XMIT:
|
|
case AlphaISA::IPR_DC_FLUSH:
|
|
case AlphaISA::IPR_IC_FLUSH:
|
|
case AlphaISA::IPR_ALT_MODE:
|
|
case AlphaISA::IPR_DTB_IA:
|
|
case AlphaISA::IPR_DTB_IAP:
|
|
case AlphaISA::IPR_ITB_IA:
|
|
case AlphaISA::IPR_ITB_IAP:
|
|
fault = Unimplemented_Opcode_Fault;
|
|
break;
|
|
|
|
default:
|
|
// invalid IPR
|
|
fault = Unimplemented_Opcode_Fault;
|
|
break;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
// Cause the simulator to break when changing to the following IPL
|
|
int break_ipl = -1;
|
|
#endif
|
|
|
|
Fault
|
|
ExecContext::setIpr(int idx, uint64_t val)
|
|
{
|
|
uint64_t *ipr = regs.ipr;
|
|
uint64_t old;
|
|
|
|
if (misspeculating())
|
|
return No_Fault;
|
|
|
|
switch (idx) {
|
|
case AlphaISA::IPR_PALtemp0:
|
|
case AlphaISA::IPR_PALtemp1:
|
|
case AlphaISA::IPR_PALtemp2:
|
|
case AlphaISA::IPR_PALtemp3:
|
|
case AlphaISA::IPR_PALtemp4:
|
|
case AlphaISA::IPR_PALtemp5:
|
|
case AlphaISA::IPR_PALtemp6:
|
|
case AlphaISA::IPR_PALtemp7:
|
|
case AlphaISA::IPR_PALtemp8:
|
|
case AlphaISA::IPR_PALtemp9:
|
|
case AlphaISA::IPR_PALtemp10:
|
|
case AlphaISA::IPR_PALtemp11:
|
|
case AlphaISA::IPR_PALtemp12:
|
|
case AlphaISA::IPR_PALtemp13:
|
|
case AlphaISA::IPR_PALtemp14:
|
|
case AlphaISA::IPR_PALtemp15:
|
|
case AlphaISA::IPR_PALtemp16:
|
|
case AlphaISA::IPR_PALtemp17:
|
|
case AlphaISA::IPR_PALtemp18:
|
|
case AlphaISA::IPR_PALtemp19:
|
|
case AlphaISA::IPR_PALtemp20:
|
|
case AlphaISA::IPR_PALtemp21:
|
|
case AlphaISA::IPR_PALtemp22:
|
|
case AlphaISA::IPR_PAL_BASE:
|
|
case AlphaISA::IPR_IC_PERR_STAT:
|
|
case AlphaISA::IPR_DC_PERR_STAT:
|
|
case AlphaISA::IPR_PMCTR:
|
|
// write entire quad w/ no side-effect
|
|
ipr[idx] = val;
|
|
break;
|
|
|
|
case AlphaISA::IPR_CC_CTL:
|
|
// This IPR resets the cycle counter. We assume this only
|
|
// happens once... let's verify that.
|
|
assert(ipr[idx] == 0);
|
|
ipr[idx] = 1;
|
|
break;
|
|
|
|
case AlphaISA::IPR_CC:
|
|
// This IPR only writes the upper 64 bits. It's ok to write
|
|
// all 64 here since we mask out the lower 32 in rpcc (see
|
|
// isa_desc).
|
|
ipr[idx] = val;
|
|
break;
|
|
|
|
case AlphaISA::IPR_PALtemp23:
|
|
// write entire quad w/ no side-effect
|
|
old = ipr[idx];
|
|
ipr[idx] = val;
|
|
kernelStats.context(old, val);
|
|
break;
|
|
|
|
case AlphaISA::IPR_DTB_PTE:
|
|
// write entire quad w/ no side-effect, tag is forthcoming
|
|
ipr[idx] = val;
|
|
break;
|
|
|
|
case AlphaISA::IPR_EXC_ADDR:
|
|
// second least significant bit in PC is always zero
|
|
ipr[idx] = val & ~2;
|
|
break;
|
|
|
|
case AlphaISA::IPR_ASTRR:
|
|
case AlphaISA::IPR_ASTER:
|
|
// only write least significant four bits - privilege mask
|
|
ipr[idx] = val & 0xf;
|
|
break;
|
|
|
|
case AlphaISA::IPR_IPLR:
|
|
#ifdef DEBUG
|
|
if (break_ipl != -1 && break_ipl == (val & 0x1f))
|
|
debug_break();
|
|
#endif
|
|
|
|
// only write least significant five bits - interrupt level
|
|
ipr[idx] = val & 0x1f;
|
|
kernelStats.swpipl(ipr[idx]);
|
|
break;
|
|
|
|
case AlphaISA::IPR_DTB_CM:
|
|
kernelStats.mode((val & 0x18) != 0);
|
|
|
|
case AlphaISA::IPR_ICM:
|
|
// only write two mode bits - processor mode
|
|
ipr[idx] = val & 0x18;
|
|
break;
|
|
|
|
case AlphaISA::IPR_ALT_MODE:
|
|
// only write two mode bits - processor mode
|
|
ipr[idx] = val & 0x18;
|
|
break;
|
|
|
|
case AlphaISA::IPR_MCSR:
|
|
// more here after optimization...
|
|
ipr[idx] = val;
|
|
break;
|
|
|
|
case AlphaISA::IPR_SIRR:
|
|
// only write software interrupt mask
|
|
ipr[idx] = val & 0x7fff0;
|
|
break;
|
|
|
|
case AlphaISA::IPR_ICSR:
|
|
ipr[idx] = val & ULL(0xffffff0300);
|
|
break;
|
|
|
|
case AlphaISA::IPR_IVPTBR:
|
|
case AlphaISA::IPR_MVPTBR:
|
|
ipr[idx] = val & ULL(0xffffffffc0000000);
|
|
break;
|
|
|
|
case AlphaISA::IPR_DC_TEST_CTL:
|
|
ipr[idx] = val & 0x1ffb;
|
|
break;
|
|
|
|
case AlphaISA::IPR_DC_MODE:
|
|
case AlphaISA::IPR_MAF_MODE:
|
|
ipr[idx] = val & 0x3f;
|
|
break;
|
|
|
|
case AlphaISA::IPR_ITB_ASN:
|
|
ipr[idx] = val & 0x7f0;
|
|
break;
|
|
|
|
case AlphaISA::IPR_DTB_ASN:
|
|
ipr[idx] = val & ULL(0xfe00000000000000);
|
|
break;
|
|
|
|
case AlphaISA::IPR_EXC_SUM:
|
|
case AlphaISA::IPR_EXC_MASK:
|
|
// any write to this register clears it
|
|
ipr[idx] = 0;
|
|
break;
|
|
|
|
case AlphaISA::IPR_INTID:
|
|
case AlphaISA::IPR_SL_RCV:
|
|
case AlphaISA::IPR_MM_STAT:
|
|
case AlphaISA::IPR_ITB_PTE_TEMP:
|
|
case AlphaISA::IPR_DTB_PTE_TEMP:
|
|
// read-only registers
|
|
return Unimplemented_Opcode_Fault;
|
|
|
|
case AlphaISA::IPR_HWINT_CLR:
|
|
case AlphaISA::IPR_SL_XMIT:
|
|
case AlphaISA::IPR_DC_FLUSH:
|
|
case AlphaISA::IPR_IC_FLUSH:
|
|
// the following are write only
|
|
ipr[idx] = val;
|
|
break;
|
|
|
|
case AlphaISA::IPR_DTB_IA:
|
|
// really a control write
|
|
ipr[idx] = 0;
|
|
|
|
dtb->flushAll();
|
|
break;
|
|
|
|
case AlphaISA::IPR_DTB_IAP:
|
|
// really a control write
|
|
ipr[idx] = 0;
|
|
|
|
dtb->flushProcesses();
|
|
break;
|
|
|
|
case AlphaISA::IPR_DTB_IS:
|
|
// really a control write
|
|
ipr[idx] = val;
|
|
|
|
dtb->flushAddr(val, DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
|
|
break;
|
|
|
|
case AlphaISA::IPR_DTB_TAG: {
|
|
struct AlphaISA::PTE pte;
|
|
|
|
// FIXME: granularity hints NYI...
|
|
if (DTB_PTE_GH(ipr[AlphaISA::IPR_DTB_PTE]) != 0)
|
|
panic("PTE GH field != 0");
|
|
|
|
// write entire quad
|
|
ipr[idx] = val;
|
|
|
|
// construct PTE for new entry
|
|
pte.ppn = DTB_PTE_PPN(ipr[AlphaISA::IPR_DTB_PTE]);
|
|
pte.xre = DTB_PTE_XRE(ipr[AlphaISA::IPR_DTB_PTE]);
|
|
pte.xwe = DTB_PTE_XWE(ipr[AlphaISA::IPR_DTB_PTE]);
|
|
pte.fonr = DTB_PTE_FONR(ipr[AlphaISA::IPR_DTB_PTE]);
|
|
pte.fonw = DTB_PTE_FONW(ipr[AlphaISA::IPR_DTB_PTE]);
|
|
pte.asma = DTB_PTE_ASMA(ipr[AlphaISA::IPR_DTB_PTE]);
|
|
pte.asn = DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]);
|
|
|
|
// insert new TAG/PTE value into data TLB
|
|
dtb->insert(val, pte);
|
|
}
|
|
break;
|
|
|
|
case AlphaISA::IPR_ITB_PTE: {
|
|
struct AlphaISA::PTE pte;
|
|
|
|
// FIXME: granularity hints NYI...
|
|
if (ITB_PTE_GH(val) != 0)
|
|
panic("PTE GH field != 0");
|
|
|
|
// write entire quad
|
|
ipr[idx] = val;
|
|
|
|
// construct PTE for new entry
|
|
pte.ppn = ITB_PTE_PPN(val);
|
|
pte.xre = ITB_PTE_XRE(val);
|
|
pte.xwe = 0;
|
|
pte.fonr = ITB_PTE_FONR(val);
|
|
pte.fonw = ITB_PTE_FONW(val);
|
|
pte.asma = ITB_PTE_ASMA(val);
|
|
pte.asn = ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]);
|
|
|
|
// insert new TAG/PTE value into data TLB
|
|
itb->insert(ipr[AlphaISA::IPR_ITB_TAG], pte);
|
|
}
|
|
break;
|
|
|
|
case AlphaISA::IPR_ITB_IA:
|
|
// really a control write
|
|
ipr[idx] = 0;
|
|
|
|
itb->flushAll();
|
|
break;
|
|
|
|
case AlphaISA::IPR_ITB_IAP:
|
|
// really a control write
|
|
ipr[idx] = 0;
|
|
|
|
itb->flushProcesses();
|
|
break;
|
|
|
|
case AlphaISA::IPR_ITB_IS:
|
|
// really a control write
|
|
ipr[idx] = val;
|
|
|
|
itb->flushAddr(val, ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]));
|
|
break;
|
|
|
|
default:
|
|
// invalid IPR
|
|
return Unimplemented_Opcode_Fault;
|
|
}
|
|
|
|
// no error...
|
|
return No_Fault;
|
|
}
|
|
|
|
/**
|
|
* Check for special simulator handling of specific PAL calls.
|
|
* If return value is false, actual PAL call will be suppressed.
|
|
*/
|
|
bool
|
|
ExecContext::simPalCheck(int palFunc)
|
|
{
|
|
kernelStats.callpal(palFunc);
|
|
|
|
switch (palFunc) {
|
|
case PAL::halt:
|
|
halt();
|
|
if (--System::numSystemsRunning == 0)
|
|
new SimExitEvent("all cpus halted");
|
|
break;
|
|
|
|
case PAL::bpt:
|
|
case PAL::bugchk:
|
|
if (system->breakpoint())
|
|
return false;
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//Forward instantiation for FastCPU object
|
|
template
|
|
void AlphaISA::processInterrupts(FastCPU *xc);
|
|
|
|
//Forward instantiation for FastCPU object
|
|
template
|
|
void AlphaISA::zeroRegisters(FastCPU *xc);
|
|
|
|
#endif // FULL_SYSTEM
|