1;; Decimal Floating Point (DFP) patterns. 2;; Copyright (C) 2007-2019 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 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 288;; Decimal builtin support 289 290(define_c_enum "unspec" 291 [UNSPEC_DDEDPD 292 UNSPEC_DENBCD 293 UNSPEC_DXEX 294 UNSPEC_DIEX 295 UNSPEC_DSCLI 296 UNSPEC_DTSTSFI 297 UNSPEC_DSCRI]) 298 299(define_code_iterator DFP_TEST [eq lt gt unordered]) 300 301(define_mode_iterator D64_D128 [DD TD]) 302 303(define_mode_attr dfp_suffix [(DD "") 304 (TD "q")]) 305 306(define_insn "dfp_ddedpd_<mode>" 307 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d") 308 (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_3_operand" "i") 309 (match_operand:D64_D128 2 "gpc_reg_operand" "d")] 310 UNSPEC_DDEDPD))] 311 "TARGET_DFP" 312 "ddedpd<dfp_suffix> %1,%0,%2" 313 [(set_attr "type" "dfp")]) 314 315(define_insn "dfp_denbcd_<mode>" 316 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d") 317 (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_1_operand" "i") 318 (match_operand:D64_D128 2 "gpc_reg_operand" "d")] 319 UNSPEC_DENBCD))] 320 "TARGET_DFP" 321 "denbcd<dfp_suffix> %1,%0,%2" 322 [(set_attr "type" "dfp")]) 323 324(define_insn "dfp_dxex_<mode>" 325 [(set (match_operand:DI 0 "gpc_reg_operand" "=d") 326 (unspec:DI [(match_operand:D64_D128 1 "gpc_reg_operand" "d")] 327 UNSPEC_DXEX))] 328 "TARGET_DFP" 329 "dxex<dfp_suffix> %0,%1" 330 [(set_attr "type" "dfp")]) 331 332(define_insn "dfp_diex_<mode>" 333 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d") 334 (unspec:D64_D128 [(match_operand:DI 1 "gpc_reg_operand" "d") 335 (match_operand:D64_D128 2 "gpc_reg_operand" "d")] 336 UNSPEC_DXEX))] 337 "TARGET_DFP" 338 "diex<dfp_suffix> %0,%1,%2" 339 [(set_attr "type" "dfp")]) 340 341(define_expand "dfptstsfi_<code>_<mode>" 342 [(set (match_dup 3) 343 (compare:CCFP 344 (unspec:D64_D128 345 [(match_operand:SI 1 "const_int_operand") 346 (match_operand:D64_D128 2 "gpc_reg_operand")] 347 UNSPEC_DTSTSFI) 348 (match_dup 4))) 349 (set (match_operand:SI 0 "register_operand") 350 (DFP_TEST:SI (match_dup 3) 351 (const_int 0))) 352 ] 353 "TARGET_P9_MISC" 354{ 355 operands[3] = gen_reg_rtx (CCFPmode); 356 operands[4] = const0_rtx; 357}) 358 359(define_insn "*dfp_sgnfcnc_<mode>" 360 [(set (match_operand:CCFP 0 "" "=y") 361 (compare:CCFP 362 (unspec:D64_D128 [(match_operand:SI 1 "const_int_operand" "n") 363 (match_operand:D64_D128 2 "gpc_reg_operand" "d")] 364 UNSPEC_DTSTSFI) 365 (match_operand:SI 3 "zero_constant" "j")))] 366 "TARGET_P9_MISC" 367{ 368 /* If immediate operand is greater than 63, it will behave as if 369 the value had been 63. The code generator does not support 370 immediate operand values greater than 63. */ 371 if (!(IN_RANGE (INTVAL (operands[1]), 0, 63))) 372 operands[1] = GEN_INT (63); 373 return "dtstsfi<dfp_suffix> %0,%1,%2"; 374} 375 [(set_attr "type" "fp")]) 376 377(define_insn "dfp_dscli_<mode>" 378 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d") 379 (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d") 380 (match_operand:QI 2 "immediate_operand" "i")] 381 UNSPEC_DSCLI))] 382 "TARGET_DFP" 383 "dscli<dfp_suffix> %0,%1,%2" 384 [(set_attr "type" "dfp")]) 385 386(define_insn "dfp_dscri_<mode>" 387 [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d") 388 (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d") 389 (match_operand:QI 2 "immediate_operand" "i")] 390 UNSPEC_DSCRI))] 391 "TARGET_DFP" 392 "dscri<dfp_suffix> %0,%1,%2" 393 [(set_attr "type" "dfp")]) 394