Mercurial > hg > CbC > CbC_gcc
diff gcc/config/rs6000/dfp.md @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | b7f97abdc517 |
children | 84e7813d76e9 |
line wrap: on
line diff
--- a/gcc/config/rs6000/dfp.md Sun Aug 21 07:07:55 2011 +0900 +++ b/gcc/config/rs6000/dfp.md Fri Oct 27 22:46:09 2017 +0900 @@ -1,6 +1,5 @@ ;; Decimal Floating Point (DFP) patterns. -;; Copyright (C) 2007, 2008, 2010 -;; Free Software Foundation, Inc. +;; Copyright (C) 2007-2017 Free Software Foundation, Inc. ;; Contributed by Ben Elliston (bje@au.ibm.com) and Peter Bergner ;; (bergner@vnet.ibm.com). @@ -24,92 +23,19 @@ ;; UNSPEC usage ;; -(define_constants - [(UNSPEC_MOVSD_LOAD 400) - (UNSPEC_MOVSD_STORE 401) +(define_c_enum "unspec" + [UNSPEC_MOVSD_LOAD + UNSPEC_MOVSD_STORE ]) -(define_expand "movsd" - [(set (match_operand:SD 0 "nonimmediate_operand" "") - (match_operand:SD 1 "any_operand" ""))] - "TARGET_HARD_FLOAT && TARGET_FPRS" - "{ rs6000_emit_move (operands[0], operands[1], SDmode); DONE; }") - -(define_split - [(set (match_operand:SD 0 "gpc_reg_operand" "") - (match_operand:SD 1 "const_double_operand" ""))] - "reload_completed - && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31) - || (GET_CODE (operands[0]) == SUBREG - && GET_CODE (SUBREG_REG (operands[0])) == REG - && REGNO (SUBREG_REG (operands[0])) <= 31))" - [(set (match_dup 2) (match_dup 3))] - " -{ - long l; - REAL_VALUE_TYPE rv; - - REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); - REAL_VALUE_TO_TARGET_DECIMAL32 (rv, l); - - if (! TARGET_POWERPC64) - operands[2] = operand_subword (operands[0], 0, 0, SDmode); - else - operands[2] = gen_lowpart (SImode, operands[0]); - - operands[3] = gen_int_mode (l, SImode); -}") - -(define_insn "movsd_hardfloat" - [(set (match_operand:SD 0 "nonimmediate_operand" "=r,r,m,f,*c*l,*q,!r,*h,!r,!r") - (match_operand:SD 1 "input_operand" "r,m,r,f,r,r,h,0,G,Fn"))] - "(gpc_reg_operand (operands[0], SDmode) - || gpc_reg_operand (operands[1], SDmode)) - && (TARGET_HARD_FLOAT && TARGET_FPRS)" - "@ - mr %0,%1 - {l%U1%X1|lwz%U1%X1} %0,%1 - {st%U0%X0|stw%U0%X0} %1,%0 - fmr %0,%1 - mt%0 %1 - mt%0 %1 - mf%1 %0 - {cror 0,0,0|nop} - # - #" - [(set_attr "type" "*,load,store,fp,mtjmpr,*,mfjmpr,*,*,*") - (set_attr "length" "4,4,4,4,4,4,4,4,4,8")]) - -(define_insn "movsd_softfloat" - [(set (match_operand:SD 0 "nonimmediate_operand" "=r,cl,q,r,r,m,r,r,r,r,r,*h") - (match_operand:SD 1 "input_operand" "r,r,r,h,m,r,I,L,R,G,Fn,0"))] - "(gpc_reg_operand (operands[0], SDmode) - || gpc_reg_operand (operands[1], SDmode)) - && (TARGET_SOFT_FLOAT || !TARGET_FPRS)" - "@ - mr %0,%1 - mt%0 %1 - mt%0 %1 - mf%1 %0 - {l%U1%X1|lwz%U1%X1} %0,%1 - {st%U0%X0|stw%U0%X0} %1,%0 - {lil|li} %0,%1 - {liu|lis} %0,%v1 - {cal|la} %0,%a1 - # - # - {cror 0,0,0|nop}" - [(set_attr "type" "*,mtjmpr,*,mfjmpr,load,store,*,*,*,*,*,*") - (set_attr "length" "4,4,4,4,4,4,4,4,4,4,8,4")]) - (define_insn "movsd_store" [(set (match_operand:DD 0 "nonimmediate_operand" "=m") (unspec:DD [(match_operand:SD 1 "input_operand" "d")] UNSPEC_MOVSD_STORE))] "(gpc_reg_operand (operands[0], DDmode) || gpc_reg_operand (operands[1], SDmode)) - && TARGET_HARD_FLOAT && TARGET_FPRS" + && TARGET_HARD_FLOAT" "stfd%U0%X0 %1,%0" [(set_attr "type" "fpstore") (set_attr "length" "4")]) @@ -120,7 +46,7 @@ UNSPEC_MOVSD_LOAD))] "(gpc_reg_operand (operands[0], SDmode) || gpc_reg_operand (operands[1], DDmode)) - && TARGET_HARD_FLOAT && TARGET_FPRS" + && TARGET_HARD_FLOAT" "lfd%U1%X1 %0,%1" [(set_attr "type" "fpload") (set_attr "length" "4")]) @@ -132,7 +58,7 @@ (float_extend:DD (match_operand:SD 1 "gpc_reg_operand" "f")))] "TARGET_DFP" "dctdp %0,%1" - [(set_attr "type" "fp")]) + [(set_attr "type" "dfp")]) (define_expand "extendsdtd2" [(set (match_operand:TD 0 "gpc_reg_operand" "=d") @@ -150,299 +76,58 @@ (float_truncate:SD (match_operand:DD 1 "gpc_reg_operand" "d")))] "TARGET_DFP" "drsp %0,%1" - [(set_attr "type" "fp")]) + [(set_attr "type" "dfp")]) -(define_expand "negdd2" - [(set (match_operand:DD 0 "gpc_reg_operand" "") - (neg:DD (match_operand:DD 1 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_FPRS" - "") - -(define_insn "*negdd2_fpr" +(define_insn "negdd2" [(set (match_operand:DD 0 "gpc_reg_operand" "=d") (neg:DD (match_operand:DD 1 "gpc_reg_operand" "d")))] - "TARGET_HARD_FLOAT && TARGET_FPRS" + "TARGET_HARD_FLOAT" "fneg %0,%1" - [(set_attr "type" "fp")]) + [(set_attr "type" "fpsimple")]) -(define_expand "absdd2" - [(set (match_operand:DD 0 "gpc_reg_operand" "") - (abs:DD (match_operand:DD 1 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_FPRS" - "") - -(define_insn "*absdd2_fpr" +(define_insn "absdd2" [(set (match_operand:DD 0 "gpc_reg_operand" "=d") (abs:DD (match_operand:DD 1 "gpc_reg_operand" "d")))] - "TARGET_HARD_FLOAT && TARGET_FPRS" + "TARGET_HARD_FLOAT" "fabs %0,%1" - [(set_attr "type" "fp")]) + [(set_attr "type" "fpsimple")]) (define_insn "*nabsdd2_fpr" [(set (match_operand:DD 0 "gpc_reg_operand" "=d") (neg:DD (abs:DD (match_operand:DD 1 "gpc_reg_operand" "d"))))] - "TARGET_HARD_FLOAT && TARGET_FPRS" + "TARGET_HARD_FLOAT" "fnabs %0,%1" - [(set_attr "type" "fp")]) - -(define_expand "movdd" - [(set (match_operand:DD 0 "nonimmediate_operand" "") - (match_operand:DD 1 "any_operand" ""))] - "" - "{ rs6000_emit_move (operands[0], operands[1], DDmode); DONE; }") - -(define_split - [(set (match_operand:DD 0 "gpc_reg_operand" "") - (match_operand:DD 1 "const_int_operand" ""))] - "! TARGET_POWERPC64 && reload_completed - && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31) - || (GET_CODE (operands[0]) == SUBREG - && GET_CODE (SUBREG_REG (operands[0])) == REG - && REGNO (SUBREG_REG (operands[0])) <= 31))" - [(set (match_dup 2) (match_dup 4)) - (set (match_dup 3) (match_dup 1))] - " -{ - int endian = (WORDS_BIG_ENDIAN == 0); - HOST_WIDE_INT value = INTVAL (operands[1]); - - operands[2] = operand_subword (operands[0], endian, 0, DDmode); - operands[3] = operand_subword (operands[0], 1 - endian, 0, DDmode); -#if HOST_BITS_PER_WIDE_INT == 32 - operands[4] = (value & 0x80000000) ? constm1_rtx : const0_rtx; -#else - operands[4] = GEN_INT (value >> 32); - operands[1] = GEN_INT (((value & 0xffffffff) ^ 0x80000000) - 0x80000000); -#endif -}") - -(define_split - [(set (match_operand:DD 0 "gpc_reg_operand" "") - (match_operand:DD 1 "const_double_operand" ""))] - "! TARGET_POWERPC64 && reload_completed - && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31) - || (GET_CODE (operands[0]) == SUBREG - && GET_CODE (SUBREG_REG (operands[0])) == REG - && REGNO (SUBREG_REG (operands[0])) <= 31))" - [(set (match_dup 2) (match_dup 4)) - (set (match_dup 3) (match_dup 5))] - " -{ - int endian = (WORDS_BIG_ENDIAN == 0); - long l[2]; - REAL_VALUE_TYPE rv; - - REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); - REAL_VALUE_TO_TARGET_DECIMAL64 (rv, l); - - operands[2] = operand_subword (operands[0], endian, 0, DDmode); - operands[3] = operand_subword (operands[0], 1 - endian, 0, DDmode); - operands[4] = gen_int_mode (l[endian], SImode); - operands[5] = gen_int_mode (l[1 - endian], SImode); -}") - -(define_split - [(set (match_operand:DD 0 "gpc_reg_operand" "") - (match_operand:DD 1 "const_double_operand" ""))] - "TARGET_POWERPC64 && reload_completed - && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31) - || (GET_CODE (operands[0]) == SUBREG - && GET_CODE (SUBREG_REG (operands[0])) == REG - && REGNO (SUBREG_REG (operands[0])) <= 31))" - [(set (match_dup 2) (match_dup 3))] - " -{ - int endian = (WORDS_BIG_ENDIAN == 0); - long l[2]; - REAL_VALUE_TYPE rv; -#if HOST_BITS_PER_WIDE_INT >= 64 - HOST_WIDE_INT val; -#endif - - REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); - REAL_VALUE_TO_TARGET_DECIMAL64 (rv, l); - - operands[2] = gen_lowpart (DImode, operands[0]); - /* HIGHPART is lower memory address when WORDS_BIG_ENDIAN. */ -#if HOST_BITS_PER_WIDE_INT >= 64 - val = ((HOST_WIDE_INT)(unsigned long)l[endian] << 32 - | ((HOST_WIDE_INT)(unsigned long)l[1 - endian])); - - operands[3] = gen_int_mode (val, DImode); -#else - operands[3] = immed_double_const (l[1 - endian], l[endian], DImode); -#endif -}") + [(set_attr "type" "fpsimple")]) -;; Don't have reload use general registers to load a constant. First, -;; it might not work if the output operand is the equivalent of -;; a non-offsettable memref, but also it is less efficient than loading -;; the constant into an FP register, since it will probably be used there. -;; The "??" is a kludge until we can figure out a more reasonable way -;; of handling these non-offsettable values. -(define_insn "*movdd_hardfloat32" - [(set (match_operand:DD 0 "nonimmediate_operand" "=!r,??r,m,d,d,m,!r,!r,!r") - (match_operand:DD 1 "input_operand" "r,m,r,d,m,d,G,H,F"))] - "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS - && (gpc_reg_operand (operands[0], DDmode) - || gpc_reg_operand (operands[1], DDmode))" - "* -{ - switch (which_alternative) - { - default: - gcc_unreachable (); - case 0: - case 1: - case 2: - return \"#\"; - case 3: - return \"fmr %0,%1\"; - case 4: - return \"lfd%U1%X1 %0,%1\"; - case 5: - return \"stfd%U0%X0 %1,%0\"; - case 6: - case 7: - case 8: - return \"#\"; - } -}" - [(set_attr "type" "two,load,store,fp,fpload,fpstore,*,*,*") - (set_attr "length" "8,16,16,4,4,4,8,12,16")]) - -(define_insn "*movdd_softfloat32" - [(set (match_operand:DD 0 "nonimmediate_operand" "=r,r,m,r,r,r") - (match_operand:DD 1 "input_operand" "r,m,r,G,H,F"))] - "! TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS) - && (gpc_reg_operand (operands[0], DDmode) - || gpc_reg_operand (operands[1], DDmode))" - "#" - [(set_attr "type" "two,load,store,*,*,*") - (set_attr "length" "8,8,8,8,12,16")]) - -; ld/std require word-aligned displacements -> 'Y' constraint. -; List Y->r and r->Y before r->r for reload. -(define_insn "*movdd_hardfloat64_mfpgpr" - [(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,d,d,m,*c*l,!r,*h,!r,!r,!r,r,d") - (match_operand:DD 1 "input_operand" "r,Y,r,d,m,d,r,h,0,G,H,F,d,r"))] - "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS - && (gpc_reg_operand (operands[0], DDmode) - || gpc_reg_operand (operands[1], DDmode))" +(define_insn "negtd2" + [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d") + (neg:TD (match_operand:TD 1 "gpc_reg_operand" "0,d")))] + "TARGET_HARD_FLOAT" "@ - std%U0%X0 %1,%0 - ld%U1%X1 %0,%1 - mr %0,%1 - fmr %0,%1 - lfd%U1%X1 %0,%1 - stfd%U0%X0 %1,%0 - mt%0 %1 - mf%1 %0 - {cror 0,0,0|nop} - # - # - # - mftgpr %0,%1 - mffgpr %0,%1" - [(set_attr "type" "store,load,*,fp,fpload,fpstore,mtjmpr,mfjmpr,*,*,*,*,mftgpr,mffgpr") - (set_attr "length" "4,4,4,4,4,4,4,4,4,8,12,16,4,4")]) - -; ld/std require word-aligned displacements -> 'Y' constraint. -; List Y->r and r->Y before r->r for reload. -(define_insn "*movdd_hardfloat64" - [(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,d,d,m,*c*l,!r,*h,!r,!r,!r") - (match_operand:DD 1 "input_operand" "r,Y,r,d,m,d,r,h,0,G,H,F"))] - "TARGET_POWERPC64 && !TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS - && (gpc_reg_operand (operands[0], DDmode) - || gpc_reg_operand (operands[1], DDmode))" - "@ - std%U0%X0 %1,%0 - ld%U1%X1 %0,%1 - mr %0,%1 - fmr %0,%1 - lfd%U1%X1 %0,%1 - stfd%U0%X0 %1,%0 - mt%0 %1 - mf%1 %0 - {cror 0,0,0|nop} - # - # - #" - [(set_attr "type" "store,load,*,fp,fpload,fpstore,mtjmpr,mfjmpr,*,*,*,*") - (set_attr "length" "4,4,4,4,4,4,4,4,4,8,12,16")]) + fneg %0,%1 + fneg %0,%1\;fmr %L0,%L1" + [(set_attr "type" "fpsimple") + (set_attr "length" "4,8")]) -(define_insn "*movdd_softfloat64" - [(set (match_operand:DD 0 "nonimmediate_operand" "=r,Y,r,cl,r,r,r,r,*h") - (match_operand:DD 1 "input_operand" "Y,r,r,r,h,G,H,F,0"))] - "TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS) - && (gpc_reg_operand (operands[0], DDmode) - || gpc_reg_operand (operands[1], DDmode))" +(define_insn "abstd2" + [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d") + (abs:TD (match_operand:TD 1 "gpc_reg_operand" "0,d")))] + "TARGET_HARD_FLOAT" "@ - ld%U1%X1 %0,%1 - std%U0%X0 %1,%0 - mr %0,%1 - mt%0 %1 - mf%1 %0 - # - # - # - {cror 0,0,0|nop}" - [(set_attr "type" "load,store,*,mtjmpr,mfjmpr,*,*,*,*") - (set_attr "length" "4,4,4,4,4,8,12,16,4")]) - -(define_expand "negtd2" - [(set (match_operand:TD 0 "gpc_reg_operand" "") - (neg:TD (match_operand:TD 1 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_FPRS" - "") - -(define_insn "*negtd2_fpr" - [(set (match_operand:TD 0 "gpc_reg_operand" "=d") - (neg:TD (match_operand:TD 1 "gpc_reg_operand" "d")))] - "TARGET_HARD_FLOAT && TARGET_FPRS" - "fneg %0,%1" - [(set_attr "type" "fp")]) - -(define_expand "abstd2" - [(set (match_operand:TD 0 "gpc_reg_operand" "") - (abs:TD (match_operand:TD 1 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_FPRS" - "") - -(define_insn "*abstd2_fpr" - [(set (match_operand:TD 0 "gpc_reg_operand" "=d") - (abs:TD (match_operand:TD 1 "gpc_reg_operand" "d")))] - "TARGET_HARD_FLOAT && TARGET_FPRS" - "fabs %0,%1" - [(set_attr "type" "fp")]) + fabs %0,%1 + fabs %0,%1\;fmr %L0,%L1" + [(set_attr "type" "fpsimple") + (set_attr "length" "4,8")]) (define_insn "*nabstd2_fpr" - [(set (match_operand:TD 0 "gpc_reg_operand" "=d") - (neg:TD (abs:TD (match_operand:TD 1 "gpc_reg_operand" "d"))))] - "TARGET_HARD_FLOAT && TARGET_FPRS" - "fnabs %0,%1" - [(set_attr "type" "fp")]) - -(define_expand "movtd" - [(set (match_operand:TD 0 "general_operand" "") - (match_operand:TD 1 "any_operand" ""))] - "TARGET_HARD_FLOAT && TARGET_FPRS" - "{ rs6000_emit_move (operands[0], operands[1], TDmode); DONE; }") - -; It's important to list the o->f and f->o moves before f->f because -; otherwise reload, given m->f, will try to pick f->f and reload it, -; which doesn't make progress. Likewise r->Y must be before r->r. -(define_insn_and_split "*movtd_internal" - [(set (match_operand:TD 0 "nonimmediate_operand" "=o,d,d,r,Y,r") - (match_operand:TD 1 "input_operand" "d,o,d,YGHF,r,r"))] - "TARGET_HARD_FLOAT && TARGET_FPRS - && (gpc_reg_operand (operands[0], TDmode) - || gpc_reg_operand (operands[1], TDmode))" - "#" - "&& reload_completed" - [(pc)] -{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; } - [(set_attr "length" "8,8,8,20,20,16")]) + [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d") + (neg:TD (abs:TD (match_operand:TD 1 "gpc_reg_operand" "0,d"))))] + "TARGET_HARD_FLOAT" + "@ + fnabs %0,%1 + fnabs %0,%1\;fmr %L0,%L1" + [(set_attr "type" "fpsimple") + (set_attr "length" "4,8")]) ;; Hardware support for decimal floating point operations. @@ -451,7 +136,7 @@ (float_extend:TD (match_operand:DD 1 "gpc_reg_operand" "d")))] "TARGET_DFP" "dctqpq %0,%1" - [(set_attr "type" "fp")]) + [(set_attr "type" "dfp")]) ;; The result of drdpq is an even/odd register pair with the converted ;; value in the even register and zero in the odd register. @@ -464,7 +149,8 @@ (clobber (match_scratch:TD 2 "=d"))] "TARGET_DFP" "drdpq %2,%1\;fmr %0,%2" - [(set_attr "type" "fp")]) + [(set_attr "type" "dfp") + (set_attr "length" "8")]) (define_insn "adddd3" [(set (match_operand:DD 0 "gpc_reg_operand" "=d") @@ -472,7 +158,7 @@ (match_operand:DD 2 "gpc_reg_operand" "d")))] "TARGET_DFP" "dadd %0,%1,%2" - [(set_attr "type" "fp")]) + [(set_attr "type" "dfp")]) (define_insn "addtd3" [(set (match_operand:TD 0 "gpc_reg_operand" "=d") @@ -480,7 +166,7 @@ (match_operand:TD 2 "gpc_reg_operand" "d")))] "TARGET_DFP" "daddq %0,%1,%2" - [(set_attr "type" "fp")]) + [(set_attr "type" "dfp")]) (define_insn "subdd3" [(set (match_operand:DD 0 "gpc_reg_operand" "=d") @@ -488,7 +174,7 @@ (match_operand:DD 2 "gpc_reg_operand" "d")))] "TARGET_DFP" "dsub %0,%1,%2" - [(set_attr "type" "fp")]) + [(set_attr "type" "dfp")]) (define_insn "subtd3" [(set (match_operand:TD 0 "gpc_reg_operand" "=d") @@ -496,7 +182,7 @@ (match_operand:TD 2 "gpc_reg_operand" "d")))] "TARGET_DFP" "dsubq %0,%1,%2" - [(set_attr "type" "fp")]) + [(set_attr "type" "dfp")]) (define_insn "muldd3" [(set (match_operand:DD 0 "gpc_reg_operand" "=d") @@ -504,7 +190,7 @@ (match_operand:DD 2 "gpc_reg_operand" "d")))] "TARGET_DFP" "dmul %0,%1,%2" - [(set_attr "type" "fp")]) + [(set_attr "type" "dfp")]) (define_insn "multd3" [(set (match_operand:TD 0 "gpc_reg_operand" "=d") @@ -512,7 +198,7 @@ (match_operand:TD 2 "gpc_reg_operand" "d")))] "TARGET_DFP" "dmulq %0,%1,%2" - [(set_attr "type" "fp")]) + [(set_attr "type" "dfp")]) (define_insn "divdd3" [(set (match_operand:DD 0 "gpc_reg_operand" "=d") @@ -520,7 +206,7 @@ (match_operand:DD 2 "gpc_reg_operand" "d")))] "TARGET_DFP" "ddiv %0,%1,%2" - [(set_attr "type" "fp")]) + [(set_attr "type" "dfp")]) (define_insn "divtd3" [(set (match_operand:TD 0 "gpc_reg_operand" "=d") @@ -528,7 +214,7 @@ (match_operand:TD 2 "gpc_reg_operand" "d")))] "TARGET_DFP" "ddivq %0,%1,%2" - [(set_attr "type" "fp")]) + [(set_attr "type" "dfp")]) (define_insn "*cmpdd_internal1" [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") @@ -536,7 +222,7 @@ (match_operand:DD 2 "gpc_reg_operand" "d")))] "TARGET_DFP" "dcmpu %0,%1,%2" - [(set_attr "type" "fpcompare")]) + [(set_attr "type" "dfp")]) (define_insn "*cmptd_internal1" [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") @@ -544,14 +230,21 @@ (match_operand:TD 2 "gpc_reg_operand" "d")))] "TARGET_DFP" "dcmpuq %0,%1,%2" - [(set_attr "type" "fpcompare")]) + [(set_attr "type" "dfp")]) + +(define_insn "floatdidd2" + [(set (match_operand:DD 0 "gpc_reg_operand" "=d") + (float:DD (match_operand:DI 1 "gpc_reg_operand" "d")))] + "TARGET_DFP && TARGET_POPCNTD" + "dcffix %0,%1" + [(set_attr "type" "dfp")]) (define_insn "floatditd2" [(set (match_operand:TD 0 "gpc_reg_operand" "=d") (float:TD (match_operand:DI 1 "gpc_reg_operand" "d")))] "TARGET_DFP" "dcffixq %0,%1" - [(set_attr "type" "fp")]) + [(set_attr "type" "dfp")]) ;; Convert a decimal64 to a decimal64 whose value is an integer. ;; This is the first stage of converting it to an integer type. @@ -561,7 +254,7 @@ (fix:DD (match_operand:DD 1 "gpc_reg_operand" "d")))] "TARGET_DFP" "drintn. 0,%0,%1,1" - [(set_attr "type" "fp")]) + [(set_attr "type" "dfp")]) ;; Convert a decimal64 whose value is an integer to an actual integer. ;; This is the second stage of converting decimal float to integer type. @@ -571,7 +264,7 @@ (fix:DI (match_operand:DD 1 "gpc_reg_operand" "d")))] "TARGET_DFP" "dctfix %0,%1" - [(set_attr "type" "fp")]) + [(set_attr "type" "dfp")]) ;; Convert a decimal128 to a decimal128 whose value is an integer. ;; This is the first stage of converting it to an integer type. @@ -581,7 +274,7 @@ (fix:TD (match_operand:TD 1 "gpc_reg_operand" "d")))] "TARGET_DFP" "drintnq. 0,%0,%1,1" - [(set_attr "type" "fp")]) + [(set_attr "type" "dfp")]) ;; Convert a decimal128 whose value is an integer to an actual integer. ;; This is the second stage of converting decimal float to integer type. @@ -591,4 +284,112 @@ (fix:DI (match_operand:TD 1 "gpc_reg_operand" "d")))] "TARGET_DFP" "dctfixq %0,%1" + [(set_attr "type" "dfp")]) + + +;; Decimal builtin support + +(define_c_enum "unspec" + [UNSPEC_DDEDPD + UNSPEC_DENBCD + UNSPEC_DXEX + UNSPEC_DIEX + UNSPEC_DSCLI + UNSPEC_DTSTSFI + UNSPEC_DSCRI]) + +(define_code_iterator DFP_TEST [eq lt gt unordered]) + +(define_mode_iterator D64_D128 [DD TD]) + +(define_mode_attr dfp_suffix [(DD "") + (TD "q")]) + +(define_insn "dfp_ddedpd_<mode>" + [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d") + (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_3_operand" "i") + (match_operand:D64_D128 2 "gpc_reg_operand" "d")] + UNSPEC_DDEDPD))] + "TARGET_DFP" + "ddedpd<dfp_suffix> %1,%0,%2" + [(set_attr "type" "dfp")]) + +(define_insn "dfp_denbcd_<mode>" + [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d") + (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_1_operand" "i") + (match_operand:D64_D128 2 "gpc_reg_operand" "d")] + UNSPEC_DENBCD))] + "TARGET_DFP" + "denbcd<dfp_suffix> %1,%0,%2" + [(set_attr "type" "dfp")]) + +(define_insn "dfp_dxex_<mode>" + [(set (match_operand:DI 0 "gpc_reg_operand" "=d") + (unspec:DI [(match_operand:D64_D128 1 "gpc_reg_operand" "d")] + UNSPEC_DXEX))] + "TARGET_DFP" + "dxex<dfp_suffix> %0,%1" + [(set_attr "type" "dfp")]) + +(define_insn "dfp_diex_<mode>" + [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d") + (unspec:D64_D128 [(match_operand:DI 1 "gpc_reg_operand" "d") + (match_operand:D64_D128 2 "gpc_reg_operand" "d")] + UNSPEC_DXEX))] + "TARGET_DFP" + "diex<dfp_suffix> %0,%1,%2" + [(set_attr "type" "dfp")]) + +(define_expand "dfptstsfi_<code>_<mode>" + [(set (match_dup 3) + (compare:CCFP + (unspec:D64_D128 + [(match_operand:SI 1 "const_int_operand" "n") + (match_operand:D64_D128 2 "gpc_reg_operand" "d")] + UNSPEC_DTSTSFI) + (match_dup 4))) + (set (match_operand:SI 0 "register_operand" "") + (DFP_TEST:SI (match_dup 3) + (const_int 0))) + ] + "TARGET_P9_MISC" +{ + operands[3] = gen_reg_rtx (CCFPmode); + operands[4] = const0_rtx; +}) + +(define_insn "*dfp_sgnfcnc_<mode>" + [(set (match_operand:CCFP 0 "" "=y") + (compare:CCFP + (unspec:D64_D128 [(match_operand:SI 1 "const_int_operand" "n") + (match_operand:D64_D128 2 "gpc_reg_operand" "d")] + UNSPEC_DTSTSFI) + (match_operand:SI 3 "zero_constant" "j")))] + "TARGET_P9_MISC" +{ + /* If immediate operand is greater than 63, it will behave as if + the value had been 63. The code generator does not support + immediate operand values greater than 63. */ + if (!(IN_RANGE (INTVAL (operands[1]), 0, 63))) + operands[1] = GEN_INT (63); + return "dtstsfi<dfp_suffix> %0,%1,%2"; +} [(set_attr "type" "fp")]) + +(define_insn "dfp_dscli_<mode>" + [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d") + (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d") + (match_operand:QI 2 "immediate_operand" "i")] + UNSPEC_DSCLI))] + "TARGET_DFP" + "dscli<dfp_suffix> %0,%1,%2" + [(set_attr "type" "dfp")]) + +(define_insn "dfp_dscri_<mode>" + [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d") + (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d") + (match_operand:QI 2 "immediate_operand" "i")] + UNSPEC_DSCRI))] + "TARGET_DFP" + "dscri<dfp_suffix> %0,%1,%2" + [(set_attr "type" "dfp")])