#include <fenv.h>
#endif
-#include "cpu/base_cpu.hh"
-#include "cpu/exetrace.hh"
-#include "sim/sim_exit.hh"
-
#ifdef FULL_SYSTEM
-#include "arch/alpha/ev5.hh"
#include "arch/alpha/pseudo_inst.hh"
#endif
+#include "cpu/base_cpu.hh"
+#include "cpu/exetrace.hh"
+#include "sim/sim_exit.hh"
}};
////////////////////////////////////////////////////////////////////
/// Print a register name for disassembly given the unique
/// dependence tag number (FP or int).
- void printReg(std::ostream &os, int reg);
+ void printReg(std::ostream &os, int reg) const;
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
output decoder {{
void
- AlphaStaticInst::printReg(std::ostream &os, int reg)
+ AlphaStaticInst::printReg(std::ostream &os, int reg) const
{
if (reg < FP_Base_DepTag) {
ccprintf(os, "r%d", reg);
}
std::string
- AlphaStaticInst::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ AlphaStaticInst::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
{
std::stringstream ss;
// Declarations for execute() methods.
def template BasicExecDeclare {{
- Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *);
+ Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const;
}};
// Basic instruction class declaration template.
// Basic instruction class execute method template.
def template BasicExecute {{
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData)
+ Trace::InstRecord *traceData) const
{
Fault fault = No_Fault;
~Nop() { }
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
%(BasicExecDeclare)s
};
}};
output decoder {{
- std::string Nop::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ std::string Nop::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
{
#ifdef SS_COMPATIBLE_DISASSEMBLY
return originalDisassembly;
output exec {{
Fault
- Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *)
+ Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *) const
{
return No_Fault;
}
{
}
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
output decoder {{
std::string
- IntegerImm::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ IntegerImm::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
std::stringstream ss;
inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
{
Fault fault = No_Fault; // dummy... this ipr access should not fault
- if (!ICSR_FPE(xc->readIpr(AlphaISA::IPR_ICSR, fault))) {
+ if (!EV5::ICSR_FPE(xc->readIpr(AlphaISA::IPR_ICSR, fault))) {
fault = Fen_Fault;
}
return fault;
}
#if defined(linux)
- int getC99RoundingMode(uint64_t fpcr_val);
+ int getC99RoundingMode(uint64_t fpcr_val) const;
#endif
// This differs from the AlphaStaticInst version only in
// printing suffixes for non-default rounding & trapping modes.
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
output decoder {{
#if defined(linux)
int
- AlphaFP::getC99RoundingMode(uint64_t fpcr_val)
+ AlphaFP::getC99RoundingMode(uint64_t fpcr_val) const
{
if (roundingMode == Dynamic) {
return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
#endif
std::string
- AlphaFP::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ AlphaFP::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
std::string mnem_str(mnemonic);
{
}
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
public:
protected:
/// Constructor
MemoryNoDisp(const char *mnem, MachInst _machInst, OpClass __opClass,
- StaticInstPtr<AlphaISA> _eaCompPtr,
- StaticInstPtr<AlphaISA> _memAccPtr)
+ StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
: Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
{
}
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
-
-
- /**
- * Base class for "fake" effective-address computation
- * instructions returnded by eaCompInst().
- */
- class EACompBase : public AlphaStaticInst
- {
- public:
- /// Constructor
- EACompBase(MachInst machInst)
- : AlphaStaticInst("(eacomp)", machInst, IntALU)
- {
- }
-
- %(BasicExecDeclare)s
- };
-
- /**
- * Base class for "fake" memory-access instructions returnded by
- * memAccInst().
- */
- class MemAccBase : public AlphaStaticInst
- {
- public:
- /// Constructor
- MemAccBase(MachInst machInst, OpClass __opClass)
- : AlphaStaticInst("(memacc)", machInst, __opClass)
- {
- }
-
- %(BasicExecDeclare)s
- };
-
}};
output decoder {{
std::string
- Memory::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB);
}
std::string
- MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
return csprintf("%-10s (r%d)", mnemonic, RB);
}
}};
-output exec {{
- Fault
- EACompBase::execute(%(CPU_exec_context)s *, Trace::InstRecord *)
- {
- panic("attempt to execute eacomp");
- }
-
- Fault
- MemAccBase::execute(%(CPU_exec_context)s *, Trace::InstRecord *)
- {
- panic("attempt to execute memacc");
- }
-}};
-
-
def format LoadAddress(code) {{
iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code))
header_output = BasicDeclare.subst(iop)
/**
* "Fake" effective address computation class for "%(mnemonic)s".
*/
- class EAComp : public EACompBase
+ class EAComp : public %(base_class)s
{
public:
/// Constructor
EAComp(MachInst machInst);
+
+ %(BasicExecDeclare)s
};
/**
* "Fake" memory access instruction class for "%(mnemonic)s".
*/
- class MemAcc : public MemAccBase
+ class MemAcc : public %(base_class)s
{
public:
/// Constructor
MemAcc(MachInst machInst);
+
+ %(BasicExecDeclare)s
};
public:
}};
def template LoadStoreConstructor {{
+ /** TODO: change op_class to AddrGenOp or something (requires
+ * creating new member of OpClass enum in op_class.hh, updating
+ * config files, etc.). */
inline %(class_name)s::EAComp::EAComp(MachInst machInst)
- : EACompBase(machInst)
+ : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
{
%(ea_constructor)s;
}
inline %(class_name)s::MemAcc::MemAcc(MachInst machInst)
- : MemAccBase(machInst, %(op_class)s)
+ : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
{
%(memacc_constructor)s;
}
}
}};
+
+def template EACompExecute {{
+ Fault
+ %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = No_Fault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+
+ if (fault == No_Fault) {
+ %(op_wb)s;
+ xc->setEA(EA);
+ }
+
+ return fault;
+ }
+}};
+
+def template MemAccExecute {{
+ Fault
+ %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = No_Fault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_nonmem_rd)s;
+ EA = xc->getEA();
+
+ if (fault == No_Fault) {
+ %(op_mem_rd)s;
+ %(code)s;
+ }
+
+ if (fault == No_Fault) {
+ %(op_mem_wb)s;
+ }
+
+ if (fault == No_Fault) {
+ %(postacc_code)s;
+ }
+
+ if (fault == No_Fault) {
+ %(op_nonmem_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+
def template LoadStoreExecute {{
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData)
+ Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = No_Fault;
def template PrefetchExecute {{
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData)
+ Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = No_Fault;
# and memory access flags (handled here).
# Would be nice to autogenerate this list, but oh well.
- valid_mem_flags = ['LOCKED', 'EVICT_NEXT', 'PF_EXCLUSIVE']
- inst_flags = []
- mem_flags = []
- for f in flags:
- if f in valid_mem_flags:
- mem_flags.append(f)
- else:
- inst_flags.append(f)
+ valid_mem_flags = ['LOCKED', 'NO_FAULT', 'EVICT_NEXT', 'PF_EXCLUSIVE']
+ mem_flags = [f for f in flags if f in valid_mem_flags]
+ inst_flags = [f for f in flags if f not in valid_mem_flags]
+
+ # add hook to get effective addresses into execution trace output.
+ ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
+ # generate code block objects
ea_cblk = CodeBlock(ea_code)
memacc_cblk = CodeBlock(memacc_code)
postacc_cblk = CodeBlock(postacc_code)
+ # Some CPU models execute the memory operation as an atomic unit,
+ # while others want to separate them into an effective address
+ # computation and a memory access operation. As a result, we need
+ # to generate three StaticInst objects. Note that the latter two
+ # are nested inside the larger "atomic" one.
+
+ # generate InstObjParams for EAComp object
+ ea_iop = InstObjParams(name, Name, base_class, ea_cblk, inst_flags)
+
+ # generate InstObjParams for MemAcc object
+ memacc_iop = InstObjParams(name, Name, base_class, memacc_cblk, inst_flags)
+ # in the split execution model, the MemAcc portion is responsible
+ # for the post-access code.
+ memacc_iop.postacc_code = postacc_cblk.code
+
+ # generate InstObjParams for unified execution
cblk = CodeBlock(ea_code + memacc_code + postacc_code)
iop = InstObjParams(name, Name, base_class, cblk, inst_flags)
iop.memacc_code = memacc_cblk.code
iop.postacc_code = postacc_cblk.code
- mem_flags = string.join(mem_flags, '|')
- if mem_flags != '':
- iop.constructor += '\n\tmemAccessFlags = ' + mem_flags + ';'
+ if mem_flags:
+ s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
+ iop.constructor += s
+ memacc_iop.constructor += s
# (header_output, decoder_output, decode_block, exec_output)
return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop),
- decode_template.subst(iop), exec_template.subst(iop))
+ decode_template.subst(iop),
+ EACompExecute.subst(ea_iop)
+ + MemAccExecute.subst(memacc_iop)
+ + exec_template.subst(iop))
}};
# Declare the prefetch instruction object.
# convert flags from tuple to list to make them mutable
- pf_flags = list(pf_flags) + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'RdPort']
+ pf_flags = list(pf_flags) + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'MemReadOp', 'NO_FAULT']
(pf_header_output, pf_decoder_output, _, pf_exec_output) = \
LoadStoreBase(name, Name + 'Prefetch', ea_code, '',
{
protected:
/// Cached program counter from last disassembly
- Addr cachedPC;
+ mutable Addr cachedPC;
/// Cached symbol table pointer from last disassembly
- const SymbolTable *cachedSymtab;
+ mutable const SymbolTable *cachedSymtab;
/// Constructor
PCDependentDisassembly(const char *mnem, MachInst _machInst,
{
}
- const std::string &disassemble(Addr pc, const SymbolTable *symtab);
+ const std::string &
+ disassemble(Addr pc, const SymbolTable *symtab) const;
};
/**
Addr branchTarget(Addr branchPC) const;
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
/**
Addr branchTarget(ExecContext *xc) const;
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
}
const std::string &
- PCDependentDisassembly::disassemble(Addr pc, const SymbolTable *symtab)
+ PCDependentDisassembly::disassemble(Addr pc,
+ const SymbolTable *symtab) const
{
if (!cachedDisassembly ||
pc != cachedPC || symtab != cachedSymtab)
}
std::string
- Branch::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
std::stringstream ss;
}
std::string
- Jump::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
std::stringstream ss;
{
}
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
output decoder {{
std::string
- EmulatedCallPal::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ EmulatedCallPal::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
{
#ifdef SS_COMPATIBLE_DISASSEMBLY
return csprintf("%s %s", "call_pal", mnemonic);
}
}};
-def format EmulatedCallPal(code) {{
- iop = InstObjParams(name, Name, 'EmulatedCallPal', CodeBlock(code))
+def format EmulatedCallPal(code, *flags) {{
+ iop = InstObjParams(name, Name, 'EmulatedCallPal', CodeBlock(code), flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
decode_block = BasicDecode.subst(iop)
CallPalBase(const char *mnem, MachInst _machInst,
OpClass __opClass);
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
}
std::string
- CallPalBase::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ CallPalBase::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
return csprintf("%-10s %#x", "call_pal", palFunc);
}
}};
-def format CallPal(code) {{
- iop = InstObjParams(name, Name, 'CallPalBase', CodeBlock(code))
+def format CallPal(code, *flags) {{
+ iop = InstObjParams(name, Name, 'CallPalBase', CodeBlock(code), flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
decode_block = BasicDecode.subst(iop)
/// Constructor
HwLoadStore(const char *mnem, MachInst _machInst, OpClass __opClass,
- StaticInstPtr<AlphaISA> _eaCompPtr,
- StaticInstPtr<AlphaISA> _memAccPtr);
+ StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr);
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
}
std::string
- HwLoadStore::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ HwLoadStore::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
#ifdef SS_COMPATIBLE_DISASSEMBLY
return csprintf("%-10s r%d,%d(r%d)", mnemonic, RA, disp, RB);
{
}
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
output decoder {{
std::string
- HwMoveIPR::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ HwMoveIPR::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
if (_numSrcRegs > 0) {
// must be mtpr
}};
def format HwMoveIPR(code) {{
- iop = InstObjParams(name, Name, 'HwMoveIPR', CodeBlock(code))
+ iop = InstObjParams(name, Name, 'HwMoveIPR', CodeBlock(code),
+ ['IprAccessOp'])
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
decode_block = BasicDecode.subst(iop)
FailUnimplemented(const char *_mnemonic, MachInst _machInst)
: AlphaStaticInst(_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);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
/**
{
private:
/// Have we warned on this instruction yet?
- bool warned;
+ mutable bool warned;
public:
/// Constructor
WarnUnimplemented(const char *_mnemonic, MachInst _machInst)
: AlphaStaticInst(_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);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
output decoder {{
std::string
- FailUnimplemented::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ FailUnimplemented::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
{
return csprintf("%-10s (unimplemented)", mnemonic);
}
std::string
- WarnUnimplemented::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ WarnUnimplemented::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
{
#ifdef SS_COMPATIBLE_DISASSEMBLY
return csprintf("%-10s", mnemonic);
output exec {{
Fault
FailUnimplemented::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData)
+ Trace::InstRecord *traceData) const
{
- if (!xc->misspeculating())
- panic("attempt to execute unimplemented instruction '%s' "
- "(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE);
+ panic("attempt to execute unimplemented instruction '%s' "
+ "(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE);
return Unimplemented_Opcode_Fault;
}
Fault
WarnUnimplemented::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData)
+ Trace::InstRecord *traceData) const
{
- if (!xc->misspeculating())
- if (!warned) {
- warn("instruction '%s' unimplemented\n", mnemonic);
- warned = true;
- }
+ if (!warned) {
+ warn("instruction '%s' unimplemented\n", mnemonic);
+ warned = true;
+ }
return No_Fault;
}
}};
-def template WarnUnimplDeclare {{
- /**
- * Static instruction class for "%(mnemonic)s".
- */
- class %(class_name)s : public %(base_class)s
- {
- public:
- /// Constructor
- %(class_name)s(MachInst machInst)
- : %(base_class)s("%(mnemonic)s", machInst)
- {
- }
- };
-}};
-
-
def format FailUnimpl() {{
iop = InstObjParams(name, 'FailUnimplemented')
decode_block = BasicDecodeWithMnemonic.subst(iop)
}};
def format WarnUnimpl() {{
- iop = InstObjParams(name, Name, 'WarnUnimplemented')
- header_output = WarnUnimplDeclare.subst(iop)
- decode_block = BasicDecode.subst(iop)
+ iop = InstObjParams(name, 'WarnUnimplemented')
+ decode_block = BasicDecodeWithMnemonic.subst(iop)
}};
output header {{
Unknown(MachInst _machInst)
: AlphaStaticInst("unknown", _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);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
output decoder {{
std::string
- Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
return csprintf("%-10s (inst 0x%x, opcode 0x%x)",
"unknown", machInst, OPCODE);
output exec {{
Fault
- Unknown::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData)
+ Unknown::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
{
- if (!xc->misspeculating())
- panic("attempt to execute unknown instruction "
- "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE);
+ panic("attempt to execute unknown instruction "
+ "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE);
return Unimplemented_Opcode_Fault;
}
}};
0x2a: ldl_l({{ EA = Rb + disp; }}, {{ Ra.sl = Mem.sl; }}, LOCKED);
0x2b: ldq_l({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uq; }}, LOCKED);
0x20: copy_load({{EA = Ra;}},
- {{ fault = xc->copySrcTranslate(EA);}},
+ {{fault = xc->copySrcTranslate(EA);}},
IsMemRef, IsLoad, IsCopy);
}
0x26: sts({{ EA = Rb + disp; }}, {{ Mem.ul = t_to_s(Fa.uq); }});
0x27: stt({{ EA = Rb + disp; }}, {{ Mem.df = Fa; }});
0x24: copy_store({{EA = Rb;}},
- {{ fault = xc->copy(EA);}},
+ {{fault = xc->copy(EA);}},
IsMemRef, IsStore, IsCopy);
}
}
0x13: decode INTFUNC { // integer multiplies
- 0x00: mull({{ Rc.sl = Ra.sl * Rb_or_imm.sl; }}, IntMULT);
- 0x20: mulq({{ Rc = Ra * Rb_or_imm; }}, IntMULT);
+ 0x00: mull({{ Rc.sl = Ra.sl * Rb_or_imm.sl; }}, IntMultOp);
+ 0x20: mulq({{ Rc = Ra * Rb_or_imm; }}, IntMultOp);
0x30: umulh({{
uint64_t hi, lo;
mul128(Ra, Rb_or_imm, hi, lo);
Rc = hi;
- }}, IntMULT);
+ }}, IntMultOp);
0x40: mullv({{
// 32-bit multiply with trap on overflow
int64_t Rax = Ra.sl; // sign extended version of Ra.sl
if (sign_bits != 0 && sign_bits != mask(33))
fault = Integer_Overflow_Fault;
Rc.sl = tmp<31:0>;
- }}, IntMULT);
+ }}, IntMultOp);
0x60: mulqv({{
// 64-bit multiply with trap on overflow
uint64_t hi, lo;
(hi == mask(64) && lo<63:> == 1)))
fault = Integer_Overflow_Fault;
Rc = lo;
- }}, IntMULT);
+ }}, IntMultOp);
}
0x1c: decode INTFUNC {
0x00: decode RA { 31: sextb({{ Rc.sb = Rb_or_imm< 7:0>; }}); }
0x01: decode RA { 31: sextw({{ Rc.sw = Rb_or_imm<15:0>; }}); }
+ 0x32: ctlz({{
+ uint64_t count = 0;
+ uint64_t temp = Rb;
+ if (temp<63:32>) temp >>= 32; else count += 32;
+ if (temp<31:16>) temp >>= 16; else count += 16;
+ if (temp<15:8>) temp >>= 8; else count += 8;
+ if (temp<7:4>) temp >>= 4; else count += 4;
+ if (temp<3:2>) temp >>= 2; else count += 2;
+ if (temp<1:1>) temp >>= 1; else count += 1;
+ if ((temp<0:0>) != 0x1) count += 1;
+ Rc = count;
+ }}, IntAluOp);
+
+ 0x33: cttz({{
+ uint64_t count = 0;
+ uint64_t temp = Rb;
+ if (!(temp<31:0>)) { temp >>= 32; count += 32; }
+ if (!(temp<15:0>)) { temp >>= 16; count += 16; }
+ if (!(temp<7:0>)) { temp >>= 8; count += 8; }
+ if (!(temp<3:0>)) { temp >>= 4; count += 4; }
+ if (!(temp<1:0>)) { temp >>= 2; count += 2; }
+ if (!(temp<0:0> & ULL(0x1))) count += 1;
+ Rc = count;
+ }}, IntAluOp);
format FailUnimpl {
0x30: ctpop();
0x31: perr();
- 0x32: ctlz();
- 0x33: cttz();
0x34: unpkbw();
0x35: unpkbl();
0x36: pkwb();
format BasicOperateWithNopCheck {
0x70: decode RB {
- 31: ftoit({{ Rc = Fa.uq; }}, FloatCVT);
+ 31: ftoit({{ Rc = Fa.uq; }}, FloatCvtOp);
}
0x78: decode RB {
31: ftois({{ Rc.sl = t_to_s(Fa.uq); }},
- FloatCVT);
+ FloatCvtOp);
}
}
}
0x4: decode RB {
31: decode FP_FULLFUNC {
format BasicOperateWithNopCheck {
- 0x004: itofs({{ Fc.uq = s_to_t(Ra.ul); }}, FloatCVT);
- 0x024: itoft({{ Fc.uq = Ra.uq; }}, FloatCVT);
+ 0x004: itofs({{ Fc.uq = s_to_t(Ra.ul); }}, FloatCvtOp);
+ 0x024: itoft({{ Fc.uq = Ra.uq; }}, FloatCvtOp);
0x014: FailUnimpl::itoff(); // VAX-format conversion
}
}
if (Fb < 0.0)
fault = Arithmetic_Fault;
Fc = sqrt(Fb);
- }}, FloatSQRT);
+ }}, FloatSqrtOp);
#else
0x0b: sqrts({{
if (Fb.sf < 0.0)
fault = Arithmetic_Fault;
Fc.sf = sqrt(Fb.sf);
- }}, FloatSQRT);
+ }}, FloatSqrtOp);
#endif
0x2b: sqrtt({{
if (Fb < 0.0)
fault = Arithmetic_Fault;
Fc = sqrt(Fb);
- }}, FloatSQRT);
+ }}, FloatSqrtOp);
}
}
}
#ifdef SS_COMPATIBLE_FP
0x00: adds({{ Fc = Fa + Fb; }});
0x01: subs({{ Fc = Fa - Fb; }});
- 0x02: muls({{ Fc = Fa * Fb; }}, FloatMULT);
- 0x03: divs({{ Fc = Fa / Fb; }}, FloatDIV);
+ 0x02: muls({{ Fc = Fa * Fb; }}, FloatMultOp);
+ 0x03: divs({{ Fc = Fa / Fb; }}, FloatDivOp);
#else
0x00: adds({{ Fc.sf = Fa.sf + Fb.sf; }});
0x01: subs({{ Fc.sf = Fa.sf - Fb.sf; }});
- 0x02: muls({{ Fc.sf = Fa.sf * Fb.sf; }}, FloatMULT);
- 0x03: divs({{ Fc.sf = Fa.sf / Fb.sf; }}, FloatDIV);
+ 0x02: muls({{ Fc.sf = Fa.sf * Fb.sf; }}, FloatMultOp);
+ 0x03: divs({{ Fc.sf = Fa.sf / Fb.sf; }}, FloatDivOp);
#endif
0x20: addt({{ Fc = Fa + Fb; }});
0x21: subt({{ Fc = Fa - Fb; }});
- 0x22: mult({{ Fc = Fa * Fb; }}, FloatMULT);
- 0x23: divt({{ Fc = Fa / Fb; }}, FloatDIV);
+ 0x22: mult({{ Fc = Fa * Fb; }}, FloatMultOp);
+ 0x23: divt({{ Fc = Fa / Fb; }}, FloatDivOp);
}
}
1: decode FP_FULLFUNC {
format BasicOperateWithNopCheck {
0x0a5, 0x5a5: cmpteq({{ Fc = (Fa == Fb) ? 2.0 : 0.0; }},
- FloatCMP);
+ FloatCmpOp);
0x0a7, 0x5a7: cmptle({{ Fc = (Fa <= Fb) ? 2.0 : 0.0; }},
- FloatCMP);
+ FloatCmpOp);
0x0a6, 0x5a6: cmptlt({{ Fc = (Fa < Fb) ? 2.0 : 0.0; }},
- FloatCMP);
+ FloatCmpOp);
0x0a4, 0x5a4: cmptun({{ // unordered
Fc = (!(Fa < Fb) && !(Fa == Fb) && !(Fa > Fb)) ? 2.0 : 0.0;
- }}, FloatCMP);
+ }}, FloatCmpOp);
}
}
}
format MiscPrefetch {
- 0xf800: wh64({{ EA = Rb; }},
- {{ xc->writeHint(EA, 64); }},
- IsMemRef, IsStore, WrPort);
+ 0xf800: wh64({{ EA = Rb & ~ULL(63); }},
+ {{ xc->writeHint(EA, 64, memAccessFlags); }},
+ IsMemRef, IsDataPrefetch, IsStore, MemWriteOp,
+ NO_FAULT);
}
format BasicOperate {
0xc000: rpcc({{
#ifdef FULL_SYSTEM
- Ra = xc->readIpr(AlphaISA::IPR_CC, fault);
+ /* Rb is a fake dependency so here is a fun way to get
+ * the parser to understand that.
+ */
+ Ra = xc->readIpr(AlphaISA::IPR_CC, fault) + (Rb & 0);
+
#else
Ra = curTick;
#endif
// them the same though.
0x0000: trapb({{ }}, IsSerializing, No_OpClass);
0x0400: excb({{ }}, IsSerializing, No_OpClass);
- 0x4000: mb({{ }}, IsMemBarrier, RdPort);
- 0x4400: wmb({{ }}, IsWriteBarrier, WrPort);
+ 0x4000: mb({{ }}, IsMemBarrier, MemReadOp);
+ 0x4400: wmb({{ }}, IsWriteBarrier, MemWriteOp);
}
#ifdef FULL_SYSTEM
format BasicOperate {
0xe000: rc({{
Ra = xc->readIntrFlag();
- if (!xc->misspeculating()) {
- xc->setIntrFlag(0);
- }
- }});
+ xc->setIntrFlag(0);
+ }}, IsNonSpeculative);
0xf000: rs({{
Ra = xc->readIntrFlag();
- if (!xc->misspeculating()) {
- xc->setIntrFlag(1);
- }
- }});
+ xc->setIntrFlag(1);
+ }}, IsNonSpeculative);
}
#else
format FailUnimpl {
fault = Unimplemented_Opcode_Fault;
}
else {
- bool dopal = true;
-
- if (!xc->misspeculating()) {
- // check to see if simulator wants to do something special
- // on this PAL call (including maybe suppress it)
- dopal = xc->simPalCheck(palFunc);
+ // check to see if simulator wants to do something special
+ // on this PAL call (including maybe suppress it)
+ bool dopal = xc->simPalCheck(palFunc);
- if (dopal) {
- AlphaISA::swap_palshadow(&xc->xcBase()->regs, true);
- xc->setIpr(AlphaISA::IPR_EXC_ADDR, NPC);
- }
- }
-
- // if we're misspeculating, it's still safe (if
- // unrealistic) to set NPC, as the control-flow change
- // won't get committed.
if (dopal) {
+ AlphaISA::swap_palshadow(&xc->xcBase()->regs, true);
+ xc->setIpr(AlphaISA::IPR_EXC_ADDR, NPC);
NPC = xc->readIpr(AlphaISA::IPR_PAL_BASE, fault) + palOffset;
}
}
- }});
+ }}, IsNonSpeculative);
#else
0x00: decode PALFUNC {
format EmulatedCallPal {
0x00: halt ({{
- if (!xc->misspeculating())
- SimExit(curTick, "halt instruction encountered");
- }});
+ SimExit(curTick, "halt instruction encountered");
+ }}, IsNonSpeculative);
0x83: callsys({{
- if (!xc->misspeculating())
- xc->syscall();
- }});
+ xc->syscall();
+ }}, IsNonSpeculative);
// Read uniq reg into ABI return value register (r0)
0x9e: rduniq({{ R0 = Runiq; }});
// Write uniq reg with value from ABI arg register (r16)
// M5 special opcodes use the reserved 0x01 opcode space
0x01: decode M5FUNC {
0x00: arm({{
- if (!xc->misspeculating())
- AlphaPseudo::arm(xc->xcBase());
- }});
+ AlphaPseudo::arm(xc->xcBase());
+ }}, IsNonSpeculative);
0x01: quiesce({{
- if (!xc->misspeculating())
- AlphaPseudo::quiesce(xc->xcBase());
- }});
+ AlphaPseudo::quiesce(xc->xcBase());
+ }}, IsNonSpeculative);
0x10: ivlb({{
- if (!xc->misspeculating())
- AlphaPseudo::ivlb(xc->xcBase());
- }}, No_OpClass);
+ AlphaPseudo::ivlb(xc->xcBase());
+ }}, No_OpClass, IsNonSpeculative);
0x11: ivle({{
- if (!xc->misspeculating())
- AlphaPseudo::ivle(xc->xcBase());
- }}, No_OpClass);
+ AlphaPseudo::ivle(xc->xcBase());
+ }}, No_OpClass, IsNonSpeculative);
0x20: m5exit_old({{
- if (!xc->misspeculating())
- AlphaPseudo::m5exit_old(xc->xcBase());
- }}, No_OpClass);
+ AlphaPseudo::m5exit_old(xc->xcBase());
+ }}, No_OpClass, IsNonSpeculative);
0x21: m5exit({{
- if (!xc->misspeculating())
- AlphaPseudo::m5exit(xc->xcBase());
- }}, No_OpClass);
+ AlphaPseudo::m5exit(xc->xcBase());
+ }}, No_OpClass, IsNonSpeculative);
0x30: initparam({{ Ra = xc->xcBase()->cpu->system->init_param; }});
0x40: resetstats({{
- if (!xc->misspeculating())
- AlphaPseudo::resetstats(xc->xcBase());
- }});
+ AlphaPseudo::resetstats(xc->xcBase());
+ }}, IsNonSpeculative);
0x41: dumpstats({{
- if (!xc->misspeculating())
- AlphaPseudo::dumpstats(xc->xcBase());
- }});
+ AlphaPseudo::dumpstats(xc->xcBase());
+ }}, IsNonSpeculative);
0x42: dumpresetstats({{
- if (!xc->misspeculating())
- AlphaPseudo::dumpresetstats(xc->xcBase());
- }});
+ AlphaPseudo::dumpresetstats(xc->xcBase());
+ }}, IsNonSpeculative);
0x43: m5checkpoint({{
- if (!xc->misspeculating())
- AlphaPseudo::m5checkpoint(xc->xcBase());
- }});
+ AlphaPseudo::m5checkpoint(xc->xcBase());
+ }}, IsNonSpeculative);
+ 0x50: m5readfile({{
+ AlphaPseudo::readfile(xc->xcBase());
+ }}, IsNonSpeculative);
+ 0x51: m5break({{
+ AlphaPseudo::debugbreak(xc->xcBase());
+ }}, IsNonSpeculative);
+ 0x52: m5switchcpu({{
+ AlphaPseudo::switchcpu(xc->xcBase());
+ }}, IsNonSpeculative);
+
}
}