diff --git a/lib/Target/ARM/ARMAddressingModes.h b/lib/Target/ARM/ARMAddressingModes.h index 7dc2dca58ce..15c9ec1fc23 100644 --- a/lib/Target/ARM/ARMAddressingModes.h +++ b/lib/Target/ARM/ARMAddressingModes.h @@ -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 diff --git a/lib/Target/ARM/ARMConstantIslandPass.cpp b/lib/Target/ARM/ARMConstantIslandPass.cpp index 19c311c4f28..9fedaa46543 100644 --- a/lib/Target/ARM/ARMConstantIslandPass.cpp +++ b/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -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; diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index 258adb583ac..15136909bf9 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -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()) { diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index a9c66a5506d..072e9a260e7 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -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 val> { diff --git a/lib/Target/ARM/ARMInstrInfo.h b/lib/Target/ARM/ARMInstrInfo.h index cdc420820d5..f30104f27c9 100644 --- a/lib/Target/ARM/ARMInstrInfo.h +++ b/lib/Target/ARM/ARMInstrInfo.h @@ -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, diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index b3f7a7d0e2e..380012108ea 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -287,6 +287,14 @@ def addrmode5 : Operand, let MIOperandInfo = (ops GPR, i32imm); } +// addrmode6 := reg with optional writeback +// +def addrmode6 : Operand, + ComplexPattern { + let PrintMethod = "printAddrMode6Operand"; + let MIOperandInfo = (ops GPR:$addr, GPR:$upd, i32imm); +} + // addrmodepc := pc + reg // def addrmodepc : Operand, diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp index 773f279d864..20a1a93c05f 100644 --- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp @@ -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) {