Home | History | Annotate | Line # | Download | only in rs6000
dfp.md revision 1.12
      1 ;; Decimal Floating Point (DFP) patterns.
      2 ;; Copyright (C) 2007-2020 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 ; Either of the two decimal modes.
     32 (define_mode_iterator DDTD [DD TD])
     33 
     34 (define_mode_attr q [(DD "") (TD "q")])
     35 
     36 
     37 (define_insn "movsd_store"
     38   [(set (match_operand:DD 0 "nonimmediate_operand" "=m")
     39 	(unspec:DD [(match_operand:SD 1 "input_operand" "d")]
     40 		   UNSPEC_MOVSD_STORE))]
     41   "(gpc_reg_operand (operands[0], DDmode)
     42    || gpc_reg_operand (operands[1], SDmode))
     43    && TARGET_HARD_FLOAT"
     44   "stfd%U0%X0 %1,%0"
     45   [(set_attr "type" "fpstore")])
     46 
     47 (define_insn "movsd_load"
     48   [(set (match_operand:SD 0 "nonimmediate_operand" "=f")
     49 	(unspec:SD [(match_operand:DD 1 "input_operand" "m")]
     50 		   UNSPEC_MOVSD_LOAD))]
     51   "(gpc_reg_operand (operands[0], SDmode)
     52    || gpc_reg_operand (operands[1], DDmode))
     53    && TARGET_HARD_FLOAT"
     54   "lfd%U1%X1 %0,%1"
     55   [(set_attr "type" "fpload")])
     56 
     57 ;; Hardware support for decimal floating point operations.
     58 
     59 (define_insn "extendsddd2"
     60   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
     61 	(float_extend:DD (match_operand:SD 1 "gpc_reg_operand" "f")))]
     62   "TARGET_DFP"
     63   "dctdp %0,%1"
     64   [(set_attr "type" "dfp")])
     65 
     66 (define_expand "extendsdtd2"
     67   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
     68 	(float_extend:TD (match_operand:SD 1 "gpc_reg_operand" "d")))]
     69   "TARGET_DFP"
     70 {
     71   rtx tmp = gen_reg_rtx (DDmode);
     72   emit_insn (gen_extendsddd2 (tmp, operands[1]));
     73   emit_insn (gen_extendddtd2 (operands[0], tmp));
     74   DONE;
     75 })
     76 
     77 (define_insn "truncddsd2"
     78   [(set (match_operand:SD 0 "gpc_reg_operand" "=f")
     79 	(float_truncate:SD (match_operand:DD 1 "gpc_reg_operand" "d")))]
     80   "TARGET_DFP"
     81   "drsp %0,%1"
     82   [(set_attr "type" "dfp")])
     83 
     84 (define_insn "negdd2"
     85   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
     86 	(neg:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
     87   "TARGET_HARD_FLOAT"
     88   "fneg %0,%1"
     89   [(set_attr "type" "fpsimple")])
     90 
     91 (define_insn "absdd2"
     92   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
     93 	(abs:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
     94   "TARGET_HARD_FLOAT"
     95   "fabs %0,%1"
     96   [(set_attr "type" "fpsimple")])
     97 
     98 (define_insn "*nabsdd2_fpr"
     99   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
    100 	(neg:DD (abs:DD (match_operand:DD 1 "gpc_reg_operand" "d"))))]
    101   "TARGET_HARD_FLOAT"
    102   "fnabs %0,%1"
    103   [(set_attr "type" "fpsimple")])
    104 
    105 (define_insn "negtd2"
    106   [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
    107 	(neg:TD (match_operand:TD 1 "gpc_reg_operand" "0,d")))]
    108   "TARGET_HARD_FLOAT"
    109   "@
    110    fneg %0,%1
    111    fneg %0,%1\;fmr %L0,%L1"
    112   [(set_attr "type" "fpsimple")
    113    (set_attr "length" "4,8")])
    114 
    115 (define_insn "abstd2"
    116   [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
    117 	(abs:TD (match_operand:TD 1 "gpc_reg_operand" "0,d")))]
    118   "TARGET_HARD_FLOAT"
    119   "@
    120    fabs %0,%1
    121    fabs %0,%1\;fmr %L0,%L1"
    122   [(set_attr "type" "fpsimple")
    123    (set_attr "length" "4,8")])
    124 
    125 (define_insn "*nabstd2_fpr"
    126   [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
    127 	(neg:TD (abs:TD (match_operand:TD 1 "gpc_reg_operand" "0,d"))))]
    128   "TARGET_HARD_FLOAT"
    129   "@
    130    fnabs %0,%1
    131    fnabs %0,%1\;fmr %L0,%L1"
    132   [(set_attr "type" "fpsimple")
    133    (set_attr "length" "4,8")])
    134 
    135 ;; Hardware support for decimal floating point operations.
    136 
    137 (define_insn "extendddtd2"
    138   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
    139 	(float_extend:TD (match_operand:DD 1 "gpc_reg_operand" "d")))]
    140   "TARGET_DFP"
    141   "dctqpq %0,%1"
    142   [(set_attr "type" "dfp")])
    143 
    144 ;; The result of drdpq is an even/odd register pair with the converted
    145 ;; value in the even register and zero in the odd register.
    146 ;; FIXME: Avoid the register move by using a reload constraint to ensure
    147 ;; that the result is the first of the pair receiving the result of drdpq.
    148 
    149 (define_insn "trunctddd2"
    150   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
    151 	(float_truncate:DD (match_operand:TD 1 "gpc_reg_operand" "d")))
    152    (clobber (match_scratch:TD 2 "=d"))]
    153   "TARGET_DFP"
    154   "drdpq %2,%1\;fmr %0,%2"
    155   [(set_attr "type" "dfp")
    156    (set_attr "length" "8")])
    157 
    158 (define_insn "add<mode>3"
    159   [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d")
    160 	(plus:DDTD (match_operand:DDTD 1 "gpc_reg_operand" "%d")
    161 		   (match_operand:DDTD 2 "gpc_reg_operand" "d")))]
    162   "TARGET_DFP"
    163   "dadd<q> %0,%1,%2"
    164   [(set_attr "type" "dfp")])
    165 
    166 (define_insn "sub<mode>3"
    167   [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d")
    168 	(minus:DDTD (match_operand:DDTD 1 "gpc_reg_operand" "d")
    169 		    (match_operand:DDTD 2 "gpc_reg_operand" "d")))]
    170   "TARGET_DFP"
    171   "dsub<q> %0,%1,%2"
    172   [(set_attr "type" "dfp")])
    173 
    174 (define_insn "mul<mode>3"
    175   [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d")
    176 	(mult:DDTD (match_operand:DDTD 1 "gpc_reg_operand" "%d")
    177 		   (match_operand:DDTD 2 "gpc_reg_operand" "d")))]
    178   "TARGET_DFP"
    179   "dmul<q> %0,%1,%2"
    180   [(set_attr "type" "dfp")])
    181 
    182 (define_insn "div<mode>3"
    183   [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d")
    184 	(div:DDTD (match_operand:DDTD 1 "gpc_reg_operand" "d")
    185 		  (match_operand:DDTD 2 "gpc_reg_operand" "d")))]
    186   "TARGET_DFP"
    187   "ddiv<q> %0,%1,%2"
    188   [(set_attr "type" "dfp")])
    189 
    190 (define_insn "*cmp<mode>_internal1"
    191   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
    192 	(compare:CCFP (match_operand:DDTD 1 "gpc_reg_operand" "d")
    193 		      (match_operand:DDTD 2 "gpc_reg_operand" "d")))]
    194   "TARGET_DFP"
    195   "dcmpu<q> %0,%1,%2"
    196   [(set_attr "type" "dfp")])
    197 
    198 (define_insn "floatdidd2"
    199   [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
    200 	(float:DD (match_operand:DI 1 "gpc_reg_operand" "d")))]
    201   "TARGET_DFP && TARGET_POPCNTD"
    202   "dcffix %0,%1"
    203   [(set_attr "type" "dfp")])
    204 
    205 (define_insn "floatditd2"
    206   [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
    207 	(float:TD (match_operand:DI 1 "gpc_reg_operand" "d")))]
    208   "TARGET_DFP"
    209   "dcffixq %0,%1"
    210   [(set_attr "type" "dfp")])
    211 
    212 ;; Convert a decimal64/128 to a decimal64/128 whose value is an integer.
    213 ;; This is the first stage of converting it to an integer type.
    214 
    215 (define_insn "ftrunc<mode>2"
    216   [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d")
    217 	(fix:DDTD (match_operand:DDTD 1 "gpc_reg_operand" "d")))]
    218   "TARGET_DFP"
    219   "drintn<q>. 0,%0,%1,1"
    220   [(set_attr "type" "dfp")])
    221 
    222 ;; Convert a decimal64/128 whose value is an integer to an actual integer.
    223 ;; This is the second stage of converting decimal float to integer type.
    224 
    225 (define_insn "fix<mode>di2"
    226   [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
    227 	(fix:DI (match_operand:DDTD 1 "gpc_reg_operand" "d")))]
    228   "TARGET_DFP"
    229   "dctfix<q> %0,%1"
    230   [(set_attr "type" "dfp")])
    231 
    233 ;; Decimal builtin support
    234 
    235 (define_c_enum "unspec"
    236   [UNSPEC_DDEDPD
    237    UNSPEC_DENBCD
    238    UNSPEC_DXEX
    239    UNSPEC_DIEX
    240    UNSPEC_DSCLI
    241    UNSPEC_DTSTSFI
    242    UNSPEC_DSCRI])
    243 
    244 (define_code_iterator DFP_TEST [eq lt gt unordered])
    245 
    246 (define_insn "dfp_ddedpd_<mode>"
    247   [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d")
    248 	(unspec:DDTD [(match_operand:QI 1 "const_0_to_3_operand" "i")
    249 		      (match_operand:DDTD 2 "gpc_reg_operand" "d")]
    250 		     UNSPEC_DDEDPD))]
    251   "TARGET_DFP"
    252   "ddedpd<q> %1,%0,%2"
    253   [(set_attr "type" "dfp")])
    254 
    255 (define_insn "dfp_denbcd_<mode>"
    256   [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d")
    257 	(unspec:DDTD [(match_operand:QI 1 "const_0_to_1_operand" "i")
    258 		      (match_operand:DDTD 2 "gpc_reg_operand" "d")]
    259 		     UNSPEC_DENBCD))]
    260   "TARGET_DFP"
    261   "denbcd<q> %1,%0,%2"
    262   [(set_attr "type" "dfp")])
    263 
    264 (define_insn "dfp_dxex_<mode>"
    265   [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
    266 	(unspec:DI [(match_operand:DDTD 1 "gpc_reg_operand" "d")]
    267 		   UNSPEC_DXEX))]
    268   "TARGET_DFP"
    269   "dxex<q> %0,%1"
    270   [(set_attr "type" "dfp")])
    271 
    272 (define_insn "dfp_diex_<mode>"
    273   [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d")
    274 	(unspec:DDTD [(match_operand:DI 1 "gpc_reg_operand" "d")
    275 		      (match_operand:DDTD 2 "gpc_reg_operand" "d")]
    276 		     UNSPEC_DXEX))]
    277   "TARGET_DFP"
    278   "diex<q> %0,%1,%2"
    279   [(set_attr "type" "dfp")])
    280 
    281 (define_expand "dfptstsfi_<code>_<mode>"
    282   [(set (match_dup 3)
    283 	(compare:CCFP (unspec:DDTD [(match_operand:SI 1 "const_int_operand")
    284 				    (match_operand:DDTD 2 "gpc_reg_operand")]
    285 				   UNSPEC_DTSTSFI)
    286 		      (const_int 0)))
    287    (set (match_operand:SI 0 "register_operand")
    288 	(DFP_TEST:SI (match_dup 3)
    289 		     (const_int 0)))
    290   ]
    291   "TARGET_P9_MISC"
    292 {
    293   if (<CODE> == UNORDERED && !HONOR_NANS (<MODE>mode))
    294     {
    295       emit_move_insn (operands[0], const0_rtx);
    296       DONE;
    297     }
    298 
    299   operands[3] = gen_reg_rtx (CCFPmode);
    300 })
    301 
    302 (define_insn "*dfp_sgnfcnc_<mode>"
    303   [(set (match_operand:CCFP 0 "" "=y")
    304 	(compare:CCFP
    305 	 (unspec:DDTD [(match_operand:SI 1 "const_int_operand" "n")
    306 		       (match_operand:DDTD 2 "gpc_reg_operand" "d")]
    307 		      UNSPEC_DTSTSFI)
    308 	 (match_operand:SI 3 "zero_constant" "j")))]
    309   "TARGET_P9_MISC"
    310 {
    311   /* If immediate operand is greater than 63, it will behave as if
    312      the value had been 63.  The code generator does not support
    313      immediate operand values greater than 63.  */
    314   if (!(IN_RANGE (INTVAL (operands[1]), 0, 63)))
    315     operands[1] = GEN_INT (63);
    316   return "dtstsfi<q> %0,%1,%2";
    317 }
    318   [(set_attr "type" "fp")])
    319 
    320 (define_insn "dfp_dscli_<mode>"
    321   [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d")
    322 	(unspec:DDTD [(match_operand:DDTD 1 "gpc_reg_operand" "d")
    323 		      (match_operand:QI 2 "immediate_operand" "i")]
    324 		     UNSPEC_DSCLI))]
    325   "TARGET_DFP"
    326   "dscli<q> %0,%1,%2"
    327   [(set_attr "type" "dfp")])
    328 
    329 (define_insn "dfp_dscri_<mode>"
    330   [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d")
    331 	(unspec:DDTD [(match_operand:DDTD 1 "gpc_reg_operand" "d")
    332 		      (match_operand:QI 2 "immediate_operand" "i")]
    333 		     UNSPEC_DSCRI))]
    334   "TARGET_DFP"
    335   "dscri<q> %0,%1,%2"
    336   [(set_attr "type" "dfp")])
    337