Don't use PassInfo* as a type identifier for passes. Instead, use the address of...
[oota-llvm.git] / lib / Target / ARM / ARMCodeEmitter.cpp
index 49e83c3f8a9632ed0f1ea55ea7a5327949e894de..089d1c51598f41c9ccfa6b2e4db36abbfc9596f3 100644 (file)
@@ -55,6 +55,7 @@ namespace {
     const std::vector<MachineConstantPoolEntry> *MCPEs;
     const std::vector<MachineJumpTableEntry> *MJTEs;
     bool IsPIC;
+    bool IsThumb;
 
     void getAnalysisUsage(AnalysisUsage &AU) const {
       AU.addRequired<MachineModuleInfo>();
@@ -64,11 +65,11 @@ namespace {
     static char ID;
   public:
     ARMCodeEmitter(TargetMachine &tm, JITCodeEmitter &mce)
-      : MachineFunctionPass(&ID), JTI(0),
+      : MachineFunctionPass(ID), JTI(0),
         II((const ARMInstrInfo *)tm.getInstrInfo()),
         TD(tm.getTargetData()), TM(tm),
-    MCE(mce), MCPEs(0), MJTEs(0),
-    IsPIC(TM.getRelocationModel() == Reloc::PIC_) {}
+        MCE(mce), MCPEs(0), MJTEs(0),
+        IsPIC(TM.getRelocationModel() == Reloc::PIC_), IsThumb(false) {}
 
     /// getBinaryCodeForInstr - This function, generated by the
     /// CodeEmitterGenerator using TableGen, produces the binary encoding for
@@ -139,7 +140,8 @@ namespace {
 
     void emitMiscInstruction(const MachineInstr &MI);
 
-    void emitNEONGetLaneInstruction(const MachineInstr &MI);
+    void emitNEONLaneInstruction(const MachineInstr &MI);
+    void emitNEONDupInstruction(const MachineInstr &MI);
     void emitNEON1RegModImmInstruction(const MachineInstr &MI);
     void emitNEON2RegInstruction(const MachineInstr &MI);
     void emitNEON3RegInstruction(const MachineInstr &MI);
@@ -199,6 +201,7 @@ bool ARMCodeEmitter::runOnMachineFunction(MachineFunction &MF) {
   MJTEs = 0;
   if (MF.getJumpTableInfo()) MJTEs = &MF.getJumpTableInfo()->getJumpTables();
   IsPIC = TM.getRelocationModel() == Reloc::PIC_;
+  IsThumb = MF.getInfo<ARMFunctionInfo>()->isThumbFunction();
   JTI->Initialize(MF, IsPIC);
   MMI = &getAnalysis<MachineModuleInfo>();
   MCE.setModuleInfo(MMI);
@@ -415,7 +418,11 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) {
     break;
   // NEON instructions.
   case ARMII::NGetLnFrm:
-    emitNEONGetLaneInstruction(MI);
+  case ARMII::NSetLnFrm:
+    emitNEONLaneInstruction(MI);
+    break;
+  case ARMII::NDupFrm:
+    emitNEONDupInstruction(MI);
     break;
   case ARMII::N1RegModImmFrm:
     emitNEON1RegModImmInstruction(MI);
@@ -647,6 +654,19 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) {
   switch (Opcode) {
   default:
     llvm_unreachable("ARMCodeEmitter::emitPseudoInstruction");
+  case ARM::BX:
+  case ARM::BMOVPCRX:
+  case ARM::BXr9:
+  case ARM::BMOVPCRXr9: {
+    // First emit mov lr, pc
+    unsigned Binary = 0x01a0e00f;
+    Binary |= II->getPredicate(&MI) << ARMII::CondShift;
+    emitWordLE(Binary);
+
+    // and then emit the branch.
+    emitMiscBranchInstruction(MI);
+    break;
+  }
   case TargetOpcode::INLINEASM: {
     // We allow inline assembler nodes with empty bodies - they can
     // implicitly define registers, which is ok for JIT.
@@ -655,7 +675,7 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) {
     }
     break;
   }
-  case TargetOpcode::DBG_LABEL:
+  case TargetOpcode::PROLOG_LABEL:
   case TargetOpcode::EH_LABEL:
     MCE.emitLabel(MI.getOperand(0).getMCSymbol());
     break;
@@ -1585,16 +1605,37 @@ static unsigned encodeNEONRm(const MachineInstr &MI, unsigned OpIdx) {
   return Binary;
 }
 
-void ARMCodeEmitter::emitNEONGetLaneInstruction(const MachineInstr &MI) {
+/// convertNEONDataProcToThumb - Convert the ARM mode encoding for a NEON
+/// data-processing instruction to the corresponding Thumb encoding.
+static unsigned convertNEONDataProcToThumb(unsigned Binary) {
+  assert((Binary & 0xfe000000) == 0xf2000000 &&
+         "not an ARM NEON data-processing instruction");
+  unsigned UBit = (Binary >> 24) & 1;
+  return 0xef000000 | (UBit << 28) | (Binary & 0xffffff);
+}
+
+void ARMCodeEmitter::emitNEONLaneInstruction(const MachineInstr &MI) {
   unsigned Binary = getBinaryCodeForInstr(MI);
 
+  unsigned RegTOpIdx, RegNOpIdx, LnOpIdx;
+  const TargetInstrDesc &TID = MI.getDesc();
+  if ((TID.TSFlags & ARMII::FormMask) == ARMII::NGetLnFrm) {
+    RegTOpIdx = 0;
+    RegNOpIdx = 1;
+    LnOpIdx = 2;
+  } else { // ARMII::NSetLnFrm
+    RegTOpIdx = 2;
+    RegNOpIdx = 0;
+    LnOpIdx = 3;
+  }
+
   // Set the conditional execution predicate
-  Binary |= II->getPredicate(&MI) << ARMII::CondShift;
+  Binary |= (IsThumb ? ARMCC::AL : II->getPredicate(&MI)) << ARMII::CondShift;
 
-  unsigned RegT = MI.getOperand(0).getReg();
+  unsigned RegT = MI.getOperand(RegTOpIdx).getReg();
   RegT = ARMRegisterInfo::getRegisterNumbering(RegT);
   Binary |= (RegT << ARMII::RegRdShift);
-  Binary |= encodeNEONRn(MI, 1);
+  Binary |= encodeNEONRn(MI, RegNOpIdx);
 
   unsigned LaneShift;
   if ((Binary & (1 << 22)) != 0)
@@ -1604,7 +1645,7 @@ void ARMCodeEmitter::emitNEONGetLaneInstruction(const MachineInstr &MI) {
   else
     LaneShift = 2; // 32-bit elements
 
-  unsigned Lane = MI.getOperand(2).getImm() << LaneShift;
+  unsigned Lane = MI.getOperand(LnOpIdx).getImm() << LaneShift;
   unsigned Opc1 = Lane >> 2;
   unsigned Opc2 = Lane & 3;
   assert((Opc1 & 3) == 0 && "out-of-range lane number operand");
@@ -1614,6 +1655,19 @@ void ARMCodeEmitter::emitNEONGetLaneInstruction(const MachineInstr &MI) {
   emitWordLE(Binary);
 }
 
+void ARMCodeEmitter::emitNEONDupInstruction(const MachineInstr &MI) {
+  unsigned Binary = getBinaryCodeForInstr(MI);
+
+  // Set the conditional execution predicate
+  Binary |= (IsThumb ? ARMCC::AL : II->getPredicate(&MI)) << ARMII::CondShift;
+
+  unsigned RegT = MI.getOperand(1).getReg();
+  RegT = ARMRegisterInfo::getRegisterNumbering(RegT);
+  Binary |= (RegT << ARMII::RegRdShift);
+  Binary |= encodeNEONRn(MI, 0);
+  emitWordLE(Binary);
+}
+
 void ARMCodeEmitter::emitNEON1RegModImmInstruction(const MachineInstr &MI) {
   unsigned Binary = getBinaryCodeForInstr(MI);
   // Destination register is encoded in Dd.
@@ -1621,15 +1675,13 @@ void ARMCodeEmitter::emitNEON1RegModImmInstruction(const MachineInstr &MI) {
   // Immediate fields: Op, Cmode, I, Imm3, Imm4
   unsigned Imm = MI.getOperand(1).getImm();
   unsigned Op = (Imm >> 12) & 1;
-  Binary |= (Op << 5);
   unsigned Cmode = (Imm >> 8) & 0xf;
-  Binary |= (Cmode << 8);
   unsigned I = (Imm >> 7) & 1;
-  Binary |= (I << 24);
   unsigned Imm3 = (Imm >> 4) & 0x7;
-  Binary |= (Imm3 << 16);
   unsigned Imm4 = Imm & 0xf;
-  Binary |= Imm4;
+  Binary |= (I << 24) | (Imm3 << 16) | (Cmode << 8) | (Op << 5) | Imm4;
+  if (IsThumb)
+    Binary = convertNEONDataProcToThumb(Binary);
   emitWordLE(Binary);
 }
 
@@ -1642,6 +1694,8 @@ void ARMCodeEmitter::emitNEON2RegInstruction(const MachineInstr &MI) {
   if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)
     ++OpIdx;
   Binary |= encodeNEONRm(MI, OpIdx);
+  if (IsThumb)
+    Binary = convertNEONDataProcToThumb(Binary);
   // FIXME: This does not handle VDUPfdf or VDUPfqf.
   emitWordLE(Binary);
 }
@@ -1658,6 +1712,8 @@ void ARMCodeEmitter::emitNEON3RegInstruction(const MachineInstr &MI) {
   if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)
     ++OpIdx;
   Binary |= encodeNEONRm(MI, OpIdx);
+  if (IsThumb)
+    Binary = convertNEONDataProcToThumb(Binary);
   // FIXME: This does not handle VMOVDneon or VMOVQ.
   emitWordLE(Binary);
 }