static_inst.hh revision 12616:4b463b4dc098
18012Ssaidi@eecs.umich.edu/* 28012Ssaidi@eecs.umich.edu * Copyright (c) 2010-2013,2016-2018 ARM Limited 38012Ssaidi@eecs.umich.edu * All rights reserved 48012Ssaidi@eecs.umich.edu * 58012Ssaidi@eecs.umich.edu * The license below extends only to copyright in the software and shall 68012Ssaidi@eecs.umich.edu * not be construed as granting a license to any other intellectual 78012Ssaidi@eecs.umich.edu * property including but not limited to intellectual property relating 88012Ssaidi@eecs.umich.edu * to a hardware implementation of the functionality of the software 98012Ssaidi@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 108012Ssaidi@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 118012Ssaidi@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 128012Ssaidi@eecs.umich.edu * modified or unmodified, in source code or in binary form. 138012Ssaidi@eecs.umich.edu * 148012Ssaidi@eecs.umich.edu * Copyright (c) 2007-2008 The Florida State University 158012Ssaidi@eecs.umich.edu * All rights reserved. 168012Ssaidi@eecs.umich.edu * 178012Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 188012Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are 198012Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright 208012Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 218012Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 228012Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 238012Ssaidi@eecs.umich.edu * documentation and/or other materials provided with the distribution; 248012Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its 258012Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from 268012Ssaidi@eecs.umich.edu * this software without specific prior written permission. 278012Ssaidi@eecs.umich.edu * 288012Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 298012Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 308012Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 318012Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 328012Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 338012Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 348012Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 358012Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 368012Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 378012Ssaidi@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 388012Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 398012Ssaidi@eecs.umich.edu * 408012Ssaidi@eecs.umich.edu * Authors: Stephen Hines 418012Ssaidi@eecs.umich.edu */ 428012Ssaidi@eecs.umich.edu#ifndef __ARCH_ARM_INSTS_STATICINST_HH__ 438012Ssaidi@eecs.umich.edu#define __ARCH_ARM_INSTS_STATICINST_HH__ 448012Ssaidi@eecs.umich.edu 458012Ssaidi@eecs.umich.edu#include <memory> 468012Ssaidi@eecs.umich.edu 478012Ssaidi@eecs.umich.edu#include "arch/arm/faults.hh" 488012Ssaidi@eecs.umich.edu#include "arch/arm/utility.hh" 498012Ssaidi@eecs.umich.edu#include "arch/arm/system.hh" 508012Ssaidi@eecs.umich.edu#include "base/trace.hh" 518008Ssaidi@eecs.umich.edu#include "cpu/exec_context.hh" 528008Ssaidi@eecs.umich.edu#include "cpu/static_inst.hh" 538008Ssaidi@eecs.umich.edu#include "sim/byteswap.hh" 548008Ssaidi@eecs.umich.edu#include "sim/full_system.hh" 558008Ssaidi@eecs.umich.edu 568008Ssaidi@eecs.umich.edunamespace ArmISA 578008Ssaidi@eecs.umich.edu{ 588008Ssaidi@eecs.umich.edu 598008Ssaidi@eecs.umich.educlass ArmStaticInst : public StaticInst 608008Ssaidi@eecs.umich.edu{ 618008Ssaidi@eecs.umich.edu protected: 628008Ssaidi@eecs.umich.edu bool aarch64; 638008Ssaidi@eecs.umich.edu uint8_t intWidth; 648008Ssaidi@eecs.umich.edu 658008Ssaidi@eecs.umich.edu int32_t shift_rm_imm(uint32_t base, uint32_t shamt, 668008Ssaidi@eecs.umich.edu uint32_t type, uint32_t cfval) const; 678008Ssaidi@eecs.umich.edu int32_t shift_rm_rs(uint32_t base, uint32_t shamt, 688008Ssaidi@eecs.umich.edu uint32_t type, uint32_t cfval) const; 698008Ssaidi@eecs.umich.edu 708008Ssaidi@eecs.umich.edu bool shift_carry_imm(uint32_t base, uint32_t shamt, 718008Ssaidi@eecs.umich.edu uint32_t type, uint32_t cfval) const; 728008Ssaidi@eecs.umich.edu bool shift_carry_rs(uint32_t base, uint32_t shamt, 738008Ssaidi@eecs.umich.edu uint32_t type, uint32_t cfval) const; 748008Ssaidi@eecs.umich.edu 758008Ssaidi@eecs.umich.edu int64_t shiftReg64(uint64_t base, uint64_t shiftAmt, 768008Ssaidi@eecs.umich.edu ArmShiftType type, uint8_t width) const; 778008Ssaidi@eecs.umich.edu int64_t extendReg64(uint64_t base, ArmExtendType type, 788008Ssaidi@eecs.umich.edu uint64_t shiftAmt, uint8_t width) const; 798008Ssaidi@eecs.umich.edu 808008Ssaidi@eecs.umich.edu template<int width> 818008Ssaidi@eecs.umich.edu static inline bool 828008Ssaidi@eecs.umich.edu saturateOp(int32_t &res, int64_t op1, int64_t op2, bool sub=false) 838008Ssaidi@eecs.umich.edu { 848008Ssaidi@eecs.umich.edu int64_t midRes = sub ? (op1 - op2) : (op1 + op2); 858008Ssaidi@eecs.umich.edu if (bits(midRes, width) != bits(midRes, width - 1)) { 868008Ssaidi@eecs.umich.edu if (midRes > 0) 878008Ssaidi@eecs.umich.edu res = (LL(1) << (width - 1)) - 1; 888008Ssaidi@eecs.umich.edu else 898008Ssaidi@eecs.umich.edu res = -(LL(1) << (width - 1)); 908008Ssaidi@eecs.umich.edu return true; 918008Ssaidi@eecs.umich.edu } else { 928008Ssaidi@eecs.umich.edu res = midRes; 938008Ssaidi@eecs.umich.edu return false; 948008Ssaidi@eecs.umich.edu } 958008Ssaidi@eecs.umich.edu } 968008Ssaidi@eecs.umich.edu 978008Ssaidi@eecs.umich.edu static inline bool 988008Ssaidi@eecs.umich.edu satInt(int32_t &res, int64_t op, int width) 998008Ssaidi@eecs.umich.edu { 1008008Ssaidi@eecs.umich.edu width--; 1018008Ssaidi@eecs.umich.edu if (op >= (LL(1) << width)) { 1028008Ssaidi@eecs.umich.edu res = (LL(1) << width) - 1; 1038008Ssaidi@eecs.umich.edu return true; 1048008Ssaidi@eecs.umich.edu } else if (op < -(LL(1) << width)) { 1058008Ssaidi@eecs.umich.edu res = -(LL(1) << width); 1068008Ssaidi@eecs.umich.edu return true; 1078008Ssaidi@eecs.umich.edu } else { 1088008Ssaidi@eecs.umich.edu res = op; 1098008Ssaidi@eecs.umich.edu return false; 1108008Ssaidi@eecs.umich.edu } 1118008Ssaidi@eecs.umich.edu } 1128008Ssaidi@eecs.umich.edu 1138008Ssaidi@eecs.umich.edu template<int width> 1148008Ssaidi@eecs.umich.edu static inline bool 1158008Ssaidi@eecs.umich.edu uSaturateOp(uint32_t &res, int64_t op1, int64_t op2, bool sub=false) 1168008Ssaidi@eecs.umich.edu { 1178008Ssaidi@eecs.umich.edu int64_t midRes = sub ? (op1 - op2) : (op1 + op2); 1188008Ssaidi@eecs.umich.edu if (midRes >= (LL(1) << width)) { 1198008Ssaidi@eecs.umich.edu res = (LL(1) << width) - 1; 1208008Ssaidi@eecs.umich.edu return true; 1218008Ssaidi@eecs.umich.edu } else if (midRes < 0) { 1228008Ssaidi@eecs.umich.edu res = 0; 1238008Ssaidi@eecs.umich.edu return true; 1248008Ssaidi@eecs.umich.edu } else { 1258008Ssaidi@eecs.umich.edu res = midRes; 1268008Ssaidi@eecs.umich.edu return false; 1278008Ssaidi@eecs.umich.edu } 1288008Ssaidi@eecs.umich.edu } 1298008Ssaidi@eecs.umich.edu 1308008Ssaidi@eecs.umich.edu static inline bool 1318008Ssaidi@eecs.umich.edu uSatInt(int32_t &res, int64_t op, int width) 1328008Ssaidi@eecs.umich.edu { 1338008Ssaidi@eecs.umich.edu if (op >= (LL(1) << width)) { 1348008Ssaidi@eecs.umich.edu res = (LL(1) << width) - 1; 1358008Ssaidi@eecs.umich.edu return true; 1368008Ssaidi@eecs.umich.edu } else if (op < 0) { 1378008Ssaidi@eecs.umich.edu res = 0; 1388008Ssaidi@eecs.umich.edu return true; 1398008Ssaidi@eecs.umich.edu } else { 1408008Ssaidi@eecs.umich.edu res = op; 1418008Ssaidi@eecs.umich.edu return false; 1428008Ssaidi@eecs.umich.edu } 1438008Ssaidi@eecs.umich.edu } 1448008Ssaidi@eecs.umich.edu 1458008Ssaidi@eecs.umich.edu // Constructor 1468008Ssaidi@eecs.umich.edu ArmStaticInst(const char *mnem, ExtMachInst _machInst, 1478008Ssaidi@eecs.umich.edu OpClass __opClass) 1488008Ssaidi@eecs.umich.edu : StaticInst(mnem, _machInst, __opClass) 1498008Ssaidi@eecs.umich.edu { 1508008Ssaidi@eecs.umich.edu aarch64 = machInst.aarch64; 1518008Ssaidi@eecs.umich.edu if (bits(machInst, 28, 24) == 0x10) 1528008Ssaidi@eecs.umich.edu intWidth = 64; // Force 64-bit width for ADR/ADRP 1538008Ssaidi@eecs.umich.edu else 1548008Ssaidi@eecs.umich.edu intWidth = (aarch64 && bits(machInst, 31)) ? 64 : 32; 1558008Ssaidi@eecs.umich.edu } 1568008Ssaidi@eecs.umich.edu 1578008Ssaidi@eecs.umich.edu /// Print a register name for disassembly given the unique 1588008Ssaidi@eecs.umich.edu /// dependence tag number (FP or int). 1598008Ssaidi@eecs.umich.edu void printIntReg(std::ostream &os, RegIndex reg_idx) const; 1608008Ssaidi@eecs.umich.edu void printFloatReg(std::ostream &os, RegIndex reg_idx) const; 1618008Ssaidi@eecs.umich.edu void printVecReg(std::ostream &os, RegIndex reg_idx) const; 1628008Ssaidi@eecs.umich.edu void printCCReg(std::ostream &os, RegIndex reg_idx) const; 1638008Ssaidi@eecs.umich.edu void printMiscReg(std::ostream &os, RegIndex reg_idx) const; 1648008Ssaidi@eecs.umich.edu void printMnemonic(std::ostream &os, 1658008Ssaidi@eecs.umich.edu const std::string &suffix = "", 1668008Ssaidi@eecs.umich.edu bool withPred = true, 1678008Ssaidi@eecs.umich.edu bool withCond64 = false, 1688008Ssaidi@eecs.umich.edu ConditionCode cond64 = COND_UC) const; 1698008Ssaidi@eecs.umich.edu void printTarget(std::ostream &os, Addr target, 1708008Ssaidi@eecs.umich.edu const SymbolTable *symtab) const; 1718008Ssaidi@eecs.umich.edu void printCondition(std::ostream &os, unsigned code, 1728008Ssaidi@eecs.umich.edu bool noImplicit=false) const; 1738008Ssaidi@eecs.umich.edu void printMemSymbol(std::ostream &os, const SymbolTable *symtab, 1748008Ssaidi@eecs.umich.edu const std::string &prefix, const Addr addr, 1758008Ssaidi@eecs.umich.edu const std::string &suffix) const; 1768008Ssaidi@eecs.umich.edu void printShiftOperand(std::ostream &os, IntRegIndex rm, 1778008Ssaidi@eecs.umich.edu bool immShift, uint32_t shiftAmt, 1788008Ssaidi@eecs.umich.edu IntRegIndex rs, ArmShiftType type) const; 1798008Ssaidi@eecs.umich.edu void printExtendOperand(bool firstOperand, std::ostream &os, 1808008Ssaidi@eecs.umich.edu IntRegIndex rm, ArmExtendType type, 1818008Ssaidi@eecs.umich.edu int64_t shiftAmt) const; 1828008Ssaidi@eecs.umich.edu 1838008Ssaidi@eecs.umich.edu 1848008Ssaidi@eecs.umich.edu void printDataInst(std::ostream &os, bool withImm) const; 1858008Ssaidi@eecs.umich.edu void printDataInst(std::ostream &os, bool withImm, bool immShift, bool s, 1868008Ssaidi@eecs.umich.edu IntRegIndex rd, IntRegIndex rn, IntRegIndex rm, 1878008Ssaidi@eecs.umich.edu IntRegIndex rs, uint32_t shiftAmt, ArmShiftType type, 1888008Ssaidi@eecs.umich.edu uint64_t imm) const; 1898008Ssaidi@eecs.umich.edu 1908008Ssaidi@eecs.umich.edu void 1918008Ssaidi@eecs.umich.edu advancePC(PCState &pcState) const override 1928008Ssaidi@eecs.umich.edu { 1938008Ssaidi@eecs.umich.edu pcState.advance(); 1948008Ssaidi@eecs.umich.edu } 1958008Ssaidi@eecs.umich.edu 1968008Ssaidi@eecs.umich.edu std::string generateDisassembly( 1978008Ssaidi@eecs.umich.edu Addr pc, const SymbolTable *symtab) const override; 1988008Ssaidi@eecs.umich.edu 1998008Ssaidi@eecs.umich.edu static inline uint32_t 2008008Ssaidi@eecs.umich.edu cpsrWriteByInstr(CPSR cpsr, uint32_t val, SCR scr, NSACR nsacr, 2018008Ssaidi@eecs.umich.edu uint8_t byteMask, bool affectState, bool nmfi, ThreadContext *tc) 2028008Ssaidi@eecs.umich.edu { 2038008Ssaidi@eecs.umich.edu bool privileged = (cpsr.mode != MODE_USER); 2048008Ssaidi@eecs.umich.edu bool haveVirt = ArmSystem::haveVirtualization(tc); 2058008Ssaidi@eecs.umich.edu bool haveSecurity = ArmSystem::haveSecurity(tc); 2068008Ssaidi@eecs.umich.edu bool isSecure = inSecureState(scr, cpsr) || !haveSecurity; 2078008Ssaidi@eecs.umich.edu 2088008Ssaidi@eecs.umich.edu uint32_t bitMask = 0; 2098008Ssaidi@eecs.umich.edu 2108008Ssaidi@eecs.umich.edu if (bits(byteMask, 3)) { 2118008Ssaidi@eecs.umich.edu unsigned lowIdx = affectState ? 24 : 27; 2128008Ssaidi@eecs.umich.edu bitMask = bitMask | mask(31, lowIdx); 2138008Ssaidi@eecs.umich.edu } 2148008Ssaidi@eecs.umich.edu if (bits(byteMask, 2)) { 2158008Ssaidi@eecs.umich.edu bitMask = bitMask | mask(19, 16); 2168008Ssaidi@eecs.umich.edu } 2178008Ssaidi@eecs.umich.edu if (bits(byteMask, 1)) { 2188008Ssaidi@eecs.umich.edu unsigned highIdx = affectState ? 15 : 9; 2198008Ssaidi@eecs.umich.edu unsigned lowIdx = (privileged && (isSecure || scr.aw || haveVirt)) 2208008Ssaidi@eecs.umich.edu ? 8 : 9; 2218008Ssaidi@eecs.umich.edu bitMask = bitMask | mask(highIdx, lowIdx); 2228008Ssaidi@eecs.umich.edu } 2238008Ssaidi@eecs.umich.edu if (bits(byteMask, 0)) { 2248008Ssaidi@eecs.umich.edu if (privileged) { 2258008Ssaidi@eecs.umich.edu bitMask |= 1 << 7; 2268008Ssaidi@eecs.umich.edu if ( (!nmfi || !((val >> 6) & 0x1)) && 2278008Ssaidi@eecs.umich.edu (isSecure || scr.fw || haveVirt) ) { 2288008Ssaidi@eecs.umich.edu bitMask |= 1 << 6; 2298008Ssaidi@eecs.umich.edu } 2308008Ssaidi@eecs.umich.edu // Now check the new mode is allowed 2318008Ssaidi@eecs.umich.edu OperatingMode newMode = (OperatingMode) (val & mask(5)); 2328008Ssaidi@eecs.umich.edu OperatingMode oldMode = (OperatingMode)(uint32_t)cpsr.mode; 2338008Ssaidi@eecs.umich.edu if (!badMode(newMode)) { 2348008Ssaidi@eecs.umich.edu bool validModeChange = true; 2358008Ssaidi@eecs.umich.edu // Check for attempts to enter modes only permitted in 2368008Ssaidi@eecs.umich.edu // Secure state from Non-secure state. These are Monitor 2378008Ssaidi@eecs.umich.edu // mode ('10110'), and FIQ mode ('10001') if the Security 2388008Ssaidi@eecs.umich.edu // Extensions have reserved it. 2398008Ssaidi@eecs.umich.edu if (!isSecure && newMode == MODE_MON) 2408008Ssaidi@eecs.umich.edu validModeChange = false; 2418008Ssaidi@eecs.umich.edu if (!isSecure && newMode == MODE_FIQ && nsacr.rfr == '1') 2428008Ssaidi@eecs.umich.edu validModeChange = false; 2438008Ssaidi@eecs.umich.edu // There is no Hyp mode ('11010') in Secure state, so that 2448008Ssaidi@eecs.umich.edu // is UNPREDICTABLE 2458008Ssaidi@eecs.umich.edu if (scr.ns == '0' && newMode == MODE_HYP) 2468008Ssaidi@eecs.umich.edu validModeChange = false; 2478008Ssaidi@eecs.umich.edu // Cannot move into Hyp mode directly from a Non-secure 2488008Ssaidi@eecs.umich.edu // PL1 mode 2498008Ssaidi@eecs.umich.edu if (!isSecure && oldMode != MODE_HYP && newMode == MODE_HYP) 2508008Ssaidi@eecs.umich.edu validModeChange = false; 2518008Ssaidi@eecs.umich.edu // Cannot move out of Hyp mode with this function except 2528008Ssaidi@eecs.umich.edu // on an exception return 2538008Ssaidi@eecs.umich.edu if (oldMode == MODE_HYP && newMode != MODE_HYP && !affectState) 2548008Ssaidi@eecs.umich.edu validModeChange = false; 2558008Ssaidi@eecs.umich.edu // Must not change to 64 bit when running in 32 bit mode 2568008Ssaidi@eecs.umich.edu if (!opModeIs64(oldMode) && opModeIs64(newMode)) 2578008Ssaidi@eecs.umich.edu validModeChange = false; 2588008Ssaidi@eecs.umich.edu 2598008Ssaidi@eecs.umich.edu // If we passed all of the above then set the bit mask to 2608008Ssaidi@eecs.umich.edu // copy the mode accross 2618008Ssaidi@eecs.umich.edu if (validModeChange) { 2628008Ssaidi@eecs.umich.edu bitMask = bitMask | mask(5); 2638008Ssaidi@eecs.umich.edu } else { 2648008Ssaidi@eecs.umich.edu warn_once("Illegal change to CPSR mode attempted\n"); 2658008Ssaidi@eecs.umich.edu } 2668008Ssaidi@eecs.umich.edu } else { 2678008Ssaidi@eecs.umich.edu warn_once("Ignoring write of bad mode to CPSR.\n"); 2688008Ssaidi@eecs.umich.edu } 2698008Ssaidi@eecs.umich.edu } 2708008Ssaidi@eecs.umich.edu if (affectState) 2718008Ssaidi@eecs.umich.edu bitMask = bitMask | (1 << 5); 2728008Ssaidi@eecs.umich.edu } 2738008Ssaidi@eecs.umich.edu 2748008Ssaidi@eecs.umich.edu return ((uint32_t)cpsr & ~bitMask) | (val & bitMask); 2758008Ssaidi@eecs.umich.edu } 2768008Ssaidi@eecs.umich.edu 2778008Ssaidi@eecs.umich.edu static inline uint32_t 2788008Ssaidi@eecs.umich.edu spsrWriteByInstr(uint32_t spsr, uint32_t val, 2798008Ssaidi@eecs.umich.edu uint8_t byteMask, bool affectState) 2808008Ssaidi@eecs.umich.edu { 2818008Ssaidi@eecs.umich.edu uint32_t bitMask = 0; 2828008Ssaidi@eecs.umich.edu 2838008Ssaidi@eecs.umich.edu if (bits(byteMask, 3)) 2848008Ssaidi@eecs.umich.edu bitMask = bitMask | mask(31, 24); 2858008Ssaidi@eecs.umich.edu if (bits(byteMask, 2)) 2868008Ssaidi@eecs.umich.edu bitMask = bitMask | mask(19, 16); 2878008Ssaidi@eecs.umich.edu if (bits(byteMask, 1)) 2888008Ssaidi@eecs.umich.edu bitMask = bitMask | mask(15, 8); 2898008Ssaidi@eecs.umich.edu if (bits(byteMask, 0)) 2908008Ssaidi@eecs.umich.edu bitMask = bitMask | mask(7, 0); 2918008Ssaidi@eecs.umich.edu 2928008Ssaidi@eecs.umich.edu return ((spsr & ~bitMask) | (val & bitMask)); 293 } 294 295 static inline Addr 296 readPC(ExecContext *xc) 297 { 298 return xc->pcState().instPC(); 299 } 300 301 static inline void 302 setNextPC(ExecContext *xc, Addr val) 303 { 304 PCState pc = xc->pcState(); 305 pc.instNPC(val); 306 xc->pcState(pc); 307 } 308 309 template<class T> 310 static inline T 311 cSwap(T val, bool big) 312 { 313 if (big) { 314 return gtobe(val); 315 } else { 316 return gtole(val); 317 } 318 } 319 320 template<class T, class E> 321 static inline T 322 cSwap(T val, bool big) 323 { 324 const unsigned count = sizeof(T) / sizeof(E); 325 union { 326 T tVal; 327 E eVals[count]; 328 } conv; 329 conv.tVal = htog(val); 330 if (big) { 331 for (unsigned i = 0; i < count; i++) { 332 conv.eVals[i] = gtobe(conv.eVals[i]); 333 } 334 } else { 335 for (unsigned i = 0; i < count; i++) { 336 conv.eVals[i] = gtole(conv.eVals[i]); 337 } 338 } 339 return gtoh(conv.tVal); 340 } 341 342 // Perform an interworking branch. 343 static inline void 344 setIWNextPC(ExecContext *xc, Addr val) 345 { 346 PCState pc = xc->pcState(); 347 pc.instIWNPC(val); 348 xc->pcState(pc); 349 } 350 351 // Perform an interworking branch in ARM mode, a regular branch 352 // otherwise. 353 static inline void 354 setAIWNextPC(ExecContext *xc, Addr val) 355 { 356 PCState pc = xc->pcState(); 357 pc.instAIWNPC(val); 358 xc->pcState(pc); 359 } 360 361 inline Fault 362 disabledFault() const 363 { 364 return std::make_shared<UndefinedInstruction>(machInst, false, 365 mnemonic, true); 366 } 367 368 // Utility function used by checkForWFxTrap32 and checkForWFxTrap64 369 // Returns true if processor has to trap a WFI/WFE instruction. 370 bool isWFxTrapping(ThreadContext *tc, 371 ExceptionLevel targetEL, bool isWfe) const; 372 373 /** 374 * Trap an access to Advanced SIMD or FP registers due to access 375 * control bits. 376 * 377 * See aarch64/exceptions/traps/AArch64.AdvSIMDFPAccessTrap in the 378 * ARM ARM psueodcode library. 379 * 380 * @param el Target EL for the trap 381 */ 382 Fault advSIMDFPAccessTrap64(ExceptionLevel el) const; 383 384 385 /** 386 * Check an Advaned SIMD access against CPTR_EL2 and CPTR_EL3. 387 * 388 * See aarch64/exceptions/traps/AArch64.CheckFPAdvSIMDTrap in the 389 * ARM ARM psueodcode library. 390 */ 391 Fault checkFPAdvSIMDTrap64(ThreadContext *tc, CPSR cpsr) const; 392 393 /** 394 * Check an Advaned SIMD access against CPACR_EL1, CPTR_EL2, and 395 * CPTR_EL3. 396 * 397 * See aarch64/exceptions/traps/AArch64.CheckFPAdvSIMDEnabled in the 398 * ARM ARM psueodcode library. 399 */ 400 Fault checkFPAdvSIMDEnabled64(ThreadContext *tc, 401 CPSR cpsr, CPACR cpacr) const; 402 403 /** 404 * Check if a VFP/SIMD access from aarch32 should be allowed. 405 * 406 * See aarch32/exceptions/traps/AArch32.CheckAdvSIMDOrFPEnabled in the 407 * ARM ARM psueodcode library. 408 */ 409 Fault checkAdvSIMDOrFPEnabled32(ThreadContext *tc, 410 CPSR cpsr, CPACR cpacr, 411 NSACR nsacr, FPEXC fpexc, 412 bool fpexc_check, bool advsimd) const; 413 414 /** 415 * Check if WFE/WFI instruction execution in aarch32 should be trapped. 416 * 417 * See aarch32/exceptions/traps/AArch32.checkForWFxTrap in the 418 * ARM ARM psueodcode library. 419 */ 420 Fault checkForWFxTrap32(ThreadContext *tc, 421 ExceptionLevel tgtEl, bool isWfe) const; 422 423 /** 424 * Check if WFE/WFI instruction execution in aarch64 should be trapped. 425 * 426 * See aarch64/exceptions/traps/AArch64.checkForWFxTrap in the 427 * ARM ARM psueodcode library. 428 */ 429 Fault checkForWFxTrap64(ThreadContext *tc, 430 ExceptionLevel tgtEl, bool isWfe) const; 431 432 /** 433 * WFE/WFI trapping helper function. 434 */ 435 Fault trapWFx(ThreadContext *tc, CPSR cpsr, SCR scr, bool isWfe) const; 436 437 /** 438 * Check if SETEND instruction execution in aarch32 should be trapped. 439 * 440 * See aarch32/exceptions/traps/AArch32.CheckSETENDEnabled in the 441 * ARM ARM pseudocode library. 442 */ 443 Fault checkSETENDEnabled(ThreadContext *tc, CPSR cpsr) const; 444 445 /** 446 * UNDEFINED behaviour in AArch32 447 * 448 * See aarch32/exceptions/traps/AArch32.UndefinedFault in the 449 * ARM ARM pseudocode library. 450 */ 451 Fault undefinedFault32(ThreadContext *tc, ExceptionLevel el) const; 452 453 /** 454 * UNDEFINED behaviour in AArch64 455 * 456 * See aarch64/exceptions/traps/AArch64.UndefinedFault in the 457 * ARM ARM pseudocode library. 458 */ 459 Fault undefinedFault64(ThreadContext *tc, ExceptionLevel el) const; 460 461 /** 462 * Get the new PSTATE from a SPSR register in preparation for an 463 * exception return. 464 * 465 * See shared/functions/system/SetPSTATEFromPSR in the ARM ARM 466 * pseudocode library. 467 */ 468 CPSR getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const; 469 470 /** 471 * Return true if exceptions normally routed to EL1 are being handled 472 * at an Exception level using AArch64, because either EL1 is using 473 * AArch64 or TGE is in force and EL2 is using AArch64. 474 * 475 * See aarch32/exceptions/exceptions/AArch32.GeneralExceptionsToAArch64 476 * in the ARM ARM pseudocode library. 477 */ 478 bool generalExceptionsToAArch64(ThreadContext *tc, 479 ExceptionLevel pstateEL) const; 480 481 public: 482 virtual void 483 annotateFault(ArmFault *fault) {} 484 485 uint8_t 486 getIntWidth() const 487 { 488 return intWidth; 489 } 490 491 /** Returns the byte size of current instruction */ 492 ssize_t 493 instSize() const 494 { 495 return (!machInst.thumb || machInst.bigThumb) ? 4 : 2; 496 } 497 498 /** 499 * Returns the real encoding of the instruction: 500 * the machInst field is in fact always 64 bit wide and 501 * contains some instruction metadata, which means it differs 502 * from the real opcode. 503 */ 504 MachInst 505 encoding() const 506 { 507 return static_cast<MachInst>(machInst & (mask(instSize() * 8))); 508 } 509 510 size_t 511 asBytes(void *buf, size_t max_size) override 512 { 513 return simpleAsBytes(buf, max_size, machInst); 514 } 515}; 516} 517 518#endif //__ARCH_ARM_INSTS_STATICINST_HH__ 519