From: Diogo N. Sampaio Date: Fri, 8 Mar 2019 17:11:20 +0000 (+0000) Subject: [ARM][FIX] Fix vfmal.f16 and vfmsl.f16 operand X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=081955550000c9c95ba7dd2847d13e4c503c146f;p=llvm [ARM][FIX] Fix vfmal.f16 and vfmsl.f16 operand The indexed variant of vfmal.f16 and vfmsl.f16 instructions use the uppser bits of the indexed operand to store the index (1 bit for the double variant, 2 bits for the quad). This limits the usable registers to d0 - d7 or s0 - s15. This patch enforces this limitation. Differential Revision: https://reviews.llvm.org/D59021 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@355707 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td index 90aa574cbde..2c996b571d6 100644 --- a/lib/Target/ARM/ARMInstrNEON.td +++ b/lib/Target/ARM/ARMInstrNEON.td @@ -5121,10 +5121,11 @@ class N3VCP8F16Q0; -class VFMQ0 S> +// Vd, Vs, Vs[0-15], Idx[0-1] +class VFMD S> : N3VLaneCP8<0, S, 0, 1, (outs DPR:$Vd), - (ins SPR:$Vn, SPR:$Vm, VectorIndex32:$idx), - IIC_VMACD, opc, "f16", "$Vd, $Vn, $Vm$idx", "", []> { + (ins SPR:$Vn, SPR_8:$Vm, VectorIndex32:$idx), + IIC_VMACD, opc, type, "$Vd, $Vn, $Vm$idx", "", []> { bit idx; let Inst{3} = idx; let Inst{19-16} = Vn{4-1}; @@ -5133,10 +5134,11 @@ class VFMQ0 S> let Inst{2-0} = Vm{3-1}; } -class VFMQ1 S> +// Vq, Vd, Vd[0-7], Idx[0-3] +class VFMQ S> : N3VLaneCP8<0, S, 1, 1, (outs QPR:$Vd), - (ins DPR:$Vn, DPR:$Vm, VectorIndex16:$idx), - IIC_VMACD, opc, "f16", "$Vd, $Vn, $Vm$idx", "", []> { + (ins DPR:$Vn, DPR_8:$Vm, VectorIndex16:$idx), + IIC_VMACD, opc, type, "$Vd, $Vn, $Vm$idx", "", []> { bits<2> idx; let Inst{5} = idx{1}; let Inst{3} = idx{0}; @@ -5148,10 +5150,10 @@ def VFMALD : N3VCP8F16Q0<"vfmal", DPR, SPR, SPR, 0b00, 0b10, 1>; def VFMSLD : N3VCP8F16Q0<"vfmsl", DPR, SPR, SPR, 0b01, 0b10, 1>; def VFMALQ : N3VCP8F16Q1<"vfmal", QPR, DPR, DPR, 0b00, 0b10, 1>; def VFMSLQ : N3VCP8F16Q1<"vfmsl", QPR, DPR, DPR, 0b01, 0b10, 1>; -def VFMALDI : VFMQ0<"vfmal", 0b00>; -def VFMSLDI : VFMQ0<"vfmsl", 0b01>; -def VFMALQI : VFMQ1<"vfmal", 0b00>; -def VFMSLQI : VFMQ1<"vfmsl", 0b01>; +def VFMALDI : VFMD<"vfmal", "f16", 0b00>; +def VFMSLDI : VFMD<"vfmsl", "f16", 0b01>; +def VFMALQI : VFMQ<"vfmal", "f16", 0b00>; +def VFMSLQI : VFMQ<"vfmsl", "f16", 0b01>; } } // HasNEON, HasFP16FML diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index b65a0753de0..e92bcc5ba51 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -165,6 +165,8 @@ static DecodeStatus DecodeDPRRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeDPR_8RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeSPR_8RegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder); static DecodeStatus DecodeDPR_VFP2RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, @@ -1045,6 +1047,13 @@ static DecodeStatus DecodeDPR_8RegisterClass(MCInst &Inst, unsigned RegNo, return DecodeDPRRegisterClass(Inst, RegNo, Address, Decoder); } +static DecodeStatus DecodeSPR_8RegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder) { + if (RegNo > 15) + return MCDisassembler::Fail; + return DecodeSPRRegisterClass(Inst, RegNo, Address, Decoder); +} + static DecodeStatus DecodeDPR_VFP2RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { diff --git a/test/MC/ARM/armv8a-fpmul-error.s b/test/MC/ARM/armv8a-fpmul-error.s index b63239bc0fd..85f087f4fbf 100644 --- a/test/MC/ARM/armv8a-fpmul-error.s +++ b/test/MC/ARM/armv8a-fpmul-error.s @@ -6,6 +6,10 @@ vfmsl.f16 d0, s1, s2[-1] vfmal.f16 q0, d1, d2[4] VFMSL.F16 Q0, D1, D2[4] vfmal.f16 q0, d1, d2[-1] +VFMSL.F16 D0, S1, S16[0] +vfmal.f16 d0, s1, s16[0] +VFMSL.F16 Q0, D1, D8[0] +vfmal.f16 q0, d1, d8[0] //CHECK-ERROR: error: invalid operand for instruction //CHECK-ERROR-NEXT: VFMAL.F16 D0, S1, S2[2] @@ -25,3 +29,39 @@ vfmal.f16 q0, d1, d2[-1] //CHECK-ERROR-NEXT: error: invalid operand for instruction //CHECK-ERROR-NEXT: vfmal.f16 q0, d1, d2[-1] //CHECK-ERROR-NEXT: ^ +//CHECK-ERROR-NEXT: error: invalid instruction, any one of the following would fix this: +//CHECK-ERROR-NEXT: VFMSL.F16 D0, S1, S16[0] +//CHECK-ERROR-NEXT: ^ +//CHECK-ERROR-NEXT: note: operand must be a register in range [s0, s15] +//CHECK-ERROR-NEXT: VFMSL.F16 D0, S1, S16[0] +//CHECK-ERROR-NEXT: ^ +//CHECK-ERROR-NEXT: note: too many operands for instruction +//CHECK-ERROR-NEXT: VFMSL.F16 D0, S1, S16[0] +//CHECK-ERROR-NEXT: ^ +//CHECK-ERROR-NEXT: error: invalid instruction, any one of the following would fix this: +//CHECK-ERROR-NEXT: vfmal.f16 d0, s1, s16[0] +//CHECK-ERROR-NEXT: ^ +//CHECK-ERROR-NEXT: note: operand must be a register in range [s0, s15] +//CHECK-ERROR-NEXT: vfmal.f16 d0, s1, s16[0] +//CHECK-ERROR-NEXT: ^ +//CHECK-ERROR-NEXT: note: too many operands for instruction +//CHECK-ERROR-NEXT: vfmal.f16 d0, s1, s16[0] +//CHECK-ERROR-NEXT: ^ +//CHECK-ERROR-NEXT: : error: invalid instruction, any one of the following would fix this: +//CHECK-ERROR-NEXT: VFMSL.F16 Q0, D1, D8[0] +//CHECK-ERROR-NEXT: ^ +//CHECK-ERROR-NEXT: : note: operand must be a register in range [d0, d7] +//CHECK-ERROR-NEXT: VFMSL.F16 Q0, D1, D8[0] +//CHECK-ERROR-NEXT: ^ +//CHECK-ERROR-NEXT: : note: too many operands for instruction +//CHECK-ERROR-NEXT: VFMSL.F16 Q0, D1, D8[0] +//CHECK-ERROR-NEXT: ^ +//CHECK-ERROR-NEXT: : error: invalid instruction, any one of the following would fix this: +//CHECK-ERROR-NEXT: vfmal.f16 q0, d1, d8[0] +//CHECK-ERROR-NEXT: ^ +//CHECK-ERROR-NEXT: : note: operand must be a register in range [d0, d7] +//CHECK-ERROR-NEXT: vfmal.f16 q0, d1, d8[0] +//CHECK-ERROR-NEXT: ^ +//CHECK-ERROR-NEXT: 1: note: too many operands for instruction +//CHECK-ERROR-NEXT: vfmal.f16 q0, d1, d8[0] +//CHECK-ERROR-NEXT: ^