diff --git a/arch/alpha/isa_desc b/arch/alpha/isa_desc index 0da087f97..0d1e7138f 100644 --- a/arch/alpha/isa_desc +++ b/arch/alpha/isa_desc @@ -5,7 +5,7 @@ let {{ 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 "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" @@ -143,7 +141,8 @@ declare {{ /// @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 + 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))) { @@ -152,7 +151,8 @@ declare {{ return fault; } #else - inline Fault checkFpEnableFault(ExecContext *xc) + template + inline Fault checkFpEnableFault(XC *xc) { return No_Fault; } @@ -239,44 +239,29 @@ def template BasicDeclare {{ %(constructor)s; } - Fault execute(SimpleCPU *cpu, ExecContext *xc, - 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; - } + %(exec_func_declarations)s }; }}; +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 {{ 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 def format BasicOperate(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() { } - 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 @@ -335,6 +308,12 @@ declare {{ 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 @@ -350,7 +329,7 @@ declare {{ }}; 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) {{ iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code), 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 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) }}; @@ -544,10 +526,10 @@ declare {{ #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]; @@ -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 {{ { bool fast = (FP_TRAPMODE == AlphaFP::Imprecise @@ -752,15 +616,34 @@ def template FloatingPointDecode {{ } }}; - // 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) }}; @@ -833,13 +716,11 @@ declare {{ { } - 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"); } }; /** @@ -855,13 +736,11 @@ declare {{ { } - 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"); } }; }}; @@ -869,7 +748,7 @@ declare {{ def format LoadAddress(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; } - 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; - } - - 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; - } + %(exec_func_declarations)s }; }}; +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 {{ /** @@ -1048,44 +897,29 @@ def template PrefetchDeclare {{ %(constructor)s; } - Fault execute(SimpleCPU *cpu, ExecContext *xc, - 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; - } + %(exec_func_declarations)s }; }}; +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 // Ra == 31 to detect nops @@ -1118,7 +952,8 @@ global LoadStoreBase 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). @@ -1149,7 +984,7 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '', 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) }}; @@ -1163,7 +998,7 @@ def format LoadOrNop(ea_code, memacc_code, *flags) {{ // 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') @@ -1172,12 +1007,13 @@ def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{ # 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) }}; @@ -1369,7 +1205,7 @@ def format CondBranch(code) {{ 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 {{ @@ -1379,17 +1215,20 @@ def UncondCtrlBase(name, Name, base_class, npc_expr, flags): 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) {{ @@ -1432,7 +1271,7 @@ declare {{ def format EmulatedCallPal(code) {{ iop = InstObjParams(name, Name, 'EmulatedCallPal', CodeBlock(code)) - return iop.subst('BasicDeclare', 'BasicDecode') + return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute') }}; declare {{ @@ -1483,7 +1322,7 @@ declare {{ def format CallPal(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) {{ iop = InstObjParams(name, Name, 'HwMoveIPR', CodeBlock(code)) - return iop.subst('BasicDeclare', 'BasicDecode') + return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute') }}; declare {{ @@ -1605,7 +1444,7 @@ declare {{ { } - Fault execute(SimpleCPU *cpu, ExecContext *xc, + Fault execute(SimpleCPUExecContext *xc, Trace::InstRecord *traceData) { panic("attempt to execute unimplemented instruction '%s' " @@ -1613,11 +1452,11 @@ declare {{ 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); @@ -1652,7 +1491,7 @@ declare {{ { } - Fault execute(SimpleCPU *cpu, ExecContext *xc, + Fault execute(SimpleCPUExecContext *xc, Trace::InstRecord *traceData) { if (!warned) { @@ -1663,10 +1502,10 @@ declare {{ return No_Fault; } - Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst, + Fault execute(FullCPUExecContext *xc, Trace::InstRecord *traceData) { - if (!xc->spec_mode && !warned) { + if (!xc->misspeculating() && !warned) { warn("instruction '%s' unimplemented\n", mnemonic); warned = true; } @@ -1703,12 +1542,12 @@ def template WarnUnimplDeclare {{ 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 {{ @@ -1726,7 +1565,7 @@ declare {{ { } - Fault execute(SimpleCPU *cpu, ExecContext *xc, + Fault execute(SimpleCPUExecContext *xc, Trace::InstRecord *traceData) { panic("attempt to execute unknown instruction " @@ -1734,11 +1573,11 @@ declare {{ 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; @@ -1753,7 +1592,7 @@ declare {{ }}; def format Unknown() {{ - return ('', 'return new Unknown(machInst);\n') + return ('', 'return new Unknown(machInst);\n', '') }}; declare {{ @@ -1855,7 +1694,7 @@ decode OPCODE default Unknown::unknown() { 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 = memAccessObj->copySrcTranslate(EA);}}, + {{ fault = xc->copySrcTranslate(EA);}}, IsMemRef, IsLoad, IsCopy); } @@ -1877,7 +1716,7 @@ decode OPCODE default Unknown::unknown() { 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 = memAccessObj->copy(EA);}}, + {{ fault = xc->copy(EA);}}, IsMemRef, IsStore, IsCopy); } @@ -2383,7 +2222,7 @@ decode OPCODE default Unknown::unknown() { format MiscPrefetch { 0xf800: wh64({{ EA = Rb; }}, - {{ memAccessObj->writeHint(EA, 64); }}, + {{ xc->writeHint(EA, 64); }}, IsMemRef, IsStore, WrPort); } @@ -2421,15 +2260,15 @@ decode OPCODE default Unknown::unknown() { #ifdef FULL_SYSTEM format BasicOperate { 0xe000: rc({{ - Ra = xc->regs.intrflag; + Ra = xc->readIntrFlag(); if (!xc->misspeculating()) { - xc->regs.intrflag = 0; + xc->setIntrFlag(0); } }}); 0xf000: rs({{ - Ra = xc->regs.intrflag; + Ra = xc->readIntrFlag(); 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) dopal = xc->simPalCheck(palFunc); - Annotate::Callpal(xc, palFunc); + Annotate::Callpal(xc->xcBase(), palFunc); if (dopal) { - AlphaISA::swap_palshadow(&xc->regs, true); + AlphaISA::swap_palshadow(&xc->xcBase()->regs, true); xc->setIpr(AlphaISA::IPR_EXC_ADDR, NPC); } } @@ -2519,48 +2358,48 @@ decode OPCODE default Unknown::unknown() { 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 = 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()); }}); } } @@ -2568,7 +2407,7 @@ decode OPCODE default Unknown::unknown() { 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 { @@ -2577,7 +2416,7 @@ decode OPCODE default Unknown::unknown() { }}); 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 { diff --git a/arch/isa_parser.py b/arch/isa_parser.py index 2e3c0df35..0ee9e2e2d 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -32,20 +32,10 @@ import os import sys import re import string +import traceback # get type names 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 # to the search path. Assumes we're compiling in a subdirectory # of 'build' in the current tree. @@ -225,8 +215,8 @@ def p_specification(t): isa_name = t[2] namespace = isa_name + "Inst" global_decls2 = t[3] - (inst_decls, code) = t[4] - code = indent(code) + (inst_decls, decode_code, exec_code) = t[4] + decode_code = indent(decode_code) # grab the last three path components of isa_desc_filename filename = '/'.join(isa_desc_filename.split('/')[-3:]) # if the isa_desc file defines a 'rcs_id' string, @@ -306,6 +296,8 @@ namespace %(namespace)s %(inst_decls)s +%(exec_code)s + } // namespace %(namespace)s ////////////////////// @@ -316,7 +308,7 @@ StaticInstPtr<%(isa_name)s> %(isa_name)s::decodeInst(%(isa_name)s::MachInst machInst) { using namespace %(namespace)s; -%(code)s +%(decode_code)s } // decodeInst ''' % vars() output.close() @@ -461,18 +453,19 @@ def p_param_1(t): def p_decode_block(t): 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE' 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 # default statement in decode_stmt_list if not has_default: - (default_decls, default_code) = default_defaults + (default_decls, default_decode, default_exec) = default_defaults decls += default_decls - code += default_code + decode_code += default_decode + exec_code += default_exec t[0] = (decls, ''' switch (%s) { %s } -''' % (t[2], indent(code))) +''' % (t[2], indent(decode_code)), exec_code) # The opt_default statement serves only to push the "default defaults" # 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): 'opt_default : DEFAULT inst' # push the new default - (decls, code) = t[2] - defaultStack.push((decls, '\ndefault:\n%sbreak;' % code)) + (decls, decode_code, exec_code) = t[2] + defaultStack.push((decls, '\ndefault:\n%sbreak;' % decode_code, exec_code)) # no meaningful value returned t[0] = None @@ -499,12 +492,12 @@ def p_decode_stmt_list_0(t): def p_decode_stmt_list_1(t): 'decode_stmt_list : decode_stmt decode_stmt_list' - (decls1, code1, has_default1) = t[1] - (decls2, code2, has_default2) = t[2] + (decls1, decode_code1, exec_code1, has_default1) = t[1] + (decls2, decode_code2, exec_code2, has_default2) = t[2] if (has_default1 and has_default2): error(t.lineno(1), 'Two default cases in decode block') - t[0] = (decls1 + '\n' + decls2, code1 + '\n' + code2, - has_default1 or has_default2) + t[0] = (decls1 + '\n' + decls2, decode_code1 + '\n' + decode_code2, + exec_code1 + '\n' + exec_code2, has_default1 or has_default2) # # Decode statement rules @@ -525,7 +518,7 @@ def p_decode_stmt_list_1(t): # the other statements. def p_decode_stmt_cpp(t): 'decode_stmt : CPPDIRECTIVE' - t[0] = (t[1], t[1], 0) + t[0] = (t[1], t[1], t[1], 0) # A format block 'format { ... }' sets the default instruction # 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): 'decode_stmt : case_label COLON decode_block' (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 # 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!). def p_decode_stmt_inst(t): 'decode_stmt : case_label COLON inst SEMI' (label, is_default) = t[1] - (decls, code) = t[3] - t[0] = (decls, '\n%s:%sbreak;' % (label, indent(code)), is_default) + (decls, decode_code, exec_code) = t[3] + 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' def p_case_label_0(t): @@ -596,12 +591,13 @@ def p_inst_0(t): 'inst : ID LPAREN arg_list RPAREN' # Pass the ID and arg list to the current format class to deal with. 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 = re.sub('(?m)^', '//', args) args = re.sub('^//', '', 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: # "::()" @@ -611,9 +607,10 @@ def p_inst_1(t): format = formatMap[t[1]] except KeyError: 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]) - t[0] = (comment + decls, comment + code) + t[0] = (comment + decls, comment + decode_code, comment + exec_code) def p_arg_list_0(t): 'arg_list : empty' @@ -673,7 +670,8 @@ class Format: code = ' pass\n' param_list = string.join(params, ", ") f = 'def defInst(name, Name, ' + param_list + '):\n' + code - exec(f) + c = compile(f, 'def format ' + id, 'exec') + exec(c) self.func = defInst def defineInst(self, name, args, lineno): @@ -773,8 +771,9 @@ def error(lineno, string): # Like error(), but include a Python stack backtrace (for processing # Python exceptions). def error_bt(lineno, string): + traceback.print_exc() 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) return c - def makeRead(self, op_desc, cpu_model): + def makeRead(self, op_desc): (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] if (type == 'float' or type == 'double'): 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' % \ (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] if (type == 'float' or type == 'double'): error(0, 'Attempt to write integer register as FP') @@ -988,7 +987,7 @@ class FloatRegOperandTraits(OperandTraits): (op_desc.dest_reg_idx, self.reg_spec) return c - def makeRead(self, op_desc, cpu_model): + def makeRead(self, op_desc): (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] bit_select = 0 if (type == 'float'): @@ -1007,7 +1006,7 @@ class FloatRegOperandTraits(OperandTraits): else: 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] final_val = op_desc.munged_name if (type == 'float'): @@ -1044,7 +1043,7 @@ class ControlRegOperandTraits(OperandTraits): (op_desc.dest_reg_idx, self.reg_spec) return c - def makeRead(self, op_desc, cpu_model): + def makeRead(self, op_desc): (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] bit_select = 0 if (type == 'float' or type == 'double'): @@ -1056,7 +1055,7 @@ class ControlRegOperandTraits(OperandTraits): return '%s = bits(%s, %d, 0);\n' % \ (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] if (type == 'float' or type == 'double'): 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 return c - def makeRead(self, op_desc, cpu_model): + def makeRead(self, op_desc): (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] 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) - def makeWrite(self, op_desc, cpu_model): + def makeWrite(self, op_desc): (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] 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' \ % (eff_type, op_desc.munged_name, op_desc.base_name, op_desc.base_name) @@ -1105,10 +1104,10 @@ class NPCOperandTraits(OperandTraits): def makeConstructor(self, op_desc): return '' - def makeRead(self, op_desc, cpu_model): + def makeRead(self, op_desc): 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 @@ -1172,21 +1171,17 @@ class OperandDescriptor: def finalize(self): self.flags = self.traits.getFlags(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: - self.simple_rd = self.traits.makeRead(self, 'simple') - self.dtld_rd = self.traits.makeRead(self, 'dtld') + self.op_rd = self.traits.makeRead(self) else: - self.simple_rd = '' - self.dtld_rd = '' + self.op_rd = '' if self.is_dest: - self.simple_wb = self.traits.makeWrite(self, 'simple') - self.dtld_wb = self.traits.makeWrite(self, 'dtld') + self.op_wb = self.traits.makeWrite(self) else: - self.simple_wb = '' - self.dtld_wb = '' + self.op_wb = '' class OperandDescriptorList: def __init__(self): @@ -1348,32 +1343,21 @@ class CodeBlock: self.constructor += \ '\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() not_mem = lambda op: not op.traits.isMem() - self.simple_rd = self.operands.concatAttrStrings('simple_rd') - self.simple_wb = self.operands.concatAttrStrings('simple_wb') - self.simple_mem_rd = \ - self.operands.concatSomeAttrStrings(is_mem, 'simple_rd') - self.simple_mem_wb = \ - self.operands.concatSomeAttrStrings(is_mem, 'simple_wb') - self.simple_nonmem_rd = \ - self.operands.concatSomeAttrStrings(not_mem, 'simple_rd') - self.simple_nonmem_wb = \ - self.operands.concatSomeAttrStrings(not_mem, 'simple_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.op_rd = self.operands.concatAttrStrings('op_rd') + self.op_wb = self.operands.concatAttrStrings('op_wb') + self.op_mem_rd = \ + self.operands.concatSomeAttrStrings(is_mem, 'op_rd') + self.op_mem_wb = \ + self.operands.concatSomeAttrStrings(is_mem, 'op_wb') + self.op_nonmem_rd = \ + self.operands.concatSomeAttrStrings(not_mem, 'op_rd') + self.op_nonmem_wb = \ + self.operands.concatSomeAttrStrings(not_mem, 'op_wb') self.flags = self.operands.concatAttrLists('flags') @@ -1401,6 +1385,10 @@ class InstObjParams: self.mnemonic = mnem self.class_name = class_name self.base_class = base_class + self.exec_func_declarations = ''' + Fault execute(SimpleCPUExecContext *, Trace::InstRecord *); + Fault execute(FullCPUExecContext *, Trace::InstRecord *); +''' if code_block: for code_attr in code_block.__dict__.keys(): setattr(self, code_attr, getattr(code_block, code_attr)) @@ -1431,20 +1419,48 @@ class InstObjParams: else: 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): result = [] for t in args: - if not templateMap.has_key(t): + try: template = templateMap[t] + except KeyError: error(0, 'InstObjParams::subst: undefined template "%s"' % t) - try: - result.append(templateMap[t] % self.__dict__) - except KeyError, key: - error(0, 'InstObjParams::subst: no definition for "%s"' % key) + if template.find('%(cpu_model)') != -1: + tmp = '' + for cpu_model in ('SimpleCPUExecContext', 'FullCPUExecContext'): + self.cpu_model = cpu_model + tmp += self._subst(template) + result.append(tmp) + else: + result.append(self._subst(template)) if len(args) == 1: result = result[0] 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]) diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh index f2f2c0879..7be83539a 100644 --- a/cpu/exec_context.hh +++ b/cpu/exec_context.hh @@ -387,7 +387,10 @@ class ExecContext #ifdef FULL_SYSTEM uint64_t readIpr(int idx, Fault &fault); Fault setIpr(int idx, uint64_t val); + int readIntrFlag() { return regs.intrflag; } + void setIntrFlag(int val) { regs.intrflag = val; } Fault hwrei(); + bool inPalMode() { return PC_PAL(regs.pc); } void ev5_trap(Fault fault); bool simPalCheck(int palFunc); #endif diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc index f29d9d60e..065140883 100644 --- a/cpu/simple_cpu/simple_cpu.cc +++ b/cpu/simple_cpu/simple_cpu.cc @@ -714,7 +714,7 @@ SimpleCPU::tick() xc->func_exe_inst++; - fault = si->execute(this, xc, traceData); + fault = si->execute(this, traceData); #ifdef FULL_SYSTEM SWContext *ctx = xc->swCtx; diff --git a/cpu/simple_cpu/simple_cpu.hh b/cpu/simple_cpu/simple_cpu.hh index d634753b9..4977e6992 100644 --- a/cpu/simple_cpu/simple_cpu.hh +++ b/cpu/simple_cpu/simple_cpu.hh @@ -250,6 +250,56 @@ class SimpleCPU : public BaseCPU Fault copySrcTranslate(Addr src); 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__ diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh index cdf9aefa0..57208f8e6 100644 --- a/cpu/static_inst.hh +++ b/cpu/static_inst.hh @@ -41,10 +41,10 @@ // forward declarations class ExecContext; -class SpecExecContext; -class SimpleCPU; -class FullCPU; class DynInst; +typedef DynInst FullCPUExecContext; +class SimpleCPU; +typedef SimpleCPU SimpleCPUExecContext; class SymbolTable; namespace Trace { @@ -307,13 +307,13 @@ class StaticInst : public StaticInstBase /** * Execute this instruction under SimpleCPU model. */ - virtual Fault execute(SimpleCPU *cpu, ExecContext *xc, + virtual Fault execute(SimpleCPUExecContext *xc, Trace::InstRecord *traceData) = 0; /** * 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; /**