Fix emission of move immediate for ARM integrated assembler.

BUG= https://code.google.com/p/nativeclient/issues/detail?id=4334
R=jpp@chromium.org

Review URL: https://codereview.chromium.org/1397043003 .
diff --git a/src/DartARM32/assembler_arm.cc b/src/DartARM32/assembler_arm.cc
index fee25dc..ec942d0 100644
--- a/src/DartARM32/assembler_arm.cc
+++ b/src/DartARM32/assembler_arm.cc
@@ -71,7 +71,8 @@
   buffer_.Emit<int32_t>(value);
 }
 
-
+#if 0
+// Moved to class AssemblerARM32.
 void Assembler::EmitType01(Condition cond,
                            int type,
                            Opcode opcode,
@@ -90,7 +91,7 @@
                      o.encoding();
   Emit(encoding);
 }
-
+#endif
 
 void Assembler::EmitType5(Condition cond, int32_t offset, bool link) {
   ASSERT(cond != kNoCondition);
@@ -277,10 +278,13 @@
 }
 
 
+#if 0
+// Moved to AssemblerARM32::mov(..FlexImm..)
+// TODO(kschimpf) other forms of move.
 void Assembler::mov(Register rd, Operand o, Condition cond) {
   EmitType01(cond, o.type(), MOV, 0, R0, rd, o);
 }
-
+#endif
 
 void Assembler::movs(Register rd, Operand o, Condition cond) {
   EmitType01(cond, o.type(), MOV, 1, R0, rd, o);
diff --git a/src/DartARM32/assembler_arm.h b/src/DartARM32/assembler_arm.h
index 7893d6f..31c93c4 100644
--- a/src/DartARM32/assembler_arm.h
+++ b/src/DartARM32/assembler_arm.h
@@ -28,7 +28,7 @@
 class StubEntry;
 
 #if 0
-// Moved to: ARM32::AssemblerARM32.
+// Moved to: ARM32::AssemblerARM32 as needed
 // Instruction encoding bits.
 enum {
   H   = 1 << 5,   // halfword (or byte)
@@ -139,12 +139,15 @@
     encoding_ = immediate;
   }
 
+#if 0
+  // Moved to AssemblerARM32::encodeImm12FromFlexImm.
   // Data-processing operands - Rotated immediate.
   Operand(uint32_t rotate, uint32_t immed8) {
     ASSERT((rotate < (1 << kRotateBits)) && (immed8 < (1 << kImmed8Bits)));
     type_ = 1;
     encoding_ = (rotate << kRotateShift) | (immed8 << kImmed8Shift);
   }
+#endif
 
   // Data-processing operands - Register.
   explicit Operand(Register rm) {
@@ -465,7 +468,11 @@
   void orr(Register rd, Register rn, Operand o, Condition cond = AL);
   void orrs(Register rd, Register rn, Operand o, Condition cond = AL);
 
+#if 0
+  // Moved to IceAssemblerARM32::mov(..FlexImm..)
+  // TODO(kschimpf) other forms of move.
   void mov(Register rd, Operand o, Condition cond = AL);
+#endif
   void movs(Register rd, Operand o, Condition cond = AL);
 
   void bic(Register rd, Register rn, Operand o, Condition cond = AL);
@@ -1084,6 +1091,8 @@
                         bool is_unique,
                         Register pp);
 
+#if 0
+  // Moved to class AssemblerARM32.
   void EmitType01(Condition cond,
                   int type,
                   Opcode opcode,
@@ -1091,6 +1100,7 @@
                   Register rn,
                   Register rd,
                   Operand o);
+#endif
 
   void EmitType5(Condition cond, int32_t offset, bool link);
 
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp
index ab22450..16f1e4a 100644
--- a/src/IceAssemblerARM32.cpp
+++ b/src/IceAssemblerARM32.cpp
@@ -24,6 +24,65 @@
 
 namespace Ice {
 
+// The following define individual bits.
+static constexpr uint32_t B0 = 1;
+static constexpr uint32_t B2 = 1 << 2;
+static constexpr uint32_t B3 = 1 << 3;
+static constexpr uint32_t B4 = 1 << 4;
+static constexpr uint32_t B5 = 1 << 5;
+static constexpr uint32_t B6 = 1 << 6;
+static constexpr uint32_t B21 = 1 << 21;
+static constexpr uint32_t B24 = 1 << 24;
+
+// Constants used for the decoding or encoding of the individual fields of
+// instructions. Based on ARM section A5.1.
+static constexpr uint32_t kConditionShift = 28;
+static constexpr uint32_t kOpcodeShift = 21;
+static constexpr uint32_t kRdShift = 12;
+static constexpr uint32_t kRmShift = 0;
+static constexpr uint32_t kRnShift = 16;
+static constexpr uint32_t kSShift = 20;
+static constexpr uint32_t kTypeShift = 25;
+
+// Immediate instruction fields encoding.
+static constexpr uint32_t kImmed8Bits = 8;
+static constexpr uint32_t kImmed8Shift = 0;
+static constexpr uint32_t kRotateBits = 4;
+static constexpr uint32_t kRotateShift = 8;
+
+// Types of instructions.
+static constexpr uint32_t kInstTypeImmediate = 1;
+
+inline uint32_t encodeBool(bool b) { return b ? 1 : 0; }
+
+inline uint32_t encodeGPRRegister(RegARM32::GPRRegister Rn) {
+  return static_cast<uint32_t>(Rn);
+}
+
+inline bool isGPRRegisterDefined(RegARM32::GPRRegister R) {
+  return R != RegARM32::Encoded_Not_GPR;
+}
+
+inline bool isGPRRegisterDefined(uint32_t R) {
+  return R != encodeGPRRegister(RegARM32::Encoded_Not_GPR);
+}
+
+inline bool isConditionDefined(CondARM32::Cond Cond) {
+  return Cond != CondARM32::kNone;
+}
+
+inline uint32_t encodeCondition(CondARM32::Cond Cond) {
+  return static_cast<uint32_t>(Cond);
+}
+
+// Converts rotated immediate into imm12.
+inline uint32_t encodeImm12FromFlexImm(const OperandARM32FlexImm &FlexImm) {
+  uint32_t Immed8 = FlexImm.getImm();
+  uint32_t Rotate = FlexImm.getRotateAmt();
+  assert((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits)));
+  return (Rotate << kRotateShift) | (Immed8 << kImmed8Shift);
+}
+
 Label *ARM32::AssemblerARM32::getOrCreateLabel(SizeT Number,
                                                LabelVector &Labels) {
   Label *L = nullptr;
@@ -56,20 +115,47 @@
   label->bindTo(bound);
 }
 
-void ARM32::AssemblerARM32::bkpt(uint16_t imm16) {
-  AssemblerBuffer::EnsureCapacity ensured(&Buffer);
-  emitInt32(BkptEncoding(imm16));
+void ARM32::AssemblerARM32::emitType01(CondARM32::Cond Cond, uint32_t Type,
+                                       uint32_t Opcode, bool SetCc, uint32_t Rn,
+                                       uint32_t Rd, uint32_t Imm12) {
+  assert(isGPRRegisterDefined(Rd));
+  assert(Cond != CondARM32::kNone);
+  uint32_t Encoding = encodeCondition(Cond) << kConditionShift |
+                      (Type << kTypeShift) | (Opcode << kOpcodeShift) |
+                      (encodeBool(SetCc) << kSShift) | (Rn << kRnShift) |
+                      (Rd << kRdShift) | Imm12;
+  emitInst(Encoding);
 }
 
-void ARM32::AssemblerARM32::bx(RegARM32::GPRRegister rm, CondARM32::Cond cond) {
-  // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond.
-  assert(rm != RegARM32::Encoded_Not_GPR);
-  assert(cond != CondARM32::kNone);
+void ARM32::AssemblerARM32::bkpt(uint16_t imm16) {
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
-  int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | B24 |
-                     B21 | (0xfff << 8) | B4 |
-                     (static_cast<int32_t>(rm) << kRmShift);
-  emitInt32(encoding);
+  uint32_t Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 |
+                      ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf);
+  emitInst(Encoding);
+}
+
+void ARM32::AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) {
+  // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond.
+  // (ARM section A8.8.27, encoding A1).
+  assert(isGPRRegisterDefined(Rm));
+  assert(isConditionDefined(Cond));
+  AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+  uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | B21 |
+                      (0xfff << 8) | B4 | (encodeGPRRegister(Rm) << kRmShift);
+  emitInst(Encoding);
+}
+
+void ARM32::AssemblerARM32::mov(RegARM32::GPRRegister Rd,
+                                const OperandARM32FlexImm &FlexImm,
+                                CondARM32::Cond Cond) {
+  // cccc0011101s0000ddddiiiiiiiiiiii (ARM section A8.8.102, encoding A1)
+  assert(isConditionDefined(Cond));
+  AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+  bool SetCc = false; // Note: We don't use movs in this assembler.
+  uint32_t Rn = 0;
+  uint32_t Mov = B3 | B2 | B0; // 1101.
+  emitType01(Cond, kInstTypeImmediate, Mov, SetCc, Rn, encodeGPRRegister(Rd),
+             encodeImm12FromFlexImm(FlexImm));
 }
 
 } // end of namespace Ice
diff --git a/src/IceAssemblerARM32.h b/src/IceAssemblerARM32.h
index 2b6bbb1..f3885bf 100644
--- a/src/IceAssemblerARM32.h
+++ b/src/IceAssemblerARM32.h
@@ -18,6 +18,10 @@
 /// \file
 /// This file implements the Assembler class for ARM32.
 ///
+/// Note: All references to ARM "section" documentation refers to the "ARM
+/// Architecture Reference Manual, ARMv7-A and ARMv7-R edition". See:
+/// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0406c
+///
 //===----------------------------------------------------------------------===//
 
 #ifndef SUBZERO_SRC_ICEASSEMBLERARM32_H
@@ -27,6 +31,7 @@
 #include "IceConditionCodesARM32.h"
 #include "IceDefs.h"
 #include "IceFixups.h"
+#include "IceInstARM32.h"
 #include "IceRegistersARM32.h"
 #include "IceTargetLowering.h"
 
@@ -74,8 +79,8 @@
   }
 
   Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override {
-    (void)NodeNumber;
-    llvm_unreachable("Not yet implemented.");
+    assert(NodeNumber < CfgNodeLabels.size());
+    return CfgNodeLabels[NodeNumber];
   }
 
   void bindCfgNodeLabel(SizeT NodeNumber) override {
@@ -90,145 +95,18 @@
   }
   void bind(Label *label);
 
-  void bkpt(uint16_t imm16);
+  void bkpt(uint16_t Imm16);
 
-  void bx(RegARM32::GPRRegister rm, CondARM32::Cond cond = CondARM32::AL);
+  void mov(RegARM32::GPRRegister Rd, const OperandARM32FlexImm &FlexImm,
+           CondARM32::Cond Cond);
+
+  void bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond = CondARM32::AL);
 
   static bool classof(const Assembler *Asm) {
     return Asm->getKind() == Asm_ARM32;
   }
 
 private:
-  // Instruction encoding bits.
-
-  // halfword (or byte)
-  static constexpr uint32_t H = 1 << 5;
-  // load (or store)
-  static constexpr uint32_t L = 1 << 20;
-  // set condition code (or leave unchanged)
-  static constexpr uint32_t S = 1 << 20;
-  // writeback base register (or leave unchanged)
-  static constexpr uint32_t W = 1 << 21;
-  // accumulate in multiply instruction (or not)
-  static constexpr uint32_t A = 1 << 21;
-  // unsigned byte (or word)
-  static constexpr uint32_t B = 1 << 22;
-  // high/lo bit of start of s/d register range
-  static constexpr uint32_t D = 1 << 22;
-  // long (or short)
-  static constexpr uint32_t N = 1 << 22;
-  // positive (or negative) offset/index
-  static constexpr uint32_t U = 1 << 23;
-  // offset/pre-indexed addressing (or post-indexed addressing)
-  static constexpr uint32_t P = 1 << 24;
-  // immediate shifter operand (or not)
-  static constexpr uint32_t I = 1 << 25;
-
-  // The following define individual bits.
-  static constexpr uint32_t B0 = 1;
-  static constexpr uint32_t B1 = 1 << 1;
-  static constexpr uint32_t B2 = 1 << 2;
-  static constexpr uint32_t B3 = 1 << 3;
-  static constexpr uint32_t B4 = 1 << 4;
-  static constexpr uint32_t B5 = 1 << 5;
-  static constexpr uint32_t B6 = 1 << 6;
-  static constexpr uint32_t B7 = 1 << 7;
-  static constexpr uint32_t B8 = 1 << 8;
-  static constexpr uint32_t B9 = 1 << 9;
-  static constexpr uint32_t B10 = 1 << 10;
-  static constexpr uint32_t B11 = 1 << 11;
-  static constexpr uint32_t B12 = 1 << 12;
-  static constexpr uint32_t B16 = 1 << 16;
-  static constexpr uint32_t B17 = 1 << 17;
-  static constexpr uint32_t B18 = 1 << 18;
-  static constexpr uint32_t B19 = 1 << 19;
-  static constexpr uint32_t B20 = 1 << 20;
-  static constexpr uint32_t B21 = 1 << 21;
-  static constexpr uint32_t B22 = 1 << 22;
-  static constexpr uint32_t B23 = 1 << 23;
-  static constexpr uint32_t B24 = 1 << 24;
-  static constexpr uint32_t B25 = 1 << 25;
-  static constexpr uint32_t B26 = 1 << 26;
-  static constexpr uint32_t B27 = 1 << 27;
-
-  // Constants used for the decoding or encoding of the individual fields of
-  // instructions. Based on section A5.1 from the "ARM Architecture Reference
-  // Manual, ARMv7-A and ARMv7-R edition". See:
-  // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0406c
-  static constexpr uint32_t kConditionShift = 28;
-  static constexpr uint32_t kConditionBits = 4;
-  static constexpr uint32_t kTypeShift = 25;
-  static constexpr uint32_t kTypeBits = 3;
-  static constexpr uint32_t kLinkShift = 24;
-  static constexpr uint32_t kLinkBits = 1;
-  static constexpr uint32_t kUShift = 23;
-  static constexpr uint32_t kUBits = 1;
-  static constexpr uint32_t kOpcodeShift = 21;
-  static constexpr uint32_t kOpcodeBits = 4;
-  static constexpr uint32_t kSShift = 20;
-  static constexpr uint32_t kSBits = 1;
-  static constexpr uint32_t kRnShift = 16;
-  static constexpr uint32_t kRnBits = 4;
-  static constexpr uint32_t kRdShift = 12;
-  static constexpr uint32_t kRdBits = 4;
-  static constexpr uint32_t kRsShift = 8;
-  static constexpr uint32_t kRsBits = 4;
-  static constexpr uint32_t kRmShift = 0;
-  static constexpr uint32_t kRmBits = 4;
-
-  // Immediate instruction fields encoding.
-  static constexpr uint32_t kRotateShift = 8;
-  static constexpr uint32_t kRotateBits = 4;
-  static constexpr uint32_t kImmed8Shift = 0;
-  static constexpr uint32_t kImmed8Bits = 8;
-
-  // Shift instruction register fields encodings.
-  static constexpr uint32_t kShiftImmShift = 7;
-  static constexpr uint32_t kShiftRegisterShift = 8;
-  static constexpr uint32_t kShiftImmBits = 5;
-  static constexpr uint32_t kShiftShift = 5;
-  static constexpr uint32_t kShiftBits = 2;
-
-  // Load/store instruction offset field encoding.
-  static constexpr uint32_t kOffset12Shift = 0;
-  static constexpr uint32_t kOffset12Bits = 12;
-  static constexpr uint32_t kOffset12Mask = 0x00000fff;
-
-  // Mul instruction register field encodings.
-  static constexpr uint32_t kMulRdShift = 16;
-  static constexpr uint32_t kMulRdBits = 4;
-  static constexpr uint32_t kMulRnShift = 12;
-  static constexpr uint32_t kMulRnBits = 4;
-
-  // Div instruction register field encodings.
-  static constexpr uint32_t kDivRdShift = 16;
-  static constexpr uint32_t kDivRdBits = 4;
-  static constexpr uint32_t kDivRmShift = 8;
-  static constexpr uint32_t kDivRmBints = 4;
-  static constexpr uint32_t kDivRnShift = 0;
-  static constexpr uint32_t kDivRnBits = 4;
-
-  // ldrex/strex register field encodings.
-  static constexpr uint32_t kLdExRnShift = 16;
-  static constexpr uint32_t kLdExRtShift = 12;
-  static constexpr uint32_t kStrExRnShift = 16;
-  static constexpr uint32_t kStrExRdShift = 12;
-  static constexpr uint32_t kStrExRtShift = 0;
-
-  // MRC instruction offset field encoding.
-  static constexpr uint32_t kCRmShift = 0;
-  static constexpr uint32_t kCRmBits = 4;
-  static constexpr uint32_t kOpc2Shift = 5;
-  static constexpr uint32_t kOpc2Bits = 3;
-  static constexpr uint32_t kCoprocShift = 8;
-  static constexpr uint32_t kCoprocBits = 4;
-  static constexpr uint32_t kCRnShift = 16;
-  static constexpr uint32_t kCRnBits = 4;
-  static constexpr uint32_t kOpc1Shift = 21;
-  static constexpr uint32_t kOpc1Bits = 3;
-
-  static constexpr uint32_t kBranchOffsetMask = 0x00ffffff;
-
   // A vector of pool-allocated x86 labels for CFG nodes.
   using LabelVector = std::vector<Label *>;
   LabelVector CfgNodeLabels;
@@ -238,14 +116,12 @@
     return getOrCreateLabel(NodeNumber, CfgNodeLabels);
   }
 
-  void emitInt32(int32_t Value) { Buffer.emit<int32_t>(Value); }
+  void emitInst(uint32_t Value) { Buffer.emit<uint32_t>(Value); }
 
-  static int32_t BkptEncoding(uint16_t imm16) {
-    // bkpt requires that the cond field is AL.
-    // cccc00010010iiiiiiiiiiii0111iiii where cccc=AL and i in imm16
-    return (CondARM32::AL << kConditionShift) | B24 | B21 |
-           ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf);
-  }
+  // Pattern cccctttoooosnnnnddddiiiiiiiiiiii where cccc=Cond, ttt=Type,
+  // oooo=Opcode, nnnn=Rn, dddd=Rd, iiiiiiiiiiii=imm12 (See ARM section A5.2.3).
+  void emitType01(CondARM32::Cond Cond, uint32_t Type, uint32_t Opcode,
+                  bool SetCc, uint32_t Rn, uint32_t Rd, uint32_t imm12);
 };
 
 } // end of namespace ARM32
diff --git a/src/IceInstARM32.cpp b/src/IceInstARM32.cpp
index b45d2f1..7e510ca 100644
--- a/src/IceInstARM32.cpp
+++ b/src/IceInstARM32.cpp
@@ -592,6 +592,29 @@
   }
 }
 
+void InstARM32Mov::emitIASSingleDestSingleSource(const Cfg *Func) const {
+  ARM32::AssemblerARM32 *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
+  Variable *Dest = getDest();
+  Operand *Src0 = getSrc(0);
+  // Note: Loop is used so that we can short circuit using break.
+  do {
+    if (Dest->hasReg()) {
+      Type DestTy = Dest->getType();
+      const bool DestIsVector = isVectorType(DestTy);
+      const bool DestIsScalarFP = isScalarFloatingType(DestTy);
+      const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0);
+      if (DestIsVector || DestIsScalarFP || CoreVFPMove)
+        break;
+      if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Src0)) {
+        Asm->mov(static_cast<RegARM32::GPRRegister>(Dest->getRegNum()),
+                 *FlexImm, getPredicate());
+        return;
+      }
+    }
+  } while (0);
+  llvm_unreachable("not yet implemented");
+}
+
 void InstARM32Mov::emit(const Cfg *Func) const {
   if (!BuildDefs::dump())
     return;
@@ -612,7 +635,13 @@
 void InstARM32Mov::emitIAS(const Cfg *Func) const {
   assert(getSrcSize() == 1);
   (void)Func;
-  llvm_unreachable("Not yet implemented");
+  assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type.");
+  if (isMultiDest())
+    llvm_unreachable("Not yet implemented");
+  if (isMultiSource())
+    llvm_unreachable("Not yet implemented");
+  // Must be single source/dest.
+  emitIASSingleDestSingleSource(Func);
 }
 
 void InstARM32Mov::dump(const Cfg *Func) const {
diff --git a/src/IceInstARM32.h b/src/IceInstARM32.h
index 60b2484..680c30a 100644
--- a/src/IceInstARM32.h
+++ b/src/IceInstARM32.h
@@ -1175,6 +1175,8 @@
   void emitSingleDestMultiSource(const Cfg *Func) const;
   void emitSingleDestSingleSource(const Cfg *Func) const;
 
+  void emitIASSingleDestSingleSource(const Cfg *Func) const;
+
   Variable *DestHi = nullptr;
 };
 
diff --git a/tests_lit/assembler/arm32/mov-imm.ll b/tests_lit/assembler/arm32/mov-imm.ll
new file mode 100644
index 0000000..3cabd57
--- /dev/null
+++ b/tests_lit/assembler/arm32/mov-imm.ll
@@ -0,0 +1,243 @@
+; Show that we know how to translate move (immediate) ARM instruction.
+
+; RUN: %p2i --filetype=asm -i %s --target=arm32 \
+; RUN:   | FileCheck %s --check-prefix=ASM
+; RUN: %p2i --filetype=iasm -i %s --target=arm32 \
+; RUN:   | FileCheck %s --check-prefix=IASM
+
+define internal i32 @Imm1() {
+  ret i32 1
+}
+
+; ASM-LABEL: Imm1:
+; ASM: mov	r0, #1
+; IASM-LABEL: Imm1:
+; IASM:	.byte 0x1
+; IASM:	.byte 0x0
+; IASM:	.byte 0xa0
+; IASM:	.byte 0xe3
+
+
+define internal i32 @rotateFImmAA() {
+  ; immediate = 0x000002a8 = b 0000 0000 0000 0000 0000 0010 1010 1000
+  ret i32 680 
+}
+
+; ASM-LABEL: rotateFImmAA:
+; ASM: mov	r0, #680
+
+; IASM-LABEL: rotateFImmAA:
+; IASM:	.byte 0xaa
+; IASM:	.byte 0xf
+; IASM:	.byte 0xa0
+; IASM:	.byte 0xe3
+
+define internal i32 @rotateEImmAA() {
+ ; immediate = 0x00000aa0 = b 0000 0000 0000 0000 0000 1010 1010 0000
+  ret i32 2720
+}
+
+; ASM-LABEL: rotateEImmAA:
+; ASM: mov	r0, #2720
+
+; IASM-LABEL: rotateEImmAA:
+; IASM:	.byte 0xaa
+; IASM:	.byte 0xe
+; IASM:	.byte 0xa0
+; IASM:	.byte 0xe3
+
+define internal i32 @rotateDImmAA() {
+  ; immediate = 0x00002a80 = b 0000 0000 0000 0000 0010 1010 1000 0000
+  ret i32 10880 
+}
+
+; ASM-LABEL: rotateDImmAA:
+; ASM: mov	r0, #10880
+
+; IASM-LABEL: rotateDImmAA:
+; IASM:	.byte 0xaa
+; IASM:	.byte 0xd
+; IASM:	.byte 0xa0
+; IASM:	.byte 0xe3
+
+define internal i32 @rotateCImmAA() {
+  ; immediate = 0x0000aa00 = b 0000 0000 0000 0000 1010 1010 0000 0000
+  ret i32 43520 
+}
+
+; ASM-LABEL: rotateCImmAA:
+; ASM: mov	r0, #43520
+
+; IASM-LABEL: rotateCImmAA:
+; IASM:	.byte 0xaa
+; IASM:	.byte 0xc
+; IASM:	.byte 0xa0
+; IASM:	.byte 0xe3
+
+define internal i32 @rotateBImmAA() {
+  ; immediate = 0x0002a800 = b 0000 0000 0000 0010 1010 1000 0000 0000
+  ret i32 174080 
+}
+
+; ASM-LABEL: rotateBImmAA:
+; ASM: mov	r0, #174080
+
+; IASM-LABEL: rotateBImmAA:
+; IASM:	.byte 0xaa
+; IASM:	.byte 0xb
+; IASM:	.byte 0xa0
+; IASM:	.byte 0xe3
+
+define internal i32 @rotateAImmAA() {
+  ; immediate = 0x000aa000 = b 0000 0000 0000 1010 1010 0000 0000 0000
+  ret i32 696320 
+}
+
+; ASM-LABEL: rotateAImmAA:
+; ASM: mov	r0, #696320
+
+; IASM-LABEL: rotateAImmAA:
+; IASM:	.byte 0xaa
+; IASM:	.byte 0xa
+; IASM:	.byte 0xa0
+; IASM:	.byte 0xe3
+
+define internal i32 @rotate9ImmAA() {
+  ; immediate = 0x002a8000 = b 0000 0000 0010 1010 1000 0000 0000 0000
+  ret i32 2785280
+}
+
+; ASM-LABEL: rotate9ImmAA:
+; ASM: mov	r0, #2785280
+
+; IASM-LABEL: rotate9ImmAA:
+; IASM:	.byte 0xaa
+; IASM:	.byte 0x9
+; IASM:	.byte 0xa0
+; IASM:	.byte 0xe3
+
+define internal i32 @rotate8ImmAA() {
+  ; immediate = 0x00aa0000 = b 0000 0000 1010 1010 0000 0000 0000 0000
+  ret i32 11141120
+}
+
+; ASM-LABEL: rotate8ImmAA:
+; ASM: mov	r0, #11141120
+
+; IASM-LABEL: rotate8ImmAA:
+; IASM:	.byte 0xaa
+; IASM:	.byte 0x8
+; IASM:	.byte 0xa0
+; IASM:	.byte 0xe3
+
+define internal i32 @rotate7ImmAA() {
+  ; immediate = 0x02a80000 = b 0000 0010 1010 1000 0000 0000 0000 0000
+  ret i32 44564480
+}
+
+; ASM-LABEL: rotate7ImmAA:
+; ASM: 	mov	r0, #44564480
+
+; IASM-LABEL: rotate7ImmAA:
+; IASM:	.byte 0xaa
+; IASM:	.byte 0x7
+; IASM:	.byte 0xa0
+; IASM:	.byte 0xe3
+
+define internal i32 @rotate6ImmAA() {
+  ; immediate = 0x0aa00000 = b 0000 1010 1010 0000 0000 0000 0000 0000
+  ret i32 178257920
+}
+
+; ASM-LABEL: rotate6ImmAA:
+; ASM: 	mov	r0, #178257920
+
+; IASM-LABEL: rotate6ImmAA:
+; IASM:	.byte 0xaa
+; IASM:	.byte 0x6
+; IASM:	.byte 0xa0
+; IASM:	.byte 0xe3
+
+define internal i32 @rotate5ImmAA() {
+  ; immediate = 0x2a800000 = b 0010 1010 1000 0000 0000 0000 0000 0000
+  ret i32 713031680
+}
+
+; ASM-LABEL: rotate5ImmAA:
+; ASM: 	mov	r0, #713031680
+
+; IASM-LABEL: rotate5ImmAA:
+; IASM:	.byte 0xaa
+; IASM:	.byte 0x5
+; IASM:	.byte 0xa0
+; IASM:	.byte 0xe3
+
+define internal i32 @rotate4ImmAA() {
+  ; immediate = 0xaa000000 = b 1010 1010 0000 0000 0000 0000 0000 0000
+  ret i32 2852126720
+}
+
+; ASM-LABEL: rotate4ImmAA:
+; ASM: mov	r0, #2852126720
+
+; IASM-LABEL: rotate4ImmAA:
+; IASM:	.byte 0xaa
+; IASM:	.byte 0x4
+; IASM:	.byte 0xa0
+; IASM:	.byte 0xe3
+
+define internal i32 @rotate3ImmAA() {
+  ; immediate = 0xa8000002 = b 1010 1000 0000 0000 0000 0000 0000 0010
+  ret i32 2818572290
+}
+
+; ASM-LABEL: rotate3ImmAA:
+; ASM: mov	r0, #2818572290
+
+; IASM-LABEL: rotate3ImmAA:
+; IASM:	.byte 0xaa
+; IASM:	.byte 0x3
+; IASM:	.byte 0xa0
+; IASM:	.byte 0xe3
+
+define internal i32 @rotate2ImmAA() {
+  ; immediate = 0xa000000a = b 1010 0000 0000 0000 0000 0000 0000 1010
+  ret i32 2684354570
+}
+
+; ASM-LABEL: rotate2ImmAA:
+; ASM: 	mov	r0, #2684354570
+
+; IASM-LABEL: rotate2ImmAA:
+; IASM:	.byte 0xaa
+; IASM:	.byte 0x2
+; IASM:	.byte 0xa0
+; IASM:	.byte 0xe3
+
+define internal i32 @rotate1ImmAA() {
+  ; immediate = 0x8000002a = b 1000 1000 0000 0000 0000 0000 0010 1010
+  ret i32 2147483690
+}
+
+; ASM-LABEL: rotate1ImmAA:
+; ASM: mov	r0, #2147483690
+
+; IASM-LABEL: rotate1ImmAA:
+; IASM:	.byte 0xaa
+; IASM:	.byte 0x1
+; IASM:	.byte 0xa0
+; IASM:	.byte 0xe3
+
+define internal i32 @rotate0ImmAA() {
+  ; immediate = 0x000000aa = b 0000 0000 0000 0000 0000 0000 1010 1010
+  ret i32 170
+}
+
+; ASM-LABEL: rotate0ImmAA:
+; ASM: mov	r0, #170
+
+; IASM-LABEL: rotate0ImmAA:
+; IASM:	.byte 0xaa
+; IASM:	.byte 0x0
+; IASM:	.byte 0xa0
+; IASM:	.byte 0xe3