Add support for encoding 3-register NEON instructions, and fix
authorBob Wilson <bob.wilson@apple.com>
Fri, 25 Jun 2010 22:40:46 +0000 (22:40 +0000)
committerBob Wilson <bob.wilson@apple.com>
Fri, 25 Jun 2010 22:40:46 +0000 (22:40 +0000)
emitNEON2RegInstruction's handling of 2-address operands.

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

lib/Target/ARM/ARMCodeEmitter.cpp

index 0269afa3d4dad2dc1b9500c3347d9a178b0b137c..7f3c5d80f1e55b436907fa2ba912592c3b506843 100644 (file)
@@ -141,6 +141,7 @@ namespace {
 
     void emitNEON1RegModImmInstruction(const MachineInstr &MI);
     void emitNEON2RegInstruction(const MachineInstr &MI);
+    void emitNEON3RegInstruction(const MachineInstr &MI);
 
     /// getMachineOpValue - Return binary encoding of operand. If the machine
     /// operand requires relocation, record the relocation and return zero.
@@ -418,6 +419,9 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) {
   case ARMII::N2RegFrm:
     emitNEON2RegInstruction(MI);
     break;
+  case ARMII::N3RegFrm:
+    emitNEON3RegInstruction(MI);
+    break;
   }
   MCE.processDebugLoc(MI.getDebugLoc(), false);
 }
@@ -1559,6 +1563,15 @@ static unsigned encodeNEONRd(const MachineInstr &MI, unsigned OpIdx) {
   return Binary;
 }
 
+static unsigned encodeNEONRn(const MachineInstr &MI, unsigned OpIdx) {
+  unsigned RegN = MI.getOperand(OpIdx).getReg();
+  unsigned Binary = 0;
+  RegN = ARMRegisterInfo::getRegisterNumbering(RegN);
+  Binary |= (RegN & 0xf) << ARMII::RegRnShift;
+  Binary |= ((RegN >> 4) & 1) << ARMII::N_BitShift;
+  return Binary;
+}
+
 static unsigned encodeNEONRm(const MachineInstr &MI, unsigned OpIdx) {
   unsigned RegM = MI.getOperand(OpIdx).getReg();
   unsigned Binary = 0;
@@ -1588,12 +1601,32 @@ void ARMCodeEmitter::emitNEON1RegModImmInstruction(const MachineInstr &MI) {
 }
 
 void ARMCodeEmitter::emitNEON2RegInstruction(const MachineInstr &MI) {
+  const TargetInstrDesc &TID = MI.getDesc();
   unsigned Binary = getBinaryCodeForInstr(MI);
-  // Destination register is encoded in Dd.
-  Binary |= encodeNEONRd(MI, 0);
-  Binary |= encodeNEONRm(MI, 1);
+  // Destination register is encoded in Dd; source register in Dm.
+  unsigned OpIdx = 0;
+  Binary |= encodeNEONRd(MI, OpIdx++);
+  if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)
+    ++OpIdx;
+  Binary |= encodeNEONRm(MI, OpIdx);
   // FIXME: This does not handle VDUPfdf or VDUPfqf.
   emitWordLE(Binary);
 }
 
+void ARMCodeEmitter::emitNEON3RegInstruction(const MachineInstr &MI) {
+  const TargetInstrDesc &TID = MI.getDesc();
+  unsigned Binary = getBinaryCodeForInstr(MI);
+  // Destination register is encoded in Dd; source registers in Dn and Dm.
+  unsigned OpIdx = 0;
+  Binary |= encodeNEONRd(MI, OpIdx++);
+  if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)
+    ++OpIdx;
+  Binary |= encodeNEONRn(MI, OpIdx++);
+  if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)
+    ++OpIdx;
+  Binary |= encodeNEONRm(MI, OpIdx);
+  // FIXME: This does not handle VMOVDneon or VMOVQ.
+  emitWordLE(Binary);
+}
+
 #include "ARMGenCodeEmitter.inc"