<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Bruno,<div><br></div><div>This is causing clang test failures.</div><div><br></div><div><span class="Apple-style-span" style="font-family: Times; "><pre style="font-family: 'Courier New', courier, monotype; "><span class="stdout" style="font-family: 'Courier New', courier, monotype; color: black; ">LLVM :: CodeGen/ARM/ldr_post.ll
LLVM :: CodeGen/ARM/ldst-f32-2-i32.ll
LLVM :: CodeGen/ARM/str_pre-2.ll</span></pre></span><div>Can you take a look ?</div><div>Thanks,</div><div>-</div><div>Devang</div><div><br></div><div><div>On Mar 31, 2011, at 7:52 AM, Bruno Cardoso Lopes wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>Author: bruno<br>Date: Thu Mar 31 09:52:28 2011<br>New Revision: 128632<br><br>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=128632&view=rev">http://llvm.org/viewvc/llvm-project?rev=128632&view=rev</a><br>Log:<br>Reapply r128585 without generating a lib depedency cycle. An updated log:<br><br>- Implement asm parsing support for LDRT, LDRBT, STRT, STRBT and<br> {STR,LDC}{2}_{PRE,POST} fixing the encoding wherever is possible.<br>- Move all instructions which use am2offset without a pattern to use<br> addrmode2.<br>- Add a new encoding bit to describe the index mode used and teach<br> printAddrMode2Operand to check by the addressing mode which index<br> mode to print.<br>- Testcases<br><br>Added:<br> llvm/trunk/test/MC/ARM/arm_addrmode2.s<br>Modified:<br> llvm/trunk/lib/Target/ARM/ARMAddressingModes.h<br> llvm/trunk/lib/Target/ARM/ARMBaseInfo.h<br> llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h<br> llvm/trunk/lib/Target/ARM/ARMInstrFormats.td<br> llvm/trunk/lib/Target/ARM/ARMInstrInfo.td<br> llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp<br> llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp<br> llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp<br> llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.h<br><br>Modified: llvm/trunk/lib/Target/ARM/ARMAddressingModes.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMAddressingModes.h?rev=128632&r1=128631&r2=128632&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMAddressingModes.h?rev=128632&r1=128631&r2=128632&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/ARMAddressingModes.h (original)<br>+++ llvm/trunk/lib/Target/ARM/ARMAddressingModes.h Thu Mar 31 09:52:28 2011<br>@@ -408,16 +408,18 @@<br> //<br> // The first operand is always a Reg. The second operand is a reg if in<br> // reg/reg form, otherwise it's reg#0. The third field encodes the operation<br>- // in bit 12, the immediate in bits 0-11, and the shift op in 13-15.<br>+ // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. The<br>+ // forth operand 16-17 encodes the index mode.<br> //<br> // If this addressing mode is a frame index (before prolog/epilog insertion<br> // and code rewriting), this operand will have the form: FI#, reg0, <offs><br> // with no shift amount for the frame offset.<br> //<br>- static inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO) {<br>+ static inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO,<br>+ unsigned IdxMode = 0) {<br> assert(Imm12 < (1 << 12) && "Imm too large!");<br> bool isSub = Opc == sub;<br>- return Imm12 | ((int)isSub << 12) | (SO << 13);<br>+ return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16) ;<br> }<br> static inline unsigned getAM2Offset(unsigned AM2Opc) {<br> return AM2Opc & ((1 << 12)-1);<br>@@ -426,7 +428,10 @@<br> return ((AM2Opc >> 12) & 1) ? sub : add;<br> }<br> static inline ShiftOpc getAM2ShiftOpc(unsigned AM2Opc) {<br>- return (ShiftOpc)(AM2Opc >> 13);<br>+ return (ShiftOpc)((AM2Opc >> 13) & 7);<br>+ }<br>+ static inline unsigned getAM2IdxMode(unsigned AM2Opc) {<br>+ return (AM2Opc >> 16);<br> }<br><br><br><br>Modified: llvm/trunk/lib/Target/ARM/ARMBaseInfo.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInfo.h?rev=128632&r1=128631&r2=128632&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInfo.h?rev=128632&r1=128631&r2=128632&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/ARMBaseInfo.h (original)<br>+++ llvm/trunk/lib/Target/ARM/ARMBaseInfo.h Thu Mar 31 09:52:28 2011<br>@@ -200,6 +200,59 @@<br> }<br><br> namespace ARMII {<br>+<br>+ /// ARM Index Modes<br>+ enum IndexMode {<br>+ IndexModeNone = 0,<br>+ IndexModePre = 1,<br>+ IndexModePost = 2,<br>+ IndexModeUpd = 3<br>+ };<br>+<br>+ /// ARM Addressing Modes<br>+ enum AddrMode {<br>+ AddrModeNone = 0,<br>+ AddrMode1 = 1,<br>+ AddrMode2 = 2,<br>+ AddrMode3 = 3,<br>+ AddrMode4 = 4,<br>+ AddrMode5 = 5,<br>+ AddrMode6 = 6,<br>+ AddrModeT1_1 = 7,<br>+ AddrModeT1_2 = 8,<br>+ AddrModeT1_4 = 9,<br>+ AddrModeT1_s = 10, // i8 * 4 for pc and sp relative data<br>+ AddrModeT2_i12 = 11,<br>+ AddrModeT2_i8 = 12,<br>+ AddrModeT2_so = 13,<br>+ AddrModeT2_pc = 14, // +/- i12 for pc relative data<br>+ AddrModeT2_i8s4 = 15, // i8 * 4<br>+ AddrMode_i12 = 16<br>+ };<br>+<br>+ inline static const char *AddrModeToString(AddrMode addrmode) {<br>+ switch (addrmode) {<br>+ default: llvm_unreachable("Unknown memory operation");<br>+ case AddrModeNone: return "AddrModeNone";<br>+ case AddrMode1: return "AddrMode1";<br>+ case AddrMode2: return "AddrMode2";<br>+ case AddrMode3: return "AddrMode3";<br>+ case AddrMode4: return "AddrMode4";<br>+ case AddrMode5: return "AddrMode5";<br>+ case AddrMode6: return "AddrMode6";<br>+ case AddrModeT1_1: return "AddrModeT1_1";<br>+ case AddrModeT1_2: return "AddrModeT1_2";<br>+ case AddrModeT1_4: return "AddrModeT1_4";<br>+ case AddrModeT1_s: return "AddrModeT1_s";<br>+ case AddrModeT2_i12: return "AddrModeT2_i12";<br>+ case AddrModeT2_i8: return "AddrModeT2_i8";<br>+ case AddrModeT2_so: return "AddrModeT2_so";<br>+ case AddrModeT2_pc: return "AddrModeT2_pc";<br>+ case AddrModeT2_i8s4: return "AddrModeT2_i8s4";<br>+ case AddrMode_i12: return "AddrMode_i12";<br>+ }<br>+ }<br>+<br> /// Target Operand Flag enum.<br> enum TOF {<br> //===------------------------------------------------------------------===//<br><br>Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h?rev=128632&r1=128631&r2=128632&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h?rev=128632&r1=128631&r2=128632&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h (original)<br>+++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h Thu Mar 31 09:52:28 2011<br>@@ -34,25 +34,7 @@<br><br> //===------------------------------------------------------------------===//<br> // This four-bit field describes the addressing mode used.<br>-<br>- AddrModeMask = 0x1f,<br>- AddrModeNone = 0,<br>- AddrMode1 = 1,<br>- AddrMode2 = 2,<br>- AddrMode3 = 3,<br>- AddrMode4 = 4,<br>- AddrMode5 = 5,<br>- AddrMode6 = 6,<br>- AddrModeT1_1 = 7,<br>- AddrModeT1_2 = 8,<br>- AddrModeT1_4 = 9,<br>- AddrModeT1_s = 10, // i8 * 4 for pc and sp relative data<br>- AddrModeT2_i12 = 11,<br>- AddrModeT2_i8 = 12,<br>- AddrModeT2_so = 13,<br>- AddrModeT2_pc = 14, // +/- i12 for pc relative data<br>- AddrModeT2_i8s4 = 15, // i8 * 4<br>- AddrMode_i12 = 16,<br>+ AddrModeMask = 0x1f, // The AddrMode enums are declared in ARMBaseInfo.h<br><br> // Size* - Flags to keep track of the size of an instruction.<br> SizeShift = 5,<br>@@ -64,11 +46,9 @@<br><br> // IndexMode - Unindex, pre-indexed, or post-indexed are valid for load<br> // and store ops only. Generic "updating" flag is used for ld/st multiple.<br>+ // The index mode enums are declared in ARMBaseInfo.h<br> IndexModeShift = 8,<br> IndexModeMask = 3 << IndexModeShift,<br>- IndexModePre = 1,<br>- IndexModePost = 2,<br>- IndexModeUpd = 3,<br><br> //===------------------------------------------------------------------===//<br> // Instruction encoding formats.<br><br>Modified: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrFormats.td?rev=128632&r1=128631&r2=128632&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrFormats.td?rev=128632&r1=128631&r2=128632&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/ARMInstrFormats.td (original)<br>+++ llvm/trunk/lib/Target/ARM/ARMInstrFormats.td Thu Mar 31 09:52:28 2011<br>@@ -515,15 +515,15 @@<br> : AI2ldstidx<0, isByte, isPre, oops, iops, im, f, itin, opc, asm, cstr,<br> pattern> {<br> // AM2 store w/ two operands: (GPR, am2offset)<br>+ // {17-14} Rn<br> // {13} 1 == Rm, 0 == imm12<br> // {12} isAdd<br> // {11-0} imm12/Rm<br>- bits<14> offset;<br>- bits<4> Rn;<br>- let Inst{25} = offset{13};<br>- let Inst{23} = offset{12};<br>- let Inst{19-16} = Rn;<br>- let Inst{11-0} = offset{11-0};<br>+ bits<18> addr;<br>+ let Inst{25} = addr{13};<br>+ let Inst{23} = addr{12};<br>+ let Inst{19-16} = addr{17-14};<br>+ let Inst{11-0} = addr{11-0};<br> }<br><br> // addrmode3 instructions<br><br>Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=128632&r1=128631&r2=128632&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=128632&r1=128631&r2=128632&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)<br>+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Thu Mar 31 09:52:28 2011<br>@@ -498,6 +498,12 @@<br> let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);<br> }<br><br>+def MemMode2AsmOperand : AsmOperandClass {<br>+ let Name = "MemMode2";<br>+ let SuperClasses = [];<br>+ let ParserMethod = "tryParseMemMode2Operand";<br>+}<br>+<br> // addrmode2 := reg +/- imm12<br> // := reg +/- reg shop imm<br> //<br>@@ -505,6 +511,7 @@<br> ComplexPattern<i32, 3, "SelectAddrMode2", []> {<br> let EncoderMethod = "getAddrMode2OpValue";<br> let PrintMethod = "printAddrMode2Operand";<br>+ let ParserMatchClass = MemMode2AsmOperand;<br> let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);<br> }<br><br>@@ -1656,20 +1663,21 @@<br> let Inst{23} = addr{12};<br> let Inst{19-16} = addr{17-14};<br> let Inst{11-0} = addr{11-0};<br>+ let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";<br> }<br> def _POST : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb),<br>- (ins GPR:$Rn, am2offset:$offset),<br>- IndexModePost, LdFrm, itin,<br>- opc, "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", []> {<br>+ (ins addrmode2:$addr), IndexModePost, LdFrm, itin,<br>+ opc, "\t$Rt, $addr", "$addr.base = $Rn_wb", []> {<br>+ // {17-14} Rn<br> // {13} 1 == Rm, 0 == imm12<br> // {12} isAdd<br> // {11-0} imm12/Rm<br>- bits<14> offset;<br>- bits<4> Rn;<br>- let Inst{25} = offset{13};<br>- let Inst{23} = offset{12};<br>- let Inst{19-16} = Rn;<br>- let Inst{11-0} = offset{11-0};<br>+ bits<18> addr;<br>+ let Inst{25} = addr{13};<br>+ let Inst{23} = addr{12};<br>+ let Inst{19-16} = addr{17-14};<br>+ let Inst{11-0} = addr{11-0};<br>+ let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";<br> }<br> }<br><br>@@ -1714,17 +1722,35 @@<br><br> // LDRT, LDRBT, LDRSBT, LDRHT, LDRSHT are for disassembly only.<br> let mayLoad = 1, neverHasSideEffects = 1 in {<br>-def LDRT : AI2ldstidx<1, 0, 0, (outs GPR:$dst, GPR:$base_wb),<br>- (ins GPR:$base, am2offset:$offset), IndexModePost,<br>- LdFrm, IIC_iLoad_ru,<br>- "ldrt", "\t$dst, [$base], $offset", "$base = $base_wb", []> {<br>+def LDRT : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$base_wb),<br>+ (ins addrmode2:$addr), IndexModePost, LdFrm, IIC_iLoad_ru,<br>+ "ldrt", "\t$Rt, $addr", "$addr.base = $base_wb", []> {<br>+ // {17-14} Rn<br>+ // {13} 1 == Rm, 0 == imm12<br>+ // {12} isAdd<br>+ // {11-0} imm12/Rm<br>+ bits<18> addr;<br>+ let Inst{25} = addr{13};<br>+ let Inst{23} = addr{12};<br> let Inst{21} = 1; // overwrite<br>-}<br>-def LDRBT : AI2ldstidx<1, 1, 0, (outs GPR:$dst, GPR:$base_wb),<br>- (ins GPR:$base, am2offset:$offset), IndexModePost,<br>- LdFrm, IIC_iLoad_bh_ru,<br>- "ldrbt", "\t$dst, [$base], $offset", "$base = $base_wb", []> {<br>+ let Inst{19-16} = addr{17-14};<br>+ let Inst{11-0} = addr{11-0};<br>+ let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";<br>+}<br>+def LDRBT : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$base_wb),<br>+ (ins addrmode2:$addr), IndexModePost, LdFrm, IIC_iLoad_bh_ru,<br>+ "ldrbt", "\t$Rt, $addr", "$addr.base = $base_wb", []> {<br>+ // {17-14} Rn<br>+ // {13} 1 == Rm, 0 == imm12<br>+ // {12} isAdd<br>+ // {11-0} imm12/Rm<br>+ bits<18> addr;<br>+ let Inst{25} = addr{13};<br>+ let Inst{23} = addr{12};<br> let Inst{21} = 1; // overwrite<br>+ let Inst{19-16} = addr{17-14};<br>+ let Inst{11-0} = addr{11-0};<br>+ let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";<br> }<br> def LDRSBT : AI3ldstidx<0b1101, 1, 1, 0, (outs GPR:$dst, GPR:$base_wb),<br> (ins GPR:$base, am3offset:$offset), IndexModePost,<br>@@ -1818,20 +1844,20 @@<br><br> // STRT, STRBT, and STRHT are for disassembly only.<br><br>-def STRT : AI2stridx<0, 0, (outs GPR:$Rn_wb),<br>- (ins GPR:$Rt, GPR:$Rn,am2offset:$offset),<br>+def STRT : AI2stridx<0, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, addrmode2:$addr),<br> IndexModePost, StFrm, IIC_iStore_ru,<br>- "strt", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb",<br>+ "strt", "\t$Rt, $addr", "$addr.base = $Rn_wb",<br> [/* For disassembly only; pattern left blank */]> {<br> let Inst{21} = 1; // overwrite<br>+ let AsmMatchConverter = "CvtStWriteBackRegAddrMode2";<br> }<br><br>-def STRBT : AI2stridx<1, 0, (outs GPR:$Rn_wb),<br>- (ins GPR:$Rt, GPR:$Rn, am2offset:$offset),<br>+def STRBT : AI2stridx<1, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, addrmode2:$addr),<br> IndexModePost, StFrm, IIC_iStore_bh_ru,<br>- "strbt", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb",<br>+ "strbt", "\t$Rt, $addr", "$addr.base = $Rn_wb",<br> [/* For disassembly only; pattern left blank */]> {<br> let Inst{21} = 1; // overwrite<br>+ let AsmMatchConverter = "CvtStWriteBackRegAddrMode2";<br> }<br><br> def STRHT: AI3sthpo<(outs GPR:$base_wb),<br>@@ -3391,8 +3417,9 @@<br> let Inst{23-20} = opc1;<br> }<br><br>-class ACI<dag oops, dag iops, string opc, string asm><br>- : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, BrFrm, NoItinerary,<br>+class ACI<dag oops, dag iops, string opc, string asm,<br>+ IndexMode im = IndexModeNone><br>+ : I<oops, iops, AddrModeNone, Size4Bytes, im, BrFrm, NoItinerary,<br> opc, asm, "", [/* For disassembly only; pattern left blank */]> {<br> let Inst{27-25} = 0b110;<br> }<br>@@ -3411,7 +3438,7 @@<br><br> def _PRE : ACI<(outs),<br> (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),<br>- opc, "\tp$cop, cr$CRd, $addr!"> {<br>+ opc, "\tp$cop, cr$CRd, $addr!", IndexModePre> {<br> let Inst{31-28} = op31_28;<br> let Inst{24} = 1; // P = 1<br> let Inst{21} = 1; // W = 1<br>@@ -3420,8 +3447,8 @@<br> }<br><br> def _POST : ACI<(outs),<br>- (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, am2offset:$offset),<br>- opc, "\tp$cop, cr$CRd, [$base], $offset"> {<br>+ (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),<br>+ opc, "\tp$cop, cr$CRd, $addr", IndexModePost> {<br> let Inst{31-28} = op31_28;<br> let Inst{24} = 0; // P = 0<br> let Inst{21} = 1; // W = 1<br>@@ -3452,7 +3479,7 @@<br><br> def L_PRE : ACI<(outs),<br> (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),<br>- !strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr!"> {<br>+ !strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr!", IndexModePre> {<br> let Inst{31-28} = op31_28;<br> let Inst{24} = 1; // P = 1<br> let Inst{21} = 1; // W = 1<br>@@ -3461,8 +3488,8 @@<br> }<br><br> def L_POST : ACI<(outs),<br>- (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, am2offset:$offset),<br>- !strconcat(opc, "l"), "\tp$cop, cr$CRd, [$base], $offset"> {<br>+ (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),<br>+ !strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr", IndexModePost> {<br> let Inst{31-28} = op31_28;<br> let Inst{24} = 0; // P = 0<br> let Inst{21} = 1; // W = 1<br><br>Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=128632&r1=128631&r2=128632&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=128632&r1=128631&r2=128632&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original)<br>+++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Thu Mar 31 09:52:28 2011<br>@@ -48,7 +48,8 @@<br> bool TryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);<br> bool TryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);<br> bool ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);<br>- bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);<br>+ bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &,<br>+ ARMII::AddrMode AddrMode);<br> bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);<br> bool ParsePrefix(ARMMCExpr::VariantKind &RefKind);<br> const MCExpr *ApplyPrefixToExpr(const MCExpr *E,<br>@@ -95,6 +96,14 @@<br> SmallVectorImpl<MCParsedAsmOperand*>&);<br> OperandMatchResultTy tryParseMSRMaskOperand(<br> SmallVectorImpl<MCParsedAsmOperand*>&);<br>+ OperandMatchResultTy tryParseMemMode2Operand(<br>+ SmallVectorImpl<MCParsedAsmOperand*>&);<br>+<br>+ // Asm Match Converter Methods<br>+ bool CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,<br>+ const SmallVectorImpl<MCParsedAsmOperand*> &);<br>+ bool CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,<br>+ const SmallVectorImpl<MCParsedAsmOperand*> &);<br><br> public:<br> ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)<br>@@ -172,6 +181,7 @@<br><br> /// Combined record for all forms of ARM address expressions.<br> struct {<br>+ ARMII::AddrMode AddrMode;<br> unsigned BaseRegNum;<br> union {<br> unsigned RegNum; ///< Offset register num, when OffsetIsReg.<br>@@ -293,7 +303,9 @@<br><br> /// @name Memory Operand Accessors<br> /// @{<br>-<br>+ ARMII::AddrMode getMemAddrMode() const {<br>+ return Mem.AddrMode;<br>+ }<br> unsigned getMemBaseRegNum() const {<br> return Mem.BaseRegNum;<br> }<br>@@ -338,6 +350,27 @@<br> bool isMemBarrierOpt() const { return Kind == MemBarrierOpt; }<br> bool isMemory() const { return Kind == Memory; }<br> bool isShifter() const { return Kind == Shifter; }<br>+ bool isMemMode2() const {<br>+ if (getMemAddrMode() != ARMII::AddrMode2)<br>+ return false;<br>+<br>+ if (getMemOffsetIsReg())<br>+ return true;<br>+<br>+ if (getMemNegative() &&<br>+ !(getMemPostindexed() || getMemPreindexed()))<br>+ return false;<br>+<br>+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());<br>+ if (!CE) return false;<br>+ int64_t Value = CE->getValue();<br>+<br>+ // The offset must be in the range 0-4095 (imm12).<br>+ if (Value > 4095 || Value < -4095)<br>+ return false;<br>+<br>+ return true;<br>+ }<br> bool isMemMode5() const {<br> if (!isMemory() || getMemOffsetIsReg() || getMemWriteback() ||<br> getMemNegative())<br>@@ -465,6 +498,47 @@<br> "No offset operand support in mode 7");<br> }<br><br>+ void addMemMode2Operands(MCInst &Inst, unsigned N) const {<br>+ assert(isMemMode2() && "Invalid mode or number of operands!");<br>+ Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum()));<br>+ unsigned IdxMode = (getMemPreindexed() | getMemPostindexed() << 1);<br>+<br>+ if (getMemOffsetIsReg()) {<br>+ Inst.addOperand(MCOperand::CreateReg(getMemOffsetRegNum()));<br>+<br>+ ARM_AM::AddrOpc AMOpc = getMemNegative() ? ARM_AM::sub : ARM_AM::add;<br>+ ARM_AM::ShiftOpc ShOpc = ARM_AM::no_shift;<br>+ int64_t ShiftAmount = 0;<br>+<br>+ if (getMemOffsetRegShifted()) {<br>+ ShOpc = getMemShiftType();<br>+ const MCConstantExpr *CE =<br>+ dyn_cast<MCConstantExpr>(getMemShiftAmount());<br>+ ShiftAmount = CE->getValue();<br>+ }<br>+<br>+ Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(AMOpc, ShiftAmount,<br>+ ShOpc, IdxMode)));<br>+ return;<br>+ }<br>+<br>+ // Create a operand placeholder to always yield the same number of operands.<br>+ Inst.addOperand(MCOperand::CreateReg(0));<br>+<br>+ // FIXME: #-0 is encoded differently than #0. Does the parser preserve<br>+ // the difference?<br>+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());<br>+ assert(CE && "Non-constant mode 2 offset operand!");<br>+ int64_t Offset = CE->getValue();<br>+<br>+ if (Offset >= 0)<br>+ Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(ARM_AM::add,<br>+ Offset, ARM_AM::no_shift, IdxMode)));<br>+ else<br>+ Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(ARM_AM::sub,<br>+ -Offset, ARM_AM::no_shift, IdxMode)));<br>+ }<br>+<br> void addMemMode5Operands(MCInst &Inst, unsigned N) const {<br> assert(N == 2 && isMemMode5() && "Invalid number of operands!");<br><br>@@ -599,9 +673,9 @@<br> return Op;<br> }<br><br>- static ARMOperand *CreateMem(unsigned BaseRegNum, bool OffsetIsReg,<br>- const MCExpr *Offset, int OffsetRegNum,<br>- bool OffsetRegShifted,<br>+ static ARMOperand *CreateMem(ARMII::AddrMode AddrMode, unsigned BaseRegNum,<br>+ bool OffsetIsReg, const MCExpr *Offset,<br>+ int OffsetRegNum, bool OffsetRegShifted,<br> enum ARM_AM::ShiftOpc ShiftType,<br> const MCExpr *ShiftAmount, bool Preindexed,<br> bool Postindexed, bool Negative, bool Writeback,<br>@@ -618,6 +692,7 @@<br> "Cannot have expression offset and register offset!");<br><br> ARMOperand *Op = new ARMOperand(Memory);<br>+ Op->Mem.AddrMode = AddrMode;<br> Op->Mem.BaseRegNum = BaseRegNum;<br> Op->Mem.OffsetIsReg = OffsetIsReg;<br> if (OffsetIsReg)<br>@@ -689,7 +764,8 @@<br> break;<br> case Memory:<br> OS << "<memory "<br>- << "base:" << getMemBaseRegNum();<br>+ << "am:" << ARMII::AddrModeToString(getMemAddrMode())<br>+ << " base:" << getMemBaseRegNum();<br> if (getMemOffsetIsReg()) {<br> OS << " offset:<register " << getMemOffsetRegNum();<br> if (getMemOffsetRegShifted()) {<br>@@ -1132,13 +1208,57 @@<br> return MatchOperand_Success;<br> }<br><br>+/// tryParseMemMode2Operand - Try to parse memory addressing mode 2 operand.<br>+ARMAsmParser::OperandMatchResultTy ARMAsmParser::<br>+tryParseMemMode2Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {<br>+ SMLoc S = Parser.getTok().getLoc();<br>+ const AsmToken &Tok = Parser.getTok();<br>+ assert(<a href="http://Tok.is">Tok.is</a>(AsmToken::LBrac) && "Token is not a \"[\"");<br>+<br>+ if (ParseMemory(Operands, ARMII::AddrMode2))<br>+ return MatchOperand_NoMatch;<br>+<br>+ return MatchOperand_Success;<br>+}<br>+<br>+/// CvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.<br>+/// Needed here because the Asm Gen Matcher can't handle properly tied operands<br>+/// when they refer multiple MIOperands inside a single one.<br>+bool ARMAsmParser::<br>+CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,<br>+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {<br>+ ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);<br>+<br>+ // Create a writeback register dummy placeholder.<br>+ Inst.addOperand(MCOperand::CreateImm(0));<br>+<br>+ ((ARMOperand*)Operands[3])->addMemMode2Operands(Inst, 3);<br>+ ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);<br>+ return true;<br>+}<br>+<br>+/// CvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.<br>+/// Needed here because the Asm Gen Matcher can't handle properly tied operands<br>+/// when they refer multiple MIOperands inside a single one.<br>+bool ARMAsmParser::<br>+CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,<br>+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {<br>+ // Create a writeback register dummy placeholder.<br>+ Inst.addOperand(MCOperand::CreateImm(0));<br>+ ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);<br>+ ((ARMOperand*)Operands[3])->addMemMode2Operands(Inst, 3);<br>+ ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);<br>+ return true;<br>+}<br>+<br> /// Parse an ARM memory expression, return false if successful else return true<br> /// or an error. The first token must be a '[' when called.<br> ///<br> /// TODO Only preindexing and postindexing addressing are started, unindexed<br> /// with option, etc are still to do.<br> bool ARMAsmParser::<br>-ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {<br>+ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands,<br>+ ARMII::AddrMode AddrMode = ARMII::AddrModeNone) {<br> SMLoc S, E;<br> assert(Parser.getTok().is(AsmToken::LBrac) &&<br> "Token is not a Left Bracket");<br>@@ -1196,6 +1316,9 @@<br> ExclaimTok.getLoc());<br> Writeback = true;<br> Parser.Lex(); // Eat exclaim token<br>+ } else { // In addressing mode 2, pre-indexed mode always end with "!"<br>+ if (AddrMode == ARMII::AddrMode2)<br>+ Preindexed = false;<br> }<br> } else {<br> // The "[Rn" we have so far was not followed by a comma.<br>@@ -1231,11 +1354,10 @@<br> Offset = MCConstantExpr::Create(0, getContext());<br> }<br><br>- Operands.push_back(ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset,<br>- OffsetRegNum, OffsetRegShifted,<br>- ShiftType, ShiftAmount, Preindexed,<br>- Postindexed, Negative, Writeback,<br>- S, E));<br>+ Operands.push_back(ARMOperand::CreateMem(AddrMode, BaseRegNum, OffsetIsReg,<br>+ Offset, OffsetRegNum, OffsetRegShifted,<br>+ ShiftType, ShiftAmount, Preindexed,<br>+ Postindexed, Negative, Writeback, S, E));<br> if (WBOp)<br> Operands.push_back(WBOp);<br><br><br>Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp?rev=128632&r1=128631&r2=128632&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp?rev=128632&r1=128631&r2=128632&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp (original)<br>+++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp Thu Mar 31 09:52:28 2011<br>@@ -643,8 +643,11 @@<br> if (PW) {<br> MI.addOperand(MCOperand::CreateReg(0));<br> ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;<br>+ const TargetInstrDesc &TID = ARMInsts[Opcode];<br>+ unsigned IndexMode =<br>+ (TID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;<br> unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, slice(insn, 7, 0) << 2,<br>- ARM_AM::no_shift);<br>+ ARM_AM::no_shift, IndexMode);<br> MI.addOperand(MCOperand::CreateImm(Offset));<br> OpIdx = 5;<br> } else {<br>@@ -1073,6 +1076,8 @@<br> return false;<br><br> ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;<br>+ unsigned IndexMode =<br>+ (TID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;<br> if (getIBit(insn) == 0) {<br> // For pre- and post-indexed case, add a reg0 operand (Addressing Mode #2).<br> // Otherwise, skip the reg operand since for addrmode_imm12, Rn has already<br>@@ -1084,7 +1089,8 @@<br><br> // Disassemble the 12-bit immediate offset.<br> unsigned Imm12 = slice(insn, 11, 0);<br>- unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, Imm12, ARM_AM::no_shift);<br>+ unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, Imm12, ARM_AM::no_shift,<br>+ IndexMode);<br> MI.addOperand(MCOperand::CreateImm(Offset));<br> OpIdx += 1;<br> } else {<br>@@ -1099,7 +1105,7 @@<br> // A8.4.1. Possible rrx or shift amount of 32...<br> getImmShiftSE(ShOp, ShImm);<br> MI.addOperand(MCOperand::CreateImm(<br>- ARM_AM::getAM2Opc(AddrOpcode, ShImm, ShOp)));<br>+ ARM_AM::getAM2Opc(AddrOpcode, ShImm, ShOp, IndexMode)));<br> OpIdx += 2;<br> }<br><br><br>Modified: llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp?rev=128632&r1=128631&r2=128632&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp?rev=128632&r1=128631&r2=128632&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp (original)<br>+++ llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp Thu Mar 31 09:52:28 2011<br>@@ -181,18 +181,12 @@<br> }<br> }<br><br>-<br>-void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,<br>- raw_ostream &O) {<br>+void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,<br>+ raw_ostream &O) {<br> const MCOperand &MO1 = MI->getOperand(Op);<br> const MCOperand &MO2 = MI->getOperand(Op+1);<br> const MCOperand &MO3 = MI->getOperand(Op+2);<br><br>- if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.<br>- printOperand(MI, Op, O);<br>- return;<br>- }<br>-<br> O << "[" << getRegisterName(MO1.getReg());<br><br> if (!MO2.getReg()) {<br>@@ -215,6 +209,50 @@<br> O << "]";<br> }<br><br>+void ARMInstPrinter::printAM2PostIndexOp(const MCInst *MI, unsigned Op,<br>+ raw_ostream &O) {<br>+ const MCOperand &MO1 = MI->getOperand(Op);<br>+ const MCOperand &MO2 = MI->getOperand(Op+1);<br>+ const MCOperand &MO3 = MI->getOperand(Op+2);<br>+<br>+ O << "[" << getRegisterName(MO1.getReg()) << "], ";<br>+<br>+ if (!MO2.getReg()) {<br>+ unsigned ImmOffs = ARM_AM::getAM2Offset(MO3.getImm());<br>+ O << '#'<br>+ << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))<br>+ << ImmOffs;<br>+ return;<br>+ }<br>+<br>+ O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))<br>+ << getRegisterName(MO2.getReg());<br>+<br>+ if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))<br>+ O << ", "<br>+ << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))<br>+ << " #" << ShImm;<br>+}<br>+<br>+void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,<br>+ raw_ostream &O) {<br>+ const MCOperand &MO1 = MI->getOperand(Op);<br>+<br>+ if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.<br>+ printOperand(MI, Op, O);<br>+ return;<br>+ }<br>+<br>+ const MCOperand &MO3 = MI->getOperand(Op+2);<br>+ unsigned IdxMode = ARM_AM::getAM2IdxMode(MO3.getImm());<br>+<br>+ if (IdxMode == ARMII::IndexModePost) {<br>+ printAM2PostIndexOp(MI, Op, O);<br>+ return;<br>+ }<br>+ printAM2PreOrOffsetIndexOp(MI, Op, O);<br>+}<br>+<br> void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,<br> unsigned OpNum,<br> raw_ostream &O) {<br><br>Modified: llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.h?rev=128632&r1=128631&r2=128632&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.h?rev=128632&r1=128631&r2=128632&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.h (original)<br>+++ llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.h Thu Mar 31 09:52:28 2011<br>@@ -42,7 +42,11 @@<br> void printSOImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);<br><br> void printSORegOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);<br>+<br> void printAddrMode2Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);<br>+ void printAM2PostIndexOp(const MCInst *MI, unsigned OpNum, raw_ostream &O);<br>+ void printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned OpNum,<br>+ raw_ostream &O);<br> void printAddrMode2OffsetOperand(const MCInst *MI, unsigned OpNum,<br> raw_ostream &O);<br> void printAddrMode3Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);<br><br>Added: llvm/trunk/test/MC/ARM/arm_addrmode2.s<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/arm_addrmode2.s?rev=128632&view=auto">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/arm_addrmode2.s?rev=128632&view=auto</a><br>==============================================================================<br>--- llvm/trunk/test/MC/ARM/arm_addrmode2.s (added)<br>+++ llvm/trunk/test/MC/ARM/arm_addrmode2.s Thu Mar 31 09:52:28 2011<br>@@ -0,0 +1,38 @@<br>+@ RUN: llvm-mc -mcpu=cortex-a8 -triple arm-unknown-unknown -show-encoding %s | FileCheck %s<br>+<br>+@ Post-indexed<br>+@ CHECK: ldrt r1, [r0], r2 @ encoding: [0x02,0x10,0xb0,0xe6]<br>+@ CHECK: ldrt r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0xb0,0xe6]<br>+@ CHECK: ldrt r1, [r0], #4 @ encoding: [0x04,0x10,0xb0,0xe4]<br>+@ CHECK: ldrbt r1, [r0], r2 @ encoding: [0x02,0x10,0xf0,0xe6]<br>+@ CHECK: ldrbt r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0xf0,0xe6]<br>+@ CHECK: ldrbt r1, [r0], #4 @ encoding: [0x04,0x10,0xf0,0xe4]<br>+@ CHECK: strt r1, [r0], r2 @ encoding: [0x02,0x10,0xa0,0xe6]<br>+@ CHECK: strt r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0xa0,0xe6]<br>+@ CHECK: strt r1, [r0], #4 @ encoding: [0x04,0x10,0xa0,0xe4]<br>+@ CHECK: strbt r1, [r0], r2 @ encoding: [0x02,0x10,0xe0,0xe6]<br>+@ CHECK: strbt r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0xe0,0xe6]<br>+@ CHECK: strbt r1, [r0], #4 @ encoding: [0x04,0x10,0xe0,0xe4]<br>+@ CHECK: ldr r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0x90,0xe6]<br>+@ CHECK: ldrb r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0xd0,0xe6]<br>+ ldrt r1, [r0], r2<br>+ ldrt r1, [r0], r2, lsr #3<br>+ ldrt r1, [r0], #4<br>+ ldrbt r1, [r0], r2<br>+ ldrbt r1, [r0], r2, lsr #3<br>+ ldrbt r1, [r0], #4<br>+ strt r1, [r0], r2<br>+ strt r1, [r0], r2, lsr #3<br>+ strt r1, [r0], #4<br>+ strbt r1, [r0], r2<br>+ strbt r1, [r0], r2, lsr #3<br>+ strbt r1, [r0], #4<br>+ ldr r1, [r0], r2, lsr #3<br>+ ldrb r1, [r0], r2, lsr #3<br>+<br>+@ Pre-indexed<br>+@ CHECK: ldr r1, [r0, r2, lsr #3]! @ encoding: [0xa2,0x11,0xb0,0xe7]<br>+@ CHECK: ldrb r1, [r0, r2, lsr #3]! @ encoding: [0xa2,0x11,0xf0,0xe7]<br>+ ldr r1, [r0, r2, lsr #3]!<br>+ ldrb r1, [r0, r2, lsr #3]!<br>+<br><br><br>_______________________________________________<br>llvm-commits mailing list<br><a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits<br></div></blockquote></div><br></div></body></html>