From: Colin LeMahieu Date: Wed, 7 Jan 2015 20:24:09 +0000 (+0000) Subject: [Hexagon] Adding encodings for v5 floating point instructions. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=22ddfae848783584d1a9e629354865596f5bd571;p=oota-llvm.git [Hexagon] Adding encodings for v5 floating point instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225372 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/Hexagon/HexagonInstrInfoV5.td b/lib/Target/Hexagon/HexagonInstrInfoV5.td index 876c8dbb9b1..47243ae8f30 100644 --- a/lib/Target/Hexagon/HexagonInstrInfoV5.td +++ b/lib/Target/Hexagon/HexagonInstrInfoV5.td @@ -112,6 +112,332 @@ def S5_popcountp : ALU64_rr<(outs IntRegs:$Rd), (ins DoubleRegs:$Rss), let Inst{20-16} = Rss; } +let Uses = [USR], isFP = 1, hasNewValue = 1, opNewValue = 0 in +class T_MInstFloat MajOp, bits<3> MinOp> + : MInst<(outs IntRegs:$Rd), + (ins IntRegs:$Rs, IntRegs:$Rt), + "$Rd = "#mnemonic#"($Rs, $Rt)", [], + "" , M_tc_3or4x_SLOT23 > , + Requires<[HasV5T]> { + bits<5> Rd; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1110; + + let Inst{27-24} = 0b1011; + let Inst{23-21} = MajOp; + let Inst{20-16} = Rs; + let Inst{13} = 0b0; + let Inst{12-8} = Rt; + let Inst{7-5} = MinOp; + let Inst{4-0} = Rd; + } + +let isCommutable = 1, isCodeGenOnly = 0 in { + def F2_sfadd : T_MInstFloat < "sfadd", 0b000, 0b000>; + def F2_sfmpy : T_MInstFloat < "sfmpy", 0b010, 0b000>; +} + +let isCodeGenOnly = 0 in +def F2_sfsub : T_MInstFloat < "sfsub", 0b000, 0b001>; + +let Itinerary = M_tc_3x_SLOT23, isCodeGenOnly = 0 in { + def F2_sfmax : T_MInstFloat < "sfmax", 0b100, 0b000>; + def F2_sfmin : T_MInstFloat < "sfmin", 0b100, 0b001>; +} + +let isCodeGenOnly = 0 in { +def F2_sffixupn : T_MInstFloat < "sffixupn", 0b110, 0b000>; +def F2_sffixupd : T_MInstFloat < "sffixupd", 0b110, 0b001>; +} + +// F2_sfrecipa: Reciprocal approximation for division. +let Uses = [USR], isPredicateLate = 1, isFP = 1, +hasSideEffects = 0, hasNewValue = 1, isCodeGenOnly = 0 in +def F2_sfrecipa: MInst < + (outs IntRegs:$Rd, PredRegs:$Pe), + (ins IntRegs:$Rs, IntRegs:$Rt), + "$Rd, $Pe = sfrecipa($Rs, $Rt)">, + Requires<[HasV5T]> { + bits<5> Rd; + bits<2> Pe; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1110; + let Inst{27-21} = 0b1011111; + let Inst{20-16} = Rs; + let Inst{13} = 0b0; + let Inst{12-8} = Rt; + let Inst{7} = 0b1; + let Inst{6-5} = Pe; + let Inst{4-0} = Rd; + } + +// F2_dfcmpeq: Floating point compare for equal. +let Uses = [USR], isCompare = 1, isFP = 1 in +class T_fcmp MinOp, + list pattern = [] > + : ALU64Inst <(outs PredRegs:$dst), (ins RC:$src1, RC:$src2), + "$dst = "#mnemonic#"($src1, $src2)", pattern, + "" , ALU64_tc_2early_SLOT23 > , + Requires<[HasV5T]> { + bits<2> dst; + bits<5> src1; + bits<5> src2; + + let IClass = 0b1101; + + let Inst{27-21} = 0b0010111; + let Inst{20-16} = src1; + let Inst{12-8} = src2; + let Inst{7-5} = MinOp; + let Inst{1-0} = dst; + } + +class T_fcmp64 MinOp> + : T_fcmp { + let IClass = 0b1101; + let Inst{27-21} = 0b0010111; +} + +class T_fcmp32 MinOp> + : T_fcmp { + let IClass = 0b1100; + let Inst{27-21} = 0b0111111; +} + +let isCodeGenOnly = 0 in { +def F2_dfcmpeq : T_fcmp64<"dfcmp.eq", setoeq, 0b000>; +def F2_dfcmpgt : T_fcmp64<"dfcmp.gt", setogt, 0b001>; +def F2_dfcmpge : T_fcmp64<"dfcmp.ge", setoge, 0b010>; +def F2_dfcmpuo : T_fcmp64<"dfcmp.uo", setuo, 0b011>; + +def F2_sfcmpge : T_fcmp32<"sfcmp.ge", setoge, 0b000>; +def F2_sfcmpuo : T_fcmp32<"sfcmp.uo", setuo, 0b001>; +def F2_sfcmpeq : T_fcmp32<"sfcmp.eq", setoeq, 0b011>; +def F2_sfcmpgt : T_fcmp32<"sfcmp.gt", setogt, 0b100>; +} + +// F2 convert template classes: +let Uses = [USR], isFP = 1 in +class F2_RDD_RSS_CONVERT MinOp, + SDNode Op, PatLeaf RCOut, PatLeaf RCIn, + string chop =""> + : SInst <(outs DoubleRegs:$Rdd), (ins DoubleRegs:$Rss), + "$Rdd = "#mnemonic#"($Rss)"#chop, + [(set RCOut:$Rdd, (Op RCIn:$Rss))], "", + S_2op_tc_3or4x_SLOT23> { + bits<5> Rdd; + bits<5> Rss; + + let IClass = 0b1000; + + let Inst{27-21} = 0b0000111; + let Inst{20-16} = Rss; + let Inst{7-5} = MinOp; + let Inst{4-0} = Rdd; + } + +let Uses = [USR], isFP = 1 in +class F2_RDD_RS_CONVERT MinOp, + SDNode Op, PatLeaf RCOut, PatLeaf RCIn, + string chop =""> + : SInst <(outs DoubleRegs:$Rdd), (ins IntRegs:$Rs), + "$Rdd = "#mnemonic#"($Rs)"#chop, + [(set RCOut:$Rdd, (Op RCIn:$Rs))], "", + S_2op_tc_3or4x_SLOT23> { + bits<5> Rdd; + bits<5> Rs; + + let IClass = 0b1000; + + let Inst{27-21} = 0b0100100; + let Inst{20-16} = Rs; + let Inst{7-5} = MinOp; + let Inst{4-0} = Rdd; + } + +let Uses = [USR], isFP = 1, hasNewValue = 1 in +class F2_RD_RSS_CONVERT MinOp, + SDNode Op, PatLeaf RCOut, PatLeaf RCIn, + string chop =""> + : SInst <(outs IntRegs:$Rd), (ins DoubleRegs:$Rss), + "$Rd = "#mnemonic#"($Rss)"#chop, + [(set RCOut:$Rd, (Op RCIn:$Rss))], "", + S_2op_tc_3or4x_SLOT23> { + bits<5> Rd; + bits<5> Rss; + + let IClass = 0b1000; + + let Inst{27-24} = 0b1000; + let Inst{23-21} = MinOp; + let Inst{20-16} = Rss; + let Inst{7-5} = 0b001; + let Inst{4-0} = Rd; + } + +let Uses = [USR], isFP = 1, hasNewValue = 1 in +class F2_RD_RS_CONVERT MajOp, bits<3> MinOp, + SDNode Op, PatLeaf RCOut, PatLeaf RCIn, + string chop =""> + : SInst <(outs IntRegs:$Rd), (ins IntRegs:$Rs), + "$Rd = "#mnemonic#"($Rs)"#chop, + [(set RCOut:$Rd, (Op RCIn:$Rs))], "", + S_2op_tc_3or4x_SLOT23> { + bits<5> Rd; + bits<5> Rs; + + let IClass = 0b1000; + + let Inst{27-24} = 0b1011; + let Inst{23-21} = MajOp; + let Inst{20-16} = Rs; + let Inst{7-5} = MinOp; + let Inst{4-0} = Rd; + } + +// Convert single precision to double precision and vice-versa. +let isCodeGenOnly = 0 in { +def F2_conv_sf2df : F2_RDD_RS_CONVERT <"convert_sf2df", 0b000, + fextend, F64, F32>; + +def F2_conv_df2sf : F2_RD_RSS_CONVERT <"convert_df2sf", 0b000, + fround, F32, F64>; + +// Convert Integer to Floating Point. +def F2_conv_d2sf : F2_RD_RSS_CONVERT <"convert_d2sf", 0b010, + sint_to_fp, F32, I64>; +def F2_conv_ud2sf : F2_RD_RSS_CONVERT <"convert_ud2sf", 0b001, + uint_to_fp, F32, I64>; +def F2_conv_uw2sf : F2_RD_RS_CONVERT <"convert_uw2sf", 0b001, 0b000, + uint_to_fp, F32, I32>; +def F2_conv_w2sf : F2_RD_RS_CONVERT <"convert_w2sf", 0b010, 0b000, + sint_to_fp, F32, I32>; +def F2_conv_d2df : F2_RDD_RSS_CONVERT <"convert_d2df", 0b011, + sint_to_fp, F64, I64>; +def F2_conv_ud2df : F2_RDD_RSS_CONVERT <"convert_ud2df", 0b010, + uint_to_fp, F64, I64>; +def F2_conv_uw2df : F2_RDD_RS_CONVERT <"convert_uw2df", 0b001, + uint_to_fp, F64, I32>; +def F2_conv_w2df : F2_RDD_RS_CONVERT <"convert_w2df", 0b010, + sint_to_fp, F64, I32>; + +// Convert Floating Point to Integer - default. +def F2_conv_df2uw_chop : F2_RD_RSS_CONVERT <"convert_df2uw", 0b101, + fp_to_uint, I32, F64, ":chop">; +def F2_conv_df2w_chop : F2_RD_RSS_CONVERT <"convert_df2w", 0b111, + fp_to_sint, I32, F64, ":chop">; +def F2_conv_sf2uw_chop : F2_RD_RS_CONVERT <"convert_sf2uw", 0b011, 0b001, + fp_to_uint, I32, F32, ":chop">; +def F2_conv_sf2w_chop : F2_RD_RS_CONVERT <"convert_sf2w", 0b100, 0b001, + fp_to_sint, I32, F32, ":chop">; +def F2_conv_df2d_chop : F2_RDD_RSS_CONVERT <"convert_df2d", 0b110, + fp_to_sint, I64, F64, ":chop">; +def F2_conv_df2ud_chop : F2_RDD_RSS_CONVERT <"convert_df2ud", 0b111, + fp_to_uint, I64, F64, ":chop">; +def F2_conv_sf2d_chop : F2_RDD_RS_CONVERT <"convert_sf2d", 0b110, + fp_to_sint, I64, F32, ":chop">; +def F2_conv_sf2ud_chop : F2_RDD_RS_CONVERT <"convert_sf2ud", 0b101, + fp_to_uint, I64, F32, ":chop">; + +// Convert Floating Point to Integer: non-chopped. +let AddedComplexity = 20, Predicates = [HasV5T, IEEERndNearV5T] in { + def F2_conv_df2d : F2_RDD_RSS_CONVERT <"convert_df2d", 0b000, + fp_to_sint, I64, F64>; + def F2_conv_df2ud : F2_RDD_RSS_CONVERT <"convert_df2ud", 0b001, + fp_to_uint, I64, F64>; + def F2_conv_sf2ud : F2_RDD_RS_CONVERT <"convert_sf2ud", 0b011, + fp_to_uint, I64, F32>; + def F2_conv_sf2d : F2_RDD_RS_CONVERT <"convert_sf2d", 0b100, + fp_to_sint, I64, F32>; + def F2_conv_df2uw : F2_RD_RSS_CONVERT <"convert_df2uw", 0b011, + fp_to_uint, I32, F64>; + def F2_conv_df2w : F2_RD_RSS_CONVERT <"convert_df2w", 0b100, + fp_to_sint, I32, F64>; + def F2_conv_sf2uw : F2_RD_RS_CONVERT <"convert_sf2uw", 0b011, 0b000, + fp_to_uint, I32, F32>; + def F2_conv_sf2w : F2_RD_RS_CONVERT <"convert_sf2w", 0b100, 0b000, + fp_to_sint, I32, F32>; +} +} + +// Fix up radicand. +let Uses = [USR], isFP = 1, hasNewValue = 1, isCodeGenOnly = 0 in +def F2_sffixupr: SInst<(outs IntRegs:$Rd), (ins IntRegs:$Rs), + "$Rd = sffixupr($Rs)", + [], "" , S_2op_tc_3or4x_SLOT23>, Requires<[HasV5T]> { + bits<5> Rd; + bits<5> Rs; + + let IClass = 0b1000; + + let Inst{27-21} = 0b1011101; + let Inst{20-16} = Rs; + let Inst{7-5} = 0b000; + let Inst{4-0} = Rd; + } + +// F2_sffma: Floating-point fused multiply add. +let Uses = [USR], isFP = 1, hasNewValue = 1 in +class T_sfmpy_acc + : MInst<(outs IntRegs:$Rx), + (ins IntRegs:$dst2, IntRegs:$Rs, IntRegs:$Rt), + "$Rx "#!if(isSub, "-=","+=")#" sfmpy($Rs, $Rt)"#!if(isLib, ":lib",""), + [], "$dst2 = $Rx" , M_tc_3_SLOT23 > , + Requires<[HasV5T]> { + bits<5> Rx; + bits<5> Rs; + bits<5> Rt; + + let IClass = 0b1110; + + let Inst{27-21} = 0b1111000; + let Inst{20-16} = Rs; + let Inst{13} = 0b0; + let Inst{12-8} = Rt; + let Inst{7} = 0b1; + let Inst{6} = isLib; + let Inst{5} = isSub; + let Inst{4-0} = Rx; + } + +let isCodeGenOnly = 0 in { +def F2_sffma: T_sfmpy_acc <0, 0>; +def F2_sffms: T_sfmpy_acc <1, 0>; +def F2_sffma_lib: T_sfmpy_acc <0, 1>; +def F2_sffms_lib: T_sfmpy_acc <1, 1>; +} + +// Floating-point fused multiply add w/ additional scaling (2**pu). +let Uses = [USR], isFP = 1, hasNewValue = 1, isCodeGenOnly = 0 in +def F2_sffma_sc: MInst < + (outs IntRegs:$Rx), + (ins IntRegs:$dst2, IntRegs:$Rs, IntRegs:$Rt, PredRegs:$Pu), + "$Rx += sfmpy($Rs, $Rt, $Pu):scale" , + [], "$dst2 = $Rx" , M_tc_3_SLOT23 > , + Requires<[HasV5T]> { + bits<5> Rx; + bits<5> Rs; + bits<5> Rt; + bits<2> Pu; + + let IClass = 0b1110; + + let Inst{27-21} = 0b1111011; + let Inst{20-16} = Rs; + let Inst{13} = 0b0; + let Inst{12-8} = Rt; + let Inst{7} = 0b1; + let Inst{6-5} = Pu; + let Inst{4-0} = Rx; + } + + // Convert single precision to double precision and vice-versa. def CONVERT_sf2df : ALU64_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src), "$dst = convert_sf2df($src)", diff --git a/test/MC/Disassembler/Hexagon/xtype_fp.txt b/test/MC/Disassembler/Hexagon/xtype_fp.txt new file mode 100644 index 00000000000..d41e9ac1c1c --- /dev/null +++ b/test/MC/Disassembler/Hexagon/xtype_fp.txt @@ -0,0 +1,98 @@ +# RUN: llvm-mc --triple hexagon -disassemble < %s | FileCheck %s + +0x11 0xdf 0x15 0xeb +# CHECK: r17 = sfadd(r21, r31) +0x03 0xd5 0xf1 0xc7 +# CHECK: p3 = sfcmp.ge(r17, r21) +0x23 0xd5 0xf1 0xc7 +# CHECK: p3 = sfcmp.uo(r17, r21) +0x63 0xd5 0xf1 0xc7 +# CHECK: p3 = sfcmp.eq(r17, r21) +0x83 0xd5 0xf1 0xc7 +# CHECK: p3 = sfcmp.gt(r17, r21) +0x03 0xd4 0xf0 0xd2 +# CHECK: p3 = dfcmp.eq(r17:16, r21:20) +0x23 0xd4 0xf0 0xd2 +# CHECK: p3 = dfcmp.gt(r17:16, r21:20) +0x43 0xd4 0xf0 0xd2 +# CHECK: p3 = dfcmp.ge(r17:16, r21:20) +0x63 0xd4 0xf0 0xd2 +# CHECK: p3 = dfcmp.uo(r17:16, r21:20) +0x10 0xc0 0x95 0x84 +# CHECK: r17:16 = convert_sf2df(r21) +0x31 0xc0 0x14 0x88 +# CHECK: r17 = convert_df2sf(r21:20) +0x50 0xc0 0xf4 0x80 +# CHECK: r17:16 = convert_ud2df(r21:20) +0x70 0xc0 0xf4 0x80 +# CHECK: r17:16 = convert_d2df(r21:20) +0x30 0xc0 0x95 0x84 +# CHECK: r17:16 = convert_uw2df(r21) +0x50 0xc0 0x95 0x84 +# CHECK: r17:16 = convert_w2df(r21) +0x31 0xc0 0x34 0x88 +# CHECK: r17 = convert_ud2sf(r21:20) +0x31 0xc0 0x54 0x88 +# CHECK: r17 = convert_d2sf(r21:20) +0x11 0xc0 0x35 0x8b +# CHECK: r17 = convert_uw2sf(r21) +0x11 0xc0 0x55 0x8b +# CHECK: r17 = convert_w2sf(r21) +0x10 0xc0 0xf4 0x80 +# CHECK: r17:16 = convert_df2d(r21:20) +0x30 0xc0 0xf4 0x80 +# CHECK: r17:16 = convert_df2ud(r21:20) +0xd0 0xc0 0xf4 0x80 +# CHECK: r17:16 = convert_df2d(r21:20):chop +0xf0 0xc0 0xf4 0x80 +# CHECK: r17:16 = convert_df2ud(r21:20):chop +0x70 0xc0 0x95 0x84 +# CHECK: r17:16 = convert_sf2ud(r21) +0x90 0xc0 0x95 0x84 +# CHECK: r17:16 = convert_sf2d(r21) +0xb0 0xc0 0x95 0x84 +# CHECK: r17:16 = convert_sf2ud(r21):chop +0xd0 0xc0 0x95 0x84 +# CHECK: r17:16 = convert_sf2d(r21):chop +0x31 0xc0 0x74 0x88 +# CHECK: r17 = convert_df2uw(r21:20) +0x31 0xc0 0x94 0x88 +# CHECK: r17 = convert_df2w(r21:20) +0x31 0xc0 0xb4 0x88 +# CHECK: r17 = convert_df2uw(r21:20):chop +0x31 0xc0 0xf4 0x88 +# CHECK: r17 = convert_df2w(r21:20):chop +0x11 0xc0 0x75 0x8b +# CHECK: r17 = convert_sf2uw(r21) +0x31 0xc0 0x75 0x8b +# CHECK: r17 = convert_sf2uw(r21):chop +0x11 0xc0 0x95 0x8b +# CHECK: r17 = convert_sf2w(r21) +0x31 0xc0 0x95 0x8b +# CHECK: r17 = convert_sf2w(r21):chop +0x11 0xc0 0xb5 0x8b +# CHECK: r17 = sffixupr(r21) +0x11 0xdf 0xd5 0xeb +# CHECK: r17 = sffixupn(r21, r31) +0x31 0xdf 0xd5 0xeb +# CHECK: r17 = sffixupd(r21, r31) +0x91 0xdf 0x15 0xef +# CHECK: r17 += sfmpy(r21, r31) +0xb1 0xdf 0x15 0xef +# CHECK: r17 -= sfmpy(r21, r31) +0xf1 0xdf 0x75 0xef +# CHECK: r17 += sfmpy(r21, r31, p3):scale +0xd1 0xdf 0x15 0xef +# CHECK: r17 += sfmpy(r21, r31):lib +0xf1 0xdf 0x15 0xef +# CHECK: r17 -= sfmpy(r21, r31):lib +0x11 0xdf 0x95 0xeb +# CHECK: r17 = sfmax(r21, r31) +0x31 0xdf 0x95 0xeb +# CHECK: r17 = sfmin(r21, r31) +0x11 0xdf 0x55 0xeb +# CHECK: r17 = sfmpy(r21, r31) +0xf1 0xdf 0xf5 0xeb +# CHECK: r17, p3 = sfrecipa(r21, r31) +0x31 0xdf 0x15 0xeb +# CHECK: r17 = sfsub(r21, r31)