// -*- mode:c++ -*- // Copyright (c) 2003-2005 The Regents of The University of Michigan // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer; // redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution; // neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Authors: Steve Reinhardt //////////////////////////////////////////////////////////////////// // // Alpha ISA description file. // //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// // // Output include file directives. // output header {{ #include #include #include #include "config/ss_compatible_fp.hh" #include "cpu/static_inst.hh" #include "arch/alpha/faults.hh" #include "mem/request.hh" // some constructors use MemReq flags }}; output decoder {{ #include "base/cprintf.hh" #include "base/fenv.hh" #include "base/loader/symtab.hh" #include "config/ss_compatible_fp.hh" #include "cpu/exec_context.hh" // for Jump::branchTarget() #include using namespace AlphaISA; }}; output exec {{ #include #if FULL_SYSTEM #include "sim/pseudo_inst.hh" #endif #include "base/fenv.hh" #include "config/ss_compatible_fp.hh" #include "cpu/base.hh" #include "cpu/exetrace.hh" #include "sim/sim_exit.hh" #include "mem/packet_impl.hh" using namespace AlphaISA; }}; //////////////////////////////////////////////////////////////////// // // Namespace statement. Everything below this line will be in the // AlphaISAInst namespace. // namespace AlphaISA; //////////////////////////////////////////////////////////////////// // // Bitfield definitions. // // Universal (format-independent) fields def bitfield PALMODE <32:32>; def bitfield OPCODE <31:26>; def bitfield RA <25:21>; def bitfield RB <20:16>; // Memory format def signed bitfield MEMDISP <15: 0>; // displacement def bitfield MEMFUNC <15: 0>; // function code (same field, unsigned) // Memory-format jumps def bitfield JMPFUNC <15:14>; // function code (disp<15:14>) def bitfield JMPHINT <13: 0>; // tgt Icache idx hint (disp<13:0>) // Branch format def signed bitfield BRDISP <20: 0>; // displacement // Integer operate format(s>; def bitfield INTIMM <20:13>; // integer immediate (literal) def bitfield IMM <12:12>; // immediate flag def bitfield INTFUNC <11: 5>; // function code def bitfield RC < 4: 0>; // dest reg // Floating-point operate format def bitfield FA <25:21>; def bitfield FB <20:16>; def bitfield FP_FULLFUNC <15: 5>; // complete function code def bitfield FP_TRAPMODE <15:13>; // trapping mode def bitfield FP_ROUNDMODE <12:11>; // rounding mode def bitfield FP_TYPEFUNC <10: 5>; // type+func: handiest for decoding def bitfield FP_SRCTYPE <10: 9>; // source reg type def bitfield FP_SHORTFUNC < 8: 5>; // short function code def bitfield FP_SHORTFUNC_TOP2 <8:7>; // top 2 bits of short func code def bitfield FC < 4: 0>; // dest reg // PALcode format def bitfield PALFUNC <25: 0>; // function code // EV5 PAL instructions: // HW_LD/HW_ST def bitfield HW_LDST_PHYS <15>; // address is physical def bitfield HW_LDST_ALT <14>; // use ALT_MODE IPR def bitfield HW_LDST_WRTCK <13>; // HW_LD only: fault if no write acc def bitfield HW_LDST_QUAD <12>; // size: 0=32b, 1=64b def bitfield HW_LDST_VPTE <11>; // HW_LD only: is PTE fetch def bitfield HW_LDST_LOCK <10>; // HW_LD only: is load locked def bitfield HW_LDST_COND <10>; // HW_ST only: is store conditional def signed bitfield HW_LDST_DISP <9:0>; // signed displacement // HW_REI def bitfield HW_REI_TYP <15:14>; // type: stalling vs. non-stallingk def bitfield HW_REI_MBZ <13: 0>; // must be zero // HW_MTPR/MW_MFPR def bitfield HW_IPR_IDX <15:0>; // IPR index // M5 instructions def bitfield M5FUNC <7:0>; def operand_types {{ 'sb' : ('signed int', 8), 'ub' : ('unsigned int', 8), 'sw' : ('signed int', 16), 'uw' : ('unsigned int', 16), 'sl' : ('signed int', 32), 'ul' : ('unsigned int', 32), 'sq' : ('signed int', 64), 'uq' : ('unsigned int', 64), 'sf' : ('float', 32), 'df' : ('float', 64) }}; def operands {{ # Int regs default to unsigned, but code should not count on this. # For clarity, descriptions that depend on unsigned behavior should # explicitly specify '.uq'. 'Ra': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RA] : RA', 'IsInteger', 1), 'Rb': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RB] : RB', 'IsInteger', 2), 'Rc': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RC] : RC', 'IsInteger', 3), 'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1), 'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2), 'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3), 'Mem': ('Mem', 'uq', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4), 'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4), 'Runiq': ('ControlReg', 'uq', 'TheISA::Uniq_DepTag', None, 1), 'FPCR': (' ControlReg', 'uq', 'TheISA::Fpcr_DepTag', None, 1), # The next two are hacks for non-full-system call-pal emulation 'R0': ('IntReg', 'uq', '0', None, 1), 'R16': ('IntReg', 'uq', '16', None, 1), 'R17': ('IntReg', 'uq', '17', None, 1), 'R18': ('IntReg', 'uq', '18', None, 1) }}; //////////////////////////////////////////////////////////////////// // // Basic instruction classes/templates/formats etc. // output header {{ // uncomment the following to get SimpleScalar-compatible disassembly // (useful for diffing output traces). // #define SS_COMPATIBLE_DISASSEMBLY /** * Base class for all Alpha static instructions. */ class AlphaStaticInst : public StaticInst { protected: /// Make AlphaISA register dependence tags directly visible in /// this class and derived classes. Maybe these should really /// live here and not in the AlphaISA namespace. enum DependenceTags { FP_Base_DepTag = AlphaISA::FP_Base_DepTag, Fpcr_DepTag = AlphaISA::Fpcr_DepTag, Uniq_DepTag = AlphaISA::Uniq_DepTag, Lock_Flag_DepTag = AlphaISA::Lock_Flag_DepTag, Lock_Addr_DepTag = AlphaISA::Lock_Addr_DepTag, IPR_Base_DepTag = AlphaISA::IPR_Base_DepTag }; /// Constructor. AlphaStaticInst(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : StaticInst(mnem, _machInst, __opClass) { } /// Print a register name for disassembly given the unique /// dependence tag number (FP or int). void printReg(std::ostream &os, int reg) const; std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; }}; output decoder {{ void AlphaStaticInst::printReg(std::ostream &os, int reg) const { if (reg < FP_Base_DepTag) { ccprintf(os, "r%d", reg); } else { ccprintf(os, "f%d", reg - FP_Base_DepTag); } } std::string AlphaStaticInst::generateDisassembly(Addr pc, const SymbolTable *symtab) const { std::stringstream ss; ccprintf(ss, "%-10s ", mnemonic); // just print the first two source regs... if there's // a third one, it's a read-modify-write dest (Rc), // e.g. for CMOVxx if (_numSrcRegs > 0) { printReg(ss, _srcRegIdx[0]); } if (_numSrcRegs > 1) { ss << ","; printReg(ss, _srcRegIdx[1]); } // just print the first dest... if there's a second one, // it's generally implicit if (_numDestRegs > 0) { if (_numSrcRegs > 0) ss << ","; printReg(ss, _destRegIdx[0]); } return ss.str(); } }}; // Declarations for execute() methods. def template BasicExecDeclare {{ Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const; }}; // Basic instruction class declaration template. def template BasicDeclare {{ /** * Static instruction class for "%(mnemonic)s". */ class %(class_name)s : public %(base_class)s { public: /// Constructor. %(class_name)s(ExtMachInst machInst); %(BasicExecDeclare)s }; }}; // Basic instruction class constructor template. def template BasicConstructor {{ inline %(class_name)s::%(class_name)s(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) { %(constructor)s; } }}; // Basic instruction class execute method template. def template BasicExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { Fault fault = NoFault; %(fp_enable_check)s; %(op_decl)s; %(op_rd)s; %(code)s; if (fault == NoFault) { %(op_wb)s; } return fault; } }}; // Basic decode template. def template BasicDecode {{ return new %(class_name)s(machInst); }}; // Basic decode template, passing mnemonic in as string arg to constructor. def template BasicDecodeWithMnemonic {{ return new %(class_name)s("%(mnemonic)s", machInst); }}; // The most basic instruction format... used only for a few misc. insts def format BasicOperate(code, *flags) {{ iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code), flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) exec_output = BasicExecute.subst(iop) }}; //////////////////////////////////////////////////////////////////// // // Nop // output header {{ /** * Static instruction class for no-ops. This is a leaf class. */ class Nop : public AlphaStaticInst { /// Disassembly of original instruction. const std::string originalDisassembly; public: /// Constructor Nop(const std::string _originalDisassembly, ExtMachInst _machInst) : AlphaStaticInst("nop", _machInst, No_OpClass), originalDisassembly(_originalDisassembly) { flags[IsNop] = true; } ~Nop() { } std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; %(BasicExecDeclare)s }; /// Helper function for decoding nops. Substitute Nop object /// for original inst passed in as arg (and delete latter). static inline AlphaStaticInst * makeNop(AlphaStaticInst *inst) { AlphaStaticInst *nop = new Nop(inst->disassemble(0), inst->machInst); delete inst; return nop; } }}; output decoder {{ std::string Nop::generateDisassembly(Addr pc, const SymbolTable *symtab) const { #ifdef SS_COMPATIBLE_DISASSEMBLY return originalDisassembly; #else return csprintf("%-10s (%s)", "nop", originalDisassembly); #endif } }}; output exec {{ Fault Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *) const { return NoFault; } }}; // integer & FP operate instructions use Rc as dest, so check for // Rc == 31 to detect nops def template OperateNopCheckDecode {{ { AlphaStaticInst *i = new %(class_name)s(machInst); if (RC == 31) { i = makeNop(i); } return i; } }}; // Like BasicOperate format, but generates NOP if RC/FC == 31 def format BasicOperateWithNopCheck(code, *opt_args) {{ iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code), opt_args) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = OperateNopCheckDecode.subst(iop) exec_output = BasicExecute.subst(iop) }}; // Integer instruction templates, formats, etc. ##include "int.isa" // Floating-point instruction templates, formats, etc. ##include "fp.isa" // Memory instruction templates, formats, etc. ##include "mem.isa" // Branch/jump instruction templates, formats, etc. ##include "branch.isa" // PAL instruction templates, formats, etc. ##include "pal.isa" // Opcdec fault instruction templates, formats, etc. ##include "opcdec.isa" // Unimplemented instruction templates, formats, etc. ##include "unimp.isa" // Unknown instruction templates, formats, etc. ##include "unknown.isa" // Execution utility functions ##include "util.isa" // The actual decoder ##include "decoder.isa"