ARMAddressingModes.h revision f49810c7e60807c43a68ab02c936a4ee77a4d2cf
1a8e2989ece6dc46df59b0768184028257f913843Evan Cheng//===- ARMAddressingModes.h - ARM Addressing Modes --------------*- C++ -*-===// 2a8e2989ece6dc46df59b0768184028257f913843Evan Cheng// 3a8e2989ece6dc46df59b0768184028257f913843Evan Cheng// The LLVM Compiler Infrastructure 4a8e2989ece6dc46df59b0768184028257f913843Evan Cheng// 54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source 64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details. 7a8e2989ece6dc46df59b0768184028257f913843Evan Cheng// 8a8e2989ece6dc46df59b0768184028257f913843Evan Cheng//===----------------------------------------------------------------------===// 9a8e2989ece6dc46df59b0768184028257f913843Evan Cheng// 10a8e2989ece6dc46df59b0768184028257f913843Evan Cheng// This file contains the ARM addressing mode implementation stuff. 11a8e2989ece6dc46df59b0768184028257f913843Evan Cheng// 12a8e2989ece6dc46df59b0768184028257f913843Evan Cheng//===----------------------------------------------------------------------===// 13a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 14a8e2989ece6dc46df59b0768184028257f913843Evan Cheng#ifndef LLVM_TARGET_ARM_ARMADDRESSINGMODES_H 15a8e2989ece6dc46df59b0768184028257f913843Evan Cheng#define LLVM_TARGET_ARM_ARMADDRESSINGMODES_H 16a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 17a8e2989ece6dc46df59b0768184028257f913843Evan Cheng#include "llvm/CodeGen/SelectionDAGNodes.h" 18a8e2989ece6dc46df59b0768184028257f913843Evan Cheng#include "llvm/Support/MathExtras.h" 19a8e2989ece6dc46df59b0768184028257f913843Evan Cheng#include <cassert> 20a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 21a8e2989ece6dc46df59b0768184028257f913843Evan Chengnamespace llvm { 22a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 23a8e2989ece6dc46df59b0768184028257f913843Evan Cheng/// ARM_AM - ARM Addressing Mode Stuff 24a8e2989ece6dc46df59b0768184028257f913843Evan Chengnamespace ARM_AM { 25a8e2989ece6dc46df59b0768184028257f913843Evan Cheng enum ShiftOpc { 26a8e2989ece6dc46df59b0768184028257f913843Evan Cheng no_shift = 0, 27a8e2989ece6dc46df59b0768184028257f913843Evan Cheng asr, 28a8e2989ece6dc46df59b0768184028257f913843Evan Cheng lsl, 29a8e2989ece6dc46df59b0768184028257f913843Evan Cheng lsr, 30a8e2989ece6dc46df59b0768184028257f913843Evan Cheng ror, 31a8e2989ece6dc46df59b0768184028257f913843Evan Cheng rrx 32a8e2989ece6dc46df59b0768184028257f913843Evan Cheng }; 33a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 34a8e2989ece6dc46df59b0768184028257f913843Evan Cheng enum AddrOpc { 35a8e2989ece6dc46df59b0768184028257f913843Evan Cheng add = '+', sub = '-' 36a8e2989ece6dc46df59b0768184028257f913843Evan Cheng }; 37a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 38a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline const char *getShiftOpcStr(ShiftOpc Op) { 39a8e2989ece6dc46df59b0768184028257f913843Evan Cheng switch (Op) { 40a8e2989ece6dc46df59b0768184028257f913843Evan Cheng default: assert(0 && "Unknown shift opc!"); 41a8e2989ece6dc46df59b0768184028257f913843Evan Cheng case ARM_AM::asr: return "asr"; 42a8e2989ece6dc46df59b0768184028257f913843Evan Cheng case ARM_AM::lsl: return "lsl"; 43a8e2989ece6dc46df59b0768184028257f913843Evan Cheng case ARM_AM::lsr: return "lsr"; 44a8e2989ece6dc46df59b0768184028257f913843Evan Cheng case ARM_AM::ror: return "ror"; 45a8e2989ece6dc46df59b0768184028257f913843Evan Cheng case ARM_AM::rrx: return "rrx"; 46a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 47a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 48a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 49475871a144eb604ddaf37503397ba0941442e5fbDan Gohman static inline ShiftOpc getShiftOpcForNode(SDValue N) { 50a8e2989ece6dc46df59b0768184028257f913843Evan Cheng switch (N.getOpcode()) { 51a8e2989ece6dc46df59b0768184028257f913843Evan Cheng default: return ARM_AM::no_shift; 52a8e2989ece6dc46df59b0768184028257f913843Evan Cheng case ISD::SHL: return ARM_AM::lsl; 53a8e2989ece6dc46df59b0768184028257f913843Evan Cheng case ISD::SRL: return ARM_AM::lsr; 54a8e2989ece6dc46df59b0768184028257f913843Evan Cheng case ISD::SRA: return ARM_AM::asr; 55a8e2989ece6dc46df59b0768184028257f913843Evan Cheng case ISD::ROTR: return ARM_AM::ror; 56a8e2989ece6dc46df59b0768184028257f913843Evan Cheng //case ISD::ROTL: // Only if imm -> turn into ROTR. 57a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // Can't handle RRX here, because it would require folding a flag into 58a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // the addressing mode. :( This causes us to miss certain things. 59a8e2989ece6dc46df59b0768184028257f913843Evan Cheng //case ARMISD::RRX: return ARM_AM::rrx; 60a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 61a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 62a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 63a8e2989ece6dc46df59b0768184028257f913843Evan Cheng enum AMSubMode { 64a8e2989ece6dc46df59b0768184028257f913843Evan Cheng bad_am_submode = 0, 65a8e2989ece6dc46df59b0768184028257f913843Evan Cheng ia, 66a8e2989ece6dc46df59b0768184028257f913843Evan Cheng ib, 67a8e2989ece6dc46df59b0768184028257f913843Evan Cheng da, 68a8e2989ece6dc46df59b0768184028257f913843Evan Cheng db 69a8e2989ece6dc46df59b0768184028257f913843Evan Cheng }; 70a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 71a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline const char *getAMSubModeStr(AMSubMode Mode) { 72a8e2989ece6dc46df59b0768184028257f913843Evan Cheng switch (Mode) { 73a8e2989ece6dc46df59b0768184028257f913843Evan Cheng default: assert(0 && "Unknown addressing sub-mode!"); 74a8e2989ece6dc46df59b0768184028257f913843Evan Cheng case ARM_AM::ia: return "ia"; 75a8e2989ece6dc46df59b0768184028257f913843Evan Cheng case ARM_AM::ib: return "ib"; 76a8e2989ece6dc46df59b0768184028257f913843Evan Cheng case ARM_AM::da: return "da"; 77a8e2989ece6dc46df59b0768184028257f913843Evan Cheng case ARM_AM::db: return "db"; 78a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 79a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 80a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 81a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline const char *getAMSubModeAltStr(AMSubMode Mode, bool isLD) { 82a8e2989ece6dc46df59b0768184028257f913843Evan Cheng switch (Mode) { 83a8e2989ece6dc46df59b0768184028257f913843Evan Cheng default: assert(0 && "Unknown addressing sub-mode!"); 84a8e2989ece6dc46df59b0768184028257f913843Evan Cheng case ARM_AM::ia: return isLD ? "fd" : "ea"; 85a8e2989ece6dc46df59b0768184028257f913843Evan Cheng case ARM_AM::ib: return isLD ? "ed" : "fa"; 86a8e2989ece6dc46df59b0768184028257f913843Evan Cheng case ARM_AM::da: return isLD ? "fa" : "ed"; 87a8e2989ece6dc46df59b0768184028257f913843Evan Cheng case ARM_AM::db: return isLD ? "ea" : "fd"; 88a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 89a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 90a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 91a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// rotr32 - Rotate a 32-bit unsigned value right by a specified # bits. 92a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// 93a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline unsigned rotr32(unsigned Val, unsigned Amt) { 94a8e2989ece6dc46df59b0768184028257f913843Evan Cheng assert(Amt < 32 && "Invalid rotate amount"); 95a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return (Val >> Amt) | (Val << ((32-Amt)&31)); 96a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 97a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 98a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// rotl32 - Rotate a 32-bit unsigned value left by a specified # bits. 99a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// 100a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline unsigned rotl32(unsigned Val, unsigned Amt) { 101a8e2989ece6dc46df59b0768184028257f913843Evan Cheng assert(Amt < 32 && "Invalid rotate amount"); 102a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return (Val << Amt) | (Val >> ((32-Amt)&31)); 103a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 104a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 105a8e2989ece6dc46df59b0768184028257f913843Evan Cheng //===--------------------------------------------------------------------===// 106a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // Addressing Mode #1: shift_operand with registers 107a8e2989ece6dc46df59b0768184028257f913843Evan Cheng //===--------------------------------------------------------------------===// 108a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 109a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // This 'addressing mode' is used for arithmetic instructions. It can 110a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // represent things like: 111a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // reg 112a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // reg [asr|lsl|lsr|ror|rrx] reg 113a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // reg [asr|lsl|lsr|ror|rrx] imm 114a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 115a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // This is stored three operands [rega, regb, opc]. The first is the base 116a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // reg, the second is the shift amount (or reg0 if not present or imm). The 117a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // third operand encodes the shift opcode and the imm if a reg isn't present. 118a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 119a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm) { 120a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return ShOp | (Imm << 3); 121a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 122a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline unsigned getSORegOffset(unsigned Op) { 123a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return Op >> 3; 124a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 125a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline ShiftOpc getSORegShOp(unsigned Op) { 126a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return (ShiftOpc)(Op & 7); 127a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 128a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 129a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// getSOImmValImm - Given an encoded imm field for the reg/imm form, return 130a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// the 8-bit imm value. 131a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline unsigned getSOImmValImm(unsigned Imm) { 132a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return Imm & 0xFF; 133a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 134d83712ad678ae453f3342762c78142f851d3a2d3Bob Wilson /// getSOImmValRot - Given an encoded imm field for the reg/imm form, return 135a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// the rotate amount. 136a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline unsigned getSOImmValRot(unsigned Imm) { 137a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return (Imm >> 8) * 2; 138a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 139a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 140a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// getSOImmValRotate - Try to handle Imm with an immediate shifter operand, 141a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// computing the rotate amount to use. If this immediate value cannot be 142a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// handled with a single shifter-op, determine a good rotate amount that will 143a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// take a maximal chunk of bits out of the immediate. 144a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline unsigned getSOImmValRotate(unsigned Imm) { 145a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 8-bit (or less) immediates are trivially shifter_operands with a rotate 146a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // of zero. 147a8e2989ece6dc46df59b0768184028257f913843Evan Cheng if ((Imm & ~255U) == 0) return 0; 148a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 149a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // Use CTZ to compute the rotate amount. 150a8e2989ece6dc46df59b0768184028257f913843Evan Cheng unsigned TZ = CountTrailingZeros_32(Imm); 151a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 152a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // Rotate amount must be even. Something like 0x200 must be rotated 8 bits, 153a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // not 9. 154a8e2989ece6dc46df59b0768184028257f913843Evan Cheng unsigned RotAmt = TZ & ~1; 155a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 156a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // If we can handle this spread, return it. 157a8e2989ece6dc46df59b0768184028257f913843Evan Cheng if ((rotr32(Imm, RotAmt) & ~255U) == 0) 158a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return (32-RotAmt)&31; // HW rotates right, not left. 159a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 160a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // For values like 0xF000000F, we should skip the first run of ones, then 161a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // retry the hunt. 162a8e2989ece6dc46df59b0768184028257f913843Evan Cheng if (Imm & 1) { 163a8e2989ece6dc46df59b0768184028257f913843Evan Cheng unsigned TrailingOnes = CountTrailingZeros_32(~Imm); 164a8e2989ece6dc46df59b0768184028257f913843Evan Cheng if (TrailingOnes != 32) { // Avoid overflow on 0xFFFFFFFF 165a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // Restart the search for a high-order bit after the initial seconds of 166a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // ones. 167a8e2989ece6dc46df59b0768184028257f913843Evan Cheng unsigned TZ2 = CountTrailingZeros_32(Imm & ~((1 << TrailingOnes)-1)); 168a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 169a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // Rotate amount must be even. 170a8e2989ece6dc46df59b0768184028257f913843Evan Cheng unsigned RotAmt2 = TZ2 & ~1; 171a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 172a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // If this fits, use it. 173a8e2989ece6dc46df59b0768184028257f913843Evan Cheng if (RotAmt2 != 32 && (rotr32(Imm, RotAmt2) & ~255U) == 0) 174a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return (32-RotAmt2)&31; // HW rotates right, not left. 175a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 176a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 177a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 178a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // Otherwise, we have no way to cover this span of bits with a single 179a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // shifter_op immediate. Return a chunk of bits that will be useful to 180a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // handle. 181a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return (32-RotAmt)&31; // HW rotates right, not left. 182a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 183a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 184a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// getSOImmVal - Given a 32-bit immediate, if it is something that can fit 185a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// into an shifter_operand immediate operand, return the 12-bit encoding for 186a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// it. If not, return -1. 187a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline int getSOImmVal(unsigned Arg) { 188a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 8-bit (or less) immediates are trivially shifter_operands with a rotate 189a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // of zero. 190a8e2989ece6dc46df59b0768184028257f913843Evan Cheng if ((Arg & ~255U) == 0) return Arg; 191a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 192a8e2989ece6dc46df59b0768184028257f913843Evan Cheng unsigned RotAmt = getSOImmValRotate(Arg); 193a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 194a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // If this cannot be handled with a single shifter_op, bail out. 195a8e2989ece6dc46df59b0768184028257f913843Evan Cheng if (rotr32(~255U, RotAmt) & Arg) 196a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return -1; 197a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 198a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // Encode this correctly. 199a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return rotl32(Arg, RotAmt) | ((RotAmt>>1) << 8); 200a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 201a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 202a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// isSOImmTwoPartVal - Return true if the specified value can be obtained by 203a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// or'ing together two SOImmVal's. 204a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline bool isSOImmTwoPartVal(unsigned V) { 205a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // If this can be handled with a single shifter_op, bail out. 206a8e2989ece6dc46df59b0768184028257f913843Evan Cheng V = rotr32(~255U, getSOImmValRotate(V)) & V; 207a8e2989ece6dc46df59b0768184028257f913843Evan Cheng if (V == 0) 208a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return false; 209a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 210a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // If this can be handled with two shifter_op's, accept. 211a8e2989ece6dc46df59b0768184028257f913843Evan Cheng V = rotr32(~255U, getSOImmValRotate(V)) & V; 212a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return V == 0; 213a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 214a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 215a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal, 216a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// return the first chunk of it. 217a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline unsigned getSOImmTwoPartFirst(unsigned V) { 218a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return rotr32(255U, getSOImmValRotate(V)) & V; 219a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 220a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 221a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal, 222a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// return the second chunk of it. 223a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline unsigned getSOImmTwoPartSecond(unsigned V) { 224a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // Mask out the first hunk. 225a8e2989ece6dc46df59b0768184028257f913843Evan Cheng V = rotr32(~255U, getSOImmValRotate(V)) & V; 226a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 227a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // Take what's left. 228a8e2989ece6dc46df59b0768184028257f913843Evan Cheng assert(V == (rotr32(255U, getSOImmValRotate(V)) & V)); 229a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return V; 230a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 231a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 232a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// getThumbImmValShift - Try to handle Imm with a 8-bit immediate followed 233a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// by a left shift. Returns the shift amount to use. 234a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline unsigned getThumbImmValShift(unsigned Imm) { 235a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 8-bit (or less) immediates are trivially immediate operand with a shift 236a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // of zero. 237a8e2989ece6dc46df59b0768184028257f913843Evan Cheng if ((Imm & ~255U) == 0) return 0; 238a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 239a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // Use CTZ to compute the shift amount. 240a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return CountTrailingZeros_32(Imm); 241a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 242a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 243a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// isThumbImmShiftedVal - Return true if the specified value can be obtained 244a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// by left shifting a 8-bit immediate. 245a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline bool isThumbImmShiftedVal(unsigned V) { 246a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // If this can be handled with 247a8e2989ece6dc46df59b0768184028257f913843Evan Cheng V = (~255U << getThumbImmValShift(V)) & V; 248a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return V == 0; 249a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 250a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 251f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// getThumbImm16ValShift - Try to handle Imm with a 16-bit immediate followed 252f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// by a left shift. Returns the shift amount to use. 253f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng static inline unsigned getThumbImm16ValShift(unsigned Imm) { 254f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng // 16-bit (or less) immediates are trivially immediate operand with a shift 255f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng // of zero. 256f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng if ((Imm & ~65535U) == 0) return 0; 257f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng 258f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng // Use CTZ to compute the shift amount. 259f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng return CountTrailingZeros_32(Imm); 260f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng } 261f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng 262f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// isThumbImm16ShiftedVal - Return true if the specified value can be 263f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// obtained by left shifting a 16-bit immediate. 264f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng static inline bool isThumbImm16ShiftedVal(unsigned V) { 265f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng // If this can be handled with 266f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng V = (~65535U << getThumbImm16ValShift(V)) & V; 267f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng return V == 0; 268f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng } 269f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng 270a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// getThumbImmNonShiftedVal - If V is a value that satisfies 271a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// isThumbImmShiftedVal, return the non-shiftd value. 272a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline unsigned getThumbImmNonShiftedVal(unsigned V) { 273a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return V >> getThumbImmValShift(V); 274a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 275a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 276f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// getT2SOImmValDecode - Given a 12-bit encoded Thumb-2 modified immediate, 277f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// return the corresponding 32-bit immediate value. 278f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// See ARM Reference Manual A6.3.2. 279f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng static inline unsigned getT2SOImmValDecode(unsigned Imm) { 280f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng unsigned Base = Imm & 0xff; 281f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng switch ((Imm >> 8) & 0xf) { 282f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng case 0: 283f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng return Base; 284f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng case 1: 285f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng return Base | (Base << 16); 286f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng case 2: 287f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng return (Base << 8) | (Base << 24); 288f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng case 3: 289f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng return Base | (Base << 8) | (Base << 16) | (Base << 24); 290f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng default: 291f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng break; 292f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng } 293f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng 294f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng // shifted immediate 295f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng unsigned RotAmount = ((Imm >> 7) & 0x1f) - 8; 296f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng return (Base | 0x80) << (24 - RotAmount); 297f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng } 298f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng 299f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// getT2SOImmValSplat - Return the 12-bit encoded representation 300f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// if the specified value can be obtained by splatting the low 8 bits 301f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// into every other byte or every byte of a 32-bit value. i.e., 302f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// 00000000 00000000 00000000 abcdefgh control = 0 303f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// 00000000 abcdefgh 00000000 abcdefgh control = 1 304f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// abcdefgh 00000000 abcdefgh 00000000 control = 2 305f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// abcdefgh abcdefgh abcdefgh abcdefgh control = 3 306f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// Return -1 if none of the above apply. 307f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// See ARM Reference Manual A6.3.2. 308f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng static inline int getT2SOImmValSplat (unsigned V) { 309f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng unsigned u, Vs, Imm; 310f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng // control = 0 311f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng if ((V & 0xffffff00) == 0) 312f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng return V; 313f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng 314f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng // If the value is zeroes in the first byte, just shift those off 315f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng Vs = ((V & 0xff) == 0) ? V >> 8 : V; 316f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng // Any passing value only has 8 bits of payload, splatted across the word 317f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng Imm = Vs & 0xff; 318f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng // Likewise, any passing values have the payload splatted into the 3rd byte 319f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng u = Imm | (Imm << 16); 320f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng 321f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng // control = 1 or 2 322f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng if (Vs == u) 323f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng return (((Vs == V) ? 1 : 2) << 8) | Imm; 324f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng 325f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng // control = 3 326f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng if (Vs == (u | (u << 8))) 327f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng return (3 << 8) | Imm; 328f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng 329f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng return -1; 330f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng } 331f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng 332f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// getT2SOImmValRotate - Return the 12-bit encoded representation if the 333f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// specified value is a rotated 8-bit value. Return -1 if no rotation 334f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// encoding is possible. 335f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// See ARM Reference Manual A6.3.2. 336f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng static inline int getT2SOImmValRotate (unsigned V) { 337f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng unsigned RotAmt = CountLeadingZeros_32(V); 338f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng if (RotAmt >= 24) 339f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng return -1; 340f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng 341f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng // If 'Arg' can be handled with a single shifter_op return the value. 342f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng if ((rotr32(0xff000000U, RotAmt) & V) == V) 343f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng return (rotr32(V, 24 - RotAmt) & 0x7f) | ((RotAmt + 8) << 7); 344f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng 345f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng return -1; 346f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng } 347f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng 348f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit 349f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// into a Thumb-2 shifter_operand immediate operand, return the 12-bit 350f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// encoding for it. If not, return -1. 351f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng /// See ARM Reference Manual A6.3.2. 352f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng static inline int getT2SOImmVal(unsigned Arg) { 353f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng // If 'Arg' is an 8-bit splat, then get the encoded value. 354f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng int Splat = getT2SOImmValSplat(Arg); 355f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng if (Splat != -1) 356f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng return Splat; 357f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng 358f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng // If 'Arg' can be handled with a single shifter_op return the value. 359f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng int Rot = getT2SOImmValRotate(Arg); 360f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng if (Rot != -1) 361f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng return Rot; 362f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng 363f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng return -1; 364f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng } 365f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng 366f49810c7e60807c43a68ab02c936a4ee77a4d2cfEvan Cheng 367a8e2989ece6dc46df59b0768184028257f913843Evan Cheng //===--------------------------------------------------------------------===// 368a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // Addressing Mode #2 369a8e2989ece6dc46df59b0768184028257f913843Evan Cheng //===--------------------------------------------------------------------===// 370a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 371a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // This is used for most simple load/store instructions. 372a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 373a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // addrmode2 := reg +/- reg shop imm 374a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // addrmode2 := reg +/- imm12 375a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 376a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // The first operand is always a Reg. The second operand is a reg if in 377a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // reg/reg form, otherwise it's reg#0. The third field encodes the operation 378a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. 379a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 380a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // If this addressing mode is a frame index (before prolog/epilog insertion 381a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // and code rewriting), this operand will have the form: FI#, reg0, <offs> 382a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // with no shift amount for the frame offset. 383a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 384a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO) { 385a8e2989ece6dc46df59b0768184028257f913843Evan Cheng assert(Imm12 < (1 << 12) && "Imm too large!"); 386a8e2989ece6dc46df59b0768184028257f913843Evan Cheng bool isSub = Opc == sub; 387a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return Imm12 | ((int)isSub << 12) | (SO << 13); 388a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 389a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline unsigned getAM2Offset(unsigned AM2Opc) { 390a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return AM2Opc & ((1 << 12)-1); 391a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 392a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline AddrOpc getAM2Op(unsigned AM2Opc) { 393a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return ((AM2Opc >> 12) & 1) ? sub : add; 394a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 395a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline ShiftOpc getAM2ShiftOpc(unsigned AM2Opc) { 396a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return (ShiftOpc)(AM2Opc >> 13); 397a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 398a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 399a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 400a8e2989ece6dc46df59b0768184028257f913843Evan Cheng //===--------------------------------------------------------------------===// 401a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // Addressing Mode #3 402a8e2989ece6dc46df59b0768184028257f913843Evan Cheng //===--------------------------------------------------------------------===// 403a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 404a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // This is used for sign-extending loads, and load/store-pair instructions. 405a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 406a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // addrmode3 := reg +/- reg 407a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // addrmode3 := reg +/- imm8 408a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 409a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // The first operand is always a Reg. The second operand is a reg if in 410a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // reg/reg form, otherwise it's reg#0. The third field encodes the operation 411a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // in bit 8, the immediate in bits 0-7. 412a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 413a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// getAM3Opc - This function encodes the addrmode3 opc field. 414a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset) { 415a8e2989ece6dc46df59b0768184028257f913843Evan Cheng bool isSub = Opc == sub; 416a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return ((int)isSub << 8) | Offset; 417a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 418a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline unsigned char getAM3Offset(unsigned AM3Opc) { 419a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return AM3Opc & 0xFF; 420a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 421a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline AddrOpc getAM3Op(unsigned AM3Opc) { 422a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return ((AM3Opc >> 8) & 1) ? sub : add; 423a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 424a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 425a8e2989ece6dc46df59b0768184028257f913843Evan Cheng //===--------------------------------------------------------------------===// 426a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // Addressing Mode #4 427a8e2989ece6dc46df59b0768184028257f913843Evan Cheng //===--------------------------------------------------------------------===// 428a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 429a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // This is used for load / store multiple instructions. 430a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 431a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // addrmode4 := reg, <mode> 432a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 433a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // The four modes are: 434a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // IA - Increment after 435a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // IB - Increment before 436a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // DA - Decrement after 437a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // DB - Decrement before 438a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 439a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // If the 4th bit (writeback)is set, then the base register is updated after 440a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // the memory transfer. 441a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 442a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline AMSubMode getAM4SubMode(unsigned Mode) { 443a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return (AMSubMode)(Mode & 0x7); 444a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 445a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 446a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline unsigned getAM4ModeImm(AMSubMode SubMode, bool WB = false) { 447a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return (int)SubMode | ((int)WB << 3); 448a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 449a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 450a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline bool getAM4WBFlag(unsigned Mode) { 451a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return (Mode >> 3) & 1; 452a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 453a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 454a8e2989ece6dc46df59b0768184028257f913843Evan Cheng //===--------------------------------------------------------------------===// 455a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // Addressing Mode #5 456a8e2989ece6dc46df59b0768184028257f913843Evan Cheng //===--------------------------------------------------------------------===// 457a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 458a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // This is used for coprocessor instructions, such as FP load/stores. 459a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 460a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // addrmode5 := reg +/- imm8*4 461a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 462a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // The first operand is always a Reg. The third field encodes the operation 463a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // in bit 8, the immediate in bits 0-7. 464a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 465a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // This can also be used for FP load/store multiple ops. The third field encodes 466a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // writeback mode in bit 8, the number of registers (or 2 times the number of 467a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // registers for DPR ops) in bits 0-7. In addition, bit 9-11 encodes one of the 468a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // following two sub-modes: 469a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // 470a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // IA - Increment after 471a8e2989ece6dc46df59b0768184028257f913843Evan Cheng // DB - Decrement before 472a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 473a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// getAM5Opc - This function encodes the addrmode5 opc field. 474a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline unsigned getAM5Opc(AddrOpc Opc, unsigned char Offset) { 475a8e2989ece6dc46df59b0768184028257f913843Evan Cheng bool isSub = Opc == sub; 476a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return ((int)isSub << 8) | Offset; 477a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 478a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline unsigned char getAM5Offset(unsigned AM5Opc) { 479a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return AM5Opc & 0xFF; 480a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 481a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline AddrOpc getAM5Op(unsigned AM5Opc) { 482a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return ((AM5Opc >> 8) & 1) ? sub : add; 483a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 484a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 485a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// getAM5Opc - This function encodes the addrmode5 opc field for FLDM and 486a8e2989ece6dc46df59b0768184028257f913843Evan Cheng /// FSTM instructions. 487a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline unsigned getAM5Opc(AMSubMode SubMode, bool WB, 488a8e2989ece6dc46df59b0768184028257f913843Evan Cheng unsigned char Offset) { 489a8e2989ece6dc46df59b0768184028257f913843Evan Cheng assert((SubMode == ia || SubMode == db) && 490a8e2989ece6dc46df59b0768184028257f913843Evan Cheng "Illegal addressing mode 5 sub-mode!"); 491a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return ((int)SubMode << 9) | ((int)WB << 8) | Offset; 492a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 493a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline AMSubMode getAM5SubMode(unsigned AM5Opc) { 494a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return (AMSubMode)((AM5Opc >> 9) & 0x7); 495a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 496a8e2989ece6dc46df59b0768184028257f913843Evan Cheng static inline bool getAM5WBFlag(unsigned AM5Opc) { 497a8e2989ece6dc46df59b0768184028257f913843Evan Cheng return ((AM5Opc >> 8) & 1); 498a8e2989ece6dc46df59b0768184028257f913843Evan Cheng } 499a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 500a8e2989ece6dc46df59b0768184028257f913843Evan Cheng} // end namespace ARM_AM 501a8e2989ece6dc46df59b0768184028257f913843Evan Cheng} // end namespace llvm 502a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 503a8e2989ece6dc46df59b0768184028257f913843Evan Cheng#endif 504a8e2989ece6dc46df59b0768184028257f913843Evan Cheng 505