Index: lib/Target/ARM/ARMInstrInfo.td =================================================================== --- lib/Target/ARM/ARMInstrInfo.td +++ lib/Target/ARM/ARMInstrInfo.td @@ -603,7 +603,11 @@ } // shifter_operand operands: so_reg_reg, so_reg_imm, and mod_imm. -def ShiftedRegAsmOperand : AsmOperandClass { let Name = "RegShiftedReg"; } +def ShiftedRegAsmOperand : AsmOperandClass { + let Name = "RegShiftedReg"; + let DiagnosticString = "shifted register operand must use two registers in " + "the range [r0, r15]"; +} def so_reg_reg : Operand, // reg reg imm ComplexPattern { @@ -614,7 +618,10 @@ let MIOperandInfo = (ops GPRnopc, GPRnopc, i32imm); } -def ShiftedImmAsmOperand : AsmOperandClass { let Name = "RegShiftedImm"; } +def ShiftedImmAsmOperand : AsmOperandClass { + let Name = "RegShiftedImm"; + let DiagnosticString = "shifted register operand must be in the range [r0, r15]"; +} def so_reg_imm : Operand, // reg imm ComplexPattern { @@ -898,7 +905,12 @@ // Define ARM specific addressing modes. // addrmode_imm12 := reg +/- imm12 // -def MemImm12OffsetAsmOperand : AsmOperandClass { let Name = "MemImm12Offset"; } +def MemImm12OffsetAsmOperand : AsmOperandClass { + let Name = "MemImm12Offset"; + let DiagnosticString = "operand must be a memory reference with base " + "register in the range [r0, r15], and immediate " + "offset in the range [-4095, 4095]"; +} class AddrMode_Imm12 : MemOperand, ComplexPattern { // 12-bit immediate operand. Note that instructions using this encode @@ -921,7 +933,12 @@ // ldst_so_reg := reg +/- reg shop imm // -def MemRegOffsetAsmOperand : AsmOperandClass { let Name = "MemRegOffset"; } +def MemRegOffsetAsmOperand : AsmOperandClass { + let Name = "MemRegOffset"; + let DiagnosticString = "operand must be a memory reference with base and " + "index registers in the range [r0, r15], and an " + "optional shift"; +} def ldst_so_reg : MemOperand, ComplexPattern { let EncoderMethod = "getLdStSORegOpValue"; @@ -962,6 +979,8 @@ def PostIdxRegAsmOperand : AsmOperandClass { let Name = "PostIdxReg"; let ParserMethod = "parsePostIdxReg"; + let DiagnosticString = "post-index register operand must in be in " + "the range [r0, r15]"; } def postidx_reg : MemOperand { let EncoderMethod = "getPostIdxRegOpValue"; @@ -974,6 +993,8 @@ def PostIdxRegShiftedAsmOperand : AsmOperandClass { let Name = "PostIdxRegShifted"; let ParserMethod = "parsePostIdxReg"; + let DiagnosticString = "post-index register operand must in be in " + "the range [r0, r15]"; } def am2offset_reg : MemOperand, ComplexPattern { let EncoderMethod = "getAddrMode3OpValue"; @@ -1025,6 +1052,8 @@ def AM3OffsetAsmOperand : AsmOperandClass { let Name = "AM3Offset"; let ParserMethod = "parseAM3Offset"; + let DiagnosticString = "post-index register operand must in be in " + "the range [r0, r15]"; } def am3offset : MemOperand, ComplexPattern { let EncoderMethod = "getAddrMode5OpValue"; @@ -1063,7 +1097,12 @@ // addrmode5fp16 := reg +/- imm8*2 // -def AddrMode5FP16AsmOperand : AsmOperandClass { let Name = "AddrMode5FP16"; } +def AddrMode5FP16AsmOperand : AsmOperandClass { + let Name = "AddrMode5FP16"; + let DiagnosticString = "operand must be a memory reference using a register " + "in range [r0, r15] and an immediate in " + "range [-510, 510] and a multiple of 2"; +} class AddrMode5FP16 : Operand, ComplexPattern { let EncoderMethod = "getAddrMode5FP16OpValue"; @@ -1119,7 +1158,9 @@ // VLD/VST instructions and checking the alignment is not specified. def AddrMode6AlignNoneAsmOperand : AsmOperandClass { let Name = "AlignedMemoryNone"; - let DiagnosticString = "alignment must be omitted"; + let DiagnosticString = "operand must be a memory reference using a register " + "in the range [r0, r15], and alignment must be " + "omitted"; } def addrmode6alignNone : AddrMode6Align { // The alignment specifier can only be omitted. @@ -1130,7 +1171,9 @@ // VLD/VST instructions and checking the alignment value. def AddrMode6Align16AsmOperand : AsmOperandClass { let Name = "AlignedMemory16"; - let DiagnosticString = "alignment must be 16 or omitted"; + let DiagnosticString = "operand must be a memory reference using a register " + "in the range [r0, r15], and alignment must be " + "16 or omitted"; } def addrmode6align16 : AddrMode6Align { // The alignment specifier can only be 16 or omitted. @@ -1141,7 +1184,9 @@ // VLD/VST instructions and checking the alignment value. def AddrMode6Align32AsmOperand : AsmOperandClass { let Name = "AlignedMemory32"; - let DiagnosticString = "alignment must be 32 or omitted"; + let DiagnosticString = "operand must be a memory reference using a register " + "in the range [r0, r15], and alignment must be " + "32 or omitted"; } def addrmode6align32 : AddrMode6Align { // The alignment specifier can only be 32 or omitted. @@ -1152,7 +1197,9 @@ // VLD/VST instructions and checking the alignment value. def AddrMode6Align64AsmOperand : AsmOperandClass { let Name = "AlignedMemory64"; - let DiagnosticString = "alignment must be 64 or omitted"; + let DiagnosticString = "operand must be a memory reference using a register " + "in the range [r0, r15], and alignment must be " + "64 or omitted"; } def addrmode6align64 : AddrMode6Align { // The alignment specifier can only be 64 or omitted. @@ -1163,7 +1210,9 @@ // for VLD/VST instructions and checking the alignment value. def AddrMode6Align64or128AsmOperand : AsmOperandClass { let Name = "AlignedMemory64or128"; - let DiagnosticString = "alignment must be 64, 128 or omitted"; + let DiagnosticString = "operand must be a memory reference using a register " + "in the range [r0, r15], and alignment must be " + "64, 128 or omitted"; } def addrmode6align64or128 : AddrMode6Align { // The alignment specifier can only be 64, 128 or omitted. @@ -1174,7 +1223,9 @@ // encoding for VLD/VST instructions and checking the alignment value. def AddrMode6Align64or128or256AsmOperand : AsmOperandClass { let Name = "AlignedMemory64or128or256"; - let DiagnosticString = "alignment must be 64, 128, 256 or omitted"; + let DiagnosticString = "operand must be a memory reference using a register " + "in the range [r0, r15], and alignment must be " + "64, 128, 256 or omitted"; } def addrmode6align64or128or256 : AddrMode6Align { // The alignment specifier can only be 64, 128, 256 or omitted. @@ -1205,7 +1256,9 @@ // VLD-dup instruction and checking the alignment is not specified. def AddrMode6dupAlignNoneAsmOperand : AsmOperandClass { let Name = "DupAlignedMemoryNone"; - let DiagnosticString = "alignment must be omitted"; + let DiagnosticString = "operand must be a memory reference using a register " + "in the range [r0, r15], and alignment must be " + "omitted"; } def addrmode6dupalignNone : AddrMode6DupAlign { // The alignment specifier can only be omitted. @@ -1216,7 +1269,9 @@ // instruction and checking the alignment value. def AddrMode6dupAlign16AsmOperand : AsmOperandClass { let Name = "DupAlignedMemory16"; - let DiagnosticString = "alignment must be 16 or omitted"; + let DiagnosticString = "operand must be a memory reference using a register " + "in the range [r0, r15], and alignment must be " + "16 or omitted"; } def addrmode6dupalign16 : AddrMode6DupAlign { // The alignment specifier can only be 16 or omitted. @@ -1227,7 +1282,9 @@ // instruction and checking the alignment value. def AddrMode6dupAlign32AsmOperand : AsmOperandClass { let Name = "DupAlignedMemory32"; - let DiagnosticString = "alignment must be 32 or omitted"; + let DiagnosticString = "operand must be a memory reference using a register " + "in the range [r0, r15], and alignment must be " + "32 or omitted"; } def addrmode6dupalign32 : AddrMode6DupAlign { // The alignment specifier can only be 32 or omitted. @@ -1238,7 +1295,9 @@ // instructions and checking the alignment value. def AddrMode6dupAlign64AsmOperand : AsmOperandClass { let Name = "DupAlignedMemory64"; - let DiagnosticString = "alignment must be 64 or omitted"; + let DiagnosticString = "operand must be a memory reference using a register " + "in the range [r0, r15], and alignment must be " + "64 or omitted"; } def addrmode6dupalign64 : AddrMode6DupAlign { // The alignment specifier can only be 64 or omitted. @@ -1249,7 +1308,9 @@ // for VLD instructions and checking the alignment value. def AddrMode6dupAlign64or128AsmOperand : AsmOperandClass { let Name = "DupAlignedMemory64or128"; - let DiagnosticString = "alignment must be 64, 128 or omitted"; + let DiagnosticString = "operand must be a memory reference using a register " + "in the range [r0, r15], and alignment must be " + "64, 128 or omitted"; } def addrmode6dupalign64or128 : AddrMode6DupAlign { // The alignment specifier can only be 64, 128 or omitted. @@ -1266,7 +1327,11 @@ // addr_offset_none := reg // -def MemNoOffsetAsmOperand : AsmOperandClass { let Name = "MemNoOffset"; } +def MemNoOffsetAsmOperand : AsmOperandClass { + let Name = "MemNoOffset"; + let DiagnosticString = "operand must be a memory reference using a register " + "in range [r0, r15], and no offset"; +} def addr_offset_none : MemOperand, ComplexPattern { let PrintMethod = "printAddrMode7Operand"; Index: lib/Target/ARM/ARMInstrThumb.td =================================================================== --- lib/Target/ARM/ARMInstrThumb.td +++ lib/Target/ARM/ARMInstrThumb.td @@ -119,6 +119,9 @@ // or relocatable expression... def ThumbMemPC : AsmOperandClass { let Name = "ThumbMemPC"; + let DiagnosticString = "operand must be a PC-relative memory reference " + "with immediate offset in the range [0, 1020] " + "and a multiple of 4"; } let OperandType = "OPERAND_PCREL" in { @@ -178,7 +181,11 @@ // t_addrmode_rr := reg + reg // -def t_addrmode_rr_asm_operand : AsmOperandClass { let Name = "MemThumbRR"; } +def t_addrmode_rr_asm_operand : AsmOperandClass { + let Name = "MemThumbRR"; + let DiagnosticString = "operand must be a memory reference with base " + "and index registers in the range [r0, r7]"; +} def t_addrmode_rr : MemOperand, ComplexPattern { let EncoderMethod = "getThumbAddrModeRegRegOpValue"; @@ -222,7 +229,12 @@ // t_addrmode_is4 := reg + imm5 * 4 // -def t_addrmode_is4_asm_operand : AsmOperandClass { let Name = "MemThumbRIs4"; } +def t_addrmode_is4_asm_operand : AsmOperandClass { + let Name = "MemThumbRIs4"; + let DiagnosticString = "operand must be a memory reference with base " + "register in range [r0, r7], and immediate " + "offset in the range [0, 124] and a multiple of 4"; +} def t_addrmode_is4 : MemOperand, ComplexPattern { let EncoderMethod = "getAddrModeISOpValue"; @@ -234,7 +246,12 @@ // t_addrmode_is2 := reg + imm5 * 2 // -def t_addrmode_is2_asm_operand : AsmOperandClass { let Name = "MemThumbRIs2"; } +def t_addrmode_is2_asm_operand : AsmOperandClass { + let Name = "MemThumbRIs2"; + let DiagnosticString = "operand must be a memory reference with base " + "register in range [r0, r7], and immediate offset " + "in the range [0, 62] and a multiple of 2"; +} def t_addrmode_is2 : MemOperand, ComplexPattern { let EncoderMethod = "getAddrModeISOpValue"; @@ -246,7 +263,12 @@ // t_addrmode_is1 := reg + imm5 // -def t_addrmode_is1_asm_operand : AsmOperandClass { let Name = "MemThumbRIs1"; } +def t_addrmode_is1_asm_operand : AsmOperandClass { + let Name = "MemThumbRIs1"; + let DiagnosticString = "operand must be a memory reference with base " + "register in range [r0, r7], and immediate offset " + "in the range [0, 31]"; +} def t_addrmode_is1 : MemOperand, ComplexPattern { let EncoderMethod = "getAddrModeISOpValue"; @@ -260,7 +282,12 @@ // // FIXME: This really shouldn't have an explicit SP operand at all. It should // be implicit, just like in the instruction encoding itself. -def t_addrmode_sp_asm_operand : AsmOperandClass { let Name = "MemThumbSPI"; } +def t_addrmode_sp_asm_operand : AsmOperandClass { + let Name = "MemThumbSPI"; + let DiagnosticString = "operand must be a memory reference with base " + "register SP, and an immediate offset in the range " + "[0, 1020] and a multiple of 4"; +} def t_addrmode_sp : MemOperand, ComplexPattern { let EncoderMethod = "getAddrModeThumbSPOpValue"; Index: lib/Target/ARM/ARMInstrThumb2.td =================================================================== --- lib/Target/ARM/ARMInstrThumb2.td +++ lib/Target/ARM/ARMInstrThumb2.td @@ -152,7 +152,12 @@ // Define Thumb2 specific addressing modes. // t2addrmode_imm12 := reg + imm12 -def t2addrmode_imm12_asmoperand : AsmOperandClass {let Name="MemUImm12Offset";} +def t2addrmode_imm12_asmoperand : AsmOperandClass { + let Name="MemUImm12Offset"; + let DiagnosticString = "operand must be a memory reference with base " + "register in the range [r0, r15], and immediate " + "offset in the range [0, 4095]"; +} def t2addrmode_imm12 : MemOperand, ComplexPattern { let PrintMethod = "printAddrModeImm12Operand"; @@ -168,7 +173,12 @@ let PrintMethod = "printThumbLdrLabelOperand"; } -def t2ldr_pcrel_imm12_asmoperand : AsmOperandClass {let Name = "MemPCRelImm12";} +def t2ldr_pcrel_imm12_asmoperand : AsmOperandClass { + let Name = "MemPCRelImm12"; + let DiagnosticString = "operand must be a PC-relative memory reference " + "with immediate offset in the range [-4095, 4095]"; +} + def t2ldr_pcrel_imm12 : Operand { let ParserMatchClass = t2ldr_pcrel_imm12_asmoperand; // used for assembler pseudo instruction and maps to t2ldrlabel, so @@ -182,7 +192,12 @@ } // t2addrmode_posimm8 := reg + imm8 -def MemPosImm8OffsetAsmOperand : AsmOperandClass {let Name="MemPosImm8Offset";} +def MemPosImm8OffsetAsmOperand : AsmOperandClass { + let Name="MemPosImm8Offset"; + let DiagnosticString = "operand must be a memory reference with base " + "register in the range [r0, r15], and immediate " + "offset in the range [0, 255]"; +} def t2addrmode_posimm8 : MemOperand { let PrintMethod = "printT2AddrModeImm8Operand"; let EncoderMethod = "getT2AddrModeImm8OpValue"; @@ -192,7 +207,12 @@ } // t2addrmode_negimm8 := reg - imm8 -def MemNegImm8OffsetAsmOperand : AsmOperandClass {let Name="MemNegImm8Offset";} +def MemNegImm8OffsetAsmOperand : AsmOperandClass { + let Name="MemNegImm8Offset"; + let DiagnosticString = "operand must be a memory reference with base " + "register in the range [r0, r14], and immediate " + "offset in the range [-255, -1]"; +} def t2addrmode_negimm8 : MemOperand, ComplexPattern { let PrintMethod = "printT2AddrModeImm8Operand"; @@ -203,7 +223,12 @@ } // t2addrmode_imm8 := reg +/- imm8 -def MemImm8OffsetAsmOperand : AsmOperandClass { let Name = "MemImm8Offset"; } +def MemImm8OffsetAsmOperand : AsmOperandClass { + let Name = "MemImm8Offset"; + let DiagnosticString = "operand must be a memory reference with base " + "register in the range [r0, r14], and immediate " + "offset in range [-255, 255]"; +} class T2AddrMode_Imm8 : MemOperand, ComplexPattern { let EncoderMethod = "getT2AddrModeImm8OpValue"; @@ -229,7 +254,12 @@ } // t2addrmode_imm8s4 := reg +/- (imm8 << 2) -def MemImm8s4OffsetAsmOperand : AsmOperandClass {let Name = "MemImm8s4Offset";} +def MemImm8s4OffsetAsmOperand : AsmOperandClass { + let Name = "MemImm8s4Offset"; + let DiagnosticString = "operand must be a memory address with base register " + "in range [r0, r15], and immediate offset in the " + "range [-1020, 1020] and a multiple of 4"; +} class T2AddrMode_Imm8s4 : MemOperand { let EncoderMethod = "getT2AddrModeImm8s4OpValue"; let DecoderMethod = "DecodeT2AddrModeImm8s4"; @@ -255,6 +285,9 @@ // t2addrmode_imm0_1020s4 := reg + (imm8 << 2) def MemImm0_1020s4OffsetAsmOperand : AsmOperandClass { let Name = "MemImm0_1020s4Offset"; + let DiagnosticString = "operand must be a memory reference with base " + "register in the range [r0, r15], and immediate " + "offset in range [0, 1020] and a multiple of 4"; } def t2addrmode_imm0_1020s4 : MemOperand, ComplexPattern { @@ -266,7 +299,13 @@ } // t2addrmode_so_reg := reg + (reg << imm2) -def t2addrmode_so_reg_asmoperand : AsmOperandClass {let Name="T2MemRegOffset";} +def t2addrmode_so_reg_asmoperand : AsmOperandClass { + let Name="T2MemRegOffset"; + let DiagnosticString = "operand must be a memory reference with base " + "register in the range [r0, r14], index register " + "in the range [r0, r15] and left shift by " + "0, 1, 2, or 3"; +} def t2addrmode_so_reg : MemOperand, ComplexPattern { let PrintMethod = "printT2AddrModeSoRegOperand"; @@ -277,13 +316,24 @@ } // Addresses for the TBB/TBH instructions. -def addrmode_tbb_asmoperand : AsmOperandClass { let Name = "MemTBB"; } +def addrmode_tbb_asmoperand : AsmOperandClass { + let Name = "MemTBB"; + let DiagnosticString = "operand must be a memory reference with base " + "register in the range [r0, r12] or [r14, r15], " + "and index register in the range [r0, r14]"; +} def addrmode_tbb : MemOperand { let PrintMethod = "printAddrModeTBB"; let ParserMatchClass = addrmode_tbb_asmoperand; let MIOperandInfo = (ops GPR:$Rn, rGPR:$Rm); } -def addrmode_tbh_asmoperand : AsmOperandClass { let Name = "MemTBH"; } +def addrmode_tbh_asmoperand : AsmOperandClass { + let Name = "MemTBH"; + let DiagnosticString = "operand must be a memory reference with base " + "register in the range [r0, r12] or [r14, r15], " + "and index register in the range [r0, r14] shifted " + "left by 1"; +} def addrmode_tbh : MemOperand { let PrintMethod = "printAddrModeTBH"; let ParserMatchClass = addrmode_tbh_asmoperand; Index: lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -1150,10 +1150,30 @@ bool isToken() const override { return Kind == k_Token; } bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; } bool isInstSyncBarrierOpt() const { return Kind == k_InstSyncBarrierOpt; } - bool isMem() const override { return Kind == k_Memory; } + bool isMem() const override { + if (Kind != k_Memory) + return false; + if (Memory.BaseRegNum && + !ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Memory.BaseRegNum)) + return false; + if (Memory.OffsetRegNum && + !ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Memory.OffsetRegNum)) + return false; + return true; + } bool isShifterImm() const { return Kind == k_ShifterImmediate; } - bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; } - bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; } + bool isRegShiftedReg() const { + return Kind == k_ShiftedRegister && + ARMMCRegisterClasses[ARM::GPRRegClassID].contains( + RegShiftedReg.SrcReg) && + ARMMCRegisterClasses[ARM::GPRRegClassID].contains( + RegShiftedReg.ShiftReg); + } + bool isRegShiftedImm() const { + return Kind == k_ShiftedImmediate && + ARMMCRegisterClasses[ARM::GPRRegClassID].contains( + RegShiftedImm.SrcReg); + } bool isRotImm() const { return Kind == k_RotateImmediate; } bool isModImm() const { return Kind == k_ModifiedImmediate; } @@ -1192,9 +1212,12 @@ bool isConstantPoolImm() const { return Kind == k_ConstantPoolImmediate; } bool isBitfield() const { return Kind == k_BitfieldDescriptor; } - bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; } + bool isPostIdxRegShifted() const { + return Kind == k_PostIndexRegister && + ARMMCRegisterClasses[ARM::GPRRegClassID].contains(PostIdxReg.RegNum); + } bool isPostIdxReg() const { - return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift; + return isPostIdxRegShifted() && PostIdxReg.ShiftTy == ARM_AM::no_shift; } bool isMemNoOffset(bool alignOK = false, unsigned Alignment = 0) const { if (!isMem()) @@ -1331,10 +1354,10 @@ } bool isAM3Offset() const { - if (Kind != k_Immediate && Kind != k_PostIndexRegister) + if (isPostIdxReg()) + return true; + if (!isImm()) return false; - if (Kind == k_PostIndexRegister) - return PostIdxReg.ShiftTy == ARM_AM::no_shift; // Immediate offset in range [-255, 255]. const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; @@ -1380,6 +1403,8 @@ if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative || Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0) return false; + if (Memory.BaseRegNum == ARM::SP || Memory.OffsetRegNum == ARM::PC) + return false; return true; } @@ -1388,6 +1413,8 @@ Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 || Memory.Alignment != 0 ) return false; + if (Memory.BaseRegNum == ARM::SP || Memory.OffsetRegNum == ARM::PC) + return false; return true; } Index: test/MC/ARM/arm-reg-addr-errors.s =================================================================== --- /dev/null +++ test/MC/ARM/arm-reg-addr-errors.s @@ -0,0 +1,60 @@ +@ RUN: not llvm-mc -triple=armv7a-eabi -mattr=+fullfp16 < %s 2>&1 | FileCheck %s + +add r3, r0, r1, lsl s6 +@ CHECK: [[@LINE-1]]:17: note: shifted register operand must use two registers in the range [r0, r15] +add r3, r0, r1, lsl d6 +@ CHECK: [[@LINE-1]]:17: note: shifted register operand must use two registers in the range [r0, r15] +add r3, r0, r1, lsl q6 +@ CHECK: [[@LINE-1]]:17: note: shifted register operand must use two registers in the range [r0, r15] +add r3, r0, r1, lsl cpsr +@ CHECK: [[@LINE-1]]:17: note: shifted register operand must use two registers in the range [r0, r15] +add r3, r0, s1, lsl #2 +@ CHECK: [[@LINE-1]]:17: note: shifted register operand must be in the range [r0, r15] +add r3, r0, d1, lsl #2 +@ CHECK: [[@LINE-1]]:17: note: shifted register operand must be in the range [r0, r15] +add r3, r0, q1, lsl #2 +@ CHECK: [[@LINE-1]]:17: note: shifted register operand must be in the range [r0, r15] +add r3, r0, cpsr, lsl #2 +@ CHECK: [[@LINE-1]]:19: note: shifted register operand must be in the range [r0, r15] +ldr r0, [s1, #-4095] +@ CHECK: [[@LINE-1]]:9: note: operand must be a memory reference with base register in the range [r0, r15], and immediate offset in the range [-4095, 4095] +ldr r4, [s1, r2, lsl #2] +@ CHECK: [[@LINE-1]]:9: note: operand must be a memory reference with base and index registers in the range [r0, r15], and an optional shift +ldr r4, [r1, s2, lsl #2] +@ CHECK: [[@LINE-1]]:9: note: operand must be a memory reference with base and index registers in the range [r0, r15], and an optional shift +ldrht r0, [r1], s0 +@ CHECK: [[@LINE-1]]:17: note: post-index register operand must in be in the range [r0, r15] +ldr r0, [r1], s2, lsl #3 +@ CHECK: [[@LINE-1]]:15: note: post-index register operand must in be in the range [r0, r15] +ldrd r2, r3, [s4] +@ CHECK: [[@LINE-1]]:14: error: operand must be a memory reference using a register in range [r0, r15], and an offset register in range [r0, r15] or an immediate offset in range [-255, 255] +ldrd r2, r3, [r4], s5 +@ CHECK: [[@LINE-1]]:20: note: post-index register operand must in be in the range [r0, r15] +ldc p0, cr2, [s1, #4] +@ CHECK: [[@LINE-1]]:14: error: operand must be a memory reference using a register in range [r0, r15], and an immediate offset in range [0, 1020] and a multiple of 4 +vldr.16 s1, [s7, #4] +@ CHECK: [[@LINE-1]]:13: error: operand must be a memory reference using a register in range [r0, r15] and an immediate in range [-510, 510] and a multiple of 2 +vld1.8 {d1[0]}, [q5:16] +@ CHECK: [[@LINE-1]]:17: error: operand must be a memory reference using a register in the range [r0, r15], and alignment must be omitted +vld1.16 {d1[0]}, [q5:16] +@ CHECK: [[@LINE-1]]:18: error: operand must be a memory reference using a register in the range [r0, r15], and alignment must be 16 or omitted +vld1.32 {d1[0]}, [s5:32] +@ CHECK: [[@LINE-1]]:18: error: operand must be a memory reference using a register in the range [r0, r15], and alignment must be 32 or omitted +vld1.64 {d2}, [s7:64] +@ CHECK: [[@LINE-1]]:15: error: operand must be a memory reference using a register in the range [r0, r15], and alignment must be 64 or omitted +vld4.32 {d1[1], d2[1], d3[1], d4[1]}, [s0:128] +@ CHECK: [[@LINE-1]]:39: error: operand must be a memory reference using a register in the range [r0, r15], and alignment must be 64, 128 or omitted +vld4.32 {d1, d2, d3, d4}, [s0:256] +@ CHECK: [[@LINE-1]]:27: error: operand must be a memory reference using a register in the range [r0, r15], and alignment must be 64, 128, 256 or omitted +vld1.8 {d0[], d1[]}, [s0] +@ CHECK: [[@LINE-1]]:22: error: operand must be a memory reference using a register in the range [r0, r15], and alignment must be omitted +vld1.16 {d0[]}, [s7:16] +@ CHECK: [[@LINE-1]]:17: error: operand must be a memory reference using a register in the range [r0, r15], and alignment must be 16 or omitted +vld1.32 {d0[]}, [d7:32] +@CHECK: [[@LINE-1]]:17: error: operand must be a memory reference using a register in the range [r0, r15], and alignment must be 32 or omitted +vld2.32 {d0[], d1[]}, [s7:64] +@CHECK: [[@LINE-1]]:23: error: operand must be a memory reference using a register in the range [r0, r15], and alignment must be 64 or omitted +vld4.32 {d0[], d1[], d2[], d3[]}, [s7:64] +@CHECK: [[@LINE-1]]:35: error: operand must be a memory reference using a register in the range [r0, r15], and alignment must be 64, 128 or omitted +ldc p0, cr2, [s1], #4 +@CHECK: [[@LINE-1]]:14: error: operand must be a memory reference using a register in range [r0, r15], and no offset Index: test/MC/ARM/ldrd-strd-gnu-arm-bad-imm.s =================================================================== --- test/MC/ARM/ldrd-strd-gnu-arm-bad-imm.s +++ test/MC/ARM/ldrd-strd-gnu-arm-bad-imm.s @@ -2,12 +2,12 @@ .text @ CHECK: error: invalid instruction, any one of the following would fix this: @ CHECK: ldrd r0, [r0, #512] -@ CHECK: note: invalid operand for instruction +@ CHECK: note: operand must be a memory reference using a register in range [r0, r15], and an offset register in range [r0, r15] or an immediate offset in range [-255, 255] @ CHECK: note: instruction requires: thumb2 ldrd r0, [r0, #512] @ CHECK: error: invalid instruction, any one of the following would fix this: @ CHECK: strd r0, [r0, #512] -@ CHECK: note: invalid operand for instruction +@ CHECK: note: operand must be a memory reference using a register in range [r0, r15], and an offset register in range [r0, r15] or an immediate offset in range [-255, 255] @ CHECK: note: instruction requires: thumb2 strd r0, [r0, #512] Index: test/MC/ARM/thumb-diagnostics.s =================================================================== --- test/MC/ARM/thumb-diagnostics.s +++ test/MC/ARM/thumb-diagnostics.s @@ -211,20 +211,25 @@ @ CHECK-ERRORS: ^ @ CHECK-ERRORS: note: instruction requires: thumb2 @ CHECK-ERRORS: note: instruction requires: arm-mode -@ CHECK-ERRORS: note: invalid operand for instruction +@ CHECK-ERRORS: note: operand must be a memory reference with base register SP, and an immediate offset in the range [0, 1020] and a multiple of 4 +@ CHECK-ERRORS: note: operand must be a memory reference with base and index registers in the range [r0, r7] +@ CHECK-ERRORS: note: operand must be a memory reference with base register in range [r0, r7], and immediate offset in the range [0, 124] and a multiple of 4 @ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: @ CHECK-ERRORS: str r5, [r1, #3] @ CHECK-ERRORS: ^ @ CHECK-ERRORS: note: instruction requires: thumb2 @ CHECK-ERRORS: note: instruction requires: arm-mode -@ CHECK-ERRORS: note: invalid operand for instruction +@ CHECK-ERRORS: note: operand must be a memory reference with base register SP, and an immediate offset in the range [0, 1020] and a multiple of 4 +@ CHECK-ERRORS: note: operand must be a memory reference with base and index registers in the range [r0, r7] +@ CHECK-ERRORS: note: operand must be a memory reference with base register in range [r0, r7], and immediate offset in the range [0, 124] and a multiple of 4 @ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: @ CHECK-ERRORS: str r3, [r7, #128] @ CHECK-ERRORS: ^ @ CHECK-ERRORS: note: instruction requires: thumb2 @ CHECK-ERRORS: note: instruction requires: arm-mode -@ CHECK-ERRORS: note: invalid operand for instruction - +@ CHECK-ERRORS: note: operand must be a memory reference with base register SP, and an immediate offset in the range [0, 1020] and a multiple of 4 +@ CHECK-ERRORS: note: operand must be a memory reference with base and index registers in the range [r0, r7] +@ CHECK-ERRORS: note: operand must be a memory reference with base register in range [r0, r7], and immediate offset in the range [0, 124] and a multiple of 4 @ Out of range immediate for SVC instruction. svc #-1 svc #256 Index: test/MC/ARM/thumb-reg-addr-errors.s =================================================================== --- /dev/null +++ test/MC/ARM/thumb-reg-addr-errors.s @@ -0,0 +1,49 @@ +@ RUN: not llvm-mc -triple=thumbv7a-eabi < %s 2>&1 | FileCheck %s + +ldr r0, [s0, #48] +@CHECK: [[@LINE-1]]:9: note: operand must be a memory reference with base register SP, and an immediate offset in the range [0, 1020] and a multiple of 4 +@CHECK: [[@LINE-2]]:9: note: operand must be a PC-relative memory reference with immediate offset in the range [0, 1020] and a multiple of 4 +ldrb r0, [s7, r1] +@CHECK: [[@LINE-1]]:10: note: operand must be a memory reference with base and index registers in the range [r0, r7] +ldrb r0, [r7, s1] +@CHECK: [[@LINE-1]]:10: note: operand must be a memory reference with base and index registers in the range [r0, r7] +ldr r0, [s7, #4] +@CHECK: [[@LINE-1]]:9: note: operand must be a memory reference with base register in range [r0, r7], and immediate offset in the range [0, 124] and a multiple of 4 +ldrh r0, [s7, #6] +@CHECK: [[@LINE-1]]:10: note: operand must be a memory reference with base register in range [r0, r7], and immediate offset in the range [0, 62] and a multiple of 2 +ldrb r0, [s7, #31] +@CHECK: [[@LINE-1]]:10: note: operand must be a memory reference with base register in range [r0, r7], and immediate offset in the range [0, 31] +ldr.w r0, [s0, #2000] +@CHECK: [[@LINE-1]]:11: note: operand must be a memory reference with base register in the range [r0, r15], and immediate offset in the range [0, 4095] +ldr.w r0, [s0, #-4095] +@CHECK: [[@LINE-1]]:11: note: operand must be a PC-relative memory reference with immediate offset in the range [-4095, 4095] +ldrt r0, [s0, #255] +@CHECK: [[@LINE-1]]:10: error: operand must be a memory reference with base register in the range [r0, r15], and immediate offset in the range [0, 255] +ldr r0, [s1, #-255] +@CHECK: [[@LINE-1]]:9: note: operand must be a memory reference with base register in the range [r0, r14], and immediate offset in the range [-255, -1] +strt r0, [s2, #255] +@CHECK: [[@LINE-1]]:10: error: operand must be a memory reference with base register in the range [r0, r14], and immediate offset in range [-255, 255] +ldrd r0, r1, [s0, #-1020] +@CHECK: [[@LINE-1]]:14: error: operand must be a memory address with base register in range [r0, r15], and immediate offset in the range [-1020, 1020] and a multiple of 4 +ldrex r0, [s0, #1000] +@CHECK: [[@LINE-1]]:11: error: operand must be a memory reference with base register in the range [r0, r15], and immediate offset in range [0, 1020] and a multiple of 4 +ldr r0, [s1, r2, lsl #3] +@CHECK: [[@LINE-1]]:9: note: operand must be a memory reference with base register in the range [r0, r14], index register in the range [r0, r15] and left shift by 0, 1, 2, or 3 +ldr r0, [r1, s2, lsl #3] +@CHECK: [[@LINE-1]]:9: note: operand must be a memory reference with base register in the range [r0, r14], index register in the range [r0, r15] and left shift by 0, 1, 2, or 3 +tbb [sp, r1] +@CHECK: [[@LINE-1]]:5: error: operand must be a memory reference with base register in the range [r0, r12] or [r14, r15], and index register in the range [r0, r14] +tbb [r12, pc] +@CHECK: [[@LINE-1]]:5: error: operand must be a memory reference with base register in the range [r0, r12] or [r14, r15], and index register in the range [r0, r14] +tbb [s0, r0] +@CHECK: [[@LINE-1]]:5: error: operand must be a memory reference with base register in the range [r0, r12] or [r14, r15], and index register in the range [r0, r14] +tbb [r0, s0] +@CHECK: [[@LINE-1]]:5: error: operand must be a memory reference with base register in the range [r0, r12] or [r14, r15], and index register in the range [r0, r14] +tbh [r13, r1, lsl #1] +@CHECK: [[@LINE-1]]:5: error: operand must be a memory reference with base register in the range [r0, r12] or [r14, r15], and index register in the range [r0, r14] shifted left by 1 +tbh [r12, pc, lsl #1] +@CHECK: [[@LINE-1]]:5: error: operand must be a memory reference with base register in the range [r0, r12] or [r14, r15], and index register in the range [r0, r14] shifted left by 1 +tbh [s0, r0, lsl #1] +@CHECK: [[@LINE-1]]:5: error: operand must be a memory reference with base register in the range [r0, r12] or [r14, r15], and index register in the range [r0, r14] shifted left by 1 +tbh [r0, s0, lsl #1] +@CHECK: [[@LINE-1]]:5: error: operand must be a memory reference with base register in the range [r0, r12] or [r14, r15], and index register in the range [r0, r14] shifted left by 1 Index: test/MC/ARM/thumb2-diagnostics.s =================================================================== --- test/MC/ARM/thumb2-diagnostics.s +++ test/MC/ARM/thumb2-diagnostics.s @@ -114,29 +114,37 @@ @ PC is not valid as base of load ldr r0, [pc, r0] - ldrb r1, [pc, r2] - ldrh r3, [pc, r3] - pld r4, [pc, r5] - str r6, [pc, r7] - strb r7 [pc, r8] - strh r9, [pc, r10] @ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: +@ CHECK-ERRORS-NEXT: ldr r0, [pc, r0] @ CHECK-ERRORS: note: invalid operand for instruction @ CHECK-ERRORS: note: instruction requires: arm-mode + ldrb r1, [pc, r2] @ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: -@ CHECK-ERRORS: note: invalid operand for instruction +@ CHECK-ERRORS-NEXT: ldrb r1, [pc, r2] @ CHECK-ERRORS: note: instruction requires: arm-mode +@ CHECK-ERRORS: note: invalid operand for instruction + ldrh r3, [pc, r3] @ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: +@ CHECK-ERRORS-NEXT: ldrh r3, [pc, r3] @ CHECK-ERRORS: note: instruction requires: arm-mode @ CHECK-ERRORS: note: invalid operand for instruction + pld r4, [pc, r5] @ CHECK-ERRORS: error: invalid instruction +@ CHECK-ERRORS-NEXT: pld r4, [pc, r5] + str r6, [pc, r7] @ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: -@ CHECK-ERRORS: note: invalid operand for instruction +@ CHECK-ERRORS-NEXT: str r6, [pc, r7] +@ CHECK-ERRORS: note: operand must be a memory reference with base register in the range [r0, r14], index register in the range [r0, r15] and left shift by 0, 1, 2, or 3 @ CHECK-ERRORS: note: instruction requires: arm-mode + strb r7 [pc, r8] @ CHECK-ERRORS: error: immediate value expected for vector index +@ CHECK-ERRORS-NEXT: strb r7 [pc, r8] + strh r9, [pc, r10] @ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: +@ CHECK-ERRORS-NEXT: strh r9, [pc, r10] @ CHECK-ERRORS: note: instruction requires: arm-mode -@ CHECK-ERRORS: note: invalid operand for instruction +@ CHECK-ERRORS: note: operand must be a memory reference with base register in the range [r0, r14], and immediate offset in the range [-255, -1] + @ SWP(B) is an ARM-only instruction swp r0, r1, [r2]