#define LLVM_TARGET_ARM_ARMADDRESSINGMODES_H
#include "llvm/CodeGen/SelectionDAGNodes.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
namespace llvm {
-
+
/// ARM_AM - ARM Addressing Mode Stuff
namespace ARM_AM {
enum ShiftOpc {
ror,
rrx
};
-
+
enum AddrOpc {
add = '+', sub = '-'
};
-
+
static inline const char *getShiftOpcStr(ShiftOpc Op) {
switch (Op) {
- default: assert(0 && "Unknown shift opc!");
+ default: llvm_unreachable("Unknown shift opc!");
case ARM_AM::asr: return "asr";
case ARM_AM::lsl: return "lsl";
case ARM_AM::lsr: return "lsr";
case ARM_AM::rrx: return "rrx";
}
}
-
+
static inline ShiftOpc getShiftOpcForNode(SDValue N) {
switch (N.getOpcode()) {
default: return ARM_AM::no_shift;
static inline const char *getAMSubModeStr(AMSubMode Mode) {
switch (Mode) {
- default: assert(0 && "Unknown addressing sub-mode!");
+ default: llvm_unreachable("Unknown addressing sub-mode!");
case ARM_AM::ia: return "ia";
case ARM_AM::ib: return "ib";
case ARM_AM::da: return "da";
static inline const char *getAMSubModeAltStr(AMSubMode Mode, bool isLD) {
switch (Mode) {
- default: assert(0 && "Unknown addressing sub-mode!");
+ default: llvm_unreachable("Unknown addressing sub-mode!");
case ARM_AM::ia: return isLD ? "fd" : "ea";
case ARM_AM::ib: return isLD ? "ed" : "fa";
case ARM_AM::da: return isLD ? "fa" : "ed";
assert(Amt < 32 && "Invalid rotate amount");
return (Val >> Amt) | (Val << ((32-Amt)&31));
}
-
+
/// rotl32 - Rotate a 32-bit unsigned value left by a specified # bits.
///
static inline unsigned rotl32(unsigned Val, unsigned Amt) {
assert(Amt < 32 && "Invalid rotate amount");
return (Val << Amt) | (Val >> ((32-Amt)&31));
}
-
+
//===--------------------------------------------------------------------===//
// Addressing Mode #1: shift_operand with registers
//===--------------------------------------------------------------------===//
static inline unsigned getSOImmValRot(unsigned Imm) {
return (Imm >> 8) * 2;
}
-
+
/// getSOImmValRotate - Try to handle Imm with an immediate shifter operand,
/// computing the rotate amount to use. If this immediate value cannot be
/// handled with a single shifter-op, determine a good rotate amount that will
// 8-bit (or less) immediates are trivially shifter_operands with a rotate
// of zero.
if ((Imm & ~255U) == 0) return 0;
-
+
// Use CTZ to compute the rotate amount.
unsigned TZ = CountTrailingZeros_32(Imm);
-
+
// Rotate amount must be even. Something like 0x200 must be rotated 8 bits,
// not 9.
unsigned RotAmt = TZ & ~1;
-
+
// If we can handle this spread, return it.
if ((rotr32(Imm, RotAmt) & ~255U) == 0)
return (32-RotAmt)&31; // HW rotates right, not left.
// Restart the search for a high-order bit after the initial seconds of
// ones.
unsigned TZ2 = CountTrailingZeros_32(Imm & ~((1 << TrailingOnes)-1));
-
+
// Rotate amount must be even.
unsigned RotAmt2 = TZ2 & ~1;
-
+
// If this fits, use it.
if (RotAmt2 != 32 && (rotr32(Imm, RotAmt2) & ~255U) == 0)
return (32-RotAmt2)&31; // HW rotates right, not left.
}
}
-
+
// Otherwise, we have no way to cover this span of bits with a single
// shifter_op immediate. Return a chunk of bits that will be useful to
// handle.
// 8-bit (or less) immediates are trivially shifter_operands with a rotate
// of zero.
if ((Arg & ~255U) == 0) return Arg;
-
+
unsigned RotAmt = getSOImmValRotate(Arg);
// If this cannot be handled with a single shifter_op, bail out.
if (rotr32(~255U, RotAmt) & Arg)
return -1;
-
+
// Encode this correctly.
return rotl32(Arg, RotAmt) | ((RotAmt>>1) << 8);
}
-
+
/// isSOImmTwoPartVal - Return true if the specified value can be obtained by
/// or'ing together two SOImmVal's.
static inline bool isSOImmTwoPartVal(unsigned V) {
V = rotr32(~255U, getSOImmValRotate(V)) & V;
if (V == 0)
return false;
-
+
// If this can be handled with two shifter_op's, accept.
V = rotr32(~255U, getSOImmValRotate(V)) & V;
return V == 0;
}
-
+
/// getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal,
/// return the first chunk of it.
static inline unsigned getSOImmTwoPartFirst(unsigned V) {
/// getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal,
/// return the second chunk of it.
static inline unsigned getSOImmTwoPartSecond(unsigned V) {
- // Mask out the first hunk.
+ // Mask out the first hunk.
V = rotr32(~255U, getSOImmValRotate(V)) & V;
-
+
// Take what's left.
assert(V == (rotr32(255U, getSOImmValRotate(V)) & V));
return V;
}
-
+
/// getThumbImmValShift - Try to handle Imm with a 8-bit immediate followed
/// by a left shift. Returns the shift amount to use.
static inline unsigned getThumbImmValShift(unsigned Imm) {
/// isThumbImmShiftedVal - Return true if the specified value can be obtained
/// by left shifting a 8-bit immediate.
static inline bool isThumbImmShiftedVal(unsigned V) {
- // If this can be handled with
+ // If this can be handled with
V = (~255U << getThumbImmValShift(V)) & V;
return V == 0;
}
return CountTrailingZeros_32(Imm);
}
- /// isThumbImm16ShiftedVal - Return true if the specified value can be
+ /// isThumbImm16ShiftedVal - Return true if the specified value can be
/// obtained by left shifting a 16-bit immediate.
static inline bool isThumbImm16ShiftedVal(unsigned V) {
- // If this can be handled with
+ // If this can be handled with
V = (~65535U << getThumbImm16ValShift(V)) & V;
return V == 0;
}
return V >> getThumbImmValShift(V);
}
- /// getT2SOImmValDecode - Given a 12-bit encoded Thumb-2 modified immediate,
- /// return the corresponding 32-bit immediate value.
- /// See ARM Reference Manual A6.3.2.
- static inline unsigned getT2SOImmValDecode(unsigned Imm) {
- unsigned Base = Imm & 0xff;
- switch ((Imm >> 8) & 0xf) {
- case 0:
- return Base;
- case 1:
- return Base | (Base << 16);
- case 2:
- return (Base << 8) | (Base << 24);
- case 3:
- return Base | (Base << 8) | (Base << 16) | (Base << 24);
- default:
- break;
- }
-
- // shifted immediate
- unsigned RotAmount = ((Imm >> 7) & 0x1f) - 8;
- return (Base | 0x80) << (24 - RotAmount);
- }
/// getT2SOImmValSplat - Return the 12-bit encoded representation
/// if the specified value can be obtained by splatting the low 8 bits
/// abcdefgh abcdefgh abcdefgh abcdefgh control = 3
/// Return -1 if none of the above apply.
/// See ARM Reference Manual A6.3.2.
- static inline int getT2SOImmValSplat(unsigned V) {
+ static inline int getT2SOImmValSplatVal(unsigned V) {
unsigned u, Vs, Imm;
// control = 0
- if ((V & 0xffffff00) == 0)
+ if ((V & 0xffffff00) == 0)
return V;
-
+
// If the value is zeroes in the first byte, just shift those off
Vs = ((V & 0xff) == 0) ? V >> 8 : V;
// Any passing value only has 8 bits of payload, splatted across the word
return -1;
}
- /// getT2SOImmValRotate - Return the 12-bit encoded representation if the
+ /// getT2SOImmValRotateVal - Return the 12-bit encoded representation if the
/// specified value is a rotated 8-bit value. Return -1 if no rotation
/// encoding is possible.
/// See ARM Reference Manual A6.3.2.
- static inline int getT2SOImmValRotate (unsigned V) {
+ static inline int getT2SOImmValRotateVal(unsigned V) {
unsigned RotAmt = CountLeadingZeros_32(V);
if (RotAmt >= 24)
return -1;
}
/// getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit
- /// into a Thumb-2 shifter_operand immediate operand, return the 12-bit
+ /// into a Thumb-2 shifter_operand immediate operand, return the 12-bit
/// encoding for it. If not, return -1.
/// See ARM Reference Manual A6.3.2.
static inline int getT2SOImmVal(unsigned Arg) {
// If 'Arg' is an 8-bit splat, then get the encoded value.
- int Splat = getT2SOImmValSplat(Arg);
+ int Splat = getT2SOImmValSplatVal(Arg);
if (Splat != -1)
return Splat;
-
+
// If 'Arg' can be handled with a single shifter_op return the value.
- int Rot = getT2SOImmValRotate(Arg);
+ int Rot = getT2SOImmValRotateVal(Arg);
if (Rot != -1)
return Rot;
return -1;
}
-
+
//===--------------------------------------------------------------------===//
// Addressing Mode #2
// If this addressing mode is a frame index (before prolog/epilog insertion
// and code rewriting), this operand will have the form: FI#, reg0, <offs>
// with no shift amount for the frame offset.
- //
+ //
static inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO) {
assert(Imm12 < (1 << 12) && "Imm too large!");
bool isSub = Opc == sub;
static inline ShiftOpc getAM2ShiftOpc(unsigned AM2Opc) {
return (ShiftOpc)(AM2Opc >> 13);
}
-
-
+
+
//===--------------------------------------------------------------------===//
// Addressing Mode #3
//===--------------------------------------------------------------------===//
// The first operand is always a Reg. The second operand is a reg if in
// reg/reg form, otherwise it's reg#0. The third field encodes the operation
// in bit 8, the immediate in bits 0-7.
-
+
/// getAM3Opc - This function encodes the addrmode3 opc field.
static inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset) {
bool isSub = Opc == sub;
static inline AddrOpc getAM3Op(unsigned AM3Opc) {
return ((AM3Opc >> 8) & 1) ? sub : add;
}
-
+
//===--------------------------------------------------------------------===//
// Addressing Mode #4
//===--------------------------------------------------------------------===//
//
// IA - Increment after
// DB - Decrement before
-
+
/// getAM5Opc - This function encodes the addrmode5 opc field.
static inline unsigned getAM5Opc(AddrOpc Opc, unsigned char Offset) {
bool isSub = Opc == sub;