diff options
Diffstat (limited to 'lib/Target')
-rw-r--r-- | lib/Target/ARM/ARMAddressingModes.h | 2 | ||||
-rw-r--r-- | lib/Target/ARM/ARMConstantIslandPass.cpp | 11 | ||||
-rw-r--r-- | lib/Target/ARM/ARMISelDAGToDAG.cpp | 159 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrFormats.td | 70 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrInfo.h | 12 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrInfo.td | 37 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrThumb.td | 28 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrThumb2.td | 44 | ||||
-rw-r--r-- | lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp | 167 | ||||
-rw-r--r-- | lib/Target/ARM/README.txt | 7 | ||||
-rw-r--r-- | lib/Target/ARM/ThumbRegisterInfo.cpp | 6 |
11 files changed, 387 insertions, 156 deletions
diff --git a/lib/Target/ARM/ARMAddressingModes.h b/lib/Target/ARM/ARMAddressingModes.h index 005eb7a10f..bf79152093 100644 --- a/lib/Target/ARM/ARMAddressingModes.h +++ b/lib/Target/ARM/ARMAddressingModes.h @@ -305,7 +305,7 @@ namespace ARM_AM { /// abcdefgh abcdefgh abcdefgh abcdefgh control = 3 /// Return -1 if none of the above apply. /// See ARM Reference Manual A6.3.2. - static inline int getT2SOImmValSplat (unsigned V) { + static inline int getT2SOImmValSplat(unsigned V) { unsigned u, Vs, Imm; // control = 0 if ((V & 0xffffff00) == 0) diff --git a/lib/Target/ARM/ARMConstantIslandPass.cpp b/lib/Target/ARM/ARMConstantIslandPass.cpp index db723fe832..d37e9f2cf0 100644 --- a/lib/Target/ARM/ARMConstantIslandPass.cpp +++ b/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -447,21 +447,24 @@ void ARMConstantIslands::InitialFunctionScan(MachineFunction &Fn, Bits = 8; Scale = 4; // +-(offset_8*4) break; - case ARMII::AddrModeT1: + case ARMII::AddrModeT1_1: Bits = 5; // +offset_5 break; - case ARMII::AddrModeT2: + case ARMII::AddrModeT1_2: Bits = 5; Scale = 2; // +(offset_5*2) break; - case ARMII::AddrModeT4: + case ARMII::AddrModeT1_4: Bits = 5; Scale = 4; // +(offset_5*4) break; - case ARMII::AddrModeTs: + case ARMII::AddrModeT1_s: Bits = 8; Scale = 4; // +(offset_8*4) break; + case ARMII::AddrModeT2_pc: + Bits = 12; // +-offset_12 + break; } // Remember that this is a user of a CP entry. diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index 200371bbaf..7035064c7f 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -64,6 +64,8 @@ public: SDNode *Select(SDValue Op); virtual void InstructionSelect(); + bool SelectShifterOperandReg(SDValue Op, SDValue N, SDValue &A, + SDValue &B, SDValue &C); bool SelectAddrMode2(SDValue Op, SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc); bool SelectAddrMode2Offset(SDValue Op, SDValue N, @@ -92,10 +94,15 @@ public: bool SelectThumbAddrModeSP(SDValue Op, SDValue N, SDValue &Base, SDValue &OffImm); - bool SelectShifterOperandReg(SDValue Op, SDValue N, SDValue &A, - SDValue &B, SDValue &C); bool SelectT2ShifterOperandReg(SDValue Op, SDValue N, SDValue &BaseReg, SDValue &Opc); + bool SelectT2AddrModeImm12(SDValue Op, SDValue N, SDValue &Base, + SDValue &OffImm); + bool SelectT2AddrModeImm8(SDValue Op, SDValue N, SDValue &Base, + SDValue &OffImm); + bool SelectT2AddrModeSoReg(SDValue Op, SDValue N, SDValue &Base, + SDValue &OffReg, SDValue &ShImm); + // Include the pieces autogenerated from the target description. #include "ARMGenDAGISel.inc" @@ -116,6 +123,30 @@ void ARMDAGToDAGISel::InstructionSelect() { CurDAG->RemoveDeadNodes(); } +bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue Op, + SDValue N, + SDValue &BaseReg, + SDValue &ShReg, + SDValue &Opc) { + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); + + // Don't match base register only case. That is matched to a separate + // lower complexity pattern with explicit register operand. + if (ShOpcVal == ARM_AM::no_shift) return false; + + BaseReg = N.getOperand(0); + unsigned ShImmVal = 0; + if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { + ShReg = CurDAG->getRegister(0, MVT::i32); + ShImmVal = RHS->getZExtValue() & 31; + } else { + ShReg = N.getOperand(1); + } + Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), + MVT::i32); + return true; +} + bool ARMDAGToDAGISel::SelectAddrMode2(SDValue Op, SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc) { @@ -519,30 +550,6 @@ bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue Op, SDValue N, return false; } -bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue Op, - SDValue N, - SDValue &BaseReg, - SDValue &ShReg, - SDValue &Opc) { - ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); - - // Don't match base register only case. That is matched to a separate - // lower complexity pattern with explicit register operand. - if (ShOpcVal == ARM_AM::no_shift) return false; - - BaseReg = N.getOperand(0); - unsigned ShImmVal = 0; - if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { - ShReg = CurDAG->getRegister(0, MVT::i32); - ShImmVal = RHS->getZExtValue() & 31; - } else { - ShReg = N.getOperand(1); - } - Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), - MVT::i32); - return true; -} - bool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue Op, SDValue N, SDValue &BaseReg, SDValue &Opc) { @@ -563,6 +570,106 @@ bool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue Op, SDValue N, return false; } +bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue Op, SDValue N, + SDValue &Base, SDValue &OffImm) { + // Match simple R + imm12 operands. + if (N.getOpcode() != ISD::ADD) + return false; + + if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits. + Base = N.getOperand(0); + OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); + return true; + } + } + + return false; +} + +bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue Op, SDValue N, + SDValue &Base, SDValue &OffImm) { + if (N.getOpcode() == ISD::ADD) { + if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if (RHSC < 0 && RHSC > -0x100) { // 8 bits. + Base = N.getOperand(0); + OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); + return true; + } + } + } else if (N.getOpcode() == ISD::SUB) { + if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if (RHSC >= 0 && RHSC < 0x100) { // 8 bits. + Base = N.getOperand(0); + OffImm = CurDAG->getTargetConstant(-RHSC, MVT::i32); + return true; + } + } + } + + return false; +} + +bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue Op, SDValue N, + SDValue &Base, + SDValue &OffReg, SDValue &ShImm) { + // Base only. + if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) { + Base = N; + if (N.getOpcode() == ISD::FrameIndex) { + int FI = cast<FrameIndexSDNode>(N)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } else if (N.getOpcode() == ARMISD::Wrapper) { + Base = N.getOperand(0); + if (Base.getOpcode() == ISD::TargetConstantPool) + return false; // We want to select t2LDRpci instead. + } + OffReg = CurDAG->getRegister(0, MVT::i32); + ShImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + + // Look for (R + R) or (R + (R << [1,2,3])). + unsigned ShAmt = 0; + Base = N.getOperand(0); + OffReg = N.getOperand(1); + + // Swap if it is ((R << c) + R). + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg); + if (ShOpcVal != ARM_AM::lsl) { + ShOpcVal = ARM_AM::getShiftOpcForNode(Base); + if (ShOpcVal == ARM_AM::lsl) + std::swap(Base, OffReg); + } + + if (ShOpcVal == ARM_AM::lsl) { + // Check to see if the RHS of the shift is a constant, if not, we can't fold + // it. + if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) { + ShAmt = Sh->getZExtValue(); + if (ShAmt >= 4) { + ShAmt = 0; + ShOpcVal = ARM_AM::no_shift; + } else + OffReg = OffReg.getOperand(0); + } else { + ShOpcVal = ARM_AM::no_shift; + } + } else if (SelectT2AddrModeImm12(Op, N, Base, ShImm) || + SelectT2AddrModeImm8 (Op, N, Base, ShImm)) + // Don't match if it's possible to match to one of the r +/- imm cases. + return false; + + ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32); + + return true; +} + +//===--------------------------------------------------------------------===// + /// getAL - Returns a ARMCC::AL immediate node. static inline SDValue getAL(SelectionDAG *CurDAG) { return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32); diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index d7371b0254..a98bf1e856 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -59,6 +59,47 @@ def NEONDupFrm : Format<27>; class UnaryDP { bit isUnaryDataProc = 1; } //===----------------------------------------------------------------------===// +// ARM Instruction flags. These need to match ARMInstrInfo.h. +// + +// Addressing mode. +class AddrMode<bits<4> val> { + bits<4> Value = val; +} +def AddrModeNone : AddrMode<0>; +def AddrMode1 : AddrMode<1>; +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>; + +// Instruction size. +class SizeFlagVal<bits<3> val> { + bits<3> Value = val; +} +def SizeInvalid : SizeFlagVal<0>; // Unset. +def SizeSpecial : SizeFlagVal<1>; // Pseudo or special. +def Size8Bytes : SizeFlagVal<2>; +def Size4Bytes : SizeFlagVal<3>; +def Size2Bytes : SizeFlagVal<4>; + +// Load / store index mode. +class IndexMode<bits<2> val> { + bits<2> Value = val; +} +def IndexModeNone : IndexMode<0>; +def IndexModePre : IndexMode<1>; +def IndexModePost : IndexMode<2>; + +//===----------------------------------------------------------------------===// // ARM Instruction templates. // @@ -706,7 +747,6 @@ class ARMV6Pat<dag pattern, dag result> : Pat<pattern, result> { // Thumb Instruction Format Definitions. // - // TI - Thumb instruction. class ThumbI<dag outs, dag ins, AddrMode am, SizeFlagVal sz, @@ -721,18 +761,6 @@ class ThumbI<dag outs, dag ins, AddrMode am, SizeFlagVal sz, class TI<dag outs, dag ins, string asm, list<dag> pattern> : ThumbI<outs, ins, AddrModeNone, Size2Bytes, asm, "", pattern>; -class TI1<dag outs, dag ins, string asm, list<dag> pattern> - : ThumbI<outs, ins, AddrModeT1, Size2Bytes, asm, "", pattern>; -class TI2<dag outs, dag ins, string asm, list<dag> pattern> - : ThumbI<outs, ins, AddrModeT2, Size2Bytes, asm, "", pattern>; -class TI4<dag outs, dag ins, string asm, list<dag> pattern> - : ThumbI<outs, ins, AddrModeT4, Size2Bytes, asm, "", pattern>; -class TIs<dag outs, dag ins, string asm, list<dag> pattern> - : ThumbI<outs, ins, AddrModeTs, Size2Bytes, asm, "", pattern>; - -// Two-address instructions -class TIt<dag outs, dag ins, string asm, list<dag> pattern> - : ThumbI<outs, ins, AddrModeNone, Size2Bytes, asm, "$lhs = $dst", pattern>; // BL, BLX(1) are translated by assembler into two instructions class TIx2<dag outs, dag ins, string asm, list<dag> pattern> @@ -764,6 +792,14 @@ class Thumb1I<dag outs, dag ins, AddrMode am, SizeFlagVal sz, class T1I<dag outs, dag ins, string asm, list<dag> pattern> : Thumb1I<outs, ins, AddrModeNone, Size2Bytes, asm, "", pattern>; +class T1I1<dag outs, dag ins, string asm, list<dag> pattern> + : Thumb1I<outs, ins, AddrModeT1_1, Size2Bytes, asm, "", pattern>; +class T1I2<dag outs, dag ins, string asm, list<dag> pattern> + : Thumb1I<outs, ins, AddrModeT1_2, Size2Bytes, asm, "", pattern>; +class T1I4<dag outs, dag ins, string asm, list<dag> pattern> + : Thumb1I<outs, ins, AddrModeT1_4, Size2Bytes, asm, "", pattern>; +class T1Is<dag outs, dag ins, string asm, list<dag> pattern> + : Thumb1I<outs, ins, AddrModeT1_s, Size2Bytes, asm, "", pattern>; // Two-address instructions class T1It<dag outs, dag ins, string asm, list<dag> pattern> @@ -812,6 +848,14 @@ class Thumb2XI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, class T2I<dag oops, dag iops, string opc, string asm, list<dag> pattern> : Thumb2I<oops, iops, AddrModeNone, Size4Bytes, opc, asm, "", pattern>; +class T2Ii12<dag oops, dag iops, string opc, string asm, list<dag> pattern> + : Thumb2I<oops, iops, AddrModeT2_i12, Size4Bytes, opc, asm, "", pattern>; +class T2Ii8<dag oops, dag iops, string opc, string asm, list<dag> pattern> + : Thumb2I<oops, iops, AddrModeT2_i8, Size4Bytes, opc, asm, "", pattern>; +class T2Iso<dag oops, dag iops, string opc, string asm, list<dag> pattern> + : Thumb2I<oops, iops, AddrModeT2_so, Size4Bytes, opc, asm, "", pattern>; +class T2Ipc<dag oops, dag iops, string opc, string asm, list<dag> pattern> + : Thumb2I<oops, iops, AddrModeT2_pc, Size4Bytes, opc, asm, "", pattern>; class T2sI<dag oops, dag iops, string opc, string asm, list<dag> pattern> : Thumb2sI<oops, iops, AddrModeNone, Size4Bytes, opc, asm, "", pattern>; diff --git a/lib/Target/ARM/ARMInstrInfo.h b/lib/Target/ARM/ARMInstrInfo.h index 7e3aa6c7a3..ac1eec0921 100644 --- a/lib/Target/ARM/ARMInstrInfo.h +++ b/lib/Target/ARM/ARMInstrInfo.h @@ -39,10 +39,14 @@ namespace ARMII { AddrMode3 = 3, AddrMode4 = 4, AddrMode5 = 5, - AddrModeT1 = 6, - AddrModeT2 = 7, - AddrModeT4 = 8, - AddrModeTs = 9, // i8 * 4 for pc and sp relative data + 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 // 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 cb7b7b98c7..611cb60a9d 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -309,43 +309,6 @@ def cc_out : OptionalDefOperand<OtherVT, (ops CCR), (ops (i32 zero_reg))> { } //===----------------------------------------------------------------------===// -// ARM Instruction flags. These need to match ARMInstrInfo.h. -// - -// Addressing mode. -class AddrMode<bits<4> val> { - bits<4> Value = val; -} -def AddrModeNone : AddrMode<0>; -def AddrMode1 : AddrMode<1>; -def AddrMode2 : AddrMode<2>; -def AddrMode3 : AddrMode<3>; -def AddrMode4 : AddrMode<4>; -def AddrMode5 : AddrMode<5>; -def AddrModeT1 : AddrMode<6>; -def AddrModeT2 : AddrMode<7>; -def AddrModeT4 : AddrMode<8>; -def AddrModeTs : AddrMode<9>; - -// Instruction size. -class SizeFlagVal<bits<3> val> { - bits<3> Value = val; -} -def SizeInvalid : SizeFlagVal<0>; // Unset. -def SizeSpecial : SizeFlagVal<1>; // Pseudo or special. -def Size8Bytes : SizeFlagVal<2>; -def Size4Bytes : SizeFlagVal<3>; -def Size2Bytes : SizeFlagVal<4>; - -// Load / store index mode. -class IndexMode<bits<2> val> { - bits<2> Value = val; -} -def IndexModeNone : IndexMode<0>; -def IndexModePre : IndexMode<1>; -def IndexModePost : IndexMode<2>; - -//===----------------------------------------------------------------------===// include "ARMInstrFormats.td" diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 7927ca53b8..dce0c1d573 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -211,68 +211,68 @@ let isBranch = 1, isTerminator = 1 in // let canFoldAsLoad = 1 in -def tLDR : TI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), +def tLDR : T1I4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), "ldr $dst, $addr", [(set tGPR:$dst, (load t_addrmode_s4:$addr))]>; -def tLDRB : TI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), +def tLDRB : T1I1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), "ldrb $dst, $addr", [(set tGPR:$dst, (zextloadi8 t_addrmode_s1:$addr))]>; -def tLDRH : TI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), +def tLDRH : T1I2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), "ldrh $dst, $addr", [(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>; -def tLDRSB : TI1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), +def tLDRSB : T1I1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), "ldrsb $dst, $addr", [(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>; -def tLDRSH : TI2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), +def tLDRSH : T1I2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), "ldrsh $dst, $addr", [(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>; let canFoldAsLoad = 1 in -def tLDRspi : TIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), +def tLDRspi : T1Is<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), "ldr $dst, $addr", [(set tGPR:$dst, (load t_addrmode_sp:$addr))]>; // Special instruction for restore. It cannot clobber condition register // when it's expanded by eliminateCallFramePseudoInstr(). let canFoldAsLoad = 1, mayLoad = 1 in -def tRestore : TIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), +def tRestore : T1Is<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), "ldr $dst, $addr", []>; // Load tconstpool let canFoldAsLoad = 1 in -def tLDRpci : TIs<(outs tGPR:$dst), (ins i32imm:$addr), +def tLDRpci : T1Is<(outs tGPR:$dst), (ins i32imm:$addr), "ldr $dst, $addr", [(set tGPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>; // Special LDR for loads from non-pc-relative constpools. let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1 in -def tLDRcp : TIs<(outs tGPR:$dst), (ins i32imm:$addr), +def tLDRcp : T1Is<(outs tGPR:$dst), (ins i32imm:$addr), "ldr $dst, $addr", []>; -def tSTR : TI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), +def tSTR : T1I4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), "str $src, $addr", [(store tGPR:$src, t_addrmode_s4:$addr)]>; -def tSTRB : TI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), +def tSTRB : T1I1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), "strb $src, $addr", [(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>; -def tSTRH : TI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), +def tSTRH : T1I2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), "strh $src, $addr", [(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>; -def tSTRspi : TIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), +def tSTRspi : T1Is<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), "str $src, $addr", [(store tGPR:$src, t_addrmode_sp:$addr)]>; let mayStore = 1 in { // Special instruction for spill. It cannot clobber condition register // when it's expanded by eliminateCallFramePseudoInstr(). -def tSpill : TIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), +def tSpill : T1Is<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), "str $src, $addr", []>; } diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index bfdf7192f4..538fcc22a1 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -127,6 +127,30 @@ def t2_lo16AllZero : PatLeaf<(i32 imm), [{ }], t2_hi16>; +// Define Thumb2 specific addressing modes. + +// t2addrmode_imm12 := reg + imm12 +def t2addrmode_imm12 : Operand<i32>, + ComplexPattern<i32, 2, "SelectT2AddrModeImm12", []> { + let PrintMethod = "printT2AddrModeImm12Operand"; + let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); +} + +// t2addrmode_imm8 := reg - imm8 +def t2addrmode_imm8 : Operand<i32>, + ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> { + let PrintMethod = "printT2AddrModeImm8Operand"; + let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); +} + +// t2addrmode_so_reg := reg + reg << imm2 +def t2addrmode_so_reg : Operand<i32>, + ComplexPattern<i32, 3, "SelectT2AddrModeSoReg", []> { + let PrintMethod = "printT2AddrModeSoRegOperand"; + let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm); +} + + //===----------------------------------------------------------------------===// // Multiclass helpers... // @@ -409,6 +433,26 @@ def t2ADDrSPs : T2XI<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs), // Load / store Instructions. // +// Load +let canFoldAsLoad = 1 in { +def t2LDRi12 : T2Ii12<(outs GPR:$dst), (ins t2addrmode_imm12:$addr), + "ldr", " $dst, $addr", + [(set GPR:$dst, (load t2addrmode_imm12:$addr))]>; + +def t2LDRi8 : T2Ii8<(outs GPR:$dst), (ins t2addrmode_imm8:$addr), + "ldr", " $dst, $addr", + [(set GPR:$dst, (load t2addrmode_imm8:$addr))]>; + +def t2LDRs : T2Iso<(outs GPR:$dst), (ins t2addrmode_so_reg:$addr), + "ldr", " $dst, $addr", + [(set GPR:$dst, (load t2addrmode_so_reg:$addr))]>; + +// Load tconstpool +def t2LDRpci : T2Ipc<(outs GPR:$dst), (ins i32imm:$addr), + "ldr", " $dst, $addr", + [(set GPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>; +} // canFoldAsLoad + //===----------------------------------------------------------------------===// // Move Instructions. // diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp index 400f628aa5..45c6727c72 100644 --- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp @@ -93,45 +93,48 @@ namespace { return "ARM Assembly Printer"; } - void printOperand(const MachineInstr *MI, int opNum, + void printOperand(const MachineInstr *MI, int OpNum, const char *Modifier = 0); - void printSOImmOperand(const MachineInstr *MI, int opNum); - void printSOImm2PartOperand(const MachineInstr *MI, int opNum); - void printSORegOperand(const MachineInstr *MI, int opNum); - void printAddrMode2Operand(const MachineInstr *MI, int OpNo); - void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNo); - void printAddrMode3Operand(const MachineInstr *MI, int OpNo); - void printAddrMode3OffsetOperand(const MachineInstr *MI, int OpNo); - void printAddrMode4Operand(const MachineInstr *MI, int OpNo, + void printSOImmOperand(const MachineInstr *MI, int OpNum); + void printSOImm2PartOperand(const MachineInstr *MI, int OpNum); + void printSORegOperand(const MachineInstr *MI, int OpNum); + void printAddrMode2Operand(const MachineInstr *MI, int OpNum); + void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNum); + void printAddrMode3Operand(const MachineInstr *MI, int OpNum); + void printAddrMode3OffsetOperand(const MachineInstr *MI, int OpNum); + void printAddrMode4Operand(const MachineInstr *MI, int OpNum, const char *Modifier = 0); - void printAddrMode5Operand(const MachineInstr *MI, int OpNo, + void printAddrMode5Operand(const MachineInstr *MI, int OpNum, const char *Modifier = 0); - void printAddrModePCOperand(const MachineInstr *MI, int OpNo, + void printAddrModePCOperand(const MachineInstr *MI, int OpNum, const char *Modifier = 0); - void printBitfieldInvMaskImmOperand (const MachineInstr *MI, int OpNo); + void printBitfieldInvMaskImmOperand (const MachineInstr *MI, int OpNum); - void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNo); - void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNo, + void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNum); + void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNum, unsigned Scale); - void printThumbAddrModeS1Operand(const MachineInstr *MI, int OpNo); - void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNo); - void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNo); - void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNo); + void printThumbAddrModeS1Operand(const MachineInstr *MI, int OpNum); + void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNum); + void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNum); + void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNum); - void printT2SOImmOperand(const MachineInstr *MI, int opNum); + void printT2SOImmOperand(const MachineInstr *MI, int OpNum); void printT2SOOperand(const MachineInstr *MI, int OpNum); - - void printPredicateOperand(const MachineInstr *MI, int opNum); - void printSBitModifierOperand(const MachineInstr *MI, int opNum); - void printPCLabel(const MachineInstr *MI, int opNum); - void printRegisterList(const MachineInstr *MI, int opNum); - void printCPInstOperand(const MachineInstr *MI, int opNum, + void printT2AddrModeImm12Operand(const MachineInstr *MI, int OpNum); + void printT2AddrModeImm8Operand(const MachineInstr *MI, int OpNum); + void printT2AddrModeSoRegOperand(const MachineInstr *MI, int OpNum); + + void printPredicateOperand(const MachineInstr *MI, int OpNum); + void printSBitModifierOperand(const MachineInstr *MI, int OpNum); + void printPCLabel(const MachineInstr *MI, int OpNum); + void printRegisterList(const MachineInstr *MI, int OpNum); + void printCPInstOperand(const MachineInstr *MI, int OpNum, const char *Modifier); - void printJTBlockOperand(const MachineInstr *MI, int opNum); + void printJTBlockOperand(const MachineInstr *MI, int OpNum); - virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, unsigned AsmVariant, const char *ExtraCode); - virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, unsigned AsmVariant, const char *ExtraCode); @@ -282,9 +285,9 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { return false; } -void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum, +void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, const char *Modifier) { - const MachineOperand &MO = MI->getOperand(opNum); + const MachineOperand &MO = MI->getOperand(OpNum); switch (MO.getType()) { case MachineOperand::MO_Register: { unsigned Reg = MO.getReg(); @@ -606,6 +609,8 @@ ARMAsmPrinter::printBitfieldInvMaskImmOperand(const MachineInstr *MI, int Op) { O << "#" << lsb << ", #" << width; } +//===--------------------------------------------------------------------===// + void ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr *MI, int Op) { const MachineOperand &MO1 = MI->getOperand(Op); @@ -659,6 +664,8 @@ void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) { O << "]"; } +//===--------------------------------------------------------------------===// + /// printT2SOImmOperand - T2SOImm is: /// 1. a 4-bit splat control value and 8 bit immediate value /// 2. a 5-bit rotate amount and a non-zero 8-bit immediate value @@ -694,47 +701,99 @@ void ARMAsmPrinter::printT2SOOperand(const MachineInstr *MI, int OpNum) { O << "#" << ARM_AM::getSORegOffset(MO2.getImm()); } +void ARMAsmPrinter::printT2AddrModeImm12Operand(const MachineInstr *MI, + int OpNum) { + const MachineOperand &MO1 = MI->getOperand(OpNum); + const MachineOperand &MO2 = MI->getOperand(OpNum+1); + + O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + + unsigned OffImm = MO2.getImm(); + if (OffImm) // Don't print +0. + O << ", #+" << OffImm; + O << "]"; +} + +void ARMAsmPrinter::printT2AddrModeImm8Operand(const MachineInstr *MI, + int OpNum) { + const MachineOperand &MO1 = MI->getOperand(OpNum); + const MachineOperand &MO2 = MI->getOperand(OpNum+1); + + O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + + int32_t OffImm = (int32_t)MO2.getImm(); + // Don't print +0. + if (OffImm < 0) + O << ", #-" << -OffImm; + else if (OffImm > 0) + O << ", #+" << OffImm; + O << "]"; +} + +void ARMAsmPrinter::printT2AddrModeSoRegOperand(const MachineInstr *MI, + int OpNum) { + const MachineOperand &MO1 = MI->getOperand(OpNum); + const MachineOperand &MO2 = MI->getOperand(OpNum+1); + const MachineOperand &MO3 = MI->getOperand(OpNum+2); + + O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + + if (MO2.getReg()) { + O << ", +" + << TM.getRegisterInfo()->get(MO2.getReg()).AsmName; -void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int opNum) { - ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(opNum).getImm(); + unsigned ShAmt = MO3.getImm(); + if (ShAmt) { + assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!"); + O << ", lsl #" << ShAmt; + } + } + O << "]"; +} + + +//===--------------------------------------------------------------------===// + +void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int OpNum) { + ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); if (CC != ARMCC::AL) O << ARMCondCodeToString(CC); } -void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int opNum){ - unsigned Reg = MI->getOperand(opNum).getReg(); +void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int OpNum){ + unsigned Reg = MI->getOperand(OpNum).getReg(); if (Reg) { assert(Reg == ARM::CPSR && "Expect ARM CPSR register!"); O << 's'; } } -void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int opNum) { - int Id = (int)MI->getOperand(opNum).getImm(); +void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int OpNum) { + int Id = (int)MI->getOperand(OpNum).getImm(); O << TAI->getPrivateGlobalPrefix() << "PC" << Id; } -void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int opNum) { +void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int OpNum) { O << "{"; - for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) { + for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) { printOperand(MI, i); if (i != e-1) O << ", "; } O << "}"; } -void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNo, +void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNum, const char *Modifier) { assert(Modifier && "This operand only works with a modifier!"); // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the // data itself. if (!strcmp(Modifier, "label")) { - unsigned ID = MI->getOperand(OpNo).getImm(); + unsigned ID = MI->getOperand(OpNum).getImm(); O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' << ID << ":\n"; } else { assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE"); - unsigned CPI = MI->getOperand(OpNo).getIndex(); + unsigned CPI = MI->getOperand(OpNum).getIndex(); const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPI]; @@ -746,9 +805,9 @@ void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNo, } } -void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNo) { - const MachineOperand &MO1 = MI->getOperand(OpNo); - const MachineOperand &MO2 = MI->getOperand(OpNo+1); // Unique Id +void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNum) { + const MachineOperand &MO1 = MI->getOperand(OpNum); + const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id unsigned JTI = MO1.getIndex(); O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' << JTI << '_' << MO2.getImm() << ":\n"; @@ -787,7 +846,7 @@ void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNo) { } -bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, +bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, unsigned AsmVari |