Add a new addressing mode for NEON load/store instructions.
authorBob Wilson <bob.wilson@apple.com>
Wed, 1 Jul 2009 23:16:05 +0000 (23:16 +0000)
committerBob Wilson <bob.wilson@apple.com>
Wed, 1 Jul 2009 23:16:05 +0000 (23:16 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74658 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMAddressingModes.h
lib/Target/ARM/ARMConstantIslandPass.cpp
lib/Target/ARM/ARMISelDAGToDAG.cpp
lib/Target/ARM/ARMInstrFormats.td
lib/Target/ARM/ARMInstrInfo.h
lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp

index 7dc2dca58ce957d1620ce36025de0d6f8cb81c68..15c9ec1fc23cf44338c1219a9ae65f89c4629df7 100644 (file)
@@ -496,7 +496,29 @@ namespace ARM_AM {
   static inline bool getAM5WBFlag(unsigned AM5Opc) {
     return ((AM5Opc >> 8) & 1);
   }
-  
+
+  //===--------------------------------------------------------------------===//
+  // Addressing Mode #6
+  //===--------------------------------------------------------------------===//
+  //
+  // This is used for NEON load / store instructions.
+  //
+  // addrmode6 := reg with optional writeback
+  //
+  // This is stored in three operands [regaddr, regupdate, opc].  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.
+
+  static inline unsigned getAM6Opc(bool WB = false) {
+    return (int)WB;
+  }
+
+  static inline bool getAM6WBFlag(unsigned Mode) {
+    return Mode & 1;
+  }
+
 } // end namespace ARM_AM
 } // end namespace llvm
 
index 19c311c4f280cd5c9fc93bcf2a3a485d101568c0..9fedaa465434a80bb50574a784bb4b5da7c95159 100644 (file)
@@ -462,6 +462,7 @@ void ARMConstantIslands::InitialFunctionScan(MachineFunction &Fn,
             Bits = 8;
             Scale = 4;  // +-(offset_8*4)
             break;
+            // addrmode6 has no immediate offset.
           case ARMII::AddrModeT1_1:
             Bits = 5;  // +offset_5
             break;
index 258adb583ac7f6378efdb495d9008d51db77f927..15136909bf9c0660c8ee597b7a723af7c528ffa6 100644 (file)
@@ -76,9 +76,11 @@ public:
                              SDValue &Offset, SDValue &Opc);
   bool SelectAddrMode5(SDValue Op, SDValue N, SDValue &Base,
                        SDValue &Offset);
+  bool SelectAddrMode6(SDValue Op, SDValue N, SDValue &Addr, SDValue &Update,
+                       SDValue &Opc);
 
   bool SelectAddrModePC(SDValue Op, SDValue N, SDValue &Offset,
-                         SDValue &Label);
+                        SDValue &Label);
 
   bool SelectThumbAddrModeRR(SDValue Op, SDValue N, SDValue &Base,
                              SDValue &Offset);
@@ -105,7 +107,6 @@ public:
   bool SelectT2AddrModeSoReg(SDValue Op, SDValue N, SDValue &Base,
                              SDValue &OffReg, SDValue &ShImm);
 
-  
   // Include the pieces autogenerated from the target description.
 #include "ARMGenDAGISel.inc"
 
@@ -415,6 +416,16 @@ bool ARMDAGToDAGISel::SelectAddrMode5(SDValue Op, SDValue N,
   return true;
 }
 
+bool ARMDAGToDAGISel::SelectAddrMode6(SDValue Op, SDValue N,
+                                      SDValue &Addr, SDValue &Update,
+                                      SDValue &Opc) {
+  Addr = N;
+  // The optional writeback is handled in ARMLoadStoreOpt.
+  Update = CurDAG->getRegister(0, MVT::i32);
+  Opc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(false), MVT::i32);
+  return true;
+}
+
 bool ARMDAGToDAGISel::SelectAddrModePC(SDValue Op, SDValue N,
                                         SDValue &Offset, SDValue &Label) {
   if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
index a9c66a5506d63046323134562cdcae9e5e2cd84b..072e9a260e73b9a14a49506e9de677ad688de4fc 100644 (file)
@@ -72,15 +72,16 @@ def AddrMode2     : AddrMode<2>;
 def AddrMode3     : AddrMode<3>;
 def AddrMode4     : AddrMode<4>;
 def AddrMode5     : AddrMode<5>;
-def AddrModeT1_1  : AddrMode<6>;
-def AddrModeT1_2  : AddrMode<7>;
-def AddrModeT1_4  : AddrMode<8>;
-def AddrModeT1_s  : AddrMode<9>;
-def AddrModeT2_i12: AddrMode<10>;
-def AddrModeT2_i8 : AddrMode<11>;
-def AddrModeT2_so : AddrMode<12>;
-def AddrModeT2_pc : AddrMode<13>;
-def AddrModeT2_i8s4 : AddrMode<14>;
+def AddrMode6     : AddrMode<6>;
+def AddrModeT1_1  : AddrMode<7>;
+def AddrModeT1_2  : AddrMode<8>;
+def AddrModeT1_4  : AddrMode<9>;
+def AddrModeT1_s  : AddrMode<10>;
+def AddrModeT2_i12: AddrMode<12>;
+def AddrModeT2_i8 : AddrMode<12>;
+def AddrModeT2_so : AddrMode<13>;
+def AddrModeT2_pc : AddrMode<14>;
+def AddrModeT2_i8s4 : AddrMode<15>;
 
 // Instruction size.
 class SizeFlagVal<bits<3> val> {
index cdc420820d5753985094820504bca6af9a279785..f30104f27c9918b14be6a8aa9eef036f72b9b7a1 100644 (file)
@@ -39,15 +39,16 @@ namespace ARMII {
     AddrMode3       = 3,
     AddrMode4       = 4,
     AddrMode5       = 5,
-    AddrModeT1_1    = 6,
-    AddrModeT1_2    = 7,
-    AddrModeT1_4    = 8,
-    AddrModeT1_s    = 9,  // i8 * 4 for pc and sp relative data
-    AddrModeT2_i12  = 10,
-    AddrModeT2_i8   = 11,
-    AddrModeT2_so   = 12,
-    AddrModeT2_pc   = 13, // +/- i12 for pc relative data
-    AddrModeT2_i8s4 = 14, // i8 * 4
+    AddrMode6       = 6,
+    AddrModeT1_1    = 7,
+    AddrModeT1_2    = 8,
+    AddrModeT1_4    = 9,
+    AddrModeT1_s    = 10, // i8 * 4 for pc and sp relative data
+    AddrModeT2_i12  = 11,
+    AddrModeT2_i8   = 12,
+    AddrModeT2_so   = 13,
+    AddrModeT2_pc   = 14, // +/- i12 for pc relative data
+    AddrModeT2_i8s4 = 15, // i8 * 4
 
     // Size* - Flags to keep track of the size of an instruction.
     SizeShift     = 4,
index b3f7a7d0e2eb077fd652f3213878c09a1ddcddbe..380012108eadd13ccd73cfa2f98d149624d2db67 100644 (file)
@@ -287,6 +287,14 @@ def addrmode5 : Operand<i32>,
   let MIOperandInfo = (ops GPR, i32imm);
 }
 
+// addrmode6 := reg with optional writeback
+//
+def addrmode6 : Operand<i32>,
+                ComplexPattern<i32, 3, "SelectAddrMode6", []> {
+  let PrintMethod = "printAddrMode6Operand";
+  let MIOperandInfo = (ops GPR:$addr, GPR:$upd, i32imm);
+}
+
 // addrmodepc := pc + reg
 //
 def addrmodepc : Operand<i32>,
index 773f279d864215f9637c154571068e5209bbc948..20a1a93c05f04db213cb2022755fe25add19ba8c 100644 (file)
@@ -105,6 +105,7 @@ namespace {
                                const char *Modifier = 0);
     void printAddrMode5Operand(const MachineInstr *MI, int OpNum,
                                const char *Modifier = 0);
+    void printAddrMode6Operand(const MachineInstr *MI, int OpNum);
     void printAddrModePCOperand(const MachineInstr *MI, int OpNum,
                                 const char *Modifier = 0);
     void printBitfieldInvMaskImmOperand (const MachineInstr *MI, int OpNum);
@@ -587,6 +588,22 @@ void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op,
   O << "]";
 }
 
+void ARMAsmPrinter::printAddrMode6Operand(const MachineInstr *MI, int Op) {
+  const MachineOperand &MO1 = MI->getOperand(Op);
+  const MachineOperand &MO2 = MI->getOperand(Op+1);
+  const MachineOperand &MO3 = MI->getOperand(Op+2);
+
+  // FIXME: No support yet for specifying alignment.
+  O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName << "]";
+
+  if (ARM_AM::getAM6WBFlag(MO3.getImm())) {
+    if (MO2.getReg() == 0)
+      O << "!";
+    else
+      O << ", " << TM.getRegisterInfo()->get(MO2.getReg()).AsmName;
+  }
+}
+
 void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op,
                                            const char *Modifier) {
   if (Modifier && strcmp(Modifier, "label") == 0) {