Thumb2 assembler aliases for "mov(shifted register)"
authorJim Grosbach <grosbach@apple.com>
Tue, 13 Dec 2011 22:45:11 +0000 (22:45 +0000)
committerJim Grosbach <grosbach@apple.com>
Tue, 13 Dec 2011 22:45:11 +0000 (22:45 +0000)
rdar://10549767

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146520 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMInstrThumb2.td
lib/Target/ARM/AsmParser/ARMAsmParser.cpp
test/MC/ARM/basic-thumb2-instructions.s

index 6f9201c0e7fce3470f3cba959c5a9907b6290ff7..c8ab59fc6f1293baee5982e1b29e7c2aaf267ec2 100644 (file)
@@ -4126,3 +4126,10 @@ def : t2InstAlias<"mul${p} $Rn, $Rm",
 // "neg" is and alias for "rsb rd, rn, #0"
 def : t2InstAlias<"neg${s}${p} $Rd, $Rm",
                   (t2RSBri rGPR:$Rd, rGPR:$Rm, 0, pred:$p, cc_out:$s)>;
+
+// MOV so_reg assembler pseudos. InstAlias isn't expressive enough for
+// these, unfortunately.
+def t2MOVsi: t2AsmPseudo<"mov${p} $Rd, $shift",
+                         (ins rGPR:$Rd, t2_so_reg:$shift, pred:$p)>;
+def t2MOVSsi: t2AsmPseudo<"movs${p} $Rd, $shift",
+                          (ins rGPR:$Rd, t2_so_reg:$shift, pred:$p)>;
index 745fa897725359a5e81a2bc72a8425e88bc7fdbe..b7db86acf0782c9a5afdc5cefa1c82a4c8d97b02 100644 (file)
@@ -5248,7 +5248,44 @@ processInstruction(MCInst &Inst,
     Inst = TmpInst;
     return true;
   }
-  // Handle the MOV complex aliases.
+  // Handle the Thumb2 mode MOV complex aliases.
+  case ARM::t2MOVsi:
+  case ARM::t2MOVSsi: {
+    // Which instruction to expand to depends on the CCOut operand and
+    // whether we're in an IT block if the register operands are low
+    // registers.
+    bool isNarrow = false;
+    if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
+        isARMLowRegister(Inst.getOperand(1).getReg()) &&
+        inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
+      isNarrow = true;
+    MCInst TmpInst;
+    unsigned newOpc;
+    switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
+    default: llvm_unreachable("unexpected opcode!");
+    case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
+    case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
+    case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
+    case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
+    }
+    unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
+    if (Ammount == 32) Ammount = 0;
+    TmpInst.setOpcode(newOpc);
+    TmpInst.addOperand(Inst.getOperand(0)); // Rd
+    if (isNarrow)
+      TmpInst.addOperand(MCOperand::CreateReg(
+          Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
+    TmpInst.addOperand(Inst.getOperand(1)); // Rn
+    TmpInst.addOperand(MCOperand::CreateImm(Ammount));
+    TmpInst.addOperand(Inst.getOperand(3)); // CondCode
+    TmpInst.addOperand(Inst.getOperand(4));
+    if (!isNarrow)
+      TmpInst.addOperand(MCOperand::CreateReg(
+          Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
+    Inst = TmpInst;
+    return true;
+  }
+  // Handle the ARM mode MOV complex aliases.
   case ARM::ASRr:
   case ARM::LSRr:
   case ARM::LSLr:
index 9577ea6b05f3a9ef5fb052fec35d06e2ad12470b..028e17bdc9a7cdc0454593ce6db29359418dd7c2 100644 (file)
@@ -1147,6 +1147,18 @@ _func:
 
 @ CHECK: mvn   r3, #2                  @ encoding: [0x6f,0xf0,0x02,0x03]
 
+@------------------------------------------------------------------------------
+@ MOV(shifted register)
+@------------------------------------------------------------------------------
+        mov r6, r2, lsl #16
+        mov r6, r2, lsr #16
+        movs r6, r2, asr #32
+        movs r6, r2, ror #5
+
+@ CHECK: lsl.w r6, r2, #16             @ encoding: [0x4f,0xea,0x02,0x46]
+@ CHECK: lsr.w r6, r2, #16             @ encoding: [0x4f,0xea,0x12,0x46]
+@ CHECK: asrs  r6, r2, #32             @ encoding: [0x16,0x10]
+@ CHECK: rors.w        r6, r2, #5              @ encoding: [0x5f,0xea,0x72,0x16]
 
 
 @------------------------------------------------------------------------------