/* * 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 */ #ifndef __ARCH_ARM_MEM_HH__ #define __ARCH_ARM_MEM_HH__ #include "arch/arm/insts/pred_inst.hh" namespace ArmISA { 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 override; }; class MightBeMicro : public PredOp { protected: MightBeMicro(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : PredOp(mnem, _machInst, __opClass) {} void advancePC(PCState &pcState) const { if (flags[IsLastMicroop]) { pcState.uEnd(); } else if (flags[IsMicroop]) { pcState.uAdvance(); } else { pcState.advance(); } } }; // The address is a base register plus an immediate. class RfeOp : public MightBeMicro { public: enum AddrMode { DecrementAfter, DecrementBefore, IncrementAfter, IncrementBefore }; protected: IntRegIndex base; AddrMode mode; bool wb; IntRegIndex ura, urb, urc; static const unsigned numMicroops = 3; StaticInstPtr *uops; RfeOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, IntRegIndex _base, AddrMode _mode, bool _wb) : MightBeMicro(mnem, _machInst, __opClass), base(_base), mode(_mode), wb(_wb), ura(INTREG_UREG0), urb(INTREG_UREG1), urc(INTREG_UREG2), uops(NULL) {} virtual ~RfeOp() { delete [] uops; } StaticInstPtr fetchMicroop(MicroPC microPC) const override { assert(uops != NULL && microPC < numMicroops); return uops[microPC]; } std::string generateDisassembly( Addr pc, const SymbolTable *symtab) const override; }; // The address is a base register plus an immediate. class SrsOp : public MightBeMicro { public: enum AddrMode { DecrementAfter, DecrementBefore, IncrementAfter, IncrementBefore }; protected: uint32_t regMode; AddrMode mode; bool wb; static const unsigned numMicroops = 2; StaticInstPtr *uops; SrsOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, uint32_t _regMode, AddrMode _mode, bool _wb) : MightBeMicro(mnem, _machInst, __opClass), regMode(_regMode), mode(_mode), wb(_wb), uops(NULL) {} virtual ~SrsOp() { delete [] uops; } StaticInstPtr fetchMicroop(MicroPC microPC) const override { assert(uops != NULL && microPC < numMicroops); return uops[microPC]; } std::string generateDisassembly( Addr pc, const SymbolTable *symtab) const override; }; class Memory : public MightBeMicro { public: enum AddrMode { AddrMd_Offset, AddrMd_PreIndex, AddrMd_PostIndex }; protected: IntRegIndex dest; IntRegIndex base; bool add; static const unsigned numMicroops = 3; StaticInstPtr *uops; Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass, IntRegIndex _dest, IntRegIndex _base, bool _add) : MightBeMicro(mnem, _machInst, __opClass), dest(_dest), base(_base), add(_add), uops(NULL) {} virtual ~Memory() { delete [] uops; } StaticInstPtr fetchMicroop(MicroPC microPC) const override { assert(uops != NULL && microPC < numMicroops); return uops[microPC]; } virtual void printOffset(std::ostream &os) const {} virtual void printDest(std::ostream &os) const { printIntReg(os, dest); } void printInst(std::ostream &os, AddrMode addrMode) const; }; // The address is a base register plus an immediate. class MemoryImm : public Memory { protected: 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 { int32_t pImm = imm; if (!add) pImm = -pImm; ccprintf(os, "#%d", pImm); } }; class MemoryExImm : public MemoryImm { protected: 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 printDest(std::ostream &os) const { printIntReg(os, result); os << ", "; MemoryImm::printDest(os); } }; // The address is a base register plus an immediate. class MemoryDImm : public MemoryImm { protected: 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 printDest(std::ostream &os) const { MemoryImm::printDest(os); os << ", "; printIntReg(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 { printIntReg(os, result); os << ", "; MemoryDImm::printDest(os); } }; // The address is a shifted register plus an immediate class MemoryReg : public Memory { protected: 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 printDest(std::ostream &os) const { MemoryReg::printDest(os); os << ", "; printIntReg(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(); } }; } #endif //__ARCH_ARM_INSTS_MEM_HH__