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