diff options
Diffstat (limited to 'src/arch/arm/isa/formats')
-rw-r--r-- | src/arch/arm/isa/formats/basic.isa | 103 | ||||
-rw-r--r-- | src/arch/arm/isa/formats/branch.isa | 307 | ||||
-rw-r--r-- | src/arch/arm/isa/formats/formats.isa | 57 | ||||
-rw-r--r-- | src/arch/arm/isa/formats/fp.isa | 150 | ||||
-rw-r--r-- | src/arch/arm/isa/formats/macromem.isa | 389 | ||||
-rw-r--r-- | src/arch/arm/isa/formats/mem.isa | 593 | ||||
-rw-r--r-- | src/arch/arm/isa/formats/pred.isa | 402 | ||||
-rw-r--r-- | src/arch/arm/isa/formats/unimp.isa | 144 | ||||
-rw-r--r-- | src/arch/arm/isa/formats/unknown.isa | 84 | ||||
-rw-r--r-- | src/arch/arm/isa/formats/util.isa | 217 |
10 files changed, 2446 insertions, 0 deletions
diff --git a/src/arch/arm/isa/formats/basic.isa b/src/arch/arm/isa/formats/basic.isa new file mode 100644 index 000000000..d154b987c --- /dev/null +++ b/src/arch/arm/isa/formats/basic.isa @@ -0,0 +1,103 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +// 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(MachInst machInst); + %(BasicExecDeclare)s + }; +}}; + +// Basic instruction class constructor template. +def template BasicConstructor {{ + inline %(class_name)s::%(class_name)s(MachInst 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); +}}; + +// Definitions of execute methods that panic. +def template BasicExecPanic {{ +Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const +{ + panic("Execute method called when it shouldn't!"); +} +}}; + +// The most basic instruction format... +def format BasicOp(code, *flags) {{ + iop = InstObjParams(name, Name, 'ArmStaticInst', code, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; diff --git a/src/arch/arm/isa/formats/branch.isa b/src/arch/arm/isa/formats/branch.isa new file mode 100644 index 000000000..40aa4a952 --- /dev/null +++ b/src/arch/arm/isa/formats/branch.isa @@ -0,0 +1,307 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Control transfer instructions +// + +output header {{ + +#include <iostream> + + /** + * Base class for instructions whose disassembly is not purely a + * function of the machine instruction (i.e., it depends on the + * PC). This class overrides the disassemble() method to check + * the PC and symbol table values before re-using a cached + * disassembly string. This is necessary for branches and jumps, + * where the disassembly string includes the target address (which + * may depend on the PC and/or symbol table). + */ + class PCDependentDisassembly : public PredOp + { + protected: + /// Cached program counter from last disassembly + mutable Addr cachedPC; + + /// Cached symbol table pointer from last disassembly + mutable const SymbolTable *cachedSymtab; + + /// Constructor + PCDependentDisassembly(const char *mnem, MachInst _machInst, + OpClass __opClass) + : PredOp(mnem, _machInst, __opClass), + cachedPC(0), cachedSymtab(0) + { + } + + const std::string & + disassemble(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for branches (PC-relative control transfers), + * conditional or unconditional. + */ + class Branch : public PCDependentDisassembly + { + protected: + /// target address (signed) Displacement . + int32_t disp; + + /// Constructor. + Branch(const char *mnem, MachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + disp(OFFSET << 2) + { + //If Bit 26 is 1 then Sign Extend + if ( (disp & 0x02000000) > 0 ) { + disp |= 0xFC000000; + } + } + + Addr branchTarget(Addr branchPC) const; + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for branch and exchange instructions on the ARM + */ + class BranchExchange : public PredOp + { + protected: + /// Constructor + BranchExchange(const char *mnem, MachInst _machInst, + OpClass __opClass) + : PredOp(mnem, _machInst, __opClass) + { + } + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + + /** + * Base class for jumps (register-indirect control transfers). In + * the Arm ISA, these are always unconditional. + */ + class Jump : public PCDependentDisassembly + { + protected: + + /// Displacement to target address (signed). + int32_t disp; + + uint32_t target; + + public: + /// Constructor + Jump(const char *mnem, MachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + disp(OFFSET << 2) + { + } + + Addr branchTarget(ThreadContext *tc) const; + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + Addr + Branch::branchTarget(Addr branchPC) const + { + return branchPC + 8 + disp; + } + + Addr + Jump::branchTarget(ThreadContext *tc) const + { + Addr NPC = tc->readPC() + 8; + uint64_t Rb = tc->readIntReg(_srcRegIdx[0]); + return (Rb & ~3) | (NPC & 1); + } + + const std::string & + PCDependentDisassembly::disassemble(Addr pc, + const SymbolTable *symtab) const + { + if (!cachedDisassembly || + pc != cachedPC || symtab != cachedSymtab) + { + if (cachedDisassembly) + delete cachedDisassembly; + + cachedDisassembly = + new std::string(generateDisassembly(pc, symtab)); + cachedPC = pc; + cachedSymtab = symtab; + } + + return *cachedDisassembly; + } + + std::string + Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + Addr target = pc + 8 + disp; + + std::string str; + if (symtab && symtab->findSymbol(target, str)) + ss << str; + else + ccprintf(ss, "0x%x", target); + + return ss.str(); + } + + std::string + BranchExchange::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + } + + return ss.str(); + } + + std::string + Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + return ss.str(); + } +}}; + +def format Branch(code,*opt_flags) {{ + + #Build Instruction Flags + #Use Link & Likely Flags to Add Link/Condition Code + inst_flags = ('IsDirectControl', ) + for x in opt_flags: + if x == 'Link': + code += 'LR = NPC;\n' + else: + inst_flags += (x, ) + + #Take into account uncond. branch instruction + if 'cond == 1' in code: + inst_flags += ('IsUnCondControl', ) + else: + inst_flags += ('IsCondControl', ) + + icode = 'if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) {\n' + icode += code + icode += ' NPC = NPC + 4 + disp;\n' + icode += '} else {\n' + icode += ' NPC = NPC;\n' + icode += '};\n' + + code = icode + + iop = InstObjParams(name, Name, 'Branch', code, inst_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +def format BranchExchange(code,*opt_flags) {{ + #Build Instruction Flags + #Use Link & Likely Flags to Add Link/Condition Code + inst_flags = ('IsIndirectControl', ) + for x in opt_flags: + if x == 'Link': + code += 'LR = NPC;\n' + else: + inst_flags += (x, ) + + #Take into account uncond. branch instruction + if 'cond == 1' in code: + inst_flags += ('IsUnCondControl', ) + else: + inst_flags += ('IsCondControl', ) + + #Condition code + + icode = 'if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) {\n' + icode += code + icode += ' NPC = Rm & 0xfffffffe; // Masks off bottom bit\n' + icode += '} else {\n' + icode += ' NPC = NPC;\n' + icode += '};\n' + + code = icode + + iop = InstObjParams(name, Name, 'BranchExchange', code, inst_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +def format Jump(code, *opt_flags) {{ + #Build Instruction Flags + #Use Link Flag to Add Link Code + inst_flags = ('IsIndirectControl', 'IsUncondControl') + for x in opt_flags: + if x == 'Link': + code = 'LR = NPC;\n' + code + elif x == 'ClearHazards': + code += '/* Code Needed to Clear Execute & Inst Hazards */\n' + else: + inst_flags += (x, ) + + iop = InstObjParams(name, Name, 'Jump', code, inst_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) + #exec_output = PredOpExecute.subst(iop) +}}; + + diff --git a/src/arch/arm/isa/formats/formats.isa b/src/arch/arm/isa/formats/formats.isa new file mode 100644 index 000000000..5f6faa741 --- /dev/null +++ b/src/arch/arm/isa/formats/formats.isa @@ -0,0 +1,57 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//Templates from this format are used later +//Include the basic format +##include "basic.isa" + +//Include support for predicated instructions +##include "pred.isa" + +//Include utility functions +##include "util.isa" + +//Include the float formats +##include "fp.isa" + +//Include the mem format +##include "mem.isa" + +//Include the macro-mem format +##include "macromem.isa" + +//Include the branch format +##include "branch.isa" + +//Include the unimplemented format +##include "unimp.isa" + +//Include the unknown format +##include "unknown.isa" diff --git a/src/arch/arm/isa/formats/fp.isa b/src/arch/arm/isa/formats/fp.isa new file mode 100644 index 000000000..682c76079 --- /dev/null +++ b/src/arch/arm/isa/formats/fp.isa @@ -0,0 +1,150 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Floating Point operate instructions +// + +output header {{ + + /** + * Base class for FP operations. + */ + class FPAOp : public PredOp + { + protected: + + /// Constructor + FPAOp(const char *mnem, MachInst _machInst, OpClass __opClass) : PredOp(mnem, _machInst, __opClass) + { + } + + //std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + +}}; + +output exec {{ +}}; + +def template FPAExecute {{ + 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 (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode) && + fault == NoFault) + { + %(op_wb)s; + } + + return fault; + } +}}; + +def template FloatDoubleDecode {{ + { + ArmStaticInst *i = NULL; + switch (OPCODE_19 << 1 | OPCODE_7) + { + case 0: + i = (ArmStaticInst *)new %(class_name)sS(machInst); + break; + case 1: + i = (ArmStaticInst *)new %(class_name)sD(machInst); + break; + case 2: + case 3: + default: + panic("Cannot decode float/double nature of the instruction"); + } + return i; + } +}}; + +// Primary format for float point operate instructions: +def format FloatOp(code, *flags) {{ + orig_code = code + + cblk = code + iop = InstObjParams(name, Name, 'FPAOp', cblk, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + exec_output = FPAExecute.subst(iop) + + sng_cblk = code + sng_iop = InstObjParams(name, Name+'S', 'FPAOp', sng_cblk, flags) + header_output += BasicDeclare.subst(sng_iop) + decoder_output += BasicConstructor.subst(sng_iop) + exec_output += FPAExecute.subst(sng_iop) + + dbl_code = re.sub(r'\.sf', '.df', orig_code) + + dbl_cblk = dbl_code + dbl_iop = InstObjParams(name, Name+'D', 'FPAOp', dbl_cblk, flags) + header_output += BasicDeclare.subst(dbl_iop) + decoder_output += BasicConstructor.subst(dbl_iop) + exec_output += FPAExecute.subst(dbl_iop) + + decode_block = FloatDoubleDecode.subst(iop) +}}; + +let {{ + calcFPCcCode = ''' + uint16_t _in, _iz, _ic, _iv; + + _in = %(fReg1)s < %(fReg2)s; + _iz = %(fReg1)s == %(fReg2)s; + _ic = %(fReg1)s >= %(fReg2)s; + _iv = (isnan(%(fReg1)s) || isnan(%(fReg2)s)) & 1; + + Cpsr = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 | + (Cpsr & 0x0FFFFFFF); + ''' +}}; + +def format FloatCmp(fReg1, fReg2, *flags) {{ + code = calcFPCcCode % vars() + iop = InstObjParams(name, Name, 'FPAOp', code, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = FPAExecute.subst(iop) +}}; + + diff --git a/src/arch/arm/isa/formats/macromem.isa b/src/arch/arm/isa/formats/macromem.isa new file mode 100644 index 000000000..bc055d74e --- /dev/null +++ b/src/arch/arm/isa/formats/macromem.isa @@ -0,0 +1,389 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Macro Memory-format instructions +// + +output header {{ + + /** + * Arm Macro Memory operations like LDM/STM + */ + class ArmMacroMemoryOp : public PredMacroOp + { + protected: + /// Memory request flags. See mem_req_base.hh. + unsigned memAccessFlags; + /// Pointer to EAComp object. + const StaticInstPtr eaCompPtr; + /// Pointer to MemAcc object. + const StaticInstPtr memAccPtr; + + uint32_t reglist; + uint32_t ones; + uint32_t puswl, + prepost, + up, + psruser, + writeback, + loadop; + + ArmMacroMemoryOp(const char *mnem, MachInst _machInst, OpClass __opClass, + StaticInstPtr _eaCompPtr = nullStaticInstPtr, + StaticInstPtr _memAccPtr = nullStaticInstPtr) + : PredMacroOp(mnem, _machInst, __opClass), + memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr), + reglist(REGLIST), ones(0), puswl(PUSWL), prepost(PREPOST), up(UP), + psruser(PSRUSER), writeback(WRITEBACK), loadop(LOADOP) + { + ones = number_of_ones(reglist); + numMicroops = ones + writeback + 1; + // Remember that writeback adds a uop + microOps = new StaticInstPtr[numMicroops]; + } + }; + + /** + * Arm Macro FPA operations to fix ldfd and stfd instructions + */ + class ArmMacroFPAOp : public PredMacroOp + { + protected: + uint32_t puswl, + prepost, + up, + psruser, + writeback, + loadop; + int32_t disp8; + + ArmMacroFPAOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : PredMacroOp(mnem, _machInst, __opClass), + puswl(PUSWL), prepost(PREPOST), up(UP), + psruser(PSRUSER), writeback(WRITEBACK), loadop(LOADOP), + disp8(IMMED_7_0 << 2) + { + numMicroops = 3 + writeback; + microOps = new StaticInstPtr[numMicroops]; + } + }; + + /** + * Arm Macro FM operations to fix lfm and sfm + */ + class ArmMacroFMOp : public PredMacroOp + { + protected: + uint32_t punwl, + prepost, + up, + n1bit, + writeback, + loadop, + n0bit, + count; + int32_t disp8; + + ArmMacroFMOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : PredMacroOp(mnem, _machInst, __opClass), + punwl(PUNWL), prepost(PREPOST), up(UP), + n1bit(OPCODE_22), writeback(WRITEBACK), loadop(LOADOP), + n0bit(OPCODE_15), disp8(IMMED_7_0 << 2) + { + // Transfer 1-4 registers based on n1 and n0 bits (with 00 repr. 4) + count = (n1bit << 1) | n0bit; + if (count == 0) + count = 4; + numMicroops = (3*count) + writeback; + microOps = new StaticInstPtr[numMicroops]; + } + }; + + +}}; + + +output decoder {{ +}}; + +def template MacroStoreDeclare {{ + /** + * Static instructions class for a store multiple instruction + */ + class %(class_name)s : public %(base_class)s + { + public: + // Constructor + %(class_name)s(MachInst machInst); + %(BasicExecDeclare)s + }; +}}; + +def template MacroStoreConstructor {{ + inline %(class_name)s::%(class_name)s(MachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(constructor)s; + uint32_t regs_to_handle = reglist; + uint32_t j = 0, + start_addr = 0, + end_addr = 0; + + switch (puswl) + { + case 0x01: // L ldmda_l + start_addr = (ones << 2) - 4; + end_addr = 0; + break; + case 0x03: // WL ldmda_wl + start_addr = (ones << 2) - 4; + end_addr = 0; + break; + case 0x08: // U stmia_u + start_addr = 0; + end_addr = (ones << 2) - 4; + break; + case 0x09: // U L ldmia_ul + start_addr = 0; + end_addr = (ones << 2) - 4; + break; + case 0x0b: // U WL ldmia + start_addr = 0; + end_addr = (ones << 2) - 4; + break; + case 0x11: // P L ldmdb + start_addr = (ones << 2); // U-bit is already 0 for subtract + end_addr = 4; // negative 4 + break; + case 0x12: // P W stmdb + start_addr = (ones << 2); // U-bit is already 0 for subtract + end_addr = 4; // negative 4 + break; + case 0x18: // PU stmib + start_addr = 4; + end_addr = (ones << 2) + 4; + break; + case 0x19: // PU L ldmib + start_addr = 4; + end_addr = (ones << 2) + 4; + break; + default: + panic("Unhandled Load/Store Multiple Instruction"); + break; + } + + //TODO - Add addi_uop/subi_uop here to create starting addresses + //Just using addi with 0 offset makes a "copy" of Rn for our use + uint32_t newMachInst = 0; + newMachInst = machInst & 0xffff0000; + microOps[0] = new Addi_uop(newMachInst); + + for (int i = 1; i < ones+1; i++) + { + // Get next available bit for transfer + while (! ( regs_to_handle & (1<<j))) + j++; + regs_to_handle &= ~(1<<j); + + microOps[i] = gen_ldrstr_uop(machInst, loadop, j, start_addr); + + if (up) + start_addr += 4; + else + start_addr -= 4; + } + + /* TODO: Take a look at how these 2 values should meet together + if (start_addr != (end_addr - 4)) + { + fprintf(stderr, "start_addr: %d\n", start_addr); + fprintf(stderr, "end_addr: %d\n", end_addr); + panic("start_addr does not meet end_addr"); + } + */ + + if (writeback) + { + uint32_t newMachInst = machInst & 0xf0000000; + uint32_t rn = (machInst >> 16) & 0x0f; + // 3322 2222 2222 1111 1111 11 + // 1098 7654 3210 9876 5432 1098 7654 3210 + // COND 0010 0100 [RN] [RD] 0000 [ IMM ] + // sub rn, rn, imm + newMachInst |= 0x02400000; + newMachInst |= ((rn << 16) | (rn << 12)); + newMachInst |= (ones << 2); + if (up) + { + microOps[numMicroops-1] = new Addi_rd_uop(newMachInst); + } + else + { + microOps[numMicroops-1] = new Subi_rd_uop(newMachInst); + } + } + microOps[numMicroops-1]->setLastMicroop(); + } + +}}; + +def template MacroStoreExecute {{ + 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; + } +}}; + +def template MacroFPAConstructor {{ + inline %(class_name)s::%(class_name)s(MachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(constructor)s; + + uint32_t start_addr = 0; + + if (prepost) + start_addr = disp8; + else + start_addr = 0; + + emit_ldfstf_uops(microOps, 0, machInst, loadop, up, start_addr); + + if (writeback) + { + uint32_t newMachInst = machInst & 0xf0000000; + uint32_t rn = (machInst >> 16) & 0x0f; + // 3322 2222 2222 1111 1111 11 + // 1098 7654 3210 9876 5432 1098 7654 3210 + // COND 0010 0100 [RN] [RD] 0000 [ IMM ] + // sub rn, rn, imm + newMachInst |= 0x02400000; + newMachInst |= ((rn << 16) | (rn << 12)); + if (up) + { + newMachInst |= disp8; + microOps[numMicroops-1] = new Addi_rd_uop(newMachInst); + } + else + { + newMachInst |= disp8; + microOps[numMicroops-1] = new Subi_rd_uop(newMachInst); + } + } + microOps[numMicroops-1]->setLastMicroop(); + } + +}}; + + +def template MacroFMConstructor {{ + inline %(class_name)s::%(class_name)s(MachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(constructor)s; + + uint32_t start_addr = 0; + + if (prepost) + start_addr = disp8; + else + start_addr = 0; + + for (int i = 0; i < count; i++) + { + emit_ldfstf_uops(microOps, 3*i, machInst, loadop, up, start_addr); + } + + if (writeback) + { + uint32_t newMachInst = machInst & 0xf0000000; + uint32_t rn = (machInst >> 16) & 0x0f; + // 3322 2222 2222 1111 1111 11 + // 1098 7654 3210 9876 5432 1098 7654 3210 + // COND 0010 0100 [RN] [RD] 0000 [ IMM ] + // sub rn, rn, imm + newMachInst |= 0x02400000; + newMachInst |= ((rn << 16) | (rn << 12)); + if (up) + { + newMachInst |= disp8; + microOps[numMicroops-1] = new Addi_rd_uop(newMachInst); + } + else + { + newMachInst |= disp8; + microOps[numMicroops-1] = new Subi_rd_uop(newMachInst); + } + } + microOps[numMicroops-1]->setLastMicroop(); + } + +}}; + + +def format ArmMacroStore(code, mem_flags = [], inst_flag = [], *opt_flags) {{ + iop = InstObjParams(name, Name, 'ArmMacroMemoryOp', code, opt_flags) + header_output = MacroStoreDeclare.subst(iop) + decoder_output = MacroStoreConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = MacroStoreExecute.subst(iop) +}}; + +def format ArmMacroFPAOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{ + iop = InstObjParams(name, Name, 'ArmMacroFPAOp', code, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = MacroFPAConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = PredOpExecute.subst(iop) +}}; + +def format ArmMacroFMOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{ + iop = InstObjParams(name, Name, 'ArmMacroFMOp', code, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = MacroFMConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = PredOpExecute.subst(iop) +}}; + + + diff --git a/src/arch/arm/isa/formats/mem.isa b/src/arch/arm/isa/formats/mem.isa new file mode 100644 index 000000000..0c736f947 --- /dev/null +++ b/src/arch/arm/isa/formats/mem.isa @@ -0,0 +1,593 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Memory-format instructions +// + +output header {{ + /** + * Base class for general Arm memory-format instructions. + */ + class Memory : public PredOp + { + protected: + + /// Memory request flags. See mem_req_base.hh. + unsigned memAccessFlags; + /// Pointer to EAComp object. + const StaticInstPtr eaCompPtr; + /// Pointer to MemAcc object. + const StaticInstPtr memAccPtr; + + /// Displacement for EA calculation (signed). + int32_t disp; + int32_t disp8; + int32_t up; + int32_t hilo, + shift_size, + shift; + + /// Constructor + Memory(const char *mnem, MachInst _machInst, OpClass __opClass, + StaticInstPtr _eaCompPtr = nullStaticInstPtr, + StaticInstPtr _memAccPtr = nullStaticInstPtr) + : PredOp(mnem, _machInst, __opClass), + memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr), + disp(IMMED_11_0), disp8(IMMED_7_0 << 2), up(UP), + hilo((IMMED_HI_11_8 << 4) | IMMED_LO_3_0), + shift_size(SHIFT_SIZE), shift(SHIFT) + { + // When Up is not set, then we must subtract by the displacement + if (!up) + { + disp = -disp; + disp8 = -disp8; + hilo = -hilo; + } + } + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + + public: + + const StaticInstPtr &eaCompInst() const { return eaCompPtr; } + const StaticInstPtr &memAccInst() const { return memAccPtr; } + }; + + /** + * Base class for a few miscellaneous memory-format insts + * that don't interpret the disp field + */ + class MemoryNoDisp : public Memory + { + protected: + /// Constructor + MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + StaticInstPtr _eaCompPtr = nullStaticInstPtr, + StaticInstPtr _memAccPtr = nullStaticInstPtr) + : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr) + { + } + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + + +output decoder {{ + std::string + Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return csprintf("%-10s", mnemonic); + } + + std::string + MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return csprintf("%-10s", mnemonic); + } +}}; + +def template LoadStoreDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + protected: + + /** + * "Fake" effective address computation class for "%(mnemonic)s". + */ + class EAComp : public %(base_class)s + { + public: + /// Constructor + EAComp(MachInst machInst); + + %(BasicExecDeclare)s + }; + + /** + * "Fake" memory access instruction class for "%(mnemonic)s". + */ + class MemAcc : public %(base_class)s + { + public: + /// Constructor + MemAcc(MachInst machInst); + + %(BasicExecDeclare)s + }; + + public: + + /// Constructor. + %(class_name)s(MachInst machInst); + + %(BasicExecDeclare)s + + %(InitiateAccDeclare)s + + %(CompleteAccDeclare)s + }; +}}; + + +def template InitiateAccDeclare {{ + Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + + +def template CompleteAccDeclare {{ + Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + + +def template EACompConstructor {{ + inline %(class_name)s::EAComp::EAComp(MachInst machInst) + : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp) + { + %(constructor)s; + } +}}; + + +def template MemAccConstructor {{ + inline %(class_name)s::MemAcc::MemAcc(MachInst machInst) + : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s) + { + %(constructor)s; + } +}}; + + +def template LoadStoreConstructor {{ + inline %(class_name)s::%(class_name)s(MachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + new EAComp(machInst), new MemAcc(machInst)) + { + %(constructor)s; + } +}}; + + +def template EACompExecute {{ + Fault + %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + if (fault == NoFault) { + %(op_wb)s; + xc->setEA(EA); + } + } + + return fault; + } +}}; + +def template LoadMemAccExecute {{ + Fault + %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + EA = xc->getEA(); + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + if (fault == NoFault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); + %(memacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + return fault; + } +}}; + + +def template LoadExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + if (fault == NoFault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); + %(memacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + return fault; + } +}}; + + +def template LoadInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_src_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + if (fault == NoFault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags); + } + } + + return fault; + } +}}; + + +def template LoadCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + // ARM instructions will not have a pkt if the predicate is false + Mem = pkt->get<typeof(Mem)>(); + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + return fault; + } +}}; + + +def template StoreMemAccExecute {{ + Fault + %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + EA = xc->getEA(); + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, NULL); + if (traceData) { traceData->setData(Mem); } + } + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + return fault; + } +}}; + + +def template StoreExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, NULL); + if (traceData) { traceData->setData(Mem); } + } + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + return fault; + } +}}; + +def template StoreInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, NULL); + if (traceData) { traceData->setData(Mem); } + } + + // Need to write back any potential address register update + if (fault == NoFault) { + %(op_wb)s; + } + } + + return fault; + } +}}; + + +def template StoreCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_dest_decl)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + return fault; + } +}}; + +def template StoreCondCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_dest_decl)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + return fault; + } +}}; + + +def template MiscMemAccExecute {{ + Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + EA = xc->getEA(); + + if (fault == NoFault) { + %(memacc_code)s; + } + } + + return NoFault; + } +}}; + +def template MiscExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + if (fault == NoFault) { + %(memacc_code)s; + } + } + + return NoFault; + } +}}; + +def template MiscInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("Misc instruction does not support split access method!"); + return NoFault; + } +}}; + + +def template MiscCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("Misc instruction does not support split access method!"); + + return NoFault; + } +}}; + +def format ArmLoadMemory(memacc_code, ea_code = {{ EA = Rn + disp; }}, + mem_flags = [], inst_flags = []) {{ + ea_code = ArmGenericCodeSubs(ea_code) + memacc_code = ArmGenericCodeSubs(memacc_code) + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + decode_template = BasicDecode, + exec_template_base = 'Load') +}}; + +def format ArmStoreMemory(memacc_code, ea_code = {{ EA = Rn + disp; }}, + mem_flags = [], inst_flags = []) {{ + ea_code = ArmGenericCodeSubs(ea_code) + memacc_code = ArmGenericCodeSubs(memacc_code) + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + exec_template_base = 'Store') +}}; + diff --git a/src/arch/arm/isa/formats/pred.isa b/src/arch/arm/isa/formats/pred.isa new file mode 100644 index 000000000..1e9dba07e --- /dev/null +++ b/src/arch/arm/isa/formats/pred.isa @@ -0,0 +1,402 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Predicated Instruction Execution +// + +output header {{ +#include <iostream> + + enum ArmPredicateBits { + COND_EQ = 0, + COND_NE, // 1 + COND_CS, // 2 + COND_CC, // 3 + COND_MI, // 4 + COND_PL, // 5 + COND_VS, // 6 + COND_VC, // 7 + COND_HI, // 8 + COND_LS, // 9 + COND_GE, // 10 + COND_LT, // 11 + COND_GT, // 12 + COND_LE, // 13 + COND_AL, // 14 + COND_NV // 15 + }; + + inline uint32_t + rotate_imm(uint32_t immValue, uint32_t rotateValue) + { + return ((immValue >> (int)(rotateValue & 31)) | + (immValue << (32 - (int)(rotateValue & 31)))); + } + + inline uint32_t nSet(uint32_t cpsr) { return cpsr & (1<<31); } + inline uint32_t zSet(uint32_t cpsr) { return cpsr & (1<<30); } + inline uint32_t cSet(uint32_t cpsr) { return cpsr & (1<<29); } + inline uint32_t vSet(uint32_t cpsr) { return cpsr & (1<<28); } + + inline bool arm_predicate(uint32_t cpsr, uint32_t predBits) + { + + enum ArmPredicateBits armPredBits = (enum ArmPredicateBits) predBits; + uint32_t result = 0; + switch (armPredBits) + { + case COND_EQ: + result = zSet(cpsr); break; + case COND_NE: + result = !zSet(cpsr); break; + case COND_CS: + result = cSet(cpsr); break; + case COND_CC: + result = !cSet(cpsr); break; + case COND_MI: + result = nSet(cpsr); break; + case COND_PL: + result = !nSet(cpsr); break; + case COND_VS: + result = vSet(cpsr); break; + case COND_VC: + result = !vSet(cpsr); break; + case COND_HI: + result = cSet(cpsr) && !zSet(cpsr); break; + case COND_LS: + result = !cSet(cpsr) || zSet(cpsr); break; + case COND_GE: + result = (!nSet(cpsr) && !vSet(cpsr)) || (nSet(cpsr) && vSet(cpsr)); break; + case COND_LT: + result = (nSet(cpsr) && !vSet(cpsr)) || (!nSet(cpsr) && vSet(cpsr)); break; + case COND_GT: + result = (!nSet(cpsr) && !vSet(cpsr) && !zSet(cpsr)) || (nSet(cpsr) && vSet(cpsr) && !zSet(cpsr)); break; + case COND_LE: + result = (nSet(cpsr) && !vSet(cpsr)) || (!nSet(cpsr) && vSet(cpsr)) || zSet(cpsr); break; + case COND_AL: result = 1; break; + case COND_NV: result = 0; break; + default: + fprintf(stderr, "Unhandled predicate condition: %d\n", armPredBits); + exit(1); + } + if (result) + return true; + else + return false; + } + + + /** + * Base class for predicated integer operations. + */ + class PredOp : public ArmStaticInst + { + protected: + + uint32_t condCode; + + /// Constructor + PredOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + ArmStaticInst(mnem, _machInst, __opClass), + condCode(COND_CODE) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for predicated immediate operations. + */ + class PredImmOp : public PredOp + { + protected: + + uint32_t imm; + uint32_t rotate; + uint32_t rotated_imm; + uint32_t rotated_carry; + + /// Constructor + PredImmOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + PredOp(mnem, _machInst, __opClass), + imm(IMM), rotate(ROTATE << 1), rotated_imm(0), + rotated_carry(0) + { + rotated_imm = rotate_imm(imm, rotate); + if (rotate != 0) + rotated_carry = (rotated_imm >> 31) & 1; + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for predicated integer operations. + */ + class PredIntOp : public PredOp + { + protected: + + uint32_t shift_size; + uint32_t shift; + + /// Constructor + PredIntOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + PredOp(mnem, _machInst, __opClass), + shift_size(SHIFT_SIZE), shift(SHIFT) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for predicated macro-operations. + */ + class PredMacroOp : public PredOp + { + protected: + + uint32_t numMicroops; + StaticInstPtr * microOps; + + /// Constructor + PredMacroOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + PredOp(mnem, _machInst, __opClass), + numMicroops(0) + { + // We rely on the subclasses of this object to handle the + // initialization of the micro-operations, since they are + // all of variable length + flags[IsMacroop] = true; + } + + ~PredMacroOp() + { + if (numMicroops) + delete [] microOps; + } + + StaticInstPtr fetchMicroop(MicroPC microPC) + { + assert(microPC < numMicroops); + return microOps[microPC]; + } + + %(BasicExecPanic)s + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for predicated micro-operations. + */ + class PredMicroop : public PredOp + { + /// Constructor + PredMicroop(const char *mnem, MachInst _machInst, OpClass __opClass) : + PredOp(mnem, _machInst, __opClass) + { + flags[IsMicroop] = true; + } + }; + +}}; + +def template PredOpExecute {{ + 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 (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + if (fault == NoFault) + { + %(op_wb)s; + } + } + else + return NoFault; + // Predicated false instructions should not return faults + + return fault; + } +}}; + +//Outputs to decoder.cc +output decoder {{ + std::string PredOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + } + + ss << ", "; + + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + ss << ", "; + } + + return ss.str(); + } + + std::string PredImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + } + + ss << ", "; + + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + ss << ", "; + } + + return ss.str(); + } + + std::string PredIntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + } + + ss << ", "; + + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + ss << ", "; + } + + return ss.str(); + } + + std::string PredMacroOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + return ss.str(); + } + +}}; + +let {{ + + calcCcCode = ''' + uint16_t _ic, _iv, _iz, _in; + + _in = (resTemp >> 31) & 1; + _iz = (resTemp == 0); + _iv = %(ivValue)s & 1; + _ic = %(icValue)s & 1; + + Cpsr = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 | + (Cpsr & 0x0FFFFFFF); + + DPRINTF(Arm, "in = %%d\\n", _in); + DPRINTF(Arm, "iz = %%d\\n", _iz); + DPRINTF(Arm, "ic = %%d\\n", _ic); + DPRINTF(Arm, "iv = %%d\\n", _iv); + ''' + +}}; + +def format PredOp(code, *opt_flags) {{ + iop = InstObjParams(name, Name, 'PredOp', code, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = PredOpExecute.subst(iop) +}}; + +def format PredImmOp(code, *opt_flags) {{ + iop = InstObjParams(name, Name, 'PredImmOp', code, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = PredOpExecute.subst(iop) +}}; + +def format PredImmOpCc(code, icValue, ivValue, *opt_flags) {{ + ccCode = calcCcCode % vars() + code += ccCode; + iop = InstObjParams(name, Name, 'PredImmOp', + {"code": code, "cc_code": ccCode}, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = PredOpExecute.subst(iop) +}}; + +def format PredIntOp(code, *opt_flags) {{ + new_code = ArmGenericCodeSubs(code) + iop = InstObjParams(name, Name, 'PredIntOp', new_code, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = PredOpExecute.subst(iop) +}}; + +def format PredIntOpCc(code, icValue, ivValue, *opt_flags) {{ + ccCode = calcCcCode % vars() + code += ccCode; + new_code = ArmGenericCodeSubs(code) + iop = InstObjParams(name, Name, 'PredIntOp', + {"code": new_code, "cc_code": ccCode }, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = PredOpExecute.subst(iop) +}}; + diff --git a/src/arch/arm/isa/formats/unimp.isa b/src/arch/arm/isa/formats/unimp.isa new file mode 100644 index 000000000..c82bb41c6 --- /dev/null +++ b/src/arch/arm/isa/formats/unimp.isa @@ -0,0 +1,144 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Unimplemented instructions +// + +output header {{ + /** + * Static instruction class for unimplemented instructions that + * cause simulator termination. Note that these are recognized + * (legal) instructions that the simulator does not support; the + * 'Unknown' class is used for unrecognized/illegal instructions. + * This is a leaf class. + */ + class FailUnimplemented : public ArmStaticInst + { + public: + /// Constructor + FailUnimplemented(const char *_mnemonic, MachInst _machInst) + : ArmStaticInst(_mnemonic, _machInst, No_OpClass) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for unimplemented instructions that cause a warning + * to be printed (but do not terminate simulation). This + * implementation is a little screwy in that it will print a + * warning for each instance of a particular unimplemented machine + * instruction, not just for each unimplemented opcode. Should + * probably make the 'warned' flag a static member of the derived + * class. + */ + class WarnUnimplemented : public ArmStaticInst + { + private: + /// Have we warned on this instruction yet? + mutable bool warned; + + public: + /// Constructor + WarnUnimplemented(const char *_mnemonic, MachInst _machInst) + : ArmStaticInst(_mnemonic, _machInst, No_OpClass), warned(false) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string + FailUnimplemented::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + return csprintf("%-10s (unimplemented)", mnemonic); + } + + std::string + WarnUnimplemented::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + return csprintf("%-10s (unimplemented)", mnemonic); + } +}}; + +output exec {{ + Fault + FailUnimplemented::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("attempt to execute unimplemented instruction '%s' " + "(inst 0x%08x, opcode 0x%x, binary:%s)", mnemonic, machInst, OPCODE, + inst2string(machInst)); + return new UnimplementedOpcodeFault; + } + + Fault + WarnUnimplemented::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + if (!warned) { + warn("\tinstruction '%s' unimplemented\n", mnemonic); + warned = true; + } + + return NoFault; + } +}}; + + +def format FailUnimpl() {{ + iop = InstObjParams(name, 'FailUnimplemented') + decode_block = BasicDecodeWithMnemonic.subst(iop) +}}; + +def format WarnUnimpl() {{ + iop = InstObjParams(name, 'WarnUnimplemented') + decode_block = BasicDecodeWithMnemonic.subst(iop) +}}; + diff --git a/src/arch/arm/isa/formats/unknown.isa b/src/arch/arm/isa/formats/unknown.isa new file mode 100644 index 000000000..3d13ef616 --- /dev/null +++ b/src/arch/arm/isa/formats/unknown.isa @@ -0,0 +1,84 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Unknown instructions +// + +output header {{ + /** + * Static instruction class for unknown (illegal) instructions. + * These cause simulator termination if they are executed in a + * non-speculative mode. This is a leaf class. + */ + class Unknown : public ArmStaticInst + { + public: + /// Constructor + Unknown(MachInst _machInst) + : ArmStaticInst("unknown", _machInst, No_OpClass) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string + Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return csprintf("%-10s (inst 0x%x, opcode 0x%x, binary:%s)", + "unknown", machInst, OPCODE, inst2string(machInst)); + } +}}; + +output exec {{ + Fault + Unknown::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("attempt to execute unknown instruction " + "(inst 0x%08x, opcode 0x%x, binary: %s)", machInst, OPCODE, inst2string(machInst)); + return new UnimplementedOpcodeFault; + } +}}; + +def format Unknown() {{ + decode_block = 'return new Unknown(machInst);\n' +}}; + diff --git a/src/arch/arm/isa/formats/util.isa b/src/arch/arm/isa/formats/util.isa new file mode 100644 index 000000000..ee6339c02 --- /dev/null +++ b/src/arch/arm/isa/formats/util.isa @@ -0,0 +1,217 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +let {{ + +# Generic substitutions for Arm instructions +def ArmGenericCodeSubs(code): + # Substitute in the shifted portion of operations + new_code = re.sub(r'Rm_Imm', 'shift_rm_imm(Rm, shift_size, shift, Cpsr<29:>)', code) + new_code = re.sub(r'Rm_Rs', 'shift_rm_rs(Rm, Rs, shift, Cpsr<29:>)', new_code) + new_code = re.sub(r'^', 'Cpsr = Cpsr;', new_code) + return new_code + +def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + postacc_code = '', base_class = 'Memory', + decode_template = BasicDecode, exec_template_base = ''): + # Make sure flags are in lists (convert to lists if not). + mem_flags = makeList(mem_flags) + inst_flags = makeList(inst_flags) + + # add hook to get effective addresses into execution trace output. + ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n' + + # Some CPU models execute the memory operation as an atomic unit, + # while others want to separate them into an effective address + # computation and a memory access operation. As a result, we need + # to generate three StaticInst objects. Note that the latter two + # are nested inside the larger "atomic" one. + + # Generate InstObjParams for each of the three objects. Note that + # they differ only in the set of code objects contained (which in + # turn affects the object's overall operand list). + iop = InstObjParams(name, Name, base_class, + { 'ea_code':ea_code, 'memacc_code':memacc_code, 'postacc_code':postacc_code }, + inst_flags) + ea_iop = InstObjParams(name, Name, base_class, + { 'ea_code':ea_code }, + inst_flags) + memacc_iop = InstObjParams(name, Name, base_class, + { 'memacc_code':memacc_code, 'postacc_code':postacc_code }, + inst_flags) + + if mem_flags: + s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' + iop.constructor += s + memacc_iop.constructor += s + + # select templates + + # The InitiateAcc template is the same for StoreCond templates as the + # corresponding Store template.. + StoreCondInitiateAcc = StoreInitiateAcc + + memAccExecTemplate = eval(exec_template_base + 'MemAccExecute') + fullExecTemplate = eval(exec_template_base + 'Execute') + initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') + completeAccTemplate = eval(exec_template_base + 'CompleteAcc') + + # (header_output, decoder_output, decode_block, exec_output) + return (LoadStoreDeclare.subst(iop), + EACompConstructor.subst(ea_iop) + + MemAccConstructor.subst(memacc_iop) + + LoadStoreConstructor.subst(iop), + decode_template.subst(iop), + EACompExecute.subst(ea_iop) + + memAccExecTemplate.subst(memacc_iop) + + fullExecTemplate.subst(iop) + + initiateAccTemplate.subst(iop) + + completeAccTemplate.subst(iop)) +}}; + + +output header {{ + std::string inst2string(MachInst machInst); + StaticInstPtr gen_ldrstr_uop(uint32_t baseinst, int loadop, uint32_t rd, int32_t disp); + int emit_ldfstf_uops(StaticInstPtr* microOps, int index, uint32_t baseinst, int loadop, int up, int32_t disp); +}}; + +output decoder {{ + + std::string inst2string(MachInst machInst) + { + std::string str = ""; + uint32_t mask = 0x80000000; + + for(int i=0; i < 32; i++) { + if ((machInst & mask) == 0) { + str += "0"; + } else { + str += "1"; + } + + mask = mask >> 1; + } + + return str; + } + + // Generate the bit pattern for an Ldr_uop or Str_uop; + StaticInstPtr + gen_ldrstr_uop(uint32_t baseinst, int loadop, uint32_t rd, int32_t disp) + { + StaticInstPtr newInst; + uint32_t newMachInst = baseinst & 0xffff0000; + newMachInst |= (rd << 12); + newMachInst |= disp; + if (loadop) + newInst = new Ldr_uop(newMachInst); + else + newInst = new Str_uop(newMachInst); + return newInst; + } + + // Emits uops for a double fp move + int + emit_ldfstf_uops(StaticInstPtr* microOps, int index, uint32_t baseinst, int loadop, int up, int32_t disp) + { + StaticInstPtr newInst; + uint32_t newMachInst; + + if (loadop) + { + newMachInst = baseinst & 0xfffff000; + newMachInst |= (disp & 0x0fff); + newInst = new Ldlo_uop(newMachInst); + microOps[index++] = newInst; + + newMachInst = baseinst & 0xfffff000; + if (up) + newMachInst |= ((disp + 4) & 0x0fff); + else + newMachInst |= ((disp - 4) & 0x0fff); + newInst = new Ldhi_uop(newMachInst); + microOps[index++] = newInst; + + newMachInst = baseinst & 0xf000f000; + newInst = new Mvtd_uop(newMachInst); + microOps[index++] = newInst; + } + else + { + newMachInst = baseinst & 0xf000f000; + newInst = new Mvfd_uop(newMachInst); + microOps[index++] = newInst; + + newMachInst = baseinst & 0xfffff000; + newMachInst |= (disp & 0x0fff); + newInst = new Stlo_uop(newMachInst); + microOps[index++] = newInst; + + newMachInst = baseinst & 0xfffff000; + if (up) + newMachInst |= ((disp + 4) & 0x0fff); + else + newMachInst |= ((disp - 4) & 0x0fff); + newInst = new Sthi_uop(newMachInst); + microOps[index++] = newInst; + } + return 3; + } + +}}; + +output exec {{ + + using namespace ArmISA; + + /// CLEAR ALL CPU INST/EXE HAZARDS + inline void + clear_exe_inst_hazards() + { + //CODE HERE + } + +#if FULL_SYSTEM + inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) + { + return NoFault; + } +#else + inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) + { + return NoFault; + } +#endif + + +}}; + + |