| /* |
| * Copyright (c) 2010, 2012-2013, 2017 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_TYPES_HH__ |
| #define __ARCH_ARM_TYPES_HH__ |
| |
| #include "arch/generic/types.hh" |
| #include "base/bitunion.hh" |
| #include "base/logging.hh" |
| #include "base/types.hh" |
| #include "debug/Decoder.hh" |
| |
| namespace ArmISA |
| { |
| typedef uint32_t MachInst; |
| |
| BitUnion8(ITSTATE) |
| /* Note that the split (cond, mask) below is not as in ARM ARM. |
| * But it is more convenient for simulation. The condition |
| * is always the concatenation of the top 3 bits and the next bit, |
| * which applies when one of the bottom 4 bits is set. |
| * Refer to predecoder.cc for the use case. |
| */ |
| Bitfield<7, 4> cond; |
| Bitfield<3, 0> mask; |
| // Bitfields for moving to/from CPSR |
| Bitfield<7, 2> top6; |
| Bitfield<1, 0> bottom2; |
| EndBitUnion(ITSTATE) |
| |
| BitUnion64(ExtMachInst) |
| // Decoder state |
| Bitfield<63, 62> decoderFault; // See DecoderFault |
| |
| // 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; |
| Bitfield<34> aarch64; |
| |
| // 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; |
| Bitfield<15> opcode15; |
| 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; |
| |
| Bitfield<11, 8> rs; |
| |
| SubBitUnion(puswl, 24, 20) |
| Bitfield<24> prepost; |
| Bitfield<23> up; |
| Bitfield<22> psruser; |
| Bitfield<21> writeback; |
| Bitfield<20> loadOp; |
| EndSubBitUnion(puswl) |
| |
| Bitfield<24, 20> pubwl; |
| |
| Bitfield<7, 0> imm; |
| |
| Bitfield<11, 8> rotate; |
| |
| Bitfield<11, 0> immed11_0; |
| Bitfield<7, 0> immed7_0; |
| |
| Bitfield<11, 8> immedHi11_8; |
| Bitfield<3, 0> immedLo3_0; |
| |
| Bitfield<15, 0> regList; |
| |
| Bitfield<23, 0> offset; |
| |
| Bitfield<23, 0> immed23_0; |
| |
| Bitfield<11, 8> cpNum; |
| Bitfield<18, 16> fn; |
| Bitfield<14, 12> fd; |
| Bitfield<3> fpRegImm; |
| Bitfield<3, 0> fm; |
| Bitfield<2, 0> fpImm; |
| Bitfield<24, 20> punwl; |
| |
| Bitfield<15, 8> 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) |
| |
| class PCState : public GenericISA::UPCState<MachInst> |
| { |
| protected: |
| |
| typedef GenericISA::UPCState<MachInst> Base; |
| |
| enum FlagBits { |
| ThumbBit = (1 << 0), |
| JazelleBit = (1 << 1), |
| AArch64Bit = (1 << 2) |
| }; |
| uint8_t flags; |
| uint8_t nextFlags; |
| uint8_t _itstate; |
| uint8_t _nextItstate; |
| uint8_t _size; |
| public: |
| PCState() : flags(0), nextFlags(0), _itstate(0), _nextItstate(0), |
| _size(0) |
| {} |
| |
| void |
| set(Addr val) |
| { |
| Base::set(val); |
| npc(val + (thumb() ? 2 : 4)); |
| } |
| |
| PCState(Addr val) : flags(0), nextFlags(0), _itstate(0), |
| _nextItstate(0), _size(0) |
| { set(val); } |
| |
| bool |
| thumb() const |
| { |
| return flags & ThumbBit; |
| } |
| |
| void |
| thumb(bool val) |
| { |
| if (val) |
| flags |= ThumbBit; |
| else |
| flags &= ~ThumbBit; |
| } |
| |
| bool |
| nextThumb() const |
| { |
| return nextFlags & ThumbBit; |
| } |
| |
| void |
| nextThumb(bool val) |
| { |
| if (val) |
| nextFlags |= ThumbBit; |
| else |
| nextFlags &= ~ThumbBit; |
| } |
| |
| void size(uint8_t s) { _size = s; } |
| uint8_t size() const { return _size; } |
| |
| bool |
| branching() const |
| { |
| return ((this->pc() + this->size()) != this->npc()); |
| } |
| |
| |
| bool |
| jazelle() const |
| { |
| return flags & JazelleBit; |
| } |
| |
| void |
| jazelle(bool val) |
| { |
| if (val) |
| flags |= JazelleBit; |
| else |
| flags &= ~JazelleBit; |
| } |
| |
| bool |
| nextJazelle() const |
| { |
| return nextFlags & JazelleBit; |
| } |
| |
| void |
| nextJazelle(bool val) |
| { |
| if (val) |
| nextFlags |= JazelleBit; |
| else |
| nextFlags &= ~JazelleBit; |
| } |
| |
| bool |
| aarch64() const |
| { |
| return flags & AArch64Bit; |
| } |
| |
| void |
| aarch64(bool val) |
| { |
| if (val) |
| flags |= AArch64Bit; |
| else |
| flags &= ~AArch64Bit; |
| } |
| |
| bool |
| nextAArch64() const |
| { |
| return nextFlags & AArch64Bit; |
| } |
| |
| void |
| nextAArch64(bool val) |
| { |
| if (val) |
| nextFlags |= AArch64Bit; |
| else |
| nextFlags &= ~AArch64Bit; |
| } |
| |
| |
| uint8_t |
| itstate() const |
| { |
| return _itstate; |
| } |
| |
| void |
| itstate(uint8_t value) |
| { |
| _itstate = value; |
| } |
| |
| uint8_t |
| nextItstate() const |
| { |
| return _nextItstate; |
| } |
| |
| void |
| nextItstate(uint8_t value) |
| { |
| _nextItstate = value; |
| } |
| |
| void |
| advance() |
| { |
| Base::advance(); |
| flags = nextFlags; |
| npc(pc() + (thumb() ? 2 : 4)); |
| |
| if (_nextItstate) { |
| _itstate = _nextItstate; |
| _nextItstate = 0; |
| } else if (_itstate) { |
| ITSTATE it = _itstate; |
| uint8_t cond_mask = it.mask; |
| uint8_t thumb_cond = it.cond; |
| DPRINTF(Decoder, "Advancing ITSTATE from %#x,%#x.\n", |
| thumb_cond, cond_mask); |
| cond_mask <<= 1; |
| uint8_t new_bit = bits(cond_mask, 4); |
| cond_mask &= mask(4); |
| if (cond_mask == 0) |
| thumb_cond = 0; |
| else |
| replaceBits(thumb_cond, 0, new_bit); |
| DPRINTF(Decoder, "Advancing ITSTATE to %#x,%#x.\n", |
| thumb_cond, cond_mask); |
| it.mask = cond_mask; |
| it.cond = thumb_cond; |
| _itstate = it; |
| } |
| } |
| |
| void |
| uEnd() |
| { |
| advance(); |
| upc(0); |
| nupc(1); |
| } |
| |
| Addr |
| instPC() const |
| { |
| return pc() + (thumb() ? 4 : 8); |
| } |
| |
| void |
| instNPC(Addr val) |
| { |
| // @todo: review this when AArch32/64 interprocessing is |
| // supported |
| if (aarch64()) |
| npc(val); // AArch64 doesn't force PC alignment, a PC |
| // Alignment Fault can be raised instead |
| else |
| npc(val &~ mask(nextThumb() ? 1 : 2)); |
| } |
| |
| Addr |
| instNPC() const |
| { |
| return npc(); |
| } |
| |
| // Perform an interworking branch. |
| void |
| instIWNPC(Addr val) |
| { |
| bool thumbEE = (thumb() && jazelle()); |
| |
| Addr newPC = val; |
| if (thumbEE) { |
| if (bits(newPC, 0)) { |
| newPC = newPC & ~mask(1); |
| } // else we have a bad interworking address; do not call |
| // panic() since the instruction could be executed |
| // speculatively |
| } else { |
| if (bits(newPC, 0)) { |
| nextThumb(true); |
| newPC = newPC & ~mask(1); |
| } else if (!bits(newPC, 1)) { |
| nextThumb(false); |
| } else { |
| // This state is UNPREDICTABLE in the ARM architecture |
| // The easy thing to do is just mask off the bit and |
| // stay in the current mode, so we'll do that. |
| newPC &= ~mask(2); |
| } |
| } |
| npc(newPC); |
| } |
| |
| // Perform an interworking branch in ARM mode, a regular branch |
| // otherwise. |
| void |
| instAIWNPC(Addr val) |
| { |
| if (!thumb() && !jazelle()) |
| instIWNPC(val); |
| else |
| instNPC(val); |
| } |
| |
| bool |
| operator == (const PCState &opc) const |
| { |
| return Base::operator == (opc) && |
| flags == opc.flags && nextFlags == opc.nextFlags && |
| _itstate == opc._itstate && _nextItstate == opc._nextItstate; |
| } |
| |
| bool |
| operator != (const PCState &opc) const |
| { |
| return !(*this == opc); |
| } |
| |
| void |
| serialize(CheckpointOut &cp) const override |
| { |
| Base::serialize(cp); |
| SERIALIZE_SCALAR(flags); |
| SERIALIZE_SCALAR(_size); |
| SERIALIZE_SCALAR(nextFlags); |
| SERIALIZE_SCALAR(_itstate); |
| SERIALIZE_SCALAR(_nextItstate); |
| } |
| |
| void |
| unserialize(CheckpointIn &cp) override |
| { |
| Base::unserialize(cp); |
| UNSERIALIZE_SCALAR(flags); |
| UNSERIALIZE_SCALAR(_size); |
| UNSERIALIZE_SCALAR(nextFlags); |
| UNSERIALIZE_SCALAR(_itstate); |
| UNSERIALIZE_SCALAR(_nextItstate); |
| } |
| }; |
| |
| // Shift types for ARM instructions |
| enum ArmShiftType { |
| LSL = 0, |
| LSR, |
| ASR, |
| ROR |
| }; |
| |
| // Extension types for ARM instructions |
| enum ArmExtendType { |
| UXTB = 0, |
| UXTH = 1, |
| UXTW = 2, |
| UXTX = 3, |
| SXTB = 4, |
| SXTH = 5, |
| SXTW = 6, |
| SXTX = 7 |
| }; |
| |
| typedef int RegContextParam; |
| typedef int RegContextVal; |
| |
| //used in FP convert & round function |
| enum ConvertType{ |
| SINGLE_TO_DOUBLE, |
| SINGLE_TO_WORD, |
| SINGLE_TO_LONG, |
| |
| DOUBLE_TO_SINGLE, |
| DOUBLE_TO_WORD, |
| DOUBLE_TO_LONG, |
| |
| LONG_TO_SINGLE, |
| LONG_TO_DOUBLE, |
| LONG_TO_WORD, |
| LONG_TO_PS, |
| |
| WORD_TO_SINGLE, |
| WORD_TO_DOUBLE, |
| WORD_TO_LONG, |
| WORD_TO_PS, |
| |
| PL_TO_SINGLE, |
| PU_TO_SINGLE |
| }; |
| |
| //used in FP convert & round function |
| enum RoundMode{ |
| RND_ZERO, |
| RND_DOWN, |
| RND_UP, |
| RND_NEAREST |
| }; |
| |
| enum ExceptionLevel { |
| EL0 = 0, |
| EL1, |
| EL2, |
| EL3 |
| }; |
| |
| enum OperatingMode { |
| MODE_EL0T = 0x0, |
| MODE_EL1T = 0x4, |
| MODE_EL1H = 0x5, |
| MODE_EL2T = 0x8, |
| MODE_EL2H = 0x9, |
| MODE_EL3T = 0xC, |
| MODE_EL3H = 0xD, |
| MODE_USER = 16, |
| MODE_FIQ = 17, |
| MODE_IRQ = 18, |
| MODE_SVC = 19, |
| MODE_MON = 22, |
| MODE_ABORT = 23, |
| MODE_HYP = 26, |
| MODE_UNDEFINED = 27, |
| MODE_SYSTEM = 31, |
| MODE_MAXMODE = MODE_SYSTEM |
| }; |
| |
| enum ExceptionClass { |
| EC_INVALID = -1, |
| EC_UNKNOWN = 0x0, |
| EC_TRAPPED_WFI_WFE = 0x1, |
| EC_TRAPPED_CP15_MCR_MRC = 0x3, |
| EC_TRAPPED_CP15_MCRR_MRRC = 0x4, |
| EC_TRAPPED_CP14_MCR_MRC = 0x5, |
| EC_TRAPPED_CP14_LDC_STC = 0x6, |
| EC_TRAPPED_HCPTR = 0x7, |
| EC_TRAPPED_SIMD_FP = 0x7, // AArch64 alias |
| EC_TRAPPED_CP10_MRC_VMRS = 0x8, |
| EC_TRAPPED_BXJ = 0xA, |
| EC_TRAPPED_CP14_MCRR_MRRC = 0xC, |
| EC_ILLEGAL_INST = 0xE, |
| EC_SVC_TO_HYP = 0x11, |
| EC_SVC = 0x11, // AArch64 alias |
| EC_HVC = 0x12, |
| EC_SMC_TO_HYP = 0x13, |
| EC_SMC = 0x13, // AArch64 alias |
| EC_SVC_64 = 0x15, |
| EC_HVC_64 = 0x16, |
| EC_SMC_64 = 0x17, |
| EC_TRAPPED_MSR_MRS_64 = 0x18, |
| EC_PREFETCH_ABORT_TO_HYP = 0x20, |
| EC_PREFETCH_ABORT_LOWER_EL = 0x20, // AArch64 alias |
| EC_PREFETCH_ABORT_FROM_HYP = 0x21, |
| EC_PREFETCH_ABORT_CURR_EL = 0x21, // AArch64 alias |
| EC_PC_ALIGNMENT = 0x22, |
| EC_DATA_ABORT_TO_HYP = 0x24, |
| EC_DATA_ABORT_LOWER_EL = 0x24, // AArch64 alias |
| EC_DATA_ABORT_FROM_HYP = 0x25, |
| EC_DATA_ABORT_CURR_EL = 0x25, // AArch64 alias |
| EC_STACK_PTR_ALIGNMENT = 0x26, |
| EC_FP_EXCEPTION = 0x28, |
| EC_FP_EXCEPTION_64 = 0x2C, |
| EC_SERROR = 0x2F, |
| EC_SOFTWARE_BREAKPOINT = 0x38, |
| }; |
| |
| /** |
| * Instruction decoder fault codes in ExtMachInst. |
| */ |
| enum DecoderFault : std::uint8_t { |
| OK = 0x0, ///< No fault |
| UNALIGNED = 0x1, ///< Unaligned instruction fault |
| |
| PANIC = 0x3, ///< Internal gem5 error |
| }; |
| |
| BitUnion8(OperatingMode64) |
| Bitfield<0> spX; |
| Bitfield<3, 2> el; |
| Bitfield<4> width; |
| EndBitUnion(OperatingMode64) |
| |
| static bool inline |
| opModeIs64(OperatingMode mode) |
| { |
| return ((OperatingMode64)(uint8_t)mode).width == 0; |
| } |
| |
| static bool inline |
| opModeIsH(OperatingMode mode) |
| { |
| return (mode == MODE_EL1H || mode == MODE_EL2H || mode == MODE_EL3H); |
| } |
| |
| static bool inline |
| opModeIsT(OperatingMode mode) |
| { |
| return (mode == MODE_EL0T || mode == MODE_EL1T || mode == MODE_EL2T || |
| mode == MODE_EL3T); |
| } |
| |
| static ExceptionLevel inline |
| opModeToEL(OperatingMode mode) |
| { |
| bool aarch32 = ((mode >> 4) & 1) ? true : false; |
| if (aarch32) { |
| switch (mode) { |
| case MODE_USER: |
| return EL0; |
| case MODE_FIQ: |
| case MODE_IRQ: |
| case MODE_SVC: |
| case MODE_ABORT: |
| case MODE_UNDEFINED: |
| case MODE_SYSTEM: |
| return EL1; |
| case MODE_HYP: |
| return EL2; |
| case MODE_MON: |
| return EL3; |
| default: |
| panic("Invalid operating mode: %d", mode); |
| break; |
| } |
| } else { |
| // aarch64 |
| return (ExceptionLevel) ((mode >> 2) & 3); |
| } |
| } |
| |
| static inline bool |
| badMode(OperatingMode mode) |
| { |
| switch (mode) { |
| case MODE_EL0T: |
| case MODE_EL1T: |
| case MODE_EL1H: |
| case MODE_EL2T: |
| case MODE_EL2H: |
| case MODE_EL3T: |
| case MODE_EL3H: |
| case MODE_USER: |
| case MODE_FIQ: |
| case MODE_IRQ: |
| case MODE_SVC: |
| case MODE_MON: |
| case MODE_ABORT: |
| case MODE_HYP: |
| case MODE_UNDEFINED: |
| case MODE_SYSTEM: |
| return false; |
| default: |
| return true; |
| } |
| } |
| |
| |
| static inline bool |
| badMode32(OperatingMode mode) |
| { |
| switch (mode) { |
| case MODE_USER: |
| case MODE_FIQ: |
| case MODE_IRQ: |
| case MODE_SVC: |
| case MODE_MON: |
| case MODE_ABORT: |
| case MODE_HYP: |
| case MODE_UNDEFINED: |
| case MODE_SYSTEM: |
| return false; |
| default: |
| return true; |
| } |
| } |
| |
| } // namespace ArmISA |
| |
| #endif |