summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/alpha/utility.hh7
-rwxr-xr-xsrc/arch/isa_parser.py18
-rw-r--r--src/arch/mips/utility.hh7
-rw-r--r--src/arch/sparc/SConscript1
-rw-r--r--src/arch/sparc/asi.cc279
-rw-r--r--src/arch/sparc/asi.hh55
-rw-r--r--src/arch/sparc/isa/base.isa2
-rw-r--r--src/arch/sparc/isa/bitfields.isa4
-rw-r--r--src/arch/sparc/isa/decoder.isa305
-rw-r--r--src/arch/sparc/isa/formats.isa9
-rw-r--r--src/arch/sparc/isa/formats/basic.isa13
-rw-r--r--src/arch/sparc/isa/formats/blockmem.isa370
-rw-r--r--src/arch/sparc/isa/formats/branch.isa6
-rw-r--r--src/arch/sparc/isa/formats/integerop.isa12
-rw-r--r--src/arch/sparc/isa/formats/mem.isa116
-rw-r--r--src/arch/sparc/isa/formats/micro.isa103
-rw-r--r--src/arch/sparc/isa/formats/priv.isa4
-rw-r--r--src/arch/sparc/isa/formats/unimp.isa147
-rw-r--r--src/arch/sparc/isa/main.isa2
-rw-r--r--src/arch/sparc/isa/operands.isa29
-rw-r--r--src/arch/sparc/utility.hh17
-rw-r--r--src/cpu/checker/cpu_impl.hh2
-rw-r--r--src/cpu/exetrace.cc95
-rw-r--r--src/cpu/o3/fetch_impl.hh2
-rw-r--r--src/cpu/ozone/front_end_impl.hh2
-rw-r--r--src/cpu/simple/base.cc50
-rw-r--r--src/cpu/simple/base.hh1
-rw-r--r--src/cpu/simple_thread.hh20
-rw-r--r--src/cpu/static_inst.cc7
-rw-r--r--src/cpu/static_inst.hh22
-rw-r--r--src/cpu/thread_state.cc4
-rw-r--r--src/cpu/thread_state.hh10
-rw-r--r--src/kern/linux/linux.hh4
-rw-r--r--src/kern/solaris/solaris.hh4
-rw-r--r--src/kern/tru64/tru64.hh56
-rw-r--r--src/sim/syscall_emul.hh8
-rw-r--r--util/statetrace/arch/tracechild_sparc.cc172
-rw-r--r--util/statetrace/arch/tracechild_sparc.hh8
38 files changed, 1654 insertions, 319 deletions
diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh
index d3ccc0444..0304d1c3a 100644
--- a/src/arch/alpha/utility.hh
+++ b/src/arch/alpha/utility.hh
@@ -37,16 +37,17 @@
#include "arch/alpha/isa_traits.hh"
#include "arch/alpha/regfile.hh"
#include "base/misc.hh"
+#include "cpu/thread_context.hh"
namespace AlphaISA
{
static inline ExtMachInst
- makeExtMI(MachInst inst, const uint64_t &pc) {
+ makeExtMI(MachInst inst, ThreadContext * xc) {
#if FULL_SYSTEM
ExtMachInst ext_inst = inst;
- if (pc && 0x1)
- return ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32);
+ if (xc->readPC() && 0x1)
+ return ext_inst|=(static_cast<ExtMachInst>(xc->readPC() & 0x1) << 32);
else
return ext_inst;
#else
diff --git a/src/arch/isa_parser.py b/src/arch/isa_parser.py
index 4d522e18a..b235398f1 100755
--- a/src/arch/isa_parser.py
+++ b/src/arch/isa_parser.py
@@ -1636,7 +1636,7 @@ opClassRE = re.compile(r'.*Op|No_OpClass')
class InstObjParams:
def __init__(self, mnem, class_name, base_class = '',
- code = None, opt_args = [], *extras):
+ code = None, opt_args = [], extras = {}):
self.mnemonic = mnem
self.class_name = class_name
self.base_class = base_class
@@ -1648,13 +1648,23 @@ class InstObjParams:
else:
origCode = code
codeBlock = CodeBlock(code)
- compositeCode = '\n'.join([origCode] +
- [pair[1] for pair in extras])
+ 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 extras:
+ 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:
diff --git a/src/arch/mips/utility.hh b/src/arch/mips/utility.hh
index ae2fe1aea..56689ba4d 100644
--- a/src/arch/mips/utility.hh
+++ b/src/arch/mips/utility.hh
@@ -35,6 +35,7 @@
#include "arch/mips/types.hh"
#include "base/misc.hh"
#include "config/full_system.hh"
+#include "cpu/thread_context.hh"
//XXX This is needed for size_t. We should use something other than size_t
//#include "kern/linux/linux.hh"
#include "sim/host.hh"
@@ -86,11 +87,11 @@ namespace MipsISA {
}
static inline ExtMachInst
- makeExtMI(MachInst inst, const uint64_t &pc) {
+ makeExtMI(MachInst inst, ThreadContext * xc) {
#if FULL_SYSTEM
ExtMachInst ext_inst = inst;
- if (pc && 0x1)
- return ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32);
+ if (xc->readPC() && 0x1)
+ return ext_inst|=(static_cast<ExtMachInst>(xc->readPC() & 0x1) << 32);
else
return ext_inst;
#else
diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript
index 66f2b57e0..e317502e0 100644
--- a/src/arch/sparc/SConscript
+++ b/src/arch/sparc/SConscript
@@ -44,6 +44,7 @@ Import('env')
# Base sources used by all configurations.
base_sources = Split('''
+ asi.cc
faults.cc
floatregfile.cc
intregfile.cc
diff --git a/src/arch/sparc/asi.cc b/src/arch/sparc/asi.cc
new file mode 100644
index 000000000..00c9e041e
--- /dev/null
+++ b/src/arch/sparc/asi.cc
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#include "arch/sparc/asi.hh"
+
+namespace SparcISA
+{
+ bool AsiIsBlock(ASI asi)
+ {
+ return
+ (asi == ASI_BLK_AIUP) ||
+ (asi == ASI_BLK_AIUS) ||
+ (asi == ASI_BLK_AIUPL) ||
+ (asi == ASI_BLK_AIUSL) ||
+ (asi == ASI_BLK_P) ||
+ (asi == ASI_BLK_S) ||
+ (asi == ASI_BLK_PL) ||
+ (asi == ASI_BLK_SL);
+ }
+
+ bool AsiIsPrimary(ASI asi)
+ {
+ return
+ (asi == ASI_AIUP) ||
+ (asi == ASI_BLK_AIUP) ||
+ (asi == ASI_AIUPL) ||
+ (asi == ASI_BLK_AIUPL) ||
+ (asi == ASI_LDTX_AIUP) ||
+ (asi == ASI_LDTX_AIUPL) ||
+ (asi == ASI_P) ||
+ (asi == ASI_PNF) ||
+ (asi == ASI_PL) ||
+ (asi == ASI_PNFL) ||
+ (asi == ASI_PST8_P) ||
+ (asi == ASI_PST16_P) ||
+ (asi == ASI_PST32_P) ||
+ (asi == ASI_PST8_PL) ||
+ (asi == ASI_PST16_PL) ||
+ (asi == ASI_PST32_PL) ||
+ (asi == ASI_FL8_P) ||
+ (asi == ASI_FL16_P) ||
+ (asi == ASI_FL8_PL) ||
+ (asi == ASI_FL16_PL) ||
+ (asi == ASI_LDTX_P) ||
+ (asi == ASI_LDTX_PL) ||
+ (asi == ASI_BLK_P) ||
+ (asi == ASI_BLK_PL);
+ }
+
+ bool AsiIsSecondary(ASI asi)
+ {
+ return
+ (asi == ASI_AIUS) ||
+ (asi == ASI_BLK_AIUS) ||
+ (asi == ASI_AIUSL) ||
+ (asi == ASI_BLK_AIUSL) ||
+ (asi == ASI_LDTX_AIUS) ||
+ (asi == ASI_LDTX_AIUSL) ||
+ (asi == ASI_S) ||
+ (asi == ASI_SNF) ||
+ (asi == ASI_SL) ||
+ (asi == ASI_SNFL) ||
+ (asi == ASI_PST8_S) ||
+ (asi == ASI_PST16_S) ||
+ (asi == ASI_PST32_S) ||
+ (asi == ASI_PST8_SL) ||
+ (asi == ASI_PST16_SL) ||
+ (asi == ASI_PST32_SL) ||
+ (asi == ASI_FL8_S) ||
+ (asi == ASI_FL16_S) ||
+ (asi == ASI_FL8_SL) ||
+ (asi == ASI_FL16_SL) ||
+ (asi == ASI_LDTX_S) ||
+ (asi == ASI_LDTX_SL) ||
+ (asi == ASI_BLK_S) ||
+ (asi == ASI_BLK_SL);
+ }
+
+ bool AsiNucleus(ASI asi)
+ {
+ return
+ (asi == ASI_N) ||
+ (asi == ASI_NL) ||
+ (asi == ASI_LDTX_N) ||
+ (asi == ASI_LDTX_NL);
+ }
+
+ bool AsiIsAsIfUser(ASI asi)
+ {
+ return
+ (asi == ASI_AIUP) ||
+ (asi == ASI_AIUS) ||
+ (asi == ASI_BLK_AIUP) ||
+ (asi == ASI_BLK_AIUS) ||
+ (asi == ASI_AIUPL) ||
+ (asi == ASI_AIUSL) ||
+ (asi == ASI_BLK_AIUPL) ||
+ (asi == ASI_BLK_AIUSL) ||
+ (asi == ASI_LDTX_AIUP) ||
+ (asi == ASI_LDTX_AIUS) ||
+ (asi == ASI_LDTX_AIUPL) ||
+ (asi == ASI_LDTX_AIUSL);
+ }
+
+ bool AsiIsIO(ASI asi)
+ {
+ return
+ (asi == ASI_REAL_IO) ||
+ (asi == ASI_REAL_IO_L);
+ }
+
+ bool AsiIsReal(ASI asi)
+ {
+ return
+ (asi == ASI_REAL) ||
+ (asi == ASI_REAL_IO) ||
+ (asi == ASI_REAL_L) ||
+ (asi == ASI_REAL_IO_L) ||
+ (asi == ASI_LDTX_REAL) ||
+ (asi == ASI_LDTX_REAL_L) ||
+ (asi == ASI_MMU_REAL);
+ }
+
+ bool AsiIsLittle(ASI asi)
+ {
+ return
+ (asi == ASI_NL) ||
+ (asi == ASI_AIUPL) ||
+ (asi == ASI_AIUSL) ||
+ (asi == ASI_REAL_L) ||
+ (asi == ASI_REAL_IO_L) ||
+ (asi == ASI_BLK_AIUPL) ||
+ (asi == ASI_BLK_AIUSL) ||
+ (asi == ASI_LDTX_AIUPL) ||
+ (asi == ASI_LDTX_AIUSL) ||
+ (asi == ASI_LDTX_REAL_L) ||
+ (asi == ASI_LDTX_NL) ||
+ (asi == ASI_PL) ||
+ (asi == ASI_SL) ||
+ (asi == ASI_PNFL) ||
+ (asi == ASI_SNFL) ||
+ (asi == ASI_PST8_PL) ||
+ (asi == ASI_PST8_SL) ||
+ (asi == ASI_PST16_PL) ||
+ (asi == ASI_PST16_SL) ||
+ (asi == ASI_PST32_PL) ||
+ (asi == ASI_PST32_SL) ||
+ (asi == ASI_FL8_PL) ||
+ (asi == ASI_FL8_SL) ||
+ (asi == ASI_FL16_PL) ||
+ (asi == ASI_FL16_SL) ||
+ (asi == ASI_LDTX_PL) ||
+ (asi == ASI_LDTX_SL) ||
+ (asi == ASI_BLK_PL) ||
+ (asi == ASI_BLK_SL);
+ }
+
+ bool AsiIsTwin(ASI asi)
+ {
+ return
+ (asi == ASI_LDTX_AIUP) ||
+ (asi == ASI_LDTX_AIUS) ||
+ (asi == ASI_LDTX_REAL) ||
+ (asi == ASI_LDTX_N) ||
+ (asi == ASI_LDTX_AIUPL) ||
+ (asi == ASI_LDTX_AIUSL) ||
+ (asi == ASI_LDTX_REAL_L) ||
+ (asi == ASI_LDTX_NL) ||
+ (asi == ASI_LDTX_P) ||
+ (asi == ASI_LDTX_S) ||
+ (asi == ASI_LDTX_PL) ||
+ (asi == ASI_LDTX_SL);
+ }
+
+ bool AsiIsPartialStore(ASI asi)
+ {
+ return
+ (asi == ASI_PST8_P) ||
+ (asi == ASI_PST8_S) ||
+ (asi == ASI_PST16_P) ||
+ (asi == ASI_PST16_S) ||
+ (asi == ASI_PST32_P) ||
+ (asi == ASI_PST32_S) ||
+ (asi == ASI_PST8_PL) ||
+ (asi == ASI_PST8_SL) ||
+ (asi == ASI_PST16_PL) ||
+ (asi == ASI_PST16_SL) ||
+ (asi == ASI_PST32_PL) ||
+ (asi == ASI_PST32_SL);
+ }
+
+ bool AsiIsFloatingLoad(ASI asi)
+ {
+ return
+ (asi == ASI_FL8_P) ||
+ (asi == ASI_FL8_S) ||
+ (asi == ASI_FL16_P) ||
+ (asi == ASI_FL16_S) ||
+ (asi == ASI_FL8_PL) ||
+ (asi == ASI_FL8_SL) ||
+ (asi == ASI_FL16_PL) ||
+ (asi == ASI_FL16_SL);
+ }
+
+ bool AsiIsNoFault(ASI asi)
+ {
+ return
+ (asi == ASI_PNF) ||
+ (asi == ASI_SNF) ||
+ (asi == ASI_PNFL) ||
+ (asi == ASI_SNFL);
+ }
+
+ bool AsiIsScratchPad(ASI asi)
+ {
+ return
+ (asi == ASI_SCRATCHPAD) ||
+ (asi == ASI_HYP_SCRATCHPAD);
+ }
+
+ bool AsiIsCmt(ASI asi)
+ {
+ return
+ (asi == ASI_CMT_PER_STRAND) ||
+ (asi == ASI_CMT_SHARED);
+ }
+
+ bool AsiIsQueue(ASI asi)
+ {
+ return asi == ASI_QUEUE;
+ }
+
+ bool AsiIsDtlb(ASI asi)
+ {
+ return
+ (asi == ASI_DTLB_DATA_IN_REG) ||
+ (asi == ASI_DTLB_DATA_ACCESS_REG) ||
+ (asi == ASI_DTLB_TAG_READ_REG);
+ }
+
+ bool AsiIsMmu(ASI asi)
+ {
+ return
+ (asi == ASI_MMU_CONTEXTID) ||
+ (asi == ASI_IMMU) ||
+ (asi == ASI_MMU_REAL) ||
+ (asi == ASI_MMU) ||
+ (asi == ASI_DMMU) ||
+ (asi == ASI_UMMU) ||
+ (asi == ASI_DMMU_DEMAP);
+ }
+}
diff --git a/src/arch/sparc/asi.hh b/src/arch/sparc/asi.hh
index 482e077e0..876567225 100644
--- a/src/arch/sparc/asi.hh
+++ b/src/arch/sparc/asi.hh
@@ -156,23 +156,23 @@ namespace SparcISA
ASI_PST32_SL = 0xCD,
ASI_PST32_SECONDARY_LITTLE = ASI_PST32_SL,
//0xCE-0xCF implementation dependent
- ASI_PL8_P = 0xD0,
- ASI_PL8_PRIMARY = ASI_PL8_P,
- ASI_PL8_S = 0xD1,
- ASI_PL8_SECONDARY = ASI_PL8_S,
- ASI_PL16_P = 0xD2,
- ASI_PL16_PRIMARY = ASI_PL16_P,
- ASI_PL16_S = 0xD3,
- ASI_PL16_SECONDARY = ASI_PL16_S,
+ ASI_FL8_P = 0xD0,
+ ASI_FL8_PRIMARY = ASI_FL8_P,
+ ASI_FL8_S = 0xD1,
+ ASI_FL8_SECONDARY = ASI_FL8_S,
+ ASI_FL16_P = 0xD2,
+ ASI_FL16_PRIMARY = ASI_FL16_P,
+ ASI_FL16_S = 0xD3,
+ ASI_FL16_SECONDARY = ASI_FL16_S,
//0xD4-0xD7 implementation dependent
- ASI_PL8_PL = 0xD8,
- ASI_PL8_PRIMARY_LITTLE = ASI_PL8_PL,
- ASI_PL8_SL = 0xD9,
- ASI_PL8_SECONDARY_LITTLE = ASI_PL8_SL,
- ASI_PL16_PL = 0xDA,
- ASI_PL16_PRIMARY_LITTLE = ASI_PL16_PL,
- ASI_PL16_SL = 0xDB,
- ASI_PL16_SECONDARY_LITTLE = ASI_PL16_SL,
+ ASI_FL8_PL = 0xD8,
+ ASI_FL8_PRIMARY_LITTLE = ASI_FL8_PL,
+ ASI_FL8_SL = 0xD9,
+ ASI_FL8_SECONDARY_LITTLE = ASI_FL8_SL,
+ ASI_FL16_PL = 0xDA,
+ ASI_FL16_PRIMARY_LITTLE = ASI_FL16_PL,
+ ASI_FL16_SL = 0xDB,
+ ASI_FL16_SECONDARY_LITTLE = ASI_FL16_SL,
//0xDC-0xDF implementation dependent
//0xE0-0xE1 reserved
ASI_LDTX_P = 0xE2,
@@ -193,9 +193,30 @@ namespace SparcISA
ASI_BLK_PL = 0xF8,
ASI_BLOCK_PRIMARY_LITTLE = ASI_BLK_PL,
ASI_BLK_SL = 0xF9,
- ASI_BLOCK_SECONDARY_LITTLE = ASI_BLK_SL
+ ASI_BLOCK_SECONDARY_LITTLE = ASI_BLK_SL,
//0xFA-0xFF implementation dependent
+ MAX_ASI = 0xFF
};
+
+ //Functions that classify an asi
+ bool AsiIsBlock(ASI);
+ bool AsiIsPrimary(ASI);
+ bool AsiIsSecondary(ASI);
+ bool AsiIsNucleus(ASI);
+ bool AsiIsAsIfUser(ASI);
+ bool AsiIsIO(ASI);
+ bool AsiIsReal(ASI);
+ bool AsiIsLittle(ASI);
+ bool AsiIsTwin(ASI);
+ bool AsiIsPartialStore(ASI);
+ bool AsiIsFloatingLoad(ASI);
+ bool AsiIsNoFault(ASI);
+ bool AsiIsScratchPad(ASI);
+ bool AsiIsCmt(ASI);
+ bool AsiIsQueue(ASI);
+ bool AsiIsDtlb(ASI);
+ bool AsiIsMmu(ASI);
+
};
#endif // __ARCH_SPARC_TLB_HH__
diff --git a/src/arch/sparc/isa/base.isa b/src/arch/sparc/isa/base.isa
index b518265aa..a4c022411 100644
--- a/src/arch/sparc/isa/base.isa
+++ b/src/arch/sparc/isa/base.isa
@@ -77,7 +77,7 @@ output header {{
protected:
// Constructor.
SparcStaticInst(const char *mnem,
- MachInst _machInst, OpClass __opClass)
+ ExtMachInst _machInst, OpClass __opClass)
: StaticInst(mnem, _machInst, __opClass)
{
}
diff --git a/src/arch/sparc/isa/bitfields.isa b/src/arch/sparc/isa/bitfields.isa
index 27f52fa29..372f5c4ef 100644
--- a/src/arch/sparc/isa/bitfields.isa
+++ b/src/arch/sparc/isa/bitfields.isa
@@ -76,3 +76,7 @@ def bitfield SIMM11 <10:0>;
def bitfield SIMM13 <12:0>;
def bitfield SW_TRAP <7:0>;
def bitfield X <12>;
+
+// Extended bitfields which aren't part of the actual instruction.
+
+def bitfield EXT_ASI <39:32>;
diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa
index 1384b21a0..9da6bdd33 100644
--- a/src/arch/sparc/isa/decoder.isa
+++ b/src/arch/sparc/isa/decoder.isa
@@ -441,7 +441,7 @@ decode OP default Unknown::unknown()
0x34: decode OPF{
format BasicOperate{
0x01: fmovs({{
- Frd.uw = Frs2.uw;
+ Frds.uw = Frs2s.uw;
//fsr.ftt = fsr.cexc = 0
Fsr &= ~(7 << 14);
Fsr &= ~(0x1F);
@@ -454,7 +454,7 @@ decode OP default Unknown::unknown()
}});
0x03: Trap::fmovq({{fault = new FpDisabled;}});
0x05: fnegs({{
- Frd.uw = Frs2.uw ^ (1UL << 31);
+ Frds.uw = Frs2s.uw ^ (1UL << 31);
//fsr.ftt = fsr.cexc = 0
Fsr &= ~(7 << 14);
Fsr &= ~(0x1F);
@@ -467,7 +467,7 @@ decode OP default Unknown::unknown()
}});
0x07: Trap::fnegq({{fault = new FpDisabled;}});
0x09: fabss({{
- Frd.uw = ((1UL << 31) - 1) & Frs2.uw;
+ Frds.uw = ((1UL << 31) - 1) & Frs2s.uw;
//fsr.ftt = fsr.cexc = 0
Fsr &= ~(7 << 14);
Fsr &= ~(0x1F);
@@ -479,55 +479,55 @@ decode OP default Unknown::unknown()
Fsr &= ~(0x1F);
}});
0x0B: Trap::fabsq({{fault = new FpDisabled;}});
- 0x29: fsqrts({{Frd.sf = sqrt(Frs2.sf);}});
+ 0x29: fsqrts({{Frds.sf = sqrt(Frs2s.sf);}});
0x2A: fsqrtd({{Frd.df = sqrt(Frs2.df);}});
0x2B: Trap::fsqrtq({{fault = new FpDisabled;}});
- 0x41: fadds({{Frd.sf = Frs1.sf + Frs2.sf;}});
+ 0x41: fadds({{Frds.sf = Frs1s.sf + Frs2s.sf;}});
0x42: faddd({{Frd.df = Frs1.df + Frs2.df;}});
0x43: Trap::faddq({{fault = new FpDisabled;}});
- 0x45: fsubs({{Frd.sf = Frs1.sf - Frs2.sf;}});
+ 0x45: fsubs({{Frds.sf = Frs1s.sf - Frs2s.sf;}});
0x46: fsubd({{Frd.df = Frs1.df - Frs2.df;}});
0x47: Trap::fsubq({{fault = new FpDisabled;}});
- 0x49: fmuls({{Frd.sf = Frs1.sf * Frs2.sf;}});
+ 0x49: fmuls({{Frds.sf = Frs1s.sf * Frs2s.sf;}});
0x4A: fmuld({{Frd.df = Frs1.df * Frs2.df;}});
0x4B: Trap::fmulq({{fault = new FpDisabled;}});
- 0x4D: fdivs({{Frd.sf = Frs1.sf / Frs2.sf;}});
+ 0x4D: fdivs({{Frds.sf = Frs1s.sf / Frs2s.sf;}});
0x4E: fdivd({{Frd.df = Frs1.df / Frs2.df;}});
0x4F: Trap::fdivq({{fault = new FpDisabled;}});
- 0x69: fsmuld({{Frd.df = Frs1.sf * Frs2.sf;}});
+ 0x69: fsmuld({{Frd.df = Frs1s.sf * Frs2s.sf;}});
0x6E: Trap::fdmulq({{fault = new FpDisabled;}});
0x81: fstox({{
- Frd.df = (double)static_cast<int64_t>(Frs2.sf);
+ Frd.df = (double)static_cast<int64_t>(Frs2s.sf);
}});
0x82: fdtox({{
Frd.df = (double)static_cast<int64_t>(Frs2.df);
}});
0x83: Trap::fqtox({{fault = new FpDisabled;}});
0x84: fxtos({{
- Frd.sf = static_cast<float>((int64_t)Frs2.df);
+ Frds.sf = static_cast<float>((int64_t)Frs2.df);
}});
0x88: fxtod({{
Frd.df = static_cast<double>((int64_t)Frs2.df);
}});
0x8C: Trap::fxtoq({{fault = new FpDisabled;}});
0xC4: fitos({{
- Frd.sf = static_cast<float>((int32_t)Frs2.sf);
+ Frds.sf = static_cast<float>((int32_t)Frs2s.sf);
}});
- 0xC6: fdtos({{Frd.sf = Frs2.df;}});
+ 0xC6: fdtos({{Frds.sf = Frs2.df;}});
0xC7: Trap::fqtos({{fault = new FpDisabled;}});
0xC8: fitod({{
- Frd.df = static_cast<double>((int32_t)Frs2.sf);
+ Frd.df = static_cast<double>((int32_t)Frs2s.sf);
}});
- 0xC9: fstod({{Frd.df = Frs2.sf;}});
+ 0xC9: fstod({{Frd.df = Frs2s.sf;}});
0xCB: Trap::fqtod({{fault = new FpDisabled;}});
0xCC: Trap::fitoq({{fault = new FpDisabled;}});
0xCD: Trap::fstoq({{fault = new FpDisabled;}});
0xCE: Trap::fdtoq({{fault = new FpDisabled;}});
0xD1: fstoi({{
- Frd.sf = (float)static_cast<int32_t>(Frs2.sf);
+ Frds.sf = (float)static_cast<int32_t>(Frs2s.sf);
}});
0xD2: fdtoi({{
- Frd.sf = (float)static_cast<int32_t>(Frs2.df);
+ Frds.sf = (float)static_cast<int32_t>(Frs2.df);
}});
0xD3: Trap::fqtoi({{fault = new FpDisabled;}});
default: Trap::fpop1({{fault = new FpDisabled;}});
@@ -620,7 +620,7 @@ decode OP default Unknown::unknown()
0x56: Trap::fpsub32({{fault = new IllegalInstruction;}});
0x57: Trap::fpsub32s({{fault = new IllegalInstruction;}});
0x60: BasicOperate::fzero({{Frd.df = 0;}});
- 0x61: BasicOperate::fzeros({{Frd.sf = 0;}});
+ 0x61: BasicOperate::fzeros({{Frds.sf = 0;}});
0x62: Trap::fnor({{fault = new IllegalInstruction;}});
0x63: Trap::fnors({{fault = new IllegalInstruction;}});
0x64: Trap::fandnot2({{fault = new IllegalInstruction;}});
@@ -629,7 +629,7 @@ decode OP default Unknown::unknown()
Frd.df = (double)(~((uint64_t)Frs2.df));
}});
0x67: BasicOperate::fnot2s({{
- Frd.sf = (float)(~((uint32_t)Frs2.sf));
+ Frds.sf = (float)(~((uint32_t)Frs2s.sf));
}});
0x68: Trap::fandnot1({{fault = new IllegalInstruction;}});
0x69: Trap::fandnot1s({{fault = new IllegalInstruction;}});
@@ -637,7 +637,7 @@ decode OP default Unknown::unknown()
Frd.df = (double)(~((uint64_t)Frs1.df));
}});
0x6B: BasicOperate::fnot1s({{
- Frd.sf = (float)(~((uint32_t)Frs1.sf));
+ Frds.sf = (float)(~((uint32_t)Frs1s.sf));
}});
0x6C: Trap::fxor({{fault = new IllegalInstruction;}});
0x6D: Trap::fxors({{fault = new IllegalInstruction;}});
@@ -820,92 +820,251 @@ decode OP default Unknown::unknown()
}
0x3: decode OP3 {
format Load {
- 0x00: lduw({{Rd = Mem;}}, {{32}});
- 0x01: ldub({{Rd = Mem;}}, {{8}});
- 0x02: lduh({{Rd = Mem;}}, {{16}});
+ 0x00: lduw({{Rd = Mem.uw;}});
+ 0x01: ldub({{Rd = Mem.ub;}});
+ 0x02: lduh({{Rd = Mem.uhw;}});
0x03: ldd({{
- uint64_t val = Mem;
+ uint64_t val = Mem.udw;
RdLow = val<31:0>;
RdHigh = val<63:32>;
- }}, {{64}});
+ }});
}
format Store {
- 0x04: stw({{Mem = Rd.sw;}}, {{32}});
- 0x05: stb({{Mem = Rd.sb;}}, {{8}});
- 0x06: sth({{Mem = Rd.shw;}}, {{16}});
- 0x07: std({{Mem = RdLow<31:0> | (RdHigh<31:0> << 32);}}, {{64}});
+ 0x04: stw({{Mem.uw = Rd.sw;}});
+ 0x05: stb({{Mem.ub = Rd.sb;}});
+ 0x06: sth({{Mem.uhw = Rd.shw;}});
+ 0x07: std({{Mem.udw = RdLow<31:0> | (RdHigh<31:0> << 32);}});
}
format Load {
- 0x08: ldsw({{Rd = (int32_t)Mem;}}, {{32}});
- 0x09: ldsb({{Rd = (int8_t)Mem;}}, {{8}});
- 0x0A: ldsh({{Rd = (int16_t)Mem;}}, {{16}});
- 0x0B: ldx({{Rd = (int64_t)Mem;}}, {{64}});
+ 0x08: ldsw({{Rd = (int32_t)Mem.sw;}});
+ 0x09: ldsb({{Rd = (int8_t)Mem.sb;}});
+ 0x0A: ldsh({{Rd = (int16_t)Mem.shw;}});
+ 0x0B: ldx({{Rd = (int64_t)Mem.sdw;}});
0x0D: ldstub({{
- Rd = Mem;
- Mem = 0xFF;
- }}, {{8}});
+ Rd = Mem.ub;
+ Mem.ub = 0xFF;
+ }});
}
- 0x0E: Store::stx({{Mem = Rd}}, {{64}});
+ 0x0E: Store::stx({{Mem.udw = Rd}});
0x0F: LoadStore::swap({{
uint32_t temp = Rd;
- Rd = Mem;
- Mem = temp;
- }}, {{32}});
+ Rd = Mem.uw;
+ Mem.uw = temp;
+ }});
format Load {
- 0x10: lduwa({{Rd = Mem;}}, {{32}});
- 0x11: lduba({{Rd = Mem;}}, {{8}});
- 0x12: lduha({{Rd = Mem;}}, {{16}});
+ 0x10: lduwa({{Rd = Mem.uw;}});
+ 0x11: lduba({{Rd = Mem.ub;}});
+ 0x12: lduha({{Rd = Mem.uhw;}});
0x13: ldda({{
- uint64_t val = Mem;
+ uint64_t val = Mem.udw;
RdLow = val<31:0>;
RdHigh = val<63:32>;
- }}, {{64}});
+ }});
}
format Store {
- 0x14: stwa({{Mem = Rd;}}, {{32}});
- 0x15: stba({{Mem = Rd;}}, {{8}});
- 0x16: stha({{Mem = Rd;}}, {{16}});
- 0x17: stda({{Mem = RdLow<31:0> | RdHigh<31:0> << 32;}}, {{64}});
+ 0x14: stwa({{Mem.uw = Rd;}});
+ 0x15: stba({{Mem.ub = Rd;}});
+ 0x16: stha({{Mem.uhw = Rd;}});
+ 0x17: stda({{Mem.udw = RdLow<31:0> | RdHigh<31:0> << 32;}});
}
format Load {
- 0x18: ldswa({{Rd = (int32_t)Mem;}}, {{32}});
- 0x19: ldsba({{Rd = (int8_t)Mem;}}, {{8}});
- 0x1A: ldsha({{Rd = (int16_t)Mem;}}, {{16}});
- 0x1B: ldxa({{Rd = (int64_t)Mem;}}, {{64}});
+ 0x18: ldswa({{Rd = (int32_t)Mem.sw;}});
+ 0x19: ldsba({{Rd = (int8_t)Mem.sb;}});
+ 0x1A: ldsha({{Rd = (int16_t)Mem.shw;}});
+ 0x1B: ldxa({{Rd = (int64_t)Mem.sdw;}});
}
0x1D: LoadStore::ldstuba({{
- Rd = Mem;
- Mem = 0xFF;
- }}, {{8}});
- 0x1E: Store::stxa({{Mem = Rd}}, {{64}});
+ Rd = Mem.ub;
+ Mem.ub = 0xFF;
+ }});
+ 0x1E: Store::stxa({{Mem.udw = Rd}});
0x1F: LoadStore::swapa({{
uint32_t temp = Rd;
- Rd = Mem;
- Mem = temp;
- }}, {{32}});
+ Rd = Mem.uw;
+ Mem.uw = temp;
+ }});
format Trap {
- 0x20: Load::ldf({{Frd.uw = Mem;}}, {{32}});
+ 0x20: Load::ldf({{Frd.uw = Mem.uw;}});
0x21: decode X {
- 0x0: Load::ldfsr({{Fsr = Mem<31:0> | Fsr<63:32>;}}, {{32}});
- 0x1: Load::ldxfsr({{Fsr = Mem;}}, {{64}});
+ 0x0: Load::ldfsr({{Fsr = Mem.uw | Fsr<63:32>;}});
+ 0x1: Load::ldxfsr({{Fsr = Mem.udw;}});
}
0x22: ldqf({{fault = new FpDisabled;}});
- 0x23: Load::lddf({{Frd.udw = Mem;}}, {{64}});
- 0x24: Store::stf({{Mem = Frd.uw;}}, {{32}});
+ 0x23: Load::lddf({{Frd.udw = Mem.udw;}});
+ 0x24: Store::stf({{Mem.uw = Frd.uw;}});
0x25: decode X {
- 0x0: Store::stfsr({{Mem = Fsr<31:0>;}}, {{32}});
- 0x1: Store::stxfsr({{Mem = Fsr;}}, {{64}});
+ 0x0: Store::stfsr({{Mem.uw = Fsr<31:0>;}});
+ 0x1: Store::stxfsr({{Mem.udw = Fsr;}});
}
0x26: stqf({{fault = new FpDisabled;}});
- 0x27: Store::stdf({{Mem = Frd.udw;}}, {{64}});
+ 0x27: Store::stdf({{Mem.udw = Frd.udw;}});
0x2D: Nop::prefetch({{ }});
- 0x30: Load::ldfa({{Frd.uw = Mem;}}, {{32}});
+ 0x30: Load::ldfa({{Frd.uw = Mem.uw;}});
0x32: ldqfa({{fault = new FpDisabled;}});
- 0x33: Load::lddfa({{Frd.udw = Mem;}}, {{64}});
- 0x34: Store::stfa({{Mem = Frd.uw;}}, {{32}});
+ format LoadAlt {
+ 0x33: decode EXT_ASI {
+ //ASI_NUCLEUS
+ 0x04: FailUnimpl::lddfa_n();
+ //ASI_NUCLEUS_LITTLE
+ 0x0C: FailUnimpl::lddfa_nl();
+ //ASI_AS_IF_USER_PRIMARY
+ 0x10: FailUnimpl::lddfa_aiup();
+ //ASI_AS_IF_USER_PRIMARY_LITTLE
+ 0x18: FailUnimpl::lddfa_aiupl();
+ //ASI_AS_IF_USER_SECONDARY
+ 0x11: FailUnimpl::lddfa_aius();
+ //ASI_AS_IF_USER_SECONDARY_LITTLE
+ 0x19: FailUnimpl::lddfa_aiusl();
+ //ASI_REAL
+ 0x14: FailUnimpl::lddfa_real();
+ //ASI_REAL_LITTLE
+ 0x1C: FailUnimpl::lddfa_real_l();
+ //ASI_REAL_IO
+ 0x15: FailUnimpl::lddfa_real_io();
+ //ASI_REAL_IO_LITTLE
+ 0x1D: FailUnimpl::lddfa_real_io_l();
+ //ASI_PRIMARY
+ 0x80: FailUnimpl::lddfa_p();
+ //ASI_PRIMARY_LITTLE
+ 0x88: FailUnimpl::lddfa_pl();
+ //ASI_SECONDARY
+ 0x81: FailUnimpl::lddfa_s();
+ //ASI_SECONDARY_LITTLE
+ 0x89: FailUnimpl::lddfa_sl();
+ //ASI_PRIMARY_NO_FAULT
+ 0x82: FailUnimpl::lddfa_pnf();
+ //ASI_PRIMARY_NO_FAULT_LITTLE
+ 0x8A: FailUnimpl::lddfa_pnfl();
+ //ASI_SECONDARY_NO_FAULT
+ 0x83: FailUnimpl::lddfa_snf();
+ //ASI_SECONDARY_NO_FAULT_LITTLE
+ 0x8B: FailUnimpl::lddfa_snfl();
+
+ format BlockLoad {
+ // LDBLOCKF
+ //ASI_BLOCK_AS_IF_USER_PRIMARY
+ 0x16: FailUnimpl::ldblockf_aiup();
+ //ASI_BLOCK_AS_IF_USER_SECONDARY
+ 0x17: FailUnimpl::ldblockf_aius();
+ //ASI_BLOCK_AS_IF_USER_PRIMARY_LITTLE
+ 0x1E: FailUnimpl::ldblockf_aiupl();
+ //ASI_BLOCK_AS_IF_USER_SECONDARY_LITTLE
+ 0x1F: FailUnimpl::ldblockf_aiusl();
+ //ASI_BLOCK_PRIMARY
+ 0xF0: ldblockf_p({{Frd_N.udw = Mem.udw;}});
+ //ASI_BLOCK_SECONDARY
+ 0xF1: FailUnimpl::ldblockf_s();
+ //ASI_BLOCK_PRIMARY_LITTLE
+ 0xF8: FailUnimpl::ldblockf_pl();
+ //ASI_BLOCK_SECONDARY_LITTLE
+ 0xF9: FailUnimpl::ldblockf_sl();
+ }
+
+ //LDSHORTF
+ //ASI_FL8_PRIMARY
+ 0xD0: FailUnimpl::ldshortf_8p();
+ //ASI_FL8_SECONDARY
+ 0xD1: FailUnimpl::ldshortf_8s();
+ //ASI_FL8_PRIMARY_LITTLE
+ 0xD8: FailUnimpl::ldshortf_8pl();
+ //ASI_FL8_SECONDARY_LITTLE
+ 0xD9: FailUnimpl::ldshortf_8sl();
+ //ASI_FL16_PRIMARY
+ 0xD2: FailUnimpl::ldshortf_16p();
+ //ASI_FL16_SECONDARY
+ 0xD3: FailUnimpl::ldshortf_16s();
+ //ASI_FL16_PRIMARY_LITTLE
+ 0xDA: FailUnimpl::ldshortf_16pl();
+ //ASI_FL16_SECONDARY_LITTLE
+ 0xDB: FailUnimpl::ldshortf_16sl();
+ //Not an ASI which is legal with lddfa
+ default: Trap::lddfa_bad_asi(
+ {{fault = new DataAccessException;}});
+ }
+ }
+ 0x34: Store::stfa({{Mem.uw = Frd.uw;}});
0x36: stqfa({{fault = new FpDisabled;}});
- //XXX need to work in the ASI thing
- 0x37: Store::stdfa({{Mem = Frd.udw;}}, {{64}});
+ format StoreAlt {
+ 0x37: decode EXT_ASI {
+ //ASI_NUCLEUS
+ 0x04: FailUnimpl::stdfa_n();
+ //ASI_NUCLEUS_LITTLE
+ 0x0C: FailUnimpl::stdfa_nl();
+ //ASI_AS_IF_USER_PRIMARY
+ 0x10: FailUnimpl::stdfa_aiup();
+ //ASI_AS_IF_USER_PRIMARY_LITTLE
+ 0x18: FailUnimpl::stdfa_aiupl();
+ //ASI_AS_IF_USER_SECONDARY
+ 0x11: FailUnimpl::stdfa_aius();
+ //ASI_AS_IF_USER_SECONDARY_LITTLE
+ 0x19: FailUnimpl::stdfa_aiusl();
+ //ASI_REAL
+ 0x14: FailUnimpl::stdfa_real();
+ //ASI_REAL_LITTLE
+ 0x1C: FailUnimpl::stdfa_real_l();
+ //ASI_REAL_IO
+ 0x15: FailUnimpl::stdfa_real_io();
+ //ASI_REAL_IO_LITTLE
+ 0x1D: FailUnimpl::stdfa_real_io_l();
+ //ASI_PRIMARY
+ 0x80: FailUnimpl::stdfa_p();
+ //ASI_PRIMARY_LITTLE
+ 0x88: FailUnimpl::stdfa_pl();
+ //ASI_SECONDARY
+ 0x81: FailUnimpl::stdfa_s();
+ //ASI_SECONDARY_LITTLE
+ 0x89: FailUnimpl::stdfa_sl();
+ //ASI_PRIMARY_NO_FAULT
+ 0x82: FailUnimpl::stdfa_pnf();
+ //ASI_PRIMARY_NO_FAULT_LITTLE
+ 0x8A: FailUnimpl::stdfa_pnfl();
+ //ASI_SECONDARY_NO_FAULT
+ 0x83: FailUnimpl::stdfa_snf();
+ //ASI_SECONDARY_NO_FAULT_LITTLE
+ 0x8B: FailUnimpl::stdfa_snfl();
+
+ format BlockStore {
+ // STBLOCKF
+ //ASI_BLOCK_AS_IF_USER_PRIMARY
+ 0x16: FailUnimpl::stblockf_aiup();
+ //ASI_BLOCK_AS_IF_USER_SECONDARY
+ 0x17: FailUnimpl::stblockf_aius();
+ //ASI_BLOCK_AS_IF_USER_PRIMARY_LITTLE
+ 0x1E: FailUnimpl::stblockf_aiupl();
+ //ASI_BLOCK_AS_IF_USER_SECONDARY_LITTLE
+ 0x1F: FailUnimpl::stblockf_aiusl();
+ //ASI_BLOCK_PRIMARY
+ 0xF0: stblockf_p({{Mem.udw = Frd_N.udw;}});
+ //ASI_BLOCK_SECONDARY
+ 0xF1: FailUnimpl::stblockf_s();
+ //ASI_BLOCK_PRIMARY_LITTLE
+ 0xF8: FailUnimpl::stblockf_pl();
+ //ASI_BLOCK_SECONDARY_LITTLE
+ 0xF9: FailUnimpl::stblockf_sl();
+ }
+
+ //STSHORTF
+ //ASI_FL8_PRIMARY
+ 0xD0: FailUnimpl::stshortf_8p();
+ //ASI_FL8_SECONDARY
+ 0xD1: FailUnimpl::stshortf_8s();
+ //ASI_FL8_PRIMARY_LITTLE
+ 0xD8: FailUnimpl::stshortf_8pl();
+ //ASI_FL8_SECONDARY_LITTLE
+ 0xD9: FailUnimpl::stshortf_8sl();
+ //ASI_FL16_PRIMARY
+ 0xD2: FailUnimpl::stshortf_16p();
+ //ASI_FL16_SECONDARY
+ 0xD3: FailUnimpl::stshortf_16s();
+ //ASI_FL16_PRIMARY_LITTLE
+ 0xDA: FailUnimpl::stshortf_16pl();
+ //ASI_FL16_SECONDARY_LITTLE
+ 0xDB: FailUnimpl::stshortf_16sl();
+ //Not an ASI which is legal with lddfa
+ default: Trap::stdfa_bad_asi(
+ {{fault = new DataAccessException;}});
+ }
+ }
0x3C: Cas::casa({{
uint64_t val = Mem.uw;
if(Rs2.uw == val)
diff --git a/src/arch/sparc/isa/formats.isa b/src/arch/sparc/isa/formats.isa
index 17d68061b..e044aee1f 100644
--- a/src/arch/sparc/isa/formats.isa
+++ b/src/arch/sparc/isa/formats.isa
@@ -2,6 +2,9 @@
//Templates from this format are used later
##include "formats/basic.isa"
+//Include base classes for microcoding instructions
+##include "formats/micro.isa"
+
//Include the noop format
##include "formats/nop.isa"
@@ -11,12 +14,18 @@
//Include the memory format
##include "formats/mem.isa"
+//Include the block memory format
+##include "formats/blockmem.isa"
+
//Include the compare and swap format
##include "formats/cas.isa"
//Include the trap format
##include "formats/trap.isa"
+//Include the unimplemented format
+##include "formats/unimp.isa"
+
//Include the "unknown" format
##include "formats/unknown.isa"
diff --git a/src/arch/sparc/isa/formats/basic.isa b/src/arch/sparc/isa/formats/basic.isa
index 0a47a7ffe..042201de4 100644
--- a/src/arch/sparc/isa/formats/basic.isa
+++ b/src/arch/sparc/isa/formats/basic.isa
@@ -33,6 +33,14 @@ def template BasicExecDeclare {{
Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const;
}};
+// Definitions of execute methods that panic.
+def template BasicExecPanic {{
+ Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const
+ {
+ panic("Execute method called when it shouldn't!");
+ }
+}};
+
// Basic instruction class declaration template.
def template BasicDeclare {{
/**
@@ -80,6 +88,11 @@ def template BasicDecode {{
return new %(class_name)s(machInst);
}};
+// Basic decode template, passing mnemonic in as string arg to constructor.
+def template BasicDecodeWithMnemonic {{
+ return new %(class_name)s("%(mnemonic)s", machInst);
+}};
+
// The most basic instruction format... used only for a few misc. insts
def format BasicOperate(code, *flags) {{
iop = InstObjParams(name, Name, 'SparcStaticInst',
diff --git a/src/arch/sparc/isa/formats/blockmem.isa b/src/arch/sparc/isa/formats/blockmem.isa
new file mode 100644
index 000000000..4a2a14a15
--- /dev/null
+++ b/src/arch/sparc/isa/formats/blockmem.isa
@@ -0,0 +1,370 @@
+////////////////////////////////////////////////////////////////////
+//
+// Block Memory instructions
+//
+
+output header {{
+
+ class BlockMem : public SparcMacroInst
+ {
+ protected:
+
+ // Constructor
+ // We make the assumption that all block memory operations
+ // Will take 8 instructions to execute
+ BlockMem(const char *mnem,
+ ExtMachInst _machInst, OpClass __opClass) :
+ SparcMacroInst(mnem, _machInst, __opClass, 8)
+ {}
+ };
+
+ class BlockMemImm : public BlockMem
+ {
+ protected:
+
+ // Constructor
+ BlockMemImm(const char *mnem,
+ ExtMachInst _machInst, OpClass __opClass) :
+ BlockMem(mnem, _machInst, __opClass),
+ imm(sext<13>(SIMM13))
+ {}
+
+ const int32_t imm;
+ };
+
+ class BlockMemMicro : public SparcDelayedMicroInst
+ {
+ protected:
+
+ // Constructor
+ BlockMemMicro(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass, int8_t _offset) :
+ SparcDelayedMicroInst(mnem, _machInst, __opClass),
+ offset(_offset)
+ {}
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+
+ const int8_t offset;
+ };
+
+ class BlockMemImmMicro : public BlockMemMicro
+ {
+ protected:
+
+ // Constructor
+ BlockMemImmMicro(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass, int8_t _offset) :
+ BlockMemMicro(mnem, _machInst, __opClass, _offset),
+ imm(sext<13>(SIMM13))
+ {}
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+
+ const int32_t imm;
+ };
+}};
+
+output decoder {{
+ std::string BlockMemMicro::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+ bool load = flags[IsLoad];
+ bool save = flags[IsStore];
+
+ printMnemonic(response, mnemonic);
+ if(save)
+ {
+ printReg(response, _srcRegIdx[0]);
+ ccprintf(response, ", ");
+ }
+ ccprintf(response, "[ ");
+ printReg(response, _srcRegIdx[!save ? 0 : 1]);
+ ccprintf(response, " + ");
+ printReg(response, _srcRegIdx[!save ? 1 : 2]);
+ ccprintf(response, " ]");
+ if(load)
+ {
+ ccprintf(response, ", ");
+ printReg(response, _destRegIdx[0]);
+ }
+
+ return response.str();
+ }
+
+ std::string BlockMemImmMicro::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+ bool load = flags[IsLoad];
+ bool save = flags[IsStore];
+
+ printMnemonic(response, mnemonic);
+ if(save)
+ {
+ printReg(response, _srcRegIdx[1]);
+ ccprintf(response, ", ");
+ }
+ ccprintf(response, "[ ");
+ printReg(response, _srcRegIdx[0]);
+ if(imm >= 0)
+ ccprintf(response, " + 0x%x ]", imm);
+ else
+ ccprintf(response, " + -0x%x ]", -imm);
+ if(load)
+ {
+ ccprintf(response, ", ");
+ printReg(response, _destRegIdx[0]);
+ }
+
+ return response.str();
+ }
+
+}};
+
+def template LoadStoreExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+ uint64_t write_result = 0;
+ Addr EA;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(priv_check)s;
+ %(ea_code)s;
+ DPRINTF(Sparc, "The address is 0x%x\n", EA);
+ xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0);
+ %(code)s;
+
+ if(fault == NoFault)
+ {
+ xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result);
+ //Write the resulting state to the execution context
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+def template BlockMemDeclare {{
+ /**
+ * Static instruction class for a block memory operation
+ */
+ class %(class_name)s : public %(base_class)s
+ {
+ public:
+ //Constructor
+ %(class_name)s(ExtMachInst machInst);
+
+ protected:
+ class %(class_name)s_0 : public %(base_class)sMicro
+ {
+ public:
+ //Constructor
+ %(class_name)s_0(ExtMachInst machInst);
+ %(BasicExecDeclare)s
+ };
+
+ class %(class_name)s_1 : public %(base_class)sMicro
+ {
+ public:
+ //Constructor
+ %(class_name)s_1(ExtMachInst machInst);
+ %(BasicExecDeclare)s
+ };
+
+ class %(class_name)s_2 : public %(base_class)sMicro
+ {
+ public:
+ //Constructor
+ %(class_name)s_2(ExtMachInst machInst);
+ %(BasicExecDeclare)s
+ };
+
+ class %(class_name)s_3 : public %(base_class)sMicro
+ {
+ public:
+ //Constructor
+ %(class_name)s_3(ExtMachInst machInst);
+ %(BasicExecDeclare)s
+ };
+
+ class %(class_name)s_4 : public %(base_class)sMicro
+ {
+ public:
+ //Constructor
+ %(class_name)s_4(ExtMachInst machInst);
+ %(BasicExecDeclare)s
+ };
+
+ class %(class_name)s_5 : public %(base_class)sMicro
+ {
+ public:
+ //Constructor
+ %(class_name)s_5(ExtMachInst machInst);
+ %(BasicExecDeclare)s
+ };
+
+ class %(class_name)s_6 : public %(base_class)sMicro
+ {
+ public:
+ //Constructor
+ %(class_name)s_6(ExtMachInst machInst);
+ %(BasicExecDeclare)s
+ };
+
+ class %(class_name)s_7 : public %(base_class)sMicro
+ {
+ public:
+ //Constructor
+ %(class_name)s_7(ExtMachInst machInst);
+ %(BasicExecDeclare)s
+ };
+ };
+}};
+
+// Basic instruction class constructor template.
+def template BlockMemConstructor {{
+ inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
+ : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+ {
+ %(constructor)s;
+ microOps[0] = new %(class_name)s_0(machInst);
+ microOps[1] = new %(class_name)s_1(machInst);
+ microOps[2] = new %(class_name)s_2(machInst);
+ microOps[3] = new %(class_name)s_3(machInst);
+ microOps[4] = new %(class_name)s_4(machInst);
+ microOps[5] = new %(class_name)s_5(machInst);
+ microOps[6] = new %(class_name)s_6(machInst);
+ microOps[7] = new %(class_name)s_7(machInst);
+ }
+}};
+
+def template BlockMemMicroConstructor {{
+ inline %(class_name)s::
+ %(class_name)s_%(micro_pc)s::
+ %(class_name)s_%(micro_pc)s(ExtMachInst machInst) :
+ %(base_class)sMicro("%(mnemonic)s[%(micro_pc)s]",
+ machInst, %(op_class)s, %(micro_pc)s * 8)
+ {
+ %(constructor)s;
+ %(set_flags)s;
+ }
+}};
+
+def template MicroLoadExecute {{
+ Fault %(class_name)s::%(class_name)s_%(micro_pc)s::execute(
+ %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+ Addr EA;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+ %(fault_check)s;
+ DPRINTF(Sparc, "The address is 0x%x\n", EA);
+ xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0);
+ %(code)s;
+
+ if(fault == NoFault)
+ {
+ //Write the resulting state to the execution context
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+def template MicroStoreExecute {{
+ Fault %(class_name)s::%(class_name)s_%(micro_pc)s::execute(
+ %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+ uint64_t write_result = 0;
+ Addr EA;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+ %(fault_check)s;
+ DPRINTF(Sparc, "The address is 0x%x\n", EA);
+ %(code)s;
+
+ if(fault == NoFault)
+ {
+ xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result);
+ //Write the resulting state to the execution context
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+let {{
+
+ def doBlockMemFormat(code, execute, name, Name, opt_flags):
+ # XXX Need to take care of pstate.hpriv as well. The lower ASIs
+ # are split into ones that are available in priv and hpriv, and
+ # those that are only available in hpriv
+ faultCheck = '''if(bits(Pstate,2,2) == 0 && (EXT_ASI & 0x80) == 0)
+ return new PrivilegedAction;
+ if(AsiIsAsIfUser((ASI)EXT_ASI) && !bits(Pstate,2,2))
+ return new PrivilegedAction;
+ //The LSB can be zero, since it's really the MSB in doubles
+ //and quads
+ if(RD & 0xe)
+ return new IllegalInstruction;
+ if(EA & 0x3f)
+ return new MemAddressNotAligned;
+ '''
+ addrCalcReg = 'EA = Rs1 + Rs2 + offset;'
+ addrCalcImm = 'EA = Rs1 + imm + offset;'
+ iop = InstObjParams(name, Name, 'BlockMem', code, opt_flags)
+ iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', code, opt_flags)
+ header_output = BlockMemDeclare.subst(iop) + BlockMemDeclare.subst(iop_imm)
+ decoder_output = BlockMemConstructor.subst(iop) + BlockMemConstructor.subst(iop_imm)
+ decode_block = ROrImmDecode.subst(iop)
+ matcher = re.compile(r'Frd_N')
+ exec_output = ''
+ for microPC in range(8):
+ flag_code = ''
+ if (microPC == 7):
+ flag_code = "flags[IsLastMicroOp] = true"
+ pcedCode = matcher.sub("Frd_%d" % microPC, code)
+ iop = InstObjParams(name, Name, 'BlockMem', pcedCode,
+ opt_flags, {"ea_code": addrCalcReg,
+ "fault_check": faultCheck, "micro_pc": microPC,
+ "set_flags": flag_code})
+ iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', pcedCode,
+ opt_flags, {"ea_code": addrCalcImm,
+ "fault_check": faultCheck, "micro_pc": microPC,
+ "set_flags": flag_code})
+ exec_output += execute.subst(iop)
+ exec_output += execute.subst(iop_imm)
+ decoder_output += BlockMemMicroConstructor.subst(iop)
+ decoder_output += BlockMemMicroConstructor.subst(iop_imm)
+ faultCheck = ''
+ return (header_output, decoder_output, exec_output, decode_block)
+}};
+
+def format BlockLoad(code, *opt_flags) {{
+ (header_output,
+ decoder_output,
+ exec_output,
+ decode_block) = doBlockMemFormat(code, MicroLoadExecute,
+ name, Name, opt_flags)
+}};
+
+def format BlockStore(code, *opt_flags) {{
+ (header_output,
+ decoder_output,
+ exec_output,
+ decode_block) = doBlockMemFormat(code, MicroStoreExecute,
+ name, Name, opt_flags)
+}};
diff --git a/src/arch/sparc/isa/formats/branch.isa b/src/arch/sparc/isa/formats/branch.isa
index 2c206354b..5fb7ade2d 100644
--- a/src/arch/sparc/isa/formats/branch.isa
+++ b/src/arch/sparc/isa/formats/branch.isa
@@ -80,7 +80,7 @@ output header {{
OpClass __opClass) :
BranchDisp(mnem, _machInst, __opClass)
{
- disp = sign_ext(_machInst << 2, bits + 2);
+ disp = sext<bits + 2>((_machInst & mask(bits)) << 2);
}
};
@@ -95,7 +95,7 @@ output header {{
OpClass __opClass) :
BranchDisp(mnem, _machInst, __opClass)
{
- disp = sign_ext((D16HI << 16) | (D16LO << 2), 18);
+ disp = sext<18>((D16HI << 16) | (D16LO << 2));
}
};
@@ -108,7 +108,7 @@ output header {{
protected:
// Constructor
BranchImm13(const char *mnem, MachInst _machInst, OpClass __opClass) :
- Branch(mnem, _machInst, __opClass), imm(sign_ext(SIMM13, 13))
+ Branch(mnem, _machInst, __opClass), imm(sext<13>(SIMM13))
{
}
diff --git a/src/arch/sparc/isa/formats/integerop.isa b/src/arch/sparc/isa/formats/integerop.isa
index 83c7e6958..4f8ebebcc 100644
--- a/src/arch/sparc/isa/formats/integerop.isa
+++ b/src/arch/sparc/isa/formats/integerop.isa
@@ -87,7 +87,7 @@ output header {{
OpClass __opClass) :
IntOpImm(mnem, _machInst, __opClass)
{
- imm = sign_ext(SIMM10, 10);
+ imm = sext<10>(SIMM10);
}
};
@@ -102,7 +102,7 @@ output header {{
OpClass __opClass) :
IntOpImm(mnem, _machInst, __opClass)
{
- imm = sign_ext(SIMM11, 11);
+ imm = sext<11>(SIMM11);
}
};
@@ -117,7 +117,7 @@ output header {{
OpClass __opClass) :
IntOpImm(mnem, _machInst, __opClass)
{
- imm = sign_ext(SIMM13, 13);
+ imm = sext<13>(SIMM13);
}
};
@@ -264,13 +264,13 @@ let {{
(usesImm, code, immCode,
rString, iString) = splitOutImm(code)
iop = InstObjParams(name, Name, 'IntOp', code,
- opt_flags, ("cc_code", ccCode))
+ opt_flags, {"cc_code": ccCode})
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))
+ immCode, opt_flags, {"cc_code": ccCode})
header_output += BasicDeclare.subst(imm_iop)
decoder_output += BasicConstructor.subst(imm_iop)
exec_output += IntOpExecute.subst(imm_iop)
@@ -341,7 +341,7 @@ def format IntOpCcRes(code, *opt_flags) {{
def format SetHi(code, *opt_flags) {{
iop = InstObjParams(name, Name, 'SetHi',
- code, opt_flags, ("cc_code", ''))
+ code, opt_flags, {"cc_code": ''})
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
exec_output = IntOpExecute.subst(iop)
diff --git a/src/arch/sparc/isa/formats/mem.isa b/src/arch/sparc/isa/formats/mem.isa
index 9011c1fc6..b046bdd1c 100644
--- a/src/arch/sparc/isa/formats/mem.isa
+++ b/src/arch/sparc/isa/formats/mem.isa
@@ -32,7 +32,7 @@ output header {{
MemImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
Mem(mnem, _machInst, __opClass)
{
- imm = sign_ext(SIMM13, 13);
+ imm = sext<13>(SIMM13);
}
std::string generateDisassembly(Addr pc,
@@ -97,9 +97,10 @@ output decoder {{
return response.str();
}
+
}};
-def template MemExecute {{
+def template LoadExecute {{
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
{
@@ -107,14 +108,14 @@ def template MemExecute {{
Addr EA;
%(op_decl)s;
%(op_rd)s;
+ %(priv_check)s;
%(ea_code)s;
DPRINTF(Sparc, "The address is 0x%x\n", EA);
- %(load)s;
+ xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0);
%(code)s;
if(fault == NoFault)
{
- %(store)s;
//Write the resulting state to the execution context
%(op_wb)s;
}
@@ -123,49 +124,118 @@ def template MemExecute {{
}
}};
-let {{
- # Leave memAccessFlags at 0 for now
- loadString = "xc->read(EA, (uint%(width)s_t&)Mem, 0);"
- storeString = "uint64_t write_result = 0; \
- xc->write((uint%(width)s_t)Mem, EA, 0, &write_result);"
+def template StoreExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+ uint64_t write_result = 0;
+ Addr EA;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(priv_check)s;
+ %(ea_code)s;
+ DPRINTF(Sparc, "The address is 0x%x\n", EA);
+ %(code)s;
+
+ if(fault == NoFault)
+ {
+ xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result);
+ //Write the resulting state to the execution context
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
- def doMemFormat(code, load, store, name, Name, opt_flags):
+def template LoadStoreExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+ uint64_t write_result = 0;
+ Addr EA;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(priv_check)s;
+ %(ea_code)s;
+ DPRINTF(Sparc, "The address is 0x%x\n", EA);
+ xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0);
+ %(code)s;
+
+ if(fault == NoFault)
+ {
+ xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result);
+ //Write the resulting state to the execution context
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+let {{
+ # XXX Need to take care of pstate.hpriv as well. The lower ASIs are split
+ # into ones that are available in priv and hpriv, and those that are only
+ # available in hpriv
+ privilegedString = '''if(bits(Pstate,2,2) == 0 && (EXT_ASI & 0x80) == 0)
+ return new PrivilegedAction;
+ if(AsiIsAsIfUser(EXT_ASI) && !bits(Pstate,2,2))
+ return new PrivilegedAction;'''
+
+ def doMemFormat(code, execute, priv, name, Name, opt_flags):
addrCalcReg = 'EA = Rs1 + Rs2;'
addrCalcImm = 'EA = Rs1 + imm;'
iop = InstObjParams(name, Name, 'Mem', code,
- opt_flags, ("ea_code", addrCalcReg),
- ("load", load), ("store", store))
+ opt_flags, {"ea_code": addrCalcReg,
+ "priv_check": priv})
iop_imm = InstObjParams(name, Name + 'Imm', 'MemImm', code,
- opt_flags, ("ea_code", addrCalcImm),
- ("load", load), ("store", store))
+ opt_flags, {"ea_code": addrCalcImm,
+ "priv_check": priv})
header_output = BasicDeclare.subst(iop) + BasicDeclare.subst(iop_imm)
decoder_output = BasicConstructor.subst(iop) + BasicConstructor.subst(iop_imm)
decode_block = ROrImmDecode.subst(iop)
- exec_output = MemExecute.subst(iop) + MemExecute.subst(iop_imm)
+ exec_output = execute.subst(iop) + execute.subst(iop_imm)
return (header_output, decoder_output, exec_output, decode_block)
}};
-def format Load(code, width, *opt_flags) {{
+def format LoadAlt(code, *opt_flags) {{
+ (header_output,
+ decoder_output,
+ exec_output,
+ decode_block) = doMemFormat(code, LoadExecute,
+ privelegedString, name, Name, opt_flags)
+}};
+
+def format StoreAlt(code, *opt_flags) {{
+ (header_output,
+ decoder_output,
+ exec_output,
+ decode_block) = doMemFormat(code, StoreExecute,
+ privilegedString, name, Name, opt_flags)
+}};
+
+def format Load(code, *opt_flags) {{
(header_output,
decoder_output,
exec_output,
decode_block) = doMemFormat(code,
- loadString % {"width":width}, '', name, Name, opt_flags)
+ LoadExecute, '', name, Name, opt_flags)
}};
-def format Store(code, width, *opt_flags) {{
+def format Store(code, *opt_flags) {{
(header_output,
decoder_output,
exec_output,
- decode_block) = doMemFormat(code, '',
- storeString % {"width":width}, name, Name, opt_flags)
+ decode_block) = doMemFormat(code,
+ StoreExecute, '', name, Name, opt_flags)
}};
-def format LoadStore(code, width, *opt_flags) {{
+def format LoadStore(code, *opt_flags) {{
(header_output,
decoder_output,
exec_output,
decode_block) = doMemFormat(code,
- loadString % {"width":width}, storeString % {"width":width},
- name, Name, opt_flags)
+ LoadStoreExecute, '', name, Name, opt_flags)
}};
diff --git a/src/arch/sparc/isa/formats/micro.isa b/src/arch/sparc/isa/formats/micro.isa
new file mode 100644
index 000000000..82d7fb4cb
--- /dev/null
+++ b/src/arch/sparc/isa/formats/micro.isa
@@ -0,0 +1,103 @@
+// Copyright (c) 2006 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: Gabe Black
+
+output header {{
+
+ class SparcMacroInst : public SparcStaticInst
+ {
+ protected:
+ const uint32_t numMicroOps;
+
+ //Constructor.
+ SparcMacroInst(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass, uint32_t _numMicroOps)
+ : SparcStaticInst(mnem, _machInst, __opClass),
+ numMicroOps(_numMicroOps)
+ {
+ assert(numMicroOps);
+ microOps = new StaticInstPtr[numMicroOps];
+ flags[IsMacroOp] = true;
+ }
+
+ ~SparcMacroInst()
+ {
+ delete [] microOps;
+ }
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+
+ StaticInstPtr * microOps;
+
+ StaticInstPtr fetchMicroOp(MicroPC microPC)
+ {
+ assert(microPC < numMicroOps);
+ return microOps[microPC];
+ }
+
+ %(BasicExecPanic)s
+ };
+
+ class SparcMicroInst : public SparcStaticInst
+ {
+ protected:
+ //Constructor.
+ SparcMicroInst(const char *mnem,
+ ExtMachInst _machInst, OpClass __opClass)
+ : SparcStaticInst(mnem, _machInst, __opClass)
+ {
+ flags[IsMicroOp] = true;
+ }
+ };
+
+ class SparcDelayedMicroInst : public SparcMicroInst
+ {
+ protected:
+ //Constructor.
+ SparcDelayedMicroInst(const char *mnem,
+ ExtMachInst _machInst, OpClass __opClass)
+ : SparcMicroInst(mnem, _machInst, __opClass)
+ {
+ flags[IsDelayedCommit] = true;
+ }
+ };
+}};
+
+output decoder {{
+
+ std::string SparcMacroInst::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+
+ printMnemonic(response, mnemonic);
+
+ return response.str();
+ }
+
+}};
diff --git a/src/arch/sparc/isa/formats/priv.isa b/src/arch/sparc/isa/formats/priv.isa
index d7ee01519..2a38422a7 100644
--- a/src/arch/sparc/isa/formats/priv.isa
+++ b/src/arch/sparc/isa/formats/priv.isa
@@ -103,13 +103,13 @@ let {{
(usesImm, code, immCode,
rString, iString) = splitOutImm(code)
iop = InstObjParams(name, Name, 'Priv', code,
- opt_flags, ("check", checkCode))
+ opt_flags, {"check": checkCode})
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
exec_output = PrivExecute.subst(iop)
if usesImm:
imm_iop = InstObjParams(name, Name + 'Imm', 'PrivImm',
- immCode, opt_flags, ("check", checkCode))
+ immCode, opt_flags, {"check": checkCode})
header_output += BasicDeclare.subst(imm_iop)
decoder_output += BasicConstructor.subst(imm_iop)
exec_output += PrivExecute.subst(imm_iop)
diff --git a/src/arch/sparc/isa/formats/unimp.isa b/src/arch/sparc/isa/formats/unimp.isa
new file mode 100644
index 000000000..a623507a1
--- /dev/null
+++ b/src/arch/sparc/isa/formats/unimp.isa
@@ -0,0 +1,147 @@
+// -*- mode:c++ -*-
+
+// 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: Steve Reinhardt
+
+////////////////////////////////////////////////////////////////////
+//
+// Unimplemented instructions
+//
+
+output header {{
+ /**
+ * Static instruction class for unimplemented instructions that
+ * cause simulator termination. Note that these are recognized
+ * (legal) instructions that the simulator does not support; the
+ * 'Unknown' class is used for unrecognized/illegal instructions.
+ * This is a leaf class.
+ */
+ class FailUnimplemented : public SparcStaticInst
+ {
+ public:
+ /// Constructor
+ FailUnimplemented(const char *_mnemonic, ExtMachInst _machInst)
+ : SparcStaticInst(_mnemonic, _machInst, No_OpClass)
+ {
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for unimplemented instructions that cause a warning
+ * to be printed (but do not terminate simulation). This
+ * implementation is a little screwy in that it will print a
+ * warning for each instance of a particular unimplemented machine
+ * instruction, not just for each unimplemented opcode. Should
+ * probably make the 'warned' flag a static member of the derived
+ * class.
+ */
+ class WarnUnimplemented : public SparcStaticInst
+ {
+ private:
+ /// Have we warned on this instruction yet?
+ mutable bool warned;
+
+ public:
+ /// Constructor
+ WarnUnimplemented(const char *_mnemonic, ExtMachInst _machInst)
+ : SparcStaticInst(_mnemonic, _machInst, No_OpClass), warned(false)
+ {
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string
+ FailUnimplemented::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s (unimplemented)", mnemonic);
+ }
+
+ std::string
+ WarnUnimplemented::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+ return csprintf("%-10s", mnemonic);
+#else
+ return csprintf("%-10s (unimplemented)", mnemonic);
+#endif
+ }
+}};
+
+output exec {{
+ Fault
+ FailUnimplemented::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ panic("attempt to execute unimplemented instruction '%s' "
+ "(inst 0x%08x)", mnemonic, machInst);
+ return NoFault;
+ }
+
+ Fault
+ WarnUnimplemented::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ if (!warned) {
+ warn("instruction '%s' unimplemented\n", mnemonic);
+ warned = true;
+ }
+
+ return NoFault;
+ }
+}};
+
+
+def format FailUnimpl() {{
+ iop = InstObjParams(name, 'FailUnimplemented')
+ decode_block = BasicDecodeWithMnemonic.subst(iop)
+}};
+
+def format WarnUnimpl() {{
+ iop = InstObjParams(name, 'WarnUnimplemented')
+ decode_block = BasicDecodeWithMnemonic.subst(iop)
+}};
+
diff --git a/src/arch/sparc/isa/main.isa b/src/arch/sparc/isa/main.isa
index 14acf54fa..765c98ed1 100644
--- a/src/arch/sparc/isa/main.isa
+++ b/src/arch/sparc/isa/main.isa
@@ -26,7 +26,7 @@
// (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: Korey Sewell
+// Authors: Gabe Black
////////////////////////////////////////////////////////////////////
//
diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa
index 605816083..40926a5fb 100644
--- a/src/arch/sparc/isa/operands.isa
+++ b/src/arch/sparc/isa/operands.isa
@@ -42,6 +42,16 @@ def operand_types {{
'qf' : ('float', 128)
}};
+output header {{
+ // A function to "decompress" double and quad floating point
+ // register numbers stuffed into 5 bit fields. These have their
+ // MSB put in the LSB position but are otherwise normal.
+ static inline unsigned int dfpr(unsigned int regNum)
+ {
+ return (regNum & (~1)) | ((regNum & 1) << 5);
+ }
+}};
+
def operands {{
# Int regs default to unsigned, but code should not count on this.
# For clarity, descriptions that depend on unsigned behavior should
@@ -51,9 +61,22 @@ def operands {{
'RdHigh': ('IntReg', 'udw', 'RD | 1', 'IsInteger', 3),
'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 4),
'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 5),
- 'Frd': ('FloatReg', 'df', 'RD', 'IsFloating', 10),
- 'Frs1': ('FloatReg', 'df', 'RS1', 'IsFloating', 11),
- 'Frs2': ('FloatReg', 'df', 'RS2', 'IsFloating', 12),
+ '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.
+ # Note that this adds twice N to the register number.
+ 'Frd_0': ('FloatReg', 'df', 'dfpr(RD)', 'IsFloating', 10),
+ 'Frd_1': ('FloatReg', 'df', 'dfpr(RD) + 2', 'IsFloating', 10),
+ 'Frd_2': ('FloatReg', 'df', 'dfpr(RD) + 4', 'IsFloating', 10),
+ 'Frd_3': ('FloatReg', 'df', 'dfpr(RD) + 6', 'IsFloating', 10),
+ 'Frd_4': ('FloatReg', 'df', 'dfpr(RD) + 8', 'IsFloating', 10),
+ 'Frd_5': ('FloatReg', 'df', 'dfpr(RD) + 10', 'IsFloating', 10),
+ 'Frd_6': ('FloatReg', 'df', 'dfpr(RD) + 12', 'IsFloating', 10),
+ 'Frd_7': ('FloatReg', 'df', 'dfpr(RD) + 14', 'IsFloating', 10),
+ 'Frs1s': ('FloatReg', 'df', 'RS1', 'IsFloating', 11),
+ 'Frs1': ('FloatReg', 'df', 'dfpr(RS1)', 'IsFloating', 11),
+ 'Frs2s': ('FloatReg', 'df', 'RS2', 'IsFloating', 12),
+ 'Frs2': ('FloatReg', 'df', 'dfpr(RS2)', 'IsFloating', 12),
'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 20),
'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 31),
'NNPC': ('NNPC', 'udw', None, (None, None, 'IsControl' ), 32),
diff --git a/src/arch/sparc/utility.hh b/src/arch/sparc/utility.hh
index f1c071148..23fddf0e9 100644
--- a/src/arch/sparc/utility.hh
+++ b/src/arch/sparc/utility.hh
@@ -33,12 +33,25 @@
#include "arch/sparc/isa_traits.hh"
#include "base/misc.hh"
+#include "base/bitfield.hh"
+#include "cpu/thread_context.hh"
namespace SparcISA
{
inline ExtMachInst
- makeExtMI(MachInst inst, const Addr &pc) {
- return ExtMachInst(inst);
+ makeExtMI(MachInst inst, ThreadContext * xc) {
+ ExtMachInst emi = (unsigned MachInst) inst;
+ //The I bit, bit 13, is used to figure out where the ASI
+ //should come from. Use that in the ExtMachInst. This is
+ //slightly redundant, but it removes the need to put a condition
+ //into all the execute functions
+ if(inst & (1 << 13))
+ emi |= (static_cast<ExtMachInst>(xc->readMiscReg(MISCREG_ASI))
+ << (sizeof(MachInst) * 8));
+ else
+ emi |= (static_cast<ExtMachInst>(bits(inst, 12, 5))
+ << (sizeof(MachInst) * 8));
+ return emi;
}
inline bool isCallerSaveIntegerRegister(unsigned int reg) {
diff --git a/src/cpu/checker/cpu_impl.hh b/src/cpu/checker/cpu_impl.hh
index ba34c5cfc..36c7349e6 100644
--- a/src/cpu/checker/cpu_impl.hh
+++ b/src/cpu/checker/cpu_impl.hh
@@ -200,7 +200,7 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
validateInst(inst);
curStaticInst = StaticInst::decode(makeExtMI(machInst,
- thread->readPC()));
+ thread->getTC()));
#if FULL_SYSTEM
thread->setInst(machInst);
diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc
index 8b1e60aea..9d85311bb 100644
--- a/src/cpu/exetrace.cc
+++ b/src/cpu/exetrace.cc
@@ -60,61 +60,66 @@ Trace::InstRecord::dump(ostream &outs)
if (flags[PRINT_REG_DELTA])
{
#if THE_ISA == SPARC_ISA
- static uint64_t regs[32] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0};
- static uint64_t ccr = 0;
- static uint64_t y = 0;
- static uint64_t floats[32];
- uint64_t newVal;
- static const char * prefixes[4] = {"G", "O", "L", "I"};
-
- char buf[256];
- sprintf(buf, "PC = 0x%016llx", thread->readNextPC());
- outs << buf;
- sprintf(buf, " NPC = 0x%016llx", thread->readNextNPC());
- outs << buf;
- newVal = thread->readMiscReg(SparcISA::MISCREG_CCR);
- if(newVal != ccr)
+ //Don't print what happens for each micro-op, just print out
+ //once at the last op, and for regular instructions.
+ if(!staticInst->isMicroOp() || staticInst->isLastMicroOp())
{
- sprintf(buf, " CCR = 0x%016llx", newVal);
+ static uint64_t regs[32] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
+ static uint64_t ccr = 0;
+ static uint64_t y = 0;
+ static uint64_t floats[32];
+ uint64_t newVal;
+ static const char * prefixes[4] = {"G", "O", "L", "I"};
+
+ char buf[256];
+ sprintf(buf, "PC = 0x%016llx", thread->readNextPC());
outs << buf;
- ccr = newVal;
- }
- newVal = thread->readMiscReg(SparcISA::MISCREG_Y);
- if(newVal != y)
- {
- sprintf(buf, " Y = 0x%016llx", newVal);
+ sprintf(buf, " NPC = 0x%016llx", thread->readNextNPC());
outs << buf;
- y = newVal;
- }
- for(int y = 0; y < 4; y++)
- {
- for(int x = 0; x < 8; x++)
+ newVal = thread->readMiscReg(SparcISA::MISCREG_CCR);
+ if(newVal != ccr)
+ {
+ sprintf(buf, " CCR = 0x%016llx", newVal);
+ outs << buf;
+ ccr = newVal;
+ }
+ newVal = thread->readMiscReg(SparcISA::MISCREG_Y);
+ if(newVal != y)
+ {
+ sprintf(buf, " Y = 0x%016llx", newVal);
+ outs << buf;
+ y = newVal;
+ }
+ for(int y = 0; y < 4; y++)
{
- int index = x + 8 * y;
- newVal = thread->readIntReg(index);
- if(regs[index] != newVal)
+ for(int x = 0; x < 8; x++)
{
- sprintf(buf, " %s%d = 0x%016llx", prefixes[y], x, newVal);
- outs << buf;
- regs[index] = newVal;
+ int index = x + 8 * y;
+ newVal = thread->readIntReg(index);
+ if(regs[index] != newVal)
+ {
+ sprintf(buf, " %s%d = 0x%016llx", prefixes[y], x, newVal);
+ outs << buf;
+ regs[index] = newVal;
+ }
}
}
- }
- for(int y = 0; y < 32; y++)
- {
- newVal = thread->readFloatRegBits(2 * y, 64);
- if(floats[y] != newVal)
+ for(int y = 0; y < 32; y++)
{
- sprintf(buf, " F%d = 0x%016llx", y, newVal);
- outs << buf;
- floats[y] = newVal;
+ newVal = thread->readFloatRegBits(2 * y, 64);
+ if(floats[y] != newVal)
+ {
+ sprintf(buf, " F%d = 0x%016llx", 2 * y, newVal);
+ outs << buf;
+ floats[y] = newVal;
+ }
}
+ outs << endl;
}
- outs << endl;
#endif
}
else if (flags[INTEL_FORMAT]) {
diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh
index da75bfecf..e7bf83b20 100644
--- a/src/cpu/o3/fetch_impl.hh
+++ b/src/cpu/o3/fetch_impl.hh
@@ -1118,7 +1118,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
inst = TheISA::gtoh(*reinterpret_cast<TheISA::MachInst *>
(&cacheData[tid][offset]));
- ext_inst = TheISA::makeExtMI(inst, fetch_PC);
+ ext_inst = TheISA::makeExtMI(inst, cpu->tcBase(tid));
// Create a new DynInst from the instruction fetched.
DynInstPtr instruction = new DynInst(ext_inst, fetch_PC,
diff --git a/src/cpu/ozone/front_end_impl.hh b/src/cpu/ozone/front_end_impl.hh
index eed6de6dd..36e87ec9c 100644
--- a/src/cpu/ozone/front_end_impl.hh
+++ b/src/cpu/ozone/front_end_impl.hh
@@ -883,7 +883,7 @@ FrontEnd<Impl>::getInstFromCacheline()
// Get the instruction from the array of the cache line.
inst = htog(*reinterpret_cast<MachInst *>(&cacheData[offset]));
- ExtMachInst decode_inst = TheISA::makeExtMI(inst, PC);
+ ExtMachInst decode_inst = TheISA::makeExtMI(inst, tc);
// Create a new DynInst from the instruction fetched.
DynInstPtr instruction = new DynInst(decode_inst, PC, PC+sizeof(MachInst),
diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc
index a79d3c542..cbb3980cb 100644
--- a/src/cpu/simple/base.cc
+++ b/src/cpu/simple/base.cc
@@ -396,7 +396,20 @@ BaseSimpleCPU::preExecute()
// decode the instruction
inst = gtoh(inst);
- curStaticInst = StaticInst::decode(makeExtMI(inst, thread->readPC()));
+ //If we're not in the middle of a macro instruction
+ if (!curMacroStaticInst) {
+ StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->getTC()));
+ if (instPtr->isMacroOp()) {
+ curMacroStaticInst = instPtr;
+ curStaticInst = curMacroStaticInst->fetchMicroOp(0);
+ } else {
+ curStaticInst = instPtr;
+ }
+ } else {
+ //Read the next micro op from the macro op
+ curStaticInst = curMacroStaticInst->fetchMicroOp(thread->readMicroPC());
+ }
+
traceData = Trace::getInstRecord(curTick, tc, curStaticInst,
thread->readPC());
@@ -446,18 +459,35 @@ BaseSimpleCPU::advancePC(Fault fault)
{
if (fault != NoFault) {
fault->invoke(tc);
- }
- else {
- // go to the next instruction
- thread->setPC(thread->readNextPC());
+ } else {
+ //If we're at the last micro op for this instruction
+ if (curStaticInst->isLastMicroOp()) {
+ //We should be working with a macro op
+ assert(curMacroStaticInst);
+ //Close out this macro op, and clean up the
+ //microcode state
+ curMacroStaticInst = StaticInst::nullStaticInstPtr;
+ thread->setMicroPC(0);
+ thread->setNextMicroPC(1);
+ }
+ //If we're still in a macro op
+ if (curMacroStaticInst) {
+ //Advance the micro pc
+ thread->setMicroPC(thread->readNextMicroPC());
+ //Advance the "next" micro pc. Note that there are no delay
+ //slots, and micro ops are "word" addressed.
+ thread->setNextMicroPC(thread->readNextMicroPC() + 1);
+ } else {
+ // go to the next instruction
+ thread->setPC(thread->readNextPC());
#if ISA_HAS_DELAY_SLOT
- thread->setNextPC(thread->readNextNPC());
- thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
- assert(thread->readNextPC() != thread->readNextNPC());
+ thread->setNextPC(thread->readNextNPC());
+ thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
+ assert(thread->readNextPC() != thread->readNextNPC());
#else
- thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
+ thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
#endif
-
+ }
}
#if FULL_SYSTEM
diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh
index 57cfa3c2c..af6b6f835 100644
--- a/src/cpu/simple/base.hh
+++ b/src/cpu/simple/base.hh
@@ -128,6 +128,7 @@ class BaseSimpleCPU : public BaseCPU
TheISA::IntReg dataReg;
StaticInstPtr curStaticInst;
+ StaticInstPtr curMacroStaticInst;
void checkForInterrupts();
Fault setupFetchRequest(Request *req);
diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh
index 6fa6500bd..fe22e6c43 100644
--- a/src/cpu/simple_thread.hh
+++ b/src/cpu/simple_thread.hh
@@ -377,6 +377,16 @@ class SimpleThread : public ThreadState
regs.setPC(val);
}
+ uint64_t readMicroPC()
+ {
+ return microPC;
+ }
+
+ void setMicroPC(uint64_t val)
+ {
+ microPC = val;
+ }
+
uint64_t readNextPC()
{
return regs.readNextPC();
@@ -387,6 +397,16 @@ class SimpleThread : public ThreadState
regs.setNextPC(val);
}
+ uint64_t readNextMicroPC()
+ {
+ return nextMicroPC;
+ }
+
+ void setNextMicroPC(uint64_t val)
+ {
+ nextMicroPC = val;
+ }
+
uint64_t readNextNPC()
{
return regs.readNextNPC();
diff --git a/src/cpu/static_inst.cc b/src/cpu/static_inst.cc
index c311d2282..cb4a7cdf7 100644
--- a/src/cpu/static_inst.cc
+++ b/src/cpu/static_inst.cc
@@ -75,3 +75,10 @@ StaticInst::hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const
return false;
}
+StaticInstPtr
+StaticInst::fetchMicroOp(MicroPC micropc)
+{
+ panic("StaticInst::fetchMicroOp() called on instruction "
+ "that is not microcoded.");
+}
+
diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh
index 578d14191..523cfae40 100644
--- a/src/cpu/static_inst.hh
+++ b/src/cpu/static_inst.hh
@@ -67,6 +67,8 @@ namespace Trace {
class InstRecord;
}
+typedef uint32_t MicroPC;
+
/**
* Base, ISA-independent static instruction class.
*
@@ -139,6 +141,14 @@ class StaticInstBase : public RefCounted
IsIprAccess, ///< Accesses IPRs
IsUnverifiable, ///< Can't be verified by a checker
+ //Flags for microcode
+ IsMacroOp, ///< Is a macroop containing microops
+ IsMicroOp, ///< Is a microop
+ IsDelayedCommit, ///< This microop doesn't commit right away
+ IsLastMicroOp, ///< This microop ends a microop sequence
+ //This flag doesn't do anything yet
+ IsMicroBranch, ///< This microop branches within the microcode for a macroop
+
NumFlags
};
@@ -230,6 +240,12 @@ class StaticInstBase : public RefCounted
bool isQuiesce() const { return flags[IsQuiesce]; }
bool isIprAccess() const { return flags[IsIprAccess]; }
bool isUnverifiable() const { return flags[IsUnverifiable]; }
+ bool isMacroOp() const { return flags[IsMacroOp]; }
+ bool isMicroOp() const { return flags[IsMicroOp]; }
+ bool isDelayedCommit() const { return flags[IsDelayedCommit]; }
+ bool isLastMicroOp() const { return flags[IsLastMicroOp]; }
+ //This flag doesn't do anything yet
+ bool isMicroBranch() const { return flags[IsMicroBranch]; }
//@}
/// Operation class. Used to select appropriate function unit in issue.
@@ -347,6 +363,12 @@ class StaticInst : public StaticInstBase
#include "cpu/static_inst_exec_sigs.hh"
/**
+ * Return the microop that goes with a particular micropc. This should
+ * only be defined/used in macroops which will contain microops
+ */
+ virtual StaticInstPtr fetchMicroOp(MicroPC micropc);
+
+ /**
* Return the target address for a PC-relative branch.
* Invalid if not a PC-relative branch (i.e. isDirectCtrl()
* should be true).
diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc
index 6a96560f1..c644ae8d7 100644
--- a/src/cpu/thread_state.cc
+++ b/src/cpu/thread_state.cc
@@ -42,13 +42,13 @@
ThreadState::ThreadState(int _cpuId, int _tid)
: cpuId(_cpuId), tid(_tid), lastActivate(0), lastSuspend(0),
profile(NULL), profileNode(NULL), profilePC(0), quiesceEvent(NULL),
- funcExeInst(0), storeCondFailures(0)
+ microPC(0), nextMicroPC(1), funcExeInst(0), storeCondFailures(0)
#else
ThreadState::ThreadState(int _cpuId, int _tid, Process *_process,
short _asid, MemObject *mem)
: cpuId(_cpuId), tid(_tid), lastActivate(0), lastSuspend(0),
process(_process), asid(_asid),
- funcExeInst(0), storeCondFailures(0)
+ microPC(0), nextMicroPC(1), funcExeInst(0), storeCondFailures(0)
#endif
{
numInst = 0;
diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh
index 14e033b7f..60353760c 100644
--- a/src/cpu/thread_state.hh
+++ b/src/cpu/thread_state.hh
@@ -200,6 +200,16 @@ struct ThreadState {
*/
TheISA::MachInst inst;
+ /** The current microcode pc for the currently executing macro
+ * operation.
+ */
+ MicroPC microPC;
+
+ /** The next microcode pc for the currently executing macro
+ * operation.
+ */
+ MicroPC nextMicroPC;
+
public:
/**
* Temporary storage to pass the source address from copy_load to
diff --git a/src/kern/linux/linux.hh b/src/kern/linux/linux.hh
index 3a2677642..6e0b37d91 100644
--- a/src/kern/linux/linux.hh
+++ b/src/kern/linux/linux.hh
@@ -54,11 +54,11 @@ class Linux : public OperatingSystem
//@{
/// Basic Linux types.
-/* typedef uint64_t size_t;
+ typedef uint64_t size_t;
typedef uint64_t off_t;
typedef int64_t time_t;
typedef uint32_t uid_t;
- typedef uint32_t gid_t;*/
+ typedef uint32_t gid_t;
//@}
/// Stat buffer. Note that we can't call it 'stat' since that
diff --git a/src/kern/solaris/solaris.hh b/src/kern/solaris/solaris.hh
index a5ca41cdd..ed574fdbf 100644
--- a/src/kern/solaris/solaris.hh
+++ b/src/kern/solaris/solaris.hh
@@ -56,7 +56,7 @@ class Solaris : public OperatingSystem
//@{
/// Basic Solaris types.
-/* typedef uint64_t size_t;
+ typedef uint64_t size_t;
typedef uint64_t off_t;
typedef int64_t time_t;
typedef int32_t uid_t;
@@ -65,7 +65,7 @@ class Solaris : public OperatingSystem
typedef uint64_t ino_t;
typedef uint64_t dev_t;
typedef uint32_t mode_t;
- typedef uint32_t nlink_t;*/
+ typedef uint32_t nlink_t;
//@}
struct tgt_timespec {
diff --git a/src/kern/tru64/tru64.hh b/src/kern/tru64/tru64.hh
index 18671c364..2ee4014db 100644
--- a/src/kern/tru64/tru64.hh
+++ b/src/kern/tru64/tru64.hh
@@ -393,34 +393,6 @@ class Tru64 : public OperatingSystem
uint64_t pad2[2]; //!< pad2
};
- /*/// Helper function to convert a host stat buffer to a target stat
- /// buffer. Also copies the target buffer out to the simulated
- /// memory space. Used by stat(), fstat(), and lstat().
- template <class T>
- static void
- copyOutStatBuf(TranslatingPort *mem, Addr addr, global_stat *host)
- {
- using namespace TheISA;
-
- TypedBufferArg<T> tgt(addr);
-
- tgt->st_dev = htog(host->st_dev);
- tgt->st_ino = htog(host->st_ino);
- tgt->st_mode = htog(host->st_mode);
- tgt->st_nlink = htog(host->st_nlink);
- tgt->st_uid = htog(host->st_uid);
- tgt->st_gid = htog(host->st_gid);
- tgt->st_rdev = htog(host->st_rdev);
- tgt->st_size = htog(host->st_size);
- tgt->st_atimeX = htog(host->st_atime);
- tgt->st_mtimeX = htog(host->st_mtime);
- tgt->st_ctimeX = htog(host->st_ctime);
- tgt->st_blksize = htog(host->st_blksize);
- tgt->st_blocks = htog(host->st_blocks);
-
- tgt.copyOut(mem);
- }*/
-
/// Helper function to convert a host statfs buffer to a target statfs
/// buffer. Also copies the target buffer out to the simulated
/// memory space. Used by statfs() and fstatfs().
@@ -450,34 +422,6 @@ class Tru64 : public OperatingSystem
tgt.copyOut(mem);
}
-/* /// Helper function to convert a host stat buffer to an old pre-F64
- /// (4.x) target stat buffer. Also copies the target buffer out to
- /// the simulated memory space. Used by pre_F64_stat(),
- /// pre_F64_fstat(), and pre_F64_lstat().
- static void
- copyOutPreF64StatBuf(TranslatingPort *mem, Addr addr, struct stat *host)
- {
- using namespace TheISA;
-
- TypedBufferArg<Tru64::pre_F64_stat> tgt(addr);
-
- tgt->st_dev = htog(host->st_dev);
- tgt->st_ino = htog(host->st_ino);
- tgt->st_mode = htog(host->st_mode);
- tgt->st_nlink = htog(host->st_nlink);
- tgt->st_uid = htog(host->st_uid);
- tgt->st_gid = htog(host->st_gid);
- tgt->st_rdev = htog(host->st_rdev);
- tgt->st_size = htog(host->st_size);
- tgt->st_atimeX = htog(host->st_atime);
- tgt->st_mtimeX = htog(host->st_mtime);
- tgt->st_ctimeX = htog(host->st_ctime);
- tgt->st_blksize = htog(host->st_blksize);
- tgt->st_blocks = htog(host->st_blocks);
-
- tgt.copyOut(mem);
- }*/
-
/// The target system's hostname.
static const char *hostname;
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
index edd4e331d..e79712a19 100644
--- a/src/sim/syscall_emul.hh
+++ b/src/sim/syscall_emul.hh
@@ -356,6 +356,14 @@ convertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false)
tgt->st_dev = htog(tgt->st_dev);
tgt->st_ino = host->st_ino;
tgt->st_ino = htog(tgt->st_ino);
+ tgt->st_mode = host->st_mode;
+ tgt->st_mode = htog(tgt->st_mode);
+ tgt->st_nlink = host->st_nlink;
+ tgt->st_nlink = htog(tgt->st_nlink);
+ tgt->st_uid = host->st_uid;
+ tgt->st_uid = htog(tgt->st_uid);
+ tgt->st_gid = host->st_gid;
+ tgt->st_gid = htog(tgt->st_gid);
if (fakeTTY)
tgt->st_rdev = 0x880d;
else
diff --git a/util/statetrace/arch/tracechild_sparc.cc b/util/statetrace/arch/tracechild_sparc.cc
index 378de0865..bad81b647 100644
--- a/util/statetrace/arch/tracechild_sparc.cc
+++ b/util/statetrace/arch/tracechild_sparc.cc
@@ -47,10 +47,10 @@ string SparcTraceChild::regNames[numregs] = {
//Input registers
"i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7",
//Floating point
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
- "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+ "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
+ "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",
+ "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
+ "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
//Miscelaneous
"fsr", "fprs", "pc", "npc", "y", "cwp", "pstate", "asi", "ccr"};
@@ -98,37 +98,37 @@ int64_t getRegs(regs & myregs, fpu & myfpu,
case SparcTraceChild::I7: return inputs[7];
//Floating point
case SparcTraceChild::F0: return myfpu.f_fpstatus.fpu_fr[0];
- case SparcTraceChild::F1: return myfpu.f_fpstatus.fpu_fr[1];
- case SparcTraceChild::F2: return myfpu.f_fpstatus.fpu_fr[2];
- case SparcTraceChild::F3: return myfpu.f_fpstatus.fpu_fr[3];
- case SparcTraceChild::F4: return myfpu.f_fpstatus.fpu_fr[4];
- case SparcTraceChild::F5: return myfpu.f_fpstatus.fpu_fr[5];
- case SparcTraceChild::F6: return myfpu.f_fpstatus.fpu_fr[6];
- case SparcTraceChild::F7: return myfpu.f_fpstatus.fpu_fr[7];
- case SparcTraceChild::F8: return myfpu.f_fpstatus.fpu_fr[8];
- case SparcTraceChild::F9: return myfpu.f_fpstatus.fpu_fr[9];
- case SparcTraceChild::F10: return myfpu.f_fpstatus.fpu_fr[10];
- case SparcTraceChild::F11: return myfpu.f_fpstatus.fpu_fr[11];
- case SparcTraceChild::F12: return myfpu.f_fpstatus.fpu_fr[12];
- case SparcTraceChild::F13: return myfpu.f_fpstatus.fpu_fr[13];
- case SparcTraceChild::F14: return myfpu.f_fpstatus.fpu_fr[14];
- case SparcTraceChild::F15: return myfpu.f_fpstatus.fpu_fr[15];
- case SparcTraceChild::F16: return myfpu.f_fpstatus.fpu_fr[16];
- case SparcTraceChild::F17: return myfpu.f_fpstatus.fpu_fr[17];
- case SparcTraceChild::F18: return myfpu.f_fpstatus.fpu_fr[18];
- case SparcTraceChild::F19: return myfpu.f_fpstatus.fpu_fr[19];
- case SparcTraceChild::F20: return myfpu.f_fpstatus.fpu_fr[20];
- case SparcTraceChild::F21: return myfpu.f_fpstatus.fpu_fr[21];
- case SparcTraceChild::F22: return myfpu.f_fpstatus.fpu_fr[22];
- case SparcTraceChild::F23: return myfpu.f_fpstatus.fpu_fr[23];
- case SparcTraceChild::F24: return myfpu.f_fpstatus.fpu_fr[24];
- case SparcTraceChild::F25: return myfpu.f_fpstatus.fpu_fr[25];
- case SparcTraceChild::F26: return myfpu.f_fpstatus.fpu_fr[26];
- case SparcTraceChild::F27: return myfpu.f_fpstatus.fpu_fr[27];
- case SparcTraceChild::F28: return myfpu.f_fpstatus.fpu_fr[28];
- case SparcTraceChild::F29: return myfpu.f_fpstatus.fpu_fr[29];
- case SparcTraceChild::F30: return myfpu.f_fpstatus.fpu_fr[30];
- case SparcTraceChild::F31: return myfpu.f_fpstatus.fpu_fr[31];
+ case SparcTraceChild::F2: return myfpu.f_fpstatus.fpu_fr[1];
+ case SparcTraceChild::F4: return myfpu.f_fpstatus.fpu_fr[2];
+ case SparcTraceChild::F6: return myfpu.f_fpstatus.fpu_fr[3];
+ case SparcTraceChild::F8: return myfpu.f_fpstatus.fpu_fr[4];
+ case SparcTraceChild::F10: return myfpu.f_fpstatus.fpu_fr[5];
+ case SparcTraceChild::F12: return myfpu.f_fpstatus.fpu_fr[6];
+ case SparcTraceChild::F14: return myfpu.f_fpstatus.fpu_fr[7];
+ case SparcTraceChild::F16: return myfpu.f_fpstatus.fpu_fr[8];
+ case SparcTraceChild::F18: return myfpu.f_fpstatus.fpu_fr[9];
+ case SparcTraceChild::F20: return myfpu.f_fpstatus.fpu_fr[10];
+ case SparcTraceChild::F22: return myfpu.f_fpstatus.fpu_fr[11];
+ case SparcTraceChild::F24: return myfpu.f_fpstatus.fpu_fr[12];
+ case SparcTraceChild::F26: return myfpu.f_fpstatus.fpu_fr[13];
+ case SparcTraceChild::F28: return myfpu.f_fpstatus.fpu_fr[14];
+ case SparcTraceChild::F30: return myfpu.f_fpstatus.fpu_fr[15];
+ case SparcTraceChild::F32: return myfpu.f_fpstatus.fpu_fr[16];
+ case SparcTraceChild::F34: return myfpu.f_fpstatus.fpu_fr[17];
+ case SparcTraceChild::F36: return myfpu.f_fpstatus.fpu_fr[18];
+ case SparcTraceChild::F38: return myfpu.f_fpstatus.fpu_fr[19];
+ case SparcTraceChild::F40: return myfpu.f_fpstatus.fpu_fr[20];
+ case SparcTraceChild::F42: return myfpu.f_fpstatus.fpu_fr[21];
+ case SparcTraceChild::F44: return myfpu.f_fpstatus.fpu_fr[22];
+ case SparcTraceChild::F46: return myfpu.f_fpstatus.fpu_fr[23];
+ case SparcTraceChild::F48: return myfpu.f_fpstatus.fpu_fr[24];
+ case SparcTraceChild::F50: return myfpu.f_fpstatus.fpu_fr[25];
+ case SparcTraceChild::F52: return myfpu.f_fpstatus.fpu_fr[26];
+ case SparcTraceChild::F54: return myfpu.f_fpstatus.fpu_fr[27];
+ case SparcTraceChild::F56: return myfpu.f_fpstatus.fpu_fr[28];
+ case SparcTraceChild::F58: return myfpu.f_fpstatus.fpu_fr[29];
+ case SparcTraceChild::F60: return myfpu.f_fpstatus.fpu_fr[30];
+ case SparcTraceChild::F62: return myfpu.f_fpstatus.fpu_fr[31];
//Miscelaneous
case SparcTraceChild::FSR: return myfpu.f_fpstatus.Fpu_fsr;
case SparcTraceChild::FPRS: return myregs.r_fprs;
@@ -188,46 +188,110 @@ bool SparcTraceChild::step()
//being breakpointed should be word (64bit) aligned, and that both the
//next instruction and the instruction after that need to be breakpointed
//so that annulled branches will still stop as well.
+
+ /*
+ * Useful constants
+ */
const static uint64_t breakInst = 0x91d02001;
const static uint64_t breakWord = breakInst | (breakInst << 32);
- const static uint64_t lowMask = (uint64_t)(0xFFFFFFFF);
+ const static uint64_t lowMask = 0xFFFFFFFFULL;
const static uint64_t highMask = lowMask << 32;
+
+ /*
+ * storage for the original contents of the child process's memory
+ */
uint64_t originalInst, originalAnnulInst;
+
+ /*
+ * Get information about where the process is and is headed next.
+ */
+ uint64_t currentPC = getRegVal(PC);
+ bool unalignedPC = currentPC & 7;
+ uint64_t alignedPC = currentPC & (~7);
uint64_t nextPC = getRegVal(NPC);
- bool unaligned = nextPC & 7;
- uint64_t alignedPC = nextPC & (~7);
- originalInst = ptrace(PTRACE_PEEKTEXT, pid, alignedPC, 0);
- if(unaligned)
+ bool unalignedNPC = nextPC & 7;
+ uint64_t alignedNPC = nextPC & (~7);
+
+ /*
+ * Store the original contents of the child process's memory
+ */
+ originalInst = ptrace(PTRACE_PEEKTEXT, pid, alignedNPC, 0);
+ //Save a ptrace call if we can
+ if(unalignedNPC)
{
- originalAnnulInst = ptrace(PTRACE_PEEKTEXT, pid, alignedPC+8, 0);
+ originalAnnulInst = ptrace(PTRACE_PEEKTEXT, pid, alignedNPC+8, 0);
}
- uint64_t newInst;
- if(unaligned)
+
+ /*
+ * Prepare breakpointed copies of child processes memory
+ */
+ uint64_t newInst, newAnnulInst;
+ //If the current instruction is in the same word as the npc
+ if(alignedPC == alignedNPC)
{
- newInst = (originalInst & highMask) | (breakInst << 0);
- if(ptrace(PTRACE_POKETEXT, pid, alignedPC, newInst) != 0)
- cerr << "Poke failed" << endl;
- newInst = (originalAnnulInst & lowMask) | (breakInst << 32);
- if(ptrace(PTRACE_POKETEXT, pid, alignedPC+8, newInst) != 0)
- cerr << "Poke failed" << endl;
+ //Make sure we only replace the other part
+ if(unalignedPC)
+ newInst = (originalInst & lowMask) | (breakWord & highMask);
+ else
+ newInst = (originalInst & highMask) | (breakWord & lowMask);
+ }
+ else
+ {
+ //otherwise replace the whole thing
+ newInst = breakWord;
+ }
+ //If the current instruction is in the same word as the word after
+ //the npc
+ if(alignedPC == alignedNPC+8)
+ {
+ //Make sure we only replace the other part
+ if(unalignedPC)
+ newAnnulInst = (originalAnnulInst & lowMask) | (breakWord & highMask);
+ else
+ newAnnulInst = (originalAnnulInst & highMask) | (breakWord & lowMask);
}
else
{
- if(ptrace(PTRACE_POKETEXT, pid, alignedPC, breakWord) != 0)
+ //otherwise replace the whole thing
+ newAnnulInst = breakWord;
+ }
+
+ /*
+ * Stuff the breakpoint instructions into the child's address space.
+ */
+ //Replace the word at npc
+ if(ptrace(PTRACE_POKETEXT, pid, alignedNPC, newInst) != 0)
+ cerr << "Poke failed" << endl;
+ //Replace the next word, if necessary
+ if(unalignedNPC)
+ {
+ if(ptrace(PTRACE_POKETEXT, pid, alignedNPC+8, newAnnulInst) != 0)
cerr << "Poke failed" << endl;
}
+
+ /*
+ * Restart the child process
+ */
//Note that the "addr" parameter is supposed to be ignored, but in at
//least one version of the kernel, it must be 1 or it will set what
//pc to continue from
- if(ptrace(PTRACE_CONT, pid, /*nextPC - 4*/ 1, 0) != 0)
+ if(ptrace(PTRACE_CONT, pid, 1, 0) != 0)
cerr << "Cont failed" << endl;
doWait();
+
+ /*
+ * Update our record of the child's state
+ */
update(pid);
- if(ptrace(PTRACE_POKETEXT, pid, alignedPC, originalInst) != 0)
+
+ /*
+ * Put back the original contents of the childs address space
+ */
+ if(ptrace(PTRACE_POKETEXT, pid, alignedNPC, originalInst) != 0)
cerr << "Repoke failed" << endl;
- if(unaligned)
+ if(unalignedNPC)
{
- if(ptrace(PTRACE_POKETEXT, pid, alignedPC+8, originalAnnulInst) != 0)
+ if(ptrace(PTRACE_POKETEXT, pid, alignedNPC+8, originalAnnulInst) != 0)
cerr << "Repoke failed" << endl;
}
return true;
diff --git a/util/statetrace/arch/tracechild_sparc.hh b/util/statetrace/arch/tracechild_sparc.hh
index d177d5941..80770211a 100644
--- a/util/statetrace/arch/tracechild_sparc.hh
+++ b/util/statetrace/arch/tracechild_sparc.hh
@@ -57,10 +57,10 @@ public:
//Input registers
I0, I1, I2, I3, I4, I5, I6, I7,
//Floating point
- F0, F1, F2, F3, F4, F5, F6, F7,
- F8, F9, F10, F11, F12, F13, F14, F15,
- F16, F17, F18, F19, F20, F21, F22, F23,
- F24, F25, F26, F27, F28, F29, F30, F31,
+ F0, F2, F4, F6, F8, F10, F12, F14,
+ F16, F18, F20, F22, F24, F26, F28, F30,
+ F32, F34, F36, F38, F40, F42, F44, F46,
+ F48, F50, F52, F54, F56, F58, F60, F62,
//Miscelaneous
FSR, FPRS, PC, NPC, Y, CWP, PSTATE, ASI, CCR,
numregs