diff -r 84bd4089958b configs/common/cpu2000.py --- a/configs/common/cpu2000.py Tue May 25 20:15:44 2010 -0700 +++ b/configs/common/cpu2000.py Wed May 26 18:10:45 2010 -0500 @@ -663,7 +663,7 @@ stdin = None def __init__(self, isa, os, input_set): - if isa == 'alpha': + if (isa == 'alpha' or isa == 'arm'): self.endian = 'lendian' elif (isa == 'sparc' or isa == 'sparc32'): self.endian = 'bendian' diff -r 84bd4089958b src/arch/arm/ArmTLB.py --- a/src/arch/arm/ArmTLB.py Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/ArmTLB.py Wed May 26 18:10:45 2010 -0500 @@ -1,8 +1,17 @@ # -*- mode:python -*- -# Copyright (c) 2007-2008 The Florida State University +# Copyright (c) 2009 ARM Limited # All rights reserved. # +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# # 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 @@ -26,12 +35,28 @@ # (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 +# Authors: Ali Saidi +from m5.defines import buildEnv from m5.SimObject import SimObject from m5.params import * +from m5.proxy import * + +if buildEnv['FULL_SYSTEM']: + from MemObject import MemObject + + class ArmTableWalker(MemObject): + type = 'ArmTableWalker' + cxx_class = 'ArmISA::TableWalker' + port = Port("Port for TableWalker to do walk the translation with") + sys = Param.System(Parent.any, "system object parameter") + min_backoff = Param.Tick(0, "Minimum backoff delay after failed send") + max_backoff = Param.Tick(100000, "Minimum backoff delay after failed send") + class ArmTLB(SimObject): type = 'ArmTLB' cxx_class = 'ArmISA::TLB' size = Param.Int(64, "TLB size") + if buildEnv['FULL_SYSTEM']: + walker = Param.ArmTableWalker(ArmTableWalker(), "HW Table walker") diff -r 84bd4089958b src/arch/arm/SConscript --- a/src/arch/arm/SConscript Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/SConscript Wed May 26 18:10:45 2010 -0500 @@ -1,7 +1,18 @@ # -*- mode:python -*- +# Copyright (c) 2009 ARM Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# # Copyright (c) 2007-2008 The Florida State University -# Copyright (c) 2009 ARM Limited # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -37,12 +48,16 @@ # Scons bug id: 2006 M5 Bug id: 308 Dir('isa/formats') Source('faults.cc') - Source('insts/branch.cc') + Source('insts/macromem.cc') Source('insts/mem.cc') + Source('insts/misc.cc') Source('insts/pred_inst.cc') Source('insts/static_inst.cc') + Source('insts/vfp.cc') + Source('isa.cc') + Source('miscregs.cc') + Source('predecoder.cc') Source('nativetrace.cc') - Source('pagetable.cc') Source('tlb.cc') Source('vtophys.cc') Source('utility.cc') @@ -51,11 +66,14 @@ SimObject('ArmTLB.py') TraceFlag('Arm') + TraceFlag('TLBVerbose') TraceFlag('Faults', "Trace Exceptions, interrupts, svc/swi") + TraceFlag('Predecoder', "Instructions returned by the predecoder") if env['FULL_SYSTEM']: Source('interrupts.cc') Source('stacktrace.cc') Source('system.cc') + Source('table_walker.cc') SimObject('ArmInterrupts.py') SimObject('ArmSystem.py') diff -r 84bd4089958b src/arch/arm/faults.hh --- a/src/arch/arm/faults.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/faults.hh Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,15 @@ -/* +/* Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2003-2005 The Regents of The University of Michigan * Copyright (c) 2007-2008 The Florida State University * All rights reserved. @@ -33,6 +44,7 @@ #ifndef __ARM_FAULTS_HH__ #define __ARM_FAULTS_HH__ +#include "arch/arm/miscregs.hh" #include "arch/arm/types.hh" #include "config/full_system.hh" #include "sim/faults.hh" @@ -43,12 +55,36 @@ { typedef const Addr FaultOffset; -class ArmFaultBase : public FaultBase +class ArmFault : public FaultBase { protected: Addr getVector(ThreadContext *tc); public: + enum StatusEncoding + { + AlignmentFault = 0x1, + DebugEvent = 0x2, + AccessFlag0 = 0x3, + InstructionCacheMaintenance = 0x4, + Translation0 = 0x5, + AccessFlag1 = 0x6, + Translation1 = 0x7, + SynchronousExternalAbort0 = 0x8, + Domain0 = 0x9, + SynchronousExternalAbort1 = 0xa, + Domain1 = 0xb, + TranslationTableWalkExtAbt0 = 0xc, + Permission0 = 0xd, + TranslationTableWalkExtAbt1 = 0xe, + Permission1 = 0xf, + AsynchronousExternalAbort = 0x16, + MemoryAccessAsynchronousParityError = 0x18, + MemoryAccessSynchronousParityError = 0x19, + TranslationTableWalkPrtyErr0 = 0x1c, + TranslationTableWalkPrtyErr1 = 0x1e, + }; + struct FaultVals { const FaultName name; @@ -74,7 +110,7 @@ }; template -class ArmFault : public ArmFaultBase +class ArmFaultVals : public ArmFault { protected: static FaultVals vals; @@ -90,14 +126,93 @@ bool fiqDisable() { return vals.fiqDisable; } }; +class Reset : public ArmFaultVals +#if FULL_SYSTEM +{ + public: + void invoke(ThreadContext *tc); +}; +#else +{}; +#endif //FULL_SYSTEM -class Reset : public ArmFault {}; -class UndefinedInstruction : public ArmFault {}; -class SupervisorCall : public ArmFault {}; -class PrefetchAbort : public ArmFault {}; -class DataAbort : public ArmFault {}; -class Interrupt : public ArmFault {}; -class FastInterrupt : public ArmFault {}; +class UndefinedInstruction : public ArmFaultVals +{ +#if !FULL_SYSTEM + protected: + ExtMachInst machInst; + bool unknown; + const char *mnemonic; + + public: + UndefinedInstruction(ExtMachInst _machInst, + bool _unknown, + const char *_mnemonic = NULL) : + machInst(_machInst), unknown(_unknown), mnemonic(_mnemonic) + { + } + + void invoke(ThreadContext *tc); +#endif +}; + +class SupervisorCall : public ArmFaultVals +{ +#if !FULL_SYSTEM + protected: + ExtMachInst machInst; + + public: + SupervisorCall(ExtMachInst _machInst) : machInst(_machInst) + {} + + void invoke(ThreadContext *tc); +#endif +}; + +template +class AbortFault : public ArmFaultVals +{ + protected: + Addr faultAddr; + bool write; + uint8_t domain; + uint8_t status; + + public: + AbortFault(Addr _faultAddr, bool _write, + uint8_t _domain, uint8_t _status) : + faultAddr(_faultAddr), write(_write), + domain(_domain), status(_status) + {} + + void invoke(ThreadContext *tc); +}; + +class PrefetchAbort : public AbortFault +{ + public: + static const MiscRegIndex FsrIndex = MISCREG_IFSR; + static const MiscRegIndex FarIndex = MISCREG_IFAR; + + PrefetchAbort(Addr _addr, uint8_t _status) : + AbortFault(_addr, false, 0, _status) + {} +}; + +class DataAbort : public AbortFault +{ + public: + static const MiscRegIndex FsrIndex = MISCREG_DFSR; + static const MiscRegIndex FarIndex = MISCREG_DFAR; + + DataAbort(Addr _addr, uint8_t _domain, bool _write, uint8_t _status) : + AbortFault(_addr, _write, _domain, _status) + {} +}; + +class Interrupt : public ArmFaultVals {}; +class FastInterrupt : public ArmFaultVals {}; } // ArmISA namespace diff -r 84bd4089958b src/arch/arm/faults.cc --- a/src/arch/arm/faults.cc Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/faults.cc Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,15 @@ -/* +/* Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2003-2005 The Regents of The University of Michigan * Copyright (c) 2007-2008 The Florida State University * All rights reserved. @@ -38,38 +49,38 @@ namespace ArmISA { -template<> ArmFaultBase::FaultVals ArmFault::vals = +template<> ArmFault::FaultVals ArmFaultVals::vals = {"reset", 0x00, MODE_SVC, 0, 0, true, true}; -template<> ArmFaultBase::FaultVals ArmFault::vals = +template<> ArmFault::FaultVals ArmFaultVals::vals = {"Undefined Instruction", 0x04, MODE_UNDEFINED, 4 ,2, false, false} ; -template<> ArmFaultBase::FaultVals ArmFault::vals = +template<> ArmFault::FaultVals ArmFaultVals::vals = {"Supervisor Call", 0x08, MODE_SVC, 4, 2, false, false}; -template<> ArmFaultBase::FaultVals ArmFault::vals = +template<> ArmFault::FaultVals ArmFaultVals::vals = {"Prefetch Abort", 0x0C, MODE_ABORT, 4, 4, true, false}; -template<> ArmFaultBase::FaultVals ArmFault::vals = +template<> ArmFault::FaultVals ArmFaultVals::vals = {"Data Abort", 0x10, MODE_ABORT, 8, 8, true, false}; -template<> ArmFaultBase::FaultVals ArmFault::vals = +template<> ArmFault::FaultVals ArmFaultVals::vals = {"IRQ", 0x18, MODE_IRQ, 4, 4, true, false}; -template<> ArmFaultBase::FaultVals ArmFault::vals = +template<> ArmFault::FaultVals ArmFaultVals::vals = {"FIQ", 0x1C, MODE_FIQ, 4, 4, true, true}; Addr -ArmFaultBase::getVector(ThreadContext *tc) +ArmFault::getVector(ThreadContext *tc) { // ARM ARM B1-3 SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); - + // panic if SCTLR.VE because I have no idea what to do with vectored // interrupts assert(!sctlr.ve); - + if (!sctlr.v) return offset(); return offset() + HighVecs; @@ -79,7 +90,7 @@ #if FULL_SYSTEM void -ArmFaultBase::invoke(ThreadContext *tc) +ArmFault::invoke(ThreadContext *tc) { // ARM ARM B1.6.3 FaultBase::invoke(tc); @@ -95,11 +106,11 @@ cpsr.it1 = cpsr.it2 = 0; cpsr.j = 0; - if (sctlr.te) - cpsr.t = 1; + cpsr.t = sctlr.te; cpsr.a = cpsr.a | abortDisable(); cpsr.f = cpsr.f | fiqDisable(); cpsr.i = 1; + cpsr.e = sctlr.ee; tc->setMiscReg(MISCREG_CPSR, cpsr); tc->setIntReg(INTREG_LR, tc->readPC() + (saved_cpsr.t ? thumbPcOffset() : armPcOffset())); @@ -122,15 +133,84 @@ break; default: panic("unknown Mode\n"); - } - - DPRINTF(Faults, "Invoking Fault: %s cpsr: %#x PC: %#x lr: %#x\n", name(), cpsr, - tc->readPC(), tc->readIntReg(INTREG_LR)); - tc->setPC(getVector(tc)); - tc->setNextPC(getVector(tc) + cpsr.t ? 2 : 4 ); + } + + Addr pc = tc->readPC(); + Addr newPc = getVector(tc) | (sctlr.te ? (ULL(1) << PcTBitShift) : 0); + DPRINTF(Faults, "Invoking Fault: %s cpsr: %#x PC: %#x lr: %#x newVector: %#x\n", + name(), cpsr, pc, tc->readIntReg(INTREG_LR), newPc); + tc->setPC(newPc); + tc->setNextPC(newPc + cpsr.t ? 2 : 4 ); + tc->setMicroPC(0); + tc->setNextMicroPC(1); } + +void +Reset::invoke(ThreadContext *tc) +{ + tc->getCpuPtr()->clearInterrupts(); + tc->clearArchRegs(); + ArmFault::invoke(tc); +} + +#else + +void +UndefinedInstruction::invoke(ThreadContext *tc) +{ + assert(unknown || mnemonic != NULL); + if (unknown) { + panic("Attempted to execute unknown instruction (inst 0x%08x)", + machInst); + } else { + panic("Attempted to execute unimplemented instruction " + "'%s' (inst 0x%08x)", mnemonic, machInst); + } +} + +void +SupervisorCall::invoke(ThreadContext *tc) +{ + // As of now, there isn't a 32 bit thumb version of this instruction. + assert(!machInst.bigThumb); + uint32_t callNum; + if (machInst.thumb) { + callNum = bits(machInst, 7, 0); + } else { + callNum = bits(machInst, 23, 0); + } + if (callNum == 0) { + callNum = tc->readIntReg(INTREG_R7); + } + tc->syscall(callNum); + + // Advance the PC since that won't happen automatically. + tc->setPC(tc->readNextPC()); + tc->setNextPC(tc->readNextNPC()); + tc->setMicroPC(0); + tc->setNextMicroPC(1); +} + #endif // FULL_SYSTEM +template +void +AbortFault::invoke(ThreadContext *tc) +{ + ArmFaultVals::invoke(tc); + FSR fsr = 0; + fsr.fsLow = bits(status, 3, 0); + fsr.fsHigh = bits(status, 4); + fsr.domain = domain; + fsr.wnr = (write ? 1 : 0); + fsr.ext = 0; + tc->setMiscReg(T::FsrIndex, fsr); + tc->setMiscReg(T::FarIndex, faultAddr); +} + +template void AbortFault::invoke(ThreadContext *tc); +template void AbortFault::invoke(ThreadContext *tc); + // return via SUBS pc, lr, xxx; rfe, movs, ldm diff -r 84bd4089958b src/arch/arm/insts/branch.hh --- a/src/arch/arm/insts/branch.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/insts/branch.hh Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,16 @@ -/* Copyright (c) 2007-2008 The Florida State University +/* Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2007-2008 The Florida State University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,107 +45,90 @@ namespace ArmISA { -/** - * 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 +// Branch to a target computed with an immediate +class BranchImm : public PredOp { protected: - /// Cached program counter from last disassembly - mutable Addr cachedPC; + int32_t imm; - /// 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; + public: + BranchImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + int32_t _imm) : + PredOp(mnem, _machInst, __opClass), imm(_imm) + {} }; -/** - * Base class for branches (PC-relative control transfers), - * conditional or unconditional. - */ -class Branch : public PCDependentDisassembly +// Conditionally Branch to a target computed with an immediate +class BranchImmCond : public BranchImm { protected: - /// target address (signed) Displacement . - int32_t disp; + // This will mask the condition code stored for PredOp. Ideally these two + // class would cooperate, but they're not set up to do that at the moment. + ConditionCode condCode; - /// Constructor. - Branch(const char *mnem, MachInst _machInst, OpClass __opClass) - : PCDependentDisassembly(mnem, _machInst, __opClass), - disp(machInst.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; + public: + BranchImmCond(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + int32_t _imm, ConditionCode _condCode) : + BranchImm(mnem, _machInst, __opClass, _imm), condCode(_condCode) + {} }; -/** - * Base class for branch and exchange instructions on the ARM - */ -class BranchExchange : public PredOp +// Branch to a target computed with a register +class BranchReg : public PredOp { protected: - /// Constructor - BranchExchange(const char *mnem, MachInst _machInst, - OpClass __opClass) - : PredOp(mnem, _machInst, __opClass) - { - } + IntRegIndex op1; - std::string - generateDisassembly(Addr pc, const SymbolTable *symtab) const; + public: + BranchReg(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _op1) : + PredOp(mnem, _machInst, __opClass), op1(_op1) + {} }; - -/** - * Base class for jumps (register-indirect control transfers). In - * the Arm ISA, these are always unconditional. - */ -class Jump : public PCDependentDisassembly +// Conditionally Branch to a target computed with a register +class BranchRegCond : public BranchReg { protected: - - /// Displacement to target address (signed). - int32_t disp; - - uint32_t target; + // This will mask the condition code stored for PredOp. Ideally these two + // class would cooperate, but they're not set up to do that at the moment. + ConditionCode condCode; public: - /// Constructor - Jump(const char *mnem, MachInst _machInst, OpClass __opClass) - : PCDependentDisassembly(mnem, _machInst, __opClass), - disp(machInst.offset << 2) - { - } + BranchRegCond(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _op1, ConditionCode _condCode) : + BranchReg(mnem, _machInst, __opClass, _op1), condCode(_condCode) + {} +}; - Addr branchTarget(ThreadContext *tc) const; +// Branch to a target computed with two registers +class BranchRegReg : public PredOp +{ + protected: + IntRegIndex op1; + IntRegIndex op2; - std::string - generateDisassembly(Addr pc, const SymbolTable *symtab) const; + public: + BranchRegReg(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _op1, IntRegIndex _op2) : + PredOp(mnem, _machInst, __opClass), op1(_op1), op2(_op2) + {} }; + +// Branch to a target computed with an immediate and a register +class BranchImmReg : public PredOp +{ + protected: + int32_t imm; + IntRegIndex op1; + + public: + BranchImmReg(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + int32_t _imm, IntRegIndex _op1) : + PredOp(mnem, _machInst, __opClass), imm(_imm), op1(_op1) + {} +}; + } #endif //__ARCH_ARM_INSTS_BRANCH_HH__ diff -r 84bd4089958b src/arch/arm/insts/branch.cc --- a/src/arch/arm/insts/branch.cc Tue May 25 20:15:44 2010 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -/* 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 - */ - -#include "arch/arm/insts/branch.hh" -#include "base/loader/symtab.hh" - -namespace ArmISA -{ -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; - - printMnemonic(ss); - ss << "\t"; - - Addr target = pc + 8 + disp; - ccprintf(ss, "%#x", target); - printMemSymbol(ss, symtab, " <", target, ">"); - - return ss.str(); -} - -std::string -BranchExchange::generateDisassembly(Addr pc, const SymbolTable *symtab) const -{ - std::stringstream ss; - printMnemonic(ss); - if (_numSrcRegs > 0) { - printReg(ss, _srcRegIdx[0]); - } - return ss.str(); -} - -std::string -Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const -{ - std::stringstream ss; - printMnemonic(ss); - return ss.str(); -} -} diff -r 84bd4089958b src/arch/arm/insts/macromem.hh --- a/src/arch/arm/insts/macromem.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/insts/macromem.hh Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,16 @@ -/* Copyright (c) 2007-2008 The Florida State University +/* Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2007-2008 The Florida State University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,6 +42,7 @@ #define __ARCH_ARM_MACROMEM_HH__ #include "arch/arm/insts/pred_inst.hh" +#include "arch/arm/tlb.hh" namespace ArmISA { @@ -47,9 +60,28 @@ } /** + * Base class for Memory microops + */ +class MicroOp : public PredOp +{ + protected: + MicroOp(const char *mnem, ExtMachInst machInst, OpClass __opClass) + : PredOp(mnem, machInst, __opClass) + { + } + + public: + void + setDelayedCommit() + { + flags[IsDelayedCommit] = true; + } +}; + +/** * Microops of the form IntRegA = IntRegB op Imm */ -class MicroIntOp : public PredOp +class MicroIntOp : public MicroOp { protected: RegIndex ura, urb; @@ -57,7 +89,7 @@ MicroIntOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, RegIndex _ura, RegIndex _urb, uint8_t _imm) - : PredOp(mnem, machInst, __opClass), + : MicroOp(mnem, machInst, __opClass), ura(_ura), urb(_urb), imm(_imm) { } @@ -69,104 +101,39 @@ class MicroMemOp : public MicroIntOp { protected: + bool up; unsigned memAccessFlags; MicroMemOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, - RegIndex _ura, RegIndex _urb, uint8_t _imm) + RegIndex _ura, RegIndex _urb, bool _up, uint8_t _imm) : MicroIntOp(mnem, machInst, __opClass, _ura, _urb, _imm), - memAccessFlags(0) + up(_up), memAccessFlags(TLB::MustBeOne | TLB::AlignWord) { } }; /** - * Arm Macro Memory operations like LDM/STM + * Base class for microcoded integer memory instructions. */ -class ArmMacroMemoryOp : public PredMacroOp +class MacroMemOp : public PredMacroOp { protected: - /// Memory request flags. See mem_req_base.hh. - unsigned memAccessFlags; - - uint32_t reglist; - uint32_t ones; - - ArmMacroMemoryOp(const char *mnem, ExtMachInst _machInst, - OpClass __opClass) - : PredMacroOp(mnem, _machInst, __opClass), memAccessFlags(0), - reglist(machInst.regList), ones(0) - { - ones = number_of_ones(reglist); - numMicroops = ones + machInst.puswl.writeback + 1; - // Remember that writeback adds a uop - microOps = new StaticInstPtr[numMicroops]; - } + MacroMemOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, + IntRegIndex rn, bool index, bool up, bool user, + bool writeback, bool load, uint32_t reglist); }; /** - * Arm Macro FPA operations to fix ldfd and stfd instructions + * Base class for microcoded floating point memory instructions. */ -class ArmMacroFPAOp : public PredMacroOp +class MacroVFPMemOp : public PredMacroOp { protected: - uint32_t puswl, - prepost, - up, - psruser, - writeback, - loadop; - int32_t disp8; - - ArmMacroFPAOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) - : PredMacroOp(mnem, _machInst, __opClass), - puswl(machInst.puswl), - prepost(machInst.puswl.prepost), - up(machInst.puswl.up), - psruser(machInst.puswl.psruser), - writeback(machInst.puswl.writeback), - loadop(machInst.puswl.loadOp), - disp8(machInst.immed7_0 << 2) - { - numMicroops = 3 + writeback; - microOps = new StaticInstPtr[numMicroops]; - } + MacroVFPMemOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, + IntRegIndex rn, RegIndex vd, bool single, bool up, + bool writeback, bool load, uint32_t offset); }; -/** - * 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, ExtMachInst _machInst, OpClass __opClass) - : PredMacroOp(mnem, _machInst, __opClass), - punwl(machInst.punwl), - prepost(machInst.puswl.prepost), - up(machInst.puswl.up), - n1bit(machInst.opcode22), - writeback(machInst.puswl.writeback), - loadop(machInst.puswl.loadOp), - n0bit(machInst.opcode15), - disp8(machInst.immed7_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]; - } -}; } #endif //__ARCH_ARM_INSTS_MACROMEM_HH__ diff -r 84bd4089958b src/arch/arm/insts/macromem.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/insts/macromem.cc Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,217 @@ +/* Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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 + */ + +#include "arch/arm/insts/macromem.hh" +#include "arch/arm/decoder.hh" + +using namespace ArmISAInst; + +namespace ArmISA +{ + +MacroMemOp::MacroMemOp(const char *mnem, ExtMachInst machInst, + OpClass __opClass, IntRegIndex rn, + bool index, bool up, bool user, bool writeback, + bool load, uint32_t reglist) : + PredMacroOp(mnem, machInst, __opClass) +{ + uint32_t regs = reglist; + uint32_t ones = number_of_ones(reglist); + // Remember that writeback adds a uop + numMicroops = ones + (writeback ? 1 : 0) + 1; + microOps = new StaticInstPtr[numMicroops]; + uint32_t addr = 0; + + if (!up) + addr = (ones << 2) - 4; + + if (!index) + addr += 4; + + StaticInstPtr *uop = microOps; + StaticInstPtr wbUop; + if (writeback) { + if (up) { + wbUop = new MicroAddiUop(machInst, rn, rn, ones * 4); + } else { + wbUop = new MicroSubiUop(machInst, rn, rn, ones * 4); + } + } + + // Add 0 to Rn and stick it in ureg0. + // This is equivalent to a move. + *uop = new MicroAddiUop(machInst, INTREG_UREG0, rn, 0); + + // Write back at the start for loads. This covers the ldm exception return + // case where the base needs to be written in the old mode. Stores may need + // the original value of the base, but they don't change mode and can + // write back at the end like before. + if (load && writeback) { + *++uop = wbUop; + } + + unsigned reg = 0; + bool force_user = user & !bits(reglist, 15); + bool exception_ret = user & bits(reglist, 15); + + for (int i = 0; i < ones; i++) { + // Find the next register. + while (!bits(regs, reg)) + reg++; + replaceBits(regs, reg, 0); + + unsigned regIdx = reg; + if (force_user) { + regIdx = intRegInMode(MODE_USER, regIdx); + } + + if (load) { + if (reg == INTREG_PC && exception_ret) { + // This must be the exception return form of ldm. + *++uop = new MicroLdrRetUop(machInst, regIdx, + INTREG_UREG0, up, addr); + } else { + *++uop = new MicroLdrUop(machInst, regIdx, + INTREG_UREG0, up, addr); + } + } else { + *++uop = new MicroStrUop(machInst, regIdx, INTREG_UREG0, up, addr); + } + + if (up) + addr += 4; + else + addr -= 4; + } + + if (!load && writeback) { + *++uop = wbUop; + } + + (*uop)->setLastMicroop(); + + for (StaticInstPtr *curUop = microOps; + !(*curUop)->isLastMicroop(); curUop++) { + MicroOp * uopPtr = dynamic_cast(curUop->get()); + assert(uopPtr); + uopPtr->setDelayedCommit(); + } +} + +MacroVFPMemOp::MacroVFPMemOp(const char *mnem, ExtMachInst machInst, + OpClass __opClass, IntRegIndex rn, + RegIndex vd, bool single, bool up, + bool writeback, bool load, uint32_t offset) : + PredMacroOp(mnem, machInst, __opClass) +{ + int i = 0; + + // The lowest order bit selects fldmx (set) or fldmd (clear). These seem + // to be functionally identical except that fldmx is deprecated. For now + // we'll assume they're otherwise interchangable. + int count = (single ? offset : (offset / 2)); + if (count == 0 || count > NumFloatArchRegs) + warn_once("Bad offset field for VFP load/store multiple.\n"); + if (count == 0) { + // Force there to be at least one microop so the macroop makes sense. + writeback = true; + } + if (count > NumFloatArchRegs) + count = NumFloatArchRegs; + + numMicroops = count * (single ? 1 : 2) + (writeback ? 1 : 0); + microOps = new StaticInstPtr[numMicroops]; + + int64_t addr = 0; + + if (!up) + addr = 4 * offset; + + bool tempUp = up; + for (int j = 0; j < count; j++) { + if (load) { + microOps[i++] = new MicroLdrFpUop(machInst, vd++, rn, + tempUp, addr); + if (!single) + microOps[i++] = new MicroLdrFpUop(machInst, vd++, rn, tempUp, + addr + (up ? 4 : -4)); + } else { + microOps[i++] = new MicroStrFpUop(machInst, vd++, rn, + tempUp, addr); + if (!single) + microOps[i++] = new MicroStrFpUop(machInst, vd++, rn, tempUp, + addr + (up ? 4 : -4)); + } + if (!tempUp) { + addr -= (single ? 4 : 8); + // The microops don't handle negative displacement, so turn if we + // hit zero, flip polarity and start adding. + if (addr <= 0) { + tempUp = true; + addr = -addr; + } + } else { + addr += (single ? 4 : 8); + } + } + + if (writeback) { + if (up) { + microOps[i++] = + new MicroAddiUop(machInst, rn, rn, 4 * offset); + } else { + microOps[i++] = + new MicroSubiUop(machInst, rn, rn, 4 * offset); + } + } + + assert(numMicroops == i); + microOps[numMicroops - 1]->setLastMicroop(); + + for (StaticInstPtr *curUop = microOps; + !(*curUop)->isLastMicroop(); curUop++) { + MicroOp * uopPtr = dynamic_cast(curUop->get()); + assert(uopPtr); + uopPtr->setDelayedCommit(); + } +} + +} diff -r 84bd4089958b src/arch/arm/insts/mem.hh --- a/src/arch/arm/insts/mem.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/insts/mem.hh Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,17 @@ -/* Copyright (c) 2007-2008 The Florida State University +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2007-2008 The Florida State University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,106 +46,380 @@ namespace ArmISA { -/** - * Base class for general Arm memory-format instructions. - */ + +class Swap : public PredOp +{ + protected: + IntRegIndex dest; + IntRegIndex op1; + IntRegIndex base; + + Swap(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _base) + : PredOp(mnem, _machInst, __opClass), + dest(_dest), op1(_op1), base(_base) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +// The address is a base register plus an immediate. +class RfeOp : public PredOp +{ + public: + enum AddrMode { + DecrementAfter, + DecrementBefore, + IncrementAfter, + IncrementBefore + }; + protected: + IntRegIndex base; + AddrMode mode; + bool wb; + + RfeOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _base, AddrMode _mode, bool _wb) + : PredOp(mnem, _machInst, __opClass), + base(_base), mode(_mode), wb(_wb) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +// The address is a base register plus an immediate. +class SrsOp : public PredOp +{ + public: + enum AddrMode { + DecrementAfter, + DecrementBefore, + IncrementAfter, + IncrementBefore + }; + protected: + uint32_t regMode; + AddrMode mode; + bool wb; + + SrsOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + uint32_t _regMode, AddrMode _mode, bool _wb) + : PredOp(mnem, _machInst, __opClass), + regMode(_regMode), mode(_mode), wb(_wb) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + class Memory : public PredOp { + public: + enum AddrMode { + AddrMd_Offset, + AddrMd_PreIndex, + AddrMd_PostIndex + }; + protected: - /// Memory request flags. See mem_req_base.hh. - unsigned memAccessFlags; + IntRegIndex dest; + IntRegIndex base; + bool add; - /// 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, ExtMachInst _machInst, OpClass __opClass) + Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _base, bool _add) : PredOp(mnem, _machInst, __opClass), - memAccessFlags(0), - disp(machInst.immed11_0), - disp8(machInst.immed7_0 << 2), - up(machInst.puswl.up), - hilo((machInst.immedHi11_8 << 4) | machInst.immedLo3_0), - shift_size(machInst.shiftSize), shift(machInst.shift) - { - } - - std::string - generateDisassembly(Addr pc, const SymbolTable *symtab) const; + dest(_dest), base(_base), add(_add) + {} virtual void printOffset(std::ostream &os) const {} + + virtual void + printDest(std::ostream &os) const + { + printReg(os, dest); + } + + void printInst(std::ostream &os, AddrMode addrMode) const; }; -class MemoryDisp : public Memory +// The address is a base register plus an immediate. +class MemoryImm : public Memory { protected: - /// Constructor - MemoryDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) - : Memory(mnem, _machInst, __opClass) - { - } + int32_t imm; + + MemoryImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _base, bool _add, int32_t _imm) + : Memory(mnem, _machInst, __opClass, _dest, _base, _add), imm(_imm) + {} void printOffset(std::ostream &os) const { - ccprintf(os, "#%#x", (machInst.puswl.up ? disp : -disp)); + int32_t pImm = imm; + if (!add) + pImm = -pImm; + ccprintf(os, "#%d", pImm); } }; -class MemoryHilo : public Memory +class MemoryExImm : public MemoryImm { protected: - /// Constructor - MemoryHilo(const char *mnem, ExtMachInst _machInst, OpClass __opClass) - : Memory(mnem, _machInst, __opClass) - { - } + IntRegIndex result; + + MemoryExImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _result, IntRegIndex _dest, IntRegIndex _base, + bool _add, int32_t _imm) + : MemoryImm(mnem, _machInst, __opClass, _dest, _base, _add, _imm), + result(_result) + {} void - printOffset(std::ostream &os) const + printDest(std::ostream &os) const { - ccprintf(os, "#%#x", (machInst.puswl.up ? hilo : -hilo)); + printReg(os, result); + os << ", "; + MemoryImm::printDest(os); } }; -class MemoryShift : public Memory +// The address is a base register plus an immediate. +class MemoryDImm : public MemoryImm { protected: - /// Constructor - MemoryShift(const char *mnem, ExtMachInst _machInst, OpClass __opClass) - : Memory(mnem, _machInst, __opClass) - { - } + IntRegIndex dest2; + + MemoryDImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, int32_t _imm) + : MemoryImm(mnem, _machInst, __opClass, _dest, _base, _add, _imm), + dest2(_dest2) + {} void - printOffset(std::ostream &os) const + printDest(std::ostream &os) const { - printShiftOperand(os); + MemoryImm::printDest(os); + os << ", "; + printReg(os, dest2); } }; +class MemoryExDImm : public MemoryDImm +{ + protected: + IntRegIndex result; + + MemoryExDImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _result, IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, int32_t _imm) + : MemoryDImm(mnem, _machInst, __opClass, _dest, _dest2, + _base, _add, _imm), result(_result) + {} + + void + printDest(std::ostream &os) const + { + printReg(os, result); + os << ", "; + MemoryDImm::printDest(os); + } +}; + +// The address is a shifted register plus an immediate class MemoryReg : public Memory { protected: - /// Constructor - MemoryReg(const char *mnem, ExtMachInst _machInst, OpClass __opClass) - : Memory(mnem, _machInst, __opClass) - { - } + int32_t shiftAmt; + ArmShiftType shiftType; + IntRegIndex index; + + MemoryReg(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _base, bool _add, + int32_t _shiftAmt, ArmShiftType _shiftType, + IntRegIndex _index) + : Memory(mnem, _machInst, __opClass, _dest, _base, _add), + shiftAmt(_shiftAmt), shiftType(_shiftType), index(_index) + {} + + void printOffset(std::ostream &os) const; +}; + +class MemoryDReg : public MemoryReg +{ + protected: + IntRegIndex dest2; + + MemoryDReg(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, + int32_t _shiftAmt, ArmShiftType _shiftType, + IntRegIndex _index) + : MemoryReg(mnem, _machInst, __opClass, _dest, _base, _add, + _shiftAmt, _shiftType, _index), + dest2(_dest2) + {} void - printOffset(std::ostream &os) const + printDest(std::ostream &os) const { - os << (machInst.puswl.up ? "+ " : "- "); - printReg(os, machInst.rm); + MemoryReg::printDest(os); + os << ", "; + printReg(os, dest2); + } +}; + +template +class MemoryOffset : public Base +{ + protected: + MemoryOffset(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _base, + bool _add, int32_t _imm) + : Base(mnem, _machInst, __opClass, _dest, _base, _add, _imm) + {} + + MemoryOffset(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _base, + bool _add, int32_t _shiftAmt, ArmShiftType _shiftType, + IntRegIndex _index) + : Base(mnem, _machInst, __opClass, _dest, _base, _add, + _shiftAmt, _shiftType, _index) + {} + + MemoryOffset(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, int32_t _imm) + : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, _imm) + {} + + MemoryOffset(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _result, + IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, int32_t _imm) + : Base(mnem, _machInst, __opClass, _result, + _dest, _dest2, _base, _add, _imm) + {} + + MemoryOffset(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, + int32_t _shiftAmt, ArmShiftType _shiftType, + IntRegIndex _index) + : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, + _shiftAmt, _shiftType, _index) + {} + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + this->printInst(ss, Memory::AddrMd_Offset); + return ss.str(); + } +}; + +template +class MemoryPreIndex : public Base +{ + protected: + MemoryPreIndex(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _base, + bool _add, int32_t _imm) + : Base(mnem, _machInst, __opClass, _dest, _base, _add, _imm) + {} + + MemoryPreIndex(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _base, + bool _add, int32_t _shiftAmt, ArmShiftType _shiftType, + IntRegIndex _index) + : Base(mnem, _machInst, __opClass, _dest, _base, _add, + _shiftAmt, _shiftType, _index) + {} + + MemoryPreIndex(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, int32_t _imm) + : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, _imm) + {} + + MemoryPreIndex(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _result, + IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, int32_t _imm) + : Base(mnem, _machInst, __opClass, _result, + _dest, _dest2, _base, _add, _imm) + {} + + MemoryPreIndex(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, + int32_t _shiftAmt, ArmShiftType _shiftType, + IntRegIndex _index) + : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, + _shiftAmt, _shiftType, _index) + {} + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + this->printInst(ss, Memory::AddrMd_PreIndex); + return ss.str(); + } +}; + +template +class MemoryPostIndex : public Base +{ + protected: + MemoryPostIndex(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _base, + bool _add, int32_t _imm) + : Base(mnem, _machInst, __opClass, _dest, _base, _add, _imm) + {} + + MemoryPostIndex(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _base, + bool _add, int32_t _shiftAmt, ArmShiftType _shiftType, + IntRegIndex _index) + : Base(mnem, _machInst, __opClass, _dest, _base, _add, + _shiftAmt, _shiftType, _index) + {} + + MemoryPostIndex(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, int32_t _imm) + : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, _imm) + {} + + MemoryPostIndex(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _result, + IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, int32_t _imm) + : Base(mnem, _machInst, __opClass, _result, + _dest, _dest2, _base, _add, _imm) + {} + + MemoryPostIndex(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2, + IntRegIndex _base, bool _add, + int32_t _shiftAmt, ArmShiftType _shiftType, + IntRegIndex _index) + : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, + _shiftAmt, _shiftType, _index) + {} + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + this->printInst(ss, Memory::AddrMd_PostIndex); + return ss.str(); } }; } diff -r 84bd4089958b src/arch/arm/insts/mem.cc --- a/src/arch/arm/insts/mem.cc Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/insts/mem.cc Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,16 @@ -/* Copyright (c) 2007-2008 The Florida State University +/* Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2007-2008 The Florida State University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,24 +42,160 @@ #include "arch/arm/insts/mem.hh" #include "base/loader/symtab.hh" +using namespace std; + namespace ArmISA { -std::string -Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const + +void +MemoryReg::printOffset(std::ostream &os) const { - std::stringstream ss; + if (!add) + os << "-"; + printReg(os, index); + if (shiftType != LSL || shiftAmt != 0) { + switch (shiftType) { + case LSL: + ccprintf(os, " LSL #%d", shiftAmt); + break; + case LSR: + if (shiftAmt == 0) { + ccprintf(os, " LSR #%d", 32); + } else { + ccprintf(os, " LSR #%d", shiftAmt); + } + break; + case ASR: + if (shiftAmt == 0) { + ccprintf(os, " ASR #%d", 32); + } else { + ccprintf(os, " ASR #%d", shiftAmt); + } + break; + case ROR: + if (shiftAmt == 0) { + ccprintf(os, " RRX"); + } else { + ccprintf(os, " ROR #%d", shiftAmt); + } + break; + } + } +} + +string +Swap::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + stringstream ss; printMnemonic(ss); - printReg(ss, machInst.rd); + printReg(ss, dest); + ss << ", "; + printReg(ss, op1); ss << ", ["; - printReg(ss, machInst.rn); - ss << ", "; - if (machInst.puswl.prepost == 1) - printOffset(ss); + printReg(ss, base); ss << "]"; - if (machInst.puswl.prepost == 0) - printOffset(ss); - else if (machInst.puswl.writeback) - ss << "!"; return ss.str(); } + +string +RfeOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + stringstream ss; + switch (mode) { + case DecrementAfter: + printMnemonic(ss, "da"); + break; + case DecrementBefore: + printMnemonic(ss, "db"); + break; + case IncrementAfter: + printMnemonic(ss, "ia"); + break; + case IncrementBefore: + printMnemonic(ss, "ib"); + break; + } + printReg(ss, base); + if (wb) { + ss << "!"; + } + return ss.str(); } + +string +SrsOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + stringstream ss; + switch (mode) { + case DecrementAfter: + printMnemonic(ss, "da"); + break; + case DecrementBefore: + printMnemonic(ss, "db"); + break; + case IncrementAfter: + printMnemonic(ss, "ia"); + break; + case IncrementBefore: + printMnemonic(ss, "ib"); + break; + } + printReg(ss, INTREG_SP); + if (wb) { + ss << "!"; + } + ss << ", #"; + switch (regMode) { + case MODE_USER: + ss << "user"; + break; + case MODE_FIQ: + ss << "fiq"; + break; + case MODE_IRQ: + ss << "irq"; + break; + case MODE_SVC: + ss << "supervisor"; + break; + case MODE_MON: + ss << "monitor"; + break; + case MODE_ABORT: + ss << "abort"; + break; + case MODE_UNDEFINED: + ss << "undefined"; + break; + case MODE_SYSTEM: + ss << "system"; + break; + default: + ss << "unrecognized"; + break; + } + return ss.str(); +} + +void +Memory::printInst(std::ostream &os, AddrMode addrMode) const +{ + printMnemonic(os); + printDest(os); + os << ", ["; + printReg(os, base); + if (addrMode != AddrMd_PostIndex) { + os << ", "; + printOffset(os); + os << "]"; + if (addrMode == AddrMd_PreIndex) { + os << "!"; + } + } else { + os << "] "; + printOffset(os); + + } +} + +} diff -r 84bd4089958b src/arch/arm/insts/misc.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/insts/misc.hh Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Gabe Black + */ + +#ifndef __ARCH_ARM_INSTS_MISC_HH__ +#define __ARCH_ARM_INSTS_MISC_HH__ + +#include "arch/arm/insts/pred_inst.hh" + +class MrsOp : public PredOp +{ + protected: + IntRegIndex dest; + + MrsOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest) : + PredOp(mnem, _machInst, __opClass), dest(_dest) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class MsrBase : public PredOp +{ + protected: + uint8_t byteMask; + + MsrBase(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + uint8_t _byteMask) : + PredOp(mnem, _machInst, __opClass), byteMask(_byteMask) + {} + + void printMsrBase(std::ostream &os) const; +}; + +class MsrImmOp : public MsrBase +{ + protected: + uint32_t imm; + + MsrImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + uint32_t _imm, uint8_t _byteMask) : + MsrBase(mnem, _machInst, __opClass, _byteMask), imm(_imm) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class MsrRegOp : public MsrBase +{ + protected: + IntRegIndex op1; + + MsrRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _op1, uint8_t _byteMask) : + MsrBase(mnem, _machInst, __opClass, _byteMask), op1(_op1) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class ImmOp : public PredOp +{ + protected: + uint64_t imm; + + ImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + uint64_t _imm) : + PredOp(mnem, _machInst, __opClass), imm(_imm) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class RegImmOp : public PredOp +{ + protected: + IntRegIndex dest; + uint64_t imm; + + RegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, uint64_t _imm) : + PredOp(mnem, _machInst, __opClass), dest(_dest), imm(_imm) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class RegRegOp : public PredOp +{ + protected: + IntRegIndex dest; + IntRegIndex op1; + + RegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1) : + PredOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class RegImmRegOp : public PredOp +{ + protected: + IntRegIndex dest; + uint64_t imm; + IntRegIndex op1; + + RegImmRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, uint64_t _imm, IntRegIndex _op1) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), imm(_imm), op1(_op1) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class RegRegRegImmOp : public PredOp +{ + protected: + IntRegIndex dest; + IntRegIndex op1; + IntRegIndex op2; + uint64_t imm; + + RegRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, + uint64_t _imm) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), op1(_op1), op2(_op2), imm(_imm) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class RegRegRegRegOp : public PredOp +{ + protected: + IntRegIndex dest; + IntRegIndex op1; + IntRegIndex op2; + IntRegIndex op3; + + RegRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, + IntRegIndex _op2, IntRegIndex _op3) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), op1(_op1), op2(_op2), op3(_op3) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class RegRegRegOp : public PredOp +{ + protected: + IntRegIndex dest; + IntRegIndex op1; + IntRegIndex op2; + + RegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), op1(_op1), op2(_op2) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class RegRegImmOp : public PredOp +{ + protected: + IntRegIndex dest; + IntRegIndex op1; + uint64_t imm; + + RegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, + uint64_t _imm) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), op1(_op1), imm(_imm) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class RegRegImmImmOp : public PredOp +{ + protected: + IntRegIndex dest; + IntRegIndex op1; + uint64_t imm1; + uint64_t imm2; + + RegRegImmImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, + uint64_t _imm1, uint64_t _imm2) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), op1(_op1), imm1(_imm1), imm2(_imm2) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class RegImmRegShiftOp : public PredOp +{ + protected: + IntRegIndex dest; + uint64_t imm; + IntRegIndex op1; + int32_t shiftAmt; + ArmShiftType shiftType; + + RegImmRegShiftOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, uint64_t _imm, IntRegIndex _op1, + int32_t _shiftAmt, ArmShiftType _shiftType) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), imm(_imm), op1(_op1), + shiftAmt(_shiftAmt), shiftType(_shiftType) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class UnknownOp : public PredOp +{ + protected: + + UnknownOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : + PredOp(mnem, _machInst, __opClass) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +#endif diff -r 84bd4089958b src/arch/arm/insts/misc.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/insts/misc.cc Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Gabe Black + */ + +#include "arch/arm/insts/misc.hh" + +std::string +MrsOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest); + ss << ", "; + bool foundPsr = false; + for (unsigned i = 0; i < numSrcRegs(); i++) { + int idx = srcRegIdx(i); + if (idx < Ctrl_Base_DepTag) { + continue; + } + idx -= Ctrl_Base_DepTag; + if (idx == MISCREG_CPSR) { + ss << "cpsr"; + foundPsr = true; + break; + } + if (idx == MISCREG_SPSR) { + ss << "spsr"; + foundPsr = true; + break; + } + } + if (!foundPsr) { + ss << "????"; + } + return ss.str(); +} + +void +MsrBase::printMsrBase(std::ostream &os) const +{ + printMnemonic(os); + bool apsr = false; + bool foundPsr = false; + for (unsigned i = 0; i < numDestRegs(); i++) { + int idx = destRegIdx(i); + if (idx < Ctrl_Base_DepTag) { + continue; + } + idx -= Ctrl_Base_DepTag; + if (idx == MISCREG_CPSR) { + os << "cpsr_"; + foundPsr = true; + break; + } + if (idx == MISCREG_SPSR) { + if (bits(byteMask, 1, 0)) { + os << "spsr_"; + } else { + os << "apsr_"; + apsr = true; + } + foundPsr = true; + break; + } + } + if (!foundPsr) { + os << "????"; + return; + } + if (bits(byteMask, 3)) { + if (apsr) { + os << "nzcvq"; + } else { + os << "f"; + } + } + if (bits(byteMask, 2)) { + if (apsr) { + os << "g"; + } else { + os << "s"; + } + } + if (bits(byteMask, 1)) { + os << "x"; + } + if (bits(byteMask, 0)) { + os << "c"; + } +} + +std::string +MsrImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMsrBase(ss); + ccprintf(ss, ", #%#x", imm); + return ss.str(); +} + +std::string +MsrRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMsrBase(ss); + ss << ", "; + printReg(ss, op1); + return ss.str(); +} + +std::string +ImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + ccprintf(ss, "#%d", imm); + return ss.str(); +} + +std::string +RegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest); + ccprintf(ss, ", #%d", imm); + return ss.str(); +} + +std::string +RegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest); + ss << ", "; + printReg(ss, op1); + return ss.str(); +} + +std::string +RegRegRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest); + ss << ", "; + printReg(ss, op1); + ss << ", "; + printReg(ss, op2); + ccprintf(ss, ", #%d", imm); + return ss.str(); +} + +std::string +RegRegRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest); + ss << ", "; + printReg(ss, op1); + ss << ", "; + printReg(ss, op2); + ss << ", "; + printReg(ss, op3); + return ss.str(); +} + +std::string +RegRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest); + ss << ", "; + printReg(ss, op1); + ss << ", "; + printReg(ss, op2); + return ss.str(); +} + +std::string +RegRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest); + ss << ", "; + printReg(ss, op1); + ccprintf(ss, ", #%d", imm); + return ss.str(); +} + +std::string +RegRegImmImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest); + ss << ", "; + printReg(ss, op1); + ccprintf(ss, ", #%d, #%d", imm1, imm2); + return ss.str(); +} + +std::string +RegImmRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest); + ccprintf(ss, ", #%d, ", imm); + printReg(ss, op1); + return ss.str(); +} + +std::string +RegImmRegShiftOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest); + ccprintf(ss, ", #%d, ", imm); + printShiftOperand(ss, op1, true, shiftAmt, INTREG_ZERO, shiftType); + printReg(ss, op1); + return ss.str(); +} + +std::string +UnknownOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + return csprintf("%-10s (inst %#08x)", "unknown", machInst); +} diff -r 84bd4089958b src/arch/arm/insts/mult.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/insts/mult.hh Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,78 @@ +/* Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Gabe Black + */ +#ifndef __ARCH_ARM_INSTS_MULT_HH__ +#define __ARCH_ARM_INSTS_MULT_HH__ + +#include "arch/arm/insts/static_inst.hh" +#include "base/trace.hh" + +namespace ArmISA +{ + +/** + * Base class for multipy instructions using three registers. + */ +class Mult3 : public PredOp +{ + protected: + IntRegIndex reg0, reg1, reg2; + + Mult3(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _reg0, IntRegIndex _reg1, IntRegIndex _reg2) : + PredOp(mnem, _machInst, __opClass), + reg0(_reg0), reg1(_reg1), reg2(_reg2) + {} +}; + +/** + * Base class for multipy instructions using four registers. + */ +class Mult4 : public Mult3 +{ + protected: + IntRegIndex reg3; + + Mult4(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _reg0, IntRegIndex _reg1, + IntRegIndex _reg2, IntRegIndex _reg3) : + Mult3(mnem, _machInst, __opClass, _reg0, _reg1, _reg2), reg3(_reg3) + {} +}; +} + +#endif //__ARCH_ARM_INSTS_MULT_HH__ diff -r 84bd4089958b src/arch/arm/insts/pred_inst.hh --- a/src/arch/arm/insts/pred_inst.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/insts/pred_inst.hh Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,16 @@ -/* Copyright (c) 2007-2008 The Florida State University +/* Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2007-2008 The Florida State University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,6 +53,116 @@ (immValue << (32 - (rotateValue & 31)))); } +static inline uint32_t +modified_imm(uint8_t ctrlImm, uint8_t dataImm) +{ + uint32_t bigData = dataImm; + uint32_t bigCtrl = ctrlImm; + if (bigCtrl < 4) { + switch (bigCtrl) { + case 0: + return bigData; + case 1: + return bigData | (bigData << 16); + case 2: + return (bigData << 8) | (bigData << 24); + case 3: + return (bigData << 0) | (bigData << 8) | + (bigData << 16) | (bigData << 24); + } + } + bigCtrl = (bigCtrl << 1) | ((bigData >> 7) & 0x1); + bigData |= (1 << 7); + return bigData << (32 - bigCtrl); +} + +static inline uint64_t +simd_modified_imm(bool op, uint8_t cmode, uint8_t data) +{ + uint64_t bigData = data; + switch (cmode) { + case 0x0: + case 0x1: + bigData = (bigData << 0) | (bigData << 32); + break; + case 0x2: + case 0x3: + bigData = (bigData << 8) | (bigData << 40); + break; + case 0x4: + case 0x5: + bigData = (bigData << 16) | (bigData << 48); + break; + case 0x6: + case 0x7: + bigData = (bigData << 24) | (bigData << 56); + break; + case 0x8: + case 0x9: + bigData = (bigData << 0) | (bigData << 16) | + (bigData << 32) | (bigData << 48); + break; + case 0xa: + case 0xb: + bigData = (bigData << 8) | (bigData << 24) | + (bigData << 40) | (bigData << 56); + break; + case 0xc: + bigData = (0xffULL << 0) | (bigData << 8) | + (0xffULL << 32) | (bigData << 40); + break; + case 0xd: + bigData = (0xffffULL << 0) | (bigData << 16) | + (0xffffULL << 32) | (bigData << 48); + break; + case 0xe: + if (op) { + bigData = (bigData << 0) | (bigData << 8) | + (bigData << 16) | (bigData << 24) | + (bigData << 32) | (bigData << 40) | + (bigData << 48) | (bigData << 56); + } else { + bigData = 0; + for (int i = 7; i >= 0; i--) { + if (bits(data, i)) { + bigData |= (0xFF << (i * 8)); + } + } + } + case 0xf: + if (!op) { + uint64_t bVal = bits(bigData, 6) ? (0x1F) : (0x20); + bigData = (bits(bigData, 5, 0) << 19) | + (bVal << 25) | (bits(bigData, 7) << 31); + bigData |= (bigData << 32); + } + // Fall through + default: + panic("Illegal modified SIMD immediate parameters.\n"); + } + return bigData; +} + +static inline uint64_t +vfp_modified_imm(uint8_t data, bool wide) +{ + uint64_t bigData = data; + uint64_t repData; + if (wide) { + repData = bits(data, 6) ? 0xFF : 0; + bigData = (bits(bigData, 5, 0) << 48) | + (repData << 54) | (bits(~bigData, 6) << 62) | + (bits(bigData, 7) << 63); + } else { + repData = bits(data, 6) ? 0x1F : 0; + bigData = (bits(bigData, 5, 0) << 19) | + (repData << 25) | (bits(~bigData, 6) << 30) | + (bits(bigData, 7) << 31); + } + return bigData; +} + + /** * Base class for predicated integer operations. */ @@ -51,9 +173,11 @@ ConditionCode condCode; /// Constructor - PredOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + PredOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : ArmStaticInst(mnem, _machInst, __opClass), - condCode((ConditionCode)(unsigned)machInst.condCode) + condCode(machInst.itstateMask ? + (ConditionCode)(uint8_t)machInst.itstateCond : + (ConditionCode)(unsigned)machInst.condCode) { } }; @@ -66,19 +190,19 @@ protected: uint32_t imm; - uint32_t rotate; uint32_t rotated_imm; uint32_t rotated_carry; + uint32_t rotate; /// Constructor - PredImmOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + PredImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : PredOp(mnem, _machInst, __opClass), - imm(machInst.imm), rotate(machInst.rotate << 1), - rotated_imm(0), rotated_carry(0) + imm(machInst.imm), rotated_imm(0), rotated_carry(0), + rotate(machInst.rotate << 1) { rotated_imm = rotate_imm(imm, rotate); if (rotate != 0) - rotated_carry = (rotated_imm >> 31) & 1; + rotated_carry = bits(rotated_imm, 31); } std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; @@ -95,7 +219,7 @@ uint32_t shift; /// Constructor - PredIntOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + PredIntOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : PredOp(mnem, _machInst, __opClass), shift_size(machInst.shiftSize), shift(machInst.shift) { @@ -104,6 +228,59 @@ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; +class DataImmOp : public PredOp +{ + protected: + IntRegIndex dest, op1; + uint32_t imm; + // Whether the carry flag should be modified if that's an option for + // this instruction. + bool rotC; + + DataImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, uint32_t _imm, bool _rotC) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), op1(_op1), imm(_imm), rotC(_rotC) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class DataRegOp : public PredOp +{ + protected: + IntRegIndex dest, op1, op2; + int32_t shiftAmt; + ArmShiftType shiftType; + + DataRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, + int32_t _shiftAmt, ArmShiftType _shiftType) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), op1(_op1), op2(_op2), + shiftAmt(_shiftAmt), shiftType(_shiftType) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class DataRegRegOp : public PredOp +{ + protected: + IntRegIndex dest, op1, op2, shift; + ArmShiftType shiftType; + + DataRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, + IntRegIndex _shift, ArmShiftType _shiftType) : + PredOp(mnem, _machInst, __opClass), + dest(_dest), op1(_op1), op2(_op2), shift(_shift), + shiftType(_shiftType) + {} + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + /** * Base class for predicated macro-operations. */ @@ -115,7 +292,7 @@ StaticInstPtr * microOps; /// Constructor - PredMacroOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + PredMacroOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : PredOp(mnem, _machInst, __opClass), numMicroops(0) { @@ -147,7 +324,7 @@ class PredMicroop : public PredOp { /// Constructor - PredMicroop(const char *mnem, MachInst _machInst, OpClass __opClass) : + PredMicroop(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : PredOp(mnem, _machInst, __opClass) { flags[IsMicroop] = true; diff -r 84bd4089958b src/arch/arm/insts/pred_inst.cc --- a/src/arch/arm/insts/pred_inst.cc Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/insts/pred_inst.cc Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,16 @@ -/* Copyright (c) 2007-2008 The Florida State University +/* Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2007-2008 The Florida State University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,7 +47,16 @@ PredIntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { std::stringstream ss; - printDataInst(ss, false); + unsigned rotate = machInst.rotate * 2; + uint32_t imm = machInst.imm; + imm = (imm << (32 - rotate)) | (imm >> rotate); + printDataInst(ss, false, machInst.opcode4 == 0, machInst.sField, + (IntRegIndex)(uint32_t)machInst.rd, + (IntRegIndex)(uint32_t)machInst.rn, + (IntRegIndex)(uint32_t)machInst.rm, + (IntRegIndex)(uint32_t)machInst.rs, + machInst.shiftSize, (ArmShiftType)(uint32_t)machInst.shift, + imm); return ss.str(); } @@ -43,7 +64,40 @@ PredImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { std::stringstream ss; - printDataInst(ss, true); + printDataInst(ss, true, machInst.opcode4 == 0, machInst.sField, + (IntRegIndex)(uint32_t)machInst.rd, + (IntRegIndex)(uint32_t)machInst.rn, + (IntRegIndex)(uint32_t)machInst.rm, + (IntRegIndex)(uint32_t)machInst.rs, + machInst.shiftSize, (ArmShiftType)(uint32_t)machInst.shift, + imm); + return ss.str(); +} + +std::string +DataImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printDataInst(ss, true, false, /*XXX not really s*/ false, dest, op1, + INTREG_ZERO, INTREG_ZERO, 0, LSL, imm); + return ss.str(); +} + +std::string +DataRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printDataInst(ss, false, true, /*XXX not really s*/ false, dest, op1, + op2, INTREG_ZERO, shiftAmt, shiftType, 0); + return ss.str(); +} + +std::string +DataRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printDataInst(ss, false, false, /*XXX not really s*/ false, dest, op1, + op2, shift, 0, shiftType, 0); return ss.str(); } diff -r 84bd4089958b src/arch/arm/insts/static_inst.hh --- a/src/arch/arm/insts/static_inst.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/insts/static_inst.hh Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,16 @@ -/* Copyright (c) 2007-2008 The Florida State University +/* Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2007-2008 The Florida State University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,6 +46,7 @@ namespace ArmISA { + class ArmStaticInst : public StaticInst { protected: @@ -47,14 +60,74 @@ bool shift_carry_rs(uint32_t base, uint32_t shamt, uint32_t type, uint32_t cfval) const; - bool arm_add_carry(int32_t result, int32_t lhs, int32_t rhs) const; - bool arm_sub_carry(int32_t result, int32_t lhs, int32_t rhs) const; + template + static inline bool + saturateOp(int32_t &res, int64_t op1, int64_t op2, bool sub=false) + { + int64_t midRes = sub ? (op1 - op2) : (op1 + op2); + if (bits(midRes, width) != bits(midRes, width - 1)) { + if (midRes > 0) + res = (LL(1) << (width - 1)) - 1; + else + res = -(LL(1) << (width - 1)); + return true; + } else { + res = midRes; + return false; + } + } - bool arm_add_overflow(int32_t result, int32_t lhs, int32_t rhs) const; - bool arm_sub_overflow(int32_t result, int32_t lhs, int32_t rhs) const; + static inline bool + satInt(int32_t &res, int64_t op, int width) + { + width--; + if (op >= (LL(1) << width)) { + res = (LL(1) << width) - 1; + return true; + } else if (op < -(LL(1) << width)) { + res = -(LL(1) << width); + return true; + } else { + res = op; + return false; + } + } + + template + static inline bool + uSaturateOp(uint32_t &res, int64_t op1, int64_t op2, bool sub=false) + { + int64_t midRes = sub ? (op1 - op2) : (op1 + op2); + if (midRes >= (LL(1) << width)) { + res = (LL(1) << width) - 1; + return true; + } else if (midRes < 0) { + res = 0; + return true; + } else { + res = midRes; + return false; + } + } + + static inline bool + uSatInt(int32_t &res, int64_t op, int width) + { + if (op >= (LL(1) << width)) { + res = (LL(1) << width) - 1; + return true; + } else if (op < 0) { + res = 0; + return true; + } else { + res = op; + return false; + } + } // Constructor - ArmStaticInst(const char *mnem, MachInst _machInst, OpClass __opClass) + ArmStaticInst(const char *mnem, ExtMachInst _machInst, + OpClass __opClass) : StaticInst(mnem, _machInst, __opClass) { } @@ -68,16 +141,22 @@ void printMemSymbol(std::ostream &os, const SymbolTable *symtab, const std::string &prefix, const Addr addr, const std::string &suffix) const; - void printShiftOperand(std::ostream &os) const; + void printShiftOperand(std::ostream &os, IntRegIndex rm, + bool immShift, uint32_t shiftAmt, + IntRegIndex rs, ArmShiftType type) const; void printDataInst(std::ostream &os, bool withImm) const; + void printDataInst(std::ostream &os, bool withImm, bool immShift, bool s, + IntRegIndex rd, IntRegIndex rn, IntRegIndex rm, + IntRegIndex rs, uint32_t shiftAmt, ArmShiftType type, + uint32_t imm) const; std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; - static uint32_t + static inline uint32_t cpsrWriteByInstr(CPSR cpsr, uint32_t val, - uint8_t byteMask, bool affectState) + uint8_t byteMask, bool affectState, bool nmfi) { bool privileged = (cpsr.mode != MODE_USER); @@ -98,16 +177,24 @@ if (bits(byteMask, 0)) { if (privileged) { bitMask = bitMask | mask(7, 6); - bitMask = bitMask | mask(5); + if (!badMode((OperatingMode)(val & mask(5)))) { + bitMask = bitMask | mask(5); + } else { + warn_once("Ignoring write of bad mode to CPSR.\n"); + } } if (affectState) bitMask = bitMask | (1 << 5); } - return ((uint32_t)cpsr & ~bitMask) | (val & bitMask); + bool cpsr_f = cpsr.f; + uint32_t new_cpsr = ((uint32_t)cpsr & ~bitMask) | (val & bitMask); + if (nmfi && !cpsr_f) + new_cpsr &= ~(1 << 6); + return new_cpsr; } - static uint32_t + static inline uint32_t spsrWriteByInstr(uint32_t spsr, uint32_t val, uint8_t byteMask, bool affectState) { @@ -124,6 +211,91 @@ return ((spsr & ~bitMask) | (val & bitMask)); } + + template + static inline Addr + readPC(XC *xc) + { + Addr pc = xc->readPC(); + Addr tBit = pc & (ULL(1) << PcTBitShift); + if (tBit) + return pc + 4; + else + return pc + 8; + } + + // Perform an regular branch. + template + static inline void + setNextPC(XC *xc, Addr val) + { + Addr npc = xc->readNextPC(); + if (npc & (ULL(1) << PcTBitShift)) { + val &= ~mask(1); + } else { + val &= ~mask(2); + } + xc->setNextPC((npc & PcModeMask) | + (val & ~PcModeMask)); + } + + template + static inline T + cSwap(T val, bool big) + { + if (big) { + return gtobe(val); + } else { + return gtole(val); + } + } + + // Perform an interworking branch. + template + static inline void + setIWNextPC(XC *xc, Addr val) + { + Addr stateBits = xc->readPC() & PcModeMask; + Addr jBit = (ULL(1) << PcJBitShift); + Addr tBit = (ULL(1) << PcTBitShift); + bool thumbEE = (stateBits == (tBit | jBit)); + + Addr newPc = (val & ~PcModeMask); + if (thumbEE) { + if (bits(newPc, 0)) { + newPc = newPc & ~mask(1); + } else { + panic("Bad thumbEE interworking branch address %#x.\n", newPc); + } + } else { + if (bits(newPc, 0)) { + stateBits = tBit; + newPc = newPc & ~mask(1); + } else if (!bits(newPc, 1)) { + stateBits = 0; + } else { + warn("Bad interworking branch address %#x.\n", newPc); + } + } + newPc = newPc | stateBits; + xc->setNextPC(newPc); + } + + // Perform an interworking branch in ARM mode, a regular branch + // otherwise. + template + static inline void + setAIWNextPC(XC *xc, Addr val) + { + Addr stateBits = xc->readPC() & PcModeMask; + Addr jBit = (ULL(1) << PcJBitShift); + Addr tBit = (ULL(1) << PcTBitShift); + if (!jBit && !tBit) { + setIWNextPC(xc, val); + } else { + setNextPC(xc, val); + } + } }; } diff -r 84bd4089958b src/arch/arm/insts/static_inst.cc --- a/src/arch/arm/insts/static_inst.cc Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/insts/static_inst.cc Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,16 @@ -/* Copyright (c) 2007-2008 The Florida State University +/* Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2007-2008 The Florida State University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,7 +50,7 @@ // Shift Rm by an immediate value int32_t ArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt, - uint32_t type, uint32_t cfval) const + uint32_t type, uint32_t cfval) const { assert(shamt < 32); ArmShiftType shiftType; @@ -55,9 +67,9 @@ return base >> shamt; case ASR: if (shamt == 0) - return (int32_t)base >> 31; + return (base >> 31) | -((base & (1 << 31)) >> 31); else - return (int32_t)base >> shamt; + return (base >> shamt) | -((base & (1 << 31)) >> shamt); case ROR: if (shamt == 0) return (cfval << 31) | (base >> 1); // RRX @@ -74,7 +86,7 @@ // Shift Rm by Rs int32_t ArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt, - uint32_t type, uint32_t cfval) const + uint32_t type, uint32_t cfval) const { enum ArmShiftType shiftType; shiftType = (enum ArmShiftType) type; @@ -93,9 +105,9 @@ return base >> shamt; case ASR: if (shamt >= 32) - return (int32_t)base >> 31; + return (base >> 31) | -((base & (1 << 31)) >> 31); else - return (int32_t)base >> shamt; + return (base >> shamt) | -((base & (1 << 31)) >> shamt); case ROR: shamt = shamt & 0x1f; if (shamt == 0) @@ -114,7 +126,7 @@ // Generate C for a shift by immediate bool ArmStaticInst::shift_carry_imm(uint32_t base, uint32_t shamt, - uint32_t type, uint32_t cfval) const + uint32_t type, uint32_t cfval) const { enum ArmShiftType shiftType; shiftType = (enum ArmShiftType) type; @@ -154,7 +166,7 @@ // Generate C for a shift by Rs bool ArmStaticInst::shift_carry_rs(uint32_t base, uint32_t shamt, - uint32_t type, uint32_t cfval) const + uint32_t type, uint32_t cfval) const { enum ArmShiftType shiftType; shiftType = (enum ArmShiftType) type; @@ -192,32 +204,6 @@ } -// Generate the appropriate carry bit for an addition operation -bool -ArmStaticInst::arm_add_carry(int32_t result, int32_t lhs, int32_t rhs) const -{ - return findCarry(32, result, lhs, rhs); -} - -// Generate the appropriate carry bit for a subtraction operation -bool -ArmStaticInst::arm_sub_carry(int32_t result, int32_t lhs, int32_t rhs) const -{ - return findCarry(32, result, lhs, ~rhs); -} - -bool -ArmStaticInst::arm_add_overflow(int32_t result, int32_t lhs, int32_t rhs) const -{ - return findOverflow(32, result, lhs, rhs); -} - -bool -ArmStaticInst::arm_sub_overflow(int32_t result, int32_t lhs, int32_t rhs) const -{ - return findOverflow(32, result, lhs, ~rhs); -} - void ArmStaticInst::printReg(std::ostream &os, int reg) const { @@ -302,13 +288,16 @@ case COND_AL: // This one is implicit. break; - case COND_NV: - os << "nv"; + case COND_UC: + // Unconditional. break; default: panic("Unrecognized condition code %d.\n", condCode); } - os << suffix << " "; + os << suffix; + if (machInst.bigThumb) + os << ".w"; + os << " "; } } @@ -330,14 +319,20 @@ } void -ArmStaticInst::printShiftOperand(std::ostream &os) const +ArmStaticInst::printShiftOperand(std::ostream &os, + IntRegIndex rm, + bool immShift, + uint32_t shiftAmt, + IntRegIndex rs, + ArmShiftType type) const { - printReg(os, machInst.rm); + bool firstOp = false; - bool immShift = (machInst.opcode4 == 0); + if (rm != INTREG_ZERO) { + printReg(os, rm); + } + bool done = false; - unsigned shiftAmt = (machInst.shiftSize); - ArmShiftType type = (ArmShiftType)(uint32_t)machInst.shift; if ((type == LSR || type == ASR) && immShift && shiftAmt == 0) shiftAmt = 32; @@ -348,66 +343,74 @@ done = true; break; } - os << ", LSL"; + if (!firstOp) + os << ", "; + os << "LSL"; break; case LSR: - os << ", LSR"; + if (!firstOp) + os << ", "; + os << "LSR"; break; case ASR: - os << ", ASR"; + if (!firstOp) + os << ", "; + os << "ASR"; break; case ROR: if (immShift && shiftAmt == 0) { - os << ", RRX"; + if (!firstOp) + os << ", "; + os << "RRX"; done = true; break; } - os << ", ROR"; + if (!firstOp) + os << ", "; + os << "ROR"; break; default: panic("Tried to disassemble unrecognized shift type.\n"); } if (!done) { - os << " "; + if (!firstOp) + os << " "; if (immShift) os << "#" << shiftAmt; else - printReg(os, machInst.rs); + printReg(os, rs); } } void -ArmStaticInst::printDataInst(std::ostream &os, bool withImm) const +ArmStaticInst::printDataInst(std::ostream &os, bool withImm, + bool immShift, bool s, IntRegIndex rd, IntRegIndex rn, + IntRegIndex rm, IntRegIndex rs, uint32_t shiftAmt, + ArmShiftType type, uint32_t imm) const { - printMnemonic(os, machInst.sField ? "s" : ""); - //XXX It would be nice if the decoder figured this all out for us. - unsigned opcode = machInst.opcode; + printMnemonic(os, s ? "s" : ""); bool firstOp = true; // Destination - // Cmp, cmn, teq, and tst don't have one. - if (opcode < 8 || opcode > 0xb) { + if (rd != INTREG_ZERO) { firstOp = false; - printReg(os, machInst.rd); + printReg(os, rd); } // Source 1. - // Mov and Movn don't have one of these. - if (opcode != 0xd && opcode != 0xf) { + if (rn != INTREG_ZERO) { if (!firstOp) os << ", "; firstOp = false; - printReg(os, machInst.rn); + printReg(os, rn); } if (!firstOp) os << ", "; if (withImm) { - unsigned rotate = machInst.rotate * 2; - uint32_t imm = machInst.imm; - ccprintf(os, "#%#x", (imm << (32 - rotate)) | (imm >> rotate)); + ccprintf(os, "#%d", imm); } else { - printShiftOperand(os); + printShiftOperand(os, rm, immShift, shiftAmt, rs, type); } } diff -r 84bd4089958b src/arch/arm/insts/vfp.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/insts/vfp.hh Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,450 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Gabe Black + */ + +#ifndef __ARCH_ARM_INSTS_VFP_HH__ +#define __ARCH_ARM_INSTS_VFP_HH__ + +#include "arch/arm/insts/misc.hh" +#include "arch/arm/miscregs.hh" +#include +#include + +namespace ArmISA +{ + +enum VfpMicroMode { + VfpNotAMicroop, + VfpMicroop, + VfpFirstMicroop, + VfpLastMicroop +}; + +template +static inline void +setVfpMicroFlags(VfpMicroMode mode, T &flags) +{ + switch (mode) { + case VfpMicroop: + flags[StaticInst::IsMicroop] = true; + break; + case VfpFirstMicroop: + flags[StaticInst::IsMicroop] = + flags[StaticInst::IsFirstMicroop] = true; + break; + case VfpLastMicroop: + flags[StaticInst::IsMicroop] = + flags[StaticInst::IsLastMicroop] = true; + break; + case VfpNotAMicroop: + break; + } + if (mode == VfpMicroop || mode == VfpFirstMicroop) { + flags[StaticInst::IsDelayedCommit] = true; + } +} + +enum FeExceptionBit +{ + FeDivByZero = FE_DIVBYZERO, + FeInexact = FE_INEXACT, + FeInvalid = FE_INVALID, + FeOverflow = FE_OVERFLOW, + FeUnderflow = FE_UNDERFLOW, + FeAllExceptions = FE_ALL_EXCEPT +}; + +enum FeRoundingMode +{ + FeRoundDown = FE_DOWNWARD, + FeRoundNearest = FE_TONEAREST, + FeRoundZero = FE_TOWARDZERO, + FeRoundUpward = FE_UPWARD +}; + +enum VfpRoundingMode +{ + VfpRoundNearest = 0, + VfpRoundUpward = 1, + VfpRoundDown = 2, + VfpRoundZero = 3 +}; + +template +static inline bool +flushToZero(fpType &op) +{ + fpType junk = 0.0; + if (std::fpclassify(op) == FP_SUBNORMAL) { + uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); + op = bitsToFp(fpToBits(op) & bitMask, junk); + return true; + } + return false; +} + +template +static inline bool +flushToZero(fpType &op1, fpType &op2) +{ + bool flush1 = flushToZero(op1); + bool flush2 = flushToZero(op2); + return flush1 || flush2; +} + +template +static inline void +vfpFlushToZero(FPSCR &fpscr, fpType &op) +{ + if (fpscr.fz == 1 && flushToZero(op)) { + fpscr.idc = 1; + } +} + +template +static inline void +vfpFlushToZero(FPSCR &fpscr, fpType &op1, fpType &op2) +{ + vfpFlushToZero(fpscr, op1); + vfpFlushToZero(fpscr, op2); +} + +static inline uint32_t +fpToBits(float fp) +{ + union + { + float fp; + uint32_t bits; + } val; + val.fp = fp; + return val.bits; +} + +static inline uint64_t +fpToBits(double fp) +{ + union + { + double fp; + uint64_t bits; + } val; + val.fp = fp; + return val.bits; +} + +static inline float +bitsToFp(uint64_t bits, float junk) +{ + union + { + float fp; + uint32_t bits; + } val; + val.bits = bits; + return val.fp; +} + +static inline double +bitsToFp(uint64_t bits, double junk) +{ + union + { + double fp; + uint64_t bits; + } val; + val.bits = bits; + return val.fp; +} + +typedef int VfpSavedState; + +VfpSavedState prepFpState(uint32_t rMode); +void finishVfp(FPSCR &fpscr, VfpSavedState state); + +template +fpType fixDest(FPSCR fpscr, fpType val, fpType op1); + +template +fpType fixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2); + +template +fpType fixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2); + +float fixFpDFpSDest(FPSCR fpscr, double val); +double fixFpSFpDDest(FPSCR fpscr, float val); + +float vcvtFpSFpH(FPSCR &fpscr, float op, float dest, bool top); +float vcvtFpHFpS(FPSCR &fpscr, float op, bool top); + +static inline double +makeDouble(uint32_t low, uint32_t high) +{ + double junk = 0.0; + return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk); +} + +static inline uint32_t +lowFromDouble(double val) +{ + return fpToBits(val); +} + +static inline uint32_t +highFromDouble(double val) +{ + return fpToBits(val) >> 32; +} + +uint64_t vfpFpSToFixed(float val, bool isSigned, bool half, + uint8_t imm, bool rzero = true); +float vfpUFixedToFpS(FPSCR fpscr, uint32_t val, bool half, uint8_t imm); +float vfpSFixedToFpS(FPSCR fpscr, int32_t val, bool half, uint8_t imm); + +uint64_t vfpFpDToFixed(double val, bool isSigned, bool half, + uint8_t imm, bool rzero = true); +double vfpUFixedToFpD(FPSCR fpscr, uint32_t val, bool half, uint8_t imm); +double vfpSFixedToFpD(FPSCR fpscr, int32_t val, bool half, uint8_t imm); + +class VfpMacroOp : public PredMacroOp +{ + public: + static bool + inScalarBank(IntRegIndex idx) + { + return (idx % 32) < 8; + } + + protected: + bool wide; + + VfpMacroOp(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, bool _wide) : + PredMacroOp(mnem, _machInst, __opClass), wide(_wide) + {} + + IntRegIndex addStride(IntRegIndex idx, unsigned stride); + void nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2); + void nextIdxs(IntRegIndex &dest, IntRegIndex &op1); + void nextIdxs(IntRegIndex &dest); +}; + +static inline float +fpAddS(float a, float b) +{ + return a + b; +} + +static inline double +fpAddD(double a, double b) +{ + return a + b; +} + +static inline float +fpSubS(float a, float b) +{ + return a - b; +} + +static inline double +fpSubD(double a, double b) +{ + return a - b; +} + +static inline float +fpDivS(float a, float b) +{ + return a / b; +} + +static inline double +fpDivD(double a, double b) +{ + return a / b; +} + +static inline float +fpMulS(float a, float b) +{ + return a * b; +} + +static inline double +fpMulD(double a, double b) +{ + return a * b; +} + +class FpOp : public PredOp +{ + protected: + FpOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : + PredOp(mnem, _machInst, __opClass) + {} + + virtual float + doOp(float op1, float op2) const + { + panic("Unimplemented version of doOp called.\n"); + } + + virtual float + doOp(float op1) const + { + panic("Unimplemented version of doOp called.\n"); + } + + virtual double + doOp(double op1, double op2) const + { + panic("Unimplemented version of doOp called.\n"); + } + + virtual double + doOp(double op1) const + { + panic("Unimplemented version of doOp called.\n"); + } + + double + dbl(uint32_t low, uint32_t high) const + { + double junk = 0.0; + return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk); + } + + uint32_t + dblLow(double val) const + { + return fpToBits(val); + } + + uint32_t + dblHi(double val) const + { + return fpToBits(val) >> 32; + } + + template + fpType + binaryOp(FPSCR &fpscr, fpType op1, fpType op2, + fpType (*func)(fpType, fpType), + bool flush, uint32_t rMode) const; + + template + fpType + unaryOp(FPSCR &fpscr, fpType op1, + fpType (*func)(fpType), + bool flush, uint32_t rMode) const; +}; + +class FpRegRegOp : public FpOp +{ + protected: + IntRegIndex dest; + IntRegIndex op1; + + FpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, + VfpMicroMode mode = VfpNotAMicroop) : + FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1) + { + setVfpMicroFlags(mode, flags); + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class FpRegImmOp : public FpOp +{ + protected: + IntRegIndex dest; + uint64_t imm; + + FpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, uint64_t _imm, + VfpMicroMode mode = VfpNotAMicroop) : + FpOp(mnem, _machInst, __opClass), dest(_dest), imm(_imm) + { + setVfpMicroFlags(mode, flags); + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class FpRegRegImmOp : public FpOp +{ + protected: + IntRegIndex dest; + IntRegIndex op1; + uint64_t imm; + + FpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, + uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) : + FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), imm(_imm) + { + setVfpMicroFlags(mode, flags); + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +class FpRegRegRegOp : public FpOp +{ + protected: + IntRegIndex dest; + IntRegIndex op1; + IntRegIndex op2; + + FpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, + VfpMicroMode mode = VfpNotAMicroop) : + FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2) + { + setVfpMicroFlags(mode, flags); + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +} + +#endif //__ARCH_ARM_INSTS_VFP_HH__ diff -r 84bd4089958b src/arch/arm/insts/vfp.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/insts/vfp.cc Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,947 @@ +/* Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Gabe Black + */ + +#include "arch/arm/insts/vfp.hh" + +/* + * The asm statements below are to keep gcc from reordering code. Otherwise + * the rounding mode might be set after the operation it was intended for, the + * exception bits read before it, etc. + */ + +std::string +FpRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest + FP_Base_DepTag); + ss << ", "; + printReg(ss, op1 + FP_Base_DepTag); + return ss.str(); +} + +std::string +FpRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest + FP_Base_DepTag); + ccprintf(ss, ", #%d", imm); + return ss.str(); +} + +std::string +FpRegRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest + FP_Base_DepTag); + ss << ", "; + printReg(ss, op1 + FP_Base_DepTag); + ccprintf(ss, ", #%d", imm); + return ss.str(); +} + +std::string +FpRegRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss); + printReg(ss, dest + FP_Base_DepTag); + ss << ", "; + printReg(ss, op1 + FP_Base_DepTag); + ss << ", "; + printReg(ss, op2 + FP_Base_DepTag); + return ss.str(); +} + +namespace ArmISA +{ + +VfpSavedState +prepFpState(uint32_t rMode) +{ + int roundingMode = fegetround(); + feclearexcept(FeAllExceptions); + switch (rMode) { + case VfpRoundNearest: + fesetround(FeRoundNearest); + break; + case VfpRoundUpward: + fesetround(FeRoundUpward); + break; + case VfpRoundDown: + fesetround(FeRoundDown); + break; + case VfpRoundZero: + fesetround(FeRoundZero); + break; + } + return roundingMode; +} + +void +finishVfp(FPSCR &fpscr, VfpSavedState state) +{ + int exceptions = fetestexcept(FeAllExceptions); + bool underflow = false; + if (exceptions & FeInvalid) { + fpscr.ioc = 1; + } + if (exceptions & FeDivByZero) { + fpscr.dzc = 1; + } + if (exceptions & FeOverflow) { + fpscr.ofc = 1; + } + if (exceptions & FeUnderflow) { + underflow = true; + fpscr.ufc = 1; + } + if ((exceptions & FeInexact) && !(underflow && fpscr.fz)) { + fpscr.ixc = 1; + } + fesetround(state); +} + +template +fpType +fixDest(FPSCR fpscr, fpType val, fpType op1) +{ + int fpClass = std::fpclassify(val); + fpType junk = 0.0; + if (fpClass == FP_NAN) { + const bool single = (sizeof(val) == sizeof(float)); + const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); + const bool nan = std::isnan(op1); + if (!nan || (fpscr.dn == 1)) { + val = bitsToFp(qnan, junk); + } else if (nan) { + val = bitsToFp(fpToBits(op1) | qnan, junk); + } + } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) { + // Turn val into a zero with the correct sign; + uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); + val = bitsToFp(fpToBits(val) & bitMask, junk); + feclearexcept(FeInexact); + feraiseexcept(FeUnderflow); + } + return val; +} + +template +float fixDest(FPSCR fpscr, float val, float op1); +template +double fixDest(FPSCR fpscr, double val, double op1); + +template +fpType +fixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2) +{ + int fpClass = std::fpclassify(val); + fpType junk = 0.0; + if (fpClass == FP_NAN) { + const bool single = (sizeof(val) == sizeof(float)); + const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); + const bool nan1 = std::isnan(op1); + const bool nan2 = std::isnan(op2); + const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); + const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan); + if ((!nan1 && !nan2) || (fpscr.dn == 1)) { + val = bitsToFp(qnan, junk); + } else if (signal1) { + val = bitsToFp(fpToBits(op1) | qnan, junk); + } else if (signal2) { + val = bitsToFp(fpToBits(op2) | qnan, junk); + } else if (nan1) { + val = op1; + } else if (nan2) { + val = op2; + } + } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) { + // Turn val into a zero with the correct sign; + uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); + val = bitsToFp(fpToBits(val) & bitMask, junk); + feclearexcept(FeInexact); + feraiseexcept(FeUnderflow); + } + return val; +} + +template +float fixDest(FPSCR fpscr, float val, float op1, float op2); +template +double fixDest(FPSCR fpscr, double val, double op1, double op2); + +template +fpType +fixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2) +{ + fpType mid = fixDest(fpscr, val, op1, op2); + const bool single = (sizeof(fpType) == sizeof(float)); + const fpType junk = 0.0; + if ((single && (val == bitsToFp(0x00800000, junk) || + val == bitsToFp(0x80800000, junk))) || + (!single && (val == bitsToFp(ULL(0x0010000000000000), junk) || + val == bitsToFp(ULL(0x8010000000000000), junk))) + ) { + __asm__ __volatile__("" : "=m" (op1) : "m" (op1)); + fesetround(FeRoundZero); + fpType temp = 0.0; + __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); + temp = op1 / op2; + if (flushToZero(temp)) { + feraiseexcept(FeUnderflow); + if (fpscr.fz) { + feclearexcept(FeInexact); + mid = temp; + } + } + __asm__ __volatile__("" :: "m" (temp)); + } + return mid; +} + +template +float fixDivDest(FPSCR fpscr, float val, float op1, float op2); +template +double fixDivDest(FPSCR fpscr, double val, double op1, double op2); + +float +fixFpDFpSDest(FPSCR fpscr, double val) +{ + const float junk = 0.0; + float op1 = 0.0; + if (std::isnan(val)) { + uint64_t valBits = fpToBits(val); + uint32_t op1Bits = bits(valBits, 50, 29) | + (mask(9) << 22) | + (bits(valBits, 63) << 31); + op1 = bitsToFp(op1Bits, junk); + } + float mid = fixDest(fpscr, (float)val, op1); + if (fpscr.fz && fetestexcept(FeUnderflow | FeInexact) == + (FeUnderflow | FeInexact)) { + feclearexcept(FeInexact); + } + if (mid == bitsToFp(0x00800000, junk) || + mid == bitsToFp(0x80800000, junk)) { + __asm__ __volatile__("" : "=m" (val) : "m" (val)); + fesetround(FeRoundZero); + float temp = 0.0; + __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); + temp = val; + if (flushToZero(temp)) { + feraiseexcept(FeUnderflow); + if (fpscr.fz) { + feclearexcept(FeInexact); + mid = temp; + } + } + __asm__ __volatile__("" :: "m" (temp)); + } + return mid; +} + +double +fixFpSFpDDest(FPSCR fpscr, float val) +{ + const double junk = 0.0; + double op1 = 0.0; + if (std::isnan(val)) { + uint32_t valBits = fpToBits(val); + uint64_t op1Bits = ((uint64_t)bits(valBits, 21, 0) << 29) | + (mask(12) << 51) | + ((uint64_t)bits(valBits, 31) << 63); + op1 = bitsToFp(op1Bits, junk); + } + double mid = fixDest(fpscr, (double)val, op1); + if (mid == bitsToFp(ULL(0x0010000000000000), junk) || + mid == bitsToFp(ULL(0x8010000000000000), junk)) { + __asm__ __volatile__("" : "=m" (val) : "m" (val)); + fesetround(FeRoundZero); + double temp = 0.0; + __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); + temp = val; + if (flushToZero(temp)) { + feraiseexcept(FeUnderflow); + if (fpscr.fz) { + feclearexcept(FeInexact); + mid = temp; + } + } + __asm__ __volatile__("" :: "m" (temp)); + } + return mid; +} + +float +vcvtFpSFpH(FPSCR &fpscr, float op, float dest, bool top) +{ + float junk = 0.0; + uint32_t destBits = fpToBits(dest); + uint32_t opBits = fpToBits(op); + // Extract the operand. + bool neg = bits(opBits, 31); + uint32_t exponent = bits(opBits, 30, 23); + uint32_t oldMantissa = bits(opBits, 22, 0); + uint32_t mantissa = oldMantissa >> (23 - 10); + // Do the conversion. + uint32_t extra = oldMantissa & mask(23 - 10); + if (exponent == 0xff) { + if (oldMantissa != 0) { + // Nans. + if (bits(mantissa, 9) == 0) { + // Signalling nan. + fpscr.ioc = 1; + } + if (fpscr.ahp) { + mantissa = 0; + exponent = 0; + fpscr.ioc = 1; + } else if (fpscr.dn) { + mantissa = (1 << 9); + exponent = 0x1f; + neg = false; + } else { + exponent = 0x1f; + mantissa |= (1 << 9); + } + } else { + // Infinities. + exponent = 0x1F; + if (fpscr.ahp) { + fpscr.ioc = 1; + mantissa = 0x3ff; + } else { + mantissa = 0; + } + } + } else if (exponent == 0 && oldMantissa == 0) { + // Zero, don't need to do anything. + } else { + // Normalized or denormalized numbers. + + bool inexact = (extra != 0); + + if (exponent == 0) { + // Denormalized. + + // If flush to zero is on, this shouldn't happen. + assert(fpscr.fz == 0); + + // Check for underflow + if (inexact || fpscr.ufe) + fpscr.ufc = 1; + + // Handle rounding. + unsigned mode = fpscr.rMode; + if ((mode == VfpRoundUpward && !neg && extra) || + (mode == VfpRoundDown && neg && extra) || + (mode == VfpRoundNearest && + (extra > (1 << 9) || + (extra == (1 << 9) && bits(mantissa, 0))))) { + mantissa++; + } + + // See if the number became normalized after rounding. + if (mantissa == (1 << 10)) { + mantissa = 0; + exponent = 1; + } + } else { + // Normalized. + + // We need to track the dropped bits differently since + // more can be dropped by denormalizing. + bool topOne = bits(extra, 12); + bool restZeros = bits(extra, 11, 0) == 0; + + if (exponent <= (127 - 15)) { + // The result is too small. Denormalize. + mantissa |= (1 << 10); + while (mantissa && exponent <= (127 - 15)) { + restZeros = restZeros && !topOne; + topOne = bits(mantissa, 0); + mantissa = mantissa >> 1; + exponent++; + } + if (topOne || !restZeros) + inexact = true; + exponent = 0; + } else { + // Change bias. + exponent -= (127 - 15); + } + + if (exponent == 0 && (inexact || fpscr.ufe)) { + // Underflow + fpscr.ufc = 1; + } + + // Handle rounding. + unsigned mode = fpscr.rMode; + bool nonZero = topOne || !restZeros; + if ((mode == VfpRoundUpward && !neg && nonZero) || + (mode == VfpRoundDown && neg && nonZero) || + (mode == VfpRoundNearest && topOne && + (!restZeros || bits(mantissa, 0)))) { + mantissa++; + } + + // See if we rounded up and need to bump the exponent. + if (mantissa == (1 << 10)) { + mantissa = 0; + exponent++; + } + + // Deal with overflow + if (fpscr.ahp) { + if (exponent >= 0x20) { + exponent = 0x1f; + mantissa = 0x3ff; + fpscr.ioc = 1; + // Supress inexact exception. + inexact = false; + } + } else { + if (exponent >= 0x1f) { + if ((mode == VfpRoundNearest) || + (mode == VfpRoundUpward && !neg) || + (mode == VfpRoundDown && neg)) { + // Overflow to infinity. + exponent = 0x1f; + mantissa = 0; + } else { + // Overflow to max normal. + exponent = 0x1e; + mantissa = 0x3ff; + } + fpscr.ofc = 1; + inexact = true; + } + } + } + + if (inexact) { + fpscr.ixc = 1; + } + } + // Reassemble and install the result. + uint32_t result = bits(mantissa, 9, 0); + replaceBits(result, 14, 10, exponent); + if (neg) + result |= (1 << 15); + if (top) + replaceBits(destBits, 31, 16, result); + else + replaceBits(destBits, 15, 0, result); + return bitsToFp(destBits, junk); +} + +float +vcvtFpHFpS(FPSCR &fpscr, float op, bool top) +{ + float junk = 0.0; + uint32_t opBits = fpToBits(op); + // Extract the operand. + if (top) + opBits = bits(opBits, 31, 16); + else + opBits = bits(opBits, 15, 0); + // Extract the bitfields. + bool neg = bits(opBits, 15); + uint32_t exponent = bits(opBits, 14, 10); + uint32_t mantissa = bits(opBits, 9, 0); + // Do the conversion. + if (exponent == 0) { + if (mantissa != 0) { + // Normalize the value. + exponent = exponent + (127 - 15) + 1; + while (mantissa < (1 << 10)) { + mantissa = mantissa << 1; + exponent--; + } + } + mantissa = mantissa << (23 - 10); + } else if (exponent == 0x1f && !fpscr.ahp) { + // Infinities and nans. + exponent = 0xff; + if (mantissa != 0) { + // Nans. + mantissa = mantissa << (23 - 10); + if (bits(mantissa, 22) == 0) { + // Signalling nan. + fpscr.ioc = 1; + mantissa |= (1 << 22); + } + if (fpscr.dn) { + mantissa &= ~mask(22); + neg = false; + } + } + } else { + exponent = exponent + (127 - 15); + mantissa = mantissa << (23 - 10); + } + // Reassemble the result. + uint32_t result = bits(mantissa, 22, 0); + replaceBits(result, 30, 23, exponent); + if (neg) + result |= (1 << 31); + return bitsToFp(result, junk); +} + +uint64_t +vfpFpSToFixed(float val, bool isSigned, bool half, + uint8_t imm, bool rzero) +{ + int rmode = rzero ? FeRoundZero : fegetround(); + __asm__ __volatile__("" : "=m" (rmode) : "m" (rmode)); + fesetround(FeRoundNearest); + val = val * powf(2.0, imm); + __asm__ __volatile__("" : "=m" (val) : "m" (val)); + fesetround(rmode); + feclearexcept(FeAllExceptions); + __asm__ __volatile__("" : "=m" (val) : "m" (val)); + float origVal = val; + val = rintf(val); + int fpType = std::fpclassify(val); + if (fpType == FP_SUBNORMAL || fpType == FP_NAN) { + if (fpType == FP_NAN) { + feraiseexcept(FeInvalid); + } + val = 0.0; + } else if (origVal != val) { + switch (rmode) { + case FeRoundNearest: + if (origVal - val > 0.5) + val += 1.0; + else if (val - origVal > 0.5) + val -= 1.0; + break; + case FeRoundDown: + if (origVal < val) + val -= 1.0; + break; + case FeRoundUpward: + if (origVal > val) + val += 1.0; + break; + } + feraiseexcept(FeInexact); + } + + if (isSigned) { + if (half) { + if ((double)val < (int16_t)(1 << 15)) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return (int16_t)(1 << 15); + } + if ((double)val > (int16_t)mask(15)) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return (int16_t)mask(15); + } + return (int16_t)val; + } else { + if ((double)val < (int32_t)(1 << 31)) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return (int32_t)(1 << 31); + } + if ((double)val > (int32_t)mask(31)) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return (int32_t)mask(31); + } + return (int32_t)val; + } + } else { + if (half) { + if ((double)val < 0) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return 0; + } + if ((double)val > (mask(16))) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return mask(16); + } + return (uint16_t)val; + } else { + if ((double)val < 0) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return 0; + } + if ((double)val > (mask(32))) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return mask(32); + } + return (uint32_t)val; + } + } +} + +float +vfpUFixedToFpS(FPSCR fpscr, uint32_t val, bool half, uint8_t imm) +{ + fesetround(FeRoundNearest); + if (half) + val = (uint16_t)val; + float scale = powf(2.0, imm); + __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); + feclearexcept(FeAllExceptions); + __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); + return fixDivDest(fpscr, val / scale, (float)val, scale); +} + +float +vfpSFixedToFpS(FPSCR fpscr, int32_t val, bool half, uint8_t imm) +{ + fesetround(FeRoundNearest); + if (half) + val = sext<16>(val & mask(16)); + float scale = powf(2.0, imm); + __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); + feclearexcept(FeAllExceptions); + __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); + return fixDivDest(fpscr, val / scale, (float)val, scale); +} + +uint64_t +vfpFpDToFixed(double val, bool isSigned, bool half, + uint8_t imm, bool rzero) +{ + int rmode = rzero ? FeRoundZero : fegetround(); + fesetround(FeRoundNearest); + val = val * pow(2.0, imm); + __asm__ __volatile__("" : "=m" (val) : "m" (val)); + fesetround(rmode); + feclearexcept(FeAllExceptions); + __asm__ __volatile__("" : "=m" (val) : "m" (val)); + double origVal = val; + val = rint(val); + int fpType = std::fpclassify(val); + if (fpType == FP_SUBNORMAL || fpType == FP_NAN) { + if (fpType == FP_NAN) { + feraiseexcept(FeInvalid); + } + val = 0.0; + } else if (origVal != val) { + switch (rmode) { + case FeRoundNearest: + if (origVal - val > 0.5) + val += 1.0; + else if (val - origVal > 0.5) + val -= 1.0; + break; + case FeRoundDown: + if (origVal < val) + val -= 1.0; + break; + case FeRoundUpward: + if (origVal > val) + val += 1.0; + break; + } + feraiseexcept(FeInexact); + } + if (isSigned) { + if (half) { + if (val < (int16_t)(1 << 15)) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return (int16_t)(1 << 15); + } + if (val > (int16_t)mask(15)) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return (int16_t)mask(15); + } + return (int16_t)val; + } else { + if (val < (int32_t)(1 << 31)) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return (int32_t)(1 << 31); + } + if (val > (int32_t)mask(31)) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return (int32_t)mask(31); + } + return (int32_t)val; + } + } else { + if (half) { + if (val < 0) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return 0; + } + if (val > mask(16)) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return mask(16); + } + return (uint16_t)val; + } else { + if (val < 0) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return 0; + } + if (val > mask(32)) { + feraiseexcept(FeInvalid); + feclearexcept(FeInexact); + return mask(32); + } + return (uint32_t)val; + } + } +} + +double +vfpUFixedToFpD(FPSCR fpscr, uint32_t val, bool half, uint8_t imm) +{ + fesetround(FeRoundNearest); + if (half) + val = (uint16_t)val; + double scale = pow(2.0, imm); + __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); + feclearexcept(FeAllExceptions); + __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); + return fixDivDest(fpscr, val / scale, (double)val, scale); +} + +double +vfpSFixedToFpD(FPSCR fpscr, int32_t val, bool half, uint8_t imm) +{ + fesetround(FeRoundNearest); + if (half) + val = sext<16>(val & mask(16)); + double scale = pow(2.0, imm); + __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); + feclearexcept(FeAllExceptions); + __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); + return fixDivDest(fpscr, val / scale, (double)val, scale); +} + +template +fpType +FpOp::binaryOp(FPSCR &fpscr, fpType op1, fpType op2, + fpType (*func)(fpType, fpType), + bool flush, uint32_t rMode) const +{ + const bool single = (sizeof(fpType) == sizeof(float)); + fpType junk = 0.0; + + if (flush && flushToZero(op1, op2)) + fpscr.idc = 1; + VfpSavedState state = prepFpState(rMode); + __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2), "=m" (state) + : "m" (op1), "m" (op2), "m" (state)); + fpType dest = func(op1, op2); + __asm__ __volatile__ ("" : "=m" (dest) : "m" (dest)); + + int fpClass = std::fpclassify(dest); + // Get NAN behavior right. This varies between x86 and ARM. + if (fpClass == FP_NAN) { + const bool single = (sizeof(fpType) == sizeof(float)); + const uint64_t qnan = + single ? 0x7fc00000 : ULL(0x7ff8000000000000); + const bool nan1 = std::isnan(op1); + const bool nan2 = std::isnan(op2); + const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); + const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan); + if ((!nan1 && !nan2) || (fpscr.dn == 1)) { + dest = bitsToFp(qnan, junk); + } else if (signal1) { + dest = bitsToFp(fpToBits(op1) | qnan, junk); + } else if (signal2) { + dest = bitsToFp(fpToBits(op2) | qnan, junk); + } else if (nan1) { + dest = op1; + } else if (nan2) { + dest = op2; + } + } else if (flush && flushToZero(dest)) { + feraiseexcept(FeUnderflow); + } else if (( + (single && (dest == bitsToFp(0x00800000, junk) || + dest == bitsToFp(0x80800000, junk))) || + (!single && + (dest == bitsToFp(ULL(0x0010000000000000), junk) || + dest == bitsToFp(ULL(0x8010000000000000), junk))) + ) && rMode != VfpRoundZero) { + /* + * Correct for the fact that underflow is detected -before- rounding + * in ARM and -after- rounding in x86. + */ + fesetround(FeRoundZero); + __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2) + : "m" (op1), "m" (op2)); + fpType temp = func(op1, op2); + __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp)); + if (flush && flushToZero(temp)) { + dest = temp; + } + } + finishVfp(fpscr, state); + return dest; +} + +template +float FpOp::binaryOp(FPSCR &fpscr, float op1, float op2, + float (*func)(float, float), + bool flush, uint32_t rMode) const; +template +double FpOp::binaryOp(FPSCR &fpscr, double op1, double op2, + double (*func)(double, double), + bool flush, uint32_t rMode) const; + +template +fpType +FpOp::unaryOp(FPSCR &fpscr, fpType op1, fpType (*func)(fpType), + bool flush, uint32_t rMode) const +{ + const bool single = (sizeof(fpType) == sizeof(float)); + fpType junk = 0.0; + + if (flush && flushToZero(op1)) + fpscr.idc = 1; + VfpSavedState state = prepFpState(rMode); + __asm__ __volatile__ ("" : "=m" (op1), "=m" (state) + : "m" (op1), "m" (state)); + fpType dest = func(op1); + __asm__ __volatile__ ("" : "=m" (dest) : "m" (dest)); + + int fpClass = std::fpclassify(dest); + // Get NAN behavior right. This varies between x86 and ARM. + if (fpClass == FP_NAN) { + const bool single = (sizeof(fpType) == sizeof(float)); + const uint64_t qnan = + single ? 0x7fc00000 : ULL(0x7ff8000000000000); + const bool nan = std::isnan(op1); + if (!nan || fpscr.dn == 1) { + dest = bitsToFp(qnan, junk); + } else if (nan) { + dest = bitsToFp(fpToBits(op1) | qnan, junk); + } + } else if (flush && flushToZero(dest)) { + feraiseexcept(FeUnderflow); + } else if (( + (single && (dest == bitsToFp(0x00800000, junk) || + dest == bitsToFp(0x80800000, junk))) || + (!single && + (dest == bitsToFp(ULL(0x0010000000000000), junk) || + dest == bitsToFp(ULL(0x8010000000000000), junk))) + ) && rMode != VfpRoundZero) { + /* + * Correct for the fact that underflow is detected -before- rounding + * in ARM and -after- rounding in x86. + */ + fesetround(FeRoundZero); + __asm__ __volatile__ ("" : "=m" (op1) : "m" (op1)); + fpType temp = func(op1); + __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp)); + if (flush && flushToZero(temp)) { + dest = temp; + } + } + finishVfp(fpscr, state); + return dest; +} + +template +float FpOp::unaryOp(FPSCR &fpscr, float op1, float (*func)(float), + bool flush, uint32_t rMode) const; +template +double FpOp::unaryOp(FPSCR &fpscr, double op1, double (*func)(double), + bool flush, uint32_t rMode) const; + +IntRegIndex +VfpMacroOp::addStride(IntRegIndex idx, unsigned stride) +{ + if (wide) { + stride *= 2; + } + unsigned offset = idx % 8; + idx = (IntRegIndex)(idx - offset); + offset += stride; + idx = (IntRegIndex)(idx + (offset % 8)); + return idx; +} + +void +VfpMacroOp::nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2) +{ + unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; + assert(!inScalarBank(dest)); + dest = addStride(dest, stride); + op1 = addStride(op1, stride); + if (!inScalarBank(op2)) { + op2 = addStride(op2, stride); + } +} + +void +VfpMacroOp::nextIdxs(IntRegIndex &dest, IntRegIndex &op1) +{ + unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; + assert(!inScalarBank(dest)); + dest = addStride(dest, stride); + if (!inScalarBank(op1)) { + op1 = addStride(op1, stride); + } +} + +void +VfpMacroOp::nextIdxs(IntRegIndex &dest) +{ + unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; + assert(!inScalarBank(dest)); + dest = addStride(dest, stride); +} + +} diff -r 84bd4089958b src/arch/arm/interrupts.hh --- a/src/arch/arm/interrupts.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/interrupts.hh Wed May 26 18:10:45 2010 -0500 @@ -1,6 +1,17 @@ /* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2006 The Regents of The University of Michigan - * Copyright (c) 2009 ARM Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,6 +45,7 @@ #include "arch/arm/faults.hh" #include "arch/arm/isa_traits.hh" +#include "arch/arm/miscregs.hh" #include "arch/arm/registers.hh" #include "cpu/thread_context.hh" #include "params/ArmInterrupts.hh" @@ -47,6 +59,7 @@ private: BaseCPU * cpu; + bool interrupts[NumInterruptTypes]; uint64_t intStatus; public: @@ -74,46 +87,95 @@ void post(int int_num, int index) { + DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); + + if (int_num < 0 || int_num >= NumInterruptTypes) + panic("int_num out of bounds\n"); + + if (index != 0) + panic("No support for other interrupt indexes\n"); + + interrupts[int_num] = true; + intStatus |= ULL(1) << int_num; } void clear(int int_num, int index) { + DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); + + if (int_num < 0 || int_num >= NumInterruptTypes) + panic("int_num out of bounds\n"); + + if (index != 0) + panic("No support for other interrupt indexes\n"); + + interrupts[int_num] = false; + intStatus &= ~(ULL(1) << int_num); + } void clearAll() { + DPRINTF(Interrupt, "Interrupts all cleared\n"); intStatus = 0; + memset(interrupts, 0, sizeof(interrupts)); } bool checkInterrupts(ThreadContext *tc) const { - return intStatus; + if (!intStatus) + return false; + + CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); + + return ((interrupts[INT_IRQ] && !cpsr.i) || + (interrupts[INT_FIQ] && !cpsr.f) || + (interrupts[INT_ABT] && !cpsr.a) || + (interrupts[INT_RST])); } Fault getInterrupt(ThreadContext *tc) { - warn_once("ARM Interrupts not handled\n"); - return NoFault; + if (!intStatus) + return NoFault; + + CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); + + if (interrupts[INT_IRQ] && !cpsr.i) + return new Interrupt; + if (interrupts[INT_FIQ] && !cpsr.f) + return new FastInterrupt; + if (interrupts[INT_ABT] && !cpsr.a) + return new DataAbort(0, false, 0, + ArmFault::AsynchronousExternalAbort); + if (interrupts[INT_RST]) + return new Reset; + + panic("intStatus and interrupts not in sync\n"); } void updateIntrInfo(ThreadContext *tc) { - + ; // nothing to do } void serialize(std::ostream &os) { + SERIALIZE_ARRAY(interrupts, NumInterruptTypes); + SERIALIZE_SCALAR(intStatus); } void unserialize(Checkpoint *cp, const std::string §ion) { + UNSERIALIZE_ARRAY(interrupts, NumInterruptTypes); + UNSERIALIZE_SCALAR(intStatus); } }; } // namespace ARM_ISA diff -r 84bd4089958b src/arch/arm/interrupts.cc --- a/src/arch/arm/interrupts.cc Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/interrupts.cc Wed May 26 18:10:45 2010 -0500 @@ -2,6 +2,16 @@ * Copyright (c) 2009 ARM Limited * All rights reserved. * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * * 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 diff -r 84bd4089958b src/arch/arm/intregs.hh --- a/src/arch/arm/intregs.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/intregs.hh Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,16 @@ /* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2009 The Regents of The University of Michigan * All rights reserved. * @@ -33,6 +45,8 @@ #ifndef __ARCH_ARM_INTREGS_HH__ #define __ARCH_ARM_INTREGS_HH__ +#include "arch/arm/types.hh" + namespace ArmISA { @@ -96,8 +110,6 @@ INTREG_ZERO, // Dummy zero reg since there has to be one. INTREG_UREG0, - INTREG_RHI, - INTREG_RLO, INTREG_CONDCODES, NUM_INTREGS, @@ -324,12 +336,13 @@ return IntRegFiqMap[index]; } -static inline IntRegIndex -intRegForceUser(unsigned index) +static const unsigned intRegsPerMode = NUM_INTREGS; + +static inline int +intRegInMode(OperatingMode mode, int reg) { - assert(index < NUM_ARCH_INTREGS); - - return index == 15 ? (IntRegIndex)15 : (IntRegIndex)(index + NUM_INTREGS); + assert(reg < NUM_ARCH_INTREGS); + return mode * intRegsPerMode + reg; } } diff -r 84bd4089958b src/arch/arm/isa.hh --- a/src/arch/arm/isa.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/isa.hh Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,15 @@ -/* +/* Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2009 The Regents of The University of Michigan * All rights reserved. * @@ -29,9 +40,10 @@ */ #ifndef __ARCH_ARM_ISA_HH__ -#define __ARCH_MRM_ISA_HH__ +#define __ARCH_ARM_ISA_HH__ #include "arch/arm/registers.hh" +#include "arch/arm/tlb.hh" #include "arch/arm/types.hh" class ThreadContext; @@ -78,102 +90,12 @@ } public: - void clear() - { - memset(miscRegs, 0, sizeof(miscRegs)); - CPSR cpsr = 0; - cpsr.mode = MODE_USER; - miscRegs[MISCREG_CPSR] = cpsr; - updateRegMap(cpsr); + void clear(); - SCTLR sctlr = 0; - sctlr.nmfi = 1; - sctlr.rao1 = 1; - sctlr.rao2 = 1; - sctlr.rao3 = 1; - sctlr.rao4 = 1; - - //XXX We need to initialize the rest of the state. - } - - MiscReg - readMiscRegNoEffect(int misc_reg) - { - assert(misc_reg < NumMiscRegs); - if (misc_reg == MISCREG_SPSR) { - CPSR cpsr = miscRegs[MISCREG_CPSR]; - switch (cpsr.mode) { - case MODE_USER: - return miscRegs[MISCREG_SPSR]; - case MODE_FIQ: - return miscRegs[MISCREG_SPSR_FIQ]; - case MODE_IRQ: - return miscRegs[MISCREG_SPSR_IRQ]; - case MODE_SVC: - return miscRegs[MISCREG_SPSR_SVC]; - case MODE_MON: - return miscRegs[MISCREG_SPSR_MON]; - case MODE_ABORT: - return miscRegs[MISCREG_SPSR_ABT]; - case MODE_UNDEFINED: - return miscRegs[MISCREG_SPSR_UND]; - default: - return miscRegs[MISCREG_SPSR]; - } - } - return miscRegs[misc_reg]; - } - - MiscReg - readMiscReg(int misc_reg, ThreadContext *tc) - { - return readMiscRegNoEffect(misc_reg); - } - - void - setMiscRegNoEffect(int misc_reg, const MiscReg &val) - { - assert(misc_reg < NumMiscRegs); - if (misc_reg == MISCREG_SPSR) { - CPSR cpsr = miscRegs[MISCREG_CPSR]; - switch (cpsr.mode) { - case MODE_USER: - miscRegs[MISCREG_SPSR] = val; - return; - case MODE_FIQ: - miscRegs[MISCREG_SPSR_FIQ] = val; - return; - case MODE_IRQ: - miscRegs[MISCREG_SPSR_IRQ] = val; - return; - case MODE_SVC: - miscRegs[MISCREG_SPSR_SVC] = val; - return; - case MODE_MON: - miscRegs[MISCREG_SPSR_MON] = val; - return; - case MODE_ABORT: - miscRegs[MISCREG_SPSR_ABT] = val; - return; - case MODE_UNDEFINED: - miscRegs[MISCREG_SPSR_UND] = val; - return; - default: - miscRegs[MISCREG_SPSR] = val; - return; - } - } - miscRegs[misc_reg] = val; - } - - void - setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) - { - if (misc_reg == MISCREG_CPSR) { - updateRegMap(val); - } - return setMiscRegNoEffect(misc_reg, val); - } + MiscReg readMiscRegNoEffect(int misc_reg); + MiscReg readMiscReg(int misc_reg, ThreadContext *tc); + void setMiscRegNoEffect(int misc_reg, const MiscReg &val); + void setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc); int flattenIntIndex(int reg) @@ -184,9 +106,27 @@ } else if (reg < NUM_INTREGS) { return reg; } else { - reg -= NUM_INTREGS; - assert(reg < NUM_ARCH_INTREGS); - return reg; + int mode = reg / intRegsPerMode; + reg = reg % intRegsPerMode; + switch (mode) { + case MODE_USER: + case MODE_SYSTEM: + return INTREG_USR(reg); + case MODE_FIQ: + return INTREG_FIQ(reg); + case MODE_IRQ: + return INTREG_IRQ(reg); + case MODE_SVC: + return INTREG_SVC(reg); + case MODE_MON: + return INTREG_MON(reg); + case MODE_ABORT: + return INTREG_ABT(reg); + case MODE_UNDEFINED: + return INTREG_UND(reg); + default: + panic("Flattening into an unknown mode.\n"); + } } } @@ -204,6 +144,10 @@ ISA() { + SCTLR sctlr; + sctlr = 0; + miscRegs[MISCREG_SCTLR_RST] = sctlr; + clear(); } }; diff -r 84bd4089958b src/arch/arm/isa.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa.cc Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,459 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Gabe Black + * Ali Saidi + */ + +#include "arch/arm/isa.hh" + +namespace ArmISA +{ + +void +ISA::clear() +{ + SCTLR sctlr_rst = miscRegs[MISCREG_SCTLR_RST]; + + memset(miscRegs, 0, sizeof(miscRegs)); + CPSR cpsr = 0; + cpsr.mode = MODE_USER; + miscRegs[MISCREG_CPSR] = cpsr; + updateRegMap(cpsr); + + SCTLR sctlr = 0; + sctlr.nmfi = (bool)sctlr_rst.nmfi; + sctlr.v = (bool)sctlr_rst.v; + sctlr.u = 1; + sctlr.xp = 1; + sctlr.rao2 = 1; + sctlr.rao3 = 1; + sctlr.rao4 = 1; + miscRegs[MISCREG_SCTLR] = sctlr; + miscRegs[MISCREG_SCTLR_RST] = sctlr_rst; + + + /* + * Technically this should be 0, but we don't support those + * settings. + */ + CPACR cpacr = 0; + // Enable CP 10, 11 + cpacr.cp10 = 0x3; + cpacr.cp11 = 0x3; + miscRegs[MISCREG_CPACR] = cpacr; + + /* Start with an event in the mailbox */ + miscRegs[MISCREG_SEV_MAILBOX] = 1; + + /* + * Implemented = '5' from "M5", + * Variant = 0, + */ + miscRegs[MISCREG_MIDR] = + (0x35 << 24) | //Implementor is '5' from "M5" + (0 << 20) | //Variant + (0xf << 16) | //Architecture from CPUID scheme + (0 << 4) | //Primary part number + (0 << 0) | //Revision + 0; + + // Separate Instruction and Data TLBs. + miscRegs[MISCREG_TLBTR] = 1; + + MVFR0 mvfr0 = 0; + mvfr0.advSimdRegisters = 2; + mvfr0.singlePrecision = 2; + mvfr0.doublePrecision = 2; + mvfr0.vfpExceptionTrapping = 0; + mvfr0.divide = 1; + mvfr0.squareRoot = 1; + mvfr0.shortVectors = 1; + mvfr0.roundingModes = 1; + miscRegs[MISCREG_MVFR0] = mvfr0; + + MVFR1 mvfr1 = 0; + mvfr1.flushToZero = 1; + mvfr1.defaultNaN = 1; + mvfr1.advSimdLoadStore = 1; + mvfr1.advSimdInteger = 1; + mvfr1.advSimdSinglePrecision = 1; + mvfr1.advSimdHalfPrecision = 1; + mvfr1.vfpHalfPrecision = 1; + miscRegs[MISCREG_MVFR1] = mvfr1; + + miscRegs[MISCREG_MPIDR] = 0; + + // Reset values of PRRR and NMRR are implementation dependent + + miscRegs[MISCREG_PRRR] = + (1 << 19) | // 19 + (0 << 18) | // 18 + (0 << 17) | // 17 + (1 << 16) | // 16 + (2 << 14) | // 15:14 + (0 << 12) | // 13:12 + (2 << 10) | // 11:10 + (2 << 8) | // 9:8 + (2 << 6) | // 7:6 + (2 << 4) | // 5:4 + (1 << 2) | // 3:2 + 0; // 1:0 + miscRegs[MISCREG_NMRR] = + (1 << 30) | // 31:30 + (0 << 26) | // 27:26 + (0 << 24) | // 25:24 + (3 << 22) | // 23:22 + (2 << 20) | // 21:20 + (0 << 18) | // 19:18 + (0 << 16) | // 17:16 + (1 << 14) | // 15:14 + (0 << 12) | // 13:12 + (2 << 10) | // 11:10 + (0 << 8) | // 9:8 + (3 << 6) | // 7:6 + (2 << 4) | // 5:4 + (0 << 2) | // 3:2 + 0; // 1:0 + + //XXX We need to initialize the rest of the state. +} + +MiscReg +ISA::readMiscRegNoEffect(int misc_reg) +{ + assert(misc_reg < NumMiscRegs); + if (misc_reg == MISCREG_SPSR) { + CPSR cpsr = miscRegs[MISCREG_CPSR]; + switch (cpsr.mode) { + case MODE_USER: + return miscRegs[MISCREG_SPSR]; + case MODE_FIQ: + return miscRegs[MISCREG_SPSR_FIQ]; + case MODE_IRQ: + return miscRegs[MISCREG_SPSR_IRQ]; + case MODE_SVC: + return miscRegs[MISCREG_SPSR_SVC]; + case MODE_MON: + return miscRegs[MISCREG_SPSR_MON]; + case MODE_ABORT: + return miscRegs[MISCREG_SPSR_ABT]; + case MODE_UNDEFINED: + return miscRegs[MISCREG_SPSR_UND]; + default: + return miscRegs[MISCREG_SPSR]; + } + } + return miscRegs[misc_reg]; +} + + +MiscReg +ISA::readMiscReg(int misc_reg, ThreadContext *tc) +{ + if (misc_reg == MISCREG_CPSR) { + CPSR cpsr = miscRegs[misc_reg]; + Addr pc = tc->readPC(); + if (pc & (ULL(1) << PcJBitShift)) + cpsr.j = 1; + else + cpsr.j = 0; + if (pc & (ULL(1) << PcTBitShift)) + cpsr.t = 1; + else + cpsr.t = 0; + return cpsr; + } + if (misc_reg >= MISCREG_CP15_UNIMP_START && + misc_reg < MISCREG_CP15_END) { + panic("Unimplemented CP15 register %s read.\n", + miscRegName[misc_reg]); + } + switch (misc_reg) { + case MISCREG_CLIDR: + warn("The clidr register always reports 0 caches.\n"); + break; + case MISCREG_CCSIDR: + warn("The ccsidr register isn't implemented and " + "always reads as 0.\n"); + break; + case MISCREG_ID_PFR0: + return 0x1031; // ThumbEE | !Jazelle | Thumb | ARM + } + return readMiscRegNoEffect(misc_reg); +} + +void +ISA::setMiscRegNoEffect(int misc_reg, const MiscReg &val) +{ + assert(misc_reg < NumMiscRegs); + if (misc_reg == MISCREG_SPSR) { + CPSR cpsr = miscRegs[MISCREG_CPSR]; + switch (cpsr.mode) { + case MODE_USER: + miscRegs[MISCREG_SPSR] = val; + return; + case MODE_FIQ: + miscRegs[MISCREG_SPSR_FIQ] = val; + return; + case MODE_IRQ: + miscRegs[MISCREG_SPSR_IRQ] = val; + return; + case MODE_SVC: + miscRegs[MISCREG_SPSR_SVC] = val; + return; + case MODE_MON: + miscRegs[MISCREG_SPSR_MON] = val; + return; + case MODE_ABORT: + miscRegs[MISCREG_SPSR_ABT] = val; + return; + case MODE_UNDEFINED: + miscRegs[MISCREG_SPSR_UND] = val; + return; + default: + miscRegs[MISCREG_SPSR] = val; + return; + } + } + miscRegs[misc_reg] = val; +} + +void +ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) +{ + MiscReg newVal = val; + if (misc_reg == MISCREG_CPSR) { + updateRegMap(val); + CPSR cpsr = val; + DPRINTF(Arm, "Updating CPSR to %#x f:%d i:%d a:%d mode:%#x\n", + cpsr, cpsr.f, cpsr.i, cpsr.a, cpsr.mode); + Addr npc = tc->readNextPC() & ~PcModeMask; + if (cpsr.j) + npc = npc | (ULL(1) << PcJBitShift); + if (cpsr.t) + npc = npc | (ULL(1) << PcTBitShift); + + tc->setNextPC(npc); + } else if (misc_reg >= MISCREG_CP15_UNIMP_START && + misc_reg < MISCREG_CP15_END) { + panic("Unimplemented CP15 register %s wrote with %#x.\n", + miscRegName[misc_reg], val); + } else { + switch (misc_reg) { + case MISCREG_ITSTATE: + { + ITSTATE itstate = newVal; + CPSR cpsr = miscRegs[MISCREG_CPSR]; + cpsr.it1 = itstate.bottom2; + cpsr.it2 = itstate.top6; + miscRegs[MISCREG_CPSR] = cpsr; + DPRINTF(MiscRegs, + "Updating ITSTATE -> %#x in CPSR -> %#x.\n", + (uint8_t)itstate, (uint32_t)cpsr); + } + break; + case MISCREG_CPACR: + { + CPACR newCpacr = 0; + CPACR valCpacr = val; + newCpacr.cp10 = valCpacr.cp10; + newCpacr.cp11 = valCpacr.cp11; + if (newCpacr.cp10 != 0x3 || newCpacr.cp11 != 3) { + panic("Disabling coprocessors isn't implemented.\n"); + } + newVal = newCpacr; + } + break; + case MISCREG_CSSELR: + warn("The csselr register isn't implemented.\n"); + break; + case MISCREG_FPSCR: + { + const uint32_t ones = (uint32_t)(-1); + FPSCR fpscrMask = 0; + fpscrMask.ioc = ones; + fpscrMask.dzc = ones; + fpscrMask.ofc = ones; + fpscrMask.ufc = ones; + fpscrMask.ixc = ones; + fpscrMask.idc = ones; + fpscrMask.len = ones; + fpscrMask.stride = ones; + fpscrMask.rMode = ones; + fpscrMask.fz = ones; + fpscrMask.dn = ones; + fpscrMask.ahp = ones; + fpscrMask.qc = ones; + fpscrMask.v = ones; + fpscrMask.c = ones; + fpscrMask.z = ones; + fpscrMask.n = ones; + newVal = (newVal & (uint32_t)fpscrMask) | + (miscRegs[MISCREG_FPSCR] & ~(uint32_t)fpscrMask); + } + break; + case MISCREG_FPEXC: + { + const uint32_t fpexcMask = 0x60000000; + newVal = (newVal & fpexcMask) | + (miscRegs[MISCREG_FPEXC] & ~fpexcMask); + } + break; + case MISCREG_SCTLR: + { + DPRINTF(MiscRegs, "Writing SCTLR: %#x\n", newVal); + SCTLR sctlr = miscRegs[MISCREG_SCTLR]; + SCTLR new_sctlr = newVal; + new_sctlr.nmfi = (bool)sctlr.nmfi; + miscRegs[MISCREG_SCTLR] = (MiscReg)new_sctlr; + return; + } + case MISCREG_TLBTR: + case MISCREG_MVFR0: + case MISCREG_MVFR1: + case MISCREG_MPIDR: + case MISCREG_FPSID: + return; + case MISCREG_TLBIALLIS: + case MISCREG_TLBIALL: + warn("Need to flush all TLBs in MP\n"); + tc->getITBPtr()->flushAll(); + tc->getDTBPtr()->flushAll(); + return; + case MISCREG_ITLBIALL: + tc->getITBPtr()->flushAll(); + return; + case MISCREG_DTLBIALL: + tc->getDTBPtr()->flushAll(); + return; + case MISCREG_TLBIMVAIS: + case MISCREG_TLBIMVA: + warn("Need to flush all TLBs in MP\n"); + tc->getITBPtr()->flushMvaAsid(mbits(newVal, 31, 12), + bits(newVal, 7,0)); + tc->getDTBPtr()->flushMvaAsid(mbits(newVal, 31, 12), + bits(newVal, 7,0)); + return; + case MISCREG_TLBIASIDIS: + case MISCREG_TLBIASID: + warn("Need to flush all TLBs in MP\n"); + tc->getITBPtr()->flushAsid(bits(newVal, 7,0)); + tc->getDTBPtr()->flushAsid(bits(newVal, 7,0)); + return; + case MISCREG_TLBIMVAAIS: + case MISCREG_TLBIMVAA: + warn("Need to flush all TLBs in MP\n"); + tc->getITBPtr()->flushMva(mbits(newVal, 31,12)); + tc->getDTBPtr()->flushMva(mbits(newVal, 31,12)); + return; + case MISCREG_ITLBIMVA: + tc->getITBPtr()->flushMvaAsid(mbits(newVal, 31, 12), + bits(newVal, 7,0)); + return; + case MISCREG_DTLBIMVA: + tc->getDTBPtr()->flushMvaAsid(mbits(newVal, 31, 12), + bits(newVal, 7,0)); + return; + case MISCREG_ITLBIASID: + tc->getITBPtr()->flushAsid(bits(newVal, 7,0)); + return; + case MISCREG_DTLBIASID: + tc->getDTBPtr()->flushAsid(bits(newVal, 7,0)); + return; + case MISCREG_V2PCWPR: + case MISCREG_V2PCWPW: + case MISCREG_V2PCWUR: + case MISCREG_V2PCWUW: + case MISCREG_V2POWPR: + case MISCREG_V2POWPW: + case MISCREG_V2POWUR: + case MISCREG_V2POWUW: + { + RequestPtr req = new Request; + unsigned flags; + BaseTLB::Mode mode; + Fault fault; + switch(misc_reg) { + case MISCREG_V2PCWPR: + flags = TLB::MustBeOne; + mode = BaseTLB::Read; + break; + case MISCREG_V2PCWPW: + flags = TLB::MustBeOne; + mode = BaseTLB::Write; + break; + case MISCREG_V2PCWUR: + flags = TLB::MustBeOne | TLB::UserMode; + mode = BaseTLB::Read; + break; + case MISCREG_V2PCWUW: + flags = TLB::MustBeOne | TLB::UserMode; + mode = BaseTLB::Write; + break; + case MISCREG_V2POWPR: + case MISCREG_V2POWPW: + case MISCREG_V2POWUR: + case MISCREG_V2POWUW: + panic("Security Extensions not implemented!"); + } + req->setVirt(0, val, 1, flags, tc->readPC()); + fault = tc->getDTBPtr()->translateAtomic(req, tc, mode); + if (fault == NoFault) { + miscRegs[MISCREG_PAR] = + (req->getPaddr() & 0xfffff000) | + (tc->getDTBPtr()->getAttr() ); + DPRINTF(MiscRegs, + "MISCREG: Translated addr 0x%08x: PAR: 0x%08x\n", + val, miscRegs[MISCREG_PAR]); + } + else { + // Set fault bit and FSR + FSR fsr = miscRegs[MISCREG_DFSR]; + miscRegs[MISCREG_PAR] = + (fsr.ext << 6) | + (fsr.fsHigh << 5) | + (fsr.fsLow << 1) | + 0x1; // F bit + } + return; + } + } + } + setMiscRegNoEffect(misc_reg, newVal); +} + +} diff -r 84bd4089958b src/arch/arm/isa/bitfields.isa --- a/src/arch/arm/isa/bitfields.isa Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/isa/bitfields.isa Wed May 26 18:10:45 2010 -0500 @@ -1,5 +1,17 @@ // -*- mode:c++ -*- +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// // Copyright (c) 2007-2008 The Florida State University // All rights reserved. // @@ -39,28 +51,35 @@ def bitfield MEDIA_OPCODE mediaOpcode; def bitfield MEDIA_OPCODE2 mediaOpcode2; def bitfield USEIMM useImm; -def bitfield OPCODE_24 opcode24; +def bitfield OPCODE_24 opcode24; +def bitfield OPCODE_24_23 opcode24_23; def bitfield OPCODE_23_20 opcode23_20; def bitfield OPCODE_23_21 opcode23_21; def bitfield OPCODE_22 opcode22; -def bitfield OPCODE_20 opcode20; -def bitfield OPCODE_19 opcode19; -def bitfield OPCODE_18 opcode18; +def bitfield OPCODE_20 opcode20; +def bitfield OPCODE_19_16 opcode19_16; +def bitfield OPCODE_19 opcode19; +def bitfield OPCODE_18 opcode18; def bitfield OPCODE_15_12 opcode15_12; -def bitfield OPCODE_15 opcode15; +def bitfield OPCODE_15 opcode15; def bitfield MISC_OPCODE miscOpcode; def bitfield OPC2 opc2; def bitfield OPCODE_7 opcode7; +def bitfield OPCODE_6 opcode6; def bitfield OPCODE_4 opcode4; def bitfield IS_MISC isMisc; def bitfield SEVEN_AND_FOUR sevenAndFour; +def bitfield THUMB thumb; +def bitfield BIGTHUMB bigThumb; + // Other def bitfield COND_CODE condCode; def bitfield S_FIELD sField; def bitfield RN rn; def bitfield RD rd; +def bitfield RT rt; def bitfield SHIFT_SIZE shiftSize; def bitfield SHIFT shift; def bitfield RM rm; @@ -79,23 +98,69 @@ def bitfield IMM imm; def bitfield IMMED_11_0 immed11_0; +def bitfield IMMED_7_0 immed7_0; def bitfield IMMED_HI_11_8 immedHi11_8; def bitfield IMMED_LO_3_0 immedLo3_0; def bitfield IMMED_23_0 immed23_0; -def bitfield CPNUM cpNum; +def bitfield CPNUM cpNum; // Note that FP Regs are only 3 bits -def bitfield FN fn; -def bitfield FD fd; -def bitfield FPREGIMM fpRegImm; +def bitfield FN fn; +def bitfield FD fd; +def bitfield FPREGIMM fpRegImm; // We can just use 3:0 for FM since the hard-wired FP regs are handled in // float_regfile.hh -def bitfield FM fm; -def bitfield FPIMM fpImm; -def bitfield PUNWL punwl; +def bitfield FM fm; +def bitfield FPIMM fpImm; +def bitfield PUNWL punwl; // M5 instructions def bitfield M5FUNC m5Func; +// 16 bit thumb bitfields +def bitfield TOPCODE_15_13 topcode15_13; +def bitfield TOPCODE_13_11 topcode13_11; +def bitfield TOPCODE_12_11 topcode12_11; +def bitfield TOPCODE_12_10 topcode12_10; +def bitfield TOPCODE_11_9 topcode11_9; +def bitfield TOPCODE_11_8 topcode11_8; +def bitfield TOPCODE_10_9 topcode10_9; +def bitfield TOPCODE_10_8 topcode10_8; +def bitfield TOPCODE_9_6 topcode9_6; +def bitfield TOPCODE_7 topcode7; +def bitfield TOPCODE_7_6 topcode7_6; +def bitfield TOPCODE_7_5 topcode7_5; +def bitfield TOPCODE_7_4 topcode7_4; +def bitfield TOPCODE_3_0 topcode3_0; + +// 32 bit thumb bitfields +def bitfield HTOPCODE_12_11 htopcode12_11; +def bitfield HTOPCODE_10_9 htopcode10_9; +def bitfield HTOPCODE_9 htopcode9; +def bitfield HTOPCODE_9_8 htopcode9_8; +def bitfield HTOPCODE_9_5 htopcode9_5; +def bitfield HTOPCODE_9_4 htopcode9_4; +def bitfield HTOPCODE_8 htopcode8; +def bitfield HTOPCODE_8_7 htopcode8_7; +def bitfield HTOPCODE_8_6 htopcode8_6; +def bitfield HTOPCODE_8_5 htopcode8_5; +def bitfield HTOPCODE_7 htopcode7; +def bitfield HTOPCODE_7_5 htopcode7_5; +def bitfield HTOPCODE_6 htopcode6; +def bitfield HTOPCODE_6_5 htopcode6_5; +def bitfield HTOPCODE_5_4 htopcode5_4; +def bitfield HTOPCODE_4 htopcode4; + +def bitfield HTRN htrn; +def bitfield HTS hts; + +def bitfield LTOPCODE_15 ltopcode15; +def bitfield LTOPCODE_11_8 ltopcode11_8; +def bitfield LTOPCODE_7_6 ltopcode7_6; +def bitfield LTOPCODE_7_4 ltopcode7_4; +def bitfield LTOPCODE_4 ltopcode4; + +def bitfield LTRD ltrd; +def bitfield LTCOPROC ltcoproc; diff -r 84bd4089958b src/arch/arm/isa/copyright.txt --- a/src/arch/arm/isa/copyright.txt Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/isa/copyright.txt Wed May 26 18:10:45 2010 -0500 @@ -1,3 +1,15 @@ +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// // Copyright (c) 2007, 2008 // The Florida State University // All Rights Reserved diff -r 84bd4089958b src/arch/arm/isa/decoder.isa --- a/src/arch/arm/isa/decoder.isa Tue May 25 20:15:44 2010 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,562 +0,0 @@ -// -*- 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 - -//////////////////////////////////////////////////////////////////// -// -// The actual ARM ISA decoder -// -------------------------- -// The following instructions are specified in the ARM ISA -// Specification. Decoding closely follows the style specified -// in the ARM ISA specification document starting with Table B.1 or 3-1 -// -// - -decode ENCODING default Unknown::unknown() { -format DataOp { - 0x0: decode SEVEN_AND_FOUR { - 1: decode MISC_OPCODE { - 0x9: decode PREPOST { - 0: decode OPCODE { - 0x0: mul({{ Rn = resTemp = Rm * Rs; }}, none); - 0x1: mla({{ Rn = resTemp = (Rm * Rs) + Rd; }}, none); - 0x2: WarnUnimpl::umall(); - 0x4: umull({{ - resTemp = ((uint64_t)Rm)*((uint64_t)Rs); - Rd = (uint32_t)(resTemp & 0xffffffff); - Rn = (uint32_t)(resTemp >> 32); - }}, llbit); - 0x5: smlal({{ - resTemp = ((int64_t)Rm) * ((int64_t)Rs); - resTemp += (((uint64_t)Rn) << 32) | ((uint64_t)Rd); - Rd = (uint32_t)(resTemp & 0xffffffff); - Rn = (uint32_t)(resTemp >> 32); - }}, llbit); - 0x6: smull({{ - resTemp = ((int64_t)(int32_t)Rm)* - ((int64_t)(int32_t)Rs); - Rd = (int32_t)(resTemp & 0xffffffff); - Rn = (int32_t)(resTemp >> 32); - }}, llbit); - 0x7: umlal({{ - resTemp = ((uint64_t)Rm)*((uint64_t)Rs); - resTemp += ((uint64_t)Rn << 32)+((uint64_t)Rd); - Rd = (uint32_t)(resTemp & 0xffffffff); - Rn = (uint32_t)(resTemp >> 32); - }}, llbit); - } - 1: decode PUBWL { - 0x10: WarnUnimpl::swp(); - 0x14: WarnUnimpl::swpb(); - 0x18: WarnUnimpl::strex(); - 0x19: WarnUnimpl::ldrex(); - } - } - format AddrMode3 { - 0xb: strh_ldrh(store, {{ Mem.uh = Rd; }}, - load, {{ Rd = Mem.uh; }}); - 0xd: ldrd_ldrsb(load, {{ Rde = bits(Mem.ud, 31, 0); - Rdo = bits(Mem.ud, 63, 32); }}, - load, {{ Rd = Mem.sb; }}); - 0xf: strd_ldrsh(store, {{ Mem.ud = (Rde.ud & mask(32)) | - (Rdo.ud << 32); }}, - load, {{ Rd = Mem.sh; }}); - } - } - 0: decode IS_MISC { - 0: decode OPCODE { - 0x0: and({{ Rd = resTemp = Rn & op2; }}); - 0x1: eor({{ Rd = resTemp = Rn ^ op2; }}); - 0x2: sub({{ Rd = resTemp = Rn - op2; }}, sub); - 0x3: rsb({{ Rd = resTemp = op2 - Rn; }}, rsb); - 0x4: add({{ Rd = resTemp = Rn + op2; }}, add); - 0x5: adc({{ Rd = resTemp = Rn + op2 + CondCodes<29:>; }}, add); - 0x6: sbc({{ Rd = resTemp = Rn - op2 - !CondCodes<29:>; }}, sub); - 0x7: rsc({{ Rd = resTemp = op2 - Rn - !CondCodes<29:>; }}, rsb); - 0x8: tst({{ resTemp = Rn & op2; }}); - 0x9: teq({{ resTemp = Rn ^ op2; }}); - 0xa: cmp({{ resTemp = Rn - op2; }}, sub); - 0xb: cmn({{ resTemp = Rn + op2; }}, add); - 0xc: orr({{ Rd = resTemp = Rn | op2; }}); - 0xd: mov({{ Rd = resTemp = op2; }}); - 0xe: bic({{ Rd = resTemp = Rn & ~op2; }}); - 0xf: mvn({{ Rd = resTemp = ~op2; }}); - } - 1: decode MISC_OPCODE { - 0x0: decode OPCODE { - 0x8: PredOp::mrs_cpsr({{ - Rd = (Cpsr | CondCodes) & 0xF8FF03DF; - }}); - 0x9: decode USEIMM { - // The mask field is the same as the RN index. - 0: PredOp::msr_cpsr_reg({{ - uint32_t newCpsr = - cpsrWriteByInstr(Cpsr | CondCodes, - Rm, RN, false); - Cpsr = ~CondCodesMask & newCpsr; - CondCodes = CondCodesMask & newCpsr; - }}); - 1: PredImmOp::msr_cpsr_imm({{ - uint32_t newCpsr = - cpsrWriteByInstr(Cpsr | CondCodes, - rotated_imm, RN, false); - Cpsr = ~CondCodesMask & newCpsr; - CondCodes = CondCodesMask & newCpsr; - }}); - } - 0xa: PredOp::mrs_spsr({{ Rd = Spsr; }}); - 0xb: decode USEIMM { - // The mask field is the same as the RN index. - 0: PredOp::msr_spsr_reg({{ - Spsr = spsrWriteByInstr(Spsr, Rm, RN, false); - }}); - 1: PredImmOp::msr_spsr_imm({{ - Spsr = spsrWriteByInstr(Spsr, rotated_imm, - RN, false); - }}); - } - } - 0x1: decode OPCODE { - 0x9: BranchExchange::bx({{ }}); - 0xb: PredOp::clz({{ - Rd = ((Rm == 0) ? 32 : (31 - findMsbSet(Rm))); - }}); - } - 0x2: decode OPCODE { - 0x9: WarnUnimpl::bxj(); - } - 0x3: decode OPCODE { - 0x9: BranchExchange::blx({{ }}, Link); - } - 0x5: decode OPCODE { - 0x8: WarnUnimpl::qadd(); - 0x9: WarnUnimpl::qsub(); - 0xa: WarnUnimpl::qdadd(); - 0xb: WarnUnimpl::qdsub(); - } - 0x8: decode OPCODE { - 0x8: smlabb({{ Rn = resTemp = sext<16>(Rm<15:0>) * sext<16>(Rs<15:0>) + Rd; }}, overflow); - 0x9: WarnUnimpl::smlalbb(); - 0xa: WarnUnimpl::smlawb(); - 0xb: smulbb({{ Rn = resTemp = sext<16>(Rm<15:0>) * sext<16>(Rs<15:0>); }}, none); - } - 0xa: decode OPCODE { - 0x8: smlatb({{ Rn = resTemp = sext<16>(Rm<31:16>) * sext<16>(Rs<15:0>) + Rd; }}, overflow); - 0x9: smulwb({{ - Rn = resTemp = bits(sext<32>(Rm) * sext<16>(Rs<15:0>), 47, 16); - }}, none); - 0xa: WarnUnimpl::smlaltb(); - 0xb: smultb({{ Rn = resTemp = sext<16>(Rm<31:16>) * sext<16>(Rs<15:0>); }}, none); - } - 0xc: decode OPCODE { - 0x8: smlabt({{ Rn = resTemp = sext<16>(Rm<15:0>) * sext<16>(Rs<31:16>) + Rd; }}, overflow); - 0x9: WarnUnimpl::smlawt(); - 0xa: WarnUnimpl::smlalbt(); - 0xb: smulbt({{ Rn = resTemp = sext<16>(Rm<15:0>) * sext<16>(Rs<31:16>); }}, none); - } - 0xe: decode OPCODE { - 0x8: smlatt({{ Rn = resTemp = sext<16>(Rm<31:16>) * sext<16>(Rs<31:16>) + Rd; }}, overflow); - 0x9: smulwt({{ - Rn = resTemp = bits(sext<32>(Rm) * sext<16>(Rs<31:16>), 47, 16); - }}, none); - 0xa: WarnUnimpl::smlaltt(); - 0xb: smultt({{ Rn = resTemp = sext<16>(Rm<31:16>) * sext<16>(Rs<31:16>); }}, none); - } - } - } - } - 0x1: decode IS_MISC { - 0: decode OPCODE { - format DataImmOp { - 0x0: andi({{ Rd = resTemp = Rn & rotated_imm; }}); - 0x1: eori({{ Rd = resTemp = Rn ^ rotated_imm; }}); - 0x2: subi({{ Rd = resTemp = Rn - rotated_imm; }}, sub); - 0x3: rsbi({{ Rd = resTemp = rotated_imm - Rn; }}, rsb); - 0x4: addi({{ Rd = resTemp = Rn + rotated_imm; }}, add); - 0x5: adci({{ - Rd = resTemp = Rn + rotated_imm + CondCodes<29:>; - }}, add); - 0x6: sbci({{ - Rd = resTemp = Rn -rotated_imm - !CondCodes<29:>; - }}, sub); - 0x7: rsci({{ - Rd = resTemp = rotated_imm - Rn - !CondCodes<29:>; - }}, rsb); - 0x8: tsti({{ resTemp = Rn & rotated_imm; }}); - 0x9: teqi({{ resTemp = Rn ^ rotated_imm; }}); - 0xa: cmpi({{ resTemp = Rn - rotated_imm; }}, sub); - 0xb: cmni({{ resTemp = Rn + rotated_imm; }}, add); - 0xc: orri({{ Rd = resTemp = Rn | rotated_imm; }}); - 0xd: movi({{ Rd = resTemp = rotated_imm; }}); - 0xe: bici({{ Rd = resTemp = Rn & ~rotated_imm; }}); - 0xf: mvni({{ Rd = resTemp = ~rotated_imm; }}); - } - } - 1: decode OPCODE { - // The following two instructions aren't supposed to be defined - 0x8: DataOp::movw({{ Rd = IMMED_11_0 | (RN << 12) ; }}); - 0x9: decode RN { - 0: decode IMM { - 0: PredImmOp::nop({{ ; }}); - 1: WarnUnimpl::yield(); - 2: WarnUnimpl::wfe(); - 3: WarnUnimpl::wfi(); - 4: WarnUnimpl::sev(); - } - default: PredImmOp::msr_i_cpsr({{ - uint32_t newCpsr = - cpsrWriteByInstr(Cpsr | CondCodes, - rotated_imm, RN, false); - Cpsr = ~CondCodesMask & newCpsr; - CondCodes = CondCodesMask & newCpsr; - }}); - } - 0xa: PredOp::movt({{ Rd = IMMED_11_0 << 16 | RN << 28 | Rd<15:0>; }}); - 0xb: PredImmOp::msr_i_spsr({{ - Spsr = spsrWriteByInstr(Spsr, rotated_imm, RN, false); - }}); - } - } - 0x2: AddrMode2::addrMode2(Disp, disp); - 0x3: decode OPCODE_4 { - 0: AddrMode2::addrMode2(Shift, Rm_Imm); - 1: decode MEDIA_OPCODE { - 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7: WarnUnimpl::parallel_add_subtract_instructions(); - 0x8: decode MISC_OPCODE { - 0x1, 0x9: WarnUnimpl::pkhbt(); - 0x7: WarnUnimpl::sxtab16(); - 0xb: WarnUnimpl::sel(); - 0x5, 0xd: WarnUnimpl::pkhtb(); - 0x3: WarnUnimpl::sign_zero_extend_add(); - } - 0xa, 0xb: decode SHIFT { - 0x0, 0x2: WarnUnimpl::ssat(); - 0x1: WarnUnimpl::ssat16(); - } - 0xe, 0xf: decode SHIFT { - 0x0, 0x2: WarnUnimpl::usat(); - 0x1: WarnUnimpl::usat16(); - } - 0x10: decode RN { - 0xf: decode MISC_OPCODE { - 0x1: WarnUnimpl::smuad(); - 0x3: WarnUnimpl::smuadx(); - 0x5: WarnUnimpl::smusd(); - 0x7: WarnUnimpl::smusdx(); - } - default: decode MISC_OPCODE { - 0x1: WarnUnimpl::smlad(); - 0x3: WarnUnimpl::smladx(); - 0x5: WarnUnimpl::smlsd(); - 0x7: WarnUnimpl::smlsdx(); - } - } - 0x14: decode MISC_OPCODE { - 0x1: WarnUnimpl::smlald(); - 0x3: WarnUnimpl::smlaldx(); - 0x5: WarnUnimpl::smlsld(); - 0x7: WarnUnimpl::smlsldx(); - } - 0x15: decode RN { - 0xf: decode MISC_OPCODE { - 0x1: WarnUnimpl::smmul(); - 0x3: WarnUnimpl::smmulr(); - } - default: decode MISC_OPCODE { - 0x1: WarnUnimpl::smmla(); - 0x3: WarnUnimpl::smmlar(); - 0xd: WarnUnimpl::smmls(); - 0xf: WarnUnimpl::smmlsr(); - } - } - 0x18: decode RN { - 0xf: WarnUnimpl::usada8(); - default: WarnUnimpl::usad8(); - } - } - } - 0x4: decode PUSWL { - // Right now we only handle cases when S (PSRUSER) is not set - default: ArmMacroStore::ldmstm({{ }}); - } - 0x5: decode OPCODE_24 { - // Branch (and Link) Instructions - 0: Branch::b({{ }}); - 1: Branch::bl({{ }}, Link); - } - 0x6: decode CPNUM { - 0x1: decode PUNWL { - 0x02,0x0a: decode OPCODE_15 { - 0: ArmStoreMemory::stfs_({{ Mem.sf = Fd.sf; - Rn = Rn + disp8; }}, - {{ EA = Rn; }}); - 1: ArmMacroFPAOp::stfd_({{ }}); - } - 0x03,0x0b: decode OPCODE_15 { - 0: ArmLoadMemory::ldfs_({{ Fd.sf = Mem.sf; - Rn = Rn + disp8; }}, - {{ EA = Rn; }}); - 1: ArmMacroFPAOp::ldfd_({{ }}); - } - 0x06,0x0e: decode OPCODE_15 { - 0: ArmMacroFPAOp::stfe_nw({{ }}); - } - 0x07,0x0f: decode OPCODE_15 { - 0: ArmMacroFPAOp::ldfe_nw({{ }}); - } - 0x10,0x18: decode OPCODE_15 { - 0: ArmStoreMemory::stfs_p({{ Mem.sf = Fd.sf; }}, - {{ EA = Rn + disp8; }}); - 1: ArmMacroFPAOp::stfd_p({{ }}); - } - 0x11,0x19: decode OPCODE_15 { - 0: ArmLoadMemory::ldfs_p({{ Fd.sf = Mem.sf; }}, - {{ EA = Rn + disp8; }}); - 1: ArmMacroFPAOp::ldfd_p({{ }}); - } - 0x12,0x1a: decode OPCODE_15 { - 0: ArmStoreMemory::stfs_pw({{ Mem.sf = Fd.sf; - Rn = Rn + disp8; }}, - {{ EA = Rn + disp8; }}); - 1: ArmMacroFPAOp::stfd_pw({{ }}); - } - 0x13,0x1b: decode OPCODE_15 { - 0: ArmLoadMemory::ldfs_pw({{ Fd.sf = Mem.sf; - Rn = Rn + disp8; }}, - {{ EA = Rn + disp8; }}); - 1: ArmMacroFPAOp::ldfd_pw({{ }}); - } - 0x14,0x1c: decode OPCODE_15 { - 0: ArmMacroFPAOp::stfe_pn({{ }}); - } - 0x15,0x1d: decode OPCODE_15 { - 0: ArmMacroFPAOp::ldfe_pn({{ }}); - } - 0x16,0x1e: decode OPCODE_15 { - 0: ArmMacroFPAOp::stfe_pnw({{ }}); - } - 0x17,0x1f: decode OPCODE_15 { - 0: ArmMacroFPAOp::ldfe_pnw({{ }}); - } - } - 0x2: decode PUNWL { - // could really just decode as a single instruction - 0x00,0x04,0x08,0x0c: ArmMacroFMOp::sfm_({{ }}); - 0x01,0x05,0x09,0x0d: ArmMacroFMOp::lfm_({{ }}); - 0x02,0x06,0x0a,0x0e: ArmMacroFMOp::sfm_w({{ }}); - 0x03,0x07,0x0b,0x0f: ArmMacroFMOp::lfm_w({{ }}); - 0x10,0x14,0x18,0x1c: ArmMacroFMOp::sfm_p({{ }}); - 0x11,0x15,0x19,0x1d: ArmMacroFMOp::lfm_p({{ }}); - 0x12,0x16,0x1a,0x1e: ArmMacroFMOp::sfm_pw({{ }}); - 0x13,0x17,0x1b,0x1f: ArmMacroFMOp::lfm_pw({{ }}); - } - 0xb: decode LOADOP { - 0x0: WarnUnimpl::fstmx(); - 0x1: WarnUnimpl::fldmx(); - } - } - 0x7: decode OPCODE_24 { - 0: decode OPCODE_4 { - 0: decode CPNUM { - format FloatOp { - 0x1: decode OPCODE_23_20 { - 0x0: decode OPCODE_15 { - 0: adf({{ Fd.sf = Fn.sf + Fm.sf; }}); - 1: mvf({{ Fd.sf = Fm.sf; }}); - } - 0x1: decode OPCODE_15 { - 0: muf({{ Fd.sf = Fn.sf * Fm.sf; }}); - 1: mnf({{ Fd.sf = -Fm.sf; }}); - } - 0x2: decode OPCODE_15 { - 0: suf({{ Fd.sf = Fn.sf - Fm.sf; }}); - 1: abs({{ Fd.sf = fabs(Fm.sf); }}); - } - 0x3: decode OPCODE_15 { - 0: rsf({{ Fd.sf = Fm.sf - Fn.sf; }}); - 1: rnd({{ Fd.sf = rint(Fm.sf); }}); - } - 0x4: decode OPCODE_15 { - 0: dvf({{ Fd.sf = Fn.sf / Fm.sf; }}); - 1: sqt({{ Fd.sf = sqrt(Fm.sf); }}); - } - 0x5: decode OPCODE_15 { - 0: rdf({{ Fd.sf = Fm.sf / Fn.sf; }}); - 1: log({{ Fd.sf = log10(Fm.sf); }}); - } - 0x6: decode OPCODE_15 { - 0: pow({{ Fd.sf = pow(Fm.sf, Fn.sf); }}); - 1: lgn({{ Fd.sf = log(Fm.sf); }}); - } - 0x7: decode OPCODE_15 { - 0: rpw({{ Fd.sf = pow(Fn.sf, Fm.sf); }}); - 1: exp({{ Fd.sf = exp(Fm.sf); }}); - } - 0x8: decode OPCODE_15 { - 0: rmf({{ Fd.sf = drem(Fn.sf, Fm.sf); }}); - 1: sin({{ Fd.sf = sin(Fm.sf); }}); - } - 0x9: decode OPCODE_15 { - 0: fml({{ Fd.sf = Fn.sf * Fm.sf; }}); - 1: cos({{ Fd.sf = cos(Fm.sf); }}); - } - 0xa: decode OPCODE_15 { - 0: fdv({{ Fd.sf = Fn.sf / Fm.sf; }}); - 1: tan({{ Fd.sf = tan(Fm.sf); }}); - } - 0xb: decode OPCODE_15 { - 0: frd({{ Fd.sf = Fm.sf / Fn.sf; }}); - 1: asn({{ Fd.sf = asin(Fm.sf); }}); - } - 0xc: decode OPCODE_15 { - 0: pol({{ Fd.sf = atan2(Fn.sf, Fm.sf); }}); - 1: acs({{ Fd.sf = acos(Fm.sf); }}); - } - 0xd: decode OPCODE_15 { - 1: atn({{ Fd.sf = atan(Fm.sf); }}); - } - 0xe: decode OPCODE_15 { - // Unnormalised Round - 1: FailUnimpl::urd(); - } - 0xf: decode OPCODE_15 { - // Normalise - 1: FailUnimpl::nrm(); - } - } // OPCODE_23_20 - } // format FloatOp - } // CPNUM - 1: decode CPNUM { // 27-24=1110,4 ==1 - 1: decode OPCODE_15_12 { - format FloatOp { - 0xf: decode OPCODE_23_21 { - format FloatCmp { - 0x4: cmf({{ Fn.df }}, {{ Fm.df }}); - 0x5: cnf({{ Fn.df }}, {{ -Fm.df }}); - 0x6: cmfe({{ Fn.df }}, {{ Fm.df}}); - 0x7: cnfe({{ Fn.df }}, {{ -Fm.df}}); - } - } - default: decode OPCODE_23_20 { - 0x0: decode OPCODE_7 { - 0: flts({{ Fn.sf = (float) Rd.sw; }}); - 1: fltd({{ Fn.df = (double) Rd.sw; }}); - } - 0x1: decode OPCODE_7 { - 0: fixs({{ Rd = (uint32_t) Fm.sf; }}); - 1: fixd({{ Rd = (uint32_t) Fm.df; }}); - } - 0x2: wfs({{ Fpsr = Rd; }}); - 0x3: rfs({{ Rd = Fpsr; }}); - 0x4: FailUnimpl::wfc(); - 0x5: FailUnimpl::rfc(); - } - } // format FloatOp - } - 0xa: decode MISC_OPCODE { - 0x1: decode MEDIA_OPCODE { - 0xf: decode RN { - 0x0: FloatOp::fmrx_fpsid({{ Rd = Fpsid; }}); - 0x1: FloatOp::fmrx_fpscr({{ Rd = Fpscr; }}); - 0x8: FloatOp::fmrx_fpexc({{ Rd = Fpexc; }}); - } - 0xe: decode RN { - 0x0: FloatOp::fmxr_fpsid({{ Fpsid = Rd; }}); - 0x1: FloatOp::fmxr_fpscr({{ Fpscr = Rd; }}); - 0x8: FloatOp::fmxr_fpexc({{ Fpexc = Rd; }}); - } - } // MEDIA_OPCODE (MISC_OPCODE 0x1) - } // MISC_OPCODE (CPNUM 0xA) - 0xf: decode RN { - // Barrriers, Cache Maintence, NOPS - 7: decode OPCODE_23_21 { - 0: decode RM { - 0: decode OPC2 { - 4: decode OPCODE_20 { - 0: PredOp::mcr_cp15_nop1({{ }}); // was wfi - } - } - 1: WarnUnimpl::cp15_cache_maint(); - 4: WarnUnimpl::cp15_par(); - 5: decode OPC2 { - 0,1: WarnUnimpl::cp15_cache_maint2(); - 4: PredOp::cp15_isb({{ ; }}, IsMemBarrier, IsSerializeBefore); - 6,7: WarnUnimpl::cp15_bp_maint(); - } - 6: WarnUnimpl::cp15_cache_maint3(); - 8: WarnUnimpl::cp15_va_to_pa(); - 10: decode OPC2 { - 1,2: WarnUnimpl::cp15_cache_maint3(); - 4: PredOp::cp15_dsb({{ ; }}, IsMemBarrier, IsSerializeBefore); - 5: PredOp::cp15_dmb({{ ; }}, IsMemBarrier, IsSerializeBefore); - } - 11: WarnUnimpl::cp15_cache_maint4(); - 13: decode OPC2 { - 1: decode OPCODE_20 { - 0: PredOp::mcr_cp15_nop2({{ }}); // was prefetch - } - } - 14: WarnUnimpl::cp15_cache_maint5(); - } // RM - } // OPCODE_23_21 CR - - // Thread ID and context ID registers - // Thread ID register needs cheaper access than miscreg - 13: WarnUnimpl::mcr_mrc_cp15_c7(); - - // All the rest - default: decode OPCODE_20 { - 0: PredOp::mcr_cp15({{ - fault = setCp15Register(Rd, RN, OPCODE_23_21, RM, OPC2); - }}); - 1: PredOp::mrc_cp15({{ - fault = readCp15Register(Rd, RN, OPCODE_23_21, RM, OPC2); - }}); - } - } // RN - } // CPNUM (OP4 == 1) - } //OPCODE_4 - -#if FULL_SYSTEM - 1: PredOp::swi({{ fault = new SupervisorCall; }}, IsSerializeAfter, IsNonSpeculative, IsSyscall); -#else - 1: PredOp::swi({{ if (testPredicate(CondCodes, condCode)) - { - if (IMMED_23_0) - xc->syscall(IMMED_23_0); - else - xc->syscall(R7); - } - }}); -#endif // FULL_SYSTEM - } // OPCODE_24 - -} -} - diff -r 84bd4089958b src/arch/arm/isa/decoder/arm.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/decoder/arm.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,121 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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 + +//////////////////////////////////////////////////////////////////// +// +// The actual ARM ISA decoder +// -------------------------- +// The following instructions are specified in the ARM ISA +// Specification. Decoding closely follows the style specified +// in the ARM ISA specification document starting with Table B.1 or 3-1 +// +// + +decode COND_CODE { +0xF: ArmUnconditional::armUnconditional(); +default: decode ENCODING { +format DataOp { + 0x0: decode SEVEN_AND_FOUR { + 1: decode MISC_OPCODE { + 0x9: decode PREPOST { + 0: ArmMultAndMultAcc::armMultAndMultAcc(); + 1: ArmSyncMem::armSyncMem(); + } + 0xb, 0xd, 0xf: AddrMode3::addrMode3(); + } + 0: decode IS_MISC { + 0: ArmDataProcReg::armDataProcReg(); + 1: decode OPCODE_7 { + 0x0: decode MISC_OPCODE { + 0x0: ArmMsrMrs::armMsrMrs(); + // bxj unimplemented, treated as bx + 0x1,0x2: ArmBxClz::armBxClz(); + 0x3: decode OPCODE { + 0x9: ArmBlxReg::armBlxReg(); + } + 0x5: ArmSatAddSub::armSatAddSub(); + 0x7: Breakpoint::bkpt(); + } + 0x1: ArmHalfWordMultAndMultAcc::armHalfWordMultAndMultAcc(); + } + } + } + 0x1: decode IS_MISC { + 0: ArmDataProcImm::armDataProcImm(); + 1: ArmMisc::armMisc(); + } + 0x2: AddrMode2::addrMode2(True); + 0x3: decode OPCODE_4 { + 0: AddrMode2::addrMode2(False); + 1: decode OPCODE_24_23 { + 0x0: ArmParallelAddSubtract::armParallelAddSubtract(); + 0x1: ArmPackUnpackSatReverse::armPackUnpackSatReverse(); + 0x2: ArmSignedMultiplies::armSignedMultiplies(); + 0x3: ArmMiscMedia::armMiscMedia(); + } + } + 0x4: ArmMacroMem::armMacroMem(); + 0x5: decode OPCODE_24 { + 0: ArmBBlxImm::armBBlxImm(); + 1: ArmBlBlxImm::armBlBlxImm(); + } + 0x6: decode CPNUM { + 0xa, 0xb: ExtensionRegLoadStore::extensionRegLoadStore(); + } + 0x7: decode OPCODE_24 { + 0: decode OPCODE_4 { + 0: decode CPNUM { + 0xa, 0xb: VfpData::vfpData(); + } // CPNUM + 1: decode CPNUM { // 27-24=1110,4 ==1 + 0xa, 0xb: ShortFpTransfer::shortFpTransfer(); + 0xf: McrMrc15::mcrMrc15(); + } // CPNUM (OP4 == 1) + } //OPCODE_4 + + 1: Svc::svc(); + } // OPCODE_24 + +} +} +} + diff -r 84bd4089958b src/arch/arm/isa/decoder/decoder.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/decoder/decoder.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,48 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// Copyright (c) 2009 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: Gabe Black + +decode THUMB default Unknown::unknown() { +0: +##include "arm.isa" +1: +##include "thumb.isa" +} diff -r 84bd4089958b src/arch/arm/isa/decoder/thumb.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/decoder/thumb.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,168 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// Copyright (c) 2009 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: Gabe Black + +decode BIGTHUMB { + // 16 bit thumb instructions. + 0: decode TOPCODE_15_13 { + 0x0, 0x1: Thumb16ShiftAddSubMoveCmp::thumb16ShiftAddMoveCmp(); + 0x2: decode TOPCODE_12_10 { + 0x0: Thumb16DataProcessing::thumb16DataProcessing(); + 0x1: Thumb16SpecDataAndBx::thumb16SpecDataAndBx(); + 0x2, 0x3: Thumb16MemLit::thumb16MemLit(); + default: Thumb16MemReg::thumb16MemReg(); + } + 0x3, 0x4: Thumb16MemImm::thumb16MemImm(); + 0x5: decode TOPCODE_12_11 { + 0x0: Thumb16Adr::thumb16Adr(); + 0x1: Thumb16AddSp::thumb16AddSp(); //sp, immediate + 0x2, 0x3: Thumb16Misc::thumb16Misc(); + } + 0x6: decode TOPCODE_12_11 { + 0x0, 0x1: Thumb16MacroMem::thumb16MacroMem(); + 0x2, 0x3: Thumb16CondBranchAndSvc::thumb16CondBranchAndSvc(); + } + 0x7: decode TOPCODE_12_11 { + 0x0: Thumb16UncondBranch::thumb16UncondBranch(); + } + } + + // 32 bit thumb instructions. + 1: decode HTOPCODE_12_11 { + 0x1: decode HTOPCODE_10_9 { + 0x0: decode HTOPCODE_6 { + 0x0: decode HTOPCODE_8_7 { + 0x0, 0x3: Thumb32SrsRfe::thumb32SrsRfe(); + // This uses the same encoding as regular ARM. + default: ArmMacroMem::armMacroMem(); + } + 0x1: Thumb32LdrStrDExTbh::thumb32LdrStrDExTbh(); + } + 0x1: Thumb32DataProcShiftReg::thumb32DataProcShiftReg(); + default: decode HTOPCODE_9_8 { + 0x2: decode LTOPCODE_4 { + 0x0: decode LTCOPROC { + 0xa, 0xb: VfpData::vfpData(); + default: WarnUnimpl::cdp(); // cdp2 + } + 0x1: decode LTCOPROC { + 0xa, 0xb: ShortFpTransfer::shortFpTransfer(); + 0xf: McrMrc15::mcrMrc15(); + } + } + 0x3: WarnUnimpl::Advanced_SIMD(); + default: decode LTCOPROC { + 0xa, 0xb: ExtensionRegLoadStore::extensionRegLoadStre(); + 0xf: decode HTOPCODE_9_4 { + 0x00: Unknown::undefined(); + 0x04: WarnUnimpl::mcrr(); // mcrr2 + 0x05: WarnUnimpl::mrrc(); // mrrc2 + 0x02, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, + 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e: + WarnUnimpl::stc(); // stc2 + 0x03, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11, + 0x13, 0x15, 0x17, 0x19, 0x1b, 0x1d, 0x1f: + decode HTRN { + 0xf: WarnUnimpl::ldc(); // ldc2 (literal) + default: WarnUnimpl::ldc(); // ldc2 (immediate) + } + } + } + } + } + 0x2: decode LTOPCODE_15 { + 0x0: decode HTOPCODE_9 { + 0x0: Thumb32DataProcModImm::thumb32DataProcModImm(); + 0x1: Thumb32DataProcPlainBin::thumb32DataProcPlainBin(); + } + 0x1: Thumb32BranchesAndMiscCtrl::thumb32BranchesAndMiscCtrl(); + } + 0x3: decode HTOPCODE_10_9 { + 0x0: decode HTOPCODE_4 { + 0x0: decode HTOPCODE_8 { + 0x0: Thumb32StoreSingle::thumb32StoreSingle(); + 0x1: ThumbNeonMem::thumbNeonMem(); + } + 0x1: decode HTOPCODE_6_5 { + 0x0: LoadByteMemoryHints::loadByteMemoryHints(); + 0x1: LoadHalfwordMemoryHints::loadHalfwordMemoryHints(); + 0x2: Thumb32LoadWord::thumb32LoadWord(); + 0x3: Unknown::undefined(); + } + } + 0x1: decode HTOPCODE_8_7 { + 0x2: Thumb32MulMulAccAndAbsDiff::thumb32MulMulAccAndAbsDiff(); + 0x3: Thumb32LongMulMulAccAndDiv::thumb32LongMulMulAccAndDiv(); + default: Thumb32DataProcReg::thumb32DataProcReg(); + } + default: decode HTOPCODE_9_8 { + 0x2: decode LTOPCODE_4 { + 0x0: decode LTCOPROC { + 0xa, 0xb: VfpData::vfpData(); + default: WarnUnimpl::cdp(); // cdp2 + } + 0x1: decode LTCOPROC { + 0xa, 0xb: ShortFpTransfer::shortFpTransfer(); + 0xf: McrMrc15::mcrMrc15(); + } + } + 0x3: ThumbNeonData::thumbNeonData(); + default: decode LTCOPROC { + 0xa, 0xb: ExtensionRegLoadStore::extensionRegLoadStre(); + 0xf: decode HTOPCODE_9_4 { + 0x00: Unknown::undefined(); + 0x04: WarnUnimpl::mcrr(); // mcrr2 + 0x05: WarnUnimpl::mrrc(); // mrrc2 + 0x02, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, + 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e: + WarnUnimpl::stc(); // stc2 + 0x03, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11, + 0x13, 0x15, 0x17, 0x19, 0x1b, 0x1d, 0x1f: + decode HTRN { + 0xf: WarnUnimpl::ldc(); // ldc2 (literal) + default: WarnUnimpl::ldc(); // ldc2 (immediate) + } + } + } + } + } + } +} diff -r 84bd4089958b src/arch/arm/isa/formats/basic.isa --- a/src/arch/arm/isa/formats/basic.isa Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/isa/formats/basic.isa Wed May 26 18:10:45 2010 -0500 @@ -28,70 +28,6 @@ // // 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(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; - - %(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) diff -r 84bd4089958b src/arch/arm/isa/formats/branch.isa --- a/src/arch/arm/isa/formats/branch.isa Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/isa/formats/branch.isa Wed May 26 18:10:45 2010 -0500 @@ -1,5 +1,17 @@ // -*- mode:c++ -*- +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// // Copyright (c) 2007-2008 The Florida State University // All rights reserved. // @@ -33,99 +45,238 @@ // Control transfer instructions // -def format Branch(code,*opt_flags) {{ - - #Build Instruction Flags - #Use Link & Likely Flags to Add Link/Condition Code - inst_flags = ('IsDirectControl', ) - linking = False - for x in opt_flags: - if x == 'Link': - linking = True - 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 (testPredicate(CondCodes, condCode)) {\n' - icode += code - icode += ' NPC = NPC + 4 + disp;\n' - icode += '} else {\n' - icode += ' NPC = NPC;\n' - if linking: - icode += ' LR = LR;\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 ArmBBlxImm() {{ + decode_block = ''' + if (machInst.condCode == 0xF) { + int32_t imm = (sext<26>(bits(machInst, 23, 0) << 2)) | + (bits(machInst, 24) << 1); + return new BlxImm(machInst, imm); + } else { + return new B(machInst, sext<26>(bits(machInst, 23, 0) << 2), + (ConditionCode)(uint32_t)machInst.condCode); + } + ''' }}; -def format BranchExchange(code,*opt_flags) {{ - #Build Instruction Flags - #Use Link & Likely Flags to Add Link/Condition Code - inst_flags = ('IsIndirectControl', ) - linking = False - for x in opt_flags: - if x == 'Link': - linking = True - 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 (testPredicate(CondCodes, condCode)) {\n' - icode += code - icode += ' NPC = Rm & 0xfffffffe; // Masks off bottom bit\n' - icode += '} else {\n' - icode += ' NPC = NPC;\n' - if linking: - icode += ' LR = LR;\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 ArmBlBlxImm() {{ + decode_block = ''' + if (machInst.condCode == 0xF) { + int32_t imm = (sext<26>(bits(machInst, 23, 0) << 2)) | + (bits(machInst, 24) << 1); + return new BlxImm(machInst, imm); + } else { + return new Bl(machInst, sext<26>(bits(machInst, 23, 0) << 2), + (ConditionCode)(uint32_t)machInst.condCode); + } + ''' }}; -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) +def format ArmBxClz() {{ + decode_block = ''' + { + const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + if (OPCODE == 0x9) { + return new BxReg(machInst, rm, + (ConditionCode)(uint32_t)machInst.condCode); + } else if (OPCODE == 0xb) { + return new Clz(machInst, rd, rm); + } else { + return new Unknown(machInst); + } + } + ''' }}; +def format ArmBlxReg() {{ + decode_block = ''' + return new BlxReg(machInst, (IntRegIndex)(uint32_t)bits(machInst, 3, 0), + (ConditionCode)(uint32_t)machInst.condCode); + ''' +}}; +def format Thumb16CondBranchAndSvc() {{ + decode_block = ''' + if (bits(machInst, 11, 9) != 0x7) { + return new B(machInst, sext<9>(bits(machInst, 7, 0) << 1), + (ConditionCode)(uint32_t)bits(machInst, 11, 8)); + } else if (bits(machInst, 8)) { + return new Svc(machInst); + } else { + // This space will not be allocated in the future. + return new Unknown(machInst); + } + ''' +}}; + +def format Thumb16UncondBranch() {{ + decode_block = ''' + return new B(machInst, sext<12>(bits(machInst, 10, 0) << 1), COND_UC); + ''' +}}; + +def format Thumb32BranchesAndMiscCtrl() {{ + decode_block = ''' + { + const uint32_t op = bits(machInst, 26, 20); + const uint32_t op1 = bits(machInst, 14, 12); + switch (op1 & 0x5) { + case 0x0: + if (op == 127) { + if (op1 & 0x2) { + // Permanently undefined. + return new Unknown(machInst); + } else { + return new WarnUnimplemented("smc", machInst); + } + } else if ((op & 0x38) != 0x38) { + const uint32_t s = bits(machInst, 26); + const uint32_t j1 = bits(machInst, 13); + const uint32_t j2 = bits(machInst, 11); + const uint32_t imm6 = bits(machInst, 21, 16); + const uint32_t imm11 = bits(machInst, 10, 0); + const int32_t imm = sext<21>((s << 20) | + (j2 << 19) | (j1 << 18) | + (imm6 << 12) | (imm11 << 1)); + return new B(machInst, imm, + (ConditionCode)(uint32_t)bits(machInst, 25, 22)); + } else { + switch (op) { + case 0x38: + { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const uint8_t byteMask = bits(machInst, 11, 8); + return new MsrCpsrReg(machInst, rn, byteMask); + } + case 0x39: + { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const uint8_t byteMask = bits(machInst, 11, 8); + return new MsrSpsrReg(machInst, rn, byteMask); + } + case 0x3a: + { + const uint32_t op1 = bits(machInst, 10, 8); + const uint32_t op2 = bits(machInst, 7, 0); + if (op1 != 0) { + const bool enable = bits(machInst, 10, 9) == 0x2; + const uint32_t mods = bits(machInst, 8, 0) | + ((enable ? 1 : 0) << 9); + return new Cps(machInst, mods); + } else if ((op2 & 0xf0) == 0xf0) { + return new WarnUnimplemented("dbg", machInst); + } else { + switch (op2) { + case 0x0: + return new NopInst(machInst); + case 0x1: + return new YieldInst(machInst); + case 0x2: + return new WfeInst(machInst); + case 0x3: + return new WfiInst(machInst); + case 0x4: + return new SevInst(machInst); + default: + break; + } + } + break; + } + case 0x3b: + { + const uint32_t op = bits(machInst, 7, 4); + switch (op) { + case 0x0: + return new Leavex(machInst); + case 0x1: + return new Enterx(machInst); + case 0x2: + return new WarnUnimplemented("clrex", machInst); + case 0x4: + return new WarnUnimplemented("dsb", machInst); + case 0x5: + return new WarnUnimplemented("dmb", machInst); + case 0x6: + return new WarnUnimplemented("isb", machInst); + default: + break; + } + break; + } + case 0x3c: + { + // On systems that don't support bxj, bxj == bx + return new BxReg(machInst, + (IntRegIndex)(uint32_t)bits(machInst, 19, 16), + COND_UC); + } + case 0x3d: + { + const uint32_t imm32 = bits(machInst, 7, 0); + return new SubsImmPclr(machInst, INTREG_PC, INTREG_LR, + imm32, false); + } + case 0x3e: + { + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + return new MrsCpsr(machInst, rd); + } + case 0x3f: + { + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + return new MrsSpsr(machInst, rd); + } + } + break; + } + case 0x1: + { + const uint32_t s = bits(machInst, 26); + const uint32_t i1 = !(bits(machInst, 13) ^ s); + const uint32_t i2 = !(bits(machInst, 11) ^ s); + const uint32_t imm10 = bits(machInst, 25, 16); + const uint32_t imm11 = bits(machInst, 10, 0); + const int32_t imm = sext<25>((s << 24) | + (i1 << 23) | (i2 << 22) | + (imm10 << 12) | (imm11 << 1)); + return new B(machInst, imm, COND_UC); + } + case 0x4: + { + if (bits(machInst, 0) == 1) { + return new Unknown(machInst); + } + const uint32_t s = bits(machInst, 26); + const uint32_t i1 = !(bits(machInst, 13) ^ s); + const uint32_t i2 = !(bits(machInst, 11) ^ s); + const uint32_t imm10h = bits(machInst, 25, 16); + const uint32_t imm10l = bits(machInst, 10, 1); + const int32_t imm = sext<25>((s << 24) | + (i1 << 23) | (i2 << 22) | + (imm10h << 12) | (imm10l << 2)); + return new BlxImm(machInst, imm); + } + case 0x5: + { + const uint32_t s = bits(machInst, 26); + const uint32_t i1 = !(bits(machInst, 13) ^ s); + const uint32_t i2 = !(bits(machInst, 11) ^ s); + const uint32_t imm10 = bits(machInst, 25, 16); + const uint32_t imm11 = bits(machInst, 10, 0); + const int32_t imm = sext<25>((s << 24) | + (i1 << 23) | (i2 << 22) | + (imm10 << 12) | (imm11 << 1)); + return new Bl(machInst, imm, COND_UC); + } + default: + break; + } + return new Unknown(machInst); + } + ''' +}}; diff -r 84bd4089958b src/arch/arm/isa/formats/breakpoint.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/formats/breakpoint.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,93 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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 + +//////////////////////////////////////////////////////////////////// +// +// Breakpoint instructions +// + +output header {{ + /** + * Static instruction class for Breakpoint (illegal) instructions. + * These cause simulator termination if they are executed in a + * non-speculative mode. This is a leaf class. + */ + class Breakpoint : public ArmStaticInst + { + public: + /// Constructor + Breakpoint(ExtMachInst _machInst) + : ArmStaticInst("Breakpoint", _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 + Breakpoint::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return csprintf("%-10s (inst 0x%x)", "Breakpoint", machInst); + } +}}; + +output exec {{ + Fault + Breakpoint::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + return new PrefetchAbort(xc->readPC(), ArmFault::DebugEvent); + } +}}; + +def format Breakpoint() {{ + decode_block = 'return new Breakpoint(machInst);\n' +}}; + diff -r 84bd4089958b src/arch/arm/isa/formats/data.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/formats/data.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,1536 @@ +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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: Gabe Black + +def format ArmMiscMedia() {{ + decode_block = ''' + { + const uint32_t op1 = bits(machInst, 22, 20); + const uint32_t op2 = bits(machInst, 7, 5); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const IntRegIndex ra = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + if (op1 == 0 && op2 == 0) { + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + if (ra == 0xf) { + return new Usad8(machInst, rd, rn, rm); + } else { + return new Usada8(machInst, rd, rn, rm, ra); + } + } else if (bits(op2, 1, 0) == 0x2) { + const uint32_t lsb = bits(machInst, 11, 7); + const uint32_t msb = lsb + bits(machInst, 20, 16); + if (bits(op1, 2, 1) == 0x3) { + return new Ubfx(machInst, ra, rn, lsb, msb); + } else if (bits(op1, 2, 1) == 0x1) { + return new Sbfx(machInst, ra, rn, lsb, msb); + } + } else if (bits(op2, 1, 0) == 0x0 && bits(op1, 2, 1) == 0x2) { + const uint32_t lsb = bits(machInst, 11, 7); + const uint32_t msb = bits(machInst, 20, 16); + if (rn == 0xf) { + return new Bfc(machInst, ra, ra, lsb, msb); + } else { + return new Bfi(machInst, ra, rn, lsb, msb); + } + } + return new Unknown(machInst); + } + ''' +}}; + +def format ArmDataProcReg() {{ + pclr = ''' + return new %(className)ssRegPclr(machInst, %(dest)s, + %(op1)s, rm, imm5, + type); + ''' + instDecode = ''' + case %(opcode)#x: + if (immShift) { + if (setCc) { + if (%(dest)s == INTREG_PC) { + %(pclr)s + } else { + return new %(className)sRegCc(machInst, %(dest)s, + %(op1)s, rm, imm5, type); + } + } else { + return new %(className)sReg(machInst, %(dest)s, %(op1)s, + rm, imm5, type); + } + } else { + if (setCc) { + return new %(className)sRegRegCc(machInst, %(dest)s, + %(op1)s, rm, rs, type); + } else { + return new %(className)sRegReg(machInst, %(dest)s, + %(op1)s, rm, rs, type); + } + } + break; + ''' + + def instCode(opcode, mnem, useDest = True, useOp1 = True): + global pclr + if useDest: + dest = "rd" + else: + dest = "INTREG_ZERO" + if useOp1: + op1 = "rn" + else: + op1 = "INTREG_ZERO" + global instDecode, pclrCode + substDict = { "className": mnem.capitalize(), + "opcode": opcode, + "dest": dest, + "op1": op1 } + if useDest: + substDict["pclr"] = pclr % substDict + else: + substDict["pclr"] = "" + return instDecode % substDict + + decode_block = ''' + { + const bool immShift = (bits(machInst, 4) == 0); + const bool setCc = (bits(machInst, 20) == 1); + const uint32_t imm5 = bits(machInst, 11, 7); + const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 6, 5); + const IntRegIndex rd = (IntRegIndex)(uint32_t)RD; + const IntRegIndex rn = (IntRegIndex)(uint32_t)RN; + const IntRegIndex rm = (IntRegIndex)(uint32_t)RM; + const IntRegIndex rs = (IntRegIndex)(uint32_t)RS; + switch (OPCODE) { + ''' + decode_block += instCode(0x0, "and") + decode_block += instCode(0x1, "eor") + decode_block += instCode(0x2, "sub") + decode_block += instCode(0x3, "rsb") + decode_block += instCode(0x4, "add") + decode_block += instCode(0x5, "adc") + decode_block += instCode(0x6, "sbc") + decode_block += instCode(0x7, "rsc") + decode_block += instCode(0x8, "tst", useDest = False) + decode_block += instCode(0x9, "teq", useDest = False) + decode_block += instCode(0xa, "cmp", useDest = False) + decode_block += instCode(0xb, "cmn", useDest = False) + decode_block += instCode(0xc, "orr") + decode_block += instCode(0xd, "mov", useOp1 = False) + decode_block += instCode(0xe, "bic") + decode_block += instCode(0xf, "mvn", useOp1 = False) + decode_block += ''' + default: + return new Unknown(machInst); + } + } + ''' +}}; + +def format ArmPackUnpackSatReverse() {{ + decode_block = ''' + { + const uint32_t op1 = bits(machInst, 22, 20); + const uint32_t a = bits(machInst, 19, 16); + const uint32_t op2 = bits(machInst, 7, 5); + if (bits(op2, 0) == 0) { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const uint32_t satImm = bits(machInst, 20, 16); + const uint32_t imm = bits(machInst, 11, 7); + const ArmShiftType type = + (ArmShiftType)(uint32_t)bits(machInst, 6, 5); + if (op1 == 0) { + if (type) { + return new PkhtbReg(machInst, rd, (IntRegIndex)a, + rn, imm, type); + } else { + return new PkhbtReg(machInst, rd, (IntRegIndex)a, + rn, imm, type); + } + } else if (bits(op1, 2, 1) == 1) { + return new Ssat(machInst, rd, satImm + 1, rn, imm, type); + } else if (bits(op1, 2, 1) == 3) { + return new Usat(machInst, rd, satImm, rn, imm, type); + } + return new Unknown(machInst); + } + switch (op1) { + case 0x0: + { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + if (op2 == 0x3) { + const uint32_t rotation = + (uint32_t)bits(machInst, 11, 10) << 3; + if (a == 0xf) { + return new Sxtb16(machInst, rd, rotation, rm); + } else { + return new Sxtab16(machInst, rd, rn, rm, rotation); + } + } else if (op2 == 0x5) { + return new Sel(machInst, rd, rn, rm); + } + } + break; + case 0x2: + if (op2 == 0x1) { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const uint32_t satImm = bits(machInst, 20, 16); + return new Ssat16(machInst, rd, satImm + 1, rn); + } else if (op2 == 0x3) { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const uint32_t rotation = + (uint32_t)bits(machInst, 11, 10) << 3; + if (a == 0xf) { + return new Sxtb(machInst, rd, rotation, rm); + } else { + return new Sxtab(machInst, rd, rn, rm, rotation); + } + } + break; + case 0x3: + if (op2 == 0x1) { + IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + return new Rev(machInst, rd, rm); + } else if (op2 == 0x3) { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const uint32_t rotation = + (uint32_t)bits(machInst, 11, 10) << 3; + if (a == 0xf) { + return new Sxth(machInst, rd, rotation, rm); + } else { + return new Sxtah(machInst, rd, rn, rm, rotation); + } + } else if (op2 == 0x5) { + IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + return new Rev16(machInst, rd, rm); + } + break; + case 0x4: + if (op2 == 0x3) { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const uint32_t rotation = + (uint32_t)bits(machInst, 11, 10) << 3; + if (a == 0xf) { + return new Uxtb16(machInst, rd, rotation, rm); + } else { + return new Uxtab16(machInst, rd, rn, rm, rotation); + } + } + break; + case 0x6: + if (op2 == 0x1) { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const uint32_t satImm = bits(machInst, 20, 16); + return new Usat16(machInst, rd, satImm, rn); + } else if (op2 == 0x3) { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const uint32_t rotation = + (uint32_t)bits(machInst, 11, 10) << 3; + if (a == 0xf) { + return new Uxtb(machInst, rd, rotation, rm); + } else { + return new Uxtab(machInst, rd, rn, rm, rotation); + } + } + break; + case 0x7: + { + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + if (op2 == 0x1) { + return new Rbit(machInst, rd, rm); + } else if (op2 == 0x3) { + const uint32_t rotation = + (uint32_t)bits(machInst, 11, 10) << 3; + if (a == 0xf) { + return new Uxth(machInst, rd, rotation, rm); + } else { + return new Uxtah(machInst, rd, rn, rm, rotation); + } + } else if (op2 == 0x5) { + return new Revsh(machInst, rd, rm); + } + } + break; + } + return new Unknown(machInst); + } + ''' +}}; + +def format ArmParallelAddSubtract() {{ + decode_block=''' + { + const uint32_t op1 = bits(machInst, 21, 20); + const uint32_t op2 = bits(machInst, 7, 5); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + if (bits(machInst, 22) == 0) { + switch (op1) { + case 0x1: + switch (op2) { + case 0x0: + return new Sadd16RegCc(machInst, rd, rn, rm, 0, LSL); + case 0x1: + return new SasxRegCc(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new SsaxRegCc(machInst, rd, rn, rm, 0, LSL); + case 0x3: + return new Ssub16RegCc(machInst, rd, rn, rm, 0, LSL); + case 0x4: + return new Sadd8RegCc(machInst, rd, rn, rm, 0, LSL); + case 0x7: + return new Ssub8RegCc(machInst, rd, rn, rm, 0, LSL); + } + break; + case 0x2: + switch (op2) { + case 0x0: + return new Qadd16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x1: + return new QasxReg(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new QsaxReg(machInst, rd, rn, rm, 0, LSL); + case 0x3: + return new Qsub16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x4: + return new Qadd8Reg(machInst, rd, rn, rm, 0, LSL); + case 0x7: + return new Qsub8Reg(machInst, rd, rn, rm, 0, LSL); + } + break; + case 0x3: + switch (op2) { + case 0x0: + return new Shadd16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x1: + return new ShasxReg(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new ShsaxReg(machInst, rd, rn, rm, 0, LSL); + case 0x3: + return new Shsub16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x4: + return new Shadd8Reg(machInst, rd, rn, rm, 0, LSL); + case 0x7: + return new Shsub8Reg(machInst, rd, rn, rm, 0, LSL); + } + break; + } + } else { + switch (op1) { + case 0x1: + switch (op2) { + case 0x0: + return new Uadd16RegCc(machInst, rd, rn, rm, 0, LSL); + case 0x1: + return new UasxRegCc(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new UsaxRegCc(machInst, rd, rn, rm, 0, LSL); + case 0x3: + return new Usub16RegCc(machInst, rd, rn, rm, 0, LSL); + case 0x4: + return new Uadd8RegCc(machInst, rd, rn, rm, 0, LSL); + case 0x7: + return new Usub8RegCc(machInst, rd, rn, rm, 0, LSL); + } + break; + case 0x2: + switch (op2) { + case 0x0: + return new Uqadd16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x1: + return new UqasxReg(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new UqsaxReg(machInst, rd, rn, rm, 0, LSL); + case 0x3: + return new Uqsub16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x4: + return new Uqadd8Reg(machInst, rd, rn, rm, 0, LSL); + case 0x7: + return new Uqsub8Reg(machInst, rd, rn, rm, 0, LSL); + } + break; + case 0x3: + switch (op2) { + case 0x0: + return new Uhadd16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x1: + return new UhasxReg(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new UhsaxReg(machInst, rd, rn, rm, 0, LSL); + case 0x3: + return new Uhsub16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x4: + return new Uhadd8Reg(machInst, rd, rn, rm, 0, LSL); + case 0x7: + return new Uhsub8Reg(machInst, rd, rn, rm, 0, LSL); + } + break; + } + } + return new Unknown(machInst); + } + ''' +}}; + +def format ArmDataProcImm() {{ + pclr = ''' + return new %(className)ssImmPclr(machInst, %(dest)s, + %(op1)s, imm, false); + ''' + adr = ''' + return new AdrImm(machInst, %(dest)s, %(add)s, + imm, false); + ''' + instDecode = ''' + case %(opcode)#x: + if (setCc) { + if (%(pclrInst)s && %(dest)s == INTREG_PC) { + %(pclr)s + } else { + return new %(className)sImmCc(machInst, %(dest)s, %(op1)s, + imm, rotC); + } + } else { + if (%(adrInst)s && %(op1)s == INTREG_PC) { + %(adr)s + } else { + return new %(className)sImm(machInst, %(dest)s, %(op1)s, + imm, rotC); + } + } + break; + ''' + + def instCode(opcode, mnem, useDest = True, useOp1 = True): + global instDecode, pclr, adr + if useDest: + dest = "rd" + else: + dest = "INTREG_ZERO" + if useOp1: + op1 = "rn" + else: + op1 = "INTREG_ZERO" + substDict = { "className": mnem.capitalize(), + "opcode": opcode, + "dest": dest, + "op1": op1, + "adr": "", + "adrInst": "false" } + if useDest: + substDict["pclrInst"] = "true" + substDict["pclr"] = pclr % substDict + else: + substDict["pclrInst"] = "false" + substDict["pclr"] = "" + return instDecode % substDict + + def adrCode(opcode, mnem, add="1"): + global instDecode, pclr, adr + substDict = { "className": mnem.capitalize(), + "opcode": opcode, + "dest": "rd", + "op1": "rn", + "add": add, + "pclrInst": "true", + "adrInst": "true" } + substDict["pclr"] = pclr % substDict + substDict["adr"] = adr % substDict + return instDecode % substDict + + decode_block = ''' + { + const bool setCc = (bits(machInst, 20) == 1); + const uint32_t unrotated = bits(machInst, 7, 0); + const uint32_t rotation = (bits(machInst, 11, 8) << 1); + const bool rotC = (rotation != 0); + const uint32_t imm = rotate_imm(unrotated, rotation); + const IntRegIndex rd = (IntRegIndex)(uint32_t)RD; + const IntRegIndex rn = (IntRegIndex)(uint32_t)RN; + switch (OPCODE) { + ''' + decode_block += instCode(0x0, "and") + decode_block += instCode(0x1, "eor") + decode_block += adrCode(0x2, "sub", add="(IntRegIndex)0") + decode_block += instCode(0x3, "rsb") + decode_block += adrCode(0x4, "add", add="(IntRegIndex)1") + decode_block += instCode(0x5, "adc") + decode_block += instCode(0x6, "sbc") + decode_block += instCode(0x7, "rsc") + decode_block += instCode(0x8, "tst", useDest = False) + decode_block += instCode(0x9, "teq", useDest = False) + decode_block += instCode(0xa, "cmp", useDest = False) + decode_block += instCode(0xb, "cmn", useDest = False) + decode_block += instCode(0xc, "orr") + decode_block += instCode(0xd, "mov", useOp1 = False) + decode_block += instCode(0xe, "bic") + decode_block += instCode(0xf, "mvn", useOp1 = False) + decode_block += ''' + default: + return new Unknown(machInst); + } + } + ''' +}}; + +def format ArmSatAddSub() {{ + decode_block = ''' + { + IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + switch (OPCODE) { + case 0x8: + return new QaddRegCc(machInst, rd, rm, rn, 0, LSL); + case 0x9: + return new QsubRegCc(machInst, rd, rm, rn, 0, LSL); + case 0xa: + return new QdaddRegCc(machInst, rd, rm, rn, 0, LSL); + case 0xb: + return new QdsubRegCc(machInst, rd, rm, rn, 0, LSL); + default: + return new Unknown(machInst); + } + } + ''' +}}; + +def format Thumb32DataProcReg() {{ + decode_block = ''' + { + const uint32_t op1 = bits(machInst, 23, 20); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const uint32_t op2 = bits(machInst, 7, 4); + if (bits(machInst, 15, 12) != 0xf) { + return new Unknown(machInst); + } + if (bits(op1, 3) != 1) { + if (op2 == 0) { + IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + switch (bits(op1, 2, 0)) { + case 0x0: + return new MovRegReg(machInst, rd, + INTREG_ZERO, rn, rm, LSL); + case 0x1: + return new MovRegRegCc(machInst, rd, + INTREG_ZERO, rn, rm, LSL); + case 0x2: + return new MovRegReg(machInst, rd, + INTREG_ZERO, rn, rm, LSR); + case 0x3: + return new MovRegRegCc(machInst, rd, + INTREG_ZERO, rn, rm, LSR); + case 0x4: + return new MovRegReg(machInst, rd, + INTREG_ZERO, rn, rm, ASR); + case 0x5: + return new MovRegRegCc(machInst, rd, + INTREG_ZERO, rn, rm, ASR); + case 0x6: + return new MovRegReg(machInst, rd, + INTREG_ZERO, rn, rm, ROR); + case 0x7: + return new MovRegRegCc(machInst, rd, + INTREG_ZERO, rn, rm, ROR); + } + } else if (bits(op2, 3) == 0) { + return new Unknown(machInst); + } else { + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const uint32_t rotation = + (uint32_t)bits(machInst, 5, 4) << 3; + switch (bits(op1, 2, 0)) { + case 0x0: + if (rn == 0xf) { + return new Sxth(machInst, rd, rotation, rm); + } else { + return new Sxtah(machInst, rd, rn, rm, rotation); + } + case 0x1: + if (rn == 0xf) { + return new Uxth(machInst, rd, rotation, rm); + } else { + return new Uxtah(machInst, rd, rn, rm, rotation); + } + case 0x2: + if (rn == 0xf) { + return new Sxtb16(machInst, rd, rotation, rm); + } else { + return new Sxtab16(machInst, rd, rn, rm, rotation); + } + case 0x3: + if (rn == 0xf) { + return new Uxtb16(machInst, rd, rotation, rm); + } else { + return new Uxtab16(machInst, rd, rn, rm, rotation); + } + case 0x4: + if (rn == 0xf) { + return new Sxtb(machInst, rd, rotation, rm); + } else { + return new Sxtab(machInst, rd, rn, rm, rotation); + } + case 0x5: + if (rn == 0xf) { + return new Uxtb(machInst, rd, rotation, rm); + } else { + return new Uxtab(machInst, rd, rn, rm, rotation); + } + default: + return new Unknown(machInst); + } + } + } else { + if (bits(op2, 3) == 0) { + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + if (bits(op2, 2) == 0x0) { + const uint32_t op1 = bits(machInst, 22, 20); + const uint32_t op2 = bits(machInst, 5, 4); + switch (op2) { + case 0x0: + switch (op1) { + case 0x1: + return new Sadd16RegCc(machInst, rd, + rn, rm, 0, LSL); + case 0x2: + return new SasxRegCc(machInst, rd, + rn, rm, 0, LSL); + case 0x6: + return new SsaxRegCc(machInst, rd, + rn, rm, 0, LSL); + case 0x5: + return new Ssub16RegCc(machInst, rd, + rn, rm, 0, LSL); + case 0x0: + return new Sadd8RegCc(machInst, rd, + rn, rm, 0, LSL); + case 0x4: + return new Ssub8RegCc(machInst, rd, + rn, rm, 0, LSL); + } + break; + case 0x1: + switch (op1) { + case 0x1: + return new Qadd16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new QasxReg(machInst, rd, rn, rm, 0, LSL); + case 0x6: + return new QsaxReg(machInst, rd, rn, rm, 0, LSL); + case 0x5: + return new Qsub16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x0: + return new Qadd8Reg(machInst, rd, rn, rm, 0, LSL); + case 0x4: + return new Qsub8Reg(machInst, rd, rn, rm, 0, LSL); + } + break; + case 0x2: + switch (op1) { + case 0x1: + return new Shadd16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new ShasxReg(machInst, rd, rn, rm, 0, LSL); + case 0x6: + return new ShsaxReg(machInst, rd, rn, rm, 0, LSL); + case 0x5: + return new Shsub16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x0: + return new Shadd8Reg(machInst, rd, rn, rm, 0, LSL); + case 0x4: + return new Shsub8Reg(machInst, rd, rn, rm, 0, LSL); + } + break; + } + } else { + const uint32_t op1 = bits(machInst, 22, 20); + const uint32_t op2 = bits(machInst, 5, 4); + switch (op2) { + case 0x0: + switch (op1) { + case 0x1: + return new Uadd16RegCc(machInst, rd, + rn, rm, 0, LSL); + case 0x2: + return new UasxRegCc(machInst, rd, + rn, rm, 0, LSL); + case 0x6: + return new UsaxRegCc(machInst, rd, + rn, rm, 0, LSL); + case 0x5: + return new Usub16RegCc(machInst, rd, + rn, rm, 0, LSL); + case 0x0: + return new Uadd8RegCc(machInst, rd, + rn, rm, 0, LSL); + case 0x4: + return new Usub8RegCc(machInst, rd, + rn, rm, 0, LSL); + } + break; + case 0x1: + switch (op1) { + case 0x1: + return new Uqadd16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new UqasxReg(machInst, rd, rn, rm, 0, LSL); + case 0x6: + return new UqsaxReg(machInst, rd, rn, rm, 0, LSL); + case 0x5: + return new Uqsub16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x0: + return new Uqadd8Reg(machInst, rd, rn, rm, 0, LSL); + case 0x4: + return new Uqsub8Reg(machInst, rd, rn, rm, 0, LSL); + } + break; + case 0x2: + switch (op1) { + case 0x1: + return new Uhadd16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new UhasxReg(machInst, rd, rn, rm, 0, LSL); + case 0x6: + return new UhsaxReg(machInst, rd, rn, rm, 0, LSL); + case 0x5: + return new Uhsub16Reg(machInst, rd, rn, rm, 0, LSL); + case 0x0: + return new Uhadd8Reg(machInst, rd, rn, rm, 0, LSL); + case 0x4: + return new Uhsub8Reg(machInst, rd, rn, rm, 0, LSL); + } + break; + } + } + } else if (bits(op1, 3, 2) == 0x2 && bits(op2, 3, 2) == 0x2) { + const uint32_t op1 = bits(machInst, 21, 20); + const uint32_t op2 = bits(machInst, 5, 4); + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + switch (op1) { + case 0x0: + switch (op2) { + case 0x0: + return new QaddRegCc(machInst, rd, + rm, rn, 0, LSL); + case 0x1: + return new QdaddRegCc(machInst, rd, + rm, rn, 0, LSL); + case 0x2: + return new QsubRegCc(machInst, rd, + rm, rn, 0, LSL); + case 0x3: + return new QdsubRegCc(machInst, rd, + rm, rn, 0, LSL); + } + break; + case 0x1: + switch (op2) { + case 0x0: + return new Rev(machInst, rd, rn); + case 0x1: + return new Rev16(machInst, rd, rn); + case 0x2: + return new Rbit(machInst, rd, rm); + case 0x3: + return new Revsh(machInst, rd, rn); + } + break; + case 0x2: + if (op2 == 0) { + return new Sel(machInst, rd, rn, rm); + } + break; + case 0x3: + if (op2 == 0) { + return new Clz(machInst, rd, rm); + } + } + } + return new Unknown(machInst); + } + } + ''' +}}; + +def format Thumb16ShiftAddSubMoveCmp() {{ + decode_block = ''' + { + const uint32_t imm5 = bits(machInst, 10, 6); + const uint32_t imm3 = bits(machInst, 8, 6); + const uint32_t imm8 = bits(machInst, 7, 0); + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 2, 0); + const IntRegIndex rd8 = (IntRegIndex)(uint32_t)bits(machInst, 10, 8); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 5, 3); + const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 8, 6); + switch (bits(machInst, 13, 11)) { + case 0x0: // lsl + if (machInst.itstateMask) { + return new MovReg(machInst, rd, INTREG_ZERO, rn, imm5, LSL); + } else { + return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSL); + } + case 0x1: // lsr + if (machInst.itstateMask) { + return new MovReg(machInst, rd, INTREG_ZERO, rn, imm5, LSR); + } else { + return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSR); + } + case 0x2: // asr + if (machInst.itstateMask) { + return new MovReg(machInst, rd, INTREG_ZERO, rn, imm5, ASR); + } else { + return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, ASR); + } + case 0x3: + switch (bits(machInst, 10, 9)) { + case 0x0: + if (machInst.itstateMask) { + return new AddReg(machInst, rd, rn, rm, 0, LSL); + } else { + return new AddRegCc(machInst, rd, rn, rm, 0, LSL); + } + case 0x1: + if (machInst.itstateMask) { + return new SubReg(machInst, rd, rn, rm, 0, LSL); + } else { + return new SubRegCc(machInst, rd, rn, rm, 0, LSL); + } + case 0x2: + if (machInst.itstateMask) { + return new AddImm(machInst, rd, rn, imm3, true); + } else { + return new AddImmCc(machInst, rd, rn, imm3, true); + } + case 0x3: + if (machInst.itstateMask) { + return new SubImm(machInst, rd, rn, imm3, true); + } else { + return new SubImmCc(machInst, rd, rn, imm3, true); + } + } + case 0x4: + if (machInst.itstateMask) { + return new MovImm(machInst, rd8, INTREG_ZERO, imm8, false); + } else { + return new MovImmCc(machInst, rd8, INTREG_ZERO, imm8, false); + } + case 0x5: + return new CmpImmCc(machInst, INTREG_ZERO, rd8, imm8, true); + case 0x6: + if (machInst.itstateMask) { + return new AddImm(machInst, rd8, rd8, imm8, true); + } else { + return new AddImmCc(machInst, rd8, rd8, imm8, true); + } + case 0x7: + if (machInst.itstateMask) { + return new SubImm(machInst, rd8, rd8, imm8, true); + } else { + return new SubImmCc(machInst, rd8, rd8, imm8, true); + } + } + } + ''' +}}; + +def format Thumb16DataProcessing() {{ + decode_block = ''' + { + const IntRegIndex rdn = (IntRegIndex)(uint32_t)bits(machInst, 2, 0); + const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 5, 3); + switch (bits(machInst, 9, 6)) { + case 0x0: + if (machInst.itstateMask) { + return new AndReg(machInst, rdn, rdn, rm, 0, LSL); + } else { + return new AndRegCc(machInst, rdn, rdn, rm, 0, LSL); + } + case 0x1: + if (machInst.itstateMask) { + return new EorReg(machInst, rdn, rdn, rm, 0, LSL); + } else { + return new EorRegCc(machInst, rdn, rdn, rm, 0, LSL); + } + case 0x2: //lsl + if (machInst.itstateMask) { + return new MovRegReg(machInst, rdn, + INTREG_ZERO, rdn, rm, LSL); + } else { + return new MovRegRegCc(machInst, rdn, + INTREG_ZERO, rdn, rm, LSL); + } + case 0x3: //lsr + if (machInst.itstateMask) { + return new MovRegReg(machInst, rdn, + INTREG_ZERO, rdn, rm, LSR); + } else { + return new MovRegRegCc(machInst, rdn, + INTREG_ZERO, rdn, rm, LSR); + } + case 0x4: //asr + if (machInst.itstateMask) { + return new MovRegReg(machInst, rdn, + INTREG_ZERO, rdn, rm, ASR); + } else { + return new MovRegRegCc(machInst, rdn, + INTREG_ZERO, rdn, rm, ASR); + } + case 0x5: + if (machInst.itstateMask) { + return new AdcReg(machInst, rdn, rdn, rm, 0, LSL); + } else { + return new AdcRegCc(machInst, rdn, rdn, rm, 0, LSL); + } + case 0x6: + if (machInst.itstateMask) { + return new SbcReg(machInst, rdn, rdn, rm, 0, LSL); + } else { + return new SbcRegCc(machInst, rdn, rdn, rm, 0, LSL); + } + case 0x7: // ror + if (machInst.itstateMask) { + return new MovRegReg(machInst, rdn, + INTREG_ZERO, rdn, rm, ROR); + } else { + return new MovRegRegCc(machInst, rdn, + INTREG_ZERO, rdn, rm, ROR); + } + case 0x8: + return new TstRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL); + case 0x9: + if (machInst.itstateMask) { + return new RsbImm(machInst, rdn, rm, 0, true); + } else { + return new RsbImmCc(machInst, rdn, rm, 0, true); + } + case 0xa: + return new CmpRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL); + case 0xb: + return new CmnRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL); + case 0xc: + if (machInst.itstateMask) { + return new OrrReg(machInst, rdn, rdn, rm, 0, LSL); + } else { + return new OrrRegCc(machInst, rdn, rdn, rm, 0, LSL); + } + case 0xd: + if (machInst.itstateMask) { + return new Mul(machInst, rdn, rm, rdn); + } else { + return new MulCc(machInst, rdn, rm, rdn); + } + case 0xe: + if (machInst.itstateMask) { + return new BicReg(machInst, rdn, rdn, rm, 0, LSL); + } else { + return new BicRegCc(machInst, rdn, rdn, rm, 0, LSL); + } + case 0xf: + if (machInst.itstateMask) { + return new MvnReg(machInst, rdn, INTREG_ZERO, rm, 0, LSL); + } else { + return new MvnRegCc(machInst, rdn, INTREG_ZERO, rm, 0, LSL); + } + } + } + ''' +}}; + +def format Thumb16SpecDataAndBx() {{ + decode_block = ''' + { + const IntRegIndex rdn = + (IntRegIndex)(uint32_t)(bits(machInst, 2, 0) | + (bits(machInst, 7) << 3)); + const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 6, 3); + switch (bits(machInst, 9, 8)) { + case 0x0: + return new AddReg(machInst, rdn, rdn, rm, 0, LSL); + case 0x1: + return new CmpRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL); + case 0x2: + return new MovReg(machInst, rdn, INTREG_ZERO, rm, 0, LSL); + case 0x3: + if (bits(machInst, 7) == 0) { + return new BxReg(machInst, + (IntRegIndex)(uint32_t)bits(machInst, 6, 3), + COND_UC); + } else { + return new BlxReg(machInst, + (IntRegIndex)(uint32_t)bits(machInst, 6, 3), + COND_UC); + } + } + } + ''' +}}; + +def format Thumb16Adr() {{ + decode_block = ''' + { + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 10, 8); + const uint32_t imm8 = bits(machInst, 7, 0) << 2; + return new AdrImm(machInst, rd, (IntRegIndex)1, imm8, false); + } + ''' +}}; + +def format Thumb16AddSp() {{ + decode_block = ''' + { + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 10, 8); + const uint32_t imm8 = bits(machInst, 7, 0) << 2; + return new AddImm(machInst, rd, INTREG_SP, imm8, true); + } + ''' +}}; + +def format ArmMisc() {{ + decode_block = ''' + { + const uint32_t unrotated = bits(machInst, 7, 0); + const uint32_t rotation = (bits(machInst, 11, 8) << 1); + const uint32_t imm = rotate_imm(unrotated, rotation); + const uint8_t byteMask = bits(machInst, 19, 16); + switch (OPCODE) { + case 0x8: + return new MovImm(machInst, (IntRegIndex)(uint32_t)RD, + (IntRegIndex)INTREG_ZERO, + bits(machInst, 11, 0) | (bits(machInst, 19, 16) << 12), + false); + case 0x9: + if (RN == 0) { + switch (IMM) { + case 0x0: + return new NopInst(machInst); +#if FULL_SYSTEM + case 0x1: + return new YieldInst(machInst); + case 0x2: + return new WfeInst(machInst); + case 0x3: + return new WfiInst(machInst); + case 0x4: + return new SevInst(machInst); +#endif + default: + return new Unknown(machInst); + } + } else { + return new MsrCpsrImm(machInst, imm, byteMask); + } + case 0xa: + { + const uint32_t timm = (bits(machInst, 19, 16) << 12) | + bits(machInst, 11, 0); + return new MovtImm(machInst, (IntRegIndex)(uint32_t)RD, + (IntRegIndex)(uint32_t)RD, timm, true); + } + case 0xb: + return new MsrSpsrImm(machInst, imm, byteMask); + default: + return new Unknown(machInst); + } + } + ''' +}}; + +def format Thumb16Misc() {{ + decode_block = ''' + { + switch (bits(machInst, 11, 8)) { + case 0x0: + if (bits(machInst, 7)) { + return new SubImm(machInst, INTREG_SP, INTREG_SP, + bits(machInst, 6, 0) << 2, true); + } else { + return new AddImm(machInst, INTREG_SP, INTREG_SP, + bits(machInst, 6, 0) << 2, true); + } + case 0x2: + { + const IntRegIndex rd = + (IntRegIndex)(uint32_t)bits(machInst, 2, 0); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 5, 3); + switch (bits(machInst, 7, 6)) { + case 0x0: + return new Sxth(machInst, rd, 0, rm); + case 0x1: + return new Sxtb(machInst, rd, 0, rm); + case 0x2: + return new Uxth(machInst, rd, 0, rm); + case 0x3: + return new Uxtb(machInst, rd, 0, rm); + } + } + case 0x1: + case 0x3: + return new Cbz(machInst, + (bits(machInst, 9) << 6) | + (bits(machInst, 7, 3) << 1), + (IntRegIndex)(uint32_t)bits(machInst, 2, 0)); + case 0x4: + case 0x5: + { + const uint32_t m = bits(machInst, 8); + const uint32_t regList = bits(machInst, 7, 0) | (m << 14); + return new LdmStm(machInst, INTREG_SP, false, false, false, + true, false, regList); + } + case 0x6: + { + const uint32_t opBits = bits(machInst, 7, 5); + if (opBits == 2) { + return new Setend(machInst, bits(machInst, 3)); + } else if (opBits == 3) { + const bool enable = (bits(machInst, 4) == 0); + const uint32_t mods = (bits(machInst, 2, 0) << 5) | + ((enable ? 1 : 0) << 9); + return new Cps(machInst, mods); + } + } + case 0xa: + { + IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 2, 0); + IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 5, 3); + switch (bits(machInst, 7, 6)) { + case 0x0: + return new Rev(machInst, rd, rm); + case 0x1: + return new Rev16(machInst, rd, rm); + case 0x3: + return new Revsh(machInst, rd, rm); + default: + break; + } + } + break; + case 0x9: + case 0xb: + return new Cbnz(machInst, + (bits(machInst, 9) << 6) | + (bits(machInst, 7, 3) << 1), + (IntRegIndex)(uint32_t)bits(machInst, 2, 0)); + case 0xc: + case 0xd: + { + const uint32_t p = bits(machInst, 8); + const uint32_t regList = bits(machInst, 7, 0) | (p << 15); + return new LdmStm(machInst, INTREG_SP, true, true, false, + true, true, regList); + } + case 0xe: + return new BkptInst(machInst); + case 0xf: + if (bits(machInst, 3, 0) != 0) + return new ItInst(machInst); + switch (bits(machInst, 7, 4)) { + case 0x0: + return new NopInst(machInst); + case 0x1: + return new YieldInst(machInst); + case 0x2: + return new WfeInst(machInst); + case 0x3: + return new WfiInst(machInst); + case 0x4: + return new SevInst(machInst); + default: + return new WarnUnimplemented("unallocated_hint", machInst); + } + default: + break; + } + return new Unknown(machInst); + } + ''' +}}; + +def format Thumb32DataProcModImm() {{ + + def decInst(mnem, dest="rd", op1="rn"): + return ''' + if (s) { + return new %(mnem)sImmCc(machInst, %(dest)s, + %(op1)s, imm, rotC); + } else { + return new %(mnem)sImm(machInst, %(dest)s, + %(op1)s, imm, rotC); + } + ''' % {"mnem" : mnem, "dest" : dest, "op1" : op1} + + decode_block = ''' + { + const uint32_t op = bits(machInst, 24, 21); + const bool s = (bits(machInst, 20) == 1); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + const uint32_t ctrlImm = bits(machInst.instBits, 26) << 3 | + bits(machInst, 14, 12); + const bool rotC = ctrlImm > 3; + const uint32_t dataImm = bits(machInst, 7, 0); + const uint32_t imm = modified_imm(ctrlImm, dataImm); + switch (op) { + case 0x0: + if (rd == INTREG_PC) { + %(tst)s + } else { + %(and)s + } + case 0x1: + %(bic)s + case 0x2: + if (rn == INTREG_PC) { + %(mov)s + } else { + %(orr)s + } + case 0x3: + if (rn == INTREG_PC) { + %(mvn)s + } else { + %(orn)s + } + case 0x4: + if (rd == INTREG_PC) { + %(teq)s + } else { + %(eor)s + } + case 0x8: + if (rd == INTREG_PC) { + %(cmn)s + } else { + %(add)s + } + case 0xa: + %(adc)s + case 0xb: + %(sbc)s + case 0xd: + if (rd == INTREG_PC) { + %(cmp)s + } else { + %(sub)s + } + case 0xe: + %(rsb)s + default: + return new Unknown(machInst); + } + } + ''' % { + "tst" : decInst("Tst", "INTREG_ZERO"), + "and" : decInst("And"), + "bic" : decInst("Bic"), + "mov" : decInst("Mov", op1="INTREG_ZERO"), + "orr" : decInst("Orr"), + "mvn" : decInst("Mvn", op1="INTREG_ZERO"), + "orn" : decInst("Orn"), + "teq" : decInst("Teq", dest="INTREG_ZERO"), + "eor" : decInst("Eor"), + "cmn" : decInst("Cmn", dest="INTREG_ZERO"), + "add" : decInst("Add"), + "adc" : decInst("Adc"), + "sbc" : decInst("Sbc"), + "cmp" : decInst("Cmp", dest="INTREG_ZERO"), + "sub" : decInst("Sub"), + "rsb" : decInst("Rsb") + } +}}; + +def format Thumb32DataProcPlainBin() {{ + decode_block = ''' + { + const uint32_t op = bits(machInst, 24, 20); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + switch (op) { + case 0x0: + { + const uint32_t imm = bits(machInst, 7, 0) | + (bits(machInst, 14, 12) << 8) | + (bits(machInst, 26) << 11); + if (rn == 0xf) { + return new AdrImm(machInst, rd, (IntRegIndex)1, + imm, false); + } else { + return new AddImm(machInst, rd, rn, imm, true); + } + } + case 0x4: + { + const uint32_t imm = bits(machInst, 7, 0) | + (bits(machInst, 14, 12) << 8) | + (bits(machInst, 26) << 11) | + (bits(machInst, 19, 16) << 12); + return new MovImm(machInst, rd, INTREG_ZERO, imm, true); + } + case 0xa: + { + const uint32_t imm = bits(machInst, 7, 0) | + (bits(machInst, 14, 12) << 8) | + (bits(machInst, 26) << 11); + if (rn == 0xf) { + return new AdrImm(machInst, rd, (IntRegIndex)0, + imm, false); + } else { + return new SubImm(machInst, rd, rn, imm, true); + } + } + case 0xc: + { + const uint32_t imm = bits(machInst, 7, 0) | + (bits(machInst, 14, 12) << 8) | + (bits(machInst, 26) << 11) | + (bits(machInst, 19, 16) << 12); + return new MovtImm(machInst, rd, rd, imm, true); + } + case 0x12: + if (!(bits(machInst, 14, 12) || bits(machInst, 7, 6))) { + const uint32_t satImm = bits(machInst, 4, 0); + return new Ssat16(machInst, rd, satImm + 1, rn); + } + // Fall through on purpose... + case 0x10: + { + const uint32_t satImm = bits(machInst, 4, 0); + const uint32_t imm = bits(machInst, 7, 6) | + (bits(machInst, 14, 12) << 2); + const ArmShiftType type = + (ArmShiftType)(uint32_t)bits(machInst, 21, 20); + return new Ssat(machInst, rd, satImm + 1, rn, imm, type); + } + case 0x14: + { + const uint32_t lsb = bits(machInst, 7, 6) | + (bits(machInst, 14, 12) << 2); + const uint32_t msb = lsb + bits(machInst, 4, 0); + return new Sbfx(machInst, rd, rn, lsb, msb); + } + case 0x16: + { + const uint32_t lsb = bits(machInst, 7, 6) | + (bits(machInst, 14, 12) << 2); + const uint32_t msb = bits(machInst, 4, 0); + if (rn == 0xf) { + return new Bfc(machInst, rd, rd, lsb, msb); + } else { + return new Bfi(machInst, rd, rn, lsb, msb); + } + } + case 0x1a: + if (!(bits(machInst, 14, 12) || bits(machInst, 7, 6))) { + const uint32_t satImm = bits(machInst, 4, 0); + return new Usat16(machInst, rd, satImm, rn); + } + // Fall through on purpose... + case 0x18: + { + const uint32_t satImm = bits(machInst, 4, 0); + const uint32_t imm = bits(machInst, 7, 6) | + (bits(machInst, 14, 12) << 2); + const ArmShiftType type = + (ArmShiftType)(uint32_t)bits(machInst, 21, 20); + return new Usat(machInst, rd, satImm, rn, imm, type); + } + case 0x1c: + { + const uint32_t lsb = bits(machInst, 7, 6) | + (bits(machInst, 14, 12) << 2); + const uint32_t msb = lsb + bits(machInst, 4, 0); + return new Ubfx(machInst, rd, rn, lsb, msb); + } + default: + return new Unknown(machInst); + } + } + ''' +}}; + +def format Thumb32DataProcShiftReg() {{ + + def decInst(mnem, dest="rd", op1="rn"): + return ''' + if (s) { + return new %(mnem)sRegCc(machInst, %(dest)s, + %(op1)s, rm, amt, type); + } else { + return new %(mnem)sReg(machInst, %(dest)s, + %(op1)s, rm, amt, type); + } + ''' % {"mnem" : mnem, "dest" : dest, "op1" : op1} + + decode_block = ''' + { + const uint32_t op = bits(machInst, 24, 21); + const bool s = (bits(machInst, 20) == 1); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const uint32_t amt = (bits(machInst, 14, 12) << 2) | + bits(machInst, 7, 6); + const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 5, 4); + switch (op) { + case 0x0: + if (rd == INTREG_PC) { + %(tst)s + } else { + %(and)s + } + case 0x1: + %(bic)s + case 0x2: + if (rn == INTREG_PC) { + %(mov)s + } else { + %(orr)s + } + case 0x3: + if (rn == INTREG_PC) { + %(mvn)s + } else { + %(orn)s + } + case 0x4: + if (rd == INTREG_PC) { + %(teq)s + } else { + %(eor)s + } + case 0x6: + if (type) { + return new PkhtbReg(machInst, rd, rn, rm, amt, type); + } else { + return new PkhbtReg(machInst, rd, rn, rm, amt, type); + } + case 0x8: + if (rd == INTREG_PC) { + %(cmn)s + } else { + %(add)s + } + case 0xa: + %(adc)s + case 0xb: + %(sbc)s + case 0xd: + if (rd == INTREG_PC) { + %(cmp)s + } else { + %(sub)s + } + case 0xe: + %(rsb)s + default: + return new Unknown(machInst); + } + } + ''' % { + "tst" : decInst("Tst", "INTREG_ZERO"), + "and" : decInst("And"), + "bic" : decInst("Bic"), + "mov" : decInst("Mov", op1="INTREG_ZERO"), + "orr" : decInst("Orr"), + "mvn" : decInst("Mvn", op1="INTREG_ZERO"), + "orn" : decInst("Orn"), + "teq" : decInst("Teq", "INTREG_ZERO"), + "eor" : decInst("Eor"), + "cmn" : decInst("Cmn", "INTREG_ZERO"), + "add" : decInst("Add"), + "adc" : decInst("Adc"), + "sbc" : decInst("Sbc"), + "cmp" : decInst("Cmp", "INTREG_ZERO"), + "sub" : decInst("Sub"), + "rsb" : decInst("Rsb") + } +}}; diff -r 84bd4089958b src/arch/arm/isa/formats/formats.isa --- a/src/arch/arm/isa/formats/formats.isa Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/isa/formats/formats.isa Wed May 26 18:10:45 2010 -0500 @@ -1,5 +1,17 @@ // -*- mode:c++ -*- +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// // Copyright (c) 2007-2008 The Florida State University // All rights reserved. // @@ -35,9 +47,6 @@ //Include support for predicated instructions ##include "pred.isa" -//Include utility functions -##include "util.isa" - //Include the float formats ##include "fp.isa" @@ -50,8 +59,23 @@ //Include the branch format ##include "branch.isa" +//Miscellaneous instructions that don't fit elsewhere +##include "misc.isa" + //Include the unimplemented format ##include "unimp.isa" //Include the unknown format ##include "unknown.isa" + +//Include the breakpoint format +##include "breakpoint.isa" + +//Include the formats for data processing instructions +##include "data.isa" + +//Include the formats for multiply instructions +##include "mult.isa" + +//Unconditional instructions +##include "uncond.isa" diff -r 84bd4089958b src/arch/arm/isa/formats/fp.isa --- a/src/arch/arm/isa/formats/fp.isa Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/isa/formats/fp.isa Wed May 26 18:10:45 2010 -0500 @@ -1,5 +1,17 @@ // -*- mode:c++ -*- +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// // Copyright (c) 2007-2008 The Florida State University // All rights reserved. // @@ -33,107 +45,1434 @@ // Floating Point operate instructions // -def template FPAExecute {{ - Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const - { - Fault fault = NoFault; +let {{ + header_output = ''' + StaticInstPtr + decodeNeonMem(ExtMachInst machInst); - %(fp_enable_check)s; + StaticInstPtr + decodeNeonData(ExtMachInst machInst); + ''' - %(op_decl)s; - %(op_rd)s; + decoder_output = ''' + StaticInstPtr + decodeNeonMem(ExtMachInst machInst) + { + const uint32_t b = bits(machInst, 11, 8); + const bool a = bits(machInst, 23); + const bool l = bits(machInst, 21); - if (%(predicate_test)s) { - %(code)s; - if (fault == NoFault) { - %(op_wb)s; + if (l) { + // Load instructions. + if (a) { + switch (b) { + } + // Single. + } else { + switch (b) { + } + // Multiple. + } + } else { + // Store instructions. + if (a) { + switch (b) { + } + // Single. + } else { + switch (b) { + } + // Multiple. + } + } + return new WarnUnimplemented("neon memory", machInst); + } + ''' + + decoder_output += ''' + static StaticInstPtr + decodeNeonThreeRegistersSameLength(ExtMachInst machInst) + { + const bool u = THUMB ? bits(machInst, 28) : bits(machInst, 24); + const uint32_t a = bits(machInst, 11, 8); + const bool b = bits(machInst, 4); + const uint32_t c = bits(machInst, 21, 20); + switch (a) { + case 0x0: + if (b) { + if (bits(machInst, 9) == 0) { + return new WarnUnimplemented("vhadd", machInst); + } else { + return new WarnUnimplemented("vhsub", machInst); + } + } else { + return new WarnUnimplemented("vqadd", machInst); + } + case 0x1: + if (!b) { + return new WarnUnimplemented("vrhadd", machInst); + } else { + if (u) { + switch (c) { + case 0: + return new WarnUnimplemented("veor", machInst); + case 1: + return new WarnUnimplemented("vbsl", machInst); + case 2: + return new WarnUnimplemented("vbit", machInst); + case 3: + return new WarnUnimplemented("vbif", machInst); + } + } else { + switch (c) { + case 0: + return new WarnUnimplemented("vand (reg)", machInst); + case 1: + return new WarnUnimplemented("vbic (reg)", machInst); + case 2: + { + const IntRegIndex n = (IntRegIndex)( + (uint32_t)bits(machInst, 19, 16) | + (uint32_t)(bits(machInst, 7) << 4)); + const IntRegIndex m = (IntRegIndex)( + (uint32_t)bits(machInst, 3, 0) | + (uint32_t)(bits(machInst, 5) << 4)); + if (n == m) { + return new WarnUnimplemented("vmov (reg)", + machInst); + } else { + return new WarnUnimplemented("vorr (reg)", + machInst); + } + } + case 3: + return new WarnUnimplemented("vorn (reg)", machInst); } } + } + case 0x2: + if (b) { + return new WarnUnimplemented("vqsub", machInst); + } else { + if (bits(machInst, 9) == 0) { + return new WarnUnimplemented("vhadd", machInst); + } else { + return new WarnUnimplemented("vhsub", machInst); + } + } + case 0x3: + if (b) { + return new WarnUnimplemented("vcge (reg)", machInst); + } else { + return new WarnUnimplemented("vcgt (reg)", machInst); + } + case 0x4: + if (b) { + return new WarnUnimplemented("vqshl (reg)", machInst); + } else { + return new WarnUnimplemented("vshl (reg)", machInst); + } + case 0x5: + if (b) { + return new WarnUnimplemented("vqrshl", machInst); + } else { + return new WarnUnimplemented("vrshl", machInst); + } + case 0x6: + if (b) { + return new WarnUnimplemented("vmin (int)", machInst); + } else { + return new WarnUnimplemented("vmax (int)", machInst); + } + case 0x7: + if (b) { + return new WarnUnimplemented("vaba", machInst); + } else { + if (bits(machInst, 23) == 1) { + if (bits(machInst, 6) == 1) { + return new Unknown(machInst); + } else { + return new WarnUnimplemented("vabdl (int)", machInst); + } + } else { + return new WarnUnimplemented("vabd (int)", machInst); + } + } + case 0x8: + if (b) { + if (u) { + return new WarnUnimplemented("vceq (reg)", machInst); + } else { + return new WarnUnimplemented("vtst", machInst); + } + } else { + if (u) { + return new WarnUnimplemented("vsub (int)", machInst); + } else { + return new WarnUnimplemented("vadd (int)", machInst); + } + } + case 0x9: + if (b) { + if (u) { + return new WarnUnimplemented("vmul (poly)", machInst); + } else { + return new WarnUnimplemented("vmul (int)", machInst); + } + } else { + if (u) { + return new WarnUnimplemented("vmls (int)", machInst); + } else { + return new WarnUnimplemented("vmla (int)", machInst); + } + } + case 0xa: + if (b) { + return new WarnUnimplemented("vpmin (int)", machInst); + } else { + return new WarnUnimplemented("vpmax (int)", machInst); + } + case 0xb: + if (b) { + if (u) { + return new Unknown(machInst); + } else { + return new WarnUnimplemented("vpadd (int)", machInst); + } + } else { + if (u) { + return new WarnUnimplemented("vqrdmulh", machInst); + } else { + return new WarnUnimplemented("vqdmulh", machInst); + } + } + case 0xc: + return new Unknown(machInst); + case 0xd: + if (b) { + if (u) { + if (bits(c, 1) == 0) { + return new WarnUnimplemented("vmul (fp)", machInst); + } else { + return new Unknown(machInst); + } + } else { + if (bits(c, 1) == 0) { + return new WarnUnimplemented("vmla (fp)", machInst); + } else { + return new WarnUnimplemented("vmls (fp)", machInst); + } + } + } else { + if (u) { + if (bits(c, 1) == 0) { + return new WarnUnimplemented("vpadd (fp)", machInst); + } else { + return new WarnUnimplemented("vabd (fp)", machInst); + } + } else { + if (bits(c, 1) == 0) { + return new WarnUnimplemented("vadd (fp)", machInst); + } else { + return new WarnUnimplemented("vsub (fp)", machInst); + } + } + } + case 0xe: + if (b) { + if (u) { + if (bits(c, 1) == 0) { + return new WarnUnimplemented("vacge", machInst); + } else { + return new WarnUnimplemented("vacgt", machInst); + } + } else { + return new Unknown(machInst); + } + } else { + if (u) { + if (bits(c, 1) == 0) { + return new WarnUnimplemented("vcge (reg)", machInst); + } else { + return new WarnUnimplemented("vcgt (reg)", machInst); + } + } else { + if (bits(c, 1) == 0) { + return new WarnUnimplemented("vceq (reg)", machInst); + } else { + return new Unknown(machInst); + } + } + } + case 0xf: + if (b) { + if (u) { + return new Unknown(machInst); + } else { + if (bits(c, 1) == 0) { + return new WarnUnimplemented("vrecps", machInst); + } else { + return new WarnUnimplemented("vrsqrts", machInst); + } + } + } else { + if (u) { + if (bits(c, 1) == 0) { + return new WarnUnimplemented("vpmax (fp)", machInst); + } else { + return new WarnUnimplemented("vpmin (fp)", machInst); + } + } else { + if (bits(c, 1) == 0) { + return new WarnUnimplemented("vmax (fp)", machInst); + } else { + return new WarnUnimplemented("vmin (fp)", machInst); + } + } + } + } + return new Unknown(machInst); + } - return fault; + static StaticInstPtr + decodeNeonOneRegModImm(ExtMachInst machInst) + { + const bool op = bits(machInst, 5); + const uint32_t cmode = bits(machInst, 11, 8); + if (op) { + if (bits(cmode, 3) == 0) { + if (bits(cmode, 0) == 0) { + return new WarnUnimplemented("vmov (imm)", machInst); + } else { + return new WarnUnimplemented("vorr (imm)", machInst); + } + } else { + if (bits(cmode, 2) == 1) { + return new WarnUnimplemented("vmov (imm)", machInst); + } else { + if (bits(cmode, 0) == 0) { + return new WarnUnimplemented("vmov (imm)", machInst); + } else { + return new WarnUnimplemented("vorr (imm)", machInst); + } + } + } + } else { + if (bits(cmode, 3) == 0) { + if (bits(cmode, 0) == 0) { + return new WarnUnimplemented("vmvn (imm)", machInst); + } else { + return new WarnUnimplemented("vbic (imm)", machInst); + } + } else { + if (bits(cmode, 2) == 1) { + switch (bits(cmode, 1, 0)) { + case 0: + case 1: + return new WarnUnimplemented("vmvn (imm)", machInst); + case 2: + return new WarnUnimplemented("vmov (imm)", machInst); + case 3: + return new Unknown(machInst); + } + return new WarnUnimplemented("vmov (imm)", machInst); + } else { + if (bits(cmode, 0) == 0) { + return new WarnUnimplemented("vmvn (imm)", machInst); + } else { + return new WarnUnimplemented("vbic (imm)", machInst); + } + } + } } + return new Unknown(machInst); + } + + static StaticInstPtr + decodeNeonTwoRegAndShift(ExtMachInst machInst) + { + const uint32_t a = bits(machInst, 11, 8); + const bool u = THUMB ? bits(machInst, 28) : bits(machInst, 24); + const bool b = bits(machInst, 6); + const bool l = bits(machInst, 7); + + switch (a) { + case 0x0: + return new WarnUnimplemented("vshr", machInst); + case 0x1: + return new WarnUnimplemented("vsra", machInst); + case 0x2: + return new WarnUnimplemented("vrshr", machInst); + case 0x3: + return new WarnUnimplemented("vrsra", machInst); + case 0x4: + if (u) { + return new WarnUnimplemented("vsri", machInst); + } else { + return new Unknown(machInst); + } + case 0x5: + if (u) { + return new WarnUnimplemented("vsli", machInst); + } else { + return new WarnUnimplemented("vshl (imm)", machInst); + } + case 0x6: + case 0x7: + return new WarnUnimplemented("vqshl, vqshlu (imm)", machInst); + case 0x8: + if (l) { + return new Unknown(machInst); + } else if (u) { + if (b) { + return new WarnUnimplemented("vqrshrn, vqrshrun", machInst); + } else { + return new WarnUnimplemented("vqshrn, vqshrun", machInst); + } + } else { + if (b) { + return new WarnUnimplemented("vrshrn", machInst); + } else { + return new WarnUnimplemented("vshrn", machInst); + } + } + case 0x9: + if (l) { + return new Unknown(machInst); + } else if (b) { + return new WarnUnimplemented("vqrshrn, vqrshrun", machInst); + } else { + return new WarnUnimplemented("vqshrn, vqshrun", machInst); + } + case 0xa: + if (l || b) { + return new Unknown(machInst); + } else { + // If the shift amount is zero, it's vmovl. + return new WarnUnimplemented("vshll, vmovl", machInst); + } + case 0xe: + case 0xf: + if (l) { + return new Unknown(machInst); + } else if (a == 0xe) { + return new WarnUnimplemented("vcvt (fixed to fp)", machInst); + } else if (a == 0xf) { + return new WarnUnimplemented("vcvt (fp to fixed)", machInst); + } + } + return new Unknown(machInst); + } + + static StaticInstPtr + decodeNeonThreeRegDiffLengths(ExtMachInst machInst) + { + const bool u = THUMB ? bits(machInst, 28) : bits(machInst, 24); + const uint32_t a = bits(machInst, 11, 8); + + switch (a) { + case 0x0: + return new WarnUnimplemented("vaddl", machInst); + case 0x1: + return new WarnUnimplemented("vaddw", machInst); + case 0x2: + return new WarnUnimplemented("vsubl", machInst); + case 0x3: + return new WarnUnimplemented("vsubw", machInst); + case 0x4: + if (u) { + return new WarnUnimplemented("vraddhn", machInst); + } else { + return new WarnUnimplemented("vaddhn", machInst); + } + case 0x5: + return new WarnUnimplemented("vabal", machInst); + case 0x6: + if (u) { + return new WarnUnimplemented("vrsubhn", machInst); + } else { + return new WarnUnimplemented("vsubhn", machInst); + } + case 0x7: + if (bits(machInst, 23)) { + return new WarnUnimplemented("vabdl (int)", machInst); + } else { + return new WarnUnimplemented("vabd (int)", machInst); + } + case 0x8: + return new WarnUnimplemented("vmlal (int)", machInst); + case 0xa: + return new WarnUnimplemented("vmlsl (int)", machInst); + case 0x9: + if (bits(machInst, 23) == 0) { + if (bits(machInst, 4) == 0) { + if (u) { + return new WarnUnimplemented("vmls (int)", machInst); + } else { + return new WarnUnimplemented("vmla (int)", machInst); + } + } else { + if (u) { + return new WarnUnimplemented("vmul (poly)", machInst); + } else { + return new WarnUnimplemented("vmul (int)", machInst); + } + } + } else { + return new WarnUnimplemented("vqdmlal", machInst); + } + case 0xb: + if (!u) { + return new Unknown(machInst); + } else { + return new WarnUnimplemented("vqdmlsl", machInst); + } + case 0xc: + return new WarnUnimplemented("vmull (int)", machInst); + case 0xd: + if (!u) { + return new Unknown(machInst); + } else { + return new WarnUnimplemented("vqdmull", machInst); + } + case 0xe: + return new WarnUnimplemented("vmull (poly)", machInst); + } + return new Unknown(machInst); + } + + static StaticInstPtr + decodeNeonTwoRegScalar(ExtMachInst machInst) + { + const bool u = THUMB ? bits(machInst, 28) : bits(machInst, 24); + const uint32_t a = bits(machInst, 11, 8); + + switch (a) { + case 0x0: + return new WarnUnimplemented("vmla (int scalar)", machInst); + case 0x1: + return new WarnUnimplemented("vmla (fp scalar)", machInst); + case 0x4: + return new WarnUnimplemented("vmls (int scalar)", machInst); + case 0x5: + return new WarnUnimplemented("vmls (fp scalar)", machInst); + case 0x2: + return new WarnUnimplemented("vmlal (scalar)", machInst); + case 0x6: + return new WarnUnimplemented("vmlsl (scalar)", machInst); + case 0x3: + if (u) { + return new Unknown(machInst); + } else { + return new WarnUnimplemented("vqdmlal", machInst); + } + case 0x7: + if (u) { + return new Unknown(machInst); + } else { + return new WarnUnimplemented("vqdmlsl", machInst); + } + case 0x8: + return new WarnUnimplemented("vmul (int scalar)", machInst); + case 0x9: + return new WarnUnimplemented("vmul (fp scalar)", machInst); + case 0xa: + return new WarnUnimplemented("vmull (scalar)", machInst); + case 0xb: + if (u) { + return new Unknown(machInst); + } else { + return new WarnUnimplemented("vqdmull", machInst); + } + case 0xc: + return new WarnUnimplemented("vqdmulh", machInst); + case 0xd: + return new WarnUnimplemented("vqrdmulh", machInst); + } + return new Unknown(machInst); + } + + static StaticInstPtr + decodeNeonTwoRegMisc(ExtMachInst machInst) + { + const uint32_t a = bits(machInst, 17, 16); + const uint32_t b = bits(machInst, 10, 6); + switch (a) { + case 0x0: + switch (bits(b, 4, 1)) { + case 0x0: + return new WarnUnimplemented("vrev64", machInst); + case 0x1: + return new WarnUnimplemented("vrev32", machInst); + case 0x2: + return new WarnUnimplemented("vrev16", machInst); + case 0x4: + case 0x5: + return new WarnUnimplemented("vpaddl", machInst); + case 0x8: + return new WarnUnimplemented("vcls", machInst); + case 0x9: + return new WarnUnimplemented("vclz", machInst); + case 0xa: + return new WarnUnimplemented("vcnt", machInst); + case 0xb: + return new WarnUnimplemented("vmvn (reg)", machInst); + case 0xc: + case 0xd: + return new WarnUnimplemented("vpadal", machInst); + case 0xe: + return new WarnUnimplemented("vqabs", machInst); + case 0xf: + return new WarnUnimplemented("vqneg", machInst); + default: + return new Unknown(machInst); + } + case 0x1: + switch (bits(b, 3, 1)) { + case 0x0: + return new WarnUnimplemented("vcgt (imm #0)", machInst); + case 0x1: + return new WarnUnimplemented("vcge (imm #0)", machInst); + case 0x2: + return new WarnUnimplemented("vceq (imm #0)", machInst); + case 0x3: + return new WarnUnimplemented("vcle (imm #0)", machInst); + case 0x4: + return new WarnUnimplemented("vclt (imm #0)", machInst); + case 0x6: + return new WarnUnimplemented("vabs (imm #0)", machInst); + case 0x7: + return new WarnUnimplemented("vneg (imm #0)", machInst); + } + case 0x2: + switch (bits(b, 4, 1)) { + case 0x0: + return new WarnUnimplemented("vswp", machInst); + case 0x1: + return new WarnUnimplemented("vtrn", machInst); + case 0x2: + return new WarnUnimplemented("vuzp", machInst); + case 0x3: + return new WarnUnimplemented("vzip", machInst); + case 0x4: + if (b == 0x8) { + return new WarnUnimplemented("vmovn", machInst); + } else { + return new WarnUnimplemented("vqmovun", machInst); + } + case 0x5: + return new WarnUnimplemented("vqmovn", machInst); + case 0x6: + if (b == 0xc) { + return new WarnUnimplemented("vshll", machInst); + } else { + return new Unknown(machInst); + } + case 0xc: + case 0xe: + if (b == 0x18) { + return new WarnUnimplemented("vcvt (single to half)", + machInst); + } else if (b == 0x1c) { + return new WarnUnimplemented("vcvt (half to single)", + machInst); + } else { + return new Unknown(machInst); + } + default: + return new Unknown(machInst); + } + case 0x3: + if (bits(b, 4, 3) == 0x3) { + return new WarnUnimplemented("vcvt (fp and int)", machInst); + } else if ((b & 0x1a) == 0x10) { + return new WarnUnimplemented("vrecpe", machInst); + } else if ((b & 0x1a) == 0x12) { + return new WarnUnimplemented("vrsqrte", machInst); + } else { + return new Unknown(machInst); + } + } + return new Unknown(machInst); + } + + StaticInstPtr + decodeNeonData(ExtMachInst machInst) + { + const bool u = THUMB ? bits(machInst, 28) : bits(machInst, 24); + const uint32_t a = bits(machInst, 23, 19); + const uint32_t b = bits(machInst, 11, 8); + const uint32_t c = bits(machInst, 7, 4); + if (bits(a, 4) == 0) { + return decodeNeonThreeRegistersSameLength(machInst); + } else if ((c & 0x9) == 1) { + if ((a & 0x7) == 0) { + return decodeNeonOneRegModImm(machInst); + } else { + return decodeNeonTwoRegAndShift(machInst); + } + } else if ((c & 0x9) == 9) { + return decodeNeonTwoRegAndShift(machInst); + } else if ((c & 0x5) == 0) { + if (bits(a, 3, 2) != 0x3) { + return decodeNeonThreeRegDiffLengths(machInst); + } + } else if ((c & 0x5) == 4) { + if (bits(a, 3, 2) != 0x3) { + return decodeNeonTwoRegScalar(machInst); + } + } else if ((a & 0x16) == 0x16) { + if (!u) { + if (bits(c, 0) == 0) { + return new WarnUnimplemented("vext", machInst); + } + } else if (bits(b, 3) == 0 && bits(c, 0) == 0) { + return decodeNeonTwoRegMisc(machInst); + } else if (bits(b, 3, 2) == 0x2 && bits(c, 0) == 0) { + if (bits(machInst, 6) == 0) { + return new WarnUnimplemented("vtbl", machInst); + } else { + return new WarnUnimplemented("vtbx", machInst); + } + } else if (b == 0xc && (c & 0x9) == 0) { + return new WarnUnimplemented("vdup (scalar)", machInst); + } + } + return new Unknown(machInst); + } + ''' }}; -def template FloatDoubleDecode {{ +def format ThumbNeonMem() {{ + decode_block = ''' + return decodeNeonMem(machInst); + ''' +}}; + +def format ThumbNeonData() {{ + decode_block = ''' + return decodeNeonMem(machInst); + ''' +}}; + +let {{ + header_output = ''' + StaticInstPtr + decodeExtensionRegLoadStore(ExtMachInst machInst); + ''' + decoder_output = ''' + StaticInstPtr + decodeExtensionRegLoadStore(ExtMachInst machInst) { - 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"); + const uint32_t opcode = bits(machInst, 24, 20); + const uint32_t offset = bits(machInst, 7, 0); + const bool single = (bits(machInst, 8) == 0); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + RegIndex vd; + if (single) { + vd = (RegIndex)(uint32_t)((bits(machInst, 15, 12) << 1) | + bits(machInst, 22)); + } else { + vd = (RegIndex)(uint32_t)((bits(machInst, 15, 12) << 1) | + (bits(machInst, 22) << 5)); } - return i; + switch (bits(opcode, 4, 3)) { + case 0x0: + if (bits(opcode, 4, 1) == 0x2 && + !(machInst.thumb == 1 && bits(machInst, 28) == 1) && + !(machInst.thumb == 0 && machInst.condCode == 0xf)) { + if ((bits(machInst, 7, 4) & 0xd) != 1) { + break; + } + const IntRegIndex rt = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rt2 = + (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const bool op = bits(machInst, 20); + uint32_t vm; + if (single) { + vm = (bits(machInst, 3, 0) << 1) | bits(machInst, 5); + } else { + vm = (bits(machInst, 3, 0) << 1) | + (bits(machInst, 5) << 5); + } + if (op) { + return new Vmov2Core2Reg(machInst, rt, rt2, + (IntRegIndex)vm); + } else { + return new Vmov2Reg2Core(machInst, (IntRegIndex)vm, + rt, rt2); + } + } + break; + case 0x1: + { + if (offset == 0 || vd + offset > NumFloatArchRegs) { + break; + } + switch (bits(opcode, 1, 0)) { + case 0x0: + return new VLdmStm(machInst, rn, vd, single, + true, false, false, offset); + case 0x1: + return new VLdmStm(machInst, rn, vd, single, + true, false, true, offset); + case 0x2: + return new VLdmStm(machInst, rn, vd, single, + true, true, false, offset); + case 0x3: + // If rn == sp, then this is called vpop. + return new VLdmStm(machInst, rn, vd, single, + true, true, true, offset); + } + } + case 0x2: + if (bits(opcode, 1, 0) == 0x2) { + // If rn == sp, then this is called vpush. + return new VLdmStm(machInst, rn, vd, single, + false, true, false, offset); + } else if (bits(opcode, 1, 0) == 0x3) { + return new VLdmStm(machInst, rn, vd, single, + false, true, true, offset); + } + // Fall through on purpose + case 0x3: + const bool up = (bits(machInst, 23) == 1); + const uint32_t imm = bits(machInst, 7, 0) << 2; + RegIndex vd; + if (single) { + vd = (RegIndex)(uint32_t)((bits(machInst, 15, 12) << 1) | + (bits(machInst, 22))); + } else { + vd = (RegIndex)(uint32_t)((bits(machInst, 15, 12) << 1) | + (bits(machInst, 22) << 5)); + } + if (bits(opcode, 1, 0) == 0x0) { + if (single) { + if (up) { + return new %(vstr_us)s(machInst, vd, rn, up, imm); + } else { + return new %(vstr_s)s(machInst, vd, rn, up, imm); + } + } else { + if (up) { + return new %(vstr_ud)s(machInst, vd, vd + 1, + rn, up, imm); + } else { + return new %(vstr_d)s(machInst, vd, vd + 1, + rn, up, imm); + } + } + } else if (bits(opcode, 1, 0) == 0x1) { + if (single) { + if (up) { + return new %(vldr_us)s(machInst, vd, rn, up, imm); + } else { + return new %(vldr_s)s(machInst, vd, rn, up, imm); + } + } else { + if (up) { + return new %(vldr_ud)s(machInst, vd, vd + 1, + rn, up, imm); + } else { + return new %(vldr_d)s(machInst, vd, vd + 1, + rn, up, imm); + } + } + } + } + return new Unknown(machInst); + } + ''' % { + "vldr_us" : "VLDR_" + loadImmClassName(False, True, False), + "vldr_s" : "VLDR_" + loadImmClassName(False, False, False), + "vldr_ud" : "VLDR_" + loadDoubleImmClassName(False, True, False), + "vldr_d" : "VLDR_" + loadDoubleImmClassName(False, False, False), + "vstr_us" : "VSTR_" + storeImmClassName(False, True, False), + "vstr_s" : "VSTR_" + storeImmClassName(False, False, False), + "vstr_ud" : "VSTR_" + storeDoubleImmClassName(False, True, False), + "vstr_d" : "VSTR_" + storeDoubleImmClassName(False, False, False) } }}; -// Primary format for float point operate instructions: -def format FloatOp(code, *flags) {{ - orig_code = code - - cblk = code - iop = InstObjParams(name, Name, 'PredOp', - {"code": cblk, - "predicate_test": predicateTest}, - 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', 'PredOp', - {"code": sng_cblk, - "predicate_test": predicateTest}, - 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', 'PredOp', - {"code": dbl_cblk, - "predicate_test": predicateTest}, - flags) - header_output += BasicDeclare.subst(dbl_iop) - decoder_output += BasicConstructor.subst(dbl_iop) - exec_output += FPAExecute.subst(dbl_iop) - - decode_block = FloatDoubleDecode.subst(iop) +def format ExtensionRegLoadStore() {{ + decode_block = ''' + return decodeExtensionRegLoadStore(machInst); + ''' }}; 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; - - CondCodes = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 | - (CondCodes & 0x0FFFFFFF); - ''' + header_output = ''' + StaticInstPtr + decodeShortFpTransfer(ExtMachInst machInst); + ''' + decoder_output = ''' + StaticInstPtr + decodeShortFpTransfer(ExtMachInst machInst) + { + const uint32_t l = bits(machInst, 20); + const uint32_t c = bits(machInst, 8); + const uint32_t a = bits(machInst, 23, 21); + const uint32_t b = bits(machInst, 6, 5); + if ((machInst.thumb == 1 && bits(machInst, 28) == 1) || + (machInst.thumb == 0 && machInst.condCode == 0xf)) { + return new Unknown(machInst); + } + if (l == 0 && c == 0) { + if (a == 0) { + const uint32_t vn = (bits(machInst, 19, 16) << 1) | + bits(machInst, 7); + const IntRegIndex rt = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + if (bits(machInst, 20) == 1) { + return new VmovRegCoreW(machInst, rt, (IntRegIndex)vn); + } else { + return new VmovCoreRegW(machInst, (IntRegIndex)vn, rt); + } + } else if (a == 0x7) { + const IntRegIndex rt = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + uint32_t specReg = bits(machInst, 19, 16); + switch (specReg) { + case 0: + specReg = MISCREG_FPSID; + break; + case 1: + specReg = MISCREG_FPSCR; + break; + case 6: + specReg = MISCREG_MVFR1; + break; + case 7: + specReg = MISCREG_MVFR0; + break; + case 8: + specReg = MISCREG_FPEXC; + break; + default: + return new Unknown(machInst); + } + return new Vmsr(machInst, (IntRegIndex)specReg, rt); + } + } else if (l == 0 && c == 1) { + if (bits(a, 2) == 0) { + uint32_t vd = (bits(machInst, 7) << 5) | + (bits(machInst, 19, 16) << 1); + uint32_t index, size; + const IntRegIndex rt = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + if (bits(machInst, 22) == 1) { + size = 8; + index = (bits(machInst, 21) << 2) | + bits(machInst, 6, 5); + } else if (bits(machInst, 5) == 1) { + size = 16; + index = (bits(machInst, 21) << 1) | + bits(machInst, 6); + } else if (bits(machInst, 6) == 0) { + size = 32; + index = bits(machInst, 21); + } else { + return new Unknown(machInst); + } + if (index >= (32 / size)) { + index -= (32 / size); + vd++; + } + switch (size) { + case 8: + return new VmovCoreRegB(machInst, (IntRegIndex)vd, + rt, index); + case 16: + return new VmovCoreRegH(machInst, (IntRegIndex)vd, + rt, index); + case 32: + return new VmovCoreRegW(machInst, (IntRegIndex)vd, rt); + } + } else if (bits(b, 1) == 0) { + // A8-594 + return new WarnUnimplemented("vdup", machInst); + } + } else if (l == 1 && c == 0) { + if (a == 0) { + const uint32_t vn = (bits(machInst, 19, 16) << 1) | + bits(machInst, 7); + const IntRegIndex rt = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + if (bits(machInst, 20) == 1) { + return new VmovRegCoreW(machInst, rt, (IntRegIndex)vn); + } else { + return new VmovCoreRegW(machInst, (IntRegIndex)vn, rt); + } + } else if (a == 7) { + const IntRegIndex rt = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + uint32_t specReg = bits(machInst, 19, 16); + switch (specReg) { + case 0: + specReg = MISCREG_FPSID; + break; + case 1: + specReg = MISCREG_FPSCR; + break; + case 6: + specReg = MISCREG_MVFR1; + break; + case 7: + specReg = MISCREG_MVFR0; + break; + case 8: + specReg = MISCREG_FPEXC; + break; + default: + return new Unknown(machInst); + } + if (rt == 0xf) { + CPSR cpsrMask = 0; + cpsrMask.n = 1; + cpsrMask.z = 1; + cpsrMask.c = 1; + cpsrMask.v = 1; + return new VmrsApsr(machInst, INTREG_CONDCODES, + (IntRegIndex)specReg, (uint32_t)cpsrMask); + } else { + return new Vmrs(machInst, rt, (IntRegIndex)specReg); + } + } + } else { + uint32_t vd = (bits(machInst, 7) << 5) | + (bits(machInst, 19, 16) << 1); + uint32_t index, size; + const IntRegIndex rt = + (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const bool u = (bits(machInst, 23) == 1); + if (bits(machInst, 22) == 1) { + size = 8; + index = (bits(machInst, 21) << 2) | + bits(machInst, 6, 5); + } else if (bits(machInst, 5) == 1) { + size = 16; + index = (bits(machInst, 21) << 1) | + bits(machInst, 6); + } else if (bits(machInst, 6) == 0 && !u) { + size = 32; + index = bits(machInst, 21); + } else { + return new Unknown(machInst); + } + if (index >= (32 / size)) { + index -= (32 / size); + vd++; + } + switch (size) { + case 8: + if (u) { + return new VmovRegCoreUB(machInst, rt, + (IntRegIndex)vd, index); + } else { + return new VmovRegCoreSB(machInst, rt, + (IntRegIndex)vd, index); + } + case 16: + if (u) { + return new VmovRegCoreUH(machInst, rt, + (IntRegIndex)vd, index); + } else { + return new VmovRegCoreSH(machInst, rt, + (IntRegIndex)vd, index); + } + case 32: + return new VmovRegCoreW(machInst, rt, (IntRegIndex)vd); + } + } + return new Unknown(machInst); + } + ''' }}; -def format FloatCmp(fReg1, fReg2, *flags) {{ - code = calcFPCcCode % vars() - iop = InstObjParams(name, Name, 'PredOp', - {"code": code, - "predicate_test": predicateTest}, - flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecode.subst(iop) - exec_output = FPAExecute.subst(iop) +def format ShortFpTransfer() {{ + decode_block = ''' + return decodeShortFpTransfer(machInst); + ''' }}; +let {{ + header_output = ''' + StaticInstPtr + decodeVfpData(ExtMachInst machInst); + ''' + decoder_output = ''' + StaticInstPtr + decodeVfpData(ExtMachInst machInst) + { + const uint32_t opc1 = bits(machInst, 23, 20); + const uint32_t opc2 = bits(machInst, 19, 16); + const uint32_t opc3 = bits(machInst, 7, 6); + //const uint32_t opc4 = bits(machInst, 3, 0); + const bool single = (bits(machInst, 8) == 0); + // Used to select between vcmp and vcmpe. + const bool e = (bits(machInst, 7) == 1); + IntRegIndex vd; + IntRegIndex vm; + IntRegIndex vn; + if (single) { + vd = (IntRegIndex)(bits(machInst, 22) | + (bits(machInst, 15, 12) << 1)); + vm = (IntRegIndex)(bits(machInst, 5) | + (bits(machInst, 3, 0) << 1)); + vn = (IntRegIndex)(bits(machInst, 7) | + (bits(machInst, 19, 16) << 1)); + } else { + vd = (IntRegIndex)((bits(machInst, 22) << 5) | + (bits(machInst, 15, 12) << 1)); + vm = (IntRegIndex)((bits(machInst, 5) << 5) | + (bits(machInst, 3, 0) << 1)); + vn = (IntRegIndex)((bits(machInst, 7) << 5) | + (bits(machInst, 19, 16) << 1)); + } + switch (opc1 & 0xb /* 1011 */) { + case 0x0: + if (bits(machInst, 6) == 0) { + if (single) { + return decodeVfpRegRegRegOp( + machInst, vd, vn, vm, false); + } else { + return decodeVfpRegRegRegOp( + machInst, vd, vn, vm, true); + } + } else { + if (single) { + return decodeVfpRegRegRegOp( + machInst, vd, vn, vm, false); + } else { + return decodeVfpRegRegRegOp( + machInst, vd, vn, vm, true); + } + } + case 0x1: + if (bits(machInst, 6) == 1) { + if (single) { + return decodeVfpRegRegRegOp( + machInst, vd, vn, vm, false); + } else { + return decodeVfpRegRegRegOp( + machInst, vd, vn, vm, true); + } + } else { + if (single) { + return decodeVfpRegRegRegOp( + machInst, vd, vn, vm, false); + } else { + return decodeVfpRegRegRegOp( + machInst, vd, vn, vm, true); + } + } + case 0x2: + if ((opc3 & 0x1) == 0) { + if (single) { + return decodeVfpRegRegRegOp( + machInst, vd, vn, vm, false); + } else { + return decodeVfpRegRegRegOp( + machInst, vd, vn, vm, true); + } + } else { + if (single) { + return decodeVfpRegRegRegOp( + machInst, vd, vn, vm, false); + } else { + return decodeVfpRegRegRegOp( + machInst, vd, vn, vm, true); + } + } + case 0x3: + if ((opc3 & 0x1) == 0) { + if (single) { + return decodeVfpRegRegRegOp( + machInst, vd, vn, vm, false); + } else { + return decodeVfpRegRegRegOp( + machInst, vd, vn, vm, true); + } + } else { + if (single) { + return decodeVfpRegRegRegOp( + machInst, vd, vn, vm, false); + } else { + return decodeVfpRegRegRegOp( + machInst, vd, vn, vm, true); + } + } + case 0x8: + if ((opc3 & 0x1) == 0) { + if (single) { + return decodeVfpRegRegRegOp( + machInst, vd, vn, vm, false); + } else { + return decodeVfpRegRegRegOp( + machInst, vd, vn, vm, true); + } + } + break; + case 0xb: + if ((opc3 & 0x1) == 0) { + const uint32_t baseImm = + bits(machInst, 3, 0) | (bits(machInst, 19, 16) << 4); + if (single) { + uint32_t imm = vfp_modified_imm(baseImm, false); + return decodeVfpRegImmOp( + machInst, vd, imm, false); + } else { + uint64_t imm = vfp_modified_imm(baseImm, true); + return decodeVfpRegImmOp( + machInst, vd, imm, true); + } + } + switch (opc2) { + case 0x0: + if (opc3 == 1) { + if (single) { + return decodeVfpRegRegOp( + machInst, vd, vm, false); + } else { + return decodeVfpRegRegOp( + machInst, vd, vm, true); + } + } else { + if (single) { + return decodeVfpRegRegOp( + machInst, vd, vm, false); + } else { + return decodeVfpRegRegOp( + machInst, vd, vm, true); + } + } + case 0x1: + if (opc3 == 1) { + if (single) { + return decodeVfpRegRegOp( + machInst, vd, vm, false); + } else { + return decodeVfpRegRegOp( + machInst, vd, vm, true); + } + } else { + if (single) { + return decodeVfpRegRegOp( + machInst, vd, vm, false); + } else { + return decodeVfpRegRegOp( + machInst, vd, vm, true); + } + } + case 0x2: + case 0x3: + { + const bool toHalf = bits(machInst, 16); + const bool top = bits(machInst, 7); + if (top) { + if (toHalf) { + return new VcvtFpSFpHT(machInst, vd, vm); + } else { + return new VcvtFpHTFpS(machInst, vd, vm); + } + } else { + if (toHalf) { + return new VcvtFpSFpHB(machInst, vd, vm); + } else { + return new VcvtFpHBFpS(machInst, vd, vm); + } + } + } + case 0x4: + if (single) { + if (e) { + return new VcmpeS(machInst, vd, vm); + } else { + return new VcmpS(machInst, vd, vm); + } + } else { + if (e) { + return new VcmpeD(machInst, vd, vm); + } else { + return new VcmpD(machInst, vd, vm); + } + } + case 0x5: + if (single) { + if (e) { + return new VcmpeZeroS(machInst, vd, 0); + } else { + return new VcmpZeroS(machInst, vd, 0); + } + } else { + if (e) { + return new VcmpeZeroD(machInst, vd, 0); + } else { + return new VcmpZeroD(machInst, vd, 0); + } + } + case 0x7: + if (opc3 == 0x3) { + if (single) { + vm = (IntRegIndex)(bits(machInst, 5) | + (bits(machInst, 3, 0) << 1)); + return new VcvtFpSFpD(machInst, vd, vm); + } else { + vd = (IntRegIndex)(bits(machInst, 22) | + (bits(machInst, 15, 12) << 1)); + return new VcvtFpDFpS(machInst, vd, vm); + } + } + break; + case 0x8: + if (bits(machInst, 7) == 0) { + if (single) { + return new VcvtUIntFpS(machInst, vd, vm); + } else { + vm = (IntRegIndex)(bits(machInst, 5) | + (bits(machInst, 3, 0) << 1)); + return new VcvtUIntFpD(machInst, vd, vm); + } + } else { + if (single) { + return new VcvtSIntFpS(machInst, vd, vm); + } else { + vm = (IntRegIndex)(bits(machInst, 5) | + (bits(machInst, 3, 0) << 1)); + return new VcvtSIntFpD(machInst, vd, vm); + } + } + case 0xa: + { + const bool half = (bits(machInst, 7) == 0); + const uint32_t imm = bits(machInst, 5) | + (bits(machInst, 3, 0) << 1); + const uint32_t size = + (bits(machInst, 7) == 0 ? 16 : 32) - imm; + if (single) { + if (half) { + return new VcvtSHFixedFpS(machInst, vd, vd, size); + } else { + return new VcvtSFixedFpS(machInst, vd, vd, size); + } + } else { + if (half) { + return new VcvtSHFixedFpD(machInst, vd, vd, size); + } else { + return new VcvtSFixedFpD(machInst, vd, vd, size); + } + } + } + case 0xb: + { + const bool half = (bits(machInst, 7) == 0); + const uint32_t imm = bits(machInst, 5) | + (bits(machInst, 3, 0) << 1); + const uint32_t size = + (bits(machInst, 7) == 0 ? 16 : 32) - imm; + if (single) { + if (half) { + return new VcvtUHFixedFpS(machInst, vd, vd, size); + } else { + return new VcvtUFixedFpS(machInst, vd, vd, size); + } + } else { + if (half) { + return new VcvtUHFixedFpD(machInst, vd, vd, size); + } else { + return new VcvtUFixedFpD(machInst, vd, vd, size); + } + } + } + case 0xc: + if (bits(machInst, 7) == 0) { + if (single) { + return new VcvtFpUIntSR(machInst, vd, vm); + } else { + vd = (IntRegIndex)(bits(machInst, 22) | + (bits(machInst, 15, 12) << 1)); + return new VcvtFpUIntDR(machInst, vd, vm); + } + } else { + if (single) { + return new VcvtFpUIntS(machInst, vd, vm); + } else { + vd = (IntRegIndex)(bits(machInst, 22) | + (bits(machInst, 15, 12) << 1)); + return new VcvtFpUIntD(machInst, vd, vm); + } + } + case 0xd: + if (bits(machInst, 7) == 0) { + if (single) { + return new VcvtFpSIntSR(machInst, vd, vm); + } else { + vd = (IntRegIndex)(bits(machInst, 22) | + (bits(machInst, 15, 12) << 1)); + return new VcvtFpSIntDR(machInst, vd, vm); + } + } else { + if (single) { + return new VcvtFpSIntS(machInst, vd, vm); + } else { + vd = (IntRegIndex)(bits(machInst, 22) | + (bits(machInst, 15, 12) << 1)); + return new VcvtFpSIntD(machInst, vd, vm); + } + } + case 0xe: + { + const bool half = (bits(machInst, 7) == 0); + const uint32_t imm = bits(machInst, 5) | + (bits(machInst, 3, 0) << 1); + const uint32_t size = + (bits(machInst, 7) == 0 ? 16 : 32) - imm; + if (single) { + if (half) { + return new VcvtFpSHFixedS(machInst, vd, vd, size); + } else { + return new VcvtFpSFixedS(machInst, vd, vd, size); + } + } else { + if (half) { + return new VcvtFpSHFixedD(machInst, vd, vd, size); + } else { + return new VcvtFpSFixedD(machInst, vd, vd, size); + } + } + } + case 0xf: + { + const bool half = (bits(machInst, 7) == 0); + const uint32_t imm = bits(machInst, 5) | + (bits(machInst, 3, 0) << 1); + const uint32_t size = + (bits(machInst, 7) == 0 ? 16 : 32) - imm; + if (single) { + if (half) { + return new VcvtFpUHFixedS(machInst, vd, vd, size); + } else { + return new VcvtFpUFixedS(machInst, vd, vd, size); + } + } else { + if (half) { + return new VcvtFpUHFixedD(machInst, vd, vd, size); + } else { + return new VcvtFpUFixedD(machInst, vd, vd, size); + } + } + } + } + break; + } + return new Unknown(machInst); + } + ''' +}}; +def format VfpData() {{ + decode_block = ''' + return decodeVfpData(machInst); + ''' +}}; diff -r 84bd4089958b src/arch/arm/isa/formats/macromem.isa --- a/src/arch/arm/isa/formats/macromem.isa Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/isa/formats/macromem.isa Wed May 26 18:10:45 2010 -0500 @@ -1,7 +1,16 @@ // -*- mode:c++ -*- -// Copyright (c) 2007-2008 The Florida State University -// All rights reserved. +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -26,342 +35,24 @@ // (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 -// Gabe Black +// Authors: Gabe Black -//////////////////////////////////////////////////////////////////// -// -// Common microop templates -// - -def template MicroConstructor {{ - inline %(class_name)s::%(class_name)s(ExtMachInst machInst, - RegIndex _ura, - RegIndex _urb, - uint8_t _imm) - : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, - _ura, _urb, _imm) - { - %(constructor)s; - } +def format ArmMacroMem() {{ + decode_block = ''' + return new LdmStm(machInst, (IntRegIndex)(uint32_t)RN, !PREPOST, UP, + PSRUSER, WRITEBACK, LOADOP, machInst.regList); + ''' }}; -//////////////////////////////////////////////////////////////////// -// -// Load/store microops -// - -def template MicroMemDeclare {{ - class %(class_name)s : public %(base_class)s +def format Thumb16MacroMem() {{ + decode_block = ''' { - public: - %(class_name)s(ExtMachInst machInst, - RegIndex _ura, RegIndex _urb, - uint8_t _imm); - %(BasicExecDeclare)s - %(InitiateAccDeclare)s - %(CompleteAccDeclare)s - }; + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 10, 8); + const bool load = (bits(machInst, 11) == 1); + const uint32_t regList = bits(machInst, 7, 0); + const bool writeback = (!load || bits(regList, rn) == 0); + return new LdmStm(machInst, rn, true, true, false, + writeback, load, regList); + } + ''' }}; - -let {{ - microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop', - 'MicroMemOp', - {'memacc_code': 'Ra = Mem;', - 'ea_code': 'EA = Rb + (UP ? imm : -imm);', - 'predicate_test': predicateTest}, - ['IsMicroop']) - - microLdrRetUopCode = ''' - Ra = Mem; - Cpsr = cpsrWriteByInstr(Cpsr, Spsr, 0xF, true); - ''' - microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop', - 'MicroMemOp', - {'memacc_code': microLdrRetUopCode, - 'ea_code': - 'EA = Rb + (UP ? imm : -imm);', - 'predicate_test': predicateTest}, - ['IsMicroop']) - - microStrUopIop = InstObjParams('str_uop', 'MicroStrUop', - 'MicroMemOp', - {'memacc_code': 'Mem = Ra;', - 'ea_code': 'EA = Rb + (UP ? imm : -imm);', - 'predicate_test': predicateTest}, - ['IsMicroop']) - - header_output = MicroMemDeclare.subst(microLdrUopIop) + \ - MicroMemDeclare.subst(microLdrRetUopIop) + \ - MicroMemDeclare.subst(microStrUopIop) - decoder_output = MicroConstructor.subst(microLdrUopIop) + \ - MicroConstructor.subst(microLdrRetUopIop) + \ - MicroConstructor.subst(microStrUopIop) - exec_output = LoadExecute.subst(microLdrUopIop) + \ - LoadExecute.subst(microLdrRetUopIop) + \ - StoreExecute.subst(microStrUopIop) + \ - LoadInitiateAcc.subst(microLdrUopIop) + \ - LoadInitiateAcc.subst(microLdrRetUopIop) + \ - StoreInitiateAcc.subst(microStrUopIop) + \ - LoadCompleteAcc.subst(microLdrUopIop) + \ - LoadCompleteAcc.subst(microLdrRetUopIop) + \ - StoreCompleteAcc.subst(microStrUopIop) -}}; - -//////////////////////////////////////////////////////////////////// -// -// Integer = Integer op Immediate microops -// - -def template MicroIntDeclare {{ - class %(class_name)s : public %(base_class)s - { - public: - %(class_name)s(ExtMachInst machInst, - RegIndex _ura, RegIndex _urb, - uint8_t _imm); - %(BasicExecDeclare)s - }; -}}; - -let {{ - microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop', - 'MicroIntOp', - {'code': 'Ra = Rb + imm;', - 'predicate_test': predicateTest}, - ['IsMicroop']) - - microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop', - 'MicroIntOp', - {'code': 'Ra = Rb - imm;', - 'predicate_test': predicateTest}, - ['IsMicroop']) - - header_output = MicroIntDeclare.subst(microAddiUopIop) + \ - MicroIntDeclare.subst(microSubiUopIop) - decoder_output = MicroConstructor.subst(microAddiUopIop) + \ - MicroConstructor.subst(microSubiUopIop) - exec_output = PredOpExecute.subst(microAddiUopIop) + \ - PredOpExecute.subst(microSubiUopIop) -}}; - -//////////////////////////////////////////////////////////////////// -// -// Moving to/from double floating point registers -// - -let {{ - microMvtdUopIop = InstObjParams('mvtd_uop', 'MicroMvtdUop', - 'PredOp', - {'code': 'Fd.ud = (Rhi.ud << 32) | Rlo;', - 'predicate_test': predicateTest}, - ['IsMicroop']) - - microMvfdUopIop = InstObjParams('mvfd_uop', 'MicroMvfdUop', - 'PredOp', - {'code': '''Rhi = bits(Fd.ud, 63, 32); - Rlo = bits(Fd.ud, 31, 0);''', - 'predicate_test': predicateTest}, - ['IsMicroop']) - - header_output = BasicDeclare.subst(microMvtdUopIop) + \ - BasicDeclare.subst(microMvfdUopIop) - decoder_output = BasicConstructor.subst(microMvtdUopIop) + \ - BasicConstructor.subst(microMvfdUopIop) - exec_output = PredOpExecute.subst(microMvtdUopIop) + \ - PredOpExecute.subst(microMvfdUopIop) -}}; - -//////////////////////////////////////////////////////////////////// -// -// Macro Memory-format instructions -// - -def template MacroStoreDeclare {{ -/** - * Static instructions class for a store multiple instruction - */ -class %(class_name)s : public %(base_class)s -{ - public: - // Constructor - %(class_name)s(ExtMachInst machInst); - %(BasicExecDeclare)s -}; -}}; - -def template MacroStoreConstructor {{ -inline %(class_name)s::%(class_name)s(ExtMachInst machInst) - : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) -{ - %(constructor)s; - uint32_t regs = reglist; - uint32_t addr = 0; - bool up = machInst.puswl.up; - - if (!up) - addr = (ones << 2) - 4; - - if (machInst.puswl.prepost) - addr += 4; - - // Add 0 to Rn and stick it in ureg0. - // This is equivalent to a move. - microOps[0] = new MicroAddiUop(machInst, INTREG_UREG0, RN, 0); - - unsigned reg = 0; - bool force_user = machInst.puswl.psruser & !OPCODE_15; - bool exception_ret = machInst.puswl.psruser & OPCODE_15; - - for (int i = 1; i < ones + 1; i++) { - // Find the next register. - while (!bits(regs, reg)) - reg++; - replaceBits(regs, reg, 0); - - unsigned regIdx = reg; - if (force_user) { - regIdx = intRegForceUser(regIdx); - } - - if (machInst.puswl.loadOp) { - if (reg == INTREG_PC && exception_ret) { - // This must be the exception return form of ldm. - microOps[i] = - new MicroLdrRetUop(machInst, regIdx, INTREG_UREG0, addr); - } else { - microOps[i] = - new MicroLdrUop(machInst, regIdx, INTREG_UREG0, addr); - } - } else { - microOps[i] = - new MicroStrUop(machInst, regIdx, INTREG_UREG0, addr); - } - - if (up) - addr += 4; - else - addr -= 4; - } - - StaticInstPtr &lastUop = microOps[numMicroops - 1]; - if (machInst.puswl.writeback) { - if (up) { - lastUop = new MicroAddiUop(machInst, RN, RN, ones * 4); - } else { - lastUop = new MicroSubiUop(machInst, RN, RN, ones * 4); - } - } - lastUop->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(ExtMachInst 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) - { - if (up) { - microOps[numMicroops - 1] = - new MicroAddiUop(machInst, RN, RN, disp8); - } else { - microOps[numMicroops - 1] = - new MicroSubiUop(machInst, RN, RN, disp8); - } - } - microOps[numMicroops - 1]->setLastMicroop(); -} - -}}; - - -def template MacroFMConstructor {{ -inline %(class_name)s::%(class_name)s(ExtMachInst 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) { - if (up) { - microOps[numMicroops - 1] = - new MicroAddiUop(machInst, RN, RN, disp8); - } else { - microOps[numMicroops - 1] = - new MicroSubiUop(machInst, RN, RN, disp8); - } - } - 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": code, - "predicate_test": predicateTest}, - 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": code, - "predicate_test": predicateTest}, - opt_flags) - header_output = BasicDeclare.subst(iop) - decoder_output = MacroFMConstructor.subst(iop) - decode_block = BasicDecode.subst(iop) - exec_output = PredOpExecute.subst(iop) -}}; diff -r 84bd4089958b src/arch/arm/isa/formats/mem.isa --- a/src/arch/arm/isa/formats/mem.isa Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/isa/formats/mem.isa Wed May 26 18:10:45 2010 -0500 @@ -1,5 +1,17 @@ // -*- mode:c++ -*- +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// // Copyright (c) 2007-2008 The Florida State University // All rights reserved. // @@ -26,277 +38,17 @@ // (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 +// Authors: Gabe Black -//////////////////////////////////////////////////////////////////// -// -// Memory-format instructions -// +def format AddrMode2(imm) {{ + if eval(imm): + imm = True + else: + imm = False -def template LoadStoreDeclare {{ - /** - * Static instruction class for "%(mnemonic)s". - */ - class %(class_name)s : public %(base_class)s - { - public: - - /// Constructor. - %(class_name)s(ExtMachInst 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 LoadStoreConstructor {{ - inline %(class_name)s::%(class_name)s(ExtMachInst machInst) - : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) - { - %(constructor)s; - } -}}; - - -def template LoadExecute {{ - Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, - Trace::InstRecord *traceData) const - { - Addr EA; - Fault fault = NoFault; - - %(op_decl)s; - %(op_rd)s; - %(ea_code)s; - - if (%(predicate_test)s) - { - 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; - - %(op_src_decl)s; - %(op_rd)s; - %(ea_code)s; - - if (%(predicate_test)s) - { - 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; - - %(op_decl)s; - %(op_rd)s; - - if (%(predicate_test)s) - { - // ARM instructions will not have a pkt if the predicate is false - Mem = pkt->get(); - - if (fault == NoFault) { - %(memacc_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; - - %(op_decl)s; - %(op_rd)s; - %(ea_code)s; - - if (%(predicate_test)s) - { - if (fault == NoFault) { - %(memacc_code)s; - } - - if (fault == NoFault) { - fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, - memAccessFlags, NULL); - } - - 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; - - %(op_decl)s; - %(op_rd)s; - %(ea_code)s; - - if (%(predicate_test)s) - { - if (fault == NoFault) { - %(memacc_code)s; - } - - if (fault == NoFault) { - fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, - memAccessFlags, NULL); - } - - // 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; - - %(op_decl)s; - %(op_rd)s; - - if (%(predicate_test)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; - - %(op_dest_decl)s; - - if (%(predicate_test)s) - { - if (fault == NoFault) { - %(op_wb)s; - } - } - - return fault; - } -}}; - -let {{ def buildPUBWLCase(p, u, b, w, l): return (p << 4) + (u << 3) + (b << 2) + (w << 1) + (l << 0) - def buildMode2Inst(p, u, b, w, l, suffix, offset): - mnem = ("str", "ldr")[l] - op = ("-", "+")[u] - offset = op + ArmGenericCodeSubs(offset); - mem = ("Mem", "Mem.ub")[b] - code = ("%s = Rd;", "Rd = %s;")[l] % mem - ea_code = "EA = Rn %s;" % ("", offset)[p] - if p == 0 or w == 1: - code += "Rn = Rn %s;" % offset - if p == 0 and w == 0: - # Here's where we'll tack on a flag to make this a usermode access. - mnem += "t" - type = ("Store", "Load")[l] - newSuffix = "_%s_P%dU%dB%dW%d" % (suffix, p, u, b, w) - if b == 1: - mnem += "b" - return LoadStoreBase(mnem, mnem.capitalize() + newSuffix, - ea_code, code, mem_flags = [], inst_flags = [], - base_class = 'Memory' + suffix, - exec_template_base = type.capitalize()) - - def buildMode3Inst(p, u, i, w, type, code, mnem): - op = ("-", "+")[u] - offset = ("%s Rm", "%s hilo")[i] % op - ea_code = "EA = Rn %s;" % ("", offset)[p] - if p == 0 or w == 1: - code += "Rn = Rn %s;" % offset - newSuffix = "_P%dU%dI%dW%d" % (p, u, i, w) - suffix = ("Reg", "Hilo")[i] - return LoadStoreBase(mnem, mnem.capitalize() + newSuffix, - ea_code, code, mem_flags = [], inst_flags = [], - base_class = 'Memory' + suffix, - exec_template_base = type.capitalize()) -}}; - -def format AddrMode2(suffix, offset) {{ header_output = decoder_output = exec_output = "" decode_block = "switch(PUBWL) {\n" @@ -306,20 +58,46 @@ for u in (0, 1): for b in (0, 1): for w in (0, 1): - for l in (0, 1): - (new_header_output, - new_decoder_output, - new_decode_block, - new_exec_output) = buildMode2Inst(p, u, b, w, l, - suffix, offset) - header_output += new_header_output - decoder_output += new_decoder_output - exec_output += new_exec_output - decode_block += ''' - case %#x: - {%s} - break; - ''' % (buildPUBWLCase(p,u,b,w,l), new_decode_block) + post = (p == 0) + user = (p == 0 and w == 1) + writeback = (p == 0 or w == 1) + add = (u == 1) + if b == 0: + size = 4 + else: + size = 1 + if add: + addStr = "true" + else: + addStr = "false" + if imm: + newDecode = "return new %s(machInst, RD, RN," + \ + "%s, machInst.immed11_0);" + loadClass = loadImmClassName(post, add, writeback, + size, False, user) + storeClass = storeImmClassName(post, add, writeback, + size, False, user) + loadDecode = newDecode % (loadClass, addStr) + storeDecode = newDecode % (storeClass, addStr) + else: + newDecode = "return new %s(machInst, RD, RN, %s," + \ + "machInst.shiftSize," + \ + "machInst.shift, RM);" + loadClass = loadRegClassName(post, add, writeback, + size, False, user) + storeClass = storeRegClassName(post, add, writeback, + size, False, user) + loadDecode = newDecode % (loadClass, addStr) + storeDecode = newDecode % (storeClass, addStr) + decode = ''' + case %#x: + {%s} + break; + ''' + decode_block += decode % \ + (buildPUBWLCase(p,u,b,w,1), loadDecode) + decode_block += decode % \ + (buildPUBWLCase(p,u,b,w,0), storeDecode) decode_block += ''' default: return new Unknown(machInst); @@ -327,62 +105,952 @@ }''' }}; -def format AddrMode3(l0Type, l0Code, l1Type, l1Code) {{ - l0Code = ArmGenericCodeSubs(l0Code); - l1Code = ArmGenericCodeSubs(l1Code); +def format AddrMode3() {{ + decode = ''' + { + const uint32_t op1 = bits(machInst, 24, 20); + const uint32_t op2 = bits(machInst, 6, 5); + const uint32_t puiw = bits(machInst, 24, 21); + const uint32_t imm = IMMED_HI_11_8 << 4 | IMMED_LO_3_0; + switch (op2) { + case 0x1: + if (op1 & 0x1) { + %(ldrh)s + } else { + %(strh)s + } + case 0x2: + if (op1 & 0x1) { + %(ldrsb)s + } else if ((RT %% 2) == 0) { + %(ldrd)s + } else { + return new Unknown(machInst); + } + case 0x3: + if (op1 & 0x1) { + %(ldrsh)s + } else { + %(strd)s + } + default: + return new Unknown(machInst); + } + } + ''' - header_output = decoder_output = exec_output = "" - decode_block = "switch(PUBWL) {\n" - (l0Mnem, l1Mnem) = name.split("_"); + def decodePuiwCase(load, d, p, u, i, w, size=4, sign=False): + post = (p == 0) + user = (p == 0 and w == 1) + writeback = (p == 0 or w == 1) + add = (u == 1) + caseVal = (p << 3) + (u << 2) + (i << 1) + (w << 0) + decode = ''' + case %#x: + return new '''% caseVal + if add: + addStr = "true" + else: + addStr = "false" + if d: + dests = "RT & ~1, RT | 1" + else: + dests = "RT" + if i: + if load: + if d: + className = loadDoubleImmClassName(post, add, writeback) + else: + className = loadImmClassName(post, add, writeback, \ + size=size, sign=sign, \ + user=user) + else: + if d: + className = storeDoubleImmClassName(post, add, writeback) + else: + className = storeImmClassName(post, add, writeback, \ + size=size, sign=sign, \ + user=user) + decode += ("%s(machInst, %s, RN, %s, imm);\n" % \ + (className, dests, addStr)) + else: + if load: + if d: + className = loadDoubleRegClassName(post, add, writeback) + else: + className = loadRegClassName(post, add, writeback, \ + size=size, sign=sign, \ + user=user) + else: + if d: + className = storeDoubleRegClassName(post, add, writeback) + else: + className = storeRegClassName(post, add, writeback, \ + size=size, sign=sign, \ + user=user) + decode += ("%s(machInst, %s, RN, %s, 0, LSL, RM);\n" % \ + (className, dests, addStr)) + return decode - # Loop over all the values of p, u, i, w and l and build instructions and - # a decode block for them. - for (l, type, code, mnem) in ((0, l0Type, l0Code, l0Mnem), - (1, l1Type, l1Code, l1Mnem)): + def decodePuiw(load, d, size=4, sign=False): + global decodePuiwCase + decode = "switch (puiw) {\n" for p in (0, 1): - wset = (0, 1) - if (p == 0): - wset = (0,) for u in (0, 1): for i in (0, 1): - for w in wset: - (new_header_output, - new_decoder_output, - new_decode_block, - new_exec_output) = buildMode3Inst(p, u, i, w, - type, code, mnem) - header_output += new_header_output - decoder_output += new_decoder_output - exec_output += new_exec_output - decode_block += ''' - case %#x: - {%s} - break; - ''' % (buildPUBWLCase(p,u,i,w,l), new_decode_block) + for w in (0, 1): + decode += decodePuiwCase(load, d, p, u, i, w, + size, sign) + decode += ''' + default: + return new Unknown(machInst); + } + ''' + return decode - decode_block += ''' - default: - return new Unknown(machInst); - break; - }''' + subs = { + "ldrh" : decodePuiw(True, False, size=2), + "strh" : decodePuiw(False, False, size=2), + "ldrsb" : decodePuiw(True, False, size=1, sign=True), + "ldrd" : decodePuiw(True, True), + "ldrsh" : decodePuiw(True, False, size=2, sign=True), + "strd" : decodePuiw(False, True) + } + decode_block = decode % subs }}; -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 ArmSyncMem() {{ + decode_block = ''' + { + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rt = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rt2 = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + switch (PUBWL) { + case 0x10: + return new Swp(machInst, rt, rt2, rn); + case 0x14: + return new Swpb(machInst, rt, rt2, rn); + case 0x18: + return new %(strex)s(machInst, rt, rt2, rn, true, 0); + case 0x19: + return new %(ldrex)s(machInst, rt, rn, true, 0); + case 0x1a: + return new %(strexd)s(machInst, rt, rt2, rt2 + 1, rn, true, 0); + case 0x1b: + return new %(ldrexd)s(machInst, rt, rt + 1, rn, true, 0); + case 0x1c: + return new %(strexb)s(machInst, rt, rt2, rn, true, 0); + case 0x1d: + return new %(ldrexb)s(machInst, rt, rn, true, 0); + case 0x1e: + return new %(strexh)s(machInst, rt, rt2, rn, true, 0); + case 0x1f: + return new %(ldrexh)s(machInst, rt, rn, true, 0); + default: + return new Unknown(machInst); + } + } + ''' % { + "ldrex" : "LDREX_" + loadImmClassName(False, True, False, size=4), + "ldrexb" : "LDREXB_" + loadImmClassName(False, True, False, size=1), + "ldrexh" : "LDREXH_" + loadImmClassName(False, True, False, size=2), + "ldrexd" : "LDREXD_" + loadDoubleImmClassName(False, True, False), + "strex" : "STREX_" + storeImmClassName(False, True, False, size=4), + "strexb" : "STREXB_" + storeImmClassName(False, True, False, size=1), + "strexh" : "STREXH_" + storeImmClassName(False, True, False, size=2), + "strexd" : "STREXD_" + storeDoubleImmClassName(False, True, False) + } }}; -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') +def format Thumb32SrsRfe() {{ + decode_block = ''' + { + const bool wb = (bits(machInst, 21) == 1); + const bool add = (bits(machInst, 24, 23) == 0x3); + if (bits(machInst, 20) == 1) { + // post == add + const IntRegIndex rn = + (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + if (!add && !wb) { + return new %(rfe)s(machInst, rn, RfeOp::DecrementBefore, wb); + } else if (add && !wb) { + return new %(rfe_u)s(machInst, rn, RfeOp::IncrementAfter, wb); + } else if (!add && wb) { + return new %(rfe_w)s(machInst, rn, RfeOp::DecrementBefore, wb); + } else { + return new %(rfe_uw)s(machInst, rn, RfeOp::IncrementAfter, wb); + } + } else { + const uint32_t mode = bits(machInst, 4, 0); + if (!add && !wb) { + return new %(srs)s(machInst, mode, + SrsOp::DecrementBefore, wb); + } else if (add && !wb) { + return new %(srs_u)s(machInst, mode, + SrsOp::IncrementAfter, wb); + } else if (!add && wb) { + return new %(srs_w)s(machInst, mode, + SrsOp::DecrementBefore, wb); + } else { + return new %(srs_uw)s(machInst, mode, + SrsOp::IncrementAfter, wb); + } + } + } + ''' % { + "rfe" : "RFE_" + loadImmClassName(False, False, False, 8), + "rfe_u" : "RFE_" + loadImmClassName(True, True, False, 8), + "rfe_w" : "RFE_" + loadImmClassName(False, False, True, 8), + "rfe_uw" : "RFE_" + loadImmClassName(True, True, True, 8), + "srs" : "SRS_" + storeImmClassName(False, False, False, 8), + "srs_u" : "SRS_" + storeImmClassName(True, True, False, 8), + "srs_w" : "SRS_" + storeImmClassName(False, False, True, 8), + "srs_uw" : "SRS_" + storeImmClassName(True, True, True, 8) + } }}; +def format Thumb32LdrStrDExTbh() {{ + decode_block = ''' + { + const uint32_t op1 = bits(machInst, 24, 23); + const uint32_t op2 = bits(machInst, 21, 20); + const uint32_t op3 = bits(machInst, 7, 4); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rt = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rt2 = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const uint32_t imm8 = bits(machInst, 7, 0); + if (bits(op1, 1) == 0 && bits(op2, 1) == 0) { + if (op1 == 0) { + const uint32_t imm = bits(machInst, 7, 0) << 2; + if (op2 == 0) { + return new %(strex)s(machInst, rt2, rt, rn, true, imm); + } else { + return new %(ldrex)s(machInst, rt, rn, true, imm); + } + } else { + if (op2 == 0) { + switch (op3) { + case 0x4: + return new %(strexb)s(machInst, rd, rt, rn, true, 0); + case 0x5: + return new %(strexh)s(machInst, rd, rt, rn, true, 0); + case 0x7: + return new %(strexd)s(machInst, rd, rt, + rt2, rn, true, 0); + default: + return new Unknown(machInst); + } + } else { + switch (op3) { + case 0x0: + return new Tbb(machInst, rn, rd); + case 0x1: + return new Tbh(machInst, rn, rd); + case 0x4: + return new %(ldrexb)s(machInst, rt, rn, true, 0); + case 0x5: + return new %(ldrexh)s(machInst, rt, rn, true, 0); + case 0x7: + return new %(ldrexd)s(machInst, rt, rt2, rn, true, 0); + default: + return new Unknown(machInst); + } + } + } + } else { + const uint32_t puw = (bits(machInst, 24, 23) << 1) | + bits(machInst, 21); + const uint32_t dimm = imm8 << 2; + if (bits(op2, 0) == 0) { + switch (puw) { + case 0x1: + return new %(strd_w)s(machInst, rt, rt2, rn, false, dimm); + case 0x3: + return new %(strd_uw)s(machInst, rt, rt2, rn, true, dimm); + case 0x4: + return new %(strd_p)s(machInst, rt, rt2, rn, false, dimm); + case 0x5: + return new %(strd_pw)s(machInst, rt, rt2, rn, false, dimm); + case 0x6: + return new %(strd_pu)s(machInst, rt, rt2, rn, true, dimm); + case 0x7: + return new %(strd_puw)s(machInst, rt, rt2, rn, true, dimm); + default: + return new Unknown(machInst); + } + } else { + switch (puw) { + case 0x1: + return new %(ldrd_w)s(machInst, rt, rt2, rn, false, dimm); + case 0x3: + return new %(ldrd_uw)s(machInst, rt, rt2, rn, true, dimm); + case 0x4: + return new %(ldrd_p)s(machInst, rt, rt2, rn, false, dimm); + case 0x5: + return new %(ldrd_pw)s(machInst, rt, rt2, rn, false, dimm); + case 0x6: + return new %(ldrd_pu)s(machInst, rt, rt2, rn, true, dimm); + case 0x7: + return new %(ldrd_puw)s(machInst, rt, rt2, rn, true, dimm); + default: + return new Unknown(machInst); + } + } + } + } + ''' % { + "ldrex" : "LDREX_" + loadImmClassName(False, True, False, size=4), + "ldrexb" : "LDREXB_" + loadImmClassName(False, True, False, size=1), + "ldrexh" : "LDREXH_" + loadImmClassName(False, True, False, size=2), + "ldrexd" : "LDREXD_" + loadDoubleImmClassName(False, True, False), + "strex" : "STREX_" + storeImmClassName(False, True, False, size=4), + "strexb" : "STREXB_" + storeImmClassName(False, True, False, size=1), + "strexh" : "STREXH_" + storeImmClassName(False, True, False, size=2), + "strexd" : "STREXD_" + storeDoubleImmClassName(False, True, False), + "ldrd_w" : loadDoubleImmClassName(True, False, True), + "ldrd_uw" : loadDoubleImmClassName(True, True, True), + "ldrd_p" : loadDoubleImmClassName(False, False, False), + "ldrd_pw" : loadDoubleImmClassName(False, False, True), + "ldrd_pu" : loadDoubleImmClassName(False, True, False), + "ldrd_puw" : loadDoubleImmClassName(False, True, True), + "strd_w" : storeDoubleImmClassName(True, False, True), + "strd_uw" : storeDoubleImmClassName(True, True, True), + "strd_p" : storeDoubleImmClassName(False, False, False), + "strd_pw" : storeDoubleImmClassName(False, False, True), + "strd_pu" : storeDoubleImmClassName(False, True, False), + "strd_puw" : storeDoubleImmClassName(False, True, True) + } +}}; + +def format Thumb32LoadWord() {{ + decode = ''' + { + uint32_t op1 = bits(machInst, 24, 23); + if (bits(op1, 1) == 0) { + uint32_t op2 = bits(machInst, 11, 6); + if (HTRN == 0xF) { + if (UP) { + return new %(literal_u)s(machInst, RT, INTREG_PC, + true, IMMED_11_0); + } else { + return new %(literal)s(machInst, RT, INTREG_PC, + false, IMMED_11_0); + } + } else if (op1 == 0x1) { + return new %(imm_pu)s(machInst, RT, RN, true, IMMED_11_0); + } else if (op2 == 0) { + return new %(register)s(machInst, RT, RN, UP, + bits(machInst, 5, 4), LSL, RM); + } else if ((op2 & 0x3c) == 0x38) { + return new %(ldrt)s(machInst, RT, RN, true, IMMED_7_0); + } else if ((op2 & 0x3c) == 0x30 || //P + (op2 & 0x24) == 0x24) { //W + uint32_t puw = bits(machInst, 10, 8); + uint32_t imm = IMMED_7_0; + switch (puw) { + case 0: + case 2: + // If we're here, either P or W must have been set. + panic("Neither P or W set, but that " + "shouldn't be possible.\\n"); + case 1: + return new %(imm_w)s(machInst, RT, RN, false, imm); + case 3: + return new %(imm_uw)s(machInst, RT, RN, true, imm); + case 4: + return new %(imm_p)s(machInst, RT, RN, false, imm); + case 5: + return new %(imm_pw)s(machInst, RT, RN, false, imm); + case 6: + return new %(imm_pu)s(machInst, RT, RN, true, imm); + case 7: + return new %(imm_puw)s(machInst, RT, RN, true, imm); + } + } + } else { + return new Unknown(machInst); + } + } + ''' + classNames = { + "literal_u" : loadImmClassName(False, True, False), + "literal" : loadImmClassName(False, False, False), + "register" : loadRegClassName(False, True, False), + "ldrt" : loadImmClassName(False, True, False, user=True), + "imm_w" : loadImmClassName(True, False, True), + "imm_uw" : loadImmClassName(True, True, True), + "imm_p" : loadImmClassName(False, False, False), + "imm_pw" : loadImmClassName(False, False, True), + "imm_pu" : loadImmClassName(False, True, False), + "imm_puw" : loadImmClassName(False, True, True) + } + decode_block = decode % classNames +}}; + +def format Thumb32StoreSingle() {{ + def buildPuwDecode(size): + puwDecode = ''' + { + uint32_t puw = bits(machInst, 10, 8); + uint32_t imm = IMMED_7_0; + switch (puw) { + case 0: + case 2: + // If we're here, either P or W must have been set. + panic("Neither P or W set, but that " + "shouldn't be possible.\\n"); + case 1: + return new %(imm_w)s(machInst, RT, RN, false, imm); + case 3: + return new %(imm_uw)s(machInst, RT, RN, true, imm); + case 4: + return new %(imm_p)s(machInst, RT, RN, false, imm); + case 5: + return new %(imm_pw)s(machInst, RT, RN, false, imm); + case 6: + return new %(imm_pu)s(machInst, RT, RN, true, imm); + case 7: + return new %(imm_puw)s(machInst, RT, RN, true, imm); + } + } + ''' + return puwDecode % { + "imm_w" : storeImmClassName(True, False, True, size=size), + "imm_uw" : storeImmClassName(True, True, True, size=size), + "imm_p" : storeImmClassName(False, False, False, size=size), + "imm_pw" : storeImmClassName(False, False, True, size=size), + "imm_pu" : storeImmClassName(False, True, False, size=size), + "imm_puw" : storeImmClassName(False, True, True, size=size) + } + decode = ''' + { + uint32_t op1 = bits(machInst, 23, 21); + uint32_t op2 = bits(machInst, 11, 6); + bool op2Puw = ((op2 & 0x24) == 0x24 || + (op2 & 0x3c) == 0x30); + if (RN == 0xf) { + return new Unknown(machInst); + } + if (op1 == 4) { + return new %(strb_imm)s(machInst, RT, RN, true, IMMED_11_0); + } else if (op1 == 0 && op2Puw) { + %(strb_puw)s; + } else if (op1 == 0 && ((op2 & 0x3c) == 0x38)) { + return new %(strbt)s(machInst, RT, RN, true, IMMED_7_0); + } else if (op1 == 0 && op2 == 0) { + return new %(strb_reg)s(machInst, RT, RN, true, + bits(machInst, 5, 4), LSL, RM); + } else if (op1 == 5) { + return new %(strh_imm)s(machInst, RT, RN, true, IMMED_11_0); + } else if (op1 == 1 && op2Puw) { + %(strh_puw)s; + } else if (op1 == 1 && ((op2 & 0x3c) == 0x38)) { + return new %(strht)s(machInst, RT, RN, true, IMMED_7_0); + } else if (op1 == 1 && op2 == 0) { + return new %(strh_reg)s(machInst, RT, RN, true, + bits(machInst, 5, 4), LSL, RM); + } else if (op1 == 6) { + return new %(str_imm)s(machInst, RT, RN, true, IMMED_11_0); + } else if (op1 == 2 && op2Puw) { + %(str_puw)s; + } else if (op1 == 2 && ((op2 & 0x3c) == 0x38)) { + return new %(strt)s(machInst, RT, RN, true, IMMED_7_0); + } else if (op1 == 2 && op2 == 0) { + return new %(str_reg)s(machInst, RT, RN, true, + bits(machInst, 5, 4), LSL, RM); + } else { + return new Unknown(machInst); + } + } + ''' + classNames = { + "strb_imm" : storeImmClassName(False, True, False, size=1), + "strb_puw" : buildPuwDecode(1), + "strbt" : storeImmClassName(False, True, False, user=True, size=1), + "strb_reg" : storeRegClassName(False, True, False, size=1), + "strh_imm" : storeImmClassName(False, True, False, size=2), + "strh_puw" : buildPuwDecode(2), + "strht" : storeImmClassName(False, True, False, user=True, size=2), + "strh_reg" : storeRegClassName(False, True, False, size=2), + "str_imm" : storeImmClassName(False, True, False), + "str_puw" : buildPuwDecode(4), + "strt" : storeImmClassName(False, True, False, user=True), + "str_reg" : storeRegClassName(False, True, False) + } + decode_block = decode % classNames +}}; + +def format LoadByteMemoryHints() {{ + decode = ''' + { + const uint32_t op1 = bits(machInst, 24, 23); + const uint32_t op2 = bits(machInst, 11, 6); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rt = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const uint32_t imm12 = bits(machInst, 11, 0); + const uint32_t imm8 = bits(machInst, 7, 0); + bool pldw = bits(machInst, 21); + const uint32_t imm2 = bits(machInst, 5, 4); + if (rn == 0xf) { + if (rt == 0xf) { + const bool add = bits(machInst, 23); + if (bits(op1, 1) == 1) { + if (add) { + return new %(pli_iulit)s(machInst, INTREG_ZERO, + INTREG_PC, true, imm12); + } else { + return new %(pli_ilit)s(machInst, INTREG_ZERO, + INTREG_PC, false, imm12); + } + } else { + if (add) { + return new %(pld_iulit)s(machInst, INTREG_ZERO, + INTREG_PC, true, imm12); + } else { + return new %(pld_ilit)s(machInst, INTREG_ZERO, + INTREG_PC, false, imm12); + } + } + } else { + if (bits(op1, 1) == 1) { + if (bits(machInst, 23)) { + return new %(ldrsb_lit_u)s(machInst, rt, INTREG_PC, + true, imm12); + } else { + return new %(ldrsb_lit)s(machInst, rt, INTREG_PC, + false, imm12); + } + } else { + if (bits(machInst, 23)) { + return new %(ldrb_lit_u)s(machInst, rt, INTREG_PC, + true, imm12); + } else { + return new %(ldrb_lit)s(machInst, rt, INTREG_PC, + false, imm12); + } + } + } + } else if (rt == 0xf) { + switch (op1) { + case 0x0: + if (op2 == 0x0) { + if (pldw) { + return new %(pldw_radd)s(machInst, INTREG_ZERO, + rn, true, imm2, LSL, rm); + } else { + return new %(pld_radd)s(machInst, INTREG_ZERO, + rn, true, imm2, LSL, rm); + } + } else if (bits(op2, 5, 2) == 0xc) { + if (pldw) { + return new %(pldw_isub)s(machInst, INTREG_ZERO, + rn, false, imm8); + } else { + return new %(pld_isub)s(machInst, INTREG_ZERO, + rn, false, imm8); + } + } + break; + case 0x1: + if (pldw) { + return new %(pldw_iadd)s(machInst, INTREG_ZERO, + rn, true, imm12); + } else { + return new %(pld_iadd)s(machInst, INTREG_ZERO, + rn, true, imm12); + } + case 0x2: + if (op2 == 0x0) { + return new %(pli_radd)s(machInst, INTREG_ZERO, rn, + true, imm2, LSL, rm); + } else if (bits(op2, 5, 2) == 0xc) { + return new %(pli_ilit)s(machInst, INTREG_ZERO, + INTREG_PC, false, imm8); + } + break; + case 0x3: + return new %(pli_iulit)s(machInst, INTREG_ZERO, + INTREG_PC, true, imm12); + } + return new Unknown(machInst); + } else { + switch (op1) { + case 0x0: + if (op2 == 0) { + return new %(ldrb_radd)s(machInst, rt, rn, true, + imm2, LSL, rm); + } else if (bits(op2, 5, 2) == 0xe) { + return new %(ldrbt)s(machInst, rt, rn, true, imm8); + } else if ((op2 & 0x24) == 0x24 || bits(op2, 5, 2) == 0xc) { + const uint32_t puw = bits(machInst, 10, 8); + switch (puw) { + case 0x1: + return new %(ldrb_iw)s(machInst, rt, + rn, false, imm8); + case 0x3: + return new %(ldrb_iuw)s(machInst, rt, + rn, true, imm8); + case 0x4: + return new %(ldrb_ip)s(machInst, rt, + rn, false, imm8); + case 0x5: + return new %(ldrb_ipw)s(machInst, rt, + rn, false, imm8); + case 0x7: + return new %(ldrb_ipuw)s(machInst, rt, + rn, true, imm8); + } + } + break; + case 0x1: + return new %(ldrb_iadd)s(machInst, rt, rn, true, imm12); + case 0x2: + if (op2 == 0) { + return new %(ldrsb_radd)s(machInst, rt, rn, true, + imm2, LSL, rm); + } else if (bits(op2, 5, 2) == 0xe) { + return new %(ldrsbt)s(machInst, rt, rn, true, imm8); + } else if ((op2 & 0x24) == 0x24 || bits(op2, 5, 2) == 0xc) { + const uint32_t puw = bits(machInst, 10, 8); + switch (puw) { + case 0x1: + return new %(ldrsb_iw)s(machInst, rt, + rn, false, imm8); + case 0x3: + return new %(ldrsb_iuw)s(machInst, rt, + rn, true, imm8); + case 0x4: + return new %(ldrsb_ip)s(machInst, rt, + rn, false, imm8); + case 0x5: + return new %(ldrsb_ipw)s(machInst, rt, + rn, false, imm8); + case 0x7: + return new %(ldrsb_ipuw)s(machInst, rt, + rn, true, imm8); + } + } + break; + case 0x3: + return new %(ldrsb_iadd)s(machInst, rt, rn, true, imm12); + } + return new Unknown(machInst); + } + } + ''' + substDict = { + "ldrsb_lit_u" : loadImmClassName(False, True, False, 1, True), + "ldrsb_lit" : loadImmClassName(False, False, False, 1, True), + "ldrb_lit_u" : loadImmClassName(False, True, False, 1), + "ldrb_lit" : loadImmClassName(False, False, False, 1), + "ldrsb_radd" : loadRegClassName(False, True, False, 1, True), + "ldrb_radd" : loadRegClassName(False, True, False, 1), + "ldrsb_iw" : loadImmClassName(True, False, True, 1, True), + "ldrsb_iuw" : loadImmClassName(True, True, True, 1, True), + "ldrsb_ip" : loadImmClassName(False, False, False, 1, True), + "ldrsb_ipw" : loadImmClassName(False, False, True, 1, True), + "ldrsb_ipuw" : loadImmClassName(False, True, True, 1, True), + "ldrsb_iadd" : loadImmClassName(False, True, False, 1, True), + "ldrb_iw" : loadImmClassName(True, False, True, 1), + "ldrb_iuw" : loadImmClassName(True, True, True, 1), + "ldrb_ip" : loadImmClassName(False, False, False, 1), + "ldrb_ipw" : loadImmClassName(False, False, True, 1), + "ldrb_ipuw" : loadImmClassName(False, True, True, 1), + "ldrb_iadd" : loadImmClassName(False, True, False, 1), + "ldrbt" : loadImmClassName(False, True, False, 1, user=True), + "ldrsbt" : loadImmClassName(False, True, False, 1, True, user=True), + "pldw_radd" : "PLDW_" + loadRegClassName(False, True, False, 1), + "pld_radd" : "PLD_" + loadRegClassName(False, True, False, 1), + "pldw_isub" : "PLDW_" + loadImmClassName(False, False, False, 1), + "pld_isub" : "PLD_" + loadImmClassName(False, False, False, 1), + "pldw_iadd" : "PLDW_" + loadImmClassName(False, True, False, 1), + "pld_iadd" : "PLD_" + loadImmClassName(False, True, False, 1), + "pld_iulit" : "PLD_" + loadImmClassName(False, True, False, 1), + "pld_ilit" : "PLD_" + loadImmClassName(False, False, False, 1), + "pli_iulit" : "PLI_" + loadImmClassName(False, True, False, 1), + "pli_ilit" : "PLI_" + loadImmClassName(False, False, False, 1), + "pli_radd" : "PLI_" + loadRegClassName(False, True, False, 1), + "pli_iulit" : "PLI_" + loadImmClassName(False, True, False, 1), + "pli_ilit" : "PLI_" + loadImmClassName(False, False, False, 1) + } + decode_block = decode % substDict +}}; + +def format LoadHalfwordMemoryHints() {{ + decode = ''' + { + const uint32_t op1 = bits(machInst, 24, 23); + const uint32_t op2 = bits(machInst, 11, 6); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rt = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const uint32_t imm12 = bits(machInst, 11, 0); + const uint32_t imm8 = bits(machInst, 7, 0); + bool pldw = bits(machInst, 21); + const uint32_t imm2 = bits(machInst, 5, 4); + if (rn == 0xf) { + if (rt == 0xf) { + if (bits(op1, 1) == 1) { + // Unallocated memory hint + return new NopInst(machInst); + } else { + return new Unknown(machInst); + } + } else { + if (bits(op1, 1) == 1) { + if (bits(machInst, 23)) { + return new %(ldrsh_lit_u)s(machInst, rt, INTREG_PC, + true, imm12); + } else { + return new %(ldrsh_lit)s(machInst, rt, INTREG_PC, + false, imm12); + } + } else { + if (bits(machInst, 23)) { + return new %(ldrh_lit_u)s(machInst, rt, INTREG_PC, + true, imm12); + } else { + return new %(ldrh_lit)s(machInst, rt, INTREG_PC, + false, imm12); + } + } + } + } else if (rt == 0xf) { + switch (op1) { + case 0x0: + if (op2 == 0x0) { + if (pldw) { + return new %(pldw_radd)s(machInst, INTREG_ZERO, + rn, true, imm2, LSL, rm); + } else { + return new %(pld_radd)s(machInst, INTREG_ZERO, + rn, true, imm2, LSL, rm); + } + } else if (bits(op2, 5, 2) == 0xc) { + if (pldw) { + return new %(pldw_isub)s(machInst, INTREG_ZERO, + rn, false, imm8); + } else { + return new %(pld_isub)s(machInst, INTREG_ZERO, + rn, false, imm8); + } + } + break; + case 0x1: + if (pldw) { + return new %(pldw_iadd)s(machInst, INTREG_ZERO, + rn, true, imm12); + } else { + return new %(pld_iadd)s(machInst, INTREG_ZERO, + rn, true, imm12); + } + case 0x2: + if (op2 == 0x0 || bits(op2, 5, 2) == 0xc) { + // Unallocated memory hint + return new NopInst(machInst); + } + break; + case 0x3: + return new NopInst(machInst); + } + return new Unknown(machInst); + } else { + switch (op1) { + case 0x0: + if (op2 == 0) { + return new %(ldrh_radd)s(machInst, rt, rn, true, + imm2, LSL, rm); + } else if (bits(op2, 5, 2) == 0xe) { + return new %(ldrht)s(machInst, rt, rn, true, imm8); + } else if ((op2 & 0x24) == 0x24 || bits(op2, 5, 2) == 0xc) { + const uint32_t puw = bits(machInst, 10, 8); + switch (puw) { + case 0x1: + return new %(ldrh_iw)s(machInst, rt, + rn, false, imm8); + case 0x3: + return new %(ldrh_iuw)s(machInst, rt, + rn, true, imm8); + case 0x4: + return new %(ldrh_ip)s(machInst, rt, + rn, false, imm8); + case 0x5: + return new %(ldrh_ipw)s(machInst, rt, + rn, false, imm8); + case 0x7: + return new %(ldrh_ipuw)s(machInst, rt, + rn, true, imm8); + } + } + break; + case 0x1: + return new %(ldrh_iadd)s(machInst, rt, rn, true, imm12); + case 0x2: + if (op2 == 0) { + return new %(ldrsh_radd)s(machInst, rt, rn, true, + imm2, LSL, rm); + } else if (bits(op2, 5, 2) == 0xe) { + return new %(ldrsht)s(machInst, rt, rn, true, imm8); + } else if ((op2 & 0x24) == 0x24 || bits(op2, 5, 2) == 0xc) { + const uint32_t puw = bits(machInst, 10, 8); + switch (puw) { + case 0x1: + return new %(ldrsh_iw)s(machInst, rt, + rn, false, imm8); + case 0x3: + return new %(ldrsh_iuw)s(machInst, rt, + rn, true, imm8); + case 0x4: + return new %(ldrsh_ip)s(machInst, rt, + rn, false, imm8); + case 0x5: + return new %(ldrsh_ipw)s(machInst, rt, + rn, false, imm8); + case 0x7: + return new %(ldrsh_ipuw)s(machInst, rt, + rn, true, imm8); + } + } + break; + case 0x3: + return new %(ldrsh_iadd)s(machInst, rt, rn, true, imm12); + } + return new Unknown(machInst); + } + } + ''' + substDict = { + "ldrsh_lit_u" : loadImmClassName(False, True, False, 2, True), + "ldrsh_lit" : loadImmClassName(False, False, False, 2, True), + "ldrh_lit_u" : loadImmClassName(False, True, False, 2), + "ldrh_lit" : loadImmClassName(False, False, False, 2), + "ldrsh_radd" : loadRegClassName(False, True, False, 2, True), + "ldrh_radd" : loadRegClassName(False, True, False, 2), + "ldrsh_iw" : loadImmClassName(True, False, True, 2, True), + "ldrsh_iuw" : loadImmClassName(True, True, True, 2, True), + "ldrsh_ip" : loadImmClassName(False, False, False, 2, True), + "ldrsh_ipw" : loadImmClassName(False, False, True, 2, True), + "ldrsh_ipuw" : loadImmClassName(False, True, True, 2, True), + "ldrsh_iadd" : loadImmClassName(False, True, False, 2, True), + "ldrh_iw" : loadImmClassName(True, False, True, 2), + "ldrh_iuw" : loadImmClassName(True, True, True, 2), + "ldrh_ip" : loadImmClassName(False, False, False, 2), + "ldrh_ipw" : loadImmClassName(False, False, True, 2), + "ldrh_ipuw" : loadImmClassName(False, True, True, 2), + "ldrh_iadd" : loadImmClassName(False, True, False, 2), + "ldrht" : loadImmClassName(False, True, False, 2, user=True), + "ldrsht" : loadImmClassName(False, True, False, 2, True, user=True), + "pldw_radd" : "PLDW_" + loadRegClassName(False, True, False, 1), + "pld_radd" : "PLD_" + loadRegClassName(False, True, False, 1), + "pldw_isub" : "PLDW_" + loadImmClassName(False, False, False, 1), + "pld_isub" : "PLD_" + loadImmClassName(False, False, False, 1), + "pldw_iadd" : "PLDW_" + loadImmClassName(False, True, False, 1), + "pld_iadd" : "PLD_" + loadImmClassName(False, True, False, 1) + } + decode_block = decode % substDict +}}; + +def format Thumb16MemReg() {{ + decode = ''' + { + const uint32_t opb = bits(machInst, 11, 9); + const uint32_t rt = bits(machInst, 2, 0); + const uint32_t rn = bits(machInst, 5, 3); + const uint32_t rm = bits(machInst, 8, 6); + switch (opb) { + case 0x0: + return new %(str)s(machInst, rt, rn, true, 0, LSL, rm); + case 0x1: + return new %(strh)s(machInst, rt, rn, true, 0, LSL, rm); + case 0x2: + return new %(strb)s(machInst, rt, rn, true, 0, LSL, rm); + case 0x3: + return new %(ldrsb)s(machInst, rt, rn, true, 0, LSL, rm); + case 0x4: + return new %(ldr)s(machInst, rt, rn, true, 0, LSL, rm); + case 0x5: + return new %(ldrh)s(machInst, rt, rn, true, 0, LSL, rm); + case 0x6: + return new %(ldrb)s(machInst, rt, rn, true, 0, LSL, rm); + case 0x7: + return new %(ldrsh)s(machInst, rt, rn, true, 0, LSL, rm); + } + } + ''' + classNames = { + "str" : storeRegClassName(False, True, False), + "strh" : storeRegClassName(False, True, False, size=2), + "strb" : storeRegClassName(False, True, False, size=1), + "ldrsb" : loadRegClassName(False, True, False, sign=True, size=1), + "ldr" : loadRegClassName(False, True, False), + "ldrh" : loadRegClassName(False, True, False, size=2), + "ldrb" : loadRegClassName(False, True, False, size=1), + "ldrsh" : loadRegClassName(False, True, False, sign=True, size=2), + } + decode_block = decode % classNames +}}; + +def format Thumb16MemImm() {{ + decode = ''' + { + const uint32_t opa = bits(machInst, 15, 12); + const uint32_t opb = bits(machInst, 11, 9); + const uint32_t lrt = bits(machInst, 2, 0); + const uint32_t lrn = bits(machInst, 5, 3); + const uint32_t hrt = bits(machInst, 10, 8); + const uint32_t imm5 = bits(machInst, 10, 6); + const uint32_t imm8 = bits(machInst, 7, 0); + const bool load = bits(opb, 2); + switch (opa) { + case 0x6: + if (load) { + return new %(ldr)s(machInst, lrt, lrn, true, imm5 << 2); + } else { + return new %(str)s(machInst, lrt, lrn, true, imm5 << 2); + } + case 0x7: + if (load) { + return new %(ldrb)s(machInst, lrt, lrn, true, imm5); + } else { + return new %(strb)s(machInst, lrt, lrn, true, imm5); + } + case 0x8: + if (load) { + return new %(ldrh)s(machInst, lrt, lrn, true, imm5 << 1); + } else { + return new %(strh)s(machInst, lrt, lrn, true, imm5 << 1); + } + case 0x9: + if (load) { + return new %(ldr)s(machInst, hrt, INTREG_SP, true, imm8 << 2); + } else { + return new %(str)s(machInst, hrt, INTREG_SP, true, imm8 << 2); + } + default: + return new Unknown(machInst); + } + } + ''' + classNames = { + "ldr" : loadImmClassName(False, True, False), + "str" : storeImmClassName(False, True, False), + "ldrh" : loadImmClassName(False, True, False, size=2), + "strh" : storeImmClassName(False, True, False, size=2), + "ldrb" : loadImmClassName(False, True, False, size=1), + "strb" : storeImmClassName(False, True, False, size=1), + } + decode_block = decode % classNames +}}; + +def format Thumb16MemLit() {{ + decode_block = ''' + { + const uint32_t rt = bits(machInst, 10, 8); + const uint32_t imm8 = bits(machInst, 7, 0); + return new %s(machInst, rt, INTREG_PC, true, imm8 << 2); + } + ''' % loadImmClassName(False, True, False) +}}; + diff -r 84bd4089958b src/arch/arm/isa/formats/misc.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/formats/misc.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,194 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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: Gabe Black + +def format Svc() {{ + decode_block = "return new Svc(machInst);" +}}; + +def format ArmMsrMrs() {{ + decode_block = ''' + { + const uint8_t byteMask = bits(machInst, 19, 16); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const uint32_t opcode = bits(machInst, 24, 21); + const bool useImm = bits(machInst, 25); + + const uint32_t unrotated = bits(machInst, 7, 0); + const uint32_t rotation = (bits(machInst, 11, 8) << 1); + const uint32_t imm = rotate_imm(unrotated, rotation); + + switch (opcode) { + case 0x8: + return new MrsCpsr(machInst, rd); + case 0x9: + if (useImm) { + return new MsrCpsrImm(machInst, imm, byteMask); + } else { + return new MsrCpsrReg(machInst, rn, byteMask); + } + case 0xa: + return new MrsSpsr(machInst, rd); + case 0xb: + if (useImm) { + return new MsrSpsrImm(machInst, imm, byteMask); + } else { + return new MsrSpsrReg(machInst, rn, byteMask); + } + default: + return new Unknown(machInst); + } + } + ''' +}}; + +let {{ + header_output = ''' + StaticInstPtr + decodeMcrMrc15(ExtMachInst machInst); + ''' + decoder_output = ''' + StaticInstPtr + decodeMcrMrc15(ExtMachInst machInst) + { + const uint32_t opc1 = bits(machInst, 23, 21); + const uint32_t crn = bits(machInst, 19, 16); + const uint32_t opc2 = bits(machInst, 7, 5); + const uint32_t crm = bits(machInst, 3, 0); + const MiscRegIndex miscReg = decodeCP15Reg(crn, opc1, crm, opc2); + const IntRegIndex rt = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + + const bool isRead = bits(machInst, 20); + + switch (miscReg) { + case MISCREG_NOP: + return new NopInst(machInst); + case NUM_MISCREGS: + return new Unknown(machInst); + case MISCREG_DCCISW: + return new WarnUnimplemented( + isRead ? "mrc dccisw" : "mcr dcisw", machInst); + case MISCREG_DCCIMVAC: + return new WarnUnimplemented( + isRead ? "mrc dccimvac" : "mcr dccimvac", machInst); + case MISCREG_DCIMVAC: + return new WarnUnimplemented( + isRead ? "mrc dcimvac" : "mcr dcimvac", machInst); + case MISCREG_DCCMVAC: + return new WarnUnimplemented( + isRead ? "mrc dccmvac" : "mcr dccmvac", machInst); + case MISCREG_CP15ISB: + return new WarnUnimplemented( + isRead ? "mrc cp15isb" : "mcr cp15isb", machInst); + case MISCREG_CP15DSB: + return new WarnUnimplemented( + isRead ? "mrc cp15dsb" : "mcr cp15dsb", machInst); + case MISCREG_CP15DMB: + return new WarnUnimplemented( + isRead ? "mrc cp15dmb" : "mcr cp15dmb", machInst); + case MISCREG_ICIALLUIS: + return new WarnUnimplemented( + isRead ? "mrc icialluis" : "mcr icialluis", machInst); + case MISCREG_ICIMVAU: + return new WarnUnimplemented( + isRead ? "mrc icimvau" : "mcr icimvau", machInst); + case MISCREG_BPIMVA: + return new WarnUnimplemented( + isRead ? "mrc bpimva" : "mcr bpimva", machInst); + case MISCREG_BPIALLIS: + return new WarnUnimplemented( + isRead ? "mrc bpiallis" : "mcr bpiallis", machInst); + case MISCREG_BPIALL: + return new WarnUnimplemented( + isRead ? "mrc bpiall" : "mcr bpiall", machInst); + + // Write only. + case MISCREG_TLBIALLIS: + case MISCREG_TLBIMVAIS: + case MISCREG_TLBIASIDIS: + case MISCREG_TLBIMVAAIS: + case MISCREG_ITLBIALL: + case MISCREG_ITLBIMVA: + case MISCREG_ITLBIASID: + case MISCREG_DTLBIALL: + case MISCREG_DTLBIMVA: + case MISCREG_DTLBIASID: + case MISCREG_TLBIALL: + case MISCREG_TLBIMVA: + case MISCREG_TLBIASID: + case MISCREG_TLBIMVAA: + if (isRead) { + return new Unknown(machInst); + } else { + return new Mcr15(machInst, (IntRegIndex)miscReg, rt); + } + + // Read only in user mode. + case MISCREG_TPIDRURO: + if (isRead) { + return new Mrc15User(machInst, rt, (IntRegIndex)miscReg); + } else { + return new Mcr15(machInst, (IntRegIndex)miscReg, rt); + } + + // Read/write in user mode. + case MISCREG_TPIDRURW: + if (isRead) { + return new Mrc15User(machInst, rt, (IntRegIndex)miscReg); + } else { + return new Mcr15User(machInst, (IntRegIndex)miscReg, rt); + } + + // Read/write, priveleged only. + default: + if (isRead) { + return new Mrc15(machInst, rt, (IntRegIndex)miscReg); + } else { + return new Mcr15(machInst, (IntRegIndex)miscReg, rt); + } + } + } + ''' +}}; + +def format McrMrc15() {{ + decode_block = ''' + return decodeMcrMrc15(machInst); + ''' +}}; diff -r 84bd4089958b src/arch/arm/isa/formats/mult.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/formats/mult.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,441 @@ +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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: Gabe Black + +def format ArmMultAndMultAcc() {{ + decode_block = ''' + { + // The manual defines this field as 23-20, but bit 20 is usually + // ignored. + const uint32_t op = bits(machInst, 23, 21); + const bool s = bits(machInst, 20); + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex ra = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + switch (op) { + case 0x0: + if (s) { + return new MulCc(machInst, rd, rm, rn); + } else { + return new Mul(machInst, rd, rm, rn); + } + case 0x1: + if (s) { + return new MlaCc(machInst, rd, rn, rm, ra); + } else { + return new Mla(machInst, rd, rn, rm, ra); + } + case 0x2: + return new Umaal(machInst, ra, rd, rn, rm); + case 0x3: + return new Mls(machInst, rd, rn, rm, ra); + case 0x4: + if (s) { + return new UmullCc(machInst, ra, rd, rn, rm); + } else { + return new Umull(machInst, ra, rd, rn, rm); + } + case 0x5: + if (s) { + return new UmlalCc(machInst, ra, rd, rn, rm); + } else { + return new Umlal(machInst, ra, rd, rn, rm); + } + case 0x6: + if (s) { + return new SmullCc(machInst, ra, rd, rn, rm); + } else { + return new Smull(machInst, ra, rd, rn, rm); + } + case 0x7: + if (s) { + return new SmlalCc(machInst, ra, rd, rn, rm); + } else { + return new Smlal(machInst, ra, rd, rn, rm); + } + } + } + ''' +}}; + +def format ArmHalfWordMultAndMultAcc() {{ + decode_block = ''' + { + const uint32_t op1 = bits(machInst, 22, 21); + const bool op = bits(machInst, 5); + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex ra = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + switch (op1) { + case 0x0: + switch (bits(machInst, 6, 5)) { + case 0x0: + return new SmlabbCc(machInst, rd, rn, rm, ra); + case 0x1: + return new SmlatbCc(machInst, rd, rn, rm, ra); + case 0x2: + return new SmlabtCc(machInst, rd, rn, rm, ra); + case 0x3: + return new SmlattCc(machInst, rd, rn, rm, ra); + } + case 0x1: + if (op) { + if (bits(machInst, 6)) { + return new Smulwt(machInst, rd, rn, rm); + } else { + return new Smulwb(machInst, rd, rn, rm); + } + } else { + if (bits(machInst, 6)) { + return new SmlawtCc(machInst, rd, rn, rm, ra); + } else { + return new SmlawbCc(machInst, rd, rn, rm, ra); + } + } + case 0x2: + switch (bits(machInst, 6, 5)) { + case 0x0: + return new Smlalbb(machInst, ra, rd, rn, rm); + case 0x1: + return new Smlaltb(machInst, ra, rd, rn, rm); + case 0x2: + return new Smlalbt(machInst, ra, rd, rn, rm); + case 0x3: + return new Smlaltt(machInst, ra, rd, rn, rm); + } + case 0x3: + switch (bits(machInst, 6, 5)) { + case 0x0: + return new Smulbb(machInst, rd, rn, rm); + case 0x1: + return new Smultb(machInst, rd, rn, rm); + case 0x2: + return new Smulbt(machInst, rd, rn, rm); + case 0x3: + return new Smultt(machInst, rd, rn, rm); + } + } + } + ''' +}}; + +def format Thumb32MulMulAccAndAbsDiff() {{ + decode_block = ''' + { + const uint32_t op1 = bits(machInst, 22, 20); + const uint32_t op2 = bits(machInst, 5, 4); + const IntRegIndex ra = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + if (op1 != 0x1 && bits(op2, 1) != 0) { + return new Unknown(machInst); + } + switch (op1) { + case 0x0: + if (op2 == 0) { + if (ra == 0xf) { + return new Mul(machInst, rd, rn, rm); + } else { + return new Mla(machInst, rd, rn, rm, ra); + } + } else { + return new Mls(machInst, rd, rn, rm, ra); + } + case 0x1: + if (ra == 0xf) { + switch (bits(machInst, 5, 4)) { + case 0x0: + return new Smulbb(machInst, rd, rn, rm); + case 0x1: + return new Smulbt(machInst, rd, rn, rm); + case 0x2: + return new Smultb(machInst, rd, rn, rm); + case 0x3: + return new Smultt(machInst, rd, rn, rm); + } + } else { + switch (bits(machInst, 5, 4)) { + case 0x0: + return new SmlabbCc(machInst, rd, rn, rm, ra); + case 0x1: + return new SmlabtCc(machInst, rd, rn, rm, ra); + case 0x2: + return new SmlatbCc(machInst, rd, rn, rm, ra); + case 0x3: + return new SmlattCc(machInst, rd, rn, rm, ra); + } + } + case 0x2: + if (ra == 0xf) { + if (bits(machInst, 4)) { + return new SmuadxCc(machInst, rd, rn, rm); + } else { + return new SmuadCc(machInst, rd, rn, rm); + } + } else { + if (bits(machInst, 4)) { + return new SmladxCc(machInst, rd, rn, rm, ra); + } else { + return new SmladCc(machInst, rd, rn, rm, ra); + } + } + case 0x3: + if (ra == 0xf) { + if (bits(machInst, 4)) { + return new Smulwt(machInst, rd, rn, rm); + } else { + return new Smulwb(machInst, rd, rn, rm); + } + } else { + if (bits(machInst, 4)) { + return new SmlawtCc(machInst, rd, rn, rm, ra); + } else { + return new SmlawbCc(machInst, rd, rn, rm, ra); + } + } + case 0x4: + if (ra == 0xf) { + if (bits(machInst, 4)) { + return new Smusdx(machInst, rd, rn, rm); + } else { + return new Smusd(machInst, rd, rn, rm); + } + } else { + if (bits(machInst, 4)) { + return new SmlsdxCc(machInst, rd, rn, rm, ra); + } else { + return new SmlsdCc(machInst, rd, rn, rm, ra); + } + } + case 0x5: + if (ra == 0xf) { + if (bits(machInst, 4)) { + return new Smmulr(machInst, rd, rn, rm); + } else { + return new Smmul(machInst, rd, rn, rm); + } + } else { + if (bits(machInst, 4)) { + return new Smmlar(machInst, rd, rn, rm, ra); + } else { + return new Smmla(machInst, rd, rn, rm, ra); + } + } + case 0x6: + if (bits(machInst, 4)) { + return new Smmlsr(machInst, rd, rn, rm, ra); + } else { + return new Smmls(machInst, rd, rn, rm, ra); + } + case 0x7: + if (op2 != 0x0) { + return new Unknown(machInst); + } else if (ra == 0xf) { + return new Usad8(machInst, rd, rn, rm); + } else { + return new Usada8(machInst, rd, rn, rm, ra); + } + } + } + ''' +}}; + +def format Thumb32LongMulMulAccAndDiv() {{ + decode_block = ''' + { + const uint32_t op1 = bits(machInst, 22, 20); + const uint32_t op2 = bits(machInst, 7, 4); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rdlo = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const IntRegIndex rdhi = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + switch (op1) { + case 0x0: + if (op2 == 0x0) { + return new Smull(machInst, rdlo, rdhi, rn, rm); + } + break; + case 0x1: + if (op2 == 0xf) { + return new Sdiv(machInst, rdhi, rn, rm); + } + break; + case 0x2: + if (op2 == 0x0) { + return new Umull(machInst, rdlo, rdhi, rn, rm); + } + break; + case 0x3: + if (op2 == 0xf) { + return new Udiv(machInst, rdhi, rn, rm); + } + break; + case 0x4: + if (op2 == 0) { + return new Smlal(machInst, rdlo, rdhi, rn, rm); + } else if (bits(op2, 3, 2) == 0x2) { + switch (bits(machInst, 5, 4)) { + case 0x0: + return new Smlalbb(machInst, rdlo, rdhi, rn, rm); + case 0x1: + return new Smlalbt(machInst, rdlo, rdhi, rn, rm); + case 0x2: + return new Smlaltb(machInst, rdlo, rdhi, rn, rm); + case 0x3: + return new Smlaltt(machInst, rdlo, rdhi, rn, rm); + } + } else if (bits(op2, 3, 1) == 0x6) { + if (bits(machInst, 4)) { + return new Smlaldx(machInst, rdlo, rdhi, rn, rm); + } else { + return new Smlald(machInst, rdlo, rdhi, rn, rm); + } + } + break; + case 0x5: + if (bits(op2, 3, 1) == 0x6) { + if (bits(machInst, 4)) { + return new Smlsldx(machInst, rdlo, rdhi, rn, rm); + } else { + return new Smlsld(machInst, rdlo, rdhi, rn, rm); + } + } + break; + case 0x6: + if (op2 == 0) { + return new Umlal(machInst, rdlo, rdhi, rn, rm); + } else if (op2 == 0x6) { + return new Umaal(machInst, rdlo, rdhi, rn, rm); + } + break; + } + return new Unknown(machInst); + } + ''' +}}; + +def format ArmSignedMultiplies() {{ + decode_block = ''' + { + const uint32_t op1 = bits(machInst, 22, 20); + // This is 7-5 in the manual, but bit 5 is always ignored. + const uint32_t op2 = bits(machInst, 7, 6); + const bool aIsF = (bits(machInst, 15, 12) == 0xf); + const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); + const IntRegIndex ra = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); + const bool m = bits(machInst, 5); + switch (op1) { + case 0x0: + if (op2 == 0) { + if (aIsF) { + if (m) { + return new SmuadxCc(machInst, rd, rn, rm); + } else { + return new SmuadCc(machInst, rd, rn, rm); + } + } else { + if (m) { + return new SmladxCc(machInst, rd, rn, rm, ra); + } else { + return new SmladCc(machInst, rd, rn, rm, ra); + } + } + } else if (op2 == 1) { + if (aIsF) { + if (m) { + return new Smusdx(machInst, rd, rn, rm); + } else { + return new Smusd(machInst, rd, rn, rm); + } + } else { + if (m) { + return new SmlsdxCc(machInst, rd, rn, rm, ra); + } else { + return new SmlsdCc(machInst, rd, rn, rm, ra); + } + } + } + break; + case 0x4: + if (op2 == 0) { + if (m) { + return new Smlaldx(machInst, ra, rd, rn, rm); + } else { + return new Smlald(machInst, ra, rd, rn, rm); + } + } else if (op2 == 1) { + if (m) { + return new Smlsldx(machInst, ra, rd, rn, rm); + } else { + return new Smlsld(machInst, ra, rd, rn, rm); + } + } + break; + case 0x5: + if (op2 == 0) { + if (aIsF) { + if (m) { + return new Smmulr(machInst, rd, rn, rm); + } else { + return new Smmul(machInst, rd, rn, rm); + } + } else { + if (m) { + return new Smmlar(machInst, rd, rn, rm, ra); + } else { + return new Smmla(machInst, rd, rn, rm, ra); + } + } + } else if (op2 == 0x3) { + if (m) { + return new Smmlsr(machInst, rd, rn, rm, ra); + } else { + return new Smmls(machInst, rd, rn, rm, ra); + } + } + break; + default: + break; + } + return new Unknown(machInst); + } + ''' +}}; diff -r 84bd4089958b src/arch/arm/isa/formats/pred.isa --- a/src/arch/arm/isa/formats/pred.isa Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/isa/formats/pred.isa Wed May 26 18:10:45 2010 -0500 @@ -1,5 +1,17 @@ // -*- mode:c++ -*- +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// // Copyright (c) 2007-2008 The Florida State University // All rights reserved. // @@ -28,58 +40,6 @@ // // Authors: Stephen Hines -//////////////////////////////////////////////////////////////////// -// -// Predicated Instruction Execution -// - -let {{ - predicateTest = 'testPredicate(CondCodes, condCode)' -}}; - -def template PredOpExecute {{ - Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const - { - Fault fault = NoFault; - uint64_t resTemp = 0; - resTemp = resTemp; - %(op_decl)s; - %(op_rd)s; - - if (%(predicate_test)s) - { - %(code)s; - if (fault == NoFault) - { - %(op_wb)s; - } - } - - return fault; - } -}}; - -def template DataDecode {{ - if (machInst.opcode4 == 0) { - if (machInst.sField == 0) - return new %(class_name)sImm(machInst); - else - return new %(class_name)sImmCc(machInst); - } else { - if (machInst.sField == 0) - return new %(class_name)s(machInst); - else - return new %(class_name)sCc(machInst); - } -}}; - -def template DataImmDecode {{ - if (machInst.sField == 0) - return new %(class_name)s(machInst); - else - return new %(class_name)sCc(machInst); -}}; - let {{ calcCcCode = ''' @@ -165,6 +125,9 @@ elif flagtype == "rsb": icValue = 'findCarry(32, resTemp, rotated_imm, ~Rn)' ivValue = 'findOverflow(32, resTemp, rotated_imm, ~Rn)' + elif flagtype == "modImm": + icValue = 'rotated_carry' + ivValue = 'CondCodes<28:>' else: icValue = '(rotate ? rotated_carry:CondCodes<29:>)' ivValue = 'CondCodes<28:>' @@ -187,10 +150,10 @@ "predicate_test": predicateTest}) regCcIop = InstObjParams(name, Name + "Cc", 'PredIntOp', {"code": regCode + regCcCode, - "predicate_test": predicateTest}) + "predicate_test": condPredicateTest}) immCcIop = InstObjParams(name, Name + "ImmCc", 'PredIntOp', {"code": immCode + immCcCode, - "predicate_test": predicateTest}) + "predicate_test": condPredicateTest}) header_output = BasicDeclare.subst(regIop) + \ BasicDeclare.subst(immIop) + \ BasicDeclare.subst(regCcIop) + \ @@ -213,7 +176,7 @@ "predicate_test": predicateTest}) ccIop = InstObjParams(name, Name + "Cc", 'PredImmOp', {"code": code + getImmCcCode(flagtype), - "predicate_test": predicateTest}) + "predicate_test": condPredicateTest}) header_output = BasicDeclare.subst(iop) + \ BasicDeclare.subst(ccIop) decoder_output = BasicConstructor.subst(iop) + \ @@ -245,44 +208,3 @@ 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, - "predicate_test": predicateTest}, - 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', - {"code": new_code, - "predicate_test": predicateTest}, - 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, - "predicate_test": predicateTest}, - opt_flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecode.subst(iop) - exec_output = PredOpExecute.subst(iop) -}}; - diff -r 84bd4089958b src/arch/arm/isa/formats/uncond.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/formats/uncond.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,321 @@ +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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: Gabe Black + +def format ArmUnconditional() {{ + decode_block = ''' + { + const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); + const uint32_t op1 = bits(machInst, 27, 20); + if (bits(op1, 7) == 0) { + const uint32_t op2 = bits(machInst, 7, 4); + if (op1 == 0x10) { + if (bits((uint32_t)rn, 0) == 1 && op2 == 0) { + return new Setend(machInst, bits(machInst, 9)); + } else if (bits((uint32_t)rn, 0) == 0 && bits(op2, 1) == 0) { + const bool enable = bits(machInst, 19, 18) == 0x2; + const uint32_t mods = bits(machInst, 4, 0) | + (bits(machInst, 8, 6) << 5) | + (bits(machInst, 17) << 8) | + ((enable ? 1 : 0) << 9); + return new Cps(machInst, mods); + } + } else if (bits(op1, 6, 5) == 0x1) { + return decodeNeonData(machInst); + } else if (bits(op1, 6, 4) == 0x4) { + if (bits(op1, 0) == 0) { + return decodeNeonMem(machInst); + } else if (bits(op1, 2, 0) == 1) { + // Unallocated memory hint + return new NopInst(machInst); + } else if (bits(op1, 2, 0) == 5) { + const bool add = bits(machInst, 23); + const uint32_t imm12 = bits(machInst, 11, 0); + if (add) { + return new %(pli_iadd)s(machInst, INTREG_ZERO, + rn, add, imm12); + } else { + return new %(pli_isub)s(machInst, INTREG_ZERO, + rn, add, imm12); + } + } + } else if (bits(op1, 6, 4) == 0x5) { + if (bits(op1, 1, 0) == 0x1) { + const bool add = bits(machInst, 23); + const bool pldw = bits(machInst, 22); + const uint32_t imm12 = bits(machInst, 11, 0); + if (pldw) { + if (add) { + return new %(pldw_iadd)s(machInst, INTREG_ZERO, + rn, add, imm12); + } else { + return new %(pldw_isub)s(machInst, INTREG_ZERO, + rn, add, imm12); + } + } else { + if (add) { + return new %(pld_iadd)s(machInst, INTREG_ZERO, + rn, add, imm12); + } else { + return new %(pld_isub)s(machInst, INTREG_ZERO, + rn, add, imm12); + } + } + } else if (op1 == 0x57) { + switch (op2) { + case 0x1: + return new WarnUnimplemented("clrex", machInst); + case 0x4: + return new WarnUnimplemented("dsb", machInst); + case 0x5: + return new WarnUnimplemented("dmb", machInst); + case 0x6: + return new WarnUnimplemented("isb", machInst); + } + } + } else if (bits(op2, 0) == 0) { + switch (op1 & 0xf7) { + case 0x61: + // Unallocated memory hint + return new NopInst(machInst); + case 0x65: + { + const uint32_t imm5 = bits(machInst, 11, 7); + const uint32_t type = bits(machInst, 6, 5); + const bool add = bits(machInst, 23); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + if (add) { + return new %(pli_radd)s(machInst, INTREG_ZERO, rn, + add, imm5, type, rm); + } else { + return new %(pli_rsub)s(machInst, INTREG_ZERO, rn, + add, imm5, type, rm); + } + } + case 0x71: + case 0x75: + { + const uint32_t imm5 = bits(machInst, 11, 7); + const uint32_t type = bits(machInst, 6, 5); + const bool add = bits(machInst, 23); + const bool pldw = bits(machInst, 22); + const IntRegIndex rm = + (IntRegIndex)(uint32_t)bits(machInst, 3, 0); + if (pldw) { + if (add) { + return new %(pldw_radd)s(machInst, INTREG_ZERO, + rn, add, imm5, + type, rm); + } else { + return new %(pldw_rsub)s(machInst, INTREG_ZERO, + rn, add, imm5, + type, rm); + } + } else { + if (add) { + return new %(pld_radd)s(machInst, INTREG_ZERO, + rn, add, imm5, + type, rm); + } else { + return new %(pld_rsub)s(machInst, INTREG_ZERO, + rn, add, imm5, + type, rm); + } + } + } + } + } + } else { + switch (bits(machInst, 26, 25)) { + case 0x0: + { + const uint32_t val = ((machInst >> 20) & 0x5); + if (val == 0x4) { + const uint32_t mode = bits(machInst, 4, 0); + switch (bits(machInst, 24, 21)) { + case 0x2: + return new %(srs)s(machInst, mode, + SrsOp::DecrementAfter, false); + case 0x3: + return new %(srs_w)s(machInst, mode, + SrsOp::DecrementAfter, true); + case 0x6: + return new %(srs_u)s(machInst, mode, + SrsOp::IncrementAfter, false); + case 0x7: + return new %(srs_uw)s(machInst, mode, + SrsOp::IncrementAfter, true); + case 0xa: + return new %(srs_p)s(machInst, mode, + SrsOp::DecrementBefore, false); + case 0xb: + return new %(srs_pw)s(machInst, mode, + SrsOp::DecrementBefore, true); + case 0xe: + return new %(srs_pu)s(machInst, mode, + SrsOp::IncrementBefore, false); + case 0xf: + return new %(srs_puw)s(machInst, mode, + SrsOp::IncrementBefore, true); + } + return new Unknown(machInst); + } else if (val == 0x1) { + switch (bits(machInst, 24, 21)) { + case 0x0: + return new %(rfe)s(machInst, rn, + RfeOp::DecrementAfter, false); + case 0x1: + return new %(rfe_w)s(machInst, rn, + RfeOp::DecrementAfter, true); + case 0x4: + return new %(rfe_u)s(machInst, rn, + RfeOp::IncrementAfter, false); + case 0x5: + return new %(rfe_uw)s(machInst, rn, + RfeOp::IncrementAfter, true); + case 0x8: + return new %(rfe_p)s(machInst, rn, + RfeOp::DecrementBefore, false); + case 0x9: + return new %(rfe_pw)s(machInst, rn, + RfeOp::DecrementBefore, true); + case 0xc: + return new %(rfe_pu)s(machInst, rn, + RfeOp::IncrementBefore, false); + case 0xd: + return new %(rfe_puw)s(machInst, rn, + RfeOp::IncrementBefore, true); + } + return new Unknown(machInst); + } + } + break; + case 0x1: + { + const uint32_t imm = + (sext<26>(bits(machInst, 23, 0) << 2)) | + (bits(machInst, 24) << 1); + return new BlxImm(machInst, imm); + } + case 0x2: + if (bits(op1, 4, 0) != 0) { + if (CPNUM == 0xa || CPNUM == 0xb) { + return decodeExtensionRegLoadStore(machInst); + } + if (bits(op1, 0) == 1) { + if (rn == INTREG_PC) { + if (bits(op1, 4, 3) != 0x0) { + return new WarnUnimplemented( + "ldc, ldc2 (literal)", machInst); + } + } else { + if (op1 == 0xC3 || op1 == 0xC7) { + return new WarnUnimplemented( + "ldc, ldc2 (immediate)", machInst); + } + } + if (op1 == 0xC5) { + return new WarnUnimplemented( + "mrrc, mrrc2", machInst); + } + } else { + if (bits(op1, 4, 3) != 0 || bits(op1, 1) == 1) { + return new WarnUnimplemented( + "stc, stc2", machInst); + } else if (op1 == 0xC4) { + return new WarnUnimplemented( + "mcrr, mcrrc", machInst); + } + } + } + break; + case 0x3: + if (bits(op1, 4) == 0) { + if (CPNUM == 0xa || CPNUM == 0xb) { + return decodeShortFpTransfer(machInst); + } else if (CPNUM == 0xf) { + return decodeMcrMrc15(machInst); + } + const bool op = bits(machInst, 4); + if (op) { + if (bits(op1, 0)) { + return new WarnUnimplemented( + "mrc, mrc2", machInst); + } else { + return new WarnUnimplemented( + "mcr, mcr2", machInst); + } + } else { + return new WarnUnimplemented("cdp, cdp2", machInst); + } + } + break; + } + } + return new Unknown(machInst); + } + ''' % { + "pli_iadd" : "PLI_" + loadImmClassName(False, True, False, 1), + "pli_isub" : "PLI_" + loadImmClassName(False, False, False, 1), + "pld_iadd" : "PLD_" + loadImmClassName(False, True, False, 1), + "pld_isub" : "PLD_" + loadImmClassName(False, False, False, 1), + "pldw_iadd" : "PLDW_" + loadImmClassName(False, True, False, 1), + "pldw_isub" : "PLDW_" + loadImmClassName(False, False, False, 1), + "pli_radd" : "PLI_" + loadRegClassName(False, True, False, 1), + "pli_rsub" : "PLI_" + loadRegClassName(False, False, False, 1), + "pld_radd" : "PLD_" + loadRegClassName(False, True, False, 1), + "pld_rsub" : "PLD_" + loadRegClassName(False, False, False, 1), + "pldw_radd" : "PLDW_" + loadRegClassName(False, True, False, 1), + "pldw_rsub" : "PLDW_" + loadRegClassName(False, False, False, 1), + "rfe" : "RFE_" + loadImmClassName(True, False, False, 8), + "rfe_w" : "RFE_" + loadImmClassName(True, False, True, 8), + "rfe_u" : "RFE_" + loadImmClassName(True, True, False, 8), + "rfe_uw" : "RFE_" + loadImmClassName(True, True, True, 8), + "rfe_p" : "RFE_" + loadImmClassName(False, False, False, 8), + "rfe_pw" : "RFE_" + loadImmClassName(False, False, True, 8), + "rfe_pu" : "RFE_" + loadImmClassName(False, True, False, 8), + "rfe_puw" : "RFE_" + loadImmClassName(False, True, True, 8), + "srs" : "SRS_" + storeImmClassName(True, False, False, 8), + "srs_w" : "SRS_" + storeImmClassName(True, False, True, 8), + "srs_u" : "SRS_" + storeImmClassName(True, True, False, 8), + "srs_uw" : "SRS_" + storeImmClassName(True, True, True, 8), + "srs_p" : "SRS_" + storeImmClassName(False, False, False, 8), + "srs_pw" : "SRS_" + storeImmClassName(False, False, True, 8), + "srs_pu" : "SRS_" + storeImmClassName(False, True, False, 8), + "srs_puw" : "SRS_" + storeImmClassName(False, True, True, 8) + }; +}}; diff -r 84bd4089958b src/arch/arm/isa/formats/unimp.isa --- a/src/arch/arm/isa/formats/unimp.isa Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/isa/formats/unimp.isa Wed May 26 18:10:45 2010 -0500 @@ -1,5 +1,17 @@ // -*- mode:c++ -*- +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// // Copyright (c) 2007-2008 The Florida State University // All rights reserved. // @@ -45,7 +57,7 @@ { public: /// Constructor - FailUnimplemented(const char *_mnemonic, MachInst _machInst) + FailUnimplemented(const char *_mnemonic, ExtMachInst _machInst) : ArmStaticInst(_mnemonic, _machInst, No_OpClass) { // don't call execute() (which panics) if we're on a @@ -76,7 +88,7 @@ public: /// Constructor - WarnUnimplemented(const char *_mnemonic, MachInst _machInst) + WarnUnimplemented(const char *_mnemonic, ExtMachInst _machInst) : ArmStaticInst(_mnemonic, _machInst, No_OpClass), warned(false) { // don't call execute() (which panics) if we're on a @@ -112,10 +124,11 @@ 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 UnimpFault("Unimplemented Instruction"); +#if FULL_SYSTEM + return new UndefinedInstruction; +#else + return new UndefinedInstruction(machInst, false, mnemonic); +#endif } Fault diff -r 84bd4089958b src/arch/arm/isa/formats/unknown.isa --- a/src/arch/arm/isa/formats/unknown.isa Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/isa/formats/unknown.isa Wed May 26 18:10:45 2010 -0500 @@ -1,5 +1,17 @@ // -*- mode:c++ -*- +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// // Copyright (c) 2007-2008 The Florida State University // All rights reserved. // @@ -28,56 +40,6 @@ // // 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(ExtMachInst _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 UnimpFault("Unimplemented Instruction"); - } -}}; - def format Unknown() {{ decode_block = 'return new Unknown(machInst);\n' }}; diff -r 84bd4089958b src/arch/arm/isa/formats/util.isa --- a/src/arch/arm/isa/formats/util.isa Tue May 25 20:15:44 2010 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,129 +0,0 @@ -// -*- 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, CondCodes<29:>)', code) - new_code = re.sub(r'Rm_Rs', - 'shift_rm_rs(Rm, Rs, shift, CondCodes<29:>)', new_code) - return new_code - -def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, - 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) - - iop = InstObjParams(name, Name, base_class, - {'ea_code': ea_code, - 'memacc_code': memacc_code, - 'predicate_test': predicateTest}, - 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 - - 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), - LoadStoreConstructor.subst(iop), - decode_template.subst(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; - } - - // Emits uops for a double fp move - void - emit_ldfstf_uops(StaticInstPtr* microOps, int index, ExtMachInst machInst, - bool loadop, bool up, int32_t disp) - { - if (loadop) - { - microOps[index++] = new MicroLdrUop(machInst, 19, RN, disp); - microOps[index++] = - new MicroLdrUop(machInst, 18, RN, disp + (up ? 4 : -4)); - microOps[index++] = new MicroMvtdUop(machInst); - } - else - { - microOps[index++] = new MicroMvfdUop(machInst); - microOps[index++] = new MicroStrUop(machInst, 19, RN, disp); - microOps[index++] = - new MicroStrUop(machInst, 18, RN, disp + (up ? 4 : -4)); - } - } - -}}; - - diff -r 84bd4089958b src/arch/arm/isa/includes.isa --- a/src/arch/arm/isa/includes.isa Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/isa/includes.isa Wed May 26 18:10:45 2010 -0500 @@ -1,5 +1,17 @@ // -*- mode:c++ -*- +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// // Copyright (c) 2007-2008 The Florida State University // All rights reserved. // @@ -36,25 +48,22 @@ output header {{ #include #include -#include #include "arch/arm/insts/branch.hh" #include "arch/arm/insts/macromem.hh" #include "arch/arm/insts/mem.hh" +#include "arch/arm/insts/misc.hh" +#include "arch/arm/insts/mult.hh" #include "arch/arm/insts/pred_inst.hh" #include "arch/arm/insts/static_inst.hh" +#include "arch/arm/insts/vfp.hh" #include "arch/arm/isa_traits.hh" -#include "cpu/static_inst.hh" #include "mem/packet.hh" }}; output decoder {{ -#include -#if defined(linux) -#include -#endif - #include "arch/arm/faults.hh" +#include "arch/arm/intregs.hh" #include "arch/arm/isa_traits.hh" #include "arch/arm/utility.hh" #include "base/cprintf.hh" @@ -62,7 +71,6 @@ #include "cpu/thread_context.hh" using namespace ArmISA; -using std::isnan; }}; output exec {{ @@ -70,14 +78,13 @@ #include "arch/arm/isa_traits.hh" #include "arch/arm/utility.hh" #include "base/condcodes.hh" +#include "sim/pseudo_inst.hh" #include #if defined(linux) #include #endif -#include "cpu/base.hh" -#include "cpu/exetrace.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" #include "sim/sim_exit.hh" diff -r 84bd4089958b src/arch/arm/isa/insts/basic.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/insts/basic.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,34 @@ +// -*- 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; +}}; diff -r 84bd4089958b src/arch/arm/isa/insts/branch.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/insts/branch.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,182 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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: Gabe Black + +let {{ + + header_output = "" + decoder_output = "" + exec_output = "" + + # B, BL + for (mnem, link) in (("b", False), ("bl", True)): + bCode = ''' + Addr PC = readPC(xc); + NPC = ((PC + imm) & mask(32)) | (PC & ~mask(32)); + ''' + if (link): + bCode += ''' + Addr tBit = PC & (ULL(1) << PcTBitShift); + if (!tBit) + LR = PC - 4; + else + LR = PC | 1; + ''' + + bIop = InstObjParams(mnem, mnem.capitalize(), "BranchImmCond", + {"code": bCode, + "predicate_test": predicateTest}) + header_output += BranchImmCondDeclare.subst(bIop) + decoder_output += BranchImmCondConstructor.subst(bIop) + exec_output += PredOpExecute.subst(bIop) + + # BX, BLX + blxCode = ''' + Addr PC = readPC(xc); + Addr tBit = PC & (ULL(1) << PcTBitShift); + bool arm = !tBit; + arm = arm; // In case it's not used otherwise. + %(link)s + // Switch modes + %(branch)s + ''' + + blxList = (("blx", True, True), + ("blx", False, True), + ("bx", False, False)) + + for (mnem, imm, link) in blxList: + Name = mnem.capitalize() + if imm: + Name += "Imm" + # Since we're switching ISAs, the target ISA will be the opposite + # of the current ISA. !arm is whether the target is ARM. + newPC = '(!arm ? (roundDown(PC, 4) + imm) : (PC + imm))' + base = "BranchImm" + declare = BranchImmDeclare + constructor = BranchImmConstructor + else: + Name += "Reg" + newPC = 'Op1' + base = "BranchRegCond" + declare = BranchRegCondDeclare + constructor = BranchRegCondConstructor + if link and imm: + linkStr = ''' + // The immediate version of the blx thumb instruction + // is 32 bits wide, but "next pc" doesn't reflect that + // so we don't want to substract 2 from it at this point + if (arm) + LR = PC - 4; + else + LR = PC | 1; + ''' + elif link: + linkStr = ''' + if (arm) + LR = PC - 4; + else + LR = (PC - 2) | 1; + ''' + else: + linkStr = "" + + if imm and link: #blx with imm + branchStr = ''' + Addr tempPc = ((%(newPC)s) & mask(32)) | (PC & ~mask(32)); + FNPC = tempPc ^ (ULL(1) << PcTBitShift); + ''' + else: + branchStr = "IWNPC = %(newPC)s;" + branchStr = branchStr % { "newPC" : newPC } + + code = blxCode % {"link": linkStr, + "newPC": newPC, + "branch": branchStr} + blxIop = InstObjParams(mnem, Name, base, + {"code": code, + "predicate_test": predicateTest}) + header_output += declare.subst(blxIop) + decoder_output += constructor.subst(blxIop) + exec_output += PredOpExecute.subst(blxIop) + + #Ignore BXJ for now + + #CBNZ, CBZ. These are always unconditional as far as predicates + for (mnem, test) in (("cbz", "=="), ("cbnz", "!=")): + code = ''' + Addr PC = readPC(xc); + NPC = ((PC + imm) & mask(32)) | (PC & ~mask(32)); + ''' + predTest = "Op1 %(test)s 0" % {"test": test} + iop = InstObjParams(mnem, mnem.capitalize(), "BranchImmReg", + {"code": code, "predicate_test": predTest}) + header_output += BranchImmRegDeclare.subst(iop) + decoder_output += BranchImmRegConstructor.subst(iop) + exec_output += PredOpExecute.subst(iop) + + #TBB, TBH + for isTbh in (0, 1): + if isTbh: + eaCode = ''' + unsigned memAccessFlags = ArmISA::TLB::AllowUnaligned | + ArmISA::TLB::AlignHalfWord | + ArmISA::TLB::MustBeOne; + EA = Op1 + Op2 * 2 + ''' + accCode = "NPC = readPC(xc) + 2 * (Mem.uh);" + mnem = "tbh" + else: + eaCode = ''' + unsigned memAccessFlags = ArmISA::TLB::AllowUnaligned | + ArmISA::TLB::AlignByte | + ArmISA::TLB::MustBeOne; + EA = Op1 + Op2 + ''' + accCode = "NPC = readPC(xc) + 2 * (Mem.ub);" + mnem = "tbb" + iop = InstObjParams(mnem, mnem.capitalize(), "BranchRegReg", + {'ea_code': eaCode, + 'memacc_code': accCode, + 'predicate_test': predicateTest}) + header_output += BranchTableDeclare.subst(iop) + decoder_output += BranchRegRegConstructor.subst(iop) + exec_output += LoadExecute.subst(iop) + \ + LoadInitiateAcc.subst(iop) + \ + LoadCompleteAcc.subst(iop) +}}; diff -r 84bd4089958b src/arch/arm/isa/insts/data.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/insts/data.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,813 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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: Gabe Black + +let {{ + + header_output = "" + decoder_output = "" + exec_output = "" + + calcGECode = ''' + CondCodes = insertBits(CondCodes, 19, 16, resTemp); + ''' + + calcQCode = ''' + CondCodes = CondCodes | ((resTemp & 1) << 27); + ''' + + calcCcCode = ''' + uint16_t _ic, _iv, _iz, _in; + _in = (resTemp >> %(negBit)d) & 1; + _iz = (resTemp == 0); + _iv = %(ivValue)s & 1; + _ic = %(icValue)s & 1; + + CondCodes = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 | + (CondCodes & 0x0FFFFFFF); + + DPRINTF(Arm, "(in, iz, ic, iv) = (%%d, %%d, %%d, %%d)\\n", + _in, _iz, _ic, _iv); + ''' + + # Dict of code to set the carry flag. (imm, reg, reg-reg) + oldC = 'CondCodes<29:>' + oldV = 'CondCodes<28:>' + carryCode = { + "none": (oldC, oldC, oldC), + "llbit": (oldC, oldC, oldC), + "saturate": ('0', '0', '0'), + "overflow": ('0', '0', '0'), + "ge": ('0', '0', '0'), + "add": ('findCarry(32, resTemp, Op1, secondOp)', + 'findCarry(32, resTemp, Op1, secondOp)', + 'findCarry(32, resTemp, Op1, secondOp)'), + "sub": ('findCarry(32, resTemp, Op1, ~secondOp)', + 'findCarry(32, resTemp, Op1, ~secondOp)', + 'findCarry(32, resTemp, Op1, ~secondOp)'), + "rsb": ('findCarry(32, resTemp, secondOp, ~Op1)', + 'findCarry(32, resTemp, secondOp, ~Op1)', + 'findCarry(32, resTemp, secondOp, ~Op1)'), + "logic": ('(rotC ? bits(secondOp, 31) : %s)' % oldC, + 'shift_carry_imm(Op2, shiftAmt, shiftType, %s)' % oldC, + 'shift_carry_rs(Op2, Shift<7:0>, shiftType, %s)' % oldC) + } + # Dict of code to set the overflow flag. + overflowCode = { + "none": oldV, + "llbit": oldV, + "saturate": '0', + "overflow": '0', + "ge": '0', + "add": 'findOverflow(32, resTemp, Op1, secondOp)', + "sub": 'findOverflow(32, resTemp, Op1, ~secondOp)', + "rsb": 'findOverflow(32, resTemp, secondOp, ~Op1)', + "logic": oldV + } + + secondOpRe = re.compile("secondOp") + immOp2 = "imm" + regOp2 = "shift_rm_imm(Op2, shiftAmt, shiftType, CondCodes<29:>)" + regRegOp2 = "shift_rm_rs(Op2, Shift<7:0>, shiftType, CondCodes<29:>)" + + def buildImmDataInst(mnem, code, flagType = "logic", suffix = "Imm", \ + buildCc = True, buildNonCc = True): + cCode = carryCode[flagType] + vCode = overflowCode[flagType] + negBit = 31 + if flagType == "llbit": + negBit = 63 + if flagType == "saturate": + immCcCode = calcQCode + elif flagType == "ge": + immCcCode = calcGECode + else: + immCcCode = calcCcCode % { + "icValue": secondOpRe.sub(immOp2, cCode[0]), + "ivValue": secondOpRe.sub(immOp2, vCode), + "negBit": negBit + } + immCode = secondOpRe.sub(immOp2, code) + immIop = InstObjParams(mnem, mnem.capitalize() + suffix, "DataImmOp", + {"code" : immCode, + "predicate_test": predicateTest}) + immIopCc = InstObjParams(mnem + "s", mnem.capitalize() + suffix + "Cc", + "DataImmOp", + {"code" : immCode + immCcCode, + "predicate_test": condPredicateTest}) + + def subst(iop): + global header_output, decoder_output, exec_output + header_output += DataImmDeclare.subst(iop) + decoder_output += DataImmConstructor.subst(iop) + exec_output += PredOpExecute.subst(iop) + + if buildNonCc: + subst(immIop) + if buildCc: + subst(immIopCc) + + def buildRegDataInst(mnem, code, flagType = "logic", suffix = "Reg", \ + buildCc = True, buildNonCc = True): + cCode = carryCode[flagType] + vCode = overflowCode[flagType] + negBit = 31 + if flagType == "llbit": + negBit = 63 + if flagType == "saturate": + regCcCode = calcQCode + elif flagType == "ge": + regCcCode = calcGECode + else: + regCcCode = calcCcCode % { + "icValue": secondOpRe.sub(regOp2, cCode[1]), + "ivValue": secondOpRe.sub(regOp2, vCode), + "negBit": negBit + } + regCode = secondOpRe.sub(regOp2, code) + regIop = InstObjParams(mnem, mnem.capitalize() + suffix, "DataRegOp", + {"code" : regCode, + "predicate_test": predicateTest}) + regIopCc = InstObjParams(mnem + "s", mnem.capitalize() + suffix + "Cc", + "DataRegOp", + {"code" : regCode + regCcCode, + "predicate_test": condPredicateTest}) + + def subst(iop): + global header_output, decoder_output, exec_output + header_output += DataRegDeclare.subst(iop) + decoder_output += DataRegConstructor.subst(iop) + exec_output += PredOpExecute.subst(iop) + + if buildNonCc: + subst(regIop) + if buildCc: + subst(regIopCc) + + def buildRegRegDataInst(mnem, code, flagType = "logic", \ + suffix = "RegReg", \ + buildCc = True, buildNonCc = True): + cCode = carryCode[flagType] + vCode = overflowCode[flagType] + negBit = 31 + if flagType == "llbit": + negBit = 63 + if flagType == "saturate": + regRegCcCode = calcQCode + elif flagType == "ge": + regRegCcCode = calcGECode + else: + regRegCcCode = calcCcCode % { + "icValue": secondOpRe.sub(regRegOp2, cCode[2]), + "ivValue": secondOpRe.sub(regRegOp2, vCode), + "negBit": negBit + } + regRegCode = secondOpRe.sub(regRegOp2, code) + regRegIop = InstObjParams(mnem, mnem.capitalize() + suffix, + "DataRegRegOp", + {"code" : regRegCode, + "predicate_test": predicateTest}) + regRegIopCc = InstObjParams(mnem + "s", + mnem.capitalize() + suffix + "Cc", + "DataRegRegOp", + {"code" : regRegCode + regRegCcCode, + "predicate_test": condPredicateTest}) + + def subst(iop): + global header_output, decoder_output, exec_output + header_output += DataRegRegDeclare.subst(iop) + decoder_output += DataRegRegConstructor.subst(iop) + exec_output += PredOpExecute.subst(iop) + + if buildNonCc: + subst(regRegIop) + if buildCc: + subst(regRegIopCc) + + def buildDataInst(mnem, code, flagType = "logic", \ + aiw = True, regRegAiw = True, + subsPcLr = True): + regRegCode = instCode = code + if aiw: + instCode = "AIW" + instCode + if regRegAiw: + regRegCode = "AIW" + regRegCode + + buildImmDataInst(mnem, instCode, flagType) + buildRegDataInst(mnem, instCode, flagType) + buildRegRegDataInst(mnem, regRegCode, flagType) + if subsPcLr: + code += ''' + SCTLR sctlr = Sctlr; + uint32_t newCpsr = + cpsrWriteByInstr(Cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi); + Cpsr = ~CondCodesMask & newCpsr; + CondCodes = CondCodesMask & newCpsr; + ''' + buildImmDataInst(mnem + 's', code, flagType, + suffix = "ImmPclr", buildCc = False) + buildRegDataInst(mnem + 's', code, flagType, + suffix = "RegPclr", buildCc = False) + + buildDataInst("and", "Dest = resTemp = Op1 & secondOp;") + buildDataInst("eor", "Dest = resTemp = Op1 ^ secondOp;") + buildDataInst("sub", "Dest = resTemp = Op1 - secondOp;", "sub") + buildDataInst("rsb", "Dest = resTemp = secondOp - Op1;", "rsb") + buildDataInst("add", "Dest = resTemp = Op1 + secondOp;", "add") + buildImmDataInst("adr", ''' + Dest = resTemp = (readPC(xc) & ~0x3) + + (op1 ? secondOp : -secondOp); + ''') + buildDataInst("adc", "Dest = resTemp = Op1 + secondOp + %s;" % oldC, "add") + buildDataInst("sbc", "Dest = resTemp = Op1 - secondOp - !%s;" % oldC, "sub") + buildDataInst("rsc", "Dest = resTemp = secondOp - Op1 - !%s;" % oldC, "rsb") + buildDataInst("tst", "resTemp = Op1 & secondOp;", aiw = False) + buildDataInst("teq", "resTemp = Op1 ^ secondOp;", aiw = False) + buildDataInst("cmp", "resTemp = Op1 - secondOp;", "sub", aiw = False) + buildDataInst("cmn", "resTemp = Op1 + secondOp;", "add", aiw = False) + buildDataInst("orr", "Dest = resTemp = Op1 | secondOp;") + buildDataInst("orn", "Dest = resTemp = Op1 | ~secondOp;", aiw = False) + buildDataInst("mov", "Dest = resTemp = secondOp;", regRegAiw = False) + buildDataInst("bic", "Dest = resTemp = Op1 & ~secondOp;") + buildDataInst("mvn", "Dest = resTemp = ~secondOp;") + buildDataInst("movt", + "Dest = resTemp = insertBits(Op1, 31, 16, secondOp);", + aiw = False) + + buildRegDataInst("qadd", ''' + int32_t midRes; + resTemp = saturateOp<32>(midRes, Op1.sw, Op2.sw); + Dest = midRes; + ''', flagType="saturate", buildNonCc=False) + buildRegDataInst("qadd16", ''' + int32_t midRes; + for (unsigned i = 0; i < 2; i++) { + int high = (i + 1) * 16 - 1; + int low = i * 16; + int64_t arg1 = sext<16>(bits(Op1.sw, high, low)); + int64_t arg2 = sext<16>(bits(Op2.sw, high, low)); + saturateOp<16>(midRes, arg1, arg2); + replaceBits(resTemp, high, low, midRes); + } + Dest = resTemp; + ''', flagType="none", buildCc=False) + buildRegDataInst("qadd8", ''' + int32_t midRes; + for (unsigned i = 0; i < 4; i++) { + int high = (i + 1) * 8 - 1; + int low = i * 8; + int64_t arg1 = sext<8>(bits(Op1.sw, high, low)); + int64_t arg2 = sext<8>(bits(Op2.sw, high, low)); + saturateOp<8>(midRes, arg1, arg2); + replaceBits(resTemp, high, low, midRes); + } + Dest = resTemp; + ''', flagType="none", buildCc=False) + buildRegDataInst("qdadd", ''' + int32_t midRes; + resTemp = saturateOp<32>(midRes, Op2.sw, Op2.sw) | + saturateOp<32>(midRes, Op1.sw, midRes); + Dest = midRes; + ''', flagType="saturate", buildNonCc=False) + buildRegDataInst("qsub", ''' + int32_t midRes; + resTemp = saturateOp<32>(midRes, Op1.sw, Op2.sw, true); + Dest = midRes; + ''', flagType="saturate") + buildRegDataInst("qsub16", ''' + int32_t midRes; + for (unsigned i = 0; i < 2; i++) { + int high = (i + 1) * 16 - 1; + int low = i * 16; + int64_t arg1 = sext<16>(bits(Op1.sw, high, low)); + int64_t arg2 = sext<16>(bits(Op2.sw, high, low)); + saturateOp<16>(midRes, arg1, arg2, true); + replaceBits(resTemp, high, low, midRes); + } + Dest = resTemp; + ''', flagType="none", buildCc=False) + buildRegDataInst("qsub8", ''' + int32_t midRes; + for (unsigned i = 0; i < 4; i++) { + int high = (i + 1) * 8 - 1; + int low = i * 8; + int64_t arg1 = sext<8>(bits(Op1.sw, high, low)); + int64_t arg2 = sext<8>(bits(Op2.sw, high, low)); + saturateOp<8>(midRes, arg1, arg2, true); + replaceBits(resTemp, high, low, midRes); + } + Dest = resTemp; + ''', flagType="none", buildCc=False) + buildRegDataInst("qdsub", ''' + int32_t midRes; + resTemp = saturateOp<32>(midRes, Op2.sw, Op2.sw) | + saturateOp<32>(midRes, Op1.sw, midRes, true); + Dest = midRes; + ''', flagType="saturate", buildNonCc=False) + buildRegDataInst("qasx", ''' + int32_t midRes; + int64_t arg1Low = sext<16>(bits(Op1.sw, 15, 0)); + int64_t arg1High = sext<16>(bits(Op1.sw, 31, 16)); + int64_t arg2Low = sext<16>(bits(Op2.sw, 15, 0)); + int64_t arg2High = sext<16>(bits(Op2.sw, 31, 16)); + saturateOp<16>(midRes, arg1Low, arg2High, true); + replaceBits(resTemp, 15, 0, midRes); + saturateOp<16>(midRes, arg1High, arg2Low); + replaceBits(resTemp, 31, 16, midRes); + Dest = resTemp; + ''', flagType="none", buildCc=False) + buildRegDataInst("qsax", ''' + int32_t midRes; + int64_t arg1Low = sext<16>(bits(Op1.sw, 15, 0)); + int64_t arg1High = sext<16>(bits(Op1.sw, 31, 16)); + int64_t arg2Low = sext<16>(bits(Op2.sw, 15, 0)); + int64_t arg2High = sext<16>(bits(Op2.sw, 31, 16)); + saturateOp<16>(midRes, arg1Low, arg2High); + replaceBits(resTemp, 15, 0, midRes); + saturateOp<16>(midRes, arg1High, arg2Low, true); + replaceBits(resTemp, 31, 16, midRes); + Dest = resTemp; + ''', flagType="none", buildCc=False) + + buildRegDataInst("sadd8", ''' + uint32_t geBits = 0; + resTemp = 0; + for (unsigned i = 0; i < 4; i++) { + int high = (i + 1) * 8 - 1; + int low = i * 8; + int32_t midRes = sext<8>(bits(Op1.sw, high, low)) + + sext<8>(bits(Op2.sw, high, low)); + replaceBits(resTemp, high, low, midRes); + if (midRes >= 0) { + geBits = geBits | (1 << i); + } + } + Dest = resTemp; + resTemp = geBits; + ''', flagType="ge", buildNonCc=False) + buildRegDataInst("sadd16", ''' + uint32_t geBits = 0; + resTemp = 0; + for (unsigned i = 0; i < 2; i++) { + int high = (i + 1) * 16 - 1; + int low = i * 16; + int32_t midRes = sext<16>(bits(Op1.sw, high, low)) + + sext<16>(bits(Op2.sw, high, low)); + replaceBits(resTemp, high, low, midRes); + if (midRes >= 0) { + geBits = geBits | (0x3 << (i * 2)); + } + } + Dest = resTemp; + resTemp = geBits; + ''', flagType="ge", buildNonCc=False) + + buildRegDataInst("ssub8", ''' + uint32_t geBits = 0; + resTemp = 0; + for (unsigned i = 0; i < 4; i++) { + int high = (i + 1) * 8 - 1; + int low = i * 8; + int32_t midRes = sext<8>(bits(Op1.sw, high, low)) - + sext<8>(bits(Op2.sw, high, low)); + replaceBits(resTemp, high, low, midRes); + if (midRes >= 0) { + geBits = geBits | (1 << i); + } + } + Dest = resTemp; + resTemp = geBits; + ''', flagType="ge", buildNonCc=False) + buildRegDataInst("ssub16", ''' + uint32_t geBits = 0; + resTemp = 0; + for (unsigned i = 0; i < 2; i++) { + int high = (i + 1) * 16 - 1; + int low = i * 16; + int32_t midRes = sext<16>(bits(Op1.sw, high, low)) - + sext<16>(bits(Op2.sw, high, low)); + replaceBits(resTemp, high, low, midRes); + if (midRes >= 0) { + geBits = geBits | (0x3 << (i * 2)); + } + } + Dest = resTemp; + resTemp = geBits; + ''', flagType="ge", buildNonCc=False) + buildRegDataInst("sasx", ''' + int32_t midRes, geBits = 0; + resTemp = 0; + int64_t arg1Low = sext<16>(bits(Op1.sw, 15, 0)); + int64_t arg1High = sext<16>(bits(Op1.sw, 31, 16)); + int64_t arg2Low = sext<16>(bits(Op2.sw, 15, 0)); + int64_t arg2High = sext<16>(bits(Op2.sw, 31, 16)); + midRes = arg1Low - arg2High; + if (midRes >= 0) { + geBits = geBits | 0x3; + } + replaceBits(resTemp, 15, 0, midRes); + midRes = arg1High + arg2Low; + if (midRes >= 0) { + geBits = geBits | 0xc; + } + replaceBits(resTemp, 31, 16, midRes); + Dest = resTemp; + resTemp = geBits; + ''', flagType="ge", buildNonCc=True) + buildRegDataInst("ssax", ''' + int32_t midRes, geBits = 0; + resTemp = 0; + int64_t arg1Low = sext<16>(bits(Op1.sw, 15, 0)); + int64_t arg1High = sext<16>(bits(Op1.sw, 31, 16)); + int64_t arg2Low = sext<16>(bits(Op2.sw, 15, 0)); + int64_t arg2High = sext<16>(bits(Op2.sw, 31, 16)); + midRes = arg1Low + arg2High; + if (midRes >= 0) { + geBits = geBits | 0x3; + } + replaceBits(resTemp, 15, 0, midRes); + midRes = arg1High - arg2Low; + if (midRes >= 0) { + geBits = geBits | 0xc; + } + replaceBits(resTemp, 31, 16, midRes); + Dest = resTemp; + resTemp = geBits; + ''', flagType="ge", buildNonCc=True) + + buildRegDataInst("shadd8", ''' + resTemp = 0; + for (unsigned i = 0; i < 4; i++) { + int high = (i + 1) * 8 - 1; + int low = i * 8; + int32_t midRes = + (uint64_t)(sext<8>(bits(Op1.sw, high, low)) + + sext<8>(bits(Op2.sw, high, low))) >> 1; + replaceBits(resTemp, high, low, midRes); + } + Dest = resTemp; + ''', flagType="none", buildCc=False) + buildRegDataInst("shadd16", ''' + resTemp = 0; + for (unsigned i = 0; i < 2; i++) { + int high = (i + 1) * 16 - 1; + int low = i * 16; + int32_t midRes = + (uint64_t)(sext<16>(bits(Op1.sw, high, low)) + + sext<16>(bits(Op2.sw, high, low))) >> 1; + replaceBits(resTemp, high, low, midRes); + } + Dest = resTemp; + ''', flagType="none", buildCc=False) + buildRegDataInst("shsub8", ''' + resTemp = 0; + for (unsigned i = 0; i < 4; i++) { + int high = (i + 1) * 8 - 1; + int low = i * 8; + int32_t midRes = + (uint64_t)(sext<8>(bits(Op1.sw, high, low)) - + sext<8>(bits(Op2.sw, high, low))) >> 1; + replaceBits(resTemp, high, low, midRes); + } + Dest = resTemp; + ''', flagType="none", buildCc=False) + buildRegDataInst("shsub16", ''' + resTemp = 0; + for (unsigned i = 0; i < 2; i++) { + int high = (i + 1) * 16 - 1; + int low = i * 16; + int32_t midRes = + (uint64_t)(sext<16>(bits(Op1.sw, high, low)) - + sext<16>(bits(Op2.sw, high, low))) >> 1; + replaceBits(resTemp, high, low, midRes); + } + Dest = resTemp; + ''', flagType="none", buildCc=False) + buildRegDataInst("shasx", ''' + int32_t midRes; + resTemp = 0; + int64_t arg1Low = sext<16>(bits(Op1.sw, 15, 0)); + int64_t arg1High = sext<16>(bits(Op1.sw, 31, 16)); + int64_t arg2Low = sext<16>(bits(Op2.sw, 15, 0)); + int64_t arg2High = sext<16>(bits(Op2.sw, 31, 16)); + midRes = (uint64_t)(arg1Low - arg2High) >> 1; + replaceBits(resTemp, 15, 0, midRes); + midRes = (arg1High + arg2Low) >> 1; + replaceBits(resTemp, 31, 16, midRes); + Dest = resTemp; + ''', flagType="none", buildCc=True) + buildRegDataInst("shsax", ''' + int32_t midRes; + resTemp = 0; + int64_t arg1Low = sext<16>(bits(Op1.sw, 15, 0)); + int64_t arg1High = sext<16>(bits(Op1.sw, 31, 16)); + int64_t arg2Low = sext<16>(bits(Op2.sw, 15, 0)); + int64_t arg2High = sext<16>(bits(Op2.sw, 31, 16)); + midRes = (uint64_t)(arg1Low + arg2High) >> 1; + replaceBits(resTemp, 15, 0, midRes); + midRes = (uint64_t)(arg1High - arg2Low) >> 1; + replaceBits(resTemp, 31, 16, midRes); + Dest = resTemp; + ''', flagType="none", buildCc=True) + + buildRegDataInst("uqadd16", ''' + uint32_t midRes; + for (unsigned i = 0; i < 2; i++) { + int high = (i + 1) * 16 - 1; + int low = i * 16; + uint64_t arg1 = bits(Op1, high, low); + uint64_t arg2 = bits(Op2, high, low); + uSaturateOp<16>(midRes, arg1, arg2); + replaceBits(resTemp, high, low, midRes); + } + Dest = resTemp; + ''', flagType="none", buildCc=False) + buildRegDataInst("uqadd8", ''' + uint32_t midRes; + for (unsigned i = 0; i < 4; i++) { + int high = (i + 1) * 8 - 1; + int low = i * 8; + uint64_t arg1 = bits(Op1, high, low); + uint64_t arg2 = bits(Op2, high, low); + uSaturateOp<8>(midRes, arg1, arg2); + replaceBits(resTemp, high, low, midRes); + } + Dest = resTemp; + ''', flagType="none", buildCc=False) + buildRegDataInst("uqsub16", ''' + uint32_t midRes; + for (unsigned i = 0; i < 2; i++) { + int high = (i + 1) * 16 - 1; + int low = i * 16; + uint64_t arg1 = bits(Op1, high, low); + uint64_t arg2 = bits(Op2, high, low); + uSaturateOp<16>(midRes, arg1, arg2, true); + replaceBits(resTemp, high, low, midRes); + } + Dest = resTemp; + ''', flagType="none", buildCc=False) + buildRegDataInst("uqsub8", ''' + uint32_t midRes; + for (unsigned i = 0; i < 4; i++) { + int high = (i + 1) * 8 - 1; + int low = i * 8; + uint64_t arg1 = bits(Op1, high, low); + uint64_t arg2 = bits(Op2, high, low); + uSaturateOp<8>(midRes, arg1, arg2, true); + replaceBits(resTemp, high, low, midRes); + } + Dest = resTemp; + ''', flagType="none", buildCc=False) + buildRegDataInst("uqasx", ''' + uint32_t midRes; + uint64_t arg1Low = bits(Op1.sw, 15, 0); + uint64_t arg1High = bits(Op1.sw, 31, 16); + uint64_t arg2Low = bits(Op2.sw, 15, 0); + uint64_t arg2High = bits(Op2.sw, 31, 16); + uSaturateOp<16>(midRes, arg1Low, arg2High, true); + replaceBits(resTemp, 15, 0, midRes); + uSaturateOp<16>(midRes, arg1High, arg2Low); + replaceBits(resTemp, 31, 16, midRes); + Dest = resTemp; + ''', flagType="none", buildCc=False) + buildRegDataInst("uqsax", ''' + uint32_t midRes; + uint64_t arg1Low = bits(Op1.sw, 15, 0); + uint64_t arg1High = bits(Op1.sw, 31, 16); + uint64_t arg2Low = bits(Op2.sw, 15, 0); + uint64_t arg2High = bits(Op2.sw, 31, 16); + uSaturateOp<16>(midRes, arg1Low, arg2High); + replaceBits(resTemp, 15, 0, midRes); + uSaturateOp<16>(midRes, arg1High, arg2Low, true); + replaceBits(resTemp, 31, 16, midRes); + Dest = resTemp; + ''', flagType="none", buildCc=False) + + buildRegDataInst("uadd16", ''' + uint32_t geBits = 0; + resTemp = 0; + for (unsigned i = 0; i < 2; i++) { + int high = (i + 1) * 16 - 1; + int low = i * 16; + int32_t midRes = bits(Op1, high, low) + + bits(Op2, high, low); + if (midRes >= 0x10000) { + geBits = geBits | (0x3 << (i * 2)); + } + replaceBits(resTemp, high, low, midRes); + } + Dest = resTemp; + resTemp = geBits; + ''', flagType="ge", buildNonCc=False) + buildRegDataInst("uadd8", ''' + uint32_t geBits = 0; + resTemp = 0; + for (unsigned i = 0; i < 4; i++) { + int high = (i + 1) * 8 - 1; + int low = i * 8; + int32_t midRes = bits(Op1, high, low) + + bits(Op2, high, low); + if (midRes >= 0x100) { + geBits = geBits | (1 << i); + } + replaceBits(resTemp, high, low, midRes); + } + Dest = resTemp; + resTemp = geBits; + ''', flagType="ge", buildNonCc=False) + buildRegDataInst("usub16", ''' + uint32_t geBits = 0; + resTemp = 0; + for (unsigned i = 0; i < 2; i++) { + int high = (i + 1) * 16 - 1; + int low = i * 16; + int32_t midRes = bits(Op1, high, low) - + bits(Op2, high, low); + if (midRes >= 0) { + geBits = geBits | (0x3 << (i * 2)); + } + replaceBits(resTemp, high, low, midRes); + } + Dest = resTemp; + resTemp = geBits; + ''', flagType="ge", buildNonCc=False) + buildRegDataInst("usub8", ''' + uint32_t geBits = 0; + resTemp = 0; + for (unsigned i = 0; i < 4; i++) { + int high = (i + 1) * 8 - 1; + int low = i * 8; + int32_t midRes = bits(Op1, high, low) - + bits(Op2, high, low); + if (midRes >= 0) { + geBits = geBits | (1 << i); + } + replaceBits(resTemp, high, low, midRes); + } + Dest = resTemp; + resTemp = geBits; + ''', flagType="ge", buildNonCc=False) + buildRegDataInst("uasx", ''' + int32_t midRes, geBits = 0; + resTemp = 0; + int64_t arg1Low = bits(Op1.sw, 15, 0); + int64_t arg1High = bits(Op1.sw, 31, 16); + int64_t arg2Low = bits(Op2.sw, 15, 0); + int64_t arg2High = bits(Op2.sw, 31, 16); + midRes = arg1Low - arg2High; + if (midRes >= 0) { + geBits = geBits | 0x3; + } + replaceBits(resTemp, 15, 0, midRes); + midRes = arg1High + arg2Low; + if (midRes >= 0x10000) { + geBits = geBits | 0xc; + } + replaceBits(resTemp, 31, 16, midRes); + Dest = resTemp; + resTemp = geBits; + ''', flagType="ge", buildNonCc=False) + buildRegDataInst("usax", ''' + int32_t midRes, geBits = 0; + resTemp = 0; + int64_t arg1Low = bits(Op1.sw, 15, 0); + int64_t arg1High = bits(Op1.sw, 31, 16); + int64_t arg2Low = bits(Op2.sw, 15, 0); + int64_t arg2High = bits(Op2.sw, 31, 16); + midRes = arg1Low + arg2High; + if (midRes >= 0x10000) { + geBits = geBits | 0x3; + } + replaceBits(resTemp, 15, 0, midRes); + midRes = arg1High - arg2Low; + if (midRes >= 0) { + geBits = geBits | 0xc; + } + replaceBits(resTemp, 31, 16, midRes); + Dest = resTemp; + resTemp = geBits; + ''', flagType="ge", buildNonCc=False) + + buildRegDataInst("uhadd16", ''' + resTemp = 0; + for (unsigned i = 0; i < 2; i++) { + int high = (i + 1) * 16 - 1; + int low = i * 16; + int32_t midRes = (bits(Op1, high, low) + + bits(Op2, high, low)) >> 1; + replaceBits(resTemp, high, low, midRes); + } + Dest = resTemp; + ''', flagType="none", buildCc=False) + buildRegDataInst("uhadd8", ''' + resTemp = 0; + for (unsigned i = 0; i < 4; i++) { + int high = (i + 1) * 8 - 1; + int low = i * 8; + int32_t midRes = (bits(Op1, high, low) + + bits(Op2, high, low)) >> 1; + replaceBits(resTemp, high, low, midRes); + } + Dest = resTemp; + ''', flagType="none", buildCc=False) + buildRegDataInst("uhsub16", ''' + resTemp = 0; + for (unsigned i = 0; i < 2; i++) { + int high = (i + 1) * 16 - 1; + int low = i * 16; + int32_t midRes = (bits(Op1, high, low) - + bits(Op2, high, low)) >> 1; + replaceBits(resTemp, high, low, midRes); + } + Dest = resTemp; + ''', flagType="none", buildCc=False) + buildRegDataInst("uhsub8", ''' + resTemp = 0; + for (unsigned i = 0; i < 4; i++) { + int high = (i + 1) * 8 - 1; + int low = i * 8; + int32_t midRes = (bits(Op1, high, low) - + bits(Op2, high, low)) >> 1; + replaceBits(resTemp, high, low, midRes); + } + Dest = resTemp; + ''', flagType="none", buildCc=False) + buildRegDataInst("uhasx", ''' + int32_t midRes; + resTemp = 0; + int64_t arg1Low = bits(Op1.sw, 15, 0); + int64_t arg1High = bits(Op1.sw, 31, 16); + int64_t arg2Low = bits(Op2.sw, 15, 0); + int64_t arg2High = bits(Op2.sw, 31, 16); + midRes = (arg1Low - arg2High) >> 1; + replaceBits(resTemp, 15, 0, midRes); + midRes = (arg1High + arg2Low) >> 1; + replaceBits(resTemp, 31, 16, midRes); + Dest = resTemp; + ''', flagType="none", buildCc=False) + buildRegDataInst("uhsax", ''' + int32_t midRes; + resTemp = 0; + int64_t arg1Low = bits(Op1.sw, 15, 0); + int64_t arg1High = bits(Op1.sw, 31, 16); + int64_t arg2Low = bits(Op2.sw, 15, 0); + int64_t arg2High = bits(Op2.sw, 31, 16); + midRes = (arg1Low + arg2High) >> 1; + replaceBits(resTemp, 15, 0, midRes); + midRes = (arg1High - arg2Low) >> 1; + replaceBits(resTemp, 31, 16, midRes); + Dest = resTemp; + ''', flagType="none", buildCc=False) + + buildRegDataInst("pkhbt", ''' + uint32_t resTemp = 0; + uint16_t arg1Low = bits(Op1, 15, 0); + uint16_t arg2High = bits(secondOp, 31, 16); + replaceBits(resTemp, 15, 0, arg1Low); + replaceBits(resTemp, 31, 16, arg2High); + Dest = resTemp; + ''', flagType="none", buildCc=False) + buildRegDataInst("pkhtb", ''' + uint32_t resTemp = 0; + uint16_t arg1High = bits(Op1, 31, 16); + uint16_t arg2Low = bits(secondOp, 15, 0); + replaceBits(resTemp, 15, 0, arg2Low); + replaceBits(resTemp, 31, 16, arg1High); + Dest = resTemp; + ''', flagType="none", buildCc=False) +}}; diff -r 84bd4089958b src/arch/arm/isa/insts/div.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/insts/div.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,84 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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: Gabe Black + +let {{ + sdivCode = ''' + if (Op2.sw == 0) { + if (((SCTLR)Sctlr).dz) { +#if FULL_SYSTEM + return new UndefinedInstruction; +#else + return new UndefinedInstruction(false, mnemonic); +#endif + } + Dest.sw = 0; + } else if (Op1.sw == INT_MIN && Op2.sw == -1) { + Dest.sw = INT_MIN; + } else { + Dest.sw = Op1.sw / Op2.sw; + } + ''' + sdivIop = InstObjParams("sdiv", "Sdiv", "RegRegRegOp", + { "code": sdivCode, + "predicate_test": predicateTest }, []) + header_output = RegRegRegOpDeclare.subst(sdivIop) + decoder_output = RegRegRegOpConstructor.subst(sdivIop) + exec_output = PredOpExecute.subst(sdivIop) + + udivCode = ''' + if (Op2.uw == 0) { + if (((SCTLR)Sctlr).dz) { +#if FULL_SYSTEM + return new UndefinedInstruction; +#else + return new UndefinedInstruction(false, mnemonic); +#endif + } + Dest.uw = 0; + } else { + Dest.uw = Op1.uw / Op2.uw; + } + ''' + udivIop = InstObjParams("udiv", "Udiv", "RegRegRegOp", + { "code": udivCode, + "predicate_test": predicateTest }, []) + header_output += RegRegRegOpDeclare.subst(udivIop) + decoder_output += RegRegRegOpConstructor.subst(udivIop) + exec_output += PredOpExecute.subst(udivIop) +}}; diff -r 84bd4089958b src/arch/arm/isa/insts/fp.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/insts/fp.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,1492 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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: Gabe Black + +output header {{ + +template +class VfpMacroRegRegOp : public VfpMacroOp +{ + public: + VfpMacroRegRegOp(ExtMachInst _machInst, IntRegIndex _dest, + IntRegIndex _op1, bool _wide) : + VfpMacroOp("VfpMacroRegRegOp", _machInst, No_OpClass, _wide) + { + numMicroops = machInst.fpscrLen + 1; + assert(numMicroops > 1); + microOps = new StaticInstPtr[numMicroops]; + for (unsigned i = 0; i < numMicroops; i++) { + VfpMicroMode mode = VfpMicroop; + if (i == 0) + mode = VfpFirstMicroop; + else if (i == numMicroops - 1) + mode = VfpLastMicroop; + microOps[i] = new Micro(_machInst, _dest, _op1, mode); + nextIdxs(_dest, _op1); + } + } + + %(BasicExecPanic)s +}; + +template +static StaticInstPtr +decodeVfpRegRegOp(ExtMachInst machInst, + IntRegIndex dest, IntRegIndex op1, bool wide) +{ + if (machInst.fpscrLen == 0 || VfpMacroOp::inScalarBank(dest)) { + return new VfpOp(machInst, dest, op1); + } else { + return new VfpMacroRegRegOp(machInst, dest, op1, wide); + } +} + +template +class VfpMacroRegImmOp : public VfpMacroOp +{ + public: + VfpMacroRegImmOp(ExtMachInst _machInst, IntRegIndex _dest, uint64_t _imm, + bool _wide) : + VfpMacroOp("VfpMacroRegImmOp", _machInst, No_OpClass, _wide) + { + numMicroops = machInst.fpscrLen + 1; + microOps = new StaticInstPtr[numMicroops]; + for (unsigned i = 0; i < numMicroops; i++) { + VfpMicroMode mode = VfpMicroop; + if (i == 0) + mode = VfpFirstMicroop; + else if (i == numMicroops - 1) + mode = VfpLastMicroop; + microOps[i] = new Micro(_machInst, _dest, _imm, mode); + nextIdxs(_dest); + } + } + + %(BasicExecPanic)s +}; + +template +static StaticInstPtr +decodeVfpRegImmOp(ExtMachInst machInst, + IntRegIndex dest, uint64_t imm, bool wide) +{ + if (machInst.fpscrLen == 0 || VfpMacroOp::inScalarBank(dest)) { + return new VfpOp(machInst, dest, imm); + } else { + return new VfpMacroRegImmOp(machInst, dest, imm, wide); + } +} + +template +class VfpMacroRegRegImmOp : public VfpMacroOp +{ + public: + VfpMacroRegRegImmOp(ExtMachInst _machInst, IntRegIndex _dest, + IntRegIndex _op1, uint64_t _imm, bool _wide) : + VfpMacroOp("VfpMacroRegRegImmOp", _machInst, No_OpClass, _wide) + { + numMicroops = machInst.fpscrLen + 1; + microOps = new StaticInstPtr[numMicroops]; + for (unsigned i = 0; i < numMicroops; i++) { + VfpMicroMode mode = VfpMicroop; + if (i == 0) + mode = VfpFirstMicroop; + else if (i == numMicroops - 1) + mode = VfpLastMicroop; + microOps[i] = new Micro(_machInst, _dest, _op1, _imm, mode); + nextIdxs(_dest, _op1); + } + } + + %(BasicExecPanic)s +}; + +template +static StaticInstPtr +decodeVfpRegRegImmOp(ExtMachInst machInst, IntRegIndex dest, + IntRegIndex op1, uint64_t imm, bool wide) +{ + if (machInst.fpscrLen == 0 || VfpMacroOp::inScalarBank(dest)) { + return new VfpOp(machInst, dest, op1, imm); + } else { + return new VfpMacroRegRegImmOp(machInst, dest, op1, imm, wide); + } +} + +template +class VfpMacroRegRegRegOp : public VfpMacroOp +{ + public: + VfpMacroRegRegRegOp(ExtMachInst _machInst, IntRegIndex _dest, + IntRegIndex _op1, IntRegIndex _op2, bool _wide) : + VfpMacroOp("VfpMacroRegRegRegOp", _machInst, No_OpClass, _wide) + { + numMicroops = machInst.fpscrLen + 1; + microOps = new StaticInstPtr[numMicroops]; + for (unsigned i = 0; i < numMicroops; i++) { + VfpMicroMode mode = VfpMicroop; + if (i == 0) + mode = VfpFirstMicroop; + else if (i == numMicroops - 1) + mode = VfpLastMicroop; + microOps[i] = new Micro(_machInst, _dest, _op1, _op2, mode); + nextIdxs(_dest, _op1, _op2); + } + } + + %(BasicExecPanic)s +}; + +template +static StaticInstPtr +decodeVfpRegRegRegOp(ExtMachInst machInst, IntRegIndex dest, + IntRegIndex op1, IntRegIndex op2, bool wide) +{ + if (machInst.fpscrLen == 0 || VfpMacroOp::inScalarBank(dest)) { + return new VfpOp(machInst, dest, op1, op2); + } else { + return new VfpMacroRegRegRegOp(machInst, dest, op1, op2, wide); + } +} +}}; + +let {{ + + header_output = "" + decoder_output = "" + exec_output = "" + + vmsrIop = InstObjParams("vmsr", "Vmsr", "FpRegRegOp", + { "code": "MiscDest = Op1;", + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vmsrIop); + decoder_output += FpRegRegOpConstructor.subst(vmsrIop); + exec_output += PredOpExecute.subst(vmsrIop); + + vmrsIop = InstObjParams("vmrs", "Vmrs", "FpRegRegOp", + { "code": "Dest = MiscOp1;", + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vmrsIop); + decoder_output += FpRegRegOpConstructor.subst(vmrsIop); + exec_output += PredOpExecute.subst(vmrsIop); + + vmrsApsrCode = "Dest = (MiscOp1 & imm) | (Dest & ~imm);" + vmrsApsrIop = InstObjParams("vmrs", "VmrsApsr", "FpRegRegImmOp", + { "code": vmrsApsrCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vmrsApsrIop); + decoder_output += FpRegRegImmOpConstructor.subst(vmrsApsrIop); + exec_output += PredOpExecute.subst(vmrsApsrIop); + + vmovImmSCode = ''' + FpDest.uw = bits(imm, 31, 0); + ''' + vmovImmSIop = InstObjParams("vmov", "VmovImmS", "FpRegImmOp", + { "code": vmovImmSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegImmOpDeclare.subst(vmovImmSIop); + decoder_output += FpRegImmOpConstructor.subst(vmovImmSIop); + exec_output += PredOpExecute.subst(vmovImmSIop); + + vmovImmDCode = ''' + FpDestP0.uw = bits(imm, 31, 0); + FpDestP1.uw = bits(imm, 63, 32); + ''' + vmovImmDIop = InstObjParams("vmov", "VmovImmD", "FpRegImmOp", + { "code": vmovImmDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegImmOpDeclare.subst(vmovImmDIop); + decoder_output += FpRegImmOpConstructor.subst(vmovImmDIop); + exec_output += PredOpExecute.subst(vmovImmDIop); + + vmovImmQCode = ''' + FpDestP0.uw = bits(imm, 31, 0); + FpDestP1.uw = bits(imm, 63, 32); + FpDestP2.uw = bits(imm, 31, 0); + FpDestP3.uw = bits(imm, 63, 32); + ''' + vmovImmQIop = InstObjParams("vmov", "VmovImmQ", "FpRegImmOp", + { "code": vmovImmQCode, + "predicate_test": predicateTest }, []) + header_output += FpRegImmOpDeclare.subst(vmovImmQIop); + decoder_output += FpRegImmOpConstructor.subst(vmovImmQIop); + exec_output += PredOpExecute.subst(vmovImmQIop); + + vmovRegSCode = ''' + FpDest.uw = FpOp1.uw; + ''' + vmovRegSIop = InstObjParams("vmov", "VmovRegS", "FpRegRegOp", + { "code": vmovRegSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vmovRegSIop); + decoder_output += FpRegRegOpConstructor.subst(vmovRegSIop); + exec_output += PredOpExecute.subst(vmovRegSIop); + + vmovRegDCode = ''' + FpDestP0.uw = FpOp1P0.uw; + FpDestP1.uw = FpOp1P1.uw; + ''' + vmovRegDIop = InstObjParams("vmov", "VmovRegD", "FpRegRegOp", + { "code": vmovRegDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vmovRegDIop); + decoder_output += FpRegRegOpConstructor.subst(vmovRegDIop); + exec_output += PredOpExecute.subst(vmovRegDIop); + + vmovRegQCode = ''' + FpDestP0.uw = FpOp1P0.uw; + FpDestP1.uw = FpOp1P1.uw; + FpDestP2.uw = FpOp1P2.uw; + FpDestP3.uw = FpOp1P3.uw; + ''' + vmovRegQIop = InstObjParams("vmov", "VmovRegQ", "FpRegRegOp", + { "code": vmovRegQCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vmovRegQIop); + decoder_output += FpRegRegOpConstructor.subst(vmovRegQIop); + exec_output += PredOpExecute.subst(vmovRegQIop); + + vmovCoreRegBCode = ''' + FpDest.uw = insertBits(FpDest.uw, imm * 8, imm * 8 + 7, Op1.ub); + ''' + vmovCoreRegBIop = InstObjParams("vmov", "VmovCoreRegB", "FpRegRegImmOp", + { "code": vmovCoreRegBCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vmovCoreRegBIop); + decoder_output += FpRegRegImmOpConstructor.subst(vmovCoreRegBIop); + exec_output += PredOpExecute.subst(vmovCoreRegBIop); + + vmovCoreRegHCode = ''' + FpDest.uw = insertBits(FpDest.uw, imm * 16, imm * 16 + 15, Op1.uh); + ''' + vmovCoreRegHIop = InstObjParams("vmov", "VmovCoreRegH", "FpRegRegImmOp", + { "code": vmovCoreRegHCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vmovCoreRegHIop); + decoder_output += FpRegRegImmOpConstructor.subst(vmovCoreRegHIop); + exec_output += PredOpExecute.subst(vmovCoreRegHIop); + + vmovCoreRegWCode = ''' + FpDest.uw = Op1.uw; + ''' + vmovCoreRegWIop = InstObjParams("vmov", "VmovCoreRegW", "FpRegRegOp", + { "code": vmovCoreRegWCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vmovCoreRegWIop); + decoder_output += FpRegRegOpConstructor.subst(vmovCoreRegWIop); + exec_output += PredOpExecute.subst(vmovCoreRegWIop); + + vmovRegCoreUBCode = ''' + Dest = bits(FpOp1.uw, imm * 8, imm * 8 + 7); + ''' + vmovRegCoreUBIop = InstObjParams("vmov", "VmovRegCoreUB", "FpRegRegImmOp", + { "code": vmovRegCoreUBCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vmovRegCoreUBIop); + decoder_output += FpRegRegImmOpConstructor.subst(vmovRegCoreUBIop); + exec_output += PredOpExecute.subst(vmovRegCoreUBIop); + + vmovRegCoreUHCode = ''' + Dest = bits(FpOp1.uw, imm * 16, imm * 16 + 15); + ''' + vmovRegCoreUHIop = InstObjParams("vmov", "VmovRegCoreUH", "FpRegRegImmOp", + { "code": vmovRegCoreUHCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vmovRegCoreUHIop); + decoder_output += FpRegRegImmOpConstructor.subst(vmovRegCoreUHIop); + exec_output += PredOpExecute.subst(vmovRegCoreUHIop); + + vmovRegCoreSBCode = ''' + Dest = sext<8>(bits(FpOp1.uw, imm * 8, imm * 8 + 7)); + ''' + vmovRegCoreSBIop = InstObjParams("vmov", "VmovRegCoreSB", "FpRegRegImmOp", + { "code": vmovRegCoreSBCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vmovRegCoreSBIop); + decoder_output += FpRegRegImmOpConstructor.subst(vmovRegCoreSBIop); + exec_output += PredOpExecute.subst(vmovRegCoreSBIop); + + vmovRegCoreSHCode = ''' + Dest = sext<16>(bits(FpOp1.uw, imm * 16, imm * 16 + 15)); + ''' + vmovRegCoreSHIop = InstObjParams("vmov", "VmovRegCoreSH", "FpRegRegImmOp", + { "code": vmovRegCoreSHCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vmovRegCoreSHIop); + decoder_output += FpRegRegImmOpConstructor.subst(vmovRegCoreSHIop); + exec_output += PredOpExecute.subst(vmovRegCoreSHIop); + + vmovRegCoreWCode = ''' + Dest = FpOp1.uw; + ''' + vmovRegCoreWIop = InstObjParams("vmov", "VmovRegCoreW", "FpRegRegOp", + { "code": vmovRegCoreWCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vmovRegCoreWIop); + decoder_output += FpRegRegOpConstructor.subst(vmovRegCoreWIop); + exec_output += PredOpExecute.subst(vmovRegCoreWIop); + + vmov2Reg2CoreCode = ''' + FpDestP0.uw = Op1.uw; + FpDestP1.uw = Op2.uw; + ''' + vmov2Reg2CoreIop = InstObjParams("vmov", "Vmov2Reg2Core", "FpRegRegRegOp", + { "code": vmov2Reg2CoreCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegRegOpDeclare.subst(vmov2Reg2CoreIop); + decoder_output += FpRegRegRegOpConstructor.subst(vmov2Reg2CoreIop); + exec_output += PredOpExecute.subst(vmov2Reg2CoreIop); + + vmov2Core2RegCode = ''' + Dest.uw = FpOp2P0.uw; + Op1.uw = FpOp2P1.uw; + ''' + vmov2Core2RegIop = InstObjParams("vmov", "Vmov2Core2Reg", "FpRegRegRegOp", + { "code": vmov2Core2RegCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegRegOpDeclare.subst(vmov2Core2RegIop); + decoder_output += FpRegRegRegOpConstructor.subst(vmov2Core2RegIop); + exec_output += PredOpExecute.subst(vmov2Core2RegIop); +}}; + +let {{ + + header_output = "" + decoder_output = "" + exec_output = "" + + singleCode = ''' + FPSCR fpscr = Fpscr; + FpDest = %(op)s; + Fpscr = fpscr; + ''' + singleBinOp = "binaryOp(fpscr, FpOp1, FpOp2," + \ + "%(func)s, fpscr.fz, fpscr.rMode)" + singleUnaryOp = "unaryOp(fpscr, FpOp1, %(func)s, fpscr.fz, fpscr.rMode)" + doubleCode = ''' + FPSCR fpscr = Fpscr; + double dest = %(op)s; + Fpscr = fpscr; + FpDestP0.uw = dblLow(dest); + FpDestP1.uw = dblHi(dest); + ''' + doubleBinOp = ''' + binaryOp(fpscr, dbl(FpOp1P0.uw, FpOp1P1.uw), + dbl(FpOp2P0.uw, FpOp2P1.uw), + %(func)s, fpscr.fz, fpscr.rMode); + ''' + doubleUnaryOp = ''' + unaryOp(fpscr, dbl(FpOp1P0.uw, FpOp1P1.uw), %(func)s, + fpscr.fz, fpscr.rMode) + ''' + + def buildBinFpOp(name, Name, base, singleOp, doubleOp): + global header_output, decoder_output, exec_output + + code = singleCode % { "op": singleBinOp } + code = code % { "func": singleOp } + sIop = InstObjParams(name + "s", Name + "S", base, + { "code": code, "predicate_test": predicateTest }, []) + code = doubleCode % { "op": doubleBinOp } + code = code % { "func": doubleOp } + dIop = InstObjParams(name + "d", Name + "D", base, + { "code": code, "predicate_test": predicateTest }, []) + + declareTempl = eval(base + "Declare"); + constructorTempl = eval(base + "Constructor"); + + for iop in sIop, dIop: + header_output += declareTempl.subst(iop) + decoder_output += constructorTempl.subst(iop) + exec_output += PredOpExecute.subst(iop) + + buildBinFpOp("vadd", "Vadd", "FpRegRegRegOp", "fpAddS", "fpAddD") + buildBinFpOp("vsub", "Vsub", "FpRegRegRegOp", "fpSubS", "fpSubD") + buildBinFpOp("vdiv", "Vdiv", "FpRegRegRegOp", "fpDivS", "fpDivD") + buildBinFpOp("vmul", "Vmul", "FpRegRegRegOp", "fpMulS", "fpMulD") + + def buildUnaryFpOp(name, Name, base, singleOp, doubleOp = None): + if doubleOp is None: + doubleOp = singleOp + global header_output, decoder_output, exec_output + + code = singleCode % { "op": singleUnaryOp } + code = code % { "func": singleOp } + sIop = InstObjParams(name + "s", Name + "S", base, + { "code": code, "predicate_test": predicateTest }, []) + code = doubleCode % { "op": doubleUnaryOp } + code = code % { "func": doubleOp } + dIop = InstObjParams(name + "d", Name + "D", base, + { "code": code, "predicate_test": predicateTest }, []) + + declareTempl = eval(base + "Declare"); + constructorTempl = eval(base + "Constructor"); + + for iop in sIop, dIop: + header_output += declareTempl.subst(iop) + decoder_output += constructorTempl.subst(iop) + exec_output += PredOpExecute.subst(iop) + + buildUnaryFpOp("vsqrt", "Vsqrt", "FpRegRegOp", "sqrtf", "sqrt") + + def buildSimpleUnaryFpOp(name, Name, base, singleOp, doubleOp = None): + if doubleOp is None: + doubleOp = singleOp + global header_output, decoder_output, exec_output + + sIop = InstObjParams(name + "s", Name + "S", base, + { "code": singleCode % { "op": singleOp }, + "predicate_test": predicateTest }, []) + dIop = InstObjParams(name + "d", Name + "D", base, + { "code": doubleCode % { "op": doubleOp }, + "predicate_test": predicateTest }, []) + + declareTempl = eval(base + "Declare"); + constructorTempl = eval(base + "Constructor"); + + for iop in sIop, dIop: + header_output += declareTempl.subst(iop) + decoder_output += constructorTempl.subst(iop) + exec_output += PredOpExecute.subst(iop) + + buildSimpleUnaryFpOp("vneg", "Vneg", "FpRegRegOp", + "-FpOp1", "-dbl(FpOp1P0.uw, FpOp1P1.uw)") + buildSimpleUnaryFpOp("vabs", "Vabs", "FpRegRegOp", + "fabsf(FpOp1)", "fabs(dbl(FpOp1P0.uw, FpOp1P1.uw))") +}}; + +let {{ + + header_output = "" + decoder_output = "" + exec_output = "" + + vmlaSCode = ''' + FPSCR fpscr = Fpscr; + float mid = binaryOp(fpscr, FpOp1, FpOp2, + fpMulS, fpscr.fz, fpscr.rMode); + FpDest = binaryOp(fpscr, FpDest, mid, fpAddS, fpscr.fz, fpscr.rMode); + Fpscr = fpscr; + ''' + vmlaSIop = InstObjParams("vmlas", "VmlaS", "FpRegRegRegOp", + { "code": vmlaSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegRegOpDeclare.subst(vmlaSIop); + decoder_output += FpRegRegRegOpConstructor.subst(vmlaSIop); + exec_output += PredOpExecute.subst(vmlaSIop); + + vmlaDCode = ''' + FPSCR fpscr = Fpscr; + double mid = binaryOp(fpscr, dbl(FpOp1P0.uw, FpOp1P1.uw), + dbl(FpOp2P0.uw, FpOp2P1.uw), + fpMulD, fpscr.fz, fpscr.rMode); + double dest = binaryOp(fpscr, dbl(FpDestP0.uw, FpDestP1.uw), + mid, fpAddD, fpscr.fz, fpscr.rMode); + Fpscr = fpscr; + FpDestP0.uw = dblLow(dest); + FpDestP1.uw = dblHi(dest); + ''' + vmlaDIop = InstObjParams("vmlad", "VmlaD", "FpRegRegRegOp", + { "code": vmlaDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegRegOpDeclare.subst(vmlaDIop); + decoder_output += FpRegRegRegOpConstructor.subst(vmlaDIop); + exec_output += PredOpExecute.subst(vmlaDIop); + + vmlsSCode = ''' + FPSCR fpscr = Fpscr; + float mid = binaryOp(fpscr, FpOp1, FpOp2, + fpMulS, fpscr.fz, fpscr.rMode); + FpDest = binaryOp(fpscr, FpDest, -mid, fpAddS, fpscr.fz, fpscr.rMode); + Fpscr = fpscr; + ''' + vmlsSIop = InstObjParams("vmlss", "VmlsS", "FpRegRegRegOp", + { "code": vmlsSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegRegOpDeclare.subst(vmlsSIop); + decoder_output += FpRegRegRegOpConstructor.subst(vmlsSIop); + exec_output += PredOpExecute.subst(vmlsSIop); + + vmlsDCode = ''' + FPSCR fpscr = Fpscr; + double mid = binaryOp(fpscr, dbl(FpOp1P0.uw, FpOp1P1.uw), + dbl(FpOp2P0.uw, FpOp2P1.uw), + fpMulD, fpscr.fz, fpscr.rMode); + double dest = binaryOp(fpscr, dbl(FpDestP0.uw, FpDestP1.uw), + -mid, fpAddD, fpscr.fz, fpscr.rMode); + Fpscr = fpscr; + FpDestP0.uw = dblLow(dest); + FpDestP1.uw = dblHi(dest); + ''' + vmlsDIop = InstObjParams("vmlsd", "VmlsD", "FpRegRegRegOp", + { "code": vmlsDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegRegOpDeclare.subst(vmlsDIop); + decoder_output += FpRegRegRegOpConstructor.subst(vmlsDIop); + exec_output += PredOpExecute.subst(vmlsDIop); + + vnmlaSCode = ''' + FPSCR fpscr = Fpscr; + float mid = binaryOp(fpscr, FpOp1, FpOp2, + fpMulS, fpscr.fz, fpscr.rMode); + FpDest = binaryOp(fpscr, -FpDest, -mid, fpAddS, fpscr.fz, fpscr.rMode); + Fpscr = fpscr; + ''' + vnmlaSIop = InstObjParams("vnmlas", "VnmlaS", "FpRegRegRegOp", + { "code": vnmlaSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegRegOpDeclare.subst(vnmlaSIop); + decoder_output += FpRegRegRegOpConstructor.subst(vnmlaSIop); + exec_output += PredOpExecute.subst(vnmlaSIop); + + vnmlaDCode = ''' + FPSCR fpscr = Fpscr; + double mid = binaryOp(fpscr, dbl(FpOp1P0.uw, FpOp1P1.uw), + dbl(FpOp2P0.uw, FpOp2P1.uw), + fpMulD, fpscr.fz, fpscr.rMode); + double dest = binaryOp(fpscr, -dbl(FpDestP0.uw, FpDestP1.uw), + -mid, fpAddD, fpscr.fz, fpscr.rMode); + Fpscr = fpscr; + FpDestP0.uw = dblLow(dest); + FpDestP1.uw = dblHi(dest); + ''' + vnmlaDIop = InstObjParams("vnmlad", "VnmlaD", "FpRegRegRegOp", + { "code": vnmlaDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegRegOpDeclare.subst(vnmlaDIop); + decoder_output += FpRegRegRegOpConstructor.subst(vnmlaDIop); + exec_output += PredOpExecute.subst(vnmlaDIop); + + vnmlsSCode = ''' + FPSCR fpscr = Fpscr; + float mid = binaryOp(fpscr, FpOp1, FpOp2, + fpMulS, fpscr.fz, fpscr.rMode); + FpDest = binaryOp(fpscr, -FpDest, mid, fpAddS, fpscr.fz, fpscr.rMode); + Fpscr = fpscr; + ''' + vnmlsSIop = InstObjParams("vnmlss", "VnmlsS", "FpRegRegRegOp", + { "code": vnmlsSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegRegOpDeclare.subst(vnmlsSIop); + decoder_output += FpRegRegRegOpConstructor.subst(vnmlsSIop); + exec_output += PredOpExecute.subst(vnmlsSIop); + + vnmlsDCode = ''' + FPSCR fpscr = Fpscr; + double mid = binaryOp(fpscr, dbl(FpOp1P0.uw, FpOp1P1.uw), + dbl(FpOp2P0.uw, FpOp2P1.uw), + fpMulD, fpscr.fz, fpscr.rMode); + double dest = binaryOp(fpscr, -dbl(FpDestP0.uw, FpDestP1.uw), + mid, fpAddD, fpscr.fz, fpscr.rMode); + Fpscr = fpscr; + FpDestP0.uw = dblLow(dest); + FpDestP1.uw = dblHi(dest); + ''' + vnmlsDIop = InstObjParams("vnmlsd", "VnmlsD", "FpRegRegRegOp", + { "code": vnmlsDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegRegOpDeclare.subst(vnmlsDIop); + decoder_output += FpRegRegRegOpConstructor.subst(vnmlsDIop); + exec_output += PredOpExecute.subst(vnmlsDIop); + + vnmulSCode = ''' + FPSCR fpscr = Fpscr; + FpDest = -binaryOp(fpscr, FpOp1, FpOp2, fpMulS, fpscr.fz, fpscr.rMode); + Fpscr = fpscr; + ''' + vnmulSIop = InstObjParams("vnmuls", "VnmulS", "FpRegRegRegOp", + { "code": vnmulSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegRegOpDeclare.subst(vnmulSIop); + decoder_output += FpRegRegRegOpConstructor.subst(vnmulSIop); + exec_output += PredOpExecute.subst(vnmulSIop); + + vnmulDCode = ''' + FPSCR fpscr = Fpscr; + double dest = -binaryOp(fpscr, dbl(FpOp1P0.uw, FpOp1P1.uw), + dbl(FpOp2P0.uw, FpOp2P1.uw), + fpMulD, fpscr.fz, fpscr.rMode); + Fpscr = fpscr; + FpDestP0.uw = dblLow(dest); + FpDestP1.uw = dblHi(dest); + ''' + vnmulDIop = InstObjParams("vnmuld", "VnmulD", "FpRegRegRegOp", + { "code": vnmulDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegRegOpDeclare.subst(vnmulDIop); + decoder_output += FpRegRegRegOpConstructor.subst(vnmulDIop); + exec_output += PredOpExecute.subst(vnmulDIop); +}}; + +let {{ + + header_output = "" + decoder_output = "" + exec_output = "" + + vcvtUIntFpSCode = ''' + FPSCR fpscr = Fpscr; + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (FpOp1.uw) : "m" (FpOp1.uw)); + FpDest = FpOp1.uw; + __asm__ __volatile__("" :: "m" (FpDest)); + finishVfp(fpscr, state); + Fpscr = fpscr; + ''' + vcvtUIntFpSIop = InstObjParams("vcvt", "VcvtUIntFpS", "FpRegRegOp", + { "code": vcvtUIntFpSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcvtUIntFpSIop); + decoder_output += FpRegRegOpConstructor.subst(vcvtUIntFpSIop); + exec_output += PredOpExecute.subst(vcvtUIntFpSIop); + + vcvtUIntFpDCode = ''' + FPSCR fpscr = Fpscr; + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (FpOp1P0.uw) : "m" (FpOp1P0.uw)); + double cDest = (uint64_t)FpOp1P0.uw; + __asm__ __volatile__("" :: "m" (cDest)); + finishVfp(fpscr, state); + Fpscr = fpscr; + FpDestP0.uw = dblLow(cDest); + FpDestP1.uw = dblHi(cDest); + ''' + vcvtUIntFpDIop = InstObjParams("vcvt", "VcvtUIntFpD", "FpRegRegOp", + { "code": vcvtUIntFpDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcvtUIntFpDIop); + decoder_output += FpRegRegOpConstructor.subst(vcvtUIntFpDIop); + exec_output += PredOpExecute.subst(vcvtUIntFpDIop); + + vcvtSIntFpSCode = ''' + FPSCR fpscr = Fpscr; + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (FpOp1.sw) : "m" (FpOp1.sw)); + FpDest = FpOp1.sw; + __asm__ __volatile__("" :: "m" (FpDest)); + finishVfp(fpscr, state); + Fpscr = fpscr; + ''' + vcvtSIntFpSIop = InstObjParams("vcvt", "VcvtSIntFpS", "FpRegRegOp", + { "code": vcvtSIntFpSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcvtSIntFpSIop); + decoder_output += FpRegRegOpConstructor.subst(vcvtSIntFpSIop); + exec_output += PredOpExecute.subst(vcvtSIntFpSIop); + + vcvtSIntFpDCode = ''' + FPSCR fpscr = Fpscr; + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (FpOp1P0.sw) : "m" (FpOp1P0.sw)); + double cDest = FpOp1P0.sw; + __asm__ __volatile__("" :: "m" (cDest)); + finishVfp(fpscr, state); + Fpscr = fpscr; + FpDestP0.uw = dblLow(cDest); + FpDestP1.uw = dblHi(cDest); + ''' + vcvtSIntFpDIop = InstObjParams("vcvt", "VcvtSIntFpD", "FpRegRegOp", + { "code": vcvtSIntFpDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcvtSIntFpDIop); + decoder_output += FpRegRegOpConstructor.subst(vcvtSIntFpDIop); + exec_output += PredOpExecute.subst(vcvtSIntFpDIop); + + vcvtFpUIntSRCode = ''' + FPSCR fpscr = Fpscr; + VfpSavedState state = prepFpState(fpscr.rMode); + vfpFlushToZero(fpscr, FpOp1); + __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1)); + FpDest.uw = vfpFpSToFixed(FpOp1, false, false, 0, false); + __asm__ __volatile__("" :: "m" (FpDest.uw)); + finishVfp(fpscr, state); + Fpscr = fpscr; + ''' + vcvtFpUIntSRIop = InstObjParams("vcvt", "VcvtFpUIntSR", "FpRegRegOp", + { "code": vcvtFpUIntSRCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcvtFpUIntSRIop); + decoder_output += FpRegRegOpConstructor.subst(vcvtFpUIntSRIop); + exec_output += PredOpExecute.subst(vcvtFpUIntSRIop); + + vcvtFpUIntDRCode = ''' + FPSCR fpscr = Fpscr; + double cOp1 = dbl(FpOp1P0.uw, FpOp1P1.uw); + vfpFlushToZero(fpscr, cOp1); + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1)); + uint64_t result = vfpFpDToFixed(cOp1, false, false, 0, false); + __asm__ __volatile__("" :: "m" (result)); + finishVfp(fpscr, state); + Fpscr = fpscr; + FpDestP0.uw = result; + ''' + vcvtFpUIntDRIop = InstObjParams("vcvtr", "VcvtFpUIntDR", "FpRegRegOp", + { "code": vcvtFpUIntDRCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcvtFpUIntDRIop); + decoder_output += FpRegRegOpConstructor.subst(vcvtFpUIntDRIop); + exec_output += PredOpExecute.subst(vcvtFpUIntDRIop); + + vcvtFpSIntSRCode = ''' + FPSCR fpscr = Fpscr; + VfpSavedState state = prepFpState(fpscr.rMode); + vfpFlushToZero(fpscr, FpOp1); + __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1)); + FpDest.sw = vfpFpSToFixed(FpOp1, true, false, 0, false); + __asm__ __volatile__("" :: "m" (FpDest.sw)); + finishVfp(fpscr, state); + Fpscr = fpscr; + ''' + vcvtFpSIntSRIop = InstObjParams("vcvtr", "VcvtFpSIntSR", "FpRegRegOp", + { "code": vcvtFpSIntSRCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcvtFpSIntSRIop); + decoder_output += FpRegRegOpConstructor.subst(vcvtFpSIntSRIop); + exec_output += PredOpExecute.subst(vcvtFpSIntSRIop); + + vcvtFpSIntDRCode = ''' + FPSCR fpscr = Fpscr; + double cOp1 = dbl(FpOp1P0.uw, FpOp1P1.uw); + vfpFlushToZero(fpscr, cOp1); + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1)); + int64_t result = vfpFpDToFixed(cOp1, true, false, 0, false); + __asm__ __volatile__("" :: "m" (result)); + finishVfp(fpscr, state); + Fpscr = fpscr; + FpDestP0.uw = result; + ''' + vcvtFpSIntDRIop = InstObjParams("vcvtr", "VcvtFpSIntDR", "FpRegRegOp", + { "code": vcvtFpSIntDRCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcvtFpSIntDRIop); + decoder_output += FpRegRegOpConstructor.subst(vcvtFpSIntDRIop); + exec_output += PredOpExecute.subst(vcvtFpSIntDRIop); + + vcvtFpUIntSCode = ''' + FPSCR fpscr = Fpscr; + vfpFlushToZero(fpscr, FpOp1); + VfpSavedState state = prepFpState(fpscr.rMode); + fesetround(FeRoundZero); + __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1)); + FpDest.uw = vfpFpSToFixed(FpOp1, false, false, 0); + __asm__ __volatile__("" :: "m" (FpDest.uw)); + finishVfp(fpscr, state); + Fpscr = fpscr; + ''' + vcvtFpUIntSIop = InstObjParams("vcvt", "VcvtFpUIntS", "FpRegRegOp", + { "code": vcvtFpUIntSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcvtFpUIntSIop); + decoder_output += FpRegRegOpConstructor.subst(vcvtFpUIntSIop); + exec_output += PredOpExecute.subst(vcvtFpUIntSIop); + + vcvtFpUIntDCode = ''' + FPSCR fpscr = Fpscr; + double cOp1 = dbl(FpOp1P0.uw, FpOp1P1.uw); + vfpFlushToZero(fpscr, cOp1); + VfpSavedState state = prepFpState(fpscr.rMode); + fesetround(FeRoundZero); + __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1)); + uint64_t result = vfpFpDToFixed(cOp1, false, false, 0); + __asm__ __volatile__("" :: "m" (result)); + finishVfp(fpscr, state); + Fpscr = fpscr; + FpDestP0.uw = result; + ''' + vcvtFpUIntDIop = InstObjParams("vcvt", "VcvtFpUIntD", "FpRegRegOp", + { "code": vcvtFpUIntDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcvtFpUIntDIop); + decoder_output += FpRegRegOpConstructor.subst(vcvtFpUIntDIop); + exec_output += PredOpExecute.subst(vcvtFpUIntDIop); + + vcvtFpSIntSCode = ''' + FPSCR fpscr = Fpscr; + vfpFlushToZero(fpscr, FpOp1); + VfpSavedState state = prepFpState(fpscr.rMode); + fesetround(FeRoundZero); + __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1)); + FpDest.sw = vfpFpSToFixed(FpOp1, true, false, 0); + __asm__ __volatile__("" :: "m" (FpDest.sw)); + finishVfp(fpscr, state); + Fpscr = fpscr; + ''' + vcvtFpSIntSIop = InstObjParams("vcvt", "VcvtFpSIntS", "FpRegRegOp", + { "code": vcvtFpSIntSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcvtFpSIntSIop); + decoder_output += FpRegRegOpConstructor.subst(vcvtFpSIntSIop); + exec_output += PredOpExecute.subst(vcvtFpSIntSIop); + + vcvtFpSIntDCode = ''' + FPSCR fpscr = Fpscr; + double cOp1 = dbl(FpOp1P0.uw, FpOp1P1.uw); + vfpFlushToZero(fpscr, cOp1); + VfpSavedState state = prepFpState(fpscr.rMode); + fesetround(FeRoundZero); + __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1)); + int64_t result = vfpFpDToFixed(cOp1, true, false, 0); + __asm__ __volatile__("" :: "m" (result)); + finishVfp(fpscr, state); + Fpscr = fpscr; + FpDestP0.uw = result; + ''' + vcvtFpSIntDIop = InstObjParams("vcvt", "VcvtFpSIntD", "FpRegRegOp", + { "code": vcvtFpSIntDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcvtFpSIntDIop); + decoder_output += FpRegRegOpConstructor.subst(vcvtFpSIntDIop); + exec_output += PredOpExecute.subst(vcvtFpSIntDIop); + + vcvtFpSFpDCode = ''' + FPSCR fpscr = Fpscr; + vfpFlushToZero(fpscr, FpOp1); + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1)); + double cDest = fixFpSFpDDest(Fpscr, FpOp1); + __asm__ __volatile__("" :: "m" (cDest)); + finishVfp(fpscr, state); + Fpscr = fpscr; + FpDestP0.uw = dblLow(cDest); + FpDestP1.uw = dblHi(cDest); + ''' + vcvtFpSFpDIop = InstObjParams("vcvt", "VcvtFpSFpD", "FpRegRegOp", + { "code": vcvtFpSFpDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcvtFpSFpDIop); + decoder_output += FpRegRegOpConstructor.subst(vcvtFpSFpDIop); + exec_output += PredOpExecute.subst(vcvtFpSFpDIop); + + vcvtFpDFpSCode = ''' + FPSCR fpscr = Fpscr; + double cOp1 = dbl(FpOp1P0.uw, FpOp1P1.uw); + vfpFlushToZero(fpscr, cOp1); + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1)); + FpDest = fixFpDFpSDest(Fpscr, cOp1); + __asm__ __volatile__("" :: "m" (FpDest)); + finishVfp(fpscr, state); + Fpscr = fpscr; + ''' + vcvtFpDFpSIop = InstObjParams("vcvt", "VcvtFpDFpS", "FpRegRegOp", + { "code": vcvtFpDFpSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcvtFpDFpSIop); + decoder_output += FpRegRegOpConstructor.subst(vcvtFpDFpSIop); + exec_output += PredOpExecute.subst(vcvtFpDFpSIop); + + vcvtFpHTFpSCode = ''' + FPSCR fpscr = Fpscr; + vfpFlushToZero(fpscr, FpOp1); + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1)); + FpDest = vcvtFpHFpS(fpscr, FpOp1, true); + __asm__ __volatile__("" :: "m" (FpDest)); + finishVfp(fpscr, state); + Fpscr = fpscr; + ''' + vcvtFpHTFpSIop = InstObjParams("vcvtt", "VcvtFpHTFpS", "FpRegRegOp", + { "code": vcvtFpHTFpSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcvtFpHTFpSIop); + decoder_output += FpRegRegOpConstructor.subst(vcvtFpHTFpSIop); + exec_output += PredOpExecute.subst(vcvtFpHTFpSIop); + + vcvtFpHBFpSCode = ''' + FPSCR fpscr = Fpscr; + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1)); + FpDest = vcvtFpHFpS(fpscr, FpOp1, false); + __asm__ __volatile__("" :: "m" (FpDest)); + finishVfp(fpscr, state); + Fpscr = fpscr; + ''' + vcvtFpHBFpSIop = InstObjParams("vcvtb", "VcvtFpHBFpS", "FpRegRegOp", + { "code": vcvtFpHBFpSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcvtFpHBFpSIop); + decoder_output += FpRegRegOpConstructor.subst(vcvtFpHBFpSIop); + exec_output += PredOpExecute.subst(vcvtFpHBFpSIop); + + vcvtFpSFpHTCode = ''' + FPSCR fpscr = Fpscr; + vfpFlushToZero(fpscr, FpOp1); + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (FpOp1), "=m" (FpDest) + : "m" (FpOp1), "m" (FpDest)); + FpDest = vcvtFpSFpH(fpscr, FpOp1, FpDest, true); + __asm__ __volatile__("" :: "m" (FpDest)); + finishVfp(fpscr, state); + Fpscr = fpscr; + ''' + vcvtFpSFpHTIop = InstObjParams("vcvtt", "VcvtFpSFpHT", "FpRegRegOp", + { "code": vcvtFpHTFpSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcvtFpSFpHTIop); + decoder_output += FpRegRegOpConstructor.subst(vcvtFpSFpHTIop); + exec_output += PredOpExecute.subst(vcvtFpSFpHTIop); + + vcvtFpSFpHBCode = ''' + FPSCR fpscr = Fpscr; + vfpFlushToZero(fpscr, FpOp1); + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (FpOp1), "=m" (FpDest) + : "m" (FpOp1), "m" (FpDest)); + FpDest = vcvtFpSFpH(fpscr, FpOp1, FpDest, false); + __asm__ __volatile__("" :: "m" (FpDest)); + finishVfp(fpscr, state); + Fpscr = fpscr; + ''' + vcvtFpSFpHBIop = InstObjParams("vcvtb", "VcvtFpSFpHB", "FpRegRegOp", + { "code": vcvtFpSFpHBCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcvtFpSFpHBIop); + decoder_output += FpRegRegOpConstructor.subst(vcvtFpSFpHBIop); + exec_output += PredOpExecute.subst(vcvtFpSFpHBIop); + + vcmpSCode = ''' + FPSCR fpscr = Fpscr; + vfpFlushToZero(fpscr, FpDest, FpOp1); + if (FpDest == FpOp1) { + fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0; + } else if (FpDest < FpOp1) { + fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0; + } else if (FpDest > FpOp1) { + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0; + } else { + const uint32_t qnan = 0x7fc00000; + const bool nan1 = std::isnan(FpDest); + const bool signal1 = nan1 && ((fpToBits(FpDest) & qnan) != qnan); + const bool nan2 = std::isnan(FpOp1); + const bool signal2 = nan2 && ((fpToBits(FpOp1) & qnan) != qnan); + if (signal1 || signal2) + fpscr.ioc = 1; + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1; + } + Fpscr = fpscr; + ''' + vcmpSIop = InstObjParams("vcmps", "VcmpS", "FpRegRegOp", + { "code": vcmpSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcmpSIop); + decoder_output += FpRegRegOpConstructor.subst(vcmpSIop); + exec_output += PredOpExecute.subst(vcmpSIop); + + vcmpDCode = ''' + double cOp1 = dbl(FpOp1P0.uw, FpOp1P1.uw); + double cDest = dbl(FpDestP0.uw, FpDestP1.uw); + FPSCR fpscr = Fpscr; + vfpFlushToZero(fpscr, cDest, cOp1); + if (cDest == cOp1) { + fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0; + } else if (cDest < cOp1) { + fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0; + } else if (cDest > cOp1) { + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0; + } else { + const uint64_t qnan = ULL(0x7ff8000000000000); + const bool nan1 = std::isnan(cDest); + const bool signal1 = nan1 && ((fpToBits(cDest) & qnan) != qnan); + const bool nan2 = std::isnan(cOp1); + const bool signal2 = nan2 && ((fpToBits(cOp1) & qnan) != qnan); + if (signal1 || signal2) + fpscr.ioc = 1; + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1; + } + Fpscr = fpscr; + ''' + vcmpDIop = InstObjParams("vcmpd", "VcmpD", "FpRegRegOp", + { "code": vcmpDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcmpDIop); + decoder_output += FpRegRegOpConstructor.subst(vcmpDIop); + exec_output += PredOpExecute.subst(vcmpDIop); + + vcmpZeroSCode = ''' + FPSCR fpscr = Fpscr; + vfpFlushToZero(fpscr, FpDest); + // This only handles imm == 0 for now. + assert(imm == 0); + if (FpDest == imm) { + fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0; + } else if (FpDest < imm) { + fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0; + } else if (FpDest > imm) { + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0; + } else { + const uint32_t qnan = 0x7fc00000; + const bool nan = std::isnan(FpDest); + const bool signal = nan && ((fpToBits(FpDest) & qnan) != qnan); + if (signal) + fpscr.ioc = 1; + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1; + } + Fpscr = fpscr; + ''' + vcmpZeroSIop = InstObjParams("vcmpZeros", "VcmpZeroS", "FpRegImmOp", + { "code": vcmpZeroSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegImmOpDeclare.subst(vcmpZeroSIop); + decoder_output += FpRegImmOpConstructor.subst(vcmpZeroSIop); + exec_output += PredOpExecute.subst(vcmpZeroSIop); + + vcmpZeroDCode = ''' + // This only handles imm == 0 for now. + assert(imm == 0); + double cDest = dbl(FpDestP0.uw, FpDestP1.uw); + FPSCR fpscr = Fpscr; + vfpFlushToZero(fpscr, cDest); + if (cDest == imm) { + fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0; + } else if (cDest < imm) { + fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0; + } else if (cDest > imm) { + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0; + } else { + const uint64_t qnan = ULL(0x7ff8000000000000); + const bool nan = std::isnan(cDest); + const bool signal = nan && ((fpToBits(cDest) & qnan) != qnan); + if (signal) + fpscr.ioc = 1; + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1; + } + Fpscr = fpscr; + ''' + vcmpZeroDIop = InstObjParams("vcmpZerod", "VcmpZeroD", "FpRegImmOp", + { "code": vcmpZeroDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegImmOpDeclare.subst(vcmpZeroDIop); + decoder_output += FpRegImmOpConstructor.subst(vcmpZeroDIop); + exec_output += PredOpExecute.subst(vcmpZeroDIop); + + vcmpeSCode = ''' + FPSCR fpscr = Fpscr; + vfpFlushToZero(fpscr, FpDest, FpOp1); + if (FpDest == FpOp1) { + fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0; + } else if (FpDest < FpOp1) { + fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0; + } else if (FpDest > FpOp1) { + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0; + } else { + fpscr.ioc = 1; + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1; + } + Fpscr = fpscr; + ''' + vcmpeSIop = InstObjParams("vcmpes", "VcmpeS", "FpRegRegOp", + { "code": vcmpeSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcmpeSIop); + decoder_output += FpRegRegOpConstructor.subst(vcmpeSIop); + exec_output += PredOpExecute.subst(vcmpeSIop); + + vcmpeDCode = ''' + double cOp1 = dbl(FpOp1P0.uw, FpOp1P1.uw); + double cDest = dbl(FpDestP0.uw, FpDestP1.uw); + FPSCR fpscr = Fpscr; + vfpFlushToZero(fpscr, cDest, cOp1); + if (cDest == cOp1) { + fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0; + } else if (cDest < cOp1) { + fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0; + } else if (cDest > cOp1) { + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0; + } else { + fpscr.ioc = 1; + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1; + } + Fpscr = fpscr; + ''' + vcmpeDIop = InstObjParams("vcmped", "VcmpeD", "FpRegRegOp", + { "code": vcmpeDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegOpDeclare.subst(vcmpeDIop); + decoder_output += FpRegRegOpConstructor.subst(vcmpeDIop); + exec_output += PredOpExecute.subst(vcmpeDIop); + + vcmpeZeroSCode = ''' + FPSCR fpscr = Fpscr; + vfpFlushToZero(fpscr, FpDest); + if (FpDest == imm) { + fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0; + } else if (FpDest < imm) { + fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0; + } else if (FpDest > imm) { + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0; + } else { + fpscr.ioc = 1; + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1; + } + Fpscr = fpscr; + ''' + vcmpeZeroSIop = InstObjParams("vcmpeZeros", "VcmpeZeroS", "FpRegImmOp", + { "code": vcmpeZeroSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegImmOpDeclare.subst(vcmpeZeroSIop); + decoder_output += FpRegImmOpConstructor.subst(vcmpeZeroSIop); + exec_output += PredOpExecute.subst(vcmpeZeroSIop); + + vcmpeZeroDCode = ''' + double cDest = dbl(FpDestP0.uw, FpDestP1.uw); + FPSCR fpscr = Fpscr; + vfpFlushToZero(fpscr, cDest); + if (cDest == imm) { + fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0; + } else if (cDest < imm) { + fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0; + } else if (cDest > imm) { + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0; + } else { + fpscr.ioc = 1; + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1; + } + Fpscr = fpscr; + ''' + vcmpeZeroDIop = InstObjParams("vcmpeZerod", "VcmpeZeroD", "FpRegImmOp", + { "code": vcmpeZeroDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegImmOpDeclare.subst(vcmpeZeroDIop); + decoder_output += FpRegImmOpConstructor.subst(vcmpeZeroDIop); + exec_output += PredOpExecute.subst(vcmpeZeroDIop); +}}; + +let {{ + + header_output = "" + decoder_output = "" + exec_output = "" + + vcvtFpSFixedSCode = ''' + FPSCR fpscr = Fpscr; + vfpFlushToZero(fpscr, FpOp1); + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1)); + FpDest.sw = vfpFpSToFixed(FpOp1, true, false, imm); + __asm__ __volatile__("" :: "m" (FpDest.sw)); + finishVfp(fpscr, state); + Fpscr = fpscr; + ''' + vcvtFpSFixedSIop = InstObjParams("vcvt", "VcvtFpSFixedS", "FpRegRegImmOp", + { "code": vcvtFpSFixedSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vcvtFpSFixedSIop); + decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpSFixedSIop); + exec_output += PredOpExecute.subst(vcvtFpSFixedSIop); + + vcvtFpSFixedDCode = ''' + FPSCR fpscr = Fpscr; + double cOp1 = dbl(FpOp1P0.uw, FpOp1P1.uw); + vfpFlushToZero(fpscr, cOp1); + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1)); + uint64_t mid = vfpFpDToFixed(cOp1, true, false, imm); + __asm__ __volatile__("" :: "m" (mid)); + finishVfp(fpscr, state); + Fpscr = fpscr; + FpDestP0.uw = mid; + FpDestP1.uw = mid >> 32; + ''' + vcvtFpSFixedDIop = InstObjParams("vcvt", "VcvtFpSFixedD", "FpRegRegImmOp", + { "code": vcvtFpSFixedDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vcvtFpSFixedDIop); + decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpSFixedDIop); + exec_output += PredOpExecute.subst(vcvtFpSFixedDIop); + + vcvtFpUFixedSCode = ''' + FPSCR fpscr = Fpscr; + vfpFlushToZero(fpscr, FpOp1); + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1)); + FpDest.uw = vfpFpSToFixed(FpOp1, false, false, imm); + __asm__ __volatile__("" :: "m" (FpDest.uw)); + finishVfp(fpscr, state); + Fpscr = fpscr; + ''' + vcvtFpUFixedSIop = InstObjParams("vcvt", "VcvtFpUFixedS", "FpRegRegImmOp", + { "code": vcvtFpUFixedSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vcvtFpUFixedSIop); + decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpUFixedSIop); + exec_output += PredOpExecute.subst(vcvtFpUFixedSIop); + + vcvtFpUFixedDCode = ''' + FPSCR fpscr = Fpscr; + double cOp1 = dbl(FpOp1P0.uw, FpOp1P1.uw); + vfpFlushToZero(fpscr, cOp1); + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1)); + uint64_t mid = vfpFpDToFixed(cOp1, false, false, imm); + __asm__ __volatile__("" :: "m" (mid)); + finishVfp(fpscr, state); + Fpscr = fpscr; + FpDestP0.uw = mid; + FpDestP1.uw = mid >> 32; + ''' + vcvtFpUFixedDIop = InstObjParams("vcvt", "VcvtFpUFixedD", "FpRegRegImmOp", + { "code": vcvtFpUFixedDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vcvtFpUFixedDIop); + decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpUFixedDIop); + exec_output += PredOpExecute.subst(vcvtFpUFixedDIop); + + vcvtSFixedFpSCode = ''' + FPSCR fpscr = Fpscr; + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (FpOp1.sw) : "m" (FpOp1.sw)); + FpDest = vfpSFixedToFpS(Fpscr, FpOp1.sw, false, imm); + __asm__ __volatile__("" :: "m" (FpDest)); + finishVfp(fpscr, state); + Fpscr = fpscr; + ''' + vcvtSFixedFpSIop = InstObjParams("vcvt", "VcvtSFixedFpS", "FpRegRegImmOp", + { "code": vcvtSFixedFpSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vcvtSFixedFpSIop); + decoder_output += FpRegRegImmOpConstructor.subst(vcvtSFixedFpSIop); + exec_output += PredOpExecute.subst(vcvtSFixedFpSIop); + + vcvtSFixedFpDCode = ''' + FPSCR fpscr = Fpscr; + uint64_t mid = ((uint64_t)FpOp1P0.uw | ((uint64_t)FpOp1P1.uw << 32)); + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (mid) : "m" (mid)); + double cDest = vfpSFixedToFpD(Fpscr, mid, false, imm); + __asm__ __volatile__("" :: "m" (cDest)); + finishVfp(fpscr, state); + Fpscr = fpscr; + FpDestP0.uw = dblLow(cDest); + FpDestP1.uw = dblHi(cDest); + ''' + vcvtSFixedFpDIop = InstObjParams("vcvt", "VcvtSFixedFpD", "FpRegRegImmOp", + { "code": vcvtSFixedFpDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vcvtSFixedFpDIop); + decoder_output += FpRegRegImmOpConstructor.subst(vcvtSFixedFpDIop); + exec_output += PredOpExecute.subst(vcvtSFixedFpDIop); + + vcvtUFixedFpSCode = ''' + FPSCR fpscr = Fpscr; + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (FpOp1.uw) : "m" (FpOp1.uw)); + FpDest = vfpUFixedToFpS(Fpscr, FpOp1.uw, false, imm); + __asm__ __volatile__("" :: "m" (FpDest)); + finishVfp(fpscr, state); + Fpscr = fpscr; + ''' + vcvtUFixedFpSIop = InstObjParams("vcvt", "VcvtUFixedFpS", "FpRegRegImmOp", + { "code": vcvtUFixedFpSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vcvtUFixedFpSIop); + decoder_output += FpRegRegImmOpConstructor.subst(vcvtUFixedFpSIop); + exec_output += PredOpExecute.subst(vcvtUFixedFpSIop); + + vcvtUFixedFpDCode = ''' + FPSCR fpscr = Fpscr; + uint64_t mid = ((uint64_t)FpOp1P0.uw | ((uint64_t)FpOp1P1.uw << 32)); + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (mid) : "m" (mid)); + double cDest = vfpUFixedToFpD(Fpscr, mid, false, imm); + __asm__ __volatile__("" :: "m" (cDest)); + finishVfp(fpscr, state); + Fpscr = fpscr; + FpDestP0.uw = dblLow(cDest); + FpDestP1.uw = dblHi(cDest); + ''' + vcvtUFixedFpDIop = InstObjParams("vcvt", "VcvtUFixedFpD", "FpRegRegImmOp", + { "code": vcvtUFixedFpDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vcvtUFixedFpDIop); + decoder_output += FpRegRegImmOpConstructor.subst(vcvtUFixedFpDIop); + exec_output += PredOpExecute.subst(vcvtUFixedFpDIop); + + vcvtFpSHFixedSCode = ''' + FPSCR fpscr = Fpscr; + vfpFlushToZero(fpscr, FpOp1); + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1)); + FpDest.sh = vfpFpSToFixed(FpOp1, true, true, imm); + __asm__ __volatile__("" :: "m" (FpDest.sh)); + finishVfp(fpscr, state); + Fpscr = fpscr; + ''' + vcvtFpSHFixedSIop = InstObjParams("vcvt", "VcvtFpSHFixedS", + "FpRegRegImmOp", + { "code": vcvtFpSHFixedSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vcvtFpSHFixedSIop); + decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpSHFixedSIop); + exec_output += PredOpExecute.subst(vcvtFpSHFixedSIop); + + vcvtFpSHFixedDCode = ''' + FPSCR fpscr = Fpscr; + double cOp1 = dbl(FpOp1P0.uw, FpOp1P1.uw); + vfpFlushToZero(fpscr, cOp1); + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1)); + uint64_t result = vfpFpDToFixed(cOp1, true, true, imm); + __asm__ __volatile__("" :: "m" (result)); + finishVfp(fpscr, state); + Fpscr = fpscr; + FpDestP0.uw = result; + FpDestP1.uw = result >> 32; + ''' + vcvtFpSHFixedDIop = InstObjParams("vcvt", "VcvtFpSHFixedD", + "FpRegRegImmOp", + { "code": vcvtFpSHFixedDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vcvtFpSHFixedDIop); + decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpSHFixedDIop); + exec_output += PredOpExecute.subst(vcvtFpSHFixedDIop); + + vcvtFpUHFixedSCode = ''' + FPSCR fpscr = Fpscr; + vfpFlushToZero(fpscr, FpOp1); + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (FpOp1) : "m" (FpOp1)); + FpDest.uh = vfpFpSToFixed(FpOp1, false, true, imm); + __asm__ __volatile__("" :: "m" (FpDest.uh)); + finishVfp(fpscr, state); + Fpscr = fpscr; + ''' + vcvtFpUHFixedSIop = InstObjParams("vcvt", "VcvtFpUHFixedS", + "FpRegRegImmOp", + { "code": vcvtFpUHFixedSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vcvtFpUHFixedSIop); + decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpUHFixedSIop); + exec_output += PredOpExecute.subst(vcvtFpUHFixedSIop); + + vcvtFpUHFixedDCode = ''' + FPSCR fpscr = Fpscr; + double cOp1 = dbl(FpOp1P0.uw, FpOp1P1.uw); + vfpFlushToZero(fpscr, cOp1); + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (cOp1) : "m" (cOp1)); + uint64_t mid = vfpFpDToFixed(cOp1, false, true, imm); + __asm__ __volatile__("" :: "m" (mid)); + finishVfp(fpscr, state); + Fpscr = fpscr; + FpDestP0.uw = mid; + FpDestP1.uw = mid >> 32; + ''' + vcvtFpUHFixedDIop = InstObjParams("vcvt", "VcvtFpUHFixedD", + "FpRegRegImmOp", + { "code": vcvtFpUHFixedDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vcvtFpUHFixedDIop); + decoder_output += FpRegRegImmOpConstructor.subst(vcvtFpUHFixedDIop); + exec_output += PredOpExecute.subst(vcvtFpUHFixedDIop); + + vcvtSHFixedFpSCode = ''' + FPSCR fpscr = Fpscr; + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (FpOp1.sh) : "m" (FpOp1.sh)); + FpDest = vfpSFixedToFpS(Fpscr, FpOp1.sh, true, imm); + __asm__ __volatile__("" :: "m" (FpDest)); + finishVfp(fpscr, state); + Fpscr = fpscr; + ''' + vcvtSHFixedFpSIop = InstObjParams("vcvt", "VcvtSHFixedFpS", + "FpRegRegImmOp", + { "code": vcvtSHFixedFpSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vcvtSHFixedFpSIop); + decoder_output += FpRegRegImmOpConstructor.subst(vcvtSHFixedFpSIop); + exec_output += PredOpExecute.subst(vcvtSHFixedFpSIop); + + vcvtSHFixedFpDCode = ''' + FPSCR fpscr = Fpscr; + uint64_t mid = ((uint64_t)FpOp1P0.uw | ((uint64_t)FpOp1P1.uw << 32)); + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (mid) : "m" (mid)); + double cDest = vfpSFixedToFpD(Fpscr, mid, true, imm); + __asm__ __volatile__("" :: "m" (cDest)); + finishVfp(fpscr, state); + Fpscr = fpscr; + FpDestP0.uw = dblLow(cDest); + FpDestP1.uw = dblHi(cDest); + ''' + vcvtSHFixedFpDIop = InstObjParams("vcvt", "VcvtSHFixedFpD", + "FpRegRegImmOp", + { "code": vcvtSHFixedFpDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vcvtSHFixedFpDIop); + decoder_output += FpRegRegImmOpConstructor.subst(vcvtSHFixedFpDIop); + exec_output += PredOpExecute.subst(vcvtSHFixedFpDIop); + + vcvtUHFixedFpSCode = ''' + FPSCR fpscr = Fpscr; + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (FpOp1.uh) : "m" (FpOp1.uh)); + FpDest = vfpUFixedToFpS(Fpscr, FpOp1.uh, true, imm); + __asm__ __volatile__("" :: "m" (FpDest)); + finishVfp(fpscr, state); + Fpscr = fpscr; + ''' + vcvtUHFixedFpSIop = InstObjParams("vcvt", "VcvtUHFixedFpS", + "FpRegRegImmOp", + { "code": vcvtUHFixedFpSCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vcvtUHFixedFpSIop); + decoder_output += FpRegRegImmOpConstructor.subst(vcvtUHFixedFpSIop); + exec_output += PredOpExecute.subst(vcvtUHFixedFpSIop); + + vcvtUHFixedFpDCode = ''' + FPSCR fpscr = Fpscr; + uint64_t mid = ((uint64_t)FpOp1P0.uw | ((uint64_t)FpOp1P1.uw << 32)); + VfpSavedState state = prepFpState(fpscr.rMode); + __asm__ __volatile__("" : "=m" (mid) : "m" (mid)); + double cDest = vfpUFixedToFpD(Fpscr, mid, true, imm); + __asm__ __volatile__("" :: "m" (cDest)); + finishVfp(fpscr, state); + Fpscr = fpscr; + FpDestP0.uw = dblLow(cDest); + FpDestP1.uw = dblHi(cDest); + ''' + vcvtUHFixedFpDIop = InstObjParams("vcvt", "VcvtUHFixedFpD", + "FpRegRegImmOp", + { "code": vcvtUHFixedFpDCode, + "predicate_test": predicateTest }, []) + header_output += FpRegRegImmOpDeclare.subst(vcvtUHFixedFpDIop); + decoder_output += FpRegRegImmOpConstructor.subst(vcvtUHFixedFpDIop); + exec_output += PredOpExecute.subst(vcvtUHFixedFpDIop); +}}; diff -r 84bd4089958b src/arch/arm/isa/insts/insts.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/insts/insts.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,74 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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: Gabe Black + +//Basic forms of various templates +##include "basic.isa" + +//Useful bits shared by memory instructions +##include "mem.isa" + +//Loads of a single item +##include "ldr.isa" + +//Miscellaneous instructions that don't fit elsewhere +##include "misc.isa" + +//Stores of a single item +##include "str.isa" + +//Swaps +##include "swap.isa" + +//Load/store multiple +##include "macromem.isa" + +//Data processing instructions +##include "data.isa" + +//Branches +##include "branch.isa" + +//Multiply +##include "mult.isa" + +//Divide +##include "div.isa" + +//FP (VFP and Neon) +##include "fp.isa" diff -r 84bd4089958b src/arch/arm/isa/insts/ldr.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/insts/ldr.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,354 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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: Gabe Black + +let {{ + + header_output = "" + decoder_output = "" + exec_output = "" + + def loadImmClassName(post, add, writeback, \ + size=4, sign=False, user=False): + return memClassName("LOAD_IMM", post, add, writeback, + size, sign, user) + + def loadRegClassName(post, add, writeback, \ + size=4, sign=False, user=False): + return memClassName("LOAD_REG", post, add, writeback, + size, sign, user) + + def loadDoubleImmClassName(post, add, writeback): + return memClassName("LOAD_IMMD", post, add, writeback, 4, False, False) + + def loadDoubleRegClassName(post, add, writeback): + return memClassName("LOAD_REGD", post, add, writeback, 4, False, False) + + def emitLoad(name, Name, imm, eaCode, accCode, \ + memFlags, instFlags, base, double=False): + global header_output, decoder_output, exec_output + + (newHeader, + newDecoder, + newExec) = loadStoreBase(name, Name, imm, + eaCode, accCode, "", + memFlags, instFlags, double, False, + base, execTemplateBase = 'Load') + + header_output += newHeader + decoder_output += newDecoder + exec_output += newExec + + def buildImmLoad(mnem, post, add, writeback, \ + size=4, sign=False, user=False, \ + prefetch=False, ldrex=False, vldr=False): + name = mnem + Name = loadImmClassName(post, add, writeback, \ + size, sign, user) + + if add: + op = " +" + else: + op = " -" + + offset = op + " imm" + eaCode = "EA = Base" + if not post: + eaCode += offset + eaCode += ";" + + memFlags = ["ArmISA::TLB::MustBeOne", "%d" % (size - 1)] + if user: + memFlags.append("ArmISA::TLB::UserMode") + + if prefetch: + Name = "%s_%s" % (mnem.upper(), Name) + memFlags.append("Request::PREFETCH") + accCode = ''' + uint64_t temp = Mem%s;\n + temp = temp; + ''' % buildMemSuffix(sign, size) + elif vldr: + Name = "%s_%s" % (mnem.upper(), Name) + accCode = "FpDest.uw = cSwap(Mem%s, ((CPSR)Cpsr).e);\n" % \ + buildMemSuffix(sign, size) + else: + if ldrex: + memFlags.append("Request::LLSC") + Name = "%s_%s" % (mnem.upper(), Name) + accCode = "IWDest = cSwap(Mem%s, ((CPSR)Cpsr).e);" % \ + buildMemSuffix(sign, size) + + if not prefetch and not ldrex and not vldr: + memFlags.append("ArmISA::TLB::AllowUnaligned") + + if writeback: + accCode += "Base = Base %s;\n" % offset + base = buildMemBase("MemoryImm", post, writeback) + + emitLoad(name, Name, True, eaCode, accCode, memFlags, [], base) + + def buildRfeLoad(mnem, post, add, writeback): + name = mnem + Name = "RFE_" + loadImmClassName(post, add, writeback, 8) + + offset = 0 + if post != add: + offset += 4 + if not add: + offset -= 8 + + eaCode = "EA = Base + %d;" % offset + + wbDiff = -8 + if add: + wbDiff = 8 + accCode = ''' + CPSR cpsr = Cpsr; + SCTLR sctlr = Sctlr; + NPC = cSwap(Mem.ud, cpsr.e); + uint32_t newCpsr = + cpsrWriteByInstr(cpsr | CondCodes, + cSwap(Mem.ud >> 32, cpsr.e), + 0xF, true, sctlr.nmfi); + Cpsr = ~CondCodesMask & newCpsr; + CondCodes = CondCodesMask & newCpsr; + ''' + if writeback: + accCode += "Base = Base + %s;\n" % wbDiff + + global header_output, decoder_output, exec_output + + (newHeader, + newDecoder, + newExec) = RfeBase(name, Name, eaCode, accCode, + ["ArmISA::TLB::AlignWord", "ArmISA::TLB::MustBeOne"], []) + + header_output += newHeader + decoder_output += newDecoder + exec_output += newExec + + def buildRegLoad(mnem, post, add, writeback, size=4, sign=False, \ + user=False, prefetch=False): + name = mnem + Name = loadRegClassName(post, add, writeback, + size, sign, user) + + if add: + op = " +" + else: + op = " -" + + offset = op + " shift_rm_imm(Index, shiftAmt," + \ + " shiftType, CondCodes<29:>)" + eaCode = "EA = Base" + if not post: + eaCode += offset + eaCode += ";" + + memFlags = ["%d" % (size - 1), "ArmISA::TLB::MustBeOne"] + if user: + memFlags.append("ArmISA::TLB::UserMode") + + if prefetch: + Name = "%s_%s" % (mnem.upper(), Name) + memFlags.append("Request::PREFETCH") + accCode = ''' + uint64_t temp = Mem%s;\n + temp = temp; + ''' % buildMemSuffix(sign, size) + else: + accCode = "IWDest = cSwap(Mem%s, ((CPSR)Cpsr).e);" % \ + buildMemSuffix(sign, size) + if writeback: + accCode += "Base = Base %s;\n" % offset + + if not prefetch: + memFlags.append("ArmISA::TLB::AllowUnaligned") + + base = buildMemBase("MemoryReg", post, writeback) + + emitLoad(name, Name, False, eaCode, accCode, \ + memFlags, [], base) + + def buildDoubleImmLoad(mnem, post, add, writeback, \ + ldrex=False, vldr=False): + name = mnem + Name = loadDoubleImmClassName(post, add, writeback) + + if add: + op = " +" + else: + op = " -" + + offset = op + " imm" + eaCode = "EA = Base" + if not post: + eaCode += offset + eaCode += ";" + + if not vldr: + accCode = ''' + CPSR cpsr = Cpsr; + Dest = cSwap(Mem.ud, cpsr.e); + Dest2 = cSwap(Mem.ud >> 32, cpsr.e); + ''' + else: + accCode = ''' + uint64_t swappedMem = cSwap(Mem.ud, ((CPSR)Cpsr).e); + FpDest.uw = (uint32_t)swappedMem; + FpDest2.uw = (uint32_t)(swappedMem >> 32); + ''' + if ldrex: + memFlags = ["Request::LLSC"] + else: + memFlags = [] + if ldrex or vldr: + Name = "%s_%s" % (mnem.upper(), Name) + if writeback: + accCode += "Base = Base %s;\n" % offset + base = buildMemBase("MemoryDImm", post, writeback) + + memFlags.extend(["ArmISA::TLB::MustBeOne", + "ArmISA::TLB::AlignWord"]) + + emitLoad(name, Name, True, eaCode, accCode, \ + memFlags, [], base, double=True) + + def buildDoubleRegLoad(mnem, post, add, writeback): + name = mnem + Name = loadDoubleRegClassName(post, add, writeback) + + if add: + op = " +" + else: + op = " -" + + offset = op + " shift_rm_imm(Index, shiftAmt," + \ + " shiftType, CondCodes<29:>)" + eaCode = "EA = Base" + if not post: + eaCode += offset + eaCode += ";" + + accCode = ''' + CPSR cpsr = Cpsr; + Dest = cSwap(Mem.ud, cpsr.e); + Dest2 = cSwap(Mem.ud >> 32, cpsr.e); + ''' + if writeback: + accCode += "Base = Base %s;\n" % offset + base = buildMemBase("MemoryDReg", post, writeback) + + emitLoad(name, Name, False, eaCode, accCode, + ["ArmISA::TLB::MustBeOne", "ArmISA::TLB::AlignWord"], + [], base, double=True) + + def buildLoads(mnem, size=4, sign=False, user=False): + buildImmLoad(mnem, True, True, True, size, sign, user) + buildRegLoad(mnem, True, True, True, size, sign, user) + buildImmLoad(mnem, True, False, True, size, sign, user) + buildRegLoad(mnem, True, False, True, size, sign, user) + buildImmLoad(mnem, False, True, True, size, sign, user) + buildRegLoad(mnem, False, True, True, size, sign, user) + buildImmLoad(mnem, False, False, True, size, sign, user) + buildRegLoad(mnem, False, False, True, size, sign, user) + buildImmLoad(mnem, False, True, False, size, sign, user) + buildRegLoad(mnem, False, True, False, size, sign, user) + buildImmLoad(mnem, False, False, False, size, sign, user) + buildRegLoad(mnem, False, False, False, size, sign, user) + + def buildDoubleLoads(mnem): + buildDoubleImmLoad(mnem, True, True, True) + buildDoubleRegLoad(mnem, True, True, True) + buildDoubleImmLoad(mnem, True, False, True) + buildDoubleRegLoad(mnem, True, False, True) + buildDoubleImmLoad(mnem, False, True, True) + buildDoubleRegLoad(mnem, False, True, True) + buildDoubleImmLoad(mnem, False, False, True) + buildDoubleRegLoad(mnem, False, False, True) + buildDoubleImmLoad(mnem, False, True, False) + buildDoubleRegLoad(mnem, False, True, False) + buildDoubleImmLoad(mnem, False, False, False) + buildDoubleRegLoad(mnem, False, False, False) + + def buildRfeLoads(mnem): + buildRfeLoad(mnem, True, True, True) + buildRfeLoad(mnem, True, True, False) + buildRfeLoad(mnem, True, False, True) + buildRfeLoad(mnem, True, False, False) + buildRfeLoad(mnem, False, True, True) + buildRfeLoad(mnem, False, True, False) + buildRfeLoad(mnem, False, False, True) + buildRfeLoad(mnem, False, False, False) + + def buildPrefetches(mnem): + buildRegLoad(mnem, False, False, False, size=1, prefetch=True) + buildImmLoad(mnem, False, False, False, size=1, prefetch=True) + buildRegLoad(mnem, False, True, False, size=1, prefetch=True) + buildImmLoad(mnem, False, True, False, size=1, prefetch=True) + + buildLoads("ldr") + buildLoads("ldrt", user=True) + buildLoads("ldrb", size=1) + buildLoads("ldrbt", size=1, user=True) + buildLoads("ldrsb", size=1, sign=True) + buildLoads("ldrsbt", size=1, sign=True, user=True) + buildLoads("ldrh", size=2) + buildLoads("ldrht", size=2, user=True) + buildLoads("hdrsh", size=2, sign=True) + buildLoads("ldrsht", size=2, sign=True, user=True) + + buildDoubleLoads("ldrd") + + buildRfeLoads("rfe") + + buildPrefetches("pld") + buildPrefetches("pldw") + buildPrefetches("pli") + + buildImmLoad("ldrex", False, True, False, size=4, ldrex=True) + buildImmLoad("ldrexh", False, True, False, size=2, ldrex=True) + buildImmLoad("ldrexb", False, True, False, size=1, ldrex=True) + buildDoubleImmLoad("ldrexd", False, True, False, ldrex=True) + + buildImmLoad("vldr", False, True, False, size=4, vldr=True) + buildImmLoad("vldr", False, False, False, size=4, vldr=True) + buildDoubleImmLoad("vldr", False, True, False, vldr=True) + buildDoubleImmLoad("vldr", False, False, False, vldr=True) +}}; diff -r 84bd4089958b src/arch/arm/isa/insts/macromem.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/insts/macromem.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,152 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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 +// Gabe Black + +//////////////////////////////////////////////////////////////////// +// +// Load/store microops +// + +let {{ + microLdrUopCode = "IWRa = cSwap(Mem.uw, ((CPSR)Cpsr).e);" + microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop', + 'MicroMemOp', + {'memacc_code': microLdrUopCode, + 'ea_code': 'EA = Rb + (up ? imm : -imm);', + 'predicate_test': predicateTest}, + ['IsMicroop']) + + microLdrFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);" + microLdrFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrFpUop', + 'MicroMemOp', + {'memacc_code': microLdrFpUopCode, + 'ea_code': 'EA = Rb + (up ? imm : -imm);', + 'predicate_test': predicateTest}, + ['IsMicroop']) + + microLdrRetUopCode = ''' + CPSR cpsr = Cpsr; + SCTLR sctlr = Sctlr; + uint32_t newCpsr = + cpsrWriteByInstr(cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi); + Cpsr = ~CondCodesMask & newCpsr; + CondCodes = CondCodesMask & newCpsr; + IWNPC = cSwap(Mem.uw, cpsr.e) | ((Spsr & 0x20) ? 1 : 0); + ''' + microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop', + 'MicroMemOp', + {'memacc_code': microLdrRetUopCode, + 'ea_code': + 'EA = Rb + (up ? imm : -imm);', + 'predicate_test': condPredicateTest}, + ['IsMicroop']) + + microStrUopCode = "Mem = cSwap(Ra.uw, ((CPSR)Cpsr).e);" + microStrUopIop = InstObjParams('str_uop', 'MicroStrUop', + 'MicroMemOp', + {'memacc_code': microStrUopCode, + 'postacc_code': "", + 'ea_code': 'EA = Rb + (up ? imm : -imm);', + 'predicate_test': predicateTest}, + ['IsMicroop']) + + microStrFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" + microStrFpUopIop = InstObjParams('strfp_uop', 'MicroStrFpUop', + 'MicroMemOp', + {'memacc_code': microStrFpUopCode, + 'postacc_code': "", + 'ea_code': 'EA = Rb + (up ? imm : -imm);', + 'predicate_test': predicateTest}, + ['IsMicroop']) + + header_output = decoder_output = exec_output = '' + + loadIops = (microLdrUopIop, microLdrFpUopIop, microLdrRetUopIop) + storeIops = (microStrUopIop, microStrFpUopIop) + for iop in loadIops + storeIops: + header_output += MicroMemDeclare.subst(iop) + decoder_output += MicroMemConstructor.subst(iop) + for iop in loadIops: + exec_output += LoadExecute.subst(iop) + \ + LoadInitiateAcc.subst(iop) + \ + LoadCompleteAcc.subst(iop) + for iop in storeIops: + exec_output += StoreExecute.subst(iop) + \ + StoreInitiateAcc.subst(iop) + \ + StoreCompleteAcc.subst(iop) +}}; + +//////////////////////////////////////////////////////////////////// +// +// Integer = Integer op Immediate microops +// + +let {{ + microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop', + 'MicroIntOp', + {'code': 'Ra = Rb + imm;', + 'predicate_test': predicateTest}, + ['IsMicroop']) + + microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop', + 'MicroIntOp', + {'code': 'Ra = Rb - imm;', + 'predicate_test': predicateTest}, + ['IsMicroop']) + + header_output = MicroIntDeclare.subst(microAddiUopIop) + \ + MicroIntDeclare.subst(microSubiUopIop) + decoder_output = MicroIntConstructor.subst(microAddiUopIop) + \ + MicroIntConstructor.subst(microSubiUopIop) + exec_output = PredOpExecute.subst(microAddiUopIop) + \ + PredOpExecute.subst(microSubiUopIop) +}}; + +let {{ + iop = InstObjParams("ldmstm", "LdmStm", 'MacroMemOp', "", []) + header_output = MacroMemDeclare.subst(iop) + decoder_output = MacroMemConstructor.subst(iop) + + vfpIop = InstObjParams("vldmstm", "VLdmStm", 'MacroVFPMemOp', "", []) + header_output += MacroVFPMemDeclare.subst(vfpIop) + decoder_output += MacroVFPMemConstructor.subst(vfpIop) +}}; diff -r 84bd4089958b src/arch/arm/isa/insts/mem.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/insts/mem.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,206 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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: Gabe Black + +let {{ + def loadStoreBaseWork(name, Name, imm, swp, rfe, srs, codeBlobs, + memFlags, instFlags, double, strex, + base = 'Memory', execTemplateBase = ''): + # Make sure flags are in lists (convert to lists if not). + memFlags = makeList(memFlags) + instFlags = makeList(instFlags) + + eaCode = codeBlobs["ea_code"] + + # This shouldn't be part of the eaCode, but until the exec templates + # are converted over it's the easiest place to put it. + eaCode += '\n unsigned memAccessFlags = ' + eaCode += (string.join(memFlags, '|') + ';') + + codeBlobs["ea_code"] = eaCode + + iop = InstObjParams(name, Name, base, codeBlobs, instFlags) + + fullExecTemplate = eval(execTemplateBase + 'Execute') + initiateAccTemplate = eval(execTemplateBase + 'InitiateAcc') + completeAccTemplate = eval(execTemplateBase + 'CompleteAcc') + + if swp: + declareTemplate = SwapDeclare + constructTemplate = SwapConstructor + elif rfe: + declareTemplate = RfeDeclare + constructTemplate = RfeConstructor + elif srs: + declareTemplate = SrsDeclare + constructTemplate = SrsConstructor + elif imm: + if double: + declareTemplate = LoadStoreDImmDeclare + constructTemplate = LoadStoreDImmConstructor + if strex: + declareTemplate = StoreExDImmDeclare + constructTemplate = StoreExDImmConstructor + elif strex: + declareTemplate = StoreExImmDeclare + constructTemplate = StoreExImmConstructor + else: + declareTemplate = LoadStoreImmDeclare + constructTemplate = LoadStoreImmConstructor + else: + if double: + declareTemplate = LoadStoreDRegDeclare + constructTemplate = LoadStoreDRegConstructor + else: + declareTemplate = LoadStoreRegDeclare + constructTemplate = LoadStoreRegConstructor + + # (header_output, decoder_output, decode_block, exec_output) + return (declareTemplate.subst(iop), + constructTemplate.subst(iop), + fullExecTemplate.subst(iop) + + initiateAccTemplate.subst(iop) + + completeAccTemplate.subst(iop)) + + def pickPredicate(blobs): + for val in blobs.values(): + if re.search('(?" % base + elif not post and writeback: + base = "MemoryPreIndex<%s>" % base + elif not post and not writeback: + base = "MemoryOffset<%s>" % base + else: + raise Exception, "Illegal combination of post and writeback" + return base +}}; + diff -r 84bd4089958b src/arch/arm/isa/insts/misc.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/insts/misc.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,694 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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: Gabe Black + +let {{ + + svcCode = ''' +#if FULL_SYSTEM + fault = new SupervisorCall; +#else + fault = new SupervisorCall(machInst); +#endif + ''' + + svcIop = InstObjParams("svc", "Svc", "PredOp", + { "code": svcCode, + "predicate_test": predicateTest }, ["IsSyscall"]) + header_output = BasicDeclare.subst(svcIop) + decoder_output = BasicConstructor.subst(svcIop) + exec_output = PredOpExecute.subst(svcIop) + +}}; + +let {{ + + header_output = decoder_output = exec_output = "" + + mrsCpsrCode = "Dest = (Cpsr | CondCodes) & 0xF8FF03DF" + mrsCpsrIop = InstObjParams("mrs", "MrsCpsr", "MrsOp", + { "code": mrsCpsrCode, + "predicate_test": condPredicateTest }, []) + header_output += MrsDeclare.subst(mrsCpsrIop) + decoder_output += MrsConstructor.subst(mrsCpsrIop) + exec_output += PredOpExecute.subst(mrsCpsrIop) + + mrsSpsrCode = "Dest = Spsr" + mrsSpsrIop = InstObjParams("mrs", "MrsSpsr", "MrsOp", + { "code": mrsSpsrCode, + "predicate_test": predicateTest }, []) + header_output += MrsDeclare.subst(mrsSpsrIop) + decoder_output += MrsConstructor.subst(mrsSpsrIop) + exec_output += PredOpExecute.subst(mrsSpsrIop) + + msrCpsrRegCode = ''' + SCTLR sctlr = Sctlr; + uint32_t newCpsr = + cpsrWriteByInstr(Cpsr | CondCodes, Op1, byteMask, false, sctlr.nmfi); + Cpsr = ~CondCodesMask & newCpsr; + CondCodes = CondCodesMask & newCpsr; + ''' + msrCpsrRegIop = InstObjParams("msr", "MsrCpsrReg", "MsrRegOp", + { "code": msrCpsrRegCode, + "predicate_test": condPredicateTest }, []) + header_output += MsrRegDeclare.subst(msrCpsrRegIop) + decoder_output += MsrRegConstructor.subst(msrCpsrRegIop) + exec_output += PredOpExecute.subst(msrCpsrRegIop) + + msrSpsrRegCode = "Spsr = spsrWriteByInstr(Spsr, Op1, byteMask, false);" + msrSpsrRegIop = InstObjParams("msr", "MsrSpsrReg", "MsrRegOp", + { "code": msrSpsrRegCode, + "predicate_test": predicateTest }, []) + header_output += MsrRegDeclare.subst(msrSpsrRegIop) + decoder_output += MsrRegConstructor.subst(msrSpsrRegIop) + exec_output += PredOpExecute.subst(msrSpsrRegIop) + + msrCpsrImmCode = ''' + SCTLR sctlr = Sctlr; + uint32_t newCpsr = + cpsrWriteByInstr(Cpsr | CondCodes, imm, byteMask, false, sctlr.nmfi); + Cpsr = ~CondCodesMask & newCpsr; + CondCodes = CondCodesMask & newCpsr; + ''' + msrCpsrImmIop = InstObjParams("msr", "MsrCpsrImm", "MsrImmOp", + { "code": msrCpsrImmCode, + "predicate_test": condPredicateTest }, []) + header_output += MsrImmDeclare.subst(msrCpsrImmIop) + decoder_output += MsrImmConstructor.subst(msrCpsrImmIop) + exec_output += PredOpExecute.subst(msrCpsrImmIop) + + msrSpsrImmCode = "Spsr = spsrWriteByInstr(Spsr, imm, byteMask, false);" + msrSpsrImmIop = InstObjParams("msr", "MsrSpsrImm", "MsrImmOp", + { "code": msrSpsrImmCode, + "predicate_test": predicateTest }, []) + header_output += MsrImmDeclare.subst(msrSpsrImmIop) + decoder_output += MsrImmConstructor.subst(msrSpsrImmIop) + exec_output += PredOpExecute.subst(msrSpsrImmIop) + + revCode = ''' + uint32_t val = Op1; + Dest = swap_byte(val); + ''' + revIop = InstObjParams("rev", "Rev", "RegRegOp", + { "code": revCode, + "predicate_test": predicateTest }, []) + header_output += RegRegOpDeclare.subst(revIop) + decoder_output += RegRegOpConstructor.subst(revIop) + exec_output += PredOpExecute.subst(revIop) + + rev16Code = ''' + uint32_t val = Op1; + Dest = (bits(val, 15, 8) << 0) | + (bits(val, 7, 0) << 8) | + (bits(val, 31, 24) << 16) | + (bits(val, 23, 16) << 24); + ''' + rev16Iop = InstObjParams("rev16", "Rev16", "RegRegOp", + { "code": rev16Code, + "predicate_test": predicateTest }, []) + header_output += RegRegOpDeclare.subst(rev16Iop) + decoder_output += RegRegOpConstructor.subst(rev16Iop) + exec_output += PredOpExecute.subst(rev16Iop) + + revshCode = ''' + uint16_t val = Op1; + Dest = sext<16>(swap_byte(val)); + ''' + revshIop = InstObjParams("revsh", "Revsh", "RegRegOp", + { "code": revshCode, + "predicate_test": predicateTest }, []) + header_output += RegRegOpDeclare.subst(revshIop) + decoder_output += RegRegOpConstructor.subst(revshIop) + exec_output += PredOpExecute.subst(revshIop) + + rbitCode = ''' + uint8_t *opBytes = (uint8_t *)&Op1; + uint32_t resTemp; + uint8_t *destBytes = (uint8_t *)&resTemp; + // This reverses the bytes and bits of the input, or so says the + // internet. + for (int i = 0; i < 4; i++) { + uint32_t temp = opBytes[i]; + temp = (temp * 0x0802 & 0x22110) | (temp * 0x8020 & 0x88440); + destBytes[3 - i] = (temp * 0x10101) >> 16; + } + Dest = resTemp; + ''' + rbitIop = InstObjParams("rbit", "Rbit", "RegRegOp", + { "code": rbitCode, + "predicate_test": predicateTest }, []) + header_output += RegRegOpDeclare.subst(rbitIop) + decoder_output += RegRegOpConstructor.subst(rbitIop) + exec_output += PredOpExecute.subst(rbitIop) + + clzCode = ''' + Dest = (Op1 == 0) ? 32 : (31 - findMsbSet(Op1)); + ''' + clzIop = InstObjParams("clz", "Clz", "RegRegOp", + { "code": clzCode, + "predicate_test": predicateTest }, []) + header_output += RegRegOpDeclare.subst(clzIop) + decoder_output += RegRegOpConstructor.subst(clzIop) + exec_output += PredOpExecute.subst(clzIop) + + ssatCode = ''' + int32_t operand = shift_rm_imm(Op1, shiftAmt, shiftType, 0); + int32_t res; + if (satInt(res, operand, imm)) + CondCodes = CondCodes | (1 << 27); + else + CondCodes = CondCodes; + Dest = res; + ''' + ssatIop = InstObjParams("ssat", "Ssat", "RegImmRegShiftOp", + { "code": ssatCode, + "predicate_test": condPredicateTest }, []) + header_output += RegImmRegShiftOpDeclare.subst(ssatIop) + decoder_output += RegImmRegShiftOpConstructor.subst(ssatIop) + exec_output += PredOpExecute.subst(ssatIop) + + usatCode = ''' + int32_t operand = shift_rm_imm(Op1, shiftAmt, shiftType, 0); + int32_t res; + if (uSatInt(res, operand, imm)) + CondCodes = CondCodes | (1 << 27); + else + CondCodes = CondCodes; + Dest = res; + ''' + usatIop = InstObjParams("usat", "Usat", "RegImmRegShiftOp", + { "code": usatCode, + "predicate_test": condPredicateTest }, []) + header_output += RegImmRegShiftOpDeclare.subst(usatIop) + decoder_output += RegImmRegShiftOpConstructor.subst(usatIop) + exec_output += PredOpExecute.subst(usatIop) + + ssat16Code = ''' + int32_t res; + uint32_t resTemp = 0; + CondCodes = CondCodes; + int32_t argLow = sext<16>(bits(Op1, 15, 0)); + int32_t argHigh = sext<16>(bits(Op1, 31, 16)); + if (satInt(res, argLow, imm)) + CondCodes = CondCodes | (1 << 27); + replaceBits(resTemp, 15, 0, res); + if (satInt(res, argHigh, imm)) + CondCodes = CondCodes | (1 << 27); + replaceBits(resTemp, 31, 16, res); + Dest = resTemp; + ''' + ssat16Iop = InstObjParams("ssat16", "Ssat16", "RegImmRegOp", + { "code": ssat16Code, + "predicate_test": condPredicateTest }, []) + header_output += RegImmRegOpDeclare.subst(ssat16Iop) + decoder_output += RegImmRegOpConstructor.subst(ssat16Iop) + exec_output += PredOpExecute.subst(ssat16Iop) + + usat16Code = ''' + int32_t res; + uint32_t resTemp = 0; + CondCodes = CondCodes; + int32_t argLow = sext<16>(bits(Op1, 15, 0)); + int32_t argHigh = sext<16>(bits(Op1, 31, 16)); + if (uSatInt(res, argLow, imm)) + CondCodes = CondCodes | (1 << 27); + replaceBits(resTemp, 15, 0, res); + if (uSatInt(res, argHigh, imm)) + CondCodes = CondCodes | (1 << 27); + replaceBits(resTemp, 31, 16, res); + Dest = resTemp; + ''' + usat16Iop = InstObjParams("usat16", "Usat16", "RegImmRegOp", + { "code": usat16Code, + "predicate_test": condPredicateTest }, []) + header_output += RegImmRegOpDeclare.subst(usat16Iop) + decoder_output += RegImmRegOpConstructor.subst(usat16Iop) + exec_output += PredOpExecute.subst(usat16Iop) + + sxtbIop = InstObjParams("sxtb", "Sxtb", "RegImmRegOp", + { "code": + "Dest = sext<8>((uint8_t)(Op1.ud >> imm));", + "predicate_test": predicateTest }, []) + header_output += RegImmRegOpDeclare.subst(sxtbIop) + decoder_output += RegImmRegOpConstructor.subst(sxtbIop) + exec_output += PredOpExecute.subst(sxtbIop) + + sxtabIop = InstObjParams("sxtab", "Sxtab", "RegRegRegImmOp", + { "code": + ''' + Dest = sext<8>((uint8_t)(Op2.ud >> imm)) + + Op1; + ''', + "predicate_test": predicateTest }, []) + header_output += RegRegRegImmOpDeclare.subst(sxtabIop) + decoder_output += RegRegRegImmOpConstructor.subst(sxtabIop) + exec_output += PredOpExecute.subst(sxtabIop) + + sxtb16Code = ''' + uint32_t resTemp = 0; + replaceBits(resTemp, 15, 0, sext<8>(bits(Op1, imm + 7, imm))); + replaceBits(resTemp, 31, 16, + sext<8>(bits(Op1, (imm + 23) % 32, (imm + 16) % 32))); + Dest = resTemp; + ''' + sxtb16Iop = InstObjParams("sxtb16", "Sxtb16", "RegImmRegOp", + { "code": sxtb16Code, + "predicate_test": predicateTest }, []) + header_output += RegImmRegOpDeclare.subst(sxtb16Iop) + decoder_output += RegImmRegOpConstructor.subst(sxtb16Iop) + exec_output += PredOpExecute.subst(sxtb16Iop) + + sxtab16Code = ''' + uint32_t resTemp = 0; + replaceBits(resTemp, 15, 0, sext<8>(bits(Op2, imm + 7, imm)) + + bits(Op1, 15, 0)); + replaceBits(resTemp, 31, 16, + sext<8>(bits(Op2, (imm + 23) % 32, (imm + 16) % 32)) + + bits(Op1, 31, 16)); + Dest = resTemp; + ''' + sxtab16Iop = InstObjParams("sxtab16", "Sxtab16", "RegRegRegImmOp", + { "code": sxtab16Code, + "predicate_test": predicateTest }, []) + header_output += RegRegRegImmOpDeclare.subst(sxtab16Iop) + decoder_output += RegRegRegImmOpConstructor.subst(sxtab16Iop) + exec_output += PredOpExecute.subst(sxtab16Iop) + + sxthCode = ''' + uint64_t rotated = (uint32_t)Op1; + rotated = (rotated | (rotated << 32)) >> imm; + Dest = sext<16>((uint16_t)rotated); + ''' + sxthIop = InstObjParams("sxth", "Sxth", "RegImmRegOp", + { "code": sxthCode, + "predicate_test": predicateTest }, []) + header_output += RegImmRegOpDeclare.subst(sxthIop) + decoder_output += RegImmRegOpConstructor.subst(sxthIop) + exec_output += PredOpExecute.subst(sxthIop) + + sxtahCode = ''' + uint64_t rotated = (uint32_t)Op2; + rotated = (rotated | (rotated << 32)) >> imm; + Dest = sext<16>((uint16_t)rotated) + Op1; + ''' + sxtahIop = InstObjParams("sxtah", "Sxtah", "RegRegRegImmOp", + { "code": sxtahCode, + "predicate_test": predicateTest }, []) + header_output += RegRegRegImmOpDeclare.subst(sxtahIop) + decoder_output += RegRegRegImmOpConstructor.subst(sxtahIop) + exec_output += PredOpExecute.subst(sxtahIop) + + uxtbIop = InstObjParams("uxtb", "Uxtb", "RegImmRegOp", + { "code": "Dest = (uint8_t)(Op1.ud >> imm);", + "predicate_test": predicateTest }, []) + header_output += RegImmRegOpDeclare.subst(uxtbIop) + decoder_output += RegImmRegOpConstructor.subst(uxtbIop) + exec_output += PredOpExecute.subst(uxtbIop) + + uxtabIop = InstObjParams("uxtab", "Uxtab", "RegRegRegImmOp", + { "code": + "Dest = (uint8_t)(Op2.ud >> imm) + Op1;", + "predicate_test": predicateTest }, []) + header_output += RegRegRegImmOpDeclare.subst(uxtabIop) + decoder_output += RegRegRegImmOpConstructor.subst(uxtabIop) + exec_output += PredOpExecute.subst(uxtabIop) + + uxtb16Code = ''' + uint32_t resTemp = 0; + replaceBits(resTemp, 15, 0, (uint8_t)(bits(Op1, imm + 7, imm))); + replaceBits(resTemp, 31, 16, + (uint8_t)(bits(Op1, (imm + 23) % 32, (imm + 16) % 32))); + Dest = resTemp; + ''' + uxtb16Iop = InstObjParams("uxtb16", "Uxtb16", "RegImmRegOp", + { "code": uxtb16Code, + "predicate_test": predicateTest }, []) + header_output += RegImmRegOpDeclare.subst(uxtb16Iop) + decoder_output += RegImmRegOpConstructor.subst(uxtb16Iop) + exec_output += PredOpExecute.subst(uxtb16Iop) + + uxtab16Code = ''' + uint32_t resTemp = 0; + replaceBits(resTemp, 15, 0, (uint8_t)(bits(Op2, imm + 7, imm)) + + bits(Op1, 15, 0)); + replaceBits(resTemp, 31, 16, + (uint8_t)(bits(Op2, (imm + 23) % 32, (imm + 16) % 32)) + + bits(Op1, 31, 16)); + Dest = resTemp; + ''' + uxtab16Iop = InstObjParams("uxtab16", "Uxtab16", "RegRegRegImmOp", + { "code": uxtab16Code, + "predicate_test": predicateTest }, []) + header_output += RegRegRegImmOpDeclare.subst(uxtab16Iop) + decoder_output += RegRegRegImmOpConstructor.subst(uxtab16Iop) + exec_output += PredOpExecute.subst(uxtab16Iop) + + uxthCode = ''' + uint64_t rotated = (uint32_t)Op1; + rotated = (rotated | (rotated << 32)) >> imm; + Dest = (uint16_t)rotated; + ''' + uxthIop = InstObjParams("uxth", "Uxth", "RegImmRegOp", + { "code": uxthCode, + "predicate_test": predicateTest }, []) + header_output += RegImmRegOpDeclare.subst(uxthIop) + decoder_output += RegImmRegOpConstructor.subst(uxthIop) + exec_output += PredOpExecute.subst(uxthIop) + + uxtahCode = ''' + uint64_t rotated = (uint32_t)Op2; + rotated = (rotated | (rotated << 32)) >> imm; + Dest = (uint16_t)rotated + Op1; + ''' + uxtahIop = InstObjParams("uxtah", "Uxtah", "RegRegRegImmOp", + { "code": uxtahCode, + "predicate_test": predicateTest }, []) + header_output += RegRegRegImmOpDeclare.subst(uxtahIop) + decoder_output += RegRegRegImmOpConstructor.subst(uxtahIop) + exec_output += PredOpExecute.subst(uxtahIop) + + selCode = ''' + uint32_t resTemp = 0; + for (unsigned i = 0; i < 4; i++) { + int low = i * 8; + int high = low + 7; + replaceBits(resTemp, high, low, + bits(CondCodes, 16 + i) ? + bits(Op1, high, low) : bits(Op2, high, low)); + } + Dest = resTemp; + ''' + selIop = InstObjParams("sel", "Sel", "RegRegRegOp", + { "code": selCode, + "predicate_test": condPredicateTest }, []) + header_output += RegRegRegOpDeclare.subst(selIop) + decoder_output += RegRegRegOpConstructor.subst(selIop) + exec_output += PredOpExecute.subst(selIop) + + usad8Code = ''' + uint32_t resTemp = 0; + for (unsigned i = 0; i < 4; i++) { + int low = i * 8; + int high = low + 7; + int32_t diff = bits(Op1, high, low) - + bits(Op2, high, low); + resTemp += ((diff < 0) ? -diff : diff); + } + Dest = resTemp; + ''' + usad8Iop = InstObjParams("usad8", "Usad8", "RegRegRegOp", + { "code": usad8Code, + "predicate_test": predicateTest }, []) + header_output += RegRegRegOpDeclare.subst(usad8Iop) + decoder_output += RegRegRegOpConstructor.subst(usad8Iop) + exec_output += PredOpExecute.subst(usad8Iop) + + usada8Code = ''' + uint32_t resTemp = 0; + for (unsigned i = 0; i < 4; i++) { + int low = i * 8; + int high = low + 7; + int32_t diff = bits(Op1, high, low) - + bits(Op2, high, low); + resTemp += ((diff < 0) ? -diff : diff); + } + Dest = Op3 + resTemp; + ''' + usada8Iop = InstObjParams("usada8", "Usada8", "RegRegRegRegOp", + { "code": usada8Code, + "predicate_test": predicateTest }, []) + header_output += RegRegRegRegOpDeclare.subst(usada8Iop) + decoder_output += RegRegRegRegOpConstructor.subst(usada8Iop) + exec_output += PredOpExecute.subst(usada8Iop) + + bkptIop = InstObjParams("bkpt", "BkptInst", "ArmStaticInst", + "return new PrefetchAbort(PC, ArmFault::DebugEvent);") + header_output += BasicDeclare.subst(bkptIop) + decoder_output += BasicConstructor.subst(bkptIop) + exec_output += BasicExecute.subst(bkptIop) + + nopIop = InstObjParams("nop", "NopInst", "PredOp", \ + { "code" : "", "predicate_test" : predicateTest }) + header_output += BasicDeclare.subst(nopIop) + decoder_output += BasicConstructor.subst(nopIop) + exec_output += PredOpExecute.subst(nopIop) + + yieldIop = InstObjParams("yield", "YieldInst", "PredOp", \ + { "code" : "", "predicate_test" : predicateTest }) + header_output += BasicDeclare.subst(yieldIop) + decoder_output += BasicConstructor.subst(yieldIop) + exec_output += PredOpExecute.subst(yieldIop) + + wfeCode = ''' +#if FULL_SYSTEM + if (SevMailbox) + SevMailbox = 0; + else + PseudoInst::quiesce(xc->tcBase()); +#endif + ''' + wfeIop = InstObjParams("wfe", "WfeInst", "PredOp", \ + { "code" : wfeCode, "predicate_test" : predicateTest }, + ["IsNonSpeculative", "IsQuiesce"]) + header_output += BasicDeclare.subst(wfeIop) + decoder_output += BasicConstructor.subst(wfeIop) + exec_output += PredOpExecute.subst(wfeIop) + + wfiCode = ''' +#if FULL_SYSTEM + PseudoInst::quiesce(xc->tcBase()); +#endif + ''' + wfiIop = InstObjParams("wfi", "WfiInst", "PredOp", \ + { "code" : wfiCode, "predicate_test" : predicateTest }, + ["IsNonSpeculative", "IsQuiesce"]) + header_output += BasicDeclare.subst(wfiIop) + decoder_output += BasicConstructor.subst(wfiIop) + exec_output += PredOpExecute.subst(wfiIop) + + sevCode = ''' + // Need a way for O3 to not scoreboard these accesses as pipe flushes. + System *sys = xc->tcBase()->getSystemPtr(); + for (int x = 0; x < sys->numContexts(); x++) { + ThreadContext *oc = sys->getThreadContext(x); + oc->setMiscReg(MISCREG_SEV_MAILBOX, 1); + } + ''' + sevIop = InstObjParams("sev", "SevInst", "PredOp", \ + { "code" : sevCode, "predicate_test" : predicateTest }, + ["IsNonSpeculative", "IsQuiesce"]) + header_output += BasicDeclare.subst(sevIop) + decoder_output += BasicConstructor.subst(sevIop) + exec_output += PredOpExecute.subst(sevIop) + + itIop = InstObjParams("it", "ItInst", "PredOp", \ + { "code" : "Itstate = machInst.newItstate;", + "predicate_test" : predicateTest }) + header_output += BasicDeclare.subst(itIop) + decoder_output += BasicConstructor.subst(itIop) + exec_output += PredOpExecute.subst(itIop) + unknownCode = ''' +#if FULL_SYSTEM + return new UndefinedInstruction; +#else + return new UndefinedInstruction(machInst, true); +#endif + ''' + unknownIop = InstObjParams("unknown", "Unknown", "UnknownOp", \ + { "code": unknownCode, + "predicate_test": predicateTest }) + header_output += BasicDeclare.subst(unknownIop) + decoder_output += BasicConstructor.subst(unknownIop) + exec_output += PredOpExecute.subst(unknownIop) + + ubfxCode = ''' + Dest = bits(Op1, imm2, imm1); + ''' + ubfxIop = InstObjParams("ubfx", "Ubfx", "RegRegImmImmOp", + { "code": ubfxCode, + "predicate_test": predicateTest }, []) + header_output += RegRegImmImmOpDeclare.subst(ubfxIop) + decoder_output += RegRegImmImmOpConstructor.subst(ubfxIop) + exec_output += PredOpExecute.subst(ubfxIop) + + sbfxCode = ''' + int32_t resTemp = bits(Op1, imm2, imm1); + Dest = resTemp | -(resTemp & (1 << (imm2 - imm1))); + ''' + sbfxIop = InstObjParams("sbfx", "Sbfx", "RegRegImmImmOp", + { "code": sbfxCode, + "predicate_test": predicateTest }, []) + header_output += RegRegImmImmOpDeclare.subst(sbfxIop) + decoder_output += RegRegImmImmOpConstructor.subst(sbfxIop) + exec_output += PredOpExecute.subst(sbfxIop) + + bfcCode = ''' + Dest = Op1 & ~(mask(imm2 - imm1 + 1) << imm1); + ''' + bfcIop = InstObjParams("bfc", "Bfc", "RegRegImmImmOp", + { "code": bfcCode, + "predicate_test": predicateTest }, []) + header_output += RegRegImmImmOpDeclare.subst(bfcIop) + decoder_output += RegRegImmImmOpConstructor.subst(bfcIop) + exec_output += PredOpExecute.subst(bfcIop) + + bfiCode = ''' + uint32_t bitMask = (mask(imm2 - imm1 + 1) << imm1); + Dest = ((Op1 << imm1) & bitMask) | (Dest & ~bitMask); + ''' + bfiIop = InstObjParams("bfi", "Bfi", "RegRegImmImmOp", + { "code": bfiCode, + "predicate_test": predicateTest }, []) + header_output += RegRegImmImmOpDeclare.subst(bfiIop) + decoder_output += RegRegImmImmOpConstructor.subst(bfiIop) + exec_output += PredOpExecute.subst(bfiIop) + + mrc15code = ''' + CPSR cpsr = Cpsr; + if (cpsr.mode == MODE_USER) +#if FULL_SYSTEM + return new UndefinedInstruction; +#else + return new UndefinedInstruction(false, mnemonic); +#endif + Dest = MiscOp1; + ''' + + mrc15Iop = InstObjParams("mrc", "Mrc15", "RegRegOp", + { "code": mrc15code, + "predicate_test": predicateTest }, []) + header_output += RegRegOpDeclare.subst(mrc15Iop) + decoder_output += RegRegOpConstructor.subst(mrc15Iop) + exec_output += PredOpExecute.subst(mrc15Iop) + + + mcr15code = ''' + CPSR cpsr = Cpsr; + if (cpsr.mode == MODE_USER) +#if FULL_SYSTEM + return new UndefinedInstruction; +#else + return new UndefinedInstruction(false, mnemonic); +#endif + MiscDest = Op1; + ''' + mcr15Iop = InstObjParams("mcr", "Mcr15", "RegRegOp", + { "code": mcr15code, + "predicate_test": predicateTest }, []) + header_output += RegRegOpDeclare.subst(mcr15Iop) + decoder_output += RegRegOpConstructor.subst(mcr15Iop) + exec_output += PredOpExecute.subst(mcr15Iop) + + mrc15UserIop = InstObjParams("mrc", "Mrc15User", "RegRegOp", + { "code": "Dest = MiscOp1;", + "predicate_test": predicateTest }, []) + header_output += RegRegOpDeclare.subst(mrc15UserIop) + decoder_output += RegRegOpConstructor.subst(mrc15UserIop) + exec_output += PredOpExecute.subst(mrc15UserIop) + + mcr15UserIop = InstObjParams("mcr", "Mcr15User", "RegRegOp", + { "code": "MiscDest = Op1", + "predicate_test": predicateTest }, []) + header_output += RegRegOpDeclare.subst(mcr15UserIop) + decoder_output += RegRegOpConstructor.subst(mcr15UserIop) + exec_output += PredOpExecute.subst(mcr15UserIop) + + enterxCode = ''' + FNPC = NPC | (1ULL << PcJBitShift) | (1ULL << PcTBitShift); + ''' + enterxIop = InstObjParams("enterx", "Enterx", "PredOp", + { "code": enterxCode, + "predicate_test": predicateTest }, []) + header_output += BasicDeclare.subst(enterxIop) + decoder_output += BasicConstructor.subst(enterxIop) + exec_output += PredOpExecute.subst(enterxIop) + + leavexCode = ''' + FNPC = (NPC & ~(1ULL << PcJBitShift)) | (1ULL << PcTBitShift); + ''' + leavexIop = InstObjParams("leavex", "Leavex", "PredOp", + { "code": leavexCode, + "predicate_test": predicateTest }, []) + header_output += BasicDeclare.subst(leavexIop) + decoder_output += BasicConstructor.subst(leavexIop) + exec_output += PredOpExecute.subst(leavexIop) + + setendCode = ''' + CPSR cpsr = Cpsr; + cpsr.e = imm; + Cpsr = cpsr; + ''' + setendIop = InstObjParams("setend", "Setend", "ImmOp", + { "code": setendCode, + "predicate_test": predicateTest }, []) + header_output += ImmOpDeclare.subst(setendIop) + decoder_output += ImmOpConstructor.subst(setendIop) + exec_output += PredOpExecute.subst(setendIop) + + cpsCode = ''' + uint32_t mode = bits(imm, 4, 0); + uint32_t f = bits(imm, 5); + uint32_t i = bits(imm, 6); + uint32_t a = bits(imm, 7); + bool setMode = bits(imm, 8); + bool enable = bits(imm, 9); + CPSR cpsr = Cpsr; + SCTLR sctlr = Sctlr; + if (cpsr.mode != MODE_USER) { + if (enable) { + if (f) cpsr.f = 0; + if (i) cpsr.i = 0; + if (a) cpsr.a = 0; + } else { + if (f && !sctlr.nmfi) cpsr.f = 1; + if (i) cpsr.i = 1; + if (a) cpsr.a = 1; + } + if (setMode) { + cpsr.mode = mode; + } + } + Cpsr = cpsr; + ''' + cpsIop = InstObjParams("cps", "Cps", "ImmOp", + { "code": cpsCode, + "predicate_test": predicateTest }, []) + header_output += ImmOpDeclare.subst(cpsIop) + decoder_output += ImmOpConstructor.subst(cpsIop) + exec_output += PredOpExecute.subst(cpsIop) +}}; diff -r 84bd4089958b src/arch/arm/isa/insts/mult.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/insts/mult.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,387 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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: Gabe Black + +let {{ + + header_output = "" + decoder_output = "" + exec_output = "" + + calcQCode = ''' + CondCodes = CondCodes | ((resTemp & 1) << 27); + ''' + + calcCcCode = ''' + uint16_t _iz, _in; + _in = (resTemp >> %(negBit)d) & 1; + _iz = ((%(zType)s)resTemp == 0); + + CondCodes = _in << 31 | _iz << 30 | (CondCodes & 0x3FFFFFFF); + + DPRINTF(Arm, "(in, iz) = (%%d, %%d)\\n", _in, _iz); + ''' + + def buildMultInst(mnem, doCc, unCc, regs, code, flagType): + global header_output, decoder_output, exec_output + cCode = carryCode[flagType] + vCode = overflowCode[flagType] + zType = "uint32_t" + negBit = 31 + if flagType == "llbit": + zType = "uint64_t" + negBit = 63 + if flagType == "overflow": + ccCode = calcQCode + else: + ccCode = calcCcCode % { + "negBit": negBit, + "zType": zType + } + + if not regs in (3, 4): + raise Exception, "Multiplication instructions with %d " + \ + "registers are not implemented" + + if regs == 3: + base = 'Mult3' + else: + base = 'Mult4' + + Name = mnem.capitalize() + + if unCc: + iop = InstObjParams(mnem, Name, base, + {"code" : code, + "predicate_test": predicateTest}) + if doCc: + iopCc = InstObjParams(mnem + "s", Name + "Cc", base, + {"code" : code + ccCode, + "predicate_test": condPredicateTest}) + + if regs == 3: + declare = Mult3Declare + constructor = Mult3Constructor + else: + declare = Mult4Declare + constructor = Mult4Constructor + + if unCc: + header_output += declare.subst(iop) + decoder_output += constructor.subst(iop) + exec_output += PredOpExecute.subst(iop) + if doCc: + header_output += declare.subst(iopCc) + decoder_output += constructor.subst(iopCc) + exec_output += PredOpExecute.subst(iopCc) + + def buildMult3Inst(mnem, code, flagType = "logic"): + buildMultInst(mnem, True, True, 3, code, flagType) + + def buildMult3InstCc(mnem, code, flagType = "logic"): + buildMultInst(mnem, True, False, 3, code, flagType) + + def buildMult3InstUnCc(mnem, code, flagType = "logic"): + buildMultInst(mnem, False, True, 3, code, flagType) + + def buildMult4Inst(mnem, code, flagType = "logic"): + buildMultInst(mnem, True, True, 4, code, flagType) + + def buildMult4InstCc(mnem, code, flagType = "logic"): + buildMultInst(mnem, True, False, 4, code, flagType) + + def buildMult4InstUnCc(mnem, code, flagType = "logic"): + buildMultInst(mnem, False, True, 4, code, flagType) + + buildMult4Inst ("mla", "Reg0 = resTemp = Reg1 * Reg2 + Reg3;") + buildMult4InstUnCc("mls", "Reg0 = resTemp = Reg3 - Reg1 * Reg2;") + buildMult3Inst ("mul", "Reg0 = resTemp = Reg1 * Reg2;") + buildMult4InstCc ("smlabb", '''Reg0 = resTemp = + sext<16>(bits(Reg1, 15, 0)) * + sext<16>(bits(Reg2.sw, 15, 0)) + + Reg3.sw; + resTemp = bits(resTemp, 32) != + bits(resTemp, 31); + ''', "overflow") + buildMult4InstCc ("smlabt", '''Reg0 = resTemp = + sext<16>(bits(Reg1, 15, 0)) * + sext<16>(bits(Reg2.sw, 31, 16)) + + Reg3.sw; + resTemp = bits(resTemp, 32) != + bits(resTemp, 31); + ''', "overflow") + buildMult4InstCc ("smlatb", '''Reg0 = resTemp = + sext<16>(bits(Reg1, 31, 16)) * + sext<16>(bits(Reg2.sw, 15, 0)) + + Reg3.sw; + resTemp = bits(resTemp, 32) != + bits(resTemp, 31); + ''', "overflow") + buildMult4InstCc ("smlatt", '''Reg0 = resTemp = + sext<16>(bits(Reg1, 31, 16)) * + sext<16>(bits(Reg2.sw, 31, 16)) + + Reg3.sw; + resTemp = bits(resTemp, 32) != + bits(resTemp, 31); + ''', "overflow") + buildMult4InstCc ("smlad", '''Reg0 = resTemp = + sext<16>(bits(Reg1, 31, 16)) * + sext<16>(bits(Reg2, 31, 16)) + + sext<16>(bits(Reg1, 15, 0)) * + sext<16>(bits(Reg2, 15, 0)) + + Reg3.sw; + resTemp = bits(resTemp, 32) != + bits(resTemp, 31); + ''', "overflow") + buildMult4InstCc ("smladx", '''Reg0 = resTemp = + sext<16>(bits(Reg1, 31, 16)) * + sext<16>(bits(Reg2, 15, 0)) + + sext<16>(bits(Reg1, 15, 0)) * + sext<16>(bits(Reg2, 31, 16)) + + Reg3.sw; + resTemp = bits(resTemp, 32) != + bits(resTemp, 31); + ''', "overflow") + buildMult4Inst ("smlal", '''resTemp = sext<32>(Reg2) * sext<32>(Reg3) + + (int64_t)((Reg1.ud << 32) | Reg0.ud); + Reg0.ud = (uint32_t)resTemp; + Reg1.ud = (uint32_t)(resTemp >> 32); + ''', "llbit") + buildMult4InstUnCc("smlalbb", '''resTemp = sext<16>(bits(Reg2, 15, 0)) * + sext<16>(bits(Reg3, 15, 0)) + + (int64_t)((Reg1.ud << 32) | + Reg0.ud); + Reg0.ud = (uint32_t)resTemp; + Reg1.ud = (uint32_t)(resTemp >> 32); + ''') + buildMult4InstUnCc("smlalbt", '''resTemp = sext<16>(bits(Reg2, 15, 0)) * + sext<16>(bits(Reg3, 31, 16)) + + (int64_t)((Reg1.ud << 32) | + Reg0.ud); + Reg0.ud = (uint32_t)resTemp; + Reg1.ud = (uint32_t)(resTemp >> 32); + ''') + buildMult4InstUnCc("smlaltb", '''resTemp = sext<16>(bits(Reg2, 31, 16)) * + sext<16>(bits(Reg3, 15, 0)) + + (int64_t)((Reg1.ud << 32) | + Reg0.ud); + Reg0.ud = (uint32_t)resTemp; + Reg1.ud = (uint32_t)(resTemp >> 32); + ''') + buildMult4InstUnCc("smlaltt", '''resTemp = sext<16>(bits(Reg2, 31, 16)) * + sext<16>(bits(Reg3, 31, 16)) + + (int64_t)((Reg1.ud << 32) | + Reg0.ud); + Reg0.ud = (uint32_t)resTemp; + Reg1.ud = (uint32_t)(resTemp >> 32); + ''') + buildMult4InstUnCc("smlald", '''resTemp = + sext<16>(bits(Reg2, 31, 16)) * + sext<16>(bits(Reg3, 31, 16)) + + sext<16>(bits(Reg2, 15, 0)) * + sext<16>(bits(Reg3, 15, 0)) + + (int64_t)((Reg1.ud << 32) | + Reg0.ud); + Reg0.ud = (uint32_t)resTemp; + Reg1.ud = (uint32_t)(resTemp >> 32); + ''') + buildMult4InstUnCc("smlaldx", '''resTemp = + sext<16>(bits(Reg2, 31, 16)) * + sext<16>(bits(Reg3, 15, 0)) + + sext<16>(bits(Reg2, 15, 0)) * + sext<16>(bits(Reg3, 31, 16)) + + (int64_t)((Reg1.ud << 32) | + Reg0.ud); + Reg0.ud = (uint32_t)resTemp; + Reg1.ud = (uint32_t)(resTemp >> 32); + ''') + buildMult4InstCc ("smlawb", '''Reg0 = resTemp = + (Reg1.sw * + sext<16>(bits(Reg2, 15, 0)) + + ((int64_t)Reg3.sw << 16)) >> 16; + resTemp = bits(resTemp, 32) != + bits(resTemp, 31); + ''', "overflow") + buildMult4InstCc ("smlawt", '''Reg0 = resTemp = + (Reg1.sw * + sext<16>(bits(Reg2, 31, 16)) + + ((int64_t)Reg3.sw << 16)) >> 16; + resTemp = bits(resTemp, 32) != + bits(resTemp, 31); + ''', "overflow") + buildMult4InstCc ("smlsd", '''Reg0 = resTemp = + sext<16>(bits(Reg1, 15, 0)) * + sext<16>(bits(Reg2, 15, 0)) - + sext<16>(bits(Reg1, 31, 16)) * + sext<16>(bits(Reg2, 31, 16)) + + Reg3.sw; + resTemp = bits(resTemp, 32) != + bits(resTemp, 31); + ''', "overflow") + buildMult4InstCc ("smlsdx", '''Reg0 = resTemp = + sext<16>(bits(Reg1, 15, 0)) * + sext<16>(bits(Reg2, 31, 16)) - + sext<16>(bits(Reg1, 31, 16)) * + sext<16>(bits(Reg2, 15, 0)) + + Reg3.sw; + resTemp = bits(resTemp, 32) != + bits(resTemp, 31); + ''', "overflow") + buildMult4InstUnCc("smlsld", '''resTemp = + sext<16>(bits(Reg2, 15, 0)) * + sext<16>(bits(Reg3, 15, 0)) - + sext<16>(bits(Reg2, 31, 16)) * + sext<16>(bits(Reg3, 31, 16)) + + (int64_t)((Reg1.ud << 32) | + Reg0.ud); + Reg0.ud = (uint32_t)resTemp; + Reg1.ud = (uint32_t)(resTemp >> 32); + ''') + buildMult4InstUnCc("smlsldx", '''resTemp = + sext<16>(bits(Reg2, 15, 0)) * + sext<16>(bits(Reg3, 31, 16)) - + sext<16>(bits(Reg2, 31, 16)) * + sext<16>(bits(Reg3, 15, 0)) + + (int64_t)((Reg1.ud << 32) | + Reg0.ud); + Reg0.ud = (uint32_t)resTemp; + Reg1.ud = (uint32_t)(resTemp >> 32); + ''') + buildMult4InstUnCc("smmla", '''Reg0 = resTemp = + ((int64_t)(Reg3.ud << 32) + + (int64_t)Reg1.sw * + (int64_t)Reg2.sw) >> 32; + ''') + buildMult4InstUnCc("smmlar", '''Reg0 = resTemp = + ((int64_t)(Reg3.ud << 32) + + (int64_t)Reg1.sw * + (int64_t)Reg2.sw + + ULL(0x80000000)) >> 32; + ''') + buildMult4InstUnCc("smmls", '''Reg0 = resTemp = + ((int64_t)(Reg3.ud << 32) - + (int64_t)Reg1.sw * + (int64_t)Reg2.sw) >> 32; + ''') + buildMult4InstUnCc("smmlsr", '''Reg0 = resTemp = + ((int64_t)(Reg3.ud << 32) - + (int64_t)Reg1.sw * + (int64_t)Reg2.sw + + ULL(0x80000000)) >> 32; + ''') + buildMult3InstUnCc("smmul", '''Reg0 = resTemp = + ((int64_t)Reg1.sw * + (int64_t)Reg2.sw) >> 32; + ''') + buildMult3InstUnCc("smmulr", '''Reg0 = resTemp = + ((int64_t)Reg1.sw * + (int64_t)Reg2.sw + + ULL(0x80000000)) >> 32; + ''') + buildMult3InstCc ("smuad", '''Reg0 = resTemp = + sext<16>(bits(Reg1, 15, 0)) * + sext<16>(bits(Reg2, 15, 0)) + + sext<16>(bits(Reg1, 31, 16)) * + sext<16>(bits(Reg2, 31, 16)); + resTemp = bits(resTemp, 32) != + bits(resTemp, 31); + ''', "overflow") + buildMult3InstCc ("smuadx", '''Reg0 = resTemp = + sext<16>(bits(Reg1, 15, 0)) * + sext<16>(bits(Reg2, 31, 16)) + + sext<16>(bits(Reg1, 31, 16)) * + sext<16>(bits(Reg2, 15, 0)); + resTemp = bits(resTemp, 32) != + bits(resTemp, 31); + ''', "overflow") + buildMult3InstUnCc("smulbb", '''Reg0 = resTemp = + sext<16>(bits(Reg1, 15, 0)) * + sext<16>(bits(Reg2, 15, 0)); + ''') + buildMult3InstUnCc("smulbt", '''Reg0 = resTemp = + sext<16>(bits(Reg1, 15, 0)) * + sext<16>(bits(Reg2, 31, 16)); + ''') + buildMult3InstUnCc("smultb", '''Reg0 = resTemp = + sext<16>(bits(Reg1, 31, 16)) * + sext<16>(bits(Reg2, 15, 0)); + ''') + buildMult3InstUnCc("smultt", '''Reg0 = resTemp = + sext<16>(bits(Reg1, 31, 16)) * + sext<16>(bits(Reg2, 31, 16)); + ''') + buildMult4Inst ("smull", '''resTemp = (int64_t)Reg2.sw * + (int64_t)Reg3.sw; + Reg0 = (int32_t)resTemp; + Reg1 = (int32_t)(resTemp >> 32); + ''', "llbit") + buildMult3InstUnCc("smulwb", '''Reg0 = resTemp = + (Reg1.sw * + sext<16>(bits(Reg2, 15, 0))) >> 16; + ''') + buildMult3InstUnCc("smulwt", '''Reg0 = resTemp = + (Reg1.sw * + sext<16>(bits(Reg2, 31, 16))) >> 16; + ''') + buildMult3InstUnCc("smusd", '''Reg0 = resTemp = + sext<16>(bits(Reg1, 15, 0)) * + sext<16>(bits(Reg2, 15, 0)) - + sext<16>(bits(Reg1, 31, 16)) * + sext<16>(bits(Reg2, 31, 16)); + ''') + buildMult3InstUnCc("smusdx", '''Reg0 = resTemp = + sext<16>(bits(Reg1, 15, 0)) * + sext<16>(bits(Reg2, 31, 16)) - + sext<16>(bits(Reg1, 31, 16)) * + sext<16>(bits(Reg2, 15, 0)); + ''') + buildMult4InstUnCc("umaal", '''resTemp = Reg2.ud * Reg3.ud + + Reg0.ud + Reg1.ud; + Reg0.ud = (uint32_t)resTemp; + Reg1.ud = (uint32_t)(resTemp >> 32); + ''') + buildMult4Inst ("umlal", '''resTemp = Reg2.ud * Reg3.ud + Reg0.ud + + (Reg1.ud << 32); + Reg0.ud = (uint32_t)resTemp; + Reg1.ud = (uint32_t)(resTemp >> 32); + ''', "llbit") + buildMult4Inst ("umull", '''resTemp = Reg2.ud * Reg3.ud; + Reg0 = (uint32_t)resTemp; + Reg1 = (uint32_t)(resTemp >> 32); + ''', "llbit") +}}; diff -r 84bd4089958b src/arch/arm/isa/insts/str.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/insts/str.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,334 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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: Gabe Black + +let {{ + + header_output = "" + decoder_output = "" + exec_output = "" + + def storeImmClassName(post, add, writeback, \ + size=4, sign=False, user=False): + return memClassName("STORE_IMM", post, add, writeback, + size, sign, user) + + def storeRegClassName(post, add, writeback, \ + size=4, sign=False, user=False): + return memClassName("STORE_REG", post, add, writeback, + size, sign, user) + + def storeDoubleImmClassName(post, add, writeback): + return memClassName("STORE_IMMD", post, add, writeback, + 4, False, False) + + def storeDoubleRegClassName(post, add, writeback): + return memClassName("STORE_REGD", post, add, writeback, + 4, False, False) + + def emitStore(name, Name, imm, eaCode, accCode, postAccCode, \ + memFlags, instFlags, base, double=False, strex=False, + execTemplateBase = 'Store'): + global header_output, decoder_output, exec_output + + (newHeader, + newDecoder, + newExec) = loadStoreBase(name, Name, imm, + eaCode, accCode, postAccCode, + memFlags, instFlags, double, strex, + base, execTemplateBase = execTemplateBase) + + header_output += newHeader + decoder_output += newDecoder + exec_output += newExec + + def buildImmStore(mnem, post, add, writeback, \ + size=4, sign=False, user=False, \ + strex=False, vstr=False): + name = mnem + Name = storeImmClassName(post, add, writeback, \ + size, sign, user) + + if add: + op = " +" + else: + op = " -" + + offset = op + " imm" + eaCode = "EA = Base" + if not post: + eaCode += offset + eaCode += ";" + + if vstr: + accCode = ''' + Mem%(suffix)s = cSwap(FpDest.uw, ((CPSR)Cpsr).e); + ''' % { "suffix" : buildMemSuffix(sign, size) } + else: + accCode = ''' + Mem%(suffix)s = cSwap(Dest%(suffix)s, ((CPSR)Cpsr).e); + ''' % { "suffix" : buildMemSuffix(sign, size) } + if writeback: + accCode += "Base = Base %s;\n" % offset + + memFlags = ["ArmISA::TLB::MustBeOne", "%d" % (size - 1)] + if user: + memFlags.append("ArmISA::TLB::UserMode") + + if strex: + memFlags.append("Request::LLSC") + Name = "%s_%s" % (mnem.upper(), Name) + base = buildMemBase("MemoryExImm", post, writeback) + postAccCode = "Result = !writeResult;" + execTemplateBase = 'StoreEx' + else: + if vstr: + Name = "%s_%s" % (mnem.upper(), Name) + else: + memFlags.append("ArmISA::TLB::AllowUnaligned") + base = buildMemBase("MemoryImm", post, writeback) + postAccCode = "" + execTemplateBase = 'Store' + + emitStore(name, Name, True, eaCode, accCode, postAccCode, \ + memFlags, [], base, strex=strex, + execTemplateBase = execTemplateBase) + + def buildSrsStore(mnem, post, add, writeback): + name = mnem + Name = "SRS_" + storeImmClassName(post, add, writeback, 8) + + offset = 0 + if post != add: + offset += 4 + if not add: + offset -= 8 + + eaCode = "EA = SpMode + %d;" % offset + + wbDiff = -8 + if add: + wbDiff = 8 + accCode = ''' + CPSR cpsr = Cpsr; + Mem.ud = (uint64_t)cSwap(LR.uw, cpsr.e) | + ((uint64_t)cSwap(Spsr.uw, cpsr.e) << 32); + ''' + if writeback: + accCode += "SpMode = SpMode + %s;\n" % wbDiff + + global header_output, decoder_output, exec_output + + (newHeader, + newDecoder, + newExec) = SrsBase(name, Name, eaCode, accCode, + ["ArmISA::TLB::AlignWord", "ArmISA::TLB::MustBeOne"], []) + + header_output += newHeader + decoder_output += newDecoder + exec_output += newExec + + def buildRegStore(mnem, post, add, writeback, \ + size=4, sign=False, user=False, strex=False): + name = mnem + Name = storeRegClassName(post, add, writeback, + size, sign, user) + + if add: + op = " +" + else: + op = " -" + + offset = op + " shift_rm_imm(Index, shiftAmt," + \ + " shiftType, CondCodes<29:>)" + eaCode = "EA = Base" + if not post: + eaCode += offset + eaCode += ";" + + accCode = "Mem%(suffix)s = cSwap(Dest%(suffix)s, ((CPSR)Cpsr).e);" % \ + { "suffix" : buildMemSuffix(sign, size) } + if writeback: + accCode += "Base = Base %s;\n" % offset + base = buildMemBase("MemoryReg", post, writeback) + + memFlags = ["ArmISA::TLB::MustBeOne", \ + "ArmISA::TLB::AllowUnaligned", \ + "%d" % (size - 1)] + if user: + memFlags.append("ArmISA::TLB::UserMode") + + emitStore(name, Name, False, eaCode, accCode, "",\ + memFlags, [], base) + + def buildDoubleImmStore(mnem, post, add, writeback, \ + strex=False, vstr=False): + name = mnem + Name = storeDoubleImmClassName(post, add, writeback) + + if add: + op = " +" + else: + op = " -" + + offset = op + " imm" + eaCode = "EA = Base" + if not post: + eaCode += offset + eaCode += ";" + + if vstr: + accCode = ''' + uint64_t swappedMem = (uint64_t)FpDest.uw | + ((uint64_t)FpDest2.uw << 32); + Mem.ud = cSwap(swappedMem, ((CPSR)Cpsr).e); + ''' + else: + accCode = ''' + CPSR cpsr = Cpsr; + Mem.ud = (uint64_t)cSwap(Dest.uw, cpsr.e) | + ((uint64_t)cSwap(Dest2.uw, cpsr.e) << 32); + ''' + if writeback: + accCode += "Base = Base %s;\n" % offset + + memFlags = ["ArmISA::TLB::MustBeOne", + "ArmISA::TLB::AlignWord"] + if strex: + memFlags.append("Request::LLSC") + base = buildMemBase("MemoryExDImm", post, writeback) + postAccCode = "Result = !writeResult;" + else: + base = buildMemBase("MemoryDImm", post, writeback) + postAccCode = "" + if vstr or strex: + Name = "%s_%s" % (mnem.upper(), Name) + + emitStore(name, Name, True, eaCode, accCode, postAccCode, \ + memFlags, [], base, double=True, strex=strex) + + def buildDoubleRegStore(mnem, post, add, writeback): + name = mnem + Name = storeDoubleRegClassName(post, add, writeback) + + if add: + op = " +" + else: + op = " -" + + offset = op + " shift_rm_imm(Index, shiftAmt," + \ + " shiftType, CondCodes<29:>)" + eaCode = "EA = Base" + if not post: + eaCode += offset + eaCode += ";" + + accCode = ''' + CPSR cpsr = Cpsr; + Mem.ud = (uint64_t)cSwap(Dest.uw, cpsr.e) | + ((uint64_t)cSwap(Dest2.uw, cpsr.e) << 32); + ''' + if writeback: + accCode += "Base = Base %s;\n" % offset + base = buildMemBase("MemoryDReg", post, writeback) + + memFlags = ["ArmISA::TLB::MustBeOne", + "ArmISA::TLB::AlignWord"] + + emitStore(name, Name, False, eaCode, accCode, "", \ + memFlags, [], base, double=True) + + def buildStores(mnem, size=4, sign=False, user=False): + buildImmStore(mnem, True, True, True, size, sign, user) + buildRegStore(mnem, True, True, True, size, sign, user) + buildImmStore(mnem, True, False, True, size, sign, user) + buildRegStore(mnem, True, False, True, size, sign, user) + buildImmStore(mnem, False, True, True, size, sign, user) + buildRegStore(mnem, False, True, True, size, sign, user) + buildImmStore(mnem, False, False, True, size, sign, user) + buildRegStore(mnem, False, False, True, size, sign, user) + buildImmStore(mnem, False, True, False, size, sign, user) + buildRegStore(mnem, False, True, False, size, sign, user) + buildImmStore(mnem, False, False, False, size, sign, user) + buildRegStore(mnem, False, False, False, size, sign, user) + + def buildDoubleStores(mnem): + buildDoubleImmStore(mnem, True, True, True) + buildDoubleRegStore(mnem, True, True, True) + buildDoubleImmStore(mnem, True, False, True) + buildDoubleRegStore(mnem, True, False, True) + buildDoubleImmStore(mnem, False, True, True) + buildDoubleRegStore(mnem, False, True, True) + buildDoubleImmStore(mnem, False, False, True) + buildDoubleRegStore(mnem, False, False, True) + buildDoubleImmStore(mnem, False, True, False) + buildDoubleRegStore(mnem, False, True, False) + buildDoubleImmStore(mnem, False, False, False) + buildDoubleRegStore(mnem, False, False, False) + + def buildSrsStores(mnem): + buildSrsStore(mnem, True, True, True) + buildSrsStore(mnem, True, True, False) + buildSrsStore(mnem, True, False, True) + buildSrsStore(mnem, True, False, False) + buildSrsStore(mnem, False, True, True) + buildSrsStore(mnem, False, True, False) + buildSrsStore(mnem, False, False, True) + buildSrsStore(mnem, False, False, False) + + buildStores("str") + buildStores("strt", user=True) + buildStores("strb", size=1) + buildStores("strbt", size=1, user=True) + buildStores("strh", size=2) + buildStores("strht", size=2, user=True) + + buildSrsStores("srs") + + buildDoubleStores("strd") + + buildImmStore("strex", False, True, False, size=4, strex=True) + buildImmStore("strexh", False, True, False, size=2, strex=True) + buildImmStore("strexb", False, True, False, size=1, strex=True) + buildDoubleImmStore("strexd", False, True, False, strex=True) + + buildImmStore("vstr", False, True, False, size=4, vstr=True) + buildImmStore("vstr", False, False, False, size=4, vstr=True) + buildDoubleImmStore("vstr", False, True, False, vstr=True) + buildDoubleImmStore("vstr", False, False, False, vstr=True) +}}; diff -r 84bd4089958b src/arch/arm/isa/insts/swap.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/insts/swap.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,67 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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: Gabe Black + +let {{ + + header_output = decoder_output = exec_output = "" + + (newHeader, + newDecoder, + newExec) = SwapBase("swp", "Swp", "EA = Base;", + "Mem = cSwap(Op1.uw, ((CPSR)Cpsr).e);", + "Dest = cSwap((uint32_t)memData, ((CPSR)Cpsr).e);", + ["Request::MEM_SWAP", + "ArmISA::TLB::AlignWord", + "ArmISA::TLB::MustBeOne"], []) + header_output += newHeader + decoder_output += newDecoder + exec_output += newExec + + (newHeader, + newDecoder, + newExec) = SwapBase("swpb", "Swpb", "EA = Base;", + "Mem.ub = cSwap(Op1.ub, ((CPSR)Cpsr).e);", + "Dest.ub = cSwap((uint8_t)memData, ((CPSR)Cpsr).e);", + ["Request::MEM_SWAP", + "ArmISA::TLB::AlignByte", + "ArmISA::TLB::MustBeOne"], []) + header_output += newHeader + decoder_output += newDecoder + exec_output += newExec +}}; diff -r 84bd4089958b src/arch/arm/isa/main.isa --- a/src/arch/arm/isa/main.isa Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/isa/main.isa Wed May 26 18:10:45 2010 -0500 @@ -1,5 +1,17 @@ // -*- mode:c++ -*- +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// // Copyright (c) 2007-2008 The Florida State University // All rights reserved. // @@ -50,8 +62,14 @@ //Include the operand_types and operand definitions ##include "operands.isa" +//Templates for the C++ versions of the instructions +##include "templates/templates.isa" + +//Include manually defined instructions +##include "insts/insts.isa" + //Include the definitions for the instruction formats ##include "formats/formats.isa" //Include the decoder definition -##include "decoder.isa" +##include "decoder/decoder.isa" diff -r 84bd4089958b src/arch/arm/isa/operands.isa --- a/src/arch/arm/isa/operands.isa Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/isa/operands.isa Wed May 26 18:10:45 2010 -0500 @@ -1,5 +1,16 @@ // -*- mode:c++ -*- - +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// // Copyright (c) 2007-2008 The Florida State University // All rights reserved. // @@ -42,52 +53,140 @@ let {{ maybePCRead = ''' - ((%(reg_idx)s == PCReg) ? (xc->readPC() + 8) : + ((%(reg_idx)s == PCReg) ? (readPC(xc) & ~PcModeMask) : + xc->%(func)s(this, %(op_idx)s)) + ''' + maybeAlignedPCRead = ''' + ((%(reg_idx)s == PCReg) ? (roundDown(readPC(xc) & ~PcModeMask, 4)) : xc->%(func)s(this, %(op_idx)s)) ''' maybePCWrite = ''' - ((%(reg_idx)s == PCReg) ? xc->setNextPC(%(final_val)s) : + ((%(reg_idx)s == PCReg) ? setNextPC(xc, %(final_val)s) : xc->%(func)s(this, %(op_idx)s, %(final_val)s)) ''' + maybeIWPCWrite = ''' + ((%(reg_idx)s == PCReg) ? setIWNextPC(xc, %(final_val)s) : + xc->%(func)s(this, %(op_idx)s, %(final_val)s)) + ''' + maybeAIWPCWrite = ''' + if (%(reg_idx)s == PCReg) { + bool thumb = THUMB; + if (thumb) { + setNextPC(xc, %(final_val)s); + } else { + setIWNextPC(xc, %(final_val)s); + } + } else { + xc->%(func)s(this, %(op_idx)s, %(final_val)s); + } + ''' + + readNPC = 'xc->readNextPC() & ~PcModeMask' + writeNPC = 'setNextPC(xc, %(final_val)s)' + writeIWNPC = 'setIWNextPC(xc, %(final_val)s)' + forceNPC = 'xc->setNextPC(%(final_val)s)' }}; def operands {{ + #Abstracted integer reg operands + 'Dest': ('IntReg', 'uw', 'dest', 'IsInteger', 2, + maybePCRead, maybePCWrite), + 'FpDest': ('FloatReg', 'sf', '(dest + 0)', 'IsFloating', 2), + 'FpDestP0': ('FloatReg', 'sf', '(dest + 0)', 'IsFloating', 2), + 'FpDestP1': ('FloatReg', 'sf', '(dest + 1)', 'IsFloating', 2), + 'FpDestP2': ('FloatReg', 'sf', '(dest + 2)', 'IsFloating', 2), + 'FpDestP3': ('FloatReg', 'sf', '(dest + 3)', 'IsFloating', 2), + 'Result': ('IntReg', 'uw', 'result', 'IsInteger', 2, + maybePCRead, maybePCWrite), + 'Dest2': ('IntReg', 'uw', 'dest2', 'IsInteger', 2, + maybePCRead, maybePCWrite), + 'FpDest2': ('FloatReg', 'sf', '(dest2 + 0)', 'IsFloating', 2), + 'FpDest2P0': ('FloatReg', 'sf', '(dest2 + 0)', 'IsFloating', 2), + 'FpDest2P1': ('FloatReg', 'sf', '(dest2 + 1)', 'IsFloating', 2), + 'FpDest2P2': ('FloatReg', 'sf', '(dest2 + 2)', 'IsFloating', 2), + 'FpDest2P3': ('FloatReg', 'sf', '(dest2 + 3)', 'IsFloating', 2), + 'IWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 2, + maybePCRead, maybeIWPCWrite), + 'AIWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 2, + maybePCRead, maybeAIWPCWrite), + 'SpMode': ('IntReg', 'uw', + 'intRegInMode((OperatingMode)regMode, INTREG_SP)', + 'IsInteger', 2), + 'MiscDest': ('ControlReg', 'uw', 'dest', (None, None, 'IsControl'), 2), + 'Base': ('IntReg', 'uw', 'base', 'IsInteger', 0, + maybeAlignedPCRead, maybePCWrite), + 'Index': ('IntReg', 'uw', 'index', 'IsInteger', 2, + maybePCRead, maybePCWrite), + 'Op1': ('IntReg', 'uw', 'op1', 'IsInteger', 2, + maybePCRead, maybePCWrite), + 'FpOp1': ('FloatReg', 'sf', '(op1 + 0)', 'IsFloating', 2), + 'FpOp1P0': ('FloatReg', 'sf', '(op1 + 0)', 'IsFloating', 2), + 'FpOp1P1': ('FloatReg', 'sf', '(op1 + 1)', 'IsFloating', 2), + 'FpOp1P2': ('FloatReg', 'sf', '(op1 + 2)', 'IsFloating', 2), + 'FpOp1P3': ('FloatReg', 'sf', '(op1 + 3)', 'IsFloating', 2), + 'MiscOp1': ('ControlReg', 'uw', 'op1', (None, None, 'IsControl'), 2), + 'Op2': ('IntReg', 'uw', 'op2', 'IsInteger', 2, + maybePCRead, maybePCWrite), + 'FpOp2': ('FloatReg', 'sf', '(op2 + 0)', 'IsFloating', 2), + 'FpOp2P0': ('FloatReg', 'sf', '(op2 + 0)', 'IsFloating', 2), + 'FpOp2P1': ('FloatReg', 'sf', '(op2 + 1)', 'IsFloating', 2), + 'FpOp2P2': ('FloatReg', 'sf', '(op2 + 2)', 'IsFloating', 2), + 'FpOp2P3': ('FloatReg', 'sf', '(op2 + 3)', 'IsFloating', 2), + 'Op3': ('IntReg', 'uw', 'op3', 'IsInteger', 2, + maybePCRead, maybePCWrite), + 'Shift': ('IntReg', 'uw', 'shift', 'IsInteger', 2, + maybePCRead, maybePCWrite), + 'Reg0': ('IntReg', 'uw', 'reg0', 'IsInteger', 2, + maybePCRead, maybePCWrite), + 'Reg1': ('IntReg', 'uw', 'reg1', 'IsInteger', 2, + maybePCRead, maybePCWrite), + 'Reg2': ('IntReg', 'uw', 'reg2', 'IsInteger', 2, + maybePCRead, maybePCWrite), + 'Reg3': ('IntReg', 'uw', 'reg3', 'IsInteger', 2, + maybePCRead, maybePCWrite), #General Purpose Integer Reg Operands - 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 1, maybePCRead, maybePCWrite), + 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 2, maybePCRead, maybePCWrite), 'Rm': ('IntReg', 'uw', 'RM', 'IsInteger', 2, maybePCRead, maybePCWrite), - 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 4, maybePCRead, maybePCWrite), - 'R7': ('IntReg', 'uw', '7', 'IsInteger', 5), - 'R0': ('IntReg', 'uw', '0', 'IsInteger', 0), + 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 2, maybePCRead, maybePCWrite), + 'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 2, maybePCRead, maybePCWrite), + 'R7': ('IntReg', 'uw', '7', 'IsInteger', 2), + 'R0': ('IntReg', 'uw', '0', 'IsInteger', 2), - #Destination register for load/store double instructions - 'Rdo': ('IntReg', 'uw', '(RD & ~1)', 'IsInteger', 4, maybePCRead, maybePCWrite), - 'Rde': ('IntReg', 'uw', '(RD | 1)', 'IsInteger', 5, maybePCRead, maybePCWrite), - - 'Rhi': ('IntReg', 'uw', 'INTREG_RHI', 'IsInteger', 7), - 'Rlo': ('IntReg', 'uw', 'INTREG_RLO', 'IsInteger', 8), - 'LR': ('IntReg', 'uw', 'INTREG_LR', 'IsInteger', 9), - 'CondCodes': ('IntReg', 'uw', 'INTREG_CONDCODES', 'IsInteger', 10), + 'LR': ('IntReg', 'uw', 'INTREG_LR', 'IsInteger', 2), + 'CondCodes': ('IntReg', 'uw', 'INTREG_CONDCODES', None, 2), + 'OptCondCodes': ('IntReg', 'uw', + '''(condCode == COND_AL || condCode == COND_UC) ? + INTREG_ZERO : INTREG_CONDCODES''', None, 2), #Register fields for microops - 'Ra' : ('IntReg', 'uw', 'ura', 'IsInteger', 11, maybePCRead, maybePCWrite), - 'Rb' : ('IntReg', 'uw', 'urb', 'IsInteger', 12, maybePCRead, maybePCWrite), + 'Ra' : ('IntReg', 'uw', 'ura', 'IsInteger', 2, maybePCRead, maybePCWrite), + 'IWRa' : ('IntReg', 'uw', 'ura', 'IsInteger', 2, + maybePCRead, maybeIWPCWrite), + 'Fa' : ('FloatReg', 'sf', 'ura', 'IsFloating', 2), + 'Rb' : ('IntReg', 'uw', 'urb', 'IsInteger', 2, maybePCRead, maybePCWrite), #General Purpose Floating Point Reg Operands - 'Fd': ('FloatReg', 'df', 'FD', 'IsFloating', 20), - 'Fn': ('FloatReg', 'df', 'FN', 'IsFloating', 21), - 'Fm': ('FloatReg', 'df', 'FM', 'IsFloating', 22), + 'Fd': ('FloatReg', 'df', 'FD', 'IsFloating', 2), + 'Fn': ('FloatReg', 'df', 'FN', 'IsFloating', 2), + 'Fm': ('FloatReg', 'df', 'FM', 'IsFloating', 2), #Memory Operand - 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 30), + 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 2), - 'Cpsr': ('ControlReg', 'uw', 'MISCREG_CPSR', (None, None, 'IsControl'), 40), - 'Spsr': ('ControlReg', 'uw', 'MISCREG_SPSR', (None, None, 'IsControl'), 41), - 'Fpsr': ('ControlReg', 'uw', 'MISCREG_FPSR', (None, None, 'IsControl'), 42), - 'Fpsid': ('ControlReg', 'uw', 'MISCREG_FPSID', (None, None, 'IsControl'), 43), - 'Fpscr': ('ControlReg', 'uw', 'MISCREG_FPSCR', (None, None, 'IsControl'), 44), - 'Fpexc': ('ControlReg', 'uw', 'MISCREG_FPEXC', (None, None, 'IsControl'), 45), - 'NPC': ('NPC', 'uw', None, (None, None, 'IsControl'), 50), - 'NNPC': ('NNPC', 'uw', None, (None, None, 'IsControl'), 51) - + 'Cpsr': ('ControlReg', 'uw', 'MISCREG_CPSR', (None, None, 'IsControl'), 1), + 'Itstate': ('ControlReg', 'ub', 'MISCREG_ITSTATE', None, 2), + 'Spsr': ('ControlReg', 'uw', 'MISCREG_SPSR', None, 2), + 'Fpsr': ('ControlReg', 'uw', 'MISCREG_FPSR', None, 2), + 'Fpsid': ('ControlReg', 'uw', 'MISCREG_FPSID', None, 2), + 'Fpscr': ('ControlReg', 'uw', 'MISCREG_FPSCR', None, 2), + 'Fpexc': ('ControlReg', 'uw', 'MISCREG_FPEXC', None, 2), + 'Sctlr': ('ControlReg', 'uw', 'MISCREG_SCTLR', None, 2), + 'SevMailbox': ('ControlReg', 'uw', 'MISCREG_SEV_MAILBOX', None, 2), + 'PC': ('PC', 'ud', None, None, 2), + 'NPC': ('NPC', 'ud', None, (None, None, 'IsControl'), 2, + readNPC, writeNPC), + 'FNPC': ('NPC', 'ud', None, (None, None, 'IsControl'), 2, + readNPC, forceNPC), + 'IWNPC': ('NPC', 'ud', None, (None, None, 'IsControl'), 2, + readNPC, writeIWNPC), }}; diff -r 84bd4089958b src/arch/arm/isa/templates/basic.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/templates/basic.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,93 @@ +// -*- 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(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; + + %(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!"); +} +}}; diff -r 84bd4089958b src/arch/arm/isa/templates/branch.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/templates/branch.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,177 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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: Gabe Black + +def template BranchImmDeclare {{ +class %(class_name)s : public %(base_class)s +{ + public: + // Constructor + %(class_name)s(ExtMachInst machInst, int32_t _imm); + %(BasicExecDeclare)s +}; +}}; + +def template BranchImmConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + int32_t _imm) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, _imm) + { + %(constructor)s; + } +}}; + +def template BranchImmCondDeclare {{ +class %(class_name)s : public %(base_class)s +{ + public: + // Constructor + %(class_name)s(ExtMachInst machInst, int32_t _imm, + ConditionCode _condCode); + %(BasicExecDeclare)s +}; +}}; + +def template BranchImmCondConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + int32_t _imm, + ConditionCode _condCode) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _imm, _condCode) + { + %(constructor)s; + } +}}; + +def template BranchRegDeclare {{ +class %(class_name)s : public %(base_class)s +{ + public: + // Constructor + %(class_name)s(ExtMachInst machInst, IntRegIndex _op1); + %(BasicExecDeclare)s +}; +}}; + +def template BranchRegConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _op1) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, _op1) + { + %(constructor)s; + } +}}; + +def template BranchRegCondDeclare {{ +class %(class_name)s : public %(base_class)s +{ + public: + // Constructor + %(class_name)s(ExtMachInst machInst, IntRegIndex _op1, + ConditionCode _condCode); + %(BasicExecDeclare)s +}; +}}; + +def template BranchRegCondConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _op1, + ConditionCode _condCode) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _op1, _condCode) + { + %(constructor)s; + } +}}; + +def template BranchRegRegDeclare {{ +class %(class_name)s : public %(base_class)s +{ + public: + // Constructor + %(class_name)s(ExtMachInst machInst, + IntRegIndex _op1, IntRegIndex _op2); + %(BasicExecDeclare)s +}; +}}; + +def template BranchTableDeclare {{ +class %(class_name)s : public %(base_class)s +{ + public: + // Constructor + %(class_name)s(ExtMachInst machInst, + IntRegIndex _op1, IntRegIndex _op2); + %(BasicExecDeclare)s + + %(InitiateAccDeclare)s + + %(CompleteAccDeclare)s +}; +}}; + +def template BranchRegRegConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _op1, + IntRegIndex _op2) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, _op1, _op2) + { + %(constructor)s; + } +}}; + +def template BranchImmRegDeclare {{ +class %(class_name)s : public %(base_class)s +{ + public: + // Constructor + %(class_name)s(ExtMachInst machInst, + int32_t imm, IntRegIndex _op1); + %(BasicExecDeclare)s +}; +}}; + +def template BranchImmRegConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + int32_t _imm, + IntRegIndex _op1) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, _imm, _op1) + { + %(constructor)s; + } +}}; diff -r 84bd4089958b src/arch/arm/isa/templates/macromem.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/templates/macromem.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,160 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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 +// Gabe Black + +//////////////////////////////////////////////////////////////////// +// +// Load/store microops +// + +def template MicroMemDeclare {{ + class %(class_name)s : public %(base_class)s + { + public: + %(class_name)s(ExtMachInst machInst, + RegIndex _ura, RegIndex _urb, bool _up, + uint8_t _imm); + %(BasicExecDeclare)s + %(InitiateAccDeclare)s + %(CompleteAccDeclare)s + }; +}}; + +def template MicroMemConstructor {{ + %(class_name)s::%(class_name)s(ExtMachInst machInst, + RegIndex _ura, + RegIndex _urb, + bool _up, + uint8_t _imm) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _ura, _urb, _up, _imm) + { + %(constructor)s; + } +}}; + +//////////////////////////////////////////////////////////////////// +// +// Integer = Integer op Immediate microops +// + +def template MicroIntDeclare {{ + class %(class_name)s : public %(base_class)s + { + public: + %(class_name)s(ExtMachInst machInst, + RegIndex _ura, RegIndex _urb, + uint8_t _imm); + %(BasicExecDeclare)s + }; +}}; + +def template MicroIntConstructor {{ + %(class_name)s::%(class_name)s(ExtMachInst machInst, + RegIndex _ura, + RegIndex _urb, + uint8_t _imm) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _ura, _urb, _imm) + { + %(constructor)s; + } +}}; + +//////////////////////////////////////////////////////////////////// +// +// Macro Memory-format instructions +// + +def template MacroMemDeclare {{ +/** + * Static instructions class for a store multiple instruction + */ +class %(class_name)s : public %(base_class)s +{ + public: + // Constructor + %(class_name)s(ExtMachInst machInst, IntRegIndex rn, + bool index, bool up, bool user, bool writeback, bool load, + uint32_t reglist); + %(BasicExecPanic)s +}; +}}; + +def template MacroMemConstructor {{ +%(class_name)s::%(class_name)s(ExtMachInst machInst, IntRegIndex rn, + bool index, bool up, bool user, bool writeback, bool load, + uint32_t reglist) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, rn, + index, up, user, writeback, load, reglist) +{ + %(constructor)s; +} + +}}; + +def template MacroVFPMemDeclare {{ +/** + * Static instructions class for a store multiple instruction + */ +class %(class_name)s : public %(base_class)s +{ + public: + // Constructor + %(class_name)s(ExtMachInst machInst, IntRegIndex rn, + RegIndex vd, bool single, bool up, bool writeback, + bool load, uint32_t offset); + %(BasicExecPanic)s +}; +}}; + +def template MacroVFPMemConstructor {{ +%(class_name)s::%(class_name)s(ExtMachInst machInst, IntRegIndex rn, + RegIndex vd, bool single, bool up, bool writeback, bool load, + uint32_t offset) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, rn, + vd, single, up, writeback, load, offset) +{ + %(constructor)s; +} + +}}; diff -r 84bd4089958b src/arch/arm/isa/templates/mem.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/templates/mem.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,736 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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 + + +def template SwapExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(op_decl)s; + uint64_t memData = 0; + %(op_rd)s; + %(ea_code)s; + + if (%(predicate_test)s) + { + %(preacc_code)s; + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, + EA, memAccessFlags, &memData); + } + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + +def template SwapInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(op_decl)s; + uint64_t memData = 0; + %(op_rd)s; + %(ea_code)s; + + if (%(predicate_test)s) + { + %(preacc_code)s; + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, &memData); + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + +def template SwapCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(op_decl)s; + %(op_rd)s; + + if (%(predicate_test)s) + { + // ARM instructions will not have a pkt if the predicate is false + uint64_t memData = pkt->get(); + + %(postacc_code)s; + + if (fault == NoFault) { + %(op_wb)s; + } + } + + if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + +def template LoadExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (%(predicate_test)s) + { + if (fault == NoFault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); + %(memacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + +def template StoreExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (%(predicate_test)s) + { + 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) { + %(op_wb)s; + } + } + + if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + +def template StoreExExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (%(predicate_test)s) + { + if (fault == NoFault) { + %(memacc_code)s; + } + + uint64_t writeResult; + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, &writeResult); + if (traceData) { traceData->setData(Mem); } + } + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + +def template StoreExInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (%(predicate_test)s) + { + 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; + } + } + + if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + +def template StoreInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (%(predicate_test)s) + { + 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; + } + } + + if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + +def template LoadInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(op_src_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (%(predicate_test)s) + { + if (fault == NoFault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags); + } + } else if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + +def template LoadCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(op_decl)s; + %(op_rd)s; + + if (%(predicate_test)s) + { + // ARM instructions will not have a pkt if the predicate is false + Mem = pkt->get(); + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + +def template StoreCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(op_decl)s; + %(op_rd)s; + + if (%(predicate_test)s) + { + if (fault == NoFault) { + %(op_wb)s; + } + } + + if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + +def template StoreExCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(op_decl)s; + %(op_rd)s; + + if (%(predicate_test)s) + { + uint64_t writeResult = pkt->req->getExtraData(); + %(postacc_code)s; + + if (fault == NoFault) { + %(op_wb)s; + } + } + + if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + +def template RfeDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + public: + + /// Constructor. + %(class_name)s(ExtMachInst machInst, + uint32_t _base, int _mode, bool _wb); + + %(BasicExecDeclare)s + + %(InitiateAccDeclare)s + + %(CompleteAccDeclare)s + }; +}}; + +def template SrsDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + public: + + /// Constructor. + %(class_name)s(ExtMachInst machInst, + uint32_t _regMode, int _mode, bool _wb); + + %(BasicExecDeclare)s + + %(InitiateAccDeclare)s + + %(CompleteAccDeclare)s + }; +}}; + +def template SwapDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + public: + + /// Constructor. + %(class_name)s(ExtMachInst machInst, + uint32_t _dest, uint32_t _op1, uint32_t _base); + + %(BasicExecDeclare)s + + %(InitiateAccDeclare)s + + %(CompleteAccDeclare)s + }; +}}; + +def template LoadStoreDImmDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + public: + + /// Constructor. + %(class_name)s(ExtMachInst machInst, + uint32_t _dest, uint32_t _dest2, + uint32_t _base, bool _add, int32_t _imm); + + %(BasicExecDeclare)s + + %(InitiateAccDeclare)s + + %(CompleteAccDeclare)s + }; +}}; + +def template StoreExDImmDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + public: + + /// Constructor. + %(class_name)s(ExtMachInst machInst, + uint32_t _result, uint32_t _dest, uint32_t _dest2, + uint32_t _base, bool _add, int32_t _imm); + + %(BasicExecDeclare)s + + %(InitiateAccDeclare)s + + %(CompleteAccDeclare)s + }; +}}; + +def template LoadStoreImmDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + public: + + /// Constructor. + %(class_name)s(ExtMachInst machInst, + uint32_t _dest, uint32_t _base, bool _add, int32_t _imm); + + %(BasicExecDeclare)s + + %(InitiateAccDeclare)s + + %(CompleteAccDeclare)s + }; +}}; + +def template StoreExImmDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + public: + + /// Constructor. + %(class_name)s(ExtMachInst machInst, + uint32_t _result, uint32_t _dest, uint32_t _base, + bool _add, int32_t _imm); + + %(BasicExecDeclare)s + + %(InitiateAccDeclare)s + + %(CompleteAccDeclare)s + }; +}}; + +def template LoadStoreDRegDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + public: + + /// Constructor. + %(class_name)s(ExtMachInst machInst, + uint32_t _dest, uint32_t _dest2, + uint32_t _base, bool _add, + int32_t _shiftAmt, uint32_t _shiftType, + uint32_t _index); + + %(BasicExecDeclare)s + + %(InitiateAccDeclare)s + + %(CompleteAccDeclare)s + }; +}}; + +def template LoadStoreRegDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + public: + + /// Constructor. + %(class_name)s(ExtMachInst machInst, + uint32_t _dest, uint32_t _base, bool _add, + int32_t _shiftAmt, uint32_t _shiftType, + uint32_t _index); + + %(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 RfeConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + uint32_t _base, int _mode, bool _wb) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + (IntRegIndex)_base, (AddrMode)_mode, _wb) + { + %(constructor)s; + } +}}; + +def template SrsConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + uint32_t _regMode, int _mode, bool _wb) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + (OperatingMode)_regMode, (AddrMode)_mode, _wb) + { + %(constructor)s; + } +}}; + +def template SwapConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + uint32_t _dest, uint32_t _op1, uint32_t _base) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + (IntRegIndex)_dest, (IntRegIndex)_op1, (IntRegIndex)_base) + { + %(constructor)s; + } +}}; + +def template LoadStoreDImmConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + uint32_t _dest, uint32_t _dest2, + uint32_t _base, bool _add, int32_t _imm) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + (IntRegIndex)_dest, (IntRegIndex)_dest2, + (IntRegIndex)_base, _add, _imm) + { + %(constructor)s; + } +}}; + +def template StoreExDImmConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + uint32_t _result, uint32_t _dest, uint32_t _dest2, + uint32_t _base, bool _add, int32_t _imm) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + (IntRegIndex)_result, + (IntRegIndex)_dest, (IntRegIndex)_dest2, + (IntRegIndex)_base, _add, _imm) + { + %(constructor)s; + } +}}; + +def template LoadStoreImmConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + uint32_t _dest, uint32_t _base, bool _add, int32_t _imm) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + (IntRegIndex)_dest, (IntRegIndex)_base, _add, _imm) + { + %(constructor)s; + } +}}; + +def template StoreExImmConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + uint32_t _result, uint32_t _dest, uint32_t _base, + bool _add, int32_t _imm) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + (IntRegIndex)_result, (IntRegIndex)_dest, + (IntRegIndex)_base, _add, _imm) + { + %(constructor)s; + } +}}; + +def template LoadStoreDRegConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + uint32_t _dest, uint32_t _dest2, uint32_t _base, bool _add, + int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + (IntRegIndex)_dest, (IntRegIndex)_dest2, + (IntRegIndex)_base, _add, + _shiftAmt, (ArmShiftType)_shiftType, + (IntRegIndex)_index) + { + %(constructor)s; + } +}}; + +def template LoadStoreRegConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + uint32_t _dest, uint32_t _base, bool _add, + int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + (IntRegIndex)_dest, (IntRegIndex)_base, _add, + _shiftAmt, (ArmShiftType)_shiftType, + (IntRegIndex)_index) + { + %(constructor)s; + } +}}; diff -r 84bd4089958b src/arch/arm/isa/templates/misc.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/templates/misc.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,338 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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: Gabe Black + +def template MrsDeclare {{ +class %(class_name)s : public %(base_class)s +{ + protected: + public: + // Constructor + %(class_name)s(ExtMachInst machInst, IntRegIndex _dest); + %(BasicExecDeclare)s +}; +}}; + +def template MrsConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _dest) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, _dest) + { + %(constructor)s; + } +}}; + +def template MsrRegDeclare {{ +class %(class_name)s : public %(base_class)s +{ + protected: + public: + // Constructor + %(class_name)s(ExtMachInst machInst, IntRegIndex _op1, uint8_t mask); + %(BasicExecDeclare)s +}; +}}; + +def template MsrRegConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _op1, + uint8_t mask) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, _op1, mask) + { + %(constructor)s; + } +}}; + +def template MsrImmDeclare {{ +class %(class_name)s : public %(base_class)s +{ + protected: + public: + // Constructor + %(class_name)s(ExtMachInst machInst, uint32_t imm, uint8_t mask); + %(BasicExecDeclare)s +}; +}}; + +def template MsrImmConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + uint32_t imm, + uint8_t mask) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, imm, mask) + { + %(constructor)s; + } +}}; + +def template ImmOpDeclare {{ +class %(class_name)s : public %(base_class)s +{ + protected: + public: + // Constructor + %(class_name)s(ExtMachInst machInst, uint64_t _imm); + %(BasicExecDeclare)s +}; +}}; + +def template ImmOpConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, uint64_t _imm) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, _imm) + { + %(constructor)s; + } +}}; + +def template RegImmOpDeclare {{ +class %(class_name)s : public %(base_class)s +{ + protected: + public: + // Constructor + %(class_name)s(ExtMachInst machInst, IntRegIndex _dest, uint64_t _imm); + %(BasicExecDeclare)s +}; +}}; + +def template RegImmOpConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, uint64_t _imm) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, _dest, _imm) + { + %(constructor)s; + } +}}; + +def template RegRegOpDeclare {{ +class %(class_name)s : public %(base_class)s +{ + protected: + public: + // Constructor + %(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, IntRegIndex _op1); + %(BasicExecDeclare)s +}; +}}; + +def template RegRegOpConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, IntRegIndex _op1) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, _dest, _op1) + { + %(constructor)s; + } +}}; + +def template RegRegRegImmOpDeclare {{ +class %(class_name)s : public %(base_class)s +{ + protected: + public: + // Constructor + %(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, + uint64_t _imm); + %(BasicExecDeclare)s +}; +}}; + +def template RegRegRegImmOpConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, + IntRegIndex _op1, + IntRegIndex _op2, + uint64_t _imm) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _dest, _op1, _op2, _imm) + { + %(constructor)s; + } +}}; + +def template RegRegRegRegOpDeclare {{ +class %(class_name)s : public %(base_class)s +{ + protected: + public: + // Constructor + %(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, IntRegIndex _op1, + IntRegIndex _op2, IntRegIndex _op3); + %(BasicExecDeclare)s +}; +}}; + +def template RegRegRegRegOpConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, + IntRegIndex _op1, + IntRegIndex _op2, + IntRegIndex _op3) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _dest, _op1, _op2, _op3) + { + %(constructor)s; + } +}}; + +def template RegRegRegOpDeclare {{ +class %(class_name)s : public %(base_class)s +{ + protected: + public: + // Constructor + %(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2); + %(BasicExecDeclare)s +}; +}}; + +def template RegRegRegOpConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, + IntRegIndex _op1, + IntRegIndex _op2) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _dest, _op1, _op2) + { + %(constructor)s; + } +}}; + +def template RegRegImmOpDeclare {{ +class %(class_name)s : public %(base_class)s +{ + protected: + public: + // Constructor + %(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, IntRegIndex _op1, + uint64_t _imm); + %(BasicExecDeclare)s +}; +}}; + +def template RegRegImmOpConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, + IntRegIndex _op1, + uint64_t _imm) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _dest, _op1, _imm) + { + %(constructor)s; + } +}}; + +def template RegRegImmImmOpDeclare {{ +class %(class_name)s : public %(base_class)s +{ + protected: + public: + // Constructor + %(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, IntRegIndex _op1, + uint64_t _imm1, uint64_t _imm2); + %(BasicExecDeclare)s +}; +}}; + +def template RegRegImmImmOpConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, + IntRegIndex _op1, + uint64_t _imm1, + uint64_t _imm2) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _dest, _op1, _imm1, _imm2) + { + %(constructor)s; + } +}}; + +def template RegImmRegOpDeclare {{ +class %(class_name)s : public %(base_class)s +{ + protected: + public: + // Constructor + %(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, uint64_t _imm, IntRegIndex _op1); + %(BasicExecDeclare)s +}; +}}; + +def template RegImmRegOpConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, + uint64_t _imm, + IntRegIndex _op1) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _dest, _imm, _op1) + { + %(constructor)s; + } +}}; + +def template RegImmRegShiftOpDeclare {{ +class %(class_name)s : public %(base_class)s +{ + protected: + public: + // Constructor + %(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, uint64_t _imm, IntRegIndex _op1, + int32_t _shiftAmt, ArmShiftType _shiftType); + %(BasicExecDeclare)s +}; +}}; + +def template RegImmRegShiftOpConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, + uint64_t _imm, + IntRegIndex _op1, + int32_t _shiftAmt, + ArmShiftType _shiftType) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _dest, _imm, _op1, _shiftAmt, _shiftType) + { + %(constructor)s; + } +}}; diff -r 84bd4089958b src/arch/arm/isa/templates/mult.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/templates/mult.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,86 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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: Gabe Black + +def template Mult3Declare {{ +class %(class_name)s : public %(base_class)s +{ + public: + // Constructor + %(class_name)s(ExtMachInst machInst, IntRegIndex _reg0, + IntRegIndex _reg1, IntRegIndex _reg2); + %(BasicExecDeclare)s +}; +}}; + +def template Mult3Constructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _reg0, + IntRegIndex _reg1, + IntRegIndex _reg2) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _reg0, _reg1, _reg2) + { + %(constructor)s; + } +}}; + +def template Mult4Declare {{ +class %(class_name)s : public %(base_class)s +{ + public: + // Constructor + %(class_name)s(ExtMachInst machInst, + IntRegIndex _reg0, IntRegIndex _reg1, + IntRegIndex _reg2, IntRegIndex _reg3); + %(BasicExecDeclare)s +}; +}}; + +def template Mult4Constructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _reg0, + IntRegIndex _reg1, + IntRegIndex _reg2, + IntRegIndex _reg3) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _reg0, _reg1, _reg2, _reg3) + { + %(constructor)s; + } +}}; diff -r 84bd4089958b src/arch/arm/isa/templates/pred.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/templates/pred.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,174 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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 +// + +let {{ + predicateTest = 'testPredicate(OptCondCodes, condCode)' + condPredicateTest = 'testPredicate(CondCodes, condCode)' +}}; + +def template DataImmDeclare {{ +class %(class_name)s : public %(base_class)s +{ + public: + // Constructor + %(class_name)s(ExtMachInst machInst, IntRegIndex _dest, + IntRegIndex _op1, uint32_t _imm, bool _rotC=true); + %(BasicExecDeclare)s +}; +}}; + +def template DataImmConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, + IntRegIndex _op1, + uint32_t _imm, + bool _rotC) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _dest, _op1, _imm, _rotC) + { + %(constructor)s; + } +}}; + +def template DataRegDeclare {{ +class %(class_name)s : public %(base_class)s +{ + public: + // Constructor + %(class_name)s(ExtMachInst machInst, IntRegIndex _dest, + IntRegIndex _op1, IntRegIndex _op2, + int32_t _shiftAmt, ArmShiftType _shiftType); + %(BasicExecDeclare)s +}; +}}; + +def template DataRegConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, + IntRegIndex _op1, + IntRegIndex _op2, + int32_t _shiftAmt, + ArmShiftType _shiftType) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _dest, _op1, _op2, _shiftAmt, _shiftType) + { + %(constructor)s; + } +}}; + +def template DataRegRegDeclare {{ +class %(class_name)s : public %(base_class)s +{ + public: + // Constructor + %(class_name)s(ExtMachInst machInst, IntRegIndex _dest, + IntRegIndex _op1, IntRegIndex _op2, IntRegIndex _shift, + ArmShiftType _shiftType); + %(BasicExecDeclare)s +}; +}}; + +def template DataRegRegConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, + IntRegIndex _op1, + IntRegIndex _op2, + IntRegIndex _shift, + ArmShiftType _shiftType) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _dest, _op1, _op2, _shift, _shiftType) + { + %(constructor)s; + } +}}; + +def template PredOpExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + uint64_t resTemp = 0; + resTemp = resTemp; + %(op_decl)s; + %(op_rd)s; + + if (%(predicate_test)s) + { + %(code)s; + if (fault == NoFault) + { + %(op_wb)s; + } + } + + if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + +def template DataDecode {{ + if (machInst.opcode4 == 0) { + if (machInst.sField == 0) + return new %(class_name)sImm(machInst); + else + return new %(class_name)sImmCc(machInst); + } else { + if (machInst.sField == 0) + return new %(class_name)s(machInst); + else + return new %(class_name)sCc(machInst); + } +}}; + +def template DataImmDecode {{ + if (machInst.sField == 0) + return new %(class_name)s(machInst); + else + return new %(class_name)sCc(machInst); +}}; diff -r 84bd4089958b src/arch/arm/isa/templates/templates.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/templates/templates.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,62 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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: Gabe Black + +//Basic instruction templates +##include "basic.isa" + +//Templates for predicated instructions +##include "pred.isa" + +//Templates for memory instructions +##include "mem.isa" + +//Miscellaneous instructions that don't fit elsewhere +##include "misc.isa" + +//Templates for microcoded memory instructions +##include "macromem.isa" + +//Templates for branches +##include "branch.isa" + +//Templates for multiplies +##include "mult.isa" + +//Templates for VFP instructions +##include "vfp.isa" diff -r 84bd4089958b src/arch/arm/isa/templates/vfp.isa --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/isa/templates/vfp.isa Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,132 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 ARM Limited +// All rights reserved +// +// The license below extends only to copyright in the software and shall +// not be construed as granting a license to any other intellectual +// property including but not limited to intellectual property relating +// to a hardware implementation of the functionality of the software +// licensed hereunder. You may use the software subject to the license +// terms below provided that you ensure that this notice is replicated +// unmodified and in its entirety in all distributions of the software, +// modified or unmodified, in source code or in binary form. +// +// 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: Gabe Black + +def template FpRegRegOpDeclare {{ +class %(class_name)s : public %(base_class)s +{ + public: + // Constructor + %(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, IntRegIndex _op1, + VfpMicroMode mode = VfpNotAMicroop); + %(BasicExecDeclare)s +}; +}}; + +def template FpRegRegOpConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, IntRegIndex _op1, + VfpMicroMode mode) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _dest, _op1, mode) + { + %(constructor)s; + } +}}; + +def template FpRegImmOpDeclare {{ +class %(class_name)s : public %(base_class)s +{ + public: + // Constructor + %(class_name)s(ExtMachInst machInst, IntRegIndex _dest, + uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop); + %(BasicExecDeclare)s +}; +}}; + +def template FpRegImmOpConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, uint64_t _imm, VfpMicroMode mode) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _dest, _imm, mode) + { + %(constructor)s; + } +}}; + +def template FpRegRegImmOpDeclare {{ +class %(class_name)s : public %(base_class)s +{ + public: + // Constructor + %(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, IntRegIndex _op1, + uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop); + %(BasicExecDeclare)s +}; +}}; + +def template FpRegRegImmOpConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, + IntRegIndex _op1, + uint64_t _imm, + VfpMicroMode mode) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _dest, _op1, _imm, mode) + { + %(constructor)s; + } +}}; + +def template FpRegRegRegOpDeclare {{ +class %(class_name)s : public %(base_class)s +{ + public: + // Constructor + %(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, + VfpMicroMode mode = VfpNotAMicroop); + %(BasicExecDeclare)s +}; +}}; + +def template FpRegRegRegOpConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _dest, + IntRegIndex _op1, + IntRegIndex _op2, + VfpMicroMode mode) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _dest, _op1, _op2, mode) + { + %(constructor)s; + } +}}; diff -r 84bd4089958b src/arch/arm/isa_traits.hh --- a/src/arch/arm/isa_traits.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/isa_traits.hh Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,16 @@ /* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2003-2005 The Regents of The University of Michigan * Copyright (c) 2007-2008 The Florida State University * All rights reserved. @@ -98,6 +110,7 @@ const int LogVMPageSize = 12; // 4K bytes const int VMPageSize = (1 << LogVMPageSize); + // Shouldn't this be 1 because of Thumb?! Dynamic? --Ali const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned const int MachineBytes = 4; @@ -109,6 +122,22 @@ // Memory accesses cannot be unaligned const bool HasUnalignedMemAcc = false; + + enum InterruptTypes + { + INT_RST, + INT_ABT, + INT_IRQ, + INT_FIQ, + NumInterruptTypes + }; + + // These otherwise unused bits of the PC are used to select a mode + // like the J and T bits of the CPSR. + static const Addr PcJBitShift = 33; + static const Addr PcTBitShift = 34; + static const Addr PcModeMask = (ULL(1) << PcJBitShift) | + (ULL(1) << PcTBitShift); }; using namespace ArmISA; diff -r 84bd4089958b src/arch/arm/linux/linux.hh --- a/src/arch/arm/linux/linux.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/linux/linux.hh Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,16 @@ /* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2003-2005 The Regents of The University of Michigan * Copyright (c) 2007-2008 The Florida State University * All rights reserved. @@ -26,7 +38,8 @@ * (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 + * Authors: Ali Saidi + * Stephen Hines */ #ifndef __ARCH_ARM_LINUX_LINUX_HH__ @@ -46,6 +59,14 @@ static const int NUM_OPEN_FLAGS; //@{ + /// Basic ARM Linux types + typedef uint32_t size_t; + typedef uint32_t off_t; + typedef int32_t time_t; + typedef int32_t clock_t; + //@} + + //@{ /// open(2) flag values. static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY @@ -58,11 +79,14 @@ static const int TGT_O_NONBLOCK = 00004000; //!< O_NONBLOCK static const int TGT_O_SYNC = 00010000; //!< O_SYNC static const int TGT_FASYNC = 00020000; //!< FASYNC - static const int TGT_O_DIRECTORY = 00040000; //!< O_DIRECTORY - static const int TGT_O_NOFOLLOW = 00100000; //!< O_NOFOLLOW - static const int TGT_O_DIRECT = 00200000; //!< O_DIRECT - static const int TGT_O_LARGEFILE = 00400000; //!< O_LARGEFILE + static const int TGT_O_DIRECT = 00040000; //!< O_DIRECT + static const int TGT_O_LARGEFILE = 00100000; //!< O_LARGEFILE + static const int TGT_O_DIRECTORY = 00200000; //!< O_DIRECTORY + static const int TGT_O_NOFOLLOW = 00400000; //!< O_NOFOLLOW static const int TGT_O_NOATIME = 01000000; //!< O_NOATIME + static const int TGT_O_CLOEXEC = 02000000; //!< O_NOATIME + + //@} /// For mmap(). @@ -85,7 +109,7 @@ static const unsigned FIONREAD_ = 0x4004667f; static const unsigned TIOCISATTY_ = 0x2000745e; static const unsigned TIOCGETS_ = 0x402c7413; - static const unsigned TIOCGETA_ = 0x40127417; + static const unsigned TIOCGETA_ = 0x5405; static const unsigned TCSETAW_ = 0x5407; // 2.6.15 kernel //@} @@ -107,6 +131,25 @@ TGT_RLIMIT_LOCKS = 10 }; + /// Limit struct for getrlimit/setrlimit. + struct rlimit { + uint32_t rlim_cur; //!< soft limit + uint32_t rlim_max; //!< hard limit + }; + + /// For gettimeofday(). + struct timeval { + int32_t tv_sec; //!< seconds + int32_t tv_usec; //!< microseconds + }; + + // For writev/readv + struct tgt_iovec { + uint32_t iov_base; // void * + uint32_t iov_len; + }; + + typedef struct { uint32_t st_dev; uint32_t st_ino; @@ -163,6 +206,34 @@ uint32_t mem_unit; /* Memory unit size in bytes */ } tgt_sysinfo; + /// For getrusage(). + struct rusage { + struct timeval ru_utime; //!< user time used + struct timeval ru_stime; //!< system time used + int32_t ru_maxrss; //!< max rss + int32_t ru_ixrss; //!< integral shared memory size + int32_t ru_idrss; //!< integral unshared data " + int32_t ru_isrss; //!< integral unshared stack " + int32_t ru_minflt; //!< page reclaims - total vmfaults + int32_t ru_majflt; //!< page faults + int32_t ru_nswap; //!< swaps + int32_t ru_inblock; //!< block input operations + int32_t ru_oublock; //!< block output operations + int32_t ru_msgsnd; //!< messages sent + int32_t ru_msgrcv; //!< messages received + int32_t ru_nsignals; //!< signals received + int32_t ru_nvcsw; //!< voluntary context switches + int32_t ru_nivcsw; //!< involuntary " + }; + + /// For times(). + struct tms { + int32_t tms_utime; //!< user time + int32_t tms_stime; //!< system time + int32_t tms_cutime; //!< user time of children + int32_t tms_cstime; //!< system time of children + }; + }; diff -r 84bd4089958b src/arch/arm/linux/linux.cc --- a/src/arch/arm/linux/linux.cc Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/linux/linux.cc Wed May 26 18:10:45 2010 -0500 @@ -56,15 +56,30 @@ { ArmLinux::TGT_O_RDONLY, O_RDONLY }, { ArmLinux::TGT_O_WRONLY, O_WRONLY }, { ArmLinux::TGT_O_RDWR, O_RDWR }, + { ArmLinux::TGT_O_CREAT, O_CREAT }, + { ArmLinux::TGT_O_EXCL, O_EXCL }, + { ArmLinux::TGT_O_NOCTTY, O_NOCTTY }, + { ArmLinux::TGT_O_TRUNC, O_TRUNC }, { ArmLinux::TGT_O_APPEND, O_APPEND }, - { ArmLinux::TGT_O_CREAT, O_CREAT }, - { ArmLinux::TGT_O_TRUNC, O_TRUNC }, - { ArmLinux::TGT_O_EXCL, O_EXCL }, { ArmLinux::TGT_O_NONBLOCK, O_NONBLOCK }, - { ArmLinux::TGT_O_NOCTTY, O_NOCTTY }, #ifdef O_SYNC { ArmLinux::TGT_O_SYNC, O_SYNC }, #endif +#ifdef FASYNC + { ArmLinux::TGT_FASYNC, FASYNC }, +#endif +#ifdef O_DIRECT + { ArmLinux::TGT_O_DIRECT, O_DIRECT }, +#endif +#ifdef O_LARGEFILE + { ArmLinux::TGT_O_LARGEFILE, O_LARGEFILE }, +#endif +#ifdef O_DIRECTORY + { ArmLinux::TGT_O_DIRECTORY, O_DIRECTORY }, +#endif +#ifdef O_NOFOLLOW + { ArmLinux::TGT_O_NOFOLLOW, O_NOFOLLOW }, +#endif #endif /* _MSC_VER */ }; diff -r 84bd4089958b src/arch/arm/linux/process.hh --- a/src/arch/arm/linux/process.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/linux/process.hh Wed May 26 18:10:45 2010 -0500 @@ -38,7 +38,8 @@ class ArmLinuxProcess : public ArmLiveProcess { public: - ArmLinuxProcess(LiveProcessParams * params, ObjectFile *objFile); + ArmLinuxProcess(LiveProcessParams * params, ObjectFile *objFile, + ObjectFile::Arch _arch); virtual SyscallDesc* getDesc(int callnum); diff -r 84bd4089958b src/arch/arm/linux/process.cc --- a/src/arch/arm/linux/process.cc Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/linux/process.cc Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,16 @@ /* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2003-2005 The Regents of The University of Michigan * Copyright (c) 2007-2008 The Florida State University * All rights reserved. @@ -28,6 +40,7 @@ * * Authors: Korey Sewell * Stephen Hines + * Ali Saidi */ #include "arch/arm/linux/linux.hh" @@ -55,9 +68,9 @@ strcpy(name->sysname, "Linux"); strcpy(name->nodename, "m5.eecs.umich.edu"); - strcpy(name->release, "2.6.16.19"); + strcpy(name->release, "2.6.29"); strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); - strcpy(name->machine, "arm"); + strcpy(name->machine, "armv7l"); name.copyOut(tc->getMemPort()); return 0; @@ -71,18 +84,18 @@ /* 4 */ SyscallDesc("write", writeFunc), /* 5 */ SyscallDesc("open", openFunc), /* 6 */ SyscallDesc("close", closeFunc), - /* 7 */ SyscallDesc("waitpid", unimplementedFunc), //??? + /* 7 */ SyscallDesc("unused#7", unimplementedFunc), /* 8 */ SyscallDesc("creat", unimplementedFunc), /* 9 */ SyscallDesc("link", unimplementedFunc), /* 10 */ SyscallDesc("unlink", unlinkFunc), /* 11 */ SyscallDesc("execve", unimplementedFunc), /* 12 */ SyscallDesc("chdir", unimplementedFunc), - /* 13 */ SyscallDesc("time", unimplementedFunc), + /* 13 */ SyscallDesc("time", timeFunc), /* 14 */ SyscallDesc("mknod", unimplementedFunc), /* 15 */ SyscallDesc("chmod", chmodFunc), /* 16 */ SyscallDesc("lchown", chownFunc), - /* 17 */ SyscallDesc("break", brkFunc), //??? - /* 18 */ SyscallDesc("unused#18", unimplementedFunc), //??? + /* 17 */ SyscallDesc("unused#17", unimplementedFunc), + /* 18 */ SyscallDesc("unused#18", unimplementedFunc), /* 19 */ SyscallDesc("lseek", lseekFunc), /* 20 */ SyscallDesc("getpid", getpidFunc), /* 21 */ SyscallDesc("mount", unimplementedFunc), @@ -95,77 +108,77 @@ /* 28 */ SyscallDesc("unused#28", unimplementedFunc), /* 29 */ SyscallDesc("pause", unimplementedFunc), /* 30 */ SyscallDesc("utime", unimplementedFunc), - /* 31 */ SyscallDesc("stty", unimplementedFunc), - /* 32 */ SyscallDesc("gtty", unimplementedFunc), + /* 31 */ SyscallDesc("unused#31", unimplementedFunc), + /* 32 */ SyscallDesc("unused#32", unimplementedFunc), /* 33 */ SyscallDesc("access", unimplementedFunc), /* 34 */ SyscallDesc("nice", unimplementedFunc), - /* 35 */ SyscallDesc("ftime", unimplementedFunc), + /* 35 */ SyscallDesc("unused#35", unimplementedFunc), /* 36 */ SyscallDesc("sync", unimplementedFunc), /* 37 */ SyscallDesc("kill", ignoreFunc), - /* 38 */ SyscallDesc("rename", unimplementedFunc), - /* 39 */ SyscallDesc("mkdir", unimplementedFunc), + /* 38 */ SyscallDesc("rename", renameFunc), + /* 39 */ SyscallDesc("mkdir", mkdirFunc), /* 40 */ SyscallDesc("rmdir", unimplementedFunc), - /* 41 */ SyscallDesc("dup", unimplementedFunc), - /* 42 */ SyscallDesc("pipe", unimplementedFunc), - /* 43 */ SyscallDesc("times", ignoreFunc), - /* 44 */ SyscallDesc("prof", unimplementedFunc), + /* 41 */ SyscallDesc("dup", dupFunc), + /* 42 */ SyscallDesc("pipe", pipePseudoFunc), + /* 43 */ SyscallDesc("times", timesFunc), + /* 44 */ SyscallDesc("unused#44", unimplementedFunc), /* 45 */ SyscallDesc("brk", brkFunc), /* 46 */ SyscallDesc("setgid", unimplementedFunc), /* 47 */ SyscallDesc("getgid", getgidFunc), - /* 48 */ SyscallDesc("signal", ignoreFunc), + /* 48 */ SyscallDesc("unused#48", unimplementedFunc), /* 49 */ SyscallDesc("geteuid", geteuidFunc), /* 50 */ SyscallDesc("getegid", getegidFunc), /* 51 */ SyscallDesc("acct", unimplementedFunc), /* 52 */ SyscallDesc("umount2", unimplementedFunc), - /* 53 */ SyscallDesc("lock", unimplementedFunc), + /* 53 */ SyscallDesc("unused#53", unimplementedFunc), /* 54 */ SyscallDesc("ioctl", ioctlFunc), /* 55 */ SyscallDesc("fcntl", fcntlFunc), - /* 56 */ SyscallDesc("mpx", unimplementedFunc), + /* 56 */ SyscallDesc("unused#56", unimplementedFunc), /* 57 */ SyscallDesc("setpgid", unimplementedFunc), - /* 58 */ SyscallDesc("ulimit", unimplementedFunc), + /* 58 */ SyscallDesc("unused#58", unimplementedFunc), /* 59 */ SyscallDesc("unused#59", unimplementedFunc), /* 60 */ SyscallDesc("umask", unimplementedFunc), /* 61 */ SyscallDesc("chroot", unimplementedFunc), /* 62 */ SyscallDesc("ustat", unimplementedFunc), /* 63 */ SyscallDesc("dup2", unimplementedFunc), - /* 64 */ SyscallDesc("getppid", getpagesizeFunc), + /* 64 */ SyscallDesc("getppid", getppidFunc), /* 65 */ SyscallDesc("getpgrp", unimplementedFunc), /* 66 */ SyscallDesc("setsid", unimplementedFunc), /* 67 */ SyscallDesc("sigaction",unimplementedFunc), - /* 68 */ SyscallDesc("sgetmask", unimplementedFunc), - /* 69 */ SyscallDesc("ssetmask", unimplementedFunc), + /* 68 */ SyscallDesc("unused#68", unimplementedFunc), + /* 69 */ SyscallDesc("unused#69", unimplementedFunc), /* 70 */ SyscallDesc("setreuid", unimplementedFunc), /* 71 */ SyscallDesc("setregid", unimplementedFunc), /* 72 */ SyscallDesc("sigsuspend", unimplementedFunc), /* 73 */ SyscallDesc("sigpending", unimplementedFunc), /* 74 */ SyscallDesc("sethostname", ignoreFunc), - /* 75 */ SyscallDesc("setrlimit", unimplementedFunc), + /* 75 */ SyscallDesc("setrlimit", ignoreFunc), /* 76 */ SyscallDesc("getrlimit", unimplementedFunc), - /* 77 */ SyscallDesc("getrusage", unimplementedFunc), - /* 78 */ SyscallDesc("gettimeofday", unimplementedFunc), + /* 77 */ SyscallDesc("getrusage", getrusageFunc), + /* 78 */ SyscallDesc("gettimeofday", gettimeofdayFunc), /* 79 */ SyscallDesc("settimeofday", unimplementedFunc), /* 80 */ SyscallDesc("getgroups", unimplementedFunc), /* 81 */ SyscallDesc("setgroups", unimplementedFunc), /* 82 */ SyscallDesc("reserved#82", unimplementedFunc), /* 83 */ SyscallDesc("symlink", unimplementedFunc), /* 84 */ SyscallDesc("unused#84", unimplementedFunc), - /* 85 */ SyscallDesc("readlink", unimplementedFunc), + /* 85 */ SyscallDesc("readlink", readlinkFunc), /* 86 */ SyscallDesc("uselib", unimplementedFunc), - /* 87 */ SyscallDesc("swapon", gethostnameFunc), + /* 87 */ SyscallDesc("swapon", unimplementedFunc), /* 88 */ SyscallDesc("reboot", unimplementedFunc), /* 89 */ SyscallDesc("readdir", unimplementedFunc), /* 90 */ SyscallDesc("mmap", mmapFunc), - /* 91 */ SyscallDesc("munmap",munmapFunc), + /* 91 */ SyscallDesc("munmap", munmapFunc), /* 92 */ SyscallDesc("truncate", truncateFunc), /* 93 */ SyscallDesc("ftruncate", ftruncateFunc), /* 94 */ SyscallDesc("fchmod", unimplementedFunc), /* 95 */ SyscallDesc("fchown", unimplementedFunc), /* 96 */ SyscallDesc("getpriority", unimplementedFunc), /* 97 */ SyscallDesc("setpriority", unimplementedFunc), - /* 98 */ SyscallDesc("profil", unimplementedFunc), + /* 98 */ SyscallDesc("unused#98", unimplementedFunc), /* 99 */ SyscallDesc("statfs", unimplementedFunc), /* 100 */ SyscallDesc("fstatfs", unimplementedFunc), - /* 101 */ SyscallDesc("ioperm", unimplementedFunc), + /* 101 */ SyscallDesc("unused#101", unimplementedFunc), /* 102 */ SyscallDesc("socketcall", unimplementedFunc), /* 103 */ SyscallDesc("syslog", unimplementedFunc), /* 104 */ SyscallDesc("setitimer", unimplementedFunc), @@ -174,10 +187,10 @@ /* 107 */ SyscallDesc("lstat", unimplementedFunc), /* 108 */ SyscallDesc("fstat", fstatFunc), /* 109 */ SyscallDesc("unused#109", unimplementedFunc), - /* 110 */ SyscallDesc("iopl", unimplementedFunc), + /* 110 */ SyscallDesc("unused#101", unimplementedFunc), /* 111 */ SyscallDesc("vhangup", unimplementedFunc), - /* 112 */ SyscallDesc("idle", ignoreFunc), - /* 113 */ SyscallDesc("vm86", unimplementedFunc), + /* 112 */ SyscallDesc("unused#112", unimplementedFunc), + /* 113 */ SyscallDesc("syscall", unimplementedFunc), /* 114 */ SyscallDesc("wait4", unimplementedFunc), /* 115 */ SyscallDesc("swapoff", unimplementedFunc), /* 116 */ SyscallDesc("sysinfo", sysinfoFunc), @@ -187,24 +200,24 @@ /* 120 */ SyscallDesc("clone", unimplementedFunc), /* 121 */ SyscallDesc("setdomainname", unimplementedFunc), /* 122 */ SyscallDesc("uname", unameFunc), - /* 123 */ SyscallDesc("modify_ldt", unimplementedFunc), + /* 123 */ SyscallDesc("unused#123", unimplementedFunc), /* 124 */ SyscallDesc("adjtimex", unimplementedFunc), /* 125 */ SyscallDesc("mprotect", ignoreFunc), /* 126 */ SyscallDesc("sigprocmask", unimplementedFunc), - /* 127 */ SyscallDesc("create_module", unimplementedFunc), + /* 127 */ SyscallDesc("unused#127", unimplementedFunc), /* 128 */ SyscallDesc("init_module", unimplementedFunc), /* 129 */ SyscallDesc("delete_module", unimplementedFunc), - /* 130 */ SyscallDesc("get_kernel_syms", unimplementedFunc), + /* 130 */ SyscallDesc("unused#130", unimplementedFunc), /* 131 */ SyscallDesc("quotactl", unimplementedFunc), /* 132 */ SyscallDesc("getpgid", unimplementedFunc), /* 133 */ SyscallDesc("fchdir", unimplementedFunc), /* 134 */ SyscallDesc("bdflush", unimplementedFunc), /* 135 */ SyscallDesc("sysfs", unimplementedFunc), /* 136 */ SyscallDesc("personality", unimplementedFunc), - /* 137 */ SyscallDesc("afs_syscall", unimplementedFunc), + /* 137 */ SyscallDesc("reserved#138", unimplementedFunc), /* 138 */ SyscallDesc("setfsuid", unimplementedFunc), /* 139 */ SyscallDesc("setfsgid", unimplementedFunc), - /* 140 */ SyscallDesc("llseek", unimplementedFunc), + /* 140 */ SyscallDesc("llseek", _llseekFunc), /* 141 */ SyscallDesc("getdents", unimplementedFunc), /* 142 */ SyscallDesc("newselect", unimplementedFunc), /* 143 */ SyscallDesc("flock", unimplementedFunc), @@ -227,18 +240,18 @@ /* 160 */ SyscallDesc("sched_get_priority_min", unimplementedFunc), /* 161 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc), /* 162 */ SyscallDesc("nanosleep", unimplementedFunc), - /* 163 */ SyscallDesc("mremap", unimplementedFunc), // ARM-specific + /* 163 */ SyscallDesc("mremap", mremapFunc), // ARM-specific /* 164 */ SyscallDesc("setresuid", unimplementedFunc), /* 165 */ SyscallDesc("getresuid", unimplementedFunc), - /* 166 */ SyscallDesc("vm862", unimplementedFunc), - /* 167 */ SyscallDesc("query_module", unimplementedFunc), + /* 166 */ SyscallDesc("unused#166", unimplementedFunc), + /* 167 */ SyscallDesc("unused#167", unimplementedFunc), /* 168 */ SyscallDesc("poll", unimplementedFunc), /* 169 */ SyscallDesc("nfsservctl", unimplementedFunc), /* 170 */ SyscallDesc("setresgid", unimplementedFunc), /* 171 */ SyscallDesc("getresgid", unimplementedFunc), /* 172 */ SyscallDesc("prctl", unimplementedFunc), /* 173 */ SyscallDesc("rt_sigreturn", unimplementedFunc), - /* 174 */ SyscallDesc("rt_sigaction", unimplementedFunc), + /* 174 */ SyscallDesc("rt_sigaction", ignoreFunc), /* 175 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), /* 176 */ SyscallDesc("rt_sigpending", unimplementedFunc), /* 177 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), @@ -247,19 +260,19 @@ /* 180 */ SyscallDesc("pread64", unimplementedFunc), /* 181 */ SyscallDesc("pwrite64", unimplementedFunc), /* 182 */ SyscallDesc("chown", unimplementedFunc), - /* 183 */ SyscallDesc("getcwd", unimplementedFunc), + /* 183 */ SyscallDesc("getcwd", getcwdFunc), /* 184 */ SyscallDesc("capget", unimplementedFunc), /* 185 */ SyscallDesc("capset", unimplementedFunc), /* 186 */ SyscallDesc("sigaltstack", unimplementedFunc), /* 187 */ SyscallDesc("sendfile", unimplementedFunc), - /* 188 */ SyscallDesc("getpmsg", unimplementedFunc), - /* 189 */ SyscallDesc("putpmsg", unimplementedFunc), + /* 188 */ SyscallDesc("unused#188", unimplementedFunc), + /* 189 */ SyscallDesc("unused#189", unimplementedFunc), /* 190 */ SyscallDesc("vfork", unimplementedFunc), - /* 191 */ SyscallDesc("getrlimit", unimplementedFunc), + /* 191 */ SyscallDesc("getrlimit", getrlimitFunc), /* 192 */ SyscallDesc("mmap2", mmapFunc), /* 193 */ SyscallDesc("truncate64", unimplementedFunc), - /* 194 */ SyscallDesc("ftruncate64", unimplementedFunc), - /* 195 */ SyscallDesc("stat64", unimplementedFunc), + /* 194 */ SyscallDesc("ftruncate64", ftruncate64Func), + /* 195 */ SyscallDesc("stat64", stat64Func), /* 196 */ SyscallDesc("lstat64", lstat64Func), /* 197 */ SyscallDesc("fstat64", fstat64Func), /* 198 */ SyscallDesc("lchown", unimplementedFunc), @@ -286,7 +299,7 @@ /* 219 */ SyscallDesc("mincore", unimplementedFunc), /* 220 */ SyscallDesc("madvise", unimplementedFunc), /* 221 */ SyscallDesc("fcntl64", fcntl64Func), - /* 222 */ SyscallDesc("tux", unimplementedFunc), + /* 222 */ SyscallDesc("unused#222", unimplementedFunc), /* 223 */ SyscallDesc("unknown#223", unimplementedFunc), /* 224 */ SyscallDesc("gettid", unimplementedFunc), /* 225 */ SyscallDesc("readahead", unimplementedFunc), @@ -312,14 +325,14 @@ /* 245 */ SyscallDesc("io_getevents", unimplementedFunc), /* 246 */ SyscallDesc("io_submit", unimplementedFunc), /* 247 */ SyscallDesc("io_cancel", unimplementedFunc), - /* 248 */ SyscallDesc("exit_group", exitFunc), + /* 248 */ SyscallDesc("exit_group", exitGroupFunc), /* 249 */ SyscallDesc("lookup_dcookie", unimplementedFunc), /* 250 */ SyscallDesc("epoll_create", unimplementedFunc), /* 251 */ SyscallDesc("epoll_ctl", unimplementedFunc), /* 252 */ SyscallDesc("epoll_wait", unimplementedFunc), /* 253 */ SyscallDesc("remap_file_pages", unimplementedFunc), - /* 254 */ SyscallDesc("set_thread_area", unimplementedFunc), - /* 255 */ SyscallDesc("get_thread_area", unimplementedFunc), + /* 254 */ SyscallDesc("unused#254", unimplementedFunc), + /* 255 */ SyscallDesc("unused#255", unimplementedFunc), /* 256 */ SyscallDesc("set_tid_address", unimplementedFunc), /* 257 */ SyscallDesc("timer_create", unimplementedFunc), /* 258 */ SyscallDesc("timer_settime", unimplementedFunc), @@ -377,7 +390,7 @@ /* 310 */ SyscallDesc("request_key", unimplementedFunc), /* 311 */ SyscallDesc("keyctl", unimplementedFunc), /* 312 */ SyscallDesc("semtimedop", unimplementedFunc), - /* 313 */ SyscallDesc("vserver", unimplementedFunc), + /* 313 */ SyscallDesc("unused#313", unimplementedFunc), /* 314 */ SyscallDesc("ioprio_set", unimplementedFunc), /* 315 */ SyscallDesc("ioprio_get", unimplementedFunc), /* 316 */ SyscallDesc("inotify_init", unimplementedFunc), @@ -411,6 +424,26 @@ /* 344 */ SyscallDesc("move_pages", unimplementedFunc), /* 345 */ SyscallDesc("getcpu", unimplementedFunc), /* 346 */ SyscallDesc("epoll_pwait", unimplementedFunc), + /* 347 */ SyscallDesc("sys_kexec_load", unimplementedFunc), + /* 348 */ SyscallDesc("sys_utimensat", unimplementedFunc), + /* 349 */ SyscallDesc("sys_signalfd", unimplementedFunc), + /* 350 */ SyscallDesc("sys_timerfd_create", unimplementedFunc), + /* 351 */ SyscallDesc("sys_eventfd", unimplementedFunc), + /* 352 */ SyscallDesc("sys_fallocate", unimplementedFunc), + /* 353 */ SyscallDesc("sys_timerfd_settime", unimplementedFunc), + /* 354 */ SyscallDesc("sys_timerfd_gettime", unimplementedFunc), + /* 355 */ SyscallDesc("sys_signalfd4", unimplementedFunc), + /* 356 */ SyscallDesc("sys_eventfd2", unimplementedFunc), + /* 357 */ SyscallDesc("sys_epoll_create1", unimplementedFunc), + /* 358 */ SyscallDesc("sys_dup3", unimplementedFunc), + /* 359 */ SyscallDesc("sys_pipe2", unimplementedFunc), + /* 360 */ SyscallDesc("sys_inotify_init1", unimplementedFunc), + /* 361 */ SyscallDesc("sys_preadv", unimplementedFunc), + /* 362 */ SyscallDesc("sys_pwritev", unimplementedFunc), + /* 363 */ SyscallDesc("sys_rt_tgsigqueueinfo", unimplementedFunc), + /* 364 */ SyscallDesc("sys_perf_event_open", unimplementedFunc), + /* 365 */ SyscallDesc("sys_recvmmsg", unimplementedFunc), + }; /// Target set_tls() handler. @@ -435,8 +468,8 @@ }; ArmLinuxProcess::ArmLinuxProcess(LiveProcessParams * params, - ObjectFile *objFile) - : ArmLiveProcess(params, objFile), + ObjectFile *objFile, ObjectFile::Arch _arch) + : ArmLiveProcess(params, objFile, _arch), Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)), Num_Priv_Syscall_Descs(sizeof(privSyscallDescs) / sizeof(SyscallDesc)) { } @@ -485,6 +518,7 @@ } // We don't have barriers, so just return. + // @todo Add a barrrier in this code uint8_t memory_barrier[] = { 0x0e, 0xf0, 0xa0, 0xe1 //usr_ret lr @@ -494,6 +528,7 @@ // This -should- be atomic, but I don't think all the support that we'd // need is implemented. There should also be memory barriers around it. + // @todo replace this with ldrex/strex and dmb uint8_t cmpxchg[] = { 0x00, 0x30, 0x92, 0xe5, //ldr r3, [r2] diff -r 84bd4089958b src/arch/arm/miscregs.hh --- a/src/arch/arm/miscregs.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/miscregs.hh Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,15 @@ -/* +/* Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2009 The Regents of The University of Michigan * All rights reserved. * @@ -50,11 +61,12 @@ COND_GT, // 12 COND_LE, // 13 COND_AL, // 14 - COND_NV // 15 + COND_UC // 15 }; enum MiscRegIndex { MISCREG_CPSR = 0, + MISCREG_ITSTATE, MISCREG_SPSR, MISCREG_SPSR_FIQ, MISCREG_SPSR_IRQ, @@ -66,13 +78,149 @@ MISCREG_FPSID, MISCREG_FPSCR, MISCREG_FPEXC, - MISCREG_SCTLR, + MISCREG_MVFR0, + MISCREG_MVFR1, + MISCREG_SCTLR_RST, + MISCREG_SEV_MAILBOX, + + // CP15 registers + MISCREG_CP15_START, + MISCREG_SCTLR = MISCREG_CP15_START, + MISCREG_DCCISW, + MISCREG_DCCIMVAC, + MISCREG_DCCMVAC, + MISCREG_CONTEXTIDR, + MISCREG_TPIDRURW, + MISCREG_TPIDRURO, + MISCREG_TPIDRPRW, + MISCREG_CP15ISB, + MISCREG_CP15DSB, + MISCREG_CP15DMB, + MISCREG_CPACR, + MISCREG_CLIDR, + MISCREG_CCSIDR, + MISCREG_CSSELR, + MISCREG_ICIALLUIS, + MISCREG_ICIALLU, + MISCREG_ICIMVAU, + MISCREG_BPIMVA, + MISCREG_BPIALLIS, + MISCREG_BPIALL, + MISCREG_MIDR, + MISCREG_TTBR0, + MISCREG_TTBR1, + MISCREG_TLBTR, + MISCREG_DACR, + MISCREG_TLBIALLIS, + MISCREG_TLBIMVAIS, + MISCREG_TLBIASIDIS, + MISCREG_TLBIMVAAIS, + MISCREG_ITLBIALL, + MISCREG_ITLBIMVA, + MISCREG_ITLBIASID, + MISCREG_DTLBIALL, + MISCREG_DTLBIMVA, + MISCREG_DTLBIASID, + MISCREG_TLBIALL, + MISCREG_TLBIMVA, + MISCREG_TLBIASID, + MISCREG_TLBIMVAA, + MISCREG_DFSR, + MISCREG_IFSR, + MISCREG_DFAR, + MISCREG_IFAR, + MISCREG_MPIDR, + MISCREG_PRRR, + MISCREG_NMRR, + MISCREG_TTBCR, + MISCREG_ID_PFR0, + MISCREG_CTR, + MISCREG_SCR, + MISCREG_SDER, + MISCREG_PAR, + MISCREG_V2PCWPR, + MISCREG_V2PCWPW, + MISCREG_V2PCWUR, + MISCREG_V2PCWUW, + MISCREG_V2POWPR, + MISCREG_V2POWPW, + MISCREG_V2POWUR, + MISCREG_V2POWUW, + MISCREG_CP15_UNIMP_START, + MISCREG_TCMTR = MISCREG_CP15_UNIMP_START, + MISCREG_ID_PFR1, + MISCREG_ID_DFR0, + MISCREG_ID_AFR0, + MISCREG_ID_MMFR0, + MISCREG_ID_MMFR1, + MISCREG_ID_MMFR2, + MISCREG_ID_MMFR3, + MISCREG_ID_ISAR0, + MISCREG_ID_ISAR1, + MISCREG_ID_ISAR2, + MISCREG_ID_ISAR3, + MISCREG_ID_ISAR4, + MISCREG_ID_ISAR5, + MISCREG_AIDR, + MISCREG_ACTLR, + MISCREG_ADFSR, + MISCREG_AIFSR, + MISCREG_DCIMVAC, + MISCREG_DCISW, + MISCREG_MCCSW, + MISCREG_DCCMVAU, + MISCREG_NSACR, + MISCREG_VBAR, + MISCREG_MVBAR, + MISCREG_ISR, + MISCREG_FCEIDR, + + + MISCREG_CP15_END, + + // Dummy indices + MISCREG_NOP = MISCREG_CP15_END, + MISCREG_RAZ, + NUM_MISCREGS }; + MiscRegIndex decodeCP15Reg(unsigned crn, unsigned opc1, + unsigned crm, unsigned opc2); + const char * const miscRegName[NUM_MISCREGS] = { - "cpsr", "spsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_und", - "spsr_abt", "fpsr", "fpsid", "fpscr", "fpexc", "sctlr" + "cpsr", "itstate", "spsr", "spsr_fiq", "spsr_irq", "spsr_svc", + "spsr_mon", "spsr_und", "spsr_abt", + "fpsr", "fpsid", "fpscr", "fpexc", "mvfr0", "mvfr1", + "sctlr_rst", "sev_mailbox", + "sctlr", "dccisw", "dccimvac", "dccmvac", + "contextidr", "tpidrurw", "tpidruro", "tpidrprw", + "cp15isb", "cp15dsb", "cp15dmb", "cpacr", + "clidr", "ccsidr", "csselr", + "icialluis", "iciallu", "icimvau", + "bpimva", "bpiallis", "bpiall", + "midr", "ttbr0", "ttbr1", "tlbtr", "dacr", + "tlbiallis", "tlbimvais", "tlbiasidis", "tlbimvaais", + "itlbiall", "itlbimva", "itlbiasid", + "dtlbiall", "dtlbimva", "dtlbiasid", + "tlbiall", "tlbimva", "tlbiasid", "tlbimvaa", + "dfsr", "ifsr", "dfar", "ifar", "mpidr", + "prrr", "nmrr", "ttbcr", "id_pfr0", "ctr", + "scr", "sder", "par", + "v2pcwpr", "v2pcwpw", "v2pcwur", "v2pcwuw", + "v2powpr", "v2powpw", "v2powur", "v2powuw", + // Unimplemented below + "tcmtr", + "id_pfr1", "id_dfr0", "id_afr0", + "id_mmfr0", "id_mmfr1", "id_mmfr2", "id_mmfr3", + "id_isar0", "id_isar1", "id_isar2", "id_isar3", "id_isar4", "id_isar5", + "aidr", "actlr", + "adfsr", "aifsr", + "dcimvac", "dcisw", "mccsw", + "dccmvau", + "nsacr", + "vbar", "mvbar", "isr", "fceidr", + "nop", "raz" }; BitUnion32(CPSR) @@ -93,34 +241,163 @@ Bitfield<4, 0> mode; EndBitUnion(CPSR) + BitUnion8(ITSTATE) + Bitfield<7, 4> cond; + Bitfield<3, 0> mask; + // Bitfields for moving to/from CPSR + Bitfield<7, 2> top6; + Bitfield<1, 0> bottom2; + EndBitUnion(ITSTATE) + // This mask selects bits of the CPSR that actually go in the CondCodes // integer register to allow renaming. static const uint32_t CondCodesMask = 0xF80F0000; BitUnion32(SCTLR) + Bitfield<31> ie; // Instruction endianness Bitfield<30> te; // Thumb Exception Enable Bitfield<29> afe; // Access flag enable Bitfield<28> tre; // TEX Remap bit Bitfield<27> nmfi;// Non-maskable fast interrupts enable Bitfield<25> ee; // Exception Endianness bit Bitfield<24> ve; // Interrupt vectors enable - Bitfield<23> rao1;// Read as one + Bitfield<23> xp; // Extended page table enable bit Bitfield<22> u; // Alignment (now unused) Bitfield<21> fi; // Fast interrupts configuration enable + Bitfield<19> dz; // Divide by Zero fault enable bit Bitfield<18> rao2;// Read as one - Bitfield<17> ha; // Hardware access flag enable + Bitfield<17> br; // Background region bit Bitfield<16> rao3;// Read as one Bitfield<14> rr; // Round robin cache replacement Bitfield<13> v; // Base address for exception vectors Bitfield<12> i; // instruction cache enable Bitfield<11> z; // branch prediction enable bit Bitfield<10> sw; // Enable swp/swpb + Bitfield<9,8> rs; // deprecated protection bits Bitfield<6,3> rao4;// Read as one Bitfield<7> b; // Endianness support (unused) Bitfield<2> c; // Cache enable bit Bitfield<1> a; // Alignment fault checking Bitfield<0> m; // MMU enable bit EndBitUnion(SCTLR) + + BitUnion32(CPACR) + Bitfield<1, 0> cp0; + Bitfield<3, 2> cp1; + Bitfield<5, 4> cp2; + Bitfield<7, 6> cp3; + Bitfield<9, 8> cp4; + Bitfield<11, 10> cp5; + Bitfield<13, 12> cp6; + Bitfield<15, 14> cp7; + Bitfield<17, 16> cp8; + Bitfield<19, 18> cp9; + Bitfield<21, 20> cp10; + Bitfield<23, 22> cp11; + Bitfield<25, 24> cp12; + Bitfield<27, 26> cp13; + Bitfield<30> d32dis; + Bitfield<31> asedis; + EndBitUnion(CPACR) + + BitUnion32(FSR) + Bitfield<3, 0> fsLow; + Bitfield<7, 4> domain; + Bitfield<10> fsHigh; + Bitfield<11> wnr; + Bitfield<12> ext; + EndBitUnion(FSR) + + BitUnion32(FPSCR) + Bitfield<0> ioc; + Bitfield<1> dzc; + Bitfield<2> ofc; + Bitfield<3> ufc; + Bitfield<4> ixc; + Bitfield<7> idc; + Bitfield<8> ioe; + Bitfield<9> dze; + Bitfield<10> ofe; + Bitfield<11> ufe; + Bitfield<12> ixe; + Bitfield<15> ide; + Bitfield<18, 16> len; + Bitfield<21, 20> stride; + Bitfield<23, 22> rMode; + Bitfield<24> fz; + Bitfield<25> dn; + Bitfield<26> ahp; + Bitfield<27> qc; + Bitfield<28> v; + Bitfield<29> c; + Bitfield<30> z; + Bitfield<31> n; + EndBitUnion(FPSCR) + + BitUnion32(MVFR0) + Bitfield<3, 0> advSimdRegisters; + Bitfield<7, 4> singlePrecision; + Bitfield<11, 8> doublePrecision; + Bitfield<15, 12> vfpExceptionTrapping; + Bitfield<19, 16> divide; + Bitfield<23, 20> squareRoot; + Bitfield<27, 24> shortVectors; + Bitfield<31, 28> roundingModes; + EndBitUnion(MVFR0) + + BitUnion32(MVFR1) + Bitfield<3, 0> flushToZero; + Bitfield<7, 4> defaultNaN; + Bitfield<11, 8> advSimdLoadStore; + Bitfield<15, 12> advSimdInteger; + Bitfield<19, 16> advSimdSinglePrecision; + Bitfield<23, 20> advSimdHalfPrecision; + Bitfield<27, 24> vfpHalfPrecision; + Bitfield<31, 28> raz; + EndBitUnion(MVFR1) + + BitUnion32(PRRR) + Bitfield<1,0> tr0; + Bitfield<3,2> tr1; + Bitfield<5,4> tr2; + Bitfield<7,6> tr3; + Bitfield<9,8> tr4; + Bitfield<11,10> tr5; + Bitfield<13,12> tr6; + Bitfield<15,14> tr7; + Bitfield<16> ds0; + Bitfield<17> ds1; + Bitfield<18> ns0; + Bitfield<19> ns1; + Bitfield<24> nos0; + Bitfield<25> nos1; + Bitfield<26> nos2; + Bitfield<27> nos3; + Bitfield<28> nos4; + Bitfield<29> nos5; + Bitfield<30> nos6; + Bitfield<31> nos7; + EndBitUnion(PRRR) + + BitUnion32(NMRR) + Bitfield<1,0> ir0; + Bitfield<3,2> ir1; + Bitfield<5,4> ir2; + Bitfield<7,6> ir3; + Bitfield<9,8> ir4; + Bitfield<11,10> ir5; + Bitfield<13,12> ir6; + Bitfield<15,14> ir7; + Bitfield<17,16> or0; + Bitfield<19,18> or1; + Bitfield<21,20> or2; + Bitfield<23,22> or3; + Bitfield<25,24> or4; + Bitfield<27,26> or5; + Bitfield<29,28> or6; + Bitfield<31,30> or7; + EndBitUnion(NMRR) + }; #endif // __ARCH_ARM_MISCREGS_HH__ diff -r 84bd4089958b src/arch/arm/miscregs.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/miscregs.cc Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Gabe Black + * Ali Saidi + */ + +#include "arch/arm/isa.hh" +#include "arch/arm/miscregs.hh" +#include "base/misc.hh" + +namespace ArmISA +{ + +MiscRegIndex +decodeCP15Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2) +{ + switch (crn) { + case 0: + switch (opc1) { + case 0: + switch (crm) { + case 0: + switch (opc2) { + case 1: + return MISCREG_CTR; + case 2: + return MISCREG_TCMTR; + case 3: + return MISCREG_TLBTR; + case 5: + return MISCREG_MPIDR; + default: + return MISCREG_MIDR; + } + break; + case 1: + switch (opc2) { + case 0: + return MISCREG_ID_PFR0; + case 1: + return MISCREG_ID_PFR1; + case 2: + return MISCREG_ID_DFR0; + case 3: + return MISCREG_ID_AFR0; + case 4: + return MISCREG_ID_MMFR0; + case 5: + return MISCREG_ID_MMFR1; + case 6: + return MISCREG_ID_MMFR2; + case 7: + return MISCREG_ID_MMFR3; + } + break; + case 2: + switch (opc2) { + case 0: + return MISCREG_ID_ISAR0; + case 1: + return MISCREG_ID_ISAR1; + case 2: + return MISCREG_ID_ISAR2; + case 3: + return MISCREG_ID_ISAR3; + case 4: + return MISCREG_ID_ISAR4; + case 5: + return MISCREG_ID_ISAR5; + case 6: + case 7: + return MISCREG_RAZ; // read as zero + } + break; + default: + return MISCREG_RAZ; // read as zero + } + break; + case 1: + if (crm == 0) { + switch (opc2) { + case 0: + return MISCREG_CCSIDR; + case 1: + return MISCREG_CLIDR; + case 7: + return MISCREG_AIDR; + } + } + break; + case 2: + if (crm == 0 && opc2 == 0) { + return MISCREG_CSSELR; + } + break; + } + break; + case 1: + if (opc1 == 0) { + if (crm == 0) { + switch (opc2) { + case 0: + return MISCREG_SCTLR; + case 1: + return MISCREG_ACTLR; + case 0x2: + return MISCREG_CPACR; + } + } else if (crm == 1) { + switch (opc2) { + case 0: + return MISCREG_SCR; + case 1: + return MISCREG_SDER; + case 2: + return MISCREG_NSACR; + } + } + } + break; + case 2: + if (opc1 == 0 && crm == 0) { + switch (opc2) { + case 0: + return MISCREG_TTBR0; + case 1: + return MISCREG_TTBR1; + case 2: + return MISCREG_TTBCR; + } + } + break; + case 3: + if (opc1 == 0 && crm == 0 && opc2 == 0) { + return MISCREG_DACR; + } + break; + case 5: + if (opc1 == 0) { + if (crm == 0) { + if (opc2 == 0) { + return MISCREG_DFSR; + } else if (opc2 == 1) { + return MISCREG_IFSR; + } + } else if (crm == 1) { + if (opc2 == 0) { + return MISCREG_ADFSR; + } else if (opc2 == 1) { + return MISCREG_AIFSR; + } + } + } + break; + case 6: + if (opc1 == 0 && crm == 0) { + switch (opc2) { + case 0: + return MISCREG_DFAR; + case 2: + return MISCREG_IFAR; + } + } + break; + case 7: + if (opc1 == 0) { + switch (crm) { + case 0: + if (opc2 == 4) { + return MISCREG_NOP; + } + break; + case 1: + switch (opc2) { + case 0: + return MISCREG_ICIALLUIS; + case 6: + return MISCREG_BPIALLIS; + } + break; + case 4: + if (opc2 == 0) { + return MISCREG_PAR; + } + break; + case 5: + switch (opc2) { + case 0: + return MISCREG_ICIALLU; + case 1: + return MISCREG_ICIMVAU; + case 4: + return MISCREG_CP15ISB; + case 6: + return MISCREG_BPIALL; + case 7: + return MISCREG_BPIMVA; + } + break; + case 6: + if (opc2 == 1) { + return MISCREG_DCIMVAC; + } else if (opc2 == 2) { + return MISCREG_DCISW; + } + break; + case 8: + switch (opc2) { + case 0: + return MISCREG_V2PCWPR; + case 1: + return MISCREG_V2PCWPW; + case 2: + return MISCREG_V2PCWUR; + case 3: + return MISCREG_V2PCWUW; + case 4: + return MISCREG_V2POWPR; + case 5: + return MISCREG_V2POWPW; + case 6: + return MISCREG_V2POWUR; + case 7: + return MISCREG_V2POWUW; + } + break; + case 10: + switch (opc2) { + case 1: + return MISCREG_DCCMVAC; + case 2: + return MISCREG_MCCSW; + case 4: + return MISCREG_CP15DSB; + case 5: + return MISCREG_CP15DMB; + } + break; + case 11: + if (opc2 == 1) { + return MISCREG_DCCMVAU; + } + break; + case 13: + if (opc2 == 1) { + return MISCREG_NOP; + } + break; + case 14: + if (opc2 == 1) { + return MISCREG_DCCIMVAC; + } else if (opc2 == 2) { + return MISCREG_DCCISW; + } + break; + } + } + break; + case 8: + if (opc1 == 0) { + switch (crm) { + case 3: + switch (opc2) { + case 0: + return MISCREG_TLBIALLIS; + case 1: + return MISCREG_TLBIMVAIS; + case 2: + return MISCREG_TLBIASIDIS; + case 3: + return MISCREG_TLBIMVAAIS; + } + break; + case 5: + switch (opc2) { + case 0: + return MISCREG_ITLBIALL; + case 1: + return MISCREG_ITLBIMVA; + case 2: + return MISCREG_ITLBIASID; + } + break; + case 6: + switch (opc2) { + case 0: + return MISCREG_DTLBIALL; + case 1: + return MISCREG_DTLBIMVA; + case 2: + return MISCREG_DTLBIASID; + } + break; + case 7: + switch (opc2) { + case 0: + return MISCREG_TLBIALL; + case 1: + return MISCREG_TLBIMVA; + case 2: + return MISCREG_TLBIASID; + case 3: + return MISCREG_TLBIMVAA; + } + break; + } + } + break; + case 9: + if (opc1 >= 0 && opc1 <= 7) { + switch (crm) { + case 0: + case 1: + case 2: + case 5: + case 6: + case 7: + case 8: + //Reserved for Branch Predictor, Cache and TCM operations + case 12: + case 13: + case 14: + case 15: + // Reserved for Performance monitors + break; + } + } + break; + case 10: + if (opc1 == 0) { + // crm 0, 1, 4, and 8, with op2 0 - 7, reserved for TLB lockdown + if (crm == 2) { // TEX Remap Registers + if (opc2 == 0) { + return MISCREG_PRRR; + } else if (opc2 == 1) { + return MISCREG_NMRR; + } + } + } + break; + case 11: + if (opc1 >= 0 && opc1 <=7) { + switch (crm) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 15: + // Reserved for DMA operations for TCM access + break; + } + } + break; + case 12: + if (opc1 == 0) { + if (crm == 0) { + if (opc2 == 0) { + return MISCREG_VBAR; + } else if (opc2 == 1) { + return MISCREG_MVBAR; + } + } else if (crm == 1) { + if (opc2 == 0) { + return MISCREG_ISR; + } + } + } + break; + case 13: + if (opc1 == 0) { + if (crm == 0) { + switch (opc2) { + case 0: + return MISCREG_FCEIDR; + case 1: + return MISCREG_CONTEXTIDR; + case 2: + return MISCREG_TPIDRURW; + case 3: + return MISCREG_TPIDRURO; + case 4: + return MISCREG_TPIDRPRW; + } + } + } + break; + case 15: + // Implementation defined + break; + } + warn("Unknown miscreg: CRn: %d Opc1: %d CRm: %d opc2: %d\n", + crn, opc1, crm, opc2); + // Unrecognized register + return NUM_MISCREGS; +} + +}; diff -r 84bd4089958b src/arch/arm/nativetrace.cc --- a/src/arch/arm/nativetrace.cc Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/nativetrace.cc Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,16 @@ /* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2006 The Regents of The University of Michigan * All rights reserved. * @@ -113,6 +125,14 @@ nState.update(this); mState.update(tc); + // If a syscall just happened native trace needs another tick + if ((mState.oldState[STATE_PC] == nState.oldState[STATE_PC]) && + (mState.newState[STATE_PC] - 4 == nState.newState[STATE_PC])) { + DPRINTF(ExecRegDelta, "Advancing to match PCs after syscall\n"); + nState.update(this); + + } + bool errorFound = false; // Regular int regs for (int i = 0; i < STATE_NUMVALS; i++) { diff -r 84bd4089958b src/arch/arm/pagetable.hh --- a/src/arch/arm/pagetable.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/pagetable.hh Wed May 26 18:10:45 2010 -0500 @@ -1,7 +1,17 @@ /* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2002-2005 The Regents of The University of Michigan - * Copyright (c) 2007 MIPS Technologies, Inc. - * Copyright (c) 2007-2008 The Florida State University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,10 +37,7 @@ * (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: Nathan Binkert - * Steve Reinhardt - * Jaidev Patwardhan - * Stephen Hines + * Authors: Ali Saidi */ #ifndef __ARCH_ARM_PAGETABLE_H__ @@ -43,59 +50,158 @@ namespace ArmISA { - struct VAddr +struct VAddr +{ + VAddr(Addr a) { panic("not implemented yet."); } +}; + + +// ITB/DTB page table entry +struct PTE +{ + void serialize(std::ostream &os) { - static const int ImplBits = 43; - static const Addr ImplMask = (ULL(1) << ImplBits) - 1; - static const Addr UnImplMask = ~ImplMask; + panic("Need to implement PTE serialization\n"); + } - VAddr(Addr a) : addr(a) {} - Addr addr; - operator Addr() const { return addr; } - const VAddr &operator=(Addr a) { addr = a; return *this; } + void unserialize(Checkpoint *cp, const std::string §ion) + { + panic("Need to implement PTE serialization\n"); + } - Addr vpn() const { return (addr & ImplMask) >> PageShift; } - Addr page() const { return addr & Page_Mask; } - Addr offset() const { return addr & PageOffset; } +}; - Addr level3() const - { return ArmISA::PteAddr(addr >> PageShift); } - Addr level2() const - { return ArmISA::PteAddr(addr >> (NPtePageShift + PageShift)); } - Addr level1() const - { return ArmISA::PteAddr(addr >> (2 * NPtePageShift + PageShift)); } +struct TlbRange +{ + Addr va; + Addr size; + int contextId; + bool global; + + inline bool + operator<(const TlbRange &r2) const + { + if (!(global || r2.global)) { + if (contextId < r2.contextId) + return true; + else if (contextId > r2.contextId) + return false; + } + + if (va < r2.va) + return true; + return false; + } + + inline bool + operator==(const TlbRange &r2) const + { + return va == r2.va && + size == r2.size && + contextId == r2.contextId && + global == r2.global; + } +}; + + +// ITB/DTB table entry +struct TlbEntry +{ + public: + enum MemoryType { + StronglyOrdered, + Device, + Normal + }; + enum DomainType { + DomainNoAccess = 0, + DomainClient, + DomainReserved, + DomainManager }; - // ITB/DTB page table entry - struct PTE + // Matching variables + Addr pfn; + Addr size; // Size of this entry, == Type of TLB Rec + Addr vpn; // Virtual Page Number + uint32_t asid; // Address Space Identifier + uint8_t N; // Number of bits in pagesize + bool global; + bool valid; + + // Type of memory + bool nonCacheable; // Can we wrap this in mtype? + bool sNp; // Section descriptor + + // Memory Attributes + MemoryType mtype; + uint8_t innerAttrs; + uint8_t outerAttrs; + bool shareable; + uint32_t attributes; // Memory attributes formatted for PAR + + + // Access permissions + bool xn; // Execute Never + uint8_t ap:3; // Access permissions bits + uint8_t domain:4; // Access Domain + + TlbRange range; // For fast TLB searching + + //Construct an entry that maps to physical address addr for SE mode + TlbEntry(Addr _asn, Addr _vaddr, Addr _paddr) { - Addr Mask; // What parts of the VAddr (from bits 28..11) should be used in translation (includes Mask and MaskX from PageMask) - Addr VPN; // Virtual Page Number (/2) (Includes VPN2 + VPN2X .. bits 31..11 from EntryHi) - uint8_t asid; // Address Space ID (8 bits) // Lower 8 bits of EntryHi + pfn = _paddr >> PageShift; + size = PageBytes - 1; + asid = _asn; + global = false; + valid = true; - bool G; // Global Bit - Obtained by an *AND* of EntryLo0 and EntryLo1 G bit + vpn = _vaddr >> PageShift; - /* Contents of Entry Lo0 */ - Addr PFN0; // Physical Frame Number - Even - bool D0; // Even entry Dirty Bit - bool V0; // Even entry Valid Bit - uint8_t C0; // Cache Coherency Bits - Even + nonCacheable = sNp = false; - /* Contents of Entry Lo1 */ - Addr PFN1; // Physical Frame Number - Odd - bool D1; // Odd entry Dirty Bit - bool V1; // Odd entry Valid Bit - uint8_t C1; // Cache Coherency Bits (3 bits) + xn = 0; + ap = 0; // ??? + domain = DomainClient; //??? + } - /* The next few variables are put in as optimizations to reduce TLB lookup overheads */ - /* For a given Mask, what is the address shift amount, and what is the OffsetMask */ - int AddrShiftAmount; - int OffsetMask; + TlbEntry() + {} - bool Valid() { return (V0 | V1);}; - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); - }; + void + updateVaddr(Addr new_vaddr) + { + vpn = new_vaddr >> PageShift; + } + + Addr + pageStart() + { + return pfn << PageShift; + } + + bool + match(Addr va, uint8_t cid) + { + Addr v = vpn << N; + if (valid && va >= v && va <= v + size && (global || cid == asid)) + return true; + return false; + } + + Addr + pAddr(Addr va) + { + return (pfn << N) | (va & size); + } + + void serialize(std::ostream &os) { panic("Need to Implement\n"); } + void unserialize(Checkpoint *cp, const std::string §ion) + { panic("Need to Implement\n");} +}; + + }; #endif // __ARCH_ARM_PAGETABLE_H__ diff -r 84bd4089958b src/arch/arm/pagetable.cc --- a/src/arch/arm/pagetable.cc Tue May 25 20:15:44 2010 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2002-2005 The Regents of The University of Michigan - * Copyright (c) 2007 MIPS Technologies, Inc. - * 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: Nathan Binkert - * Steve Reinhardt - * Jaidev Patwardhan - * Stephen Hines - */ - -#include "arch/arm/pagetable.hh" -#include "sim/serialize.hh" - -namespace ArmISA -{ - void - PTE::serialize(std::ostream &os) - { - SERIALIZE_SCALAR(Mask); - SERIALIZE_SCALAR(VPN); - SERIALIZE_SCALAR(asid); - SERIALIZE_SCALAR(G); - SERIALIZE_SCALAR(PFN0); - SERIALIZE_SCALAR(D0); - SERIALIZE_SCALAR(V0); - SERIALIZE_SCALAR(C0); - SERIALIZE_SCALAR(PFN1); - SERIALIZE_SCALAR(D1); - SERIALIZE_SCALAR(V1); - SERIALIZE_SCALAR(C1); - SERIALIZE_SCALAR(AddrShiftAmount); - SERIALIZE_SCALAR(OffsetMask); - } - - void - PTE::unserialize(Checkpoint *cp, const std::string §ion) - { - UNSERIALIZE_SCALAR(Mask); - UNSERIALIZE_SCALAR(VPN); - UNSERIALIZE_SCALAR(asid); - UNSERIALIZE_SCALAR(G); - UNSERIALIZE_SCALAR(PFN0); - UNSERIALIZE_SCALAR(D0); - UNSERIALIZE_SCALAR(V0); - UNSERIALIZE_SCALAR(C0); - UNSERIALIZE_SCALAR(PFN1); - UNSERIALIZE_SCALAR(D1); - UNSERIALIZE_SCALAR(V1); - UNSERIALIZE_SCALAR(C1); - UNSERIALIZE_SCALAR(AddrShiftAmount); - UNSERIALIZE_SCALAR(OffsetMask); - } -} diff -r 84bd4089958b src/arch/arm/predecoder.hh --- a/src/arch/arm/predecoder.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/predecoder.hh Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,15 @@ -/* +/* Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2006 The Regents of The University of Michigan * Copyright (c) 2007-2008 The Florida State University * All rights reserved. @@ -34,7 +45,7 @@ #define __ARCH_ARM_PREDECODER_HH__ #include "arch/arm/types.hh" -#include "base/misc.hh" +#include "arch/arm/miscregs.hh" #include "base/types.hh" class ThreadContext; @@ -47,35 +58,42 @@ ThreadContext * tc; //The extended machine instruction being generated ExtMachInst emi; + MachInst data; + bool bigThumb; + int offset; + ITSTATE itstate; public: - Predecoder(ThreadContext * _tc) : tc(_tc) - {} + void reset() + { + bigThumb = false; + offset = 0; + emi = 0; + } + + Predecoder(ThreadContext * _tc) : + tc(_tc), data(0) + { + reset(); + } ThreadContext * getTC() { return tc; } - void setTC(ThreadContext * _tc) + void + setTC(ThreadContext * _tc) { tc = _tc; } - void process() - {} - - void reset() - {} + void advanceThumbCond(); + void process(); //Use this to give data to the predecoder. This should be used //when there is control flow. - void moreBytes(Addr pc, Addr fetchPC, MachInst inst) - { - emi = inst; - emi.sevenAndFour = bits(inst, 7) && bits(inst, 4); - emi.isMisc = (bits(inst, 24, 23) == 0x2 && bits(inst, 20) == 0); - } + void moreBytes(Addr pc, Addr fetchPC, MachInst inst); //Use this to give data to the predecoder. This should be used //when instructions are executed in order. @@ -86,18 +104,27 @@ bool needMoreBytes() { - return true; + return sizeof(MachInst) > offset; } bool extMachInstReady() { - return true; + // The only way an instruction wouldn't be ready is if this is a + // 32 bit ARM instruction that's not 32 bit aligned. + return !bigThumb; + } + + int getInstSize() + { + return (!emi.thumb || emi.bigThumb) ? 4 : 2; } //This returns a constant reference to the ExtMachInst to avoid a copy - const ExtMachInst & getExtMachInst() + ExtMachInst getExtMachInst() { - return emi; + ExtMachInst thisEmi = emi; + emi = 0; + return thisEmi; } }; }; diff -r 84bd4089958b src/arch/arm/predecoder.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/predecoder.cc Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,163 @@ +/* Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2006 The Regents of The University of Michigan + * 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: Gabe Black + */ + +#include "arch/arm/isa_traits.hh" +#include "arch/arm/predecoder.hh" +#include "base/trace.hh" +#include "cpu/thread_context.hh" + +namespace ArmISA +{ + +void +Predecoder::advanceThumbCond() +{ + uint8_t condMask = itstate.mask; + uint8_t thumbCond = itstate.cond; + DPRINTF(Predecoder, "Advancing ITSTATE from %#x, %#x.\n", + thumbCond, condMask); + condMask = condMask << 1; + uint8_t newBit = bits(condMask, 4); + condMask &= mask(4); + if (condMask == 0) { + thumbCond = 0; + } else { + replaceBits(thumbCond, 0, newBit); + } + DPRINTF(Predecoder, "Advancing ITSTATE to %#x, %#x.\n", + thumbCond, condMask); + itstate.mask = condMask; + itstate.cond = thumbCond; +} + +void +Predecoder::process() +{ + if (!emi.thumb) { + emi.instBits = data; + emi.sevenAndFour = bits(data, 7) && bits(data, 4); + emi.isMisc = (bits(data, 24, 23) == 0x2 && + bits(data, 20) == 0); + DPRINTF(Predecoder, "Arm inst: %#x.\n", (uint64_t)emi); + } else { + uint16_t word = (data >> (offset * 8)); + if (bigThumb) { + // A 32 bit thumb inst is half collected. + emi.instBits = emi.instBits | word; + bigThumb = false; + offset += 2; + DPRINTF(Predecoder, "Second half of 32 bit Thumb: %#x.\n", + emi.instBits); + if (itstate.mask) { + emi.itstate = itstate; + advanceThumbCond(); + emi.newItstate = itstate; + } + } else { + uint16_t highBits = word & 0xF800; + if (highBits == 0xE800 || highBits == 0xF000 || + highBits == 0xF800) { + // The start of a 32 bit thumb inst. + emi.bigThumb = 1; + if (offset == 0) { + // We've got the whole thing. + emi.instBits = (data >> 16) | (data << 16); + DPRINTF(Predecoder, "All of 32 bit Thumb: %#x.\n", + emi.instBits); + offset += 4; + if (itstate.mask) { + emi.itstate = itstate; + advanceThumbCond(); + emi.newItstate = itstate; + } + } else { + // We only have the first half word. + DPRINTF(Predecoder, + "First half of 32 bit Thumb.\n"); + emi.instBits = (uint32_t)word << 16; + bigThumb = true; + offset += 2; + } + } else { + // A 16 bit thumb inst. + offset += 2; + emi.instBits = word; + // Set the condition code field artificially. + emi.condCode = COND_UC; + DPRINTF(Predecoder, "16 bit Thumb: %#x.\n", + emi.instBits); + if (bits(word, 15, 8) == 0xbf && + bits(word, 3, 0) != 0x0) { + emi.itstate = itstate; + itstate = bits(word, 7, 0); + emi.newItstate = itstate; + DPRINTF(Predecoder, + "IT detected, cond = %#x, mask = %#x\n", + itstate.cond, itstate.mask); + } else if (itstate.mask) { + emi.itstate = itstate; + advanceThumbCond(); + emi.newItstate = itstate; + } + } + } + } +} + +//Use this to give data to the predecoder. This should be used +//when there is control flow. +void +Predecoder::moreBytes(Addr pc, Addr fetchPC, MachInst inst) +{ + data = inst; + offset = (fetchPC >= pc) ? 0 : pc - fetchPC; + emi.thumb = (pc & (ULL(1) << PcTBitShift)) ? 1 : 0; + FPSCR fpscr = tc->readMiscReg(MISCREG_FPSCR); + emi.fpscrLen = fpscr.len; + emi.fpscrStride = fpscr.stride; + CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); + itstate.top6 = cpsr.it2; + itstate.bottom2 = cpsr.it1; + process(); +} + +} diff -r 84bd4089958b src/arch/arm/process.hh --- a/src/arch/arm/process.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/process.hh Wed May 26 18:10:45 2010 -0500 @@ -33,6 +33,7 @@ #include #include +#include "base/loader/object_file.hh" #include "sim/process.hh" class LiveProcess; @@ -42,7 +43,9 @@ class ArmLiveProcess : public LiveProcess { protected: - ArmLiveProcess(LiveProcessParams * params, ObjectFile *objFile); + ObjectFile::Arch arch; + ArmLiveProcess(LiveProcessParams * params, ObjectFile *objFile, + ObjectFile::Arch _arch); void startup(); diff -r 84bd4089958b src/arch/arm/process.cc --- a/src/arch/arm/process.cc Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/process.cc Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,16 @@ /* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2007-2008 The Florida State University * All rights reserved. * @@ -26,6 +38,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Stephen Hines + * Ali Saidi */ #include "arch/arm/isa_traits.hh" @@ -43,8 +56,9 @@ using namespace std; using namespace ArmISA; -ArmLiveProcess::ArmLiveProcess(LiveProcessParams *params, ObjectFile *objFile) - : LiveProcess(params, objFile) +ArmLiveProcess::ArmLiveProcess(LiveProcessParams *params, ObjectFile *objFile, + ObjectFile::Arch _arch) + : LiveProcess(params, objFile), arch(_arch) { stack_base = 0xbf000000L; @@ -56,7 +70,7 @@ brk_point = roundUp(brk_point, VMPageSize); // Set up region for mmaps. For now, start at bottom of kuseg space. - mmap_start = mmap_end = 0x70000000L; + mmap_start = mmap_end = 0x40000000L; } void @@ -117,7 +131,11 @@ Arm_Edsp = 1 << 7, Arm_Java = 1 << 8, Arm_Iwmmxt = 1 << 9, - Arm_Crunch = 1 << 10 + Arm_Crunch = 1 << 10, + Arm_ThumbEE = 1 << 11, + Arm_Neon = 1 << 12, + Arm_Vfpv3 = 1 << 13, + Arm_Vfpv3d16 = 1 << 14 }; //Setup the auxilliary vectors. These will already have endian conversion. @@ -133,9 +151,13 @@ // Arm_Fpa | Arm_Vfp | Arm_Edsp | - Arm_Java | +// Arm_Java | // Arm_Iwmmxt | // Arm_Crunch | + Arm_ThumbEE | + Arm_Neon | + Arm_Vfpv3 | + Arm_Vfpv3d16 | 0; //Bits which describe the system hardware capabilities @@ -168,9 +190,13 @@ auxv.push_back(auxv_t(M5_AT_EGID, egid())); //Whether to enable "secure mode" in the executable auxv.push_back(auxv_t(M5_AT_SECURE, 0)); + + // Pointer to 16 bytes of random data + auxv.push_back(auxv_t(M5_AT_RANDOM, 0)); + //The filename of the program auxv.push_back(auxv_t(M5_AT_EXECFN, 0)); - //The string "v51" with unknown meaning + //The string "v71" -- ARM v7 architecture auxv.push_back(auxv_t(M5_AT_PLATFORM, 0)); } @@ -179,9 +205,12 @@ // A sentry NULL void pointer at the top of the stack. int sentry_size = intSize; - string platform = "v51"; + string platform = "v71"; int platform_size = platform.size() + 1; + // Bytes for AT_RANDOM above, we'll just keep them 0 + int aux_random_size = 16; // as per the specification + // The aux vectors are put on the stack in two groups. The first group are // the vectors that are generated as the elf is loaded. The second group // are the ones that were computed ahead of time and include the platform @@ -199,7 +228,7 @@ int info_block_size = sentry_size + env_data_size + arg_data_size + - aux_data_size + platform_size; + aux_data_size + platform_size + aux_random_size; //Each auxilliary vector is two 4 byte words int aux_array_size = intSize * 2 * (auxv.size() + 1); @@ -239,7 +268,8 @@ uint32_t env_data_base = aux_data_base - env_data_size; uint32_t arg_data_base = env_data_base - arg_data_size; uint32_t platform_base = arg_data_base - platform_size; - uint32_t auxv_array_base = platform_base - aux_array_size - aux_padding; + uint32_t aux_random_base = platform_base - aux_random_size; + uint32_t auxv_array_base = aux_random_base - aux_array_size - aux_padding; uint32_t envp_array_base = auxv_array_base - envp_array_size; uint32_t argv_array_base = envp_array_base - argv_array_size; uint32_t argc_base = argv_array_base - argc_size; @@ -248,6 +278,7 @@ DPRINTF(Stack, "0x%x - aux data\n", aux_data_base); DPRINTF(Stack, "0x%x - env data\n", env_data_base); DPRINTF(Stack, "0x%x - arg data\n", arg_data_base); + DPRINTF(Stack, "0x%x - random data\n", aux_random_base); DPRINTF(Stack, "0x%x - platform base\n", platform_base); DPRINTF(Stack, "0x%x - auxv array\n", auxv_array_base); DPRINTF(Stack, "0x%x - envp array\n", envp_array_base); @@ -274,6 +305,9 @@ } else if (auxv[i].a_type == M5_AT_EXECFN) { auxv[i].a_val = aux_data_base; initVirtMem->writeString(aux_data_base, filename.c_str()); + } else if (auxv[i].a_type == M5_AT_RANDOM) { + auxv[i].a_val = aux_random_base; + // Just leave the value 0, we don't want randomness } } @@ -316,6 +350,8 @@ } Addr prog_entry = objFile->entryPoint(); + if (arch == ObjectFile::Thumb) + prog_entry = (prog_entry & ~mask(1)) | (ULL(1) << PcTBitShift); tc->setPC(prog_entry); tc->setNextPC(prog_entry + sizeof(MachInst)); diff -r 84bd4089958b src/arch/arm/registers.hh --- a/src/arch/arm/registers.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/registers.hh Wed May 26 18:10:45 2010 -0500 @@ -40,7 +40,7 @@ using ArmISAInst::MaxInstSrcRegs; using ArmISAInst::MaxInstDestRegs; -typedef uint8_t RegIndex; +typedef uint16_t RegIndex; typedef uint64_t IntReg; @@ -53,7 +53,8 @@ // Constants Related to the number of registers const int NumIntArchRegs = NUM_ARCH_INTREGS; -const int NumFloatArchRegs = 16; +// The number of single precision floating point registers +const int NumFloatArchRegs = 64; const int NumFloatSpecialRegs = 5; const int NumIntRegs = NUM_INTREGS; diff -r 84bd4089958b src/arch/arm/table_walker.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/table_walker.hh Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Ali Saidi + */ + +#ifndef __ARCH_ARM_TABLE_WALKER_HH__ +#define __ARCH_ARM_TABLE_WALKER_HH__ + +#include "arch/arm/miscregs.hh" +#include "arch/arm/tlb.hh" +#include "mem/mem_object.hh" +#include "mem/request.hh" +#include "mem/request.hh" +#include "params/ArmTableWalker.hh" +#include "sim/faults.hh" +#include "sim/eventq.hh" + +class DmaPort; +class ThreadContext; + +namespace ArmISA { +class Translation; +class TLB; + +class TableWalker : public MemObject +{ + protected: + struct L1Descriptor { + /** Type of page table entry ARM DDI 0406B: B3-8*/ + enum EntryType { + Ignore, + PageTable, + Section, + Reserved + }; + + /** The raw bits of the entry */ + uint32_t data; + + /** This entry has been modified (access flag set) and needs to be + * written back to memory */ + bool _dirty; + + EntryType type() const + { + return (EntryType)(data & 0x3); + } + + /** Is the page a Supersection (16MB)?*/ + bool supersection() const + { + return bits(data, 18); + } + + /** Return the physcal address of the entry, bits in position*/ + Addr paddr() const + { + if (supersection()) + panic("Super sections not implemented\n"); + return mbits(data, 31,20); + } + + /** Return the physical frame, bits shifted right */ + Addr pfn() const + { + if (supersection()) + panic("Super sections not implemented\n"); + return bits(data, 31,20); + } + + /** Is the translation global (no asid used)? */ + bool global() const + { + return bits(data, 4); + } + + /** Is the translation not allow execution? */ + bool xn() const + { + return bits(data, 17); + } + + /** Three bit access protection flags */ + uint8_t ap() const + { + return (bits(data, 15) << 2) | bits(data,11,10); + } + + /** Domain Client/Manager: ARM DDI 0406B: B3-31 */ + uint8_t domain() const + { + return bits(data,8,5); + } + + /** Address of L2 descriptor if it exists */ + Addr l2Addr() const + { + return mbits(data, 31,10); + } + + /** Memory region attributes: ARM DDI 0406B: B3-32. + * These bits are largly ignored by M5 and only used to + * provide the illusion that the memory system cares about + * anything but cachable vs. uncachable. + */ + uint8_t texcb() const + { + return bits(data, 2) | bits(data,3) << 1 | bits(data, 14, 12) << 2; + } + + /** If the section is shareable. See texcb() comment. */ + bool shareable() const + { + return bits(data, 16); + } + + /** Set access flag that this entry has been touched. Mark + * the entry as requiring a writeback, in the future. + */ + void setAp0() + { + data |= 1 << 10; + _dirty = true; + } + + /** This entry needs to be written back to memory */ + bool dirty() const + { + return _dirty; + } + }; + + /** Level 2 page table descriptor */ + struct L2Descriptor { + + /** The raw bits of the entry. */ + uint32_t data; + + /** This entry has been modified (access flag set) and needs to be + * written back to memory */ + bool _dirty; + + /** Is the entry invalid */ + bool invalid() const + { + return bits(data, 1,0) == 0;; + } + + /** What is the size of the mapping? */ + bool large() const + { + return bits(data, 1) == 0; + } + + /** Is execution allowed on this mapping? */ + bool xn() const + { + return large() ? bits(data, 15) : bits(data, 0); + } + + /** Is the translation global (no asid used)? */ + bool global() const + { + return !bits(data, 11); + } + + /** Three bit access protection flags */ + uint8_t ap() const + { + return bits(data, 5, 4) | (bits(data, 9) << 2); + } + + /** Memory region attributes: ARM DDI 0406B: B3-32 */ + uint8_t texcb() const + { + return large() ? + (bits(data, 2) | (bits(data,3) << 1) | (bits(data, 14, 12) << 2)) : + (bits(data, 2) | (bits(data,3) << 1) | (bits(data, 8, 6) << 2)); + } + + /** Return the physical frame, bits shifted right */ + Addr pfn() const + { + return large() ? bits(data, 31, 16) : bits(data, 31, 12); + } + + /** If the section is shareable. See texcb() comment. */ + bool shareable() const + { + return bits(data, 10); + } + + /** Set access flag that this entry has been touched. Mark + * the entry as requiring a writeback, in the future. + */ + void setAp0() + { + data |= 1 << 4; + _dirty = true; + } + + /** This entry needs to be written back to memory */ + bool dirty() const + { + return _dirty; + } + + }; + + /** Port to issue translation requests from */ + DmaPort *port; + + /** TLB that is initiating these table walks */ + TLB *tlb; + + /** Thread context that we're doing the walk for */ + ThreadContext *tc; + + /** Request that is currently being serviced */ + RequestPtr req; + + /** Context ID that we're servicing the request under */ + uint8_t contextId; + + /** Translation state for delayed requests */ + TLB::Translation *transState; + + /** The fault that we are going to return */ + Fault fault; + + /** The virtual address that is being translated */ + Addr vaddr; + + /** Cached copy of the sctlr as it existed when translation began */ + SCTLR sctlr; + + /** Cached copy of the cpsr as it existed when the translation began */ + CPSR cpsr; + + /** Width of the base address held in TTRB0 */ + uint32_t N; + + /** If the access is a write */ + bool isWrite; + + /** If the access is not from user mode */ + bool isPriv; + + /** If the access is a fetch (for execution, and no-exec) must be checked?*/ + bool isFetch; + + /** If the mode is timing or atomic */ + bool timing; + + L1Descriptor l1Desc; + L2Descriptor l2Desc; + + /** Save mode for use in delayed response */ + BaseTLB::Mode mode; + + /** Whether L1/L2 descriptor response is delayed in timing mode */ + bool delayed; + + public: + typedef ArmTableWalkerParams Params; + TableWalker(const Params *p); + virtual ~TableWalker(); + + const Params * + params() const + { + return dynamic_cast(_params); + } + + virtual unsigned int drain(Event *de) { panic("write me\n"); } + virtual Port *getPort(const std::string &if_name, int idx = -1); + + Fault walk(RequestPtr req, ThreadContext *tc, uint8_t cid, TLB::Mode mode, + TLB::Translation *_trans, bool timing); + + void setTlb(TLB *_tlb) { tlb = _tlb; } + void memAttrs(ThreadContext *tc, TlbEntry &te, uint8_t texcb, bool s); + + private: + + void doL1Descriptor(); + void doL1DescriptorWrapper(); + EventWrapper doL1DescEvent; + + void doL2Descriptor(); + void doL2DescriptorWrapper(); + EventWrapper doL2DescEvent; + + +}; + + +} // namespace ArmISA + +#endif //__ARCH_ARM_TABLE_WALKER_HH__ + diff -r 84bd4089958b src/arch/arm/table_walker.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch/arm/table_walker.cc Wed May 26 18:10:45 2010 -0500 @@ -0,0 +1,577 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Ali Saidi + */ + +#include "arch/arm/faults.hh" +#include "arch/arm/table_walker.hh" +#include "arch/arm/tlb.hh" +#include "dev/io_device.hh" +#include "cpu/thread_context.hh" + + +using namespace ArmISA; + +TableWalker::TableWalker(const Params *p) + : MemObject(p), port(NULL), tlb(NULL), tc(NULL), req(NULL), + doL1DescEvent(this), doL2DescEvent(this) +{} + +TableWalker::~TableWalker() +{ + ; +} + + +unsigned int +drain(Event *de) +{ + panic("Not implemented\n"); +} + +Port* +TableWalker::getPort(const std::string &if_name, int idx) +{ + if (if_name == "port") { + if (port != NULL) + fatal("%s: port already connected to %s", + name(), port->getPeer()->name()); + System *sys = params()->sys; + Tick minb = params()->min_backoff; + Tick maxb = params()->max_backoff; + port = new DmaPort(this, sys, minb, maxb); + return port; + } + return NULL; +} + +Fault +TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _mode, + TLB::Translation *_trans, bool _timing) +{ + // Right now 1 CPU == 1 TLB == 1 TLB walker + // In the future we might want to change this as multiple + // threads/contexts could share a walker and/or a TLB + if (tc || req) + panic("Overlapping TLB walks attempted\n"); + + tc = _tc; + transState = _trans; + req = _req; + fault = NoFault; + contextId = _cid; + timing = _timing; + mode = _mode; + + /** @todo These should be cached or grabbed from cached copies in + the TLB, all these miscreg reads are expensive */ + vaddr = req->getVaddr() & ~PcModeMask; + sctlr = tc->readMiscReg(MISCREG_SCTLR); + cpsr = tc->readMiscReg(MISCREG_CPSR); + N = tc->readMiscReg(MISCREG_TTBCR); + Addr ttbr = 0; + + isFetch = (mode == TLB::Execute); + isWrite = (mode == TLB::Write); + isPriv = (cpsr.mode != MODE_USER); + + // If translation isn't enabled, we shouldn't be here + assert(sctlr.m); + + DPRINTF(TLB, "Begining table walk for address %#x, TTBCR: %#x, bits:%#x\n", + vaddr, N, mbits(vaddr, 31, 32-N)); + + if (N == 0 || !mbits(vaddr, 31, 32-N)) { + DPRINTF(TLB, " - Selecting TTBR0\n"); + ttbr = tc->readMiscReg(MISCREG_TTBR0); + } else { + DPRINTF(TLB, " - Selecting TTBR1\n"); + ttbr = tc->readMiscReg(MISCREG_TTBR1); + N = 0; + } + + Addr l1desc_addr = mbits(ttbr, 31, 14-N) | (bits(vaddr,31-N,20) << 2); + DPRINTF(TLB, " - Descriptor at address %#x\n", l1desc_addr); + + + // Trickbox address check + fault = tlb->walkTrickBoxCheck(l1desc_addr, vaddr, sizeof(uint32_t), + isFetch, isWrite, 0, true); + if (fault) { + tc = NULL; + req = NULL; + return fault; + } + + if (timing) { + port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), + &doL1DescEvent, (uint8_t*)&l1Desc.data, (Tick)0); + } else { + port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), + NULL, (uint8_t*)&l1Desc.data, (Tick)0); + doL1Descriptor(); + } + + return fault; +} + +void +TableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, uint8_t texcb, bool s) +{ + // Note: tc local variable is hiding tc class variable + DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s); + te.shareable = false; // default value + bool outer_shareable = false; + if (sctlr.tre == 0) { + switch(texcb) { + case 0: // Stongly-ordered + te.nonCacheable = true; + te.mtype = TlbEntry::StronglyOrdered; + te.shareable = true; + te.innerAttrs = 1; + te.outerAttrs = 0; + break; + case 1: // Shareable Device + te.nonCacheable = true; + te.mtype = TlbEntry::Device; + te.shareable = true; + te.innerAttrs = 3; + te.outerAttrs = 0; + break; + case 2: // Outer and Inner Write-Through, no Write-Allocate + te.mtype = TlbEntry::Normal; + te.shareable = s; + te.innerAttrs = 6; + te.outerAttrs = bits(texcb, 1, 0); + break; + case 3: // Outer and Inner Write-Back, no Write-Allocate + te.mtype = TlbEntry::Normal; + te.shareable = s; + te.innerAttrs = 7; + te.outerAttrs = bits(texcb, 1, 0); + break; + case 4: // Outer and Inner Non-cacheable + te.nonCacheable = true; + te.mtype = TlbEntry::Normal; + te.shareable = s; + te.innerAttrs = 0; + te.outerAttrs = bits(texcb, 1, 0); + break; + case 5: // Reserved + break; + case 6: // Implementation Defined + break; + case 7: // Outer and Inner Write-Back, Write-Allocate + te.mtype = TlbEntry::Normal; + te.shareable = s; + te.innerAttrs = 5; + te.outerAttrs = 1; + break; + case 8: // Non-shareable Device + te.nonCacheable = true; + te.mtype = TlbEntry::Device; + te.shareable = false; + te.innerAttrs = 3; + te.outerAttrs = 0; + break; + case 9 ... 15: // Reserved + break; + case 16 ... 31: // Cacheable Memory + te.mtype = TlbEntry::Normal; + te.shareable = s; + if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0) + te.nonCacheable = true; + te.innerAttrs = bits(texcb, 1, 0); + te.outerAttrs = bits(texcb, 3, 2); + break; + default: + panic("More than 32 states for 5 bits?\n"); + } + } else { + assert(tc); + PRRR prrr = tc->readMiscReg(MISCREG_PRRR); + NMRR nmrr = tc->readMiscReg(MISCREG_NMRR); + DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr); + uint8_t curr_tr, curr_ir, curr_or; + switch(bits(texcb, 2,0)) { + case 0: + curr_tr = prrr.tr0; + curr_ir = nmrr.ir0; + curr_or = nmrr.or0; + outer_shareable = (prrr.nos0 == 0); + break; + case 1: + curr_tr = prrr.tr1; + curr_ir = nmrr.ir1; + curr_or = nmrr.or1; + outer_shareable = (prrr.nos1 == 0); + break; + case 2: + curr_tr = prrr.tr2; + curr_ir = nmrr.ir2; + curr_or = nmrr.or2; + outer_shareable = (prrr.nos2 == 0); + break; + case 3: + curr_tr = prrr.tr3; + curr_ir = nmrr.ir3; + curr_or = nmrr.or3; + outer_shareable = (prrr.nos3 == 0); + break; + case 4: + curr_tr = prrr.tr4; + curr_ir = nmrr.ir4; + curr_or = nmrr.or4; + outer_shareable = (prrr.nos4 == 0); + break; + case 5: + curr_tr = prrr.tr5; + curr_ir = nmrr.ir5; + curr_or = nmrr.or5; + outer_shareable = (prrr.nos5 == 0); + break; + case 6: + panic("Imp defined type\n"); + case 7: + curr_tr = prrr.tr7; + curr_ir = nmrr.ir7; + curr_or = nmrr.or7; + outer_shareable = (prrr.nos7 == 0); + break; + } + + switch(curr_tr) { + case 0: + DPRINTF(TLBVerbose, "StronglyOrdered\n"); + te.mtype = TlbEntry::StronglyOrdered; + te.nonCacheable = true; + te.innerAttrs = 1; + te.outerAttrs = 0; + te.shareable = true; + break; + case 1: + DPRINTF(TLBVerbose, "Device ds1:%d ds0:%d s:%d\n", + prrr.ds1, prrr.ds0, s); + te.mtype = TlbEntry::Device; + te.nonCacheable = true; + te.innerAttrs = 3; + te.outerAttrs = 0; + if (prrr.ds1 && s) + te.shareable = true; + if (prrr.ds0 && !s) + te.shareable = true; + break; + case 2: + DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n", + prrr.ns1, prrr.ns0, s); + te.mtype = TlbEntry::Normal; + if (prrr.ns1 && s) + te.shareable = true; + if (prrr.ns0 && !s) + te.shareable = true; + //te.shareable = outer_shareable; + break; + case 3: + panic("Reserved type"); + } + + if (te.mtype == TlbEntry::Normal){ + switch(curr_ir) { + case 0: + te.nonCacheable = true; + te.innerAttrs = 0; + break; + case 1: + te.innerAttrs = 5; + break; + case 2: + te.innerAttrs = 6; + break; + case 3: + te.innerAttrs = 7; + break; + } + + switch(curr_or) { + case 0: + te.nonCacheable = true; + te.outerAttrs = 0; + break; + case 1: + te.outerAttrs = 1; + break; + case 2: + te.outerAttrs = 2; + break; + case 3: + te.outerAttrs = 3; + break; + } + } + } + + /** Formatting for Physical Address Register (PAR) + * Only including lower bits (TLB info here) + * PAR: + * PA [31:12] + * Reserved [11] + * TLB info [10:1] + * NOS [10] (Not Outer Sharable) + * NS [9] (Non-Secure) + * -- [8] (Implementation Defined) + * SH [7] (Sharable) + * Inner[6:4](Inner memory attributes) + * Outer[3:2](Outer memory attributes) + * SS [1] (SuperSection) + * F [0] (Fault, Fault Status in [6:1] if faulted) + */ + te.attributes = ( + ((outer_shareable ? 0:1) << 10) | + // TODO: NS Bit + ((te.shareable ? 1:0) << 7) | + (te.innerAttrs << 4) | + (te.outerAttrs << 2) + // TODO: Supersection bit + // TODO: Fault bit + ); + + +} + +void +TableWalker::doL1Descriptor() +{ + DPRINTF(TLB, "L1 descriptor for %#x is %#x\n", vaddr, l1Desc.data); + TlbEntry te; + + switch (l1Desc.type()) { + case L1Descriptor::Ignore: + case L1Descriptor::Reserved: + if (!delayed) { + tc = NULL; + req = NULL; + } + DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n"); + if (isFetch) + fault = new PrefetchAbort(vaddr, ArmFault::Translation0); + else + fault = new DataAbort(vaddr, NULL, isWrite, + ArmFault::Translation0); + return; + case L1Descriptor::Section: + if (sctlr.afe && bits(l1Desc.ap(), 0) == 0) { + /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is + * enabled if set, do l1.Desc.setAp0() instead of generating + * AccessFlag0 + */ + + fault = new DataAbort(vaddr, NULL, isWrite, + ArmFault::AccessFlag0); + } + + if (l1Desc.supersection()) { + panic("Haven't implemented supersections\n"); + } + te.N = 20; + te.pfn = l1Desc.pfn(); + te.size = (1<> te.N; + te.sNp = true; + te.xn = l1Desc.xn(); + te.ap = l1Desc.ap(); + te.domain = l1Desc.domain(); + te.asid = contextId; + memAttrs(tc, te, l1Desc.texcb(), l1Desc.shareable()); + + DPRINTF(TLB, "Inserting Section Descriptor into TLB\n"); + DPRINTF(TLB, " - N%d pfn:%#x size: %#x global:%d valid: %d\n", + te.N, te.pfn, te.size, te.global, te.valid); + DPRINTF(TLB, " - vpn:%#x sNp: %d xn:%d ap:%d domain: %d asid:%d\n", + te.vpn, te.sNp, te.xn, te.ap, te.domain, te.asid); + DPRINTF(TLB, " - domain from l1 desc: %d data: %#x bits:%d\n", + l1Desc.domain(), l1Desc.data, (l1Desc.data >> 5) & 0xF ); + + if (!timing) { + tc = NULL; + req = NULL; + } + tlb->insert(vaddr, te); + + return; + case L1Descriptor::PageTable: + Addr l2desc_addr; + l2desc_addr = l1Desc.l2Addr() | (bits(vaddr, 19,12) << 2); + DPRINTF(TLB, "L1 descriptor points to page table at: %#x\n", + l2desc_addr); + + // Trickbox address check + fault = tlb->walkTrickBoxCheck(l2desc_addr, vaddr, sizeof(uint32_t), + isFetch, isWrite, l1Desc.domain(), false); + if (fault) { + if (!timing) { + tc = NULL; + req = NULL; + } + return; + } + + + if (timing) { + delayed = true; + port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), + &doL2DescEvent, (uint8_t*)&l2Desc.data, 0); + } else { + port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), + NULL, (uint8_t*)&l2Desc.data, 0); + doL2Descriptor(); + } + return; + default: + panic("A new type in a 2 bit field?\n"); + } +} + +void +TableWalker::doL2Descriptor() +{ + DPRINTF(TLB, "L2 descriptor for %#x is %#x\n", vaddr, l2Desc.data); + TlbEntry te; + + if (l2Desc.invalid()) { + DPRINTF(TLB, "L2 descriptor invalid, causing fault\n"); + if (!delayed) { + tc = NULL; + req = NULL; + } + if (isFetch) + fault = new PrefetchAbort(vaddr, ArmFault::Translation1); + else + fault = new DataAbort(vaddr, l1Desc.domain(), isWrite, + ArmFault::Translation1); + return; + } + + if (sctlr.afe && bits(l2Desc.ap(), 0) == 0) { + /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled + * if set, do l2.Desc.setAp0() instead of generating AccessFlag0 + */ + + fault = new DataAbort(vaddr, NULL, isWrite, ArmFault::AccessFlag1); + } + + if (l2Desc.large()) { + te.N = 16; + te.pfn = l2Desc.pfn(); + } else { + te.N = 12; + te.pfn = l2Desc.pfn(); + } + + te.valid = true; + te.size = (1 << te.N) - 1; + te.asid = contextId; + te.sNp = false; + te.vpn = vaddr >> te.N; + te.global = l2Desc.global(); + te.xn = l2Desc.xn(); + te.ap = l2Desc.ap(); + te.domain = l1Desc.domain(); + memAttrs(tc, te, l2Desc.texcb(), l2Desc.shareable()); + + if (!delayed) { + tc = NULL; + req = NULL; + } + tlb->insert(vaddr, te); +} + +void +TableWalker::doL1DescriptorWrapper() +{ + delayed = false; + + DPRINTF(TLBVerbose, "calling doL1Descriptor\n"); + doL1Descriptor(); + + // Check if fault was generated + if (fault != NoFault) { + transState->finish(fault, req, tc, mode); + + req = NULL; + tc = NULL; + delayed = false; + } + else if (!delayed) { + DPRINTF(TLBVerbose, "calling translateTiming again\n"); + fault = tlb->translateTiming(req, tc, transState, mode); + + req = NULL; + tc = NULL; + delayed = false; + } +} + +void +TableWalker::doL2DescriptorWrapper() +{ + assert(delayed); + + DPRINTF(TLBVerbose, "calling doL2Descriptor\n"); + doL2Descriptor(); + + // Check if fault was generated + if (fault != NoFault) { + transState->finish(fault, req, tc, mode); + } + else { + DPRINTF(TLBVerbose, "calling translateTiming again\n"); + fault = tlb->translateTiming(req, tc, transState, mode); + } + + req = NULL; + tc = NULL; + delayed = false; +} + +ArmISA::TableWalker * +ArmTableWalkerParams::create() +{ + return new ArmISA::TableWalker(this); +} + diff -r 84bd4089958b src/arch/arm/tlb.hh --- a/src/arch/arm/tlb.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/tlb.hh Wed May 26 18:10:45 2010 -0500 @@ -1,7 +1,17 @@ /* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2001-2005 The Regents of The University of Michigan - * Copyright (c) 2007 MIPS Technologies, Inc. - * Copyright (c) 2007-2008 The Florida State University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,9 +37,7 @@ * (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: Nathan Binkert - * Steve Reinhardt - * Stephen Hines + * Authors: Ali Saidi */ #ifndef __ARCH_ARM_TLB_HH__ @@ -49,54 +57,47 @@ class ThreadContext; -/* ARM does not distinguish between a DTLB and an ITLB -> unified TLB - However, to maintain compatibility with other architectures, we'll - simply create an ITLB and DTLB that will point to the real TLB */ namespace ArmISA { -// WARN: This particular TLB entry is not necessarily conformed to ARM ISA -struct TlbEntry -{ - Addr _pageStart; - TlbEntry() {} - TlbEntry(Addr asn, Addr vaddr, Addr paddr) : _pageStart(paddr) {} - - void - updateVaddr(Addr new_vaddr) - { - panic("unimplemented"); - } - - Addr pageStart() - { - return _pageStart; - } - - void serialize(std::ostream &os) - { - SERIALIZE_SCALAR(_pageStart); - } - - void unserialize(Checkpoint *cp, const std::string §ion) - { - UNSERIALIZE_SCALAR(_pageStart); - } - -}; +class TableWalker; class TLB : public BaseTLB { + public: + enum ArmFlags { + AlignmentMask = 0x7, + + AlignByte = 0x0, + AlignHalfWord = 0x1, + AlignWord = 0x3, + AlignDoubleWord = 0x7, + + AllowUnaligned = 0x8, + // Priv code operating as if it wasn't + UserMode = 0x10, + // Because zero otherwise looks like a valid setting and may be used + // accidentally, this bit must be non-zero to show it was used on + // purpose. + MustBeOne = 0x20 + }; protected: typedef std::multimap PageTable; PageTable lookupTable; // Quick lookup into page table - ArmISA::PTE *table; // the Page Table + TlbEntry *table; // the Page Table int size; // TLB Size int nlu; // not last used entry (for replacement) + uint32_t _attr; // Memory attributes for last accessed TLB entry + +#if FULL_SYSTEM + TableWalker *tableWalker; +#endif + void nextnlu() { if (++nlu >= size) nlu = 0; } - ArmISA::PTE *lookup(Addr vpn, uint8_t asn) const; + TlbEntry *lookup(Addr vpn, uint8_t asn); + // Access Stats mutable Stats::Scalar read_hits; mutable Stats::Scalar read_misses; mutable Stats::Scalar read_acv; @@ -110,32 +111,70 @@ Stats::Formula invalids; Stats::Formula accesses; + public: typedef ArmTLBParams Params; TLB(const Params *p); - int probeEntry(Addr vpn,uint8_t) const; - ArmISA::PTE *getEntry(unsigned) const; virtual ~TLB(); - int smallPages; int getsize() const { return size; } - ArmISA::PTE &index(bool advance = true); - void insert(Addr vaddr, ArmISA::PTE &pte); - void insertAt(ArmISA::PTE &pte, unsigned Index, int _smallPages); + void insert(Addr vaddr, TlbEntry &pte); + + /** Reset the entire TLB */ void flushAll(); + + /** Remove any entries that match both a va and asn + * @param mva virtual address to flush + * @param asn contextid/asn to flush on match + */ + void flushMvaAsid(Addr mva, uint64_t asn); + + /** Remove any entries that match the asn + * @param asn contextid/asn to flush on match + */ + void flushAsid(uint64_t asn); + + /** Remove all entries that match the va regardless of asn + * @param mva address to flush from cache + */ + void flushMva(Addr mva); + + Fault trickBoxCheck(RequestPtr req, Mode mode, uint8_t domain, bool sNp); + Fault walkTrickBoxCheck(Addr pa, Addr va, Addr sz, bool is_exec, + bool is_write, uint8_t domain, bool sNp); + + void printTlb(); + void demapPage(Addr vaddr, uint64_t asn) { - panic("demapPage unimplemented.\n"); + flushMvaAsid(vaddr, asn); } - // static helper functions... really static bool validVirtualAddress(Addr vaddr); - static Fault checkCacheability(RequestPtr &req); + /** Accessor functions for memory attributes for last accessed TLB entry + */ + void + setAttr(uint32_t attr) + { + _attr = attr; + } + uint32_t + getAttr() const + { + return _attr; + } +#if FULL_SYSTEM + Fault translateFs(RequestPtr req, ThreadContext *tc, Mode mode, + Translation *translation, bool &delay, bool timing); +#else + Fault translateSe(RequestPtr req, ThreadContext *tc, Mode mode, + Translation *translation, bool &delay, bool timing); +#endif Fault translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode); - void translateTiming(RequestPtr req, ThreadContext *tc, + Fault translateTiming(RequestPtr req, ThreadContext *tc, Translation *translation, Mode mode); // Checkpointing diff -r 84bd4089958b src/arch/arm/tlb.cc --- a/src/arch/arm/tlb.cc Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/tlb.cc Wed May 26 18:10:45 2010 -0500 @@ -1,7 +1,17 @@ /* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2001-2005 The Regents of The University of Michigan - * Copyright (c) 2007 MIPS Technologies, Inc. - * Copyright (c) 2007-2008 The Florida State University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,10 +37,9 @@ * (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: Nathan Binkert + * Authors: Ali Saidi + * Nathan Binkert * Steve Reinhardt - * Jaidev Patwardhan - * Stephen Hines */ #include @@ -48,23 +57,25 @@ #include "params/ArmTLB.hh" #include "sim/process.hh" +#if FULL_SYSTEM +#include "arch/arm/table_walker.hh" +#endif using namespace std; using namespace ArmISA; -/////////////////////////////////////////////////////////////////////// -// -// ARM TLB -// - -#define MODE2MASK(X) (1 << (X)) - TLB::TLB(const Params *p) : BaseTLB(p), size(p->size), nlu(0) +#if FULL_SYSTEM + , tableWalker(p->walker) +#endif { - table = new ArmISA::PTE[size]; - memset(table, 0, sizeof(ArmISA::PTE[size])); - smallPages=0; + table = new TlbEntry[size]; + memset(table, 0, sizeof(TlbEntry[size])); + +#if FULL_SYSTEM + tableWalker->setTlb(this); +#endif } TLB::~TLB() @@ -73,146 +84,157 @@ delete [] table; } -// look up an entry in the TLB -ArmISA::PTE * -TLB::lookup(Addr vpn, uint8_t asn) const +TlbEntry* +TLB::lookup(Addr va, uint8_t cid) { - // assume not found... - ArmISA::PTE *retval = NULL; - PageTable::const_iterator i = lookupTable.find(vpn); - if (i != lookupTable.end()) { - while (i->first == vpn) { - int index = i->second; - ArmISA::PTE *pte = &table[index]; + // XXX This should either turn into a TlbMap or add caching - /* 1KB TLB Lookup code - from ARM ARM Volume III - Rev. 2.50 */ - Addr Mask = pte->Mask; - Addr InvMask = ~Mask; - Addr VPN = pte->VPN; - // warn("Valid: %d - %d\n",pte->V0,pte->V1); - if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid))) - { // We have a VPN + ASID Match - retval = pte; - break; - } - ++i; + TlbEntry *retval = NULL; + + // Do some kind of caching, fast indexing, anything + + int x = 0; + while (retval == NULL && x < size) { + if (table[x].match(va, cid)) { + retval = &table[x]; + if (x == nlu) + nextnlu(); + + break; } + x++; } - DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn, - retval ? "hit" : "miss", retval ? retval->PFN1 : 0); + DPRINTF(TLBVerbose, "Lookup %#x, cid %#x -> %s ppn %#x size: %#x pa: %#x ap:%d\n", + va, cid, retval ? "hit" : "miss", retval ? retval->pfn : 0, + retval ? retval->size : 0, retval ? retval->pAddr(va) : 0, + retval ? retval->ap : 0); + ; return retval; } -ArmISA::PTE* TLB::getEntry(unsigned Index) const -{ - // Make sure that Index is valid - assert(Indexfirst == vpn) { - int index = i->second; - ArmISA::PTE *pte = &table[index]; - - /* 1KB TLB Lookup code - from ARM ARM Volume III - Rev. 2.50 */ - Addr Mask = pte->Mask; - Addr InvMask = ~Mask; - Addr VPN = pte->VPN; - if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid))) - { // We have a VPN + ASID Match - retval = pte; - Ind = index; - break; - } - - ++i; - } - } - DPRINTF(Arm,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn,asn,Ind); - return Ind; -} -Fault inline -TLB::checkCacheability(RequestPtr &req) -{ - Addr VAddrUncacheable = 0xA0000000; - // In ARM, cacheability is controlled by certain bits of the virtual address - // or by the TLB entry - if((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) { - // mark request as uncacheable - req->setFlags(Request::UNCACHEABLE); - } - return NoFault; -} -void TLB::insertAt(ArmISA::PTE &pte, unsigned Index, int _smallPages) -{ - smallPages=_smallPages; - if(Index > size){ - warn("Attempted to write at index (%d) beyond TLB size (%d)",Index,size); - } else { - // Update TLB - DPRINTF(TLB,"TLB[%d]: %x %x %x %x\n",Index,pte.Mask<<11,((pte.VPN << 11) | pte.asid),((pte.PFN0 <<6) | (pte.C0 << 3) | (pte.D0 << 2) | (pte.V0 <<1) | pte.G), - ((pte.PFN1 <<6) | (pte.C1 << 3) | (pte.D1 << 2) | (pte.V1 <<1) | pte.G)); - if(table[Index].V0 == true || table[Index].V1 == true){ // Previous entry is valid - PageTable::iterator i = lookupTable.find(table[Index].VPN); - lookupTable.erase(i); - } - table[Index]=pte; - // Update fast lookup table - lookupTable.insert(make_pair(table[Index].VPN, Index)); - // int TestIndex=probeEntry(pte.VPN,pte.asid); - // warn("Inserted at: %d, Found at: %d (%x)\n",Index,TestIndex,pte.Mask); - } - -} - // insert a new TLB entry void -TLB::insert(Addr addr, ArmISA::PTE &pte) +TLB::insert(Addr addr, TlbEntry &entry) { - fatal("TLB Insert not yet implemented\n"); + DPRINTF(TLB, "Inserting entry into TLB with pfn:%#x size:%#x vpn: %#x" + " asid:%d N:%d global:%d valid:%d nc:%d sNp:%d xn:%d ap:%#x" + " domain:%#x\n", entry.pfn, entry.size, entry.vpn, entry.asid, + entry.N, entry.global, entry.valid, entry.nonCacheable, entry.sNp, + entry.xn, entry.ap, entry.domain); + + if (table[nlu].valid) + DPRINTF(TLB, " - Replacing Valid entry %#x, asn %d ppn %#x size: %#x ap:%d\n", + table[nlu].vpn << table[nlu].N, table[nlu].asid, table[nlu].pfn << table[nlu].N, + table[nlu].size, table[nlu].ap); + + // XXX Update caching, lookup table etc + table[nlu] = entry; + + // XXX Figure out how entries are generally inserted in ARM + nextnlu(); } void +TLB::printTlb() +{ + int x = 0; + TlbEntry *te; + DPRINTF(TLB, "Current TLB contents:\n"); + while (x < size) { + te = &table[x]; + if (te->valid) + DPRINTF(TLB, " * %#x, asn %d ppn %#x size: %#x ap:%d\n", + te->vpn << te->N, te->asid, te->pfn << te->N, te->size, te->ap); + x++; + } +} + + +void TLB::flushAll() { - DPRINTF(TLB, "flushAll\n"); - memset(table, 0, sizeof(ArmISA::PTE[size])); - lookupTable.clear(); + DPRINTF(TLB, "Flushing all TLB entries\n"); + int x = 0; + TlbEntry *te; + while (x < size) { + te = &table[x]; + if (te->valid) + DPRINTF(TLB, " - %#x, asn %d ppn %#x size: %#x ap:%d\n", + te->vpn << te->N, te->asid, te->pfn << te->N, te->size, te->ap); + x++; + } + + memset(table, 0, sizeof(TlbEntry[size])); nlu = 0; } + +void +TLB::flushMvaAsid(Addr mva, uint64_t asn) +{ + DPRINTF(TLB, "Flushing mva %#x asid: %#x\n", mva, asn); + TlbEntry *te; + + te = lookup(mva, asn); + while (te != NULL) { + DPRINTF(TLB, " - %#x, asn %d ppn %#x size: %#x ap:%d\n", + te->vpn << te->N, te->asid, te->pfn << te->N, te->size, te->ap); + te->valid = false; + te = lookup(mva,asn); + } +} + +void +TLB::flushAsid(uint64_t asn) +{ + DPRINTF(TLB, "Flushing all entries with asid: %#x\n", asn); + + int x = 0; + TlbEntry *te; + + while (x < size) { + te = &table[x]; + if (te->asid == asn) { + te->valid = false; + DPRINTF(TLB, " - %#x, asn %d ppn %#x size: %#x ap:%d\n", + te->vpn << te->N, te->asid, te->pfn << te->N, te->size, te->ap); + } + x++; + } +} + +void +TLB::flushMva(Addr mva) +{ + DPRINTF(TLB, "Flushing all entries with mva: %#x\n", mva); + + int x = 0; + TlbEntry *te; + + while (x < size) { + te = &table[x]; + Addr v = te->vpn << te->N; + if (mva >= v && mva < v + te->size) { + te->valid = false; + DPRINTF(TLB, " - %#x, asn %d ppn %#x size: %#x ap:%d\n", + te->vpn << te->N, te->asid, te->pfn << te->N, te->size, te->ap); + } + x++; + } +} + void TLB::serialize(ostream &os) { - SERIALIZE_SCALAR(size); - SERIALIZE_SCALAR(nlu); - - for (int i = 0; i < size; i++) { - nameOut(os, csprintf("%s.PTE%d", name(), i)); - table[i].serialize(os); - } + panic("Implement Serialize\n"); } void TLB::unserialize(Checkpoint *cp, const string §ion) { - UNSERIALIZE_SCALAR(size); - UNSERIALIZE_SCALAR(nlu); - for (int i = 0; i < size; i++) { - table[i].unserialize(cp, csprintf("%s.PTE%d", section, i)); - if (table[i].V0 || table[i].V1) { - lookupTable.insert(make_pair(table[i].VPN, i)); - } - } + panic("Need to properly unserialize TLB\n"); } void @@ -275,47 +297,268 @@ accesses = read_accesses + write_accesses; } +#if !FULL_SYSTEM +Fault +TLB::translateSe(RequestPtr req, ThreadContext *tc, Mode mode, + Translation *translation, bool &delay, bool timing) +{ + // XXX Cache misc registers and have miscreg write function inv cache + Addr vaddr = req->getVaddr() & ~PcModeMask; + SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); + uint32_t flags = req->getFlags(); + + bool is_fetch = (mode == Execute); + bool is_write = (mode == Write); + + if (!is_fetch) { + assert(flags & MustBeOne); + if (sctlr.a || !(flags & AllowUnaligned)) { + if (vaddr & flags & AlignmentMask) { + return new DataAbort(vaddr, 0, is_write, ArmFault::AlignmentFault); + } + } + } + + Addr paddr; + Process *p = tc->getProcessPtr(); + + if (!p->pTable->translate(vaddr, paddr)) + return Fault(new GenericPageTableFault(vaddr)); + req->setPaddr(paddr); + + return NoFault; +} + +#else // FULL_SYSTEM + +Fault +TLB::trickBoxCheck(RequestPtr req, Mode mode, uint8_t domain, bool sNp) +{ + return NoFault; +} + +Fault +TLB::walkTrickBoxCheck(Addr pa, Addr va, Addr sz, bool is_exec, + bool is_write, uint8_t domain, bool sNp) +{ + return NoFault; +} + +Fault +TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode, + Translation *translation, bool &delay, bool timing) +{ + // XXX Cache misc registers and have miscreg write function inv cache + Addr vaddr = req->getVaddr() & ~PcModeMask; + SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); + CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); + uint32_t flags = req->getFlags(); + + bool is_fetch = (mode == Execute); + bool is_write = (mode == Write); + bool is_priv = (cpsr.mode != MODE_USER) && !(flags & UserMode); + + DPRINTF(TLBVerbose, "CPSR is user:%d UserMode:%d\n", cpsr.mode == MODE_USER, flags + & UserMode); + if (!is_fetch) { + assert(flags & MustBeOne); + if (sctlr.a || !(flags & AllowUnaligned)) { + if (vaddr & flags & AlignmentMask) { + return new DataAbort(vaddr, 0, is_write, ArmFault::AlignmentFault); + } + } + } + + uint32_t context_id = tc->readMiscReg(MISCREG_CONTEXTIDR); + Fault fault; + + + if (!sctlr.m) { + req->setPaddr(vaddr); + if (sctlr.tre == 0) { + req->setFlags(Request::UNCACHEABLE); + } else { + PRRR prrr = tc->readMiscReg(MISCREG_PRRR); + NMRR nmrr = tc->readMiscReg(MISCREG_NMRR); + + if (nmrr.ir0 == 0 || nmrr.or0 == 0 || prrr.tr0 != 0x2) + req->setFlags(Request::UNCACHEABLE); + } + + // Set memory attributes + TlbEntry temp_te; + tableWalker->memAttrs(tc, temp_te, 0, 1); + temp_te.shareable = true; + DPRINTF(TLBVerbose, "(No MMU) setting memory attributes: shareable:\ + %d, innerAttrs: %d, outerAttrs: %d\n", temp_te.shareable, + temp_te.innerAttrs, temp_te.outerAttrs); + setAttr(temp_te.attributes); + + return trickBoxCheck(req, mode, 0, false); + } + + DPRINTF(TLBVerbose, "Translating vaddr=%#x context=%d\n", vaddr, context_id); + // Translation enabled + + TlbEntry *te = lookup(vaddr, context_id); + if (te == NULL) { + // start translation table walk, pass variables rather than + // re-retreaving in table walker for speed + DPRINTF(TLB, "TLB Miss: Starting hardware table walker for %#x(%d)\n", + vaddr, context_id); + fault = tableWalker->walk(req, tc, context_id, mode, translation, + timing); + if (timing) { + delay = true; + // for timing mode, return and wait for table walk + return fault; + } + if (fault) + return fault; + + te = lookup(vaddr, context_id); + if (!te) + printTlb(); + assert(te); + } + + // Set memory attributes + DPRINTF(TLBVerbose, + "Setting memory attributes: shareable: %d, innerAttrs: %d, \ + outerAttrs: %d\n", + te->shareable, te->innerAttrs, te->outerAttrs); + setAttr(te->attributes); + + uint32_t dacr = tc->readMiscReg(MISCREG_DACR); + switch ( (dacr >> (te->domain * 2)) & 0x3) { + case 0: + DPRINTF(TLB, "TLB Fault: Data abort on domain. DACR: %#x domain: %#x" + " write:%d sNp:%d\n", dacr, te->domain, is_write, te->sNp); + if (is_fetch) + return new PrefetchAbort(vaddr, + (te->sNp ? ArmFault::Domain0 : ArmFault::Domain1)); + else + return new DataAbort(vaddr, te->domain, is_write, + (te->sNp ? ArmFault::Domain0 : ArmFault::Domain1)); + case 1: + // Continue with permissions check + break; + case 2: + panic("UNPRED domain\n"); + case 3: + req->setPaddr(te->pAddr(vaddr)); + fault = trickBoxCheck(req, mode, te->domain, te->sNp); + if (fault) + return fault; + return NoFault; + } + + uint8_t ap = te->ap; + + if (sctlr.afe == 1) + ap |= 1; + + bool abt; + + /* if (!sctlr.xp) + ap &= 0x3; +*/ + switch (ap) { + case 0: + DPRINTF(TLB, "Access permissions 0, checking rs:%#x\n", (int)sctlr.rs); + if (!sctlr.xp) { + switch ((int)sctlr.rs) { + case 2: + abt = is_write; + break; + case 1: + abt = is_write || !is_priv; + break; + case 0: + case 3: + default: + abt = true; + break; + } + } else { + abt = true; + } + break; + case 1: + abt = !is_priv; + break; + case 2: + abt = !is_priv && is_write; + break; + case 3: + abt = false; + break; + case 4: + panic("UNPRED premissions\n"); + case 5: + abt = !is_priv || is_write; + break; + case 6: + case 7: + abt = is_write; + break; + default: + panic("Unknown permissions\n"); + } + if ((is_fetch) && (abt || te->xn)) { + DPRINTF(TLB, "TLB Fault: Prefetch abort on permission check. AP:%d priv:%d" + " write:%d sNp:%d\n", ap, is_priv, is_write, te->sNp); + return new PrefetchAbort(vaddr, + (te->sNp ? ArmFault::Permission0 : + ArmFault::Permission1)); + } else if (abt) { + DPRINTF(TLB, "TLB Fault: Data abort on permission check. AP:%d priv:%d" + " write:%d sNp:%d\n", ap, is_priv, is_write, te->sNp); + return new DataAbort(vaddr, te->domain, is_write, + (te->sNp ? ArmFault::Permission0 : + ArmFault::Permission1)); + } + + req->setPaddr(te->pAddr(vaddr)); + // Check for a trickbox generated address fault + fault = trickBoxCheck(req, mode, te->domain, te->sNp); + if (fault) + return fault; + + return NoFault; +} + +#endif + Fault TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode) { -#if !FULL_SYSTEM - Process * p = tc->getProcessPtr(); - - Fault fault = p->pTable->translate(req); - if(fault != NoFault) - return fault; - - return NoFault; + bool delay = false; + Fault fault; +#if FULL_SYSTEM + fault = translateFs(req, tc, mode, NULL, delay, false); #else - SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); - if (!sctlr.m) { - req->setPaddr(req->getVaddr()); - return NoFault; - } - panic("MMU translation not implemented\n"); - return NoFault; - - + fault = translateSe(req, tc, mode, NULL, delay, false); #endif + assert(!delay); + return fault; } -void +Fault TLB::translateTiming(RequestPtr req, ThreadContext *tc, Translation *translation, Mode mode) { assert(translation); - translation->finish(translateAtomic(req, tc, mode), req, tc, mode); -} - -ArmISA::PTE & -TLB::index(bool advance) -{ - ArmISA::PTE *pte = &table[nlu]; - - if (advance) - nextnlu(); - - return *pte; + bool delay = false; + Fault fault; +#if FULL_SYSTEM + fault = translateFs(req, tc, mode, translation, delay, true); +#else + fault = translateSe(req, tc, mode, translation, delay, true); +#endif + if (!delay) + translation->finish(fault, req, tc, mode); + return fault; } ArmISA::TLB * diff -r 84bd4089958b src/arch/arm/types.hh --- a/src/arch/arm/types.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/types.hh Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,15 @@ -/* +/* Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2007-2008 The Florida State University * All rights reserved. * @@ -39,20 +50,38 @@ typedef uint32_t MachInst; BitUnion64(ExtMachInst) + Bitfield<63, 56> newItstate; + // ITSTATE bits + Bitfield<55, 48> itstate; + Bitfield<55, 52> itstateCond; + Bitfield<51, 48> itstateMask; + + // FPSCR fields + Bitfield<41, 40> fpscrStride; + Bitfield<39, 37> fpscrLen; + + // Bitfields to select mode. + Bitfield<36> thumb; + Bitfield<35> bigThumb; + // Made up bitfields that make life easier. Bitfield<33> sevenAndFour; Bitfield<32> isMisc; + uint32_t instBits; + // All the different types of opcode fields. Bitfield<27, 25> encoding; Bitfield<25> useImm; Bitfield<24, 21> opcode; Bitfield<24, 20> mediaOpcode; Bitfield<24> opcode24; + Bitfield<24, 23> opcode24_23; Bitfield<23, 20> opcode23_20; Bitfield<23, 21> opcode23_21; Bitfield<20> opcode20; Bitfield<22> opcode22; + Bitfield<19, 16> opcode19_16; Bitfield<19> opcode19; Bitfield<18> opcode18; Bitfield<15, 12> opcode15_12; @@ -60,12 +89,14 @@ Bitfield<7, 4> miscOpcode; Bitfield<7,5> opc2; Bitfield<7> opcode7; + Bitfield<6> opcode6; Bitfield<4> opcode4; Bitfield<31, 28> condCode; Bitfield<20> sField; Bitfield<19, 16> rn; Bitfield<15, 12> rd; + Bitfield<15, 12> rt; Bitfield<11, 7> shiftSize; Bitfield<6, 5> shift; Bitfield<3, 0> rm; @@ -107,6 +138,52 @@ Bitfield<24, 20> punwl; Bitfield<7, 0> m5Func; + + // 16 bit thumb bitfields + Bitfield<15, 13> topcode15_13; + Bitfield<13, 11> topcode13_11; + Bitfield<12, 11> topcode12_11; + Bitfield<12, 10> topcode12_10; + Bitfield<11, 9> topcode11_9; + Bitfield<11, 8> topcode11_8; + Bitfield<10, 9> topcode10_9; + Bitfield<10, 8> topcode10_8; + Bitfield<9, 6> topcode9_6; + Bitfield<7> topcode7; + Bitfield<7, 6> topcode7_6; + Bitfield<7, 5> topcode7_5; + Bitfield<7, 4> topcode7_4; + Bitfield<3, 0> topcode3_0; + + // 32 bit thumb bitfields + Bitfield<28, 27> htopcode12_11; + Bitfield<26, 25> htopcode10_9; + Bitfield<25> htopcode9; + Bitfield<25, 24> htopcode9_8; + Bitfield<25, 21> htopcode9_5; + Bitfield<25, 20> htopcode9_4; + Bitfield<24> htopcode8; + Bitfield<24, 23> htopcode8_7; + Bitfield<24, 22> htopcode8_6; + Bitfield<24, 21> htopcode8_5; + Bitfield<23> htopcode7; + Bitfield<23, 21> htopcode7_5; + Bitfield<22> htopcode6; + Bitfield<22, 21> htopcode6_5; + Bitfield<21, 20> htopcode5_4; + Bitfield<20> htopcode4; + + Bitfield<19, 16> htrn; + Bitfield<20> hts; + + Bitfield<15> ltopcode15; + Bitfield<11, 8> ltopcode11_8; + Bitfield<7, 6> ltopcode7_6; + Bitfield<7, 4> ltopcode7_4; + Bitfield<4> ltopcode4; + + Bitfield<11, 8> ltrd; + Bitfield<11, 8> ltcoproc; EndBitUnion(ExtMachInst) // Shift types for ARM instructions @@ -166,6 +243,24 @@ MODE_SYSTEM = 31 }; + static inline bool + badMode(OperatingMode mode) + { + switch (mode) { + case MODE_USER: + case MODE_FIQ: + case MODE_IRQ: + case MODE_SVC: + case MODE_MON: + case MODE_ABORT: + case MODE_UNDEFINED: + case MODE_SYSTEM: + return false; + default: + return true; + } + } + struct CoreSpecific { // Empty for now on the ARM }; diff -r 84bd4089958b src/arch/arm/utility.hh --- a/src/arch/arm/utility.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/utility.hh Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,15 @@ -/* +/* Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2003-2005 The Regents of The University of Michigan * Copyright (c) 2007-2008 The Florida State University * All rights reserved. @@ -36,6 +47,7 @@ #include "arch/arm/miscregs.hh" #include "arch/arm/types.hh" #include "base/hashmap.hh" +#include "base/trace.hh" #include "base/types.hh" #include "cpu/thread_context.hh" @@ -70,7 +82,7 @@ case COND_GT: return !(cpsr.n ^ cpsr.v || cpsr.z); case COND_LE: return (cpsr.n ^ cpsr.v || cpsr.z); case COND_AL: return true; - case COND_NV: return false; + case COND_UC: return true; default: panic("Unhandled predicate condition: %d\n", code); } diff -r 84bd4089958b src/arch/arm/utility.cc --- a/src/arch/arm/utility.cc Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/arm/utility.cc Wed May 26 18:10:45 2010 -0500 @@ -2,6 +2,15 @@ * Copyright (c) 2009 ARM Limited * All rights reserved. * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * 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 diff -r 84bd4089958b src/arch/isa_parser.py --- a/src/arch/isa_parser.py Tue May 25 20:15:44 2010 -0700 +++ b/src/arch/isa_parser.py Wed May 26 18:10:45 2010 -0500 @@ -388,12 +388,14 @@ type (e.g., "32-bit integer register").''' def buildReadCode(self, func = None): - code = self.read_code % {"name": self.base_name, - "func": func, - "op_idx": self.src_reg_idx, - "reg_idx": self.reg_spec, - "size": self.size, - "ctype": self.ctype} + subst_dict = {"name": self.base_name, + "func": func, + "reg_idx": self.reg_spec, + "size": self.size, + "ctype": self.ctype} + if hasattr(self, 'src_reg_idx'): + subst_dict['op_idx'] = self.src_reg_idx + code = self.read_code % subst_dict if self.size != self.dflt_size: return '%s = bits(%s, %d, 0);\n' % \ (self.base_name, code, self.size-1) @@ -406,13 +408,15 @@ final_val = 'sext<%d>(%s)' % (self.size, self.base_name) else: final_val = self.base_name - code = self.write_code % {"name": self.base_name, - "func": func, - "op_idx": self.dest_reg_idx, - "reg_idx": self.reg_spec, - "size": self.size, - "ctype": self.ctype, - "final_val": final_val} + subst_dict = {"name": self.base_name, + "func": func, + "reg_idx": self.reg_spec, + "size": self.size, + "ctype": self.ctype, + "final_val": final_val} + if hasattr(self, 'dest_reg_idx'): + subst_dict['op_idx'] = self.dest_reg_idx + code = self.write_code % subst_dict return ''' { %s final_val = %s; diff -r 84bd4089958b src/base/loader/elf_object.cc --- a/src/base/loader/elf_object.cc Tue May 25 20:15:44 2010 -0700 +++ b/src/base/loader/elf_object.cc Wed May 26 18:10:45 2010 -0500 @@ -34,6 +34,7 @@ #include "gelf.h" +#include "base/bitfield.hh" #include "base/loader/elf_object.hh" #include "base/loader/symtab.hh" #include "base/misc.hh" @@ -96,7 +97,11 @@ } else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) { arch = ObjectFile::Alpha; } else if (ehdr.e_machine == EM_ARM) { - arch = ObjectFile::Arm; + if (bits(ehdr.e_entry, 0)) { + arch = ObjectFile::Thumb; + } else { + arch = ObjectFile::Arm; + } } else if (ehdr.e_machine == EM_PPC && ehdr.e_ident[EI_CLASS] == ELFCLASS32) { if (ehdr.e_ident[EI_DATA] == ELFDATA2MSB) { diff -r 84bd4089958b src/base/loader/object_file.hh --- a/src/base/loader/object_file.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/base/loader/object_file.hh Wed May 26 18:10:45 2010 -0500 @@ -53,6 +53,7 @@ X86_64, I386, Arm, + Thumb, Power }; diff -r 84bd4089958b src/cpu/BaseCPU.py --- a/src/cpu/BaseCPU.py Tue May 25 20:15:44 2010 -0700 +++ b/src/cpu/BaseCPU.py Wed May 26 18:10:45 2010 -0500 @@ -114,7 +114,6 @@ interrupts = Param.MipsInterrupts( MipsInterrupts(), "Interrupt Controller") elif buildEnv['TARGET_ISA'] == 'arm': - UnifiedTLB = Param.Bool(True, "Is this a Unified TLB?") dtb = Param.ArmTLB(ArmTLB(), "Data TLB") itb = Param.ArmTLB(ArmTLB(), "Instruction TLB") if buildEnv['FULL_SYSTEM']: @@ -158,6 +157,10 @@ "interrupts.pio", "interrupts.int_port"] + if buildEnv['TARGET_ISA'] == 'arm' and buildEnv['FULL_SYSTEM']: + _mem_ports = ["itb.walker.port", + "dtb.walker.port"] + def connectMemPorts(self, bus): for p in self._mem_ports: if p != 'physmem_port': @@ -170,8 +173,9 @@ self.icache_port = ic.cpu_side self.dcache_port = dc.cpu_side self._mem_ports = ['icache.mem_side', 'dcache.mem_side'] - if buildEnv['TARGET_ISA'] == 'x86' and buildEnv['FULL_SYSTEM']: - self._mem_ports += ["itb.walker_port", "dtb.walker_port"] + if buildEnv['FULL_SYSTEM']: + if buildEnv['TARGET_ISA'] in ['x86', 'arm']: + self._mem_ports += ["itb.walker.port", "dtb.walker.port"] def addTwoLevelCacheHierarchy(self, ic, dc, l2c): self.addPrivateSplitL1Caches(ic, dc) diff -r 84bd4089958b src/cpu/exetrace.cc --- a/src/cpu/exetrace.cc Tue May 25 20:15:44 2010 -0700 +++ b/src/cpu/exetrace.cc Wed May 26 18:10:45 2010 -0500 @@ -33,6 +33,7 @@ #include +#include "arch/isa_traits.hh" #include "base/loader/symtab.hh" #include "cpu/base.hh" #include "cpu/exetrace.hh" @@ -70,18 +71,22 @@ std::string sym_str; Addr sym_addr; + Addr cur_pc = PC; +#if THE_ISA == ARM_ISA + cur_pc &= ~PcModeMask; +#endif if (debugSymbolTable && IsOn(ExecSymbol) #if FULL_SYSTEM && !inUserMode(thread) #endif - && debugSymbolTable->findNearestSymbol(PC, sym_str, sym_addr)) { - if (PC != sym_addr) - sym_str += csprintf("+%d", PC - sym_addr); + && debugSymbolTable->findNearestSymbol(cur_pc, sym_str, sym_addr)) { + if (cur_pc != sym_addr) + sym_str += csprintf("+%d",cur_pc - sym_addr); outs << "@" << sym_str; } else { - outs << "0x" << hex << PC; + outs << "0x" << hex << cur_pc; } if (inst->isMicroop()) { @@ -97,7 +102,7 @@ // outs << setw(26) << left; - outs << inst->disassemble(PC, debugSymbolTable); + outs << inst->disassemble(cur_pc, debugSymbolTable); if (ran) { outs << " : "; diff -r 84bd4089958b src/cpu/simple/base.cc --- a/src/cpu/simple/base.cc Tue May 25 20:15:44 2010 -0700 +++ b/src/cpu/simple/base.cc Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,16 @@ /* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2002-2005 The Regents of The University of Michigan * All rights reserved. * @@ -345,9 +357,10 @@ Fault interrupt = interrupts->getInterrupt(tc); if (interrupt != NoFault) { - predecoder.reset(); + fetchOffset = 0; interrupts->updateIntrInfo(tc); interrupt->invoke(tc); + predecoder.reset(); } } #endif @@ -410,7 +423,7 @@ //If an instruction is ready, decode it. Otherwise, we'll have to //fetch beyond the MachInst at the current pc. if (predecoder.extMachInstReady()) { -#if THE_ISA == X86_ISA +#if THE_ISA == X86_ISA || THE_ISA == ARM_ISA thread->setNextPC(thread->readPC() + predecoder.getInstSize()); #endif // X86_ISA stayAtPC = false; @@ -495,8 +508,8 @@ fetchOffset = 0; if (fault != NoFault) { curMacroStaticInst = StaticInst::nullStaticInstPtr; + fault->invoke(tc); predecoder.reset(); - fault->invoke(tc); } else { //If we're at the last micro op for this instruction if (curStaticInst && curStaticInst->isLastMicroop()) { diff -r 84bd4089958b src/cpu/simple_thread.hh --- a/src/cpu/simple_thread.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/cpu/simple_thread.hh Wed May 26 18:10:45 2010 -0500 @@ -254,6 +254,7 @@ PC = nextPC = nextNPC = 0; memset(intRegs, 0, sizeof(intRegs)); memset(floatRegs.i, 0, sizeof(floatRegs.i)); + isa.clear(); } // @@ -272,14 +273,20 @@ { int flatIndex = isa.flattenFloatIndex(reg_idx); assert(flatIndex < TheISA::NumFloatRegs); - return floatRegs.f[flatIndex]; + FloatReg regVal = floatRegs.f[flatIndex]; + DPRINTF(FloatRegs, "Reading float reg %d as %f, %#x.\n", + reg_idx, regVal, floatRegs.i[flatIndex]); + return regVal; } FloatRegBits readFloatRegBits(int reg_idx) { int flatIndex = isa.flattenFloatIndex(reg_idx); assert(flatIndex < TheISA::NumFloatRegs); - return floatRegs.i[flatIndex]; + FloatRegBits regVal = floatRegs.i[flatIndex]; + DPRINTF(FloatRegs, "Reading float reg %d bits as %#x, %f.\n", + reg_idx, regVal, floatRegs.f[flatIndex]); + return regVal; } void setIntReg(int reg_idx, uint64_t val) @@ -295,6 +302,8 @@ int flatIndex = isa.flattenFloatIndex(reg_idx); assert(flatIndex < TheISA::NumFloatRegs); floatRegs.f[flatIndex] = val; + DPRINTF(FloatRegs, "Setting float reg %d to %f, %#x.\n", + reg_idx, val, floatRegs.i[flatIndex]); } void setFloatRegBits(int reg_idx, FloatRegBits val) @@ -302,6 +311,8 @@ int flatIndex = isa.flattenFloatIndex(reg_idx); assert(flatIndex < TheISA::NumFloatRegs); floatRegs.i[flatIndex] = val; + DPRINTF(FloatRegs, "Setting float reg %d bits to %#x, %#f.\n", + reg_idx, val, floatRegs.f[flatIndex]); } uint64_t readPC() diff -r 84bd4089958b src/dev/arm/SConscript --- a/src/dev/arm/SConscript Tue May 25 20:15:44 2010 -0700 +++ b/src/dev/arm/SConscript Wed May 26 18:10:45 2010 -0500 @@ -3,6 +3,15 @@ # Copyright (c) 2009 ARM Limited # All rights reserved. # +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# # 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 diff -r 84bd4089958b src/dev/arm/Versatile.py --- a/src/dev/arm/Versatile.py Tue May 25 20:15:44 2010 -0700 +++ b/src/dev/arm/Versatile.py Wed May 26 18:10:45 2010 -0500 @@ -1,7 +1,18 @@ -# Copyright (c) 2006-2007 The Regents of The University of Michigan # Copyright (c) 2009 ARM Limited # All rights reserved. # +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +##Copyright (c) 2006-2007 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 diff -r 84bd4089958b src/dev/arm/versatile.hh --- a/src/dev/arm/versatile.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/dev/arm/versatile.hh Wed May 26 18:10:45 2010 -0500 @@ -1,6 +1,16 @@ -/* +/* Copyright (c) 2009 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2004-2005 The Regents of The University of Michigan - * Copyright (c) 2009 ARM Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -r 84bd4089958b src/dev/arm/versatile.cc --- a/src/dev/arm/versatile.cc Tue May 25 20:15:44 2010 -0700 +++ b/src/dev/arm/versatile.cc Wed May 26 18:10:45 2010 -0500 @@ -1,6 +1,17 @@ /* + * Copyright (c) 2009 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2004-2005 The Regents of The University of Michigan - * Copyright (c) 2009 ARM Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -r 84bd4089958b src/dev/copy_engine.cc --- a/src/dev/copy_engine.cc Tue May 25 20:15:44 2010 -0700 +++ b/src/dev/copy_engine.cc Wed May 26 18:10:45 2010 -0500 @@ -110,7 +110,8 @@ { Port *peer; - cePort = new DmaPort(ce, ce->sys); + cePort = new DmaPort(ce, ce->sys, ce->params()->min_backoff_delay, + ce->params()->max_backoff_delay); peer = ce->dmaPort->getPeer()->getOwner()->getPort(""); peer->setPeer(cePort); cePort->setPeer(peer); diff -r 84bd4089958b src/dev/io_device.hh --- a/src/dev/io_device.hh Tue May 25 20:15:44 2010 -0700 +++ b/src/dev/io_device.hh Wed May 26 18:10:45 2010 -0500 @@ -92,13 +92,14 @@ /** Amount to delay completion of dma by */ Tick delay; + DmaReqState(Event *ce, Port *p, Addr tb, Tick _delay) : completionEvent(ce), outPort(p), totBytes(tb), numBytes(0), delay(_delay) {} }; - DmaDevice *device; + MemObject *device; std::list transmitList; /** The system that device/port are in. This is used to select which mode @@ -119,6 +120,12 @@ * recived, decreases as responses are recived. */ Tick backoffTime; + /** Minimum time that device should back off for after failed sendTiming */ + Tick minBackoffDelay; + + /** Maximum time that device should back off for after failed sendTiming */ + Tick maxBackoffDelay; + /** If the port is currently waiting for a retry before it can send whatever * it is that it's sending. */ bool inRetry; @@ -145,7 +152,7 @@ EventWrapper backoffEvent; public: - DmaPort(DmaDevice *dev, System *s); + DmaPort(MemObject *dev, System *s, Tick min_backoff, Tick max_backoff); void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, uint8_t *data, Tick delay); @@ -256,8 +263,6 @@ { protected: DmaPort *dmaPort; - Tick minBackoffDelay; - Tick maxBackoffDelay; public: typedef DmaDeviceParams Params; @@ -298,7 +303,8 @@ if (dmaPort != NULL) fatal("%s: dma port already connected to %s", name(), dmaPort->getPeer()->name()); - dmaPort = new DmaPort(this, sys); + dmaPort = new DmaPort(this, sys, params()->min_backoff_delay, + params()->max_backoff_delay); return dmaPort; } else return NULL; diff -r 84bd4089958b src/dev/io_device.cc --- a/src/dev/io_device.cc Tue May 25 20:15:44 2010 -0700 +++ b/src/dev/io_device.cc Wed May 26 18:10:45 2010 -0500 @@ -99,10 +99,11 @@ } -DmaPort::DmaPort(DmaDevice *dev, System *s) +DmaPort::DmaPort(MemObject *dev, System *s, Tick min_backoff, Tick max_backoff) : Port(dev->name() + "-dmaport", dev), device(dev), sys(s), pendingCount(0), actionInProgress(0), drainEvent(NULL), - backoffTime(0), inRetry(false), backoffEvent(this) + backoffTime(0), minBackoffDelay(min_backoff), + maxBackoffDelay(max_backoff), inRetry(false), backoffEvent(this) { } bool @@ -112,9 +113,9 @@ DPRINTF(DMA, "Received nacked %s addr %#x\n", pkt->cmdString(), pkt->getAddr()); - if (backoffTime < device->minBackoffDelay) - backoffTime = device->minBackoffDelay; - else if (backoffTime < device->maxBackoffDelay) + if (backoffTime < minBackoffDelay) + backoffTime = minBackoffDelay; + else if (backoffTime < maxBackoffDelay) backoffTime <<= 1; reschedule(backoffEvent, curTick + backoffTime, true); @@ -138,10 +139,12 @@ state->numBytes += pkt->req->getSize(); assert(state->totBytes >= state->numBytes); if (state->totBytes == state->numBytes) { - if (state->delay) - schedule(state->completionEvent, curTick + state->delay); - else - state->completionEvent->process(); + if (state->completionEvent) { + if (state->delay) + schedule(state->completionEvent, curTick + state->delay); + else + state->completionEvent->process(); + } delete state; } delete pkt->req; @@ -159,8 +162,7 @@ } DmaDevice::DmaDevice(const Params *p) - : PioDevice(p), dmaPort(NULL), minBackoffDelay(p->min_backoff_delay), - maxBackoffDelay(p->max_backoff_delay) + : PioDevice(p), dmaPort(NULL) { } @@ -221,8 +223,6 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, uint8_t *data, Tick delay) { - assert(event); - assert(device->getState() == SimObject::Running); DmaReqState *reqState = new DmaReqState(event, this, size, delay); @@ -313,11 +313,14 @@ DPRINTF(DMA, "--Received response for DMA for addr: %#x size: %d nb: %d, tot: %d sched %d\n", pkt->req->getPaddr(), pkt->req->getSize(), state->numBytes, - state->totBytes, state->completionEvent->scheduled()); + state->totBytes, + state->completionEvent ? state->completionEvent->scheduled() : 0 ); if (state->totBytes == state->numBytes) { - assert(!state->completionEvent->scheduled()); - schedule(state->completionEvent, curTick + lat + state->delay); + if (state->completionEvent) { + assert(!state->completionEvent->scheduled()); + schedule(state->completionEvent, curTick + lat + state->delay); + } delete state; delete pkt->req; } diff -r 84bd4089958b src/sim/process.cc --- a/src/sim/process.cc Tue May 25 20:15:44 2010 -0700 +++ b/src/sim/process.cc Wed May 26 18:10:45 2010 -0500 @@ -755,14 +755,15 @@ fatal("Unknown/unsupported operating system."); } #elif THE_ISA == ARM_ISA - if (objFile->getArch() != ObjectFile::Arm) + if (objFile->getArch() != ObjectFile::Arm && + objFile->getArch() != ObjectFile::Thumb) fatal("Object file architecture does not match compiled ISA (ARM)."); switch (objFile->getOpSys()) { case ObjectFile::UnknownOpSys: warn("Unknown operating system; assuming Linux."); // fall through case ObjectFile::Linux: - process = new ArmLinuxProcess(params, objFile); + process = new ArmLinuxProcess(params, objFile, objFile->getArch()); break; case ObjectFile::LinuxArmOABI: fatal("M5 does not support ARM OABI binaries. Please recompile with an" diff -r 84bd4089958b tests/quick/00.hello/ref/arm/linux/simple-atomic/config.ini --- a/tests/quick/00.hello/ref/arm/linux/simple-atomic/config.ini Tue May 25 20:15:44 2010 -0700 +++ b/tests/quick/00.hello/ref/arm/linux/simple-atomic/config.ini Wed May 26 18:10:45 2010 -0500 @@ -58,7 +58,7 @@ env= errout=cerr euid=100 -executable=/proj/aatl_perfmod_arch/m5_system_files/regression/test-progs/hello/bin/arm/linux/hello +executable=/dist/m5/regression/test-progs/hello/bin/arm/linux/hello gid=100 input=cin max_stack_size=67108864 diff -r 84bd4089958b tests/quick/00.hello/ref/arm/linux/simple-atomic/simerr --- a/tests/quick/00.hello/ref/arm/linux/simple-atomic/simerr Tue May 25 20:15:44 2010 -0700 +++ b/tests/quick/00.hello/ref/arm/linux/simple-atomic/simerr Wed May 26 18:10:45 2010 -0500 @@ -1,5 +1,3 @@ warn: Sockets disabled, not accepting gdb connections For more information see: http://www.m5sim.org/warn/d946bea6 -warn: instruction 'fstmx' unimplemented -For more information see: http://www.m5sim.org/warn/21b09adb hack: be nice to actually delete the event here diff -r 84bd4089958b tests/quick/00.hello/ref/arm/linux/simple-atomic/simout --- a/tests/quick/00.hello/ref/arm/linux/simple-atomic/simout Tue May 25 20:15:44 2010 -0700 +++ b/tests/quick/00.hello/ref/arm/linux/simple-atomic/simout Wed May 26 18:10:45 2010 -0500 @@ -5,12 +5,12 @@ All Rights Reserved -M5 compiled Feb 25 2010 04:11:39 -M5 revision 1a33ca29ec29 6980 default share-aware-test-update.patch tip qtip -M5 started Feb 25 2010 04:11:44 -M5 executing on SC2B0619 +M5 compiled Feb 27 2010 17:02:03 +M5 revision 3ba6c6c19ddd 7101 default qtip syscallfromintstats.patch tip +M5 started Feb 27 2010 17:02:04 +M5 executing on tater command line: build/ARM_SE/m5.fast -d build/ARM_SE/tests/fast/quick/00.hello/arm/linux/simple-atomic -re tests/run.py build/ARM_SE/tests/fast/quick/00.hello/arm/linux/simple-atomic Global frequency set at 1000000000000 ticks per second info: Entering event queue @ 0. Starting simulation... Hello world! -Exiting @ tick 2748500 because target called exit() +Exiting @ tick 2756500 because target called exit() diff -r 84bd4089958b tests/quick/00.hello/ref/arm/linux/simple-atomic/stats.txt --- a/tests/quick/00.hello/ref/arm/linux/simple-atomic/stats.txt Tue May 25 20:15:44 2010 -0700 +++ b/tests/quick/00.hello/ref/arm/linux/simple-atomic/stats.txt Wed May 26 18:10:45 2010 -0500 @@ -1,13 +1,13 @@ ---------- Begin Simulation Statistics ---------- -host_inst_rate 1074248 # Simulator instruction rate (inst/s) -host_mem_usage 180696 # Number of bytes of host memory used -host_seconds 0.01 # Real time elapsed on the host -host_tick_rate 511253720 # Simulator tick rate (ticks/s) +host_inst_rate 12327 # Simulator instruction rate (inst/s) +host_mem_usage 201392 # Number of bytes of host memory used +host_seconds 0.45 # Real time elapsed on the host +host_tick_rate 6174277 # Simulator tick rate (ticks/s) sim_freq 1000000000000 # Frequency of simulated ticks -sim_insts 5498 # Number of instructions simulated +sim_insts 5501 # Number of instructions simulated sim_seconds 0.000003 # Number of seconds simulated -sim_ticks 2748500 # Number of ticks simulated +sim_ticks 2756500 # Number of ticks simulated system.cpu.dtb.accesses 0 # DTB accesses system.cpu.dtb.hits 0 # DTB hits system.cpu.dtb.misses 0 # DTB misses @@ -28,9 +28,9 @@ system.cpu.itb.write_hits 0 # DTB write hits system.cpu.itb.write_misses 0 # DTB write misses system.cpu.not_idle_fraction 1 # Percentage of non-idle cycles -system.cpu.numCycles 5498 # number of cpu cycles simulated -system.cpu.num_insts 5498 # Number of instructions executed -system.cpu.num_refs 2127 # Number of memory references +system.cpu.numCycles 5514 # number of cpu cycles simulated +system.cpu.num_insts 5501 # Number of instructions executed +system.cpu.num_refs 2143 # Number of memory references system.cpu.workload.PROG:num_syscalls 13 # Number of system calls ---------- End Simulation Statistics ---------- diff -r 84bd4089958b util/statetrace/arch/tracechild_arm.hh --- a/util/statetrace/arch/tracechild_arm.hh Tue May 25 20:15:44 2010 -0700 +++ b/util/statetrace/arch/tracechild_arm.hh Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,16 @@ /* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2009 The Regents of The University of Michigan * All rights reserved. * @@ -63,15 +75,16 @@ user_regs regs; user_regs oldregs; bool regDiffSinceUpdate[numregs]; - + bool foundMvn; + protected: bool update(int pid); - + public: ARMTraceChild(); bool sendState(int socket); - int getNumRegs() + int getNumRegs() { return numregs; } @@ -90,7 +103,7 @@ int64_t getRegVal(int num); int64_t getOldRegVal(int num); - + bool step(); uint64_t getPC() diff -r 84bd4089958b util/statetrace/arch/tracechild_arm.cc --- a/util/statetrace/arch/tracechild_arm.cc Tue May 25 20:15:44 2010 -0700 +++ b/util/statetrace/arch/tracechild_arm.cc Wed May 26 18:10:45 2010 -0500 @@ -1,4 +1,16 @@ /* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2006-2009 The Regents of The University of Michigan * All rights reserved. * @@ -33,6 +45,7 @@ #include #include #include +#include #include "tracechild_arm.hh" @@ -46,6 +59,8 @@ ARMTraceChild::ARMTraceChild() { + foundMvn = false; + for (int x = 0; x < numregs; x++) { memset(®s, 0, sizeof(regs)); memset(&oldregs, 0, sizeof(regs)); @@ -79,7 +94,7 @@ toSend -= sent; messagePtr += sent; } - + return true; } @@ -97,7 +112,7 @@ cerr << "update: " << strerror(errno) << endl; return false; } - + for(unsigned int x = 0; x < numregs; x++) regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x)); return true; @@ -207,25 +222,39 @@ uint32_t lr = getRegVal(14); uint32_t pc = getPC(); - uint32_t lrOp; + uint32_t lrOp, subsOp; + char obuf[128]; + bool patch = false; // Since ARM uses software breakpoints behind the scenes, they don't work // in read only areas like the page of routines provided by the kernel. The // link register generally holds the address the process wants to the // kernel to return to after it's done, so we'll install a software - // breakpoint there. If the lr happens to point to the next instruction - // we'll leave out our breakpoint to avoid an infinite loop. This isn't a - // fool proof strategy, but it should work well in all the reasonable - // scenarios I can think of right now. + // breakpoint there. + // + // Calls into the kernel user page always follow the form: + // MVN ... + // + // SUB PC, ... + // + // So we look for this pattern and set a breakpoint on the LR at the SUB + // instruction. - if (pc != lr) { + + subsOp = ptrace(PTRACE_PEEKDATA, pid, pc, 0); + if ((subsOp & 0xFFFF0FFF) == 0xe3e00a0f) + foundMvn = true; + + if (foundMvn && ((subsOp & 0xFFF0F000) == 0xe240f000)) { + foundMvn = false; lrOp = ptrace(PTRACE_PEEKDATA, pid, lr, 0); ptrace(PTRACE_POKEDATA, pid, lr, bkpt_inst); + patch = true; } ptraceSingleStep(); - if (pc != lr) { + + if (patch) ptrace(PTRACE_POKEDATA, pid, lr, lrOp); - } } diff -r 84bd4089958b util/statetrace/statetrace.cc --- a/util/statetrace/statetrace.cc Tue May 25 20:15:44 2010 -0700 +++ b/util/statetrace/statetrace.cc Wed May 26 18:10:45 2010 -0500 @@ -49,7 +49,13 @@ void printUsage(const char * execName) { - cout << execName << " -h | -r -- " << endl; + cout << execName << " -- " << endl; + cout << "options:" << endl; + cout << " -h print this help" << endl; + cout << " --host remote m5 host to connect to" << endl; + cout << " -r print register names" << endl; + cout << " -i print initial stack state" << endl; + cout << " -nt don't print an instruction trace" << endl; } int main(int argc, char * argv[], char * envp[]) @@ -62,6 +68,11 @@ bool printInitial = false; bool printTrace = true; string host = "localhost"; + + if (argc == 1) { + printUsage(argv[0]); + return 0; + } for(int x = 1; x < argc; x++) { if(!strcmp(argv[x], "-h"))