diff options
Diffstat (limited to 'src/arch/sparc/ua2005.cc')
-rw-r--r-- | src/arch/sparc/ua2005.cc | 245 |
1 files changed, 141 insertions, 104 deletions
diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc index 0db5f6acc..00a44275c 100644 --- a/src/arch/sparc/ua2005.cc +++ b/src/arch/sparc/ua2005.cc @@ -24,8 +24,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Ali Saidi */ #include "arch/sparc/miscregfile.hh" @@ -38,103 +36,107 @@ using namespace SparcISA; void MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, - ThreadContext *tc) + ThreadContext *tc) { int64_t time; switch (miscReg) { /* Full system only ASRs */ - case MISCREG_SOFTINT: - // Check if we are going to interrupt because of something - setReg(miscReg, val); - tc->getCpuPtr()->checkInterrupts = true; - warn("Writing to softint not really supported, writing: %#x\n", val); - break; - - case MISCREG_SOFTINT_CLR: - return setRegWithEffect(miscReg, ~val & softint, tc); - case MISCREG_SOFTINT_SET: - return setRegWithEffect(miscReg, val | softint, tc); - - case MISCREG_TICK_CMPR: - if (tickCompare == NULL) - tickCompare = new TickCompareEvent(this, tc); - setReg(miscReg, val); - if ((tick_cmpr & mask(63)) && tickCompare->scheduled()) - tickCompare->deschedule(); - time = (tick_cmpr & mask(63)) - (tick & mask(63)); - if (!(tick_cmpr & ~mask(63)) && time > 0) - tickCompare->schedule(time * tc->getCpuPtr()->cycles(1)); - warn ("writing to TICK compare register %#X\n", val); - break; - - case MISCREG_STICK_CMPR: - if (sTickCompare == NULL) - sTickCompare = new STickCompareEvent(this, tc); - setReg(miscReg, val); - if ((stick_cmpr & mask(63)) && sTickCompare->scheduled()) - sTickCompare->deschedule(); - time = (stick_cmpr & mask(63)) - (stick & mask(63)); - if (!(stick_cmpr & ~mask(63)) && time > 0) - sTickCompare->schedule(time * tc->getCpuPtr()->cycles(1)); - warn ("writing to sTICK compare register value %#X\n", val); - break; - - case MISCREG_PSTATE: - if (val & ie && !(pstate & ie)) { - tc->getCpuPtr()->checkInterrupts = true; - } - setReg(miscReg, val); - - case MISCREG_PIL: - if (val < pil) { - tc->getCpuPtr()->checkInterrupts = true; - } - setReg(miscReg, val); - break; - - case MISCREG_HVER: - panic("Shouldn't be writing HVER\n"); - - case MISCREG_HTBA: - // clear lower 7 bits on writes. - setReg(miscReg, val & ULL(~0x7FFF)); - break; - - case MISCREG_QUEUE_CPU_MONDO_HEAD: - case MISCREG_QUEUE_CPU_MONDO_TAIL: - case MISCREG_QUEUE_DEV_MONDO_HEAD: - case MISCREG_QUEUE_DEV_MONDO_TAIL: - case MISCREG_QUEUE_RES_ERROR_HEAD: - case MISCREG_QUEUE_RES_ERROR_TAIL: - case MISCREG_QUEUE_NRES_ERROR_HEAD: - case MISCREG_QUEUE_NRES_ERROR_TAIL: - setReg(miscReg, val); - tc->getCpuPtr()->checkInterrupts = true; - break; - - case MISCREG_HSTICK_CMPR: - if (hSTickCompare == NULL) - hSTickCompare = new HSTickCompareEvent(this, tc); - setReg(miscReg, val); - if ((hstick_cmpr & mask(63)) && hSTickCompare->scheduled()) - hSTickCompare->deschedule(); - time = (hstick_cmpr & mask(63)) - (stick & mask(63)); - if (!(hstick_cmpr & ~mask(63)) && time > 0) - hSTickCompare->schedule(time * tc->getCpuPtr()->cycles(1)); - warn ("writing to hsTICK compare register value %#X\n", val); - break; - - case MISCREG_HPSTATE: - // T1000 spec says impl. dependent val must always be 1 - setReg(miscReg, val | id); - break; - case MISCREG_HTSTATE: - case MISCREG_STRAND_STS_REG: - setReg(miscReg, val); - break; - - default: - panic("Invalid write to FS misc register %s\n", getMiscRegName(miscReg)); + case MISCREG_SOFTINT: + setReg(miscReg, val);; + break; + + case MISCREG_SOFTINT_CLR: + return setRegWithEffect(MISCREG_SOFTINT, ~val & softint, tc); + case MISCREG_SOFTINT_SET: + tc->getCpuPtr()->checkInterrupts = true; + tc->getCpuPtr()->post_interrupt(soft_interrupt); + return setRegWithEffect(MISCREG_SOFTINT, val | softint, tc); + + case MISCREG_TICK_CMPR: + if (tickCompare == NULL) + tickCompare = new TickCompareEvent(this, tc); + setReg(miscReg, val); + if ((tick_cmpr & mask(63)) && tickCompare->scheduled()) + tickCompare->deschedule(); + time = (tick_cmpr & mask(63)) - (tick & mask(63)); + if (!(tick_cmpr & ~mask(63)) && time > 0) + tickCompare->schedule(time * tc->getCpuPtr()->cycles(1)); + panic("writing to TICK compare register %#X\n", val); + break; + + case MISCREG_STICK_CMPR: + if (sTickCompare == NULL) + sTickCompare = new STickCompareEvent(this, tc); + setReg(miscReg, val); + if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled()) + sTickCompare->deschedule(); + time = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) - + tc->getCpuPtr()->instCount(); + if (!(stick_cmpr & ~mask(63)) && time > 0) + sTickCompare->schedule(time * tc->getCpuPtr()->cycles(1) + curTick); + DPRINTF(Timer, "writing to sTICK compare register value %#X\n", val); + break; + + case MISCREG_PSTATE: + if (val & PSTATE::ie && !(pstate & PSTATE::ie)) { + tc->getCpuPtr()->checkInterrupts = true; + } + setReg(miscReg, val); + + case MISCREG_PIL: + if (val < pil) { + tc->getCpuPtr()->checkInterrupts = true; + } + setReg(miscReg, val); + break; + + case MISCREG_HVER: + panic("Shouldn't be writing HVER\n"); + + case MISCREG_HINTP: + setReg(miscReg, val); + + case MISCREG_HTBA: + // clear lower 7 bits on writes. + setReg(miscReg, val & ULL(~0x7FFF)); + break; + + case MISCREG_QUEUE_CPU_MONDO_HEAD: + case MISCREG_QUEUE_CPU_MONDO_TAIL: + case MISCREG_QUEUE_DEV_MONDO_HEAD: + case MISCREG_QUEUE_DEV_MONDO_TAIL: + case MISCREG_QUEUE_RES_ERROR_HEAD: + case MISCREG_QUEUE_RES_ERROR_TAIL: + case MISCREG_QUEUE_NRES_ERROR_HEAD: + case MISCREG_QUEUE_NRES_ERROR_TAIL: + setReg(miscReg, val); + tc->getCpuPtr()->checkInterrupts = true; + break; + + case MISCREG_HSTICK_CMPR: + if (hSTickCompare == NULL) + hSTickCompare = new HSTickCompareEvent(this, tc); + setReg(miscReg, val); + if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled()) + hSTickCompare->deschedule(); + time = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) - + tc->getCpuPtr()->instCount(); + if (!(hstick_cmpr & ~mask(63)) && time > 0) + hSTickCompare->schedule(curTick + time * tc->getCpuPtr()->cycles(1)); + DPRINTF(Timer, "writing to hsTICK compare register value %#X\n", val); + break; + + case MISCREG_HPSTATE: + // T1000 spec says impl. dependent val must always be 1 + setReg(miscReg, val | HPSTATE::id); + break; + case MISCREG_HTSTATE: + case MISCREG_STRAND_STS_REG: + setReg(miscReg, val); + break; + + default: + panic("Invalid write to FS misc register %s\n", getMiscRegName(miscReg)); } } @@ -142,7 +144,7 @@ MiscReg MiscRegFile::readFSRegWithEffect(int miscReg, ThreadContext * tc) { switch (miscReg) { - /* Privileged registers. */ + /* Privileged registers. */ case MISCREG_QUEUE_CPU_MONDO_HEAD: case MISCREG_QUEUE_CPU_MONDO_TAIL: case MISCREG_QUEUE_DEV_MONDO_HEAD: @@ -172,12 +174,12 @@ MiscRegFile::readFSRegWithEffect(int miscReg, ThreadContext * tc) } } /* - In Niagra STICK==TICK so this isn't needed - case MISCREG_STICK: - SparcSystem *sys; - sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr()); - assert(sys != NULL); - return curTick/Clock::Int::ns - sys->sysTick | (stick & ~(mask(63))); + In Niagra STICK==TICK so this isn't needed + case MISCREG_STICK: + SparcSystem *sys; + sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr()); + assert(sys != NULL); + return curTick/Clock::Int::ns - sys->sysTick | (stick & ~(mask(63))); */ @@ -191,12 +193,47 @@ MiscRegFile::processTickCompare(ThreadContext *tc) void MiscRegFile::processSTickCompare(ThreadContext *tc) { - panic("tick compare not implemented\n"); + // since our microcode instructions take two cycles we need to check if + // we're actually at the correct cycle or we need to wait a little while + // more + int ticks; + ticks = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) - + tc->getCpuPtr()->instCount(); + assert(ticks >= 0 && "stick compare missed interrupt cycle"); + + if (ticks == 0) { + DPRINTF(Timer, "STick compare cycle reached at %#x\n", + (stick_cmpr & mask(63))); + if (!(tc->readMiscReg(MISCREG_STICK_CMPR) & (ULL(1) << 63))) { + tc->getCpuPtr()->post_interrupt(soft_interrupt); + tc->getCpuPtr()->checkInterrupts = true; + setRegWithEffect(MISCREG_SOFTINT, softint | (ULL(1) << 16), tc); + } + } else + sTickCompare->schedule(ticks * tc->getCpuPtr()->cycles(1) + curTick); } void MiscRegFile::processHSTickCompare(ThreadContext *tc) { - panic("tick compare not implemented\n"); + // since our microcode instructions take two cycles we need to check if + // we're actually at the correct cycle or we need to wait a little while + // more + int ticks; + ticks = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) - + tc->getCpuPtr()->instCount(); + assert(ticks >= 0 && "hstick compare missed interrupt cycle"); + + if (ticks == 0) { + DPRINTF(Timer, "HSTick compare cycle reached at %#x\n", + (stick_cmpr & mask(63))); + if (!(tc->readMiscReg(MISCREG_HSTICK_CMPR) & (ULL(1) << 63))) { + setRegWithEffect(MISCREG_HINTP, 1, tc); + tc->getCpuPtr()->post_interrupt(hstick_match); + tc->getCpuPtr()->checkInterrupts = true; + } + // Need to do something to cause interrupt to happen here !!! @todo + } else + sTickCompare->schedule(ticks * tc->getCpuPtr()->cycles(1) + curTick); } |