diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index b2111674dd4..0ba7b40177e 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -1129,13 +1129,12 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { } { MCInst TmpInst; - TmpInst.setOpcode(ARM::tSTR); + TmpInst.setOpcode(ARM::tSTRi); TmpInst.addOperand(MCOperand::CreateReg(ValReg)); TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); // The offset immediate is #4. The operand value is scaled by 4 for the // tSTR instruction. TmpInst.addOperand(MCOperand::CreateImm(1)); - TmpInst.addOperand(MCOperand::CreateReg(0)); // Predicate. TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); TmpInst.addOperand(MCOperand::CreateReg(0)); @@ -1312,13 +1311,12 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { unsigned ScratchReg = MI->getOperand(1).getReg(); { MCInst TmpInst; - TmpInst.setOpcode(ARM::tLDR); + TmpInst.setOpcode(ARM::tLDRi); TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); // The offset immediate is #8. The operand value is scaled by 4 for the - // tSTR instruction. + // tLDR instruction. TmpInst.addOperand(MCOperand::CreateImm(2)); - TmpInst.addOperand(MCOperand::CreateReg(0)); // Predicate. TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); TmpInst.addOperand(MCOperand::CreateReg(0)); @@ -1336,11 +1334,10 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { } { MCInst TmpInst; - TmpInst.setOpcode(ARM::tLDR); + TmpInst.setOpcode(ARM::tLDRi); TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); TmpInst.addOperand(MCOperand::CreateImm(1)); - TmpInst.addOperand(MCOperand::CreateReg(0)); // Predicate. TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); TmpInst.addOperand(MCOperand::CreateReg(0)); @@ -1348,10 +1345,9 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { } { MCInst TmpInst; - TmpInst.setOpcode(ARM::tLDR); + TmpInst.setOpcode(ARM::tLDRr); TmpInst.addOperand(MCOperand::CreateReg(ARM::R7)); TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); - TmpInst.addOperand(MCOperand::CreateImm(0)); TmpInst.addOperand(MCOperand::CreateReg(0)); // Predicate. TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 5e302ae2813..0c403a9a059 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -193,7 +193,7 @@ namespace { const { return 0; } unsigned getSORegOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } - unsigned getTAddrModeRegRegOpValue(const MachineInstr &MI, unsigned Op) + unsigned getThumbAddrModeRegRegOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } unsigned getT2AddrModeImm12OpValue(const MachineInstr &MI, unsigned Op) const { return 0; } @@ -265,6 +265,8 @@ namespace { const { return 0; } uint32_t getAddrModeSOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } + uint32_t getAddrModeISOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } uint32_t getAddrModePCOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } uint32_t getAddrMode5OpValue(const MachineInstr &MI, unsigned Op) const { diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index f96f68fa16a..476fe6efac1 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -130,18 +130,24 @@ public: bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label); + // Thumb Addressing Modes: bool SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset); - bool SelectThumbAddrModeRI5(SDValue N, unsigned Scale, - SDValue &Base, SDValue &OffImm, - SDValue &Offset); - bool SelectThumbAddrModeS1(SDValue N, SDValue &Base, - SDValue &OffImm, SDValue &Offset); - bool SelectThumbAddrModeS2(SDValue N, SDValue &Base, - SDValue &OffImm, SDValue &Offset); - bool SelectThumbAddrModeS4(SDValue N, SDValue &Base, - SDValue &OffImm, SDValue &Offset); + bool SelectThumbAddrModeRI(SDValue N, SDValue &Base, SDValue &Offset, + unsigned Scale); + bool SelectThumbAddrModeRI5S1(SDValue N, SDValue &Base, SDValue &Offset); + bool SelectThumbAddrModeRI5S2(SDValue N, SDValue &Base, SDValue &Offset); + bool SelectThumbAddrModeRI5S4(SDValue N, SDValue &Base, SDValue &Offset); + bool SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, SDValue &Base, + SDValue &OffImm); + bool SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base, + SDValue &OffImm); + bool SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base, + SDValue &OffImm); + bool SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base, + SDValue &OffImm); bool SelectThumbAddrModeSP(SDValue N, SDValue &Base, SDValue &OffImm); + // Thumb 2 Addressing Modes: bool SelectT2ShifterOperandReg(SDValue N, SDValue &BaseReg, SDValue &Opc); bool SelectT2AddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm); @@ -872,9 +878,16 @@ bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N, MVT::i32); return true; } + return false; } + +//===----------------------------------------------------------------------===// +// Thumb Addressing Modes +//===----------------------------------------------------------------------===// + + bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset){ // FIXME dl should come from the parent load or store, not the address @@ -893,13 +906,13 @@ bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N, } bool -ARMDAGToDAGISel::SelectThumbAddrModeRI5(SDValue N, - unsigned Scale, SDValue &Base, - SDValue &OffImm, SDValue &Offset) { +ARMDAGToDAGISel::SelectThumbAddrModeRI(SDValue N, SDValue &Base, + SDValue &Offset, unsigned Scale) { if (Scale == 4) { SDValue TmpBase, TmpOffImm; if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm)) return false; // We want to select tLDRspi / tSTRspi instead. + if (N.getOpcode() == ARMISD::Wrapper && N.getOperand(0).getOpcode() == ISD::TargetConstantPool) return false; // We want to select tLDRpci instead. @@ -907,14 +920,13 @@ ARMDAGToDAGISel::SelectThumbAddrModeRI5(SDValue N, if (N.getOpcode() != ISD::ADD) { if (N.getOpcode() == ARMISD::Wrapper && - !(Subtarget->useMovt() && - N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { + (!Subtarget->useMovt() || + N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress)) Base = N.getOperand(0); - } else + else Base = N; Offset = CurDAG->getRegister(0, MVT::i32); - OffImm = CurDAG->getTargetConstant(0, MVT::i32); return true; } @@ -925,6 +937,68 @@ ARMDAGToDAGISel::SelectThumbAddrModeRI5(SDValue N, (RHSR && RHSR->getReg() == ARM::SP)) { Base = N; Offset = CurDAG->getRegister(0, MVT::i32); + return true; + } + + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + + if ((RHSC & (Scale - 1)) == 0) { // The constant is implicitly multiplied. + RHSC /= Scale; + + if (RHSC >= 0 && RHSC < 32) + return false; + } + } + + Base = N.getOperand(0); + Offset = N.getOperand(1); + return true; +} + +bool +ARMDAGToDAGISel::SelectThumbAddrModeRI5S1(SDValue N, + SDValue &Base, + SDValue &Offset) { + return SelectThumbAddrModeRI(N, Base, Offset, 1); +} + +bool +ARMDAGToDAGISel::SelectThumbAddrModeRI5S2(SDValue N, + SDValue &Base, + SDValue &Offset) { + return SelectThumbAddrModeRI(N, Base, Offset, 2); +} + +bool +ARMDAGToDAGISel::SelectThumbAddrModeRI5S4(SDValue N, + SDValue &Base, + SDValue &Offset) { + return SelectThumbAddrModeRI(N, Base, Offset, 4); +} + +bool +ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, + SDValue &Base, SDValue &OffImm) { + if (Scale == 4) { + SDValue TmpBase, TmpOffImm; + if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm)) + return false; // We want to select tLDRspi / tSTRspi instead. + + if (N.getOpcode() == ARMISD::Wrapper && + N.getOperand(0).getOpcode() == ISD::TargetConstantPool) + return false; // We want to select tLDRpci instead. + } + + if (N.getOpcode() != ISD::ADD) { + if (N.getOpcode() == ARMISD::Wrapper && + !(Subtarget->useMovt() && + N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { + Base = N.getOperand(0); + } else { + Base = N; + } + OffImm = CurDAG->getTargetConstant(0, MVT::i32); return true; } @@ -932,11 +1006,12 @@ ARMDAGToDAGISel::SelectThumbAddrModeRI5(SDValue N, // If the RHS is + imm5 * scale, fold into addr mode. if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { int RHSC = (int)RHS->getZExtValue(); - if ((RHSC & (Scale-1)) == 0) { // The constant is implicitly multiplied. + + if ((RHSC & (Scale - 1)) == 0) { // The constant is implicitly multiplied. RHSC /= Scale; + if (RHSC >= 0 && RHSC < 32) { Base = N.getOperand(0); - Offset = CurDAG->getRegister(0, MVT::i32); OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); return true; } @@ -944,27 +1019,26 @@ ARMDAGToDAGISel::SelectThumbAddrModeRI5(SDValue N, } Base = N.getOperand(0); - Offset = N.getOperand(1); OffImm = CurDAG->getTargetConstant(0, MVT::i32); return true; } -bool ARMDAGToDAGISel::SelectThumbAddrModeS1(SDValue N, - SDValue &Base, SDValue &OffImm, - SDValue &Offset) { - return SelectThumbAddrModeRI5(N, 1, Base, OffImm, Offset); +bool +ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base, + SDValue &OffImm) { + return SelectThumbAddrModeImm5S(N, 4, Base, OffImm); } -bool ARMDAGToDAGISel::SelectThumbAddrModeS2(SDValue N, - SDValue &Base, SDValue &OffImm, - SDValue &Offset) { - return SelectThumbAddrModeRI5(N, 2, Base, OffImm, Offset); +bool +ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base, + SDValue &OffImm) { + return SelectThumbAddrModeImm5S(N, 2, Base, OffImm); } -bool ARMDAGToDAGISel::SelectThumbAddrModeS4(SDValue N, - SDValue &Base, SDValue &OffImm, - SDValue &Offset) { - return SelectThumbAddrModeRI5(N, 4, Base, OffImm, Offset); +bool +ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base, + SDValue &OffImm) { + return SelectThumbAddrModeImm5S(N, 1, Base, OffImm); } bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N, @@ -1003,6 +1077,12 @@ bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N, return false; } + +//===----------------------------------------------------------------------===// +// Thumb 2 Addressing Modes +//===----------------------------------------------------------------------===// + + bool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue N, SDValue &BaseReg, SDValue &Opc) { if (DisableShifterOp) diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index c1192910113..2d416ebc5aa 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -94,8 +94,13 @@ def t_blxtarget : Operand { let EncoderMethod = "getThumbBLXTargetOpValue"; } -def MemModeThumbAsmOperand : AsmOperandClass { - let Name = "MemModeThumb"; +def MemModeRegThumbAsmOperand : AsmOperandClass { + let Name = "MemModeRegThumb"; + let SuperClasses = []; +} + +def MemModeImmThumbAsmOperand : AsmOperandClass { + let Name = "MemModeImmThumb"; let SuperClasses = []; } @@ -103,42 +108,64 @@ def MemModeThumbAsmOperand : AsmOperandClass { // def t_addrmode_rr : Operand, ComplexPattern { - let EncoderMethod = "getTAddrModeRegRegOpValue"; + let EncoderMethod = "getThumbAddrModeRegRegOpValue"; let PrintMethod = "printThumbAddrModeRROperand"; let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); } -// t_addrmode_s4 := reg + reg -// reg + imm5 * 4 +// t_addrmode_rrs := reg + reg // -def t_addrmode_s4 : Operand, - ComplexPattern { - let EncoderMethod = "getAddrModeSOpValue"; - let PrintMethod = "printThumbAddrModeS4Operand"; - let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg); - let ParserMatchClass = MemModeThumbAsmOperand; +def t_addrmode_rrs1 : Operand, + ComplexPattern { + let EncoderMethod = "getThumbAddrModeRegRegOpValue"; + let PrintMethod = "printThumbAddrModeRROperand"; + let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); + let ParserMatchClass = MemModeRegThumbAsmOperand; } -// t_addrmode_s2 := reg + reg -// reg + imm5 * 2 -// -def t_addrmode_s2 : Operand, - ComplexPattern { - let EncoderMethod = "getAddrModeSOpValue"; - let PrintMethod = "printThumbAddrModeS2Operand"; - let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg); - let ParserMatchClass = MemModeThumbAsmOperand; +def t_addrmode_rrs2 : Operand, + ComplexPattern { + let EncoderMethod = "getThumbAddrModeRegRegOpValue"; + let PrintMethod = "printThumbAddrModeRROperand"; + let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); + let ParserMatchClass = MemModeRegThumbAsmOperand; +} +def t_addrmode_rrs4 : Operand, + ComplexPattern { + let EncoderMethod = "getThumbAddrModeRegRegOpValue"; + let PrintMethod = "printThumbAddrModeRROperand"; + let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); + let ParserMatchClass = MemModeRegThumbAsmOperand; } -// t_addrmode_s1 := reg + reg -// reg + imm5 +// t_addrmode_is4 := reg + imm5 * 4 // -def t_addrmode_s1 : Operand, - ComplexPattern { - let EncoderMethod = "getAddrModeSOpValue"; - let PrintMethod = "printThumbAddrModeS1Operand"; - let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg); - let ParserMatchClass = MemModeThumbAsmOperand; +def t_addrmode_is4 : Operand, + ComplexPattern { + let EncoderMethod = "getAddrModeISOpValue"; + let PrintMethod = "printThumbAddrModeImm5S4Operand"; + let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); + let ParserMatchClass = MemModeImmThumbAsmOperand; +} + +// t_addrmode_is2 := reg + imm5 * 2 +// +def t_addrmode_is2 : Operand, + ComplexPattern { + let EncoderMethod = "getAddrModeISOpValue"; + let PrintMethod = "printThumbAddrModeImm5S2Operand"; + let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); + let ParserMatchClass = MemModeImmThumbAsmOperand; +} + +// t_addrmode_is1 := reg + imm5 +// +def t_addrmode_is1 : Operand, + ComplexPattern { + let EncoderMethod = "getAddrModeISOpValue"; + let PrintMethod = "printThumbAddrModeImm5S1Operand"; + let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); + let ParserMatchClass = MemModeImmThumbAsmOperand; } // t_addrmode_sp := sp + imm8 * 4 @@ -148,14 +175,14 @@ def t_addrmode_sp : Operand, let EncoderMethod = "getAddrModeThumbSPOpValue"; let PrintMethod = "printThumbAddrModeSPOperand"; let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); - let ParserMatchClass = MemModeThumbAsmOperand; + let ParserMatchClass = MemModeImmThumbAsmOperand; } // t_addrmode_pc :=