diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index 16b7bc5e404..ed73d363380 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -1551,8 +1551,8 @@ class ADbI opcod1, bits<2> opcod2, bit op6, bit op4, dag oops, // FP, binary, not predicated class ADbInp opcod1, bits<2> opcod2, bit opcod3, dag oops, dag iops, InstrItinClass itin, string asm, list pattern> - : VFPXI + : VFPXI { // Instruction operands. bits<5> Dd; @@ -1577,7 +1577,7 @@ class ADbInp opcod1, bits<2> opcod2, bit opcod3, dag oops, dag iops, let Inst{4} = 0; } -// Single precision, unary +// Single precision, unary, predicated class ASuI opcod1, bits<2> opcod2, bits<4> opcod3, bits<2> opcod4, bit opcod5, dag oops, dag iops, InstrItinClass itin, string opc, string asm, list pattern> @@ -1601,6 +1601,33 @@ class ASuI opcod1, bits<2> opcod2, bits<4> opcod3, bits<2> opcod4, let Inst{4} = opcod5; } +// Single precision, unary, non-predicated +class ASuInp opcod1, bits<2> opcod2, bits<4> opcod3, bits<2> opcod4, + bit opcod5, dag oops, dag iops, InstrItinClass itin, + string asm, list pattern> + : VFPXI { + // Instruction operands. + bits<5> Sd; + bits<5> Sm; + + let Inst{31-28} = 0b1111; + + // Encode instruction operands. + let Inst{3-0} = Sm{4-1}; + let Inst{5} = Sm{0}; + let Inst{15-12} = Sd{4-1}; + let Inst{22} = Sd{0}; + + let Inst{27-23} = opcod1; + let Inst{21-20} = opcod2; + let Inst{19-16} = opcod3; + let Inst{11-9} = 0b101; + let Inst{8} = 0; // Single precision + let Inst{7-6} = opcod4; + let Inst{4} = opcod5; +} + // Single precision unary, if no NEON. Same as ASuI except not available if // NEON is enabled. class ASuIn opcod1, bits<2> opcod2, bits<4> opcod3, bits<2> opcod4, diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td index 27e2df4bfd4..27f1578b5ea 100644 --- a/lib/Target/ARM/ARMInstrVFP.td +++ b/lib/Target/ARM/ARMInstrVFP.td @@ -583,6 +583,57 @@ def VCVTTDH : ADuI<0b11101, 0b11, 0b0011, 0b11, 0, let Inst{5} = Dm{4}; } +multiclass vcvt_inst rm> { + let PostEncoderMethod = "" in { + def SS : ASuInp<0b11101, 0b11, 0b1100, 0b11, 0, + (outs SPR:$Sd), (ins SPR:$Sm), + NoItinerary, !strconcat("vcvt", opc, ".s32.f32\t$Sd, $Sm"), + []>, Requires<[HasV8FP]> { + let Inst{17-16} = rm; + } + + def US : ASuInp<0b11101, 0b11, 0b1100, 0b01, 0, + (outs SPR:$Sd), (ins SPR:$Sm), + NoItinerary, !strconcat("vcvt", opc, ".u32.f32\t$Sd, $Sm"), + []>, Requires<[HasV8FP]> { + let Inst{17-16} = rm; + } + + def SD : ASuInp<0b11101, 0b11, 0b1100, 0b11, 0, + (outs SPR:$Sd), (ins DPR:$Dm), + NoItinerary, !strconcat("vcvt", opc, ".s32.f64\t$Sd, $Dm"), + []>, Requires<[HasV8FP]> { + bits<5> Dm; + + let Inst{17-16} = rm; + + // Encode instruction operands + let Inst{3-0} = Dm{3-0}; + let Inst{5} = Dm{4}; + let Inst{8} = 1; + } + + def UD : ASuInp<0b11101, 0b11, 0b1100, 0b01, 0, + (outs SPR:$Sd), (ins DPR:$Dm), + NoItinerary, !strconcat("vcvt", opc, ".u32.f64\t$Sd, $Dm"), + []>, Requires<[HasV8FP]> { + bits<5> Dm; + + let Inst{17-16} = rm; + + // Encode instruction operands + let Inst{3-0} = Dm{3-0}; + let Inst{5} = Dm{4}; + let Inst{8} = 1; + } + } +} + +defm VCVTA : vcvt_inst<"a", 0b00>; +defm VCVTN : vcvt_inst<"n", 0b01>; +defm VCVTP : vcvt_inst<"p", 0b10>; +defm VCVTM : vcvt_inst<"m", 0b11>; + def VNEGD : ADuI<0b11101, 0b11, 0b0001, 0b01, 0, (outs DPR:$Dd), (ins DPR:$Dm), IIC_fpUNA64, "vneg", ".f64\t$Dd, $Dm", diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index f7f19014895..56557e3736c 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -4906,7 +4906,8 @@ StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic, Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" || Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" || Mnemonic == "fmuls" || Mnemonic == "vmaxnm" || Mnemonic == "vminnm" || - Mnemonic.startswith("vsel")) + Mnemonic == "vcvta" || Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || + Mnemonic == "vcvtm" || Mnemonic.startswith("vsel")) return Mnemonic; // First, split out any predication code. Ignore mnemonics we know aren't @@ -5006,8 +5007,9 @@ getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, if (Mnemonic == "bkpt" || Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "cps" || Mnemonic == "it" || Mnemonic == "cbz" || Mnemonic == "trap" || Mnemonic == "setend" || - Mnemonic.startswith("cps") || Mnemonic == "vmaxnm" || - Mnemonic == "vminnm" || Mnemonic.startswith("vsel")) { + Mnemonic.startswith("cps") || Mnemonic.startswith("vsel") || + Mnemonic == "vmaxnm" || Mnemonic == "vminnm" || Mnemonic == "vcvta" || + Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || Mnemonic == "vcvtm") { // These mnemonics are never predicable CanAcceptPredicationCode = false; } else if (!isThumb()) { diff --git a/test/MC/ARM/v8fp.s b/test/MC/ARM/v8fp.s index 05a7f1badde..36cec8b9874 100644 --- a/test/MC/ARM/v8fp.s +++ b/test/MC/ARM/v8fp.s @@ -22,6 +22,44 @@ vcvtblt.f16.f64 s4, d1 @ CHECK: vcvtblt.f16.f64 s4, d1 @ encoding: [0x41,0x2b,0xb3,0xbe] + +@ VCVT{A,N,P,M} + + vcvta.s32.f32 s2, s3 +@ CHECK: vcvta.s32.f32 s2, s3 @ encoding: [0xe1,0x1a,0xbc,0xfe] + vcvta.s32.f64 s2, d3 +@ CHECK: vcvta.s32.f64 s2, d3 @ encoding: [0xc3,0x1b,0xbc,0xfe] + vcvtn.s32.f32 s6, s23 +@ CHECK: vcvtn.s32.f32 s6, s23 @ encoding: [0xeb,0x3a,0xbd,0xfe] + vcvtn.s32.f64 s6, d23 +@ CHECK: vcvtn.s32.f64 s6, d23 @ encoding: [0xe7,0x3b,0xbd,0xfe] + vcvtp.s32.f32 s0, s4 +@ CHECK: vcvtp.s32.f32 s0, s4 @ encoding: [0xc2,0x0a,0xbe,0xfe] + vcvtp.s32.f64 s0, d4 +@ CHECK: vcvtp.s32.f64 s0, d4 @ encoding: [0xc4,0x0b,0xbe,0xfe] + vcvtm.s32.f32 s17, s8 +@ CHECK: vcvtm.s32.f32 s17, s8 @ encoding: [0xc4,0x8a,0xff,0xfe] + vcvtm.s32.f64 s17, d8 +@ CHECK: vcvtm.s32.f64 s17, d8 @ encoding: [0xc8,0x8b,0xff,0xfe] + + vcvta.u32.f32 s2, s3 +@ CHECK: vcvta.u32.f32 s2, s3 @ encoding: [0x61,0x1a,0xbc,0xfe] + vcvta.u32.f64 s2, d3 +@ CHECK: vcvta.u32.f64 s2, d3 @ encoding: [0x43,0x1b,0xbc,0xfe] + vcvtn.u32.f32 s6, s23 +@ CHECK: vcvtn.u32.f32 s6, s23 @ encoding: [0x6b,0x3a,0xbd,0xfe] + vcvtn.u32.f64 s6, d23 +@ CHECK: vcvtn.u32.f64 s6, d23 @ encoding: [0x67,0x3b,0xbd,0xfe] + vcvtp.u32.f32 s0, s4 +@ CHECK: vcvtp.u32.f32 s0, s4 @ encoding: [0x42,0x0a,0xbe,0xfe] + vcvtp.u32.f64 s0, d4 +@ CHECK: vcvtp.u32.f64 s0, d4 @ encoding: [0x44,0x0b,0xbe,0xfe] + vcvtm.u32.f32 s17, s8 +@ CHECK: vcvtm.u32.f32 s17, s8 @ encoding: [0x44,0x8a,0xff,0xfe] + vcvtm.u32.f64 s17, d8 +@ CHECK: vcvtm.u32.f64 s17, d8 @ encoding: [0x48,0x8b,0xff,0xfe] + + @ VSEL vselge.f32 s4, s1, s23 @ CHECK: vselge.f32 s4, s1, s23 @ encoding: [0xab,0x2a,0x20,0xfe] diff --git a/test/MC/Disassembler/ARM/v8fp.txt b/test/MC/Disassembler/ARM/v8fp.txt index a805f817681..9c9d47058a7 100644 --- a/test/MC/Disassembler/ARM/v8fp.txt +++ b/test/MC/Disassembler/ARM/v8fp.txt @@ -25,6 +25,55 @@ # CHECK: vcvtblt.f16.f64 s4, d1 +0xe1 0x1a 0xbc 0xfe +# CHECK: vcvta.s32.f32 s2, s3 + +0xc3 0x1b 0xbc 0xfe +# CHECK: vcvta.s32.f64 s2, d3 + +0xeb 0x3a 0xbd 0xfe +# CHECK: vcvtn.s32.f32 s6, s23 + +0xe7 0x3b 0xbd 0xfe +# CHECK: vcvtn.s32.f64 s6, d23 + +0xc2 0x0a 0xbe 0xfe +# CHECK: vcvtp.s32.f32 s0, s4 + +0xc4 0x0b 0xbe 0xfe +# CHECK: vcvtp.s32.f64 s0, d4 + +0xc4 0x8a 0xff 0xfe +# CHECK: vcvtm.s32.f32 s17, s8 + +0xc8 0x8b 0xff 0xfe +# CHECK: vcvtm.s32.f64 s17, d8 + +0x61 0x1a 0xbc 0xfe +# CHECK: vcvta.u32.f32 s2, s3 + +0x43 0x1b 0xbc 0xfe +# CHECK: vcvta.u32.f64 s2, d3 + +0x6b 0x3a 0xbd 0xfe +# CHECK: vcvtn.u32.f32 s6, s23 + +0x67 0x3b 0xbd 0xfe +# CHECK: vcvtn.u32.f64 s6, d23 + +0x42 0x0a 0xbe 0xfe +# CHECK: vcvtp.u32.f32 s0, s4 + +0x44 0x0b 0xbe 0xfe +# CHECK: vcvtp.u32.f64 s0, d4 + +0x44 0x8a 0xff 0xfe +# CHECK: vcvtm.u32.f32 s17, s8 + +0x48 0x8b 0xff 0xfe +# CHECK: vcvtm.u32.f64 s17, d8 + + 0xab 0x2a 0x20 0xfe # CHECK: vselge.f32 s4, s1, s23