From 2bd0118472de352745a2e038245fab4974f7c87e Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Tue, 11 Oct 2011 21:55:36 +0000 Subject: [PATCH] ARM assembly parsing and encoding for LDC{2}{L}/STC{2}{L} instructions. Fill out the rest of the encoding information, update to properly mark the LDC/STC instructions as predicable while the LDC2/STC2 instructions are not, and adjust the parser accordingly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141721 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrInfo.td | 181 ++++++++++++++-------- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 26 +++- test/MC/ARM/basic-arm-instructions.s | 81 ++++++++++ 3 files changed, 222 insertions(+), 66 deletions(-) diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index a89a5898eba..d43da911e22 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -651,8 +651,10 @@ def postidx_imm8 : Operand { // 9 bit value: // {8} 1 is imm8 is non-negative. 0 otherwise. // {7-0} [0,255] imm8 value, scaled by 4. +def PostIdxImm8s4AsmOperand : AsmOperandClass { let Name = "PostIdxImm8s4"; } def postidx_imm8s4 : Operand { let PrintMethod = "printPostIdxImm8s4Operand"; + let ParserMatchClass = PostIdxImm8s4AsmOperand; let MIOperandInfo = (ops i32imm); } @@ -4246,117 +4248,168 @@ def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1, class ACI - : InoP { + : I { let Inst{27-25} = 0b110; } - -multiclass LdStCop op31_28, bit load, dag ops, string opc, string cond>{ - def _OFFSET : ACI<(outs), - !con((ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), ops), - !strconcat(opc, cond), "\t$cop, $CRd, $addr"> { - let Inst{31-28} = op31_28; +class ACInoP + : InoP { + let Inst{31-28} = 0b1111; + let Inst{27-25} = 0b110; +} +multiclass LdStCop { + def _OFFSET : ACI<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), + asm, "\t$cop, $CRd, $addr"> { + bits<13> addr; + bits<4> cop; + bits<4> CRd; let Inst{24} = 1; // P = 1 + let Inst{23} = addr{8}; + let Inst{22} = Dbit; let Inst{21} = 0; // W = 0 - let Inst{22} = 0; // D = 0 let Inst{20} = load; + let Inst{19-16} = addr{12-9}; + let Inst{15-12} = CRd; + let Inst{11-8} = cop; + let Inst{7-0} = addr{7-0}; let DecoderMethod = "DecodeCopMemInstruction"; } - - def _PRE : ACI<(outs), - !con((ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), ops), - !strconcat(opc, cond), "\t$cop, $CRd, $addr!", IndexModePre> { - let Inst{31-28} = op31_28; + def _PRE : ACI<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), + asm, "\t$cop, $CRd, $addr!", IndexModePre> { + bits<13> addr; + bits<4> cop; + bits<4> CRd; let Inst{24} = 1; // P = 1 + let Inst{23} = addr{8}; + let Inst{22} = Dbit; let Inst{21} = 1; // W = 1 - let Inst{22} = 0; // D = 0 let Inst{20} = load; + let Inst{19-16} = addr{12-9}; + let Inst{15-12} = CRd; + let Inst{11-8} = cop; + let Inst{7-0} = addr{7-0}; let DecoderMethod = "DecodeCopMemInstruction"; } - - def _POST : ACI<(outs), - !con((ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr, - postidx_imm8s4:$offset), ops), - !strconcat(opc, cond), "\t$cop, $CRd, $addr, $offset", - IndexModePost> { - let Inst{31-28} = op31_28; + def _POST: ACI<(outs), (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr, + postidx_imm8s4:$offset), + asm, "\t$cop, $CRd, $addr, $offset", IndexModePost> { + bits<9> offset; + bits<4> addr; + bits<4> cop; + bits<4> CRd; let Inst{24} = 0; // P = 0 + let Inst{23} = offset{8}; + let Inst{22} = Dbit; let Inst{21} = 1; // W = 1 - let Inst{22} = 0; // D = 0 let Inst{20} = load; + let Inst{19-16} = addr; + let Inst{15-12} = CRd; + let Inst{11-8} = cop; + let Inst{7-0} = offset{7-0}; let DecoderMethod = "DecodeCopMemInstruction"; } - def _OPTION : ACI<(outs), - !con((ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$base, - nohash_imm:$option), - ops), - !strconcat(opc, cond), "\t$cop, $CRd, $base, \\{$option\\}"> { - let Inst{31-28} = op31_28; + (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr, + nohash_imm:$option), + asm, "\t$cop, $CRd, $addr, \\{$option\\}"> { + bits<8> option; + bits<4> addr; + bits<4> cop; + bits<4> CRd; let Inst{24} = 0; // P = 0 let Inst{23} = 1; // U = 1 + let Inst{22} = Dbit; let Inst{21} = 0; // W = 0 - let Inst{22} = 0; // D = 0 let Inst{20} = load; + let Inst{19-16} = addr; + let Inst{15-12} = CRd; + let Inst{11-8} = cop; + let Inst{7-0} = option; let DecoderMethod = "DecodeCopMemInstruction"; } - - def L_OFFSET : ACI<(outs), - !con((ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), ops), - !strconcat(!strconcat(opc, "l"), cond), "\t$cop, $CRd, $addr"> { - let Inst{31-28} = op31_28; +} +multiclass LdSt2Cop { + def _OFFSET : ACInoP<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), + asm, "\t$cop, $CRd, $addr"> { + bits<13> addr; + bits<4> cop; + bits<4> CRd; let Inst{24} = 1; // P = 1 + let Inst{23} = addr{8}; + let Inst{22} = Dbit; let Inst{21} = 0; // W = 0 - let Inst{22} = 1; // D = 1 let Inst{20} = load; + let Inst{19-16} = addr{12-9}; + let Inst{15-12} = CRd; + let Inst{11-8} = cop; + let Inst{7-0} = addr{7-0}; let DecoderMethod = "DecodeCopMemInstruction"; } - - def L_PRE : ACI<(outs), - !con((ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), ops), - !strconcat(!strconcat(opc, "l"), cond), "\t$cop, $CRd, $addr!", - IndexModePre> { - let Inst{31-28} = op31_28; + def _PRE : ACInoP<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), + asm, "\t$cop, $CRd, $addr!", IndexModePre> { + bits<13> addr; + bits<4> cop; + bits<4> CRd; let Inst{24} = 1; // P = 1 + let Inst{23} = addr{8}; + let Inst{22} = Dbit; let Inst{21} = 1; // W = 1 - let Inst{22} = 1; // D = 1 let Inst{20} = load; + let Inst{19-16} = addr{12-9}; + let Inst{15-12} = CRd; + let Inst{11-8} = cop; + let Inst{7-0} = addr{7-0}; let DecoderMethod = "DecodeCopMemInstruction"; } - - def L_POST : ACI<(outs), - !con((ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr, - postidx_imm8s4:$offset), ops), - !strconcat(!strconcat(opc, "l"), cond), "\t$cop, $CRd, $addr, $offset", - IndexModePost> { - let Inst{31-28} = op31_28; + def _POST: ACInoP<(outs), (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr, + postidx_imm8s4:$offset), + asm, "\t$cop, $CRd, $addr, $offset", IndexModePost> { + bits<9> offset; + bits<4> addr; + bits<4> cop; + bits<4> CRd; let Inst{24} = 0; // P = 0 + let Inst{23} = offset{8}; + let Inst{22} = Dbit; let Inst{21} = 1; // W = 1 - let Inst{22} = 1; // D = 1 let Inst{20} = load; + let Inst{19-16} = addr; + let Inst{15-12} = CRd; + let Inst{11-8} = cop; + let Inst{7-0} = offset{7-0}; let DecoderMethod = "DecodeCopMemInstruction"; } - - def L_OPTION : ACI<(outs), - !con((ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$base, - nohash_imm:$option), - ops), - !strconcat(!strconcat(opc, "l"), cond), - "\t$cop, $CRd, $base, \\{$option\\}"> { - let Inst{31-28} = op31_28; + def _OPTION : ACInoP<(outs), + (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr, + nohash_imm:$option), + asm, "\t$cop, $CRd, $addr, \\{$option\\}"> { + bits<8> option; + bits<4> addr; + bits<4> cop; + bits<4> CRd; let Inst{24} = 0; // P = 0 let Inst{23} = 1; // U = 1 + let Inst{22} = Dbit; let Inst{21} = 0; // W = 0 - let Inst{22} = 1; // D = 1 let Inst{20} = load; + let Inst{19-16} = addr; + let Inst{15-12} = CRd; + let Inst{11-8} = cop; + let Inst{7-0} = option; let DecoderMethod = "DecodeCopMemInstruction"; } } -defm LDC : LdStCop<{?,?,?,?}, 1, (ins pred:$p), "ldc", "${p}">; -defm LDC2 : LdStCop<0b1111, 1, (ins), "ldc2", "">; -defm STC : LdStCop<{?,?,?,?}, 0, (ins pred:$p), "stc", "${p}">; -defm STC2 : LdStCop<0b1111, 0, (ins), "stc2", "">; +defm LDC : LdStCop <1, 0, "ldc">; +defm LDCL : LdStCop <1, 1, "ldcl">; +defm STC : LdStCop <0, 0, "stc">; +defm STCL : LdStCop <0, 1, "stcl">; +defm LDC2 : LdSt2Cop<1, 0, "ldc2">; +defm LDC2L : LdSt2Cop<1, 1, "ldc2l">; +defm STC2 : LdSt2Cop<0, 0, "stc2">; +defm STC2L : LdSt2Cop<0, 1, "stc2l">; //===----------------------------------------------------------------------===// // Move between coprocessor and ARM core register. diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index bdebc76a9b1..afb6e5684dd 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -874,6 +874,15 @@ public: int64_t Val = CE->getValue(); return (Val > -256 && Val < 256) || (Val == INT32_MIN); } + bool isPostIdxImm8s4() const { + if (Kind != k_Immediate) + return false; + const MCConstantExpr *CE = dyn_cast(getImm()); + if (!CE) return false; + int64_t Val = CE->getValue(); + return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) || + (Val == INT32_MIN); + } bool isMSRMask() const { return Kind == k_MSRMask; } bool isProcIFlags() const { return Kind == k_ProcIFlags; } @@ -1356,6 +1365,18 @@ public: Inst.addOperand(MCOperand::CreateImm(Imm)); } + void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + const MCConstantExpr *CE = dyn_cast(getImm()); + assert(CE && "non-constant post-idx-imm8s4 operand!"); + int Imm = CE->getValue(); + bool isAdd = Imm >= 0; + if (Imm == INT32_MIN) Imm = 0; + // Immediate is scaled by 4. + Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8; + Inst.addOperand(MCOperand::CreateImm(Imm)); + } + void addPostIdxRegOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum)); @@ -3539,8 +3560,9 @@ getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" || (Mnemonic == "clrex" && !isThumb()) || (Mnemonic == "nop" && isThumbOne()) || - ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw") && - !isThumb()) || + ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" || + Mnemonic == "ldc2" || Mnemonic == "ldc2l" || + Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) || ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) && !isThumb()) || Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) { diff --git a/test/MC/ARM/basic-arm-instructions.s b/test/MC/ARM/basic-arm-instructions.s index 38aa1067c2d..04054e95c0e 100644 --- a/test/MC/ARM/basic-arm-instructions.s +++ b/test/MC/ARM/basic-arm-instructions.s @@ -642,6 +642,87 @@ Lforward: @ CHECK: isb sy @ encoding: [0x6f,0xf0,0x7f,0xf5] +@------------------------------------------------------------------------------ +@ LDC{L}/LDC2{L} +@------------------------------------------------------------------------------ + ldc2 p0, c8, [r1, #4] + ldc2 p1, c7, [r2] + ldc2 p2, c6, [r3, #-224] + ldc2 p3, c5, [r4, #-120]! + ldc2 p4, c4, [r5], #16 + ldc2 p5, c3, [r6], #-72 + ldc2l p6, c2, [r7, #4] + ldc2l p7, c1, [r8] + ldc2l p8, c0, [r9, #-224] + ldc2l p9, c1, [r10, #-120]! + ldc2l p10, c2, [r11], #16 + ldc2l p11, c3, [r12], #-72 + + ldc p12, c4, [r0, #4] + ldc p13, c5, [r1] + ldc p14, c6, [r2, #-224] + ldc p15, c7, [r3, #-120]! + ldc p5, c8, [r4], #16 + ldc p4, c9, [r5], #-72 + ldcl p3, c10, [r6, #4] + ldcl p2, c11, [r7] + ldcl p1, c12, [r8, #-224] + ldcl p0, c13, [r9, #-120]! + ldcl p6, c14, [r10], #16 + ldcl p7, c15, [r11], #-72 + + ldclo p12, c4, [r0, #4] + ldchi p13, c5, [r1] + ldccs p14, c6, [r2, #-224] + ldccc p15, c7, [r3, #-120]! + ldceq p5, c8, [r4], #16 + ldcgt p4, c9, [r5], #-72 + ldcllt p3, c10, [r6, #4] + ldclge p2, c11, [r7] + ldclle p1, c12, [r8, #-224] + ldclne p0, c13, [r9, #-120]! + ldcleq p6, c14, [r10], #16 + ldclhi p7, c15, [r11], #-72 + +@ CHECK: ldc2 p0, c8, [r1, #4] @ encoding: [0x01,0x80,0x91,0xfd] +@ CHECK: ldc2 p1, c7, [r2] @ encoding: [0x00,0x71,0x92,0xfd] +@ CHECK: ldc2 p2, c6, [r3, #-224] @ encoding: [0x38,0x62,0x13,0xfd] +@ CHECK: ldc2 p3, c5, [r4, #-120]! @ encoding: [0x1e,0x53,0x34,0xfd] +@ CHECK: ldc2 p4, c4, [r5], #16 @ encoding: [0x04,0x44,0xb5,0xfc] +@ CHECK: ldc2 p5, c3, [r6], #-72 @ encoding: [0x12,0x35,0x36,0xfc] +@ CHECK: ldc2l p6, c2, [r7, #4] @ encoding: [0x01,0x26,0xd7,0xfd] +@ CHECK: ldc2l p7, c1, [r8] @ encoding: [0x00,0x17,0xd8,0xfd] +@ CHECK: ldc2l p8, c0, [r9, #-224] @ encoding: [0x38,0x08,0x59,0xfd] +@ CHECK: ldc2l p9, c1, [r10, #-120]! @ encoding: [0x1e,0x19,0x7a,0xfd] +@ CHECK: ldc2l p10, c2, [r11], #16 @ encoding: [0x04,0x2a,0xfb,0xfc] +@ CHECK: ldc2l p11, c3, [r12], #-72 @ encoding: [0x12,0x3b,0x7c,0xfc] + +@ CHECK: ldc p12, c4, [r0, #4] @ encoding: [0x01,0x4c,0x90,0xed] +@ CHECK: ldc p13, c5, [r1] @ encoding: [0x00,0x5d,0x91,0xed] +@ CHECK: ldc p14, c6, [r2, #-224] @ encoding: [0x38,0x6e,0x12,0xed] +@ CHECK: ldc p15, c7, [r3, #-120]! @ encoding: [0x1e,0x7f,0x33,0xed] +@ CHECK: ldc p5, c8, [r4], #16 @ encoding: [0x04,0x85,0xb4,0xec] +@ CHECK: ldc p4, c9, [r5], #-72 @ encoding: [0x12,0x94,0x35,0xec] +@ CHECK: ldcl p3, c10, [r6, #4] @ encoding: [0x01,0xa3,0xd6,0xed] +@ CHECK: ldcl p2, c11, [r7] @ encoding: [0x00,0xb2,0xd7,0xed] +@ CHECK: ldcl p1, c12, [r8, #-224] @ encoding: [0x38,0xc1,0x58,0xed] +@ CHECK: ldcl p0, c13, [r9, #-120]! @ encoding: [0x1e,0xd0,0x79,0xed] +@ CHECK: ldcl p6, c14, [r10], #16 @ encoding: [0x04,0xe6,0xfa,0xec] +@ CHECK: ldcl p7, c15, [r11], #-72 @ encoding: [0x12,0xf7,0x7b,0xec] + +@ CHECK: ldclo p12, c4, [r0, #4] @ encoding: [0x01,0x4c,0x90,0x3d] +@ CHECK: ldchi p13, c5, [r1] @ encoding: [0x00,0x5d,0x91,0x8d] +@ CHECK: ldchs p14, c6, [r2, #-224] @ encoding: [0x38,0x6e,0x12,0x2d] +@ CHECK: ldclo p15, c7, [r3, #-120]! @ encoding: [0x1e,0x7f,0x33,0x3d] +@ CHECK: ldceq p5, c8, [r4], #16 @ encoding: [0x04,0x85,0xb4,0x0c] +@ CHECK: ldcgt p4, c9, [r5], #-72 @ encoding: [0x12,0x94,0x35,0xcc] +@ CHECK: ldcllt p3, c10, [r6, #4] @ encoding: [0x01,0xa3,0xd6,0xbd] +@ CHECK: ldclge p2, c11, [r7] @ encoding: [0x00,0xb2,0xd7,0xad] +@ CHECK: ldclle p1, c12, [r8, #-224] @ encoding: [0x38,0xc1,0x58,0xdd] +@ CHECK: ldclne p0, c13, [r9, #-120]! @ encoding: [0x1e,0xd0,0x79,0x1d] +@ CHECK: ldcleq p6, c14, [r10], #16 @ encoding: [0x04,0xe6,0xfa,0x0c] +@ CHECK: ldclhi p7, c15, [r11], #-72 @ encoding: [0x12,0xf7,0x7b,0x8c] + @------------------------------------------------------------------------------ @ LDM*