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