diff options
Diffstat (limited to 'src')
167 files changed, 2807 insertions, 1843 deletions
diff --git a/src/SConscript b/src/SConscript index 229418703..74bed9a7e 100644 --- a/src/SConscript +++ b/src/SConscript @@ -62,6 +62,7 @@ base_sources = Split(''' base/pollevent.cc base/range.cc base/random.cc + base/remote_gdb.cc base/sat_counter.cc base/socket.cc base/statistics.cc @@ -172,7 +173,6 @@ mysql_sources = Split(''' full_system_sources = Split(''' base/crc.cc base/inet.cc - base/remote_gdb.cc cpu/intr_control.cc cpu/profile.cc @@ -304,37 +304,56 @@ def makeEnv(label, objsfx, strip = False, **kwargs): newEnv.Program(bin, make_objs(sources, newEnv)) if strip: stripped_bin = bin + '.stripped' - newEnv.Command(stripped_bin, bin, 'strip $SOURCE -o $TARGET') + if sys.platform == 'sunos5': + newEnv.Command(stripped_bin, bin, 'cp $SOURCE $TARGET; strip $TARGET') + else: + newEnv.Command(stripped_bin, bin, 'strip $SOURCE -o $TARGET') bin = stripped_bin targets = newEnv.Concat(exe, [bin, 'python/m5py.zip']) newEnv.M5Binary = targets[0] envList.append(newEnv) # Debug binary -# Solaris seems to have some issue with DWARF2 debugging information, it's ok -# with stabs though -if sys.platform == 'sunos5': - debug_flag = '-gstabs+' +ccflags = {} +if env['GCC']: + if sys.platform == 'sunos5': + ccflags['debug'] = '-gstabs+' + else: + ccflags['debug'] = '-ggdb3' + ccflags['opt'] = '-g -O3' + ccflags['fast'] = '-O3' + ccflags['prof'] = '-O3 -g -pg' +elif env['SUNCC']: + ccflags['debug'] = '-g0' + ccflags['opt'] = '-g -O' + ccflags['fast'] = '-fast' + ccflags['prof'] = '-fast -g -pg' +elif env['ICC']: + ccflags['debug'] = '-g -O0' + ccflags['opt'] = '-g -O' + ccflags['fast'] = '-fast' + ccflags['prof'] = '-fast -g -pg' else: - debug_flag = '-ggdb3' + print 'Unknown compiler, please fix compiler options' + Exit(1) makeEnv('debug', '.do', - CCFLAGS = Split('%s -O0' % debug_flag), + CCFLAGS = Split(ccflags['debug']), CPPDEFINES = ['DEBUG', 'TRACING_ON=1']) # Optimized binary makeEnv('opt', '.o', - CCFLAGS = Split('-g -O3'), + CCFLAGS = Split(ccflags['opt']), CPPDEFINES = ['TRACING_ON=1']) # "Fast" binary makeEnv('fast', '.fo', strip = True, - CCFLAGS = Split('-O3'), + CCFLAGS = Split(ccflags['fast']), CPPDEFINES = ['NDEBUG', 'TRACING_ON=0']) # Profiled binary makeEnv('prof', '.po', - CCFLAGS = Split('-O3 -g -pg'), + CCFLAGS = Split(ccflags['prof']), CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], LINKFLAGS = '-pg') diff --git a/src/arch/alpha/SConscript b/src/arch/alpha/SConscript index 3cc5ec270..addd49884 100644 --- a/src/arch/alpha/SConscript +++ b/src/arch/alpha/SConscript @@ -52,6 +52,7 @@ base_sources = Split(''' intregfile.cc miscregfile.cc regfile.cc + remote_gdb.cc ''') # Full-system sources @@ -66,7 +67,6 @@ full_system_sources = Split(''' osfpal.cc pagetable.cc stacktrace.cc - remote_gdb.cc system.cc tlb.cc tru64/system.cc diff --git a/src/arch/alpha/isa/branch.isa b/src/arch/alpha/isa/branch.isa index 7438e7e18..974193efd 100644 --- a/src/arch/alpha/isa/branch.isa +++ b/src/arch/alpha/isa/branch.isa @@ -218,7 +218,7 @@ def template JumpOrBranchDecode {{ def format CondBranch(code) {{ code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n'; - iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), + iop = InstObjParams(name, Name, 'Branch', code, ('IsDirectControl', 'IsCondControl')) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) @@ -230,8 +230,7 @@ let {{ def UncondCtrlBase(name, Name, base_class, npc_expr, flags): # Declare basic control transfer w/o link (i.e. link reg is R31) nolink_code = 'NPC = %s;\n' % npc_expr - nolink_iop = InstObjParams(name, Name, base_class, - CodeBlock(nolink_code), flags) + nolink_iop = InstObjParams(name, Name, base_class, nolink_code, flags) header_output = BasicDeclare.subst(nolink_iop) decoder_output = BasicConstructor.subst(nolink_iop) exec_output = BasicExecute.subst(nolink_iop) @@ -239,7 +238,7 @@ def UncondCtrlBase(name, Name, base_class, npc_expr, flags): # Generate declaration of '*AndLink' version, append to decls link_code = 'Ra = NPC & ~3;\n' + nolink_code link_iop = InstObjParams(name, Name + 'AndLink', base_class, - CodeBlock(link_code), flags) + link_code, flags) header_output += BasicDeclare.subst(link_iop) decoder_output += BasicConstructor.subst(link_iop) exec_output += BasicExecute.subst(link_iop) diff --git a/src/arch/alpha/isa/fp.isa b/src/arch/alpha/isa/fp.isa index 3b5575f62..c845ea442 100644 --- a/src/arch/alpha/isa/fp.isa +++ b/src/arch/alpha/isa/fp.isa @@ -293,7 +293,7 @@ def template FloatingPointDecode {{ // currently unimplemented (will fail). // - Generates NOP if FC == 31. def format FloatingPointOperate(code, *opt_args) {{ - iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args) + iop = InstObjParams(name, Name, 'AlphaFP', code, opt_args) decode_block = FloatingPointDecode.subst(iop) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) @@ -303,7 +303,7 @@ def format FloatingPointOperate(code, *opt_args) {{ // Special format for cvttq where rounding mode is pre-decoded def format FPFixedRounding(code, class_suffix, *opt_args) {{ Name += class_suffix - iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args) + iop = InstObjParams(name, Name, 'AlphaFP', code, opt_args) decode_block = FloatingPointDecode.subst(iop) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) diff --git a/src/arch/alpha/isa/int.isa b/src/arch/alpha/isa/int.isa index 45e096ebd..bd9c3ccd9 100644 --- a/src/arch/alpha/isa/int.isa +++ b/src/arch/alpha/isa/int.isa @@ -113,16 +113,14 @@ def format IntegerOperate(code, *opt_flags) {{ imm_code = re.sub(r'Rb_or_imm(\.\w+)?', 'imm', orig_code) # generate declaration for register version - cblk = CodeBlock(code) - iop = InstObjParams(name, Name, 'AlphaStaticInst', cblk, opt_flags) + iop = InstObjParams(name, Name, 'AlphaStaticInst', code, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) exec_output = BasicExecute.subst(iop) if uses_imm: # append declaration for imm version - imm_cblk = CodeBlock(imm_code) - imm_iop = InstObjParams(name, Name + 'Imm', 'IntegerImm', imm_cblk, + imm_iop = InstObjParams(name, Name + 'Imm', 'IntegerImm', imm_code, opt_flags) header_output += BasicDeclare.subst(imm_iop) decoder_output += BasicConstructor.subst(imm_iop) diff --git a/src/arch/alpha/isa/main.isa b/src/arch/alpha/isa/main.isa index 6e65cf9d3..d72dfe34a 100644 --- a/src/arch/alpha/isa/main.isa +++ b/src/arch/alpha/isa/main.isa @@ -338,7 +338,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, 'AlphaStaticInst', CodeBlock(code), flags) + iop = InstObjParams(name, Name, 'AlphaStaticInst', code, flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) @@ -424,8 +424,7 @@ def template OperateNopCheckDecode {{ // Like BasicOperate format, but generates NOP if RC/FC == 31 def format BasicOperateWithNopCheck(code, *opt_args) {{ - iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code), - opt_args) + iop = InstObjParams(name, Name, 'AlphaStaticInst', code, opt_args) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = OperateNopCheckDecode.subst(iop) diff --git a/src/arch/alpha/isa/mem.isa b/src/arch/alpha/isa/mem.isa index 02291ed6b..c0bdd2c05 100644 --- a/src/arch/alpha/isa/mem.isa +++ b/src/arch/alpha/isa/mem.isa @@ -126,7 +126,7 @@ output decoder {{ }}; def format LoadAddress(code) {{ - iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code)) + iop = InstObjParams(name, Name, 'MemoryDisp32', code) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) @@ -191,22 +191,28 @@ def template CompleteAccDeclare {{ }}; -def template LoadStoreConstructor {{ +def template EACompConstructor {{ /** TODO: change op_class to AddrGenOp or something (requires * creating new member of OpClass enum in op_class.hh, updating * config files, etc.). */ inline %(class_name)s::EAComp::EAComp(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp) { - %(ea_constructor)s; + %(constructor)s; } +}}; + +def template MemAccConstructor {{ inline %(class_name)s::MemAcc::MemAcc(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s) { - %(memacc_constructor)s; + %(constructor)s; } +}}; + +def template LoadStoreConstructor {{ inline %(class_name)s::%(class_name)s(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, new EAComp(machInst), new MemAcc(machInst)) @@ -227,7 +233,7 @@ def template EACompExecute {{ %(fp_enable_check)s; %(op_decl)s; %(op_rd)s; - %(code)s; + %(ea_code)s; if (fault == NoFault) { %(op_wb)s; @@ -253,7 +259,7 @@ def template LoadMemAccExecute {{ if (fault == NoFault) { fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); - %(code)s; + %(memacc_code)s; } if (fault == NoFault) { @@ -352,7 +358,7 @@ def template StoreMemAccExecute {{ EA = xc->getEA(); if (fault == NoFault) { - %(code)s; + %(memacc_code)s; } if (fault == NoFault) { @@ -497,7 +503,7 @@ def template MiscMemAccExecute {{ EA = xc->getEA(); if (fault == NoFault) { - %(code)s; + %(memacc_code)s; } return NoFault; @@ -582,63 +588,24 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, # add hook to get effective addresses into execution trace output. ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n' - # generate code block objects - ea_cblk = CodeBlock(ea_code) - memacc_cblk = CodeBlock(memacc_code) - postacc_cblk = CodeBlock(postacc_code) - # Some CPU models execute the memory operation as an atomic unit, # while others want to separate them into an effective address # computation and a memory access operation. As a result, we need # to generate three StaticInst objects. Note that the latter two # are nested inside the larger "atomic" one. - # generate InstObjParams for EAComp object - ea_iop = InstObjParams(name, Name, base_class, ea_cblk, inst_flags) - - # generate InstObjParams for MemAcc object - memacc_iop = InstObjParams(name, Name, base_class, memacc_cblk, inst_flags) - # in the split execution model, the MemAcc portion is responsible - # for the post-access code. - memacc_iop.postacc_code = postacc_cblk.code - - # generate InstObjParams for InitiateAcc, CompleteAcc object - # The code used depends on the template being used - if (exec_template_base == 'Load'): - initiateacc_cblk = CodeBlock(ea_code + memacc_code) - completeacc_cblk = CodeBlock(memacc_code + postacc_code) - elif (exec_template_base.startswith('Store')): - initiateacc_cblk = CodeBlock(ea_code + memacc_code) - completeacc_cblk = CodeBlock(postacc_code) - else: - initiateacc_cblk = '' - completeacc_cblk = '' - - initiateacc_iop = InstObjParams(name, Name, base_class, initiateacc_cblk, - inst_flags) - - completeacc_iop = InstObjParams(name, Name, base_class, completeacc_cblk, - inst_flags) - - if (exec_template_base == 'Load'): - initiateacc_iop.ea_code = ea_cblk.code - initiateacc_iop.memacc_code = memacc_cblk.code - completeacc_iop.memacc_code = memacc_cblk.code - completeacc_iop.postacc_code = postacc_cblk.code - elif (exec_template_base.startswith('Store')): - initiateacc_iop.ea_code = ea_cblk.code - initiateacc_iop.memacc_code = memacc_cblk.code - completeacc_iop.postacc_code = postacc_cblk.code - - # generate InstObjParams for unified execution - cblk = CodeBlock(ea_code + memacc_code + postacc_code) - iop = InstObjParams(name, Name, base_class, cblk, inst_flags) - - iop.ea_constructor = ea_cblk.constructor - iop.ea_code = ea_cblk.code - iop.memacc_constructor = memacc_cblk.constructor - iop.memacc_code = memacc_cblk.code - iop.postacc_code = postacc_cblk.code + # Generate InstObjParams for each of the three objects. Note that + # they differ only in the set of code objects contained (which in + # turn affects the object's overall operand list). + iop = InstObjParams(name, Name, base_class, + { 'ea_code':ea_code, 'memacc_code':memacc_code, 'postacc_code':postacc_code }, + inst_flags) + ea_iop = InstObjParams(name, Name, base_class, + { 'ea_code':ea_code }, + inst_flags) + memacc_iop = InstObjParams(name, Name, base_class, + { 'memacc_code':memacc_code, 'postacc_code':postacc_code }, + inst_flags) if mem_flags: s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' @@ -659,13 +626,16 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, completeAccTemplate = eval(exec_template_base + 'CompleteAcc') # (header_output, decoder_output, decode_block, exec_output) - return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop), + return (LoadStoreDeclare.subst(iop), + EACompConstructor.subst(ea_iop) + + MemAccConstructor.subst(memacc_iop) + + LoadStoreConstructor.subst(iop), decode_template.subst(iop), EACompExecute.subst(ea_iop) + memAccExecTemplate.subst(memacc_iop) + fullExecTemplate.subst(iop) - + initiateAccTemplate.subst(initiateacc_iop) - + completeAccTemplate.subst(completeacc_iop)) + + initiateAccTemplate.subst(iop) + + completeAccTemplate.subst(iop)) }}; def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }}, diff --git a/src/arch/alpha/isa/pal.isa b/src/arch/alpha/isa/pal.isa index f4c10da1d..294b92e2f 100644 --- a/src/arch/alpha/isa/pal.isa +++ b/src/arch/alpha/isa/pal.isa @@ -68,7 +68,7 @@ output decoder {{ }}; def format EmulatedCallPal(code, *flags) {{ - iop = InstObjParams(name, Name, 'EmulatedCallPal', CodeBlock(code), flags) + iop = InstObjParams(name, Name, 'EmulatedCallPal', code, flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) @@ -131,7 +131,7 @@ output decoder {{ }}; def format CallPal(code, *flags) {{ - iop = InstObjParams(name, Name, 'CallPalBase', CodeBlock(code), flags) + iop = InstObjParams(name, Name, 'CallPalBase', code, flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) @@ -269,8 +269,7 @@ output decoder {{ def format HwMoveIPR(code, *flags) {{ all_flags = ['IprAccessOp'] all_flags += flags - iop = InstObjParams(name, Name, 'HwMoveIPR', CodeBlock(code), - all_flags) + iop = InstObjParams(name, Name, 'HwMoveIPR', code, all_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) diff --git a/src/arch/alpha/isa_traits.hh b/src/arch/alpha/isa_traits.hh index 35d9ce843..a267ac034 100644 --- a/src/arch/alpha/isa_traits.hh +++ b/src/arch/alpha/isa_traits.hh @@ -132,7 +132,7 @@ namespace AlphaISA const int NumPALShadowRegs = 8; const int NumFloatArchRegs = 32; // @todo: Figure out what this number really should be. - const int NumMiscArchRegs = 32; + const int NumMiscArchRegs = 77; const int NumIntRegs = NumIntArchRegs + NumPALShadowRegs; const int NumFloatRegs = NumFloatArchRegs; diff --git a/src/arch/alpha/regfile.hh b/src/arch/alpha/regfile.hh index ff5830822..54372da36 100644 --- a/src/arch/alpha/regfile.hh +++ b/src/arch/alpha/regfile.hh @@ -78,13 +78,11 @@ namespace AlphaISA Addr readNextNPC() { - return nnpc; + return npc + sizeof(MachInst); } void setNextNPC(Addr val) - { - nnpc = val; - } + { } protected: IntRegFile intRegFile; // (signed) integer register file @@ -189,6 +187,11 @@ namespace AlphaISA } }; + static inline int flattenIntIndex(ThreadContext * tc, int reg) + { + return reg; + } + void copyRegs(ThreadContext *src, ThreadContext *dest); void copyMiscRegs(ThreadContext *src, ThreadContext *dest); diff --git a/src/arch/alpha/remote_gdb.cc b/src/arch/alpha/remote_gdb.cc index f23fc3205..4637bd7a6 100644 --- a/src/arch/alpha/remote_gdb.cc +++ b/src/arch/alpha/remote_gdb.cc @@ -121,14 +121,18 @@ #include <string> #include <unistd.h> +#include "config/full_system.hh" +#if FULL_SYSTEM +#include "arch/alpha/vtophys.hh" +#endif + #include "arch/alpha/kgdb.h" +#include "arch/alpha/utility.hh" #include "arch/alpha/remote_gdb.hh" -#include "arch/vtophys.hh" #include "base/intmath.hh" #include "base/remote_gdb.hh" #include "base/socket.hh" #include "base/trace.hh" -#include "config/full_system.hh" #include "cpu/thread_context.hh" #include "cpu/static_inst.hh" #include "mem/physical.hh" @@ -152,6 +156,9 @@ RemoteGDB::RemoteGDB(System *_system, ThreadContext *c) bool RemoteGDB::acc(Addr va, size_t len) { +#if !FULL_SYSTEM + panic("acc function needs to be rewritten for SE mode\n"); +#else Addr last_va; va = TheISA::TruncPage(va); @@ -191,6 +198,7 @@ RemoteGDB::acc(Addr va, size_t len) DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va); return true; +#endif } /////////////////////////////////////////////////////////// diff --git a/src/arch/alpha/syscallreturn.hh b/src/arch/alpha/syscallreturn.hh index 803c3b7da..47b4ac8c7 100644 --- a/src/arch/alpha/syscallreturn.hh +++ b/src/arch/alpha/syscallreturn.hh @@ -32,54 +32,25 @@ #ifndef __ARCH_ALPHA_SYSCALLRETURN_HH__ #define __ARCH_ALPHA_SYSCALLRETURN_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" +#include "sim/syscallreturn.hh" namespace AlphaISA { - static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs) + static inline void setSyscallReturn(SyscallReturn return_value, + ThreadContext * tc) { // check for error condition. Alpha syscall convention is to // indicate success/failure in reg a3 (r19) and put the // return value itself in the standard return value reg (v0). if (return_value.successful()) { // no error - regs->setIntReg(SyscallSuccessReg, 0); - regs->setIntReg(ReturnValueReg, return_value.value()); + tc->setIntReg(SyscallSuccessReg, 0); + tc->setIntReg(ReturnValueReg, return_value.value()); } else { // got an error, return details - regs->setIntReg(SyscallSuccessReg, (IntReg)-1); - regs->setIntReg(ReturnValueReg, -return_value.value()); + tc->setIntReg(SyscallSuccessReg, (IntReg)-1); + tc->setIntReg(ReturnValueReg, -return_value.value()); } } } diff --git a/src/arch/alpha/system.cc b/src/arch/alpha/system.cc index cd923948c..ed0938aeb 100644 --- a/src/arch/alpha/system.cc +++ b/src/arch/alpha/system.cc @@ -195,12 +195,6 @@ AlphaSystem::setAlphaAccess(Addr access) panic("could not find m5AlphaAccess\n"); } -bool -AlphaSystem::breakpoint() -{ - return remoteGDB[0]->trap(SIGTRAP); -} - void AlphaSystem::serialize(std::ostream &os) { diff --git a/src/arch/alpha/system.hh b/src/arch/alpha/system.hh index 0c073a68c..f92b71c9a 100644 --- a/src/arch/alpha/system.hh +++ b/src/arch/alpha/system.hh @@ -56,8 +56,6 @@ class AlphaSystem : public System ~AlphaSystem(); - virtual bool breakpoint(); - /** * Serialization stuff */ diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh index 100736555..9a06cc2a4 100644 --- a/src/arch/alpha/utility.hh +++ b/src/arch/alpha/utility.hh @@ -121,9 +121,9 @@ namespace AlphaISA template <class TC> void zeroRegisters(TC *tc); -#if FULL_SYSTEM // Alpha IPR register accessors - inline bool PcPAL(Addr addr) { return addr & 0x1; } + inline bool PcPAL(Addr addr) { return addr & 0x3; } +#if FULL_SYSTEM //////////////////////////////////////////////////////////////////////// // diff --git a/src/arch/isa_parser.py b/src/arch/isa_parser.py index 59eb18c9c..07ae72cb8 100755 --- a/src/arch/isa_parser.py +++ b/src/arch/isa_parser.py @@ -808,8 +808,7 @@ class GenCode: # a defineInst() method that generates the code for an instruction # definition. -exportContextSymbols = ('InstObjParams', 'CodeBlock', - 'makeList', 're', 'string') +exportContextSymbols = ('InstObjParams', 'makeList', 're', 'string') exportContext = {} @@ -1003,27 +1002,80 @@ def substBitOps(code): # Template objects are format strings that allow substitution from # the attribute spaces of other objects (e.g. InstObjParams instances). +labelRE = re.compile(r'[^%]%\(([^\)]+)\)[sd]') + class Template: def __init__(self, t): self.template = t def subst(self, d): + myDict = None + + # Protect non-Python-dict substitutions (e.g. if there's a printf + # in the templated C++ code) + template = protect_non_subst_percents(self.template) + # CPU-model-specific substitutions are handled later (in GenCode). + template = protect_cpu_symbols(template) + + # Build a dict ('myDict') to use for the template substitution. # Start with the template namespace. Make a copy since we're # going to modify it. myDict = templateMap.copy() - # if the argument is a dictionary, we just use it. - if isinstance(d, dict): + + if isinstance(d, InstObjParams): + # If we're dealing with an InstObjParams object, we need + # to be a little more sophisticated. The instruction-wide + # parameters are already formed, but the parameters which + # are only function wide still need to be generated. + compositeCode = '' + + myDict.update(d.__dict__) + # The "operands" and "snippets" attributes of the InstObjParams + # objects are for internal use and not substitution. + del myDict['operands'] + del myDict['snippets'] + + snippetLabels = [l for l in labelRE.findall(template) + if d.snippets.has_key(l)] + + snippets = dict([(s, mungeSnippet(d.snippets[s])) + for s in snippetLabels]) + + myDict.update(snippets) + + compositeCode = ' '.join(map(str, snippets.values())) + + # Add in template itself in case it references any + # operands explicitly (like Mem) + compositeCode += ' ' + template + + operands = SubOperandList(compositeCode, d.operands) + + myDict['op_decl'] = operands.concatAttrStrings('op_decl') + + is_src = lambda op: op.is_src + is_dest = lambda op: op.is_dest + + myDict['op_src_decl'] = \ + operands.concatSomeAttrStrings(is_src, 'op_src_decl') + myDict['op_dest_decl'] = \ + operands.concatSomeAttrStrings(is_dest, 'op_dest_decl') + + myDict['op_rd'] = operands.concatAttrStrings('op_rd') + myDict['op_wb'] = operands.concatAttrStrings('op_wb') + + if d.operands.memOperand: + myDict['mem_acc_size'] = d.operands.memOperand.mem_acc_size + myDict['mem_acc_type'] = d.operands.memOperand.mem_acc_type + + elif isinstance(d, dict): + # if the argument is a dictionary, we just use it. myDict.update(d) - # if the argument is an object, we use its attribute map. elif hasattr(d, '__dict__'): + # if the argument is an object, we use its attribute map. myDict.update(d.__dict__) else: raise TypeError, "Template.subst() arg must be or have dictionary" - # Protect non-Python-dict substitutions (e.g. if there's a printf - # in the templated C++ code) - template = protect_non_subst_percents(self.template) - # CPU-model-specific substitutions are handled later (in GenCode). - template = protect_cpu_symbols(template) return template % myDict # Convert to string. This handles the case when a template with a @@ -1296,10 +1348,10 @@ class ControlRegOperand(Operand): def makeConstructor(self): c = '' if self.is_src: - c += '\n\t_srcRegIdx[%d] = %s;' % \ + c += '\n\t_srcRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \ (self.src_reg_idx, self.reg_spec) if self.is_dest: - c += '\n\t_destRegIdx[%d] = %s;' % \ + c += '\n\t_destRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \ (self.dest_reg_idx, self.reg_spec) return c @@ -1307,7 +1359,7 @@ class ControlRegOperand(Operand): bit_select = 0 if (self.ctype == 'float' or self.ctype == 'double'): error(0, 'Attempt to read control register as FP') - base = 'xc->readMiscRegWithEffect(%s)' % self.reg_spec + base = 'xc->readMiscRegOperandWithEffect(this, %s)' % self.src_reg_idx if self.size == self.dflt_size: return '%s = %s;\n' % (self.base_name, base) else: @@ -1317,7 +1369,8 @@ class ControlRegOperand(Operand): def makeWrite(self): if (self.ctype == 'float' or self.ctype == 'double'): error(0, 'Attempt to write control register as FP') - wb = 'xc->setMiscRegWithEffect(%s, %s);\n' % (self.reg_spec, self.base_name) + wb = 'xc->setMiscRegOperandWithEffect(this, %s, %s);\n' % \ + (self.dest_reg_idx, self.base_name) wb += 'if (traceData) { traceData->setData(%s); }' % \ self.base_name return wb @@ -1550,6 +1603,48 @@ class OperandList: def sort(self): self.items.sort(lambda a, b: a.sort_pri - b.sort_pri) +class SubOperandList(OperandList): + + # Find all the operands in the given code block. Returns an operand + # descriptor list (instance of class OperandList). + def __init__(self, code, master_list): + self.items = [] + self.bases = {} + # delete comments so we don't match on reg specifiers inside + code = commentRE.sub('', code) + # search for operands + next_pos = 0 + while 1: + match = operandsRE.search(code, next_pos) + if not match: + # no more matches: we're done + break + op = match.groups() + # regexp groups are operand full name, base, and extension + (op_full, op_base, op_ext) = op + # find this op in the master list + op_desc = master_list.find_base(op_base) + if not op_desc: + error(0, 'Found operand %s which is not in the master list!' \ + ' This is an internal error' % \ + op_base) + else: + # See if we've already found this operand + op_desc = self.find_base(op_base) + if not op_desc: + # if not, add a reference to it to this sub list + self.append(master_list.bases[op_base]) + + # start next search after end of current match + next_pos = match.end() + self.sort() + self.memOperand = None + for op_desc in self.items: + if op_desc.isMem(): + if self.memOperand: + error(0, "Code block has more than one memory operand.") + self.memOperand = op_desc + # Regular expression object to match C++ comments # (used in findOperands()) commentRE = re.compile(r'//.*\n') @@ -1564,8 +1659,12 @@ assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE) def substMungedOpNames(code): return operandsWithExtRE.sub(r'\1', code) -def joinLists(t): - return map(string.join, t) +# Fix up code snippets for final substitution in templates. +def mungeSnippet(s): + if isinstance(s, str): + return substMungedOpNames(substBitOps(s)) + else: + return s def makeFlagConstructor(flag_list): if len(flag_list) == 0: @@ -1583,11 +1682,24 @@ def makeFlagConstructor(flag_list): code = pre + string.join(flag_list, post + pre) + post return code -class CodeBlock: - def __init__(self, code): - self.orig_code = code - self.operands = OperandList(code) - self.code = substMungedOpNames(substBitOps(code)) +# Assume all instruction flags are of the form 'IsFoo' +instFlagRE = re.compile(r'Is.*') + +# OpClass constants end in 'Op' except No_OpClass +opClassRE = re.compile(r'.*Op|No_OpClass') + +class InstObjParams: + def __init__(self, mnem, class_name, base_class = '', + snippets = {}, opt_args = []): + self.mnemonic = mnem + self.class_name = class_name + self.base_class = base_class + if not isinstance(snippets, dict): + snippets = {'code' : snippets} + compositeCode = ' '.join(map(str, snippets.values())) + self.snippets = snippets + + self.operands = OperandList(compositeCode) self.constructor = self.operands.concatAttrStrings('constructor') self.constructor += \ '\n\t_numSrcRegs = %d;' % self.operands.numSrcRegs @@ -1597,28 +1709,10 @@ class CodeBlock: '\n\t_numFPDestRegs = %d;' % self.operands.numFPDestRegs self.constructor += \ '\n\t_numIntDestRegs = %d;' % self.operands.numIntDestRegs - - self.op_decl = self.operands.concatAttrStrings('op_decl') - - is_src = lambda op: op.is_src - is_dest = lambda op: op.is_dest - - self.op_src_decl = \ - self.operands.concatSomeAttrStrings(is_src, 'op_src_decl') - self.op_dest_decl = \ - self.operands.concatSomeAttrStrings(is_dest, 'op_dest_decl') - - self.op_rd = self.operands.concatAttrStrings('op_rd') - self.op_wb = self.operands.concatAttrStrings('op_wb') - self.flags = self.operands.concatAttrLists('flags') - if self.operands.memOperand: - self.mem_acc_size = self.operands.memOperand.mem_acc_size - self.mem_acc_type = self.operands.memOperand.mem_acc_type - # Make a basic guess on the operand class (function unit type). - # These are good enough for most cases, and will be overridden + # These are good enough for most cases, and can be overridden # later otherwise. if 'IsStore' in self.flags: self.op_class = 'MemWriteOp' @@ -1629,48 +1723,6 @@ class CodeBlock: else: self.op_class = 'IntAluOp' -# Assume all instruction flags are of the form 'IsFoo' -instFlagRE = re.compile(r'Is.*') - -# OpClass constants end in 'Op' except No_OpClass -opClassRE = re.compile(r'.*Op|No_OpClass') - -class InstObjParams: - def __init__(self, mnem, class_name, base_class = '', - code = None, opt_args = [], extras = {}): - self.mnemonic = mnem - self.class_name = class_name - self.base_class = base_class - if code: - #If the user already made a CodeBlock, pick the parts from it - if isinstance(code, CodeBlock): - origCode = code.orig_code - codeBlock = code - else: - origCode = code - codeBlock = CodeBlock(code) - stringExtras = {} - otherExtras = {} - for (k, v) in extras.items(): - if type(v) == str: - stringExtras[k] = v - else: - otherExtras[k] = v - compositeCode = "\n".join([origCode] + stringExtras.values()) - # compositeCode = '\n'.join([origCode] + - # [pair[1] for pair in extras]) - compositeBlock = CodeBlock(compositeCode) - for code_attr in compositeBlock.__dict__.keys(): - setattr(self, code_attr, getattr(compositeBlock, code_attr)) - for (key, snippet) in stringExtras.items(): - setattr(self, key, CodeBlock(snippet).code) - for (key, item) in otherExtras.items(): - setattr(self, key, item) - self.code = codeBlock.code - self.orig_code = origCode - else: - self.constructor = '' - self.flags = [] # Optional arguments are assumed to be either StaticInst flags # or an OpClass value. To avoid having to import a complete # list of these values to match against, we do it ad-hoc diff --git a/src/arch/mips/isa/decoder.isa b/src/arch/mips/isa/decoder.isa index d65e3eb94..99c9e1604 100644 --- a/src/arch/mips/isa/decoder.isa +++ b/src/arch/mips/isa/decoder.isa @@ -154,19 +154,22 @@ decode OPCODE_HI default Unknown::unknown() { 0x3: decode FUNCTION_LO { format HiLoOp { - 0x0: mult({{ val = Rs.sd * Rt.sd; }}); - 0x1: multu({{ val = Rs.ud * Rt.ud; }}); - } - - format HiLoMiscOp { - 0x2: div({{ if (Rt.sd != 0) { - HI = Rs.sd % Rt.sd; - LO = Rs.sd / Rt.sd; + 0x0: mult({{ int64_t val = Rs.sd * Rt.sd; }}); + 0x1: multu({{ uint64_t val = Rs.ud * Rt.ud; }}); + 0x2: div({{ //Initialized to placate g++ + int64_t val = 0; + if (Rt.sd != 0) { + int64_t hi = Rs.sd % Rt.sd; + int64_t lo = Rs.sd / Rt.sd; + val = (hi << 32) | lo; } }}); - 0x3: divu({{ if (Rt.ud != 0) { - HI = Rs.ud % Rt.ud; - LO = Rs.ud / Rt.ud; + 0x3: divu({{ //Initialized to placate g++ + uint64_t val = 0; + if (Rt.ud != 0) { + uint64_t hi = Rs.ud % Rt.ud; + uint64_t lo = Rs.ud / Rt.ud; + val = (hi << 32) | lo; } }}); } @@ -950,17 +953,17 @@ decode OPCODE_HI default Unknown::unknown() { }}); format HiLoOp { - 0x0: madd({{ val = ((int64_t) HI << 32 | LO) + - (Rs.sd * Rt.sd); + 0x0: madd({{ int64_t val = ((int64_t) HI << 32 | LO) + + (Rs.sd * Rt.sd); }}); - 0x1: maddu({{ val = ((uint64_t) HI << 32 | LO) + - (Rs.ud * Rt.ud); + 0x1: maddu({{ uint64_t val = ((uint64_t) HI << 32 | LO) + + (Rs.ud * Rt.ud); }}); - 0x4: msub({{ val = ((int64_t) HI << 32 | LO) - - (Rs.sd * Rt.sd); + 0x4: msub({{ int64_t val = ((int64_t) HI << 32 | LO) - + (Rs.sd * Rt.sd); }}); - 0x5: msubu({{ val = ((uint64_t) HI << 32 | LO) - - (Rs.ud * Rt.ud); + 0x5: msubu({{ uint64_t val = ((uint64_t) HI << 32 | LO) - + (Rs.ud * Rt.ud); }}); } } diff --git a/src/arch/mips/isa/formats/basic.isa b/src/arch/mips/isa/formats/basic.isa index 29a445b2c..ec065b865 100644 --- a/src/arch/mips/isa/formats/basic.isa +++ b/src/arch/mips/isa/formats/basic.isa @@ -88,7 +88,7 @@ def template BasicDecodeWithMnemonic {{ // The most basic instruction format... def format BasicOp(code, *flags) {{ - iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) + iop = InstObjParams(name, Name, 'MipsStaticInst', code, flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) diff --git a/src/arch/mips/isa/formats/branch.isa b/src/arch/mips/isa/formats/branch.isa index 8c89fbfa2..a67f04dca 100644 --- a/src/arch/mips/isa/formats/branch.isa +++ b/src/arch/mips/isa/formats/branch.isa @@ -247,7 +247,7 @@ def format Branch(code,*opt_flags) {{ code += '} else {\n' code += not_taken_code - iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), inst_flags) + iop = InstObjParams(name, Name, 'Branch', code, inst_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) @@ -266,7 +266,7 @@ def format Jump(code, *opt_flags) {{ else: inst_flags += (x, ) - iop = InstObjParams(name, Name, 'Jump', CodeBlock(code), inst_flags) + iop = InstObjParams(name, Name, 'Jump', code, inst_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) diff --git a/src/arch/mips/isa/formats/control.isa b/src/arch/mips/isa/formats/control.isa index 6c7d396f3..1c63a6e22 100644 --- a/src/arch/mips/isa/formats/control.isa +++ b/src/arch/mips/isa/formats/control.isa @@ -130,7 +130,7 @@ output decoder {{ }}; def format System(code, *flags) {{ - iop = InstObjParams(name, Name, 'Control', CodeBlock(code), flags) + iop = InstObjParams(name, Name, 'Control', code, flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) @@ -138,7 +138,7 @@ def format System(code, *flags) {{ }}; def format CP0Control(code, *flags) {{ - iop = InstObjParams(name, Name, 'CP0Control', CodeBlock(code), flags) + iop = InstObjParams(name, Name, 'CP0Control', code, flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) @@ -146,7 +146,7 @@ def format CP0Control(code, *flags) {{ }}; def format CP1Control(code, *flags) {{ - iop = InstObjParams(name, Name, 'CP1Control', CodeBlock(code), flags) + iop = InstObjParams(name, Name, 'CP1Control', code, flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) diff --git a/src/arch/mips/isa/formats/fp.isa b/src/arch/mips/isa/formats/fp.isa index 153f3f949..ac6805cc7 100644 --- a/src/arch/mips/isa/formats/fp.isa +++ b/src/arch/mips/isa/formats/fp.isa @@ -209,7 +209,7 @@ def template FloatingPointExecute {{ // Primary format for float point operate instructions: def format FloatOp(code, *flags) {{ - iop = InstObjParams(name, Name, 'FPOp', CodeBlock(code), flags) + iop = InstObjParams(name, Name, 'FPOp', code, flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) @@ -248,7 +248,7 @@ def format FloatCompareOp(cond_code, *flags) {{ code += cond_code + '}' code += 'FCSR = genCCVector(FCSR, CC, cond);\n' - iop = InstObjParams(name, Name, 'FPCompareOp', CodeBlock(code)) + iop = InstObjParams(name, Name, 'FPCompareOp', code) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) @@ -299,7 +299,7 @@ def format FloatConvertOp(code, *flags) {{ else: code += 'val); ' - iop = InstObjParams(name, Name, 'FPOp', CodeBlock(code)) + iop = InstObjParams(name, Name, 'FPOp', code) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) @@ -307,7 +307,7 @@ def format FloatConvertOp(code, *flags) {{ }}; def format FloatAccOp(code, *flags) {{ - iop = InstObjParams(name, Name, 'FPOp', CodeBlock(code), flags) + iop = InstObjParams(name, Name, 'FPOp', code, flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) @@ -316,7 +316,7 @@ def format FloatAccOp(code, *flags) {{ // Primary format for float64 operate instructions: def format Float64Op(code, *flags) {{ - iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) + iop = InstObjParams(name, Name, 'MipsStaticInst', code, flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) @@ -364,7 +364,7 @@ def format FloatPSCompareOp(cond_code1, cond_code2, *flags) {{ code += cond_code2 code += 'FCSR = genCCVector(FCSR, CC, cond2);}\n}' - iop = InstObjParams(name, Name, 'FPCompareOp', CodeBlock(code)) + iop = InstObjParams(name, Name, 'FPCompareOp', code) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) diff --git a/src/arch/mips/isa/formats/int.isa b/src/arch/mips/isa/formats/int.isa index 654dd8921..2f131f6d9 100644 --- a/src/arch/mips/isa/formats/int.isa +++ b/src/arch/mips/isa/formats/int.isa @@ -224,7 +224,7 @@ output decoder {{ }}; def format IntOp(code, *opt_flags) {{ - iop = InstObjParams(name, Name, 'IntOp', CodeBlock(code), opt_flags) + iop = InstObjParams(name, Name, 'IntOp', code, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = RegNopCheckDecode.subst(iop) @@ -232,7 +232,7 @@ def format IntOp(code, *opt_flags) {{ }}; def format IntImmOp(code, *opt_flags) {{ - iop = InstObjParams(name, Name, 'IntImmOp', CodeBlock(code), opt_flags) + iop = InstObjParams(name, Name, 'IntImmOp', code, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = ImmNopCheckDecode.subst(iop) @@ -240,15 +240,10 @@ def format IntImmOp(code, *opt_flags) {{ }}; def format HiLoOp(code, *opt_flags) {{ - if '.sd' in code: - code = 'int64_t ' + code - elif '.ud' in code: - code = 'uint64_t ' + code - code += 'HI = val<63:32>;\n' code += 'LO = val<31:0>;\n' - iop = InstObjParams(name, Name, 'HiLoOp', CodeBlock(code), opt_flags) + iop = InstObjParams(name, Name, 'HiLoOp', code, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) @@ -256,11 +251,11 @@ def format HiLoOp(code, *opt_flags) {{ }}; def format HiLoMiscOp(code, *opt_flags) {{ - iop = InstObjParams(name, Name, 'HiLoMiscOp', CodeBlock(code), opt_flags) + iop = InstObjParams(name, Name, 'HiLoMiscOp', code, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) - exec_output = HiLoExecute.subst(iop) + exec_output = BasicExecute.subst(iop) }}; diff --git a/src/arch/mips/isa/formats/mem.isa b/src/arch/mips/isa/formats/mem.isa index e786cfbe2..fccda2775 100644 --- a/src/arch/mips/isa/formats/mem.isa +++ b/src/arch/mips/isa/formats/mem.isa @@ -166,22 +166,28 @@ def template CompleteAccDeclare {{ }}; -def template LoadStoreConstructor {{ +def template EACompConstructor {{ /** TODO: change op_class to AddrGenOp or something (requires * creating new member of OpClass enum in op_class.hh, updating * config files, etc.). */ inline %(class_name)s::EAComp::EAComp(MachInst machInst) : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp) { - %(ea_constructor)s; + %(constructor)s; } +}}; + +def template MemAccConstructor {{ inline %(class_name)s::MemAcc::MemAcc(MachInst machInst) : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s) { - %(memacc_constructor)s; + %(constructor)s; } +}}; + +def template LoadStoreConstructor {{ inline %(class_name)s::%(class_name)s(MachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, new EAComp(machInst), new MemAcc(machInst)) @@ -202,7 +208,7 @@ def template EACompExecute {{ %(fp_enable_check)s; %(op_decl)s; %(op_rd)s; - %(code)s; + %(ea_code)s; if (fault == NoFault) { %(op_wb)s; @@ -228,7 +234,7 @@ def template LoadMemAccExecute {{ if (fault == NoFault) { fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); - %(code)s; + %(memacc_code)s; } if (fault == NoFault) { @@ -327,7 +333,7 @@ def template StoreMemAccExecute {{ EA = xc->getEA(); if (fault == NoFault) { - %(code)s; + %(memacc_code)s; } if (fault == NoFault) { @@ -471,7 +477,7 @@ def template MiscMemAccExecute {{ EA = xc->getEA(); if (fault == NoFault) { - %(code)s; + %(memacc_code)s; } return NoFault; diff --git a/src/arch/mips/isa/formats/mt.isa b/src/arch/mips/isa/formats/mt.isa index 96435f8c9..d7240335e 100644 --- a/src/arch/mips/isa/formats/mt.isa +++ b/src/arch/mips/isa/formats/mt.isa @@ -74,7 +74,7 @@ def template MTExecute {{ // Primary format for integer operate instructions: def format MipsMT() {{ code = 'panic(\"Mips MT Is Currently Unimplemented.\");\n' - iop = InstObjParams(name, Name, 'MT', CodeBlock(code)) + iop = InstObjParams(name, Name, 'MT', code) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) diff --git a/src/arch/mips/isa/formats/noop.isa b/src/arch/mips/isa/formats/noop.isa index 7f3d313ad..a8995d658 100644 --- a/src/arch/mips/isa/formats/noop.isa +++ b/src/arch/mips/isa/formats/noop.isa @@ -125,7 +125,7 @@ def template ImmNopCheckDecode {{ // Like BasicOperate format, but generates NOP if RC/FC == 31 def format BasicOperateWithNopCheck(code, *opt_args) {{ - iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), + iop = InstObjParams(name, Name, 'MipsStaticInst', code, opt_args) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) diff --git a/src/arch/mips/isa/formats/tlbop.isa b/src/arch/mips/isa/formats/tlbop.isa index b974ccbed..dbfbb8ce1 100644 --- a/src/arch/mips/isa/formats/tlbop.isa +++ b/src/arch/mips/isa/formats/tlbop.isa @@ -70,9 +70,7 @@ def template TlbOpExecute {{ // Primary format for integer operate instructions: def format TlbOp(code, *opt_flags) {{ - orig_code = code - cblk = CodeBlock(code) - iop = InstObjParams(name, Name, 'MipsStaticInst', cblk, opt_flags) + iop = InstObjParams(name, Name, 'MipsStaticInst', code, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecodeWithMnemonic.subst(iop) diff --git a/src/arch/mips/isa/formats/trap.isa b/src/arch/mips/isa/formats/trap.isa index b9066f374..96d1167d2 100644 --- a/src/arch/mips/isa/formats/trap.isa +++ b/src/arch/mips/isa/formats/trap.isa @@ -73,7 +73,7 @@ def format Trap(code, *flags) {{ code = 'warn(\"' code += 'Trap Exception Handler Is Currently Not Implemented.' code += '\");' - iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) + iop = InstObjParams(name, Name, 'MipsStaticInst', code, flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) diff --git a/src/arch/mips/isa/formats/util.isa b/src/arch/mips/isa/formats/util.isa index 73164bc0d..ec524113d 100644 --- a/src/arch/mips/isa/formats/util.isa +++ b/src/arch/mips/isa/formats/util.isa @@ -40,63 +40,24 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, # add hook to get effective addresses into execution trace output. ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n' - # generate code block objects - ea_cblk = CodeBlock(ea_code) - memacc_cblk = CodeBlock(memacc_code) - postacc_cblk = CodeBlock(postacc_code) - # Some CPU models execute the memory operation as an atomic unit, # while others want to separate them into an effective address # computation and a memory access operation. As a result, we need # to generate three StaticInst objects. Note that the latter two # are nested inside the larger "atomic" one. - # generate InstObjParams for EAComp object - ea_iop = InstObjParams(name, Name, base_class, ea_cblk, inst_flags) - - # generate InstObjParams for MemAcc object - memacc_iop = InstObjParams(name, Name, base_class, memacc_cblk, inst_flags) - # in the split execution model, the MemAcc portion is responsible - # for the post-access code. - memacc_iop.postacc_code = postacc_cblk.code - - # generate InstObjParams for InitiateAcc, CompleteAcc object - # The code used depends on the template being used - if (exec_template_base == 'Load'): - initiateacc_cblk = CodeBlock(ea_code + memacc_code) - completeacc_cblk = CodeBlock(memacc_code + postacc_code) - elif (exec_template_base.startswith('Store')): - initiateacc_cblk = CodeBlock(ea_code + memacc_code) - completeacc_cblk = CodeBlock(postacc_code) - else: - initiateacc_cblk = '' - completeacc_cblk = '' - - initiateacc_iop = InstObjParams(name, Name, base_class, initiateacc_cblk, - inst_flags) - - completeacc_iop = InstObjParams(name, Name, base_class, completeacc_cblk, - inst_flags) - - if (exec_template_base == 'Load'): - initiateacc_iop.ea_code = ea_cblk.code - initiateacc_iop.memacc_code = memacc_cblk.code - completeacc_iop.memacc_code = memacc_cblk.code - completeacc_iop.postacc_code = postacc_cblk.code - elif (exec_template_base.startswith('Store')): - initiateacc_iop.ea_code = ea_cblk.code - initiateacc_iop.memacc_code = memacc_cblk.code - completeacc_iop.postacc_code = postacc_cblk.code - - # generate InstObjParams for unified execution - cblk = CodeBlock(ea_code + memacc_code + postacc_code) - iop = InstObjParams(name, Name, base_class, cblk, inst_flags) - - iop.ea_constructor = ea_cblk.constructor - iop.ea_code = ea_cblk.code - iop.memacc_constructor = memacc_cblk.constructor - iop.memacc_code = memacc_cblk.code - iop.postacc_code = postacc_cblk.code + # Generate InstObjParams for each of the three objects. Note that + # they differ only in the set of code objects contained (which in + # turn affects the object's overall operand list). + iop = InstObjParams(name, Name, base_class, + { 'ea_code':ea_code, 'memacc_code':memacc_code, 'postacc_code':postacc_code }, + inst_flags) + ea_iop = InstObjParams(name, Name, base_class, + { 'ea_code':ea_code }, + inst_flags) + memacc_iop = InstObjParams(name, Name, base_class, + { 'memacc_code':memacc_code, 'postacc_code':postacc_code }, + inst_flags) if mem_flags: s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' @@ -117,14 +78,19 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, completeAccTemplate = eval(exec_template_base + 'CompleteAcc') # (header_output, decoder_output, decode_block, exec_output) - return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop), + return (LoadStoreDeclare.subst(iop), + EACompConstructor.subst(ea_iop) + + MemAccConstructor.subst(memacc_iop) + + LoadStoreConstructor.subst(iop), decode_template.subst(iop), EACompExecute.subst(ea_iop) + memAccExecTemplate.subst(memacc_iop) + fullExecTemplate.subst(iop) - + initiateAccTemplate.subst(initiateacc_iop) - + completeAccTemplate.subst(completeacc_iop)) + + initiateAccTemplate.subst(iop) + + completeAccTemplate.subst(iop)) }}; + + output header {{ std::string inst2string(MachInst machInst); }}; diff --git a/src/arch/mips/regfile/regfile.hh b/src/arch/mips/regfile/regfile.hh index dee883c4a..7b57b31f5 100644 --- a/src/arch/mips/regfile/regfile.hh +++ b/src/arch/mips/regfile/regfile.hh @@ -173,6 +173,11 @@ namespace MipsISA } }; + static inline int flattenIntIndex(ThreadContext * tc, int reg) + { + return reg; + } + void copyRegs(ThreadContext *src, ThreadContext *dest); void copyMiscRegs(ThreadContext *src, ThreadContext *dest); diff --git a/src/arch/mips/remote_gdb.hh b/src/arch/mips/remote_gdb.hh new file mode 100644 index 000000000..5886ab849 --- /dev/null +++ b/src/arch/mips/remote_gdb.hh @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * 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: Nathan Binkert + */ + +#ifndef __ARCH_MIPS_REMOTE_GDB_HH__ +#define __ARCH_MIPS_REMOTE_GDB_HH__ + +#include "base/remote_gdb.hh" + +namespace MipsISA +{ + class RemoteGDB : public BaseRemoteGDB + { + public: + //These needs to be written to suit MIPS + + RemoteGDB(System *system, ThreadContext *context) + : BaseRemoteGDB(system, context, 1) + {} + + bool acc(Addr, size_t) + { panic("acc not implemented for MIPS!"); } + + void getregs() + { panic("getregs not implemented for MIPS!"); } + + void setregs() + { panic("setregs not implemented for MIPS!"); } + + void clearSingleStep() + { panic("clearSingleStep not implemented for MIPS!"); } + + void setSingleStep() + { panic("setSingleStep not implemented for MIPS!"); } + }; +} + +#endif /* __ARCH_ALPHA_REMOTE_GDB_H__ */ diff --git a/src/arch/mips/syscallreturn.hh b/src/arch/mips/syscallreturn.hh index ef1093caf..47290b634 100644 --- a/src/arch/mips/syscallreturn.hh +++ b/src/arch/mips/syscallreturn.hh @@ -32,51 +32,22 @@ #ifndef __ARCH_MIPS_SYSCALLRETURN_HH__ #define __ARCH_MIPS_SYSCALLRETURN_HH__ -class SyscallReturn { - public: - template <class T> - SyscallReturn(T v, bool s) - { - retval = (uint32_t)v; - success = s; - } - - template <class T> - SyscallReturn(T v) - { - success = (v >= 0); - retval = (uint32_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 "sim/syscallreturn.hh" +#include "cpu/thread_context.hh" namespace MipsISA { - static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs) + static inline void setSyscallReturn(SyscallReturn return_value, + ThreadContext *tc) { if (return_value.successful()) { // no error - regs->setIntReg(SyscallSuccessReg, 0); - regs->setIntReg(ReturnValueReg1, return_value.value()); + tc->setIntReg(SyscallSuccessReg, 0); + tc->setIntReg(ReturnValueReg1, return_value.value()); } else { // got an error, return details - regs->setIntReg(SyscallSuccessReg, (IntReg) -1); - regs->setIntReg(ReturnValueReg1, -return_value.value()); + tc->setIntReg(SyscallSuccessReg, (IntReg) -1); + tc->setIntReg(ReturnValueReg1, -return_value.value()); } } } 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 diff --git a/src/base/compiler.hh b/src/base/compiler.hh new file mode 100644 index 000000000..dc23ed7b3 --- /dev/null +++ b/src/base/compiler.hh @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * 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 + */ + +#ifndef __BASE_COMPILER_HH__ +#define __BASE_COMPILER_HH__ + +//http://msdn2.microsoft.com/en-us/library/ms937669.aspx +//http://msdn2.microsoft.com/en-us/library/aa448724.aspx +//http://docs.sun.com/source/819-3688/sun.specific.html#marker-998278 +//http://gcc.gnu.org/onlinedocs/gcc-3.3.1/gcc/Function-Attributes.html#Function%20Attributes + +#if defined(__GNUC__) +#define M5_ATTR_NORETURN __attribute__((noreturn)) +#define M5_PRAGMA_NORETURN(x) +#define M5_DUMMY_RETURN +#elif defined(__SUNPRO_CC) +// this doesn't do anything with sun cc, but why not +#define M5_ATTR_NORETURN __sun_attr__((__noreturn__)) +#define M5_DUMMY_RETURN return (0); +#define DO_PRAGMA(x) _Pragma(#x) +#define M5_PRAGMA_NORETURN(x) DO_PRAGMA(does_not_return(x)) +#else +#error "Need to define compiler options in base/compiler.hh" +#endif + +#endif // __BASE_COMPILER_HH__ diff --git a/src/base/compression/lzss_compression.cc b/src/base/compression/lzss_compression.cc index eb35fb8f1..bd16d82c9 100644 --- a/src/base/compression/lzss_compression.cc +++ b/src/base/compression/lzss_compression.cc @@ -32,8 +32,8 @@ * LZSSCompression definitions. */ -#include <assert.h> - +#include <cassert> +#include <cstring> #include "base/compression/lzss_compression.hh" #include "base/misc.hh" //for fatal @@ -134,7 +134,7 @@ LZSSCompression::compress(uint8_t *dest, uint8_t *src, int size) if (dest_index >= size) { // Have expansion instead of compression, just copy. - memcpy(dest,src,size); + std::memcpy(dest,src,size); return size; } return dest_index; diff --git a/src/base/compression/null_compression.hh b/src/base/compression/null_compression.hh index ff110807a..798acb77a 100644 --- a/src/base/compression/null_compression.hh +++ b/src/base/compression/null_compression.hh @@ -50,11 +50,13 @@ class NullCompression : public CompressionAlgorithm int uncompress(uint8_t * dest, uint8_t *src, int size) { fatal("Can't uncompress data"); + M5_DUMMY_RETURN } int compress(uint8_t *dest, uint8_t *src, int size) { fatal("Can't compress data"); + M5_DUMMY_RETURN } }; diff --git a/src/base/cprintf.hh b/src/base/cprintf.hh index 9967b0578..dd2256e69 100644 --- a/src/base/cprintf.hh +++ b/src/base/cprintf.hh @@ -136,10 +136,10 @@ operator,(ArgList &alist, ArgListNull) inline void __cprintf(const std::string &format, ArgList &args) { args.dump(format); delete &args; } -#define __cprintf__(format, args...) \ - cp::__cprintf(format, (*(new cp::ArgList), args)) -#define cprintf(args...) \ - __cprintf__(args, cp::ArgListNull()) +#define __cprintf__(format, ...) \ + cp::__cprintf(format, (*(new cp::ArgList), __VA_ARGS__)) +#define cprintf(...) \ + __cprintf__(__VA_ARGS__, cp::ArgListNull()) // // ccprintf(stream, format, args, ...) prints to the specified stream @@ -148,10 +148,10 @@ __cprintf(const std::string &format, ArgList &args) inline void __ccprintf(std::ostream &stream, const std::string &format, ArgList &args) { args.dump(stream, format); delete &args; } -#define __ccprintf__(stream, format, args...) \ - cp::__ccprintf(stream, format, (*(new cp::ArgList), args)) -#define ccprintf(stream, args...) \ - __ccprintf__(stream, args, cp::ArgListNull()) +#define __ccprintf__(stream, format, ...) \ + cp::__ccprintf(stream, format, (*(new cp::ArgList), __VA_ARGS__)) +#define ccprintf(stream, ...) \ + __ccprintf__(stream, __VA_ARGS__, cp::ArgListNull()) // // csprintf(format, args, ...) returns a string @@ -160,10 +160,10 @@ __ccprintf(std::ostream &stream, const std::string &format, ArgList &args) inline std::string __csprintf(const std::string &format, ArgList &args) { std::string s = args.dumpToString(format); delete &args; return s; } -#define __csprintf__(format, args...) \ - cp::__csprintf(format, (*(new cp::ArgList), args)) -#define csprintf(args...) \ - __csprintf__(args, cp::ArgListNull()) +#define __csprintf__(format, ...) \ + cp::__csprintf(format, (*(new cp::ArgList), __VA_ARGS__)) +#define csprintf(...) \ + __csprintf__(__VA_ARGS__, cp::ArgListNull()) } diff --git a/src/base/cprintf_formats.hh b/src/base/cprintf_formats.hh index 3ea20446d..0af493217 100644 --- a/src/base/cprintf_formats.hh +++ b/src/base/cprintf_formats.hh @@ -84,21 +84,21 @@ _format_integer(std::ostream &out, const T &data, Format &fmt) switch (fmt.base) { case Format::hex: - out.setf(ios::hex, ios::basefield); + out.setf(std::ios::hex, std::ios::basefield); break; case Format::oct: - out.setf(ios::oct, ios::basefield); + out.setf(std::ios::oct, std::ios::basefield); break; case Format::dec: - out.setf(ios::dec, ios::basefield); + out.setf(std::ios::dec, std::ios::basefield); break; } if (fmt.alternate_form) { if (!fmt.fill_zero) - out.setf(ios::showbase); + out.setf(std::ios::showbase); else { switch (fmt.base) { case Format::hex: @@ -122,13 +122,13 @@ _format_integer(std::ostream &out, const T &data, Format &fmt) out.width(fmt.width); if (fmt.flush_left && !fmt.fill_zero) - out.setf(ios::left); + out.setf(std::ios::left); if (fmt.print_sign) - out.setf(ios::showpos); + out.setf(std::ios::showpos); if (fmt.uppercase) - out.setf(ios::uppercase); + out.setf(std::ios::uppercase); out << data; } @@ -148,7 +148,7 @@ _format_float(std::ostream &out, const T &data, Format &fmt) if (fmt.precision == 0) fmt.precision = 1; else - out.setf(ios::scientific); + out.setf(std::ios::scientific); out.precision(fmt.precision); } else @@ -156,7 +156,7 @@ _format_float(std::ostream &out, const T &data, Format &fmt) out.width(fmt.width); if (fmt.uppercase) - out.setf(ios::uppercase); + out.setf(std::ios::uppercase); break; case Format::fixed: @@ -164,7 +164,7 @@ _format_float(std::ostream &out, const T &data, Format &fmt) if (fmt.width > 0) out.width(fmt.width); - out.setf(ios::fixed); + out.setf(std::ios::fixed); out.precision(fmt.precision); } else if (fmt.width > 0) @@ -216,7 +216,7 @@ _format_string(std::ostream &out, const T &data, Format &fmt) if (fmt.width > 0) out.width(fmt.width); if (fmt.flush_left) - out.setf(ios::left); + out.setf(std::ios::left); out << data; #endif diff --git a/src/base/hashmap.hh b/src/base/hashmap.hh index 570cbc152..b78cc02e8 100644 --- a/src/base/hashmap.hh +++ b/src/base/hashmap.hh @@ -59,7 +59,7 @@ namespace m5 { // namespace __hash_namespace { -#if !defined(__LP64__) && !defined(__alpha__) +#if !defined(__LP64__) && !defined(__alpha__) && !defined(__SUNPRO_CC) template<> struct hash<uint64_t> { size_t operator()(uint64_t r) const { diff --git a/src/base/hostinfo.cc b/src/base/hostinfo.cc index a7c93e712..7cc07c11e 100644 --- a/src/base/hostinfo.cc +++ b/src/base/hostinfo.cc @@ -33,6 +33,7 @@ #include <math.h> #include <unistd.h> +#include <stdio.h> #include <cstdlib> #include <cstring> #include <string> diff --git a/src/base/loader/object_file.cc b/src/base/loader/object_file.cc index da5aa9552..7424b9305 100644 --- a/src/base/loader/object_file.cc +++ b/src/base/loader/object_file.cc @@ -101,7 +101,7 @@ ObjectFile::close() } if (fileData) { - ::munmap(fileData, len); + ::munmap((char*)fileData, len); fileData = NULL; } } @@ -147,7 +147,7 @@ createObjectFile(const string &fname, bool raw) // don't know what it is close(fd); - munmap(fileData, len); + munmap((char*)fileData, len); return NULL; } diff --git a/src/base/misc.hh b/src/base/misc.hh index 1c5720ce1..c12c2fe20 100644 --- a/src/base/misc.hh +++ b/src/base/misc.hh @@ -33,8 +33,13 @@ #define __MISC_HH__ #include <assert.h> +#include "base/compiler.hh" #include "base/cprintf.hh" +#if defined(__SUNPRO_CC) +#define __FUNCTION__ "how to fix me?" +#endif + // // This implements a cprintf based panic() function. panic() should // be called when something happens that should never ever happen @@ -43,12 +48,13 @@ // // void __panic(const std::string&, cp::ArgList &, const char*, const char*, int) - __attribute__((noreturn)); -#define __panic__(format, args...) \ - __panic(format, (*(new cp::ArgList), args), \ - __FUNCTION__, __FILE__, __LINE__) -#define panic(args...) \ - __panic__(args, cp::ArgListNull()) + M5_ATTR_NORETURN; +#define __panic__(format, ...) \ + __panic(format, (*(new cp::ArgList), __VA_ARGS__), \ + __FUNCTION__ , __FILE__, __LINE__) +#define panic(...) \ + __panic__(__VA_ARGS__, cp::ArgListNull()) +M5_PRAGMA_NORETURN(__panic) // // This implements a cprintf based fatal() function. fatal() should @@ -59,32 +65,33 @@ void __panic(const std::string&, cp::ArgList &, const char*, const char*, int) // panic() does. // void __fatal(const std::string&, cp::ArgList &, const char*, const char*, int) - __attribute__((noreturn)); -#define __fatal__(format, args...) \ - __fatal(format, (*(new cp::ArgList), args), \ - __FUNCTION__, __FILE__, __LINE__) -#define fatal(args...) \ - __fatal__(args, cp::ArgListNull()) + M5_ATTR_NORETURN; +#define __fatal__(format, ...) \ + __fatal(format, (*(new cp::ArgList), __VA_ARGS__), \ + __FUNCTION__ , __FILE__, __LINE__) +#define fatal(...) \ + __fatal__(__VA_ARGS__, cp::ArgListNull()) +M5_PRAGMA_NORETURN(__fatal) // // This implements a cprintf based warn // void __warn(const std::string&, cp::ArgList &, const char*, const char*, int); -#define __warn__(format, args...) \ - __warn(format, (*(new cp::ArgList), args), \ - __FUNCTION__, __FILE__, __LINE__) -#define warn(args...) \ - __warn__(args, cp::ArgListNull()) +#define __warn__(format, ...) \ + __warn(format, (*(new cp::ArgList), __VA_ARGS__), \ + __FUNCTION__ , __FILE__, __LINE__) +#define warn(...) \ + __warn__(__VA_ARGS__, cp::ArgListNull()) // Only print the warning message the first time it is seen. This // doesn't check the warning string itself, it just only lets one // warning come from the statement. So, even if the arguments change // and that would have resulted in a different warning message, // subsequent messages would still be supressed. -#define warn_once(args...) do { \ +#define warn_once(...) do { \ static bool once = false; \ if (!once) { \ - __warn__(args, cp::ArgListNull()); \ + __warn__(__VA_ARGS__, cp::ArgListNull()); \ once = true; \ } \ } while (0) diff --git a/src/base/pollevent.cc b/src/base/pollevent.cc index fd5b09d28..32724b74d 100644 --- a/src/base/pollevent.cc +++ b/src/base/pollevent.cc @@ -30,7 +30,7 @@ #include <sys/ioctl.h> #include <sys/types.h> -#if defined(__sun__) +#if defined(__sun__) || defined(__SUNPRO_CC) #include <sys/file.h> #endif diff --git a/src/base/random.cc b/src/base/random.cc index 82c9e3566..0ccedcb00 100644 --- a/src/base/random.cc +++ b/src/base/random.cc @@ -29,12 +29,17 @@ * Ali Saidi */ +#if defined(__sun) +#include <ieeefp.h> +#endif +#ifdef __SUNPRO_CC +#include <stdlib.h> +#include <math.h> +#endif + #include <cstdlib> #include <cmath> -#if defined(__sun__) -#include <ieeefp.h> -#endif #include "sim/param.hh" #include "base/random.hh" @@ -72,7 +77,7 @@ getLong() double m5round(double r) { -#if defined(__sun__) +#if defined(__sun) double val; fp_rnd oldrnd = fpsetround(FP_RN); val = rint(r); diff --git a/src/base/remote_gdb.cc b/src/base/remote_gdb.cc index 59a9b87d5..b28beba89 100644 --- a/src/base/remote_gdb.cc +++ b/src/base/remote_gdb.cc @@ -121,16 +121,21 @@ #include <string> #include <unistd.h> +#include "config/full_system.hh" + +#if FULL_SYSTEM #include "arch/vtophys.hh" +#endif + #include "base/intmath.hh" #include "base/remote_gdb.hh" #include "base/socket.hh" #include "base/trace.hh" -#include "config/full_system.hh" #include "cpu/thread_context.hh" #include "cpu/static_inst.hh" -#include "mem/physical.hh" +//#include "mem/physical.hh" #include "mem/port.hh" +#include "mem/translating_port.hh" #include "sim/system.hh" using namespace std; @@ -448,9 +453,17 @@ BaseRemoteGDB::read(Addr vaddr, size_t size, char *data) DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size); - VirtualPort *vp = context->getVirtPort(context); - vp->readBlob(vaddr, (uint8_t*)data, size); - context->delVirtPort(vp); +#if FULL_SYSTEM + VirtualPort *port = context->getVirtPort(context); +#else + TranslatingPort *port = context->getMemPort(); +#endif + port->readBlob(vaddr, (uint8_t*)data, size); +#if FULL_SYSTEM + context->delVirtPort(port); +#else + delete port; +#endif #if TRACING_ON if (DTRACE(GDBRead)) { @@ -487,9 +500,17 @@ BaseRemoteGDB::write(Addr vaddr, size_t size, const char *data) } else DPRINTFNR("\n"); } - VirtualPort *vp = context->getVirtPort(context); - vp->writeBlob(vaddr, (uint8_t*)data, size); - context->delVirtPort(vp); +#if FULL_SYSTEM + VirtualPort *port = context->getVirtPort(context); +#else + TranslatingPort *port = context->getMemPort(); +#endif + port->writeBlob(vaddr, (uint8_t*)data, size); +#if FULL_SYSTEM + context->delVirtPort(port); +#else + delete port; +#endif return true; } @@ -610,7 +631,8 @@ BaseRemoteGDB::trap(int type) uint64_t val; size_t datalen, len; char data[GDBPacketBufLen + 1]; - char buffer[gdbregs.bytes() * 2 + 256]; + char *buffer; + int bufferSize; const char *p; char command, subcmd; string var; @@ -619,6 +641,9 @@ BaseRemoteGDB::trap(int type) if (!attached) return false; + bufferSize = gdbregs.bytes() * 2 + 256; + buffer = (char*)malloc(bufferSize); + DPRINTF(GDBMisc, "trap: PC=%#x NPC=%#x\n", context->readPC(), context->readNextPC()); @@ -638,7 +663,7 @@ BaseRemoteGDB::trap(int type) active = true; else // Tell remote host that an exception has occurred. - snprintf((char *)buffer, sizeof(buffer), "S%02x", type); + snprintf((char *)buffer, bufferSize, "S%02x", type); send(buffer); // Stick frame regs into our reg cache. @@ -656,13 +681,13 @@ BaseRemoteGDB::trap(int type) // if this command came from a running gdb, answer it -- // the other guy has no way of knowing if we're in or out // of this loop when he issues a "remote-signal". - snprintf((char *)buffer, sizeof(buffer), + snprintf((char *)buffer, bufferSize, "S%02x", type); send(buffer); continue; case GDBRegR: - if (2 * gdbregs.bytes() > sizeof(buffer)) + if (2 * gdbregs.bytes() > bufferSize) panic("buffer too small"); mem2hex(buffer, gdbregs.regs, gdbregs.bytes()); @@ -709,7 +734,7 @@ BaseRemoteGDB::trap(int type) send("E03"); continue; } - if (len > sizeof(buffer)) { + if (len > bufferSize) { send("E04"); continue; } @@ -745,7 +770,7 @@ BaseRemoteGDB::trap(int type) send("E08"); continue; } - p = hex2mem(buffer, p, sizeof(buffer)); + p = hex2mem(buffer, p, bufferSize); if (p == NULL) { send("E09"); continue; @@ -916,6 +941,7 @@ BaseRemoteGDB::trap(int type) } out: + free(buffer); return true; } diff --git a/src/base/remote_gdb.hh b/src/base/remote_gdb.hh index 9a3201c95..92e599585 100644 --- a/src/base/remote_gdb.hh +++ b/src/base/remote_gdb.hh @@ -32,6 +32,7 @@ #define __REMOTE_GDB_HH__ #include <map> +#include <sys/signal.h> #include "arch/types.hh" #include "cpu/pc_event.hh" @@ -177,6 +178,10 @@ class BaseRemoteGDB virtual bool acc(Addr addr, size_t len) = 0; bool trap(int type); + virtual bool breakpoint() + { + return trap(SIGTRAP); + } protected: virtual void getregs() = 0; diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 577ea5eab..2b1b327e5 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -50,6 +50,9 @@ #include <algorithm> #include <cassert> +#ifdef __SUNPRO_CC +#include <math.h> +#endif #include <cmath> #include <functional> #include <iosfwd> @@ -395,7 +398,7 @@ class Wrap : public Child public: Wrap() { - map(new Data<Child>(*this)); + this->map(new Data<Child>(*this)); } /** @@ -1410,7 +1413,7 @@ struct DistStor else if (val > params.max) overflow += number; else { - int index = (int)floor((val - params.min) / params.bucket_size); + int index = (int)std::floor((val - params.min) / params.bucket_size); assert(index < size(params)); cvec[index] += number; } diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc index c4448efc9..ae0d65537 100644 --- a/src/base/stats/text.cc +++ b/src/base/stats/text.cc @@ -32,6 +32,10 @@ #define _GLIBCPP_USE_C99 1 #endif +#if defined(__sun) +#include <math.h> +#endif + #include <iostream> #include <sstream> #include <fstream> diff --git a/src/base/time.cc b/src/base/time.cc index cbc7256ee..76ba355b7 100644 --- a/src/base/time.cc +++ b/src/base/time.cc @@ -105,7 +105,11 @@ Time::date(string format) const char buf[256]; if (format.empty()) { +#ifdef __SUNPRO_CC + ctime_r(&sec, buf, 256); +#else ctime_r(&sec, buf); +#endif buf[24] = '\0'; return buf; } diff --git a/src/base/time.hh b/src/base/time.hh index 7aa4c50db..f10cc5d6c 100644 --- a/src/base/time.hh +++ b/src/base/time.hh @@ -97,7 +97,7 @@ std::ostream &operator<<(std::ostream &out, const Time &time); * @(#)time.h 8.2 (Berkeley) 7/10/94 */ -#if defined(__sun__) +#if defined(__sun) #define timersub(tvp, uvp, vvp) \ do { \ (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ diff --git a/src/base/timebuf.hh b/src/base/timebuf.hh index 1d0de8278..348f7a673 100644 --- a/src/base/timebuf.hh +++ b/src/base/timebuf.hh @@ -33,6 +33,7 @@ #define __BASE_TIMEBUF_HH__ #include <cassert> +#include <cstring> #include <vector> template <class T> @@ -143,7 +144,7 @@ class TimeBuffer char *ptr = data; for (int i = 0; i < size; i++) { index[i] = ptr; - memset(ptr, 0, sizeof(T)); + std::memset(ptr, 0, sizeof(T)); new (ptr) T; ptr += sizeof(T); } @@ -171,7 +172,7 @@ class TimeBuffer if (ptr >= size) ptr -= size; (reinterpret_cast<T *>(index[ptr]))->~T(); - memset(index[ptr], 0, sizeof(T)); + std::memset(index[ptr], 0, sizeof(T)); new (index[ptr]) T; } diff --git a/src/base/trace.hh b/src/base/trace.hh index 9b053990c..a46643159 100644 --- a/src/base/trace.hh +++ b/src/base/trace.hh @@ -186,39 +186,39 @@ do { \ Trace::dataDump(curTick, name(), data, count); \ } while (0) -#define __dprintf(cycle, name, format, args...) \ - Trace::dprintf(format, (*(new cp::ArgList), args), cycle, name) +#define __dprintf(cycle, name, format, ...) \ + Trace::dprintf(format, (*(new cp::ArgList), __VA_ARGS__), cycle, name) -#define DPRINTF(x, args...) \ +#define DPRINTF(x, ...) \ do { \ if (Trace::IsOn(Trace::x)) \ - __dprintf(curTick, name(), args, cp::ArgListNull()); \ + __dprintf(curTick, name(), __VA_ARGS__, cp::ArgListNull()); \ } while (0) -#define DPRINTFR(x, args...) \ +#define DPRINTFR(x, ...) \ do { \ if (Trace::IsOn(Trace::x)) \ - __dprintf((Tick)-1, std::string(), args, cp::ArgListNull()); \ + __dprintf((Tick)-1, std::string(), __VA_ARGS__, cp::ArgListNull()); \ } while (0) -#define DPRINTFN(args...) \ +#define DPRINTFN(...) \ do { \ - __dprintf(curTick, name(), args, cp::ArgListNull()); \ + __dprintf(curTick, name(), __VA_ARGS__, cp::ArgListNull()); \ } while (0) -#define DPRINTFNR(args...) \ +#define DPRINTFNR(...) \ do { \ - __dprintf((Tick)-1, string(), args, cp::ArgListNull()); \ + __dprintf((Tick)-1, string(), __VA_ARGS__, cp::ArgListNull()); \ } while (0) #else // !TRACING_ON #define DTRACE(x) (false) #define DCOUT(x) if (0) DebugOut() -#define DPRINTF(x, args...) do {} while (0) -#define DPRINTFR(args...) do {} while (0) -#define DPRINTFN(args...) do {} while (0) -#define DPRINTFNR(args...) do {} while (0) +#define DPRINTF(x, ...) do {} while (0) +#define DPRINTFR(...) do {} while (0) +#define DPRINTFN(...) do {} while (0) +#define DPRINTFNR(...) do {} while (0) #define DDUMP(x, data, count) do {} while (0) #endif // TRACING_ON diff --git a/src/cpu/SConscript b/src/cpu/SConscript index 5771a7904..4d4b7574c 100644 --- a/src/cpu/SConscript +++ b/src/cpu/SConscript @@ -54,18 +54,18 @@ execfile(models_db.srcnode().abspath) exec_sig_template = ''' virtual Fault execute(%s *xc, Trace::InstRecord *traceData) const = 0; virtual Fault initiateAcc(%s *xc, Trace::InstRecord *traceData) const -{ panic("initiateAcc not defined!"); }; +{ panic("initiateAcc not defined!"); M5_DUMMY_RETURN }; virtual Fault completeAcc(Packet *pkt, %s *xc, Trace::InstRecord *traceData) const -{ panic("completeAcc not defined!"); }; +{ panic("completeAcc not defined!"); M5_DUMMY_RETURN }; ''' mem_ini_sig_template = ''' -virtual Fault initiateAcc(%s *xc, Trace::InstRecord *traceData) const { panic("Not defined!"); }; +virtual Fault initiateAcc(%s *xc, Trace::InstRecord *traceData) const { panic("Not defined!"); M5_DUMMY_RETURN }; ''' mem_comp_sig_template = ''' -virtual Fault completeAcc(uint8_t *data, %s *xc, Trace::InstRecord *traceData) const { panic("Not defined!"); return NoFault; }; +virtual Fault completeAcc(uint8_t *data, %s *xc, Trace::InstRecord *traceData) const { panic("Not defined!"); return NoFault; M5_DUMMY_RETURN }; ''' # Generate a temporary CPU list, including the CheckerCPU if diff --git a/src/cpu/activity.cc b/src/cpu/activity.cc index 9a0f6d98d..15e0556ad 100644 --- a/src/cpu/activity.cc +++ b/src/cpu/activity.cc @@ -28,6 +28,8 @@ * Authors: Kevin Lim */ +#include <cstring> + #include "base/timebuf.hh" #include "cpu/activity.hh" @@ -37,7 +39,7 @@ ActivityRecorder::ActivityRecorder(int num_stages, int longest_latency, activityCount(activity), numStages(num_stages) { stageActive = new bool[numStages]; - memset(stageActive, 0, numStages); + std::memset(stageActive, 0, numStages); } void @@ -114,7 +116,7 @@ void ActivityRecorder::reset() { activityCount = 0; - memset(stageActive, 0, numStages); + std::memset(stageActive, 0, numStages); for (int i = 0; i < longestLatency + 1; ++i) activityBuffer.advance(); } diff --git a/src/cpu/base.cc b/src/cpu/base.cc index deb4e02c4..8440d2320 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -298,6 +298,16 @@ BaseCPU::registerThreadContexts() } +int +BaseCPU::findContext(ThreadContext *tc) +{ + for (int i = 0; i < threadContexts.size(); ++i) { + if (tc == threadContexts[i]) + return i; + } + return 0; +} + void BaseCPU::switchOut() { @@ -389,12 +399,14 @@ BaseCPU::clear_interrupts() void BaseCPU::serialize(std::ostream &os) { + SERIALIZE_SCALAR(instCnt); interrupts.serialize(os); } void BaseCPU::unserialize(Checkpoint *cp, const std::string §ion) { + UNSERIALIZE_SCALAR(instCnt); interrupts.unserialize(cp, section); } diff --git a/src/cpu/base.hh b/src/cpu/base.hh index 3ae9c60b6..a1265b748 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -142,6 +142,12 @@ class BaseCPU : public MemObject /// Notify the CPU that the indicated context is now halted. virtual void haltContext(int thread_num) {} + /// Given a Thread Context pointer return the thread num + int findContext(ThreadContext *tc); + + /// Given a thread num get tho thread context for it + ThreadContext *getContext(int tn) { return threadContexts[tn]; } + public: struct Params { diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index 9037c96df..515cd0836 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -39,6 +39,7 @@ #include "base/fast_alloc.hh" #include "base/trace.hh" #include "config/full_system.hh" +#include "cpu/o3/comm.hh" #include "cpu/exetrace.hh" #include "cpu/inst_seq.hh" #include "cpu/op_class.hh" @@ -62,10 +63,6 @@ class BaseDynInst : public FastAlloc, public RefCounted typedef typename Impl::CPUType ImplCPU; typedef typename ImplCPU::ImplState ImplState; - // Binary machine instruction type. - typedef TheISA::MachInst MachInst; - // Extended machine instruction type - typedef TheISA::ExtMachInst ExtMachInst; // Logical register index type. typedef TheISA::RegIndex RegIndex; // Integer register type. @@ -212,6 +209,7 @@ class BaseDynInst : public FastAlloc, public RefCounted /** PC of this instruction. */ Addr PC; + protected: /** Next non-speculative PC. It is not filled in at fetch, but rather * once the target of the branch is truly known (either decode or * execute). @@ -224,6 +222,14 @@ class BaseDynInst : public FastAlloc, public RefCounted /** Predicted next PC. */ Addr predPC; + /** Predicted next NPC. */ + Addr predNPC; + + /** If this is a branch that was predicted taken */ + bool predTaken; + + public: + /** Count of total number of dynamic instructions. */ static int instcount; @@ -236,16 +242,116 @@ class BaseDynInst : public FastAlloc, public RefCounted */ bool _readySrcRegIdx[MaxInstSrcRegs]; + protected: + /** Flattened register index of the destination registers of this + * instruction. + */ + TheISA::RegIndex _flatDestRegIdx[TheISA::MaxInstDestRegs]; + + /** Flattened register index of the source registers of this + * instruction. + */ + TheISA::RegIndex _flatSrcRegIdx[TheISA::MaxInstSrcRegs]; + + /** Physical register index of the destination registers of this + * instruction. + */ + PhysRegIndex _destRegIdx[TheISA::MaxInstDestRegs]; + + /** Physical register index of the source registers of this + * instruction. + */ + PhysRegIndex _srcRegIdx[TheISA::MaxInstSrcRegs]; + + /** Physical register index of the previous producers of the + * architected destinations. + */ + PhysRegIndex _prevDestRegIdx[TheISA::MaxInstDestRegs]; + public: + + /** Returns the physical register index of the i'th destination + * register. + */ + PhysRegIndex renamedDestRegIdx(int idx) const + { + return _destRegIdx[idx]; + } + + /** Returns the physical register index of the i'th source register. */ + PhysRegIndex renamedSrcRegIdx(int idx) const + { + return _srcRegIdx[idx]; + } + + /** Returns the flattened register index of the i'th destination + * register. + */ + TheISA::RegIndex flattenedDestRegIdx(int idx) const + { + return _flatDestRegIdx[idx]; + } + + /** Returns the flattened register index of the i'th source register */ + TheISA::RegIndex flattenedSrcRegIdx(int idx) const + { + return _flatSrcRegIdx[idx]; + } + + /** Returns the physical register index of the previous physical register + * that remapped to the same logical register index. + */ + PhysRegIndex prevDestRegIdx(int idx) const + { + return _prevDestRegIdx[idx]; + } + + /** Renames a destination register to a physical register. Also records + * the previous physical register that the logical register mapped to. + */ + void renameDestReg(int idx, + PhysRegIndex renamed_dest, + PhysRegIndex previous_rename) + { + _destRegIdx[idx] = renamed_dest; + _prevDestRegIdx[idx] = previous_rename; + } + + /** Renames a source logical register to the physical register which + * has/will produce that logical register's result. + * @todo: add in whether or not the source register is ready. + */ + void renameSrcReg(int idx, PhysRegIndex renamed_src) + { + _srcRegIdx[idx] = renamed_src; + } + + /** Flattens a source architectural register index into a logical index. + */ + void flattenSrcReg(int idx, TheISA::RegIndex flattened_src) + { + _flatSrcRegIdx[idx] = flattened_src; + } + + /** Flattens a destination architectural register index into a logical + * index. + */ + void flattenDestReg(int idx, TheISA::RegIndex flattened_dest) + { + _flatDestRegIdx[idx] = flattened_dest; + } + /** BaseDynInst constructor given a binary instruction. * @param inst The binary instruction. * @param PC The PC of the instruction. * @param pred_PC The predicted next PC. + * @param pred_NPC The predicted next NPC. * @param seq_num The sequence number of the instruction. * @param cpu Pointer to the instruction's CPU. */ - BaseDynInst(ExtMachInst inst, Addr PC, Addr pred_PC, InstSeqNum seq_num, - ImplCPU *cpu); + BaseDynInst(TheISA::ExtMachInst inst, Addr PC, Addr NPC, + Addr pred_PC, Addr pred_NPC, + InstSeqNum seq_num, ImplCPU *cpu); /** BaseDynInst constructor given a StaticInst pointer. * @param _staticInst The StaticInst for this BaseDynInst. @@ -287,29 +393,46 @@ class BaseDynInst : public FastAlloc, public RefCounted /** Returns the next NPC. This could be the speculative next NPC if it is * called prior to the actual branch target being calculated. */ - Addr readNextNPC() { return nextNPC; } + Addr readNextNPC() + { +#if ISA_HAS_DELAY_SLOT + return nextNPC; +#else + return nextPC + sizeof(TheISA::MachInst); +#endif + } /** Set the predicted target of this current instruction. */ - void setPredTarg(Addr predicted_PC) { predPC = predicted_PC; } + void setPredTarg(Addr predicted_PC, Addr predicted_NPC) + { + predPC = predicted_PC; + predNPC = predicted_NPC; + } + + /** Returns the predicted PC immediately after the branch. */ + Addr readPredPC() { return predPC; } - /** Returns the predicted target of the branch. */ - Addr readPredTarg() { return predPC; } + /** Returns the predicted PC two instructions after the branch */ + Addr readPredNPC() { return predNPC; } /** Returns whether the instruction was predicted taken or not. */ - bool predTaken() -#if ISA_HAS_DELAY_SLOT - { return predPC != (nextPC + sizeof(MachInst)); } -#else - { return predPC != (PC + sizeof(MachInst)); } -#endif + bool readPredTaken() + { + return predTaken; + } + + void setPredTaken(bool predicted_taken) + { + predTaken = predicted_taken; + } /** Returns whether the instruction mispredicted. */ bool mispredicted() -#if ISA_HAS_DELAY_SLOT - { return predPC != nextNPC; } -#else - { return predPC != nextPC; } -#endif + { + return readPredPC() != readNextPC() || + readPredNPC() != readNextNPC(); + } + // // Instruction types. Forward checks to StaticInst object. // diff --git a/src/cpu/base_dyn_inst_impl.hh b/src/cpu/base_dyn_inst_impl.hh index 2f6859de2..c3d71e428 100644 --- a/src/cpu/base_dyn_inst_impl.hh +++ b/src/cpu/base_dyn_inst_impl.hh @@ -62,17 +62,20 @@ my_hash_t thishash; #endif template <class Impl> -BaseDynInst<Impl>::BaseDynInst(TheISA::ExtMachInst machInst, Addr inst_PC, - Addr pred_PC, InstSeqNum seq_num, - ImplCPU *cpu) +BaseDynInst<Impl>::BaseDynInst(TheISA::ExtMachInst machInst, + Addr inst_PC, Addr inst_NPC, + Addr pred_PC, Addr pred_NPC, + InstSeqNum seq_num, ImplCPU *cpu) : staticInst(machInst), traceData(NULL), cpu(cpu) { seqNum = seq_num; PC = inst_PC; - nextPC = PC + sizeof(TheISA::MachInst); + nextPC = inst_NPC; nextNPC = nextPC + sizeof(TheISA::MachInst); predPC = pred_PC; + predNPC = pred_NPC; + predTaken = false; initVars(); } diff --git a/src/cpu/cpuevent.hh b/src/cpu/cpuevent.hh index c973621c0..5816c6ca1 100644 --- a/src/cpu/cpuevent.hh +++ b/src/cpu/cpuevent.hh @@ -71,6 +71,7 @@ class CpuEvent : public Event */ static void replaceThreadContext(ThreadContext *oldTc, ThreadContext *newTc); + ThreadContext* getTC() { return tc; } }; template <class T, void (T::* F)(ThreadContext *tc)> diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 26e8b6b44..e34ae3731 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -147,13 +147,15 @@ Trace::InstRecord::dump(ostream &outs) outs << hex; outs << "PC = " << thread->readNextPC(); outs << " NPC = " << thread->readNextNPC(); - newVal = thread->readMiscReg(SparcISA::MISCREG_CCR); + newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2); + //newVal = thread->readMiscReg(SparcISA::MISCREG_CCR); if(newVal != ccr) { outs << " CCR = " << newVal; ccr = newVal; } - newVal = thread->readMiscReg(SparcISA::MISCREG_Y); + newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 1); + //newVal = thread->readMiscReg(SparcISA::MISCREG_Y); if(newVal != y) { outs << " Y = " << newVal; @@ -293,7 +295,8 @@ Trace::InstRecord::dump(ostream &outs) bool diffPC = false; bool diffCC = false; bool diffInst = false; - bool diffRegs = false; + bool diffIntRegs = false; + bool diffFpRegs = false; bool diffTpc = false; bool diffTnpc = false; bool diffTstate = false; @@ -304,6 +307,7 @@ Trace::InstRecord::dump(ostream &outs) bool diffHtba = false; bool diffPstate = false; bool diffY = false; + bool diffFsr = false; bool diffCcr = false; bool diffTl = false; bool diffGl = false; @@ -355,12 +359,18 @@ Trace::InstRecord::dump(ostream &outs) (SparcISA::MachInst)staticInst->machInst) { diffInst = true; } - for (int i = 0; i < TheISA::NumIntArchRegs; i++) { + // assume we have %g0 working correctly + for (int i = 1; i < TheISA::NumIntArchRegs; i++) { if (thread->readIntReg(i) != shared_data->intregs[i]) { - diffRegs = true; + diffIntRegs = true; } } - uint64_t oldTl = thread->readMiscReg(MISCREG_TL); + for (int i = 0; i < TheISA::NumFloatRegs/2; i++) { + if (thread->readFloatRegBits(i*2,FloatRegFile::DoubleWidth) != shared_data->fpregs[i]) { + diffFpRegs = true; + } + } + uint64_t oldTl = thread->readMiscReg(MISCREG_TL); if (oldTl != shared_data->tl) diffTl = true; for (int i = 1; i <= MaxTL; i++) { @@ -397,9 +407,15 @@ Trace::InstRecord::dump(ostream &outs) diffHtba = true; if(shared_data->pstate != thread->readMiscReg(MISCREG_PSTATE)) diffPstate = true; - if(shared_data->y != thread->readMiscReg(MISCREG_Y)) + //if(shared_data->y != thread->readMiscReg(MISCREG_Y)) + if(shared_data->y != + thread->readIntReg(NumIntArchRegs + 1)) diffY = true; - if(shared_data->ccr != thread->readMiscReg(MISCREG_CCR)) + if(shared_data->fsr != thread->readMiscReg(MISCREG_FSR)) + diffFsr = true; + //if(shared_data->ccr != thread->readMiscReg(MISCREG_CCR)) + if(shared_data->ccr != + thread->readIntReg(NumIntArchRegs + 2)) diffCcr = true; if(shared_data->gl != thread->readMiscReg(MISCREG_GL)) diffGl = true; @@ -409,14 +425,22 @@ Trace::InstRecord::dump(ostream &outs) diffPil = true; if(shared_data->cwp != thread->readMiscReg(MISCREG_CWP)) diffCwp = true; - if(shared_data->cansave != thread->readMiscReg(MISCREG_CANSAVE)) + //if(shared_data->cansave != thread->readMiscReg(MISCREG_CANSAVE)) + if(shared_data->cansave != + thread->readIntReg(NumIntArchRegs + 3)) diffCansave = true; + //if(shared_data->canrestore != + // thread->readMiscReg(MISCREG_CANRESTORE)) if(shared_data->canrestore != - thread->readMiscReg(MISCREG_CANRESTORE)) + thread->readIntReg(NumIntArchRegs + 4)) diffCanrestore = true; - if(shared_data->otherwin != thread->readMiscReg(MISCREG_OTHERWIN)) + //if(shared_data->otherwin != thread->readMiscReg(MISCREG_OTHERWIN)) + if(shared_data->otherwin != + thread->readIntReg(NumIntArchRegs + 6)) diffOtherwin = true; - if(shared_data->cleanwin != thread->readMiscReg(MISCREG_CLEANWIN)) + //if(shared_data->cleanwin != thread->readMiscReg(MISCREG_CLEANWIN)) + if(shared_data->cleanwin != + thread->readIntReg(NumIntArchRegs + 5)) diffCleanwin = true; for (int i = 0; i < 64; i++) { @@ -426,12 +450,12 @@ Trace::InstRecord::dump(ostream &outs) diffTlb = true; } - if ((diffPC || diffCC || diffInst || diffRegs || diffTpc || - diffTnpc || diffTstate || diffTt || diffHpstate || - diffHtstate || diffHtba || diffPstate || diffY || - diffCcr || diffTl || diffGl || diffAsi || diffPil || - diffCwp || diffCansave || diffCanrestore || - diffOtherwin || diffCleanwin || diffTlb) + if ((diffPC || diffCC || diffInst || diffIntRegs || + diffFpRegs || diffTpc || diffTnpc || diffTstate || + diffTt || diffHpstate || diffHtstate || diffHtba || + diffPstate || diffY || diffCcr || diffTl || diffFsr || + diffGl || diffAsi || diffPil || diffCwp || diffCansave || + diffCanrestore || diffOtherwin || diffCleanwin || diffTlb) && !((staticInst->machInst & 0xC1F80000) == 0x81D00000) && !(((staticInst->machInst & 0xC0000000) == 0xC0000000) && shared_data->tl == thread->readMiscReg(MISCREG_TL) + 1) @@ -444,8 +468,10 @@ Trace::InstRecord::dump(ostream &outs) outs << " [CC]"; if (diffInst) outs << " [Instruction]"; - if (diffRegs) + if (diffIntRegs) outs << " [IntRegs]"; + if (diffFpRegs) + outs << " [FpRegs]"; if (diffTpc) outs << " [Tpc]"; if (diffTnpc) @@ -464,6 +490,8 @@ Trace::InstRecord::dump(ostream &outs) outs << " [Pstate]"; if (diffY) outs << " [Y]"; + if (diffFsr) + outs << " [FSR]"; if (diffCcr) outs << " [Ccr]"; if (diffTl) @@ -530,10 +558,15 @@ Trace::InstRecord::dump(ostream &outs) thread->readMiscReg(MISCREG_PSTATE), shared_data->pstate); printRegPair(outs, "Y", - thread->readMiscReg(MISCREG_Y), + //thread->readMiscReg(MISCREG_Y), + thread->readIntReg(NumIntArchRegs + 1), shared_data->y); + printRegPair(outs, "FSR", + thread->readMiscReg(MISCREG_FSR), + shared_data->fsr); printRegPair(outs, "Ccr", - thread->readMiscReg(MISCREG_CCR), + //thread->readMiscReg(MISCREG_CCR), + thread->readIntReg(NumIntArchRegs + 2), shared_data->ccr); printRegPair(outs, "Tl", thread->readMiscReg(MISCREG_TL), @@ -551,16 +584,20 @@ Trace::InstRecord::dump(ostream &outs) thread->readMiscReg(MISCREG_CWP), shared_data->cwp); printRegPair(outs, "Cansave", - thread->readMiscReg(MISCREG_CANSAVE), + //thread->readMiscReg(MISCREG_CANSAVE), + thread->readIntReg(NumIntArchRegs + 3), shared_data->cansave); printRegPair(outs, "Canrestore", - thread->readMiscReg(MISCREG_CANRESTORE), + //thread->readMiscReg(MISCREG_CANRESTORE), + thread->readIntReg(NumIntArchRegs + 4), shared_data->canrestore); printRegPair(outs, "Otherwin", - thread->readMiscReg(MISCREG_OTHERWIN), + //thread->readMiscReg(MISCREG_OTHERWIN), + thread->readIntReg(NumIntArchRegs + 6), shared_data->otherwin); printRegPair(outs, "Cleanwin", - thread->readMiscReg(MISCREG_CLEANWIN), + //thread->readMiscReg(MISCREG_CLEANWIN), + thread->readIntReg(NumIntArchRegs + 5), shared_data->cleanwin); outs << endl; for (int i = 1; i <= MaxTL; i++) { @@ -588,26 +625,22 @@ Trace::InstRecord::dump(ostream &outs) printSectionHeader(outs, "General Purpose Registers"); static const char * regtypes[4] = {"%g", "%o", "%l", "%i"}; - for(int y = 0; y < 4; y++) - { - for(int x = 0; x < 8; x++) - { + for(int y = 0; y < 4; y++) { + for(int x = 0; x < 8; x++) { char label[8]; sprintf(label, "%s%d", regtypes[y], x); printRegPair(outs, label, thread->readIntReg(y*8+x), shared_data->intregs[y*8+x]); - /*outs << regtypes[y] << x << " " ; - outs << "0x" << hex << setw(16) - << thread->readIntReg(y*8+x); - if (thread->readIntReg(y*8 + x) - != shared_data->intregs[y*8+x]) - outs << " X "; - else - outs << " | "; - outs << "0x" << setw(16) << hex - << shared_data->intregs[y*8+x] - << endl;*/ + } + } + if (diffFpRegs) { + for (int x = 0; x < 32; x++) { + char label[8]; + sprintf(label, "%%f%d", x); + printRegPair(outs, label, + thread->readFloatRegBits(x,FloatRegFile::DoubleWidth), + shared_data->fpregs[x]); } } if (diffTlb) { diff --git a/src/cpu/exetrace.hh b/src/cpu/exetrace.hh index 6562e5265..a825f6a82 100644 --- a/src/cpu/exetrace.hh +++ b/src/cpu/exetrace.hh @@ -32,6 +32,7 @@ #ifndef __EXETRACE_HH__ #define __EXETRACE_HH__ +#include <cstring> #include <fstream> #include <vector> @@ -169,7 +170,7 @@ InstRecord::setRegs(const IntRegFile ®s) if (!iregs) iregs = new iRegFile; - memcpy(&iregs->regs, ®s, sizeof(IntRegFile)); + std::memcpy(&iregs->regs, ®s, sizeof(IntRegFile)); regs_valid = true; } diff --git a/src/cpu/m5legion_interface.h b/src/cpu/m5legion_interface.h index c3ba5986e..373dc5cdc 100644 --- a/src/cpu/m5legion_interface.h +++ b/src/cpu/m5legion_interface.h @@ -1,5 +1,5 @@ /* - * 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 @@ -30,7 +30,7 @@ #include <unistd.h> -#define VERSION 0xA1000007 +#define VERSION 0xA1000009 #define OWN_M5 0x000000AA #define OWN_LEGION 0x00000055 @@ -47,6 +47,7 @@ typedef struct { uint32_t instruction; uint32_t new_instruction; uint64_t intregs[32]; + uint64_t fpregs[32]; uint64_t tpc[8]; uint64_t tnpc[8]; @@ -60,6 +61,7 @@ typedef struct { uint16_t pstate; uint64_t y; + uint64_t fsr; uint8_t ccr; uint8_t tl; uint8_t gl; diff --git a/src/cpu/o3/alpha/cpu.hh b/src/cpu/o3/alpha/cpu.hh index 0078db69f..4a2086296 100644 --- a/src/cpu/o3/alpha/cpu.hh +++ b/src/cpu/o3/alpha/cpu.hh @@ -37,12 +37,6 @@ #include "cpu/o3/cpu.hh" #include "sim/byteswap.hh" -namespace TheISA -{ - class ITB; - class DTB; -} - class EndQuiesceEvent; namespace Kernel { class Statistics; @@ -61,14 +55,6 @@ class TranslatingPort; template <class Impl> class AlphaO3CPU : public FullO3CPU<Impl> { - protected: - typedef TheISA::IntReg IntReg; - typedef TheISA::FloatReg FloatReg; - typedef TheISA::FloatRegBits FloatRegBits; - typedef TheISA::MiscReg MiscReg; - typedef TheISA::RegFile RegFile; - typedef TheISA::MiscRegFile MiscRegFile; - public: typedef O3ThreadState<Impl> ImplState; typedef O3ThreadState<Impl> Thread; @@ -77,13 +63,6 @@ class AlphaO3CPU : public FullO3CPU<Impl> /** Constructs an AlphaO3CPU with the given parameters. */ AlphaO3CPU(Params *params); -#if FULL_SYSTEM - /** ITB pointer. */ - AlphaISA::ITB *itb; - /** DTB pointer. */ - AlphaISA::DTB *dtb; -#endif - /** Registers statistics. */ void regStats(); @@ -91,19 +70,19 @@ class AlphaO3CPU : public FullO3CPU<Impl> /** Translates instruction requestion. */ Fault translateInstReq(RequestPtr &req, Thread *thread) { - return itb->translate(req, thread->getTC()); + return this->itb->translate(req, thread->getTC()); } /** Translates data read request. */ Fault translateDataReadReq(RequestPtr &req, Thread *thread) { - return dtb->translate(req, thread->getTC(), false); + return this->dtb->translate(req, thread->getTC(), false); } /** Translates data write request. */ Fault translateDataWriteReq(RequestPtr &req, Thread *thread) { - return dtb->translate(req, thread->getTC(), true); + return this->dtb->translate(req, thread->getTC(), true); } #else @@ -127,20 +106,22 @@ class AlphaO3CPU : public FullO3CPU<Impl> #endif /** Reads a miscellaneous register. */ - MiscReg readMiscReg(int misc_reg, unsigned tid); + TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid); /** Reads a misc. register, including any side effects the read * might have as defined by the architecture. */ - MiscReg readMiscRegWithEffect(int misc_reg, unsigned tid); + TheISA::MiscReg readMiscRegWithEffect(int misc_reg, unsigned tid); /** Sets a miscellaneous register. */ - void setMiscReg(int misc_reg, const MiscReg &val, unsigned tid); + void setMiscReg(int misc_reg, const TheISA::MiscReg &val, + unsigned tid); /** Sets a misc. register, including any side effects the write * might have as defined by the architecture. */ - void setMiscRegWithEffect(int misc_reg, const MiscReg &val, unsigned tid); + void setMiscRegWithEffect(int misc_reg, const TheISA::MiscReg &val, + unsigned tid); /** Initiates a squash of all in-flight instructions for a given * thread. The source of the squash is an external update of @@ -175,10 +156,10 @@ class AlphaO3CPU : public FullO3CPU<Impl> */ void syscall(int64_t callnum, int tid); /** Gets a syscall argument. */ - IntReg getSyscallArg(int i, int tid); + TheISA::IntReg getSyscallArg(int i, int tid); /** Used to shift args for indirect syscall. */ - void setSyscallArg(int i, IntReg val, int tid); + void setSyscallArg(int i, TheISA::IntReg val, int tid); /** Sets the return value of a syscall. */ void setSyscallReturn(SyscallReturn return_value, int tid); diff --git a/src/cpu/o3/alpha/cpu_impl.hh b/src/cpu/o3/alpha/cpu_impl.hh index 980e70fdd..41f149963 100644 --- a/src/cpu/o3/alpha/cpu_impl.hh +++ b/src/cpu/o3/alpha/cpu_impl.hh @@ -55,12 +55,7 @@ #endif template <class Impl> -AlphaO3CPU<Impl>::AlphaO3CPU(Params *params) -#if FULL_SYSTEM - : FullO3CPU<Impl>(params), itb(params->itb), dtb(params->dtb) -#else - : FullO3CPU<Impl>(params) -#endif +AlphaO3CPU<Impl>::AlphaO3CPU(Params *params) : FullO3CPU<Impl>(params) { DPRINTF(O3CPU, "Creating AlphaO3CPU object.\n"); @@ -173,15 +168,16 @@ AlphaO3CPU<Impl>::readMiscRegWithEffect(int misc_reg, unsigned tid) template <class Impl> void -AlphaO3CPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid) +AlphaO3CPU<Impl>::setMiscReg(int misc_reg, const TheISA::MiscReg &val, + unsigned tid) { this->regFile.setMiscReg(misc_reg, val, tid); } template <class Impl> void -AlphaO3CPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val, - unsigned tid) +AlphaO3CPU<Impl>::setMiscRegWithEffect(int misc_reg, + const TheISA::MiscReg &val, unsigned tid) { this->regFile.setMiscRegWithEffect(misc_reg, val, tid); } @@ -312,7 +308,7 @@ AlphaO3CPU<Impl>::getSyscallArg(int i, int tid) template <class Impl> void -AlphaO3CPU<Impl>::setSyscallArg(int i, IntReg val, int tid) +AlphaO3CPU<Impl>::setSyscallArg(int i, TheISA::IntReg val, int tid) { this->setArchIntReg(AlphaISA::ArgumentReg0 + i, val, tid); } @@ -321,17 +317,6 @@ template <class Impl> void AlphaO3CPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid) { - // check for error condition. Alpha syscall convention is to - // indicate success/failure in reg a3 (r19) and put the - // return value itself in the standard return value reg (v0). - if (return_value.successful()) { - // no error - this->setArchIntReg(TheISA::SyscallSuccessReg, 0, tid); - this->setArchIntReg(TheISA::ReturnValueReg, return_value.value(), tid); - } else { - // got an error, return details - this->setArchIntReg(TheISA::SyscallSuccessReg, (IntReg) -1, tid); - this->setArchIntReg(TheISA::ReturnValueReg, -return_value.value(), tid); - } + TheISA::setSyscallReturn(return_value, this->tcBase(tid)); } #endif diff --git a/src/cpu/o3/alpha/dyn_inst.hh b/src/cpu/o3/alpha/dyn_inst.hh index 49cc5a201..603a1b52d 100644 --- a/src/cpu/o3/alpha/dyn_inst.hh +++ b/src/cpu/o3/alpha/dyn_inst.hh @@ -73,8 +73,9 @@ class AlphaDynInst : public BaseDynInst<Impl> public: /** BaseDynInst constructor given a binary instruction. */ - AlphaDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC, InstSeqNum seq_num, - O3CPU *cpu); + AlphaDynInst(ExtMachInst inst, Addr PC, Addr NPC, + Addr Pred_PC, Addr Pred_NPC, + InstSeqNum seq_num, O3CPU *cpu); /** BaseDynInst constructor given a static inst pointer. */ AlphaDynInst(StaticInstPtr &_staticInst); @@ -123,6 +124,44 @@ class AlphaDynInst : public BaseDynInst<Impl> this->threadNumber); } + /** Reads a miscellaneous register. */ + TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx) + { + return this->cpu->readMiscReg( + si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, + this->threadNumber); + } + + /** Reads a misc. register, including any side-effects the read + * might have as defined by the architecture. + */ + TheISA::MiscReg readMiscRegOperandWithEffect(const StaticInst *si, int idx) + { + return this->cpu->readMiscRegWithEffect( + si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, + this->threadNumber); + } + + /** Sets a misc. register. */ + void setMiscRegOperand(const StaticInst * si, int idx, const MiscReg &val) + { + this->instResult.integer = val; + return this->cpu->setMiscReg( + si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, + val, this->threadNumber); + } + + /** Sets a misc. register, including any side-effects the write + * might have as defined by the architecture. + */ + void setMiscRegOperandWithEffect(const StaticInst *si, int idx, + const MiscReg &val) + { + return this->cpu->setMiscRegWithEffect( + si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, + val, this->threadNumber); + } + #if FULL_SYSTEM /** Calls hardware return from error interrupt. */ Fault hwrei(); @@ -134,22 +173,6 @@ class AlphaDynInst : public BaseDynInst<Impl> void syscall(int64_t callnum); #endif - private: - /** Physical register index of the destination registers of this - * instruction. - */ - PhysRegIndex _destRegIdx[MaxInstDestRegs]; - - /** Physical register index of the source registers of this - * instruction. - */ - PhysRegIndex _srcRegIdx[MaxInstSrcRegs]; - - /** Physical register index of the previous producers of the - * architected destinations. - */ - PhysRegIndex _prevDestRegIdx[MaxInstDestRegs]; - public: // The register accessor methods provide the index of the @@ -165,28 +188,28 @@ class AlphaDynInst : public BaseDynInst<Impl> uint64_t readIntRegOperand(const StaticInst *si, int idx) { - return this->cpu->readIntReg(_srcRegIdx[idx]); + return this->cpu->readIntReg(this->_srcRegIdx[idx]); } FloatReg readFloatRegOperand(const StaticInst *si, int idx, int width) { - return this->cpu->readFloatReg(_srcRegIdx[idx], width); + return this->cpu->readFloatReg(this->_srcRegIdx[idx], width); } FloatReg readFloatRegOperand(const StaticInst *si, int idx) { - return this->cpu->readFloatReg(_srcRegIdx[idx]); + return this->cpu->readFloatReg(this->_srcRegIdx[idx]); } FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx, int width) { - return this->cpu->readFloatRegBits(_srcRegIdx[idx], width); + return this->cpu->readFloatRegBits(this->_srcRegIdx[idx], width); } FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx) { - return this->cpu->readFloatRegBits(_srcRegIdx[idx]); + return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]); } /** @todo: Make results into arrays so they can handle multiple dest @@ -194,79 +217,37 @@ class AlphaDynInst : public BaseDynInst<Impl> */ void setIntRegOperand(const StaticInst *si, int idx, uint64_t val) { - this->cpu->setIntReg(_destRegIdx[idx], val); + this->cpu->setIntReg(this->_destRegIdx[idx], val); BaseDynInst<Impl>::setIntRegOperand(si, idx, val); } void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val, int width) { - this->cpu->setFloatReg(_destRegIdx[idx], val, width); + this->cpu->setFloatReg(this->_destRegIdx[idx], val, width); BaseDynInst<Impl>::setFloatRegOperand(si, idx, val, width); } void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val) { - this->cpu->setFloatReg(_destRegIdx[idx], val); + this->cpu->setFloatReg(this->_destRegIdx[idx], val); BaseDynInst<Impl>::setFloatRegOperand(si, idx, val); } void setFloatRegOperandBits(const StaticInst *si, int idx, FloatRegBits val, int width) { - this->cpu->setFloatRegBits(_destRegIdx[idx], val, width); + this->cpu->setFloatRegBits(this->_destRegIdx[idx], val, width); BaseDynInst<Impl>::setFloatRegOperandBits(si, idx, val); } void setFloatRegOperandBits(const StaticInst *si, int idx, FloatRegBits val) { - this->cpu->setFloatRegBits(_destRegIdx[idx], val); + this->cpu->setFloatRegBits(this->_destRegIdx[idx], val); BaseDynInst<Impl>::setFloatRegOperandBits(si, idx, val); } - /** Returns the physical register index of the i'th destination - * register. - */ - PhysRegIndex renamedDestRegIdx(int idx) const - { - return _destRegIdx[idx]; - } - - /** Returns the physical register index of the i'th source register. */ - PhysRegIndex renamedSrcRegIdx(int idx) const - { - return _srcRegIdx[idx]; - } - - /** Returns the physical register index of the previous physical register - * that remapped to the same logical register index. - */ - PhysRegIndex prevDestRegIdx(int idx) const - { - return _prevDestRegIdx[idx]; - } - - /** Renames a destination register to a physical register. Also records - * the previous physical register that the logical register mapped to. - */ - void renameDestReg(int idx, - PhysRegIndex renamed_dest, - PhysRegIndex previous_rename) - { - _destRegIdx[idx] = renamed_dest; - _prevDestRegIdx[idx] = previous_rename; - } - - /** Renames a source logical register to the physical register which - * has/will produce that logical register's result. - * @todo: add in whether or not the source register is ready. - */ - void renameSrcReg(int idx, PhysRegIndex renamed_src) - { - _srcRegIdx[idx] = renamed_src; - } - public: /** Calculates EA part of a memory instruction. Currently unused, * though it may be useful in the future if we want to split diff --git a/src/cpu/o3/alpha/dyn_inst_impl.hh b/src/cpu/o3/alpha/dyn_inst_impl.hh index 6fc548a85..50cdec408 100644 --- a/src/cpu/o3/alpha/dyn_inst_impl.hh +++ b/src/cpu/o3/alpha/dyn_inst_impl.hh @@ -31,9 +31,10 @@ #include "cpu/o3/alpha/dyn_inst.hh" template <class Impl> -AlphaDynInst<Impl>::AlphaDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC, +AlphaDynInst<Impl>::AlphaDynInst(ExtMachInst inst, Addr PC, Addr NPC, + Addr Pred_PC, Addr Pred_NPC, InstSeqNum seq_num, O3CPU *cpu) - : BaseDynInst<Impl>(inst, PC, Pred_PC, seq_num, cpu) + : BaseDynInst<Impl>(inst, PC, NPC, Pred_PC, Pred_NPC, seq_num, cpu) { initVars(); } @@ -53,11 +54,11 @@ AlphaDynInst<Impl>::initVars() // as the normal register entries. It will allow the IQ to work // without any modifications. for (int i = 0; i < this->staticInst->numDestRegs(); i++) { - _destRegIdx[i] = this->staticInst->destRegIdx(i); + this->_destRegIdx[i] = this->staticInst->destRegIdx(i); } for (int i = 0; i < this->staticInst->numSrcRegs(); i++) { - _srcRegIdx[i] = this->staticInst->srcRegIdx(i); + this->_srcRegIdx[i] = this->staticInst->srcRegIdx(i); this->_readySrcRegIdx[i] = 0; } } diff --git a/src/cpu/o3/alpha/thread_context.hh b/src/cpu/o3/alpha/thread_context.hh index bcecb7087..6d61501ac 100644 --- a/src/cpu/o3/alpha/thread_context.hh +++ b/src/cpu/o3/alpha/thread_context.hh @@ -36,12 +36,6 @@ class AlphaTC : public O3ThreadContext<Impl> { public: #if FULL_SYSTEM - /** Returns a pointer to the ITB. */ - virtual AlphaISA::ITB *getITBPtr() { return this->cpu->itb; } - - /** Returns a pointer to the DTB. */ - virtual AlphaISA::DTB *getDTBPtr() { return this->cpu->dtb; } - /** Returns pointer to the quiesce event. */ virtual EndQuiesceEvent *getQuiesceEvent() { @@ -51,8 +45,7 @@ class AlphaTC : public O3ThreadContext<Impl> virtual uint64_t readNextNPC() { - panic("Alpha has no NextNPC!"); - return 0; + return this->readNextPC() + sizeof(TheISA::MachInst); } virtual void setNextNPC(uint64_t val) diff --git a/src/cpu/o3/bpred_unit_impl.hh b/src/cpu/o3/bpred_unit_impl.hh index 477c8e4cb..84c50b4da 100644 --- a/src/cpu/o3/bpred_unit_impl.hh +++ b/src/cpu/o3/bpred_unit_impl.hh @@ -149,7 +149,7 @@ BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, unsigned tid) using TheISA::MachInst; bool pred_taken = false; - Addr target; + Addr target = PC; ++lookups; @@ -233,14 +233,7 @@ BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, unsigned tid) } } - if (pred_taken) { - // Set the PC and the instruction's predicted target. - PC = target; - inst->setPredTarg(target); - } else { - PC = PC + sizeof(MachInst); - inst->setPredTarg(PC); - } + PC = target; predHist[tid].push_front(predict_record); diff --git a/src/cpu/o3/comm.hh b/src/cpu/o3/comm.hh index aa58fc20e..d96919007 100644 --- a/src/cpu/o3/comm.hh +++ b/src/cpu/o3/comm.hh @@ -87,9 +87,10 @@ struct DefaultIEWDefaultCommit { bool squash[Impl::MaxThreads]; bool branchMispredict[Impl::MaxThreads]; bool branchTaken[Impl::MaxThreads]; - bool condDelaySlotBranch[Impl::MaxThreads]; + bool squashDelaySlot[Impl::MaxThreads]; uint64_t mispredPC[Impl::MaxThreads]; uint64_t nextPC[Impl::MaxThreads]; + uint64_t nextNPC[Impl::MaxThreads]; InstSeqNum squashedSeqNum[Impl::MaxThreads]; bool includeSquashInst[Impl::MaxThreads]; @@ -121,6 +122,7 @@ struct TimeBufStruct { bool branchTaken; uint64_t mispredPC; uint64_t nextPC; + uint64_t nextNPC; unsigned branchCount; }; @@ -160,6 +162,7 @@ struct TimeBufStruct { bool branchTaken; uint64_t mispredPC; uint64_t nextPC; + uint64_t nextNPC; // Represents the instruction that has either been retired or // squashed. Similar to having a single bus that broadcasts the diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index 483c2f71b..f1457922c 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -519,6 +519,7 @@ DefaultCommit<Impl>::squashAll(unsigned tid) toIEW->commitInfo[tid].branchMispredict = false; toIEW->commitInfo[tid].nextPC = PC[tid]; + toIEW->commitInfo[tid].nextNPC = nextPC[tid]; } template <class Impl> @@ -734,27 +735,15 @@ DefaultCommit<Impl>::commit() InstSeqNum squashed_inst = fromIEW->squashedSeqNum[tid]; #if ISA_HAS_DELAY_SLOT - InstSeqNum bdelay_done_seq_num; - bool squash_bdelay_slot; - - if (fromIEW->branchMispredict[tid]) { - if (fromIEW->branchTaken[tid] && - fromIEW->condDelaySlotBranch[tid]) { - DPRINTF(Commit, "[tid:%i]: Cond. delay slot branch" - "mispredicted as taken. Squashing after previous " - "inst, [sn:%i]\n", - tid, squashed_inst); - bdelay_done_seq_num = squashed_inst; - squash_bdelay_slot = true; - } else { - DPRINTF(Commit, "[tid:%i]: Branch Mispredict. Squashing " - "after delay slot [sn:%i]\n", tid, squashed_inst+1); - bdelay_done_seq_num = squashed_inst + 1; - squash_bdelay_slot = false; - } - } else { - bdelay_done_seq_num = squashed_inst; - squash_bdelay_slot = true; + InstSeqNum bdelay_done_seq_num = squashed_inst; + bool squash_bdelay_slot = fromIEW->squashDelaySlot[tid]; + bool branchMispredict = fromIEW->branchMispredict[tid]; + + // Squashing/not squashing the branch delay slot only makes + // sense when you're squashing from a branch, ie from a branch + // mispredict. + if (branchMispredict && !squash_bdelay_slot) { + bdelay_done_seq_num++; } #endif @@ -793,6 +782,7 @@ DefaultCommit<Impl>::commit() fromIEW->branchTaken[tid]; toIEW->commitInfo[tid].nextPC = fromIEW->nextPC[tid]; + toIEW->commitInfo[tid].nextNPC = fromIEW->nextNPC[tid]; toIEW->commitInfo[tid].mispredPC = fromIEW->mispredPC[tid]; @@ -1122,7 +1112,7 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) // Update the commit rename map for (int i = 0; i < head_inst->numDestRegs(); i++) { - renameMap[tid]->setEntry(head_inst->destRegIdx(i), + renameMap[tid]->setEntry(head_inst->flattenedDestRegIdx(i), head_inst->renamedDestRegIdx(i)); } diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 18cc87c0b..66c75a12d 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -150,6 +150,10 @@ FullO3CPU<Impl>::DeallocateContextEvent::description() template <class Impl> FullO3CPU<Impl>::FullO3CPU(Params *params) : BaseO3CPU(params), +#if FULL_SYSTEM + itb(params->itb), + dtb(params->dtb), +#endif tickEvent(this), removeInstsThisCycle(false), fetch(params), @@ -657,9 +661,7 @@ FullO3CPU<Impl>::insertThread(unsigned tid) //Set PC/NPC/NNPC setPC(src_tc->readPC(), tid); setNextPC(src_tc->readNextPC(), tid); -#if ISA_HAS_DELAY_SLOT setNextNPC(src_tc->readNextNPC(), tid); -#endif src_tc->setStatus(ThreadContext::Active); @@ -698,7 +700,7 @@ FullO3CPU<Impl>::removeThread(unsigned tid) // Squash Throughout Pipeline InstSeqNum squash_seq_num = commit.rob->readHeadInst(tid)->seqNum; - fetch.squash(0, squash_seq_num, true, tid); + fetch.squash(0, sizeof(TheISA::MachInst), squash_seq_num, true, tid); decode.squash(tid); rename.squash(squash_seq_num, tid); iew.squash(tid); diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 2bf9cb23b..d217a3e85 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -91,9 +91,6 @@ template <class Impl> class FullO3CPU : public BaseO3CPU { public: - typedef TheISA::FloatReg FloatReg; - typedef TheISA::FloatRegBits FloatRegBits; - // Typedefs from the Impl here. typedef typename Impl::CPUPol CPUPolicy; typedef typename Impl::Params Params; @@ -114,6 +111,11 @@ class FullO3CPU : public BaseO3CPU SwitchedOut }; +#if FULL_SYSTEM + TheISA::ITB * itb; + TheISA::DTB * dtb; +#endif + /** Overall CPU status. */ Status _status; @@ -382,23 +384,23 @@ class FullO3CPU : public BaseO3CPU /** Register accessors. Index refers to the physical register index. */ uint64_t readIntReg(int reg_idx); - FloatReg readFloatReg(int reg_idx); + TheISA::FloatReg readFloatReg(int reg_idx); - FloatReg readFloatReg(int reg_idx, int width); + TheISA::FloatReg readFloatReg(int reg_idx, int width); - FloatRegBits readFloatRegBits(int reg_idx); + TheISA::FloatRegBits readFloatRegBits(int reg_idx); - FloatRegBits readFloatRegBits(int reg_idx, int width); + TheISA::FloatRegBits readFloatRegBits(int reg_idx, int width); void setIntReg(int reg_idx, uint64_t val); - void setFloatReg(int reg_idx, FloatReg val); + void setFloatReg(int reg_idx, TheISA::FloatReg val); - void setFloatReg(int reg_idx, FloatReg val, int width); + void setFloatReg(int reg_idx, TheISA::FloatReg val, int width); - void setFloatRegBits(int reg_idx, FloatRegBits val); + void setFloatRegBits(int reg_idx, TheISA::FloatRegBits val); - void setFloatRegBits(int reg_idx, FloatRegBits val, int width); + void setFloatRegBits(int reg_idx, TheISA::FloatRegBits val, int width); uint64_t readArchIntReg(int reg_idx, unsigned tid); diff --git a/src/cpu/o3/decode_impl.hh b/src/cpu/o3/decode_impl.hh index 26ed40c67..79a0bfdbf 100644 --- a/src/cpu/o3/decode_impl.hh +++ b/src/cpu/o3/decode_impl.hh @@ -282,6 +282,10 @@ DefaultDecode<Impl>::squash(DynInstPtr &inst, unsigned tid) toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum; toFetch->decodeInfo[tid].squash = true; toFetch->decodeInfo[tid].nextPC = inst->branchTarget(); + ///FIXME There needs to be a way to set the nextPC and nextNPC + ///explicitly for ISAs with delay slots. + toFetch->decodeInfo[tid].nextNPC = + inst->branchTarget() + sizeof(TheISA::MachInst); #if ISA_HAS_DELAY_SLOT toFetch->decodeInfo[tid].branchTaken = inst->readNextNPC() != (inst->readNextPC() + sizeof(TheISA::MachInst)); @@ -743,9 +747,9 @@ DefaultDecode<Impl>::decodeInsts(unsigned tid) // Ensure that if it was predicted as a branch, it really is a // branch. - if (inst->predTaken() && !inst->isControl()) { - DPRINTF(Decode, "PredPC : %#x != NextPC: %#x\n",inst->predPC, - inst->nextPC + 4); + if (inst->readPredTaken() && !inst->isControl()) { + DPRINTF(Decode, "PredPC : %#x != NextPC: %#x\n", + inst->readPredPC(), inst->readNextPC() + 4); panic("Instruction predicted as a branch!"); @@ -762,26 +766,29 @@ DefaultDecode<Impl>::decodeInsts(unsigned tid) if (inst->isDirectCtrl() && inst->isUncondCtrl()) { ++decodeBranchResolved; - if (inst->branchTarget() != inst->readPredTarg()) { + if (inst->branchTarget() != inst->readPredPC()) { ++decodeBranchMispred; // Might want to set some sort of boolean and just do // a check at the end #if !ISA_HAS_DELAY_SLOT squash(inst, inst->threadNumber); - inst->setPredTarg(inst->branchTarget()); + Addr target = inst->branchTarget(); + inst->setPredTarg(target, target + sizeof(TheISA::MachInst)); break; #else // If mispredicted as taken, then ignore delay slot // instruction... else keep delay slot and squash // after it is sent to rename - if (inst->predTaken() && inst->isCondDelaySlot()) { + if (inst->readPredTaken() && inst->isCondDelaySlot()) { DPRINTF(Decode, "[tid:%i]: Conditional delay slot inst." "[sn:%i] PC %#x mispredicted as taken.\n", tid, inst->seqNum, inst->PC); bdelayDoneSeqNum[tid] = inst->seqNum; squash(inst, inst->threadNumber); - inst->setPredTarg(inst->branchTarget()); + Addr target = inst->branchTarget(); + inst->setPredTarg(target, + target + sizeof(TheISA::MachInst)); break; } else { DPRINTF(Decode, "[tid:%i]: Misprediction detected at " @@ -800,7 +807,9 @@ DefaultDecode<Impl>::decodeInsts(unsigned tid) if (squashAfterDelaySlot[tid]) { assert(!inst->isSquashed()); squash(squashInst[tid], squashInst[tid]->threadNumber); - squashInst[tid]->setPredTarg(squashInst[tid]->branchTarget()); + Addr target = squashInst[tid]->branchTarget(); + squashInst[tid]->setPredTarg(target, + target + sizeof(TheISA::MachInst)); assert(!inst->isSquashed()); break; } diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index e880e14e4..8347ed775 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -239,13 +239,13 @@ class DefaultFetch bool fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid); /** Squashes a specific thread and resets the PC. */ - inline void doSquash(const Addr &new_PC, unsigned tid); + inline void doSquash(const Addr &new_PC, const Addr &new_NPC, unsigned tid); /** Squashes a specific thread and resets the PC. Also tells the CPU to * remove any instructions between fetch and decode that should be sqaushed. */ - void squashFromDecode(const Addr &new_PC, const InstSeqNum &seq_num, - unsigned tid); + void squashFromDecode(const Addr &new_PC, const Addr &new_NPC, + const InstSeqNum &seq_num, unsigned tid); /** Checks if a thread is stalled. */ bool checkStall(unsigned tid) const; @@ -259,7 +259,8 @@ class DefaultFetch * remove any instructions that are not in the ROB. The source of this * squash should be the commit stage. */ - void squash(const Addr &new_PC, const InstSeqNum &seq_num, + void squash(const Addr &new_PC, const Addr &new_NPC, + const InstSeqNum &seq_num, bool squash_delay_slot, unsigned tid); /** Ticks the fetch stage, processing all inputs signals and fetching @@ -361,19 +362,6 @@ class DefaultFetch /** Tracks how many instructions has been fetched this cycle. */ int numInst; - /** Tracks delay slot information for threads in ISAs which use - * delay slots; - */ - struct DelaySlotInfo { - InstSeqNum delaySlotSeqNum; - InstSeqNum branchSeqNum; - int numInsts; - Addr targetAddr; - bool targetReady; - }; - - DelaySlotInfo delaySlotInfo[Impl::MaxThreads]; - /** Source of possible stalls. */ struct Stalls { bool decode; diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index fe320fa79..b80fc72e1 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -319,9 +319,7 @@ DefaultFetch<Impl>::initStage() for (int tid = 0; tid < numThreads; tid++) { PC[tid] = cpu->readPC(tid); nextPC[tid] = cpu->readNextPC(tid); -#if ISA_HAS_DELAY_SLOT nextNPC[tid] = cpu->readNextNPC(tid); -#endif } // Size of cache block. @@ -343,11 +341,6 @@ DefaultFetch<Impl>::initStage() cacheDataPC[tid] = 0; cacheDataValid[tid] = false; - delaySlotInfo[tid].branchSeqNum = -1; - delaySlotInfo[tid].numInsts = 0; - delaySlotInfo[tid].targetAddr = 0; - delaySlotInfo[tid].targetReady = false; - stalls[tid].decode = false; stalls[tid].rename = false; stalls[tid].iew = false; @@ -441,10 +434,8 @@ DefaultFetch<Impl>::takeOverFrom() nextPC[i] = cpu->readNextPC(i); #if ISA_HAS_DELAY_SLOT nextNPC[i] = cpu->readNextNPC(i); - delaySlotInfo[i].branchSeqNum = -1; - delaySlotInfo[i].numInsts = 0; - delaySlotInfo[i].targetAddr = 0; - delaySlotInfo[i].targetReady = false; +#else + nextNPC[i] = nextPC[i] + sizeof(TheISA::MachInst); #endif fetchStatus[i] = Running; } @@ -503,54 +494,41 @@ DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC, bool predict_taken; if (!inst->isControl()) { -#if ISA_HAS_DELAY_SLOT - Addr cur_PC = next_PC; - next_PC = cur_PC + instSize; //next_NPC; - next_NPC = cur_PC + (2 * instSize);//next_NPC + instSize; - inst->setPredTarg(next_NPC); -#else - next_PC = next_PC + instSize; - inst->setPredTarg(next_PC); -#endif + next_PC = next_NPC; + next_NPC = next_NPC + instSize; + inst->setPredTarg(next_PC, next_NPC); + inst->setPredTaken(false); return false; } int tid = inst->threadNumber; -#if ISA_HAS_DELAY_SLOT Addr pred_PC = next_PC; predict_taken = branchPred.predict(inst, pred_PC, tid); - if (predict_taken) { - DPRINTF(Fetch, "[tid:%i]: Branch predicted to be true.\n", tid); +/* if (predict_taken) { + DPRINTF(Fetch, "[tid:%i]: Branch predicted to be taken to %#x.\n", + tid, pred_PC); } else { - DPRINTF(Fetch, "[tid:%i]: Branch predicted to be false.\n", tid); - } + DPRINTF(Fetch, "[tid:%i]: Branch predicted to be not taken.\n", tid); + }*/ - if (predict_taken) { - next_PC = next_NPC; +#if ISA_HAS_DELAY_SLOT + next_PC = next_NPC; + if (predict_taken) next_NPC = pred_PC; - - // Update delay slot info - ++delaySlotInfo[tid].numInsts; - delaySlotInfo[tid].targetAddr = pred_PC; - DPRINTF(Fetch, "[tid:%i]: %i delay slot inst(s) to process.\n", tid, - delaySlotInfo[tid].numInsts); - } else { // !predict_taken - if (inst->isCondDelaySlot()) { - next_PC = pred_PC; - // The delay slot is skipped here if there is on - // prediction - } else { - next_PC = next_NPC; - // No need to declare a delay slot here since - // there is no for the pred. target to jump - } - - next_NPC = next_NPC + instSize; - } + else + next_NPC += instSize; #else - predict_taken = branchPred.predict(inst, next_PC, tid); + if (predict_taken) + next_PC = pred_PC; + else + next_PC += instSize; + next_NPC = next_PC + instSize; #endif +/* DPRINTF(Fetch, "[tid:%i]: Branch predicted to go to %#x and then %#x.\n", + tid, next_PC, next_NPC);*/ + inst->setPredTarg(next_PC, next_NPC); + inst->setPredTaken(predict_taken); ++fetchedBranches; @@ -671,14 +649,15 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid template <class Impl> inline void -DefaultFetch<Impl>::doSquash(const Addr &new_PC, unsigned tid) +DefaultFetch<Impl>::doSquash(const Addr &new_PC, + const Addr &new_NPC, unsigned tid) { - DPRINTF(Fetch, "[tid:%i]: Squashing, setting PC to: %#x.\n", - tid, new_PC); + DPRINTF(Fetch, "[tid:%i]: Squashing, setting PC to: %#x, NPC to: %#x.\n", + tid, new_PC, new_NPC); PC[tid] = new_PC; - nextPC[tid] = new_PC + instSize; - nextNPC[tid] = new_PC + (2 * instSize); + nextPC[tid] = new_NPC; + nextNPC[tid] = new_NPC + instSize; // Clear the icache miss if it's outstanding. if (fetchStatus[tid] == IcacheWaitResponse) { @@ -704,21 +683,13 @@ DefaultFetch<Impl>::doSquash(const Addr &new_PC, unsigned tid) template<class Impl> void -DefaultFetch<Impl>::squashFromDecode(const Addr &new_PC, +DefaultFetch<Impl>::squashFromDecode(const Addr &new_PC, const Addr &new_NPC, const InstSeqNum &seq_num, unsigned tid) { DPRINTF(Fetch, "[tid:%i]: Squashing from decode.\n",tid); - doSquash(new_PC, tid); - -#if ISA_HAS_DELAY_SLOT - if (seq_num <= delaySlotInfo[tid].branchSeqNum) { - delaySlotInfo[tid].numInsts = 0; - delaySlotInfo[tid].targetAddr = 0; - delaySlotInfo[tid].targetReady = false; - } -#endif + doSquash(new_PC, new_NPC, tid); // Tell the CPU to remove any instructions that are in flight between // fetch and decode. @@ -793,20 +764,15 @@ DefaultFetch<Impl>::updateFetchStatus() template <class Impl> void -DefaultFetch<Impl>::squash(const Addr &new_PC, const InstSeqNum &seq_num, +DefaultFetch<Impl>::squash(const Addr &new_PC, const Addr &new_NPC, + const InstSeqNum &seq_num, bool squash_delay_slot, unsigned tid) { DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n",tid); - doSquash(new_PC, tid); + doSquash(new_PC, new_NPC, tid); #if ISA_HAS_DELAY_SLOT - if (seq_num <= delaySlotInfo[tid].branchSeqNum) { - delaySlotInfo[tid].numInsts = 0; - delaySlotInfo[tid].targetAddr = 0; - delaySlotInfo[tid].targetReady = false; - } - // Tell the CPU to remove any instructions that are not in the ROB. cpu->removeInstsNotInROB(tid, squash_delay_slot, seq_num); #else @@ -929,6 +895,7 @@ DefaultFetch<Impl>::checkSignalsAndUpdate(unsigned tid) #endif // In any case, squash. squash(fromCommit->commitInfo[tid].nextPC, + fromCommit->commitInfo[tid].nextNPC, doneSeqNum, fromCommit->commitInfo[tid].squashDelaySlot, tid); @@ -984,8 +951,12 @@ DefaultFetch<Impl>::checkSignalsAndUpdate(unsigned tid) #else InstSeqNum doneSeqNum = fromDecode->decodeInfo[tid].doneSeqNum; #endif + DPRINTF(Fetch, "Squashing from decode with PC = %#x, NPC = %#x\n", + fromDecode->decodeInfo[tid].nextPC, + fromDecode->decodeInfo[tid].nextNPC); // Squash unless we're already squashing squashFromDecode(fromDecode->decodeInfo[tid].nextPC, + fromDecode->decodeInfo[tid].nextNPC, doneSeqNum, tid); @@ -1042,6 +1013,8 @@ DefaultFetch<Impl>::fetch(bool &status_change) // The current PC. Addr &fetch_PC = PC[tid]; + Addr &fetch_NPC = nextPC[tid]; + // Fault code for memory access. Fault fault = NoFault; @@ -1098,7 +1071,8 @@ DefaultFetch<Impl>::fetch(bool &status_change) } Addr next_PC = fetch_PC; - Addr next_NPC = next_PC + instSize; + Addr next_NPC = fetch_NPC; + InstSeqNum inst_seq; MachInst inst; ExtMachInst ext_inst; @@ -1117,15 +1091,22 @@ DefaultFetch<Impl>::fetch(bool &status_change) // ended this fetch block. bool predicted_branch = false; - // Need to keep track of whether or not a delay slot - // instruction has been fetched - for (; offset < cacheBlkSize && numInst < fetchWidth && - (!predicted_branch || delaySlotInfo[tid].numInsts > 0); + !predicted_branch; ++numInst) { + // If we're branching after this instruction, quite fetching + // from the same block then. + predicted_branch = + (fetch_PC + sizeof(TheISA::MachInst) != fetch_NPC); + if (predicted_branch) { + DPRINTF(Fetch, "Branch detected with PC = %#x, NPC = %#x\n", + fetch_PC, fetch_NPC); + } + + // Get a sequence number. inst_seq = cpu->getAndIncrementInstSeq(); @@ -1145,8 +1126,9 @@ DefaultFetch<Impl>::fetch(bool &status_change) #endif // Create a new DynInst from the instruction fetched. - DynInstPtr instruction = new DynInst(ext_inst, fetch_PC, - next_PC, + DynInstPtr instruction = new DynInst(ext_inst, + fetch_PC, fetch_NPC, + next_PC, next_NPC, inst_seq, cpu); instruction->setTid(tid); @@ -1158,6 +1140,8 @@ DefaultFetch<Impl>::fetch(bool &status_change) "[sn:%lli]\n", tid, instruction->readPC(), inst_seq); + //DPRINTF(Fetch, "[tid:%i]: MachInst is %#x\n", tid, ext_inst); + DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n", tid, instruction->staticInst->disassemble(fetch_PC)); @@ -1166,8 +1150,12 @@ DefaultFetch<Impl>::fetch(bool &status_change) instruction->staticInst, instruction->readPC()); - predicted_branch = lookupAndUpdateNextPC(instruction, next_PC, - next_NPC); + ///FIXME This needs to be more robust in dealing with delay slots +#if !ISA_HAS_DELAY_SLOT + predicted_branch |= +#endif + lookupAndUpdateNextPC(instruction, next_PC, next_NPC); + predicted_branch |= (next_PC != fetch_NPC); // Add instruction to the CPU's list of instructions. instruction->setInstListIt(cpu->addInst(instruction)); @@ -1183,6 +1171,7 @@ DefaultFetch<Impl>::fetch(bool &status_change) // Move to the next instruction, unless we have a branch. fetch_PC = next_PC; + fetch_NPC = next_NPC; if (instruction->isQuiesce()) { DPRINTF(Fetch, "Quiesce instruction encountered, halting fetch!", @@ -1194,29 +1183,6 @@ DefaultFetch<Impl>::fetch(bool &status_change) } offset += instSize; - -#if ISA_HAS_DELAY_SLOT - if (predicted_branch) { - delaySlotInfo[tid].branchSeqNum = inst_seq; - - DPRINTF(Fetch, "[tid:%i]: Delay slot branch set to [sn:%i]\n", - tid, inst_seq); - continue; - } else if (delaySlotInfo[tid].numInsts > 0) { - --delaySlotInfo[tid].numInsts; - - // It's OK to set PC to target of branch - if (delaySlotInfo[tid].numInsts == 0) { - delaySlotInfo[tid].targetReady = true; - - // Break the looping condition - predicted_branch = true; - } - - DPRINTF(Fetch, "[tid:%i]: %i delay slot inst(s) left to" - " process.\n", tid, delaySlotInfo[tid].numInsts); - } -#endif } if (offset >= cacheBlkSize) { @@ -1225,7 +1191,7 @@ DefaultFetch<Impl>::fetch(bool &status_change) } else if (numInst >= fetchWidth) { DPRINTF(Fetch, "[tid:%i]: Done fetching, reached fetch bandwidth " "for this cycle.\n", tid); - } else if (predicted_branch && delaySlotInfo[tid].numInsts <= 0) { + } else if (predicted_branch) { DPRINTF(Fetch, "[tid:%i]: Done fetching, predicted branch " "instruction encountered.\n", tid); } @@ -1238,26 +1204,13 @@ DefaultFetch<Impl>::fetch(bool &status_change) // Now that fetching is completed, update the PC to signify what the next // cycle will be. if (fault == NoFault) { + PC[tid] = next_PC; + nextPC[tid] = next_NPC; + nextNPC[tid] = next_NPC + instSize; #if ISA_HAS_DELAY_SLOT - if (delaySlotInfo[tid].targetReady && - delaySlotInfo[tid].numInsts == 0) { - // Set PC to target - PC[tid] = delaySlotInfo[tid].targetAddr; //next_PC - nextPC[tid] = next_PC + instSize; //next_NPC - nextNPC[tid] = next_PC + (2 * instSize); - - delaySlotInfo[tid].targetReady = false; - } else { - PC[tid] = next_PC; - nextPC[tid] = next_NPC; - nextNPC[tid] = next_NPC + instSize; - } - DPRINTF(Fetch, "[tid:%i]: Setting PC to %08p.\n", tid, PC[tid]); #else - DPRINTF(Fetch, "[tid:%i]: Setting PC to %08p.\n",tid, next_PC); - PC[tid] = next_PC; - nextPC[tid] = next_PC + instSize; + DPRINTF(Fetch, "[tid:%i]: Setting PC to %08p.\n", tid, next_PC); #endif } else { // We shouldn't be in an icache miss and also have a fault (an ITB @@ -1277,10 +1230,11 @@ DefaultFetch<Impl>::fetch(bool &status_change) ext_inst = TheISA::NoopMachInst; // Create a new DynInst from the dummy nop. - DynInstPtr instruction = new DynInst(ext_inst, fetch_PC, - next_PC, + DynInstPtr instruction = new DynInst(ext_inst, + fetch_PC, fetch_NPC, + next_PC, next_NPC, inst_seq, cpu); - instruction->setPredTarg(next_PC + instSize); + instruction->setPredTarg(next_PC, next_NPC); instruction->setTid(tid); instruction->setASID(tid); diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh index a8962f2f7..f24eaf2c4 100644 --- a/src/cpu/o3/iew_impl.hh +++ b/src/cpu/o3/iew_impl.hh @@ -480,23 +480,37 @@ DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, unsigned tid) toCommit->mispredPC[tid] = inst->readPC(); toCommit->branchMispredict[tid] = true; + int instSize = sizeof(TheISA::MachInst); #if ISA_HAS_DELAY_SLOT - bool branch_taken = inst->readNextNPC() != - (inst->readNextPC() + sizeof(TheISA::MachInst)); + bool branch_taken = + !(inst->readNextPC() + instSize == inst->readNextNPC() && + (inst->readNextPC() == inst->readPC() + instSize || + inst->readNextPC() == inst->readPC() + 2 * instSize)); + DPRINTF(Sparc, "Branch taken = %s [sn:%i]\n", + branch_taken ? "true": "false", inst->seqNum); toCommit->branchTaken[tid] = branch_taken; - toCommit->condDelaySlotBranch[tid] = inst->isCondDelaySlot(); - - if (inst->isCondDelaySlot() && branch_taken) { + bool squashDelaySlot = true; +// (inst->readNextPC() != inst->readPC() + sizeof(TheISA::MachInst)); + DPRINTF(Sparc, "Squash delay slot = %s [sn:%i]\n", + squashDelaySlot ? "true": "false", inst->seqNum); + toCommit->squashDelaySlot[tid] = squashDelaySlot; + //If we're squashing the delay slot, we need to pick back up at NextPC. + //Otherwise, NextPC isn't being squashed, so we should pick back up at + //NextNPC. + if (squashDelaySlot) { toCommit->nextPC[tid] = inst->readNextPC(); + toCommit->nextNPC[tid] = inst->readNextNPC(); } else { toCommit->nextPC[tid] = inst->readNextNPC(); + toCommit->nextNPC[tid] = inst->readNextNPC() + instSize; } #else toCommit->branchTaken[tid] = inst->readNextPC() != (inst->readPC() + sizeof(TheISA::MachInst)); toCommit->nextPC[tid] = inst->readNextPC(); + toCommit->nextNPC[tid] = inst->readNextPC() + instSize; #endif toCommit->includeSquashInst[tid] = false; @@ -514,6 +528,11 @@ DefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, unsigned tid) toCommit->squash[tid] = true; toCommit->squashedSeqNum[tid] = inst->seqNum; toCommit->nextPC[tid] = inst->readNextPC(); +#if ISA_HAS_DELAY_SLOT + toCommit->nextNPC[tid] = inst->readNextNPC(); +#else + toCommit->nextNPC[tid] = inst->readNextPC() + sizeof(TheISA::MachInst); +#endif toCommit->branchMispredict[tid] = false; toCommit->includeSquashInst[tid] = false; @@ -531,6 +550,11 @@ DefaultIEW<Impl>::squashDueToMemBlocked(DynInstPtr &inst, unsigned tid) toCommit->squash[tid] = true; toCommit->squashedSeqNum[tid] = inst->seqNum; toCommit->nextPC[tid] = inst->readPC(); +#if ISA_HAS_DELAY_SLOT + toCommit->nextNPC[tid] = inst->readNextPC(); +#else + toCommit->nextNPC[tid] = inst->readPC() + sizeof(TheISA::MachInst); +#endif toCommit->branchMispredict[tid] = false; // Must include the broadcasted SN in the squash. @@ -1341,17 +1365,15 @@ DefaultIEW<Impl>::executeInsts() fetchRedirect[tid] = true; DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); -#if ISA_HAS_DELAY_SLOT - DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x.\n", - inst->nextNPC); -#else - DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x.\n", - inst->nextPC); -#endif + DPRINTF(IEW, "Predicted target was %#x, %#x.\n", + inst->readPredPC(), inst->readPredNPC()); + DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x," + " NPC: %#x.\n", inst->readNextPC(), + inst->readNextNPC()); // If incorrect, then signal the ROB that it must be squashed. squashDueToBranch(inst, tid); - if (inst->predTaken()) { + if (inst->readPredTaken()) { predictedTakenIncorrect++; } else { predictedNotTakenIncorrect++; @@ -1421,7 +1443,7 @@ DefaultIEW<Impl>::writebackInsts() // mark scoreboard that this instruction is finally complete. // Either have IEW have direct access to scoreboard, or have this // as part of backwards communication. - for (int inst_num = 0; inst_num < issueWidth && + for (int inst_num = 0; inst_num < wbWidth && toCommit->insts[inst_num]; inst_num++) { DynInstPtr inst = toCommit->insts[inst_num]; int tid = inst->threadNumber; diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh index 14f9d5031..9c7eb7780 100644 --- a/src/cpu/o3/lsq_unit.hh +++ b/src/cpu/o3/lsq_unit.hh @@ -559,6 +559,12 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx) // Cast this to type T? data = storeQueue[store_idx].data >> shift_amt; + // When the data comes from the store queue entry, it's in host + // order. When it gets sent to the load, it needs to be in guest + // order so when the load converts it again, it ends up back + // in host order like the inst expects. + data = TheISA::htog(data); + assert(!load_inst->memData); load_inst->memData = new uint8_t[64]; diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index 3b84d3411..ebd9301f6 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -597,8 +597,21 @@ LSQUnit<Impl>::writebackStores() assert(!inst->memData); inst->memData = new uint8_t[64]; - memcpy(inst->memData, (uint8_t *)&storeQueue[storeWBIdx].data, - req->getSize()); + + TheISA::IntReg convertedData = + TheISA::htog(storeQueue[storeWBIdx].data); + + //FIXME This is a hack to get SPARC working. It, along with endianness + //in the memory system in general, need to be straightened out more + //formally. The problem is that the data's endianness is swapped when + //it's in the 64 bit data field in the store queue. The data that you + //want won't start at the beginning of the field anymore unless it was + //a 64 bit access. + memcpy(inst->memData, + (uint8_t *)&convertedData + + (TheISA::ByteOrderDiffers ? + (sizeof(TheISA::IntReg) - req->getSize()) : 0), + req->getSize()); PacketPtr data_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast); data_pkt->dataStatic(inst->memData); @@ -612,7 +625,7 @@ LSQUnit<Impl>::writebackStores() DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x " "to Addr:%#x, data:%#x [sn:%lli]\n", storeWBIdx, inst->readPC(), - req->getPaddr(), *(inst->memData), + req->getPaddr(), (int)*(inst->memData), inst->seqNum); // @todo: Remove this SC hack once the memory system handles it. diff --git a/src/cpu/o3/mips/cpu_impl.hh b/src/cpu/o3/mips/cpu_impl.hh index 08e9ba483..e7dbd3aba 100644 --- a/src/cpu/o3/mips/cpu_impl.hh +++ b/src/cpu/o3/mips/cpu_impl.hh @@ -220,16 +220,6 @@ template <class Impl> void MipsO3CPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid) { - // check for error condition. - if (return_value.successful()) { - // no error - this->setArchIntReg(TheISA::SyscallSuccessReg, 0, tid); - this->setArchIntReg(TheISA::ReturnValueReg, return_value.value(), tid); - } else { - // got an error, return details - this->setArchIntReg(TheISA::SyscallSuccessReg, - (TheISA::IntReg) -1, tid); - this->setArchIntReg(TheISA::ReturnValueReg, -return_value.value(), tid); - } + TheISA::setSyscallReturn(return_value, this->tcBase(tid)); } #endif diff --git a/src/cpu/o3/mips/dyn_inst.hh b/src/cpu/o3/mips/dyn_inst.hh index 833371e00..f53530908 100755 --- a/src/cpu/o3/mips/dyn_inst.hh +++ b/src/cpu/o3/mips/dyn_inst.hh @@ -54,10 +54,6 @@ class MipsDynInst : public BaseDynInst<Impl> /** Typedef for the CPU. */ typedef typename Impl::O3CPU O3CPU; - /** Binary machine instruction type. */ - typedef TheISA::MachInst MachInst; - /** Extended machine instruction type. */ - typedef TheISA::ExtMachInst ExtMachInst; /** Logical register index type. */ typedef TheISA::RegIndex RegIndex; /** Integer register index type. */ @@ -74,8 +70,10 @@ class MipsDynInst : public BaseDynInst<Impl> public: /** BaseDynInst constructor given a binary instruction. */ - MipsDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC, InstSeqNum seq_num, - O3CPU *cpu); + MipsDynInst(ExtMachInst inst, + Addr PC, Addr NPC, + Addr Pred_PC, Addr Pred_NPC, + InstSeqNum seq_num, O3CPU *cpu); /** BaseDynInst constructor given a static inst pointer. */ MipsDynInst(StaticInstPtr &_staticInst); @@ -127,22 +125,6 @@ class MipsDynInst : public BaseDynInst<Impl> /** Calls a syscall. */ void syscall(int64_t callnum); - private: - /** Physical register index of the destination registers of this - * instruction. - */ - PhysRegIndex _destRegIdx[MaxInstDestRegs]; - - /** Physical register index of the source registers of this - * instruction. - */ - PhysRegIndex _srcRegIdx[MaxInstSrcRegs]; - - /** Physical register index of the previous producers of the - * architected destinations. - */ - PhysRegIndex _prevDestRegIdx[MaxInstDestRegs]; - public: // The register accessor methods provide the index of the @@ -158,28 +140,28 @@ class MipsDynInst : public BaseDynInst<Impl> uint64_t readIntRegOperand(const StaticInst *si, int idx) { - return this->cpu->readIntReg(_srcRegIdx[idx]); + return this->cpu->readIntReg(this->_srcRegIdx[idx]); } FloatReg readFloatRegOperand(const StaticInst *si, int idx, int width) { - return this->cpu->readFloatReg(_srcRegIdx[idx], width); + return this->cpu->readFloatReg(this->_srcRegIdx[idx], width); } FloatReg readFloatRegOperand(const StaticInst *si, int idx) { - return this->cpu->readFloatReg(_srcRegIdx[idx]); + return this->cpu->readFloatReg(this->_srcRegIdx[idx]); } FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx, int width) { - return this->cpu->readFloatRegBits(_srcRegIdx[idx], width); + return this->cpu->readFloatRegBits(this->_srcRegIdx[idx], width); } FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx) { - return this->cpu->readFloatRegBits(_srcRegIdx[idx]); + return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]); } /** @todo: Make results into arrays so they can handle multiple dest @@ -187,79 +169,37 @@ class MipsDynInst : public BaseDynInst<Impl> */ void setIntRegOperand(const StaticInst *si, int idx, uint64_t val) { - this->cpu->setIntReg(_destRegIdx[idx], val); + this->cpu->setIntReg(this->_destRegIdx[idx], val); BaseDynInst<Impl>::setIntRegOperand(si, idx, val); } void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val, int width) { - this->cpu->setFloatReg(_destRegIdx[idx], val, width); + this->cpu->setFloatReg(this->_destRegIdx[idx], val, width); BaseDynInst<Impl>::setFloatRegOperand(si, idx, val, width); } void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val) { - this->cpu->setFloatReg(_destRegIdx[idx], val); + this->cpu->setFloatReg(this->_destRegIdx[idx], val); BaseDynInst<Impl>::setFloatRegOperand(si, idx, val); } void setFloatRegOperandBits(const StaticInst *si, int idx, FloatRegBits val, int width) { - this->cpu->setFloatRegBits(_destRegIdx[idx], val, width); + this->cpu->setFloatRegBits(this->_destRegIdx[idx], val, width); BaseDynInst<Impl>::setFloatRegOperandBits(si, idx, val); } void setFloatRegOperandBits(const StaticInst *si, int idx, FloatRegBits val) { - this->cpu->setFloatRegBits(_destRegIdx[idx], val); + this->cpu->setFloatRegBits(this->_destRegIdx[idx], val); BaseDynInst<Impl>::setFloatRegOperandBits(si, idx, val); } - /** Returns the physical register index of the i'th destination - * register. - */ - PhysRegIndex renamedDestRegIdx(int idx) const - { - return _destRegIdx[idx]; - } - - /** Returns the physical register index of the i'th source register. */ - PhysRegIndex renamedSrcRegIdx(int idx) const - { - return _srcRegIdx[idx]; - } - - /** Returns the physical register index of the previous physical register - * that remapped to the same logical register index. - */ - PhysRegIndex prevDestRegIdx(int idx) const - { - return _prevDestRegIdx[idx]; - } - - /** Renames a destination register to a physical register. Also records - * the previous physical register that the logical register mapped to. - */ - void renameDestReg(int idx, - PhysRegIndex renamed_dest, - PhysRegIndex previous_rename) - { - _destRegIdx[idx] = renamed_dest; - _prevDestRegIdx[idx] = previous_rename; - } - - /** Renames a source logical register to the physical register which - * has/will produce that logical register's result. - * @todo: add in whether or not the source register is ready. - */ - void renameSrcReg(int idx, PhysRegIndex renamed_src) - { - _srcRegIdx[idx] = renamed_src; - } - public: /** Calculates EA part of a memory instruction. Currently unused, * though it may be useful in the future if we want to split diff --git a/src/cpu/o3/mips/dyn_inst_impl.hh b/src/cpu/o3/mips/dyn_inst_impl.hh index 5bc01b9b3..c0f9ae771 100755 --- a/src/cpu/o3/mips/dyn_inst_impl.hh +++ b/src/cpu/o3/mips/dyn_inst_impl.hh @@ -31,9 +31,11 @@ #include "cpu/o3/mips/dyn_inst.hh" template <class Impl> -MipsDynInst<Impl>::MipsDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC, - InstSeqNum seq_num, O3CPU *cpu) - : BaseDynInst<Impl>(inst, PC, Pred_PC, seq_num, cpu) +MipsDynInst<Impl>::MipsDynInst(ExtMachInst inst, + Addr PC, Addr NPC, + Addr Pred_PC, Addr Pred_NPC, + InstSeqNum seq_num, O3CPU *cpu) + : BaseDynInst<Impl>(inst, PC, NPC, Pred_PC, Pred_NPC, seq_num, cpu) { initVars(); } @@ -53,11 +55,11 @@ MipsDynInst<Impl>::initVars() // as the normal register entries. It will allow the IQ to work // without any modifications. for (int i = 0; i < this->staticInst->numDestRegs(); i++) { - _destRegIdx[i] = this->staticInst->destRegIdx(i); + this->_destRegIdx[i] = this->staticInst->destRegIdx(i); } for (int i = 0; i < this->staticInst->numSrcRegs(); i++) { - _srcRegIdx[i] = this->staticInst->srcRegIdx(i); + this->_srcRegIdx[i] = this->staticInst->srcRegIdx(i); this->_readySrcRegIdx[i] = 0; } } diff --git a/src/cpu/o3/rename.hh b/src/cpu/o3/rename.hh index 177b9cb87..6b4628f92 100644 --- a/src/cpu/o3/rename.hh +++ b/src/cpu/o3/rename.hh @@ -411,6 +411,14 @@ class DefaultRename /** Whether or not rename needs to block this cycle. */ bool blockThisCycle; + /** Whether or not rename needs to resume a serialize instruction + * after squashing. */ + bool resumeSerialize; + + /** Whether or not rename needs to resume clearing out the skidbuffer + * after squashing. */ + bool resumeUnblocking; + /** The number of threads active in rename. */ unsigned numThreads; diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh index 3a8e503a0..e303f1cee 100644 --- a/src/cpu/o3/rename_impl.hh +++ b/src/cpu/o3/rename_impl.hh @@ -31,6 +31,8 @@ #include <list> +#include "arch/isa_traits.hh" +#include "arch/regfile.hh" #include "config/full_system.hh" #include "cpu/o3/rename.hh" @@ -41,6 +43,8 @@ DefaultRename<Impl>::DefaultRename(Params *params) commitToRenameDelay(params->commitToRenameDelay), renameWidth(params->renameWidth), commitWidth(params->commitWidth), + resumeSerialize(false), + resumeUnblocking(false), numThreads(params->numberOfThreads), maxPhysicalRegs(params->numPhysIntRegs + params->numPhysFloatRegs) { @@ -332,12 +336,22 @@ DefaultRename<Impl>::squash(const InstSeqNum &squash_seq_num, unsigned tid) // If it still needs to block, the blocking should happen the next // cycle and there should be space to hold everything due to the squash. if (renameStatus[tid] == Blocked || - renameStatus[tid] == Unblocking || - renameStatus[tid] == SerializeStall) { - + renameStatus[tid] == Unblocking) { toDecode->renameUnblock[tid] = 1; + resumeSerialize = false; serializeInst[tid] = NULL; + } else if (renameStatus[tid] == SerializeStall) { + if (serializeInst[tid]->seqNum <= squash_seq_num) { + DPRINTF(Rename, "Rename will resume serializing after squash\n"); + resumeSerialize = true; + assert(serializeInst[tid]); + } else { + resumeSerialize = false; + toDecode->renameUnblock[tid] = 1; + + serializeInst[tid] = NULL; + } } // Set the status to Squashing. @@ -392,6 +406,9 @@ DefaultRename<Impl>::squash(const InstSeqNum &squash_seq_num, unsigned tid) } slist_it++; } + resumeUnblocking = (skidBuffer[tid].size() != 0); + DPRINTF(Rename, "Resume unblocking set to %s\n", + resumeUnblocking ? "true" : "false"); #else skidBuffer[tid].clear(); #endif @@ -476,6 +493,20 @@ DefaultRename<Impl>::rename(bool &status_change, unsigned tid) ++renameSquashCycles; } else if (renameStatus[tid] == SerializeStall) { ++renameSerializeStallCycles; + // If we are currently in SerializeStall and resumeSerialize + // was set, then that means that we are resuming serializing + // this cycle. Tell the previous stages to block. + if (resumeSerialize) { + resumeSerialize = false; + block(tid); + toDecode->renameUnblock[tid] = false; + } + } else if (renameStatus[tid] == Unblocking) { + if (resumeUnblocking) { + block(tid); + resumeUnblocking = false; + toDecode->renameUnblock[tid] = false; + } } if (renameStatus[tid] == Running || @@ -741,7 +772,17 @@ DefaultRename<Impl>::skidInsert(unsigned tid) } if (skidBuffer[tid].size() > skidBufferMax) + { + typename InstQueue::iterator it; + warn("Skidbuffer contents:\n"); + for(it = skidBuffer[tid].begin(); it != skidBuffer[tid].end(); it++) + { + warn("[tid:%u]: %s [sn:%i].\n", tid, + (*it)->staticInst->disassemble(inst->readPC()), + (*it)->seqNum); + } panic("Skidbuffer Exceeded Max Size"); + } } template <class Impl> @@ -830,7 +871,10 @@ DefaultRename<Impl>::block(unsigned tid) // Only signal backwards to block if the previous stages do not think // rename is already blocked. if (renameStatus[tid] != Blocked) { - if (renameStatus[tid] != Unblocking) { + // If resumeUnblocking is set, we unblocked during the squash, + // but now we're have unblocking status. We need to tell earlier + // stages to block. + if (resumeUnblocking || renameStatus[tid] != Unblocking) { toDecode->renameBlock[tid] = true; toDecode->renameUnblock[tid] = false; wroteToTimeBuffer = true; @@ -963,13 +1007,19 @@ DefaultRename<Impl>::renameSrcRegs(DynInstPtr &inst,unsigned tid) // Will need to mark dependencies though. for (int src_idx = 0; src_idx < num_src_regs; src_idx++) { RegIndex src_reg = inst->srcRegIdx(src_idx); + RegIndex flat_src_reg = src_reg; + if (src_reg < TheISA::FP_Base_DepTag) { + flat_src_reg = TheISA::flattenIntIndex(inst->tcBase(), src_reg); + DPRINTF(Rename, "Flattening index %d to %d.\n", (int)src_reg, (int)flat_src_reg); + } + inst->flattenSrcReg(src_idx, flat_src_reg); // Look up the source registers to get the phys. register they've // been renamed to, and set the sources to those registers. - PhysRegIndex renamed_reg = renameMap[tid]->lookup(src_reg); + PhysRegIndex renamed_reg = renameMap[tid]->lookup(flat_src_reg); DPRINTF(Rename, "[tid:%u]: Looking up arch reg %i, got " - "physical reg %i.\n", tid, (int)src_reg, + "physical reg %i.\n", tid, (int)flat_src_reg, (int)renamed_reg); inst->renameSrcReg(src_idx, renamed_reg); @@ -996,20 +1046,27 @@ DefaultRename<Impl>::renameDestRegs(DynInstPtr &inst,unsigned tid) // Rename the destination registers. for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++) { RegIndex dest_reg = inst->destRegIdx(dest_idx); + RegIndex flat_dest_reg = dest_reg; + if (dest_reg < TheISA::FP_Base_DepTag) { + flat_dest_reg = TheISA::flattenIntIndex(inst->tcBase(), dest_reg); + DPRINTF(Rename, "Flattening index %d to %d.\n", (int)dest_reg, (int)flat_dest_reg); + } + + inst->flattenDestReg(dest_idx, flat_dest_reg); // Get the physical register that the destination will be // renamed to. - rename_result = renameMap[tid]->rename(dest_reg); + rename_result = renameMap[tid]->rename(flat_dest_reg); //Mark Scoreboard entry as not ready scoreboard->unsetReg(rename_result.first); DPRINTF(Rename, "[tid:%u]: Renaming arch reg %i to physical " - "reg %i.\n", tid, (int)dest_reg, + "reg %i.\n", tid, (int)flat_dest_reg, (int)rename_result.first); // Record the rename information so that a history can be kept. - RenameHistory hb_entry(inst->seqNum, dest_reg, + RenameHistory hb_entry(inst->seqNum, flat_dest_reg, rename_result.first, rename_result.second); @@ -1233,12 +1290,24 @@ DefaultRename<Impl>::checkSignalsAndUpdate(unsigned tid) if (renameStatus[tid] == Squashing) { // Switch status to running if rename isn't being told to block or // squash this cycle. - DPRINTF(Rename, "[tid:%u]: Done squashing, switching to running.\n", - tid); + if (resumeSerialize) { + DPRINTF(Rename, "[tid:%u]: Done squashing, switching to serialize.\n", + tid); - renameStatus[tid] = Running; + renameStatus[tid] = SerializeStall; + return true; + } else if (resumeUnblocking) { + DPRINTF(Rename, "[tid:%u]: Done squashing, switching to unblocking.\n", + tid); + renameStatus[tid] = Unblocking; + return true; + } else { + DPRINTF(Rename, "[tid:%u]: Done squashing, switching to running.\n", + tid); - return false; + renameStatus[tid] = Running; + return false; + } } if (renameStatus[tid] == SerializeStall) { diff --git a/src/cpu/o3/sparc/cpu.hh b/src/cpu/o3/sparc/cpu.hh index c4df79832..08ebd2710 100644 --- a/src/cpu/o3/sparc/cpu.hh +++ b/src/cpu/o3/sparc/cpu.hh @@ -37,12 +37,6 @@ #include "cpu/o3/cpu.hh" #include "sim/byteswap.hh" -namespace TheISA -{ - class ITB; - class DTB; -} - class EndQuiesceEvent; namespace Kernel { class Statistics; @@ -61,14 +55,6 @@ class TranslatingPort; template <class Impl> class SparcO3CPU : public FullO3CPU<Impl> { - protected: - typedef TheISA::IntReg IntReg; - typedef TheISA::FloatReg FloatReg; - typedef TheISA::FloatRegBits FloatRegBits; - typedef TheISA::MiscReg MiscReg; - typedef TheISA::RegFile RegFile; - typedef TheISA::MiscRegFile MiscRegFile; - public: typedef O3ThreadState<Impl> ImplState; typedef O3ThreadState<Impl> Thread; @@ -77,13 +63,6 @@ class SparcO3CPU : public FullO3CPU<Impl> /** Constructs an AlphaO3CPU with the given parameters. */ SparcO3CPU(Params *params); -#if FULL_SYSTEM - /** ITB pointer. */ - SparcISA::ITB *itb; - /** DTB pointer. */ - SparcISA::DTB *dtb; -#endif - /** Registers statistics. */ void regStats(); @@ -91,19 +70,19 @@ class SparcO3CPU : public FullO3CPU<Impl> /** Translates instruction requestion. */ Fault translateInstReq(RequestPtr &req, Thread *thread) { - return itb->translate(req, thread->getTC()); + return this->itb->translate(req, thread->getTC()); } /** Translates data read request. */ Fault translateDataReadReq(RequestPtr &req, Thread *thread) { - return dtb->translate(req, thread->getTC(), false); + return this->dtb->translate(req, thread->getTC(), false); } /** Translates data write request. */ Fault translateDataWriteReq(RequestPtr &req, Thread *thread) { - return dtb->translate(req, thread->getTC(), true); + return this->dtb->translate(req, thread->getTC(), true); } #else @@ -127,20 +106,21 @@ class SparcO3CPU : public FullO3CPU<Impl> #endif /** Reads a miscellaneous register. */ - MiscReg readMiscReg(int misc_reg, unsigned tid); + TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid); /** Reads a misc. register, including any side effects the read * might have as defined by the architecture. */ - MiscReg readMiscRegWithEffect(int misc_reg, unsigned tid); + TheISA::MiscReg readMiscRegWithEffect(int misc_reg, unsigned tid); /** Sets a miscellaneous register. */ - void setMiscReg(int misc_reg, const MiscReg &val, unsigned tid); + void setMiscReg(int misc_reg, const TheISA::MiscReg &val, unsigned tid); /** Sets a misc. register, including any side effects the write * might have as defined by the architecture. */ - void setMiscRegWithEffect(int misc_reg, const MiscReg &val, unsigned tid); + void setMiscRegWithEffect(int misc_reg, const TheISA::MiscReg &val, + unsigned tid); /** Initiates a squash of all in-flight instructions for a given * thread. The source of the squash is an external update of @@ -175,10 +155,10 @@ class SparcO3CPU : public FullO3CPU<Impl> */ void syscall(int64_t callnum, int tid); /** Gets a syscall argument. */ - IntReg getSyscallArg(int i, int tid); + TheISA::IntReg getSyscallArg(int i, int tid); /** Used to shift args for indirect syscall. */ - void setSyscallArg(int i, IntReg val, int tid); + void setSyscallArg(int i, TheISA::IntReg val, int tid); /** Sets the return value of a syscall. */ void setSyscallReturn(SyscallReturn return_value, int tid); @@ -204,4 +184,4 @@ class SparcO3CPU : public FullO3CPU<Impl> bool lockFlag; }; -#endif // __CPU_O3_ALPHA_CPU_HH__ +#endif // __CPU_O3_SPARC_CPU_HH__ diff --git a/src/cpu/o3/sparc/cpu_builder.cc b/src/cpu/o3/sparc/cpu_builder.cc index 81f419ee0..3cac89bad 100644 --- a/src/cpu/o3/sparc/cpu_builder.cc +++ b/src/cpu/o3/sparc/cpu_builder.cc @@ -55,8 +55,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(DerivO3CPU) #if FULL_SYSTEM SimObjectParam<System *> system; Param<int> cpu_id; - SimObjectParam<AlphaISA::ITB *> itb; - SimObjectParam<AlphaISA::DTB *> dtb; + SimObjectParam<SparcISA::ITB *> itb; + SimObjectParam<SparcISA::DTB *> dtb; Param<Tick> profile; Param<bool> do_quiesce; diff --git a/src/cpu/o3/sparc/cpu_impl.hh b/src/cpu/o3/sparc/cpu_impl.hh index 66bf7d1c0..c039a8fec 100644 --- a/src/cpu/o3/sparc/cpu_impl.hh +++ b/src/cpu/o3/sparc/cpu_impl.hh @@ -55,12 +55,7 @@ #endif template <class Impl> -SparcO3CPU<Impl>::SparcO3CPU(Params *params) -#if FULL_SYSTEM - : FullO3CPU<Impl>(params), itb(params->itb), dtb(params->dtb) -#else - : FullO3CPU<Impl>(params) -#endif +SparcO3CPU<Impl>::SparcO3CPU(Params *params) : FullO3CPU<Impl>(params) { DPRINTF(O3CPU, "Creating SparcO3CPU object.\n"); @@ -172,15 +167,16 @@ SparcO3CPU<Impl>::readMiscRegWithEffect(int misc_reg, unsigned tid) template <class Impl> void -SparcO3CPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid) +SparcO3CPU<Impl>::setMiscReg(int misc_reg, + const SparcISA::MiscReg &val, unsigned tid) { this->regFile.setMiscReg(misc_reg, val, tid); } template <class Impl> void -SparcO3CPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val, - unsigned tid) +SparcO3CPU<Impl>::setMiscRegWithEffect(int misc_reg, + const SparcISA::MiscReg &val, unsigned tid) { this->regFile.setMiscRegWithEffect(misc_reg, val, tid); } @@ -284,35 +280,24 @@ template <class Impl> TheISA::IntReg SparcO3CPU<Impl>::getSyscallArg(int i, int tid) { - return this->readArchIntReg(SparcISA::ArgumentReg0 + i, tid); + TheISA::IntReg idx = TheISA::flattenIntIndex(this->tcBase(tid), + SparcISA::ArgumentReg0 + i); + return this->readArchIntReg(idx, tid); } template <class Impl> void -SparcO3CPU<Impl>::setSyscallArg(int i, IntReg val, int tid) +SparcO3CPU<Impl>::setSyscallArg(int i, TheISA::IntReg val, int tid) { - this->setArchIntReg(SparcISA::ArgumentReg0 + i, val, tid); + TheISA::IntReg idx = TheISA::flattenIntIndex(this->tcBase(tid), + SparcISA::ArgumentReg0 + i); + this->setArchIntReg(idx, val, tid); } template <class Impl> void SparcO3CPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid) { - // 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 - this->setMiscReg(SparcISA::MISCREG_CCR, - this->readMiscReg(SparcISA::MISCREG_CCR, tid) & 0xEE, tid); - this->setArchIntReg(SparcISA::ReturnValueReg, - return_value.value(), tid); - } else { - // got an error, set XCC.C - this->setMiscReg(SparcISA::MISCREG_CCR, - this->readMiscReg(SparcISA::MISCREG_CCR, tid) | 0x11, tid); - this->setArchIntReg(SparcISA::ReturnValueReg, - return_value.value(), tid); - } + TheISA::setSyscallReturn(return_value, this->tcBase(tid)); } #endif diff --git a/src/cpu/o3/sparc/dyn_inst.hh b/src/cpu/o3/sparc/dyn_inst.hh index f8d6bb63f..4314488b5 100644 --- a/src/cpu/o3/sparc/dyn_inst.hh +++ b/src/cpu/o3/sparc/dyn_inst.hh @@ -32,6 +32,7 @@ #define __CPU_O3_SPARC_DYN_INST_HH__ #include "arch/sparc/isa_traits.hh" +#include "arch/sparc/types.hh" #include "cpu/base_dyn_inst.hh" #include "cpu/inst_seq.hh" #include "cpu/o3/sparc/cpu.hh" @@ -55,8 +56,8 @@ class SparcDynInst : public BaseDynInst<Impl> public: /** BaseDynInst constructor given a binary instruction. */ - SparcDynInst(TheISA::ExtMachInst inst, Addr PC, - Addr Pred_PC, InstSeqNum seq_num, O3CPU *cpu); + SparcDynInst(TheISA::ExtMachInst inst, Addr PC, Addr NPC, + Addr Pred_PC, Addr Pred_NPC, InstSeqNum seq_num, O3CPU *cpu); /** BaseDynInst constructor given a static inst pointer. */ SparcDynInst(StaticInstPtr &_staticInst); @@ -105,6 +106,45 @@ class SparcDynInst : public BaseDynInst<Impl> this->threadNumber); } + /** Reads a miscellaneous register. */ + TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx) + { + return this->cpu->readMiscReg( + si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, + this->threadNumber); + } + + /** Reads a misc. register, including any side-effects the read + * might have as defined by the architecture. + */ + TheISA::MiscReg readMiscRegOperandWithEffect(const StaticInst *si, int idx) + { + return this->cpu->readMiscRegWithEffect( + si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, + this->threadNumber); + } + + /** Sets a misc. register. */ + void setMiscRegOperand(const StaticInst * si, + int idx, const TheISA::MiscReg &val) + { + this->instResult.integer = val; + return this->cpu->setMiscReg( + si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, + val, this->threadNumber); + } + + /** Sets a misc. register, including any side-effects the write + * might have as defined by the architecture. + */ + void setMiscRegOperandWithEffect( + const StaticInst *si, int idx, const TheISA::MiscReg &val) + { + return this->cpu->setMiscRegWithEffect( + si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, + val, this->threadNumber); + } + #if FULL_SYSTEM /** Calls hardware return from error interrupt. */ Fault hwrei(); @@ -116,22 +156,6 @@ class SparcDynInst : public BaseDynInst<Impl> void syscall(int64_t callnum); #endif - private: - /** Physical register index of the destination registers of this - * instruction. - */ - PhysRegIndex _destRegIdx[TheISA::MaxInstDestRegs]; - - /** Physical register index of the source registers of this - * instruction. - */ - PhysRegIndex _srcRegIdx[TheISA::MaxInstSrcRegs]; - - /** Physical register index of the previous producers of the - * architected destinations. - */ - PhysRegIndex _prevDestRegIdx[TheISA::MaxInstDestRegs]; - public: // The register accessor methods provide the index of the @@ -145,108 +169,70 @@ class SparcDynInst : public BaseDynInst<Impl> // storage (which is pretty hard to imagine they would have reason // to do). - uint64_t readIntReg(const StaticInst *si, int idx) + uint64_t readIntRegOperand(const StaticInst *si, int idx) { - return this->cpu->readIntReg(_srcRegIdx[idx]); + uint64_t val = this->cpu->readIntReg(this->_srcRegIdx[idx]); + DPRINTF(Sparc, "Reading int reg %d (%d, %d) as %x\n", (int)this->_flatSrcRegIdx[idx], (int)this->_srcRegIdx[idx], idx, val); + return val; } - TheISA::FloatReg readFloatReg(const StaticInst *si, int idx, int width) + TheISA::FloatReg readFloatRegOperand(const StaticInst *si, + int idx, int width) { - return this->cpu->readFloatReg(_srcRegIdx[idx], width); + return this->cpu->readFloatReg(this->_srcRegIdx[idx], width); } - TheISA::FloatReg readFloatReg(const StaticInst *si, int idx) + TheISA::FloatReg readFloatRegOperand(const StaticInst *si, int idx) { - return this->cpu->readFloatReg(_srcRegIdx[idx]); + return this->cpu->readFloatReg(this->_srcRegIdx[idx]); } - TheISA::FloatRegBits readFloatRegBits(const StaticInst *si, + TheISA::FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx, int width) { - return this->cpu->readFloatRegBits(_srcRegIdx[idx], width); + return this->cpu->readFloatRegBits(this->_srcRegIdx[idx], width); } - TheISA::FloatRegBits readFloatRegBits(const StaticInst *si, int idx) + TheISA::FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx) { - return this->cpu->readFloatRegBits(_srcRegIdx[idx]); + return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]); } /** @todo: Make results into arrays so they can handle multiple dest * registers. */ - void setIntReg(const StaticInst *si, int idx, uint64_t val) + void setIntRegOperand(const StaticInst *si, int idx, uint64_t val) { - this->cpu->setIntReg(_destRegIdx[idx], val); - BaseDynInst<Impl>::setIntReg(si, idx, val); + DPRINTF(Sparc, "Setting int reg %d (%d, %d) to %x\n", (int)this->_flatDestRegIdx[idx], (int)this->_destRegIdx[idx], idx, val); + this->cpu->setIntReg(this->_destRegIdx[idx], val); + BaseDynInst<Impl>::setIntRegOperand(si, idx, val); } - void setFloatReg(const StaticInst *si, int idx, + void setFloatRegOperand(const StaticInst *si, int idx, TheISA::FloatReg val, int width) { - this->cpu->setFloatReg(_destRegIdx[idx], val, width); - BaseDynInst<Impl>::setFloatReg(si, idx, val, width); + this->cpu->setFloatReg(this->_destRegIdx[idx], val, width); + BaseDynInst<Impl>::setFloatRegOperand(si, idx, val, width); } - void setFloatReg(const StaticInst *si, int idx, TheISA::FloatReg val) + void setFloatRegOperand(const StaticInst *si, int idx, TheISA::FloatReg val) { - this->cpu->setFloatReg(_destRegIdx[idx], val); - BaseDynInst<Impl>::setFloatReg(si, idx, val); + this->cpu->setFloatReg(this->_destRegIdx[idx], val); + BaseDynInst<Impl>::setFloatRegOperand(si, idx, val); } - void setFloatRegBits(const StaticInst *si, int idx, + void setFloatRegOperandBits(const StaticInst *si, int idx, TheISA::FloatRegBits val, int width) { - this->cpu->setFloatRegBits(_destRegIdx[idx], val, width); - BaseDynInst<Impl>::setFloatRegBits(si, idx, val); + this->cpu->setFloatRegBits(this->_destRegIdx[idx], val, width); + BaseDynInst<Impl>::setFloatRegOperandBits(si, idx, val); } - void setFloatRegBits(const StaticInst *si, + void setFloatRegOperandBits(const StaticInst *si, int idx, TheISA::FloatRegBits val) { - this->cpu->setFloatRegBits(_destRegIdx[idx], val); - BaseDynInst<Impl>::setFloatRegBits(si, idx, val); - } - - /** Returns the physical register index of the i'th destination - * register. - */ - PhysRegIndex renamedDestRegIdx(int idx) const - { - return _destRegIdx[idx]; - } - - /** Returns the physical register index of the i'th source register. */ - PhysRegIndex renamedSrcRegIdx(int idx) const - { - return _srcRegIdx[idx]; - } - - /** Returns the physical register index of the previous physical register - * that remapped to the same logical register index. - */ - PhysRegIndex prevDestRegIdx(int idx) const - { - return _prevDestRegIdx[idx]; - } - - /** Renames a destination register to a physical register. Also records - * the previous physical register that the logical register mapped to. - */ - void renameDestReg(int idx, - PhysRegIndex renamed_dest, - PhysRegIndex previous_rename) - { - _destRegIdx[idx] = renamed_dest; - _prevDestRegIdx[idx] = previous_rename; - } - - /** Renames a source logical register to the physical register which - * has/will produce that logical register's result. - * @todo: add in whether or not the source register is ready. - */ - void renameSrcReg(int idx, PhysRegIndex renamed_src) - { - _srcRegIdx[idx] = renamed_src; + this->cpu->setFloatRegBits(this->_destRegIdx[idx], val); + BaseDynInst<Impl>::setFloatRegOperandBits(si, idx, val); } public: diff --git a/src/cpu/o3/sparc/dyn_inst_impl.hh b/src/cpu/o3/sparc/dyn_inst_impl.hh index 210daace2..c4d30b6f4 100644 --- a/src/cpu/o3/sparc/dyn_inst_impl.hh +++ b/src/cpu/o3/sparc/dyn_inst_impl.hh @@ -31,9 +31,10 @@ #include "cpu/o3/sparc/dyn_inst.hh" template <class Impl> -SparcDynInst<Impl>::SparcDynInst(TheISA::ExtMachInst inst, Addr PC, - Addr Pred_PC, InstSeqNum seq_num, O3CPU *cpu) - : BaseDynInst<Impl>(inst, PC, Pred_PC, seq_num, cpu) +SparcDynInst<Impl>::SparcDynInst(TheISA::ExtMachInst inst, + Addr PC, Addr NPC, Addr Pred_PC, Addr Pred_NPC, + InstSeqNum seq_num, O3CPU *cpu) + : BaseDynInst<Impl>(inst, PC, NPC, Pred_PC, Pred_NPC, seq_num, cpu) { initVars(); } @@ -53,11 +54,11 @@ SparcDynInst<Impl>::initVars() // as the normal register entries. It will allow the IQ to work // without any modifications. for (int i = 0; i < this->staticInst->numDestRegs(); i++) { - _destRegIdx[i] = this->staticInst->destRegIdx(i); + this->_destRegIdx[i] = this->staticInst->destRegIdx(i); } for (int i = 0; i < this->staticInst->numSrcRegs(); i++) { - _srcRegIdx[i] = this->staticInst->srcRegIdx(i); + this->_srcRegIdx[i] = this->staticInst->srcRegIdx(i); this->_readySrcRegIdx[i] = 0; } } @@ -126,7 +127,8 @@ template <class Impl> bool SparcDynInst<Impl>::simPalCheck(int palFunc) { - return this->cpu->simPalCheck(palFunc, this->threadNumber); + panic("simPalCheck called, but there's no PAL in SPARC!\n"); + return false; } #else template <class Impl> diff --git a/src/cpu/o3/sparc/thread_context.hh b/src/cpu/o3/sparc/thread_context.hh index 69d1e2d04..7497959e4 100644 --- a/src/cpu/o3/sparc/thread_context.hh +++ b/src/cpu/o3/sparc/thread_context.hh @@ -36,12 +36,6 @@ class SparcTC : public O3ThreadContext<Impl> { public: #if FULL_SYSTEM - /** Returns a pointer to the ITB. */ - virtual SparcISA::ITB *getITBPtr() { return this->cpu->itb; } - - /** Returns a pointer to the DTB. */ - virtual SparcISA::DTB *getDTBPtr() { return this->cpu->dtb; } - /** Returns pointer to the quiesce event. */ virtual EndQuiesceEvent *getQuiesceEvent() { @@ -62,7 +56,7 @@ class SparcTC : public O3ThreadContext<Impl> virtual void changeRegFileContext(TheISA::RegContextParam param, TheISA::RegContextVal val) { - panic("This doesn't make sense!\n"); + //XXX Ignore this for now. This -really- needs to get fixed. } diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index 390569c3d..4987d6eb4 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -66,6 +66,14 @@ class O3ThreadContext : public ThreadContext /** Pointer to the thread state that this TC corrseponds to. */ O3ThreadState<Impl> *thread; +#if FULL_SYSTEM + /** Returns a pointer to the ITB. */ + TheISA::ITB *getITBPtr() { return cpu->itb; } + + /** Returns a pointer to the DTB. */ + TheISA::DTB *getDTBPtr() { return cpu->dtb; } +#endif + /** Returns a pointer to this CPU. */ virtual BaseCPU *getCpuPtr() { return cpu; } diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index afebf294f..af98fa1f5 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -29,6 +29,7 @@ * Korey Sewell */ +#include "arch/regfile.hh" #include "cpu/o3/thread_context.hh" #include "cpu/quiesce_event.hh" @@ -305,6 +306,7 @@ template <class Impl> uint64_t O3ThreadContext<Impl>::readIntReg(int reg_idx) { + reg_idx = TheISA::flattenIntIndex(this, reg_idx); return cpu->readArchIntReg(reg_idx, thread->readTid()); } @@ -349,6 +351,7 @@ template <class Impl> void O3ThreadContext<Impl>::setIntReg(int reg_idx, uint64_t val) { + reg_idx = TheISA::flattenIntIndex(this, reg_idx); cpu->setArchIntReg(reg_idx, val, thread->readTid()); // Squash if we're not already in a state update mode. diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index 0da446c9c..baea7a546 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -219,11 +219,19 @@ class OzoneCPU : public BaseCPU uint64_t readNextNPC() { - return 0; +#if ISA_HAS_DELAY_SLOT + panic("Ozone needs to support nextNPC"); +#else + return thread->nextPC + sizeof(TheISA::MachInst); +#endif } void setNextNPC(uint64_t val) - { } + { +#if ISA_HAS_DELAY_SLOT + panic("Ozone needs to support nextNPC"); +#endif + } public: // ISA stuff: diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index c39bfa9cd..c4853b916 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -54,15 +54,15 @@ namespace TheISA } class MemObject; -class RemoteGDB; -class GDBListener; - #else class Process; #endif // FULL_SYSTEM +class RemoteGDB; +class GDBListener; + class ThreadContext; class Checkpoint; @@ -186,7 +186,8 @@ class BaseSimpleCPU : public BaseCPU // These functions are only used in CPU models that split // effective address computation from the actual memory access. void setEA(Addr EA) { panic("BaseSimpleCPU::setEA() not implemented\n"); } - Addr getEA() { panic("BaseSimpleCPU::getEA() not implemented\n"); } + Addr getEA() { panic("BaseSimpleCPU::getEA() not implemented\n"); + M5_DUMMY_RETURN} void prefetch(Addr addr, unsigned flags) { @@ -303,6 +304,31 @@ class BaseSimpleCPU : public BaseCPU return thread->setMiscRegWithEffect(misc_reg, val); } + MiscReg readMiscRegOperand(const StaticInst *si, int idx) + { + int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag; + return thread->readMiscReg(reg_idx); + } + + MiscReg readMiscRegOperandWithEffect(const StaticInst *si, int idx) + { + int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag; + return thread->readMiscRegWithEffect(reg_idx); + } + + void setMiscRegOperand(const StaticInst *si, int idx, const MiscReg &val) + { + int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag; + return thread->setMiscReg(reg_idx, val); + } + + void setMiscRegOperandWithEffect( + const StaticInst *si, int idx, const MiscReg &val) + { + int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag; + return thread->setMiscRegWithEffect(reg_idx, val); + } + #if FULL_SYSTEM Fault hwrei() { return thread->hwrei(); } void ev5_trap(Fault fault) { fault->invoke(tc); } diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index 10bbe292c..f2f79c070 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -33,6 +33,8 @@ #define __CPU_SIMPLE_THREAD_HH__ #include "arch/isa_traits.hh" +#include "arch/regfile.hh" +#include "arch/syscallreturn.hh" #include "config/full_system.hh" #include "cpu/thread_context.hh" #include "cpu/thread_state.hh" @@ -250,7 +252,7 @@ class SimpleThread : public ThreadState // uint64_t readIntReg(int reg_idx) { - return regs.readIntReg(reg_idx); + return regs.readIntReg(TheISA::flattenIntIndex(getTC(), reg_idx)); } FloatReg readFloatReg(int reg_idx, int width) @@ -275,7 +277,7 @@ class SimpleThread : public ThreadState void setIntReg(int reg_idx, uint64_t val) { - regs.setIntReg(reg_idx, val); + regs.setIntReg(TheISA::flattenIntIndex(getTC(), reg_idx), val); } void setFloatReg(int reg_idx, FloatReg val, int width) @@ -376,18 +378,20 @@ class SimpleThread : public ThreadState #if !FULL_SYSTEM TheISA::IntReg getSyscallArg(int i) { - return regs.readIntReg(TheISA::ArgumentReg0 + i); + return regs.readIntReg(TheISA::flattenIntIndex(getTC(), + TheISA::ArgumentReg0 + i)); } // used to shift args for indirect syscall void setSyscallArg(int i, TheISA::IntReg val) { - regs.setIntReg(TheISA::ArgumentReg0 + i, val); + regs.setIntReg(TheISA::flattenIntIndex(getTC(), + TheISA::ArgumentReg0 + i), val); } void setSyscallReturn(SyscallReturn return_value) { - TheISA::setSyscallReturn(return_value, ®s); + TheISA::setSyscallReturn(return_value, getTC()); } void syscall(int64_t callnum) diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index 5928eea76..416c8ab56 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -379,6 +379,7 @@ class StaticInst : public StaticInstBase { panic("StaticInst::branchTarget() called on instruction " "that is not a PC-relative branch."); + M5_DUMMY_RETURN } /** @@ -393,6 +394,7 @@ class StaticInst : public StaticInstBase panic("StaticInst::branchTarget() called on instruction " "that is not an indirect branch."); } + M5_DUMMY_RETURN /** * Return true if the instruction is a control transfer, and if so, diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index bb9cc9e16..16e491fd3 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -32,13 +32,13 @@ #define __CPU_THREAD_CONTEXT_HH__ #include "arch/regfile.hh" -#include "arch/syscallreturn.hh" #include "arch/types.hh" #include "config/full_system.hh" #include "mem/request.hh" #include "sim/faults.hh" #include "sim/host.hh" #include "sim/serialize.hh" +#include "sim/syscallreturn.hh" #include "sim/byteswap.hh" // @todo: Figure out a more architecture independent way to obtain the ITB and diff --git a/src/dev/alpha/tsunami_io.cc b/src/dev/alpha/tsunami_io.cc index d701dc98f..58933428c 100644 --- a/src/dev/alpha/tsunami_io.cc +++ b/src/dev/alpha/tsunami_io.cc @@ -65,69 +65,32 @@ TsunamiIO::RTC::RTC(const string &n, Tsunami* tsunami, const vector<int> &t, stat_regA = RTCA_32768HZ | RTCA_1024HZ; stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR; - if (year_is_bcd) { - // The RTC uses BCD for the last two digits in the year. - // They python year is a full year. - int _year = t[0] % 100; - int tens = _year / 10; - int ones = _year % 10; - - year = (tens << 4) + ones; - } else { - // Even though the datasheet says that the year field should be - // interpreted as BCD, we just enter the number of years since - // 1900 since linux seems to be happy with that (and I believe - // that Tru64 was as well) - year = t[0] - 1900; - } - - mon = t[1]; - mday = t[2]; - hour = t[3]; - min = t[4]; - sec = t[5]; - - // wday is defined to be in the range from 1 - 7 with 1 being Sunday. - // the value coming from python is in the range from 0 - 6 with 0 being - // Monday. Fix that here. - wday = t[6] + 2; - if (wday > 7) - wday -= 7; - - DPRINTFN("Real-time clock set to %s", getDateString()); -} - -std::string -TsunamiIO::RTC::getDateString() -{ struct tm tm; + parseTime(t, &tm); - memset(&tm, 0, sizeof(tm)); + year = tm.tm_year; if (year_is_bcd) { - // undo the BCD and conver to years since 1900 guessing that - // anything before 1970 is actually after 2000 - int _year = (year >> 4) * 10 + (year & 0xf); - if (_year < 70) - _year += 100; - - tm.tm_year = _year; - } else { - // number of years since 1900 - tm.tm_year = year; + // The datasheet says that the year field can be either BCD or + // years since 1900. Linux seems to be happy with years since + // 1900. + year = year % 100; + int tens = year / 10; + int ones = year % 10; + year = (tens << 4) + ones; } - // unix is 0-11 for month - tm.tm_mon = mon - 1; - tm.tm_mday = mday; - tm.tm_hour = hour; - tm.tm_min = min; - tm.tm_sec = sec; + // Unix is 0-11 for month, data seet says start at 1 + mon = tm.tm_mon + 1; + mday = tm.tm_mday; + hour = tm.tm_hour; + min = tm.tm_min; + sec = tm.tm_sec; - // to add more annoyance unix is 0 - 6 with 0 as sunday - tm.tm_wday = wday - 1; + // Datasheet says 1 is sunday + wday = tm.tm_wday + 1; - return asctime(&tm); + DPRINTFN("Real-time clock set to %s", asctime(&tm)); } void diff --git a/src/dev/alpha/tsunami_io.hh b/src/dev/alpha/tsunami_io.hh index f42af4197..f4fa62a68 100644 --- a/src/dev/alpha/tsunami_io.hh +++ b/src/dev/alpha/tsunami_io.hh @@ -125,9 +125,6 @@ class TsunamiIO : public BasicPioDevice /** RTC read data */ uint8_t readData(); - /** RTC get the date */ - std::string getDateString(); - /** * Serialize this object to the given output stream. * @param base The base name of the counter object. diff --git a/src/dev/baddev.cc b/src/dev/baddev.cc index 6a7060455..a2d2650cb 100644 --- a/src/dev/baddev.cc +++ b/src/dev/baddev.cc @@ -56,12 +56,14 @@ Tick BadDevice::read(PacketPtr pkt) { panic("Device %s not imlpmented\n", devname); + M5_DUMMY_RETURN } Tick BadDevice::write(PacketPtr pkt) { panic("Device %s not imlpmented\n", devname); + M5_DUMMY_RETURN } BEGIN_DECLARE_SIM_OBJECT_PARAMS(BadDevice) diff --git a/src/dev/ide_atareg.h b/src/dev/ide_atareg.h index df16d09d5..b9f1d9e0f 100644 --- a/src/dev/ide_atareg.h +++ b/src/dev/ide_atareg.h @@ -35,7 +35,7 @@ #if defined(linux) #include <endian.h> -#elif defined(__sun__) +#elif defined(__sun) #include <sys/isa_defs.h> #else #include <machine/endian.h> diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh index aa242d170..c56eba267 100644 --- a/src/dev/io_device.hh +++ b/src/dev/io_device.hh @@ -109,7 +109,7 @@ class DmaPort : public Port virtual bool recvTiming(PacketPtr pkt); virtual Tick recvAtomic(PacketPtr pkt) - { panic("dma port shouldn't be used for pio access."); } + { panic("dma port shouldn't be used for pio access."); M5_DUMMY_RETURN } virtual void recvFunctional(PacketPtr pkt) { panic("dma port shouldn't be used for pio access."); } diff --git a/src/dev/pciconfigall.cc b/src/dev/pciconfigall.cc index 39c8f0fa0..bd1855847 100644 --- a/src/dev/pciconfigall.cc +++ b/src/dev/pciconfigall.cc @@ -83,8 +83,10 @@ PciConfigAll::write(PacketPtr pkt) { assert(pkt->result == Packet::Unknown); panic("Attempting to write to config space on non-existant device\n"); + M5_DUMMY_RETURN } + void PciConfigAll::addressRanges(AddrRangeList &range_list) { diff --git a/src/dev/pcidev.hh b/src/dev/pcidev.hh index fbfdbb65c..56e3ffb4a 100644 --- a/src/dev/pcidev.hh +++ b/src/dev/pcidev.hh @@ -37,6 +37,8 @@ #ifndef __DEV_PCIDEV_HH__ #define __DEV_PCIDEV_HH__ +#include <cstring> + #include "dev/io_device.hh" #include "dev/pcireg.h" #include "dev/platform.hh" @@ -62,8 +64,8 @@ class PciConfigData : public SimObject PciConfigData(const std::string &name) : SimObject(name) { - memset(config.data, 0, sizeof(config.data)); - memset(BARSize, 0, sizeof(BARSize)); + std::memset(config.data, 0, sizeof(config.data)); + std::memset(BARSize, 0, sizeof(BARSize)); } /** The first 64 bytes */ diff --git a/src/dev/platform.cc b/src/dev/platform.cc index 07288249c..b2b8695a7 100644 --- a/src/dev/platform.cc +++ b/src/dev/platform.cc @@ -62,6 +62,7 @@ Addr Platform::pciToDma(Addr pciAddr) const { panic("No PCI dma support in platform."); + M5_DUMMY_RETURN } void diff --git a/src/dev/sparc/dtod.cc b/src/dev/sparc/dtod.cc index 30c7baaf5..42275c60a 100644 --- a/src/dev/sparc/dtod.cc +++ b/src/dev/sparc/dtod.cc @@ -49,12 +49,24 @@ using namespace std; using namespace TheISA; DumbTOD::DumbTOD(Params *p) - : BasicPioDevice(p), todTime(p->init_time) + : BasicPioDevice(p) { + struct tm tm; + char *tz; + pioSize = 0x08; - struct tm tm; - gmtime_r((time_t*)&todTime, &tm); + parseTime(p->init_time, &tm); + tz = getenv("TZ"); + setenv("TZ", "", 1); + tzset(); + todTime = mktime(&tm); + if (tz) + setenv("TZ", tz, 1); + else + unsetenv("TZ"); + tzset(); + DPRINTFN("Real-time clock set to %s\n", asctime(&tm)); DPRINTFN("Real-time clock set to %d\n", todTime); } @@ -80,13 +92,26 @@ DumbTOD::write(PacketPtr pkt) panic("Dumb tod device doesn't support writes\n"); } +void +DumbTOD::serialize(std::ostream &os) +{ + SERIALIZE_SCALAR(todTime); +} + +void +DumbTOD::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_SCALAR(todTime); +} + + BEGIN_DECLARE_SIM_OBJECT_PARAMS(DumbTOD) Param<Addr> pio_addr; Param<Tick> pio_latency; SimObjectParam<Platform *> platform; SimObjectParam<System *> system; - Param<time_t> time; + VectorParam<int> time; END_DECLARE_SIM_OBJECT_PARAMS(DumbTOD) @@ -96,7 +121,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(DumbTOD) INIT_PARAM(pio_latency, "Programmed IO latency"), INIT_PARAM(platform, "platform"), INIT_PARAM(system, "system object"), - INIT_PARAM(time, "System time to use (0 for actual time") + INIT_PARAM(time, "") END_INIT_SIM_OBJECT_PARAMS(DumbTOD) diff --git a/src/dev/sparc/dtod.hh b/src/dev/sparc/dtod.hh index 7d3a9f628..ddf9fcc96 100644 --- a/src/dev/sparc/dtod.hh +++ b/src/dev/sparc/dtod.hh @@ -36,6 +36,8 @@ #ifndef __DEV_SPARC_DTOD_HH__ #define __DEV_SPARC_DTOD_HH__ +#include <vector> + #include "base/range.hh" #include "dev/io_device.hh" @@ -52,7 +54,7 @@ class DumbTOD : public BasicPioDevice public: struct Params : public BasicPioDevice::Params { - time_t init_time; + std::vector<int> init_time; }; protected: const Params *params() const { return (const Params *)_params; } @@ -62,6 +64,21 @@ class DumbTOD : public BasicPioDevice virtual Tick read(PacketPtr pkt); virtual Tick write(PacketPtr pkt); + + /** + * Serialize this object to the given output stream. + * @param os The stream to serialize to. + */ + virtual void serialize(std::ostream &os); + + /** + * Reconstruct the state of this object from a checkpoint. + * @param cp The checkpoint use. + * @param section The section name of this object + */ + virtual void unserialize(Checkpoint *cp, const std::string §ion); + + }; #endif // __DEV_BADDEV_HH__ diff --git a/src/dev/sparc/mm_disk.cc b/src/dev/sparc/mm_disk.cc index 9057c28be..018415f6c 100644 --- a/src/dev/sparc/mm_disk.cc +++ b/src/dev/sparc/mm_disk.cc @@ -33,6 +33,8 @@ * in legion. Any access is translated to an offset in the disk image. */ +#include <cstring> + #include "base/trace.hh" #include "dev/sparc/mm_disk.hh" #include "dev/platform.hh" @@ -45,7 +47,7 @@ MmDisk::MmDisk(Params *p) : BasicPioDevice(p), image(p->image), curSector((uint64_t)-1), dirty(false) { - memset(&bytes, 0, SectorSize); + std::memset(&bytes, 0, SectorSize); pioSize = image->size() * SectorSize; } @@ -99,6 +101,7 @@ Tick MmDisk::write(PacketPtr pkt) { panic("need to implement\n"); + M5_DUMMY_RETURN } diff --git a/src/dev/sparc/t1000.cc b/src/dev/sparc/t1000.cc index 4a8de77a5..3a2f881f1 100644 --- a/src/dev/sparc/t1000.cc +++ b/src/dev/sparc/t1000.cc @@ -57,6 +57,7 @@ Tick T1000::intrFrequency() { panic("Need implementation\n"); + M5_DUMMY_RETURN } void @@ -89,6 +90,7 @@ Addr T1000::pciToDma(Addr pciAddr) const { panic("Need implementation\n"); + M5_DUMMY_RETURN } @@ -96,18 +98,7 @@ Addr T1000::calcConfigAddr(int bus, int dev, int func) { panic("Need implementation\n"); -} - -void -T1000::serialize(std::ostream &os) -{ - panic("Need implementation\n"); -} - -void -T1000::unserialize(Checkpoint *cp, const std::string §ion) -{ - panic("Need implementation\n"); + M5_DUMMY_RETURN } BEGIN_DECLARE_SIM_OBJECT_PARAMS(T1000) diff --git a/src/dev/sparc/t1000.hh b/src/dev/sparc/t1000.hh index 2955763a9..8e28d90e5 100644 --- a/src/dev/sparc/t1000.hh +++ b/src/dev/sparc/t1000.hh @@ -90,19 +90,6 @@ class T1000 : public Platform * Calculate the configuration address given a bus/dev/func. */ virtual Addr calcConfigAddr(int bus, int dev, int func); - - /** - * Serialize this object to the given output stream. - * @param os The stream to serialize to. - */ - virtual void serialize(std::ostream &os); - - /** - * Reconstruct the state of this object from a checkpoint. - * @param cp The checkpoint use. - * @param section The section name of this object - */ - virtual void unserialize(Checkpoint *cp, const std::string §ion); }; #endif // __DEV_T1000_HH__ diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 9c41983fc..b8c896498 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -40,6 +40,7 @@ #include <cassert> #include <iostream> +#include <cstring> #include <string> #include "sim/host.hh" @@ -125,7 +126,7 @@ Cache<TagStore,Coherence>::handleAccess(PacketPtr &pkt, int & lat, assert(offset < blkSize); assert(pkt->getSize() <= blkSize); assert(offset+pkt->getSize() <= blkSize); - memcpy(blk->data + offset, pkt->getPtr<uint8_t>(), + std::memcpy(blk->data + offset, pkt->getPtr<uint8_t>(), pkt->getSize()); } else if (!(pkt->flags & SATISFIED)) { pkt->flags |= SATISFIED; @@ -133,7 +134,7 @@ Cache<TagStore,Coherence>::handleAccess(PacketPtr &pkt, int & lat, assert(offset < blkSize); assert(pkt->getSize() <= blkSize); assert(offset + pkt->getSize() <=blkSize); - memcpy(pkt->getPtr<uint8_t>(), blk->data + offset, + std::memcpy(pkt->getPtr<uint8_t>(), blk->data + offset, pkt->getSize()); } return blk; @@ -176,7 +177,7 @@ Cache<TagStore,Coherence>::handleAccess(PacketPtr &pkt, int & lat, if (blk->checkWrite(pkt->req)) { write_data = true; blk->status |= BlkDirty; - memcpy(blk->data + offset, pkt->getPtr<uint8_t>(), + std::memcpy(blk->data + offset, pkt->getPtr<uint8_t>(), pkt->getSize()); } } else { @@ -184,7 +185,7 @@ Cache<TagStore,Coherence>::handleAccess(PacketPtr &pkt, int & lat, if (pkt->req->isLocked()) { blk->trackLoadLocked(pkt->req); } - memcpy(pkt->getPtr<uint8_t>(), blk->data + offset, + std::memcpy(pkt->getPtr<uint8_t>(), blk->data + offset, pkt->getSize()); } @@ -228,7 +229,7 @@ Cache<TagStore,Coherence>::handleFill(BlkType *blk, PacketPtr &pkt, if (pkt->isRead()) { - memcpy(blk->data, pkt->getPtr<uint8_t>(), blkSize); + std::memcpy(blk->data, pkt->getPtr<uint8_t>(), blkSize); } blk->whenReady = pkt->finishTime; @@ -249,14 +250,14 @@ Cache<TagStore,Coherence>::handleFill(BlkType *blk, PacketPtr &pkt, if (target->isWrite()) { if (blk->checkWrite(pkt->req)) { blk->status |= BlkDirty; - memcpy(blk->data + target->getOffset(blkSize), + std::memcpy(blk->data + target->getOffset(blkSize), target->getPtr<uint8_t>(), target->getSize()); } } else { if (pkt->req->isLocked()) { blk->trackLoadLocked(pkt->req); } - memcpy(target->getPtr<uint8_t>(), + std::memcpy(target->getPtr<uint8_t>(), blk->data + target->getOffset(blkSize), target->getSize()); } @@ -285,7 +286,7 @@ Cache<TagStore,Coherence>::handleFill(BlkType *blk, MSHR * mshr, blk = doReplacement(blk, pkt, new_state, writebacks); if (pkt->isRead()) { - memcpy(blk->data, pkt->getPtr<uint8_t>(), blkSize); + std::memcpy(blk->data, pkt->getPtr<uint8_t>(), blkSize); } blk->whenReady = pkt->finishTime; @@ -337,14 +338,14 @@ Cache<TagStore,Coherence>::handleFill(BlkType *blk, MSHR * mshr, if (target->isWrite()) { if (blk->checkWrite(pkt->req)) { blk->status |= BlkDirty; - memcpy(blk->data + target->getOffset(blkSize), + std::memcpy(blk->data + target->getOffset(blkSize), target->getPtr<uint8_t>(), target->getSize()); } } else { if (pkt->req->isLocked()) { blk->trackLoadLocked(pkt->req); } - memcpy(target->getPtr<uint8_t>(), + std::memcpy(target->getPtr<uint8_t>(), blk->data + target->getOffset(blkSize), target->getSize()); } @@ -384,7 +385,7 @@ Cache<TagStore,Coherence>::handleSnoop(BlkType *blk, assert(offset < blkSize); assert(pkt->getSize() <= blkSize); assert(offset + pkt->getSize() <=blkSize); - memcpy(pkt->getPtr<uint8_t>(), blk->data + offset, pkt->getSize()); + std::memcpy(pkt->getPtr<uint8_t>(), blk->data + offset, pkt->getSize()); handleSnoop(blk, new_state); } @@ -431,7 +432,7 @@ Cache<TagStore,Coherence>::writebackBlk(BlkType *blk) new Request(tags->regenerateBlkAddr(blk->tag, blk->set), blkSize, 0); PacketPtr writeback = new Packet(writebackReq, Packet::Writeback, -1); writeback->allocate(); - memcpy(writeback->getPtr<uint8_t>(),blk->data,blkSize); + std::memcpy(writeback->getPtr<uint8_t>(),blk->data,blkSize); blk->status &= ~BlkDirty; return writeback; @@ -463,7 +464,7 @@ Cache<TagStore,Coherence>::verifyData(BlkType *blk) assert(blkSize == blk->size); } - retval = memcmp(tmp_data, blk->data, blkSize) == 0; + retval = std::memcmp(tmp_data, blk->data, blkSize) == 0; delete [] tmp_data; return retval; } @@ -664,7 +665,7 @@ Cache<TagStore,Coherence>::sendResult(PacketPtr &pkt, MSHR* mshr, DPRINTF(Cache, "Block for blk addr %x moving from state " "%i to %i\n", pkt->getAddr(), old_state, new_state); //Set the state on the upgrade - memcpy(pkt->getPtr<uint8_t>(), blk->data, blkSize); + std::memcpy(pkt->getPtr<uint8_t>(), blk->data, blkSize); PacketList writebacks; handleFill(blk, mshr, new_state, writebacks, pkt); assert(writebacks.empty()); @@ -839,7 +840,7 @@ Cache<TagStore,Coherence>::snoop(PacketPtr &pkt) assert(offset < blkSize); assert(pkt->getSize() <= blkSize); assert(offset + pkt->getSize() <=blkSize); - memcpy(pkt->getPtr<uint8_t>(), mshr->pkt->getPtr<uint8_t>() + offset, pkt->getSize()); + std::memcpy(pkt->getPtr<uint8_t>(), mshr->pkt->getPtr<uint8_t>() + offset, pkt->getSize()); respondToSnoop(pkt, curTick + hitLatency); } diff --git a/src/mem/cache/miss/blocking_buffer.cc b/src/mem/cache/miss/blocking_buffer.cc index 4a431d82d..a1af88341 100644 --- a/src/mem/cache/miss/blocking_buffer.cc +++ b/src/mem/cache/miss/blocking_buffer.cc @@ -32,6 +32,7 @@ * @file * Definitions of a simple buffer for a blocking cache. */ +#include <cstring> #include "mem/cache/base_cache.hh" #include "mem/cache/miss/blocking_buffer.hh" @@ -60,7 +61,7 @@ BlockingBuffer::handleMiss(PacketPtr &pkt, int blk_size, Tick time) wb.allocate(pkt->cmd, blk_addr, blk_size, pkt); } - memcpy(wb.pkt->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), blk_size); + std::memcpy(wb.pkt->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), blk_size); cache->setBlocked(Blocked_NoWBBuffers); cache->setMasterRequest(Request_WB, time); @@ -147,7 +148,7 @@ BlockingBuffer::handleResponse(PacketPtr &pkt, Tick time) PacketPtr target = ((MSHR*)(pkt->senderState))->getTarget(); ((MSHR*)(pkt->senderState))->popTarget(); if (pkt->isRead()) { - memcpy(target->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), target->getSize()); + std::memcpy(target->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), target->getSize()); } cache->respond(target, time); assert(!((MSHR*)(pkt->senderState))->hasTargets()); @@ -191,7 +192,7 @@ BlockingBuffer::doWriteback(Addr addr, PacketPtr pkt = new Packet(req, Packet::Writeback, -1); pkt->allocate(); if (data) { - memcpy(pkt->getPtr<uint8_t>(), data, size); + std::memcpy(pkt->getPtr<uint8_t>(), data, size); } if (compressed) { @@ -217,7 +218,7 @@ BlockingBuffer::doWriteback(PacketPtr &pkt) // Since allocate as buffer copies the request, // need to copy data here. - memcpy(wb.pkt->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), pkt->getSize()); + std::memcpy(wb.pkt->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), pkt->getSize()); cache->setBlocked(Blocked_NoWBBuffers); cache->setMasterRequest(Request_WB, curTick); diff --git a/src/mem/cache/miss/blocking_buffer.hh b/src/mem/cache/miss/blocking_buffer.hh index 205068a8c..24386a249 100644 --- a/src/mem/cache/miss/blocking_buffer.hh +++ b/src/mem/cache/miss/blocking_buffer.hh @@ -90,6 +90,7 @@ public: PacketPtr &target) { fatal("Unimplemented"); + M5_DUMMY_RETURN } /** @@ -201,6 +202,7 @@ public: MSHR* allocateTargetList(Addr addr) { fatal("Unimplemented"); + M5_DUMMY_RETURN } }; diff --git a/src/mem/cache/tags/iic.cc b/src/mem/cache/tags/iic.cc index 38f9662ea..e547e112e 100644 --- a/src/mem/cache/tags/iic.cc +++ b/src/mem/cache/tags/iic.cc @@ -527,7 +527,7 @@ IIC::hash(Addr addr) const { tag = extractTag(addr); mask = hashSets-1; /* assumes iic_hash_size is a power of 2 */ x = tag & mask; - y = (tag >> (int)(::log(hashSets)/::log(2))) & mask; + y = (tag >> (int)(::log((double)hashSets)/::log((double)2))) & mask; assert (x < hashSets && y < hashSets); return x ^ y; #endif diff --git a/src/mem/cache/tags/lru.hh b/src/mem/cache/tags/lru.hh index 4b94adca6..75272544c 100644 --- a/src/mem/cache/tags/lru.hh +++ b/src/mem/cache/tags/lru.hh @@ -36,6 +36,7 @@ #ifndef __LRU_HH__ #define __LRU_HH__ +#include <cstring> #include <list> #include "mem/cache/cache_blk.hh" // base class @@ -273,7 +274,7 @@ public: */ void readData(LRUBlk *blk, uint8_t *data) { - memcpy(data, blk->data, blk->size); + std::memcpy(data, blk->data, blk->size); } /** diff --git a/src/mem/cache/tags/split.hh b/src/mem/cache/tags/split.hh index e6ace0921..840b68940 100644 --- a/src/mem/cache/tags/split.hh +++ b/src/mem/cache/tags/split.hh @@ -36,6 +36,7 @@ #ifndef __SPLIT_HH__ #define __SPLIT_HH__ +#include <cstring> #include <list> #include "mem/cache/cache_blk.hh" // base class @@ -234,6 +235,7 @@ class Split : public BaseTags int extractSet(Addr addr) const { panic("should never call this!\n"); + M5_DUMMY_RETURN } /** @@ -281,7 +283,7 @@ class Split : public BaseTags */ void readData(SplitBlk *blk, uint8_t *data) { - memcpy(data, blk->data, blk->size); + std::memcpy(data, blk->data, blk->size); } /** diff --git a/src/mem/cache/tags/split_lifo.hh b/src/mem/cache/tags/split_lifo.hh index 9001cdb14..0f8adf18d 100644 --- a/src/mem/cache/tags/split_lifo.hh +++ b/src/mem/cache/tags/split_lifo.hh @@ -36,6 +36,7 @@ #ifndef __SPLIT_LIFO_HH__ #define __SPLIT_LIFO_HH__ +#include <cstring> #include <list> #include "mem/cache/cache_blk.hh" // base class @@ -296,7 +297,7 @@ public: */ void readData(SplitBlk *blk, uint8_t *data) { - memcpy(data, blk->data, blk->size); + std::memcpy(data, blk->data, blk->size); } /** diff --git a/src/mem/cache/tags/split_lru.hh b/src/mem/cache/tags/split_lru.hh index e17a478d3..eb65445ea 100644 --- a/src/mem/cache/tags/split_lru.hh +++ b/src/mem/cache/tags/split_lru.hh @@ -36,6 +36,7 @@ #ifndef __SPLIT_LRU_HH__ #define __SPLIT_LRU_HH__ +#include <cstring> #include <list> #include "mem/cache/cache_blk.hh" // base class @@ -279,7 +280,7 @@ public: */ void readData(SplitBlk *blk, uint8_t *data) { - memcpy(data, blk->data, blk->size); + std::memcpy(data, blk->data, blk->size); } /** diff --git a/src/mem/dram.cc b/src/mem/dram.cc index 873ca5b97..394c70db6 100644 --- a/src/mem/dram.cc +++ b/src/mem/dram.cc @@ -102,7 +102,7 @@ Kluwer Academic, pages 291-310, March, 2000. #include "mem/dram.hh" #include "sim/builder.hh" - +#include <stdlib.h> #include <string> extern int maxThreadsPerCPU; @@ -203,7 +203,7 @@ DRAMMemory::DRAMMemory(Params *p) last_bank = num_banks+1; last_row = num_rows; busy_until = new Tick[num_banks]; - memset(busy_until,0,sizeof(Tick)*num_banks); /* initiliaze */ + std::memset(busy_until,0,sizeof(Tick)*num_banks); /* initiliaze */ } diff --git a/src/mem/packet.cc b/src/mem/packet.cc index e2faf4527..44805236c 100644 --- a/src/mem/packet.cc +++ b/src/mem/packet.cc @@ -36,7 +36,7 @@ */ #include <iostream> - +#include <cstring> #include "base/misc.hh" #include "base/trace.hh" #include "mem/packet.hh" @@ -183,7 +183,7 @@ fixPacket(PacketPtr func, PacketPtr timing) if (func->isRead()) { if (funcStart >= timingStart && funcEnd <= timingEnd) { func->allocate(); - memcpy(func->getPtr<uint8_t>(), timing->getPtr<uint8_t>() + + std::memcpy(func->getPtr<uint8_t>(), timing->getPtr<uint8_t>() + funcStart - timingStart, func->getSize()); func->result = Packet::Success; func->flags |= SATISFIED; @@ -199,11 +199,11 @@ fixPacket(PacketPtr func, PacketPtr timing) } } else if (func->isWrite()) { if (funcStart >= timingStart) { - memcpy(timing->getPtr<uint8_t>() + (funcStart - timingStart), + std::memcpy(timing->getPtr<uint8_t>() + (funcStart - timingStart), func->getPtr<uint8_t>(), (std::min(funcEnd, timingEnd) - funcStart) + 1); } else { // timingStart > funcStart - memcpy(timing->getPtr<uint8_t>(), + std::memcpy(timing->getPtr<uint8_t>(), func->getPtr<uint8_t>() + (timingStart - funcStart), (std::min(funcEnd, timingEnd) - timingStart) + 1); } diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 19251941f..15f605ca7 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -41,10 +41,12 @@ #include <cassert> #include <list> +#include "base/misc.hh" #include "mem/request.hh" #include "sim/host.hh" #include "sim/root.hh" + struct Packet; typedef Packet *PacketPtr; typedef uint8_t* PacketDataPtr; @@ -238,7 +240,7 @@ class Packet bool isNoAllocate() const { return (flags & NO_ALLOCATE) != 0; } bool isCompressed() const { return (flags & COMPRESSED) != 0; } - bool nic_pkt() { assert("Unimplemented\n" && 0); return false; } + bool nic_pkt() { panic("Unimplemented"); M5_DUMMY_RETURN } /** Possible results of a packet's request. */ enum Result diff --git a/src/mem/physical.cc b/src/mem/physical.cc index 7d616a4e5..eccd42bec 100644 --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -59,7 +59,7 @@ PhysicalMemory::PhysicalMemory(Params *p) int map_flags = MAP_ANON | MAP_PRIVATE; pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE, - map_flags, -1, 0); + map_flags, -1, 0); if (pmemAddr == (void *)MAP_FAILED) { perror("mmap"); @@ -84,7 +84,7 @@ PhysicalMemory::init() PhysicalMemory::~PhysicalMemory() { if (pmemAddr) - munmap(pmemAddr, params()->addrRange.size()); + munmap((char*)pmemAddr, params()->addrRange.size()); //Remove memPorts? } @@ -430,7 +430,7 @@ PhysicalMemory::unserialize(Checkpoint *cp, const string §ion) // unmap file that was mmaped in the constructor // This is done here to make sure that gzip and open don't muck with our // nice large space of memory before we reallocate it - munmap(pmemAddr, params()->addrRange.size()); + munmap((char*)pmemAddr, params()->addrRange.size()); pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); diff --git a/src/mem/port.cc b/src/mem/port.cc index bbc98c160..da719bbd9 100644 --- a/src/mem/port.cc +++ b/src/mem/port.cc @@ -32,6 +32,7 @@ * @file * Port object definitions. */ +#include <cstring> #include "base/chunk_generator.hh" #include "base/trace.hh" @@ -78,7 +79,7 @@ Port::memsetBlob(Addr addr, uint8_t val, int size) // quick and dirty... uint8_t *buf = new uint8_t[size]; - memset(buf, val, size); + std::memset(buf, val, size); blobHelper(addr, buf, size, Packet::WriteReq); delete [] buf; diff --git a/src/mem/port.hh b/src/mem/port.hh index 75afc04e6..5e55225bf 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -159,7 +159,7 @@ class Port this function to be called, a DMA interface doesn't really have a block size, so it is defaulted to a panic. */ - virtual int deviceBlockSize() { panic("??"); } + virtual int deviceBlockSize() { panic("??"); M5_DUMMY_RETURN } /** The peer port is requesting us to reply with a list of the ranges we are responsible for. @@ -261,8 +261,10 @@ class FunctionalPort : public Port {} protected: - virtual bool recvTiming(PacketPtr pkt) { panic("FuncPort is UniDir"); } - virtual Tick recvAtomic(PacketPtr pkt) { panic("FuncPort is UniDir"); } + virtual bool recvTiming(PacketPtr pkt) { panic("FuncPort is UniDir"); + M5_DUMMY_RETURN } + virtual Tick recvAtomic(PacketPtr pkt) { panic("FuncPort is UniDir"); + M5_DUMMY_RETURN } virtual void recvFunctional(PacketPtr pkt) { panic("FuncPort is UniDir"); } virtual void recvStatusChange(Status status) {} diff --git a/src/python/m5/objects/T1000.py b/src/python/m5/objects/T1000.py index 7b93268ac..85c4db6df 100644 --- a/src/python/m5/objects/T1000.py +++ b/src/python/m5/objects/T1000.py @@ -21,53 +21,53 @@ class T1000(Platform): type = 'T1000' system = Param.System(Parent.any, "system") - fake_clk = IsaFake(pio_addr=0x9600000000, pio_size=0x100000000, - warn_access="Accessing Clock Unit -- Unimplemented!") + fake_clk = IsaFake(pio_addr=0x9600000000, pio_size=0x100000000) + #warn_access="Accessing Clock Unit -- Unimplemented!") fake_membnks = IsaFake(pio_addr=0x9700000000, pio_size=16384, - ret_data64=0x0000000000000000, update_data=False, - warn_access="Accessing Memory Banks -- Unimplemented!") + ret_data64=0x0000000000000000, update_data=False) + #warn_access="Accessing Memory Banks -- Unimplemented!") - fake_iob = IsaFake(pio_addr=0x9800000000, pio_size=0x100000000, - warn_access="Accessing IOB -- Unimplemented!") + fake_iob = IsaFake(pio_addr=0x9800000000, pio_size=0x100000000) + #warn_access="Accessing IOB -- Unimplemented!") - fake_jbi = IsaFake(pio_addr=0x8000000000, pio_size=0x100000000, - warn_access="Accessing JBI -- Unimplemented!") + fake_jbi = IsaFake(pio_addr=0x8000000000, pio_size=0x100000000) + #warn_access="Accessing JBI -- Unimplemented!") fake_l2_1 = IsaFake(pio_addr=0xA900000000, pio_size=0x8, - ret_data64=0x0000000000000001, update_data=True, - warn_access="Accessing L2 Cache Banks -- Unimplemented!") + ret_data64=0x0000000000000001, update_data=True) + #warn_access="Accessing L2 Cache Banks -- Unimplemented!") fake_l2_2 = IsaFake(pio_addr=0xA900000040, pio_size=0x8, - ret_data64=0x0000000000000001, update_data=True, - warn_access="Accessing L2 Cache Banks -- Unimplemented!") + ret_data64=0x0000000000000001, update_data=True) + #warn_access="Accessing L2 Cache Banks -- Unimplemented!") fake_l2_3 = IsaFake(pio_addr=0xA900000080, pio_size=0x8, - ret_data64=0x0000000000000001, update_data=True, - warn_access="Accessing L2 Cache Banks -- Unimplemented!") + ret_data64=0x0000000000000001, update_data=True) + #warn_access="Accessing L2 Cache Banks -- Unimplemented!") fake_l2_4 = IsaFake(pio_addr=0xA9000000C0, pio_size=0x8, - ret_data64=0x0000000000000001, update_data=True, - warn_access="Accessing L2 Cache Banks -- Unimplemented!") + ret_data64=0x0000000000000001, update_data=True) + #warn_access="Accessing L2 Cache Banks -- Unimplemented!") fake_l2esr_1 = IsaFake(pio_addr=0xAB00000000, pio_size=0x8, - ret_data64=0x0000000000000000, update_data=True, - warn_access="Accessing L2 ESR Cache Banks -- Unimplemented!") + ret_data64=0x0000000000000000, update_data=True) + #warn_access="Accessing L2 ESR Cache Banks -- Unimplemented!") fake_l2esr_2 = IsaFake(pio_addr=0xAB00000040, pio_size=0x8, - ret_data64=0x0000000000000000, update_data=True, - warn_access="Accessing L2 ESR Cache Banks -- Unimplemented!") + ret_data64=0x0000000000000000, update_data=True) + #warn_access="Accessing L2 ESR Cache Banks -- Unimplemented!") fake_l2esr_3 = IsaFake(pio_addr=0xAB00000080, pio_size=0x8, - ret_data64=0x0000000000000000, update_data=True, - warn_access="Accessing L2 ESR Cache Banks -- Unimplemented!") + ret_data64=0x0000000000000000, update_data=True) + #warn_access="Accessing L2 ESR Cache Banks -- Unimplemented!") fake_l2esr_4 = IsaFake(pio_addr=0xAB000000C0, pio_size=0x8, - ret_data64=0x0000000000000000, update_data=True, - warn_access="Accessing L2 ESR Cache Banks -- Unimplemented!") + ret_data64=0x0000000000000000, update_data=True) + #warn_access="Accessing L2 ESR Cache Banks -- Unimplemented!") - fake_ssi = IsaFake(pio_addr=0xff00000000, pio_size=0x10000000, - warn_access="Accessing SSI -- Unimplemented!") + fake_ssi = IsaFake(pio_addr=0xff00000000, pio_size=0x10000000) + #warn_access="Accessing SSI -- Unimplemented!") hvuart = Uart8250(pio_addr=0xfff0c2c000) htod = DumbTOD() diff --git a/src/sim/byteswap.hh b/src/sim/byteswap.hh index 4ac1ee711..cbc0b5088 100644 --- a/src/sim/byteswap.hh +++ b/src/sim/byteswap.hh @@ -47,7 +47,7 @@ // If one doesn't exist, we pretty much get what is listed below, so it all // works out #include <byteswap.h> -#elif defined (__sun__) +#elif defined (__sun) #include <sys/isa_defs.h> #else #include <machine/endian.h> @@ -57,6 +57,8 @@ #include <libkern/OSByteOrder.h> #endif +enum ByteOrder {BigEndianByteOrder, LittleEndianByteOrder}; + //These functions actually perform the swapping for parameters //of various bit lengths static inline uint64_t @@ -131,11 +133,13 @@ template <typename T> static inline T letobe(T value) {return swap_byte(value);} //For conversions not involving the guest system, we can define the functions //conditionally based on the BYTE_ORDER macro and outside of the namespaces #if defined(_BIG_ENDIAN) || !defined(_LITTLE_ENDIAN) && BYTE_ORDER == BIG_ENDIAN +const ByteOrder HostByteOrder = BigEndianByteOrder; template <typename T> static inline T htole(T value) {return swap_byte(value);} template <typename T> static inline T letoh(T value) {return swap_byte(value);} template <typename T> static inline T htobe(T value) {return value;} template <typename T> static inline T betoh(T value) {return value;} #elif defined(_LITTLE_ENDIAN) || BYTE_ORDER == LITTLE_ENDIAN +const ByteOrder HostByteOrder = LittleEndianByteOrder; template <typename T> static inline T htole(T value) {return value;} template <typename T> static inline T letoh(T value) {return value;} template <typename T> static inline T htobe(T value) {return swap_byte(value);} @@ -146,33 +150,35 @@ template <typename T> static inline T betoh(T value) {return swap_byte(value);} namespace BigEndianGuest { - template <typename T> - static inline T gtole(T value) {return betole(value);} - template <typename T> - static inline T letog(T value) {return letobe(value);} - template <typename T> - static inline T gtobe(T value) {return value;} - template <typename T> - static inline T betog(T value) {return value;} - template <typename T> - static inline T htog(T value) {return htobe(value);} - template <typename T> - static inline T gtoh(T value) {return betoh(value);} + const bool ByteOrderDiffers = (HostByteOrder != BigEndianByteOrder); + template <typename T> + static inline T gtole(T value) {return betole(value);} + template <typename T> + static inline T letog(T value) {return letobe(value);} + template <typename T> + static inline T gtobe(T value) {return value;} + template <typename T> + static inline T betog(T value) {return value;} + template <typename T> + static inline T htog(T value) {return htobe(value);} + template <typename T> + static inline T gtoh(T value) {return betoh(value);} } namespace LittleEndianGuest { - template <typename T> - static inline T gtole(T value) {return value;} - template <typename T> - static inline T letog(T value) {return value;} - template <typename T> - static inline T gtobe(T value) {return letobe(value);} - template <typename T> - static inline T betog(T value) {return betole(value);} - template <typename T> - static inline T htog(T value) {return htole(value);} - template <typename T> - static inline T gtoh(T value) {return letoh(value);} + const bool ByteOrderDiffers = (HostByteOrder != LittleEndianByteOrder); + template <typename T> + static inline T gtole(T value) {return value;} + template <typename T> + static inline T letog(T value) {return value;} + template <typename T> + static inline T gtobe(T value) {return letobe(value);} + template <typename T> + static inline T betog(T value) {return betole(value);} + template <typename T> + static inline T htog(T value) {return htole(value);} + template <typename T> + static inline T gtoh(T value) {return letoh(value);} } #endif // __SIM_BYTE_SWAP_HH__ diff --git a/src/sim/host.hh b/src/sim/host.hh index 8b1ddbfe7..93a5fe7f2 100644 --- a/src/sim/host.hh +++ b/src/sim/host.hh @@ -38,6 +38,8 @@ #define __HOST_HH__ #include <inttypes.h> +#include <limits> + /** uint64_t constant */ #define ULL(N) ((uint64_t)N##ULL) @@ -56,7 +58,7 @@ typedef int64_t Counter; */ typedef int64_t Tick; -const Tick MaxTick = (1LL << 63) - 1; +const Tick MaxTick = std::numeric_limits<Tick>::max(); /** * Address type diff --git a/src/sim/param.cc b/src/sim/param.cc index b1c50946b..5cc69b161 100644 --- a/src/sim/param.cc +++ b/src/sim/param.cc @@ -777,3 +777,27 @@ ParamContext::describeAllContexts(ostream &os) os << endl; } } + +void +parseTime(const std::vector<int> &time, struct tm *tm) +{ + memset(tm, 0, sizeof(struct tm)); + + // UNIX is years since 1900 + tm->tm_year = time[0] - 1900; + + // Python starts at 1, UNIX starts at 0 + tm->tm_mon = time[1] - 1; + tm->tm_mday = time[2]; + tm->tm_hour = time[3]; + tm->tm_min = time[4]; + tm->tm_sec = time[5]; + + // Python has 0 as Monday, UNIX is 0 as sunday + tm->tm_wday = time[6] + 1; + if (tm->tm_wday > 6) + tm->tm_wday -= 7; + + // Python starts at 1, Unix starts at 0 + tm->tm_yday = time[7] - 1; +} diff --git a/src/sim/param.hh b/src/sim/param.hh index 2aa0456da..8a4670e27 100644 --- a/src/sim/param.hh +++ b/src/sim/param.hh @@ -781,4 +781,5 @@ SimObjectVectorParam<OBJ_CLASS *>::showType(std::ostream &os) const \ template <class T> bool parseParam(const std::string &str, T &data); template <class T> void showParam(std::ostream &os, const T &data); +void parseTime(const std::vector<int> &time, struct tm *tm); #endif // _SIM_PARAM_HH_ diff --git a/src/sim/process.cc b/src/sim/process.cc index 63ff33969..e5d868115 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -35,6 +35,7 @@ #include <string> +#include "arch/remote_gdb.hh" #include "base/intmath.hh" #include "base/loader/object_file.hh" #include "base/loader/symtab.hh" @@ -154,6 +155,13 @@ Process::registerThreadContext(ThreadContext *tc) int myIndex = threadContexts.size(); threadContexts.push_back(tc); + RemoteGDB *rgdb = new RemoteGDB(system, tc); + GDBListener *gdbl = new GDBListener(rgdb, 7000 + myIndex); + gdbl->listen(); + //gdbl->accept(); + + remoteGDB.push_back(rgdb); + // return CPU number to caller return myIndex; } diff --git a/src/sim/process.hh b/src/sim/process.hh index 616c02c00..bf65c6e06 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -51,6 +51,11 @@ class SyscallDesc; class PageTable; class TranslatingPort; class System; +class GDBListener; +namespace TheISA +{ + class RemoteGDB; +} void copyStringArray(std::vector<std::string> &strings, Addr array_ptr, @@ -72,6 +77,11 @@ class Process : public SimObject // thread contexts associated with this process std::vector<ThreadContext *> threadContexts; + // remote gdb objects + std::vector<TheISA::RemoteGDB *> remoteGDB; + std::vector<GDBListener *> gdbListen; + bool breakpoint(); + // number of CPUs (esxec contexts, really) assigned to this process. unsigned int numCpus() { return threadContexts.size(); } diff --git a/src/sim/serialize.cc b/src/sim/serialize.cc index 941f0b1c6..1ff16976d 100644 --- a/src/sim/serialize.cc +++ b/src/sim/serialize.cc @@ -57,6 +57,8 @@ using namespace std; +extern SimObject *resolveSimObject(const string &); + int Serializable::ckptMaxCount = 0; int Serializable::ckptCount = 0; int Serializable::ckptPrevCount = -1; @@ -158,7 +160,7 @@ arrayParamIn(Checkpoint *cp, const std::string §ion, void objParamIn(Checkpoint *cp, const std::string §ion, - const std::string &name, Serializable * ¶m) + const std::string &name, SimObject * ¶m) { if (!cp->findObj(section, name, param)) { fatal("Can't unserialize '%s:%s'\n", section, name); @@ -388,17 +390,15 @@ Checkpoint::find(const std::string §ion, const std::string &entry, bool Checkpoint::findObj(const std::string §ion, const std::string &entry, - Serializable *&value) + SimObject *&value) { string path; if (!db->find(section, entry, path)) return false; - if ((value = objMap[path]) != NULL) - return true; - - return false; + value = resolveSimObject(path); + return true; } diff --git a/src/sim/serialize.hh b/src/sim/serialize.hh index 880fb0785..43cd4ecf4 100644 --- a/src/sim/serialize.hh +++ b/src/sim/serialize.hh @@ -47,6 +47,7 @@ class IniFile; class Serializable; class Checkpoint; +class SimObject; template <class T> void paramOut(std::ostream &os, const std::string &name, const T ¶m); @@ -65,7 +66,7 @@ void arrayParamIn(Checkpoint *cp, const std::string §ion, void objParamIn(Checkpoint *cp, const std::string §ion, - const std::string &name, Serializable * ¶m); + const std::string &name, SimObject * ¶m); // @@ -96,7 +97,7 @@ objParamIn(Checkpoint *cp, const std::string §ion, #define UNSERIALIZE_OBJPTR(objptr) \ do { \ - Serializable *sptr; \ + SimObject *sptr; \ objParamIn(cp, section, #objptr, sptr); \ objptr = dynamic_cast<typeof(objptr)>(sptr); \ } while (0) @@ -225,7 +226,7 @@ class Checkpoint std::string &value); bool findObj(const std::string §ion, const std::string &entry, - Serializable *&value); + SimObject *&value); bool sectionExists(const std::string §ion); diff --git a/src/sim/syscallreturn.hh b/src/sim/syscallreturn.hh new file mode 100644 index 000000000..d1c43f584 --- /dev/null +++ b/src/sim/syscallreturn.hh @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * 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: Gabe Black + */ + +#ifndef __SIM_SYSCALLRETURN_HH__ +#define __SIM_SYSCALLRETURN_HH__ + +#include <inttypes.h> + +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; +}; + +#endif diff --git a/src/sim/system.cc b/src/sim/system.cc index b3ba1b8f1..f6febe4b1 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -32,6 +32,7 @@ */ #include "arch/isa_traits.hh" +#include "arch/remote_gdb.hh" #include "base/loader/object_file.hh" #include "base/loader/symtab.hh" #include "base/trace.hh" @@ -43,7 +44,6 @@ #include "sim/system.hh" #if FULL_SYSTEM #include "arch/vtophys.hh" -#include "arch/remote_gdb.hh" #include "kern/kernel_stats.hh" #endif @@ -141,14 +141,8 @@ System::~System() #endif // FULL_SYSTEM} } -#if FULL_SYSTEM - - int rgdb_wait = -1; -#endif // FULL_SYSTEM - - void System::setMemoryMode(MemoryMode mode) { @@ -156,6 +150,11 @@ System::setMemoryMode(MemoryMode mode) memoryMode = mode; } +bool System::breakpoint() +{ + return remoteGDB[0]->breakpoint(); +} + int System::registerThreadContext(ThreadContext *tc, int id) { @@ -175,7 +174,6 @@ System::registerThreadContext(ThreadContext *tc, int id) threadContexts[id] = tc; numcpus++; -#if FULL_SYSTEM RemoteGDB *rgdb = new RemoteGDB(this, tc); GDBListener *gdbl = new GDBListener(rgdb, 7000 + id); gdbl->listen(); @@ -191,7 +189,6 @@ System::registerThreadContext(ThreadContext *tc, int id) } remoteGDB[id] = rgdb; -#endif // FULL_SYSTEM return id; } @@ -213,9 +210,7 @@ System::replaceThreadContext(ThreadContext *tc, int id) } threadContexts[id] = tc; -#if FULL_SYSTEM remoteGDB[id]->replaceThreadContext(tc); -#endif // FULL_SYSTEM } #if !FULL_SYSTEM diff --git a/src/sim/system.hh b/src/sim/system.hh index b3a67bf7a..758da709e 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -55,12 +55,12 @@ class PhysicalMemory; #if FULL_SYSTEM class Platform; +#endif class GDBListener; namespace TheISA { class RemoteGDB; } -#endif class System : public SimObject { @@ -159,11 +159,9 @@ class System : public SimObject #endif public: -#if FULL_SYSTEM std::vector<TheISA::RemoteGDB *> remoteGDB; std::vector<GDBListener *> gdbListen; - virtual bool breakpoint() = 0; -#endif // FULL_SYSTEM + bool breakpoint(); public: struct Params diff --git a/src/unittest/Makefile b/src/unittest/Makefile index 0c11b9563..e22b80b48 100644 --- a/src/unittest/Makefile +++ b/src/unittest/Makefile @@ -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 |