]>
Commit | Line | Data |
---|---|---|
7393f7f8 | 1 | ;; Decimal Floating Point (DFP) patterns. |
8d9254fc | 2 | ;; Copyright (C) 2007-2020 Free Software Foundation, Inc. |
7393f7f8 BE |
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 | |
2f83c7d6 | 10 | ;; by the Free Software Foundation; either version 3, or (at your |
7393f7f8 BE |
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 | |
2f83c7d6 NC |
19 | ;; along with GCC; see the file COPYING3. If not see |
20 | ;; <http://www.gnu.org/licenses/>. | |
7393f7f8 | 21 | |
e41b2a33 PB |
22 | ;; |
23 | ;; UNSPEC usage | |
24 | ;; | |
25 | ||
f3c33d9d MM |
26 | (define_c_enum "unspec" |
27 | [UNSPEC_MOVSD_LOAD | |
28 | UNSPEC_MOVSD_STORE | |
e41b2a33 PB |
29 | ]) |
30 | ||
b1bb8160 | 31 | ; Either of the two decimal modes. |
e35f75d3 | 32 | (define_mode_iterator DDTD [DD TD]) |
b1bb8160 | 33 | |
e35f75d3 | 34 | (define_mode_attr q [(DD "") (TD "q")]) |
b1bb8160 | 35 | |
e41b2a33 | 36 | |
e41b2a33 PB |
37 | (define_insn "movsd_store" |
38 | [(set (match_operand:DD 0 "nonimmediate_operand" "=m") | |
799dbb0f | 39 | (unspec:DD [(match_operand:SD 1 "input_operand" "d")] |
e41b2a33 PB |
40 | UNSPEC_MOVSD_STORE))] |
41 | "(gpc_reg_operand (operands[0], DDmode) | |
42 | || gpc_reg_operand (operands[1], SDmode)) | |
11d8d07e | 43 | && TARGET_HARD_FLOAT" |
e41b2a33 | 44 | "stfd%U0%X0 %1,%0" |
b24a46be | 45 | [(set_attr "type" "fpstore")]) |
e41b2a33 PB |
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)) | |
11d8d07e | 53 | && TARGET_HARD_FLOAT" |
e41b2a33 | 54 | "lfd%U1%X1 %0,%1" |
b24a46be | 55 | [(set_attr "type" "fpload")]) |
e41b2a33 PB |
56 | |
57 | ;; Hardware support for decimal floating point operations. | |
58 | ||
59 | (define_insn "extendsddd2" | |
799dbb0f | 60 | [(set (match_operand:DD 0 "gpc_reg_operand" "=d") |
e41b2a33 PB |
61 | (float_extend:DD (match_operand:SD 1 "gpc_reg_operand" "f")))] |
62 | "TARGET_DFP" | |
63 | "dctdp %0,%1" | |
eda328bf | 64 | [(set_attr "type" "dfp")]) |
e41b2a33 PB |
65 | |
66 | (define_expand "extendsdtd2" | |
799dbb0f ME |
67 | [(set (match_operand:TD 0 "gpc_reg_operand" "=d") |
68 | (float_extend:TD (match_operand:SD 1 "gpc_reg_operand" "d")))] | |
e41b2a33 PB |
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") | |
799dbb0f | 79 | (float_truncate:SD (match_operand:DD 1 "gpc_reg_operand" "d")))] |
e41b2a33 PB |
80 | "TARGET_DFP" |
81 | "drsp %0,%1" | |
eda328bf | 82 | [(set_attr "type" "dfp")]) |
e41b2a33 | 83 | |
11d8d07e | 84 | (define_insn "negdd2" |
799dbb0f ME |
85 | [(set (match_operand:DD 0 "gpc_reg_operand" "=d") |
86 | (neg:DD (match_operand:DD 1 "gpc_reg_operand" "d")))] | |
11d8d07e | 87 | "TARGET_HARD_FLOAT" |
c092b045 | 88 | "fneg %0,%1" |
7c788ce2 | 89 | [(set_attr "type" "fpsimple")]) |
c092b045 | 90 | |
11d8d07e | 91 | (define_insn "absdd2" |
799dbb0f ME |
92 | [(set (match_operand:DD 0 "gpc_reg_operand" "=d") |
93 | (abs:DD (match_operand:DD 1 "gpc_reg_operand" "d")))] | |
11d8d07e | 94 | "TARGET_HARD_FLOAT" |
c092b045 | 95 | "fabs %0,%1" |
7c788ce2 | 96 | [(set_attr "type" "fpsimple")]) |
c092b045 PB |
97 | |
98 | (define_insn "*nabsdd2_fpr" | |
799dbb0f ME |
99 | [(set (match_operand:DD 0 "gpc_reg_operand" "=d") |
100 | (neg:DD (abs:DD (match_operand:DD 1 "gpc_reg_operand" "d"))))] | |
11d8d07e | 101 | "TARGET_HARD_FLOAT" |
c092b045 | 102 | "fnabs %0,%1" |
7c788ce2 | 103 | [(set_attr "type" "fpsimple")]) |
c092b045 | 104 | |
11d8d07e | 105 | (define_insn "negtd2" |
e2323f5b PB |
106 | [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d") |
107 | (neg:TD (match_operand:TD 1 "gpc_reg_operand" "0,d")))] | |
11d8d07e | 108 | "TARGET_HARD_FLOAT" |
e2323f5b PB |
109 | "@ |
110 | fneg %0,%1 | |
111 | fneg %0,%1\;fmr %L0,%L1" | |
7c788ce2 | 112 | [(set_attr "type" "fpsimple") |
e2323f5b | 113 | (set_attr "length" "4,8")]) |
c092b045 | 114 | |
11d8d07e | 115 | (define_insn "abstd2" |
e2323f5b PB |
116 | [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d") |
117 | (abs:TD (match_operand:TD 1 "gpc_reg_operand" "0,d")))] | |
11d8d07e | 118 | "TARGET_HARD_FLOAT" |
e2323f5b PB |
119 | "@ |
120 | fabs %0,%1 | |
121 | fabs %0,%1\;fmr %L0,%L1" | |
7c788ce2 | 122 | [(set_attr "type" "fpsimple") |
e2323f5b | 123 | (set_attr "length" "4,8")]) |
c092b045 PB |
124 | |
125 | (define_insn "*nabstd2_fpr" | |
e2323f5b PB |
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"))))] | |
11d8d07e | 128 | "TARGET_HARD_FLOAT" |
e2323f5b PB |
129 | "@ |
130 | fnabs %0,%1 | |
131 | fnabs %0,%1\;fmr %L0,%L1" | |
7c788ce2 | 132 | [(set_attr "type" "fpsimple") |
e2323f5b | 133 | (set_attr "length" "4,8")]) |
c092b045 | 134 | |
6ef9a246 JJ |
135 | ;; Hardware support for decimal floating point operations. |
136 | ||
137 | (define_insn "extendddtd2" | |
799dbb0f ME |
138 | [(set (match_operand:TD 0 "gpc_reg_operand" "=d") |
139 | (float_extend:TD (match_operand:DD 1 "gpc_reg_operand" "d")))] | |
6ef9a246 JJ |
140 | "TARGET_DFP" |
141 | "dctqpq %0,%1" | |
eda328bf | 142 | [(set_attr "type" "dfp")]) |
6ef9a246 JJ |
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" | |
799dbb0f ME |
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"))] | |
6ef9a246 JJ |
153 | "TARGET_DFP" |
154 | "drdpq %2,%1\;fmr %0,%2" | |
eda328bf | 155 | [(set_attr "type" "dfp") |
521466e5 | 156 | (set_attr "length" "8")]) |
6ef9a246 | 157 | |
8a8c2573 PB |
158 | (define_insn "trunctdsd2" |
159 | [(set (match_operand:SD 0 "gpc_reg_operand" "=d,d") | |
160 | (float_truncate:SD (match_operand:TD 1 "gpc_reg_operand" "d,d"))) | |
161 | (clobber (match_scratch:TD 2 "=&d,&d")) | |
162 | (clobber (match_scratch:DF 3 "=&d,&d"))] | |
163 | "TARGET_DFP" | |
164 | "@ | |
165 | mffscdrni %3,7\;drdpq %2,%1\;mffscdrn %3,%3\;drsp %0,%2 | |
166 | mffs %3\;mtfsfi 7,7,1\;drdpq %2,%1\;mtfsf 0xff,%3,1,0\;drsp %0,%2" | |
167 | [(set_attr "type" "dfp") | |
168 | (set_attr "isa" "p9,*") | |
169 | (set_attr "length" "16,20")]) | |
170 | ||
b1bb8160 | 171 | (define_insn "add<mode>3" |
e35f75d3 SB |
172 | [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") |
173 | (plus:DDTD (match_operand:DDTD 1 "gpc_reg_operand" "%d") | |
174 | (match_operand:DDTD 2 "gpc_reg_operand" "d")))] | |
6ef9a246 | 175 | "TARGET_DFP" |
e35f75d3 | 176 | "dadd<q> %0,%1,%2" |
eda328bf | 177 | [(set_attr "type" "dfp")]) |
6ef9a246 | 178 | |
b1bb8160 | 179 | (define_insn "sub<mode>3" |
e35f75d3 SB |
180 | [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") |
181 | (minus:DDTD (match_operand:DDTD 1 "gpc_reg_operand" "d") | |
182 | (match_operand:DDTD 2 "gpc_reg_operand" "d")))] | |
6ef9a246 | 183 | "TARGET_DFP" |
e35f75d3 | 184 | "dsub<q> %0,%1,%2" |
eda328bf | 185 | [(set_attr "type" "dfp")]) |
6ef9a246 | 186 | |
b1bb8160 | 187 | (define_insn "mul<mode>3" |
e35f75d3 SB |
188 | [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") |
189 | (mult:DDTD (match_operand:DDTD 1 "gpc_reg_operand" "%d") | |
190 | (match_operand:DDTD 2 "gpc_reg_operand" "d")))] | |
6ef9a246 | 191 | "TARGET_DFP" |
e35f75d3 | 192 | "dmul<q> %0,%1,%2" |
eda328bf | 193 | [(set_attr "type" "dfp")]) |
6ef9a246 | 194 | |
b1bb8160 | 195 | (define_insn "div<mode>3" |
e35f75d3 SB |
196 | [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") |
197 | (div:DDTD (match_operand:DDTD 1 "gpc_reg_operand" "d") | |
198 | (match_operand:DDTD 2 "gpc_reg_operand" "d")))] | |
6ef9a246 | 199 | "TARGET_DFP" |
e35f75d3 | 200 | "ddiv<q> %0,%1,%2" |
eda328bf | 201 | [(set_attr "type" "dfp")]) |
6ef9a246 | 202 | |
b1bb8160 | 203 | (define_insn "*cmp<mode>_internal1" |
6ef9a246 | 204 | [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") |
e35f75d3 SB |
205 | (compare:CCFP (match_operand:DDTD 1 "gpc_reg_operand" "d") |
206 | (match_operand:DDTD 2 "gpc_reg_operand" "d")))] | |
6ef9a246 | 207 | "TARGET_DFP" |
e35f75d3 | 208 | "dcmpu<q> %0,%1,%2" |
eda328bf | 209 | [(set_attr "type" "dfp")]) |
6ef9a246 | 210 | |
6f975f93 PB |
211 | (define_insn "floatdidd2" |
212 | [(set (match_operand:DD 0 "gpc_reg_operand" "=d") | |
213 | (float:DD (match_operand:DI 1 "gpc_reg_operand" "d")))] | |
214 | "TARGET_DFP && TARGET_POPCNTD" | |
215 | "dcffix %0,%1" | |
eda328bf | 216 | [(set_attr "type" "dfp")]) |
6f975f93 | 217 | |
6ef9a246 | 218 | (define_insn "floatditd2" |
799dbb0f ME |
219 | [(set (match_operand:TD 0 "gpc_reg_operand" "=d") |
220 | (float:TD (match_operand:DI 1 "gpc_reg_operand" "d")))] | |
6ef9a246 JJ |
221 | "TARGET_DFP" |
222 | "dcffixq %0,%1" | |
eda328bf | 223 | [(set_attr "type" "dfp")]) |
6ef9a246 | 224 | |
b1bb8160 | 225 | ;; Convert a decimal64/128 to a decimal64/128 whose value is an integer. |
6ef9a246 JJ |
226 | ;; This is the first stage of converting it to an integer type. |
227 | ||
b1bb8160 | 228 | (define_insn "ftrunc<mode>2" |
e35f75d3 SB |
229 | [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") |
230 | (fix:DDTD (match_operand:DDTD 1 "gpc_reg_operand" "d")))] | |
6ef9a246 | 231 | "TARGET_DFP" |
e35f75d3 | 232 | "drintn<q>. 0,%0,%1,1" |
eda328bf | 233 | [(set_attr "type" "dfp")]) |
6ef9a246 | 234 | |
b1bb8160 | 235 | ;; Convert a decimal64/128 whose value is an integer to an actual integer. |
6ef9a246 JJ |
236 | ;; This is the second stage of converting decimal float to integer type. |
237 | ||
b1bb8160 | 238 | (define_insn "fix<mode>di2" |
799dbb0f | 239 | [(set (match_operand:DI 0 "gpc_reg_operand" "=d") |
e35f75d3 | 240 | (fix:DI (match_operand:DDTD 1 "gpc_reg_operand" "d")))] |
6ef9a246 | 241 | "TARGET_DFP" |
e35f75d3 | 242 | "dctfix<q> %0,%1" |
eda328bf | 243 | [(set_attr "type" "dfp")]) |
06b39289 MM |
244 | \f |
245 | ;; Decimal builtin support | |
246 | ||
247 | (define_c_enum "unspec" | |
248 | [UNSPEC_DDEDPD | |
249 | UNSPEC_DENBCD | |
250 | UNSPEC_DXEX | |
251 | UNSPEC_DIEX | |
252 | UNSPEC_DSCLI | |
5a3a6a5e | 253 | UNSPEC_DTSTSFI |
06b39289 MM |
254 | UNSPEC_DSCRI]) |
255 | ||
5a3a6a5e KN |
256 | (define_code_iterator DFP_TEST [eq lt gt unordered]) |
257 | ||
06b39289 | 258 | (define_insn "dfp_ddedpd_<mode>" |
e35f75d3 SB |
259 | [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") |
260 | (unspec:DDTD [(match_operand:QI 1 "const_0_to_3_operand" "i") | |
261 | (match_operand:DDTD 2 "gpc_reg_operand" "d")] | |
262 | UNSPEC_DDEDPD))] | |
06b39289 | 263 | "TARGET_DFP" |
e35f75d3 | 264 | "ddedpd<q> %1,%0,%2" |
eda328bf | 265 | [(set_attr "type" "dfp")]) |
06b39289 MM |
266 | |
267 | (define_insn "dfp_denbcd_<mode>" | |
e35f75d3 SB |
268 | [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") |
269 | (unspec:DDTD [(match_operand:QI 1 "const_0_to_1_operand" "i") | |
270 | (match_operand:DDTD 2 "gpc_reg_operand" "d")] | |
271 | UNSPEC_DENBCD))] | |
06b39289 | 272 | "TARGET_DFP" |
e35f75d3 | 273 | "denbcd<q> %1,%0,%2" |
eda328bf | 274 | [(set_attr "type" "dfp")]) |
06b39289 MM |
275 | |
276 | (define_insn "dfp_dxex_<mode>" | |
05dc406d | 277 | [(set (match_operand:DI 0 "gpc_reg_operand" "=d") |
e35f75d3 | 278 | (unspec:DI [(match_operand:DDTD 1 "gpc_reg_operand" "d")] |
05dc406d | 279 | UNSPEC_DXEX))] |
06b39289 | 280 | "TARGET_DFP" |
e35f75d3 | 281 | "dxex<q> %0,%1" |
eda328bf | 282 | [(set_attr "type" "dfp")]) |
06b39289 MM |
283 | |
284 | (define_insn "dfp_diex_<mode>" | |
e35f75d3 SB |
285 | [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") |
286 | (unspec:DDTD [(match_operand:DI 1 "gpc_reg_operand" "d") | |
287 | (match_operand:DDTD 2 "gpc_reg_operand" "d")] | |
288 | UNSPEC_DXEX))] | |
06b39289 | 289 | "TARGET_DFP" |
e35f75d3 | 290 | "diex<q> %0,%1,%2" |
eda328bf | 291 | [(set_attr "type" "dfp")]) |
06b39289 | 292 | |
5a3a6a5e KN |
293 | (define_expand "dfptstsfi_<code>_<mode>" |
294 | [(set (match_dup 3) | |
e35f75d3 SB |
295 | (compare:CCFP (unspec:DDTD [(match_operand:SI 1 "const_int_operand") |
296 | (match_operand:DDTD 2 "gpc_reg_operand")] | |
297 | UNSPEC_DTSTSFI) | |
298 | (const_int 0))) | |
ad18eed2 | 299 | (set (match_operand:SI 0 "register_operand") |
e35f75d3 | 300 | (DFP_TEST:SI (match_dup 3) |
5a3a6a5e KN |
301 | (const_int 0))) |
302 | ] | |
303 | "TARGET_P9_MISC" | |
304 | { | |
bcb4b4b4 SB |
305 | if (<CODE> == UNORDERED && !HONOR_NANS (<MODE>mode)) |
306 | { | |
307 | emit_move_insn (operands[0], const0_rtx); | |
308 | DONE; | |
309 | } | |
310 | ||
5a3a6a5e | 311 | operands[3] = gen_reg_rtx (CCFPmode); |
5a3a6a5e KN |
312 | }) |
313 | ||
314 | (define_insn "*dfp_sgnfcnc_<mode>" | |
315 | [(set (match_operand:CCFP 0 "" "=y") | |
e35f75d3 SB |
316 | (compare:CCFP |
317 | (unspec:DDTD [(match_operand:SI 1 "const_int_operand" "n") | |
318 | (match_operand:DDTD 2 "gpc_reg_operand" "d")] | |
319 | UNSPEC_DTSTSFI) | |
5a3a6a5e KN |
320 | (match_operand:SI 3 "zero_constant" "j")))] |
321 | "TARGET_P9_MISC" | |
322 | { | |
323 | /* If immediate operand is greater than 63, it will behave as if | |
324 | the value had been 63. The code generator does not support | |
325 | immediate operand values greater than 63. */ | |
326 | if (!(IN_RANGE (INTVAL (operands[1]), 0, 63))) | |
327 | operands[1] = GEN_INT (63); | |
e35f75d3 | 328 | return "dtstsfi<q> %0,%1,%2"; |
5a3a6a5e KN |
329 | } |
330 | [(set_attr "type" "fp")]) | |
331 | ||
06b39289 | 332 | (define_insn "dfp_dscli_<mode>" |
e35f75d3 SB |
333 | [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") |
334 | (unspec:DDTD [(match_operand:DDTD 1 "gpc_reg_operand" "d") | |
335 | (match_operand:QI 2 "immediate_operand" "i")] | |
336 | UNSPEC_DSCLI))] | |
06b39289 | 337 | "TARGET_DFP" |
e35f75d3 | 338 | "dscli<q> %0,%1,%2" |
eda328bf | 339 | [(set_attr "type" "dfp")]) |
06b39289 MM |
340 | |
341 | (define_insn "dfp_dscri_<mode>" | |
e35f75d3 SB |
342 | [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d") |
343 | (unspec:DDTD [(match_operand:DDTD 1 "gpc_reg_operand" "d") | |
344 | (match_operand:QI 2 "immediate_operand" "i")] | |
345 | UNSPEC_DSCRI))] | |
06b39289 | 346 | "TARGET_DFP" |
e35f75d3 | 347 | "dscri<q> %0,%1,%2" |
eda328bf | 348 | [(set_attr "type" "dfp")]) |