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