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