diff options
-rw-r--r-- | lib/Target/ARM/ARMCodeEmitter.cpp | 6 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrThumb.td | 32 | ||||
-rw-r--r-- | lib/Target/ARM/ARMMCCodeEmitter.cpp | 24 | ||||
-rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 41 | ||||
-rw-r--r-- | test/MC/ARM/thumb.s | 3 |
5 files changed, 92 insertions, 14 deletions
diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 1f74a2d..a384928 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -235,8 +235,10 @@ namespace { const { return 0;} uint32_t getAddrMode3OffsetOpValue(const MachineInstr &MI, unsigned OpIdx) const { return 0;} - uint32_t getAddrMode3OpValue(const MachineInstr &MI, unsigned Op) const - { return 0; } + uint32_t getAddrMode3OpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + uint32_t getAddrModeS4OpValue(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/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 204686c..5d57cd6 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -74,6 +74,11 @@ def t_imm_s4 : Operand<i32> { // Define Thumb specific addressing modes. +def MemModeThumbAsmOperand : AsmOperandClass { + let Name = "MemModeThumb"; + let SuperClasses = []; +} + // t_addrmode_rr := reg + reg // def t_addrmode_rr : Operand<i32>, @@ -87,8 +92,10 @@ def t_addrmode_rr : Operand<i32>, // def t_addrmode_s4 : Operand<i32>, ComplexPattern<i32, 3, "SelectThumbAddrModeS4", []> { + string EncoderMethod = "getAddrModeS4OpValue"; let PrintMethod = "printThumbAddrModeS4Operand"; let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg); + let ParserMatchClass = MemModeThumbAsmOperand; } // t_addrmode_s2 := reg + reg @@ -489,8 +496,7 @@ def tSVC : T1pI<(outs), (ins i32imm:$imm), IIC_Br, let Inst{7-0} = imm; } -// A8.6.16 B: Encoding T1 -// If Inst{11-8} == 0b1110 then UNDEFINED +// The assembler uses 0xDEFE for a trap instruction. let isBarrier = 1, isTerminator = 1 in def tTRAP : TI<(outs), (ins), IIC_Br, "trap", [(trap)]>, Encoding16 { @@ -505,12 +511,26 @@ 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>; + 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 tLDRi: T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoad_r, - "ldr", "\t$dst, $addr", +def tLDRi: T1pI4<(outs tGPR:$Rt), (ins t_addrmode_s4:$addr), IIC_iLoad_r, + "ldr", "\t$Rt, $addr", []>, - T1LdSt4Imm<{1,?,?}>; + 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 tLDRB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoad_bh_r, "ldrb", "\t$dst, $addr", diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index a9f8133..a2829c9 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -136,6 +136,10 @@ public: uint32_t getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups) const; + /// getAddrModeS4OpValue - Return encoding for t_addrmode_s4 operands. + uint32_t getAddrModeS4OpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl<MCFixup> &Fixups) const; + /// getAddrMode5OpValue - Return encoding info for 'reg +/- imm8' operand. uint32_t getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups) const; @@ -540,6 +544,26 @@ 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<MCFixup> &Fixups) const { + // [Rn, Rm] + // {5-3} = Rm + // {2-0} = Rn + // + // [Rn, #imm] + // {7-3} = imm5 + // {2-0} = Rn + const MCOperand &MO = MI.getOperand(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 Rm = getARMRegisterNumbering(MO2.getReg()); + return (Rm << 3) | (Imm5 << 3) | Rn; +} + /// getAddrMode5OpValue - Return encoding info for 'reg +/- imm12' operand. uint32_t ARMMCCodeEmitter:: getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx, diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index f9a792e..31742e3 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -222,16 +222,30 @@ public: if (!isMemory() || Mem.OffsetIsReg || Mem.OffsetRegShifted || Mem.Writeback || Mem.Negative) return false; + // If there is an offset expression, make sure it's valid. - if (!Mem.Offset) - return true; + if (!Mem.Offset) return true; + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset); - if (!CE) - return false; + if (!CE) return false; + // The offset must be a multiple of 4 in the range 0-1020. int64_t Value = CE->getValue(); return ((Value & 0x3) == 0 && Value <= 1020 && Value >= -1020); } + bool isMemModeThumb() const { + if (!isMemory() || (!Mem.OffsetIsReg && !Mem.Offset) || Mem.Writeback) + return false; + + if (!Mem.Offset) return true; + + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset); + if (!CE) return false; + + // The offset must be a multiple of 4 in the range 0-124. + uint64_t Value = CE->getValue(); + return ((Value & 0x3) == 0 && Value <= 124); + } void addExpr(MCInst &Inst, const MCExpr *Expr) const { // Add as immediates when possible. Null MCExpr = 0. @@ -302,6 +316,21 @@ public: } } + void addMemModeThumbOperands(MCInst &Inst, unsigned N) const { + assert(N == 3 && isMemModeThumb() && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); + + if (Mem.Offset) { + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset); + assert(CE && "Non-constant mode offset operand!"); + Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4)); + Inst.addOperand(MCOperand::CreateReg(0)); + } else { + Inst.addOperand(MCOperand::CreateImm(0)); + Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum)); + } + } + virtual void dump(raw_ostream &OS) const; static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) { @@ -592,8 +621,8 @@ ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { int OffsetRegNum; bool OffsetRegShifted; enum ShiftType ShiftType; - const MCExpr *ShiftAmount; - const MCExpr *Offset; + const MCExpr *ShiftAmount = 0; + const MCExpr *Offset = 0; if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount, Offset, OffsetIsReg, OffsetRegNum, E)) return true; diff --git a/test/MC/ARM/thumb.s b/test/MC/ARM/thumb.s index 2db97c3..3d58521 100644 --- a/test/MC/ARM/thumb.s +++ b/test/MC/ARM/thumb.s @@ -32,3 +32,6 @@ @ CHECK: uxth r3, r6 @ encoding: [0xb3,0xb2] uxtb r3, r6 uxth r3, r6 + +@ CHECK: ldr r3, [r1, r2] @ encoding: [0x8b,0x58] + ldr r3, [r1, r2] |