root / target-ppc / fpu_helper.c @ 5b50e790
History | View | Annotate | Download (48.5 kB)
1 | bd23cd45 | Blue Swirl | /*
|
---|---|---|---|
2 | bd23cd45 | Blue Swirl | * PowerPC floating point and SPE emulation helpers for QEMU.
|
3 | bd23cd45 | Blue Swirl | *
|
4 | bd23cd45 | Blue Swirl | * Copyright (c) 2003-2007 Jocelyn Mayer
|
5 | bd23cd45 | Blue Swirl | *
|
6 | bd23cd45 | Blue Swirl | * This library is free software; you can redistribute it and/or
|
7 | bd23cd45 | Blue Swirl | * modify it under the terms of the GNU Lesser General Public
|
8 | bd23cd45 | Blue Swirl | * License as published by the Free Software Foundation; either
|
9 | bd23cd45 | Blue Swirl | * version 2 of the License, or (at your option) any later version.
|
10 | bd23cd45 | Blue Swirl | *
|
11 | bd23cd45 | Blue Swirl | * This library is distributed in the hope that it will be useful,
|
12 | bd23cd45 | Blue Swirl | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | bd23cd45 | Blue Swirl | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 | bd23cd45 | Blue Swirl | * Lesser General Public License for more details.
|
15 | bd23cd45 | Blue Swirl | *
|
16 | bd23cd45 | Blue Swirl | * You should have received a copy of the GNU Lesser General Public
|
17 | bd23cd45 | Blue Swirl | * License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
18 | bd23cd45 | Blue Swirl | */
|
19 | bd23cd45 | Blue Swirl | #include "cpu.h" |
20 | bd23cd45 | Blue Swirl | #include "helper.h" |
21 | bd23cd45 | Blue Swirl | |
22 | bd23cd45 | Blue Swirl | /*****************************************************************************/
|
23 | bd23cd45 | Blue Swirl | /* Floating point operations helpers */
|
24 | 8e703949 | Blue Swirl | uint64_t helper_float32_to_float64(CPUPPCState *env, uint32_t arg) |
25 | bd23cd45 | Blue Swirl | { |
26 | bd23cd45 | Blue Swirl | CPU_FloatU f; |
27 | bd23cd45 | Blue Swirl | CPU_DoubleU d; |
28 | bd23cd45 | Blue Swirl | |
29 | bd23cd45 | Blue Swirl | f.l = arg; |
30 | bd23cd45 | Blue Swirl | d.d = float32_to_float64(f.f, &env->fp_status); |
31 | bd23cd45 | Blue Swirl | return d.ll;
|
32 | bd23cd45 | Blue Swirl | } |
33 | bd23cd45 | Blue Swirl | |
34 | 8e703949 | Blue Swirl | uint32_t helper_float64_to_float32(CPUPPCState *env, uint64_t arg) |
35 | bd23cd45 | Blue Swirl | { |
36 | bd23cd45 | Blue Swirl | CPU_FloatU f; |
37 | bd23cd45 | Blue Swirl | CPU_DoubleU d; |
38 | bd23cd45 | Blue Swirl | |
39 | bd23cd45 | Blue Swirl | d.ll = arg; |
40 | bd23cd45 | Blue Swirl | f.f = float64_to_float32(d.d, &env->fp_status); |
41 | bd23cd45 | Blue Swirl | return f.l;
|
42 | bd23cd45 | Blue Swirl | } |
43 | bd23cd45 | Blue Swirl | |
44 | bd23cd45 | Blue Swirl | static inline int isden(float64 d) |
45 | bd23cd45 | Blue Swirl | { |
46 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
47 | bd23cd45 | Blue Swirl | |
48 | bd23cd45 | Blue Swirl | u.d = d; |
49 | bd23cd45 | Blue Swirl | |
50 | bd23cd45 | Blue Swirl | return ((u.ll >> 52) & 0x7FF) == 0; |
51 | bd23cd45 | Blue Swirl | } |
52 | bd23cd45 | Blue Swirl | |
53 | 8e703949 | Blue Swirl | uint32_t helper_compute_fprf(CPUPPCState *env, uint64_t arg, uint32_t set_fprf) |
54 | bd23cd45 | Blue Swirl | { |
55 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
56 | bd23cd45 | Blue Swirl | int isneg;
|
57 | bd23cd45 | Blue Swirl | int ret;
|
58 | bd23cd45 | Blue Swirl | |
59 | bd23cd45 | Blue Swirl | farg.ll = arg; |
60 | bd23cd45 | Blue Swirl | isneg = float64_is_neg(farg.d); |
61 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(farg.d))) {
|
62 | bd23cd45 | Blue Swirl | if (float64_is_signaling_nan(farg.d)) {
|
63 | bd23cd45 | Blue Swirl | /* Signaling NaN: flags are undefined */
|
64 | bd23cd45 | Blue Swirl | ret = 0x00;
|
65 | bd23cd45 | Blue Swirl | } else {
|
66 | bd23cd45 | Blue Swirl | /* Quiet NaN */
|
67 | bd23cd45 | Blue Swirl | ret = 0x11;
|
68 | bd23cd45 | Blue Swirl | } |
69 | bd23cd45 | Blue Swirl | } else if (unlikely(float64_is_infinity(farg.d))) { |
70 | bd23cd45 | Blue Swirl | /* +/- infinity */
|
71 | bd23cd45 | Blue Swirl | if (isneg) {
|
72 | bd23cd45 | Blue Swirl | ret = 0x09;
|
73 | bd23cd45 | Blue Swirl | } else {
|
74 | bd23cd45 | Blue Swirl | ret = 0x05;
|
75 | bd23cd45 | Blue Swirl | } |
76 | bd23cd45 | Blue Swirl | } else {
|
77 | bd23cd45 | Blue Swirl | if (float64_is_zero(farg.d)) {
|
78 | bd23cd45 | Blue Swirl | /* +/- zero */
|
79 | bd23cd45 | Blue Swirl | if (isneg) {
|
80 | bd23cd45 | Blue Swirl | ret = 0x12;
|
81 | bd23cd45 | Blue Swirl | } else {
|
82 | bd23cd45 | Blue Swirl | ret = 0x02;
|
83 | bd23cd45 | Blue Swirl | } |
84 | bd23cd45 | Blue Swirl | } else {
|
85 | bd23cd45 | Blue Swirl | if (isden(farg.d)) {
|
86 | bd23cd45 | Blue Swirl | /* Denormalized numbers */
|
87 | bd23cd45 | Blue Swirl | ret = 0x10;
|
88 | bd23cd45 | Blue Swirl | } else {
|
89 | bd23cd45 | Blue Swirl | /* Normalized numbers */
|
90 | bd23cd45 | Blue Swirl | ret = 0x00;
|
91 | bd23cd45 | Blue Swirl | } |
92 | bd23cd45 | Blue Swirl | if (isneg) {
|
93 | bd23cd45 | Blue Swirl | ret |= 0x08;
|
94 | bd23cd45 | Blue Swirl | } else {
|
95 | bd23cd45 | Blue Swirl | ret |= 0x04;
|
96 | bd23cd45 | Blue Swirl | } |
97 | bd23cd45 | Blue Swirl | } |
98 | bd23cd45 | Blue Swirl | } |
99 | bd23cd45 | Blue Swirl | if (set_fprf) {
|
100 | bd23cd45 | Blue Swirl | /* We update FPSCR_FPRF */
|
101 | bd23cd45 | Blue Swirl | env->fpscr &= ~(0x1F << FPSCR_FPRF);
|
102 | bd23cd45 | Blue Swirl | env->fpscr |= ret << FPSCR_FPRF; |
103 | bd23cd45 | Blue Swirl | } |
104 | bd23cd45 | Blue Swirl | /* We just need fpcc to update Rc1 */
|
105 | bd23cd45 | Blue Swirl | return ret & 0xF; |
106 | bd23cd45 | Blue Swirl | } |
107 | bd23cd45 | Blue Swirl | |
108 | bd23cd45 | Blue Swirl | /* Floating-point invalid operations exception */
|
109 | 8e703949 | Blue Swirl | static inline uint64_t fload_invalid_op_excp(CPUPPCState *env, int op) |
110 | bd23cd45 | Blue Swirl | { |
111 | bd23cd45 | Blue Swirl | uint64_t ret = 0;
|
112 | bd23cd45 | Blue Swirl | int ve;
|
113 | bd23cd45 | Blue Swirl | |
114 | bd23cd45 | Blue Swirl | ve = fpscr_ve; |
115 | bd23cd45 | Blue Swirl | switch (op) {
|
116 | bd23cd45 | Blue Swirl | case POWERPC_EXCP_FP_VXSNAN:
|
117 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_VXSNAN;
|
118 | bd23cd45 | Blue Swirl | break;
|
119 | bd23cd45 | Blue Swirl | case POWERPC_EXCP_FP_VXSOFT:
|
120 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_VXSOFT;
|
121 | bd23cd45 | Blue Swirl | break;
|
122 | bd23cd45 | Blue Swirl | case POWERPC_EXCP_FP_VXISI:
|
123 | bd23cd45 | Blue Swirl | /* Magnitude subtraction of infinities */
|
124 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_VXISI;
|
125 | bd23cd45 | Blue Swirl | goto update_arith;
|
126 | bd23cd45 | Blue Swirl | case POWERPC_EXCP_FP_VXIDI:
|
127 | bd23cd45 | Blue Swirl | /* Division of infinity by infinity */
|
128 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_VXIDI;
|
129 | bd23cd45 | Blue Swirl | goto update_arith;
|
130 | bd23cd45 | Blue Swirl | case POWERPC_EXCP_FP_VXZDZ:
|
131 | bd23cd45 | Blue Swirl | /* Division of zero by zero */
|
132 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_VXZDZ;
|
133 | bd23cd45 | Blue Swirl | goto update_arith;
|
134 | bd23cd45 | Blue Swirl | case POWERPC_EXCP_FP_VXIMZ:
|
135 | bd23cd45 | Blue Swirl | /* Multiplication of zero by infinity */
|
136 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_VXIMZ;
|
137 | bd23cd45 | Blue Swirl | goto update_arith;
|
138 | bd23cd45 | Blue Swirl | case POWERPC_EXCP_FP_VXVC:
|
139 | bd23cd45 | Blue Swirl | /* Ordered comparison of NaN */
|
140 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_VXVC;
|
141 | bd23cd45 | Blue Swirl | env->fpscr &= ~(0xF << FPSCR_FPCC);
|
142 | bd23cd45 | Blue Swirl | env->fpscr |= 0x11 << FPSCR_FPCC;
|
143 | bd23cd45 | Blue Swirl | /* We must update the target FPR before raising the exception */
|
144 | bd23cd45 | Blue Swirl | if (ve != 0) { |
145 | bd23cd45 | Blue Swirl | env->exception_index = POWERPC_EXCP_PROGRAM; |
146 | bd23cd45 | Blue Swirl | env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_VXVC; |
147 | bd23cd45 | Blue Swirl | /* Update the floating-point enabled exception summary */
|
148 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FEX;
|
149 | bd23cd45 | Blue Swirl | /* Exception is differed */
|
150 | bd23cd45 | Blue Swirl | ve = 0;
|
151 | bd23cd45 | Blue Swirl | } |
152 | bd23cd45 | Blue Swirl | break;
|
153 | bd23cd45 | Blue Swirl | case POWERPC_EXCP_FP_VXSQRT:
|
154 | bd23cd45 | Blue Swirl | /* Square root of a negative number */
|
155 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_VXSQRT;
|
156 | bd23cd45 | Blue Swirl | update_arith:
|
157 | bd23cd45 | Blue Swirl | env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI)); |
158 | bd23cd45 | Blue Swirl | if (ve == 0) { |
159 | bd23cd45 | Blue Swirl | /* Set the result to quiet NaN */
|
160 | bd23cd45 | Blue Swirl | ret = 0x7FF8000000000000ULL;
|
161 | bd23cd45 | Blue Swirl | env->fpscr &= ~(0xF << FPSCR_FPCC);
|
162 | bd23cd45 | Blue Swirl | env->fpscr |= 0x11 << FPSCR_FPCC;
|
163 | bd23cd45 | Blue Swirl | } |
164 | bd23cd45 | Blue Swirl | break;
|
165 | bd23cd45 | Blue Swirl | case POWERPC_EXCP_FP_VXCVI:
|
166 | bd23cd45 | Blue Swirl | /* Invalid conversion */
|
167 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_VXCVI;
|
168 | bd23cd45 | Blue Swirl | env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI)); |
169 | bd23cd45 | Blue Swirl | if (ve == 0) { |
170 | bd23cd45 | Blue Swirl | /* Set the result to quiet NaN */
|
171 | bd23cd45 | Blue Swirl | ret = 0x7FF8000000000000ULL;
|
172 | bd23cd45 | Blue Swirl | env->fpscr &= ~(0xF << FPSCR_FPCC);
|
173 | bd23cd45 | Blue Swirl | env->fpscr |= 0x11 << FPSCR_FPCC;
|
174 | bd23cd45 | Blue Swirl | } |
175 | bd23cd45 | Blue Swirl | break;
|
176 | bd23cd45 | Blue Swirl | } |
177 | bd23cd45 | Blue Swirl | /* Update the floating-point invalid operation summary */
|
178 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_VX;
|
179 | bd23cd45 | Blue Swirl | /* Update the floating-point exception summary */
|
180 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FX;
|
181 | bd23cd45 | Blue Swirl | if (ve != 0) { |
182 | bd23cd45 | Blue Swirl | /* Update the floating-point enabled exception summary */
|
183 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FEX;
|
184 | bd23cd45 | Blue Swirl | if (msr_fe0 != 0 || msr_fe1 != 0) { |
185 | bd23cd45 | Blue Swirl | helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM, |
186 | bd23cd45 | Blue Swirl | POWERPC_EXCP_FP | op); |
187 | bd23cd45 | Blue Swirl | } |
188 | bd23cd45 | Blue Swirl | } |
189 | bd23cd45 | Blue Swirl | return ret;
|
190 | bd23cd45 | Blue Swirl | } |
191 | bd23cd45 | Blue Swirl | |
192 | 8e703949 | Blue Swirl | static inline void float_zero_divide_excp(CPUPPCState *env) |
193 | bd23cd45 | Blue Swirl | { |
194 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_ZX;
|
195 | bd23cd45 | Blue Swirl | env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI)); |
196 | bd23cd45 | Blue Swirl | /* Update the floating-point exception summary */
|
197 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FX;
|
198 | bd23cd45 | Blue Swirl | if (fpscr_ze != 0) { |
199 | bd23cd45 | Blue Swirl | /* Update the floating-point enabled exception summary */
|
200 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FEX;
|
201 | bd23cd45 | Blue Swirl | if (msr_fe0 != 0 || msr_fe1 != 0) { |
202 | bd23cd45 | Blue Swirl | helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM, |
203 | bd23cd45 | Blue Swirl | POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX); |
204 | bd23cd45 | Blue Swirl | } |
205 | bd23cd45 | Blue Swirl | } |
206 | bd23cd45 | Blue Swirl | } |
207 | bd23cd45 | Blue Swirl | |
208 | 8e703949 | Blue Swirl | static inline void float_overflow_excp(CPUPPCState *env) |
209 | bd23cd45 | Blue Swirl | { |
210 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_OX;
|
211 | bd23cd45 | Blue Swirl | /* Update the floating-point exception summary */
|
212 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FX;
|
213 | bd23cd45 | Blue Swirl | if (fpscr_oe != 0) { |
214 | bd23cd45 | Blue Swirl | /* XXX: should adjust the result */
|
215 | bd23cd45 | Blue Swirl | /* Update the floating-point enabled exception summary */
|
216 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FEX;
|
217 | bd23cd45 | Blue Swirl | /* We must update the target FPR before raising the exception */
|
218 | bd23cd45 | Blue Swirl | env->exception_index = POWERPC_EXCP_PROGRAM; |
219 | bd23cd45 | Blue Swirl | env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX; |
220 | bd23cd45 | Blue Swirl | } else {
|
221 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_XX;
|
222 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FI;
|
223 | bd23cd45 | Blue Swirl | } |
224 | bd23cd45 | Blue Swirl | } |
225 | bd23cd45 | Blue Swirl | |
226 | 8e703949 | Blue Swirl | static inline void float_underflow_excp(CPUPPCState *env) |
227 | bd23cd45 | Blue Swirl | { |
228 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_UX;
|
229 | bd23cd45 | Blue Swirl | /* Update the floating-point exception summary */
|
230 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FX;
|
231 | bd23cd45 | Blue Swirl | if (fpscr_ue != 0) { |
232 | bd23cd45 | Blue Swirl | /* XXX: should adjust the result */
|
233 | bd23cd45 | Blue Swirl | /* Update the floating-point enabled exception summary */
|
234 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FEX;
|
235 | bd23cd45 | Blue Swirl | /* We must update the target FPR before raising the exception */
|
236 | bd23cd45 | Blue Swirl | env->exception_index = POWERPC_EXCP_PROGRAM; |
237 | bd23cd45 | Blue Swirl | env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX; |
238 | bd23cd45 | Blue Swirl | } |
239 | bd23cd45 | Blue Swirl | } |
240 | bd23cd45 | Blue Swirl | |
241 | 8e703949 | Blue Swirl | static inline void float_inexact_excp(CPUPPCState *env) |
242 | bd23cd45 | Blue Swirl | { |
243 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_XX;
|
244 | bd23cd45 | Blue Swirl | /* Update the floating-point exception summary */
|
245 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FX;
|
246 | bd23cd45 | Blue Swirl | if (fpscr_xe != 0) { |
247 | bd23cd45 | Blue Swirl | /* Update the floating-point enabled exception summary */
|
248 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FEX;
|
249 | bd23cd45 | Blue Swirl | /* We must update the target FPR before raising the exception */
|
250 | bd23cd45 | Blue Swirl | env->exception_index = POWERPC_EXCP_PROGRAM; |
251 | bd23cd45 | Blue Swirl | env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX; |
252 | bd23cd45 | Blue Swirl | } |
253 | bd23cd45 | Blue Swirl | } |
254 | bd23cd45 | Blue Swirl | |
255 | 8e703949 | Blue Swirl | static inline void fpscr_set_rounding_mode(CPUPPCState *env) |
256 | bd23cd45 | Blue Swirl | { |
257 | bd23cd45 | Blue Swirl | int rnd_type;
|
258 | bd23cd45 | Blue Swirl | |
259 | bd23cd45 | Blue Swirl | /* Set rounding mode */
|
260 | bd23cd45 | Blue Swirl | switch (fpscr_rn) {
|
261 | bd23cd45 | Blue Swirl | case 0: |
262 | bd23cd45 | Blue Swirl | /* Best approximation (round to nearest) */
|
263 | bd23cd45 | Blue Swirl | rnd_type = float_round_nearest_even; |
264 | bd23cd45 | Blue Swirl | break;
|
265 | bd23cd45 | Blue Swirl | case 1: |
266 | bd23cd45 | Blue Swirl | /* Smaller magnitude (round toward zero) */
|
267 | bd23cd45 | Blue Swirl | rnd_type = float_round_to_zero; |
268 | bd23cd45 | Blue Swirl | break;
|
269 | bd23cd45 | Blue Swirl | case 2: |
270 | bd23cd45 | Blue Swirl | /* Round toward +infinite */
|
271 | bd23cd45 | Blue Swirl | rnd_type = float_round_up; |
272 | bd23cd45 | Blue Swirl | break;
|
273 | bd23cd45 | Blue Swirl | default:
|
274 | bd23cd45 | Blue Swirl | case 3: |
275 | bd23cd45 | Blue Swirl | /* Round toward -infinite */
|
276 | bd23cd45 | Blue Swirl | rnd_type = float_round_down; |
277 | bd23cd45 | Blue Swirl | break;
|
278 | bd23cd45 | Blue Swirl | } |
279 | bd23cd45 | Blue Swirl | set_float_rounding_mode(rnd_type, &env->fp_status); |
280 | bd23cd45 | Blue Swirl | } |
281 | bd23cd45 | Blue Swirl | |
282 | 8e703949 | Blue Swirl | void helper_fpscr_clrbit(CPUPPCState *env, uint32_t bit)
|
283 | bd23cd45 | Blue Swirl | { |
284 | bd23cd45 | Blue Swirl | int prev;
|
285 | bd23cd45 | Blue Swirl | |
286 | bd23cd45 | Blue Swirl | prev = (env->fpscr >> bit) & 1;
|
287 | bd23cd45 | Blue Swirl | env->fpscr &= ~(1 << bit);
|
288 | bd23cd45 | Blue Swirl | if (prev == 1) { |
289 | bd23cd45 | Blue Swirl | switch (bit) {
|
290 | bd23cd45 | Blue Swirl | case FPSCR_RN1:
|
291 | bd23cd45 | Blue Swirl | case FPSCR_RN:
|
292 | 8e703949 | Blue Swirl | fpscr_set_rounding_mode(env); |
293 | bd23cd45 | Blue Swirl | break;
|
294 | bd23cd45 | Blue Swirl | default:
|
295 | bd23cd45 | Blue Swirl | break;
|
296 | bd23cd45 | Blue Swirl | } |
297 | bd23cd45 | Blue Swirl | } |
298 | bd23cd45 | Blue Swirl | } |
299 | bd23cd45 | Blue Swirl | |
300 | 8e703949 | Blue Swirl | void helper_fpscr_setbit(CPUPPCState *env, uint32_t bit)
|
301 | bd23cd45 | Blue Swirl | { |
302 | bd23cd45 | Blue Swirl | int prev;
|
303 | bd23cd45 | Blue Swirl | |
304 | bd23cd45 | Blue Swirl | prev = (env->fpscr >> bit) & 1;
|
305 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << bit;
|
306 | bd23cd45 | Blue Swirl | if (prev == 0) { |
307 | bd23cd45 | Blue Swirl | switch (bit) {
|
308 | bd23cd45 | Blue Swirl | case FPSCR_VX:
|
309 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FX;
|
310 | bd23cd45 | Blue Swirl | if (fpscr_ve) {
|
311 | bd23cd45 | Blue Swirl | goto raise_ve;
|
312 | bd23cd45 | Blue Swirl | } |
313 | 90638255 | Blue Swirl | break;
|
314 | bd23cd45 | Blue Swirl | case FPSCR_OX:
|
315 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FX;
|
316 | bd23cd45 | Blue Swirl | if (fpscr_oe) {
|
317 | bd23cd45 | Blue Swirl | goto raise_oe;
|
318 | bd23cd45 | Blue Swirl | } |
319 | bd23cd45 | Blue Swirl | break;
|
320 | bd23cd45 | Blue Swirl | case FPSCR_UX:
|
321 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FX;
|
322 | bd23cd45 | Blue Swirl | if (fpscr_ue) {
|
323 | bd23cd45 | Blue Swirl | goto raise_ue;
|
324 | bd23cd45 | Blue Swirl | } |
325 | bd23cd45 | Blue Swirl | break;
|
326 | bd23cd45 | Blue Swirl | case FPSCR_ZX:
|
327 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FX;
|
328 | bd23cd45 | Blue Swirl | if (fpscr_ze) {
|
329 | bd23cd45 | Blue Swirl | goto raise_ze;
|
330 | bd23cd45 | Blue Swirl | } |
331 | bd23cd45 | Blue Swirl | break;
|
332 | bd23cd45 | Blue Swirl | case FPSCR_XX:
|
333 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FX;
|
334 | bd23cd45 | Blue Swirl | if (fpscr_xe) {
|
335 | bd23cd45 | Blue Swirl | goto raise_xe;
|
336 | bd23cd45 | Blue Swirl | } |
337 | bd23cd45 | Blue Swirl | break;
|
338 | bd23cd45 | Blue Swirl | case FPSCR_VXSNAN:
|
339 | bd23cd45 | Blue Swirl | case FPSCR_VXISI:
|
340 | bd23cd45 | Blue Swirl | case FPSCR_VXIDI:
|
341 | bd23cd45 | Blue Swirl | case FPSCR_VXZDZ:
|
342 | bd23cd45 | Blue Swirl | case FPSCR_VXIMZ:
|
343 | bd23cd45 | Blue Swirl | case FPSCR_VXVC:
|
344 | bd23cd45 | Blue Swirl | case FPSCR_VXSOFT:
|
345 | bd23cd45 | Blue Swirl | case FPSCR_VXSQRT:
|
346 | bd23cd45 | Blue Swirl | case FPSCR_VXCVI:
|
347 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_VX;
|
348 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FX;
|
349 | bd23cd45 | Blue Swirl | if (fpscr_ve != 0) { |
350 | bd23cd45 | Blue Swirl | goto raise_ve;
|
351 | bd23cd45 | Blue Swirl | } |
352 | bd23cd45 | Blue Swirl | break;
|
353 | bd23cd45 | Blue Swirl | case FPSCR_VE:
|
354 | bd23cd45 | Blue Swirl | if (fpscr_vx != 0) { |
355 | bd23cd45 | Blue Swirl | raise_ve:
|
356 | bd23cd45 | Blue Swirl | env->error_code = POWERPC_EXCP_FP; |
357 | bd23cd45 | Blue Swirl | if (fpscr_vxsnan) {
|
358 | bd23cd45 | Blue Swirl | env->error_code |= POWERPC_EXCP_FP_VXSNAN; |
359 | bd23cd45 | Blue Swirl | } |
360 | bd23cd45 | Blue Swirl | if (fpscr_vxisi) {
|
361 | bd23cd45 | Blue Swirl | env->error_code |= POWERPC_EXCP_FP_VXISI; |
362 | bd23cd45 | Blue Swirl | } |
363 | bd23cd45 | Blue Swirl | if (fpscr_vxidi) {
|
364 | bd23cd45 | Blue Swirl | env->error_code |= POWERPC_EXCP_FP_VXIDI; |
365 | bd23cd45 | Blue Swirl | } |
366 | bd23cd45 | Blue Swirl | if (fpscr_vxzdz) {
|
367 | bd23cd45 | Blue Swirl | env->error_code |= POWERPC_EXCP_FP_VXZDZ; |
368 | bd23cd45 | Blue Swirl | } |
369 | bd23cd45 | Blue Swirl | if (fpscr_vximz) {
|
370 | bd23cd45 | Blue Swirl | env->error_code |= POWERPC_EXCP_FP_VXIMZ; |
371 | bd23cd45 | Blue Swirl | } |
372 | bd23cd45 | Blue Swirl | if (fpscr_vxvc) {
|
373 | bd23cd45 | Blue Swirl | env->error_code |= POWERPC_EXCP_FP_VXVC; |
374 | bd23cd45 | Blue Swirl | } |
375 | bd23cd45 | Blue Swirl | if (fpscr_vxsoft) {
|
376 | bd23cd45 | Blue Swirl | env->error_code |= POWERPC_EXCP_FP_VXSOFT; |
377 | bd23cd45 | Blue Swirl | } |
378 | bd23cd45 | Blue Swirl | if (fpscr_vxsqrt) {
|
379 | bd23cd45 | Blue Swirl | env->error_code |= POWERPC_EXCP_FP_VXSQRT; |
380 | bd23cd45 | Blue Swirl | } |
381 | bd23cd45 | Blue Swirl | if (fpscr_vxcvi) {
|
382 | bd23cd45 | Blue Swirl | env->error_code |= POWERPC_EXCP_FP_VXCVI; |
383 | bd23cd45 | Blue Swirl | } |
384 | bd23cd45 | Blue Swirl | goto raise_excp;
|
385 | bd23cd45 | Blue Swirl | } |
386 | bd23cd45 | Blue Swirl | break;
|
387 | bd23cd45 | Blue Swirl | case FPSCR_OE:
|
388 | bd23cd45 | Blue Swirl | if (fpscr_ox != 0) { |
389 | bd23cd45 | Blue Swirl | raise_oe:
|
390 | bd23cd45 | Blue Swirl | env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX; |
391 | bd23cd45 | Blue Swirl | goto raise_excp;
|
392 | bd23cd45 | Blue Swirl | } |
393 | bd23cd45 | Blue Swirl | break;
|
394 | bd23cd45 | Blue Swirl | case FPSCR_UE:
|
395 | bd23cd45 | Blue Swirl | if (fpscr_ux != 0) { |
396 | bd23cd45 | Blue Swirl | raise_ue:
|
397 | bd23cd45 | Blue Swirl | env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX; |
398 | bd23cd45 | Blue Swirl | goto raise_excp;
|
399 | bd23cd45 | Blue Swirl | } |
400 | bd23cd45 | Blue Swirl | break;
|
401 | bd23cd45 | Blue Swirl | case FPSCR_ZE:
|
402 | bd23cd45 | Blue Swirl | if (fpscr_zx != 0) { |
403 | bd23cd45 | Blue Swirl | raise_ze:
|
404 | bd23cd45 | Blue Swirl | env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX; |
405 | bd23cd45 | Blue Swirl | goto raise_excp;
|
406 | bd23cd45 | Blue Swirl | } |
407 | bd23cd45 | Blue Swirl | break;
|
408 | bd23cd45 | Blue Swirl | case FPSCR_XE:
|
409 | bd23cd45 | Blue Swirl | if (fpscr_xx != 0) { |
410 | bd23cd45 | Blue Swirl | raise_xe:
|
411 | bd23cd45 | Blue Swirl | env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX; |
412 | bd23cd45 | Blue Swirl | goto raise_excp;
|
413 | bd23cd45 | Blue Swirl | } |
414 | bd23cd45 | Blue Swirl | break;
|
415 | bd23cd45 | Blue Swirl | case FPSCR_RN1:
|
416 | bd23cd45 | Blue Swirl | case FPSCR_RN:
|
417 | 8e703949 | Blue Swirl | fpscr_set_rounding_mode(env); |
418 | bd23cd45 | Blue Swirl | break;
|
419 | bd23cd45 | Blue Swirl | default:
|
420 | bd23cd45 | Blue Swirl | break;
|
421 | bd23cd45 | Blue Swirl | raise_excp:
|
422 | bd23cd45 | Blue Swirl | /* Update the floating-point enabled exception summary */
|
423 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FEX;
|
424 | bd23cd45 | Blue Swirl | /* We have to update Rc1 before raising the exception */
|
425 | bd23cd45 | Blue Swirl | env->exception_index = POWERPC_EXCP_PROGRAM; |
426 | bd23cd45 | Blue Swirl | break;
|
427 | bd23cd45 | Blue Swirl | } |
428 | bd23cd45 | Blue Swirl | } |
429 | bd23cd45 | Blue Swirl | } |
430 | bd23cd45 | Blue Swirl | |
431 | 8e703949 | Blue Swirl | void helper_store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask)
|
432 | bd23cd45 | Blue Swirl | { |
433 | 7d08d856 | Aurelien Jarno | target_ulong prev, new; |
434 | bd23cd45 | Blue Swirl | int i;
|
435 | bd23cd45 | Blue Swirl | |
436 | bd23cd45 | Blue Swirl | prev = env->fpscr; |
437 | 7d08d856 | Aurelien Jarno | new = (target_ulong)arg; |
438 | 7d08d856 | Aurelien Jarno | new &= ~0x60000000LL;
|
439 | 7d08d856 | Aurelien Jarno | new |= prev & 0x60000000LL;
|
440 | 7d08d856 | Aurelien Jarno | for (i = 0; i < sizeof(target_ulong) * 2; i++) { |
441 | bd23cd45 | Blue Swirl | if (mask & (1 << i)) { |
442 | 7d08d856 | Aurelien Jarno | env->fpscr &= ~(0xFLL << (4 * i)); |
443 | 7d08d856 | Aurelien Jarno | env->fpscr |= new & (0xFLL << (4 * i)); |
444 | bd23cd45 | Blue Swirl | } |
445 | bd23cd45 | Blue Swirl | } |
446 | bd23cd45 | Blue Swirl | /* Update VX and FEX */
|
447 | bd23cd45 | Blue Swirl | if (fpscr_ix != 0) { |
448 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_VX;
|
449 | bd23cd45 | Blue Swirl | } else {
|
450 | bd23cd45 | Blue Swirl | env->fpscr &= ~(1 << FPSCR_VX);
|
451 | bd23cd45 | Blue Swirl | } |
452 | bd23cd45 | Blue Swirl | if ((fpscr_ex & fpscr_eex) != 0) { |
453 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FEX;
|
454 | bd23cd45 | Blue Swirl | env->exception_index = POWERPC_EXCP_PROGRAM; |
455 | bd23cd45 | Blue Swirl | /* XXX: we should compute it properly */
|
456 | bd23cd45 | Blue Swirl | env->error_code = POWERPC_EXCP_FP; |
457 | bd23cd45 | Blue Swirl | } else {
|
458 | bd23cd45 | Blue Swirl | env->fpscr &= ~(1 << FPSCR_FEX);
|
459 | bd23cd45 | Blue Swirl | } |
460 | 8e703949 | Blue Swirl | fpscr_set_rounding_mode(env); |
461 | bd23cd45 | Blue Swirl | } |
462 | bd23cd45 | Blue Swirl | |
463 | d6478bc7 | Fabien Chouteau | void store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask)
|
464 | d6478bc7 | Fabien Chouteau | { |
465 | d6478bc7 | Fabien Chouteau | helper_store_fpscr(env, arg, mask); |
466 | d6478bc7 | Fabien Chouteau | } |
467 | d6478bc7 | Fabien Chouteau | |
468 | 8e703949 | Blue Swirl | void helper_float_check_status(CPUPPCState *env)
|
469 | bd23cd45 | Blue Swirl | { |
470 | db72c9f2 | Tristan Gingold | int status = get_float_exception_flags(&env->fp_status);
|
471 | db72c9f2 | Tristan Gingold | |
472 | db72c9f2 | Tristan Gingold | if (status & float_flag_divbyzero) {
|
473 | db72c9f2 | Tristan Gingold | float_zero_divide_excp(env); |
474 | db72c9f2 | Tristan Gingold | } else if (status & float_flag_overflow) { |
475 | db72c9f2 | Tristan Gingold | float_overflow_excp(env); |
476 | db72c9f2 | Tristan Gingold | } else if (status & float_flag_underflow) { |
477 | db72c9f2 | Tristan Gingold | float_underflow_excp(env); |
478 | db72c9f2 | Tristan Gingold | } else if (status & float_flag_inexact) { |
479 | db72c9f2 | Tristan Gingold | float_inexact_excp(env); |
480 | db72c9f2 | Tristan Gingold | } |
481 | db72c9f2 | Tristan Gingold | |
482 | bd23cd45 | Blue Swirl | if (env->exception_index == POWERPC_EXCP_PROGRAM &&
|
483 | bd23cd45 | Blue Swirl | (env->error_code & POWERPC_EXCP_FP)) { |
484 | bd23cd45 | Blue Swirl | /* Differred floating-point exception after target FPR update */
|
485 | bd23cd45 | Blue Swirl | if (msr_fe0 != 0 || msr_fe1 != 0) { |
486 | bd23cd45 | Blue Swirl | helper_raise_exception_err(env, env->exception_index, |
487 | bd23cd45 | Blue Swirl | env->error_code); |
488 | bd23cd45 | Blue Swirl | } |
489 | bd23cd45 | Blue Swirl | } |
490 | bd23cd45 | Blue Swirl | } |
491 | bd23cd45 | Blue Swirl | |
492 | 8e703949 | Blue Swirl | void helper_reset_fpstatus(CPUPPCState *env)
|
493 | bd23cd45 | Blue Swirl | { |
494 | bd23cd45 | Blue Swirl | set_float_exception_flags(0, &env->fp_status);
|
495 | bd23cd45 | Blue Swirl | } |
496 | bd23cd45 | Blue Swirl | |
497 | bd23cd45 | Blue Swirl | /* fadd - fadd. */
|
498 | 8e703949 | Blue Swirl | uint64_t helper_fadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2) |
499 | bd23cd45 | Blue Swirl | { |
500 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1, farg2; |
501 | bd23cd45 | Blue Swirl | |
502 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
503 | bd23cd45 | Blue Swirl | farg2.ll = arg2; |
504 | bd23cd45 | Blue Swirl | |
505 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
|
506 | bd23cd45 | Blue Swirl | float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) { |
507 | bd23cd45 | Blue Swirl | /* Magnitude subtraction of infinities */
|
508 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI); |
509 | bd23cd45 | Blue Swirl | } else {
|
510 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
511 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg2.d))) { |
512 | bd23cd45 | Blue Swirl | /* sNaN addition */
|
513 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
514 | bd23cd45 | Blue Swirl | } |
515 | bd23cd45 | Blue Swirl | farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status); |
516 | bd23cd45 | Blue Swirl | } |
517 | bd23cd45 | Blue Swirl | |
518 | bd23cd45 | Blue Swirl | return farg1.ll;
|
519 | bd23cd45 | Blue Swirl | } |
520 | bd23cd45 | Blue Swirl | |
521 | bd23cd45 | Blue Swirl | /* fsub - fsub. */
|
522 | 8e703949 | Blue Swirl | uint64_t helper_fsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2) |
523 | bd23cd45 | Blue Swirl | { |
524 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1, farg2; |
525 | bd23cd45 | Blue Swirl | |
526 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
527 | bd23cd45 | Blue Swirl | farg2.ll = arg2; |
528 | bd23cd45 | Blue Swirl | |
529 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
|
530 | bd23cd45 | Blue Swirl | float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) { |
531 | bd23cd45 | Blue Swirl | /* Magnitude subtraction of infinities */
|
532 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI); |
533 | bd23cd45 | Blue Swirl | } else {
|
534 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
535 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg2.d))) { |
536 | bd23cd45 | Blue Swirl | /* sNaN subtraction */
|
537 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
538 | bd23cd45 | Blue Swirl | } |
539 | bd23cd45 | Blue Swirl | farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status); |
540 | bd23cd45 | Blue Swirl | } |
541 | bd23cd45 | Blue Swirl | |
542 | bd23cd45 | Blue Swirl | return farg1.ll;
|
543 | bd23cd45 | Blue Swirl | } |
544 | bd23cd45 | Blue Swirl | |
545 | bd23cd45 | Blue Swirl | /* fmul - fmul. */
|
546 | 8e703949 | Blue Swirl | uint64_t helper_fmul(CPUPPCState *env, uint64_t arg1, uint64_t arg2) |
547 | bd23cd45 | Blue Swirl | { |
548 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1, farg2; |
549 | bd23cd45 | Blue Swirl | |
550 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
551 | bd23cd45 | Blue Swirl | farg2.ll = arg2; |
552 | bd23cd45 | Blue Swirl | |
553 | bd23cd45 | Blue Swirl | if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
|
554 | bd23cd45 | Blue Swirl | (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) { |
555 | bd23cd45 | Blue Swirl | /* Multiplication of zero by infinity */
|
556 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ); |
557 | bd23cd45 | Blue Swirl | } else {
|
558 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
559 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg2.d))) { |
560 | bd23cd45 | Blue Swirl | /* sNaN multiplication */
|
561 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
562 | bd23cd45 | Blue Swirl | } |
563 | bd23cd45 | Blue Swirl | farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status); |
564 | bd23cd45 | Blue Swirl | } |
565 | bd23cd45 | Blue Swirl | |
566 | bd23cd45 | Blue Swirl | return farg1.ll;
|
567 | bd23cd45 | Blue Swirl | } |
568 | bd23cd45 | Blue Swirl | |
569 | bd23cd45 | Blue Swirl | /* fdiv - fdiv. */
|
570 | 8e703949 | Blue Swirl | uint64_t helper_fdiv(CPUPPCState *env, uint64_t arg1, uint64_t arg2) |
571 | bd23cd45 | Blue Swirl | { |
572 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1, farg2; |
573 | bd23cd45 | Blue Swirl | |
574 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
575 | bd23cd45 | Blue Swirl | farg2.ll = arg2; |
576 | bd23cd45 | Blue Swirl | |
577 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_infinity(farg1.d) &&
|
578 | bd23cd45 | Blue Swirl | float64_is_infinity(farg2.d))) { |
579 | bd23cd45 | Blue Swirl | /* Division of infinity by infinity */
|
580 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI); |
581 | bd23cd45 | Blue Swirl | } else if (unlikely(float64_is_zero(farg1.d) && float64_is_zero(farg2.d))) { |
582 | bd23cd45 | Blue Swirl | /* Division of zero by zero */
|
583 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ); |
584 | bd23cd45 | Blue Swirl | } else {
|
585 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
586 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg2.d))) { |
587 | bd23cd45 | Blue Swirl | /* sNaN division */
|
588 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
589 | bd23cd45 | Blue Swirl | } |
590 | bd23cd45 | Blue Swirl | farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status); |
591 | bd23cd45 | Blue Swirl | } |
592 | bd23cd45 | Blue Swirl | |
593 | bd23cd45 | Blue Swirl | return farg1.ll;
|
594 | bd23cd45 | Blue Swirl | } |
595 | bd23cd45 | Blue Swirl | |
596 | bd23cd45 | Blue Swirl | /* fctiw - fctiw. */
|
597 | 8e703949 | Blue Swirl | uint64_t helper_fctiw(CPUPPCState *env, uint64_t arg) |
598 | bd23cd45 | Blue Swirl | { |
599 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
600 | bd23cd45 | Blue Swirl | |
601 | bd23cd45 | Blue Swirl | farg.ll = arg; |
602 | bd23cd45 | Blue Swirl | |
603 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg.d))) {
|
604 | bd23cd45 | Blue Swirl | /* sNaN conversion */
|
605 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN | |
606 | bd23cd45 | Blue Swirl | POWERPC_EXCP_FP_VXCVI); |
607 | bd23cd45 | Blue Swirl | } else if (unlikely(float64_is_quiet_nan(farg.d) || |
608 | bd23cd45 | Blue Swirl | float64_is_infinity(farg.d))) { |
609 | bd23cd45 | Blue Swirl | /* qNan / infinity conversion */
|
610 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI); |
611 | bd23cd45 | Blue Swirl | } else {
|
612 | bd23cd45 | Blue Swirl | farg.ll = float64_to_int32(farg.d, &env->fp_status); |
613 | bd23cd45 | Blue Swirl | /* XXX: higher bits are not supposed to be significant.
|
614 | bd23cd45 | Blue Swirl | * to make tests easier, return the same as a real PowerPC 750
|
615 | bd23cd45 | Blue Swirl | */
|
616 | bd23cd45 | Blue Swirl | farg.ll |= 0xFFF80000ULL << 32; |
617 | bd23cd45 | Blue Swirl | } |
618 | bd23cd45 | Blue Swirl | return farg.ll;
|
619 | bd23cd45 | Blue Swirl | } |
620 | bd23cd45 | Blue Swirl | |
621 | bd23cd45 | Blue Swirl | /* fctiwz - fctiwz. */
|
622 | 8e703949 | Blue Swirl | uint64_t helper_fctiwz(CPUPPCState *env, uint64_t arg) |
623 | bd23cd45 | Blue Swirl | { |
624 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
625 | bd23cd45 | Blue Swirl | |
626 | bd23cd45 | Blue Swirl | farg.ll = arg; |
627 | bd23cd45 | Blue Swirl | |
628 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg.d))) {
|
629 | bd23cd45 | Blue Swirl | /* sNaN conversion */
|
630 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN | |
631 | bd23cd45 | Blue Swirl | POWERPC_EXCP_FP_VXCVI); |
632 | bd23cd45 | Blue Swirl | } else if (unlikely(float64_is_quiet_nan(farg.d) || |
633 | bd23cd45 | Blue Swirl | float64_is_infinity(farg.d))) { |
634 | bd23cd45 | Blue Swirl | /* qNan / infinity conversion */
|
635 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI); |
636 | bd23cd45 | Blue Swirl | } else {
|
637 | bd23cd45 | Blue Swirl | farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status); |
638 | bd23cd45 | Blue Swirl | /* XXX: higher bits are not supposed to be significant.
|
639 | bd23cd45 | Blue Swirl | * to make tests easier, return the same as a real PowerPC 750
|
640 | bd23cd45 | Blue Swirl | */
|
641 | bd23cd45 | Blue Swirl | farg.ll |= 0xFFF80000ULL << 32; |
642 | bd23cd45 | Blue Swirl | } |
643 | bd23cd45 | Blue Swirl | return farg.ll;
|
644 | bd23cd45 | Blue Swirl | } |
645 | bd23cd45 | Blue Swirl | |
646 | bd23cd45 | Blue Swirl | #if defined(TARGET_PPC64)
|
647 | bd23cd45 | Blue Swirl | /* fcfid - fcfid. */
|
648 | 8e703949 | Blue Swirl | uint64_t helper_fcfid(CPUPPCState *env, uint64_t arg) |
649 | bd23cd45 | Blue Swirl | { |
650 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
651 | bd23cd45 | Blue Swirl | |
652 | bd23cd45 | Blue Swirl | farg.d = int64_to_float64(arg, &env->fp_status); |
653 | bd23cd45 | Blue Swirl | return farg.ll;
|
654 | bd23cd45 | Blue Swirl | } |
655 | bd23cd45 | Blue Swirl | |
656 | bd23cd45 | Blue Swirl | /* fctid - fctid. */
|
657 | 8e703949 | Blue Swirl | uint64_t helper_fctid(CPUPPCState *env, uint64_t arg) |
658 | bd23cd45 | Blue Swirl | { |
659 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
660 | bd23cd45 | Blue Swirl | |
661 | bd23cd45 | Blue Swirl | farg.ll = arg; |
662 | bd23cd45 | Blue Swirl | |
663 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg.d))) {
|
664 | bd23cd45 | Blue Swirl | /* sNaN conversion */
|
665 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN | |
666 | bd23cd45 | Blue Swirl | POWERPC_EXCP_FP_VXCVI); |
667 | bd23cd45 | Blue Swirl | } else if (unlikely(float64_is_quiet_nan(farg.d) || |
668 | bd23cd45 | Blue Swirl | float64_is_infinity(farg.d))) { |
669 | bd23cd45 | Blue Swirl | /* qNan / infinity conversion */
|
670 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI); |
671 | bd23cd45 | Blue Swirl | } else {
|
672 | bd23cd45 | Blue Swirl | farg.ll = float64_to_int64(farg.d, &env->fp_status); |
673 | bd23cd45 | Blue Swirl | } |
674 | bd23cd45 | Blue Swirl | return farg.ll;
|
675 | bd23cd45 | Blue Swirl | } |
676 | bd23cd45 | Blue Swirl | |
677 | bd23cd45 | Blue Swirl | /* fctidz - fctidz. */
|
678 | 8e703949 | Blue Swirl | uint64_t helper_fctidz(CPUPPCState *env, uint64_t arg) |
679 | bd23cd45 | Blue Swirl | { |
680 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
681 | bd23cd45 | Blue Swirl | |
682 | bd23cd45 | Blue Swirl | farg.ll = arg; |
683 | bd23cd45 | Blue Swirl | |
684 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg.d))) {
|
685 | bd23cd45 | Blue Swirl | /* sNaN conversion */
|
686 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN | |
687 | bd23cd45 | Blue Swirl | POWERPC_EXCP_FP_VXCVI); |
688 | bd23cd45 | Blue Swirl | } else if (unlikely(float64_is_quiet_nan(farg.d) || |
689 | bd23cd45 | Blue Swirl | float64_is_infinity(farg.d))) { |
690 | bd23cd45 | Blue Swirl | /* qNan / infinity conversion */
|
691 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI); |
692 | bd23cd45 | Blue Swirl | } else {
|
693 | bd23cd45 | Blue Swirl | farg.ll = float64_to_int64_round_to_zero(farg.d, &env->fp_status); |
694 | bd23cd45 | Blue Swirl | } |
695 | bd23cd45 | Blue Swirl | return farg.ll;
|
696 | bd23cd45 | Blue Swirl | } |
697 | bd23cd45 | Blue Swirl | |
698 | bd23cd45 | Blue Swirl | #endif
|
699 | bd23cd45 | Blue Swirl | |
700 | 8e703949 | Blue Swirl | static inline uint64_t do_fri(CPUPPCState *env, uint64_t arg, |
701 | 8e703949 | Blue Swirl | int rounding_mode)
|
702 | bd23cd45 | Blue Swirl | { |
703 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
704 | bd23cd45 | Blue Swirl | |
705 | bd23cd45 | Blue Swirl | farg.ll = arg; |
706 | bd23cd45 | Blue Swirl | |
707 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg.d))) {
|
708 | bd23cd45 | Blue Swirl | /* sNaN round */
|
709 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN | |
710 | bd23cd45 | Blue Swirl | POWERPC_EXCP_FP_VXCVI); |
711 | bd23cd45 | Blue Swirl | } else if (unlikely(float64_is_quiet_nan(farg.d) || |
712 | bd23cd45 | Blue Swirl | float64_is_infinity(farg.d))) { |
713 | bd23cd45 | Blue Swirl | /* qNan / infinity round */
|
714 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI); |
715 | bd23cd45 | Blue Swirl | } else {
|
716 | bd23cd45 | Blue Swirl | set_float_rounding_mode(rounding_mode, &env->fp_status); |
717 | bd23cd45 | Blue Swirl | farg.ll = float64_round_to_int(farg.d, &env->fp_status); |
718 | bd23cd45 | Blue Swirl | /* Restore rounding mode from FPSCR */
|
719 | 8e703949 | Blue Swirl | fpscr_set_rounding_mode(env); |
720 | bd23cd45 | Blue Swirl | } |
721 | bd23cd45 | Blue Swirl | return farg.ll;
|
722 | bd23cd45 | Blue Swirl | } |
723 | bd23cd45 | Blue Swirl | |
724 | 8e703949 | Blue Swirl | uint64_t helper_frin(CPUPPCState *env, uint64_t arg) |
725 | bd23cd45 | Blue Swirl | { |
726 | 8e703949 | Blue Swirl | return do_fri(env, arg, float_round_nearest_even);
|
727 | bd23cd45 | Blue Swirl | } |
728 | bd23cd45 | Blue Swirl | |
729 | 8e703949 | Blue Swirl | uint64_t helper_friz(CPUPPCState *env, uint64_t arg) |
730 | bd23cd45 | Blue Swirl | { |
731 | 8e703949 | Blue Swirl | return do_fri(env, arg, float_round_to_zero);
|
732 | bd23cd45 | Blue Swirl | } |
733 | bd23cd45 | Blue Swirl | |
734 | 8e703949 | Blue Swirl | uint64_t helper_frip(CPUPPCState *env, uint64_t arg) |
735 | bd23cd45 | Blue Swirl | { |
736 | 8e703949 | Blue Swirl | return do_fri(env, arg, float_round_up);
|
737 | bd23cd45 | Blue Swirl | } |
738 | bd23cd45 | Blue Swirl | |
739 | 8e703949 | Blue Swirl | uint64_t helper_frim(CPUPPCState *env, uint64_t arg) |
740 | bd23cd45 | Blue Swirl | { |
741 | 8e703949 | Blue Swirl | return do_fri(env, arg, float_round_down);
|
742 | bd23cd45 | Blue Swirl | } |
743 | bd23cd45 | Blue Swirl | |
744 | bd23cd45 | Blue Swirl | /* fmadd - fmadd. */
|
745 | 8e703949 | Blue Swirl | uint64_t helper_fmadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2, |
746 | 8e703949 | Blue Swirl | uint64_t arg3) |
747 | bd23cd45 | Blue Swirl | { |
748 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1, farg2, farg3; |
749 | bd23cd45 | Blue Swirl | |
750 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
751 | bd23cd45 | Blue Swirl | farg2.ll = arg2; |
752 | bd23cd45 | Blue Swirl | farg3.ll = arg3; |
753 | bd23cd45 | Blue Swirl | |
754 | bd23cd45 | Blue Swirl | if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
|
755 | bd23cd45 | Blue Swirl | (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) { |
756 | bd23cd45 | Blue Swirl | /* Multiplication of zero by infinity */
|
757 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ); |
758 | bd23cd45 | Blue Swirl | } else {
|
759 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
760 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg2.d) || |
761 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg3.d))) { |
762 | bd23cd45 | Blue Swirl | /* sNaN operation */
|
763 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
764 | bd23cd45 | Blue Swirl | } |
765 | bd23cd45 | Blue Swirl | /* This is the way the PowerPC specification defines it */
|
766 | bd23cd45 | Blue Swirl | float128 ft0_128, ft1_128; |
767 | bd23cd45 | Blue Swirl | |
768 | bd23cd45 | Blue Swirl | ft0_128 = float64_to_float128(farg1.d, &env->fp_status); |
769 | bd23cd45 | Blue Swirl | ft1_128 = float64_to_float128(farg2.d, &env->fp_status); |
770 | bd23cd45 | Blue Swirl | ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status); |
771 | bd23cd45 | Blue Swirl | if (unlikely(float128_is_infinity(ft0_128) &&
|
772 | bd23cd45 | Blue Swirl | float64_is_infinity(farg3.d) && |
773 | bd23cd45 | Blue Swirl | float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) { |
774 | bd23cd45 | Blue Swirl | /* Magnitude subtraction of infinities */
|
775 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI); |
776 | bd23cd45 | Blue Swirl | } else {
|
777 | bd23cd45 | Blue Swirl | ft1_128 = float64_to_float128(farg3.d, &env->fp_status); |
778 | bd23cd45 | Blue Swirl | ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status); |
779 | bd23cd45 | Blue Swirl | farg1.d = float128_to_float64(ft0_128, &env->fp_status); |
780 | bd23cd45 | Blue Swirl | } |
781 | bd23cd45 | Blue Swirl | } |
782 | bd23cd45 | Blue Swirl | |
783 | bd23cd45 | Blue Swirl | return farg1.ll;
|
784 | bd23cd45 | Blue Swirl | } |
785 | bd23cd45 | Blue Swirl | |
786 | bd23cd45 | Blue Swirl | /* fmsub - fmsub. */
|
787 | 8e703949 | Blue Swirl | uint64_t helper_fmsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2, |
788 | 8e703949 | Blue Swirl | uint64_t arg3) |
789 | bd23cd45 | Blue Swirl | { |
790 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1, farg2, farg3; |
791 | bd23cd45 | Blue Swirl | |
792 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
793 | bd23cd45 | Blue Swirl | farg2.ll = arg2; |
794 | bd23cd45 | Blue Swirl | farg3.ll = arg3; |
795 | bd23cd45 | Blue Swirl | |
796 | bd23cd45 | Blue Swirl | if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
|
797 | bd23cd45 | Blue Swirl | (float64_is_zero(farg1.d) && |
798 | bd23cd45 | Blue Swirl | float64_is_infinity(farg2.d)))) { |
799 | bd23cd45 | Blue Swirl | /* Multiplication of zero by infinity */
|
800 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ); |
801 | bd23cd45 | Blue Swirl | } else {
|
802 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
803 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg2.d) || |
804 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg3.d))) { |
805 | bd23cd45 | Blue Swirl | /* sNaN operation */
|
806 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
807 | bd23cd45 | Blue Swirl | } |
808 | bd23cd45 | Blue Swirl | /* This is the way the PowerPC specification defines it */
|
809 | bd23cd45 | Blue Swirl | float128 ft0_128, ft1_128; |
810 | bd23cd45 | Blue Swirl | |
811 | bd23cd45 | Blue Swirl | ft0_128 = float64_to_float128(farg1.d, &env->fp_status); |
812 | bd23cd45 | Blue Swirl | ft1_128 = float64_to_float128(farg2.d, &env->fp_status); |
813 | bd23cd45 | Blue Swirl | ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status); |
814 | bd23cd45 | Blue Swirl | if (unlikely(float128_is_infinity(ft0_128) &&
|
815 | bd23cd45 | Blue Swirl | float64_is_infinity(farg3.d) && |
816 | bd23cd45 | Blue Swirl | float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) { |
817 | bd23cd45 | Blue Swirl | /* Magnitude subtraction of infinities */
|
818 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI); |
819 | bd23cd45 | Blue Swirl | } else {
|
820 | bd23cd45 | Blue Swirl | ft1_128 = float64_to_float128(farg3.d, &env->fp_status); |
821 | bd23cd45 | Blue Swirl | ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status); |
822 | bd23cd45 | Blue Swirl | farg1.d = float128_to_float64(ft0_128, &env->fp_status); |
823 | bd23cd45 | Blue Swirl | } |
824 | bd23cd45 | Blue Swirl | } |
825 | bd23cd45 | Blue Swirl | return farg1.ll;
|
826 | bd23cd45 | Blue Swirl | } |
827 | bd23cd45 | Blue Swirl | |
828 | bd23cd45 | Blue Swirl | /* fnmadd - fnmadd. */
|
829 | 8e703949 | Blue Swirl | uint64_t helper_fnmadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2, |
830 | 8e703949 | Blue Swirl | uint64_t arg3) |
831 | bd23cd45 | Blue Swirl | { |
832 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1, farg2, farg3; |
833 | bd23cd45 | Blue Swirl | |
834 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
835 | bd23cd45 | Blue Swirl | farg2.ll = arg2; |
836 | bd23cd45 | Blue Swirl | farg3.ll = arg3; |
837 | bd23cd45 | Blue Swirl | |
838 | bd23cd45 | Blue Swirl | if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
|
839 | bd23cd45 | Blue Swirl | (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) { |
840 | bd23cd45 | Blue Swirl | /* Multiplication of zero by infinity */
|
841 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ); |
842 | bd23cd45 | Blue Swirl | } else {
|
843 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
844 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg2.d) || |
845 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg3.d))) { |
846 | bd23cd45 | Blue Swirl | /* sNaN operation */
|
847 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
848 | bd23cd45 | Blue Swirl | } |
849 | bd23cd45 | Blue Swirl | /* This is the way the PowerPC specification defines it */
|
850 | bd23cd45 | Blue Swirl | float128 ft0_128, ft1_128; |
851 | bd23cd45 | Blue Swirl | |
852 | bd23cd45 | Blue Swirl | ft0_128 = float64_to_float128(farg1.d, &env->fp_status); |
853 | bd23cd45 | Blue Swirl | ft1_128 = float64_to_float128(farg2.d, &env->fp_status); |
854 | bd23cd45 | Blue Swirl | ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status); |
855 | bd23cd45 | Blue Swirl | if (unlikely(float128_is_infinity(ft0_128) &&
|
856 | bd23cd45 | Blue Swirl | float64_is_infinity(farg3.d) && |
857 | bd23cd45 | Blue Swirl | float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) { |
858 | bd23cd45 | Blue Swirl | /* Magnitude subtraction of infinities */
|
859 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI); |
860 | bd23cd45 | Blue Swirl | } else {
|
861 | bd23cd45 | Blue Swirl | ft1_128 = float64_to_float128(farg3.d, &env->fp_status); |
862 | bd23cd45 | Blue Swirl | ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status); |
863 | bd23cd45 | Blue Swirl | farg1.d = float128_to_float64(ft0_128, &env->fp_status); |
864 | bd23cd45 | Blue Swirl | } |
865 | bd23cd45 | Blue Swirl | if (likely(!float64_is_any_nan(farg1.d))) {
|
866 | bd23cd45 | Blue Swirl | farg1.d = float64_chs(farg1.d); |
867 | bd23cd45 | Blue Swirl | } |
868 | bd23cd45 | Blue Swirl | } |
869 | bd23cd45 | Blue Swirl | return farg1.ll;
|
870 | bd23cd45 | Blue Swirl | } |
871 | bd23cd45 | Blue Swirl | |
872 | bd23cd45 | Blue Swirl | /* fnmsub - fnmsub. */
|
873 | 8e703949 | Blue Swirl | uint64_t helper_fnmsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2, |
874 | 8e703949 | Blue Swirl | uint64_t arg3) |
875 | bd23cd45 | Blue Swirl | { |
876 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1, farg2, farg3; |
877 | bd23cd45 | Blue Swirl | |
878 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
879 | bd23cd45 | Blue Swirl | farg2.ll = arg2; |
880 | bd23cd45 | Blue Swirl | farg3.ll = arg3; |
881 | bd23cd45 | Blue Swirl | |
882 | bd23cd45 | Blue Swirl | if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
|
883 | bd23cd45 | Blue Swirl | (float64_is_zero(farg1.d) && |
884 | bd23cd45 | Blue Swirl | float64_is_infinity(farg2.d)))) { |
885 | bd23cd45 | Blue Swirl | /* Multiplication of zero by infinity */
|
886 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ); |
887 | bd23cd45 | Blue Swirl | } else {
|
888 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
889 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg2.d) || |
890 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg3.d))) { |
891 | bd23cd45 | Blue Swirl | /* sNaN operation */
|
892 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
893 | bd23cd45 | Blue Swirl | } |
894 | bd23cd45 | Blue Swirl | /* This is the way the PowerPC specification defines it */
|
895 | bd23cd45 | Blue Swirl | float128 ft0_128, ft1_128; |
896 | bd23cd45 | Blue Swirl | |
897 | bd23cd45 | Blue Swirl | ft0_128 = float64_to_float128(farg1.d, &env->fp_status); |
898 | bd23cd45 | Blue Swirl | ft1_128 = float64_to_float128(farg2.d, &env->fp_status); |
899 | bd23cd45 | Blue Swirl | ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status); |
900 | bd23cd45 | Blue Swirl | if (unlikely(float128_is_infinity(ft0_128) &&
|
901 | bd23cd45 | Blue Swirl | float64_is_infinity(farg3.d) && |
902 | bd23cd45 | Blue Swirl | float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) { |
903 | bd23cd45 | Blue Swirl | /* Magnitude subtraction of infinities */
|
904 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI); |
905 | bd23cd45 | Blue Swirl | } else {
|
906 | bd23cd45 | Blue Swirl | ft1_128 = float64_to_float128(farg3.d, &env->fp_status); |
907 | bd23cd45 | Blue Swirl | ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status); |
908 | bd23cd45 | Blue Swirl | farg1.d = float128_to_float64(ft0_128, &env->fp_status); |
909 | bd23cd45 | Blue Swirl | } |
910 | bd23cd45 | Blue Swirl | if (likely(!float64_is_any_nan(farg1.d))) {
|
911 | bd23cd45 | Blue Swirl | farg1.d = float64_chs(farg1.d); |
912 | bd23cd45 | Blue Swirl | } |
913 | bd23cd45 | Blue Swirl | } |
914 | bd23cd45 | Blue Swirl | return farg1.ll;
|
915 | bd23cd45 | Blue Swirl | } |
916 | bd23cd45 | Blue Swirl | |
917 | bd23cd45 | Blue Swirl | /* frsp - frsp. */
|
918 | 8e703949 | Blue Swirl | uint64_t helper_frsp(CPUPPCState *env, uint64_t arg) |
919 | bd23cd45 | Blue Swirl | { |
920 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
921 | bd23cd45 | Blue Swirl | float32 f32; |
922 | bd23cd45 | Blue Swirl | |
923 | bd23cd45 | Blue Swirl | farg.ll = arg; |
924 | bd23cd45 | Blue Swirl | |
925 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg.d))) {
|
926 | bd23cd45 | Blue Swirl | /* sNaN square root */
|
927 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
928 | bd23cd45 | Blue Swirl | } |
929 | bd23cd45 | Blue Swirl | f32 = float64_to_float32(farg.d, &env->fp_status); |
930 | bd23cd45 | Blue Swirl | farg.d = float32_to_float64(f32, &env->fp_status); |
931 | bd23cd45 | Blue Swirl | |
932 | bd23cd45 | Blue Swirl | return farg.ll;
|
933 | bd23cd45 | Blue Swirl | } |
934 | bd23cd45 | Blue Swirl | |
935 | bd23cd45 | Blue Swirl | /* fsqrt - fsqrt. */
|
936 | 8e703949 | Blue Swirl | uint64_t helper_fsqrt(CPUPPCState *env, uint64_t arg) |
937 | bd23cd45 | Blue Swirl | { |
938 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
939 | bd23cd45 | Blue Swirl | |
940 | bd23cd45 | Blue Swirl | farg.ll = arg; |
941 | bd23cd45 | Blue Swirl | |
942 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
|
943 | bd23cd45 | Blue Swirl | /* Square root of a negative nonzero number */
|
944 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT); |
945 | bd23cd45 | Blue Swirl | } else {
|
946 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg.d))) {
|
947 | bd23cd45 | Blue Swirl | /* sNaN square root */
|
948 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
949 | bd23cd45 | Blue Swirl | } |
950 | bd23cd45 | Blue Swirl | farg.d = float64_sqrt(farg.d, &env->fp_status); |
951 | bd23cd45 | Blue Swirl | } |
952 | bd23cd45 | Blue Swirl | return farg.ll;
|
953 | bd23cd45 | Blue Swirl | } |
954 | bd23cd45 | Blue Swirl | |
955 | bd23cd45 | Blue Swirl | /* fre - fre. */
|
956 | 8e703949 | Blue Swirl | uint64_t helper_fre(CPUPPCState *env, uint64_t arg) |
957 | bd23cd45 | Blue Swirl | { |
958 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
959 | bd23cd45 | Blue Swirl | |
960 | bd23cd45 | Blue Swirl | farg.ll = arg; |
961 | bd23cd45 | Blue Swirl | |
962 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg.d))) {
|
963 | bd23cd45 | Blue Swirl | /* sNaN reciprocal */
|
964 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
965 | bd23cd45 | Blue Swirl | } |
966 | bd23cd45 | Blue Swirl | farg.d = float64_div(float64_one, farg.d, &env->fp_status); |
967 | bd23cd45 | Blue Swirl | return farg.d;
|
968 | bd23cd45 | Blue Swirl | } |
969 | bd23cd45 | Blue Swirl | |
970 | bd23cd45 | Blue Swirl | /* fres - fres. */
|
971 | 8e703949 | Blue Swirl | uint64_t helper_fres(CPUPPCState *env, uint64_t arg) |
972 | bd23cd45 | Blue Swirl | { |
973 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
974 | bd23cd45 | Blue Swirl | float32 f32; |
975 | bd23cd45 | Blue Swirl | |
976 | bd23cd45 | Blue Swirl | farg.ll = arg; |
977 | bd23cd45 | Blue Swirl | |
978 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg.d))) {
|
979 | bd23cd45 | Blue Swirl | /* sNaN reciprocal */
|
980 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
981 | bd23cd45 | Blue Swirl | } |
982 | bd23cd45 | Blue Swirl | farg.d = float64_div(float64_one, farg.d, &env->fp_status); |
983 | bd23cd45 | Blue Swirl | f32 = float64_to_float32(farg.d, &env->fp_status); |
984 | bd23cd45 | Blue Swirl | farg.d = float32_to_float64(f32, &env->fp_status); |
985 | bd23cd45 | Blue Swirl | |
986 | bd23cd45 | Blue Swirl | return farg.ll;
|
987 | bd23cd45 | Blue Swirl | } |
988 | bd23cd45 | Blue Swirl | |
989 | bd23cd45 | Blue Swirl | /* frsqrte - frsqrte. */
|
990 | 8e703949 | Blue Swirl | uint64_t helper_frsqrte(CPUPPCState *env, uint64_t arg) |
991 | bd23cd45 | Blue Swirl | { |
992 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
993 | bd23cd45 | Blue Swirl | float32 f32; |
994 | bd23cd45 | Blue Swirl | |
995 | bd23cd45 | Blue Swirl | farg.ll = arg; |
996 | bd23cd45 | Blue Swirl | |
997 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
|
998 | bd23cd45 | Blue Swirl | /* Reciprocal square root of a negative nonzero number */
|
999 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT); |
1000 | bd23cd45 | Blue Swirl | } else {
|
1001 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg.d))) {
|
1002 | bd23cd45 | Blue Swirl | /* sNaN reciprocal square root */
|
1003 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
1004 | bd23cd45 | Blue Swirl | } |
1005 | bd23cd45 | Blue Swirl | farg.d = float64_sqrt(farg.d, &env->fp_status); |
1006 | bd23cd45 | Blue Swirl | farg.d = float64_div(float64_one, farg.d, &env->fp_status); |
1007 | bd23cd45 | Blue Swirl | f32 = float64_to_float32(farg.d, &env->fp_status); |
1008 | bd23cd45 | Blue Swirl | farg.d = float32_to_float64(f32, &env->fp_status); |
1009 | bd23cd45 | Blue Swirl | } |
1010 | bd23cd45 | Blue Swirl | return farg.ll;
|
1011 | bd23cd45 | Blue Swirl | } |
1012 | bd23cd45 | Blue Swirl | |
1013 | bd23cd45 | Blue Swirl | /* fsel - fsel. */
|
1014 | 8e703949 | Blue Swirl | uint64_t helper_fsel(CPUPPCState *env, uint64_t arg1, uint64_t arg2, |
1015 | 8e703949 | Blue Swirl | uint64_t arg3) |
1016 | bd23cd45 | Blue Swirl | { |
1017 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1; |
1018 | bd23cd45 | Blue Swirl | |
1019 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
1020 | bd23cd45 | Blue Swirl | |
1021 | bd23cd45 | Blue Swirl | if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) &&
|
1022 | bd23cd45 | Blue Swirl | !float64_is_any_nan(farg1.d)) { |
1023 | bd23cd45 | Blue Swirl | return arg2;
|
1024 | bd23cd45 | Blue Swirl | } else {
|
1025 | bd23cd45 | Blue Swirl | return arg3;
|
1026 | bd23cd45 | Blue Swirl | } |
1027 | bd23cd45 | Blue Swirl | } |
1028 | bd23cd45 | Blue Swirl | |
1029 | 8e703949 | Blue Swirl | void helper_fcmpu(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
|
1030 | 8e703949 | Blue Swirl | uint32_t crfD) |
1031 | bd23cd45 | Blue Swirl | { |
1032 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1, farg2; |
1033 | bd23cd45 | Blue Swirl | uint32_t ret = 0;
|
1034 | bd23cd45 | Blue Swirl | |
1035 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
1036 | bd23cd45 | Blue Swirl | farg2.ll = arg2; |
1037 | bd23cd45 | Blue Swirl | |
1038 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(farg1.d) ||
|
1039 | bd23cd45 | Blue Swirl | float64_is_any_nan(farg2.d))) { |
1040 | bd23cd45 | Blue Swirl | ret = 0x01UL;
|
1041 | bd23cd45 | Blue Swirl | } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) { |
1042 | bd23cd45 | Blue Swirl | ret = 0x08UL;
|
1043 | bd23cd45 | Blue Swirl | } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) { |
1044 | bd23cd45 | Blue Swirl | ret = 0x04UL;
|
1045 | bd23cd45 | Blue Swirl | } else {
|
1046 | bd23cd45 | Blue Swirl | ret = 0x02UL;
|
1047 | bd23cd45 | Blue Swirl | } |
1048 | bd23cd45 | Blue Swirl | |
1049 | bd23cd45 | Blue Swirl | env->fpscr &= ~(0x0F << FPSCR_FPRF);
|
1050 | bd23cd45 | Blue Swirl | env->fpscr |= ret << FPSCR_FPRF; |
1051 | bd23cd45 | Blue Swirl | env->crf[crfD] = ret; |
1052 | bd23cd45 | Blue Swirl | if (unlikely(ret == 0x01UL |
1053 | bd23cd45 | Blue Swirl | && (float64_is_signaling_nan(farg1.d) || |
1054 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg2.d)))) { |
1055 | bd23cd45 | Blue Swirl | /* sNaN comparison */
|
1056 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
1057 | bd23cd45 | Blue Swirl | } |
1058 | bd23cd45 | Blue Swirl | } |
1059 | bd23cd45 | Blue Swirl | |
1060 | 8e703949 | Blue Swirl | void helper_fcmpo(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
|
1061 | 8e703949 | Blue Swirl | uint32_t crfD) |
1062 | bd23cd45 | Blue Swirl | { |
1063 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1, farg2; |
1064 | bd23cd45 | Blue Swirl | uint32_t ret = 0;
|
1065 | bd23cd45 | Blue Swirl | |
1066 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
1067 | bd23cd45 | Blue Swirl | farg2.ll = arg2; |
1068 | bd23cd45 | Blue Swirl | |
1069 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(farg1.d) ||
|
1070 | bd23cd45 | Blue Swirl | float64_is_any_nan(farg2.d))) { |
1071 | bd23cd45 | Blue Swirl | ret = 0x01UL;
|
1072 | bd23cd45 | Blue Swirl | } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) { |
1073 | bd23cd45 | Blue Swirl | ret = 0x08UL;
|
1074 | bd23cd45 | Blue Swirl | } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) { |
1075 | bd23cd45 | Blue Swirl | ret = 0x04UL;
|
1076 | bd23cd45 | Blue Swirl | } else {
|
1077 | bd23cd45 | Blue Swirl | ret = 0x02UL;
|
1078 | bd23cd45 | Blue Swirl | } |
1079 | bd23cd45 | Blue Swirl | |
1080 | bd23cd45 | Blue Swirl | env->fpscr &= ~(0x0F << FPSCR_FPRF);
|
1081 | bd23cd45 | Blue Swirl | env->fpscr |= ret << FPSCR_FPRF; |
1082 | bd23cd45 | Blue Swirl | env->crf[crfD] = ret; |
1083 | bd23cd45 | Blue Swirl | if (unlikely(ret == 0x01UL)) { |
1084 | bd23cd45 | Blue Swirl | if (float64_is_signaling_nan(farg1.d) ||
|
1085 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg2.d)) { |
1086 | bd23cd45 | Blue Swirl | /* sNaN comparison */
|
1087 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN | |
1088 | bd23cd45 | Blue Swirl | POWERPC_EXCP_FP_VXVC); |
1089 | bd23cd45 | Blue Swirl | } else {
|
1090 | bd23cd45 | Blue Swirl | /* qNaN comparison */
|
1091 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC); |
1092 | bd23cd45 | Blue Swirl | } |
1093 | bd23cd45 | Blue Swirl | } |
1094 | bd23cd45 | Blue Swirl | } |
1095 | bd23cd45 | Blue Swirl | |
1096 | bd23cd45 | Blue Swirl | /* Single-precision floating-point conversions */
|
1097 | 8e703949 | Blue Swirl | static inline uint32_t efscfsi(CPUPPCState *env, uint32_t val) |
1098 | bd23cd45 | Blue Swirl | { |
1099 | bd23cd45 | Blue Swirl | CPU_FloatU u; |
1100 | bd23cd45 | Blue Swirl | |
1101 | bd23cd45 | Blue Swirl | u.f = int32_to_float32(val, &env->vec_status); |
1102 | bd23cd45 | Blue Swirl | |
1103 | bd23cd45 | Blue Swirl | return u.l;
|
1104 | bd23cd45 | Blue Swirl | } |
1105 | bd23cd45 | Blue Swirl | |
1106 | 8e703949 | Blue Swirl | static inline uint32_t efscfui(CPUPPCState *env, uint32_t val) |
1107 | bd23cd45 | Blue Swirl | { |
1108 | bd23cd45 | Blue Swirl | CPU_FloatU u; |
1109 | bd23cd45 | Blue Swirl | |
1110 | bd23cd45 | Blue Swirl | u.f = uint32_to_float32(val, &env->vec_status); |
1111 | bd23cd45 | Blue Swirl | |
1112 | bd23cd45 | Blue Swirl | return u.l;
|
1113 | bd23cd45 | Blue Swirl | } |
1114 | bd23cd45 | Blue Swirl | |
1115 | 8e703949 | Blue Swirl | static inline int32_t efsctsi(CPUPPCState *env, uint32_t val) |
1116 | bd23cd45 | Blue Swirl | { |
1117 | bd23cd45 | Blue Swirl | CPU_FloatU u; |
1118 | bd23cd45 | Blue Swirl | |
1119 | bd23cd45 | Blue Swirl | u.l = val; |
1120 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1121 | bd23cd45 | Blue Swirl | if (unlikely(float32_is_quiet_nan(u.f))) {
|
1122 | bd23cd45 | Blue Swirl | return 0; |
1123 | bd23cd45 | Blue Swirl | } |
1124 | bd23cd45 | Blue Swirl | |
1125 | bd23cd45 | Blue Swirl | return float32_to_int32(u.f, &env->vec_status);
|
1126 | bd23cd45 | Blue Swirl | } |
1127 | bd23cd45 | Blue Swirl | |
1128 | 8e703949 | Blue Swirl | static inline uint32_t efsctui(CPUPPCState *env, uint32_t val) |
1129 | bd23cd45 | Blue Swirl | { |
1130 | bd23cd45 | Blue Swirl | CPU_FloatU u; |
1131 | bd23cd45 | Blue Swirl | |
1132 | bd23cd45 | Blue Swirl | u.l = val; |
1133 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1134 | bd23cd45 | Blue Swirl | if (unlikely(float32_is_quiet_nan(u.f))) {
|
1135 | bd23cd45 | Blue Swirl | return 0; |
1136 | bd23cd45 | Blue Swirl | } |
1137 | bd23cd45 | Blue Swirl | |
1138 | bd23cd45 | Blue Swirl | return float32_to_uint32(u.f, &env->vec_status);
|
1139 | bd23cd45 | Blue Swirl | } |
1140 | bd23cd45 | Blue Swirl | |
1141 | 8e703949 | Blue Swirl | static inline uint32_t efsctsiz(CPUPPCState *env, uint32_t val) |
1142 | bd23cd45 | Blue Swirl | { |
1143 | bd23cd45 | Blue Swirl | CPU_FloatU u; |
1144 | bd23cd45 | Blue Swirl | |
1145 | bd23cd45 | Blue Swirl | u.l = val; |
1146 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1147 | bd23cd45 | Blue Swirl | if (unlikely(float32_is_quiet_nan(u.f))) {
|
1148 | bd23cd45 | Blue Swirl | return 0; |
1149 | bd23cd45 | Blue Swirl | } |
1150 | bd23cd45 | Blue Swirl | |
1151 | bd23cd45 | Blue Swirl | return float32_to_int32_round_to_zero(u.f, &env->vec_status);
|
1152 | bd23cd45 | Blue Swirl | } |
1153 | bd23cd45 | Blue Swirl | |
1154 | 8e703949 | Blue Swirl | static inline uint32_t efsctuiz(CPUPPCState *env, uint32_t val) |
1155 | bd23cd45 | Blue Swirl | { |
1156 | bd23cd45 | Blue Swirl | CPU_FloatU u; |
1157 | bd23cd45 | Blue Swirl | |
1158 | bd23cd45 | Blue Swirl | u.l = val; |
1159 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1160 | bd23cd45 | Blue Swirl | if (unlikely(float32_is_quiet_nan(u.f))) {
|
1161 | bd23cd45 | Blue Swirl | return 0; |
1162 | bd23cd45 | Blue Swirl | } |
1163 | bd23cd45 | Blue Swirl | |
1164 | bd23cd45 | Blue Swirl | return float32_to_uint32_round_to_zero(u.f, &env->vec_status);
|
1165 | bd23cd45 | Blue Swirl | } |
1166 | bd23cd45 | Blue Swirl | |
1167 | 8e703949 | Blue Swirl | static inline uint32_t efscfsf(CPUPPCState *env, uint32_t val) |
1168 | bd23cd45 | Blue Swirl | { |
1169 | bd23cd45 | Blue Swirl | CPU_FloatU u; |
1170 | bd23cd45 | Blue Swirl | float32 tmp; |
1171 | bd23cd45 | Blue Swirl | |
1172 | bd23cd45 | Blue Swirl | u.f = int32_to_float32(val, &env->vec_status); |
1173 | bd23cd45 | Blue Swirl | tmp = int64_to_float32(1ULL << 32, &env->vec_status); |
1174 | bd23cd45 | Blue Swirl | u.f = float32_div(u.f, tmp, &env->vec_status); |
1175 | bd23cd45 | Blue Swirl | |
1176 | bd23cd45 | Blue Swirl | return u.l;
|
1177 | bd23cd45 | Blue Swirl | } |
1178 | bd23cd45 | Blue Swirl | |
1179 | 8e703949 | Blue Swirl | static inline uint32_t efscfuf(CPUPPCState *env, uint32_t val) |
1180 | bd23cd45 | Blue Swirl | { |
1181 | bd23cd45 | Blue Swirl | CPU_FloatU u; |
1182 | bd23cd45 | Blue Swirl | float32 tmp; |
1183 | bd23cd45 | Blue Swirl | |
1184 | bd23cd45 | Blue Swirl | u.f = uint32_to_float32(val, &env->vec_status); |
1185 | bd23cd45 | Blue Swirl | tmp = uint64_to_float32(1ULL << 32, &env->vec_status); |
1186 | bd23cd45 | Blue Swirl | u.f = float32_div(u.f, tmp, &env->vec_status); |
1187 | bd23cd45 | Blue Swirl | |
1188 | bd23cd45 | Blue Swirl | return u.l;
|
1189 | bd23cd45 | Blue Swirl | } |
1190 | bd23cd45 | Blue Swirl | |
1191 | 8e703949 | Blue Swirl | static inline uint32_t efsctsf(CPUPPCState *env, uint32_t val) |
1192 | bd23cd45 | Blue Swirl | { |
1193 | bd23cd45 | Blue Swirl | CPU_FloatU u; |
1194 | bd23cd45 | Blue Swirl | float32 tmp; |
1195 | bd23cd45 | Blue Swirl | |
1196 | bd23cd45 | Blue Swirl | u.l = val; |
1197 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1198 | bd23cd45 | Blue Swirl | if (unlikely(float32_is_quiet_nan(u.f))) {
|
1199 | bd23cd45 | Blue Swirl | return 0; |
1200 | bd23cd45 | Blue Swirl | } |
1201 | bd23cd45 | Blue Swirl | tmp = uint64_to_float32(1ULL << 32, &env->vec_status); |
1202 | bd23cd45 | Blue Swirl | u.f = float32_mul(u.f, tmp, &env->vec_status); |
1203 | bd23cd45 | Blue Swirl | |
1204 | bd23cd45 | Blue Swirl | return float32_to_int32(u.f, &env->vec_status);
|
1205 | bd23cd45 | Blue Swirl | } |
1206 | bd23cd45 | Blue Swirl | |
1207 | 8e703949 | Blue Swirl | static inline uint32_t efsctuf(CPUPPCState *env, uint32_t val) |
1208 | bd23cd45 | Blue Swirl | { |
1209 | bd23cd45 | Blue Swirl | CPU_FloatU u; |
1210 | bd23cd45 | Blue Swirl | float32 tmp; |
1211 | bd23cd45 | Blue Swirl | |
1212 | bd23cd45 | Blue Swirl | u.l = val; |
1213 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1214 | bd23cd45 | Blue Swirl | if (unlikely(float32_is_quiet_nan(u.f))) {
|
1215 | bd23cd45 | Blue Swirl | return 0; |
1216 | bd23cd45 | Blue Swirl | } |
1217 | bd23cd45 | Blue Swirl | tmp = uint64_to_float32(1ULL << 32, &env->vec_status); |
1218 | bd23cd45 | Blue Swirl | u.f = float32_mul(u.f, tmp, &env->vec_status); |
1219 | bd23cd45 | Blue Swirl | |
1220 | bd23cd45 | Blue Swirl | return float32_to_uint32(u.f, &env->vec_status);
|
1221 | bd23cd45 | Blue Swirl | } |
1222 | bd23cd45 | Blue Swirl | |
1223 | 8e703949 | Blue Swirl | #define HELPER_SPE_SINGLE_CONV(name) \
|
1224 | 8e703949 | Blue Swirl | uint32_t helper_e##name(CPUPPCState *env, uint32_t val) \ |
1225 | 8e703949 | Blue Swirl | { \ |
1226 | 8e703949 | Blue Swirl | return e##name(env, val); \ |
1227 | bd23cd45 | Blue Swirl | } |
1228 | bd23cd45 | Blue Swirl | /* efscfsi */
|
1229 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_CONV(fscfsi); |
1230 | bd23cd45 | Blue Swirl | /* efscfui */
|
1231 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_CONV(fscfui); |
1232 | bd23cd45 | Blue Swirl | /* efscfuf */
|
1233 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_CONV(fscfuf); |
1234 | bd23cd45 | Blue Swirl | /* efscfsf */
|
1235 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_CONV(fscfsf); |
1236 | bd23cd45 | Blue Swirl | /* efsctsi */
|
1237 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_CONV(fsctsi); |
1238 | bd23cd45 | Blue Swirl | /* efsctui */
|
1239 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_CONV(fsctui); |
1240 | bd23cd45 | Blue Swirl | /* efsctsiz */
|
1241 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_CONV(fsctsiz); |
1242 | bd23cd45 | Blue Swirl | /* efsctuiz */
|
1243 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_CONV(fsctuiz); |
1244 | bd23cd45 | Blue Swirl | /* efsctsf */
|
1245 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_CONV(fsctsf); |
1246 | bd23cd45 | Blue Swirl | /* efsctuf */
|
1247 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_CONV(fsctuf); |
1248 | bd23cd45 | Blue Swirl | |
1249 | 8e703949 | Blue Swirl | #define HELPER_SPE_VECTOR_CONV(name) \
|
1250 | 8e703949 | Blue Swirl | uint64_t helper_ev##name(CPUPPCState *env, uint64_t val) \ |
1251 | 8e703949 | Blue Swirl | { \ |
1252 | 8e703949 | Blue Swirl | return ((uint64_t)e##name(env, val >> 32) << 32) | \ |
1253 | 8e703949 | Blue Swirl | (uint64_t)e##name(env, val); \ |
1254 | bd23cd45 | Blue Swirl | } |
1255 | bd23cd45 | Blue Swirl | /* evfscfsi */
|
1256 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_CONV(fscfsi); |
1257 | bd23cd45 | Blue Swirl | /* evfscfui */
|
1258 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_CONV(fscfui); |
1259 | bd23cd45 | Blue Swirl | /* evfscfuf */
|
1260 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_CONV(fscfuf); |
1261 | bd23cd45 | Blue Swirl | /* evfscfsf */
|
1262 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_CONV(fscfsf); |
1263 | bd23cd45 | Blue Swirl | /* evfsctsi */
|
1264 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_CONV(fsctsi); |
1265 | bd23cd45 | Blue Swirl | /* evfsctui */
|
1266 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_CONV(fsctui); |
1267 | bd23cd45 | Blue Swirl | /* evfsctsiz */
|
1268 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_CONV(fsctsiz); |
1269 | bd23cd45 | Blue Swirl | /* evfsctuiz */
|
1270 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_CONV(fsctuiz); |
1271 | bd23cd45 | Blue Swirl | /* evfsctsf */
|
1272 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_CONV(fsctsf); |
1273 | bd23cd45 | Blue Swirl | /* evfsctuf */
|
1274 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_CONV(fsctuf); |
1275 | bd23cd45 | Blue Swirl | |
1276 | bd23cd45 | Blue Swirl | /* Single-precision floating-point arithmetic */
|
1277 | 8e703949 | Blue Swirl | static inline uint32_t efsadd(CPUPPCState *env, uint32_t op1, uint32_t op2) |
1278 | bd23cd45 | Blue Swirl | { |
1279 | bd23cd45 | Blue Swirl | CPU_FloatU u1, u2; |
1280 | bd23cd45 | Blue Swirl | |
1281 | bd23cd45 | Blue Swirl | u1.l = op1; |
1282 | bd23cd45 | Blue Swirl | u2.l = op2; |
1283 | bd23cd45 | Blue Swirl | u1.f = float32_add(u1.f, u2.f, &env->vec_status); |
1284 | bd23cd45 | Blue Swirl | return u1.l;
|
1285 | bd23cd45 | Blue Swirl | } |
1286 | bd23cd45 | Blue Swirl | |
1287 | 8e703949 | Blue Swirl | static inline uint32_t efssub(CPUPPCState *env, uint32_t op1, uint32_t op2) |
1288 | bd23cd45 | Blue Swirl | { |
1289 | bd23cd45 | Blue Swirl | CPU_FloatU u1, u2; |
1290 | bd23cd45 | Blue Swirl | |
1291 | bd23cd45 | Blue Swirl | u1.l = op1; |
1292 | bd23cd45 | Blue Swirl | u2.l = op2; |
1293 | bd23cd45 | Blue Swirl | u1.f = float32_sub(u1.f, u2.f, &env->vec_status); |
1294 | bd23cd45 | Blue Swirl | return u1.l;
|
1295 | bd23cd45 | Blue Swirl | } |
1296 | bd23cd45 | Blue Swirl | |
1297 | 8e703949 | Blue Swirl | static inline uint32_t efsmul(CPUPPCState *env, uint32_t op1, uint32_t op2) |
1298 | bd23cd45 | Blue Swirl | { |
1299 | bd23cd45 | Blue Swirl | CPU_FloatU u1, u2; |
1300 | bd23cd45 | Blue Swirl | |
1301 | bd23cd45 | Blue Swirl | u1.l = op1; |
1302 | bd23cd45 | Blue Swirl | u2.l = op2; |
1303 | bd23cd45 | Blue Swirl | u1.f = float32_mul(u1.f, u2.f, &env->vec_status); |
1304 | bd23cd45 | Blue Swirl | return u1.l;
|
1305 | bd23cd45 | Blue Swirl | } |
1306 | bd23cd45 | Blue Swirl | |
1307 | 8e703949 | Blue Swirl | static inline uint32_t efsdiv(CPUPPCState *env, uint32_t op1, uint32_t op2) |
1308 | bd23cd45 | Blue Swirl | { |
1309 | bd23cd45 | Blue Swirl | CPU_FloatU u1, u2; |
1310 | bd23cd45 | Blue Swirl | |
1311 | bd23cd45 | Blue Swirl | u1.l = op1; |
1312 | bd23cd45 | Blue Swirl | u2.l = op2; |
1313 | bd23cd45 | Blue Swirl | u1.f = float32_div(u1.f, u2.f, &env->vec_status); |
1314 | bd23cd45 | Blue Swirl | return u1.l;
|
1315 | bd23cd45 | Blue Swirl | } |
1316 | bd23cd45 | Blue Swirl | |
1317 | 8e703949 | Blue Swirl | #define HELPER_SPE_SINGLE_ARITH(name) \
|
1318 | 8e703949 | Blue Swirl | uint32_t helper_e##name(CPUPPCState *env, uint32_t op1, uint32_t op2) \ |
1319 | 8e703949 | Blue Swirl | { \ |
1320 | 8e703949 | Blue Swirl | return e##name(env, op1, op2); \ |
1321 | bd23cd45 | Blue Swirl | } |
1322 | bd23cd45 | Blue Swirl | /* efsadd */
|
1323 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_ARITH(fsadd); |
1324 | bd23cd45 | Blue Swirl | /* efssub */
|
1325 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_ARITH(fssub); |
1326 | bd23cd45 | Blue Swirl | /* efsmul */
|
1327 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_ARITH(fsmul); |
1328 | bd23cd45 | Blue Swirl | /* efsdiv */
|
1329 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_ARITH(fsdiv); |
1330 | bd23cd45 | Blue Swirl | |
1331 | bd23cd45 | Blue Swirl | #define HELPER_SPE_VECTOR_ARITH(name) \
|
1332 | 8e703949 | Blue Swirl | uint64_t helper_ev##name(CPUPPCState *env, uint64_t op1, uint64_t op2) \ |
1333 | bd23cd45 | Blue Swirl | { \ |
1334 | 8e703949 | Blue Swirl | return ((uint64_t)e##name(env, op1 >> 32, op2 >> 32) << 32) | \ |
1335 | 8e703949 | Blue Swirl | (uint64_t)e##name(env, op1, op2); \ |
1336 | bd23cd45 | Blue Swirl | } |
1337 | bd23cd45 | Blue Swirl | /* evfsadd */
|
1338 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_ARITH(fsadd); |
1339 | bd23cd45 | Blue Swirl | /* evfssub */
|
1340 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_ARITH(fssub); |
1341 | bd23cd45 | Blue Swirl | /* evfsmul */
|
1342 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_ARITH(fsmul); |
1343 | bd23cd45 | Blue Swirl | /* evfsdiv */
|
1344 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_ARITH(fsdiv); |
1345 | bd23cd45 | Blue Swirl | |
1346 | bd23cd45 | Blue Swirl | /* Single-precision floating-point comparisons */
|
1347 | 8e703949 | Blue Swirl | static inline uint32_t efscmplt(CPUPPCState *env, uint32_t op1, uint32_t op2) |
1348 | bd23cd45 | Blue Swirl | { |
1349 | bd23cd45 | Blue Swirl | CPU_FloatU u1, u2; |
1350 | bd23cd45 | Blue Swirl | |
1351 | bd23cd45 | Blue Swirl | u1.l = op1; |
1352 | bd23cd45 | Blue Swirl | u2.l = op2; |
1353 | bd23cd45 | Blue Swirl | return float32_lt(u1.f, u2.f, &env->vec_status) ? 4 : 0; |
1354 | bd23cd45 | Blue Swirl | } |
1355 | bd23cd45 | Blue Swirl | |
1356 | 8e703949 | Blue Swirl | static inline uint32_t efscmpgt(CPUPPCState *env, uint32_t op1, uint32_t op2) |
1357 | bd23cd45 | Blue Swirl | { |
1358 | bd23cd45 | Blue Swirl | CPU_FloatU u1, u2; |
1359 | bd23cd45 | Blue Swirl | |
1360 | bd23cd45 | Blue Swirl | u1.l = op1; |
1361 | bd23cd45 | Blue Swirl | u2.l = op2; |
1362 | bd23cd45 | Blue Swirl | return float32_le(u1.f, u2.f, &env->vec_status) ? 0 : 4; |
1363 | bd23cd45 | Blue Swirl | } |
1364 | bd23cd45 | Blue Swirl | |
1365 | 8e703949 | Blue Swirl | static inline uint32_t efscmpeq(CPUPPCState *env, uint32_t op1, uint32_t op2) |
1366 | bd23cd45 | Blue Swirl | { |
1367 | bd23cd45 | Blue Swirl | CPU_FloatU u1, u2; |
1368 | bd23cd45 | Blue Swirl | |
1369 | bd23cd45 | Blue Swirl | u1.l = op1; |
1370 | bd23cd45 | Blue Swirl | u2.l = op2; |
1371 | bd23cd45 | Blue Swirl | return float32_eq(u1.f, u2.f, &env->vec_status) ? 4 : 0; |
1372 | bd23cd45 | Blue Swirl | } |
1373 | bd23cd45 | Blue Swirl | |
1374 | 8e703949 | Blue Swirl | static inline uint32_t efststlt(CPUPPCState *env, uint32_t op1, uint32_t op2) |
1375 | bd23cd45 | Blue Swirl | { |
1376 | bd23cd45 | Blue Swirl | /* XXX: TODO: ignore special values (NaN, infinites, ...) */
|
1377 | 8e703949 | Blue Swirl | return efscmplt(env, op1, op2);
|
1378 | bd23cd45 | Blue Swirl | } |
1379 | bd23cd45 | Blue Swirl | |
1380 | 8e703949 | Blue Swirl | static inline uint32_t efststgt(CPUPPCState *env, uint32_t op1, uint32_t op2) |
1381 | bd23cd45 | Blue Swirl | { |
1382 | bd23cd45 | Blue Swirl | /* XXX: TODO: ignore special values (NaN, infinites, ...) */
|
1383 | 8e703949 | Blue Swirl | return efscmpgt(env, op1, op2);
|
1384 | bd23cd45 | Blue Swirl | } |
1385 | bd23cd45 | Blue Swirl | |
1386 | 8e703949 | Blue Swirl | static inline uint32_t efststeq(CPUPPCState *env, uint32_t op1, uint32_t op2) |
1387 | bd23cd45 | Blue Swirl | { |
1388 | bd23cd45 | Blue Swirl | /* XXX: TODO: ignore special values (NaN, infinites, ...) */
|
1389 | 8e703949 | Blue Swirl | return efscmpeq(env, op1, op2);
|
1390 | bd23cd45 | Blue Swirl | } |
1391 | bd23cd45 | Blue Swirl | |
1392 | 8e703949 | Blue Swirl | #define HELPER_SINGLE_SPE_CMP(name) \
|
1393 | 8e703949 | Blue Swirl | uint32_t helper_e##name(CPUPPCState *env, uint32_t op1, uint32_t op2) \ |
1394 | 8e703949 | Blue Swirl | { \ |
1395 | 8e703949 | Blue Swirl | return e##name(env, op1, op2) << 2; \ |
1396 | bd23cd45 | Blue Swirl | } |
1397 | bd23cd45 | Blue Swirl | /* efststlt */
|
1398 | bd23cd45 | Blue Swirl | HELPER_SINGLE_SPE_CMP(fststlt); |
1399 | bd23cd45 | Blue Swirl | /* efststgt */
|
1400 | bd23cd45 | Blue Swirl | HELPER_SINGLE_SPE_CMP(fststgt); |
1401 | bd23cd45 | Blue Swirl | /* efststeq */
|
1402 | bd23cd45 | Blue Swirl | HELPER_SINGLE_SPE_CMP(fststeq); |
1403 | bd23cd45 | Blue Swirl | /* efscmplt */
|
1404 | bd23cd45 | Blue Swirl | HELPER_SINGLE_SPE_CMP(fscmplt); |
1405 | bd23cd45 | Blue Swirl | /* efscmpgt */
|
1406 | bd23cd45 | Blue Swirl | HELPER_SINGLE_SPE_CMP(fscmpgt); |
1407 | bd23cd45 | Blue Swirl | /* efscmpeq */
|
1408 | bd23cd45 | Blue Swirl | HELPER_SINGLE_SPE_CMP(fscmpeq); |
1409 | bd23cd45 | Blue Swirl | |
1410 | bd23cd45 | Blue Swirl | static inline uint32_t evcmp_merge(int t0, int t1) |
1411 | bd23cd45 | Blue Swirl | { |
1412 | bd23cd45 | Blue Swirl | return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1); |
1413 | bd23cd45 | Blue Swirl | } |
1414 | bd23cd45 | Blue Swirl | |
1415 | bd23cd45 | Blue Swirl | #define HELPER_VECTOR_SPE_CMP(name) \
|
1416 | 8e703949 | Blue Swirl | uint32_t helper_ev##name(CPUPPCState *env, uint64_t op1, uint64_t op2) \ |
1417 | bd23cd45 | Blue Swirl | { \ |
1418 | 8e703949 | Blue Swirl | return evcmp_merge(e##name(env, op1 >> 32, op2 >> 32), \ |
1419 | 8e703949 | Blue Swirl | e##name(env, op1, op2)); \ |
1420 | bd23cd45 | Blue Swirl | } |
1421 | bd23cd45 | Blue Swirl | /* evfststlt */
|
1422 | bd23cd45 | Blue Swirl | HELPER_VECTOR_SPE_CMP(fststlt); |
1423 | bd23cd45 | Blue Swirl | /* evfststgt */
|
1424 | bd23cd45 | Blue Swirl | HELPER_VECTOR_SPE_CMP(fststgt); |
1425 | bd23cd45 | Blue Swirl | /* evfststeq */
|
1426 | bd23cd45 | Blue Swirl | HELPER_VECTOR_SPE_CMP(fststeq); |
1427 | bd23cd45 | Blue Swirl | /* evfscmplt */
|
1428 | bd23cd45 | Blue Swirl | HELPER_VECTOR_SPE_CMP(fscmplt); |
1429 | bd23cd45 | Blue Swirl | /* evfscmpgt */
|
1430 | bd23cd45 | Blue Swirl | HELPER_VECTOR_SPE_CMP(fscmpgt); |
1431 | bd23cd45 | Blue Swirl | /* evfscmpeq */
|
1432 | bd23cd45 | Blue Swirl | HELPER_VECTOR_SPE_CMP(fscmpeq); |
1433 | bd23cd45 | Blue Swirl | |
1434 | bd23cd45 | Blue Swirl | /* Double-precision floating-point conversion */
|
1435 | 8e703949 | Blue Swirl | uint64_t helper_efdcfsi(CPUPPCState *env, uint32_t val) |
1436 | bd23cd45 | Blue Swirl | { |
1437 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1438 | bd23cd45 | Blue Swirl | |
1439 | bd23cd45 | Blue Swirl | u.d = int32_to_float64(val, &env->vec_status); |
1440 | bd23cd45 | Blue Swirl | |
1441 | bd23cd45 | Blue Swirl | return u.ll;
|
1442 | bd23cd45 | Blue Swirl | } |
1443 | bd23cd45 | Blue Swirl | |
1444 | 8e703949 | Blue Swirl | uint64_t helper_efdcfsid(CPUPPCState *env, uint64_t val) |
1445 | bd23cd45 | Blue Swirl | { |
1446 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1447 | bd23cd45 | Blue Swirl | |
1448 | bd23cd45 | Blue Swirl | u.d = int64_to_float64(val, &env->vec_status); |
1449 | bd23cd45 | Blue Swirl | |
1450 | bd23cd45 | Blue Swirl | return u.ll;
|
1451 | bd23cd45 | Blue Swirl | } |
1452 | bd23cd45 | Blue Swirl | |
1453 | 8e703949 | Blue Swirl | uint64_t helper_efdcfui(CPUPPCState *env, uint32_t val) |
1454 | bd23cd45 | Blue Swirl | { |
1455 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1456 | bd23cd45 | Blue Swirl | |
1457 | bd23cd45 | Blue Swirl | u.d = uint32_to_float64(val, &env->vec_status); |
1458 | bd23cd45 | Blue Swirl | |
1459 | bd23cd45 | Blue Swirl | return u.ll;
|
1460 | bd23cd45 | Blue Swirl | } |
1461 | bd23cd45 | Blue Swirl | |
1462 | 8e703949 | Blue Swirl | uint64_t helper_efdcfuid(CPUPPCState *env, uint64_t val) |
1463 | bd23cd45 | Blue Swirl | { |
1464 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1465 | bd23cd45 | Blue Swirl | |
1466 | bd23cd45 | Blue Swirl | u.d = uint64_to_float64(val, &env->vec_status); |
1467 | bd23cd45 | Blue Swirl | |
1468 | bd23cd45 | Blue Swirl | return u.ll;
|
1469 | bd23cd45 | Blue Swirl | } |
1470 | bd23cd45 | Blue Swirl | |
1471 | 8e703949 | Blue Swirl | uint32_t helper_efdctsi(CPUPPCState *env, uint64_t val) |
1472 | bd23cd45 | Blue Swirl | { |
1473 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1474 | bd23cd45 | Blue Swirl | |
1475 | bd23cd45 | Blue Swirl | u.ll = val; |
1476 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1477 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(u.d))) {
|
1478 | bd23cd45 | Blue Swirl | return 0; |
1479 | bd23cd45 | Blue Swirl | } |
1480 | bd23cd45 | Blue Swirl | |
1481 | bd23cd45 | Blue Swirl | return float64_to_int32(u.d, &env->vec_status);
|
1482 | bd23cd45 | Blue Swirl | } |
1483 | bd23cd45 | Blue Swirl | |
1484 | 8e703949 | Blue Swirl | uint32_t helper_efdctui(CPUPPCState *env, uint64_t val) |
1485 | bd23cd45 | Blue Swirl | { |
1486 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1487 | bd23cd45 | Blue Swirl | |
1488 | bd23cd45 | Blue Swirl | u.ll = val; |
1489 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1490 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(u.d))) {
|
1491 | bd23cd45 | Blue Swirl | return 0; |
1492 | bd23cd45 | Blue Swirl | } |
1493 | bd23cd45 | Blue Swirl | |
1494 | bd23cd45 | Blue Swirl | return float64_to_uint32(u.d, &env->vec_status);
|
1495 | bd23cd45 | Blue Swirl | } |
1496 | bd23cd45 | Blue Swirl | |
1497 | 8e703949 | Blue Swirl | uint32_t helper_efdctsiz(CPUPPCState *env, uint64_t val) |
1498 | bd23cd45 | Blue Swirl | { |
1499 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1500 | bd23cd45 | Blue Swirl | |
1501 | bd23cd45 | Blue Swirl | u.ll = val; |
1502 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1503 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(u.d))) {
|
1504 | bd23cd45 | Blue Swirl | return 0; |
1505 | bd23cd45 | Blue Swirl | } |
1506 | bd23cd45 | Blue Swirl | |
1507 | bd23cd45 | Blue Swirl | return float64_to_int32_round_to_zero(u.d, &env->vec_status);
|
1508 | bd23cd45 | Blue Swirl | } |
1509 | bd23cd45 | Blue Swirl | |
1510 | 8e703949 | Blue Swirl | uint64_t helper_efdctsidz(CPUPPCState *env, uint64_t val) |
1511 | bd23cd45 | Blue Swirl | { |
1512 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1513 | bd23cd45 | Blue Swirl | |
1514 | bd23cd45 | Blue Swirl | u.ll = val; |
1515 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1516 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(u.d))) {
|
1517 | bd23cd45 | Blue Swirl | return 0; |
1518 | bd23cd45 | Blue Swirl | } |
1519 | bd23cd45 | Blue Swirl | |
1520 | bd23cd45 | Blue Swirl | return float64_to_int64_round_to_zero(u.d, &env->vec_status);
|
1521 | bd23cd45 | Blue Swirl | } |
1522 | bd23cd45 | Blue Swirl | |
1523 | 8e703949 | Blue Swirl | uint32_t helper_efdctuiz(CPUPPCState *env, uint64_t val) |
1524 | bd23cd45 | Blue Swirl | { |
1525 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1526 | bd23cd45 | Blue Swirl | |
1527 | bd23cd45 | Blue Swirl | u.ll = val; |
1528 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1529 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(u.d))) {
|
1530 | bd23cd45 | Blue Swirl | return 0; |
1531 | bd23cd45 | Blue Swirl | } |
1532 | bd23cd45 | Blue Swirl | |
1533 | bd23cd45 | Blue Swirl | return float64_to_uint32_round_to_zero(u.d, &env->vec_status);
|
1534 | bd23cd45 | Blue Swirl | } |
1535 | bd23cd45 | Blue Swirl | |
1536 | 8e703949 | Blue Swirl | uint64_t helper_efdctuidz(CPUPPCState *env, uint64_t val) |
1537 | bd23cd45 | Blue Swirl | { |
1538 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1539 | bd23cd45 | Blue Swirl | |
1540 | bd23cd45 | Blue Swirl | u.ll = val; |
1541 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1542 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(u.d))) {
|
1543 | bd23cd45 | Blue Swirl | return 0; |
1544 | bd23cd45 | Blue Swirl | } |
1545 | bd23cd45 | Blue Swirl | |
1546 | bd23cd45 | Blue Swirl | return float64_to_uint64_round_to_zero(u.d, &env->vec_status);
|
1547 | bd23cd45 | Blue Swirl | } |
1548 | bd23cd45 | Blue Swirl | |
1549 | 8e703949 | Blue Swirl | uint64_t helper_efdcfsf(CPUPPCState *env, uint32_t val) |
1550 | bd23cd45 | Blue Swirl | { |
1551 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1552 | bd23cd45 | Blue Swirl | float64 tmp; |
1553 | bd23cd45 | Blue Swirl | |
1554 | bd23cd45 | Blue Swirl | u.d = int32_to_float64(val, &env->vec_status); |
1555 | bd23cd45 | Blue Swirl | tmp = int64_to_float64(1ULL << 32, &env->vec_status); |
1556 | bd23cd45 | Blue Swirl | u.d = float64_div(u.d, tmp, &env->vec_status); |
1557 | bd23cd45 | Blue Swirl | |
1558 | bd23cd45 | Blue Swirl | return u.ll;
|
1559 | bd23cd45 | Blue Swirl | } |
1560 | bd23cd45 | Blue Swirl | |
1561 | 8e703949 | Blue Swirl | uint64_t helper_efdcfuf(CPUPPCState *env, uint32_t val) |
1562 | bd23cd45 | Blue Swirl | { |
1563 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1564 | bd23cd45 | Blue Swirl | float64 tmp; |
1565 | bd23cd45 | Blue Swirl | |
1566 | bd23cd45 | Blue Swirl | u.d = uint32_to_float64(val, &env->vec_status); |
1567 | bd23cd45 | Blue Swirl | tmp = int64_to_float64(1ULL << 32, &env->vec_status); |
1568 | bd23cd45 | Blue Swirl | u.d = float64_div(u.d, tmp, &env->vec_status); |
1569 | bd23cd45 | Blue Swirl | |
1570 | bd23cd45 | Blue Swirl | return u.ll;
|
1571 | bd23cd45 | Blue Swirl | } |
1572 | bd23cd45 | Blue Swirl | |
1573 | 8e703949 | Blue Swirl | uint32_t helper_efdctsf(CPUPPCState *env, uint64_t val) |
1574 | bd23cd45 | Blue Swirl | { |
1575 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1576 | bd23cd45 | Blue Swirl | float64 tmp; |
1577 | bd23cd45 | Blue Swirl | |
1578 | bd23cd45 | Blue Swirl | u.ll = val; |
1579 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1580 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(u.d))) {
|
1581 | bd23cd45 | Blue Swirl | return 0; |
1582 | bd23cd45 | Blue Swirl | } |
1583 | bd23cd45 | Blue Swirl | tmp = uint64_to_float64(1ULL << 32, &env->vec_status); |
1584 | bd23cd45 | Blue Swirl | u.d = float64_mul(u.d, tmp, &env->vec_status); |
1585 | bd23cd45 | Blue Swirl | |
1586 | bd23cd45 | Blue Swirl | return float64_to_int32(u.d, &env->vec_status);
|
1587 | bd23cd45 | Blue Swirl | } |
1588 | bd23cd45 | Blue Swirl | |
1589 | 8e703949 | Blue Swirl | uint32_t helper_efdctuf(CPUPPCState *env, uint64_t val) |
1590 | bd23cd45 | Blue Swirl | { |
1591 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1592 | bd23cd45 | Blue Swirl | float64 tmp; |
1593 | bd23cd45 | Blue Swirl | |
1594 | bd23cd45 | Blue Swirl | u.ll = val; |
1595 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1596 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(u.d))) {
|
1597 | bd23cd45 | Blue Swirl | return 0; |
1598 | bd23cd45 | Blue Swirl | } |
1599 | bd23cd45 | Blue Swirl | tmp = uint64_to_float64(1ULL << 32, &env->vec_status); |
1600 | bd23cd45 | Blue Swirl | u.d = float64_mul(u.d, tmp, &env->vec_status); |
1601 | bd23cd45 | Blue Swirl | |
1602 | bd23cd45 | Blue Swirl | return float64_to_uint32(u.d, &env->vec_status);
|
1603 | bd23cd45 | Blue Swirl | } |
1604 | bd23cd45 | Blue Swirl | |
1605 | 8e703949 | Blue Swirl | uint32_t helper_efscfd(CPUPPCState *env, uint64_t val) |
1606 | bd23cd45 | Blue Swirl | { |
1607 | bd23cd45 | Blue Swirl | CPU_DoubleU u1; |
1608 | bd23cd45 | Blue Swirl | CPU_FloatU u2; |
1609 | bd23cd45 | Blue Swirl | |
1610 | bd23cd45 | Blue Swirl | u1.ll = val; |
1611 | bd23cd45 | Blue Swirl | u2.f = float64_to_float32(u1.d, &env->vec_status); |
1612 | bd23cd45 | Blue Swirl | |
1613 | bd23cd45 | Blue Swirl | return u2.l;
|
1614 | bd23cd45 | Blue Swirl | } |
1615 | bd23cd45 | Blue Swirl | |
1616 | 8e703949 | Blue Swirl | uint64_t helper_efdcfs(CPUPPCState *env, uint32_t val) |
1617 | bd23cd45 | Blue Swirl | { |
1618 | bd23cd45 | Blue Swirl | CPU_DoubleU u2; |
1619 | bd23cd45 | Blue Swirl | CPU_FloatU u1; |
1620 | bd23cd45 | Blue Swirl | |
1621 | bd23cd45 | Blue Swirl | u1.l = val; |
1622 | bd23cd45 | Blue Swirl | u2.d = float32_to_float64(u1.f, &env->vec_status); |
1623 | bd23cd45 | Blue Swirl | |
1624 | bd23cd45 | Blue Swirl | return u2.ll;
|
1625 | bd23cd45 | Blue Swirl | } |
1626 | bd23cd45 | Blue Swirl | |
1627 | bd23cd45 | Blue Swirl | /* Double precision fixed-point arithmetic */
|
1628 | 8e703949 | Blue Swirl | uint64_t helper_efdadd(CPUPPCState *env, uint64_t op1, uint64_t op2) |
1629 | bd23cd45 | Blue Swirl | { |
1630 | bd23cd45 | Blue Swirl | CPU_DoubleU u1, u2; |
1631 | bd23cd45 | Blue Swirl | |
1632 | bd23cd45 | Blue Swirl | u1.ll = op1; |
1633 | bd23cd45 | Blue Swirl | u2.ll = op2; |
1634 | bd23cd45 | Blue Swirl | u1.d = float64_add(u1.d, u2.d, &env->vec_status); |
1635 | bd23cd45 | Blue Swirl | return u1.ll;
|
1636 | bd23cd45 | Blue Swirl | } |
1637 | bd23cd45 | Blue Swirl | |
1638 | 8e703949 | Blue Swirl | uint64_t helper_efdsub(CPUPPCState *env, uint64_t op1, uint64_t op2) |
1639 | bd23cd45 | Blue Swirl | { |
1640 | bd23cd45 | Blue Swirl | CPU_DoubleU u1, u2; |
1641 | bd23cd45 | Blue Swirl | |
1642 | bd23cd45 | Blue Swirl | u1.ll = op1; |
1643 | bd23cd45 | Blue Swirl | u2.ll = op2; |
1644 | bd23cd45 | Blue Swirl | u1.d = float64_sub(u1.d, u2.d, &env->vec_status); |
1645 | bd23cd45 | Blue Swirl | return u1.ll;
|
1646 | bd23cd45 | Blue Swirl | } |
1647 | bd23cd45 | Blue Swirl | |
1648 | 8e703949 | Blue Swirl | uint64_t helper_efdmul(CPUPPCState *env, uint64_t op1, uint64_t op2) |
1649 | bd23cd45 | Blue Swirl | { |
1650 | bd23cd45 | Blue Swirl | CPU_DoubleU u1, u2; |
1651 | bd23cd45 | Blue Swirl | |
1652 | bd23cd45 | Blue Swirl | u1.ll = op1; |
1653 | bd23cd45 | Blue Swirl | u2.ll = op2; |
1654 | bd23cd45 | Blue Swirl | u1.d = float64_mul(u1.d, u2.d, &env->vec_status); |
1655 | bd23cd45 | Blue Swirl | return u1.ll;
|
1656 | bd23cd45 | Blue Swirl | } |
1657 | bd23cd45 | Blue Swirl | |
1658 | 8e703949 | Blue Swirl | uint64_t helper_efddiv(CPUPPCState *env, uint64_t op1, uint64_t op2) |
1659 | bd23cd45 | Blue Swirl | { |
1660 | bd23cd45 | Blue Swirl | CPU_DoubleU u1, u2; |
1661 | bd23cd45 | Blue Swirl | |
1662 | bd23cd45 | Blue Swirl | u1.ll = op1; |
1663 | bd23cd45 | Blue Swirl | u2.ll = op2; |
1664 | bd23cd45 | Blue Swirl | u1.d = float64_div(u1.d, u2.d, &env->vec_status); |
1665 | bd23cd45 | Blue Swirl | return u1.ll;
|
1666 | bd23cd45 | Blue Swirl | } |
1667 | bd23cd45 | Blue Swirl | |
1668 | bd23cd45 | Blue Swirl | /* Double precision floating point helpers */
|
1669 | 8e703949 | Blue Swirl | uint32_t helper_efdtstlt(CPUPPCState *env, uint64_t op1, uint64_t op2) |
1670 | bd23cd45 | Blue Swirl | { |
1671 | bd23cd45 | Blue Swirl | CPU_DoubleU u1, u2; |
1672 | bd23cd45 | Blue Swirl | |
1673 | bd23cd45 | Blue Swirl | u1.ll = op1; |
1674 | bd23cd45 | Blue Swirl | u2.ll = op2; |
1675 | bd23cd45 | Blue Swirl | return float64_lt(u1.d, u2.d, &env->vec_status) ? 4 : 0; |
1676 | bd23cd45 | Blue Swirl | } |
1677 | bd23cd45 | Blue Swirl | |
1678 | 8e703949 | Blue Swirl | uint32_t helper_efdtstgt(CPUPPCState *env, uint64_t op1, uint64_t op2) |
1679 | bd23cd45 | Blue Swirl | { |
1680 | bd23cd45 | Blue Swirl | CPU_DoubleU u1, u2; |
1681 | bd23cd45 | Blue Swirl | |
1682 | bd23cd45 | Blue Swirl | u1.ll = op1; |
1683 | bd23cd45 | Blue Swirl | u2.ll = op2; |
1684 | bd23cd45 | Blue Swirl | return float64_le(u1.d, u2.d, &env->vec_status) ? 0 : 4; |
1685 | bd23cd45 | Blue Swirl | } |
1686 | bd23cd45 | Blue Swirl | |
1687 | 8e703949 | Blue Swirl | uint32_t helper_efdtsteq(CPUPPCState *env, uint64_t op1, uint64_t op2) |
1688 | bd23cd45 | Blue Swirl | { |
1689 | bd23cd45 | Blue Swirl | CPU_DoubleU u1, u2; |
1690 | bd23cd45 | Blue Swirl | |
1691 | bd23cd45 | Blue Swirl | u1.ll = op1; |
1692 | bd23cd45 | Blue Swirl | u2.ll = op2; |
1693 | bd23cd45 | Blue Swirl | return float64_eq_quiet(u1.d, u2.d, &env->vec_status) ? 4 : 0; |
1694 | bd23cd45 | Blue Swirl | } |
1695 | bd23cd45 | Blue Swirl | |
1696 | 8e703949 | Blue Swirl | uint32_t helper_efdcmplt(CPUPPCState *env, uint64_t op1, uint64_t op2) |
1697 | bd23cd45 | Blue Swirl | { |
1698 | bd23cd45 | Blue Swirl | /* XXX: TODO: test special values (NaN, infinites, ...) */
|
1699 | 8e703949 | Blue Swirl | return helper_efdtstlt(env, op1, op2);
|
1700 | bd23cd45 | Blue Swirl | } |
1701 | bd23cd45 | Blue Swirl | |
1702 | 8e703949 | Blue Swirl | uint32_t helper_efdcmpgt(CPUPPCState *env, uint64_t op1, uint64_t op2) |
1703 | bd23cd45 | Blue Swirl | { |
1704 | bd23cd45 | Blue Swirl | /* XXX: TODO: test special values (NaN, infinites, ...) */
|
1705 | 8e703949 | Blue Swirl | return helper_efdtstgt(env, op1, op2);
|
1706 | bd23cd45 | Blue Swirl | } |
1707 | bd23cd45 | Blue Swirl | |
1708 | 8e703949 | Blue Swirl | uint32_t helper_efdcmpeq(CPUPPCState *env, uint64_t op1, uint64_t op2) |
1709 | bd23cd45 | Blue Swirl | { |
1710 | bd23cd45 | Blue Swirl | /* XXX: TODO: test special values (NaN, infinites, ...) */
|
1711 | 8e703949 | Blue Swirl | return helper_efdtsteq(env, op1, op2);
|
1712 | bd23cd45 | Blue Swirl | } |