diff --git a/llvm/lib/Target/ARM/ARMCodeEmitter.cpp b/llvm/lib/Target/ARM/ARMCodeEmitter.cpp index ee97b37764a5..9d2edf485480 100644 --- a/llvm/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/llvm/lib/Target/ARM/ARMCodeEmitter.cpp @@ -241,6 +241,10 @@ namespace { const { return 0; } uint32_t getAddrModeS4OpValue(const MachineInstr &MI, unsigned Op) const { return 0; } + uint32_t getAddrModeS2OpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + uint32_t getAddrModeS1OpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } uint32_t getAddrMode5OpValue(const MachineInstr &MI, unsigned Op) const { // {17-13} = reg // {12} = (U)nsigned (add == '1', sub == '0') diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td index 80aa24e3f461..cd6e4c83d140 100644 --- a/llvm/lib/Target/ARM/ARMInstrFormats.td +++ b/llvm/lib/Target/ARM/ARMInstrFormats.td @@ -863,15 +863,6 @@ class T1pIt; -class T1pI1 pattern> - : Thumb1pI; -class T1pI2 pattern> - : Thumb1pI; -class T1pI4 pattern> - : Thumb1pI; class T1pIs pattern> : Thumb1pI; @@ -909,11 +900,39 @@ class T1LoadStore opA, bits<3> opB> : Encoding16 { let Inst{11-9} = opB; } class T1LdSt opB> : T1LoadStore<0b0101, opB>; -class T1LdSt4Imm opB> : T1LoadStore<0b0110, opB>; // Immediate, 4 bytes -class T1LdSt1Imm opB> : T1LoadStore<0b0111, opB>; // Immediate, 1 byte -class T1LdSt2Imm opB> : T1LoadStore<0b1000, opB>; // Immediate, 2 bytes class T1LdStSP opB> : T1LoadStore<0b1001, opB>; // SP relative +// Helper classes to encode Thumb1 loads and stores. For immediates, the +// following bits are used for "opA": +// +// 0b0110 => Immediate, 4 bytes +// 0b1000 => Immediate, 2 bytes +// 0b0111 => Immediate, 1 byte +class T1LdStImm opA, bits<3> opB> : T1LoadStore; + +class T1pIEncode opcode, dag oops, dag iops, AddrMode am, + InstrItinClass itin, string opc, string asm, + list pattern> + : Thumb1pI, + T1LdSt { + bits<3> Rt; + bits<8> addr; + let Inst{8-6} = addr{5-3}; // Rm + let Inst{5-3} = addr{2-0}; // Rn + let Inst{2-0} = Rt; +} +class T1pIEncodeImm opA, bit opB, dag oops, dag iops, AddrMode am, + InstrItinClass itin, string opc, string asm, + list pattern> + : Thumb1pI, + T1LdStImm { + bits<3> Rt; + bits<8> addr; + let Inst{10-6} = addr{7-3}; // imm5 + let Inst{5-3} = addr{2-0}; // Rn + let Inst{2-0} = Rt; +} + // A6.2.5 Miscellaneous 16-bit instructions encoding. class T1Misc opcode> : Encoding16 { let Inst{15-12} = 0b1011; diff --git a/llvm/lib/Target/ARM/ARMInstrThumb.td b/llvm/lib/Target/ARM/ARMInstrThumb.td index 5d57cd6bc06e..841d198c8413 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb.td @@ -103,8 +103,10 @@ def t_addrmode_s4 : Operand, // def t_addrmode_s2 : Operand, ComplexPattern { + string EncoderMethod = "getAddrModeS2OpValue"; let PrintMethod = "printThumbAddrModeS2Operand"; let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg); + let ParserMatchClass = MemModeThumbAsmOperand; } // t_addrmode_s1 := reg + reg @@ -112,8 +114,10 @@ def t_addrmode_s2 : Operand, // def t_addrmode_s1 : Operand, ComplexPattern { + string EncoderMethod = "getAddrModeS1OpValue"; let PrintMethod = "printThumbAddrModeS1Operand"; let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg); + let ParserMatchClass = MemModeThumbAsmOperand; } // t_addrmode_sp := sp + imm8 * 4 @@ -122,6 +126,7 @@ def t_addrmode_sp : Operand, ComplexPattern { let PrintMethod = "printThumbAddrModeSPOperand"; let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); + let ParserMatchClass = MemModeThumbAsmOperand; } //===----------------------------------------------------------------------===// @@ -508,59 +513,55 @@ def tTRAP : TI<(outs), (ins), IIC_Br, // let canFoldAsLoad = 1, isReMaterializable = 1 in -def tLDR : T1pI4<(outs tGPR:$Rt), (ins t_addrmode_s4:$addr), IIC_iLoad_r, - "ldr", "\t$Rt, $addr", - [(set tGPR:$Rt, (load t_addrmode_s4:$addr))]>, - T1LdSt<0b100> { - // A8.6.60 - bits<3> Rt; - bits<8> addr; - let Inst{8-6} = addr{5-3}; // Rm - let Inst{5-3} = addr{2-0}; // Rn - let Inst{2-0} = Rt; -} +def tLDR : // A8.6.60 + T1pIEncode<0b100, (outs tGPR:$Rt), (ins t_addrmode_s4:$addr), + AddrModeT1_4, IIC_iLoad_r, + "ldr", "\t$Rt, $addr", + [(set tGPR:$Rt, (load t_addrmode_s4:$addr))]>; -def tLDRi: T1pI4<(outs tGPR:$Rt), (ins t_addrmode_s4:$addr), IIC_iLoad_r, - "ldr", "\t$Rt, $addr", - []>, - T1LdSt4Imm<{1,?,?}> { - // A8.6.57 - bits<3> Rt; - bits<8> addr; - let Inst{10-6} = addr{7-3}; // imm5 - let Inst{5-3} = addr{2-0}; // Rn - let Inst{2-0} = Rt; -} +def tLDRi: // A8.6.57 + T1pIEncodeImm<0b0110, 1, (outs tGPR:$Rt), (ins t_addrmode_s4:$addr), + AddrModeT1_4, IIC_iLoad_r, + "ldr", "\t$Rt, $addr", + []>; -def tLDRB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoad_bh_r, +def tLDRB : // A8.6.64 + T1pIEncode<0b110, (outs tGPR:$Rt), (ins t_addrmode_s1:$addr), + AddrModeT1_1, IIC_iLoad_bh_r, + "ldrb", "\t$Rt, $addr", + [(set tGPR:$Rt, (zextloadi8 t_addrmode_s1:$addr))]>; + +def tLDRBi : // A8.6.61 + T1pIEncodeImm<0b0111, 1, (outs tGPR:$dst), (ins t_addrmode_s1:$addr), + AddrModeT1_1, IIC_iLoad_bh_r, "ldrb", "\t$dst, $addr", - [(set tGPR:$dst, (zextloadi8 t_addrmode_s1:$addr))]>, - T1LdSt<0b110>; -def tLDRBi: T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoad_bh_r, - "ldrb", "\t$dst, $addr", - []>, - T1LdSt1Imm<{1,?,?}>; + []>; -def tLDRH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoad_bh_r, +def tLDRH : // A8.6.76 + T1pIEncode<0b101, (outs tGPR:$dst), (ins t_addrmode_s2:$addr), + AddrModeT1_2, IIC_iLoad_bh_r, + "ldrh", "\t$dst, $addr", + [(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>; + +def tLDRHi: // A8.6.73 + T1pIEncodeImm<0b1000, 1, (outs tGPR:$dst), (ins t_addrmode_s2:$addr), + AddrModeT1_2, IIC_iLoad_bh_r, "ldrh", "\t$dst, $addr", - [(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>, - T1LdSt<0b101>; -def tLDRHi: T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoad_bh_r, - "ldrh", "\t$dst, $addr", - []>, - T1LdSt2Imm<{1,?,?}>; + []>; let AddedComplexity = 10 in -def tLDRSB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoad_bh_r, - "ldrsb", "\t$dst, $addr", - [(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>, - T1LdSt<0b011>; +def tLDRSB : // A8.6.80 + T1pIEncode<0b011, (outs tGPR:$dst), (ins t_addrmode_rr:$addr), + AddrModeT1_1, IIC_iLoad_bh_r, + "ldrsb", "\t$dst, $addr", + [(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>; let AddedComplexity = 10 in -def tLDRSH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoad_bh_r, - "ldrsh", "\t$dst, $addr", - [(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>, - T1LdSt<0b111>; +def tLDRSH : // A8.6.84 + T1pIEncode<0b111, (outs tGPR:$dst), (ins t_addrmode_rr:$addr), + AddrModeT1_2, IIC_iLoad_bh_r, + "ldrsh", "\t$dst, $addr", + [(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>; let canFoldAsLoad = 1 in def tLDRspi : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoad_i, @@ -590,32 +591,41 @@ def tLDRcp : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoad_i, "ldr", "\t$dst, $addr", []>, T1LdStSP<{1,?,?}>; -def tSTR : T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStore_r, - "str", "\t$src, $addr", - [(store tGPR:$src, t_addrmode_s4:$addr)]>, - T1LdSt<0b000>; -def tSTRi: T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStore_r, - "str", "\t$src, $addr", - []>, - T1LdSt4Imm<{0,?,?}>; +def tSTR : // A8.6.194 + T1pIEncode<0b000, (outs), (ins tGPR:$src, t_addrmode_s4:$addr), + AddrModeT1_4, IIC_iStore_r, + "str", "\t$src, $addr", + [(store tGPR:$src, t_addrmode_s4:$addr)]>; -def tSTRB : T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStore_bh_r, - "strb", "\t$src, $addr", - [(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>, - T1LdSt<0b010>; -def tSTRBi: T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStore_bh_r, - "strb", "\t$src, $addr", - []>, - T1LdSt1Imm<{0,?,?}>; +def tSTRi : // A8.6.192 + T1pIEncodeImm<0b0110, 0, (outs), (ins tGPR:$src, t_addrmode_s4:$addr), + AddrModeT1_4, IIC_iStore_r, + "str", "\t$src, $addr", + []>; -def tSTRH : T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStore_bh_r, - "strh", "\t$src, $addr", - [(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>, - T1LdSt<0b001>; -def tSTRHi: T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStore_bh_r, - "strh", "\t$src, $addr", - []>, - T1LdSt2Imm<{0,?,?}>; +def tSTRB : // A8.6.197 + T1pIEncode<0b010, (outs), (ins tGPR:$src, t_addrmode_s1:$addr), + AddrModeT1_1, IIC_iStore_bh_r, + "strb", "\t$src, $addr", + [(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>; + +def tSTRBi : // A8.6.195 + T1pIEncodeImm<0b0111, 0, (outs), (ins tGPR:$src, t_addrmode_s1:$addr), + AddrModeT1_1, IIC_iStore_bh_r, + "strb", "\t$src, $addr", + []>; + +def tSTRH : // A8.6.207 + T1pIEncode<0b001, (outs), (ins tGPR:$src, t_addrmode_s2:$addr), + AddrModeT1_2, IIC_iStore_bh_r, + "strh", "\t$src, $addr", + [(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>; + +def tSTRHi : // A8.6.205 + T1pIEncodeImm<0b1000, 0, (outs), (ins tGPR:$src, t_addrmode_s2:$addr), + AddrModeT1_2, IIC_iStore_bh_r, + "strh", "\t$src, $addr", + []>; def tSTRspi : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStore_i, "str", "\t$src, $addr", diff --git a/llvm/lib/Target/ARM/ARMMCCodeEmitter.cpp b/llvm/lib/Target/ARM/ARMMCCodeEmitter.cpp index 0a506d594783..f68796894713 100644 --- a/llvm/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/llvm/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -140,6 +140,14 @@ public: uint32_t getAddrModeS4OpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups) const; + /// getAddrModeS2OpValue - Return encoding for t_addrmode_s2 operands. + uint32_t getAddrModeS2OpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups) const; + + /// getAddrModeS1OpValue - Return encoding for t_addrmode_s1 operands. + uint32_t getAddrModeS1OpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups) const; + /// getAddrMode5OpValue - Return encoding info for 'reg +/- imm8' operand. uint32_t getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups) const; @@ -545,10 +553,9 @@ getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx, return (Rn << 9) | Imm8 | (isAdd << 8) | (isImm << 13); } -/// getAddrModeS4OpValue - Return encoding for t_addrmode_s4 operands. -uint32_t ARMMCCodeEmitter:: -getAddrModeS4OpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl &Fixups) const { +/// getAddrModeSOpValue - Encode the t_addrmode_s# operands. +static unsigned getAddrModeSOpValue(const MCInst &MI, unsigned OpIdx, + unsigned Scale) { // [Rn, Rm] // {5-3} = Rm // {2-0} = Rn @@ -560,11 +567,32 @@ getAddrModeS4OpValue(const MCInst &MI, unsigned OpIdx, const MCOperand &MO1 = MI.getOperand(OpIdx + 1); const MCOperand &MO2 = MI.getOperand(OpIdx + 2); unsigned Rn = getARMRegisterNumbering(MO.getReg()); - unsigned Imm5 = MO1.getImm(); + unsigned Imm5 = (MO1.getImm() / Scale) & 0x1f; unsigned Rm = getARMRegisterNumbering(MO2.getReg()); return (Rm << 3) | (Imm5 << 3) | Rn; } +/// getAddrModeS4OpValue - Return encoding for t_addrmode_s4 operands. +uint32_t ARMMCCodeEmitter:: +getAddrModeS4OpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &) const { + return getAddrModeSOpValue(MI, OpIdx, 4); +} + +/// getAddrModeS2OpValue - Return encoding for t_addrmode_s2 operands. +uint32_t ARMMCCodeEmitter:: +getAddrModeS2OpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &) const { + return getAddrModeSOpValue(MI, OpIdx, 2); +} + +/// getAddrModeS1OpValue - Return encoding for t_addrmode_s1 operands. +uint32_t ARMMCCodeEmitter:: +getAddrModeS1OpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &) const { + return getAddrModeSOpValue(MI, OpIdx, 1); +} + /// getAddrMode5OpValue - Return encoding info for 'reg +/- imm12' operand. uint32_t ARMMCCodeEmitter:: getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx, diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 31742e36245a..12d892a9fbef 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -323,7 +323,7 @@ public: if (Mem.Offset) { const MCConstantExpr *CE = dyn_cast(Mem.Offset); assert(CE && "Non-constant mode offset operand!"); - Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4)); + Inst.addOperand(MCOperand::CreateImm(CE->getValue())); Inst.addOperand(MCOperand::CreateReg(0)); } else { Inst.addOperand(MCOperand::CreateImm(0));