Do a better job of factoring out CPU model in ISA description.

(Still not perfect though.)

arch/alpha/isa_desc:
    Do a better job of factoring out CPU model.  (Still not perfect though.)
    Pull execute() methods out of class declarations into separate section
    of file, allowing (1) easier replication for different CPU models and
    (2) a path to putting them all in a separate file.  Force all instruction
    execution context into a single model-dependent class (SimpleCPU itself
    for SimpleCPU, DynInst for FullCPU).
arch/isa_parser.py:
    Do a better job of factoring out CPU model.  (Still not perfect though.)
    Pull execute() methods out of class declarations into separate section
    of file, allowing (1) easier replication for different CPU models and
    (2) a path to putting them all in a separate file.
    Also restructure top level to allow parser to run under interactive
    interpreter session for easier debugging.
cpu/exec_context.hh:
    Add a few new methods to clean up isa_desc.
cpu/simple_cpu/simple_cpu.cc:
cpu/static_inst.hh:
    StaticInst::execute no longer takes a CPU and an ExecContext,
    just a unified FooCPUExecContext.
cpu/simple_cpu/simple_cpu.hh:
    Add methods to redirect calls to ExecContext so SimpleCPU
    can act as sole instruction execution context for itself.
    Typedef SimpleCPU to SimpleCPUExecContext.

--HG--
extra : convert_revision : ecc445503bc585585da5663fe61796580e744da6
This commit is contained in:
Steve Reinhardt 2004-05-10 16:10:47 -07:00
parent d66ae60f6b
commit 7cab07268f
6 changed files with 342 additions and 434 deletions

View file

@ -5,7 +5,7 @@
let {{ let {{
global rcs_id global rcs_id
rcs_id = "$Id: s.isa_desc 1.43 04/02/29 22:41:10-05:00 ehallnor@zazzer.eecs.umich.edu $" rcs_id = "$Id$"
}}; }};
@ -22,9 +22,7 @@ let {{
#include "base/misc.hh" #include "base/misc.hh"
#include "cpu/exec_context.hh" #include "cpu/exec_context.hh"
#include "cpu/exetrace.hh" #include "cpu/exetrace.hh"
#include "cpu/full_cpu/full_cpu.hh" #include "cpu/full_cpu/dyn_inst.hh"
#include "cpu/full_cpu/op_class.hh"
#include "cpu/full_cpu/spec_state.hh"
#include "cpu/simple_cpu/simple_cpu.hh" #include "cpu/simple_cpu/simple_cpu.hh"
#include "cpu/static_inst.hh" #include "cpu/static_inst.hh"
#include "sim/annotation.hh" #include "sim/annotation.hh"
@ -143,7 +141,8 @@ declare {{
/// @retval Full-system mode: No_Fault if FP is enabled, Fen_Fault /// @retval Full-system mode: No_Fault if FP is enabled, Fen_Fault
/// if not. Non-full-system mode: always returns No_Fault. /// if not. Non-full-system mode: always returns No_Fault.
#ifdef FULL_SYSTEM #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 Fault fault = No_Fault; // dummy... this ipr access should not fault
if (!ICSR_FPE(xc->readIpr(AlphaISA::IPR_ICSR, fault))) { if (!ICSR_FPE(xc->readIpr(AlphaISA::IPR_ICSR, fault))) {
@ -152,7 +151,8 @@ declare {{
return fault; return fault;
} }
#else #else
inline Fault checkFpEnableFault(ExecContext *xc) template <class XC>
inline Fault checkFpEnableFault(XC *xc)
{ {
return No_Fault; return No_Fault;
} }
@ -239,44 +239,29 @@ def template BasicDeclare {{
%(constructor)s; %(constructor)s;
} }
Fault execute(SimpleCPU *cpu, ExecContext *xc, %(exec_func_declarations)s
Trace::InstRecord *traceData)
{
SimpleCPU *memAccessObj __attribute__((unused)) = cpu;
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)
{
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;
}
}; };
}}; }};
def template BasicExecute {{
Fault %(class_name)s::execute(%(cpu_model)s *xc,
Trace::InstRecord *traceData)
{
Fault fault = No_Fault;
%(fp_enable_check)s;
%(op_decl)s;
%(op_rd)s;
%(code)s;
if (fault == No_Fault) {
%(op_wb)s;
}
return fault;
}
}};
def template BasicDecode {{ def template BasicDecode {{
return new %(class_name)s(machInst); return new %(class_name)s(machInst);
}}; }};
@ -288,7 +273,7 @@ def template BasicDecodeWithMnemonic {{
// The most basic instruction format... used only for a few misc. insts // The most basic instruction format... used only for a few misc. insts
def format BasicOperate(code, *flags) {{ def format BasicOperate(code, *flags) {{
iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code), flags) iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code), flags)
return iop.subst('BasicDeclare', 'BasicDecode') return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
}}; }};
@ -315,18 +300,6 @@ declare {{
~Nop() { } ~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) std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
{ {
#ifdef SS_COMPATIBLE_DISASSEMBLY #ifdef SS_COMPATIBLE_DISASSEMBLY
@ -335,6 +308,12 @@ declare {{
return csprintf("%-10s (%s)", "nop", originalDisassembly); return csprintf("%-10s (%s)", "nop", originalDisassembly);
#endif #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 /// Helper function for decoding nops. Substitute Nop object
@ -350,7 +329,7 @@ declare {{
}}; }};
def format Nop() {{ def format Nop() {{
return ('', 'return new Nop("%s", machInst);\n' % name) return ('', 'return new Nop("%s", machInst);\n' % name, 'return No_Fault;')
}}; }};
@ -370,7 +349,7 @@ def template OperateNopCheckDecode {{
def format BasicOperateWithNopCheck(code, *opt_args) {{ def format BasicOperateWithNopCheck(code, *opt_args) {{
iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code), iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code),
opt_args) opt_args)
return iop.subst('BasicDeclare', 'OperateNopCheckDecode') return iop.subst('BasicDeclare', 'OperateNopCheckDecode', 'BasicExecute')
}}; }};
@ -454,21 +433,24 @@ def format IntegerOperate(code, *opt_flags) {{
# generate declaration for register version # generate declaration for register version
cblk = CodeBlock(code) cblk = CodeBlock(code)
iop = InstObjParams(name, Name, 'AlphaStaticInst', cblk, opt_flags) iop = InstObjParams(name, Name, 'AlphaStaticInst', cblk, opt_flags)
decls = iop.subst('BasicDeclare') (decls, exec_code) = iop.subst('BasicDeclare', 'BasicExecute')
if uses_imm: if uses_imm:
# append declaration for imm version # append declaration for imm version
imm_cblk = CodeBlock(imm_code) imm_cblk = CodeBlock(imm_code)
imm_iop = InstObjParams(name, Name + 'Imm', 'IntegerImm', imm_cblk, imm_iop = InstObjParams(name, Name + 'Imm', 'IntegerImm', imm_cblk,
opt_flags) 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 checks IMM bit to pick correct version
decode = iop.subst('RegOrImmDecode') decode = iop.subst('RegOrImmDecode')
else: else:
# no imm version: just check for nop # no imm version: just check for nop
decode = iop.subst('OperateNopCheckDecode') decode = iop.subst('OperateNopCheckDecode')
return (decls, decode) return (decls, decode, exec_code)
}}; }};
@ -544,10 +526,10 @@ declare {{
#if defined(linux) #if defined(linux)
int int
getC99RoundingMode(ExecContext *xc) getC99RoundingMode(uint64_t fpcr_val)
{ {
if (roundingMode == Dynamic) { if (roundingMode == Dynamic) {
return alphaToC99RoundingMode[bits(xc->readFpcr(), 59, 58)]; return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
} }
else { else {
return alphaToC99RoundingMode[roundingMode]; return alphaToC99RoundingMode[roundingMode];
@ -618,124 +600,6 @@ declare {{
}}; }};
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 {{ def template FloatingPointDecode {{
{ {
bool fast = (FP_TRAPMODE == AlphaFP::Imprecise bool fast = (FP_TRAPMODE == AlphaFP::Imprecise
@ -752,15 +616,34 @@ def template FloatingPointDecode {{
} }
}}; }};
// General format for floating-point operate instructions: // General format for floating-point operate instructions:
// - Checks trapping and rounding mode flags. Trapping modes // - Checks trapping and rounding mode flags. Trapping modes
// currently unimplemented (will fail). // currently unimplemented (will fail).
// - Generates NOP if FC == 31. // - Generates NOP if FC == 31.
def format FloatingPointOperate(code, *opt_args) {{ def format FloatingPointOperate(code, *opt_args) {{
iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
opt_args) decode = iop.subst('FloatingPointDecode')
return iop.subst('FloatingPointDeclare', '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)
}}; }};
@ -833,13 +716,11 @@ declare {{
{ {
} }
Fault execute(SimpleCPU *cpu, ExecContext *xc, Fault execute(SimpleCPUExecContext *, Trace::InstRecord *)
Trace::InstRecord *traceData) { panic("attempt to execute eacomp"); }
{ panic("attempt to execute eacomp"); }
Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst, Fault execute(FullCPUExecContext *, Trace::InstRecord *)
Trace::InstRecord *traceData) { panic("attempt to execute eacomp"); }
{ panic("attempt to execute eacomp"); }
}; };
/** /**
@ -855,13 +736,11 @@ declare {{
{ {
} }
Fault execute(SimpleCPU *cpu, ExecContext *xc, Fault execute(SimpleCPUExecContext *, Trace::InstRecord *)
Trace::InstRecord *traceData) { panic("attempt to execute memacc"); }
{ panic("attempt to execute memacc"); }
Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst, Fault execute(FullCPUExecContext *, Trace::InstRecord *)
Trace::InstRecord *traceData) { panic("attempt to execute memacc"); }
{ panic("attempt to execute memacc"); }
}; };
}}; }};
@ -869,7 +748,7 @@ declare {{
def format LoadAddress(code) {{ def format LoadAddress(code) {{
iop = InstObjParams(name, Name, 'Memory', CodeBlock(code)) iop = InstObjParams(name, Name, 'Memory', CodeBlock(code))
return iop.subst('BasicDeclare', 'BasicDecode') return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
}}; }};
@ -927,72 +806,42 @@ def template LoadStoreDeclare {{
%(constructor)s; %(constructor)s;
} }
Fault execute(SimpleCPU *cpu, ExecContext *xc, %(exec_func_declarations)s
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;
}
if (fault == No_Fault) {
%(postacc_code)s;
}
if (fault == No_Fault) {
%(simple_nonmem_wb)s;
}
return fault;
}
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) {
%(dtld_nonmem_wb)s;
}
return fault;
}
}; };
}}; }};
def template LoadStoreExecute {{
Fault %(class_name)s::execute(%(cpu_model)s *xc,
Trace::InstRecord *traceData)
{
Addr EA;
Fault fault = No_Fault;
%(fp_enable_check)s;
%(op_decl)s;
%(op_nonmem_rd)s;
%(ea_code)s;
if (fault == No_Fault) {
%(op_mem_rd)s;
%(memacc_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 PrefetchDeclare {{ def template PrefetchDeclare {{
/** /**
@ -1048,44 +897,29 @@ def template PrefetchDeclare {{
%(constructor)s; %(constructor)s;
} }
Fault execute(SimpleCPU *cpu, ExecContext *xc, %(exec_func_declarations)s
Trace::InstRecord *traceData)
{
Addr EA;
Fault fault = No_Fault;
%(fp_enable_check)s;
%(exec_decl)s;
%(simple_nonmem_rd)s;
%(ea_code)s;
if (fault == No_Fault) {
cpu->prefetch(EA, memAccessFlags);
}
return No_Fault;
}
Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
Trace::InstRecord *traceData)
{
Addr EA;
Fault fault = No_Fault;
%(fp_enable_check)s;
%(exec_decl)s;
%(dtld_nonmem_rd)s;
%(ea_code)s;
if (fault == No_Fault) {
dynInst->prefetch(EA, memAccessFlags);
}
return No_Fault;
}
}; };
}}; }};
def template PrefetchExecute {{
Fault %(class_name)s::execute(%(cpu_model)s *xc,
Trace::InstRecord *traceData)
{
Addr EA;
Fault fault = 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 // load instructions use Ra as dest, so check for
// Ra == 31 to detect nops // Ra == 31 to detect nops
@ -1118,7 +952,8 @@ global LoadStoreBase
def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '', def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
base_class = 'Memory', flags = [], base_class = 'Memory', flags = [],
declare_template = 'LoadStoreDeclare', declare_template = 'LoadStoreDeclare',
decode_template = 'BasicDecode'): decode_template = 'BasicDecode',
exec_template = 'LoadStoreExecute'):
# Segregate flags into instruction flags (handled by InstObjParams) # Segregate flags into instruction flags (handled by InstObjParams)
# and memory access flags (handled here). # and memory access flags (handled here).
@ -1149,7 +984,7 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
if mem_flags != '': if mem_flags != '':
iop.constructor += '\n\tmemAccessFlags = ' + mem_flags + ';' iop.constructor += '\n\tmemAccessFlags = ' + mem_flags + ';'
return iop.subst(declare_template, decode_template) return iop.subst(declare_template, decode_template, exec_template)
}}; }};
@ -1163,7 +998,7 @@ def format LoadOrNop(ea_code, memacc_code, *flags) {{
// Note that the flags passed in apply only to the prefetch version // Note that the flags passed in apply only to the prefetch version
def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{ def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{
# declare the load instruction object and generate the decode block # declare the load instruction object and generate the decode block
(decls, decode) = \ (decls, decode, exec_code) = \
LoadStoreBase(name, Name, ea_code, memacc_code, LoadStoreBase(name, Name, ea_code, memacc_code,
decode_template = 'LoadPrefetchCheckDecode') decode_template = 'LoadPrefetchCheckDecode')
@ -1172,12 +1007,13 @@ def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{
# convert flags from tuple to list to make them mutable # 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', 'RdPort']
(pfdecls, pfdecode) = \ (pfdecls, pfdecode, pfexec) = \
LoadStoreBase(name, Name + 'Prefetch', ea_code, '', LoadStoreBase(name, Name + 'Prefetch', ea_code, '',
flags = pf_flags, flags = pf_flags,
declare_template = 'PrefetchDeclare') declare_template = 'PrefetchDeclare',
exec_template = 'PrefetchExecute')
return (decls + pfdecls, decode) return (decls + pfdecls, decode, exec_code + pfexec)
}}; }};
@ -1369,7 +1205,7 @@ def format CondBranch(code) {{
code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n'; code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n';
iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
('IsDirectControl', 'IsCondControl')) ('IsDirectControl', 'IsCondControl'))
return iop.subst('BasicDeclare', 'BasicDecode') return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
}}; }};
let {{ let {{
@ -1379,17 +1215,20 @@ def UncondCtrlBase(name, Name, base_class, npc_expr, flags):
nolink_code = 'NPC = %s;\n' % npc_expr nolink_code = 'NPC = %s;\n' % npc_expr
nolink_iop = InstObjParams(name, Name, base_class, nolink_iop = InstObjParams(name, Name, base_class,
CodeBlock(nolink_code), flags) 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 # Generate declaration of '*AndLink' version, append to decls
link_code = 'Ra = NPC & ~3;\n' + nolink_code link_code = 'Ra = NPC & ~3;\n' + nolink_code
link_iop = InstObjParams(name, Name + 'AndLink', base_class, link_iop = InstObjParams(name, Name + 'AndLink', base_class,
CodeBlock(link_code), flags) 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 # need to use link_iop for the decode template since it is expecting
# the shorter version of class_name (w/o "AndLink") # 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 UncondBranch(*flags) {{
@ -1432,7 +1271,7 @@ declare {{
def format EmulatedCallPal(code) {{ def format EmulatedCallPal(code) {{
iop = InstObjParams(name, Name, 'EmulatedCallPal', CodeBlock(code)) iop = InstObjParams(name, Name, 'EmulatedCallPal', CodeBlock(code))
return iop.subst('BasicDeclare', 'BasicDecode') return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
}}; }};
declare {{ declare {{
@ -1483,7 +1322,7 @@ declare {{
def format CallPal(code) {{ def format CallPal(code) {{
iop = InstObjParams(name, Name, 'CallPalBase', CodeBlock(code)) iop = InstObjParams(name, Name, 'CallPalBase', CodeBlock(code))
return iop.subst('BasicDeclare', 'BasicDecode') return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
}}; }};
// //
@ -1585,7 +1424,7 @@ declare {{
def format HwMoveIPR(code) {{ def format HwMoveIPR(code) {{
iop = InstObjParams(name, Name, 'HwMoveIPR', CodeBlock(code)) iop = InstObjParams(name, Name, 'HwMoveIPR', CodeBlock(code))
return iop.subst('BasicDeclare', 'BasicDecode') return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
}}; }};
declare {{ declare {{
@ -1605,7 +1444,7 @@ declare {{
{ {
} }
Fault execute(SimpleCPU *cpu, ExecContext *xc, Fault execute(SimpleCPUExecContext *xc,
Trace::InstRecord *traceData) Trace::InstRecord *traceData)
{ {
panic("attempt to execute unimplemented instruction '%s' " panic("attempt to execute unimplemented instruction '%s' "
@ -1613,11 +1452,11 @@ declare {{
return Unimplemented_Opcode_Fault; return Unimplemented_Opcode_Fault;
} }
Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst, Fault execute(FullCPUExecContext *xc,
Trace::InstRecord *traceData) Trace::InstRecord *traceData)
{ {
// don't panic if this is a misspeculated instruction // don't panic if this is a misspeculated instruction
if (!xc->spec_mode) if (!xc->misspeculating())
panic("attempt to execute unimplemented instruction '%s' " panic("attempt to execute unimplemented instruction '%s' "
"(inst 0x%08x, opcode 0x%x)", "(inst 0x%08x, opcode 0x%x)",
mnemonic, machInst, OPCODE); mnemonic, machInst, OPCODE);
@ -1652,7 +1491,7 @@ declare {{
{ {
} }
Fault execute(SimpleCPU *cpu, ExecContext *xc, Fault execute(SimpleCPUExecContext *xc,
Trace::InstRecord *traceData) Trace::InstRecord *traceData)
{ {
if (!warned) { if (!warned) {
@ -1663,10 +1502,10 @@ declare {{
return No_Fault; return No_Fault;
} }
Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst, Fault execute(FullCPUExecContext *xc,
Trace::InstRecord *traceData) Trace::InstRecord *traceData)
{ {
if (!xc->spec_mode && !warned) { if (!xc->misspeculating() && !warned) {
warn("instruction '%s' unimplemented\n", mnemonic); warn("instruction '%s' unimplemented\n", mnemonic);
warned = true; warned = true;
} }
@ -1703,12 +1542,12 @@ def template WarnUnimplDeclare {{
def format FailUnimpl() {{ def format FailUnimpl() {{
iop = InstObjParams(name, 'FailUnimplemented') iop = InstObjParams(name, 'FailUnimplemented')
return ('', iop.subst('BasicDecodeWithMnemonic')) return ('', iop.subst('BasicDecodeWithMnemonic'), '')
}}; }};
def format WarnUnimpl() {{ def format WarnUnimpl() {{
iop = InstObjParams(name, Name, 'WarnUnimplemented') iop = InstObjParams(name, Name, 'WarnUnimplemented')
return iop.subst('WarnUnimplDeclare', 'BasicDecode') return iop.subst('WarnUnimplDeclare', 'BasicDecode') + ['']
}}; }};
declare {{ declare {{
@ -1726,7 +1565,7 @@ declare {{
{ {
} }
Fault execute(SimpleCPU *cpu, ExecContext *xc, Fault execute(SimpleCPUExecContext *xc,
Trace::InstRecord *traceData) Trace::InstRecord *traceData)
{ {
panic("attempt to execute unknown instruction " panic("attempt to execute unknown instruction "
@ -1734,11 +1573,11 @@ declare {{
return Unimplemented_Opcode_Fault; return Unimplemented_Opcode_Fault;
} }
Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst, Fault execute(FullCPUExecContext *xc,
Trace::InstRecord *traceData) Trace::InstRecord *traceData)
{ {
// don't panic if this is a misspeculated instruction // don't panic if this is a misspeculated instruction
if (!xc->spec_mode) if (!xc->misspeculating())
panic("attempt to execute unknown instruction " panic("attempt to execute unknown instruction "
"(inst 0x%08x, opcode 0x%x)", machInst, OPCODE); "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE);
return Unimplemented_Opcode_Fault; return Unimplemented_Opcode_Fault;
@ -1753,7 +1592,7 @@ declare {{
}}; }};
def format Unknown() {{ def format Unknown() {{
return ('', 'return new Unknown(machInst);\n') return ('', 'return new Unknown(machInst);\n', '')
}}; }};
declare {{ declare {{
@ -1855,7 +1694,7 @@ decode OPCODE default Unknown::unknown() {
0x2a: ldl_l({{ EA = Rb + disp; }}, {{ Ra.sl = Mem.sl; }}, LOCKED); 0x2a: ldl_l({{ EA = Rb + disp; }}, {{ Ra.sl = Mem.sl; }}, LOCKED);
0x2b: ldq_l({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uq; }}, LOCKED); 0x2b: ldq_l({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uq; }}, LOCKED);
0x20: copy_load({{EA = Ra;}}, 0x20: copy_load({{EA = Ra;}},
{{ fault = memAccessObj->copySrcTranslate(EA);}}, {{ fault = xc->copySrcTranslate(EA);}},
IsMemRef, IsLoad, IsCopy); IsMemRef, IsLoad, IsCopy);
} }
@ -1877,7 +1716,7 @@ decode OPCODE default Unknown::unknown() {
0x26: sts({{ EA = Rb + disp; }}, {{ Mem.ul = t_to_s(Fa.uq); }}); 0x26: sts({{ EA = Rb + disp; }}, {{ Mem.ul = t_to_s(Fa.uq); }});
0x27: stt({{ EA = Rb + disp; }}, {{ Mem.df = Fa; }}); 0x27: stt({{ EA = Rb + disp; }}, {{ Mem.df = Fa; }});
0x24: copy_store({{EA = Rb;}}, 0x24: copy_store({{EA = Rb;}},
{{ fault = memAccessObj->copy(EA);}}, {{ fault = xc->copy(EA);}},
IsMemRef, IsStore, IsCopy); IsMemRef, IsStore, IsCopy);
} }
@ -2383,7 +2222,7 @@ decode OPCODE default Unknown::unknown() {
format MiscPrefetch { format MiscPrefetch {
0xf800: wh64({{ EA = Rb; }}, 0xf800: wh64({{ EA = Rb; }},
{{ memAccessObj->writeHint(EA, 64); }}, {{ xc->writeHint(EA, 64); }},
IsMemRef, IsStore, WrPort); IsMemRef, IsStore, WrPort);
} }
@ -2421,15 +2260,15 @@ decode OPCODE default Unknown::unknown() {
#ifdef FULL_SYSTEM #ifdef FULL_SYSTEM
format BasicOperate { format BasicOperate {
0xe000: rc({{ 0xe000: rc({{
Ra = xc->regs.intrflag; Ra = xc->readIntrFlag();
if (!xc->misspeculating()) { if (!xc->misspeculating()) {
xc->regs.intrflag = 0; xc->setIntrFlag(0);
} }
}}); }});
0xf000: rs({{ 0xf000: rs({{
Ra = xc->regs.intrflag; Ra = xc->readIntrFlag();
if (!xc->misspeculating()) { if (!xc->misspeculating()) {
xc->regs.intrflag = 1; xc->setIntrFlag(1);
} }
}}); }});
} }
@ -2458,10 +2297,10 @@ decode OPCODE default Unknown::unknown() {
// on this PAL call (including maybe suppress it) // on this PAL call (including maybe suppress it)
dopal = xc->simPalCheck(palFunc); dopal = xc->simPalCheck(palFunc);
Annotate::Callpal(xc, palFunc); Annotate::Callpal(xc->xcBase(), palFunc);
if (dopal) { if (dopal) {
AlphaISA::swap_palshadow(&xc->regs, true); AlphaISA::swap_palshadow(&xc->xcBase()->regs, true);
xc->setIpr(AlphaISA::IPR_EXC_ADDR, NPC); xc->setIpr(AlphaISA::IPR_EXC_ADDR, NPC);
} }
} }
@ -2519,48 +2358,48 @@ decode OPCODE default Unknown::unknown() {
0x01: decode M5FUNC { 0x01: decode M5FUNC {
0x00: arm({{ 0x00: arm({{
if (!xc->misspeculating()) { if (!xc->misspeculating()) {
Annotate::ARM(xc); Annotate::ARM(xc->xcBase());
xc->kernelStats.arm(); xc->xcBase()->kernelStats.arm();
} }
}}); }});
0x01: quiesce({{ 0x01: quiesce({{
if (!xc->misspeculating()) if (!xc->misspeculating())
AlphaPseudo::quiesce(xc); AlphaPseudo::quiesce(xc->xcBase());
}}); }});
0x10: ivlb({{ 0x10: ivlb({{
if (!xc->misspeculating()) { if (!xc->misspeculating()) {
Annotate::BeginInterval(xc); Annotate::BeginInterval(xc->xcBase());
xc->kernelStats.ivlb(); xc->xcBase()->kernelStats.ivlb();
} }
}}, No_OpClass); }}, No_OpClass);
0x11: ivle({{ 0x11: ivle({{
if (!xc->misspeculating()) if (!xc->misspeculating())
Annotate::EndInterval(xc); Annotate::EndInterval(xc->xcBase());
}}, No_OpClass); }}, No_OpClass);
0x20: m5exit_old({{ 0x20: m5exit_old({{
if (!xc->misspeculating()) if (!xc->misspeculating())
AlphaPseudo::m5exit_old(xc); AlphaPseudo::m5exit_old(xc->xcBase());
}}, No_OpClass); }}, No_OpClass);
0x21: m5exit({{ 0x21: m5exit({{
if (!xc->misspeculating()) if (!xc->misspeculating())
AlphaPseudo::m5exit(xc); AlphaPseudo::m5exit(xc->xcBase());
}}, No_OpClass); }}, No_OpClass);
0x30: initparam({{ Ra = cpu->system->init_param; }}); 0x30: initparam({{ Ra = xc->xcBase()->cpu->system->init_param; }});
0x40: resetstats({{ 0x40: resetstats({{
if (!xc->misspeculating()) if (!xc->misspeculating())
AlphaPseudo::resetstats(xc); AlphaPseudo::resetstats(xc->xcBase());
}}); }});
0x41: dumpstats({{ 0x41: dumpstats({{
if (!xc->misspeculating()) if (!xc->misspeculating())
AlphaPseudo::dumpstats(xc); AlphaPseudo::dumpstats(xc->xcBase());
}}); }});
0x42: dumpresetstats({{ 0x42: dumpresetstats({{
if (!xc->misspeculating()) if (!xc->misspeculating())
AlphaPseudo::dumpresetstats(xc); AlphaPseudo::dumpresetstats(xc->xcBase());
}}); }});
0x43: m5checkpoint({{ 0x43: m5checkpoint({{
if (!xc->misspeculating()) if (!xc->misspeculating())
AlphaPseudo::m5checkpoint(xc); AlphaPseudo::m5checkpoint(xc->xcBase());
}}); }});
} }
} }
@ -2568,7 +2407,7 @@ decode OPCODE default Unknown::unknown() {
format HwMoveIPR { format HwMoveIPR {
0x19: hw_mfpr({{ 0x19: hw_mfpr({{
// this instruction is only valid in PAL mode // this instruction is only valid in PAL mode
if (!PC_PAL(xc->regs.pc)) { if (!xc->inPalMode()) {
fault = Unimplemented_Opcode_Fault; fault = Unimplemented_Opcode_Fault;
} }
else { else {
@ -2577,7 +2416,7 @@ decode OPCODE default Unknown::unknown() {
}}); }});
0x1d: hw_mtpr({{ 0x1d: hw_mtpr({{
// this instruction is only valid in PAL mode // this instruction is only valid in PAL mode
if (!PC_PAL(xc->regs.pc)) { if (!xc->inPalMode()) {
fault = Unimplemented_Opcode_Fault; fault = Unimplemented_Opcode_Fault;
} }
else { else {

View file

@ -32,20 +32,10 @@ import os
import sys import sys
import re import re
import string import string
import traceback
# get type names # get type names
from types import * from types import *
# Check arguments. Right now there are only two: the name of the ISA
# description (input) file and the name of the C++ decoder (output) file.
isa_desc_filename = sys.argv[1]
decoder_filename = sys.argv[2]
# Might as well suck the file in while we're here. This way if it's a
# bad filename we don't waste a lot of time building the parser :-).
input = open(isa_desc_filename)
isa_desc = input.read()
input.close()
# Prepend the directory where the PLY lex & yacc modules are found # Prepend the directory where the PLY lex & yacc modules are found
# to the search path. Assumes we're compiling in a subdirectory # to the search path. Assumes we're compiling in a subdirectory
# of 'build' in the current tree. # of 'build' in the current tree.
@ -225,8 +215,8 @@ def p_specification(t):
isa_name = t[2] isa_name = t[2]
namespace = isa_name + "Inst" namespace = isa_name + "Inst"
global_decls2 = t[3] global_decls2 = t[3]
(inst_decls, code) = t[4] (inst_decls, decode_code, exec_code) = t[4]
code = indent(code) decode_code = indent(decode_code)
# grab the last three path components of isa_desc_filename # grab the last three path components of isa_desc_filename
filename = '/'.join(isa_desc_filename.split('/')[-3:]) filename = '/'.join(isa_desc_filename.split('/')[-3:])
# if the isa_desc file defines a 'rcs_id' string, # if the isa_desc file defines a 'rcs_id' string,
@ -306,6 +296,8 @@ namespace %(namespace)s
%(inst_decls)s %(inst_decls)s
%(exec_code)s
} // namespace %(namespace)s } // namespace %(namespace)s
////////////////////// //////////////////////
@ -316,7 +308,7 @@ StaticInstPtr<%(isa_name)s>
%(isa_name)s::decodeInst(%(isa_name)s::MachInst machInst) %(isa_name)s::decodeInst(%(isa_name)s::MachInst machInst)
{ {
using namespace %(namespace)s; using namespace %(namespace)s;
%(code)s %(decode_code)s
} // decodeInst } // decodeInst
''' % vars() ''' % vars()
output.close() output.close()
@ -461,18 +453,19 @@ def p_param_1(t):
def p_decode_block(t): def p_decode_block(t):
'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE' 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE'
default_defaults = defaultStack.pop() default_defaults = defaultStack.pop()
(decls, code, has_default) = t[5] (decls, decode_code, exec_code, has_default) = t[5]
# use the "default defaults" only if there was no explicit # use the "default defaults" only if there was no explicit
# default statement in decode_stmt_list # default statement in decode_stmt_list
if not has_default: if not has_default:
(default_decls, default_code) = default_defaults (default_decls, default_decode, default_exec) = default_defaults
decls += default_decls decls += default_decls
code += default_code decode_code += default_decode
exec_code += default_exec
t[0] = (decls, ''' t[0] = (decls, '''
switch (%s) { switch (%s) {
%s %s
} }
''' % (t[2], indent(code))) ''' % (t[2], indent(decode_code)), exec_code)
# The opt_default statement serves only to push the "default defaults" # The opt_default statement serves only to push the "default defaults"
# onto defaultStack. This value will be used by nested decode blocks, # onto defaultStack. This value will be used by nested decode blocks,
@ -488,8 +481,8 @@ def p_opt_default_0(t):
def p_opt_default_1(t): def p_opt_default_1(t):
'opt_default : DEFAULT inst' 'opt_default : DEFAULT inst'
# push the new default # push the new default
(decls, code) = t[2] (decls, decode_code, exec_code) = t[2]
defaultStack.push((decls, '\ndefault:\n%sbreak;' % code)) defaultStack.push((decls, '\ndefault:\n%sbreak;' % decode_code, exec_code))
# no meaningful value returned # no meaningful value returned
t[0] = None t[0] = None
@ -499,12 +492,12 @@ def p_decode_stmt_list_0(t):
def p_decode_stmt_list_1(t): def p_decode_stmt_list_1(t):
'decode_stmt_list : decode_stmt decode_stmt_list' 'decode_stmt_list : decode_stmt decode_stmt_list'
(decls1, code1, has_default1) = t[1] (decls1, decode_code1, exec_code1, has_default1) = t[1]
(decls2, code2, has_default2) = t[2] (decls2, decode_code2, exec_code2, has_default2) = t[2]
if (has_default1 and has_default2): if (has_default1 and has_default2):
error(t.lineno(1), 'Two default cases in decode block') error(t.lineno(1), 'Two default cases in decode block')
t[0] = (decls1 + '\n' + decls2, code1 + '\n' + code2, t[0] = (decls1 + '\n' + decls2, decode_code1 + '\n' + decode_code2,
has_default1 or has_default2) exec_code1 + '\n' + exec_code2, has_default1 or has_default2)
# #
# Decode statement rules # Decode statement rules
@ -525,7 +518,7 @@ def p_decode_stmt_list_1(t):
# the other statements. # the other statements.
def p_decode_stmt_cpp(t): def p_decode_stmt_cpp(t):
'decode_stmt : CPPDIRECTIVE' 'decode_stmt : CPPDIRECTIVE'
t[0] = (t[1], t[1], 0) t[0] = (t[1], t[1], t[1], 0)
# A format block 'format <foo> { ... }' sets the default instruction # A format block 'format <foo> { ... }' sets the default instruction
# format used to handle instruction definitions inside the block. # format used to handle instruction definitions inside the block.
@ -555,17 +548,19 @@ def p_push_format_id(t):
def p_decode_stmt_decode(t): def p_decode_stmt_decode(t):
'decode_stmt : case_label COLON decode_block' 'decode_stmt : case_label COLON decode_block'
(label, is_default) = t[1] (label, is_default) = t[1]
(decls, code) = t[3] (decls, decode_code, exec_code) = t[3]
# just wrap the decoding code from the block as a case in the # just wrap the decoding code from the block as a case in the
# outer switch statement. # outer switch statement.
t[0] = (decls, '\n%s:\n%s' % (label, indent(code)), is_default) t[0] = (decls, '\n%s:\n%s' % (label, indent(decode_code)),
exec_code, is_default)
# Instruction definition (finally!). # Instruction definition (finally!).
def p_decode_stmt_inst(t): def p_decode_stmt_inst(t):
'decode_stmt : case_label COLON inst SEMI' 'decode_stmt : case_label COLON inst SEMI'
(label, is_default) = t[1] (label, is_default) = t[1]
(decls, code) = t[3] (decls, decode_code, exec_code) = t[3]
t[0] = (decls, '\n%s:%sbreak;' % (label, indent(code)), is_default) t[0] = (decls, '\n%s:%sbreak;' % (label, indent(decode_code)),
exec_code, is_default)
# The case label is either a list of one or more constants or 'default' # The case label is either a list of one or more constants or 'default'
def p_case_label_0(t): def p_case_label_0(t):
@ -596,12 +591,13 @@ def p_inst_0(t):
'inst : ID LPAREN arg_list RPAREN' 'inst : ID LPAREN arg_list RPAREN'
# Pass the ID and arg list to the current format class to deal with. # Pass the ID and arg list to the current format class to deal with.
currentFormat = formatStack.top() currentFormat = formatStack.top()
(decls, code) = currentFormat.defineInst(t[1], t[3], t.lineno(1)) (decls, decode_code, exec_code) = \
currentFormat.defineInst(t[1], t[3], t.lineno(1))
args = ','.join(map(str, t[3])) args = ','.join(map(str, t[3]))
args = re.sub('(?m)^', '//', args) args = re.sub('(?m)^', '//', args)
args = re.sub('^//', '', args) args = re.sub('^//', '', args)
comment = '// %s::%s(%s)\n' % (currentFormat.id, t[1], args) comment = '// %s::%s(%s)\n' % (currentFormat.id, t[1], args)
t[0] = (comment + decls, comment + code) t[0] = (comment + decls, comment + decode_code, comment + exec_code)
# Define an instruction using an explicitly specified format: # Define an instruction using an explicitly specified format:
# "<fmt>::<mnemonic>(<args>)" # "<fmt>::<mnemonic>(<args>)"
@ -611,9 +607,10 @@ def p_inst_1(t):
format = formatMap[t[1]] format = formatMap[t[1]]
except KeyError: except KeyError:
error(t.lineno(1), 'instruction format "%s" not defined.' % t[1]) error(t.lineno(1), 'instruction format "%s" not defined.' % t[1])
(decls, code) = format.defineInst(t[3], t[5], t.lineno(1)) (decls, decode_code, exec_code) = \
format.defineInst(t[3], t[5], t.lineno(1))
comment = '// %s::%s(%s)\n' % (t[1], t[3], t[5]) comment = '// %s::%s(%s)\n' % (t[1], t[3], t[5])
t[0] = (comment + decls, comment + code) t[0] = (comment + decls, comment + decode_code, comment + exec_code)
def p_arg_list_0(t): def p_arg_list_0(t):
'arg_list : empty' 'arg_list : empty'
@ -673,7 +670,8 @@ class Format:
code = ' pass\n' code = ' pass\n'
param_list = string.join(params, ", ") param_list = string.join(params, ", ")
f = 'def defInst(name, Name, ' + param_list + '):\n' + code f = 'def defInst(name, Name, ' + param_list + '):\n' + code
exec(f) c = compile(f, 'def format ' + id, 'exec')
exec(c)
self.func = defInst self.func = defInst
def defineInst(self, name, args, lineno): def defineInst(self, name, args, lineno):
@ -773,8 +771,9 @@ def error(lineno, string):
# Like error(), but include a Python stack backtrace (for processing # Like error(), but include a Python stack backtrace (for processing
# Python exceptions). # Python exceptions).
def error_bt(lineno, string): def error_bt(lineno, string):
traceback.print_exc()
print >> sys.stderr, "%s:%d: %s" % (isa_desc_filename, lineno, string) print >> sys.stderr, "%s:%d: %s" % (isa_desc_filename, lineno, string)
raise sys.exit(1)
##################################################################### #####################################################################
@ -944,7 +943,7 @@ class IntRegOperandTraits(OperandTraits):
(op_desc.dest_reg_idx, self.reg_spec) (op_desc.dest_reg_idx, self.reg_spec)
return c return c
def makeRead(self, op_desc, cpu_model): def makeRead(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext] (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
if (type == 'float' or type == 'double'): if (type == 'float' or type == 'double'):
error(0, 'Attempt to read integer register as FP') error(0, 'Attempt to read integer register as FP')
@ -955,7 +954,7 @@ class IntRegOperandTraits(OperandTraits):
return '%s = bits(xc->readIntReg(_srcRegIdx[%d]), %d, 0);\n' % \ return '%s = bits(xc->readIntReg(_srcRegIdx[%d]), %d, 0);\n' % \
(op_desc.munged_name, op_desc.src_reg_idx, size-1) (op_desc.munged_name, op_desc.src_reg_idx, size-1)
def makeWrite(self, op_desc, cpu_model): def makeWrite(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext] (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
if (type == 'float' or type == 'double'): if (type == 'float' or type == 'double'):
error(0, 'Attempt to write integer register as FP') error(0, 'Attempt to write integer register as FP')
@ -988,7 +987,7 @@ class FloatRegOperandTraits(OperandTraits):
(op_desc.dest_reg_idx, self.reg_spec) (op_desc.dest_reg_idx, self.reg_spec)
return c return c
def makeRead(self, op_desc, cpu_model): def makeRead(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext] (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
bit_select = 0 bit_select = 0
if (type == 'float'): if (type == 'float'):
@ -1007,7 +1006,7 @@ class FloatRegOperandTraits(OperandTraits):
else: else:
return '%s = %s;\n' % (op_desc.munged_name, base) return '%s = %s;\n' % (op_desc.munged_name, base)
def makeWrite(self, op_desc, cpu_model): def makeWrite(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext] (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
final_val = op_desc.munged_name final_val = op_desc.munged_name
if (type == 'float'): if (type == 'float'):
@ -1044,7 +1043,7 @@ class ControlRegOperandTraits(OperandTraits):
(op_desc.dest_reg_idx, self.reg_spec) (op_desc.dest_reg_idx, self.reg_spec)
return c return c
def makeRead(self, op_desc, cpu_model): def makeRead(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext] (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
bit_select = 0 bit_select = 0
if (type == 'float' or type == 'double'): if (type == 'float' or type == 'double'):
@ -1056,7 +1055,7 @@ class ControlRegOperandTraits(OperandTraits):
return '%s = bits(%s, %d, 0);\n' % \ return '%s = bits(%s, %d, 0);\n' % \
(op_desc.munged_name, base, size-1) (op_desc.munged_name, base, size-1)
def makeWrite(self, op_desc, cpu_model): def makeWrite(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext] (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
if (type == 'float' or type == 'double'): if (type == 'float' or type == 'double'):
error(0, 'Attempt to write control register as FP') error(0, 'Attempt to write control register as FP')
@ -1087,16 +1086,16 @@ class MemOperandTraits(OperandTraits):
c += 'uint64_t %s_write_result = 0;\n' % op_desc.base_name c += 'uint64_t %s_write_result = 0;\n' % op_desc.base_name
return c return c
def makeRead(self, op_desc, cpu_model): def makeRead(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext] (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
eff_type = 'uint%d_t' % size eff_type = 'uint%d_t' % size
return 'fault = memAccessObj->read(EA, (%s&)%s, %s_flags);\n' \ return 'fault = xc->read(EA, (%s&)%s, %s_flags);\n' \
% (eff_type, op_desc.munged_name, op_desc.base_name) % (eff_type, op_desc.munged_name, op_desc.base_name)
def makeWrite(self, op_desc, cpu_model): def makeWrite(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext] (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
eff_type = 'uint%d_t' % size eff_type = 'uint%d_t' % size
return 'fault = memAccessObj->write((%s&)%s, EA, %s_flags,' \ return 'fault = xc->write((%s&)%s, EA, %s_flags,' \
' &%s_write_result);\n' \ ' &%s_write_result);\n' \
% (eff_type, op_desc.munged_name, op_desc.base_name, % (eff_type, op_desc.munged_name, op_desc.base_name,
op_desc.base_name) op_desc.base_name)
@ -1105,10 +1104,10 @@ class NPCOperandTraits(OperandTraits):
def makeConstructor(self, op_desc): def makeConstructor(self, op_desc):
return '' return ''
def makeRead(self, op_desc, cpu_model): def makeRead(self, op_desc):
return '%s = xc->readPC() + 4;\n' % op_desc.munged_name return '%s = xc->readPC() + 4;\n' % op_desc.munged_name
def makeWrite(self, op_desc, cpu_model): def makeWrite(self, op_desc):
return 'xc->setNextPC(%s);\n' % op_desc.munged_name return 'xc->setNextPC(%s);\n' % op_desc.munged_name
@ -1172,21 +1171,17 @@ class OperandDescriptor:
def finalize(self): def finalize(self):
self.flags = self.traits.getFlags(self) self.flags = self.traits.getFlags(self)
self.constructor = self.traits.makeConstructor(self) self.constructor = self.traits.makeConstructor(self)
self.exec_decl = self.traits.makeDecl(self) self.op_decl = self.traits.makeDecl(self)
if self.is_src: if self.is_src:
self.simple_rd = self.traits.makeRead(self, 'simple') self.op_rd = self.traits.makeRead(self)
self.dtld_rd = self.traits.makeRead(self, 'dtld')
else: else:
self.simple_rd = '' self.op_rd = ''
self.dtld_rd = ''
if self.is_dest: if self.is_dest:
self.simple_wb = self.traits.makeWrite(self, 'simple') self.op_wb = self.traits.makeWrite(self)
self.dtld_wb = self.traits.makeWrite(self, 'dtld')
else: else:
self.simple_wb = '' self.op_wb = ''
self.dtld_wb = ''
class OperandDescriptorList: class OperandDescriptorList:
def __init__(self): def __init__(self):
@ -1348,32 +1343,21 @@ class CodeBlock:
self.constructor += \ self.constructor += \
'\n\t_numIntDestRegs = %d;' % self.operands.numIntDestRegs '\n\t_numIntDestRegs = %d;' % self.operands.numIntDestRegs
self.exec_decl = self.operands.concatAttrStrings('exec_decl') self.op_decl = self.operands.concatAttrStrings('op_decl')
is_mem = lambda op: op.traits.isMem() is_mem = lambda op: op.traits.isMem()
not_mem = lambda op: not op.traits.isMem() not_mem = lambda op: not op.traits.isMem()
self.simple_rd = self.operands.concatAttrStrings('simple_rd') self.op_rd = self.operands.concatAttrStrings('op_rd')
self.simple_wb = self.operands.concatAttrStrings('simple_wb') self.op_wb = self.operands.concatAttrStrings('op_wb')
self.simple_mem_rd = \ self.op_mem_rd = \
self.operands.concatSomeAttrStrings(is_mem, 'simple_rd') self.operands.concatSomeAttrStrings(is_mem, 'op_rd')
self.simple_mem_wb = \ self.op_mem_wb = \
self.operands.concatSomeAttrStrings(is_mem, 'simple_wb') self.operands.concatSomeAttrStrings(is_mem, 'op_wb')
self.simple_nonmem_rd = \ self.op_nonmem_rd = \
self.operands.concatSomeAttrStrings(not_mem, 'simple_rd') self.operands.concatSomeAttrStrings(not_mem, 'op_rd')
self.simple_nonmem_wb = \ self.op_nonmem_wb = \
self.operands.concatSomeAttrStrings(not_mem, 'simple_wb') self.operands.concatSomeAttrStrings(not_mem, 'op_wb')
self.dtld_rd = self.operands.concatAttrStrings('dtld_rd')
self.dtld_wb = self.operands.concatAttrStrings('dtld_wb')
self.dtld_mem_rd = \
self.operands.concatSomeAttrStrings(is_mem, 'dtld_rd')
self.dtld_mem_wb = \
self.operands.concatSomeAttrStrings(is_mem, 'dtld_wb')
self.dtld_nonmem_rd = \
self.operands.concatSomeAttrStrings(not_mem, 'dtld_rd')
self.dtld_nonmem_wb = \
self.operands.concatSomeAttrStrings(not_mem, 'dtld_wb')
self.flags = self.operands.concatAttrLists('flags') self.flags = self.operands.concatAttrLists('flags')
@ -1401,6 +1385,10 @@ class InstObjParams:
self.mnemonic = mnem self.mnemonic = mnem
self.class_name = class_name self.class_name = class_name
self.base_class = base_class self.base_class = base_class
self.exec_func_declarations = '''
Fault execute(SimpleCPUExecContext *, Trace::InstRecord *);
Fault execute(FullCPUExecContext *, Trace::InstRecord *);
'''
if code_block: if code_block:
for code_attr in code_block.__dict__.keys(): for code_attr in code_block.__dict__.keys():
setattr(self, code_attr, getattr(code_block, code_attr)) setattr(self, code_attr, getattr(code_block, code_attr))
@ -1431,20 +1419,48 @@ class InstObjParams:
else: else:
self.fp_enable_check = '' self.fp_enable_check = ''
def _subst(self, template):
try:
return template % self.__dict__
except KeyError, key:
raise KeyError, 'InstObjParams.subst: no definition for %s' % key
def subst(self, *args): def subst(self, *args):
result = [] result = []
for t in args: for t in args:
if not templateMap.has_key(t): try: template = templateMap[t]
except KeyError:
error(0, 'InstObjParams::subst: undefined template "%s"' % t) error(0, 'InstObjParams::subst: undefined template "%s"' % t)
try: if template.find('%(cpu_model)') != -1:
result.append(templateMap[t] % self.__dict__) tmp = ''
except KeyError, key: for cpu_model in ('SimpleCPUExecContext', 'FullCPUExecContext'):
error(0, 'InstObjParams::subst: no definition for "%s"' % key) self.cpu_model = cpu_model
tmp += self._subst(template)
result.append(tmp)
else:
result.append(self._subst(template))
if len(args) == 1: if len(args) == 1:
result = result[0] result = result[0]
return result return result
# #
# All set... read in and parse the ISA description. # Read in and parse the ISA description.
# #
yacc.parse(isa_desc) def parse_isa_desc(isa_desc_file, decoder_file):
# Arguments are the name of the ISA description (input) file and
# the name of the C++ decoder (output) file.
global isa_desc_filename, decoder_filename
isa_desc_filename = isa_desc_file
decoder_filename = decoder_file
# Suck the ISA description file in.
input = open(isa_desc_filename)
isa_desc = input.read()
input.close()
# Parse it.
yacc.parse(isa_desc)
# Called as script: get args from command line.
if __name__ == '__main__':
parse_isa_desc(sys.argv[1], sys.argv[2])

View file

@ -387,7 +387,10 @@ class ExecContext
#ifdef FULL_SYSTEM #ifdef FULL_SYSTEM
uint64_t readIpr(int idx, Fault &fault); uint64_t readIpr(int idx, Fault &fault);
Fault setIpr(int idx, uint64_t val); Fault setIpr(int idx, uint64_t val);
int readIntrFlag() { return regs.intrflag; }
void setIntrFlag(int val) { regs.intrflag = val; }
Fault hwrei(); Fault hwrei();
bool inPalMode() { return PC_PAL(regs.pc); }
void ev5_trap(Fault fault); void ev5_trap(Fault fault);
bool simPalCheck(int palFunc); bool simPalCheck(int palFunc);
#endif #endif

View file

@ -714,7 +714,7 @@ SimpleCPU::tick()
xc->func_exe_inst++; xc->func_exe_inst++;
fault = si->execute(this, xc, traceData); fault = si->execute(this, traceData);
#ifdef FULL_SYSTEM #ifdef FULL_SYSTEM
SWContext *ctx = xc->swCtx; SWContext *ctx = xc->swCtx;

View file

@ -250,6 +250,56 @@ class SimpleCPU : public BaseCPU
Fault copySrcTranslate(Addr src); Fault copySrcTranslate(Addr src);
Fault copy(Addr dest); Fault copy(Addr dest);
uint64_t readIntReg(int reg_idx) { return xc->readIntReg(reg_idx); }
float readFloatRegSingle(int reg_idx)
{ return xc->readFloatRegSingle(reg_idx); }
double readFloatRegDouble(int reg_idx)
{ return xc->readFloatRegDouble(reg_idx); }
uint64_t readFloatRegInt(int reg_idx)
{ return xc->readFloatRegInt(reg_idx); }
void setIntReg(int reg_idx, uint64_t val)
{ return xc->setIntReg(reg_idx, val); }
void setFloatRegSingle(int reg_idx, float val)
{ return xc->setFloatRegSingle(reg_idx, val); }
void setFloatRegDouble(int reg_idx, double val)
{ return xc->setFloatRegDouble(reg_idx, val); }
void setFloatRegInt(int reg_idx, uint64_t val)
{ return xc->setFloatRegInt(reg_idx, val); }
uint64_t readPC() { return xc->readPC(); }
void setNextPC(uint64_t val) { return xc->setNextPC(val); }
uint64_t readUniq() { return xc->readUniq(); }
void setUniq(uint64_t val) { return xc->setUniq(val); }
uint64_t readFpcr() { return xc->readFpcr(); }
void setFpcr(uint64_t val) { return xc->setFpcr(val); }
#ifdef FULL_SYSTEM
uint64_t readIpr(int idx, Fault &fault) { return xc->readIpr(idx, fault); }
Fault setIpr(int idx, uint64_t val) { return xc->setIpr(idx, val); }
Fault hwrei() { return xc->hwrei(); }
int readIntrFlag() { return xc->readIntrFlag(); }
void setIntrFlag(int val) { xc->setIntrFlag(val); }
bool inPalMode() { return xc->inPalMode(); }
void ev5_trap(Fault fault) { return xc->ev5_trap(fault); }
bool simPalCheck(int palFunc) { return xc->simPalCheck(palFunc); }
#else
void syscall() { xc->syscall(); }
#endif
bool misspeculating() { return xc->misspeculating(); }
ExecContext *xcBase() { return xc; }
}; };
typedef SimpleCPU SimpleCPUExecContext;
#endif // __SIMPLE_CPU_HH__ #endif // __SIMPLE_CPU_HH__

View file

@ -41,10 +41,10 @@
// forward declarations // forward declarations
class ExecContext; class ExecContext;
class SpecExecContext;
class SimpleCPU;
class FullCPU;
class DynInst; class DynInst;
typedef DynInst FullCPUExecContext;
class SimpleCPU;
typedef SimpleCPU SimpleCPUExecContext;
class SymbolTable; class SymbolTable;
namespace Trace { namespace Trace {
@ -307,13 +307,13 @@ class StaticInst : public StaticInstBase
/** /**
* Execute this instruction under SimpleCPU model. * Execute this instruction under SimpleCPU model.
*/ */
virtual Fault execute(SimpleCPU *cpu, ExecContext *xc, virtual Fault execute(SimpleCPUExecContext *xc,
Trace::InstRecord *traceData) = 0; Trace::InstRecord *traceData) = 0;
/** /**
* Execute this instruction under detailed FullCPU model. * Execute this instruction under detailed FullCPU model.
*/ */
virtual Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst, virtual Fault execute(FullCPUExecContext *xc,
Trace::InstRecord *traceData) = 0; Trace::InstRecord *traceData) = 0;
/** /**