/* * Copyright (c) 2010, 2012-2013, 2016-2018 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. * * 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: Korey Sewell * Stephen Hines */ #ifndef __ARCH_ARM_UTILITY_HH__ #define __ARCH_ARM_UTILITY_HH__ #include "arch/arm/isa_traits.hh" #include "arch/arm/miscregs.hh" #include "arch/arm/types.hh" #include "base/logging.hh" #include "base/trace.hh" #include "base/types.hh" #include "cpu/static_inst.hh" #include "cpu/thread_context.hh" class ArmSystem; namespace ArmISA { inline PCState buildRetPC(const PCState &curPC, const PCState &callPC) { PCState retPC = callPC; retPC.uEnd(); return retPC; } inline bool testPredicate(uint32_t nz, uint32_t c, uint32_t v, ConditionCode code) { bool n = (nz & 0x2); bool z = (nz & 0x1); switch (code) { case COND_EQ: return z; case COND_NE: return !z; case COND_CS: return c; case COND_CC: return !c; case COND_MI: return n; case COND_PL: return !n; case COND_VS: return v; case COND_VC: return !v; case COND_HI: return (c && !z); case COND_LS: return !(c && !z); case COND_GE: return !(n ^ v); case COND_LT: return (n ^ v); case COND_GT: return !(n ^ v || z); case COND_LE: return (n ^ v || z); case COND_AL: return true; case COND_UC: return true; default: panic("Unhandled predicate condition: %d\n", code); } } /** * Function to insure ISA semantics about 0 registers. * @param tc The thread context. */ template void zeroRegisters(TC *tc); inline void startupCPU(ThreadContext *tc, int cpuId) { tc->activate(); } void copyRegs(ThreadContext *src, ThreadContext *dest); static inline void copyMiscRegs(ThreadContext *src, ThreadContext *dest) { panic("Copy Misc. Regs Not Implemented Yet\n"); } void initCPU(ThreadContext *tc, int cpuId); static inline bool inUserMode(CPSR cpsr) { return cpsr.mode == MODE_USER || cpsr.mode == MODE_EL0T; } static inline bool inUserMode(ThreadContext *tc) { return inUserMode(tc->readMiscRegNoEffect(MISCREG_CPSR)); } static inline bool inPrivilegedMode(CPSR cpsr) { return !inUserMode(cpsr); } static inline bool inPrivilegedMode(ThreadContext *tc) { return !inUserMode(tc); } bool inAArch64(ThreadContext *tc); static inline OperatingMode currOpMode(ThreadContext *tc) { CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); return (OperatingMode) (uint8_t) cpsr.mode; } static inline ExceptionLevel currEL(ThreadContext *tc) { CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); return (ExceptionLevel) (uint8_t) cpsr.el; } /** * This function checks whether selected EL provided as an argument * is using the AArch32 ISA. This information might be unavailable * at the current EL status: it hence returns a pair of boolean values: * a first boolean, true if information is available (known), * and a second one, true if EL is using AArch32, false for AArch64. * * @param tc The thread context. * @param el The target exception level. * @retval known is FALSE for EL0 if the current Exception level * is not EL0 and EL1 is using AArch64, since it cannot * determine the state of EL0; TRUE otherwise. * @retval aarch32 is TRUE if the specified Exception level is using AArch32; * FALSE otherwise. */ std::pair ELUsingAArch32K(ThreadContext *tc, ExceptionLevel el); bool ELIs32(ThreadContext *tc, ExceptionLevel el); bool ELIs64(ThreadContext *tc, ExceptionLevel el); bool isBigEndian64(ThreadContext *tc); /** * badMode is checking if the execution mode provided as an argument is * valid and implemented for AArch32 * * @param tc ThreadContext * @param mode OperatingMode to check * @return false if mode is valid and implemented, true otherwise */ bool badMode32(ThreadContext *tc, OperatingMode mode); /** * badMode is checking if the execution mode provided as an argument is * valid and implemented. * * @param tc ThreadContext * @param mode OperatingMode to check * @return false if mode is valid and implemented, true otherwise */ bool badMode(ThreadContext *tc, OperatingMode mode); static inline uint8_t itState(CPSR psr) { ITSTATE it = 0; it.top6 = psr.it2; it.bottom2 = psr.it1; return (uint8_t)it; } /** * Removes the tag from tagged addresses if that mode is enabled. * @param addr The address to be purified. * @param tc The thread context. * @param el The controlled exception level. * @return The purified address. */ Addr purifyTaggedAddr(Addr addr, ThreadContext *tc, ExceptionLevel el, TTBCR tcr); Addr purifyTaggedAddr(Addr addr, ThreadContext *tc, ExceptionLevel el); static inline bool inSecureState(SCR scr, CPSR cpsr) { switch ((OperatingMode) (uint8_t) cpsr.mode) { case MODE_MON: case MODE_EL3T: case MODE_EL3H: return true; case MODE_HYP: case MODE_EL2T: case MODE_EL2H: return false; default: return !scr.ns; } } bool inSecureState(ThreadContext *tc); /** * Return TRUE if an Exception level below EL3 is in Secure state. * Differs from inSecureState in that it ignores the current EL * or Mode in considering security state. */ inline bool isSecureBelowEL3(ThreadContext *tc); bool longDescFormatInUse(ThreadContext *tc); /** This helper function is either returing the value of * MPIDR_EL1 (by calling getMPIDR), or it is issuing a read * to VMPIDR_EL2 (as it happens in virtualized systems) */ MiscReg readMPIDR(ArmSystem *arm_sys, ThreadContext *tc); /** This helper function is returing the value of MPIDR_EL1 */ MiscReg getMPIDR(ArmSystem *arm_sys, ThreadContext *tc); static inline uint32_t mcrMrcIssBuild(bool isRead, uint32_t crm, IntRegIndex rt, uint32_t crn, uint32_t opc1, uint32_t opc2) { return (isRead << 0) | (crm << 1) | (rt << 5) | (crn << 10) | (opc1 << 14) | (opc2 << 17); } static inline void mcrMrcIssExtract(uint32_t iss, bool &isRead, uint32_t &crm, IntRegIndex &rt, uint32_t &crn, uint32_t &opc1, uint32_t &opc2) { isRead = (iss >> 0) & 0x1; crm = (iss >> 1) & 0xF; rt = (IntRegIndex) ((iss >> 5) & 0xF); crn = (iss >> 10) & 0xF; opc1 = (iss >> 14) & 0x7; opc2 = (iss >> 17) & 0x7; } static inline uint32_t mcrrMrrcIssBuild(bool isRead, uint32_t crm, IntRegIndex rt, IntRegIndex rt2, uint32_t opc1) { return (isRead << 0) | (crm << 1) | (rt << 5) | (rt2 << 10) | (opc1 << 16); } static inline uint32_t msrMrs64IssBuild(bool isRead, uint32_t op0, uint32_t op1, uint32_t crn, uint32_t crm, uint32_t op2, IntRegIndex rt) { return isRead | (crm << 1) | (rt << 5) | (crn << 10) | (op1 << 14) | (op2 << 17) | (op0 << 20); } bool mcrMrc15TrapToHyp(const MiscRegIndex miscReg, HCR hcr, CPSR cpsr, SCR scr, HDCR hdcr, HSTR hstr, HCPTR hcptr, uint32_t iss); bool mcrMrc14TrapToHyp(const MiscRegIndex miscReg, HCR hcr, CPSR cpsr, SCR scr, HDCR hdcr, HSTR hstr, HCPTR hcptr, uint32_t iss); bool mcrrMrrc15TrapToHyp(const MiscRegIndex miscReg, CPSR cpsr, SCR scr, HSTR hstr, HCR hcr, uint32_t iss); bool SPAlignmentCheckEnabled(ThreadContext* tc); uint64_t getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp); void skipFunction(ThreadContext *tc); inline void advancePC(PCState &pc, const StaticInstPtr &inst) { inst->advancePC(pc); } Addr truncPage(Addr addr); Addr roundPage(Addr addr); inline uint64_t getExecutingAsid(ThreadContext *tc) { return tc->readMiscReg(MISCREG_CONTEXTIDR); } // Decodes the register index to access based on the fields used in a MSR // or MRS instruction bool decodeMrsMsrBankedReg(uint8_t sysM, bool r, bool &isIntReg, int ®Idx, CPSR cpsr, SCR scr, NSACR nsacr, bool checkSecurity = true); // This wrapper function is used to turn the register index into a source // parameter for the instruction. See Operands.isa static inline int decodeMrsMsrBankedIntRegIndex(uint8_t sysM, bool r) { int regIdx; bool isIntReg; bool validReg; validReg = decodeMrsMsrBankedReg(sysM, r, isIntReg, regIdx, 0, 0, 0, false); return (validReg && isIntReg) ? regIdx : INTREG_DUMMY; } /** * Returns the n. of PA bits corresponding to the specified encoding. */ int decodePhysAddrRange64(uint8_t pa_enc); /** * Returns the encoding corresponding to the specified n. of PA bits. */ uint8_t encodePhysAddrRange64(int pa_size); inline ByteOrder byteOrder(ThreadContext *tc) { return isBigEndian64(tc) ? BigEndianByteOrder : LittleEndianByteOrder; }; } #endif