1*06f32e7eSjoerg //===-- ARMAddressingModes.h - ARM Addressing Modes -------------*- C++ -*-===// 2*06f32e7eSjoerg // 3*06f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*06f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information. 5*06f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*06f32e7eSjoerg // 7*06f32e7eSjoerg //===----------------------------------------------------------------------===// 8*06f32e7eSjoerg // 9*06f32e7eSjoerg // This file contains the ARM addressing mode implementation stuff. 10*06f32e7eSjoerg // 11*06f32e7eSjoerg //===----------------------------------------------------------------------===// 12*06f32e7eSjoerg 13*06f32e7eSjoerg #ifndef LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMADDRESSINGMODES_H 14*06f32e7eSjoerg #define LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMADDRESSINGMODES_H 15*06f32e7eSjoerg 16*06f32e7eSjoerg #include "llvm/ADT/APFloat.h" 17*06f32e7eSjoerg #include "llvm/ADT/APInt.h" 18*06f32e7eSjoerg #include "llvm/ADT/bit.h" 19*06f32e7eSjoerg #include "llvm/Support/ErrorHandling.h" 20*06f32e7eSjoerg #include "llvm/Support/MathExtras.h" 21*06f32e7eSjoerg #include <cassert> 22*06f32e7eSjoerg 23*06f32e7eSjoerg namespace llvm { 24*06f32e7eSjoerg 25*06f32e7eSjoerg /// ARM_AM - ARM Addressing Mode Stuff 26*06f32e7eSjoerg namespace ARM_AM { 27*06f32e7eSjoerg enum ShiftOpc { 28*06f32e7eSjoerg no_shift = 0, 29*06f32e7eSjoerg asr, 30*06f32e7eSjoerg lsl, 31*06f32e7eSjoerg lsr, 32*06f32e7eSjoerg ror, 33*06f32e7eSjoerg rrx, 34*06f32e7eSjoerg uxtw 35*06f32e7eSjoerg }; 36*06f32e7eSjoerg 37*06f32e7eSjoerg enum AddrOpc { 38*06f32e7eSjoerg sub = 0, 39*06f32e7eSjoerg add 40*06f32e7eSjoerg }; 41*06f32e7eSjoerg 42*06f32e7eSjoerg inline const char *getAddrOpcStr(AddrOpc Op) { return Op == sub ? "-" : ""; } 43*06f32e7eSjoerg 44*06f32e7eSjoerg inline const char *getShiftOpcStr(ShiftOpc Op) { 45*06f32e7eSjoerg switch (Op) { 46*06f32e7eSjoerg default: llvm_unreachable("Unknown shift opc!"); 47*06f32e7eSjoerg case ARM_AM::asr: return "asr"; 48*06f32e7eSjoerg case ARM_AM::lsl: return "lsl"; 49*06f32e7eSjoerg case ARM_AM::lsr: return "lsr"; 50*06f32e7eSjoerg case ARM_AM::ror: return "ror"; 51*06f32e7eSjoerg case ARM_AM::rrx: return "rrx"; 52*06f32e7eSjoerg case ARM_AM::uxtw: return "uxtw"; 53*06f32e7eSjoerg } 54*06f32e7eSjoerg } 55*06f32e7eSjoerg 56*06f32e7eSjoerg inline unsigned getShiftOpcEncoding(ShiftOpc Op) { 57*06f32e7eSjoerg switch (Op) { 58*06f32e7eSjoerg default: llvm_unreachable("Unknown shift opc!"); 59*06f32e7eSjoerg case ARM_AM::asr: return 2; 60*06f32e7eSjoerg case ARM_AM::lsl: return 0; 61*06f32e7eSjoerg case ARM_AM::lsr: return 1; 62*06f32e7eSjoerg case ARM_AM::ror: return 3; 63*06f32e7eSjoerg } 64*06f32e7eSjoerg } 65*06f32e7eSjoerg 66*06f32e7eSjoerg enum AMSubMode { 67*06f32e7eSjoerg bad_am_submode = 0, 68*06f32e7eSjoerg ia, 69*06f32e7eSjoerg ib, 70*06f32e7eSjoerg da, 71*06f32e7eSjoerg db 72*06f32e7eSjoerg }; 73*06f32e7eSjoerg 74*06f32e7eSjoerg inline const char *getAMSubModeStr(AMSubMode Mode) { 75*06f32e7eSjoerg switch (Mode) { 76*06f32e7eSjoerg default: llvm_unreachable("Unknown addressing sub-mode!"); 77*06f32e7eSjoerg case ARM_AM::ia: return "ia"; 78*06f32e7eSjoerg case ARM_AM::ib: return "ib"; 79*06f32e7eSjoerg case ARM_AM::da: return "da"; 80*06f32e7eSjoerg case ARM_AM::db: return "db"; 81*06f32e7eSjoerg } 82*06f32e7eSjoerg } 83*06f32e7eSjoerg 84*06f32e7eSjoerg /// rotr32 - Rotate a 32-bit unsigned value right by a specified # bits. 85*06f32e7eSjoerg /// 86*06f32e7eSjoerg inline unsigned rotr32(unsigned Val, unsigned Amt) { 87*06f32e7eSjoerg assert(Amt < 32 && "Invalid rotate amount"); 88*06f32e7eSjoerg return (Val >> Amt) | (Val << ((32-Amt)&31)); 89*06f32e7eSjoerg } 90*06f32e7eSjoerg 91*06f32e7eSjoerg /// rotl32 - Rotate a 32-bit unsigned value left by a specified # bits. 92*06f32e7eSjoerg /// 93*06f32e7eSjoerg inline unsigned rotl32(unsigned Val, unsigned Amt) { 94*06f32e7eSjoerg assert(Amt < 32 && "Invalid rotate amount"); 95*06f32e7eSjoerg return (Val << Amt) | (Val >> ((32-Amt)&31)); 96*06f32e7eSjoerg } 97*06f32e7eSjoerg 98*06f32e7eSjoerg //===--------------------------------------------------------------------===// 99*06f32e7eSjoerg // Addressing Mode #1: shift_operand with registers 100*06f32e7eSjoerg //===--------------------------------------------------------------------===// 101*06f32e7eSjoerg // 102*06f32e7eSjoerg // This 'addressing mode' is used for arithmetic instructions. It can 103*06f32e7eSjoerg // represent things like: 104*06f32e7eSjoerg // reg 105*06f32e7eSjoerg // reg [asr|lsl|lsr|ror|rrx] reg 106*06f32e7eSjoerg // reg [asr|lsl|lsr|ror|rrx] imm 107*06f32e7eSjoerg // 108*06f32e7eSjoerg // This is stored three operands [rega, regb, opc]. The first is the base 109*06f32e7eSjoerg // reg, the second is the shift amount (or reg0 if not present or imm). The 110*06f32e7eSjoerg // third operand encodes the shift opcode and the imm if a reg isn't present. 111*06f32e7eSjoerg // 112*06f32e7eSjoerg inline unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm) { 113*06f32e7eSjoerg return ShOp | (Imm << 3); 114*06f32e7eSjoerg } 115*06f32e7eSjoerg inline unsigned getSORegOffset(unsigned Op) { return Op >> 3; } 116*06f32e7eSjoerg inline ShiftOpc getSORegShOp(unsigned Op) { return (ShiftOpc)(Op & 7); } 117*06f32e7eSjoerg 118*06f32e7eSjoerg /// getSOImmValImm - Given an encoded imm field for the reg/imm form, return 119*06f32e7eSjoerg /// the 8-bit imm value. 120*06f32e7eSjoerg inline unsigned getSOImmValImm(unsigned Imm) { return Imm & 0xFF; } 121*06f32e7eSjoerg /// getSOImmValRot - Given an encoded imm field for the reg/imm form, return 122*06f32e7eSjoerg /// the rotate amount. 123*06f32e7eSjoerg inline unsigned getSOImmValRot(unsigned Imm) { return (Imm >> 8) * 2; } 124*06f32e7eSjoerg 125*06f32e7eSjoerg /// getSOImmValRotate - Try to handle Imm with an immediate shifter operand, 126*06f32e7eSjoerg /// computing the rotate amount to use. If this immediate value cannot be 127*06f32e7eSjoerg /// handled with a single shifter-op, determine a good rotate amount that will 128*06f32e7eSjoerg /// take a maximal chunk of bits out of the immediate. 129*06f32e7eSjoerg inline unsigned getSOImmValRotate(unsigned Imm) { 130*06f32e7eSjoerg // 8-bit (or less) immediates are trivially shifter_operands with a rotate 131*06f32e7eSjoerg // of zero. 132*06f32e7eSjoerg if ((Imm & ~255U) == 0) return 0; 133*06f32e7eSjoerg 134*06f32e7eSjoerg // Use CTZ to compute the rotate amount. 135*06f32e7eSjoerg unsigned TZ = countTrailingZeros(Imm); 136*06f32e7eSjoerg 137*06f32e7eSjoerg // Rotate amount must be even. Something like 0x200 must be rotated 8 bits, 138*06f32e7eSjoerg // not 9. 139*06f32e7eSjoerg unsigned RotAmt = TZ & ~1; 140*06f32e7eSjoerg 141*06f32e7eSjoerg // If we can handle this spread, return it. 142*06f32e7eSjoerg if ((rotr32(Imm, RotAmt) & ~255U) == 0) 143*06f32e7eSjoerg return (32-RotAmt)&31; // HW rotates right, not left. 144*06f32e7eSjoerg 145*06f32e7eSjoerg // For values like 0xF000000F, we should ignore the low 6 bits, then 146*06f32e7eSjoerg // retry the hunt. 147*06f32e7eSjoerg if (Imm & 63U) { 148*06f32e7eSjoerg unsigned TZ2 = countTrailingZeros(Imm & ~63U); 149*06f32e7eSjoerg unsigned RotAmt2 = TZ2 & ~1; 150*06f32e7eSjoerg if ((rotr32(Imm, RotAmt2) & ~255U) == 0) 151*06f32e7eSjoerg return (32-RotAmt2)&31; // HW rotates right, not left. 152*06f32e7eSjoerg } 153*06f32e7eSjoerg 154*06f32e7eSjoerg // Otherwise, we have no way to cover this span of bits with a single 155*06f32e7eSjoerg // shifter_op immediate. Return a chunk of bits that will be useful to 156*06f32e7eSjoerg // handle. 157*06f32e7eSjoerg return (32-RotAmt)&31; // HW rotates right, not left. 158*06f32e7eSjoerg } 159*06f32e7eSjoerg 160*06f32e7eSjoerg /// getSOImmVal - Given a 32-bit immediate, if it is something that can fit 161*06f32e7eSjoerg /// into an shifter_operand immediate operand, return the 12-bit encoding for 162*06f32e7eSjoerg /// it. If not, return -1. 163*06f32e7eSjoerg inline int getSOImmVal(unsigned Arg) { 164*06f32e7eSjoerg // 8-bit (or less) immediates are trivially shifter_operands with a rotate 165*06f32e7eSjoerg // of zero. 166*06f32e7eSjoerg if ((Arg & ~255U) == 0) return Arg; 167*06f32e7eSjoerg 168*06f32e7eSjoerg unsigned RotAmt = getSOImmValRotate(Arg); 169*06f32e7eSjoerg 170*06f32e7eSjoerg // If this cannot be handled with a single shifter_op, bail out. 171*06f32e7eSjoerg if (rotr32(~255U, RotAmt) & Arg) 172*06f32e7eSjoerg return -1; 173*06f32e7eSjoerg 174*06f32e7eSjoerg // Encode this correctly. 175*06f32e7eSjoerg return rotl32(Arg, RotAmt) | ((RotAmt>>1) << 8); 176*06f32e7eSjoerg } 177*06f32e7eSjoerg 178*06f32e7eSjoerg /// isSOImmTwoPartVal - Return true if the specified value can be obtained by 179*06f32e7eSjoerg /// or'ing together two SOImmVal's. 180*06f32e7eSjoerg inline bool isSOImmTwoPartVal(unsigned V) { 181*06f32e7eSjoerg // If this can be handled with a single shifter_op, bail out. 182*06f32e7eSjoerg V = rotr32(~255U, getSOImmValRotate(V)) & V; 183*06f32e7eSjoerg if (V == 0) 184*06f32e7eSjoerg return false; 185*06f32e7eSjoerg 186*06f32e7eSjoerg // If this can be handled with two shifter_op's, accept. 187*06f32e7eSjoerg V = rotr32(~255U, getSOImmValRotate(V)) & V; 188*06f32e7eSjoerg return V == 0; 189*06f32e7eSjoerg } 190*06f32e7eSjoerg 191*06f32e7eSjoerg /// getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal, 192*06f32e7eSjoerg /// return the first chunk of it. 193*06f32e7eSjoerg inline unsigned getSOImmTwoPartFirst(unsigned V) { 194*06f32e7eSjoerg return rotr32(255U, getSOImmValRotate(V)) & V; 195*06f32e7eSjoerg } 196*06f32e7eSjoerg 197*06f32e7eSjoerg /// getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal, 198*06f32e7eSjoerg /// return the second chunk of it. 199*06f32e7eSjoerg inline unsigned getSOImmTwoPartSecond(unsigned V) { 200*06f32e7eSjoerg // Mask out the first hunk. 201*06f32e7eSjoerg V = rotr32(~255U, getSOImmValRotate(V)) & V; 202*06f32e7eSjoerg 203*06f32e7eSjoerg // Take what's left. 204*06f32e7eSjoerg assert(V == (rotr32(255U, getSOImmValRotate(V)) & V)); 205*06f32e7eSjoerg return V; 206*06f32e7eSjoerg } 207*06f32e7eSjoerg 208*06f32e7eSjoerg /// getThumbImmValShift - Try to handle Imm with a 8-bit immediate followed 209*06f32e7eSjoerg /// by a left shift. Returns the shift amount to use. 210*06f32e7eSjoerg inline unsigned getThumbImmValShift(unsigned Imm) { 211*06f32e7eSjoerg // 8-bit (or less) immediates are trivially immediate operand with a shift 212*06f32e7eSjoerg // of zero. 213*06f32e7eSjoerg if ((Imm & ~255U) == 0) return 0; 214*06f32e7eSjoerg 215*06f32e7eSjoerg // Use CTZ to compute the shift amount. 216*06f32e7eSjoerg return countTrailingZeros(Imm); 217*06f32e7eSjoerg } 218*06f32e7eSjoerg 219*06f32e7eSjoerg /// isThumbImmShiftedVal - Return true if the specified value can be obtained 220*06f32e7eSjoerg /// by left shifting a 8-bit immediate. 221*06f32e7eSjoerg inline bool isThumbImmShiftedVal(unsigned V) { 222*06f32e7eSjoerg // If this can be handled with 223*06f32e7eSjoerg V = (~255U << getThumbImmValShift(V)) & V; 224*06f32e7eSjoerg return V == 0; 225*06f32e7eSjoerg } 226*06f32e7eSjoerg 227*06f32e7eSjoerg /// getThumbImm16ValShift - Try to handle Imm with a 16-bit immediate followed 228*06f32e7eSjoerg /// by a left shift. Returns the shift amount to use. 229*06f32e7eSjoerg inline unsigned getThumbImm16ValShift(unsigned Imm) { 230*06f32e7eSjoerg // 16-bit (or less) immediates are trivially immediate operand with a shift 231*06f32e7eSjoerg // of zero. 232*06f32e7eSjoerg if ((Imm & ~65535U) == 0) return 0; 233*06f32e7eSjoerg 234*06f32e7eSjoerg // Use CTZ to compute the shift amount. 235*06f32e7eSjoerg return countTrailingZeros(Imm); 236*06f32e7eSjoerg } 237*06f32e7eSjoerg 238*06f32e7eSjoerg /// isThumbImm16ShiftedVal - Return true if the specified value can be 239*06f32e7eSjoerg /// obtained by left shifting a 16-bit immediate. 240*06f32e7eSjoerg inline bool isThumbImm16ShiftedVal(unsigned V) { 241*06f32e7eSjoerg // If this can be handled with 242*06f32e7eSjoerg V = (~65535U << getThumbImm16ValShift(V)) & V; 243*06f32e7eSjoerg return V == 0; 244*06f32e7eSjoerg } 245*06f32e7eSjoerg 246*06f32e7eSjoerg /// getThumbImmNonShiftedVal - If V is a value that satisfies 247*06f32e7eSjoerg /// isThumbImmShiftedVal, return the non-shiftd value. 248*06f32e7eSjoerg inline unsigned getThumbImmNonShiftedVal(unsigned V) { 249*06f32e7eSjoerg return V >> getThumbImmValShift(V); 250*06f32e7eSjoerg } 251*06f32e7eSjoerg 252*06f32e7eSjoerg 253*06f32e7eSjoerg /// getT2SOImmValSplat - Return the 12-bit encoded representation 254*06f32e7eSjoerg /// if the specified value can be obtained by splatting the low 8 bits 255*06f32e7eSjoerg /// into every other byte or every byte of a 32-bit value. i.e., 256*06f32e7eSjoerg /// 00000000 00000000 00000000 abcdefgh control = 0 257*06f32e7eSjoerg /// 00000000 abcdefgh 00000000 abcdefgh control = 1 258*06f32e7eSjoerg /// abcdefgh 00000000 abcdefgh 00000000 control = 2 259*06f32e7eSjoerg /// abcdefgh abcdefgh abcdefgh abcdefgh control = 3 260*06f32e7eSjoerg /// Return -1 if none of the above apply. 261*06f32e7eSjoerg /// See ARM Reference Manual A6.3.2. 262*06f32e7eSjoerg inline int getT2SOImmValSplatVal(unsigned V) { 263*06f32e7eSjoerg unsigned u, Vs, Imm; 264*06f32e7eSjoerg // control = 0 265*06f32e7eSjoerg if ((V & 0xffffff00) == 0) 266*06f32e7eSjoerg return V; 267*06f32e7eSjoerg 268*06f32e7eSjoerg // If the value is zeroes in the first byte, just shift those off 269*06f32e7eSjoerg Vs = ((V & 0xff) == 0) ? V >> 8 : V; 270*06f32e7eSjoerg // Any passing value only has 8 bits of payload, splatted across the word 271*06f32e7eSjoerg Imm = Vs & 0xff; 272*06f32e7eSjoerg // Likewise, any passing values have the payload splatted into the 3rd byte 273*06f32e7eSjoerg u = Imm | (Imm << 16); 274*06f32e7eSjoerg 275*06f32e7eSjoerg // control = 1 or 2 276*06f32e7eSjoerg if (Vs == u) 277*06f32e7eSjoerg return (((Vs == V) ? 1 : 2) << 8) | Imm; 278*06f32e7eSjoerg 279*06f32e7eSjoerg // control = 3 280*06f32e7eSjoerg if (Vs == (u | (u << 8))) 281*06f32e7eSjoerg return (3 << 8) | Imm; 282*06f32e7eSjoerg 283*06f32e7eSjoerg return -1; 284*06f32e7eSjoerg } 285*06f32e7eSjoerg 286*06f32e7eSjoerg /// getT2SOImmValRotateVal - Return the 12-bit encoded representation if the 287*06f32e7eSjoerg /// specified value is a rotated 8-bit value. Return -1 if no rotation 288*06f32e7eSjoerg /// encoding is possible. 289*06f32e7eSjoerg /// See ARM Reference Manual A6.3.2. 290*06f32e7eSjoerg inline int getT2SOImmValRotateVal(unsigned V) { 291*06f32e7eSjoerg unsigned RotAmt = countLeadingZeros(V); 292*06f32e7eSjoerg if (RotAmt >= 24) 293*06f32e7eSjoerg return -1; 294*06f32e7eSjoerg 295*06f32e7eSjoerg // If 'Arg' can be handled with a single shifter_op return the value. 296*06f32e7eSjoerg if ((rotr32(0xff000000U, RotAmt) & V) == V) 297*06f32e7eSjoerg return (rotr32(V, 24 - RotAmt) & 0x7f) | ((RotAmt + 8) << 7); 298*06f32e7eSjoerg 299*06f32e7eSjoerg return -1; 300*06f32e7eSjoerg } 301*06f32e7eSjoerg 302*06f32e7eSjoerg /// getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit 303*06f32e7eSjoerg /// into a Thumb-2 shifter_operand immediate operand, return the 12-bit 304*06f32e7eSjoerg /// encoding for it. If not, return -1. 305*06f32e7eSjoerg /// See ARM Reference Manual A6.3.2. 306*06f32e7eSjoerg inline int getT2SOImmVal(unsigned Arg) { 307*06f32e7eSjoerg // If 'Arg' is an 8-bit splat, then get the encoded value. 308*06f32e7eSjoerg int Splat = getT2SOImmValSplatVal(Arg); 309*06f32e7eSjoerg if (Splat != -1) 310*06f32e7eSjoerg return Splat; 311*06f32e7eSjoerg 312*06f32e7eSjoerg // If 'Arg' can be handled with a single shifter_op return the value. 313*06f32e7eSjoerg int Rot = getT2SOImmValRotateVal(Arg); 314*06f32e7eSjoerg if (Rot != -1) 315*06f32e7eSjoerg return Rot; 316*06f32e7eSjoerg 317*06f32e7eSjoerg return -1; 318*06f32e7eSjoerg } 319*06f32e7eSjoerg 320*06f32e7eSjoerg inline unsigned getT2SOImmValRotate(unsigned V) { 321*06f32e7eSjoerg if ((V & ~255U) == 0) return 0; 322*06f32e7eSjoerg // Use CTZ to compute the rotate amount. 323*06f32e7eSjoerg unsigned RotAmt = countTrailingZeros(V); 324*06f32e7eSjoerg return (32 - RotAmt) & 31; 325*06f32e7eSjoerg } 326*06f32e7eSjoerg 327*06f32e7eSjoerg inline bool isT2SOImmTwoPartVal(unsigned Imm) { 328*06f32e7eSjoerg unsigned V = Imm; 329*06f32e7eSjoerg // Passing values can be any combination of splat values and shifter 330*06f32e7eSjoerg // values. If this can be handled with a single shifter or splat, bail 331*06f32e7eSjoerg // out. Those should be handled directly, not with a two-part val. 332*06f32e7eSjoerg if (getT2SOImmValSplatVal(V) != -1) 333*06f32e7eSjoerg return false; 334*06f32e7eSjoerg V = rotr32 (~255U, getT2SOImmValRotate(V)) & V; 335*06f32e7eSjoerg if (V == 0) 336*06f32e7eSjoerg return false; 337*06f32e7eSjoerg 338*06f32e7eSjoerg // If this can be handled as an immediate, accept. 339*06f32e7eSjoerg if (getT2SOImmVal(V) != -1) return true; 340*06f32e7eSjoerg 341*06f32e7eSjoerg // Likewise, try masking out a splat value first. 342*06f32e7eSjoerg V = Imm; 343*06f32e7eSjoerg if (getT2SOImmValSplatVal(V & 0xff00ff00U) != -1) 344*06f32e7eSjoerg V &= ~0xff00ff00U; 345*06f32e7eSjoerg else if (getT2SOImmValSplatVal(V & 0x00ff00ffU) != -1) 346*06f32e7eSjoerg V &= ~0x00ff00ffU; 347*06f32e7eSjoerg // If what's left can be handled as an immediate, accept. 348*06f32e7eSjoerg if (getT2SOImmVal(V) != -1) return true; 349*06f32e7eSjoerg 350*06f32e7eSjoerg // Otherwise, do not accept. 351*06f32e7eSjoerg return false; 352*06f32e7eSjoerg } 353*06f32e7eSjoerg 354*06f32e7eSjoerg inline unsigned getT2SOImmTwoPartFirst(unsigned Imm) { 355*06f32e7eSjoerg assert (isT2SOImmTwoPartVal(Imm) && 356*06f32e7eSjoerg "Immedate cannot be encoded as two part immediate!"); 357*06f32e7eSjoerg // Try a shifter operand as one part 358*06f32e7eSjoerg unsigned V = rotr32 (~255, getT2SOImmValRotate(Imm)) & Imm; 359*06f32e7eSjoerg // If the rest is encodable as an immediate, then return it. 360*06f32e7eSjoerg if (getT2SOImmVal(V) != -1) return V; 361*06f32e7eSjoerg 362*06f32e7eSjoerg // Try masking out a splat value first. 363*06f32e7eSjoerg if (getT2SOImmValSplatVal(Imm & 0xff00ff00U) != -1) 364*06f32e7eSjoerg return Imm & 0xff00ff00U; 365*06f32e7eSjoerg 366*06f32e7eSjoerg // The other splat is all that's left as an option. 367*06f32e7eSjoerg assert (getT2SOImmValSplatVal(Imm & 0x00ff00ffU) != -1); 368*06f32e7eSjoerg return Imm & 0x00ff00ffU; 369*06f32e7eSjoerg } 370*06f32e7eSjoerg 371*06f32e7eSjoerg inline unsigned getT2SOImmTwoPartSecond(unsigned Imm) { 372*06f32e7eSjoerg // Mask out the first hunk 373*06f32e7eSjoerg Imm ^= getT2SOImmTwoPartFirst(Imm); 374*06f32e7eSjoerg // Return what's left 375*06f32e7eSjoerg assert (getT2SOImmVal(Imm) != -1 && 376*06f32e7eSjoerg "Unable to encode second part of T2 two part SO immediate"); 377*06f32e7eSjoerg return Imm; 378*06f32e7eSjoerg } 379*06f32e7eSjoerg 380*06f32e7eSjoerg 381*06f32e7eSjoerg //===--------------------------------------------------------------------===// 382*06f32e7eSjoerg // Addressing Mode #2 383*06f32e7eSjoerg //===--------------------------------------------------------------------===// 384*06f32e7eSjoerg // 385*06f32e7eSjoerg // This is used for most simple load/store instructions. 386*06f32e7eSjoerg // 387*06f32e7eSjoerg // addrmode2 := reg +/- reg shop imm 388*06f32e7eSjoerg // addrmode2 := reg +/- imm12 389*06f32e7eSjoerg // 390*06f32e7eSjoerg // The first operand is always a Reg. The second operand is a reg if in 391*06f32e7eSjoerg // reg/reg form, otherwise it's reg#0. The third field encodes the operation 392*06f32e7eSjoerg // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. The 393*06f32e7eSjoerg // fourth operand 16-17 encodes the index mode. 394*06f32e7eSjoerg // 395*06f32e7eSjoerg // If this addressing mode is a frame index (before prolog/epilog insertion 396*06f32e7eSjoerg // and code rewriting), this operand will have the form: FI#, reg0, <offs> 397*06f32e7eSjoerg // with no shift amount for the frame offset. 398*06f32e7eSjoerg // 399*06f32e7eSjoerg inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO, 400*06f32e7eSjoerg unsigned IdxMode = 0) { 401*06f32e7eSjoerg assert(Imm12 < (1 << 12) && "Imm too large!"); 402*06f32e7eSjoerg bool isSub = Opc == sub; 403*06f32e7eSjoerg return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16) ; 404*06f32e7eSjoerg } 405*06f32e7eSjoerg inline unsigned getAM2Offset(unsigned AM2Opc) { 406*06f32e7eSjoerg return AM2Opc & ((1 << 12)-1); 407*06f32e7eSjoerg } 408*06f32e7eSjoerg inline AddrOpc getAM2Op(unsigned AM2Opc) { 409*06f32e7eSjoerg return ((AM2Opc >> 12) & 1) ? sub : add; 410*06f32e7eSjoerg } 411*06f32e7eSjoerg inline ShiftOpc getAM2ShiftOpc(unsigned AM2Opc) { 412*06f32e7eSjoerg return (ShiftOpc)((AM2Opc >> 13) & 7); 413*06f32e7eSjoerg } 414*06f32e7eSjoerg inline unsigned getAM2IdxMode(unsigned AM2Opc) { return (AM2Opc >> 16); } 415*06f32e7eSjoerg 416*06f32e7eSjoerg //===--------------------------------------------------------------------===// 417*06f32e7eSjoerg // Addressing Mode #3 418*06f32e7eSjoerg //===--------------------------------------------------------------------===// 419*06f32e7eSjoerg // 420*06f32e7eSjoerg // This is used for sign-extending loads, and load/store-pair instructions. 421*06f32e7eSjoerg // 422*06f32e7eSjoerg // addrmode3 := reg +/- reg 423*06f32e7eSjoerg // addrmode3 := reg +/- imm8 424*06f32e7eSjoerg // 425*06f32e7eSjoerg // The first operand is always a Reg. The second operand is a reg if in 426*06f32e7eSjoerg // reg/reg form, otherwise it's reg#0. The third field encodes the operation 427*06f32e7eSjoerg // in bit 8, the immediate in bits 0-7. The fourth operand 9-10 encodes the 428*06f32e7eSjoerg // index mode. 429*06f32e7eSjoerg 430*06f32e7eSjoerg /// getAM3Opc - This function encodes the addrmode3 opc field. 431*06f32e7eSjoerg inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset, 432*06f32e7eSjoerg unsigned IdxMode = 0) { 433*06f32e7eSjoerg bool isSub = Opc == sub; 434*06f32e7eSjoerg return ((int)isSub << 8) | Offset | (IdxMode << 9); 435*06f32e7eSjoerg } 436*06f32e7eSjoerg inline unsigned char getAM3Offset(unsigned AM3Opc) { return AM3Opc & 0xFF; } 437*06f32e7eSjoerg inline AddrOpc getAM3Op(unsigned AM3Opc) { 438*06f32e7eSjoerg return ((AM3Opc >> 8) & 1) ? sub : add; 439*06f32e7eSjoerg } 440*06f32e7eSjoerg inline unsigned getAM3IdxMode(unsigned AM3Opc) { return (AM3Opc >> 9); } 441*06f32e7eSjoerg 442*06f32e7eSjoerg //===--------------------------------------------------------------------===// 443*06f32e7eSjoerg // Addressing Mode #4 444*06f32e7eSjoerg //===--------------------------------------------------------------------===// 445*06f32e7eSjoerg // 446*06f32e7eSjoerg // This is used for load / store multiple instructions. 447*06f32e7eSjoerg // 448*06f32e7eSjoerg // addrmode4 := reg, <mode> 449*06f32e7eSjoerg // 450*06f32e7eSjoerg // The four modes are: 451*06f32e7eSjoerg // IA - Increment after 452*06f32e7eSjoerg // IB - Increment before 453*06f32e7eSjoerg // DA - Decrement after 454*06f32e7eSjoerg // DB - Decrement before 455*06f32e7eSjoerg // For VFP instructions, only the IA and DB modes are valid. 456*06f32e7eSjoerg 457*06f32e7eSjoerg inline AMSubMode getAM4SubMode(unsigned Mode) { 458*06f32e7eSjoerg return (AMSubMode)(Mode & 0x7); 459*06f32e7eSjoerg } 460*06f32e7eSjoerg 461*06f32e7eSjoerg inline unsigned getAM4ModeImm(AMSubMode SubMode) { return (int)SubMode; } 462*06f32e7eSjoerg 463*06f32e7eSjoerg //===--------------------------------------------------------------------===// 464*06f32e7eSjoerg // Addressing Mode #5 465*06f32e7eSjoerg //===--------------------------------------------------------------------===// 466*06f32e7eSjoerg // 467*06f32e7eSjoerg // This is used for coprocessor instructions, such as FP load/stores. 468*06f32e7eSjoerg // 469*06f32e7eSjoerg // addrmode5 := reg +/- imm8*4 470*06f32e7eSjoerg // 471*06f32e7eSjoerg // The first operand is always a Reg. The second operand encodes the 472*06f32e7eSjoerg // operation (add or subtract) in bit 8 and the immediate in bits 0-7. 473*06f32e7eSjoerg 474*06f32e7eSjoerg /// getAM5Opc - This function encodes the addrmode5 opc field. 475*06f32e7eSjoerg inline unsigned getAM5Opc(AddrOpc Opc, unsigned char Offset) { 476*06f32e7eSjoerg bool isSub = Opc == sub; 477*06f32e7eSjoerg return ((int)isSub << 8) | Offset; 478*06f32e7eSjoerg } 479*06f32e7eSjoerg inline unsigned char getAM5Offset(unsigned AM5Opc) { return AM5Opc & 0xFF; } 480*06f32e7eSjoerg inline AddrOpc getAM5Op(unsigned AM5Opc) { 481*06f32e7eSjoerg return ((AM5Opc >> 8) & 1) ? sub : add; 482*06f32e7eSjoerg } 483*06f32e7eSjoerg 484*06f32e7eSjoerg //===--------------------------------------------------------------------===// 485*06f32e7eSjoerg // Addressing Mode #5 FP16 486*06f32e7eSjoerg //===--------------------------------------------------------------------===// 487*06f32e7eSjoerg // 488*06f32e7eSjoerg // This is used for coprocessor instructions, such as 16-bit FP load/stores. 489*06f32e7eSjoerg // 490*06f32e7eSjoerg // addrmode5fp16 := reg +/- imm8*2 491*06f32e7eSjoerg // 492*06f32e7eSjoerg // The first operand is always a Reg. The second operand encodes the 493*06f32e7eSjoerg // operation (add or subtract) in bit 8 and the immediate in bits 0-7. 494*06f32e7eSjoerg 495*06f32e7eSjoerg /// getAM5FP16Opc - This function encodes the addrmode5fp16 opc field. 496*06f32e7eSjoerg inline unsigned getAM5FP16Opc(AddrOpc Opc, unsigned char Offset) { 497*06f32e7eSjoerg bool isSub = Opc == sub; 498*06f32e7eSjoerg return ((int)isSub << 8) | Offset; 499*06f32e7eSjoerg } 500*06f32e7eSjoerg inline unsigned char getAM5FP16Offset(unsigned AM5Opc) { 501*06f32e7eSjoerg return AM5Opc & 0xFF; 502*06f32e7eSjoerg } 503*06f32e7eSjoerg inline AddrOpc getAM5FP16Op(unsigned AM5Opc) { 504*06f32e7eSjoerg return ((AM5Opc >> 8) & 1) ? sub : add; 505*06f32e7eSjoerg } 506*06f32e7eSjoerg 507*06f32e7eSjoerg //===--------------------------------------------------------------------===// 508*06f32e7eSjoerg // Addressing Mode #6 509*06f32e7eSjoerg //===--------------------------------------------------------------------===// 510*06f32e7eSjoerg // 511*06f32e7eSjoerg // This is used for NEON load / store instructions. 512*06f32e7eSjoerg // 513*06f32e7eSjoerg // addrmode6 := reg with optional alignment 514*06f32e7eSjoerg // 515*06f32e7eSjoerg // This is stored in two operands [regaddr, align]. The first is the 516*06f32e7eSjoerg // address register. The second operand is the value of the alignment 517*06f32e7eSjoerg // specifier in bytes or zero if no explicit alignment. 518*06f32e7eSjoerg // Valid alignments depend on the specific instruction. 519*06f32e7eSjoerg 520*06f32e7eSjoerg //===--------------------------------------------------------------------===// 521*06f32e7eSjoerg // NEON/MVE Modified Immediates 522*06f32e7eSjoerg //===--------------------------------------------------------------------===// 523*06f32e7eSjoerg // 524*06f32e7eSjoerg // Several NEON and MVE instructions (e.g., VMOV) take a "modified immediate" 525*06f32e7eSjoerg // vector operand, where a small immediate encoded in the instruction 526*06f32e7eSjoerg // specifies a full NEON vector value. These modified immediates are 527*06f32e7eSjoerg // represented here as encoded integers. The low 8 bits hold the immediate 528*06f32e7eSjoerg // value; bit 12 holds the "Op" field of the instruction, and bits 11-8 hold 529*06f32e7eSjoerg // the "Cmode" field of the instruction. The interfaces below treat the 530*06f32e7eSjoerg // Op and Cmode values as a single 5-bit value. 531*06f32e7eSjoerg 532*06f32e7eSjoerg inline unsigned createVMOVModImm(unsigned OpCmode, unsigned Val) { 533*06f32e7eSjoerg return (OpCmode << 8) | Val; 534*06f32e7eSjoerg } 535*06f32e7eSjoerg inline unsigned getVMOVModImmOpCmode(unsigned ModImm) { 536*06f32e7eSjoerg return (ModImm >> 8) & 0x1f; 537*06f32e7eSjoerg } 538*06f32e7eSjoerg inline unsigned getVMOVModImmVal(unsigned ModImm) { return ModImm & 0xff; } 539*06f32e7eSjoerg 540*06f32e7eSjoerg /// decodeVMOVModImm - Decode a NEON/MVE modified immediate value into the 541*06f32e7eSjoerg /// element value and the element size in bits. (If the element size is 542*06f32e7eSjoerg /// smaller than the vector, it is splatted into all the elements.) 543*06f32e7eSjoerg inline uint64_t decodeVMOVModImm(unsigned ModImm, unsigned &EltBits) { 544*06f32e7eSjoerg unsigned OpCmode = getVMOVModImmOpCmode(ModImm); 545*06f32e7eSjoerg unsigned Imm8 = getVMOVModImmVal(ModImm); 546*06f32e7eSjoerg uint64_t Val = 0; 547*06f32e7eSjoerg 548*06f32e7eSjoerg if (OpCmode == 0xe) { 549*06f32e7eSjoerg // 8-bit vector elements 550*06f32e7eSjoerg Val = Imm8; 551*06f32e7eSjoerg EltBits = 8; 552*06f32e7eSjoerg } else if ((OpCmode & 0xc) == 0x8) { 553*06f32e7eSjoerg // 16-bit vector elements 554*06f32e7eSjoerg unsigned ByteNum = (OpCmode & 0x6) >> 1; 555*06f32e7eSjoerg Val = Imm8 << (8 * ByteNum); 556*06f32e7eSjoerg EltBits = 16; 557*06f32e7eSjoerg } else if ((OpCmode & 0x8) == 0) { 558*06f32e7eSjoerg // 32-bit vector elements, zero with one byte set 559*06f32e7eSjoerg unsigned ByteNum = (OpCmode & 0x6) >> 1; 560*06f32e7eSjoerg Val = Imm8 << (8 * ByteNum); 561*06f32e7eSjoerg EltBits = 32; 562*06f32e7eSjoerg } else if ((OpCmode & 0xe) == 0xc) { 563*06f32e7eSjoerg // 32-bit vector elements, one byte with low bits set 564*06f32e7eSjoerg unsigned ByteNum = 1 + (OpCmode & 0x1); 565*06f32e7eSjoerg Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum))); 566*06f32e7eSjoerg EltBits = 32; 567*06f32e7eSjoerg } else if (OpCmode == 0x1e) { 568*06f32e7eSjoerg // 64-bit vector elements 569*06f32e7eSjoerg for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) { 570*06f32e7eSjoerg if ((ModImm >> ByteNum) & 1) 571*06f32e7eSjoerg Val |= (uint64_t)0xff << (8 * ByteNum); 572*06f32e7eSjoerg } 573*06f32e7eSjoerg EltBits = 64; 574*06f32e7eSjoerg } else { 575*06f32e7eSjoerg llvm_unreachable("Unsupported VMOV immediate"); 576*06f32e7eSjoerg } 577*06f32e7eSjoerg return Val; 578*06f32e7eSjoerg } 579*06f32e7eSjoerg 580*06f32e7eSjoerg // Generic validation for single-byte immediate (0X00, 00X0, etc). 581*06f32e7eSjoerg inline bool isNEONBytesplat(unsigned Value, unsigned Size) { 582*06f32e7eSjoerg assert(Size >= 1 && Size <= 4 && "Invalid size"); 583*06f32e7eSjoerg unsigned count = 0; 584*06f32e7eSjoerg for (unsigned i = 0; i < Size; ++i) { 585*06f32e7eSjoerg if (Value & 0xff) count++; 586*06f32e7eSjoerg Value >>= 8; 587*06f32e7eSjoerg } 588*06f32e7eSjoerg return count == 1; 589*06f32e7eSjoerg } 590*06f32e7eSjoerg 591*06f32e7eSjoerg /// Checks if Value is a correct immediate for instructions like VBIC/VORR. 592*06f32e7eSjoerg inline bool isNEONi16splat(unsigned Value) { 593*06f32e7eSjoerg if (Value > 0xffff) 594*06f32e7eSjoerg return false; 595*06f32e7eSjoerg // i16 value with set bits only in one byte X0 or 0X. 596*06f32e7eSjoerg return Value == 0 || isNEONBytesplat(Value, 2); 597*06f32e7eSjoerg } 598*06f32e7eSjoerg 599*06f32e7eSjoerg // Encode NEON 16 bits Splat immediate for instructions like VBIC/VORR 600*06f32e7eSjoerg inline unsigned encodeNEONi16splat(unsigned Value) { 601*06f32e7eSjoerg assert(isNEONi16splat(Value) && "Invalid NEON splat value"); 602*06f32e7eSjoerg if (Value >= 0x100) 603*06f32e7eSjoerg Value = (Value >> 8) | 0xa00; 604*06f32e7eSjoerg else 605*06f32e7eSjoerg Value |= 0x800; 606*06f32e7eSjoerg return Value; 607*06f32e7eSjoerg } 608*06f32e7eSjoerg 609*06f32e7eSjoerg /// Checks if Value is a correct immediate for instructions like VBIC/VORR. 610*06f32e7eSjoerg inline bool isNEONi32splat(unsigned Value) { 611*06f32e7eSjoerg // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X. 612*06f32e7eSjoerg return Value == 0 || isNEONBytesplat(Value, 4); 613*06f32e7eSjoerg } 614*06f32e7eSjoerg 615*06f32e7eSjoerg /// Encode NEON 32 bits Splat immediate for instructions like VBIC/VORR. 616*06f32e7eSjoerg inline unsigned encodeNEONi32splat(unsigned Value) { 617*06f32e7eSjoerg assert(isNEONi32splat(Value) && "Invalid NEON splat value"); 618*06f32e7eSjoerg if (Value >= 0x100 && Value <= 0xff00) 619*06f32e7eSjoerg Value = (Value >> 8) | 0x200; 620*06f32e7eSjoerg else if (Value > 0xffff && Value <= 0xff0000) 621*06f32e7eSjoerg Value = (Value >> 16) | 0x400; 622*06f32e7eSjoerg else if (Value > 0xffffff) 623*06f32e7eSjoerg Value = (Value >> 24) | 0x600; 624*06f32e7eSjoerg return Value; 625*06f32e7eSjoerg } 626*06f32e7eSjoerg 627*06f32e7eSjoerg //===--------------------------------------------------------------------===// 628*06f32e7eSjoerg // Floating-point Immediates 629*06f32e7eSjoerg // 630*06f32e7eSjoerg inline float getFPImmFloat(unsigned Imm) { 631*06f32e7eSjoerg // We expect an 8-bit binary encoding of a floating-point number here. 632*06f32e7eSjoerg 633*06f32e7eSjoerg uint8_t Sign = (Imm >> 7) & 0x1; 634*06f32e7eSjoerg uint8_t Exp = (Imm >> 4) & 0x7; 635*06f32e7eSjoerg uint8_t Mantissa = Imm & 0xf; 636*06f32e7eSjoerg 637*06f32e7eSjoerg // 8-bit FP IEEE Float Encoding 638*06f32e7eSjoerg // abcd efgh aBbbbbbc defgh000 00000000 00000000 639*06f32e7eSjoerg // 640*06f32e7eSjoerg // where B = NOT(b); 641*06f32e7eSjoerg uint32_t I = 0; 642*06f32e7eSjoerg I |= Sign << 31; 643*06f32e7eSjoerg I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30; 644*06f32e7eSjoerg I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25; 645*06f32e7eSjoerg I |= (Exp & 0x3) << 23; 646*06f32e7eSjoerg I |= Mantissa << 19; 647*06f32e7eSjoerg return bit_cast<float>(I); 648*06f32e7eSjoerg } 649*06f32e7eSjoerg 650*06f32e7eSjoerg /// getFP16Imm - Return an 8-bit floating-point version of the 16-bit 651*06f32e7eSjoerg /// floating-point value. If the value cannot be represented as an 8-bit 652*06f32e7eSjoerg /// floating-point value, then return -1. 653*06f32e7eSjoerg inline int getFP16Imm(const APInt &Imm) { 654*06f32e7eSjoerg uint32_t Sign = Imm.lshr(15).getZExtValue() & 1; 655*06f32e7eSjoerg int32_t Exp = (Imm.lshr(10).getSExtValue() & 0x1f) - 15; // -14 to 15 656*06f32e7eSjoerg int64_t Mantissa = Imm.getZExtValue() & 0x3ff; // 10 bits 657*06f32e7eSjoerg 658*06f32e7eSjoerg // We can handle 4 bits of mantissa. 659*06f32e7eSjoerg // mantissa = (16+UInt(e:f:g:h))/16. 660*06f32e7eSjoerg if (Mantissa & 0x3f) 661*06f32e7eSjoerg return -1; 662*06f32e7eSjoerg Mantissa >>= 6; 663*06f32e7eSjoerg 664*06f32e7eSjoerg // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 665*06f32e7eSjoerg if (Exp < -3 || Exp > 4) 666*06f32e7eSjoerg return -1; 667*06f32e7eSjoerg Exp = ((Exp+3) & 0x7) ^ 4; 668*06f32e7eSjoerg 669*06f32e7eSjoerg return ((int)Sign << 7) | (Exp << 4) | Mantissa; 670*06f32e7eSjoerg } 671*06f32e7eSjoerg 672*06f32e7eSjoerg inline int getFP16Imm(const APFloat &FPImm) { 673*06f32e7eSjoerg return getFP16Imm(FPImm.bitcastToAPInt()); 674*06f32e7eSjoerg } 675*06f32e7eSjoerg 676*06f32e7eSjoerg /// getFP32Imm - Return an 8-bit floating-point version of the 32-bit 677*06f32e7eSjoerg /// floating-point value. If the value cannot be represented as an 8-bit 678*06f32e7eSjoerg /// floating-point value, then return -1. 679*06f32e7eSjoerg inline int getFP32Imm(const APInt &Imm) { 680*06f32e7eSjoerg uint32_t Sign = Imm.lshr(31).getZExtValue() & 1; 681*06f32e7eSjoerg int32_t Exp = (Imm.lshr(23).getSExtValue() & 0xff) - 127; // -126 to 127 682*06f32e7eSjoerg int64_t Mantissa = Imm.getZExtValue() & 0x7fffff; // 23 bits 683*06f32e7eSjoerg 684*06f32e7eSjoerg // We can handle 4 bits of mantissa. 685*06f32e7eSjoerg // mantissa = (16+UInt(e:f:g:h))/16. 686*06f32e7eSjoerg if (Mantissa & 0x7ffff) 687*06f32e7eSjoerg return -1; 688*06f32e7eSjoerg Mantissa >>= 19; 689*06f32e7eSjoerg if ((Mantissa & 0xf) != Mantissa) 690*06f32e7eSjoerg return -1; 691*06f32e7eSjoerg 692*06f32e7eSjoerg // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 693*06f32e7eSjoerg if (Exp < -3 || Exp > 4) 694*06f32e7eSjoerg return -1; 695*06f32e7eSjoerg Exp = ((Exp+3) & 0x7) ^ 4; 696*06f32e7eSjoerg 697*06f32e7eSjoerg return ((int)Sign << 7) | (Exp << 4) | Mantissa; 698*06f32e7eSjoerg } 699*06f32e7eSjoerg 700*06f32e7eSjoerg inline int getFP32Imm(const APFloat &FPImm) { 701*06f32e7eSjoerg return getFP32Imm(FPImm.bitcastToAPInt()); 702*06f32e7eSjoerg } 703*06f32e7eSjoerg 704*06f32e7eSjoerg /// getFP64Imm - Return an 8-bit floating-point version of the 64-bit 705*06f32e7eSjoerg /// floating-point value. If the value cannot be represented as an 8-bit 706*06f32e7eSjoerg /// floating-point value, then return -1. 707*06f32e7eSjoerg inline int getFP64Imm(const APInt &Imm) { 708*06f32e7eSjoerg uint64_t Sign = Imm.lshr(63).getZExtValue() & 1; 709*06f32e7eSjoerg int64_t Exp = (Imm.lshr(52).getSExtValue() & 0x7ff) - 1023; // -1022 to 1023 710*06f32e7eSjoerg uint64_t Mantissa = Imm.getZExtValue() & 0xfffffffffffffULL; 711*06f32e7eSjoerg 712*06f32e7eSjoerg // We can handle 4 bits of mantissa. 713*06f32e7eSjoerg // mantissa = (16+UInt(e:f:g:h))/16. 714*06f32e7eSjoerg if (Mantissa & 0xffffffffffffULL) 715*06f32e7eSjoerg return -1; 716*06f32e7eSjoerg Mantissa >>= 48; 717*06f32e7eSjoerg if ((Mantissa & 0xf) != Mantissa) 718*06f32e7eSjoerg return -1; 719*06f32e7eSjoerg 720*06f32e7eSjoerg // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 721*06f32e7eSjoerg if (Exp < -3 || Exp > 4) 722*06f32e7eSjoerg return -1; 723*06f32e7eSjoerg Exp = ((Exp+3) & 0x7) ^ 4; 724*06f32e7eSjoerg 725*06f32e7eSjoerg return ((int)Sign << 7) | (Exp << 4) | Mantissa; 726*06f32e7eSjoerg } 727*06f32e7eSjoerg 728*06f32e7eSjoerg inline int getFP64Imm(const APFloat &FPImm) { 729*06f32e7eSjoerg return getFP64Imm(FPImm.bitcastToAPInt()); 730*06f32e7eSjoerg } 731*06f32e7eSjoerg 732*06f32e7eSjoerg } // end namespace ARM_AM 733*06f32e7eSjoerg } // end namespace llvm 734*06f32e7eSjoerg 735*06f32e7eSjoerg #endif 736*06f32e7eSjoerg 737