blob: 971b459a5f5e1df12740cf26b52dcce1df5a717b [file] [log] [blame]
Evan Chenga8e29892007-01-19 07:51:42 +00001//===- ARMAddressingModes.h - ARM Addressing Modes --------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Evan Chenga8e29892007-01-19 07:51:42 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the ARM addressing mode implementation stuff.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_TARGET_ARM_ARMADDRESSINGMODES_H
15#define LLVM_TARGET_ARM_ARMADDRESSINGMODES_H
16
Evan Chenga8e29892007-01-19 07:51:42 +000017#include "llvm/Support/MathExtras.h"
18#include <cassert>
19
20namespace llvm {
Jim Grosbach764ab522009-08-11 15:33:49 +000021
Evan Chenga8e29892007-01-19 07:51:42 +000022/// ARM_AM - ARM Addressing Mode Stuff
23namespace ARM_AM {
24 enum ShiftOpc {
25 no_shift = 0,
26 asr,
27 lsl,
28 lsr,
29 ror,
30 rrx
31 };
Jim Grosbach764ab522009-08-11 15:33:49 +000032
Evan Chenga8e29892007-01-19 07:51:42 +000033 enum AddrOpc {
34 add = '+', sub = '-'
35 };
Jim Grosbach764ab522009-08-11 15:33:49 +000036
Johnny Chen9e088762010-03-17 17:52:21 +000037 static inline const char *getAddrOpcStr(AddrOpc Op) {
38 return Op == sub ? "-" : "";
39 }
40
Evan Chenga8e29892007-01-19 07:51:42 +000041 static inline const char *getShiftOpcStr(ShiftOpc Op) {
42 switch (Op) {
Chris Lattner8514e212009-10-19 21:23:15 +000043 default: assert(0 && "Unknown shift opc!");
Evan Chenga8e29892007-01-19 07:51:42 +000044 case ARM_AM::asr: return "asr";
45 case ARM_AM::lsl: return "lsl";
46 case ARM_AM::lsr: return "lsr";
47 case ARM_AM::ror: return "ror";
48 case ARM_AM::rrx: return "rrx";
49 }
50 }
Jim Grosbach764ab522009-08-11 15:33:49 +000051
Jim Grosbach42fac8e2010-10-11 23:16:21 +000052 static inline unsigned getShiftOpcEncoding(ShiftOpc Op) {
53 switch (Op) {
54 default: assert(0 && "Unknown shift opc!");
55 case ARM_AM::asr: return 2;
56 case ARM_AM::lsl: return 0;
57 case ARM_AM::lsr: return 1;
58 case ARM_AM::ror: return 3;
59 }
60 }
61
Evan Chenga8e29892007-01-19 07:51:42 +000062 enum AMSubMode {
63 bad_am_submode = 0,
64 ia,
65 ib,
66 da,
67 db
68 };
69
70 static inline const char *getAMSubModeStr(AMSubMode Mode) {
71 switch (Mode) {
Chris Lattner8514e212009-10-19 21:23:15 +000072 default: assert(0 && "Unknown addressing sub-mode!");
Evan Chenga8e29892007-01-19 07:51:42 +000073 case ARM_AM::ia: return "ia";
74 case ARM_AM::ib: return "ib";
75 case ARM_AM::da: return "da";
76 case ARM_AM::db: return "db";
77 }
78 }
79
Evan Chenga8e29892007-01-19 07:51:42 +000080 /// rotr32 - Rotate a 32-bit unsigned value right by a specified # bits.
81 ///
82 static inline unsigned rotr32(unsigned Val, unsigned Amt) {
83 assert(Amt < 32 && "Invalid rotate amount");
84 return (Val >> Amt) | (Val << ((32-Amt)&31));
85 }
Jim Grosbach764ab522009-08-11 15:33:49 +000086
Evan Chenga8e29892007-01-19 07:51:42 +000087 /// rotl32 - Rotate a 32-bit unsigned value left by a specified # bits.
88 ///
89 static inline unsigned rotl32(unsigned Val, unsigned Amt) {
90 assert(Amt < 32 && "Invalid rotate amount");
91 return (Val << Amt) | (Val >> ((32-Amt)&31));
92 }
Jim Grosbach764ab522009-08-11 15:33:49 +000093
Evan Chenga8e29892007-01-19 07:51:42 +000094 //===--------------------------------------------------------------------===//
95 // Addressing Mode #1: shift_operand with registers
96 //===--------------------------------------------------------------------===//
97 //
98 // This 'addressing mode' is used for arithmetic instructions. It can
99 // represent things like:
100 // reg
101 // reg [asr|lsl|lsr|ror|rrx] reg
102 // reg [asr|lsl|lsr|ror|rrx] imm
103 //
104 // This is stored three operands [rega, regb, opc]. The first is the base
105 // reg, the second is the shift amount (or reg0 if not present or imm). The
106 // third operand encodes the shift opcode and the imm if a reg isn't present.
107 //
108 static inline unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm) {
109 return ShOp | (Imm << 3);
110 }
111 static inline unsigned getSORegOffset(unsigned Op) {
112 return Op >> 3;
113 }
114 static inline ShiftOpc getSORegShOp(unsigned Op) {
115 return (ShiftOpc)(Op & 7);
116 }
117
118 /// getSOImmValImm - Given an encoded imm field for the reg/imm form, return
119 /// the 8-bit imm value.
120 static inline unsigned getSOImmValImm(unsigned Imm) {
121 return Imm & 0xFF;
122 }
Bob Wilsond83712a2009-03-30 18:49:37 +0000123 /// getSOImmValRot - Given an encoded imm field for the reg/imm form, return
Evan Chenga8e29892007-01-19 07:51:42 +0000124 /// the rotate amount.
125 static inline unsigned getSOImmValRot(unsigned Imm) {
126 return (Imm >> 8) * 2;
127 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000128
Evan Chenga8e29892007-01-19 07:51:42 +0000129 /// getSOImmValRotate - Try to handle Imm with an immediate shifter operand,
130 /// computing the rotate amount to use. If this immediate value cannot be
131 /// handled with a single shifter-op, determine a good rotate amount that will
132 /// take a maximal chunk of bits out of the immediate.
133 static inline unsigned getSOImmValRotate(unsigned Imm) {
134 // 8-bit (or less) immediates are trivially shifter_operands with a rotate
135 // of zero.
136 if ((Imm & ~255U) == 0) return 0;
Jim Grosbach764ab522009-08-11 15:33:49 +0000137
Evan Chenga8e29892007-01-19 07:51:42 +0000138 // Use CTZ to compute the rotate amount.
139 unsigned TZ = CountTrailingZeros_32(Imm);
Jim Grosbach764ab522009-08-11 15:33:49 +0000140
Evan Chenga8e29892007-01-19 07:51:42 +0000141 // Rotate amount must be even. Something like 0x200 must be rotated 8 bits,
142 // not 9.
143 unsigned RotAmt = TZ & ~1;
Jim Grosbach764ab522009-08-11 15:33:49 +0000144
Evan Chenga8e29892007-01-19 07:51:42 +0000145 // If we can handle this spread, return it.
146 if ((rotr32(Imm, RotAmt) & ~255U) == 0)
147 return (32-RotAmt)&31; // HW rotates right, not left.
148
Johnny Chen8a87ffb2010-04-13 20:35:16 +0000149 // For values like 0xF000000F, we should ignore the low 6 bits, then
Evan Chenga8e29892007-01-19 07:51:42 +0000150 // retry the hunt.
Johnny Chen8a87ffb2010-04-13 20:35:16 +0000151 if (Imm & 63U) {
152 unsigned TZ2 = CountTrailingZeros_32(Imm & ~63U);
Bob Wilsonb123b8b2010-04-13 02:11:48 +0000153 unsigned RotAmt2 = TZ2 & ~1;
154 if ((rotr32(Imm, RotAmt2) & ~255U) == 0)
155 return (32-RotAmt2)&31; // HW rotates right, not left.
Evan Chenga8e29892007-01-19 07:51:42 +0000156 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000157
Evan Chenga8e29892007-01-19 07:51:42 +0000158 // Otherwise, we have no way to cover this span of bits with a single
159 // shifter_op immediate. Return a chunk of bits that will be useful to
160 // handle.
161 return (32-RotAmt)&31; // HW rotates right, not left.
162 }
163
164 /// getSOImmVal - Given a 32-bit immediate, if it is something that can fit
165 /// into an shifter_operand immediate operand, return the 12-bit encoding for
166 /// it. If not, return -1.
167 static inline int getSOImmVal(unsigned Arg) {
168 // 8-bit (or less) immediates are trivially shifter_operands with a rotate
169 // of zero.
170 if ((Arg & ~255U) == 0) return Arg;
Jim Grosbach764ab522009-08-11 15:33:49 +0000171
Johnny Chene6f83872010-03-17 18:32:39 +0000172 unsigned RotAmt = getSOImmValRotate(Arg);
Evan Chenga8e29892007-01-19 07:51:42 +0000173
174 // If this cannot be handled with a single shifter_op, bail out.
175 if (rotr32(~255U, RotAmt) & Arg)
176 return -1;
Jim Grosbach764ab522009-08-11 15:33:49 +0000177
Evan Chenga8e29892007-01-19 07:51:42 +0000178 // Encode this correctly.
179 return rotl32(Arg, RotAmt) | ((RotAmt>>1) << 8);
180 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000181
Evan Chenga8e29892007-01-19 07:51:42 +0000182 /// isSOImmTwoPartVal - Return true if the specified value can be obtained by
183 /// or'ing together two SOImmVal's.
184 static inline bool isSOImmTwoPartVal(unsigned V) {
185 // If this can be handled with a single shifter_op, bail out.
186 V = rotr32(~255U, getSOImmValRotate(V)) & V;
187 if (V == 0)
188 return false;
Jim Grosbach764ab522009-08-11 15:33:49 +0000189
Evan Chenga8e29892007-01-19 07:51:42 +0000190 // If this can be handled with two shifter_op's, accept.
191 V = rotr32(~255U, getSOImmValRotate(V)) & V;
192 return V == 0;
193 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000194
Evan Chenga8e29892007-01-19 07:51:42 +0000195 /// getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal,
196 /// return the first chunk of it.
197 static inline unsigned getSOImmTwoPartFirst(unsigned V) {
198 return rotr32(255U, getSOImmValRotate(V)) & V;
199 }
200
201 /// getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal,
202 /// return the second chunk of it.
203 static inline unsigned getSOImmTwoPartSecond(unsigned V) {
Jim Grosbach764ab522009-08-11 15:33:49 +0000204 // Mask out the first hunk.
Evan Chenga8e29892007-01-19 07:51:42 +0000205 V = rotr32(~255U, getSOImmValRotate(V)) & V;
Jim Grosbach764ab522009-08-11 15:33:49 +0000206
Evan Chenga8e29892007-01-19 07:51:42 +0000207 // Take what's left.
208 assert(V == (rotr32(255U, getSOImmValRotate(V)) & V));
209 return V;
210 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000211
Evan Chenga8e29892007-01-19 07:51:42 +0000212 /// getThumbImmValShift - Try to handle Imm with a 8-bit immediate followed
213 /// by a left shift. Returns the shift amount to use.
214 static inline unsigned getThumbImmValShift(unsigned Imm) {
215 // 8-bit (or less) immediates are trivially immediate operand with a shift
216 // of zero.
217 if ((Imm & ~255U) == 0) return 0;
218
219 // Use CTZ to compute the shift amount.
220 return CountTrailingZeros_32(Imm);
221 }
222
223 /// isThumbImmShiftedVal - Return true if the specified value can be obtained
224 /// by left shifting a 8-bit immediate.
225 static inline bool isThumbImmShiftedVal(unsigned V) {
Jim Grosbach764ab522009-08-11 15:33:49 +0000226 // If this can be handled with
Evan Chenga8e29892007-01-19 07:51:42 +0000227 V = (~255U << getThumbImmValShift(V)) & V;
228 return V == 0;
229 }
230
Evan Chengf49810c2009-06-23 17:48:47 +0000231 /// getThumbImm16ValShift - Try to handle Imm with a 16-bit immediate followed
232 /// by a left shift. Returns the shift amount to use.
233 static inline unsigned getThumbImm16ValShift(unsigned Imm) {
234 // 16-bit (or less) immediates are trivially immediate operand with a shift
235 // of zero.
236 if ((Imm & ~65535U) == 0) return 0;
237
238 // Use CTZ to compute the shift amount.
239 return CountTrailingZeros_32(Imm);
240 }
241
Jim Grosbach764ab522009-08-11 15:33:49 +0000242 /// isThumbImm16ShiftedVal - Return true if the specified value can be
Evan Chengf49810c2009-06-23 17:48:47 +0000243 /// obtained by left shifting a 16-bit immediate.
244 static inline bool isThumbImm16ShiftedVal(unsigned V) {
Jim Grosbach764ab522009-08-11 15:33:49 +0000245 // If this can be handled with
Evan Chengf49810c2009-06-23 17:48:47 +0000246 V = (~65535U << getThumbImm16ValShift(V)) & V;
247 return V == 0;
248 }
249
Evan Chenga8e29892007-01-19 07:51:42 +0000250 /// getThumbImmNonShiftedVal - If V is a value that satisfies
251 /// isThumbImmShiftedVal, return the non-shiftd value.
252 static inline unsigned getThumbImmNonShiftedVal(unsigned V) {
253 return V >> getThumbImmValShift(V);
254 }
255
Evan Cheng6495f632009-07-28 05:48:47 +0000256
Evan Chengf49810c2009-06-23 17:48:47 +0000257 /// getT2SOImmValSplat - Return the 12-bit encoded representation
258 /// if the specified value can be obtained by splatting the low 8 bits
259 /// into every other byte or every byte of a 32-bit value. i.e.,
260 /// 00000000 00000000 00000000 abcdefgh control = 0
261 /// 00000000 abcdefgh 00000000 abcdefgh control = 1
262 /// abcdefgh 00000000 abcdefgh 00000000 control = 2
263 /// abcdefgh abcdefgh abcdefgh abcdefgh control = 3
264 /// Return -1 if none of the above apply.
265 /// See ARM Reference Manual A6.3.2.
Evan Cheng6495f632009-07-28 05:48:47 +0000266 static inline int getT2SOImmValSplatVal(unsigned V) {
Evan Chengf49810c2009-06-23 17:48:47 +0000267 unsigned u, Vs, Imm;
268 // control = 0
Jim Grosbach764ab522009-08-11 15:33:49 +0000269 if ((V & 0xffffff00) == 0)
Evan Chengf49810c2009-06-23 17:48:47 +0000270 return V;
Jim Grosbach764ab522009-08-11 15:33:49 +0000271
Evan Chengf49810c2009-06-23 17:48:47 +0000272 // If the value is zeroes in the first byte, just shift those off
273 Vs = ((V & 0xff) == 0) ? V >> 8 : V;
274 // Any passing value only has 8 bits of payload, splatted across the word
275 Imm = Vs & 0xff;
276 // Likewise, any passing values have the payload splatted into the 3rd byte
277 u = Imm | (Imm << 16);
278
279 // control = 1 or 2
280 if (Vs == u)
281 return (((Vs == V) ? 1 : 2) << 8) | Imm;
282
283 // control = 3
284 if (Vs == (u | (u << 8)))
285 return (3 << 8) | Imm;
286
287 return -1;
288 }
289
Evan Cheng6495f632009-07-28 05:48:47 +0000290 /// getT2SOImmValRotateVal - Return the 12-bit encoded representation if the
Evan Chengf49810c2009-06-23 17:48:47 +0000291 /// specified value is a rotated 8-bit value. Return -1 if no rotation
292 /// encoding is possible.
293 /// See ARM Reference Manual A6.3.2.
Evan Cheng6495f632009-07-28 05:48:47 +0000294 static inline int getT2SOImmValRotateVal(unsigned V) {
Evan Chengf49810c2009-06-23 17:48:47 +0000295 unsigned RotAmt = CountLeadingZeros_32(V);
296 if (RotAmt >= 24)
297 return -1;
298
299 // If 'Arg' can be handled with a single shifter_op return the value.
300 if ((rotr32(0xff000000U, RotAmt) & V) == V)
301 return (rotr32(V, 24 - RotAmt) & 0x7f) | ((RotAmt + 8) << 7);
302
303 return -1;
304 }
305
306 /// getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit
Jim Grosbach764ab522009-08-11 15:33:49 +0000307 /// into a Thumb-2 shifter_operand immediate operand, return the 12-bit
Evan Chengf49810c2009-06-23 17:48:47 +0000308 /// encoding for it. If not, return -1.
309 /// See ARM Reference Manual A6.3.2.
310 static inline int getT2SOImmVal(unsigned Arg) {
311 // If 'Arg' is an 8-bit splat, then get the encoded value.
Evan Cheng6495f632009-07-28 05:48:47 +0000312 int Splat = getT2SOImmValSplatVal(Arg);
Evan Chengf49810c2009-06-23 17:48:47 +0000313 if (Splat != -1)
314 return Splat;
Jim Grosbach764ab522009-08-11 15:33:49 +0000315
Evan Chengf49810c2009-06-23 17:48:47 +0000316 // If 'Arg' can be handled with a single shifter_op return the value.
Evan Cheng6495f632009-07-28 05:48:47 +0000317 int Rot = getT2SOImmValRotateVal(Arg);
Evan Chengf49810c2009-06-23 17:48:47 +0000318 if (Rot != -1)
319 return Rot;
320
321 return -1;
322 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000323
Jim Grosbach65b7f3a2009-10-21 20:44:34 +0000324 static inline unsigned getT2SOImmValRotate(unsigned V) {
325 if ((V & ~255U) == 0) return 0;
326 // Use CTZ to compute the rotate amount.
327 unsigned RotAmt = CountTrailingZeros_32(V);
328 return (32 - RotAmt) & 31;
329 }
330
331 static inline bool isT2SOImmTwoPartVal (unsigned Imm) {
332 unsigned V = Imm;
333 // Passing values can be any combination of splat values and shifter
334 // values. If this can be handled with a single shifter or splat, bail
335 // out. Those should be handled directly, not with a two-part val.
336 if (getT2SOImmValSplatVal(V) != -1)
337 return false;
338 V = rotr32 (~255U, getT2SOImmValRotate(V)) & V;
339 if (V == 0)
340 return false;
341
342 // If this can be handled as an immediate, accept.
343 if (getT2SOImmVal(V) != -1) return true;
344
345 // Likewise, try masking out a splat value first.
346 V = Imm;
347 if (getT2SOImmValSplatVal(V & 0xff00ff00U) != -1)
348 V &= ~0xff00ff00U;
349 else if (getT2SOImmValSplatVal(V & 0x00ff00ffU) != -1)
350 V &= ~0x00ff00ffU;
351 // If what's left can be handled as an immediate, accept.
352 if (getT2SOImmVal(V) != -1) return true;
353
354 // Otherwise, do not accept.
355 return false;
356 }
357
358 static inline unsigned getT2SOImmTwoPartFirst(unsigned Imm) {
359 assert (isT2SOImmTwoPartVal(Imm) &&
360 "Immedate cannot be encoded as two part immediate!");
361 // Try a shifter operand as one part
362 unsigned V = rotr32 (~255, getT2SOImmValRotate(Imm)) & Imm;
363 // If the rest is encodable as an immediate, then return it.
364 if (getT2SOImmVal(V) != -1) return V;
365
366 // Try masking out a splat value first.
367 if (getT2SOImmValSplatVal(Imm & 0xff00ff00U) != -1)
368 return Imm & 0xff00ff00U;
369
370 // The other splat is all that's left as an option.
371 assert (getT2SOImmValSplatVal(Imm & 0x00ff00ffU) != -1);
372 return Imm & 0x00ff00ffU;
373 }
374
375 static inline unsigned getT2SOImmTwoPartSecond(unsigned Imm) {
376 // Mask out the first hunk
377 Imm ^= getT2SOImmTwoPartFirst(Imm);
378 // Return what's left
379 assert (getT2SOImmVal(Imm) != -1 &&
380 "Unable to encode second part of T2 two part SO immediate");
381 return Imm;
382 }
383
Evan Chengf49810c2009-06-23 17:48:47 +0000384
Evan Chenga8e29892007-01-19 07:51:42 +0000385 //===--------------------------------------------------------------------===//
386 // Addressing Mode #2
387 //===--------------------------------------------------------------------===//
388 //
389 // This is used for most simple load/store instructions.
390 //
391 // addrmode2 := reg +/- reg shop imm
392 // addrmode2 := reg +/- imm12
393 //
394 // The first operand is always a Reg. The second operand is a reg if in
395 // reg/reg form, otherwise it's reg#0. The third field encodes the operation
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000396 // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. The
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000397 // fourth operand 16-17 encodes the index mode.
Evan Chenga8e29892007-01-19 07:51:42 +0000398 //
399 // If this addressing mode is a frame index (before prolog/epilog insertion
400 // and code rewriting), this operand will have the form: FI#, reg0, <offs>
401 // with no shift amount for the frame offset.
Jim Grosbach764ab522009-08-11 15:33:49 +0000402 //
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000403 static inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO,
404 unsigned IdxMode = 0) {
Evan Chenga8e29892007-01-19 07:51:42 +0000405 assert(Imm12 < (1 << 12) && "Imm too large!");
406 bool isSub = Opc == sub;
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000407 return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16) ;
Evan Chenga8e29892007-01-19 07:51:42 +0000408 }
409 static inline unsigned getAM2Offset(unsigned AM2Opc) {
410 return AM2Opc & ((1 << 12)-1);
411 }
412 static inline AddrOpc getAM2Op(unsigned AM2Opc) {
413 return ((AM2Opc >> 12) & 1) ? sub : add;
414 }
415 static inline ShiftOpc getAM2ShiftOpc(unsigned AM2Opc) {
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000416 return (ShiftOpc)((AM2Opc >> 13) & 7);
417 }
418 static inline unsigned getAM2IdxMode(unsigned AM2Opc) {
419 return (AM2Opc >> 16);
Evan Chenga8e29892007-01-19 07:51:42 +0000420 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000421
422
Evan Chenga8e29892007-01-19 07:51:42 +0000423 //===--------------------------------------------------------------------===//
424 // Addressing Mode #3
425 //===--------------------------------------------------------------------===//
426 //
427 // This is used for sign-extending loads, and load/store-pair instructions.
428 //
429 // addrmode3 := reg +/- reg
430 // addrmode3 := reg +/- imm8
431 //
432 // The first operand is always a Reg. The second operand is a reg if in
433 // reg/reg form, otherwise it's reg#0. The third field encodes the operation
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000434 // in bit 8, the immediate in bits 0-7. The fourth operand 9-10 encodes the
435 // index mode.
Jim Grosbach764ab522009-08-11 15:33:49 +0000436
Evan Chenga8e29892007-01-19 07:51:42 +0000437 /// getAM3Opc - This function encodes the addrmode3 opc field.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000438 static inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset,
439 unsigned IdxMode = 0) {
Evan Chenga8e29892007-01-19 07:51:42 +0000440 bool isSub = Opc == sub;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000441 return ((int)isSub << 8) | Offset | (IdxMode << 9);
Evan Chenga8e29892007-01-19 07:51:42 +0000442 }
443 static inline unsigned char getAM3Offset(unsigned AM3Opc) {
444 return AM3Opc & 0xFF;
445 }
446 static inline AddrOpc getAM3Op(unsigned AM3Opc) {
447 return ((AM3Opc >> 8) & 1) ? sub : add;
448 }
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000449 static inline unsigned getAM3IdxMode(unsigned AM3Opc) {
450 return (AM3Opc >> 9);
451 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000452
Evan Chenga8e29892007-01-19 07:51:42 +0000453 //===--------------------------------------------------------------------===//
454 // Addressing Mode #4
455 //===--------------------------------------------------------------------===//
456 //
457 // This is used for load / store multiple instructions.
458 //
459 // addrmode4 := reg, <mode>
460 //
461 // The four modes are:
462 // IA - Increment after
463 // IB - Increment before
464 // DA - Decrement after
465 // DB - Decrement before
Bob Wilsond4bfd542010-08-27 23:18:17 +0000466 // For VFP instructions, only the IA and DB modes are valid.
Evan Chenga8e29892007-01-19 07:51:42 +0000467
468 static inline AMSubMode getAM4SubMode(unsigned Mode) {
469 return (AMSubMode)(Mode & 0x7);
470 }
471
Bob Wilsonab346052010-03-16 17:46:45 +0000472 static inline unsigned getAM4ModeImm(AMSubMode SubMode) {
473 return (int)SubMode;
Evan Chenga8e29892007-01-19 07:51:42 +0000474 }
475
476 //===--------------------------------------------------------------------===//
477 // Addressing Mode #5
478 //===--------------------------------------------------------------------===//
479 //
480 // This is used for coprocessor instructions, such as FP load/stores.
481 //
482 // addrmode5 := reg +/- imm8*4
483 //
Bob Wilsond4d826e2009-07-01 21:22:45 +0000484 // The first operand is always a Reg. The second operand encodes the
485 // operation in bit 8 and the immediate in bits 0-7.
Jim Grosbach764ab522009-08-11 15:33:49 +0000486
Evan Chenga8e29892007-01-19 07:51:42 +0000487 /// getAM5Opc - This function encodes the addrmode5 opc field.
488 static inline unsigned getAM5Opc(AddrOpc Opc, unsigned char Offset) {
489 bool isSub = Opc == sub;
490 return ((int)isSub << 8) | Offset;
491 }
492 static inline unsigned char getAM5Offset(unsigned AM5Opc) {
493 return AM5Opc & 0xFF;
494 }
495 static inline AddrOpc getAM5Op(unsigned AM5Opc) {
496 return ((AM5Opc >> 8) & 1) ? sub : add;
497 }
498
Bob Wilson8b024a52009-07-01 23:16:05 +0000499 //===--------------------------------------------------------------------===//
500 // Addressing Mode #6
501 //===--------------------------------------------------------------------===//
502 //
503 // This is used for NEON load / store instructions.
504 //
Bob Wilson226036e2010-03-20 22:13:40 +0000505 // addrmode6 := reg with optional alignment
Bob Wilson8b024a52009-07-01 23:16:05 +0000506 //
Bob Wilson226036e2010-03-20 22:13:40 +0000507 // This is stored in two operands [regaddr, align]. The first is the
508 // address register. The second operand is the value of the alignment
Bob Wilson273ff312010-07-14 23:54:43 +0000509 // specifier in bytes or zero if no explicit alignment.
510 // Valid alignments depend on the specific instruction.
Bob Wilson8b024a52009-07-01 23:16:05 +0000511
Bob Wilson6dce00c2010-07-13 04:44:34 +0000512 //===--------------------------------------------------------------------===//
513 // NEON Modified Immediates
514 //===--------------------------------------------------------------------===//
515 //
516 // Several NEON instructions (e.g., VMOV) take a "modified immediate"
517 // vector operand, where a small immediate encoded in the instruction
518 // specifies a full NEON vector value. These modified immediates are
519 // represented here as encoded integers. The low 8 bits hold the immediate
520 // value; bit 12 holds the "Op" field of the instruction, and bits 11-8 hold
521 // the "Cmode" field of the instruction. The interfaces below treat the
522 // Op and Cmode values as a single 5-bit value.
523
524 static inline unsigned createNEONModImm(unsigned OpCmode, unsigned Val) {
525 return (OpCmode << 8) | Val;
526 }
527 static inline unsigned getNEONModImmOpCmode(unsigned ModImm) {
528 return (ModImm >> 8) & 0x1f;
529 }
530 static inline unsigned getNEONModImmVal(unsigned ModImm) {
531 return ModImm & 0xff;
532 }
533
534 /// decodeNEONModImm - Decode a NEON modified immediate value into the
535 /// element value and the element size in bits. (If the element size is
536 /// smaller than the vector, it is splatted into all the elements.)
537 static inline uint64_t decodeNEONModImm(unsigned ModImm, unsigned &EltBits) {
538 unsigned OpCmode = getNEONModImmOpCmode(ModImm);
539 unsigned Imm8 = getNEONModImmVal(ModImm);
540 uint64_t Val = 0;
541
542 if (OpCmode == 0xe) {
543 // 8-bit vector elements
544 Val = Imm8;
545 EltBits = 8;
546 } else if ((OpCmode & 0xc) == 0x8) {
547 // 16-bit vector elements
548 unsigned ByteNum = (OpCmode & 0x6) >> 1;
549 Val = Imm8 << (8 * ByteNum);
550 EltBits = 16;
551 } else if ((OpCmode & 0x8) == 0) {
552 // 32-bit vector elements, zero with one byte set
553 unsigned ByteNum = (OpCmode & 0x6) >> 1;
554 Val = Imm8 << (8 * ByteNum);
555 EltBits = 32;
556 } else if ((OpCmode & 0xe) == 0xc) {
557 // 32-bit vector elements, one byte with low bits set
558 unsigned ByteNum = 1 + (OpCmode & 0x1);
559 Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum)));
560 EltBits = 32;
561 } else if (OpCmode == 0x1e) {
562 // 64-bit vector elements
563 for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) {
564 if ((ModImm >> ByteNum) & 1)
565 Val |= (uint64_t)0xff << (8 * ByteNum);
566 }
567 EltBits = 64;
568 } else {
569 assert(false && "Unsupported NEON immediate");
570 }
571 return Val;
572 }
573
Bill Wendling2567eec2010-11-17 05:31:09 +0000574 AMSubMode getLoadStoreMultipleSubMode(int Opcode);
575
Evan Chenga8e29892007-01-19 07:51:42 +0000576} // end namespace ARM_AM
577} // end namespace llvm
578
579#endif
580