diff options
author | Sander de Smalen <sander.desmalen@arm.com> | 2018-05-29 10:39:49 +0000 |
---|---|---|
committer | Sander de Smalen <sander.desmalen@arm.com> | 2018-05-29 10:39:49 +0000 |
commit | 98686c6b156804d6c441347fdb34f4e7ebc1d588 (patch) | |
tree | f86b3fa21c513458816ed5c4e752fe199382e4af | |
parent | 6be87bce29bc55805047abbcef4f963dff00fa40 (diff) | |
download | bcm5719-llvm-98686c6b156804d6c441347fdb34f4e7ebc1d588.tar.gz bcm5719-llvm-98686c6b156804d6c441347fdb34f4e7ebc1d588.zip |
[AArch64][SVE] Asm: Support for ADD (immediate) instructions.
This patch adds addsub_imm8_opt_lsl_(i8|i16|i32|i64) operands
that are unsigned values in the range 0 to 255. For element widths of
16 bits or higher it may also be a signed multiple of 256 in the
range 0 to 65280.
Note: This also does some refactoring to reuse convenience function
getShiftedVal<shift>(), and now allows AArch64 scalar 'ADD #-4096' to be
accepted to be mapped to SUB #4096.
Reviewers: rengolin, fhahn, samparker, SjoerdMeijer, javed.absar
Reviewed By: fhahn
Differential Revision: https://reviews.llvm.org/D47310
llvm-svn: 333408
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td | 3 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp | 49 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h | 8 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/SVEInstrFormats.td | 45 | ||||
-rw-r--r-- | llvm/test/MC/AArch64/SVE/add-diagnostics.s | 69 | ||||
-rw-r--r-- | llvm/test/MC/AArch64/SVE/add.s | 85 | ||||
-rw-r--r-- | llvm/test/MC/AArch64/SVE/sub-diagnostics.s | 69 | ||||
-rw-r--r-- | llvm/test/MC/AArch64/SVE/sub.s | 88 | ||||
-rw-r--r-- | llvm/test/MC/AArch64/alias-addsubimm.s | 10 | ||||
-rw-r--r-- | llvm/test/MC/AArch64/basic-a64-diagnostics.s | 4 |
10 files changed, 413 insertions, 17 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td index ec3d9b49a15..d2a6e31e660 100644 --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -20,6 +20,9 @@ let Predicates = [HasSVE] in { defm ADD_ZPmZ : sve_int_bin_pred_arit_0<0b000, "add">; defm SUB_ZPmZ : sve_int_bin_pred_arit_0<0b001, "sub">; + defm ADD_ZI : sve_int_arith_imm0<0b000, "add">; + defm SUB_ZI : sve_int_arith_imm0<0b001, "sub">; + // Splat immediate (unpredicated) defm DUP_ZI : sve_int_dup_imm<"dup">; diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index f525c81a239..64b43c82175 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -693,7 +693,7 @@ public: || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12; } - // If it's a constant, it should be a real immediate in range: + // If it's a constant, it should be a real immediate in range. if (auto ShiftedVal = getShiftedVal<12>()) return ShiftedVal->first >= 0 && ShiftedVal->first <= 0xfff; @@ -706,20 +706,11 @@ public: if (!isShiftedImm() && !isImm()) return false; - const MCExpr *Expr; - - // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'. - if (isShiftedImm()) { - unsigned Shift = ShiftedImm.ShiftAmount; - Expr = ShiftedImm.Val; - if (Shift != 0 && Shift != 12) - return false; - } else - Expr = getImm(); + // Otherwise it should be a real negative immediate in range. + if (auto ShiftedVal = getShiftedVal<12>()) + return ShiftedVal->first < 0 && -ShiftedVal->first <= 0xfff; - // Otherwise it should be a real negative immediate in range: - const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr); - return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff; + return false; } // Signed value in the range -128 to +127. For element widths of @@ -743,6 +734,24 @@ public: return DiagnosticPredicateTy::NearMatch; } + // Unsigned value in the range 0 to 255. For element widths of + // 16 bits or higher it may also be a signed multiple of 256 in the + // range 0 to 65280. + template <typename T> DiagnosticPredicate isSVEAddSubImm() const { + if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm()))) + return DiagnosticPredicateTy::NoMatch; + + bool IsByte = + std::is_same<int8_t, typename std::make_signed<T>::type>::value; + if (auto ShiftedImm = getShiftedVal<8>()) + if (!(IsByte && ShiftedImm->second) && + AArch64_AM::isSVEAddSubImm<T>(ShiftedImm->first + << ShiftedImm->second)) + return DiagnosticPredicateTy::Match; + + return DiagnosticPredicateTy::NearMatch; + } + bool isCondCode() const { return Kind == k_CondCode; } bool isSIMDImmType10() const { @@ -3808,6 +3817,14 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode, return Error(Loc, "immediate must be an integer in range [1, 32]."); case Match_InvalidImm1_64: return Error(Loc, "immediate must be an integer in range [1, 64]."); + case Match_InvalidSVEAddSubImm8: + return Error(Loc, "immediate must be an integer in range [0, 255]" + " with a shift amount of 0"); + case Match_InvalidSVEAddSubImm16: + case Match_InvalidSVEAddSubImm32: + case Match_InvalidSVEAddSubImm64: + return Error(Loc, "immediate must be an integer in range [0, 255] or a " + "multiple of 256 in range [256, 65280]"); case Match_InvalidSVECpyImm8: return Error(Loc, "immediate must be an integer in range [-128, 255]" " with a shift amount of 0"); @@ -4344,6 +4361,10 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, case Match_InvalidImm1_16: case Match_InvalidImm1_32: case Match_InvalidImm1_64: + case Match_InvalidSVEAddSubImm8: + case Match_InvalidSVEAddSubImm16: + case Match_InvalidSVEAddSubImm32: + case Match_InvalidSVEAddSubImm64: case Match_InvalidSVECpyImm8: case Match_InvalidSVECpyImm16: case Match_InvalidSVECpyImm32: diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h index 196ed427df7..177ead2e28b 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h @@ -772,8 +772,14 @@ static inline bool isSVECpyImm(int64_t Imm) { return uint8_t(Imm) == Imm || int8_t(Imm) == Imm; else return int8_t(Imm) == Imm || int16_t(Imm & ~0xff) == Imm; +} - llvm_unreachable("Unsupported element width"); +/// Returns true if Imm is valid for ADD/SUB. +template <typename T> +static inline bool isSVEAddSubImm(int64_t Imm) { + bool IsInt8t = + std::is_same<int8_t, typename std::make_signed<T>::type>::value; + return uint8_t(Imm) == Imm || (!IsInt8t && uint16_t(Imm & ~0xff) == Imm); } inline static bool isAnyMOVZMovAlias(uint64_t Value, int RegWidth) { diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td index ad90e50494c..771d83d9a17 100644 --- a/llvm/lib/Target/AArch64/SVEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -117,6 +117,11 @@ def SVECpyImmOperand16 : SVEShiftedImmOperand<16, "Cpy", "isSVECpyImm<int16_t>"> def SVECpyImmOperand32 : SVEShiftedImmOperand<32, "Cpy", "isSVECpyImm<int32_t>">; def SVECpyImmOperand64 : SVEShiftedImmOperand<64, "Cpy", "isSVECpyImm<int64_t>">; +def SVEAddSubImmOperand8 : SVEShiftedImmOperand<8, "AddSub", "isSVEAddSubImm<int8_t>">; +def SVEAddSubImmOperand16 : SVEShiftedImmOperand<16, "AddSub", "isSVEAddSubImm<int16_t>">; +def SVEAddSubImmOperand32 : SVEShiftedImmOperand<32, "AddSub", "isSVEAddSubImm<int32_t>">; +def SVEAddSubImmOperand64 : SVEShiftedImmOperand<64, "AddSub", "isSVEAddSubImm<int64_t>">; + class imm8_opt_lsl<int ElementWidth, string printType, AsmOperandClass OpndClass, code Predicate> : Operand<i32>, ImmLeaf<i32, Predicate> { @@ -140,6 +145,19 @@ def cpy_imm8_opt_lsl_i64 : imm8_opt_lsl<64, "int64_t", SVECpyImmOperand64, [{ return AArch64_AM::isSVECpyImm<int64_t>(Imm); }]>; +def addsub_imm8_opt_lsl_i8 : imm8_opt_lsl<8, "uint8_t", SVEAddSubImmOperand8, [{ + return AArch64_AM::isSVEAddSubImm<int8_t>(Imm); +}]>; +def addsub_imm8_opt_lsl_i16 : imm8_opt_lsl<16, "uint16_t", SVEAddSubImmOperand16, [{ + return AArch64_AM::isSVEAddSubImm<int16_t>(Imm); +}]>; +def addsub_imm8_opt_lsl_i32 : imm8_opt_lsl<32, "uint32_t", SVEAddSubImmOperand32, [{ + return AArch64_AM::isSVEAddSubImm<int32_t>(Imm); +}]>; +def addsub_imm8_opt_lsl_i64 : imm8_opt_lsl<64, "uint64_t", SVEAddSubImmOperand64, [{ + return AArch64_AM::isSVEAddSubImm<int64_t>(Imm); +}]>; + //===----------------------------------------------------------------------===// // SVE PTrue - These are used extensively throughout the pattern matching so // it's important we define them first. @@ -425,6 +443,33 @@ multiclass sve_int_dup_imm<string asm> { (!cast<Instruction>(NAME # _D) ZPR64:$Zd, cpy_imm8_opt_lsl_i64:$imm), 1>; } +class sve_int_arith_imm0<bits<2> sz8_64, bits<3> opc, string asm, + ZPRRegOp zprty, Operand immtype> +: I<(outs zprty:$Zdn), (ins zprty:$_Zdn, immtype:$imm), + asm, "\t$Zdn, $_Zdn, $imm", + "", + []>, Sched<[]> { + bits<5> Zdn; + bits<9> imm; + let Inst{31-24} = 0b00100101; + let Inst{23-22} = sz8_64; + let Inst{21-19} = 0b100; + let Inst{18-16} = opc; + let Inst{15-14} = 0b11; + let Inst{13} = imm{8}; // sh + let Inst{12-5} = imm{7-0}; // imm8 + let Inst{4-0} = Zdn; + + let Constraints = "$Zdn = $_Zdn"; +} + +multiclass sve_int_arith_imm0<bits<3> opc, string asm> { + def _B : sve_int_arith_imm0<0b00, opc, asm, ZPR8, addsub_imm8_opt_lsl_i8>; + def _H : sve_int_arith_imm0<0b01, opc, asm, ZPR16, addsub_imm8_opt_lsl_i16>; + def _S : sve_int_arith_imm0<0b10, opc, asm, ZPR32, addsub_imm8_opt_lsl_i32>; + def _D : sve_int_arith_imm0<0b11, opc, asm, ZPR64, addsub_imm8_opt_lsl_i64>; +} + //===----------------------------------------------------------------------===// //SVE Index Generation Group //===----------------------------------------------------------------------===// diff --git a/llvm/test/MC/AArch64/SVE/add-diagnostics.s b/llvm/test/MC/AArch64/SVE/add-diagnostics.s index 45bbe1d2991..23042b6708c 100644 --- a/llvm/test/MC/AArch64/SVE/add-diagnostics.s +++ b/llvm/test/MC/AArch64/SVE/add-diagnostics.s @@ -75,3 +75,72 @@ add z9.d, p4/m, z10.d, z7.d // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register // CHECK-NEXT: add z9.d, p4/m, z10.d, z7.d // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid immediates + +add z0.b, z0.b, #0, lsl #8 // #0, lsl #8 is not valid for .b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] with a shift amount of 0 +// CHECK-NEXT: add z0.b, z0.b, #0, lsl #8 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +add z0.b, z0.b, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] with a shift amount of 0 +// CHECK-NEXT: add z0.b, z0.b, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +add z0.b, z0.b, #1, lsl #8 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] with a shift amount of 0 +// CHECK-NEXT: add z0.b, z0.b, #1, lsl #8 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +add z0.b, z0.b, #256 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] with a shift amount of 0 +// CHECK-NEXT: add z0.b, z0.b, #256 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +add z0.h, z0.h, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] or a multiple of 256 in range [256, 65280] +// CHECK-NEXT: add z0.h, z0.h, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +add z0.h, z0.h, #256, lsl #8 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] or a multiple of 256 in range [256, 65280] +// CHECK-NEXT: add z0.h, z0.h, #256, lsl #8 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +add z0.h, z0.h, #65536 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] or a multiple of 256 in range [256, 65280] +// CHECK-NEXT: add z0.h, z0.h, #65536 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +add z0.s, z0.s, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] or a multiple of 256 in range [256, 65280] +// CHECK-NEXT: add z0.s, z0.s, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +add z0.s, z0.s, #256, lsl #8 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] or a multiple of 256 in range [256, 65280] +// CHECK-NEXT: add z0.s, z0.s, #256, lsl #8 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +add z0.s, z0.s, #65536 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] or a multiple of 256 in range [256, 65280] +// CHECK-NEXT: add z0.s, z0.s, #65536 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +add z0.d, z0.d, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] or a multiple of 256 in range [256, 65280] +// CHECK-NEXT: add z0.d, z0.d, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +add z0.d, z0.d, #256, lsl #8 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] or a multiple of 256 in range [256, 65280] +// CHECK-NEXT: add z0.d, z0.d, #256, lsl #8 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +add z0.d, z0.d, #65536 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] or a multiple of 256 in range [256, 65280] +// CHECK-NEXT: add z0.d, z0.d, #65536 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE/add.s b/llvm/test/MC/AArch64/SVE/add.s index 144fbc23e19..f477eb95687 100644 --- a/llvm/test/MC/AArch64/SVE/add.s +++ b/llvm/test/MC/AArch64/SVE/add.s @@ -198,3 +198,88 @@ add z23.s, z13.s, z8.s // CHECK-ENCODING: [0xb7,0x01,0xa8,0x04] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: b7 01 a8 04 <unknown> + +add z0.b, z0.b, #0 +// CHECK-INST: add z0.b, z0.b, #0 +// CHECK-ENCODING: [0x00,0xc0,0x20,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 c0 20 25 <unknown> + +add z31.b, z31.b, #255 +// CHECK-INST: add z31.b, z31.b, #255 +// CHECK-ENCODING: [0xff,0xdf,0x20,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff df 20 25 <unknown> + +add z0.h, z0.h, #0 +// CHECK-INST: add z0.h, z0.h, #0 +// CHECK-ENCODING: [0x00,0xc0,0x60,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 c0 60 25 <unknown> + +add z0.h, z0.h, #0, lsl #8 +// CHECK-INST: add z0.h, z0.h, #0, lsl #8 +// CHECK-ENCODING: [0x00,0xe0,0x60,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 e0 60 25 <unknown> + +add z31.h, z31.h, #255, lsl #8 +// CHECK-INST: add z31.h, z31.h, #65280 +// CHECK-ENCODING: [0xff,0xff,0x60,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff ff 60 25 <unknown> + +add z31.h, z31.h, #65280 +// CHECK-INST: add z31.h, z31.h, #65280 +// CHECK-ENCODING: [0xff,0xff,0x60,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff ff 60 25 <unknown> + +add z0.s, z0.s, #0 +// CHECK-INST: add z0.s, z0.s, #0 +// CHECK-ENCODING: [0x00,0xc0,0xa0,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 c0 a0 25 <unknown> + +add z0.s, z0.s, #0, lsl #8 +// CHECK-INST: add z0.s, z0.s, #0, lsl #8 +// CHECK-ENCODING: [0x00,0xe0,0xa0,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 e0 a0 25 <unknown> + +add z31.s, z31.s, #255, lsl #8 +// CHECK-INST: add z31.s, z31.s, #65280 +// CHECK-ENCODING: [0xff,0xff,0xa0,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff ff a0 25 <unknown> + +add z31.s, z31.s, #65280 +// CHECK-INST: add z31.s, z31.s, #65280 +// CHECK-ENCODING: [0xff,0xff,0xa0,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff ff a0 25 <unknown> + +add z0.d, z0.d, #0 +// CHECK-INST: add z0.d, z0.d, #0 +// CHECK-ENCODING: [0x00,0xc0,0xe0,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 c0 e0 25 <unknown> + +add z0.d, z0.d, #0, lsl #8 +// CHECK-INST: add z0.d, z0.d, #0, lsl #8 +// CHECK-ENCODING: [0x00,0xe0,0xe0,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 e0 e0 25 <unknown> + +add z31.d, z31.d, #255, lsl #8 +// CHECK-INST: add z31.d, z31.d, #65280 +// CHECK-ENCODING: [0xff,0xff,0xe0,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff ff e0 25 <unknown> + +add z31.d, z31.d, #65280 +// CHECK-INST: add z31.d, z31.d, #65280 +// CHECK-ENCODING: [0xff,0xff,0xe0,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff ff e0 25 <unknown> + diff --git a/llvm/test/MC/AArch64/SVE/sub-diagnostics.s b/llvm/test/MC/AArch64/SVE/sub-diagnostics.s index e27432f2c40..4ace1ce7dab 100644 --- a/llvm/test/MC/AArch64/SVE/sub-diagnostics.s +++ b/llvm/test/MC/AArch64/SVE/sub-diagnostics.s @@ -75,3 +75,72 @@ sub z2.d, p5/m, z3.d, z11.d // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register // CHECK-NEXT: sub z2.d, p5/m, z3.d, z11.d // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid immediates + +sub z0.b, z0.b, #0, lsl #8 // #0, lsl #8 is not valid for .b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] with a shift amount of 0 +// CHECK-NEXT: sub z0.b, z0.b, #0, lsl #8 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sub z0.b, z0.b, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] with a shift amount of 0 +// CHECK-NEXT: sub z0.b, z0.b, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sub z0.b, z0.b, #1, lsl #8 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] with a shift amount of 0 +// CHECK-NEXT: sub z0.b, z0.b, #1, lsl #8 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sub z0.b, z0.b, #256 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] with a shift amount of 0 +// CHECK-NEXT: sub z0.b, z0.b, #256 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sub z0.h, z0.h, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] or a multiple of 256 in range [256, 65280] +// CHECK-NEXT: sub z0.h, z0.h, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sub z0.h, z0.h, #256, lsl #8 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] or a multiple of 256 in range [256, 65280] +// CHECK-NEXT: sub z0.h, z0.h, #256, lsl #8 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sub z0.h, z0.h, #65536 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] or a multiple of 256 in range [256, 65280] +// CHECK-NEXT: sub z0.h, z0.h, #65536 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sub z0.s, z0.s, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] or a multiple of 256 in range [256, 65280] +// CHECK-NEXT: sub z0.s, z0.s, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sub z0.s, z0.s, #256, lsl #8 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] or a multiple of 256 in range [256, 65280] +// CHECK-NEXT: sub z0.s, z0.s, #256, lsl #8 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sub z0.s, z0.s, #65536 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] or a multiple of 256 in range [256, 65280] +// CHECK-NEXT: sub z0.s, z0.s, #65536 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sub z0.d, z0.d, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] or a multiple of 256 in range [256, 65280] +// CHECK-NEXT: sub z0.d, z0.d, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sub z0.d, z0.d, #256, lsl #8 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] or a multiple of 256 in range [256, 65280] +// CHECK-NEXT: sub z0.d, z0.d, #256, lsl #8 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sub z0.d, z0.d, #65536 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 255] or a multiple of 256 in range [256, 65280] +// CHECK-NEXT: sub z0.d, z0.d, #65536 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE/sub.s b/llvm/test/MC/AArch64/SVE/sub.s index e89faf5f2d0..dcbef0bf3e5 100644 --- a/llvm/test/MC/AArch64/SVE/sub.s +++ b/llvm/test/MC/AArch64/SVE/sub.s @@ -198,3 +198,91 @@ sub z23.b, p3/m, z23.b, z13.b // CHECK-ENCODING: [0xb7,0x0d,0x01,0x04] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: b7 0d 01 04 <unknown> + +// ----------------------- +// + +sub z0.b, z0.b, #0 +// CHECK-INST: sub z0.b, z0.b, #0 +// CHECK-ENCODING: [0x00,0xc0,0x21,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 c0 21 25 <unknown> + +sub z31.b, z31.b, #255 +// CHECK-INST: sub z31.b, z31.b, #255 +// CHECK-ENCODING: [0xff,0xdf,0x21,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff df 21 25 <unknown> + +sub z0.h, z0.h, #0 +// CHECK-INST: sub z0.h, z0.h, #0 +// CHECK-ENCODING: [0x00,0xc0,0x61,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 c0 61 25 <unknown> + +sub z0.h, z0.h, #0, lsl #8 +// CHECK-INST: sub z0.h, z0.h, #0, lsl #8 +// CHECK-ENCODING: [0x00,0xe0,0x61,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 e0 61 25 <unknown> + +sub z31.h, z31.h, #255, lsl #8 +// CHECK-INST: sub z31.h, z31.h, #65280 +// CHECK-ENCODING: [0xff,0xff,0x61,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff ff 61 25 <unknown> + +sub z31.h, z31.h, #65280 +// CHECK-INST: sub z31.h, z31.h, #65280 +// CHECK-ENCODING: [0xff,0xff,0x61,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff ff 61 25 <unknown> + +sub z0.s, z0.s, #0 +// CHECK-INST: sub z0.s, z0.s, #0 +// CHECK-ENCODING: [0x00,0xc0,0xa1,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 c0 a1 25 <unknown> + +sub z0.s, z0.s, #0, lsl #8 +// CHECK-INST: sub z0.s, z0.s, #0, lsl #8 +// CHECK-ENCODING: [0x00,0xe0,0xa1,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 e0 a1 25 <unknown> + +sub z31.s, z31.s, #255, lsl #8 +// CHECK-INST: sub z31.s, z31.s, #65280 +// CHECK-ENCODING: [0xff,0xff,0xa1,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff ff a1 25 <unknown> + +sub z31.s, z31.s, #65280 +// CHECK-INST: sub z31.s, z31.s, #65280 +// CHECK-ENCODING: [0xff,0xff,0xa1,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff ff a1 25 <unknown> + +sub z0.d, z0.d, #0 +// CHECK-INST: sub z0.d, z0.d, #0 +// CHECK-ENCODING: [0x00,0xc0,0xe1,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 c0 e1 25 <unknown> + +sub z0.d, z0.d, #0, lsl #8 +// CHECK-INST: sub z0.d, z0.d, #0, lsl #8 +// CHECK-ENCODING: [0x00,0xe0,0xe1,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 e0 e1 25 <unknown> + +sub z31.d, z31.d, #255, lsl #8 +// CHECK-INST: sub z31.d, z31.d, #65280 +// CHECK-ENCODING: [0xff,0xff,0xe1,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff ff e1 25 <unknown> + +sub z31.d, z31.d, #65280 +// CHECK-INST: sub z31.d, z31.d, #65280 +// CHECK-ENCODING: [0xff,0xff,0xe1,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff ff e1 25 <unknown> + diff --git a/llvm/test/MC/AArch64/alias-addsubimm.s b/llvm/test/MC/AArch64/alias-addsubimm.s index 5c1c4799828..899cf799eb0 100644 --- a/llvm/test/MC/AArch64/alias-addsubimm.s +++ b/llvm/test/MC/AArch64/alias-addsubimm.s @@ -1,6 +1,16 @@ // RUN: llvm-mc -triple=aarch64-none-linux-gnu < %s | FileCheck %s // RUN: not llvm-mc -mattr=+no-neg-immediates -triple=aarch64-none-linux-gnu < %s 2>&1 | FileCheck %s --check-prefix=CHECK-NO-NEG-IMM + add w0, w2, #4096 + sub w0, w2, #4096 +// CHECK: add w0, w2, #1, lsl #12 +// CHECK: sub w0, w2, #1, lsl #12 + + add w0, w2, #-4096 + sub w0, w2, #-4096 +// CHECK: sub w0, w2, #1, lsl #12 +// CHECK: add w0, w2, #1, lsl #12 + // CHECK: sub w0, w2, #2, lsl #12 // CHECK: sub w0, w2, #2, lsl #12 // CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates diff --git a/llvm/test/MC/AArch64/basic-a64-diagnostics.s b/llvm/test/MC/AArch64/basic-a64-diagnostics.s index bad2a8d78a1..66285936d15 100644 --- a/llvm/test/MC/AArch64/basic-a64-diagnostics.s +++ b/llvm/test/MC/AArch64/basic-a64-diagnostics.s @@ -76,12 +76,12 @@ //------------------------------------------------------------------------------ // Out of range immediates: more than 12 bits - add w4, w5, #-4096 + add w4, w5, #-4097 add w5, w6, #0x1000 add w4, w5, #-4096, lsl #12 add w5, w6, #0x1000, lsl #12 // CHECK-ERROR: error: expected compatible register, symbol or integer in range [0, 4095] -// CHECK-ERROR-NEXT: add w4, w5, #-4096 +// CHECK-ERROR-NEXT: add w4, w5, #-4097 // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-AARCH64-NEXT: error: expected compatible register, symbol or integer in range [0, 4095] // CHECK-ERROR-AARCH64-NEXT: add w5, w6, #0x1000 |