summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2006-12-16 11:35:40 -0500
committerGabe Black <gblack@eecs.umich.edu>2006-12-16 11:35:40 -0500
commit9d0ca61b7e357ca5e83f97f8cb8f4f1037cc3eb5 (patch)
tree50e7a435de1e0f5638eba9b1b030e79daaf1aee0 /src
parent4da37bcd1bc2c42ce5f297a58b4b4bffa4e8cd4f (diff)
parentf4f00c5ae98c069f79a8b56ed93284daf7532c7e (diff)
downloadgem5-9d0ca61b7e357ca5e83f97f8cb8f4f1037cc3eb5.tar.xz
Merge zizzer:/bk/newmem
into zower.eecs.umich.edu:/eecshome/m5/newmem src/arch/isa_parser.py: src/arch/sparc/isa/formats/mem/basicmem.isa: src/arch/sparc/isa/formats/mem/blockmem.isa: src/arch/sparc/isa/formats/mem/util.isa: src/arch/sparc/miscregfile.cc: src/arch/sparc/miscregfile.hh: src/cpu/o3/iew_impl.hh: Hand Merge --HG-- extra : convert_revision : ae1b25cde85ab8ec275a09d554acd372887d4d47
Diffstat (limited to 'src')
-rw-r--r--src/arch/alpha/regfile.hh5
-rw-r--r--src/arch/alpha/syscallreturn.hh45
-rwxr-xr-xsrc/arch/isa_parser.py221
-rw-r--r--src/arch/mips/regfile/regfile.hh5
-rw-r--r--src/arch/mips/syscallreturn.hh45
-rw-r--r--src/arch/sparc/faults.cc32
-rw-r--r--src/arch/sparc/intregfile.cc9
-rw-r--r--src/arch/sparc/intregfile.hh10
-rw-r--r--src/arch/sparc/isa/decoder.isa65
-rw-r--r--src/arch/sparc/isa/formats/basic.isa3
-rw-r--r--src/arch/sparc/isa/formats/branch.isa12
-rw-r--r--src/arch/sparc/isa/formats/integerop.isa9
-rw-r--r--src/arch/sparc/isa/formats/mem/basicmem.isa24
-rw-r--r--src/arch/sparc/isa/formats/mem/blockmem.isa16
-rw-r--r--src/arch/sparc/isa/formats/mem/util.isa50
-rw-r--r--src/arch/sparc/isa/formats/nop.isa4
-rw-r--r--src/arch/sparc/isa/formats/priv.isa8
-rw-r--r--src/arch/sparc/isa/formats/trap.isa4
-rw-r--r--src/arch/sparc/isa/includes.isa7
-rw-r--r--src/arch/sparc/isa/operands.isa45
-rw-r--r--src/arch/sparc/isa_traits.hh4
-rw-r--r--src/arch/sparc/miscregfile.cc12
-rw-r--r--src/arch/sparc/miscregfile.hh14
-rw-r--r--src/arch/sparc/process.cc15
-rw-r--r--src/arch/sparc/regfile.cc80
-rw-r--r--src/arch/sparc/regfile.hh2
-rw-r--r--src/arch/sparc/sparc_traits.hh3
-rw-r--r--src/arch/sparc/syscallreturn.hh50
-rw-r--r--src/cpu/base_dyn_inst.hh152
-rw-r--r--src/cpu/base_dyn_inst_impl.hh11
-rw-r--r--src/cpu/exetrace.cc48
-rw-r--r--src/cpu/o3/alpha/cpu.hh41
-rw-r--r--src/cpu/o3/alpha/cpu_impl.hh29
-rw-r--r--src/cpu/o3/alpha/dyn_inst.hh78
-rw-r--r--src/cpu/o3/alpha/dyn_inst_impl.hh4
-rw-r--r--src/cpu/o3/alpha/thread_context.hh6
-rw-r--r--src/cpu/o3/bpred_unit_impl.hh9
-rw-r--r--src/cpu/o3/comm.hh5
-rw-r--r--src/cpu/o3/commit_impl.hh31
-rw-r--r--src/cpu/o3/cpu.cc6
-rw-r--r--src/cpu/o3/cpu.hh24
-rw-r--r--src/cpu/o3/decode_impl.hh17
-rw-r--r--src/cpu/o3/fetch.hh9
-rw-r--r--src/cpu/o3/fetch_impl.hh114
-rw-r--r--src/cpu/o3/iew_impl.hh34
-rw-r--r--src/cpu/o3/lsq_unit.hh6
-rw-r--r--src/cpu/o3/lsq_unit_impl.hh19
-rw-r--r--src/cpu/o3/mips/cpu_impl.hh12
-rwxr-xr-xsrc/cpu/o3/mips/dyn_inst.hh82
-rwxr-xr-xsrc/cpu/o3/mips/dyn_inst_impl.hh4
-rw-r--r--src/cpu/o3/rename.hh8
-rw-r--r--src/cpu/o3/rename_impl.hh95
-rw-r--r--src/cpu/o3/sparc/cpu.hh42
-rw-r--r--src/cpu/o3/sparc/cpu_builder.cc4
-rw-r--r--src/cpu/o3/sparc/cpu_impl.hh41
-rw-r--r--src/cpu/o3/sparc/dyn_inst.hh156
-rw-r--r--src/cpu/o3/sparc/dyn_inst_impl.hh14
-rw-r--r--src/cpu/o3/sparc/thread_context.hh8
-rwxr-xr-xsrc/cpu/o3/thread_context.hh8
-rwxr-xr-xsrc/cpu/o3/thread_context_impl.hh3
-rw-r--r--src/cpu/simple/base.hh25
-rw-r--r--src/cpu/simple_thread.hh14
-rw-r--r--src/cpu/thread_context.hh2
-rw-r--r--src/sim/byteswap.hh54
-rw-r--r--src/sim/syscallreturn.hh70
65 files changed, 1135 insertions, 949 deletions
diff --git a/src/arch/alpha/regfile.hh b/src/arch/alpha/regfile.hh
index ff5830822..c73c32bad 100644
--- a/src/arch/alpha/regfile.hh
+++ b/src/arch/alpha/regfile.hh
@@ -189,6 +189,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/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/isa_parser.py b/src/arch/isa_parser.py
index 59eb18c9c..5f6a33565 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,83 @@ 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):
- # 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):
- myDict.update(d)
- # if the argument is an object, we use its attribute map.
- elif hasattr(d, '__dict__'):
- myDict.update(d.__dict__)
- else:
- raise TypeError, "Template.subst() arg must be or have dictionary"
+ 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)
+
+ # if we're dealing with an InstObjParams object, we need to be a
+ # little more sophisticated. Otherwise, just do what we've always
+ # done
+ if isinstance(d, InstObjParams):
+ # The instruction wide parameters are already formed, but the
+ # parameters which are only function wide still need to be
+ # generated.
+ perFuncNames = ['op_decl', 'op_src_decl', 'op_dest_decl', \
+ 'op_rd', 'op_wb', 'mem_acc_size', 'mem_acc_type']
+ compositeCode = ''
+
+ myDict = templateMap.copy()
+ 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']
+
+ for name in labelRE.findall(template):
+ # Don't try to find a snippet to go with things that will
+ # match against attributes of d, or that are other templates,
+ # or that we're going to generate later, or that we've already
+ # found.
+ if not hasattr(d, name) and \
+ not templateMap.has_key(name) and \
+ not myDict.has_key(name) and \
+ name not in perFuncNames:
+ myDict[name] = d.snippets[name]
+ if isinstance(myDict[name], str):
+ myDict[name] = substMungedOpNames(substBitOps(myDict[name]))
+ compositeCode += (" " + myDict[name])
+ 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
+
+ else:
+ # 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):
+ myDict.update(d)
+ # if the argument is an object, we use its attribute map.
+ elif hasattr(d, '__dict__'):
+ myDict.update(d.__dict__)
+ else:
+ raise TypeError, "Template.subst() arg must be or have dictionary"
return template % myDict
# Convert to string. This handles the case when a template with a
@@ -1296,10 +1351,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 +1362,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(%s)' % self.reg_spec
if self.size == self.dflt_size:
return '%s = %s;\n' % (self.base_name, base)
else:
@@ -1317,7 +1372,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 +1606,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')
@@ -1583,11 +1681,28 @@ 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 = None, opt_args = []):
+ self.mnemonic = mnem
+ self.class_name = class_name
+ self.base_class = base_class
+ compositeCode = ''
+ if snippets:
+ if not isinstance(snippets, dict):
+ snippets = {'code' : snippets}
+ for snippet in snippets.values():
+ if isinstance(snippet, str):
+ compositeCode += (" " + snippet)
+ self.snippets = snippets
+
+ self.operands = OperandList(compositeCode)
self.constructor = self.operands.concatAttrStrings('constructor')
self.constructor += \
'\n\t_numSrcRegs = %d;' % self.operands.numSrcRegs
@@ -1597,28 +1712,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 +1726,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/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/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/faults.cc b/src/arch/sparc/faults.cc
index 64cfc832a..92fdbfdbb 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();
@@ -396,10 +398,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();
@@ -679,19 +683,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/intregfile.cc b/src/arch/sparc/intregfile.cc
index 0a8ac055f..594fe4bea 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,8 @@ IntRegFile::IntRegFile()
IntReg IntRegFile::readReg(int intReg)
{
+ DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, regs[intReg]);
+ return regs[intReg];
IntReg val;
if(intReg < NumIntArchRegs)
val = regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask];
@@ -96,6 +99,12 @@ void IntRegFile::setReg(int intReg, const IntReg &val)
if(intReg)
{
DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val);
+ regs[intReg] = val;
+ }
+ return;
+ 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)
diff --git a/src/arch/sparc/intregfile.hh b/src/arch/sparc/intregfile.hh
index d66d0fcb7..716d45a65 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>
@@ -54,15 +55,19 @@ namespace SparcISA
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/decoder.isa b/src/arch/sparc/isa/decoder.isa
index 7a48042c2..5c69598d5 100644
--- a/src/arch/sparc/isa/decoder.isa
+++ b/src/arch/sparc/isa/decoder.isa
@@ -76,9 +76,15 @@ decode OP default Unknown::unknown()
}});
0x2: bpccx(19, {{
if(passesCondition(Ccr<7:4>, COND2))
+ {
+ //warn("Took branch!\n");
NNPC = xc->readPC() + disp;
+ }
else
+ {
+ //warn("Didn't take branch!\n");
handle_annul
+ }
}});
}
}
@@ -247,16 +253,14 @@ decode OP default Unknown::unknown()
((Rs1 & val2) | (carryin & (Rs1 | val2)))<0:>)<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 = Rs1.sdw<31:0> * Rs2_or_imm13.sdw<31:0>;
- Y = resTemp<63:32>;}},
- {{0}},{{0}},{{0}},{{0}});
+ Y = resTemp<63:32>;}});
0x1C: subccc({{
int64_t resTemp, val2 = Rs2_or_imm13;
int64_t carryin = Ccr<0:0>;
@@ -266,10 +270,9 @@ decode OP default Unknown::unknown()
{{(~((Rs1<63:1> + (~(val2 + carryin))<63:1>) + (Rs1<0:> + (~(val2+carryin))<0:> + 1)<63:1>))<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;
@@ -880,16 +883,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)
@@ -897,18 +895,15 @@ decode OP default Unknown::unknown()
else
fault = new FillNNormal(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);
}
}
}});
@@ -926,7 +921,7 @@ decode OP default Unknown::unknown()
xc->syscall(R1);
#endif
}
- }});
+ }}, IsSerializeAfter, IsNonSpeculative);
0x2: Trap::tccx({{
if(passesCondition(Ccr<7:4>, COND2))
{
@@ -939,36 +934,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(Wstate<5:3>);
else
fault = new SpillNNormal(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({{
@@ -981,17 +967,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 {
diff --git a/src/arch/sparc/isa/formats/basic.isa b/src/arch/sparc/isa/formats/basic.isa
index a4c05387b..56e933763 100644
--- a/src/arch/sparc/isa/formats/basic.isa
+++ b/src/arch/sparc/isa/formats/basic.isa
@@ -95,8 +95,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..2db756320 100644
--- a/src/arch/sparc/isa/formats/branch.isa
+++ b/src/arch/sparc/isa/formats/branch.isa
@@ -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)
@@ -178,6 +178,10 @@ output decoder {{
else
ccprintf(response, ">");
}
+ else
+ {
+ ccprintf(response, "<%d>", target);
+ }
return response.str();
}
@@ -244,7 +248,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 +255,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 +265,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..363aca1a1 100644
--- a/src/arch/sparc/isa/formats/integerop.isa
+++ b/src/arch/sparc/isa/formats/integerop.isa
@@ -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..ed0c41e61 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", 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 7a1a58d13..a0b235a61 100644
--- a/src/arch/sparc/isa/formats/mem/blockmem.isa
+++ b/src/arch/sparc/isa/formats/mem/blockmem.isa
@@ -293,14 +293,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(
@@ -323,7 +323,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) {{
@@ -335,5 +335,5 @@ 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)
}};
diff --git a/src/arch/sparc/isa/formats/mem/util.isa b/src/arch/sparc/isa/formats/mem/util.isa
index 3e9fd7a7d..03b08ae18 100644
--- a/src/arch/sparc/isa/formats/mem/util.isa
+++ b/src/arch/sparc/isa/formats/mem/util.isa
@@ -144,7 +144,7 @@ def template LoadExecute {{
%(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 +162,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;
+ %(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 +182,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;
}
@@ -209,7 +214,7 @@ def template StoreExecute {{
%(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,7 +233,9 @@ def template StoreExecute {{
return fault;
}
+}};
+def template StoreInitiateAcc {{
Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
Trace::InstRecord * traceData) const
{
@@ -238,7 +245,7 @@ def template StoreExecute {{
%(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 +263,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 +285,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 = '''
@@ -310,21 +321,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,
@@ -333,8 +334,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..9c118b227 100644
--- a/src/arch/sparc/isa/formats/trap.isa
+++ b/src/arch/sparc/isa/formats/trap.isa
@@ -83,9 +83,7 @@ def template TrapExecute {{
}};
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)
diff --git a/src/arch/sparc/isa/includes.isa b/src/arch/sparc/isa/includes.isa
index 624afb693..2e7b16f20 100644
--- a/src/arch/sparc/isa/includes.isa
+++ b/src/arch/sparc/isa/includes.isa
@@ -37,12 +37,13 @@ output header {{
#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 {{
diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa
index 80ed7362c..256f2fa43 100644
--- a/src/arch/sparc/isa/operands.isa
+++ b/src/arch/sparc/isa/operands.isa
@@ -56,12 +56,23 @@ 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),
- '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 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),
+ # 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.
@@ -80,14 +91,17 @@ def operands {{
'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),
@@ -109,12 +123,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 3f0b9cad5..2b136856a 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 53559c072..6641d38bb 100644
--- a/src/arch/sparc/miscregfile.cc
+++ b/src/arch/sparc/miscregfile.cc
@@ -46,15 +46,9 @@ 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",
+ "pil", "cwp", /*"cansave", "canrestore", "cleanwin", "otherwin",
+ "wstate",*/ "gl",
return miscRegName[index];
}
diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh
index c879fd357..ace916f5b 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 */
diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc
index 405e408e5..073117a84 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
diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc
index 5d8ac6a17..691d0a0f1 100644
--- a/src/arch/sparc/regfile.cc
+++ b/src/arch/sparc/regfile.cc
@@ -151,6 +151,72 @@ 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;
+ 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 = MaxGL * 8 +
+ ((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 + MaxGL * 8 + 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 = MaxGL * 8 +
+ ((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 = MaxGL * 8 +
+ ((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);
@@ -220,8 +286,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 +302,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/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/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh
index 9037c96df..07d53d278 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.
@@ -224,6 +221,12 @@ 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;
+
/** Count of total number of dynamic instructions. */
static int instcount;
@@ -236,16 +239,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.
@@ -290,26 +393,35 @@ class BaseDynInst : public FastAlloc, public RefCounted
Addr readNextNPC() { return nextNPC; }
/** 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 target of the branch. */
- Addr readPredTarg() { return predPC; }
+ /** Returns the predicted PC immediately after the branch. */
+ Addr readPredPC() { 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 predPC != nextPC || predNPC != nextNPC;
+ }
+
//
// 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/exetrace.cc b/src/cpu/exetrace.cc
index 3fe40b4c1..98e75d83a 100644
--- a/src/cpu/exetrace.cc
+++ b/src/cpu/exetrace.cc
@@ -145,13 +145,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;
@@ -373,9 +375,13 @@ 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->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;
@@ -385,14 +391,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->readMiscReg(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 + 5))
diffOtherwin = true;
- if(shared_data->cleanwin != thread->readMiscReg(MISCREG_CLEANWIN))
+ //if(shared_data->cleanwin != thread->readMiscReg(MISCREG_CLEANWIN))
+ if(shared_data->cleanwin !=
+ thread->readMiscReg(NumIntArchRegs + 6))
diffCleanwin = true;
if ((diffPC || diffCC || diffInst || diffRegs || diffTpc ||
@@ -493,10 +507,12 @@ Trace::InstRecord::dump(ostream &outs)
thread->readMiscReg(MISCREG_PSTATE),
shared_data->pstate);
printRegPair(outs, "Y",
- thread->readMiscReg(MISCREG_Y),
+ //thread->readMiscReg(MISCREG_Y),
+ thread->readMiscReg(NumIntArchRegs + 1),
shared_data->y);
printRegPair(outs, "Ccr",
- thread->readMiscReg(MISCREG_CCR),
+ //thread->readMiscReg(MISCREG_CCR),
+ thread->readMiscReg(NumIntArchRegs + 2),
shared_data->ccr);
printRegPair(outs, "Tl",
thread->readMiscReg(MISCREG_TL),
@@ -514,16 +530,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 + 5),
shared_data->otherwin);
printRegPair(outs, "Cleanwin",
- thread->readMiscReg(MISCREG_CLEANWIN),
+ //thread->readMiscReg(MISCREG_CLEANWIN),
+ thread->readIntReg(NumIntArchRegs + 6),
shared_data->cleanwin);
outs << endl;
for (int i = 1; i <= MaxTL; i++) {
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 98fd0699a..fb0962056 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);
}
@@ -315,7 +311,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);
}
@@ -324,17 +320,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..c340a806a 100644
--- a/src/cpu/o3/alpha/dyn_inst.hh
+++ b/src/cpu/o3/alpha/dyn_inst.hh
@@ -134,22 +134,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 +149,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 +178,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..02432f721 100644
--- a/src/cpu/o3/alpha/dyn_inst_impl.hh
+++ b/src/cpu/o3/alpha/dyn_inst_impl.hh
@@ -53,11 +53,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..e4a6735c2 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()
{
diff --git a/src/cpu/o3/bpred_unit_impl.hh b/src/cpu/o3/bpred_unit_impl.hh
index 477c8e4cb..dbc603082 100644
--- a/src/cpu/o3/bpred_unit_impl.hh
+++ b/src/cpu/o3/bpred_unit_impl.hh
@@ -233,15 +233,6 @@ 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);
- }
-
predHist[tid].push_front(predict_record);
DPRINTF(Fetch, "[tid:%i]: predHist.size(): %i\n", tid, predHist[tid].size());
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 f400d757b..194138efc 100644
--- a/src/cpu/o3/commit_impl.hh
+++ b/src/cpu/o3/commit_impl.hh
@@ -514,6 +514,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>
@@ -728,28 +729,11 @@ 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];
+
+ if (!squash_bdelay_slot)
+ bdelay_done_seq_num++;
#endif
if (fromIEW->includeSquashInst[tid] == true) {
@@ -787,6 +771,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];
@@ -1117,7 +1102,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 a5a00015f..5616ba398 100644
--- a/src/cpu/o3/cpu.cc
+++ b/src/cpu/o3/cpu.cc
@@ -149,6 +149,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),
@@ -696,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 80b6cc4c9..aea56cc27 100644
--- a/src/cpu/o3/decode_impl.hh
+++ b/src/cpu/o3/decode_impl.hh
@@ -741,7 +741,7 @@ DefaultDecode<Impl>::decodeInsts(unsigned tid)
// Ensure that if it was predicted as a branch, it really is a
// branch.
- if (inst->predTaken() && !inst->isControl()) {
+ if (inst->readPredTaken() && !inst->isControl()) {
DPRINTF(Decode, "PredPC : %#x != NextPC: %#x\n",inst->predPC,
inst->nextPC + 4);
@@ -760,26 +760,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 "
@@ -798,7 +801,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..0371cd2bc 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
diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh
index 622259495..815935db3 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.
@@ -504,14 +502,14 @@ DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC,
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);
+ next_PC = next_NPC;
+ next_NPC = next_NPC + instSize;
+ inst->setPredTarg(next_PC, next_NPC);
#else
next_PC = next_PC + instSize;
- inst->setPredTarg(next_PC);
+ inst->setPredTarg(next_PC, next_PC + sizeof(TheISA::MachInst));
#endif
+ inst->setPredTaken(false);
return false;
}
@@ -521,36 +519,29 @@ DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC,
predict_taken = branchPred.predict(inst, pred_PC, tid);
if (predict_taken) {
- DPRINTF(Fetch, "[tid:%i]: Branch predicted to be true.\n", tid);
+ DPRINTF(Fetch, "[tid:%i]: Branch predicted to be taken.\n", tid);
} else {
- DPRINTF(Fetch, "[tid:%i]: Branch predicted to be false.\n", tid);
+ DPRINTF(Fetch, "[tid:%i]: Branch predicted to be not taken.\n", tid);
}
+ next_PC = next_NPC;
if (predict_taken) {
- next_PC = next_NPC;
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
- }
-
+ } else {
next_NPC = next_NPC + instSize;
}
#else
predict_taken = branchPred.predict(inst, next_PC, tid);
#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 +662,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,13 +696,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);
+ doSquash(new_PC, new_NPC, tid);
#if ISA_HAS_DELAY_SLOT
if (seq_num <= delaySlotInfo[tid].branchSeqNum) {
@@ -793,12 +785,13 @@ 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) {
@@ -928,6 +921,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);
@@ -985,6 +979,7 @@ DefaultFetch<Impl>::checkSignalsAndUpdate(unsigned tid)
#endif
// Squash unless we're already squashing
squashFromDecode(fromDecode->decodeInfo[tid].nextPC,
+ fromDecode->decodeInfo[tid].nextNPC,
doneSeqNum,
tid);
@@ -1041,6 +1036,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;
@@ -1097,7 +1094,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;
@@ -1116,15 +1114,17 @@ 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);
+
// Get a sequence number.
inst_seq = cpu->getAndIncrementInstSeq();
@@ -1144,8 +1144,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);
@@ -1157,6 +1158,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));
@@ -1165,8 +1168,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
instruction->staticInst,
instruction->readPC());
- predicted_branch = lookupAndUpdateNextPC(instruction, next_PC,
- next_NPC);
+ lookupAndUpdateNextPC(instruction, next_PC, next_NPC);
// Add instruction to the CPU's list of instructions.
instruction->setInstListIt(cpu->addInst(instruction));
@@ -1182,6 +1184,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!",
@@ -1193,29 +1196,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) {
@@ -1224,7 +1204,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);
}
@@ -1241,9 +1221,9 @@ DefaultFetch<Impl>::fetch(bool &status_change)
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);
+ PC[tid] = next_PC;
+ nextPC[tid] = next_NPC;
+ nextNPC[tid] = next_NPC + instSize;
delaySlotInfo[tid].targetReady = false;
} else {
diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh
index 76047b295..70200d648 100644
--- a/src/cpu/o3/iew_impl.hh
+++ b/src/cpu/o3/iew_impl.hh
@@ -481,18 +481,29 @@ DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, unsigned tid)
toCommit->branchMispredict[tid] = true;
#if ISA_HAS_DELAY_SLOT
- bool branch_taken = inst->readNextNPC() !=
- (inst->readNextPC() + sizeof(TheISA::MachInst));
+ int instSize = 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();
- } else {
+ toCommit->nextNPC[tid] = inst->readNextNPC();
+ } else
toCommit->nextPC[tid] = inst->readNextNPC();
- }
#else
toCommit->branchTaken[tid] = inst->readNextPC() !=
(inst->readPC() + sizeof(TheISA::MachInst));
@@ -514,6 +525,9 @@ 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();
+#endif
toCommit->branchMispredict[tid] = false;
toCommit->includeSquashInst[tid] = false;
@@ -531,6 +545,9 @@ 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->readNextNPC();
+#endif
toCommit->branchMispredict[tid] = false;
// Must include the broadcasted SN in the squash.
@@ -1338,6 +1355,7 @@ DefaultIEW<Impl>::executeInsts()
fetchRedirect[tid] = true;
DPRINTF(IEW, "Execute: Branch mispredict detected.\n");
+ DPRINTF(IEW, "Predicted target was %#x.\n", inst->predPC);
#if ISA_HAS_DELAY_SLOT
DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x.\n",
inst->nextNPC);
@@ -1348,7 +1366,7 @@ DefaultIEW<Impl>::executeInsts()
// If incorrect, then signal the ROB that it must be squashed.
squashDueToBranch(inst, tid);
- if (inst->predTaken()) {
+ if (inst->readPredTaken()) {
predictedTakenIncorrect++;
} else {
predictedNotTakenIncorrect++;
diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh
index a2e11173e..0318175c3 100644
--- a/src/cpu/o3/lsq_unit.hh
+++ b/src/cpu/o3/lsq_unit.hh
@@ -561,6 +561,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..009a08012 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. */
@@ -127,22 +123,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 +138,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 +167,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..fa8cf6cb4 100755
--- a/src/cpu/o3/mips/dyn_inst_impl.hh
+++ b/src/cpu/o3/mips/dyn_inst_impl.hh
@@ -53,11 +53,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 248d7deb6..7a7234965 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
@@ -475,6 +492,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 ||
@@ -740,7 +771,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>
@@ -827,7 +868,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;
@@ -960,13 +1004,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);
@@ -993,20 +1043,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);
@@ -1230,12 +1287,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 536a620bf..4a194cbda 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);
}
@@ -285,35 +281,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..e95ae2fd5 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 this->cpu->readIntReg(this->_srcRegIdx[idx]);
}
- 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/simple/base.hh b/src/cpu/simple/base.hh
index c39bfa9cd..dd178f64d 100644
--- a/src/cpu/simple/base.hh
+++ b/src/cpu/simple/base.hh
@@ -303,6 +303,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, &regs);
+ TheISA::setSyscallReturn(return_value, getTC());
}
void syscall(int64_t callnum)
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/sim/byteswap.hh b/src/sim/byteswap.hh
index 7b1ae701e..7b63cf6e0 100644
--- a/src/sim/byteswap.hh
+++ b/src/sim/byteswap.hh
@@ -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) || 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/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