1 ;; Decimal Floating Point (DFP) patterns. 2 ;; Copyright (C) 2007-2022 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 (set_attr "size" "128")]) 144 145 ;; The result of drdpq is an even/odd register pair with the converted 146 ;; value in the even register and zero in the odd register. 147 ;; FIXME: Avoid the register move by using a reload constraint to ensure 148 ;; that the result is the first of the pair receiving the result of drdpq. 149 150 (define_insn "trunctddd2" 151 [(set (match_operand:DD 0 "gpc_reg_operand" "=d") 152 (float_truncate:DD (match_operand:TD 1 "gpc_reg_operand" "d"))) 153 (clobber (match_scratch:TD 2 "=d"))] 154 "TARGET_DFP" 155 "drdpq %2,%1\;fmr %0,%2" 156 [(set_attr "type" "dfp") 157 (set_attr "size" "128") 158 (set_attr "length" "8")]) 159 160 (define_insn "trunctdsd2" 161 [(set (match_operand:SD 0 "gpc_reg_operand" "=d,d") 162 (float_truncate:SD (match_operand:TD 1 "gpc_reg_operand" "d,d"))) 163 (clobber (match_scratch:TD 2 "=&d,&d")) 164 (clobber (match_scratch:DF 3 "=&d,&d"))] 165 "TARGET_DFP" 166 "@ 167 mffscdrni %3,7\;drdpq %2,%1\;mffscdrn %3,%3\;drsp %0,%2 168 mffs %3\;mtfsfi 7,7,1\;drdpq %2,%1\;mtfsf 0xff,%3,1,0\;drsp %0,%2" 169 [(set_attr "type" "dfp") 170 (set_attr "isa" "p9,*") 171 (set_attr "length" "16,20")]) 172 173 (define_insn "add<mode>3" 174 [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") 175 (plus:DDTD (match_operand:DDTD 1 "gpc_reg_operand" "%d") 176 (match_operand:DDTD 2 "gpc_reg_operand" "d")))] 177 "TARGET_DFP" 178 "dadd<q> %0,%1,%2" 179 [(set_attr "type" "dfp")]) 180 181 (define_insn "sub<mode>3" 182 [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") 183 (minus:DDTD (match_operand:DDTD 1 "gpc_reg_operand" "d") 184 (match_operand:DDTD 2 "gpc_reg_operand" "d")))] 185 "TARGET_DFP" 186 "dsub<q> %0,%1,%2" 187 [(set_attr "type" "dfp")]) 188 189 (define_insn "mul<mode>3" 190 [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") 191 (mult:DDTD (match_operand:DDTD 1 "gpc_reg_operand" "%d") 192 (match_operand:DDTD 2 "gpc_reg_operand" "d")))] 193 "TARGET_DFP" 194 "dmul<q> %0,%1,%2" 195 [(set_attr "type" "dfp")]) 196 197 (define_insn "div<mode>3" 198 [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") 199 (div:DDTD (match_operand:DDTD 1 "gpc_reg_operand" "d") 200 (match_operand:DDTD 2 "gpc_reg_operand" "d")))] 201 "TARGET_DFP" 202 "ddiv<q> %0,%1,%2" 203 [(set_attr "type" "dfp")]) 204 205 (define_insn "*cmp<mode>_internal1" 206 [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") 207 (compare:CCFP (match_operand:DDTD 1 "gpc_reg_operand" "d") 208 (match_operand:DDTD 2 "gpc_reg_operand" "d")))] 209 "TARGET_DFP" 210 "dcmpu<q> %0,%1,%2" 211 [(set_attr "type" "dfp") 212 (set_attr "size" "<bits>")]) 213 214 (define_insn "floatdidd2" 215 [(set (match_operand:DD 0 "gpc_reg_operand" "=d") 216 (float:DD (match_operand:DI 1 "gpc_reg_operand" "d")))] 217 "TARGET_DFP && TARGET_POPCNTD" 218 "dcffix %0,%1" 219 [(set_attr "type" "dfp")]) 220 221 (define_insn "floatditd2" 222 [(set (match_operand:TD 0 "gpc_reg_operand" "=d") 223 (float:TD (match_operand:DI 1 "gpc_reg_operand" "d")))] 224 "TARGET_DFP" 225 "dcffixq %0,%1" 226 [(set_attr "type" "dfp") 227 (set_attr "size" "128")]) 228 229 (define_insn "floattitd2" 230 [(set (match_operand:TD 0 "gpc_reg_operand" "=d") 231 (float:TD (match_operand:TI 1 "gpc_reg_operand" "v")))] 232 "TARGET_POWER10" 233 "dcffixqq %0,%1" 234 [(set_attr "type" "dfp")]) 235 236 ;; Convert a decimal64/128 to a decimal64/128 whose value is an integer. 237 ;; This is the first stage of converting it to an integer type. 238 239 (define_insn "ftrunc<mode>2" 240 [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") 241 (fix:DDTD (match_operand:DDTD 1 "gpc_reg_operand" "d")))] 242 "TARGET_DFP" 243 "drintn<q>. 0,%0,%1,1" 244 [(set_attr "type" "dfp") 245 (set_attr "size" "<bits>")]) 246 247 ;; Convert a decimal64/128 whose value is an integer to an actual integer. 248 ;; This is the second stage of converting decimal float to integer type. 249 250 (define_insn "fix<mode>di2" 251 [(set (match_operand:DI 0 "gpc_reg_operand" "=d") 252 (fix:DI (match_operand:DDTD 1 "gpc_reg_operand" "d")))] 253 "TARGET_DFP" 254 "dctfix<q> %0,%1" 255 [(set_attr "type" "dfp") 256 (set_attr "size" "<bits>")]) 257 258 (define_insn "fixtdti2" 259 [(set (match_operand:TI 0 "gpc_reg_operand" "=v") 260 (fix:TI (match_operand:TD 1 "gpc_reg_operand" "d")))] 261 "TARGET_POWER10" 262 "dctfixqq %0,%1" 263 [(set_attr "type" "dfp")]) 264 266 ;; Decimal builtin support 267 268 (define_c_enum "unspec" 269 [UNSPEC_DDEDPD 270 UNSPEC_DENBCD 271 UNSPEC_DXEX 272 UNSPEC_DIEX 273 UNSPEC_DSCLI 274 UNSPEC_DTSTSFI 275 UNSPEC_DSCRI]) 276 277 (define_code_iterator DFP_TEST [eq lt gt unordered]) 278 279 (define_insn "dfp_ddedpd_<mode>" 280 [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") 281 (unspec:DDTD [(match_operand:QI 1 "const_0_to_3_operand" "i") 282 (match_operand:DDTD 2 "gpc_reg_operand" "d")] 283 UNSPEC_DDEDPD))] 284 "TARGET_DFP" 285 "ddedpd<q> %1,%0,%2" 286 [(set_attr "type" "dfp") 287 (set_attr "size" "<bits>")]) 288 289 (define_insn "dfp_denbcd_<mode>" 290 [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") 291 (unspec:DDTD [(match_operand:QI 1 "const_0_to_1_operand" "i") 292 (match_operand:DDTD 2 "gpc_reg_operand" "d")] 293 UNSPEC_DENBCD))] 294 "TARGET_DFP" 295 "denbcd<q> %1,%0,%2" 296 [(set_attr "type" "dfp") 297 (set_attr "size" "<bits>")]) 298 299 (define_insn "dfp_denbcd_v16qi_inst" 300 [(set (match_operand:TD 0 "gpc_reg_operand" "=d") 301 (unspec:TD [(match_operand:QI 1 "const_0_to_1_operand" "i") 302 (match_operand:V16QI 2 "register_operand" "d")] 303 UNSPEC_DENBCD))] 304 "TARGET_DFP" 305 "denbcdq %1,%0,%2" 306 [(set_attr "type" "dfp")]) 307 308 (define_expand "dfp_denbcd_v16qi" 309 [(set (match_operand:TD 0 "gpc_reg_operand" "=d") 310 (unspec:TD [(match_operand:V16QI 1 "register_operand" "v")] 311 UNSPEC_DENBCD))] 312 "TARGET_DFP" 313 { 314 // Move vs128 upper 64-bits and lower 64-bits to fp register pair 315 convert_move (operands[0], operands[1], true); 316 emit_insn (gen_dfp_denbcd_v16qi_inst (operands[0], GEN_INT(1), 317 operands[0])); 318 DONE; 319 }) 320 321 (define_insn "dfp_dxex_<mode>" 322 [(set (match_operand:DI 0 "gpc_reg_operand" "=d") 323 (unspec:DI [(match_operand:DDTD 1 "gpc_reg_operand" "d")] 324 UNSPEC_DXEX))] 325 "TARGET_DFP" 326 "dxex<q> %0,%1" 327 [(set_attr "type" "dfp") 328 (set_attr "size" "<bits>")]) 329 330 (define_insn "dfp_diex_<mode>" 331 [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") 332 (unspec:DDTD [(match_operand:DI 1 "gpc_reg_operand" "d") 333 (match_operand:DDTD 2 "gpc_reg_operand" "d")] 334 UNSPEC_DXEX))] 335 "TARGET_DFP" 336 "diex<q> %0,%1,%2" 337 [(set_attr "type" "dfp") 338 (set_attr "size" "<bits>")]) 339 340 (define_expand "dfptstsfi_<code>_<mode>" 341 [(set (match_dup 3) 342 (compare:CCFP (unspec:DDTD [(match_operand:SI 1 "const_int_operand") 343 (match_operand:DDTD 2 "gpc_reg_operand")] 344 UNSPEC_DTSTSFI) 345 (const_int 0))) 346 (set (match_operand:SI 0 "register_operand") 347 (DFP_TEST:SI (match_dup 3) 348 (const_int 0))) 349 ] 350 "TARGET_P9_MISC" 351 { 352 if (<CODE> == UNORDERED && !HONOR_NANS (<MODE>mode)) 353 { 354 emit_move_insn (operands[0], const0_rtx); 355 DONE; 356 } 357 358 operands[3] = gen_reg_rtx (CCFPmode); 359 }) 360 361 (define_insn "*dfp_sgnfcnc_<mode>" 362 [(set (match_operand:CCFP 0 "" "=y") 363 (compare:CCFP 364 (unspec:DDTD [(match_operand:SI 1 "const_int_operand" "n") 365 (match_operand:DDTD 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<q> %0,%1,%2"; 376 } 377 [(set_attr "type" "fp") 378 (set_attr "size" "<bits>")]) 379 380 (define_insn "dfp_dscli_<mode>" 381 [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") 382 (unspec:DDTD [(match_operand:DDTD 1 "gpc_reg_operand" "d") 383 (match_operand:QI 2 "immediate_operand" "i")] 384 UNSPEC_DSCLI))] 385 "TARGET_DFP" 386 "dscli<q> %0,%1,%2" 387 [(set_attr "type" "dfp") 388 (set_attr "size" "<bits>")]) 389 390 (define_insn "dfp_dscri_<mode>" 391 [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") 392 (unspec:DDTD [(match_operand:DDTD 1 "gpc_reg_operand" "d") 393 (match_operand:QI 2 "immediate_operand" "i")] 394 UNSPEC_DSCRI))] 395 "TARGET_DFP" 396 "dscri<q> %0,%1,%2" 397 [(set_attr "type" "dfp") 398 (set_attr "size" "<bits>")]) 399