diff options
Diffstat (limited to 'src/arch/sparc')
33 files changed, 1086 insertions, 483 deletions
diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript index c2ef97bfa..555bfba3d 100644 --- a/src/arch/sparc/SConscript +++ b/src/arch/sparc/SConscript @@ -50,12 +50,12 @@ base_sources = Split(''' intregfile.cc miscregfile.cc regfile.cc + remote_gdb.cc ''') # Full-system sources full_system_sources = Split(''' arguments.cc - remote_gdb.cc pagetable.cc stacktrace.cc system.cc diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc index 825ff40f6..a6f4343ae 100644 --- a/src/arch/sparc/faults.cc +++ b/src/arch/sparc/faults.cc @@ -302,10 +302,12 @@ void doREDFault(ThreadContext *tc, TrapType tt) MiscReg TSTATE = tc->readMiscReg(MISCREG_TSTATE); MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE); MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); - MiscReg CCR = tc->readMiscReg(MISCREG_CCR); + //MiscReg CCR = tc->readMiscReg(MISCREG_CCR); + MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2); MiscReg ASI = tc->readMiscReg(MISCREG_ASI); MiscReg CWP = tc->readMiscReg(MISCREG_CWP); - MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); + //MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); + MiscReg CANSAVE = tc->readMiscReg(NumIntArchRegs + 3); MiscReg GL = tc->readMiscReg(MISCREG_GL); MiscReg PC = tc->readPC(); MiscReg NPC = tc->readNextPC(); @@ -387,10 +389,12 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) MiscReg TSTATE = tc->readMiscReg(MISCREG_TSTATE); MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE); MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); - MiscReg CCR = tc->readMiscReg(MISCREG_CCR); + //MiscReg CCR = tc->readMiscReg(MISCREG_CCR); + MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2); MiscReg ASI = tc->readMiscReg(MISCREG_ASI); MiscReg CWP = tc->readMiscReg(MISCREG_CWP); - MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); + //MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); + MiscReg CANSAVE = tc->readIntReg(NumIntArchRegs + 3); MiscReg GL = tc->readMiscReg(MISCREG_GL); MiscReg PC = tc->readPC(); MiscReg NPC = tc->readNextPC(); @@ -656,19 +660,21 @@ void PageTableFault::invoke(ThreadContext *tc) { Process *p = tc->getProcessPtr(); - // address is higher than the stack region or in the current stack region - if (vaddr > p->stack_base || vaddr > p->stack_min) - FaultBase::invoke(tc); - - // We've accessed the next page - if (vaddr > p->stack_min - PageBytes) { + // We've accessed the next page of the stack, so extend the stack + // to cover it. + if(vaddr < p->stack_min && vaddr >= p->stack_min - PageBytes) + { p->stack_min -= PageBytes; - if (p->stack_base - p->stack_min > 8*1024*1024) + if(p->stack_base - p->stack_min > 8*1024*1024) fatal("Over max stack size for one thread\n"); p->pTable->allocate(p->stack_min, PageBytes); warn("Increasing stack size by one page."); - } else { - FaultBase::invoke(tc); + } + // Otherwise, we have an unexpected page fault. Report that fact, + // and what address was accessed to cause the fault. + else + { + panic("Page table fault when accessing virtual address %#x\n", vaddr); } } diff --git a/src/arch/sparc/floatregfile.cc b/src/arch/sparc/floatregfile.cc index 7f3d5a758..585782ddb 100644 --- a/src/arch/sparc/floatregfile.cc +++ b/src/arch/sparc/floatregfile.cc @@ -72,16 +72,19 @@ FloatReg FloatRegFile::readReg(int floatReg, int width) float32_t result32; memcpy(&result32, regSpace + 4 * floatReg, sizeof(result32)); result = htog(result32); + DPRINTF(Sparc, "Read FP32 register %d = 0x%x\n", floatReg, result); break; case DoubleWidth: float64_t result64; memcpy(&result64, regSpace + 4 * floatReg, sizeof(result64)); result = htog(result64); + DPRINTF(Sparc, "Read FP64 register %d = 0x%x\n", floatReg, result); break; case QuadWidth: float128_t result128; memcpy(&result128, regSpace + 4 * floatReg, sizeof(result128)); result = htog(result128); + DPRINTF(Sparc, "Read FP128 register %d = 0x%x\n", floatReg, result); break; default: panic("Attempted to read a %d bit floating point register!", width); @@ -101,16 +104,19 @@ FloatRegBits FloatRegFile::readRegBits(int floatReg, int width) uint32_t result32; memcpy(&result32, regSpace + 4 * floatReg, sizeof(result32)); result = htog(result32); + DPRINTF(Sparc, "Read FP32 bits register %d = 0x%x\n", floatReg, result); break; case DoubleWidth: uint64_t result64; memcpy(&result64, regSpace + 4 * floatReg, sizeof(result64)); result = htog(result64); + DPRINTF(Sparc, "Read FP64 bits register %d = 0x%x\n", floatReg, result); break; case QuadWidth: uint64_t result128; memcpy(&result128, regSpace + 4 * floatReg, sizeof(result128)); result = htog(result128); + DPRINTF(Sparc, "Read FP128 bits register %d = 0x%x\n", floatReg, result); break; default: panic("Attempted to read a %d bit floating point register!", width); @@ -131,10 +137,12 @@ Fault FloatRegFile::setReg(int floatReg, const FloatReg &val, int width) case SingleWidth: result32 = gtoh((uint32_t)val); memcpy(regSpace + 4 * floatReg, &result32, sizeof(result32)); + DPRINTF(Sparc, "Write FP64 register %d = 0x%x\n", floatReg, result32); break; case DoubleWidth: result64 = gtoh((uint64_t)val); memcpy(regSpace + 4 * floatReg, &result64, sizeof(result64)); + DPRINTF(Sparc, "Write FP64 register %d = 0x%x\n", floatReg, result64); break; case QuadWidth: panic("Quad width FP not implemented."); @@ -157,10 +165,12 @@ Fault FloatRegFile::setRegBits(int floatReg, const FloatRegBits &val, int width) case SingleWidth: result32 = gtoh((uint32_t)val); memcpy(regSpace + 4 * floatReg, &result32, sizeof(result32)); + DPRINTF(Sparc, "Write FP64 bits register %d = 0x%x\n", floatReg, result32); break; case DoubleWidth: result64 = gtoh((uint64_t)val); memcpy(regSpace + 4 * floatReg, &result64, sizeof(result64)); + DPRINTF(Sparc, "Write FP64 bits register %d = 0x%x\n", floatReg, result64); break; case QuadWidth: panic("Quad width FP not implemented."); @@ -173,13 +183,15 @@ Fault FloatRegFile::setRegBits(int floatReg, const FloatRegBits &val, int width) void FloatRegFile::serialize(std::ostream &os) { - SERIALIZE_ARRAY((unsigned char *)regSpace, + uint8_t *float_reg = (uint8_t*)regSpace; + SERIALIZE_ARRAY(float_reg, SingleWidth / 8 * NumFloatRegs); } void FloatRegFile::unserialize(Checkpoint *cp, const std::string §ion) { - UNSERIALIZE_ARRAY((unsigned char *)regSpace, + uint8_t *float_reg = (uint8_t*)regSpace; + UNSERIALIZE_ARRAY(float_reg, SingleWidth / 8 * NumFloatRegs); } diff --git a/src/arch/sparc/intregfile.cc b/src/arch/sparc/intregfile.cc index 60856d3fa..39a613a0d 100644 --- a/src/arch/sparc/intregfile.cc +++ b/src/arch/sparc/intregfile.cc @@ -66,6 +66,7 @@ void IntRegFile::clear() memset(regGlobals[x], 0, sizeof(IntReg) * RegsPerFrame); for(int x = 0; x < 2 * NWindows; x++) memset(regSegments[x], 0, sizeof(IntReg) * RegsPerFrame); + memset(regs, 0, sizeof(IntReg) * NumIntRegs); } IntRegFile::IntRegFile() @@ -78,6 +79,10 @@ IntRegFile::IntRegFile() IntReg IntRegFile::readReg(int intReg) { + DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, regs[intReg]); + return regs[intReg]; + /* XXX Currently not used. When used again regView/offset need to be + * serialized! IntReg val; if(intReg < NumIntArchRegs) val = regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask]; @@ -89,6 +94,7 @@ IntReg IntRegFile::readReg(int intReg) DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, val); return val; + */ } void IntRegFile::setReg(int intReg, const IntReg &val) @@ -96,13 +102,21 @@ void IntRegFile::setReg(int intReg, const IntReg &val) if(intReg) { DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val); + regs[intReg] = val; + } + return; + /* XXX Currently not used. When used again regView/offset need to be + * serialized! + if(intReg) + { + DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val); if(intReg < NumIntArchRegs) regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val; else if((intReg -= NumIntArchRegs) < NumMicroIntRegs) microRegs[intReg] = val; else panic("Tried to set non-existant integer register\n"); - } + } */ } //This doesn't effect the actual CWP register. @@ -139,20 +153,26 @@ void IntRegFile::setGlobals(int gl) void IntRegFile::serialize(std::ostream &os) { + SERIALIZE_ARRAY(regs, NumIntRegs); + SERIALIZE_ARRAY(microRegs, NumMicroIntRegs); + + /* the below doesn't seem needed unless gabe makes regview work*/ unsigned int x; for(x = 0; x < MaxGL; x++) SERIALIZE_ARRAY(regGlobals[x], RegsPerFrame); for(x = 0; x < 2 * NWindows; x++) SERIALIZE_ARRAY(regSegments[x], RegsPerFrame); - SERIALIZE_ARRAY(microRegs, NumMicroIntRegs); } void IntRegFile::unserialize(Checkpoint *cp, const std::string §ion) { + UNSERIALIZE_ARRAY(regs, NumIntRegs); + UNSERIALIZE_ARRAY(microRegs, NumMicroIntRegs); + + /* the below doesn't seem needed unless gabe makes regview work*/ unsigned int x; for(x = 0; x < MaxGL; x++) UNSERIALIZE_ARRAY(regGlobals[x], RegsPerFrame); for(unsigned int x = 0; x < 2 * NWindows; x++) UNSERIALIZE_ARRAY(regSegments[x], RegsPerFrame); - UNSERIALIZE_ARRAY(microRegs, NumMicroIntRegs); } diff --git a/src/arch/sparc/intregfile.hh b/src/arch/sparc/intregfile.hh index d66d0fcb7..665c7aa31 100644 --- a/src/arch/sparc/intregfile.hh +++ b/src/arch/sparc/intregfile.hh @@ -34,6 +34,7 @@ #include "arch/sparc/isa_traits.hh" #include "arch/sparc/types.hh" +#include "base/bitfield.hh" #include <string> @@ -47,22 +48,26 @@ namespace SparcISA std::string getIntRegName(RegIndex); const int NumIntArchRegs = 32; - const int NumIntRegs = MaxGL * 8 + NWindows * 16 + NumMicroIntRegs; + const int NumIntRegs = (MaxGL + 1) * 8 + NWindows * 16 + NumMicroIntRegs; class IntRegFile { private: friend class RegFile; protected: + //The number of bits needed to index into each 8 register frame static const int FrameOffsetBits = 3; + //The number of bits to choose between the 4 sets of 8 registers static const int FrameNumBits = 2; + //The number of registers per "frame" (8) static const int RegsPerFrame = 1 << FrameOffsetBits; - static const int FrameNumMask = + //A mask to get the frame number + static const uint64_t FrameNumMask = (FrameNumBits == sizeof(int)) ? (unsigned int)(-1) : (1 << FrameNumBits) - 1; - static const int FrameOffsetMask = + static const uint64_t FrameOffsetMask = (FrameOffsetBits == sizeof(int)) ? (unsigned int)(-1) : (1 << FrameOffsetBits) - 1; @@ -70,6 +75,7 @@ namespace SparcISA IntReg regGlobals[MaxGL+1][RegsPerFrame]; IntReg regSegments[2 * NWindows][RegsPerFrame]; IntReg microRegs[NumMicroIntRegs]; + IntReg regs[NumIntRegs]; enum regFrame {Globals, Outputs, Locals, Inputs, NumFrames}; diff --git a/src/arch/sparc/isa/base.isa b/src/arch/sparc/isa/base.isa index 4a806bfd0..693cc6876 100644 --- a/src/arch/sparc/isa/base.isa +++ b/src/arch/sparc/isa/base.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2006 The Regents of The University of Michigan +// Copyright (c) 2006-2007 The Regents of The University of Michigan // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -67,6 +67,26 @@ output header {{ OverflowSet=0x7 }; + enum FpCondTest + { + FAlways=0x8, + FNever=0x0, + FUnordered=0x7, + FGreater=0x6, + FUnorderedOrGreater=0x5, + FLess=0x4, + FUnorderedOrLess=0x3, + FLessOrGreater=0x2, + FNotEqual=0x1, + FEqual=0x9, + FUnorderedOrEqual=0xA, + FGreaterOrEqual=0xB, + FUnorderedOrGreaterOrEqual=0xC, + FLessOrEqual=0xD, + FUnorderedOrLessOrEqual=0xE, + FOrdered=0xF + }; + extern char * CondTestAbbrev[]; /** @@ -93,6 +113,8 @@ output header {{ const RegIndex indexArray[], int num) const; }; + bool passesFpCondition(uint32_t fcc, uint32_t condition); + bool passesCondition(uint32_t codes, uint32_t condition); inline int64_t sign_ext(uint64_t data, int origWidth) @@ -189,23 +211,149 @@ output decoder {{ const int MaxOutput = 16; const int MaxLocal = 24; const int MaxInput = 32; - const int MaxMicroReg = 33; - if (reg == FramePointerReg) - ccprintf(os, "%%fp"); - else if (reg == StackPointerReg) - ccprintf(os, "%%sp"); - else if(reg < MaxGlobal) - ccprintf(os, "%%g%d", reg); - else if(reg < MaxOutput) - ccprintf(os, "%%o%d", reg - MaxGlobal); - else if(reg < MaxLocal) - ccprintf(os, "%%l%d", reg - MaxOutput); - else if(reg < MaxInput) - ccprintf(os, "%%i%d", reg - MaxLocal); - else if(reg < MaxMicroReg) - ccprintf(os, "%%u%d", reg - MaxInput); - else { - ccprintf(os, "%%f%d", reg - MaxMicroReg); + const int MaxMicroReg = 40; + if (reg < FP_Base_DepTag) { + //If we used a register from the next or previous window, + //take out the offset. + while (reg >= MaxMicroReg) + reg -= MaxMicroReg; + if (reg == FramePointerReg) + ccprintf(os, "%%fp"); + else if (reg == StackPointerReg) + ccprintf(os, "%%sp"); + else if(reg < MaxGlobal) + ccprintf(os, "%%g%d", reg); + else if(reg < MaxOutput) + ccprintf(os, "%%o%d", reg - MaxGlobal); + else if(reg < MaxLocal) + ccprintf(os, "%%l%d", reg - MaxOutput); + else if(reg < MaxInput) + ccprintf(os, "%%i%d", reg - MaxLocal); + else if(reg < MaxMicroReg) + ccprintf(os, "%%u%d", reg - MaxInput); + //The fake int regs that are really control regs + else { + switch (reg - MaxMicroReg) { + case 1: + ccprintf(os, "%%y"); + break; + case 2: + ccprintf(os, "%%ccr"); + break; + case 3: + ccprintf(os, "%%cansave"); + break; + case 4: + ccprintf(os, "%%canrestore"); + break; + case 5: + ccprintf(os, "%%cleanwin"); + break; + case 6: + ccprintf(os, "%%otherwin"); + break; + case 7: + ccprintf(os, "%%wstate"); + break; + } + } + } else if (reg < Ctrl_Base_DepTag) { + ccprintf(os, "%%f%d", reg - FP_Base_DepTag); + } else { + switch (reg - Ctrl_Base_DepTag) { + case MISCREG_ASI: + ccprintf(os, "%%asi"); + break; + case MISCREG_FPRS: + ccprintf(os, "%%fprs"); + break; + case MISCREG_PCR: + ccprintf(os, "%%pcr"); + break; + case MISCREG_PIC: + ccprintf(os, "%%pic"); + break; + case MISCREG_GSR: + ccprintf(os, "%%gsr"); + break; + case MISCREG_SOFTINT: + ccprintf(os, "%%softint"); + break; + case MISCREG_SOFTINT_SET: + ccprintf(os, "%%softint_set"); + break; + case MISCREG_SOFTINT_CLR: + ccprintf(os, "%%softint_clr"); + break; + case MISCREG_TICK_CMPR: + ccprintf(os, "%%tick_cmpr"); + break; + case MISCREG_STICK: + ccprintf(os, "%%stick"); + break; + case MISCREG_STICK_CMPR: + ccprintf(os, "%%stick_cmpr"); + break; + case MISCREG_TPC: + ccprintf(os, "%%tpc"); + break; + case MISCREG_TNPC: + ccprintf(os, "%%tnpc"); + break; + case MISCREG_TSTATE: + ccprintf(os, "%%tstate"); + break; + case MISCREG_TT: + ccprintf(os, "%%tt"); + break; + case MISCREG_TICK: + ccprintf(os, "%%tick"); + break; + case MISCREG_TBA: + ccprintf(os, "%%tba"); + break; + case MISCREG_PSTATE: + ccprintf(os, "%%pstate"); + break; + case MISCREG_TL: + ccprintf(os, "%%tl"); + break; + case MISCREG_PIL: + ccprintf(os, "%%pil"); + break; + case MISCREG_CWP: + ccprintf(os, "%%cwp"); + break; + case MISCREG_GL: + ccprintf(os, "%%gl"); + break; + case MISCREG_HPSTATE: + ccprintf(os, "%%hpstate"); + break; + case MISCREG_HTSTATE: + ccprintf(os, "%%htstate"); + break; + case MISCREG_HINTP: + ccprintf(os, "%%hintp"); + break; + case MISCREG_HTBA: + ccprintf(os, "%%htba"); + break; + case MISCREG_HSTICK_CMPR: + ccprintf(os, "%%hstick_cmpr"); + break; + case MISCREG_HVER: + ccprintf(os, "%%hver"); + break; + case MISCREG_STRAND_STS_REG: + ccprintf(os, "%%strand_sts_reg"); + break; + case MISCREG_FSR: + ccprintf(os, "%%fsr"); + break; + default: + ccprintf(os, "%%ctrl%d", reg - Ctrl_Base_DepTag); + } } } @@ -241,6 +389,51 @@ output decoder {{ return ss.str(); } + bool passesFpCondition(uint32_t fcc, uint32_t condition) + { + bool u = (fcc == 3); + bool g = (fcc == 2); + bool l = (fcc == 1); + bool e = (fcc == 0); + switch(condition) + { + case FAlways: + return 1; + case FNever: + return 0; + case FUnordered: + return u; + case FGreater: + return g; + case FUnorderedOrGreater: + return u || g; + case FLess: + return l; + case FUnorderedOrLess: + return u || l; + case FLessOrGreater: + return l || g; + case FNotEqual: + return l || g || u; + case FEqual: + return e; + case FUnorderedOrEqual: + return u || e; + case FGreaterOrEqual: + return g || e; + case FUnorderedOrGreaterOrEqual: + return u || g || e; + case FLessOrEqual: + return l || e; + case FUnorderedOrLessOrEqual: + return u || l || e; + case FOrdered: + return e || l || g; + } + panic("Tried testing condition nonexistant " + "condition code %d", condition); + } + bool passesCondition(uint32_t codes, uint32_t condition) { CondCodes condCodes; @@ -290,3 +483,27 @@ output decoder {{ } }}; +output exec {{ + /// Check "FP enabled" machine status bit. Called when executing any FP + /// instruction in full-system mode. + /// @retval Full-system mode: NoFault if FP is enabled, FpDisabled + /// if not. Non-full-system mode: always returns NoFault. +#if FULL_SYSTEM + inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) + { + Fault fault = NoFault; // dummy... this ipr access should not fault + if (xc->readMiscRegWithEffect(MISCREG_PSTATE) & PSTATE::pef && + xc->readMiscRegWithEffect(MISCREG_FPRS) & 0x4) + return NoFault; + else + return new FpDisabled; + } +#else + inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) + { + return NoFault; + } +#endif +}}; + + diff --git a/src/arch/sparc/isa/bitfields.isa b/src/arch/sparc/isa/bitfields.isa index 7e884866c..e75680d2b 100644 --- a/src/arch/sparc/isa/bitfields.isa +++ b/src/arch/sparc/isa/bitfields.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2006 The Regents of The University of Michigan +// Copyright (c) 2006-2007 The Regents of The University of Michigan // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -38,7 +38,7 @@ def bitfield A <29>; def bitfield BPCC <21:20>; // for BPcc & FBPcc -def bitfield FCMPCC <26:56>; // for FCMP & FCMPEa +def bitfield FCMPCC <26:25>; // for FCMP & FCMPEa def bitfield FMOVCC <13:11>; // for FMOVcc def bitfield CC <12:11>; // for MOVcc & Tcc def bitfield MOVCC3 <18>; // also for MOVcc diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index 425ebc9d0..81443fecb 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -62,8 +62,8 @@ decode OP default Unknown::unknown() NNPC = NNPC;//Don't do anything }}); 0x1: bpn(19, {{ - NPC = xc->readNextPC() + 4; - NNPC = NPC + 4; + NNPC = NPC + 8; + NPC = NPC + 4; }}, ',a'); } default: decode BPCC @@ -103,8 +103,8 @@ decode OP default Unknown::unknown() NNPC = NNPC;//Don't do anything }}); 0x1: bn(22, {{ - NPC = xc->readNextPC() + 4; - NNPC = NPC + 4; + NNPC = NPC + 8; + NPC = NPC + 4; }}, ',a'); } default: bicc(22, {{ @@ -159,8 +159,92 @@ decode OP default Unknown::unknown() } //SETHI (or NOP if rd == 0 and imm == 0) 0x4: SetHi::sethi({{Rd.udw = imm;}}); - 0x5: Trap::fbpfcc({{fault = new FpDisabled;}}); - 0x6: Trap::fbfcc({{fault = new FpDisabled;}}); + //fbpfcc + 0x5: decode COND2 { + format BranchN { + //Branch Always + 0x8: decode A + { + 0x0: fbpa(22, {{ + NNPC = xc->readPC() + disp; + }}); + 0x1: fbpa(22, {{ + NPC = xc->readPC() + disp; + NNPC = NPC + 4; + }}, ',a'); + } + //Branch Never + 0x0: decode A + { + 0x0: fbpn(22, {{ + NNPC = NNPC;//Don't do anything + }}); + 0x1: fbpn(22, {{ + NNPC = NPC + 8; + NPC = NPC + 4; + }}, ',a'); + } + default: decode BPCC { + 0x0: fbpcc0(22, {{ + if(passesFpCondition(Fsr<11:10>, COND2)) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + 0x1: fbpcc1(22, {{ + if(passesFpCondition(Fsr<33:32>, COND2)) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + 0x2: fbpcc2(22, {{ + if(passesFpCondition(Fsr<35:34>, COND2)) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + 0x3: fbpcc3(22, {{ + if(passesFpCondition(Fsr<37:36>, COND2)) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + } + } + } + //fbfcc + 0x6: decode COND2 { + format BranchN { + //Branch Always + 0x8: decode A + { + 0x0: fba(22, {{ + NNPC = xc->readPC() + disp; + }}); + 0x1: fba(22, {{ + NPC = xc->readPC() + disp; + NNPC = NPC + 4; + }}, ',a'); + } + //Branch Never + 0x0: decode A + { + 0x0: fbn(22, {{ + NNPC = NNPC;//Don't do anything + }}); + 0x1: fbn(22, {{ + NNPC = NPC + 8; + NPC = NPC + 4; + }}, ',a'); + } + default: fbfcc(22, {{ + if(passesFpCondition(Fsr<11:10>, COND2)) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + } + } } 0x1: BranchN::call(30, {{ if (Pstate<3:>) @@ -186,7 +270,7 @@ decode OP default Unknown::unknown() Y = Rd<63:32>; }}); 0x0B: smul({{ - Rd.sdw = sext<32>(Rs1.sdw) * sext<32>(Rs2_or_imm13); + Rd.sdw = sext<32>(Rs1.sdw<31:0>) * sext<32>(Rs2_or_imm13<31:0>); Y = Rd.sdw<63:32>; }}); 0x0C: subc({{Rd.sdw = Rs1.sdw + (~Rs2_or_imm13) + 1 - Ccr<0:0>}}); @@ -246,33 +330,29 @@ decode OP default Unknown::unknown() Rd = resTemp = Rs1 + val2 + carryin;}}, {{(Rs1<31:0> + val2<31:0> + carryin)<32:>}}, {{Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>}}, - {{(Rs1<63:1> + val2<63:1> + - ((Rs1 & val2) | (carryin & (Rs1 | val2)))<0:>)<63:>}}, + {{((Rs1 & val2) | (~resTemp & (Rs1 | val2)))<63:>}}, {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}} ); - 0x1A: umulcc({{ + 0x1A: IntOpCcRes::umulcc({{ uint64_t resTemp; Rd = resTemp = Rs1.udw<31:0> * Rs2_or_imm13.udw<31:0>; - Y = resTemp<63:32>;}}, - {{0}},{{0}},{{0}},{{0}}); - 0x1B: smulcc({{ + Y = resTemp<63:32>;}}); + 0x1B: IntOpCcRes::smulcc({{ int64_t resTemp; - Rd = resTemp = sext<32>(Rs1.sdw) * sext<32>(Rs2_or_imm13); - Y = resTemp<63:32>;}}, - {{0}},{{0}},{{0}},{{0}}); + Rd = resTemp = sext<32>(Rs1.sdw<31:0>) * sext<32>(Rs2_or_imm13<31:0>); + Y = resTemp<63:32>;}}); 0x1C: subccc({{ int64_t resTemp, val2 = Rs2_or_imm13; int64_t carryin = Ccr<0:0>; Rd = resTemp = Rs1 + ~val2 + 1 - carryin;}}, - {{(~((Rs1<31:0> + (~(val2 + carryin))<31:0> + 1))<32:>)}}, + {{((~Rs1 & val2) | (resTemp & (~Rs1 | val2)))<31:>}}, {{Rs1<31:> != val2<31:> && Rs1<31:> != resTemp<31:>}}, - {{(~((Rs1<63:1> + (~(val2 + carryin))<63:1>) + (Rs1<0:> + (~(val2+carryin))<0:> + 1)<63:1>))<63:>}}, + {{((~Rs1 & val2) | (resTemp & (~Rs1 | val2)))<63:>}}, {{Rs1<63:> != val2<63:> && Rs1<63:> != resTemp<63:>}} ); - 0x1D: udivxcc({{ + 0x1D: IntOpCcRes::udivxcc({{ if(Rs2_or_imm13.udw == 0) fault = new DivisionByZero; - else Rd = Rs1.udw / Rs2_or_imm13.udw;}} - ,{{0}},{{0}},{{0}},{{0}}); + else Rd = Rs1.udw / Rs2_or_imm13.udw;}}); 0x1E: udivcc({{ uint32_t resTemp, val2 = Rs2_or_imm13.udw; int32_t overflow = 0; @@ -502,20 +582,7 @@ decode OP default Unknown::unknown() if(Rs2_or_imm13.sdw == 0) fault = new DivisionByZero; else Rd.sdw = Rs1.sdw / Rs2_or_imm13.sdw; }}); - 0x2E: decode RS1 { - 0x0: IntOp::popc({{ - int64_t count = 0; - uint64_t temp = Rs2_or_imm13; - //Count the 1s in the front 4bits until none are left - uint8_t oneBits[] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4}; - while(temp) - { - count += oneBits[temp & 0xF]; - temp = temp >> 4; - } - Rd = count; - }}); - } + 0x2E: Trap::popc({{fault = new IllegalInstruction;}}); 0x2F: decode RCOND3 { 0x1: movreq({{Rd = (Rs1.sdw == 0) ? Rs2_or_imm10 : Rd;}}); @@ -664,7 +731,7 @@ decode OP default Unknown::unknown() Fsr &= ~(7 << 14); Fsr &= ~(0x1F); }}); - 0x03: Trap::fmovq({{fault = new FpDisabled;}}); + 0x03: FpUnimpl::fmovq(); 0x05: fnegs({{ Frds.uw = Frs2s.uw ^ (1UL << 31); //fsr.ftt = fsr.cexc = 0 @@ -677,7 +744,7 @@ decode OP default Unknown::unknown() Fsr &= ~(7 << 14); Fsr &= ~(0x1F); }}); - 0x07: Trap::fnegq({{fault = new FpDisabled;}}); + 0x07: FpUnimpl::fnegq(); 0x09: fabss({{ Frds.uw = ((1UL << 31) - 1) & Frs2s.uw; //fsr.ftt = fsr.cexc = 0 @@ -690,106 +757,168 @@ decode OP default Unknown::unknown() Fsr &= ~(7 << 14); Fsr &= ~(0x1F); }}); - 0x0B: Trap::fabsq({{fault = new FpDisabled;}}); - 0x29: fsqrts({{Frds.sf = sqrt(Frs2s.sf);}}); - 0x2A: fsqrtd({{Frd.df = sqrt(Frs2.df);}}); - 0x2B: Trap::fsqrtq({{fault = new FpDisabled;}}); + 0x0B: FpUnimpl::fabsq(); + 0x29: fsqrts({{Frds.sf = std::sqrt(Frs2s.sf);}}); + 0x2A: fsqrtd({{Frd.df = std::sqrt(Frs2.df);}}); + 0x2B: FpUnimpl::fsqrtq(); 0x41: fadds({{Frds.sf = Frs1s.sf + Frs2s.sf;}}); 0x42: faddd({{Frd.df = Frs1.df + Frs2.df;}}); - 0x43: Trap::faddq({{fault = new FpDisabled;}}); + 0x43: FpUnimpl::faddq(); 0x45: fsubs({{Frds.sf = Frs1s.sf - Frs2s.sf;}}); 0x46: fsubd({{Frd.df = Frs1.df - Frs2.df;}}); - 0x47: Trap::fsubq({{fault = new FpDisabled;}}); + 0x47: FpUnimpl::fsubq(); 0x49: fmuls({{Frds.sf = Frs1s.sf * Frs2s.sf;}}); 0x4A: fmuld({{Frd.df = Frs1.df * Frs2.df;}}); - 0x4B: Trap::fmulq({{fault = new FpDisabled;}}); + 0x4B: FpUnimpl::fmulq(); 0x4D: fdivs({{Frds.sf = Frs1s.sf / Frs2s.sf;}}); 0x4E: fdivd({{Frd.df = Frs1.df / Frs2.df;}}); - 0x4F: Trap::fdivq({{fault = new FpDisabled;}}); + 0x4F: FpUnimpl::fdivq(); 0x69: fsmuld({{Frd.df = Frs1s.sf * Frs2s.sf;}}); - 0x6E: Trap::fdmulq({{fault = new FpDisabled;}}); + 0x6E: FpUnimpl::fdmulq(); 0x81: fstox({{ Frd.df = (double)static_cast<int64_t>(Frs2s.sf); }}); 0x82: fdtox({{ Frd.df = (double)static_cast<int64_t>(Frs2.df); }}); - 0x83: Trap::fqtox({{fault = new FpDisabled;}}); + 0x83: FpUnimpl::fqtox(); 0x84: fxtos({{ Frds.sf = static_cast<float>((int64_t)Frs2.df); }}); 0x88: fxtod({{ Frd.df = static_cast<double>((int64_t)Frs2.df); }}); - 0x8C: Trap::fxtoq({{fault = new FpDisabled;}}); + 0x8C: FpUnimpl::fxtoq(); 0xC4: fitos({{ Frds.sf = static_cast<float>((int32_t)Frs2s.sf); }}); 0xC6: fdtos({{Frds.sf = Frs2.df;}}); - 0xC7: Trap::fqtos({{fault = new FpDisabled;}}); + 0xC7: FpUnimpl::fqtos(); 0xC8: fitod({{ Frd.df = static_cast<double>((int32_t)Frs2s.sf); }}); 0xC9: fstod({{Frd.df = Frs2s.sf;}}); - 0xCB: Trap::fqtod({{fault = new FpDisabled;}}); - 0xCC: Trap::fitoq({{fault = new FpDisabled;}}); - 0xCD: Trap::fstoq({{fault = new FpDisabled;}}); - 0xCE: Trap::fdtoq({{fault = new FpDisabled;}}); + 0xCB: FpUnimpl::fqtod(); + 0xCC: FpUnimpl::fitoq(); + 0xCD: FpUnimpl::fstoq(); + 0xCE: FpUnimpl::fdtoq(); 0xD1: fstoi({{ Frds.sf = (float)static_cast<int32_t>(Frs2s.sf); }}); 0xD2: fdtoi({{ Frds.sf = (float)static_cast<int32_t>(Frs2.df); }}); - 0xD3: Trap::fqtoi({{fault = new FpDisabled;}}); - default: Trap::fpop1({{fault = new FpDisabled;}}); + 0xD3: FpUnimpl::fqtoi(); + default: FailUnimpl::fpop1(); + } + } + 0x35: decode OPF{ + format BasicOperate{ + 0x51: fcmps({{ + uint8_t fcc; + if(isnan(Frs1s) || isnan(Frs2s)) + fcc = 3; + else if(Frs1s < Frs2s) + fcc = 1; + else if(Frs1s > Frs2s) + fcc = 2; + else + fcc = 0; + uint8_t firstbit = 10; + if(FCMPCC) + firstbit = FCMPCC * 2 + 30; + Fsr = insertBits(Fsr, firstbit +1, firstbit, fcc); + }}); + 0x52: fcmpd({{ + uint8_t fcc; + if(isnan(Frs1s) || isnan(Frs2s)) + fcc = 3; + else if(Frs1s < Frs2s) + fcc = 1; + else if(Frs1s > Frs2s) + fcc = 2; + else + fcc = 0; + uint8_t firstbit = 10; + if(FCMPCC) + firstbit = FCMPCC * 2 + 30; + Fsr = insertBits(Fsr, firstbit +1, firstbit, fcc); + }}); + 0x53: FpUnimpl::fcmpq(); + 0x55: fcmpes({{ + uint8_t fcc = 0; + if(isnan(Frs1s) || isnan(Frs2s)) + fault = new FpExceptionIEEE754; + if(Frs1s < Frs2s) + fcc = 1; + else if(Frs1s > Frs2s) + fcc = 2; + uint8_t firstbit = 10; + if(FCMPCC) + firstbit = FCMPCC * 2 + 30; + Fsr = insertBits(Fsr, firstbit +1, firstbit, fcc); + }}); + 0x56: fcmped({{ + uint8_t fcc = 0; + if(isnan(Frs1s) || isnan(Frs2s)) + fault = new FpExceptionIEEE754; + if(Frs1s < Frs2s) + fcc = 1; + else if(Frs1s > Frs2s) + fcc = 2; + uint8_t firstbit = 10; + if(FCMPCC) + firstbit = FCMPCC * 2 + 30; + Fsr = insertBits(Fsr, firstbit +1, firstbit, fcc); + }}); + 0x57: FpUnimpl::fcmpeq(); + default: FailUnimpl::fpop2(); } } - 0x35: Trap::fpop2({{fault = new FpDisabled;}}); //This used to be just impdep1, but now it's a whole bunch //of instructions 0x36: decode OPF{ - 0x00: Trap::edge8({{fault = new IllegalInstruction;}}); - 0x01: Trap::edge8n({{fault = new IllegalInstruction;}}); - 0x02: Trap::edge8l({{fault = new IllegalInstruction;}}); - 0x03: Trap::edge8ln({{fault = new IllegalInstruction;}}); - 0x04: Trap::edge16({{fault = new IllegalInstruction;}}); - 0x05: Trap::edge16n({{fault = new IllegalInstruction;}}); - 0x06: Trap::edge16l({{fault = new IllegalInstruction;}}); - 0x07: Trap::edge16ln({{fault = new IllegalInstruction;}}); - 0x08: Trap::edge32({{fault = new IllegalInstruction;}}); - 0x09: Trap::edge32n({{fault = new IllegalInstruction;}}); - 0x0A: Trap::edge32l({{fault = new IllegalInstruction;}}); - 0x0B: Trap::edge32ln({{fault = new IllegalInstruction;}}); - 0x10: Trap::array8({{fault = new IllegalInstruction;}}); - 0x12: Trap::array16({{fault = new IllegalInstruction;}}); - 0x14: Trap::array32({{fault = new IllegalInstruction;}}); + 0x00: FailUnimpl::edge8(); + 0x01: FailUnimpl::edge8n(); + 0x02: FailUnimpl::edge8l(); + 0x03: FailUnimpl::edge8ln(); + 0x04: FailUnimpl::edge16(); + 0x05: FailUnimpl::edge16n(); + 0x06: FailUnimpl::edge16l(); + 0x07: FailUnimpl::edge16ln(); + 0x08: FailUnimpl::edge32(); + 0x09: FailUnimpl::edge32n(); + 0x0A: FailUnimpl::edge32l(); + 0x0B: FailUnimpl::edge32ln(); + 0x10: FailUnimpl::array8(); + 0x12: FailUnimpl::array16(); + 0x14: FailUnimpl::array32(); 0x18: BasicOperate::alignaddr({{ uint64_t sum = Rs1 + Rs2; Rd = sum & ~7; Gsr = (Gsr & ~7) | (sum & 7); }}); - 0x19: Trap::bmask({{fault = new IllegalInstruction;}}); + 0x19: FailUnimpl::bmask(); 0x1A: BasicOperate::alignaddresslittle({{ uint64_t sum = Rs1 + Rs2; Rd = sum & ~7; Gsr = (Gsr & ~7) | ((~sum + 1) & 7); }}); - 0x20: Trap::fcmple16({{fault = new IllegalInstruction;}}); - 0x22: Trap::fcmpne16({{fault = new IllegalInstruction;}}); - 0x24: Trap::fcmple32({{fault = new IllegalInstruction;}}); - 0x26: Trap::fcmpne32({{fault = new IllegalInstruction;}}); - 0x28: Trap::fcmpgt16({{fault = new IllegalInstruction;}}); - 0x2A: Trap::fcmpeq16({{fault = new IllegalInstruction;}}); - 0x2C: Trap::fcmpgt32({{fault = new IllegalInstruction;}}); - 0x2E: Trap::fcmpeq32({{fault = new IllegalInstruction;}}); - 0x31: Trap::fmul8x16({{fault = new IllegalInstruction;}}); - 0x33: Trap::fmul8x16au({{fault = new IllegalInstruction;}}); - 0x35: Trap::fmul8x16al({{fault = new IllegalInstruction;}}); - 0x36: Trap::fmul8sux16({{fault = new IllegalInstruction;}}); - 0x37: Trap::fmul8ulx16({{fault = new IllegalInstruction;}}); - 0x38: Trap::fmuld8sux16({{fault = new IllegalInstruction;}}); - 0x39: Trap::fmuld8ulx16({{fault = new IllegalInstruction;}}); + 0x20: FailUnimpl::fcmple16(); + 0x22: FailUnimpl::fcmpne16(); + 0x24: FailUnimpl::fcmple32(); + 0x26: FailUnimpl::fcmpne32(); + 0x28: FailUnimpl::fcmpgt16(); + 0x2A: FailUnimpl::fcmpeq16(); + 0x2C: FailUnimpl::fcmpgt32(); + 0x2E: FailUnimpl::fcmpeq32(); + 0x31: FailUnimpl::fmul8x16(); + 0x33: FailUnimpl::fmul8x16au(); + 0x35: FailUnimpl::fmul8x16al(); + 0x36: FailUnimpl::fmul8sux16(); + 0x37: FailUnimpl::fmul8ulx16(); + 0x38: FailUnimpl::fmuld8sux16(); + 0x39: FailUnimpl::fmuld8ulx16(); 0x3A: Trap::fpack32({{fault = new IllegalInstruction;}}); 0x3B: Trap::fpack16({{fault = new IllegalInstruction;}}); 0x3D: Trap::fpackfix({{fault = new IllegalInstruction;}}); @@ -821,58 +950,58 @@ decode OP default Unknown::unknown() } }}); 0x4B: Trap::fpmerge({{fault = new IllegalInstruction;}}); - 0x4C: Trap::bshuffle({{fault = new IllegalInstruction;}}); - 0x4D: Trap::fexpand({{fault = new IllegalInstruction;}}); - 0x50: Trap::fpadd16({{fault = new IllegalInstruction;}}); - 0x51: Trap::fpadd16s({{fault = new IllegalInstruction;}}); - 0x52: Trap::fpadd32({{fault = new IllegalInstruction;}}); - 0x53: Trap::fpadd32s({{fault = new IllegalInstruction;}}); - 0x54: Trap::fpsub16({{fault = new IllegalInstruction;}}); - 0x55: Trap::fpsub16s({{fault = new IllegalInstruction;}}); - 0x56: Trap::fpsub32({{fault = new IllegalInstruction;}}); - 0x57: Trap::fpsub32s({{fault = new IllegalInstruction;}}); + 0x4C: FailUnimpl::bshuffle(); + 0x4D: FailUnimpl::fexpand(); + 0x50: FailUnimpl::fpadd16(); + 0x51: FailUnimpl::fpadd16s(); + 0x52: FailUnimpl::fpadd32(); + 0x53: FailUnimpl::fpadd32s(); + 0x54: FailUnimpl::fpsub16(); + 0x55: FailUnimpl::fpsub16s(); + 0x56: FailUnimpl::fpsub32(); + 0x57: FailUnimpl::fpsub32s(); 0x60: BasicOperate::fzero({{Frd.df = 0;}}); 0x61: BasicOperate::fzeros({{Frds.sf = 0;}}); - 0x62: Trap::fnor({{fault = new IllegalInstruction;}}); - 0x63: Trap::fnors({{fault = new IllegalInstruction;}}); - 0x64: Trap::fandnot2({{fault = new IllegalInstruction;}}); - 0x65: Trap::fandnot2s({{fault = new IllegalInstruction;}}); + 0x62: FailUnimpl::fnor(); + 0x63: FailUnimpl::fnors(); + 0x64: FailUnimpl::fandnot2(); + 0x65: FailUnimpl::fandnot2s(); 0x66: BasicOperate::fnot2({{ Frd.df = (double)(~((uint64_t)Frs2.df)); }}); 0x67: BasicOperate::fnot2s({{ Frds.sf = (float)(~((uint32_t)Frs2s.sf)); }}); - 0x68: Trap::fandnot1({{fault = new IllegalInstruction;}}); - 0x69: Trap::fandnot1s({{fault = new IllegalInstruction;}}); + 0x68: FailUnimpl::fandnot1(); + 0x69: FailUnimpl::fandnot1s(); 0x6A: BasicOperate::fnot1({{ Frd.df = (double)(~((uint64_t)Frs1.df)); }}); 0x6B: BasicOperate::fnot1s({{ Frds.sf = (float)(~((uint32_t)Frs1s.sf)); }}); - 0x6C: Trap::fxor({{fault = new IllegalInstruction;}}); - 0x6D: Trap::fxors({{fault = new IllegalInstruction;}}); - 0x6E: Trap::fnand({{fault = new IllegalInstruction;}}); - 0x6F: Trap::fnands({{fault = new IllegalInstruction;}}); - 0x70: Trap::fand({{fault = new IllegalInstruction;}}); - 0x71: Trap::fands({{fault = new IllegalInstruction;}}); - 0x72: Trap::fxnor({{fault = new IllegalInstruction;}}); - 0x73: Trap::fxnors({{fault = new IllegalInstruction;}}); + 0x6C: FailUnimpl::fxor(); + 0x6D: FailUnimpl::fxors(); + 0x6E: FailUnimpl::fnand(); + 0x6F: FailUnimpl::fnands(); + 0x70: FailUnimpl::fand(); + 0x71: FailUnimpl::fands(); + 0x72: FailUnimpl::fxnor(); + 0x73: FailUnimpl::fxnors(); 0x74: BasicOperate::fsrc1({{Frd.udw = Frs1.udw;}}); - 0x75: BasicOperate::fsrc1s({{Frd.uw = Frs1.uw;}}); - 0x76: Trap::fornot2({{fault = new IllegalInstruction;}}); - 0x77: Trap::fornot2s({{fault = new IllegalInstruction;}}); + 0x75: BasicOperate::fsrc1s({{Frds.uw = Frs1s.uw;}}); + 0x76: FailUnimpl::fornot2(); + 0x77: FailUnimpl::fornot2s(); 0x78: BasicOperate::fsrc2({{Frd.udw = Frs2.udw;}}); - 0x79: BasicOperate::fsrc2s({{Frd.uw = Frs2.uw;}}); - 0x7A: Trap::fornot1({{fault = new IllegalInstruction;}}); - 0x7B: Trap::fornot1s({{fault = new IllegalInstruction;}}); - 0x7C: Trap::for({{fault = new IllegalInstruction;}}); - 0x7D: Trap::fors({{fault = new IllegalInstruction;}}); - 0x7E: Trap::fone({{fault = new IllegalInstruction;}}); - 0x7F: Trap::fones({{fault = new IllegalInstruction;}}); + 0x79: BasicOperate::fsrc2s({{Frds.uw = Frs2s.uw;}}); + 0x7A: FailUnimpl::fornot1(); + 0x7B: FailUnimpl::fornot1s(); + 0x7C: FailUnimpl::for(); + 0x7D: FailUnimpl::fors(); + 0x7E: BasicOperate::fone({{Frd.udw = std::numeric_limits<uint64_t>::max();}}); + 0x7F: BasicOperate::fones({{Frds.uw = std::numeric_limits<uint32_t>::max();}}); 0x80: Trap::shutdown({{fault = new IllegalInstruction;}}); - 0x81: Trap::siam({{fault = new IllegalInstruction;}}); + 0x81: FailUnimpl::siam(); } 0x37: Trap::impdep2({{fault = new IllegalInstruction;}}); 0x38: Branch::jmpl({{ @@ -889,16 +1018,11 @@ decode OP default Unknown::unknown() } }}); 0x39: Branch::return({{ - //If both MemAddressNotAligned and - //a fill trap happen, it's not clear - //which one should be returned. Addr target = Rs1 + Rs2_or_imm13; - if(target & 0x3) - fault = new MemAddressNotAligned; - else - NNPC = target; if(fault == NoFault) { + //Check for fills which are higher priority than alignment + //faults. if(Canrestore == 0) { if(Otherwin) @@ -906,18 +1030,15 @@ decode OP default Unknown::unknown() else fault = new FillNNormal(4*Wstate<2:0>); } + //Check for alignment faults + else if(target & 0x3) + fault = new MemAddressNotAligned; else { - //CWP should be set directly so that it always happens - //Also, this will allow writing to the new window and - //reading from the old one + NNPC = target; Cwp = (Cwp - 1 + NWindows) % NWindows; Cansave = Cansave + 1; Canrestore = Canrestore - 1; - //This is here to make sure the CWP is written - //no matter what. This ensures that the results - //are written in the new window as well. - xc->setMiscRegWithEffect(MISCREG_CWP, Cwp); } } }}); @@ -935,7 +1056,7 @@ decode OP default Unknown::unknown() xc->syscall(R1); #endif } - }}); + }}, IsSerializeAfter, IsNonSpeculative); 0x2: Trap::tccx({{ if(passesCondition(Ccr<7:4>, COND2)) { @@ -948,36 +1069,27 @@ decode OP default Unknown::unknown() xc->syscall(R1); #endif } - }}); + }}, IsSerializeAfter, IsNonSpeculative); } 0x3B: Nop::flush({{/*Instruction memory flush*/}}); 0x3C: save({{ - //CWP should be set directly so that it always happens - //Also, this will allow writing to the new window and - //reading from the old one if(Cansave == 0) { if(Otherwin) fault = new SpillNOther(4*Wstate<5:3>); else fault = new SpillNNormal(4*Wstate<2:0>); - //Cwp = (Cwp + 2) % NWindows; } else if(Cleanwin - Canrestore == 0) { - //Cwp = (Cwp + 1) % NWindows; fault = new CleanWindow; } else { Cwp = (Cwp + 1) % NWindows; - Rd = Rs1 + Rs2_or_imm13; + Rd_next = Rs1 + Rs2_or_imm13; Cansave = Cansave - 1; Canrestore = Canrestore + 1; - //This is here to make sure the CWP is written - //no matter what. This ensures that the results - //are written in the new window as well. - xc->setMiscRegWithEffect(MISCREG_CWP, Cwp); } }}); 0x3D: restore({{ @@ -990,17 +1102,10 @@ decode OP default Unknown::unknown() } else { - //CWP should be set directly so that it always happens - //Also, this will allow writing to the new window and - //reading from the old one Cwp = (Cwp - 1 + NWindows) % NWindows; - Rd = Rs1 + Rs2_or_imm13; + Rd_prev = Rs1 + Rs2_or_imm13; Cansave = Cansave + 1; Canrestore = Canrestore - 1; - //This is here to make sure the CWP is written - //no matter what. This ensures that the results - //are written in the new window as well. - xc->setMiscRegWithEffect(MISCREG_CWP, Cwp); } }}); 0x3E: decode FCN { @@ -1130,14 +1235,14 @@ decode OP default Unknown::unknown() {{ Mem.uw = Rd.uw; Rd.uw = uReg0;}}, {{EXT_ASI}}); format Trap { - 0x20: Load::ldf({{Frd.uw = Mem.uw;}}); + 0x20: Load::ldf({{Frds.uw = Mem.uw;}}); 0x21: decode X { 0x0: Load::ldfsr({{Fsr = Mem.uw | Fsr<63:32>;}}); 0x1: Load::ldxfsr({{Fsr = Mem.udw;}}); } 0x22: ldqf({{fault = new FpDisabled;}}); 0x23: Load::lddf({{Frd.udw = Mem.udw;}}); - 0x24: Store::stf({{Mem.uw = Frd.uw;}}); + 0x24: Store::stf({{Mem.uw = Frds.uw;}}); 0x25: decode X { 0x0: Store::stfsr({{Mem.uw = Fsr<31:0>;}}); 0x1: Store::stxfsr({{Mem.udw = Fsr;}}); @@ -1145,7 +1250,7 @@ decode OP default Unknown::unknown() 0x26: stqf({{fault = new FpDisabled;}}); 0x27: Store::stdf({{Mem.udw = Frd.udw;}}); 0x2D: Nop::prefetch({{ }}); - 0x30: LoadAlt::ldfa({{Frd.uw = Mem.uw;}}, {{EXT_ASI}}); + 0x30: LoadAlt::ldfa({{Frds.uw = Mem.uw;}}, {{EXT_ASI}}); 0x32: ldqfa({{fault = new FpDisabled;}}); format LoadAlt { 0x33: decode EXT_ASI { @@ -1228,7 +1333,7 @@ decode OP default Unknown::unknown() {{fault = new DataAccessException;}}); } } - 0x34: Store::stfa({{Mem.uw = Frd.uw;}}); + 0x34: Store::stfa({{Mem.uw = Frds.uw;}}); 0x36: stqfa({{fault = new FpDisabled;}}); format StoreAlt { 0x37: decode EXT_ASI { diff --git a/src/arch/sparc/isa/formats/basic.isa b/src/arch/sparc/isa/formats/basic.isa index a4c05387b..e8762a205 100644 --- a/src/arch/sparc/isa/formats/basic.isa +++ b/src/arch/sparc/isa/formats/basic.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2006 The Regents of The University of Michigan +// Copyright (c) 2006-2007 The Regents of The University of Michigan // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -38,6 +38,7 @@ def template BasicExecPanic {{ Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const { panic("Execute method called when it shouldn't!"); + M5_DUMMY_RETURN } }}; @@ -71,6 +72,7 @@ def template BasicExecute {{ { Fault fault = NoFault; + %(fp_enable_check)s; %(op_decl)s; %(op_rd)s; %(code)s; @@ -95,8 +97,7 @@ def template BasicDecodeWithMnemonic {{ // The most basic instruction format... used only for a few misc. insts def format BasicOperate(code, *flags) {{ - iop = InstObjParams(name, Name, 'SparcStaticInst', - CodeBlock(code), flags) + iop = InstObjParams(name, Name, 'SparcStaticInst', code, flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) diff --git a/src/arch/sparc/isa/formats/branch.isa b/src/arch/sparc/isa/formats/branch.isa index 5fb7ade2d..5cd3ab598 100644 --- a/src/arch/sparc/isa/formats/branch.isa +++ b/src/arch/sparc/isa/formats/branch.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2006 The Regents of The University of Michigan +// Copyright (c) 2006-2007 The Regents of The University of Michigan // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -170,7 +170,7 @@ output decoder {{ printMnemonic(response, mnemonic); ccprintf(response, "0x%x", target); - if(symtab->findNearestSymbol(target, symbol, symbolAddr)) + if(symtab && symtab->findNearestSymbol(target, symbol, symbolAddr)) { ccprintf(response, " <%s", symbol); if(symbolAddr != target) @@ -211,13 +211,13 @@ let {{ { if(A) { - NPC = xc->readNextNPC(); - NNPC = NPC + 4; + NNPC = NPC + 8; + NPC = NPC + 4; } else { - NPC = xc->readNextPC(); - NNPC = xc->readNextNPC(); + NPC = NPC; + NNPC = NNPC; } }''' }}; @@ -244,7 +244,6 @@ def format Branch(code, *opt_flags) {{ // Primary format for branch instructions: def format BranchN(bits, code, *opt_flags) {{ code = re.sub(r'handle_annul', handle_annul, code) - codeBlk = CodeBlock(code) new_opt_flags = [] for flag in opt_flags: if flag == ',a': @@ -252,7 +251,7 @@ def format BranchN(bits, code, *opt_flags) {{ Name += 'Annul' else: new_opt_flags += flag - iop = InstObjParams(name, Name, "BranchNBits<%d>" % bits, codeBlk, new_opt_flags) + iop = InstObjParams(name, Name, "BranchNBits<%d>" % bits, code, new_opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) exec_output = BranchExecute.subst(iop) @@ -262,8 +261,7 @@ def format BranchN(bits, code, *opt_flags) {{ // Primary format for branch instructions: def format BranchSplit(code, *opt_flags) {{ code = re.sub(r'handle_annul', handle_annul, code) - codeBlk = CodeBlock(code) - iop = InstObjParams(name, Name, 'BranchSplit', codeBlk, opt_flags) + iop = InstObjParams(name, Name, 'BranchSplit', code, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) exec_output = BranchExecute.subst(iop) diff --git a/src/arch/sparc/isa/formats/integerop.isa b/src/arch/sparc/isa/formats/integerop.isa index 4f8ebebcc..f877b8790 100644 --- a/src/arch/sparc/isa/formats/integerop.isa +++ b/src/arch/sparc/isa/formats/integerop.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2006 The Regents of The University of Michigan +// Copyright (c) 2006-2007 The Regents of The University of Michigan // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -154,7 +154,7 @@ output decoder {{ bool IntOp::printPseudoOps(std::ostream &os, Addr pc, const SymbolTable *symbab) const { - if(!strcmp(mnemonic, "or") && _srcRegIdx[0] == 0) + if(!std::strcmp(mnemonic, "or") && _srcRegIdx[0] == 0) { printMnemonic(os, "mov"); printSrcReg(os, 1); @@ -168,7 +168,7 @@ output decoder {{ bool IntOpImm::printPseudoOps(std::ostream &os, Addr pc, const SymbolTable *symbab) const { - if(!strcmp(mnemonic, "or")) + if(!std::strcmp(mnemonic, "or")) { if(_numSrcRegs > 0 && _srcRegIdx[0] == 0) { @@ -263,14 +263,15 @@ let {{ def doIntFormat(code, ccCode, name, Name, opt_flags): (usesImm, code, immCode, rString, iString) = splitOutImm(code) - iop = InstObjParams(name, Name, 'IntOp', code, - opt_flags, {"cc_code": ccCode}) + iop = InstObjParams(name, Name, 'IntOp', + {"code": code, "cc_code": ccCode}, + opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) exec_output = IntOpExecute.subst(iop) if usesImm: imm_iop = InstObjParams(name, Name + 'Imm', 'IntOpImm' + iString, - immCode, opt_flags, {"cc_code": ccCode}) + {"code": immCode, "cc_code": ccCode}, opt_flags) header_output += BasicDeclare.subst(imm_iop) decoder_output += BasicConstructor.subst(imm_iop) exec_output += IntOpExecute.subst(imm_iop) @@ -341,7 +342,7 @@ def format IntOpCcRes(code, *opt_flags) {{ def format SetHi(code, *opt_flags) {{ iop = InstObjParams(name, Name, 'SetHi', - code, opt_flags, {"cc_code": ''}) + {"code": code, "cc_code": ''}, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) exec_output = IntOpExecute.subst(iop) diff --git a/src/arch/sparc/isa/formats/mem/basicmem.isa b/src/arch/sparc/isa/formats/mem/basicmem.isa index 55e9fba45..1d9075a57 100644 --- a/src/arch/sparc/isa/formats/mem/basicmem.isa +++ b/src/arch/sparc/isa/formats/mem/basicmem.isa @@ -55,16 +55,20 @@ let {{ def doMemFormat(code, execute, faultCode, name, Name, asi, opt_flags): addrCalcReg = 'EA = Rs1 + Rs2;' addrCalcImm = 'EA = Rs1 + imm;' - iop = InstObjParams(name, Name, 'Mem', code, - opt_flags, {"fault_check": faultCode, "ea_code": addrCalcReg}) - iop_imm = InstObjParams(name, Name + "Imm", 'MemImm', code, - opt_flags, {"fault_check": faultCode, "ea_code": addrCalcImm}) + iop = InstObjParams(name, Name, 'Mem', + {"code": code, "fault_check": faultCode, + "ea_code": addrCalcReg}, + opt_flags) + iop_imm = InstObjParams(name, Name + "Imm", 'MemImm', + {"code": code, "fault_check": faultCode, + "ea_code": addrCalcImm}, + opt_flags) header_output = MemDeclare.subst(iop) + MemDeclare.subst(iop_imm) decoder_output = BasicConstructor.subst(iop) + BasicConstructor.subst(iop_imm) decode_block = ROrImmDecode.subst(iop) exec_output = doDualSplitExecute(code, addrCalcReg, addrCalcImm, - execute, faultCode, name, name + "Imm", Name, Name + "Imm", - asi, opt_flags) + execute, faultCode, name, name + "Imm", + Name, Name + "Imm", asi, opt_flags) return (header_output, decoder_output, exec_output, decode_block) }}; @@ -72,7 +76,7 @@ def format LoadAlt(code, asi, *opt_flags) {{ (header_output, decoder_output, exec_output, - decode_block) = doMemFormat(code, LoadExecute, + decode_block) = doMemFormat(code, LoadFuncs, AlternateASIPrivFaultCheck, name, Name, asi, opt_flags) }}; @@ -80,7 +84,7 @@ def format StoreAlt(code, asi, *opt_flags) {{ (header_output, decoder_output, exec_output, - decode_block) = doMemFormat(code, StoreExecute, + decode_block) = doMemFormat(code, StoreFuncs, AlternateASIPrivFaultCheck, name, Name, asi, opt_flags) }}; @@ -89,7 +93,7 @@ def format Load(code, *opt_flags) {{ decoder_output, exec_output, decode_block) = doMemFormat(code, - LoadExecute, '', name, Name, 0, opt_flags) + LoadFuncs, '', name, Name, 0, opt_flags) }}; def format Store(code, *opt_flags) {{ @@ -97,5 +101,5 @@ def format Store(code, *opt_flags) {{ decoder_output, exec_output, decode_block) = doMemFormat(code, - StoreExecute, '', name, Name, 0, opt_flags) + StoreFuncs, '', name, Name, 0, opt_flags) }}; diff --git a/src/arch/sparc/isa/formats/mem/blockmem.isa b/src/arch/sparc/isa/formats/mem/blockmem.isa index c36fede2e..9795d2342 100644 --- a/src/arch/sparc/isa/formats/mem/blockmem.isa +++ b/src/arch/sparc/isa/formats/mem/blockmem.isa @@ -456,14 +456,14 @@ let {{ else: flag_code = "flags[IsDelayedCommit] = true;" pcedCode = matcher.sub("Frd_%d" % microPc, code) - iop = InstObjParams(name, Name, 'BlockMem', pcedCode, - opt_flags, {"ea_code": addrCalcReg, + iop = InstObjParams(name, Name, 'BlockMem', + {"code": pcedCode, "ea_code": addrCalcReg, "fault_check": faultCode, "micro_pc": microPc, - "set_flags": flag_code}) - iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', pcedCode, - opt_flags, {"ea_code": addrCalcImm, + "set_flags": flag_code}, opt_flags) + iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', + {"code": pcedCode, "ea_code": addrCalcImm, "fault_check": faultCode, "micro_pc": microPc, - "set_flags": flag_code}) + "set_flags": flag_code}, opt_flags) decoder_output += BlockMemMicroConstructor.subst(iop) decoder_output += BlockMemMicroConstructor.subst(iop_imm) exec_output += doDualSplitExecute( @@ -496,18 +496,18 @@ let {{ else: flag_code = "flags[IsDelayedCommit] = true; flags[IsFirstMicroOp] = true;" pcedCode = matcher.sub("uReg0", code) - iop = InstObjParams(name, Name, 'TwinMem', pcedCode, - opt_flags, {"ea_code": addrCalcReg, + iop = InstObjParams(name, Name, 'TwinMem', + {"code": pcedCode, "ea_code": addrCalcReg, "fault_check": faultCode, "micro_pc": microPc, - "set_flags": flag_code}) - iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm', pcedCode, - opt_flags, {"ea_code": addrCalcImm, + "set_flags": flag_code}, opt_flags) + iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm', + {"code": pcedCode, "ea_code": addrCalcImm, "fault_check": faultCode, "micro_pc": microPc, - "set_flags": flag_code}) + "set_flags": flag_code}, opt_flags) decoder_output += BlockMemMicroConstructor.subst(iop) decoder_output += BlockMemMicroConstructor.subst(iop_imm) exec_output += doDualSplitExecute( - pcedCode, addrCalcReg, addrCalcImm, LoadExecute, faultCode, + pcedCode, addrCalcReg, addrCalcImm, LoadFuncs, faultCode, makeMicroName(name, microPc), makeMicroName(name + "Imm", microPc), makeMicroName(Name, microPc), @@ -527,7 +527,7 @@ def format BlockLoad(code, asi, *opt_flags) {{ decoder_output, exec_output, decode_block) = doBlockMemFormat(code, faultCode, - LoadExecute, name, Name, asi, opt_flags) + LoadFuncs, name, Name, asi, opt_flags) }}; def format BlockStore(code, asi, *opt_flags) {{ @@ -539,7 +539,7 @@ def format BlockStore(code, asi, *opt_flags) {{ decoder_output, exec_output, decode_block) = doBlockMemFormat(code, faultCode, - StoreExecute, name, Name, asi, opt_flags) + StoreFuncs, name, Name, asi, opt_flags) }}; def format TwinLoad(code, asi, *opt_flags) {{ diff --git a/src/arch/sparc/isa/formats/mem/util.isa b/src/arch/sparc/isa/formats/mem/util.isa index b6e0945b7..dbaabdca4 100644 --- a/src/arch/sparc/isa/formats/mem/util.isa +++ b/src/arch/sparc/isa/formats/mem/util.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2006 The Regents of The University of Michigan +// Copyright (c) 2006-2007 The Regents of The University of Michigan // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -141,10 +141,11 @@ def template LoadExecute {{ { Fault fault = NoFault; Addr EA; + %(fp_enable_check)s; %(op_decl)s; %(op_rd)s; %(ea_code)s; - DPRINTF(Sparc, "The address is 0x%x\n", EA); + DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA); %(fault_check)s; if(fault == NoFault) { @@ -162,16 +163,19 @@ def template LoadExecute {{ return fault; } +}}; +def template LoadInitiateAcc {{ Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const { Fault fault = NoFault; Addr EA; - uint%(mem_acc_size)s_t Mem; - %(ea_decl)s; - %(ea_rd)s; + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; %(ea_code)s; + DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA); %(fault_check)s; if(fault == NoFault) { @@ -179,18 +183,20 @@ def template LoadExecute {{ } return fault; } +}}; +def template LoadCompleteAcc {{ Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const { Fault fault = NoFault; - %(code_decl)s; - %(code_rd)s; + %(op_decl)s; + %(op_rd)s; Mem = pkt->get<typeof(Mem)>(); %(code)s; if(fault == NoFault) { - %(code_wb)s; + %(op_wb)s; } return fault; } @@ -206,10 +212,11 @@ def template StoreExecute {{ //It should be optomized out in all the others bool storeCond = true; Addr EA; + %(fp_enable_check)s; %(op_decl)s; %(op_rd)s; %(ea_code)s; - DPRINTF(Sparc, "The address is 0x%x\n", EA); + DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA); %(fault_check)s; if(fault == NoFault) { @@ -228,17 +235,20 @@ def template StoreExecute {{ return fault; } +}}; +def template StoreInitiateAcc {{ Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const { Fault fault = NoFault; bool storeCond = true; Addr EA; + %(fp_enable_check)s; %(op_decl)s; %(op_rd)s; %(ea_code)s; - DPRINTF(Sparc, "The address is 0x%x\n", EA); + DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA); %(fault_check)s; if(fault == NoFault) { @@ -256,7 +266,9 @@ def template StoreExecute {{ } return fault; } +}}; +def template StoreCompleteAcc {{ Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const { @@ -276,6 +288,8 @@ def template CompleteAccDeclare {{ //Here are some code snippets which check for various fault conditions let {{ + LoadFuncs = [LoadExecute, LoadInitiateAcc, LoadCompleteAcc] + StoreFuncs = [StoreExecute, StoreInitiateAcc, StoreCompleteAcc] # The LSB can be zero, since it's really the MSB in doubles and quads # and we're dealing with doubles BlockAlignmentFaultCheck = ''' @@ -316,21 +330,11 @@ let {{ //and in the other they're distributed across two. Also note that for //execute functions, the name of the base class doesn't matter. let {{ - def doSplitExecute(code, execute, name, Name, asi, opt_flags, microParam): + def doSplitExecute(execute, name, Name, asi, opt_flags, microParam): microParam["asi_val"] = asi; - codeParam = microParam.copy() - codeParam["ea_code"] = '' - codeIop = InstObjParams(name, Name, '', code, opt_flags, codeParam) - eaIop = InstObjParams(name, Name, '', microParam["ea_code"], - opt_flags, microParam) - iop = InstObjParams(name, Name, '', code, opt_flags, microParam) - (iop.ea_decl, - iop.ea_rd, - iop.ea_wb) = (eaIop.op_decl, eaIop.op_rd, eaIop.op_wb) - (iop.code_decl, - iop.code_rd, - iop.code_wb) = (codeIop.op_decl, codeIop.op_rd, codeIop.op_wb) - return execute.subst(iop) + iop = InstObjParams(name, Name, '', microParam, opt_flags) + (execf, initf, compf) = execute + return execf.subst(iop) + initf.subst(iop) + compf.subst(iop) def doDualSplitExecute(code, eaRegCode, eaImmCode, execute, @@ -339,8 +343,9 @@ let {{ for (eaCode, name, Name) in ( (eaRegCode, nameReg, NameReg), (eaImmCode, nameImm, NameImm)): - microParams = {"ea_code" : eaCode, "fault_check": faultCode} - executeCode += doSplitExecute(code, execute, name, Name, + microParams = {"code": code, "ea_code": eaCode, + "fault_check": faultCode} + executeCode += doSplitExecute(execute, name, Name, asi, opt_flags, microParams) return executeCode }}; diff --git a/src/arch/sparc/isa/formats/nop.isa b/src/arch/sparc/isa/formats/nop.isa index 37ef2e8d0..de2ba2f54 100644 --- a/src/arch/sparc/isa/formats/nop.isa +++ b/src/arch/sparc/isa/formats/nop.isa @@ -88,9 +88,7 @@ def template NopExecute {{ // Primary format for integer operate instructions: def format Nop(code, *opt_flags) {{ - orig_code = code - cblk = CodeBlock(code) - iop = InstObjParams(name, Name, 'Nop', cblk, opt_flags) + iop = InstObjParams(name, Name, 'Nop', code, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) diff --git a/src/arch/sparc/isa/formats/priv.isa b/src/arch/sparc/isa/formats/priv.isa index 3d47ca02f..36403afb4 100644 --- a/src/arch/sparc/isa/formats/priv.isa +++ b/src/arch/sparc/isa/formats/priv.isa @@ -235,8 +235,9 @@ let {{ name = mnem regBase = 'WrPriv' break - iop = InstObjParams(name, Name, regBase, code, - opt_flags, {"check": checkCode, "reg_name": regName}) + iop = InstObjParams(name, Name, regBase, + {"code": code, "check": checkCode, "reg_name": regName}, + opt_flags) header_output = BasicDeclare.subst(iop) if regName == '': decoder_output = BasicConstructor.subst(iop) @@ -245,7 +246,8 @@ let {{ exec_output = PrivExecute.subst(iop) if usesImm: imm_iop = InstObjParams(name, Name + 'Imm', regBase + 'Imm', - immCode, opt_flags, {"check": checkCode, "reg_name": regName}) + {"code": immCode, "check": checkCode, "reg_name": regName}, + opt_flags) header_output += BasicDeclare.subst(imm_iop) if regName == '': decoder_output += BasicConstructor.subst(imm_iop) diff --git a/src/arch/sparc/isa/formats/trap.isa b/src/arch/sparc/isa/formats/trap.isa index 04d467cfe..66eff35d4 100644 --- a/src/arch/sparc/isa/formats/trap.isa +++ b/src/arch/sparc/isa/formats/trap.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2006 The Regents of The University of Michigan +// Copyright (c) 2006-2007 The Regents of The University of Michigan // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -82,12 +82,53 @@ def template TrapExecute {{ } }}; +def template FpUnimplExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + %(op_decl)s; + %(op_rd)s; + %(code)s + %(op_wb)s; + return fault; + } +}}; + def format Trap(code, *opt_flags) {{ - orig_code = code - cblk = CodeBlock(code) - iop = InstObjParams(name, Name, 'Trap', cblk, opt_flags) + iop = InstObjParams(name, Name, 'Trap', code, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) exec_output = TrapExecute.subst(iop) }}; + +output header {{ + class FpUnimpl : public SparcStaticInst + { + protected: + FpUnimpl(const char *mnem, + ExtMachInst _machInst, OpClass __opClass) + : SparcStaticInst(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + return mnemonic; + } + }; +}}; + +def format FpUnimpl(*flags) {{ + fpunimpl_code = ''' + Fsr = insertBits(Fsr, 16, 14, 3); + fault = new FpExceptionOther; + ''' + iop = InstObjParams(name, Name, 'FpUnimpl', fpunimpl_code, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = FpUnimplExecute.subst(iop) +}}; diff --git a/src/arch/sparc/isa/includes.isa b/src/arch/sparc/isa/includes.isa index 0c112d481..a6dca9bf1 100644 --- a/src/arch/sparc/isa/includes.isa +++ b/src/arch/sparc/isa/includes.isa @@ -34,15 +34,17 @@ // output header {{ +#include <cstring> #include <sstream> #include <iostream> -#include "cpu/static_inst.hh" #include "arch/sparc/faults.hh" -#include "mem/request.hh" // some constructors use MemReq flags -#include "mem/packet.hh" #include "arch/sparc/isa_traits.hh" #include "arch/sparc/regfile.hh" +#include "base/misc.hh" +#include "cpu/static_inst.hh" +#include "mem/packet.hh" +#include "mem/request.hh" // some constructors use MemReq flags }}; output decoder {{ @@ -65,6 +67,7 @@ output exec {{ #endif #include <limits> +#include <cmath> #include "arch/sparc/asi.hh" #include "cpu/base.hh" #include "cpu/exetrace.hh" @@ -73,5 +76,6 @@ output exec {{ #include "mem/packet_access.hh" using namespace SparcISA; +using namespace std; }}; diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa index abb82f88c..140055010 100644 --- a/src/arch/sparc/isa/operands.isa +++ b/src/arch/sparc/isa/operands.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2006 The Regents of The University of Michigan +// Copyright (c) 2006-2007 The Regents of The University of Michigan // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -56,15 +56,26 @@ def operands {{ # Int regs default to unsigned, but code should not count on this. # For clarity, descriptions that depend on unsigned behavior should # explicitly specify '.uq'. + 'Rd': ('IntReg', 'udw', 'RD', 'IsInteger', 1), + # The Rd from the previous window + 'Rd_prev': ('IntReg', 'udw', 'RD + NumIntArchRegs + NumMicroIntRegs', 'IsInteger', 2), + # The Rd from the next window + 'Rd_next': ('IntReg', 'udw', 'RD + 2 * NumIntArchRegs + NumMicroIntRegs', 'IsInteger', 3), # For microcoded twin load instructions, RdTwin appears in the "code" - # for the instruction and is replaced by RdLow or RdHigh by the format + # for the instruction is replaced by RdLow or RdHigh by the format # before it's processed by the iop. - 'RdLow': ('IntReg', 'udw', 'RD & (~1)', 'IsInteger', 2), - 'RdHigh': ('IntReg', 'udw', 'RD | 1', 'IsInteger', 3), - 'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 4), - 'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 5), - 'uReg0': ('IntReg', 'udw', 'NumIntArchRegs', 'IsInteger', 6), + # The low (even) register of a two register pair + 'RdLow': ('IntReg', 'udw', 'RD & (~1)', 'IsInteger', 4), + # The high (odd) register of a two register pair + 'RdHigh': ('IntReg', 'udw', 'RD | 1', 'IsInteger', 5), + 'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 6), + 'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 7), + # A microcode register. Right now, this is the only one. + 'uReg0': ('IntReg', 'udw', 'NumIntArchRegs', 'IsInteger', 8), + # Because double and quad precision register numbers are decoded + # differently, they get different operands. The single precision versions + # have an s post pended to their name. 'Frds': ('FloatReg', 'sf', 'RD', 'IsFloating', 10), 'Frd': ('FloatReg', 'df', 'dfpr(RD)', 'IsFloating', 10), # Each Frd_N refers to the Nth double precision register from Frd. @@ -77,20 +88,23 @@ def operands {{ 'Frd_5': ('FloatReg', 'df', 'dfpr(RD) + 10', 'IsFloating', 10), 'Frd_6': ('FloatReg', 'df', 'dfpr(RD) + 12', 'IsFloating', 10), 'Frd_7': ('FloatReg', 'df', 'dfpr(RD) + 14', 'IsFloating', 10), - 'Frs1s': ('FloatReg', 'df', 'RS1', 'IsFloating', 11), + 'Frs1s': ('FloatReg', 'sf', 'RS1', 'IsFloating', 11), 'Frs1': ('FloatReg', 'df', 'dfpr(RS1)', 'IsFloating', 11), - 'Frs2s': ('FloatReg', 'df', 'RS2', 'IsFloating', 12), + 'Frs2s': ('FloatReg', 'sf', 'RS2', 'IsFloating', 12), 'Frs2': ('FloatReg', 'df', 'dfpr(RS2)', 'IsFloating', 12), 'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 31), 'NNPC': ('NNPC', 'udw', None, (None, None, 'IsControl' ), 32), + # Registers which are used explicitly in instructions 'R0': ('IntReg', 'udw', '0', None, 6), 'R1': ('IntReg', 'udw', '1', None, 7), 'R15': ('IntReg', 'udw', '15', 'IsInteger', 8), 'R16': ('IntReg', 'udw', '16', None, 9), # Control registers - 'Y': ('ControlReg', 'udw', 'MISCREG_Y', None, 40), - 'Ccr': ('ControlReg', 'udw', 'MISCREG_CCR', None, 41), +# 'Y': ('ControlReg', 'udw', 'MISCREG_Y', None, 40), +# 'Ccr': ('ControlReg', 'udw', 'MISCREG_CCR', None, 41), + 'Y': ('IntReg', 'udw', 'NumIntArchRegs + 1', None, 40), + 'Ccr': ('IntReg', 'udw', 'NumIntArchRegs + 2', None, 41), 'Asi': ('ControlReg', 'udw', 'MISCREG_ASI', None, 42), 'Fprs': ('ControlReg', 'udw', 'MISCREG_FPRS', None, 43), 'Pcr': ('ControlReg', 'udw', 'MISCREG_PCR', None, 44), @@ -112,12 +126,17 @@ def operands {{ 'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 59), 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 60), 'Pil': ('ControlReg', 'udw', 'MISCREG_PIL', None, 61), - 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 62), - 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 63), - 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 64), - 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 65), - 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 66), - 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 67), + 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 62), +# 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 63), +# 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 64), +# 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 65), +# 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 66), +# 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 67), + 'Cansave': ('IntReg', 'udw', 'NumIntArchRegs + 3', None, 63), + 'Canrestore': ('IntReg', 'udw', 'NumIntArchRegs + 4', None, 64), + 'Cleanwin': ('IntReg', 'udw', 'NumIntArchRegs + 5', None, 65), + 'Otherwin': ('IntReg', 'udw', 'NumIntArchRegs + 6', None, 66), + 'Wstate': ('IntReg', 'udw', 'NumIntArchRegs + 7', None, 67), 'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 68), 'Hpstate': ('ControlReg', 'udw', 'MISCREG_HPSTATE', None, 69), diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh index 8aa8ea7f3..64ae6abd8 100644 --- a/src/arch/sparc/isa_traits.hh +++ b/src/arch/sparc/isa_traits.hh @@ -58,8 +58,8 @@ namespace SparcISA // These enumerate all the registers for dependence tracking. enum DependenceTags { - FP_Base_DepTag = 33, - Ctrl_Base_DepTag = 97, + FP_Base_DepTag = 32*3+8, + Ctrl_Base_DepTag = FP_Base_DepTag + 64 }; // semantically meaningful register indices diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc index d9fcb0280..0fe3e96b2 100644 --- a/src/arch/sparc/miscregfile.cc +++ b/src/arch/sparc/miscregfile.cc @@ -46,15 +46,16 @@ class Checkpoint; string SparcISA::getMiscRegName(RegIndex index) { static::string miscRegName[NumMiscRegs] = - {"y", "ccr", "asi", "tick", "fprs", "pcr", "pic", - "gsr", "softint_set", "softint_clr", "softint", "tick_cmpr", - "stick", "stick_cmpr", - "tpc", "tnpc", "tstate", "tt", "privtick", "tba", "pstate", "tl", - "pil", "cwp", "cansave", "canrestore", "cleanwin", "otherwin", - "wstate", "gl", - "hpstate", "htstate", "hintp", "htba", "hver", "strand_sts_reg", - "hstick_cmpr", - "fsr"}; + {/*"y", "ccr",*/ "asi", "tick", "fprs", "pcr", "pic", + "gsr", "softint_set", "softint_clr", "softint", "tick_cmpr", + "stick", "stick_cmpr", + "tpc", "tnpc", "tstate", "tt", "privtick", "tba", "pstate", "tl", + "pil", "cwp", /*"cansave", "canrestore", "cleanwin", "otherwin", + "wstate",*/ "gl", + "hpstate", "htstate", "hintp", "htba", "hver", "strand_sts_reg", + "hstick_cmpr", + "fsr"}; + return miscRegName[index]; } @@ -65,8 +66,8 @@ enum RegMask void MiscRegFile::clear() { - y = 0; - ccr = 0; + //y = 0; + //ccr = 0; asi = 0; tick = ULL(1) << 63; fprs = 0; @@ -83,11 +84,11 @@ void MiscRegFile::clear() tl = 0; pil = 0; cwp = 0; - cansave = 0; - canrestore = 0; - cleanwin = 0; - otherwin = 0; - wstate = 0; + //cansave = 0; + //canrestore = 0; + //cleanwin = 0; + //otherwin = 0; + //wstate = 0; gl = 0; //In a T1, bit 11 is apparently always 1 hpstate = (1 << 11); @@ -124,6 +125,11 @@ void MiscRegFile::clear() dTlbTagAccess = 0; memset(scratchPad, 0, sizeof(scratchPad)); +#if FULL_SYSTEM + tickCompare = NULL; + sTickCompare = NULL; + hSTickCompare = NULL; +#endif } MiscReg MiscRegFile::readReg(int miscReg) @@ -149,10 +155,10 @@ MiscReg MiscRegFile::readReg(int miscReg) (uint64_t)priContext << 32 | (uint64_t)secContext << 48; - case MISCREG_Y: - return y; - case MISCREG_CCR: - return ccr; + //case MISCREG_Y: + // return y; + //case MISCREG_CCR: + // return ccr; case MISCREG_ASI: return asi; case MISCREG_FPRS: @@ -195,16 +201,16 @@ MiscReg MiscRegFile::readReg(int miscReg) return pil; case MISCREG_CWP: return cwp; - case MISCREG_CANSAVE: - return cansave; - case MISCREG_CANRESTORE: - return canrestore; - case MISCREG_CLEANWIN: - return cleanwin; - case MISCREG_OTHERWIN: - return otherwin; - case MISCREG_WSTATE: - return wstate; + //case MISCREG_CANSAVE: + // return cansave; + //case MISCREG_CANRESTORE: + // return canrestore; + //case MISCREG_CLEANWIN: + // return cleanwin; + //case MISCREG_OTHERWIN: + // return otherwin; + //case MISCREG_WSTATE: + // return wstate; case MISCREG_GL: return gl; @@ -375,12 +381,12 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc) void MiscRegFile::setReg(int miscReg, const MiscReg &val) { switch (miscReg) { - case MISCREG_Y: - y = val; - break; - case MISCREG_CCR: - ccr = val; - break; +// case MISCREG_Y: +// y = val; +// break; +// case MISCREG_CCR: +// ccr = val; +// break; case MISCREG_ASI: asi = val; break; @@ -441,21 +447,21 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val) case MISCREG_CWP: cwp = val; break; - case MISCREG_CANSAVE: - cansave = val; - break; - case MISCREG_CANRESTORE: - canrestore = val; - break; - case MISCREG_CLEANWIN: - cleanwin = val; - break; - case MISCREG_OTHERWIN: - otherwin = val; - break; - case MISCREG_WSTATE: - wstate = val; - break; +// case MISCREG_CANSAVE: +// cansave = val; +// break; +// case MISCREG_CANRESTORE: +// canrestore = val; +// break; +// case MISCREG_CLEANWIN: +// cleanwin = val; +// break; +// case MISCREG_OTHERWIN: +// otherwin = val; +// break; +// case MISCREG_WSTATE: +// wstate = val; +// break; case MISCREG_GL: gl = val; break; @@ -674,32 +680,31 @@ void MiscRegFile::setRegWithEffect(int miscReg, void MiscRegFile::serialize(std::ostream & os) { - SERIALIZE_SCALAR(pstate); - SERIALIZE_SCALAR(tba); - SERIALIZE_SCALAR(y); - SERIALIZE_SCALAR(pil); - SERIALIZE_SCALAR(gl); - SERIALIZE_SCALAR(cwp); - SERIALIZE_ARRAY(tt, MaxTL); - SERIALIZE_SCALAR(ccr); SERIALIZE_SCALAR(asi); - SERIALIZE_SCALAR(tl); - SERIALIZE_ARRAY(tpc, MaxTL); - SERIALIZE_ARRAY(tnpc, MaxTL); - SERIALIZE_ARRAY(tstate, MaxTL); SERIALIZE_SCALAR(tick); - SERIALIZE_SCALAR(cansave); - SERIALIZE_SCALAR(canrestore); - SERIALIZE_SCALAR(otherwin); - SERIALIZE_SCALAR(cleanwin); - SERIALIZE_SCALAR(wstate); - SERIALIZE_SCALAR(fsr); SERIALIZE_SCALAR(fprs); + SERIALIZE_SCALAR(gsr); + SERIALIZE_SCALAR(softint); + SERIALIZE_SCALAR(tick_cmpr); + SERIALIZE_SCALAR(stick); + SERIALIZE_SCALAR(stick_cmpr); + SERIALIZE_ARRAY(tpc,MaxTL); + SERIALIZE_ARRAY(tnpc,MaxTL); + SERIALIZE_ARRAY(tstate,MaxTL); + SERIALIZE_ARRAY(tt,MaxTL); + SERIALIZE_SCALAR(tba); + SERIALIZE_SCALAR(pstate); + SERIALIZE_SCALAR(tl); + SERIALIZE_SCALAR(pil); + SERIALIZE_SCALAR(cwp); + SERIALIZE_SCALAR(gl); SERIALIZE_SCALAR(hpstate); - SERIALIZE_ARRAY(htstate, MaxTL); + SERIALIZE_ARRAY(htstate,MaxTL); + SERIALIZE_SCALAR(hintp); SERIALIZE_SCALAR(htba); SERIALIZE_SCALAR(hstick_cmpr); SERIALIZE_SCALAR(strandStatusReg); + SERIALIZE_SCALAR(fsr); SERIALIZE_SCALAR(priContext); SERIALIZE_SCALAR(secContext); SERIALIZE_SCALAR(partId); @@ -717,6 +722,7 @@ void MiscRegFile::serialize(std::ostream & os) SERIALIZE_SCALAR(dTlbC0Config); SERIALIZE_SCALAR(dTlbCXTsbPs0); SERIALIZE_SCALAR(dTlbCXTsbPs1); + SERIALIZE_SCALAR(dTlbCXConfig); SERIALIZE_SCALAR(dTlbSfsr); SERIALIZE_SCALAR(dTlbSfar); SERIALIZE_SCALAR(dTlbTagAccess); @@ -729,36 +735,70 @@ void MiscRegFile::serialize(std::ostream & os) SERIALIZE_SCALAR(res_error_tail); SERIALIZE_SCALAR(nres_error_head); SERIALIZE_SCALAR(nres_error_tail); +#if FULL_SYSTEM + Tick tick_cmp = 0, stick_cmp = 0, hstick_cmp = 0; + ThreadContext *tc = NULL; + BaseCPU *cpu = NULL; + int tc_num = 0; + bool tick_intr_sched = true; + + if (tickCompare) + tc = tickCompare->getTC(); + else if (sTickCompare) + tc = sTickCompare->getTC(); + else if (hSTickCompare) + tc = hSTickCompare->getTC(); + else + tick_intr_sched = false; + + SERIALIZE_SCALAR(tick_intr_sched); + + if (tc) { + cpu = tc->getCpuPtr(); + tc_num = cpu->findContext(tc); + if (tickCompare && tickCompare->scheduled()) + tick_cmp = tickCompare->when(); + if (sTickCompare && sTickCompare->scheduled()) + stick_cmp = sTickCompare->when(); + if (hSTickCompare && hSTickCompare->scheduled()) + hstick_cmp = hSTickCompare->when(); + + SERIALIZE_OBJPTR(cpu); + SERIALIZE_SCALAR(tc_num); + SERIALIZE_SCALAR(tick_cmp); + SERIALIZE_SCALAR(stick_cmp); + SERIALIZE_SCALAR(hstick_cmp); + } +#endif } void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section) { - UNSERIALIZE_SCALAR(pstate); - UNSERIALIZE_SCALAR(tba); - UNSERIALIZE_SCALAR(y); - UNSERIALIZE_SCALAR(pil); - UNSERIALIZE_SCALAR(gl); - UNSERIALIZE_SCALAR(cwp); - UNSERIALIZE_ARRAY(tt, MaxTL); - UNSERIALIZE_SCALAR(ccr); UNSERIALIZE_SCALAR(asi); - UNSERIALIZE_SCALAR(tl); - UNSERIALIZE_ARRAY(tpc, MaxTL); - UNSERIALIZE_ARRAY(tnpc, MaxTL); - UNSERIALIZE_ARRAY(tstate, MaxTL); UNSERIALIZE_SCALAR(tick); - UNSERIALIZE_SCALAR(cansave); - UNSERIALIZE_SCALAR(canrestore); - UNSERIALIZE_SCALAR(otherwin); - UNSERIALIZE_SCALAR(cleanwin); - UNSERIALIZE_SCALAR(wstate); - UNSERIALIZE_SCALAR(fsr); UNSERIALIZE_SCALAR(fprs); + UNSERIALIZE_SCALAR(gsr); + UNSERIALIZE_SCALAR(softint); + UNSERIALIZE_SCALAR(tick_cmpr); + UNSERIALIZE_SCALAR(stick); + UNSERIALIZE_SCALAR(stick_cmpr); + UNSERIALIZE_ARRAY(tpc,MaxTL); + UNSERIALIZE_ARRAY(tnpc,MaxTL); + UNSERIALIZE_ARRAY(tstate,MaxTL); + UNSERIALIZE_ARRAY(tt,MaxTL); + UNSERIALIZE_SCALAR(tba); + UNSERIALIZE_SCALAR(pstate); + UNSERIALIZE_SCALAR(tl); + UNSERIALIZE_SCALAR(pil); + UNSERIALIZE_SCALAR(cwp); + UNSERIALIZE_SCALAR(gl); UNSERIALIZE_SCALAR(hpstate); - UNSERIALIZE_ARRAY(htstate, MaxTL); + UNSERIALIZE_ARRAY(htstate,MaxTL); + UNSERIALIZE_SCALAR(hintp); UNSERIALIZE_SCALAR(htba); UNSERIALIZE_SCALAR(hstick_cmpr); UNSERIALIZE_SCALAR(strandStatusReg); + UNSERIALIZE_SCALAR(fsr); UNSERIALIZE_SCALAR(priContext); UNSERIALIZE_SCALAR(secContext); UNSERIALIZE_SCALAR(partId); @@ -776,6 +816,7 @@ void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section) UNSERIALIZE_SCALAR(dTlbC0Config); UNSERIALIZE_SCALAR(dTlbCXTsbPs0); UNSERIALIZE_SCALAR(dTlbCXTsbPs1); + UNSERIALIZE_SCALAR(dTlbCXConfig); UNSERIALIZE_SCALAR(dTlbSfsr); UNSERIALIZE_SCALAR(dTlbSfar); UNSERIALIZE_SCALAR(dTlbTagAccess); @@ -787,4 +828,38 @@ void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section) UNSERIALIZE_SCALAR(res_error_head); UNSERIALIZE_SCALAR(res_error_tail); UNSERIALIZE_SCALAR(nres_error_head); - UNSERIALIZE_SCALAR(nres_error_tail);} + UNSERIALIZE_SCALAR(nres_error_tail); + +#if FULL_SYSTEM + Tick tick_cmp = 0, stick_cmp = 0, hstick_cmp = 0; + ThreadContext *tc = NULL; + BaseCPU *cpu = NULL; + int tc_num; + bool tick_intr_sched; + UNSERIALIZE_SCALAR(tick_intr_sched); + if (tick_intr_sched) { + UNSERIALIZE_OBJPTR(cpu); + if (cpu) { + UNSERIALIZE_SCALAR(tc_num); + UNSERIALIZE_SCALAR(tick_cmp); + UNSERIALIZE_SCALAR(stick_cmp); + UNSERIALIZE_SCALAR(hstick_cmp); + tc = cpu->getContext(tc_num); + + if (tick_cmp) { + tickCompare = new TickCompareEvent(this, tc); + tickCompare->schedule(tick_cmp); + } + if (stick_cmp) { + sTickCompare = new STickCompareEvent(this, tc); + sTickCompare->schedule(stick_cmp); + } + if (hstick_cmp) { + hSTickCompare = new HSTickCompareEvent(this, tc); + hSTickCompare->schedule(hstick_cmp); + } + } + } + + #endif +} diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh index 8a2e8e810..66c9f17df 100644 --- a/src/arch/sparc/miscregfile.hh +++ b/src/arch/sparc/miscregfile.hh @@ -47,8 +47,8 @@ namespace SparcISA enum MiscRegIndex { /** Ancillary State Registers */ - MISCREG_Y, /* 0 */ - MISCREG_CCR, +// MISCREG_Y, +// MISCREG_CCR, MISCREG_ASI, MISCREG_TICK, MISCREG_FPRS, @@ -73,11 +73,11 @@ namespace SparcISA MISCREG_TL, MISCREG_PIL, MISCREG_CWP, - MISCREG_CANSAVE, - MISCREG_CANRESTORE, - MISCREG_CLEANWIN, - MISCREG_OTHERWIN, - MISCREG_WSTATE, +// MISCREG_CANSAVE, +// MISCREG_CANRESTORE, +// MISCREG_CLEANWIN, +// MISCREG_OTHERWIN, +// MISCREG_WSTATE, MISCREG_GL, /** Hyper privileged registers */ @@ -171,8 +171,8 @@ namespace SparcISA private: /* ASR Registers */ - uint64_t y; // Y (used in obsolete multiplication) - uint8_t ccr; // Condition Code Register + //uint64_t y; // Y (used in obsolete multiplication) + //uint8_t ccr; // Condition Code Register uint8_t asi; // Address Space Identifier uint64_t tick; // Hardware clock-tick counter uint8_t fprs; // Floating-Point Register State @@ -197,11 +197,11 @@ namespace SparcISA uint8_t tl; // Trap Level uint8_t pil; // Process Interrupt Register uint8_t cwp; // Current Window Pointer - uint8_t cansave; // Savable windows - uint8_t canrestore; // Restorable windows - uint8_t cleanwin; // Clean windows - uint8_t otherwin; // Other windows - uint8_t wstate; // Window State + //uint8_t cansave; // Savable windows + //uint8_t canrestore; // Restorable windows + //uint8_t cleanwin; // Clean windows + //uint8_t otherwin; // Other windows + //uint8_t wstate; // Window State uint8_t gl; // Global level register /** Hyperprivileged Registers */ diff --git a/src/arch/sparc/pagetable.cc b/src/arch/sparc/pagetable.cc index 22130d41c..e91c0599f 100644 --- a/src/arch/sparc/pagetable.cc +++ b/src/arch/sparc/pagetable.cc @@ -41,9 +41,12 @@ TlbEntry::serialize(std::ostream &os) SERIALIZE_SCALAR(range.contextId); SERIALIZE_SCALAR(range.partitionId); SERIALIZE_SCALAR(range.real); - uint64_t entry4u = pte(); + uint64_t entry4u = 0; + if (valid) + entry4u = pte(); SERIALIZE_SCALAR(entry4u); SERIALIZE_SCALAR(used); + SERIALIZE_SCALAR(valid); } @@ -57,8 +60,10 @@ TlbEntry::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(range.real); uint64_t entry4u; UNSERIALIZE_SCALAR(entry4u); - pte.populate(entry4u); + if (entry4u) + pte.populate(entry4u); UNSERIALIZE_SCALAR(used); + UNSERIALIZE_SCALAR(valid); } diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 405e408e5..1e639b9a5 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -95,17 +95,22 @@ SparcLiveProcess::startup() */ //No windows contain info from other programs - threadContexts[0]->setMiscReg(MISCREG_OTHERWIN, 0); + //threadContexts[0]->setMiscReg(MISCREG_OTHERWIN, 0); + threadContexts[0]->setIntReg(NumIntArchRegs + 6, 0); //There are no windows to pop - threadContexts[0]->setMiscReg(MISCREG_CANRESTORE, 0); + //threadContexts[0]->setMiscReg(MISCREG_CANRESTORE, 0); + threadContexts[0]->setIntReg(NumIntArchRegs + 4, 0); //All windows are available to save into - threadContexts[0]->setMiscReg(MISCREG_CANSAVE, NWindows - 2); + //threadContexts[0]->setMiscReg(MISCREG_CANSAVE, NWindows - 2); + threadContexts[0]->setIntReg(NumIntArchRegs + 3, NWindows - 2); //All windows are "clean" - threadContexts[0]->setMiscReg(MISCREG_CLEANWIN, NWindows); + //threadContexts[0]->setMiscReg(MISCREG_CLEANWIN, NWindows); + threadContexts[0]->setIntReg(NumIntArchRegs + 5, NWindows); //Start with register window 0 threadContexts[0]->setMiscReg(MISCREG_CWP, 0); //Always use spill and fill traps 0 - threadContexts[0]->setMiscReg(MISCREG_WSTATE, 0); + //threadContexts[0]->setMiscReg(MISCREG_WSTATE, 0); + threadContexts[0]->setIntReg(NumIntArchRegs + 7, 0); //Set the trap level to 0 threadContexts[0]->setMiscReg(MISCREG_TL, 0); //Set the ASI register to something fixed @@ -427,5 +432,8 @@ SparcLiveProcess::argsInit(int intSize, int pageSize) threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst)); threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst))); + //Align the "stack_min" to a page boundary. + stack_min = roundDown(stack_min, pageSize); + // num_processes++; } diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc index b36133544..827e22c31 100644 --- a/src/arch/sparc/regfile.cc +++ b/src/arch/sparc/regfile.cc @@ -151,6 +151,74 @@ void RegFile::setIntReg(int intReg, const IntReg &val) intRegFile.setReg(intReg, val); } +int SparcISA::flattenIntIndex(ThreadContext * tc, int reg) +{ + int gl = tc->readMiscReg(MISCREG_GL); + int cwp = tc->readMiscReg(MISCREG_CWP); + //DPRINTF(Sparc, "Global Level = %d, Current Window Pointer = %d\n", gl, cwp); + int newReg; + //The total number of global registers + int numGlobals = (MaxGL + 1) * 8; + if(reg < 8) + { + //Global register + //Put it in the appropriate set of globals + newReg = reg + gl * 8; + } + else if(reg < NumIntArchRegs) + { + //Regular windowed register + //Put it in the window pointed to by cwp + newReg = numGlobals + + ((reg - 8 - cwp * 16 + NWindows * 16) % (NWindows * 16)); + } + else if(reg < NumIntArchRegs + NumMicroIntRegs) + { + //Microcode register + //Displace from the end of the regular registers + newReg = reg - NumIntArchRegs + numGlobals + NWindows * 16; + } + else if(reg < 2 * NumIntArchRegs + NumMicroIntRegs) + { + reg -= (NumIntArchRegs + NumMicroIntRegs); + if(reg < 8) + { + //Global register from the next window + //Put it in the appropriate set of globals + newReg = reg + gl * 8; + } + else + { + //Windowed register from the previous window + //Put it in the window before the one pointed to by cwp + newReg = numGlobals + + ((reg - 8 - (cwp - 1) * 16 + NWindows * 16) % (NWindows * 16)); + } + } + else if(reg < 3 * NumIntArchRegs + NumMicroIntRegs) + { + reg -= (2 * NumIntArchRegs + NumMicroIntRegs); + if(reg < 8) + { + //Global register from the previous window + //Put it in the appropriate set of globals + newReg = reg + gl * 8; + } + else + { + //Windowed register from the next window + //Put it in the window after the one pointed to by cwp + newReg = numGlobals + + ((reg - 8 - (cwp + 1) * 16 + NWindows * 16) % (NWindows * 16)); + } + } + else + panic("Tried to flatten invalid register index %d!\n", reg); + DPRINTF(Sparc, "Flattened register %d to %d.\n", reg, newReg); + return newReg; + //return intRegFile.flattenIndex(reg); +} + void RegFile::serialize(std::ostream &os) { intRegFile.serialize(os); @@ -158,6 +226,7 @@ void RegFile::serialize(std::ostream &os) miscRegFile.serialize(os); SERIALIZE_SCALAR(pc); SERIALIZE_SCALAR(npc); + SERIALIZE_SCALAR(nnpc); } void RegFile::unserialize(Checkpoint *cp, const std::string §ion) @@ -167,6 +236,7 @@ void RegFile::unserialize(Checkpoint *cp, const std::string §ion) miscRegFile.unserialize(cp, section); UNSERIALIZE_SCALAR(pc); UNSERIALIZE_SCALAR(npc); + UNSERIALIZE_SCALAR(nnpc); } void RegFile::changeContext(RegContextParam param, RegContextVal val) @@ -220,8 +290,8 @@ void SparcISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest) // ASRs - dest->setMiscReg(MISCREG_Y, src->readMiscReg(MISCREG_Y)); - dest->setMiscReg(MISCREG_CCR, src->readMiscReg(MISCREG_CCR)); +// dest->setMiscReg(MISCREG_Y, src->readMiscReg(MISCREG_Y)); +// dest->setMiscReg(MISCREG_CCR, src->readMiscReg(MISCREG_CCR)); dest->setMiscReg(MISCREG_ASI, src->readMiscReg(MISCREG_ASI)); dest->setMiscReg(MISCREG_TICK, src->readMiscReg(MISCREG_TICK)); dest->setMiscReg(MISCREG_FPRS, src->readMiscReg(MISCREG_FPRS)); @@ -236,11 +306,11 @@ void SparcISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest) dest->setMiscReg(MISCREG_PSTATE, src->readMiscReg(MISCREG_PSTATE)); dest->setMiscReg(MISCREG_PIL, src->readMiscReg(MISCREG_PIL)); dest->setMiscReg(MISCREG_CWP, src->readMiscReg(MISCREG_CWP)); - dest->setMiscReg(MISCREG_CANSAVE, src->readMiscReg(MISCREG_CANSAVE)); - dest->setMiscReg(MISCREG_CANRESTORE, src->readMiscReg(MISCREG_CANRESTORE)); - dest->setMiscReg(MISCREG_OTHERWIN, src->readMiscReg(MISCREG_OTHERWIN)); - dest->setMiscReg(MISCREG_CLEANWIN, src->readMiscReg(MISCREG_CLEANWIN)); - dest->setMiscReg(MISCREG_WSTATE, src->readMiscReg(MISCREG_WSTATE)); +// dest->setMiscReg(MISCREG_CANSAVE, src->readMiscReg(MISCREG_CANSAVE)); +// dest->setMiscReg(MISCREG_CANRESTORE, src->readMiscReg(MISCREG_CANRESTORE)); +// dest->setMiscReg(MISCREG_OTHERWIN, src->readMiscReg(MISCREG_OTHERWIN)); +// dest->setMiscReg(MISCREG_CLEANWIN, src->readMiscReg(MISCREG_CLEANWIN)); +// dest->setMiscReg(MISCREG_WSTATE, src->readMiscReg(MISCREG_WSTATE)); dest->setMiscReg(MISCREG_GL, src->readMiscReg(MISCREG_GL)); // Hyperprivilged registers diff --git a/src/arch/sparc/regfile.hh b/src/arch/sparc/regfile.hh index 0a09d0f66..d9af0757c 100644 --- a/src/arch/sparc/regfile.hh +++ b/src/arch/sparc/regfile.hh @@ -120,6 +120,8 @@ namespace SparcISA void changeContext(RegContextParam param, RegContextVal val); }; + int flattenIntIndex(ThreadContext * tc, int reg); + void copyRegs(ThreadContext *src, ThreadContext *dest); void copyMiscRegs(ThreadContext *src, ThreadContext *dest); diff --git a/src/arch/sparc/remote_gdb.cc b/src/arch/sparc/remote_gdb.cc index c76f8b820..21c4a468c 100644 --- a/src/arch/sparc/remote_gdb.cc +++ b/src/arch/sparc/remote_gdb.cc @@ -193,11 +193,12 @@ RemoteGDB::setregs() void RemoteGDB::clearSingleStep() { - panic("SPARC does not support hardware single stepping\n"); + warn("SPARC single stepping not implemented, " + "but clearSingleStep called\n"); } void RemoteGDB::setSingleStep() { - panic("SPARC does not support hardware single stepping\n"); + panic("SPARC single stepping not implemented.\n"); } diff --git a/src/arch/sparc/sparc_traits.hh b/src/arch/sparc/sparc_traits.hh index a3d29ea8a..d89ec1119 100644 --- a/src/arch/sparc/sparc_traits.hh +++ b/src/arch/sparc/sparc_traits.hh @@ -41,7 +41,8 @@ namespace SparcISA // Number of register windows, can legally be 3 to 32 const int NWindows = 8; - const int NumMicroIntRegs = 1; + //const int NumMicroIntRegs = 1; + const int NumMicroIntRegs = 8; // const int NumRegularIntRegs = MaxGL * 8 + NWindows * 16; // const int NumMicroIntRegs = 1; diff --git a/src/arch/sparc/syscallreturn.hh b/src/arch/sparc/syscallreturn.hh index 75a063da1..d92b12790 100644 --- a/src/arch/sparc/syscallreturn.hh +++ b/src/arch/sparc/syscallreturn.hh @@ -33,58 +33,30 @@ #include <inttypes.h> +#include "sim/syscallreturn.hh" #include "arch/sparc/regfile.hh" - -class SyscallReturn -{ - public: - template <class T> - SyscallReturn(T v, bool s) - { - retval = (uint64_t)v; - success = s; - } - - template <class T> - SyscallReturn(T v) - { - success = (v >= 0); - retval = (uint64_t)v; - } - - ~SyscallReturn() {} - - SyscallReturn& operator=(const SyscallReturn& s) - { - retval = s.retval; - success = s.success; - return *this; - } - - bool successful() { return success; } - uint64_t value() { return retval; } - - private: - uint64_t retval; - bool success; -}; +#include "cpu/thread_context.hh" namespace SparcISA { static inline void setSyscallReturn(SyscallReturn return_value, - RegFile *regs) + ThreadContext * tc) { // check for error condition. SPARC syscall convention is to // indicate success/failure in reg the carry bit of the ccr // and put the return value itself in the standard return value reg (). if (return_value.successful()) { // no error, clear XCC.C - regs->setMiscReg(MISCREG_CCR, regs->readMiscReg(MISCREG_CCR) & 0xEE); - regs->setIntReg(ReturnValueReg, return_value.value()); + tc->setIntReg(NumIntArchRegs + 2, + tc->readIntReg(NumIntArchRegs + 2) & 0xEE); + //tc->setMiscReg(MISCREG_CCR, tc->readMiscReg(MISCREG_CCR) & 0xEE); + tc->setIntReg(ReturnValueReg, return_value.value()); } else { // got an error, set XCC.C - regs->setMiscReg(MISCREG_CCR, regs->readMiscReg(MISCREG_CCR) | 0x11); - regs->setIntReg(ReturnValueReg, return_value.value()); + tc->setIntReg(NumIntArchRegs + 2, + tc->readIntReg(NumIntArchRegs + 2) | 0x11); + //tc->setMiscReg(MISCREG_CCR, tc->readMiscReg(MISCREG_CCR) | 0x11); + tc->setIntReg(ReturnValueReg, -return_value.value()); } } }; diff --git a/src/arch/sparc/system.cc b/src/arch/sparc/system.cc index da83d86fc..2600213fd 100644 --- a/src/arch/sparc/system.cc +++ b/src/arch/sparc/system.cc @@ -191,12 +191,6 @@ SparcSystem::~SparcSystem() delete partition_desc; } -bool -SparcSystem::breakpoint() -{ - panic("Need to implement"); -} - void SparcSystem::serialize(std::ostream &os) { diff --git a/src/arch/sparc/system.hh b/src/arch/sparc/system.hh index c81b093e8..ac4d34279 100644 --- a/src/arch/sparc/system.hh +++ b/src/arch/sparc/system.hh @@ -68,8 +68,6 @@ class SparcSystem : public System ~SparcSystem(); - virtual bool breakpoint(); - /** * Serialization stuff */ diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc index bf57c894f..ebc8c0e7a 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -28,6 +28,8 @@ * Authors: Ali Saidi */ +#include <cstring> + #include "arch/sparc/asi.hh" #include "arch/sparc/miscregfile.hh" #include "arch/sparc/tlb.hh" @@ -53,7 +55,7 @@ TLB::TLB(const std::string &name, int s) fatal("SPARC T1 TLB registers don't support more than 64 TLB entries."); tlb = new TlbEntry[size]; - memset(tlb, 0, sizeof(TlbEntry) * size); + std::memset(tlb, 0, sizeof(TlbEntry) * size); for (int x = 0; x < size; x++) freeList.push_back(&tlb[x]); @@ -174,8 +176,6 @@ insertAllLocked: lookupTable.erase(new_entry->range); - DPRINTF(TLB, "Using entry: %#X\n", new_entry); - assert(PTE.valid()); new_entry->range.va = va; new_entry->range.size = PTE.size() - 1; @@ -285,7 +285,6 @@ TLB::demapPage(Addr va, int partition_id, bool real, int context_id) usedEntries--; } freeList.push_front(i->second); - DPRINTF(TLB, "Freeing TLB entry : %#X\n", i->second); lookupTable.erase(i); } } @@ -302,7 +301,6 @@ TLB::demapContext(int partition_id, int context_id) tlb[x].range.partitionId == partition_id) { if (tlb[x].valid == true) { freeList.push_front(&tlb[x]); - DPRINTF(TLB, "Freeing TLB entry : %#X\n", &tlb[x]); } tlb[x].valid = false; if (tlb[x].used) { @@ -324,7 +322,6 @@ TLB::demapAll(int partition_id) if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) { if (tlb[x].valid == true){ freeList.push_front(&tlb[x]); - DPRINTF(TLB, "Freeing TLB entry : %#X\n", &tlb[x]); } tlb[x].valid = false; if (tlb[x].used) { @@ -902,7 +899,6 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG)); break; case ASI_SPARC_ERROR_STATUS_REG: - warn("returning 0 for SPARC ERROR regsiter read\n"); pkt->set((uint64_t)0); break; case ASI_HYP_SCRATCHPAD: @@ -1253,13 +1249,55 @@ doMmuWriteError: void TLB::serialize(std::ostream &os) { - panic("Need to implement serialize tlb for SPARC\n"); + SERIALIZE_SCALAR(size); + SERIALIZE_SCALAR(usedEntries); + SERIALIZE_SCALAR(lastReplaced); + + // convert the pointer based free list into an index based one + int *free_list = (int*)malloc(sizeof(int) * size); + int cntr = 0; + std::list<TlbEntry*>::iterator i; + i = freeList.begin(); + while (i != freeList.end()) { + free_list[cntr++] = ((size_t)*i - (size_t)tlb)/ sizeof(TlbEntry); + i++; + } + SERIALIZE_SCALAR(cntr); + SERIALIZE_ARRAY(free_list, cntr); + + for (int x = 0; x < size; x++) { + nameOut(os, csprintf("%s.PTE%d", name(), x)); + tlb[x].serialize(os); + } } void TLB::unserialize(Checkpoint *cp, const std::string §ion) { - panic("Need to implement unserialize tlb for SPARC\n"); + int oldSize; + + paramIn(cp, section, "size", oldSize); + if (oldSize != size) + panic("Don't support unserializing different sized TLBs\n"); + UNSERIALIZE_SCALAR(usedEntries); + UNSERIALIZE_SCALAR(lastReplaced); + + int cntr; + UNSERIALIZE_SCALAR(cntr); + + int *free_list = (int*)malloc(sizeof(int) * cntr); + freeList.clear(); + UNSERIALIZE_ARRAY(free_list, cntr); + for (int x = 0; x < cntr; x++) + freeList.push_back(&tlb[free_list[x]]); + + lookupTable.clear(); + for (int x = 0; x < size; x++) { + tlb[x].unserialize(cp, csprintf("%s.PTE%d", section, x)); + if (tlb[x].valid) + lookupTable.insert(tlb[x].range, &tlb[x]); + + } } diff --git a/src/arch/sparc/utility.hh b/src/arch/sparc/utility.hh index 5c7fe343d..3c8bdcd01 100644 --- a/src/arch/sparc/utility.hh +++ b/src/arch/sparc/utility.hh @@ -50,7 +50,7 @@ namespace SparcISA inline ExtMachInst makeExtMI(MachInst inst, ThreadContext * xc) { - ExtMachInst emi = (unsigned MachInst) inst; + ExtMachInst emi = (MachInst) inst; //The I bit, bit 13, is used to figure out where the ASI //should come from. Use that in the ExtMachInst. This is //slightly redundant, but it removes the need to put a condition |