return (Imm >> 8) * 2;
}
- /// getSOImmValOneRotate - 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, return 0.
- static inline unsigned getSOImmValOneRotate(unsigned Imm) {
- // A5.2.4 Constants with multiple encodings
- // The lowest unsigned value of rotation wins!
- for (unsigned R = 1; R <= 15; ++R)
- if ((Imm & rotr32(~255U, 2*R)) == 0)
- return 2*R;
-
- // Failed to find a suitable rotate amount.
- return 0;
- }
-
/// 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
if ((rotr32(Imm, RotAmt) & ~255U) == 0)
return (32-RotAmt)&31; // HW rotates right, not left.
- // For values like 0xF000000F, we should skip the first run of ones, then
+ // For values like 0xF000000F, we should ignore the low 6 bits, then
// retry the hunt.
- if (Imm & 1) {
- unsigned TrailingOnes = CountTrailingZeros_32(~Imm);
- if (TrailingOnes != 32) { // Avoid overflow on 0xFFFFFFFF
- // 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.
- }
+ if (Imm & 63U) {
+ unsigned TZ2 = CountTrailingZeros_32(Imm & ~63U);
+ unsigned RotAmt2 = TZ2 & ~1;
+ if ((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
// of zero.
if ((Arg & ~255U) == 0) return Arg;
- unsigned RotAmt = getSOImmValOneRotate(Arg);
+ unsigned RotAmt = getSOImmValRotate(Arg);
// If this cannot be handled with a single shifter_op, bail out.
if (rotr32(~255U, RotAmt) & Arg)
// IB - Increment before
// DA - Decrement after
// DB - Decrement before
- //
- // If the 4th bit (writeback)is set, then the base register is updated after
- // the memory transfer.
static inline AMSubMode getAM4SubMode(unsigned Mode) {
return (AMSubMode)(Mode & 0x7);
}
- static inline unsigned getAM4ModeImm(AMSubMode SubMode, bool WB = false) {
- return (int)SubMode | ((int)WB << 3);
- }
-
- static inline bool getAM4WBFlag(unsigned Mode) {
- return (Mode >> 3) & 1;
+ static inline unsigned getAM4ModeImm(AMSubMode SubMode) {
+ return (int)SubMode;
}
//===--------------------------------------------------------------------===//
// operation in bit 8 and the immediate in bits 0-7.
//
// This is also used for FP load/store multiple ops. The second operand
- // encodes the writeback mode in bit 8 and the number of registers (or 2
- // times the number of registers for DPR ops) in bits 0-7. In addition,
- // bits 9-11 encode one of the following two sub-modes:
+ // encodes the number of registers (or 2 times the number of registers
+ // for DPR ops) in bits 0-7. In addition, bits 8-10 encode one of the
+ // following two sub-modes:
//
// IA - Increment after
// DB - Decrement before
/// getAM5Opc - This function encodes the addrmode5 opc field for VLDM and
/// VSTM instructions.
- static inline unsigned getAM5Opc(AMSubMode SubMode, bool WB,
- unsigned char Offset) {
+ static inline unsigned getAM5Opc(AMSubMode SubMode, unsigned char Offset) {
assert((SubMode == ia || SubMode == db) &&
"Illegal addressing mode 5 sub-mode!");
- return ((int)SubMode << 9) | ((int)WB << 8) | Offset;
+ return ((int)SubMode << 8) | Offset;
}
static inline AMSubMode getAM5SubMode(unsigned AM5Opc) {
- return (AMSubMode)((AM5Opc >> 9) & 0x7);
- }
- static inline bool getAM5WBFlag(unsigned AM5Opc) {
- return ((AM5Opc >> 8) & 1);
+ return (AMSubMode)((AM5Opc >> 8) & 0x7);
}
//===--------------------------------------------------------------------===//
//
// This is used for NEON load / store instructions.
//
- // addrmode6 := reg with optional writeback and alignment
+ // addrmode6 := reg with optional alignment
//
- // This is stored in four operands [regaddr, regupdate, opc, align]. The
- // first is the address register. The second register holds the value of
- // a post-access increment for writeback or reg0 if no writeback or if the
- // writeback increment is the size of the memory access. The third
- // operand encodes whether there is writeback to the address register. The
- // fourth operand is the value of the alignment specifier to use or zero if
- // no explicit alignment.
-
- static inline unsigned getAM6Opc(bool WB = false) {
- return (int)WB;
- }
-
- static inline bool getAM6WBFlag(unsigned Mode) {
- return Mode & 1;
- }
+ // This is stored in two operands [regaddr, align]. The first is the
+ // address register. The second operand is the value of the alignment
+ // specifier to use or zero if no explicit alignment.
+ // Valid alignments are: 0, 8, 16, and 32 bytes, depending on the specific
+ // instruction.
} // end namespace ARM_AM
} // end namespace llvm