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