#include "base/misc.hh"
#include "cpu/exec_context.hh"
#include "cpu/exetrace.hh"
-#include "cpu/full_cpu/full_cpu.hh"
-#include "cpu/full_cpu/op_class.hh"
-#include "cpu/full_cpu/spec_state.hh"
+#include "cpu/full_cpu/dyn_inst.hh"
#include "cpu/simple_cpu/simple_cpu.hh"
#include "cpu/static_inst.hh"
#include "sim/annotation.hh"
/// @retval Full-system mode: No_Fault if FP is enabled, Fen_Fault
/// if not. Non-full-system mode: always returns No_Fault.
#ifdef FULL_SYSTEM
- inline Fault checkFpEnableFault(ExecContext *xc)
+ template <class XC>
+ inline Fault checkFpEnableFault(XC *xc)
{
Fault fault = No_Fault; // dummy... this ipr access should not fault
if (!ICSR_FPE(xc->readIpr(AlphaISA::IPR_ICSR, fault))) {
return fault;
}
#else
- inline Fault checkFpEnableFault(ExecContext *xc)
+ template <class XC>
+ inline Fault checkFpEnableFault(XC *xc)
{
return No_Fault;
}
%(constructor)s;
}
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
- Trace::InstRecord *traceData)
- {
- SimpleCPU *memAccessObj __attribute__((unused)) = cpu;
- Fault fault = No_Fault;
+ %(exec_func_declarations)s
+ };
+}};
- %(fp_enable_check)s;
- %(exec_decl)s;
- %(simple_rd)s;
- %(code)s;
+def template BasicExecute {{
+ Fault %(class_name)s::execute(%(cpu_model)s *xc,
+ Trace::InstRecord *traceData)
+ {
+ Fault fault = No_Fault;
- if (fault == No_Fault) {
- %(simple_wb)s;
- }
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
- return fault;
+ if (fault == No_Fault) {
+ %(op_wb)s;
}
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
- Trace::InstRecord *traceData)
- {
- DynInst *memAccessObj __attribute__((unused)) = dynInst;
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(exec_decl)s;
- %(dtld_rd)s;
- %(code)s;
-
- if (fault == No_Fault) {
- %(dtld_wb)s;
- }
-
- return fault;
- }
- };
+ return fault;
+ }
}};
def template BasicDecode {{
// The most basic instruction format... used only for a few misc. insts
def format BasicOperate(code, *flags) {{
iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code), flags)
- return iop.subst('BasicDeclare', 'BasicDecode')
+ return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
}};
~Nop() { }
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
- Trace::InstRecord *traceData)
- {
- return No_Fault;
- }
-
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
- Trace::InstRecord *traceData)
- {
- return No_Fault;
- }
-
std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
{
#ifdef SS_COMPATIBLE_DISASSEMBLY
return csprintf("%-10s (%s)", "nop", originalDisassembly);
#endif
}
+
+ Fault execute(SimpleCPUExecContext *, Trace::InstRecord *)
+ { return No_Fault; }
+
+ Fault execute(FullCPUExecContext *, Trace::InstRecord *)
+ { return No_Fault; }
};
/// Helper function for decoding nops. Substitute Nop object
}};
def format Nop() {{
- return ('', 'return new Nop("%s", machInst);\n' % name)
+ return ('', 'return new Nop("%s", machInst);\n' % name, 'return No_Fault;')
}};
def format BasicOperateWithNopCheck(code, *opt_args) {{
iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code),
opt_args)
- return iop.subst('BasicDeclare', 'OperateNopCheckDecode')
+ return iop.subst('BasicDeclare', 'OperateNopCheckDecode', 'BasicExecute')
}};
# generate declaration for register version
cblk = CodeBlock(code)
iop = InstObjParams(name, Name, 'AlphaStaticInst', cblk, opt_flags)
- decls = iop.subst('BasicDeclare')
+ (decls, exec_code) = iop.subst('BasicDeclare', 'BasicExecute')
if uses_imm:
# append declaration for imm version
imm_cblk = CodeBlock(imm_code)
imm_iop = InstObjParams(name, Name + 'Imm', 'IntegerImm', imm_cblk,
opt_flags)
- decls += imm_iop.subst('BasicDeclare')
+ (imm_decls, imm_exec_code) = \
+ imm_iop.subst('BasicDeclare', 'BasicExecute')
+ decls += imm_decls
+ exec_code += imm_exec_code
# decode checks IMM bit to pick correct version
decode = iop.subst('RegOrImmDecode')
else:
# no imm version: just check for nop
decode = iop.subst('OperateNopCheckDecode')
- return (decls, decode)
+ return (decls, decode, exec_code)
}};
trappingMode((enum TrappingMode)FP_TRAPMODE)
{
if (trappingMode != Imprecise) {
- warn("Warning: precise FP traps unimplemented\n");
+ warn("precise FP traps unimplemented\n");
}
}
#if defined(linux)
int
- getC99RoundingMode(ExecContext *xc)
+ getC99RoundingMode(uint64_t fpcr_val)
{
if (roundingMode == Dynamic) {
- return alphaToC99RoundingMode[bits(xc->readFpcr(), 59, 58)];
+ return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
}
else {
return alphaToC99RoundingMode[roundingMode];
}};
-def template FloatingPointDeclare {{
- /**
- * "Fast" static instruction class for "%(mnemonic)s" (imprecise
- * trapping mode, normal rounding mode).
- */
- class %(class_name)sFast : public %(base_class)s
- {
- public:
- /// Constructor.
- %(class_name)sFast(MachInst machInst)
- : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
- {
- %(constructor)s;
- }
-
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
- Trace::InstRecord *traceData)
- {
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(exec_decl)s;
- %(simple_rd)s;
- %(code)s;
-
- if (fault == No_Fault) {
- %(simple_wb)s;
- }
-
- return fault;
- }
-
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
- Trace::InstRecord *traceData)
- {
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(exec_decl)s;
- %(dtld_rd)s;
- %(code)s;
-
- if (fault == No_Fault) {
- %(dtld_wb)s;
- }
-
- return fault;
- }
- };
-
- /**
- * General static instruction class for "%(mnemonic)s". Supports
- * all the various rounding and trapping modes.
- */
- class %(class_name)sGeneral : public %(base_class)s
- {
- public:
- /// Constructor.
- %(class_name)sGeneral(MachInst machInst)
- : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
- {
- %(constructor)s;
- }
-
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
- Trace::InstRecord *traceData)
- {
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(exec_decl)s;
- %(simple_rd)s;
-
-#if defined(linux)
- fesetround(getC99RoundingMode(xc));
-#endif
-
- %(code)s;
-
-#if defined(linux)
- fesetround(FE_TONEAREST);
-#endif
-
- if (fault == No_Fault) {
- %(simple_wb)s;
- }
-
- return fault;
- }
-
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
- Trace::InstRecord *traceData)
- {
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(exec_decl)s;
- %(dtld_rd)s;
-
-#if defined(linux)
- fesetround(getC99RoundingMode(xc));
-#endif
-
- %(code)s;
-
-#if defined(linux)
- fesetround(FE_TONEAREST);
-#endif
-
- if (fault == No_Fault) {
- %(dtld_wb)s;
- }
-
- return fault;
- }
- };
-}};
-
def template FloatingPointDecode {{
{
bool fast = (FP_TRAPMODE == AlphaFP::Imprecise
}
}};
-
// General format for floating-point operate instructions:
// - Checks trapping and rounding mode flags. Trapping modes
// currently unimplemented (will fail).
// - Generates NOP if FC == 31.
def format FloatingPointOperate(code, *opt_args) {{
- iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code),
- opt_args)
- return iop.subst('FloatingPointDeclare', 'FloatingPointDecode')
+ iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
+ decode = iop.subst('FloatingPointDecode')
+
+ fast_iop = InstObjParams(name, Name + 'Fast', 'AlphaFP',
+ CodeBlock(code), opt_args)
+ (fast_declare, fast_exec) = fast_iop.subst('BasicDeclare', 'BasicExecute')
+
+ gen_code_prefix = r'''
+#if defined(linux)
+ fesetround(getC99RoundingMode(xc->readFpcr()));
+#endif
+'''
+ gen_code_suffix = r'''
+#if defined(linux)
+ fesetround(FE_TONEAREST);
+#endif
+'''
+
+ gen_iop = InstObjParams(name, Name + 'General', 'AlphaFP',
+ CodeBlock(gen_code_prefix + code + gen_code_suffix), opt_args)
+ (gen_declare, gen_exec) = gen_iop.subst('BasicDeclare', 'BasicExecute')
+
+ return (fast_declare + gen_declare, decode, fast_exec + gen_exec)
}};
{
}
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
- Trace::InstRecord *traceData)
- { panic("attempt to execute eacomp"); }
+ Fault execute(SimpleCPUExecContext *, Trace::InstRecord *)
+ { panic("attempt to execute eacomp"); }
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
- Trace::InstRecord *traceData)
- { panic("attempt to execute eacomp"); }
+ Fault execute(FullCPUExecContext *, Trace::InstRecord *)
+ { panic("attempt to execute eacomp"); }
};
/**
{
}
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
- Trace::InstRecord *traceData)
- { panic("attempt to execute memacc"); }
+ Fault execute(SimpleCPUExecContext *, Trace::InstRecord *)
+ { panic("attempt to execute memacc"); }
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
- Trace::InstRecord *traceData)
- { panic("attempt to execute memacc"); }
+ Fault execute(FullCPUExecContext *, Trace::InstRecord *)
+ { panic("attempt to execute memacc"); }
};
}};
def format LoadAddress(code) {{
iop = InstObjParams(name, Name, 'Memory', CodeBlock(code))
- return iop.subst('BasicDeclare', 'BasicDecode')
+ return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
}};
%(constructor)s;
}
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
- Trace::InstRecord *traceData)
- {
- SimpleCPU *memAccessObj = cpu;
- Addr EA;
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(exec_decl)s;
- %(simple_nonmem_rd)s;
- %(ea_code)s;
-
- if (fault == No_Fault) {
- %(simple_mem_rd)s;
- %(memacc_code)s;
- }
-
- if (fault == No_Fault) {
- %(simple_mem_wb)s;
- }
+ %(exec_func_declarations)s
+ };
+}};
- if (fault == No_Fault) {
- %(postacc_code)s;
- }
+def template LoadStoreExecute {{
+ Fault %(class_name)s::execute(%(cpu_model)s *xc,
+ Trace::InstRecord *traceData)
+ {
+ Addr EA;
+ Fault fault = No_Fault;
- if (fault == No_Fault) {
- %(simple_nonmem_wb)s;
- }
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_nonmem_rd)s;
+ %(ea_code)s;
- return fault;
+ if (fault == No_Fault) {
+ %(op_mem_rd)s;
+ %(memacc_code)s;
}
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
- Trace::InstRecord *traceData)
- {
- DynInst *memAccessObj = dynInst;
- Addr EA;
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(exec_decl)s;
- %(dtld_nonmem_rd)s;
- %(ea_code)s;
-
- if (fault == No_Fault) {
- %(dtld_mem_rd)s;
- %(memacc_code)s;
- }
-
- if (fault == No_Fault) {
- %(dtld_mem_wb)s;
- }
-
- if (fault == No_Fault) {
- %(postacc_code)s;
- }
+ if (fault == No_Fault) {
+ %(op_mem_wb)s;
+ }
- if (fault == No_Fault) {
- %(dtld_nonmem_wb)s;
- }
+ if (fault == No_Fault) {
+ %(postacc_code)s;
+ }
- return fault;
+ if (fault == No_Fault) {
+ %(op_nonmem_wb)s;
}
- };
-}};
+ return fault;
+ }
+}};
def template PrefetchDeclare {{
/**
*/
class %(class_name)s : public %(base_class)s
{
- public:
- /// Constructor
- %(class_name)s(MachInst machInst)
- : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+ protected:
+
+ /**
+ * "Fake" effective address computation class for "%(mnemonic)s".
+ */
+ class EAComp : public EACompBase
{
- %(constructor)s;
- }
+ public:
+ /// Constructor
+ EAComp(MachInst machInst)
+ : EACompBase(machInst)
+ {
+ %(ea_constructor)s;
+ }
+ };
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
- Trace::InstRecord *traceData)
+ /**
+ * "Fake" memory access instruction class for "%(mnemonic)s".
+ */
+ class MemAcc : public MemAccBase
{
- Addr EA;
- Fault fault = No_Fault;
+ public:
+ /// Constructor
+ MemAcc(MachInst machInst)
+ : MemAccBase(machInst, %(op_class)s)
+ {
+ %(memacc_constructor)s;
+ }
+ };
- %(fp_enable_check)s;
- %(exec_decl)s;
- %(simple_nonmem_rd)s;
- %(ea_code)s;
+ /// Pointer to EAComp object.
+ StaticInstPtr<AlphaISA> eaCompPtr;
+ /// Pointer to MemAcc object.
+ StaticInstPtr<AlphaISA> memAccPtr;
- if (fault == No_Fault) {
- cpu->prefetch(EA, memAccessFlags);
- }
+ public:
- return No_Fault;
- }
+ StaticInstPtr<AlphaISA> eaCompInst() { return eaCompPtr; }
+ StaticInstPtr<AlphaISA> memAccInst() { return memAccPtr; }
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
- Trace::InstRecord *traceData)
+ /// Constructor
+ %(class_name)s(MachInst machInst)
+ : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s),
+ eaCompPtr(new EAComp(machInst)), memAccPtr(new MemAcc(machInst))
{
- Addr EA;
- Fault fault = No_Fault;
+ %(constructor)s;
+ }
- %(fp_enable_check)s;
- %(exec_decl)s;
- %(dtld_nonmem_rd)s;
- %(ea_code)s;
+ %(exec_func_declarations)s
+ };
+}};
- if (fault == No_Fault) {
- dynInst->prefetch(EA, memAccessFlags);
- }
+def template PrefetchExecute {{
+ Fault %(class_name)s::execute(%(cpu_model)s *xc,
+ Trace::InstRecord *traceData)
+ {
+ Addr EA;
+ Fault fault = No_Fault;
- return No_Fault;
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_nonmem_rd)s;
+ %(ea_code)s;
+
+ if (fault == No_Fault) {
+ xc->prefetch(EA, memAccessFlags);
}
- };
-}};
+ return No_Fault;
+ }
+}};
// load instructions use Ra as dest, so check for
// Ra == 31 to detect nops
def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
base_class = 'Memory', flags = [],
declare_template = 'LoadStoreDeclare',
- decode_template = 'BasicDecode'):
+ decode_template = 'BasicDecode',
+ exec_template = 'LoadStoreExecute'):
# Segregate flags into instruction flags (handled by InstObjParams)
# and memory access flags (handled here).
if mem_flags != '':
iop.constructor += '\n\tmemAccessFlags = ' + mem_flags + ';'
- return iop.subst(declare_template, decode_template)
+ return iop.subst(declare_template, decode_template, exec_template)
}};
// Note that the flags passed in apply only to the prefetch version
def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{
# declare the load instruction object and generate the decode block
- (decls, decode) = \
+ (decls, decode, exec_code) = \
LoadStoreBase(name, Name, ea_code, memacc_code,
decode_template = 'LoadPrefetchCheckDecode')
# convert flags from tuple to list to make them mutable
pf_flags = list(pf_flags) + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'RdPort']
- (pfdecls, pfdecode) = \
+ (pfdecls, pfdecode, pfexec) = \
LoadStoreBase(name, Name + 'Prefetch', ea_code, '',
flags = pf_flags,
- declare_template = 'PrefetchDeclare')
+ declare_template = 'PrefetchDeclare',
+ exec_template = 'PrefetchExecute')
- return (decls + pfdecls, decode)
+ return (decls + pfdecls, decode, exec_code + pfexec)
}};
{
}
- Addr branchTarget(Addr branchPC)
+ Addr branchTarget(Addr branchPC) const
{
return branchPC + 4 + disp;
}
{
}
+ Addr branchTarget(ExecContext *xc) const
+ {
+ Addr NPC = xc->readPC() + 4;
+ uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
+ return (Rb & ~3) | (NPC & 1);
+ }
+
std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
{
std::stringstream ss;
code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n';
iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
('IsDirectControl', 'IsCondControl'))
- return iop.subst('BasicDeclare', 'BasicDecode')
+ return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
}};
let {{
nolink_code = 'NPC = %s;\n' % npc_expr
nolink_iop = InstObjParams(name, Name, base_class,
CodeBlock(nolink_code), flags)
- decls = nolink_iop.subst('BasicDeclare')
+ (decls, exec_code) = nolink_iop.subst('BasicDeclare', 'BasicExecute')
# Generate declaration of '*AndLink' version, append to decls
link_code = 'Ra = NPC & ~3;\n' + nolink_code
link_iop = InstObjParams(name, Name + 'AndLink', base_class,
CodeBlock(link_code), flags)
- decls += link_iop.subst('BasicDeclare')
+ (link_decls, link_exec_code) = \
+ link_iop.subst('BasicDeclare', 'BasicExecute')
+ decls += link_decls
+ exec_code += link_exec_code
# need to use link_iop for the decode template since it is expecting
# the shorter version of class_name (w/o "AndLink")
- return (decls, nolink_iop.subst('JumpOrBranchDecode'))
+ return (decls, nolink_iop.subst('JumpOrBranchDecode'), exec_code)
}};
def format UncondBranch(*flags) {{
def format EmulatedCallPal(code) {{
iop = InstObjParams(name, Name, 'EmulatedCallPal', CodeBlock(code))
- return iop.subst('BasicDeclare', 'BasicDecode')
+ return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
}};
declare {{
protected:
int palFunc; ///< Function code part of instruction
int palOffset; ///< Target PC, offset from IPR_PAL_BASE
+ bool palValid; ///< is the function code valid?
+ bool palPriv; ///< is this call privileged?
/// Constructor.
CallPalBase(const char *mnem, MachInst _machInst,
: AlphaStaticInst(mnem, _machInst, __opClass),
palFunc(PALFUNC)
{
- int palPriv = ((machInst & 0x80) != 0);
- int shortPalFunc = (machInst & 0x3f);
- palOffset = 0x2001 + (palPriv << 12) + (shortPalFunc << 6);
+ // From the 21164 HRM (paraphrased):
+ // Bit 7 of the function code (mask 0x80) indicates
+ // whether the call is privileged (bit 7 == 0) or
+ // unprivileged (bit 7 == 1). The privileged call table
+ // starts at 0x2000, the unprivielged call table starts at
+ // 0x3000. Bits 5-0 (mask 0x3f) are used to calculate the
+ // offset.
+ const int palPrivMask = 0x80;
+ const int palOffsetMask = 0x3f;
+
+ // Pal call is invalid unless all other bits are 0
+ palValid = ((machInst & ~(palPrivMask | palOffsetMask)) == 0);
+ palPriv = ((machInst & palPrivMask) == 0);
+ int shortPalFunc = (machInst & palOffsetMask);
+ // Add 1 to base to set pal-mode bit
+ palOffset = (palPriv ? 0x2001 : 0x3001) + (shortPalFunc << 6);
}
std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
def format CallPal(code) {{
iop = InstObjParams(name, Name, 'CallPalBase', CodeBlock(code))
- return iop.subst('BasicDeclare', 'BasicDecode')
+ return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
}};
//
def format HwMoveIPR(code) {{
iop = InstObjParams(name, Name, 'HwMoveIPR', CodeBlock(code))
- return iop.subst('BasicDeclare', 'BasicDecode')
+ return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
}};
declare {{
{
}
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
+ Fault execute(SimpleCPUExecContext *xc,
Trace::InstRecord *traceData)
{
panic("attempt to execute unimplemented instruction '%s' "
return Unimplemented_Opcode_Fault;
}
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
+ Fault execute(FullCPUExecContext *xc,
Trace::InstRecord *traceData)
{
// don't panic if this is a misspeculated instruction
- if (!xc->spec_mode)
+ if (!xc->misspeculating())
panic("attempt to execute unimplemented instruction '%s' "
"(inst 0x%08x, opcode 0x%x)",
mnemonic, machInst, OPCODE);
{
}
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
+ Fault execute(SimpleCPUExecContext *xc,
Trace::InstRecord *traceData)
{
if (!warned) {
- warn("Warning: instruction '%s' unimplemented\n", mnemonic);
+ warn("instruction '%s' unimplemented\n", mnemonic);
warned = true;
}
return No_Fault;
}
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
+ Fault execute(FullCPUExecContext *xc,
Trace::InstRecord *traceData)
{
- if (!xc->spec_mode && !warned) {
- warn("Warning: instruction '%s' unimplemented\n", mnemonic);
+ if (!xc->misspeculating() && !warned) {
+ warn("instruction '%s' unimplemented\n", mnemonic);
warned = true;
}
def format FailUnimpl() {{
iop = InstObjParams(name, 'FailUnimplemented')
- return ('', iop.subst('BasicDecodeWithMnemonic'))
+ return ('', iop.subst('BasicDecodeWithMnemonic'), '')
}};
def format WarnUnimpl() {{
iop = InstObjParams(name, Name, 'WarnUnimplemented')
- return iop.subst('WarnUnimplDeclare', 'BasicDecode')
+ return iop.subst('WarnUnimplDeclare', 'BasicDecode') + ['']
}};
declare {{
{
}
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
+ Fault execute(SimpleCPUExecContext *xc,
Trace::InstRecord *traceData)
{
panic("attempt to execute unknown instruction "
return Unimplemented_Opcode_Fault;
}
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
+ Fault execute(FullCPUExecContext *xc,
Trace::InstRecord *traceData)
{
// don't panic if this is a misspeculated instruction
- if (!xc->spec_mode)
+ if (!xc->misspeculating())
panic("attempt to execute unknown instruction "
"(inst 0x%08x, opcode 0x%x)", machInst, OPCODE);
return Unimplemented_Opcode_Fault;
}};
def format Unknown() {{
- return ('', 'return new Unknown(machInst);\n')
+ return ('', 'return new Unknown(machInst);\n', '')
}};
declare {{
0x23: ldt({{ EA = Rb + disp; }}, {{ Fa = Mem.df; }});
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);}},
+ IsMemRef, IsLoad, IsCopy);
}
format LoadOrPrefetch {
0x0f: stq_u({{ EA = (Rb + disp) & ~7; }}, {{ Mem.uq = Ra.uq; }});
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);}},
+ IsMemRef, IsStore, IsCopy);
}
format StoreCond {
// miscellaneous mem-format ops
0x18: decode MEMFUNC {
format WarnUnimpl {
- 0x0000: trapb();
- 0x0400: excb();
- 0x4000: mb();
- 0x4400: wmb();
0x8000: fetch();
0xa000: fetch_m();
0xe800: ecb();
format MiscPrefetch {
0xf800: wh64({{ EA = Rb; }},
- {{ memAccessObj->writeHint(EA, 64); }},
+ {{ xc->writeHint(EA, 64); }},
IsMemRef, IsStore, WrPort);
}
format BasicOperate {
- 0xc000: rpcc({{ Ra = curTick; }});
+ 0xc000: rpcc({{
+#ifdef FULL_SYSTEM
+ Ra = xc->readIpr(AlphaISA::IPR_CC, fault);
+#else
+ Ra = curTick;
+#endif
+ }});
+
+ // All of the barrier instructions below do nothing in
+ // their execute() methods (hence the empty code blocks).
+ // All of their functionality is hard-coded in the
+ // pipeline based on the flags IsSerializing,
+ // IsMemBarrier, and IsWriteBarrier. In the current
+ // detailed CPU model, the execute() function only gets
+ // called at fetch, so there's no way to generate pipeline
+ // behavior at any other stage. Once we go to an
+ // exec-in-exec CPU model we should be able to get rid of
+ // these flags and implement this behavior via the
+ // execute() methods.
+
+ // trapb is just a barrier on integer traps, where excb is
+ // a barrier on integer and FP traps. "EXCB is thus a
+ // superset of TRAPB." (Alpha ARM, Sec 4.11.4) We treat
+ // them the same though.
+ 0x0000: trapb({{ }}, IsSerializing, No_OpClass);
+ 0x0400: excb({{ }}, IsSerializing, No_OpClass);
+ 0x4000: mb({{ }}, IsMemBarrier, RdPort);
+ 0x4400: wmb({{ }}, IsWriteBarrier, WrPort);
}
#ifdef FULL_SYSTEM
format BasicOperate {
0xe000: rc({{
- Ra = xc->regs.intrflag;
+ Ra = xc->readIntrFlag();
if (!xc->misspeculating()) {
- xc->regs.intrflag = 0;
+ xc->setIntrFlag(0);
}
- }}, No_OpClass);
+ }});
0xf000: rs({{
- Ra = xc->regs.intrflag;
+ Ra = xc->readIntrFlag();
if (!xc->misspeculating()) {
- xc->regs.intrflag = 1;
+ xc->setIntrFlag(1);
}
- }}, No_OpClass);
+ }});
}
#else
format FailUnimpl {
#ifdef FULL_SYSTEM
0x00: CallPal::call_pal({{
- // check to see if simulator wants to do something special
- // on this PAL call (including maybe suppress it)
- bool dopal = xc->simPalCheck(palFunc);
-
- if (!xc->misspeculating()) {
- Annotate::Callpal(xc, palFunc);
+ if (!palValid ||
+ (palPriv
+ && xc->readIpr(AlphaISA::IPR_ICM, fault) != AlphaISA::mode_kernel)) {
+ // invalid pal function code, or attempt to do privileged
+ // PAL call in non-kernel mode
+ fault = Unimplemented_Opcode_Fault;
}
+ else {
+ bool dopal = true;
- if (dopal) {
if (!xc->misspeculating()) {
- AlphaISA::swap_palshadow(&xc->regs, true);
+ // check to see if simulator wants to do something special
+ // on this PAL call (including maybe suppress it)
+ dopal = xc->simPalCheck(palFunc);
+
+ Annotate::Callpal(xc->xcBase(), 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) {
+ NPC = xc->readIpr(AlphaISA::IPR_PAL_BASE, fault) + palOffset;
}
- xc->setIpr(AlphaISA::IPR_EXC_ADDR, NPC);
- NPC = xc->readIpr(AlphaISA::IPR_PAL_BASE, fault) + palOffset;
}
}});
#else
0x01: decode M5FUNC {
0x00: arm({{
if (!xc->misspeculating()) {
- Annotate::ARM(xc);
- xc->kernelStats.arm();
+ Annotate::ARM(xc->xcBase());
+ xc->xcBase()->kernelStats.arm();
}
}});
0x01: quiesce({{
if (!xc->misspeculating())
- AlphaPseudo::quiesce(xc);
+ AlphaPseudo::quiesce(xc->xcBase());
}});
0x10: ivlb({{
if (!xc->misspeculating()) {
- Annotate::BeginInterval(xc);
- xc->kernelStats.ivlb();
+ Annotate::BeginInterval(xc->xcBase());
+ xc->xcBase()->kernelStats.ivlb();
}
}}, No_OpClass);
0x11: ivle({{
if (!xc->misspeculating())
- Annotate::EndInterval(xc);
+ Annotate::EndInterval(xc->xcBase());
}}, No_OpClass);
0x20: m5exit_old({{
if (!xc->misspeculating())
- AlphaPseudo::m5exit_old(xc);
+ AlphaPseudo::m5exit_old(xc->xcBase());
}}, No_OpClass);
0x21: m5exit({{
if (!xc->misspeculating())
- AlphaPseudo::m5exit(xc);
+ AlphaPseudo::m5exit(xc->xcBase());
}}, No_OpClass);
- 0x30: initparam({{ Ra = xc->cpu->system->init_param; }});
+ 0x30: initparam({{ Ra = xc->xcBase()->cpu->system->init_param; }});
0x40: resetstats({{
if (!xc->misspeculating())
- AlphaPseudo::resetstats(xc);
+ AlphaPseudo::resetstats(xc->xcBase());
}});
0x41: dumpstats({{
if (!xc->misspeculating())
- AlphaPseudo::dumpstats(xc);
+ AlphaPseudo::dumpstats(xc->xcBase());
}});
0x42: dumpresetstats({{
if (!xc->misspeculating())
- AlphaPseudo::dumpresetstats(xc);
+ AlphaPseudo::dumpresetstats(xc->xcBase());
}});
0x43: m5checkpoint({{
if (!xc->misspeculating())
- AlphaPseudo::m5checkpoint(xc);
+ AlphaPseudo::m5checkpoint(xc->xcBase());
}});
}
}
format HwMoveIPR {
0x19: hw_mfpr({{
// this instruction is only valid in PAL mode
- if (!PC_PAL(xc->regs.pc)) {
+ if (!xc->inPalMode()) {
fault = Unimplemented_Opcode_Fault;
}
else {
}});
0x1d: hw_mtpr({{
// this instruction is only valid in PAL mode
- if (!PC_PAL(xc->regs.pc)) {
+ if (!xc->inPalMode()) {
fault = Unimplemented_Opcode_Fault;
}
else {