1;; Decimal Floating Point (DFP) patterns. 2;; Copyright (C) 2007-2020 Free Software Foundation, Inc. 3;; Contributed by Ben Elliston (bje@au.ibm.com) and Peter Bergner 4;; (bergner@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 232;; Decimal builtin support 233 234(define_c_enum "unspec" 235 [UNSPEC_DDEDPD 236 UNSPEC_DENBCD 237 UNSPEC_DXEX 238 UNSPEC_DIEX 239 UNSPEC_DSCLI 240 UNSPEC_DTSTSFI 241 UNSPEC_DSCRI]) 242 243(define_code_iterator DFP_TEST [eq lt gt unordered]) 244 245(define_insn "dfp_ddedpd_<mode>" 246 [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") 247 (unspec:DDTD [(match_operand:QI 1 "const_0_to_3_operand" "i") 248 (match_operand:DDTD 2 "gpc_reg_operand" "d")] 249 UNSPEC_DDEDPD))] 250 "TARGET_DFP" 251 "ddedpd<q> %1,%0,%2" 252 [(set_attr "type" "dfp")]) 253 254(define_insn "dfp_denbcd_<mode>" 255 [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") 256 (unspec:DDTD [(match_operand:QI 1 "const_0_to_1_operand" "i") 257 (match_operand:DDTD 2 "gpc_reg_operand" "d")] 258 UNSPEC_DENBCD))] 259 "TARGET_DFP" 260 "denbcd<q> %1,%0,%2" 261 [(set_attr "type" "dfp")]) 262 263(define_insn "dfp_dxex_<mode>" 264 [(set (match_operand:DI 0 "gpc_reg_operand" "=d") 265 (unspec:DI [(match_operand:DDTD 1 "gpc_reg_operand" "d")] 266 UNSPEC_DXEX))] 267 "TARGET_DFP" 268 "dxex<q> %0,%1" 269 [(set_attr "type" "dfp")]) 270 271(define_insn "dfp_diex_<mode>" 272 [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") 273 (unspec:DDTD [(match_operand:DI 1 "gpc_reg_operand" "d") 274 (match_operand:DDTD 2 "gpc_reg_operand" "d")] 275 UNSPEC_DXEX))] 276 "TARGET_DFP" 277 "diex<q> %0,%1,%2" 278 [(set_attr "type" "dfp")]) 279 280(define_expand "dfptstsfi_<code>_<mode>" 281 [(set (match_dup 3) 282 (compare:CCFP (unspec:DDTD [(match_operand:SI 1 "const_int_operand") 283 (match_operand:DDTD 2 "gpc_reg_operand")] 284 UNSPEC_DTSTSFI) 285 (const_int 0))) 286 (set (match_operand:SI 0 "register_operand") 287 (DFP_TEST:SI (match_dup 3) 288 (const_int 0))) 289 ] 290 "TARGET_P9_MISC" 291{ 292 if (<CODE> == UNORDERED && !HONOR_NANS (<MODE>mode)) 293 { 294 emit_move_insn (operands[0], const0_rtx); 295 DONE; 296 } 297 298 operands[3] = gen_reg_rtx (CCFPmode); 299}) 300 301(define_insn "*dfp_sgnfcnc_<mode>" 302 [(set (match_operand:CCFP 0 "" "=y") 303 (compare:CCFP 304 (unspec:DDTD [(match_operand:SI 1 "const_int_operand" "n") 305 (match_operand:DDTD 2 "gpc_reg_operand" "d")] 306 UNSPEC_DTSTSFI) 307 (match_operand:SI 3 "zero_constant" "j")))] 308 "TARGET_P9_MISC" 309{ 310 /* If immediate operand is greater than 63, it will behave as if 311 the value had been 63. The code generator does not support 312 immediate operand values greater than 63. */ 313 if (!(IN_RANGE (INTVAL (operands[1]), 0, 63))) 314 operands[1] = GEN_INT (63); 315 return "dtstsfi<q> %0,%1,%2"; 316} 317 [(set_attr "type" "fp")]) 318 319(define_insn "dfp_dscli_<mode>" 320 [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") 321 (unspec:DDTD [(match_operand:DDTD 1 "gpc_reg_operand" "d") 322 (match_operand:QI 2 "immediate_operand" "i")] 323 UNSPEC_DSCLI))] 324 "TARGET_DFP" 325 "dscli<q> %0,%1,%2" 326 [(set_attr "type" "dfp")]) 327 328(define_insn "dfp_dscri_<mode>" 329 [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") 330 (unspec:DDTD [(match_operand:DDTD 1 "gpc_reg_operand" "d") 331 (match_operand:QI 2 "immediate_operand" "i")] 332 UNSPEC_DSCRI))] 333 "TARGET_DFP" 334 "dscri<q> %0,%1,%2" 335 [(set_attr "type" "dfp")]) 336