Home | History | Annotate | Line # | Download | only in rs6000
dfp.md revision 1.11
      1 ;; Decimal Floating Point (DFP) patterns.
      2 ;; Copyright (C) 2007-2019 Free Software Foundation, Inc.
      3 ;; Contributed by Ben Elliston (bje (a] au.ibm.com) and Peter Bergner
      4 ;; (bergner (a] vnet.ibm.com).
      5 
      6 ;; This file is part of GCC.
      7 
      8 ;; GCC is free software; you can redistribute it and/or modify it
      9 ;; under the terms of the GNU General Public License as published
     10 ;; by the Free Software Foundation; either version 3, or (at your
     11 ;; option) any later version.
     12 
     13 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
     14 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     15 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     16 ;; License for more details.
     17 
     18 ;; You should have received a copy of the GNU General Public License
     19 ;; along with GCC; see the file COPYING3.  If not see
     20 ;; <http://www.gnu.org/licenses/>.
     21 
     22 ;;
     23 ;; UNSPEC usage
     24 ;;
     25 
     26 (define_c_enum "unspec"
     27   [UNSPEC_MOVSD_LOAD
     28    UNSPEC_MOVSD_STORE
     29   ])
     30 
     31 
     32 (define_insn "movsd_store"
     33   [(set (match_operand:DD 0 "nonimmediate_operand" "=m")
     34 	(unspec:DD [(match_operand:SD 1 "input_operand" "d")]
     35 		   UNSPEC_MOVSD_STORE))]
     36   "(gpc_reg_operand (operands[0], DDmode)
     37    || gpc_reg_operand (operands[1], SDmode))
     38    && TARGET_HARD_FLOAT"
     39   "stfd%U0%X0 %1,%0"
     40   [(set_attr "type" "fpstore")])
     41 
     42 (define_insn "movsd_load"
     43   [(set (match_operand:SD 0 "nonimmediate_operand" "=f")
     44 	(unspec:SD [(match_operand:DD 1 "input_operand" "m")]
     45 		   UNSPEC_MOVSD_LOAD))]
     46   "(gpc_reg_operand (operands[0], SDmode)
     47    || gpc_reg_operand (operands[1], DDmode))
     48    && TARGET_HARD_FLOAT"
     49   "lfd%U1%X1 %0,%1"
     50   [(set_attr "type" "fpload")])
     51 
     52 ;; Hardware support for decimal floating point operations.
     53 
     54 (define_insn "extendsddd2"
     55   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
     56 	(float_extend:DD (match_operand:SD 1 "gpc_reg_operand" "f")))]
     57   "TARGET_DFP"
     58   "dctdp %0,%1"
     59   [(set_attr "type" "dfp")])
     60 
     61 (define_expand "extendsdtd2"
     62   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
     63 	(float_extend:TD (match_operand:SD 1 "gpc_reg_operand" "d")))]
     64   "TARGET_DFP"
     65 {
     66   rtx tmp = gen_reg_rtx (DDmode);
     67   emit_insn (gen_extendsddd2 (tmp, operands[1]));
     68   emit_insn (gen_extendddtd2 (operands[0], tmp));
     69   DONE;
     70 })
     71 
     72 (define_insn "truncddsd2"
     73   [(set (match_operand:SD 0 "gpc_reg_operand" "=f")
     74 	(float_truncate:SD (match_operand:DD 1 "gpc_reg_operand" "d")))]
     75   "TARGET_DFP"
     76   "drsp %0,%1"
     77   [(set_attr "type" "dfp")])
     78 
     79 (define_insn "negdd2"
     80   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
     81 	(neg:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
     82   "TARGET_HARD_FLOAT"
     83   "fneg %0,%1"
     84   [(set_attr "type" "fpsimple")])
     85 
     86 (define_insn "absdd2"
     87   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
     88 	(abs:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
     89   "TARGET_HARD_FLOAT"
     90   "fabs %0,%1"
     91   [(set_attr "type" "fpsimple")])
     92 
     93 (define_insn "*nabsdd2_fpr"
     94   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
     95 	(neg:DD (abs:DD (match_operand:DD 1 "gpc_reg_operand" "d"))))]
     96   "TARGET_HARD_FLOAT"
     97   "fnabs %0,%1"
     98   [(set_attr "type" "fpsimple")])
     99 
    100 (define_insn "negtd2"
    101   [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
    102 	(neg:TD (match_operand:TD 1 "gpc_reg_operand" "0,d")))]
    103   "TARGET_HARD_FLOAT"
    104   "@
    105    fneg %0,%1
    106    fneg %0,%1\;fmr %L0,%L1"
    107   [(set_attr "type" "fpsimple")
    108    (set_attr "length" "4,8")])
    109 
    110 (define_insn "abstd2"
    111   [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
    112 	(abs:TD (match_operand:TD 1 "gpc_reg_operand" "0,d")))]
    113   "TARGET_HARD_FLOAT"
    114   "@
    115    fabs %0,%1
    116    fabs %0,%1\;fmr %L0,%L1"
    117   [(set_attr "type" "fpsimple")
    118    (set_attr "length" "4,8")])
    119 
    120 (define_insn "*nabstd2_fpr"
    121   [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
    122 	(neg:TD (abs:TD (match_operand:TD 1 "gpc_reg_operand" "0,d"))))]
    123   "TARGET_HARD_FLOAT"
    124   "@
    125    fnabs %0,%1
    126    fnabs %0,%1\;fmr %L0,%L1"
    127   [(set_attr "type" "fpsimple")
    128    (set_attr "length" "4,8")])
    129 
    130 ;; Hardware support for decimal floating point operations.
    131 
    132 (define_insn "extendddtd2"
    133   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
    134 	(float_extend:TD (match_operand:DD 1 "gpc_reg_operand" "d")))]
    135   "TARGET_DFP"
    136   "dctqpq %0,%1"
    137   [(set_attr "type" "dfp")])
    138 
    139 ;; The result of drdpq is an even/odd register pair with the converted
    140 ;; value in the even register and zero in the odd register.
    141 ;; FIXME: Avoid the register move by using a reload constraint to ensure
    142 ;; that the result is the first of the pair receiving the result of drdpq.
    143 
    144 (define_insn "trunctddd2"
    145   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
    146 	(float_truncate:DD (match_operand:TD 1 "gpc_reg_operand" "d")))
    147    (clobber (match_scratch:TD 2 "=d"))]
    148   "TARGET_DFP"
    149   "drdpq %2,%1\;fmr %0,%2"
    150   [(set_attr "type" "dfp")
    151    (set_attr "length" "8")])
    152 
    153 (define_insn "adddd3"
    154   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
    155 	(plus:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
    156 		 (match_operand:DD 2 "gpc_reg_operand" "d")))]
    157   "TARGET_DFP"
    158   "dadd %0,%1,%2"
    159   [(set_attr "type" "dfp")])
    160 
    161 (define_insn "addtd3"
    162   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
    163 	(plus:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
    164 		 (match_operand:TD 2 "gpc_reg_operand" "d")))]
    165   "TARGET_DFP"
    166   "daddq %0,%1,%2"
    167   [(set_attr "type" "dfp")])
    168 
    169 (define_insn "subdd3"
    170   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
    171 	(minus:DD (match_operand:DD 1 "gpc_reg_operand" "d")
    172 		  (match_operand:DD 2 "gpc_reg_operand" "d")))]
    173   "TARGET_DFP"
    174   "dsub %0,%1,%2"
    175   [(set_attr "type" "dfp")])
    176 
    177 (define_insn "subtd3"
    178   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
    179 	(minus:TD (match_operand:TD 1 "gpc_reg_operand" "d")
    180 		  (match_operand:TD 2 "gpc_reg_operand" "d")))]
    181   "TARGET_DFP"
    182   "dsubq %0,%1,%2"
    183   [(set_attr "type" "dfp")])
    184 
    185 (define_insn "muldd3"
    186   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
    187 	(mult:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
    188 		 (match_operand:DD 2 "gpc_reg_operand" "d")))]
    189   "TARGET_DFP"
    190   "dmul %0,%1,%2"
    191   [(set_attr "type" "dfp")])
    192 
    193 (define_insn "multd3"
    194   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
    195 	(mult:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
    196 		 (match_operand:TD 2 "gpc_reg_operand" "d")))]
    197   "TARGET_DFP"
    198   "dmulq %0,%1,%2"
    199   [(set_attr "type" "dfp")])
    200 
    201 (define_insn "divdd3"
    202   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
    203 	(div:DD (match_operand:DD 1 "gpc_reg_operand" "d")
    204 		(match_operand:DD 2 "gpc_reg_operand" "d")))]
    205   "TARGET_DFP"
    206   "ddiv %0,%1,%2"
    207   [(set_attr "type" "dfp")])
    208 
    209 (define_insn "divtd3"
    210   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
    211 	(div:TD (match_operand:TD 1 "gpc_reg_operand" "d")
    212 		(match_operand:TD 2 "gpc_reg_operand" "d")))]
    213   "TARGET_DFP"
    214   "ddivq %0,%1,%2"
    215   [(set_attr "type" "dfp")])
    216 
    217 (define_insn "*cmpdd_internal1"
    218   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
    219 	(compare:CCFP (match_operand:DD 1 "gpc_reg_operand" "d")
    220 		      (match_operand:DD 2 "gpc_reg_operand" "d")))]
    221   "TARGET_DFP"
    222   "dcmpu %0,%1,%2"
    223   [(set_attr "type" "dfp")])
    224 
    225 (define_insn "*cmptd_internal1"
    226   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
    227 	(compare:CCFP (match_operand:TD 1 "gpc_reg_operand" "d")
    228 		      (match_operand:TD 2 "gpc_reg_operand" "d")))]
    229   "TARGET_DFP"
    230   "dcmpuq %0,%1,%2"
    231   [(set_attr "type" "dfp")])
    232 
    233 (define_insn "floatdidd2"
    234   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
    235 	(float:DD (match_operand:DI 1 "gpc_reg_operand" "d")))]
    236   "TARGET_DFP && TARGET_POPCNTD"
    237   "dcffix %0,%1"
    238   [(set_attr "type" "dfp")])
    239 
    240 (define_insn "floatditd2"
    241   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
    242 	(float:TD (match_operand:DI 1 "gpc_reg_operand" "d")))]
    243   "TARGET_DFP"
    244   "dcffixq %0,%1"
    245   [(set_attr "type" "dfp")])
    246 
    247 ;; Convert a decimal64 to a decimal64 whose value is an integer.
    248 ;; This is the first stage of converting it to an integer type.
    249 
    250 (define_insn "ftruncdd2"
    251   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
    252 	(fix:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
    253   "TARGET_DFP"
    254   "drintn. 0,%0,%1,1"
    255   [(set_attr "type" "dfp")])
    256 
    257 ;; Convert a decimal64 whose value is an integer to an actual integer.
    258 ;; This is the second stage of converting decimal float to integer type.
    259 
    260 (define_insn "fixdddi2"
    261   [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
    262 	(fix:DI (match_operand:DD 1 "gpc_reg_operand" "d")))]
    263   "TARGET_DFP"
    264   "dctfix %0,%1"
    265   [(set_attr "type" "dfp")])
    266 
    267 ;; Convert a decimal128 to a decimal128 whose value is an integer.
    268 ;; This is the first stage of converting it to an integer type.
    269 
    270 (define_insn "ftrunctd2"
    271   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
    272 	(fix:TD (match_operand:TD 1 "gpc_reg_operand" "d")))]
    273   "TARGET_DFP"
    274   "drintnq. 0,%0,%1,1"
    275   [(set_attr "type" "dfp")])
    276 
    277 ;; Convert a decimal128 whose value is an integer to an actual integer.
    278 ;; This is the second stage of converting decimal float to integer type.
    279 
    280 (define_insn "fixtddi2"
    281   [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
    282 	(fix:DI (match_operand:TD 1 "gpc_reg_operand" "d")))]
    283   "TARGET_DFP"
    284   "dctfixq %0,%1"
    285   [(set_attr "type" "dfp")])
    286 
    287 
    289 ;; Decimal builtin support
    290 
    291 (define_c_enum "unspec"
    292   [UNSPEC_DDEDPD
    293    UNSPEC_DENBCD
    294    UNSPEC_DXEX
    295    UNSPEC_DIEX
    296    UNSPEC_DSCLI
    297    UNSPEC_DTSTSFI
    298    UNSPEC_DSCRI])
    299 
    300 (define_code_iterator DFP_TEST [eq lt gt unordered])
    301 
    302 (define_mode_iterator D64_D128 [DD TD])
    303 
    304 (define_mode_attr dfp_suffix [(DD "")
    305 			      (TD "q")])
    306 
    307 (define_insn "dfp_ddedpd_<mode>"
    308   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
    309 	(unspec:D64_D128 [(match_operand:QI 1 "const_0_to_3_operand" "i")
    310 			  (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
    311 			 UNSPEC_DDEDPD))]
    312   "TARGET_DFP"
    313   "ddedpd<dfp_suffix> %1,%0,%2"
    314   [(set_attr "type" "dfp")])
    315 
    316 (define_insn "dfp_denbcd_<mode>"
    317   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
    318 	(unspec:D64_D128 [(match_operand:QI 1 "const_0_to_1_operand" "i")
    319 			  (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
    320 			 UNSPEC_DENBCD))]
    321   "TARGET_DFP"
    322   "denbcd<dfp_suffix> %1,%0,%2"
    323   [(set_attr "type" "dfp")])
    324 
    325 (define_insn "dfp_dxex_<mode>"
    326   [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
    327 	(unspec:DI [(match_operand:D64_D128 1 "gpc_reg_operand" "d")]
    328 		   UNSPEC_DXEX))]
    329   "TARGET_DFP"
    330   "dxex<dfp_suffix> %0,%1"
    331   [(set_attr "type" "dfp")])
    332 
    333 (define_insn "dfp_diex_<mode>"
    334   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
    335 	(unspec:D64_D128 [(match_operand:DI 1 "gpc_reg_operand" "d")
    336 			  (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
    337 			 UNSPEC_DXEX))]
    338   "TARGET_DFP"
    339   "diex<dfp_suffix> %0,%1,%2"
    340   [(set_attr "type" "dfp")])
    341 
    342 (define_expand "dfptstsfi_<code>_<mode>"
    343   [(set (match_dup 3)
    344 	(compare:CCFP
    345          (unspec:D64_D128
    346 	  [(match_operand:SI 1 "const_int_operand")
    347 	   (match_operand:D64_D128 2 "gpc_reg_operand")]
    348 	  UNSPEC_DTSTSFI)
    349 	 (match_dup 4)))
    350    (set (match_operand:SI 0 "register_operand")
    351    	(DFP_TEST:SI (match_dup 3)
    352 		     (const_int 0)))
    353   ]
    354   "TARGET_P9_MISC"
    355 {
    356   operands[3] = gen_reg_rtx (CCFPmode);
    357   operands[4] = const0_rtx;
    358 })
    359 
    360 (define_insn "*dfp_sgnfcnc_<mode>"
    361   [(set (match_operand:CCFP 0 "" "=y")
    362         (compare:CCFP
    363 	 (unspec:D64_D128 [(match_operand:SI 1 "const_int_operand" "n")
    364 	 	           (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
    365           UNSPEC_DTSTSFI)
    366 	 (match_operand:SI 3 "zero_constant" "j")))]
    367   "TARGET_P9_MISC"
    368 {
    369   /* If immediate operand is greater than 63, it will behave as if
    370      the value had been 63.  The code generator does not support
    371      immediate operand values greater than 63.  */
    372   if (!(IN_RANGE (INTVAL (operands[1]), 0, 63)))
    373     operands[1] = GEN_INT (63);
    374   return "dtstsfi<dfp_suffix> %0,%1,%2";
    375 }
    376   [(set_attr "type" "fp")])
    377 
    378 (define_insn "dfp_dscli_<mode>"
    379   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
    380 	(unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
    381 			  (match_operand:QI 2 "immediate_operand" "i")]
    382 			 UNSPEC_DSCLI))]
    383   "TARGET_DFP"
    384   "dscli<dfp_suffix> %0,%1,%2"
    385   [(set_attr "type" "dfp")])
    386 
    387 (define_insn "dfp_dscri_<mode>"
    388   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
    389 	(unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
    390 			  (match_operand:QI 2 "immediate_operand" "i")]
    391 			 UNSPEC_DSCRI))]
    392   "TARGET_DFP"
    393   "dscri<dfp_suffix> %0,%1,%2"
    394   [(set_attr "type" "dfp")])
    395