Home | History | Annotate | Line # | Download | only in rs6000
dfp.md revision 1.6.2.1
      1 ;; Decimal Floating Point (DFP) patterns.
      2 ;; Copyright (C) 2007-2016 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 
    178 (define_insn "adddd3"
    179   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
    180 	(plus:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
    181 		 (match_operand:DD 2 "gpc_reg_operand" "d")))]
    182   "TARGET_DFP"
    183   "dadd %0,%1,%2"
    184   [(set_attr "type" "dfp")])
    185 
    186 (define_insn "addtd3"
    187   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
    188 	(plus:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
    189 		 (match_operand:TD 2 "gpc_reg_operand" "d")))]
    190   "TARGET_DFP"
    191   "daddq %0,%1,%2"
    192   [(set_attr "type" "dfp")])
    193 
    194 (define_insn "subdd3"
    195   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
    196 	(minus:DD (match_operand:DD 1 "gpc_reg_operand" "d")
    197 		  (match_operand:DD 2 "gpc_reg_operand" "d")))]
    198   "TARGET_DFP"
    199   "dsub %0,%1,%2"
    200   [(set_attr "type" "dfp")])
    201 
    202 (define_insn "subtd3"
    203   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
    204 	(minus:TD (match_operand:TD 1 "gpc_reg_operand" "d")
    205 		  (match_operand:TD 2 "gpc_reg_operand" "d")))]
    206   "TARGET_DFP"
    207   "dsubq %0,%1,%2"
    208   [(set_attr "type" "dfp")])
    209 
    210 (define_insn "muldd3"
    211   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
    212 	(mult:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
    213 		 (match_operand:DD 2 "gpc_reg_operand" "d")))]
    214   "TARGET_DFP"
    215   "dmul %0,%1,%2"
    216   [(set_attr "type" "dfp")])
    217 
    218 (define_insn "multd3"
    219   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
    220 	(mult:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
    221 		 (match_operand:TD 2 "gpc_reg_operand" "d")))]
    222   "TARGET_DFP"
    223   "dmulq %0,%1,%2"
    224   [(set_attr "type" "dfp")])
    225 
    226 (define_insn "divdd3"
    227   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
    228 	(div:DD (match_operand:DD 1 "gpc_reg_operand" "d")
    229 		(match_operand:DD 2 "gpc_reg_operand" "d")))]
    230   "TARGET_DFP"
    231   "ddiv %0,%1,%2"
    232   [(set_attr "type" "dfp")])
    233 
    234 (define_insn "divtd3"
    235   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
    236 	(div:TD (match_operand:TD 1 "gpc_reg_operand" "d")
    237 		(match_operand:TD 2 "gpc_reg_operand" "d")))]
    238   "TARGET_DFP"
    239   "ddivq %0,%1,%2"
    240   [(set_attr "type" "dfp")])
    241 
    242 (define_insn "*cmpdd_internal1"
    243   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
    244 	(compare:CCFP (match_operand:DD 1 "gpc_reg_operand" "d")
    245 		      (match_operand:DD 2 "gpc_reg_operand" "d")))]
    246   "TARGET_DFP"
    247   "dcmpu %0,%1,%2"
    248   [(set_attr "type" "dfp")])
    249 
    250 (define_insn "*cmptd_internal1"
    251   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
    252 	(compare:CCFP (match_operand:TD 1 "gpc_reg_operand" "d")
    253 		      (match_operand:TD 2 "gpc_reg_operand" "d")))]
    254   "TARGET_DFP"
    255   "dcmpuq %0,%1,%2"
    256   [(set_attr "type" "dfp")])
    257 
    258 (define_insn "floatdidd2"
    259   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
    260 	(float:DD (match_operand:DI 1 "gpc_reg_operand" "d")))]
    261   "TARGET_DFP && TARGET_POPCNTD"
    262   "dcffix %0,%1"
    263   [(set_attr "type" "dfp")])
    264 
    265 (define_insn "floatditd2"
    266   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
    267 	(float:TD (match_operand:DI 1 "gpc_reg_operand" "d")))]
    268   "TARGET_DFP"
    269   "dcffixq %0,%1"
    270   [(set_attr "type" "dfp")])
    271 
    272 ;; Convert a decimal64 to a decimal64 whose value is an integer.
    273 ;; This is the first stage of converting it to an integer type.
    274 
    275 (define_insn "ftruncdd2"
    276   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
    277 	(fix:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
    278   "TARGET_DFP"
    279   "drintn. 0,%0,%1,1"
    280   [(set_attr "type" "dfp")])
    281 
    282 ;; Convert a decimal64 whose value is an integer to an actual integer.
    283 ;; This is the second stage of converting decimal float to integer type.
    284 
    285 (define_insn "fixdddi2"
    286   [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
    287 	(fix:DI (match_operand:DD 1 "gpc_reg_operand" "d")))]
    288   "TARGET_DFP"
    289   "dctfix %0,%1"
    290   [(set_attr "type" "dfp")])
    291 
    292 ;; Convert a decimal128 to a decimal128 whose value is an integer.
    293 ;; This is the first stage of converting it to an integer type.
    294 
    295 (define_insn "ftrunctd2"
    296   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
    297 	(fix:TD (match_operand:TD 1 "gpc_reg_operand" "d")))]
    298   "TARGET_DFP"
    299   "drintnq. 0,%0,%1,1"
    300   [(set_attr "type" "dfp")])
    301 
    302 ;; Convert a decimal128 whose value is an integer to an actual integer.
    303 ;; This is the second stage of converting decimal float to integer type.
    304 
    305 (define_insn "fixtddi2"
    306   [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
    307 	(fix:DI (match_operand:TD 1 "gpc_reg_operand" "d")))]
    308   "TARGET_DFP"
    309   "dctfixq %0,%1"
    310   [(set_attr "type" "dfp")])
    311 
    312 
    314 ;; Decimal builtin support
    315 
    316 (define_c_enum "unspec"
    317   [UNSPEC_DDEDPD
    318    UNSPEC_DENBCD
    319    UNSPEC_DXEX
    320    UNSPEC_DIEX
    321    UNSPEC_DSCLI
    322    UNSPEC_DTSTSFI
    323    UNSPEC_DSCRI])
    324 
    325 (define_code_iterator DFP_TEST [eq lt gt unordered])
    326 
    327 (define_mode_iterator D64_D128 [DD TD])
    328 
    329 (define_mode_attr dfp_suffix [(DD "")
    330 			      (TD "q")])
    331 
    332 (define_insn "dfp_ddedpd_<mode>"
    333   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
    334 	(unspec:D64_D128 [(match_operand:QI 1 "const_0_to_3_operand" "i")
    335 			  (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
    336 			 UNSPEC_DDEDPD))]
    337   "TARGET_DFP"
    338   "ddedpd<dfp_suffix> %1,%0,%2"
    339   [(set_attr "type" "dfp")])
    340 
    341 (define_insn "dfp_denbcd_<mode>"
    342   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
    343 	(unspec:D64_D128 [(match_operand:QI 1 "const_0_to_1_operand" "i")
    344 			  (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
    345 			 UNSPEC_DENBCD))]
    346   "TARGET_DFP"
    347   "denbcd<dfp_suffix> %1,%0,%2"
    348   [(set_attr "type" "dfp")])
    349 
    350 (define_insn "dfp_dxex_<mode>"
    351   [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
    352 	(unspec:DI [(match_operand:D64_D128 1 "gpc_reg_operand" "d")]
    353 		   UNSPEC_DXEX))]
    354   "TARGET_DFP"
    355   "dxex<dfp_suffix> %0,%1"
    356   [(set_attr "type" "dfp")])
    357 
    358 (define_insn "dfp_diex_<mode>"
    359   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
    360 	(unspec:D64_D128 [(match_operand:DI 1 "gpc_reg_operand" "d")
    361 			  (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
    362 			 UNSPEC_DXEX))]
    363   "TARGET_DFP"
    364   "diex<dfp_suffix> %0,%1,%2"
    365   [(set_attr "type" "dfp")])
    366 
    367 (define_expand "dfptstsfi_<code>_<mode>"
    368   [(set (match_dup 3)
    369 	(compare:CCFP
    370          (unspec:D64_D128
    371 	  [(match_operand:SI 1 "const_int_operand" "n")
    372 	   (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
    373 	  UNSPEC_DTSTSFI)
    374 	 (match_dup 4)))
    375    (set (match_operand:SI 0 "register_operand" "")
    376    	(DFP_TEST:SI (match_dup 3)
    377 		     (const_int 0)))
    378   ]
    379   "TARGET_P9_MISC"
    380 {
    381   operands[3] = gen_reg_rtx (CCFPmode);
    382   operands[4] = const0_rtx;
    383 })
    384 
    385 (define_insn "*dfp_sgnfcnc_<mode>"
    386   [(set (match_operand:CCFP 0 "" "=y")
    387         (compare:CCFP
    388 	 (unspec:D64_D128 [(match_operand:SI 1 "const_int_operand" "n")
    389 	 	           (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
    390           UNSPEC_DTSTSFI)
    391 	 (match_operand:SI 3 "zero_constant" "j")))]
    392   "TARGET_P9_MISC"
    393 {
    394   /* If immediate operand is greater than 63, it will behave as if
    395      the value had been 63.  The code generator does not support
    396      immediate operand values greater than 63.  */
    397   if (!(IN_RANGE (INTVAL (operands[1]), 0, 63)))
    398     operands[1] = GEN_INT (63);
    399   return "dtstsfi<dfp_suffix> %0,%1,%2";
    400 }
    401   [(set_attr "type" "fp")])
    402 
    403 (define_insn "dfp_dscli_<mode>"
    404   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
    405 	(unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
    406 			  (match_operand:QI 2 "immediate_operand" "i")]
    407 			 UNSPEC_DSCLI))]
    408   "TARGET_DFP"
    409   "dscli<dfp_suffix> %0,%1,%2"
    410   [(set_attr "type" "dfp")])
    411 
    412 (define_insn "dfp_dscri_<mode>"
    413   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
    414 	(unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
    415 			  (match_operand:QI 2 "immediate_operand" "i")]
    416 			 UNSPEC_DSCRI))]
    417   "TARGET_DFP"
    418   "dscri<dfp_suffix> %0,%1,%2"
    419   [(set_attr "type" "dfp")])
    420