root / target-ppc / fpu_helper.c @ 5a37532d
History | View | Annotate | Download (49.1 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 | bd23cd45 | Blue Swirl | /*
|
434 | bd23cd45 | Blue Swirl | * We use only the 32 LSB of the incoming fpr
|
435 | bd23cd45 | Blue Swirl | */
|
436 | bd23cd45 | Blue Swirl | uint32_t prev, new; |
437 | bd23cd45 | Blue Swirl | int i;
|
438 | bd23cd45 | Blue Swirl | |
439 | bd23cd45 | Blue Swirl | prev = env->fpscr; |
440 | bd23cd45 | Blue Swirl | new = (uint32_t)arg; |
441 | bd23cd45 | Blue Swirl | new &= ~0x60000000;
|
442 | bd23cd45 | Blue Swirl | new |= prev & 0x60000000;
|
443 | bd23cd45 | Blue Swirl | for (i = 0; i < 8; i++) { |
444 | bd23cd45 | Blue Swirl | if (mask & (1 << i)) { |
445 | bd23cd45 | Blue Swirl | env->fpscr &= ~(0xF << (4 * i)); |
446 | bd23cd45 | Blue Swirl | env->fpscr |= new & (0xF << (4 * i)); |
447 | bd23cd45 | Blue Swirl | } |
448 | bd23cd45 | Blue Swirl | } |
449 | bd23cd45 | Blue Swirl | /* Update VX and FEX */
|
450 | bd23cd45 | Blue Swirl | if (fpscr_ix != 0) { |
451 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_VX;
|
452 | bd23cd45 | Blue Swirl | } else {
|
453 | bd23cd45 | Blue Swirl | env->fpscr &= ~(1 << FPSCR_VX);
|
454 | bd23cd45 | Blue Swirl | } |
455 | bd23cd45 | Blue Swirl | if ((fpscr_ex & fpscr_eex) != 0) { |
456 | bd23cd45 | Blue Swirl | env->fpscr |= 1 << FPSCR_FEX;
|
457 | bd23cd45 | Blue Swirl | env->exception_index = POWERPC_EXCP_PROGRAM; |
458 | bd23cd45 | Blue Swirl | /* XXX: we should compute it properly */
|
459 | bd23cd45 | Blue Swirl | env->error_code = POWERPC_EXCP_FP; |
460 | bd23cd45 | Blue Swirl | } else {
|
461 | bd23cd45 | Blue Swirl | env->fpscr &= ~(1 << FPSCR_FEX);
|
462 | bd23cd45 | Blue Swirl | } |
463 | 8e703949 | Blue Swirl | fpscr_set_rounding_mode(env); |
464 | bd23cd45 | Blue Swirl | } |
465 | bd23cd45 | Blue Swirl | |
466 | d6478bc7 | Fabien Chouteau | void store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask)
|
467 | d6478bc7 | Fabien Chouteau | { |
468 | d6478bc7 | Fabien Chouteau | helper_store_fpscr(env, arg, mask); |
469 | d6478bc7 | Fabien Chouteau | } |
470 | d6478bc7 | Fabien Chouteau | |
471 | 8e703949 | Blue Swirl | void helper_float_check_status(CPUPPCState *env)
|
472 | bd23cd45 | Blue Swirl | { |
473 | bd23cd45 | Blue Swirl | if (env->exception_index == POWERPC_EXCP_PROGRAM &&
|
474 | bd23cd45 | Blue Swirl | (env->error_code & POWERPC_EXCP_FP)) { |
475 | bd23cd45 | Blue Swirl | /* Differred floating-point exception after target FPR update */
|
476 | bd23cd45 | Blue Swirl | if (msr_fe0 != 0 || msr_fe1 != 0) { |
477 | bd23cd45 | Blue Swirl | helper_raise_exception_err(env, env->exception_index, |
478 | bd23cd45 | Blue Swirl | env->error_code); |
479 | bd23cd45 | Blue Swirl | } |
480 | bd23cd45 | Blue Swirl | } else {
|
481 | bd23cd45 | Blue Swirl | int status = get_float_exception_flags(&env->fp_status);
|
482 | bd23cd45 | Blue Swirl | if (status & float_flag_divbyzero) {
|
483 | 8e703949 | Blue Swirl | float_zero_divide_excp(env); |
484 | bd23cd45 | Blue Swirl | } else if (status & float_flag_overflow) { |
485 | 8e703949 | Blue Swirl | float_overflow_excp(env); |
486 | bd23cd45 | Blue Swirl | } else if (status & float_flag_underflow) { |
487 | 8e703949 | Blue Swirl | float_underflow_excp(env); |
488 | bd23cd45 | Blue Swirl | } else if (status & float_flag_inexact) { |
489 | 8e703949 | Blue Swirl | float_inexact_excp(env); |
490 | bd23cd45 | Blue Swirl | } |
491 | bd23cd45 | Blue Swirl | } |
492 | bd23cd45 | Blue Swirl | } |
493 | bd23cd45 | Blue Swirl | |
494 | 8e703949 | Blue Swirl | void helper_reset_fpstatus(CPUPPCState *env)
|
495 | bd23cd45 | Blue Swirl | { |
496 | bd23cd45 | Blue Swirl | set_float_exception_flags(0, &env->fp_status);
|
497 | bd23cd45 | Blue Swirl | } |
498 | bd23cd45 | Blue Swirl | |
499 | bd23cd45 | Blue Swirl | /* fadd - fadd. */
|
500 | 8e703949 | Blue Swirl | uint64_t helper_fadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2) |
501 | bd23cd45 | Blue Swirl | { |
502 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1, farg2; |
503 | bd23cd45 | Blue Swirl | |
504 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
505 | bd23cd45 | Blue Swirl | farg2.ll = arg2; |
506 | bd23cd45 | Blue Swirl | |
507 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
|
508 | bd23cd45 | Blue Swirl | float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) { |
509 | bd23cd45 | Blue Swirl | /* Magnitude subtraction of infinities */
|
510 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI); |
511 | bd23cd45 | Blue Swirl | } else {
|
512 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
513 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg2.d))) { |
514 | bd23cd45 | Blue Swirl | /* sNaN addition */
|
515 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
516 | bd23cd45 | Blue Swirl | } |
517 | bd23cd45 | Blue Swirl | farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status); |
518 | bd23cd45 | Blue Swirl | } |
519 | bd23cd45 | Blue Swirl | |
520 | bd23cd45 | Blue Swirl | return farg1.ll;
|
521 | bd23cd45 | Blue Swirl | } |
522 | bd23cd45 | Blue Swirl | |
523 | bd23cd45 | Blue Swirl | /* fsub - fsub. */
|
524 | 8e703949 | Blue Swirl | uint64_t helper_fsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2) |
525 | bd23cd45 | Blue Swirl | { |
526 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1, farg2; |
527 | bd23cd45 | Blue Swirl | |
528 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
529 | bd23cd45 | Blue Swirl | farg2.ll = arg2; |
530 | bd23cd45 | Blue Swirl | |
531 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
|
532 | bd23cd45 | Blue Swirl | float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) { |
533 | bd23cd45 | Blue Swirl | /* Magnitude subtraction of infinities */
|
534 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI); |
535 | bd23cd45 | Blue Swirl | } else {
|
536 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
537 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg2.d))) { |
538 | bd23cd45 | Blue Swirl | /* sNaN subtraction */
|
539 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
540 | bd23cd45 | Blue Swirl | } |
541 | bd23cd45 | Blue Swirl | farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status); |
542 | bd23cd45 | Blue Swirl | } |
543 | bd23cd45 | Blue Swirl | |
544 | bd23cd45 | Blue Swirl | return farg1.ll;
|
545 | bd23cd45 | Blue Swirl | } |
546 | bd23cd45 | Blue Swirl | |
547 | bd23cd45 | Blue Swirl | /* fmul - fmul. */
|
548 | 8e703949 | Blue Swirl | uint64_t helper_fmul(CPUPPCState *env, uint64_t arg1, uint64_t arg2) |
549 | bd23cd45 | Blue Swirl | { |
550 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1, farg2; |
551 | bd23cd45 | Blue Swirl | |
552 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
553 | bd23cd45 | Blue Swirl | farg2.ll = arg2; |
554 | bd23cd45 | Blue Swirl | |
555 | bd23cd45 | Blue Swirl | if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
|
556 | bd23cd45 | Blue Swirl | (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) { |
557 | bd23cd45 | Blue Swirl | /* Multiplication of zero by infinity */
|
558 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ); |
559 | bd23cd45 | Blue Swirl | } else {
|
560 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
561 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg2.d))) { |
562 | bd23cd45 | Blue Swirl | /* sNaN multiplication */
|
563 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
564 | bd23cd45 | Blue Swirl | } |
565 | bd23cd45 | Blue Swirl | farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status); |
566 | bd23cd45 | Blue Swirl | } |
567 | bd23cd45 | Blue Swirl | |
568 | bd23cd45 | Blue Swirl | return farg1.ll;
|
569 | bd23cd45 | Blue Swirl | } |
570 | bd23cd45 | Blue Swirl | |
571 | bd23cd45 | Blue Swirl | /* fdiv - fdiv. */
|
572 | 8e703949 | Blue Swirl | uint64_t helper_fdiv(CPUPPCState *env, uint64_t arg1, uint64_t arg2) |
573 | bd23cd45 | Blue Swirl | { |
574 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1, farg2; |
575 | bd23cd45 | Blue Swirl | |
576 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
577 | bd23cd45 | Blue Swirl | farg2.ll = arg2; |
578 | bd23cd45 | Blue Swirl | |
579 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_infinity(farg1.d) &&
|
580 | bd23cd45 | Blue Swirl | float64_is_infinity(farg2.d))) { |
581 | bd23cd45 | Blue Swirl | /* Division of infinity by infinity */
|
582 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI); |
583 | bd23cd45 | Blue Swirl | } else if (unlikely(float64_is_zero(farg1.d) && float64_is_zero(farg2.d))) { |
584 | bd23cd45 | Blue Swirl | /* Division of zero by zero */
|
585 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ); |
586 | bd23cd45 | Blue Swirl | } else {
|
587 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
588 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg2.d))) { |
589 | bd23cd45 | Blue Swirl | /* sNaN division */
|
590 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
591 | bd23cd45 | Blue Swirl | } |
592 | bd23cd45 | Blue Swirl | farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status); |
593 | bd23cd45 | Blue Swirl | } |
594 | bd23cd45 | Blue Swirl | |
595 | bd23cd45 | Blue Swirl | return farg1.ll;
|
596 | bd23cd45 | Blue Swirl | } |
597 | bd23cd45 | Blue Swirl | |
598 | bd23cd45 | Blue Swirl | /* fabs */
|
599 | 8e703949 | Blue Swirl | uint64_t helper_fabs(CPUPPCState *env, uint64_t arg) |
600 | bd23cd45 | Blue Swirl | { |
601 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
602 | bd23cd45 | Blue Swirl | |
603 | bd23cd45 | Blue Swirl | farg.ll = arg; |
604 | bd23cd45 | Blue Swirl | farg.d = float64_abs(farg.d); |
605 | bd23cd45 | Blue Swirl | return farg.ll;
|
606 | bd23cd45 | Blue Swirl | } |
607 | bd23cd45 | Blue Swirl | |
608 | bd23cd45 | Blue Swirl | /* fnabs */
|
609 | 8e703949 | Blue Swirl | uint64_t helper_fnabs(CPUPPCState *env, uint64_t arg) |
610 | bd23cd45 | Blue Swirl | { |
611 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
612 | bd23cd45 | Blue Swirl | |
613 | bd23cd45 | Blue Swirl | farg.ll = arg; |
614 | bd23cd45 | Blue Swirl | farg.d = float64_abs(farg.d); |
615 | bd23cd45 | Blue Swirl | farg.d = float64_chs(farg.d); |
616 | bd23cd45 | Blue Swirl | return farg.ll;
|
617 | bd23cd45 | Blue Swirl | } |
618 | bd23cd45 | Blue Swirl | |
619 | bd23cd45 | Blue Swirl | /* fneg */
|
620 | 8e703949 | Blue Swirl | uint64_t helper_fneg(CPUPPCState *env, uint64_t arg) |
621 | bd23cd45 | Blue Swirl | { |
622 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
623 | bd23cd45 | Blue Swirl | |
624 | bd23cd45 | Blue Swirl | farg.ll = arg; |
625 | bd23cd45 | Blue Swirl | farg.d = float64_chs(farg.d); |
626 | bd23cd45 | Blue Swirl | return farg.ll;
|
627 | bd23cd45 | Blue Swirl | } |
628 | bd23cd45 | Blue Swirl | |
629 | bd23cd45 | Blue Swirl | /* fctiw - fctiw. */
|
630 | 8e703949 | Blue Swirl | uint64_t helper_fctiw(CPUPPCState *env, uint64_t arg) |
631 | bd23cd45 | Blue Swirl | { |
632 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
633 | bd23cd45 | Blue Swirl | |
634 | bd23cd45 | Blue Swirl | farg.ll = arg; |
635 | bd23cd45 | Blue Swirl | |
636 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg.d))) {
|
637 | bd23cd45 | Blue Swirl | /* sNaN conversion */
|
638 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN | |
639 | bd23cd45 | Blue Swirl | POWERPC_EXCP_FP_VXCVI); |
640 | bd23cd45 | Blue Swirl | } else if (unlikely(float64_is_quiet_nan(farg.d) || |
641 | bd23cd45 | Blue Swirl | float64_is_infinity(farg.d))) { |
642 | bd23cd45 | Blue Swirl | /* qNan / infinity conversion */
|
643 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI); |
644 | bd23cd45 | Blue Swirl | } else {
|
645 | bd23cd45 | Blue Swirl | farg.ll = float64_to_int32(farg.d, &env->fp_status); |
646 | bd23cd45 | Blue Swirl | /* XXX: higher bits are not supposed to be significant.
|
647 | bd23cd45 | Blue Swirl | * to make tests easier, return the same as a real PowerPC 750
|
648 | bd23cd45 | Blue Swirl | */
|
649 | bd23cd45 | Blue Swirl | farg.ll |= 0xFFF80000ULL << 32; |
650 | bd23cd45 | Blue Swirl | } |
651 | bd23cd45 | Blue Swirl | return farg.ll;
|
652 | bd23cd45 | Blue Swirl | } |
653 | bd23cd45 | Blue Swirl | |
654 | bd23cd45 | Blue Swirl | /* fctiwz - fctiwz. */
|
655 | 8e703949 | Blue Swirl | uint64_t helper_fctiwz(CPUPPCState *env, uint64_t arg) |
656 | bd23cd45 | Blue Swirl | { |
657 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
658 | bd23cd45 | Blue Swirl | |
659 | bd23cd45 | Blue Swirl | farg.ll = arg; |
660 | bd23cd45 | Blue Swirl | |
661 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg.d))) {
|
662 | bd23cd45 | Blue Swirl | /* sNaN conversion */
|
663 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN | |
664 | bd23cd45 | Blue Swirl | POWERPC_EXCP_FP_VXCVI); |
665 | bd23cd45 | Blue Swirl | } else if (unlikely(float64_is_quiet_nan(farg.d) || |
666 | bd23cd45 | Blue Swirl | float64_is_infinity(farg.d))) { |
667 | bd23cd45 | Blue Swirl | /* qNan / infinity conversion */
|
668 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI); |
669 | bd23cd45 | Blue Swirl | } else {
|
670 | bd23cd45 | Blue Swirl | farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status); |
671 | bd23cd45 | Blue Swirl | /* XXX: higher bits are not supposed to be significant.
|
672 | bd23cd45 | Blue Swirl | * to make tests easier, return the same as a real PowerPC 750
|
673 | bd23cd45 | Blue Swirl | */
|
674 | bd23cd45 | Blue Swirl | farg.ll |= 0xFFF80000ULL << 32; |
675 | bd23cd45 | Blue Swirl | } |
676 | bd23cd45 | Blue Swirl | return farg.ll;
|
677 | bd23cd45 | Blue Swirl | } |
678 | bd23cd45 | Blue Swirl | |
679 | bd23cd45 | Blue Swirl | #if defined(TARGET_PPC64)
|
680 | bd23cd45 | Blue Swirl | /* fcfid - fcfid. */
|
681 | 8e703949 | Blue Swirl | uint64_t helper_fcfid(CPUPPCState *env, uint64_t arg) |
682 | bd23cd45 | Blue Swirl | { |
683 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
684 | bd23cd45 | Blue Swirl | |
685 | bd23cd45 | Blue Swirl | farg.d = int64_to_float64(arg, &env->fp_status); |
686 | bd23cd45 | Blue Swirl | return farg.ll;
|
687 | bd23cd45 | Blue Swirl | } |
688 | bd23cd45 | Blue Swirl | |
689 | bd23cd45 | Blue Swirl | /* fctid - fctid. */
|
690 | 8e703949 | Blue Swirl | uint64_t helper_fctid(CPUPPCState *env, uint64_t arg) |
691 | bd23cd45 | Blue Swirl | { |
692 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
693 | bd23cd45 | Blue Swirl | |
694 | bd23cd45 | Blue Swirl | farg.ll = arg; |
695 | bd23cd45 | Blue Swirl | |
696 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg.d))) {
|
697 | bd23cd45 | Blue Swirl | /* sNaN conversion */
|
698 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN | |
699 | bd23cd45 | Blue Swirl | POWERPC_EXCP_FP_VXCVI); |
700 | bd23cd45 | Blue Swirl | } else if (unlikely(float64_is_quiet_nan(farg.d) || |
701 | bd23cd45 | Blue Swirl | float64_is_infinity(farg.d))) { |
702 | bd23cd45 | Blue Swirl | /* qNan / infinity conversion */
|
703 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI); |
704 | bd23cd45 | Blue Swirl | } else {
|
705 | bd23cd45 | Blue Swirl | farg.ll = float64_to_int64(farg.d, &env->fp_status); |
706 | bd23cd45 | Blue Swirl | } |
707 | bd23cd45 | Blue Swirl | return farg.ll;
|
708 | bd23cd45 | Blue Swirl | } |
709 | bd23cd45 | Blue Swirl | |
710 | bd23cd45 | Blue Swirl | /* fctidz - fctidz. */
|
711 | 8e703949 | Blue Swirl | uint64_t helper_fctidz(CPUPPCState *env, uint64_t arg) |
712 | bd23cd45 | Blue Swirl | { |
713 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
714 | bd23cd45 | Blue Swirl | |
715 | bd23cd45 | Blue Swirl | farg.ll = arg; |
716 | bd23cd45 | Blue Swirl | |
717 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg.d))) {
|
718 | bd23cd45 | Blue Swirl | /* sNaN conversion */
|
719 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN | |
720 | bd23cd45 | Blue Swirl | POWERPC_EXCP_FP_VXCVI); |
721 | bd23cd45 | Blue Swirl | } else if (unlikely(float64_is_quiet_nan(farg.d) || |
722 | bd23cd45 | Blue Swirl | float64_is_infinity(farg.d))) { |
723 | bd23cd45 | Blue Swirl | /* qNan / infinity conversion */
|
724 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI); |
725 | bd23cd45 | Blue Swirl | } else {
|
726 | bd23cd45 | Blue Swirl | farg.ll = float64_to_int64_round_to_zero(farg.d, &env->fp_status); |
727 | bd23cd45 | Blue Swirl | } |
728 | bd23cd45 | Blue Swirl | return farg.ll;
|
729 | bd23cd45 | Blue Swirl | } |
730 | bd23cd45 | Blue Swirl | |
731 | bd23cd45 | Blue Swirl | #endif
|
732 | bd23cd45 | Blue Swirl | |
733 | 8e703949 | Blue Swirl | static inline uint64_t do_fri(CPUPPCState *env, uint64_t arg, |
734 | 8e703949 | Blue Swirl | int rounding_mode)
|
735 | bd23cd45 | Blue Swirl | { |
736 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
737 | bd23cd45 | Blue Swirl | |
738 | bd23cd45 | Blue Swirl | farg.ll = arg; |
739 | bd23cd45 | Blue Swirl | |
740 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg.d))) {
|
741 | bd23cd45 | Blue Swirl | /* sNaN round */
|
742 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN | |
743 | bd23cd45 | Blue Swirl | POWERPC_EXCP_FP_VXCVI); |
744 | bd23cd45 | Blue Swirl | } else if (unlikely(float64_is_quiet_nan(farg.d) || |
745 | bd23cd45 | Blue Swirl | float64_is_infinity(farg.d))) { |
746 | bd23cd45 | Blue Swirl | /* qNan / infinity round */
|
747 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI); |
748 | bd23cd45 | Blue Swirl | } else {
|
749 | bd23cd45 | Blue Swirl | set_float_rounding_mode(rounding_mode, &env->fp_status); |
750 | bd23cd45 | Blue Swirl | farg.ll = float64_round_to_int(farg.d, &env->fp_status); |
751 | bd23cd45 | Blue Swirl | /* Restore rounding mode from FPSCR */
|
752 | 8e703949 | Blue Swirl | fpscr_set_rounding_mode(env); |
753 | bd23cd45 | Blue Swirl | } |
754 | bd23cd45 | Blue Swirl | return farg.ll;
|
755 | bd23cd45 | Blue Swirl | } |
756 | bd23cd45 | Blue Swirl | |
757 | 8e703949 | Blue Swirl | uint64_t helper_frin(CPUPPCState *env, uint64_t arg) |
758 | bd23cd45 | Blue Swirl | { |
759 | 8e703949 | Blue Swirl | return do_fri(env, arg, float_round_nearest_even);
|
760 | bd23cd45 | Blue Swirl | } |
761 | bd23cd45 | Blue Swirl | |
762 | 8e703949 | Blue Swirl | uint64_t helper_friz(CPUPPCState *env, uint64_t arg) |
763 | bd23cd45 | Blue Swirl | { |
764 | 8e703949 | Blue Swirl | return do_fri(env, arg, float_round_to_zero);
|
765 | bd23cd45 | Blue Swirl | } |
766 | bd23cd45 | Blue Swirl | |
767 | 8e703949 | Blue Swirl | uint64_t helper_frip(CPUPPCState *env, uint64_t arg) |
768 | bd23cd45 | Blue Swirl | { |
769 | 8e703949 | Blue Swirl | return do_fri(env, arg, float_round_up);
|
770 | bd23cd45 | Blue Swirl | } |
771 | bd23cd45 | Blue Swirl | |
772 | 8e703949 | Blue Swirl | uint64_t helper_frim(CPUPPCState *env, uint64_t arg) |
773 | bd23cd45 | Blue Swirl | { |
774 | 8e703949 | Blue Swirl | return do_fri(env, arg, float_round_down);
|
775 | bd23cd45 | Blue Swirl | } |
776 | bd23cd45 | Blue Swirl | |
777 | bd23cd45 | Blue Swirl | /* fmadd - fmadd. */
|
778 | 8e703949 | Blue Swirl | uint64_t helper_fmadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2, |
779 | 8e703949 | Blue Swirl | uint64_t arg3) |
780 | bd23cd45 | Blue Swirl | { |
781 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1, farg2, farg3; |
782 | bd23cd45 | Blue Swirl | |
783 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
784 | bd23cd45 | Blue Swirl | farg2.ll = arg2; |
785 | bd23cd45 | Blue Swirl | farg3.ll = arg3; |
786 | bd23cd45 | Blue Swirl | |
787 | bd23cd45 | Blue Swirl | if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
|
788 | bd23cd45 | Blue Swirl | (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) { |
789 | bd23cd45 | Blue Swirl | /* Multiplication of zero by infinity */
|
790 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ); |
791 | bd23cd45 | Blue Swirl | } else {
|
792 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
793 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg2.d) || |
794 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg3.d))) { |
795 | bd23cd45 | Blue Swirl | /* sNaN operation */
|
796 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
797 | bd23cd45 | Blue Swirl | } |
798 | bd23cd45 | Blue Swirl | /* This is the way the PowerPC specification defines it */
|
799 | bd23cd45 | Blue Swirl | float128 ft0_128, ft1_128; |
800 | bd23cd45 | Blue Swirl | |
801 | bd23cd45 | Blue Swirl | ft0_128 = float64_to_float128(farg1.d, &env->fp_status); |
802 | bd23cd45 | Blue Swirl | ft1_128 = float64_to_float128(farg2.d, &env->fp_status); |
803 | bd23cd45 | Blue Swirl | ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status); |
804 | bd23cd45 | Blue Swirl | if (unlikely(float128_is_infinity(ft0_128) &&
|
805 | bd23cd45 | Blue Swirl | float64_is_infinity(farg3.d) && |
806 | bd23cd45 | Blue Swirl | float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) { |
807 | bd23cd45 | Blue Swirl | /* Magnitude subtraction of infinities */
|
808 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI); |
809 | bd23cd45 | Blue Swirl | } else {
|
810 | bd23cd45 | Blue Swirl | ft1_128 = float64_to_float128(farg3.d, &env->fp_status); |
811 | bd23cd45 | Blue Swirl | ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status); |
812 | bd23cd45 | Blue Swirl | farg1.d = float128_to_float64(ft0_128, &env->fp_status); |
813 | bd23cd45 | Blue Swirl | } |
814 | bd23cd45 | Blue Swirl | } |
815 | bd23cd45 | Blue Swirl | |
816 | bd23cd45 | Blue Swirl | return farg1.ll;
|
817 | bd23cd45 | Blue Swirl | } |
818 | bd23cd45 | Blue Swirl | |
819 | bd23cd45 | Blue Swirl | /* fmsub - fmsub. */
|
820 | 8e703949 | Blue Swirl | uint64_t helper_fmsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2, |
821 | 8e703949 | Blue Swirl | uint64_t arg3) |
822 | bd23cd45 | Blue Swirl | { |
823 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1, farg2, farg3; |
824 | bd23cd45 | Blue Swirl | |
825 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
826 | bd23cd45 | Blue Swirl | farg2.ll = arg2; |
827 | bd23cd45 | Blue Swirl | farg3.ll = arg3; |
828 | bd23cd45 | Blue Swirl | |
829 | bd23cd45 | Blue Swirl | if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
|
830 | bd23cd45 | Blue Swirl | (float64_is_zero(farg1.d) && |
831 | bd23cd45 | Blue Swirl | float64_is_infinity(farg2.d)))) { |
832 | bd23cd45 | Blue Swirl | /* Multiplication of zero by infinity */
|
833 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ); |
834 | bd23cd45 | Blue Swirl | } else {
|
835 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
836 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg2.d) || |
837 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg3.d))) { |
838 | bd23cd45 | Blue Swirl | /* sNaN operation */
|
839 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
840 | bd23cd45 | Blue Swirl | } |
841 | bd23cd45 | Blue Swirl | /* This is the way the PowerPC specification defines it */
|
842 | bd23cd45 | Blue Swirl | float128 ft0_128, ft1_128; |
843 | bd23cd45 | Blue Swirl | |
844 | bd23cd45 | Blue Swirl | ft0_128 = float64_to_float128(farg1.d, &env->fp_status); |
845 | bd23cd45 | Blue Swirl | ft1_128 = float64_to_float128(farg2.d, &env->fp_status); |
846 | bd23cd45 | Blue Swirl | ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status); |
847 | bd23cd45 | Blue Swirl | if (unlikely(float128_is_infinity(ft0_128) &&
|
848 | bd23cd45 | Blue Swirl | float64_is_infinity(farg3.d) && |
849 | bd23cd45 | Blue Swirl | float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) { |
850 | bd23cd45 | Blue Swirl | /* Magnitude subtraction of infinities */
|
851 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI); |
852 | bd23cd45 | Blue Swirl | } else {
|
853 | bd23cd45 | Blue Swirl | ft1_128 = float64_to_float128(farg3.d, &env->fp_status); |
854 | bd23cd45 | Blue Swirl | ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status); |
855 | bd23cd45 | Blue Swirl | farg1.d = float128_to_float64(ft0_128, &env->fp_status); |
856 | bd23cd45 | Blue Swirl | } |
857 | bd23cd45 | Blue Swirl | } |
858 | bd23cd45 | Blue Swirl | return farg1.ll;
|
859 | bd23cd45 | Blue Swirl | } |
860 | bd23cd45 | Blue Swirl | |
861 | bd23cd45 | Blue Swirl | /* fnmadd - fnmadd. */
|
862 | 8e703949 | Blue Swirl | uint64_t helper_fnmadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2, |
863 | 8e703949 | Blue Swirl | uint64_t arg3) |
864 | bd23cd45 | Blue Swirl | { |
865 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1, farg2, farg3; |
866 | bd23cd45 | Blue Swirl | |
867 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
868 | bd23cd45 | Blue Swirl | farg2.ll = arg2; |
869 | bd23cd45 | Blue Swirl | farg3.ll = arg3; |
870 | bd23cd45 | Blue Swirl | |
871 | bd23cd45 | Blue Swirl | if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
|
872 | bd23cd45 | Blue Swirl | (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) { |
873 | bd23cd45 | Blue Swirl | /* Multiplication of zero by infinity */
|
874 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ); |
875 | bd23cd45 | Blue Swirl | } else {
|
876 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
877 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg2.d) || |
878 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg3.d))) { |
879 | bd23cd45 | Blue Swirl | /* sNaN operation */
|
880 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
881 | bd23cd45 | Blue Swirl | } |
882 | bd23cd45 | Blue Swirl | /* This is the way the PowerPC specification defines it */
|
883 | bd23cd45 | Blue Swirl | float128 ft0_128, ft1_128; |
884 | bd23cd45 | Blue Swirl | |
885 | bd23cd45 | Blue Swirl | ft0_128 = float64_to_float128(farg1.d, &env->fp_status); |
886 | bd23cd45 | Blue Swirl | ft1_128 = float64_to_float128(farg2.d, &env->fp_status); |
887 | bd23cd45 | Blue Swirl | ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status); |
888 | bd23cd45 | Blue Swirl | if (unlikely(float128_is_infinity(ft0_128) &&
|
889 | bd23cd45 | Blue Swirl | float64_is_infinity(farg3.d) && |
890 | bd23cd45 | Blue Swirl | float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) { |
891 | bd23cd45 | Blue Swirl | /* Magnitude subtraction of infinities */
|
892 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI); |
893 | bd23cd45 | Blue Swirl | } else {
|
894 | bd23cd45 | Blue Swirl | ft1_128 = float64_to_float128(farg3.d, &env->fp_status); |
895 | bd23cd45 | Blue Swirl | ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status); |
896 | bd23cd45 | Blue Swirl | farg1.d = float128_to_float64(ft0_128, &env->fp_status); |
897 | bd23cd45 | Blue Swirl | } |
898 | bd23cd45 | Blue Swirl | if (likely(!float64_is_any_nan(farg1.d))) {
|
899 | bd23cd45 | Blue Swirl | farg1.d = float64_chs(farg1.d); |
900 | bd23cd45 | Blue Swirl | } |
901 | bd23cd45 | Blue Swirl | } |
902 | bd23cd45 | Blue Swirl | return farg1.ll;
|
903 | bd23cd45 | Blue Swirl | } |
904 | bd23cd45 | Blue Swirl | |
905 | bd23cd45 | Blue Swirl | /* fnmsub - fnmsub. */
|
906 | 8e703949 | Blue Swirl | uint64_t helper_fnmsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2, |
907 | 8e703949 | Blue Swirl | uint64_t arg3) |
908 | bd23cd45 | Blue Swirl | { |
909 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1, farg2, farg3; |
910 | bd23cd45 | Blue Swirl | |
911 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
912 | bd23cd45 | Blue Swirl | farg2.ll = arg2; |
913 | bd23cd45 | Blue Swirl | farg3.ll = arg3; |
914 | bd23cd45 | Blue Swirl | |
915 | bd23cd45 | Blue Swirl | if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
|
916 | bd23cd45 | Blue Swirl | (float64_is_zero(farg1.d) && |
917 | bd23cd45 | Blue Swirl | float64_is_infinity(farg2.d)))) { |
918 | bd23cd45 | Blue Swirl | /* Multiplication of zero by infinity */
|
919 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ); |
920 | bd23cd45 | Blue Swirl | } else {
|
921 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
922 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg2.d) || |
923 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg3.d))) { |
924 | bd23cd45 | Blue Swirl | /* sNaN operation */
|
925 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
926 | bd23cd45 | Blue Swirl | } |
927 | bd23cd45 | Blue Swirl | /* This is the way the PowerPC specification defines it */
|
928 | bd23cd45 | Blue Swirl | float128 ft0_128, ft1_128; |
929 | bd23cd45 | Blue Swirl | |
930 | bd23cd45 | Blue Swirl | ft0_128 = float64_to_float128(farg1.d, &env->fp_status); |
931 | bd23cd45 | Blue Swirl | ft1_128 = float64_to_float128(farg2.d, &env->fp_status); |
932 | bd23cd45 | Blue Swirl | ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status); |
933 | bd23cd45 | Blue Swirl | if (unlikely(float128_is_infinity(ft0_128) &&
|
934 | bd23cd45 | Blue Swirl | float64_is_infinity(farg3.d) && |
935 | bd23cd45 | Blue Swirl | float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) { |
936 | bd23cd45 | Blue Swirl | /* Magnitude subtraction of infinities */
|
937 | 8e703949 | Blue Swirl | farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI); |
938 | bd23cd45 | Blue Swirl | } else {
|
939 | bd23cd45 | Blue Swirl | ft1_128 = float64_to_float128(farg3.d, &env->fp_status); |
940 | bd23cd45 | Blue Swirl | ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status); |
941 | bd23cd45 | Blue Swirl | farg1.d = float128_to_float64(ft0_128, &env->fp_status); |
942 | bd23cd45 | Blue Swirl | } |
943 | bd23cd45 | Blue Swirl | if (likely(!float64_is_any_nan(farg1.d))) {
|
944 | bd23cd45 | Blue Swirl | farg1.d = float64_chs(farg1.d); |
945 | bd23cd45 | Blue Swirl | } |
946 | bd23cd45 | Blue Swirl | } |
947 | bd23cd45 | Blue Swirl | return farg1.ll;
|
948 | bd23cd45 | Blue Swirl | } |
949 | bd23cd45 | Blue Swirl | |
950 | bd23cd45 | Blue Swirl | /* frsp - frsp. */
|
951 | 8e703949 | Blue Swirl | uint64_t helper_frsp(CPUPPCState *env, uint64_t arg) |
952 | bd23cd45 | Blue Swirl | { |
953 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
954 | bd23cd45 | Blue Swirl | float32 f32; |
955 | bd23cd45 | Blue Swirl | |
956 | bd23cd45 | Blue Swirl | farg.ll = arg; |
957 | bd23cd45 | Blue Swirl | |
958 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg.d))) {
|
959 | bd23cd45 | Blue Swirl | /* sNaN square root */
|
960 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
961 | bd23cd45 | Blue Swirl | } |
962 | bd23cd45 | Blue Swirl | f32 = float64_to_float32(farg.d, &env->fp_status); |
963 | bd23cd45 | Blue Swirl | farg.d = float32_to_float64(f32, &env->fp_status); |
964 | bd23cd45 | Blue Swirl | |
965 | bd23cd45 | Blue Swirl | return farg.ll;
|
966 | bd23cd45 | Blue Swirl | } |
967 | bd23cd45 | Blue Swirl | |
968 | bd23cd45 | Blue Swirl | /* fsqrt - fsqrt. */
|
969 | 8e703949 | Blue Swirl | uint64_t helper_fsqrt(CPUPPCState *env, uint64_t arg) |
970 | bd23cd45 | Blue Swirl | { |
971 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
972 | bd23cd45 | Blue Swirl | |
973 | bd23cd45 | Blue Swirl | farg.ll = arg; |
974 | bd23cd45 | Blue Swirl | |
975 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
|
976 | bd23cd45 | Blue Swirl | /* Square root of a negative nonzero number */
|
977 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT); |
978 | bd23cd45 | Blue Swirl | } else {
|
979 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg.d))) {
|
980 | bd23cd45 | Blue Swirl | /* sNaN square root */
|
981 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
982 | bd23cd45 | Blue Swirl | } |
983 | bd23cd45 | Blue Swirl | farg.d = float64_sqrt(farg.d, &env->fp_status); |
984 | bd23cd45 | Blue Swirl | } |
985 | bd23cd45 | Blue Swirl | return farg.ll;
|
986 | bd23cd45 | Blue Swirl | } |
987 | bd23cd45 | Blue Swirl | |
988 | bd23cd45 | Blue Swirl | /* fre - fre. */
|
989 | 8e703949 | Blue Swirl | uint64_t helper_fre(CPUPPCState *env, uint64_t arg) |
990 | bd23cd45 | Blue Swirl | { |
991 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
992 | bd23cd45 | Blue Swirl | |
993 | bd23cd45 | Blue Swirl | farg.ll = arg; |
994 | bd23cd45 | Blue Swirl | |
995 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg.d))) {
|
996 | bd23cd45 | Blue Swirl | /* sNaN reciprocal */
|
997 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
998 | bd23cd45 | Blue Swirl | } |
999 | bd23cd45 | Blue Swirl | farg.d = float64_div(float64_one, farg.d, &env->fp_status); |
1000 | bd23cd45 | Blue Swirl | return farg.d;
|
1001 | bd23cd45 | Blue Swirl | } |
1002 | bd23cd45 | Blue Swirl | |
1003 | bd23cd45 | Blue Swirl | /* fres - fres. */
|
1004 | 8e703949 | Blue Swirl | uint64_t helper_fres(CPUPPCState *env, uint64_t arg) |
1005 | bd23cd45 | Blue Swirl | { |
1006 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
1007 | bd23cd45 | Blue Swirl | float32 f32; |
1008 | bd23cd45 | Blue Swirl | |
1009 | bd23cd45 | Blue Swirl | farg.ll = arg; |
1010 | bd23cd45 | Blue Swirl | |
1011 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg.d))) {
|
1012 | bd23cd45 | Blue Swirl | /* sNaN reciprocal */
|
1013 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
1014 | bd23cd45 | Blue Swirl | } |
1015 | bd23cd45 | Blue Swirl | farg.d = float64_div(float64_one, farg.d, &env->fp_status); |
1016 | bd23cd45 | Blue Swirl | f32 = float64_to_float32(farg.d, &env->fp_status); |
1017 | bd23cd45 | Blue Swirl | farg.d = float32_to_float64(f32, &env->fp_status); |
1018 | bd23cd45 | Blue Swirl | |
1019 | bd23cd45 | Blue Swirl | return farg.ll;
|
1020 | bd23cd45 | Blue Swirl | } |
1021 | bd23cd45 | Blue Swirl | |
1022 | bd23cd45 | Blue Swirl | /* frsqrte - frsqrte. */
|
1023 | 8e703949 | Blue Swirl | uint64_t helper_frsqrte(CPUPPCState *env, uint64_t arg) |
1024 | bd23cd45 | Blue Swirl | { |
1025 | bd23cd45 | Blue Swirl | CPU_DoubleU farg; |
1026 | bd23cd45 | Blue Swirl | float32 f32; |
1027 | bd23cd45 | Blue Swirl | |
1028 | bd23cd45 | Blue Swirl | farg.ll = arg; |
1029 | bd23cd45 | Blue Swirl | |
1030 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
|
1031 | bd23cd45 | Blue Swirl | /* Reciprocal square root of a negative nonzero number */
|
1032 | 8e703949 | Blue Swirl | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT); |
1033 | bd23cd45 | Blue Swirl | } else {
|
1034 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_signaling_nan(farg.d))) {
|
1035 | bd23cd45 | Blue Swirl | /* sNaN reciprocal square root */
|
1036 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
1037 | bd23cd45 | Blue Swirl | } |
1038 | bd23cd45 | Blue Swirl | farg.d = float64_sqrt(farg.d, &env->fp_status); |
1039 | bd23cd45 | Blue Swirl | farg.d = float64_div(float64_one, farg.d, &env->fp_status); |
1040 | bd23cd45 | Blue Swirl | f32 = float64_to_float32(farg.d, &env->fp_status); |
1041 | bd23cd45 | Blue Swirl | farg.d = float32_to_float64(f32, &env->fp_status); |
1042 | bd23cd45 | Blue Swirl | } |
1043 | bd23cd45 | Blue Swirl | return farg.ll;
|
1044 | bd23cd45 | Blue Swirl | } |
1045 | bd23cd45 | Blue Swirl | |
1046 | bd23cd45 | Blue Swirl | /* fsel - fsel. */
|
1047 | 8e703949 | Blue Swirl | uint64_t helper_fsel(CPUPPCState *env, uint64_t arg1, uint64_t arg2, |
1048 | 8e703949 | Blue Swirl | uint64_t arg3) |
1049 | bd23cd45 | Blue Swirl | { |
1050 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1; |
1051 | bd23cd45 | Blue Swirl | |
1052 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
1053 | bd23cd45 | Blue Swirl | |
1054 | bd23cd45 | Blue Swirl | if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) &&
|
1055 | bd23cd45 | Blue Swirl | !float64_is_any_nan(farg1.d)) { |
1056 | bd23cd45 | Blue Swirl | return arg2;
|
1057 | bd23cd45 | Blue Swirl | } else {
|
1058 | bd23cd45 | Blue Swirl | return arg3;
|
1059 | bd23cd45 | Blue Swirl | } |
1060 | bd23cd45 | Blue Swirl | } |
1061 | bd23cd45 | Blue Swirl | |
1062 | 8e703949 | Blue Swirl | void helper_fcmpu(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
|
1063 | 8e703949 | Blue Swirl | uint32_t crfD) |
1064 | bd23cd45 | Blue Swirl | { |
1065 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1, farg2; |
1066 | bd23cd45 | Blue Swirl | uint32_t ret = 0;
|
1067 | bd23cd45 | Blue Swirl | |
1068 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
1069 | bd23cd45 | Blue Swirl | farg2.ll = arg2; |
1070 | bd23cd45 | Blue Swirl | |
1071 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(farg1.d) ||
|
1072 | bd23cd45 | Blue Swirl | float64_is_any_nan(farg2.d))) { |
1073 | bd23cd45 | Blue Swirl | ret = 0x01UL;
|
1074 | bd23cd45 | Blue Swirl | } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) { |
1075 | bd23cd45 | Blue Swirl | ret = 0x08UL;
|
1076 | bd23cd45 | Blue Swirl | } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) { |
1077 | bd23cd45 | Blue Swirl | ret = 0x04UL;
|
1078 | bd23cd45 | Blue Swirl | } else {
|
1079 | bd23cd45 | Blue Swirl | ret = 0x02UL;
|
1080 | bd23cd45 | Blue Swirl | } |
1081 | bd23cd45 | Blue Swirl | |
1082 | bd23cd45 | Blue Swirl | env->fpscr &= ~(0x0F << FPSCR_FPRF);
|
1083 | bd23cd45 | Blue Swirl | env->fpscr |= ret << FPSCR_FPRF; |
1084 | bd23cd45 | Blue Swirl | env->crf[crfD] = ret; |
1085 | bd23cd45 | Blue Swirl | if (unlikely(ret == 0x01UL |
1086 | bd23cd45 | Blue Swirl | && (float64_is_signaling_nan(farg1.d) || |
1087 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg2.d)))) { |
1088 | bd23cd45 | Blue Swirl | /* sNaN comparison */
|
1089 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); |
1090 | bd23cd45 | Blue Swirl | } |
1091 | bd23cd45 | Blue Swirl | } |
1092 | bd23cd45 | Blue Swirl | |
1093 | 8e703949 | Blue Swirl | void helper_fcmpo(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
|
1094 | 8e703949 | Blue Swirl | uint32_t crfD) |
1095 | bd23cd45 | Blue Swirl | { |
1096 | bd23cd45 | Blue Swirl | CPU_DoubleU farg1, farg2; |
1097 | bd23cd45 | Blue Swirl | uint32_t ret = 0;
|
1098 | bd23cd45 | Blue Swirl | |
1099 | bd23cd45 | Blue Swirl | farg1.ll = arg1; |
1100 | bd23cd45 | Blue Swirl | farg2.ll = arg2; |
1101 | bd23cd45 | Blue Swirl | |
1102 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(farg1.d) ||
|
1103 | bd23cd45 | Blue Swirl | float64_is_any_nan(farg2.d))) { |
1104 | bd23cd45 | Blue Swirl | ret = 0x01UL;
|
1105 | bd23cd45 | Blue Swirl | } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) { |
1106 | bd23cd45 | Blue Swirl | ret = 0x08UL;
|
1107 | bd23cd45 | Blue Swirl | } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) { |
1108 | bd23cd45 | Blue Swirl | ret = 0x04UL;
|
1109 | bd23cd45 | Blue Swirl | } else {
|
1110 | bd23cd45 | Blue Swirl | ret = 0x02UL;
|
1111 | bd23cd45 | Blue Swirl | } |
1112 | bd23cd45 | Blue Swirl | |
1113 | bd23cd45 | Blue Swirl | env->fpscr &= ~(0x0F << FPSCR_FPRF);
|
1114 | bd23cd45 | Blue Swirl | env->fpscr |= ret << FPSCR_FPRF; |
1115 | bd23cd45 | Blue Swirl | env->crf[crfD] = ret; |
1116 | bd23cd45 | Blue Swirl | if (unlikely(ret == 0x01UL)) { |
1117 | bd23cd45 | Blue Swirl | if (float64_is_signaling_nan(farg1.d) ||
|
1118 | bd23cd45 | Blue Swirl | float64_is_signaling_nan(farg2.d)) { |
1119 | bd23cd45 | Blue Swirl | /* sNaN comparison */
|
1120 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN | |
1121 | bd23cd45 | Blue Swirl | POWERPC_EXCP_FP_VXVC); |
1122 | bd23cd45 | Blue Swirl | } else {
|
1123 | bd23cd45 | Blue Swirl | /* qNaN comparison */
|
1124 | 8e703949 | Blue Swirl | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC); |
1125 | bd23cd45 | Blue Swirl | } |
1126 | bd23cd45 | Blue Swirl | } |
1127 | bd23cd45 | Blue Swirl | } |
1128 | bd23cd45 | Blue Swirl | |
1129 | bd23cd45 | Blue Swirl | /* Single-precision floating-point conversions */
|
1130 | 8e703949 | Blue Swirl | static inline uint32_t efscfsi(CPUPPCState *env, uint32_t val) |
1131 | bd23cd45 | Blue Swirl | { |
1132 | bd23cd45 | Blue Swirl | CPU_FloatU u; |
1133 | bd23cd45 | Blue Swirl | |
1134 | bd23cd45 | Blue Swirl | u.f = int32_to_float32(val, &env->vec_status); |
1135 | bd23cd45 | Blue Swirl | |
1136 | bd23cd45 | Blue Swirl | return u.l;
|
1137 | bd23cd45 | Blue Swirl | } |
1138 | bd23cd45 | Blue Swirl | |
1139 | 8e703949 | Blue Swirl | static inline uint32_t efscfui(CPUPPCState *env, uint32_t val) |
1140 | bd23cd45 | Blue Swirl | { |
1141 | bd23cd45 | Blue Swirl | CPU_FloatU u; |
1142 | bd23cd45 | Blue Swirl | |
1143 | bd23cd45 | Blue Swirl | u.f = uint32_to_float32(val, &env->vec_status); |
1144 | bd23cd45 | Blue Swirl | |
1145 | bd23cd45 | Blue Swirl | return u.l;
|
1146 | bd23cd45 | Blue Swirl | } |
1147 | bd23cd45 | Blue Swirl | |
1148 | 8e703949 | Blue Swirl | static inline int32_t efsctsi(CPUPPCState *env, uint32_t val) |
1149 | bd23cd45 | Blue Swirl | { |
1150 | bd23cd45 | Blue Swirl | CPU_FloatU u; |
1151 | bd23cd45 | Blue Swirl | |
1152 | bd23cd45 | Blue Swirl | u.l = val; |
1153 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1154 | bd23cd45 | Blue Swirl | if (unlikely(float32_is_quiet_nan(u.f))) {
|
1155 | bd23cd45 | Blue Swirl | return 0; |
1156 | bd23cd45 | Blue Swirl | } |
1157 | bd23cd45 | Blue Swirl | |
1158 | bd23cd45 | Blue Swirl | return float32_to_int32(u.f, &env->vec_status);
|
1159 | bd23cd45 | Blue Swirl | } |
1160 | bd23cd45 | Blue Swirl | |
1161 | 8e703949 | Blue Swirl | static inline uint32_t efsctui(CPUPPCState *env, uint32_t val) |
1162 | bd23cd45 | Blue Swirl | { |
1163 | bd23cd45 | Blue Swirl | CPU_FloatU u; |
1164 | bd23cd45 | Blue Swirl | |
1165 | bd23cd45 | Blue Swirl | u.l = val; |
1166 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1167 | bd23cd45 | Blue Swirl | if (unlikely(float32_is_quiet_nan(u.f))) {
|
1168 | bd23cd45 | Blue Swirl | return 0; |
1169 | bd23cd45 | Blue Swirl | } |
1170 | bd23cd45 | Blue Swirl | |
1171 | bd23cd45 | Blue Swirl | return float32_to_uint32(u.f, &env->vec_status);
|
1172 | bd23cd45 | Blue Swirl | } |
1173 | bd23cd45 | Blue Swirl | |
1174 | 8e703949 | Blue Swirl | static inline uint32_t efsctsiz(CPUPPCState *env, uint32_t val) |
1175 | bd23cd45 | Blue Swirl | { |
1176 | bd23cd45 | Blue Swirl | CPU_FloatU u; |
1177 | bd23cd45 | Blue Swirl | |
1178 | bd23cd45 | Blue Swirl | u.l = val; |
1179 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1180 | bd23cd45 | Blue Swirl | if (unlikely(float32_is_quiet_nan(u.f))) {
|
1181 | bd23cd45 | Blue Swirl | return 0; |
1182 | bd23cd45 | Blue Swirl | } |
1183 | bd23cd45 | Blue Swirl | |
1184 | bd23cd45 | Blue Swirl | return float32_to_int32_round_to_zero(u.f, &env->vec_status);
|
1185 | bd23cd45 | Blue Swirl | } |
1186 | bd23cd45 | Blue Swirl | |
1187 | 8e703949 | Blue Swirl | static inline uint32_t efsctuiz(CPUPPCState *env, uint32_t val) |
1188 | bd23cd45 | Blue Swirl | { |
1189 | bd23cd45 | Blue Swirl | CPU_FloatU u; |
1190 | bd23cd45 | Blue Swirl | |
1191 | bd23cd45 | Blue Swirl | u.l = val; |
1192 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1193 | bd23cd45 | Blue Swirl | if (unlikely(float32_is_quiet_nan(u.f))) {
|
1194 | bd23cd45 | Blue Swirl | return 0; |
1195 | bd23cd45 | Blue Swirl | } |
1196 | bd23cd45 | Blue Swirl | |
1197 | bd23cd45 | Blue Swirl | return float32_to_uint32_round_to_zero(u.f, &env->vec_status);
|
1198 | bd23cd45 | Blue Swirl | } |
1199 | bd23cd45 | Blue Swirl | |
1200 | 8e703949 | Blue Swirl | static inline uint32_t efscfsf(CPUPPCState *env, uint32_t val) |
1201 | bd23cd45 | Blue Swirl | { |
1202 | bd23cd45 | Blue Swirl | CPU_FloatU u; |
1203 | bd23cd45 | Blue Swirl | float32 tmp; |
1204 | bd23cd45 | Blue Swirl | |
1205 | bd23cd45 | Blue Swirl | u.f = int32_to_float32(val, &env->vec_status); |
1206 | bd23cd45 | Blue Swirl | tmp = int64_to_float32(1ULL << 32, &env->vec_status); |
1207 | bd23cd45 | Blue Swirl | u.f = float32_div(u.f, tmp, &env->vec_status); |
1208 | bd23cd45 | Blue Swirl | |
1209 | bd23cd45 | Blue Swirl | return u.l;
|
1210 | bd23cd45 | Blue Swirl | } |
1211 | bd23cd45 | Blue Swirl | |
1212 | 8e703949 | Blue Swirl | static inline uint32_t efscfuf(CPUPPCState *env, uint32_t val) |
1213 | bd23cd45 | Blue Swirl | { |
1214 | bd23cd45 | Blue Swirl | CPU_FloatU u; |
1215 | bd23cd45 | Blue Swirl | float32 tmp; |
1216 | bd23cd45 | Blue Swirl | |
1217 | bd23cd45 | Blue Swirl | u.f = uint32_to_float32(val, &env->vec_status); |
1218 | bd23cd45 | Blue Swirl | tmp = uint64_to_float32(1ULL << 32, &env->vec_status); |
1219 | bd23cd45 | Blue Swirl | u.f = float32_div(u.f, tmp, &env->vec_status); |
1220 | bd23cd45 | Blue Swirl | |
1221 | bd23cd45 | Blue Swirl | return u.l;
|
1222 | bd23cd45 | Blue Swirl | } |
1223 | bd23cd45 | Blue Swirl | |
1224 | 8e703949 | Blue Swirl | static inline uint32_t efsctsf(CPUPPCState *env, uint32_t val) |
1225 | bd23cd45 | Blue Swirl | { |
1226 | bd23cd45 | Blue Swirl | CPU_FloatU u; |
1227 | bd23cd45 | Blue Swirl | float32 tmp; |
1228 | bd23cd45 | Blue Swirl | |
1229 | bd23cd45 | Blue Swirl | u.l = val; |
1230 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1231 | bd23cd45 | Blue Swirl | if (unlikely(float32_is_quiet_nan(u.f))) {
|
1232 | bd23cd45 | Blue Swirl | return 0; |
1233 | bd23cd45 | Blue Swirl | } |
1234 | bd23cd45 | Blue Swirl | tmp = uint64_to_float32(1ULL << 32, &env->vec_status); |
1235 | bd23cd45 | Blue Swirl | u.f = float32_mul(u.f, tmp, &env->vec_status); |
1236 | bd23cd45 | Blue Swirl | |
1237 | bd23cd45 | Blue Swirl | return float32_to_int32(u.f, &env->vec_status);
|
1238 | bd23cd45 | Blue Swirl | } |
1239 | bd23cd45 | Blue Swirl | |
1240 | 8e703949 | Blue Swirl | static inline uint32_t efsctuf(CPUPPCState *env, uint32_t val) |
1241 | bd23cd45 | Blue Swirl | { |
1242 | bd23cd45 | Blue Swirl | CPU_FloatU u; |
1243 | bd23cd45 | Blue Swirl | float32 tmp; |
1244 | bd23cd45 | Blue Swirl | |
1245 | bd23cd45 | Blue Swirl | u.l = val; |
1246 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1247 | bd23cd45 | Blue Swirl | if (unlikely(float32_is_quiet_nan(u.f))) {
|
1248 | bd23cd45 | Blue Swirl | return 0; |
1249 | bd23cd45 | Blue Swirl | } |
1250 | bd23cd45 | Blue Swirl | tmp = uint64_to_float32(1ULL << 32, &env->vec_status); |
1251 | bd23cd45 | Blue Swirl | u.f = float32_mul(u.f, tmp, &env->vec_status); |
1252 | bd23cd45 | Blue Swirl | |
1253 | bd23cd45 | Blue Swirl | return float32_to_uint32(u.f, &env->vec_status);
|
1254 | bd23cd45 | Blue Swirl | } |
1255 | bd23cd45 | Blue Swirl | |
1256 | 8e703949 | Blue Swirl | #define HELPER_SPE_SINGLE_CONV(name) \
|
1257 | 8e703949 | Blue Swirl | uint32_t helper_e##name(CPUPPCState *env, uint32_t val) \ |
1258 | 8e703949 | Blue Swirl | { \ |
1259 | 8e703949 | Blue Swirl | return e##name(env, val); \ |
1260 | bd23cd45 | Blue Swirl | } |
1261 | bd23cd45 | Blue Swirl | /* efscfsi */
|
1262 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_CONV(fscfsi); |
1263 | bd23cd45 | Blue Swirl | /* efscfui */
|
1264 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_CONV(fscfui); |
1265 | bd23cd45 | Blue Swirl | /* efscfuf */
|
1266 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_CONV(fscfuf); |
1267 | bd23cd45 | Blue Swirl | /* efscfsf */
|
1268 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_CONV(fscfsf); |
1269 | bd23cd45 | Blue Swirl | /* efsctsi */
|
1270 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_CONV(fsctsi); |
1271 | bd23cd45 | Blue Swirl | /* efsctui */
|
1272 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_CONV(fsctui); |
1273 | bd23cd45 | Blue Swirl | /* efsctsiz */
|
1274 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_CONV(fsctsiz); |
1275 | bd23cd45 | Blue Swirl | /* efsctuiz */
|
1276 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_CONV(fsctuiz); |
1277 | bd23cd45 | Blue Swirl | /* efsctsf */
|
1278 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_CONV(fsctsf); |
1279 | bd23cd45 | Blue Swirl | /* efsctuf */
|
1280 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_CONV(fsctuf); |
1281 | bd23cd45 | Blue Swirl | |
1282 | 8e703949 | Blue Swirl | #define HELPER_SPE_VECTOR_CONV(name) \
|
1283 | 8e703949 | Blue Swirl | uint64_t helper_ev##name(CPUPPCState *env, uint64_t val) \ |
1284 | 8e703949 | Blue Swirl | { \ |
1285 | 8e703949 | Blue Swirl | return ((uint64_t)e##name(env, val >> 32) << 32) | \ |
1286 | 8e703949 | Blue Swirl | (uint64_t)e##name(env, val); \ |
1287 | bd23cd45 | Blue Swirl | } |
1288 | bd23cd45 | Blue Swirl | /* evfscfsi */
|
1289 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_CONV(fscfsi); |
1290 | bd23cd45 | Blue Swirl | /* evfscfui */
|
1291 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_CONV(fscfui); |
1292 | bd23cd45 | Blue Swirl | /* evfscfuf */
|
1293 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_CONV(fscfuf); |
1294 | bd23cd45 | Blue Swirl | /* evfscfsf */
|
1295 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_CONV(fscfsf); |
1296 | bd23cd45 | Blue Swirl | /* evfsctsi */
|
1297 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_CONV(fsctsi); |
1298 | bd23cd45 | Blue Swirl | /* evfsctui */
|
1299 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_CONV(fsctui); |
1300 | bd23cd45 | Blue Swirl | /* evfsctsiz */
|
1301 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_CONV(fsctsiz); |
1302 | bd23cd45 | Blue Swirl | /* evfsctuiz */
|
1303 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_CONV(fsctuiz); |
1304 | bd23cd45 | Blue Swirl | /* evfsctsf */
|
1305 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_CONV(fsctsf); |
1306 | bd23cd45 | Blue Swirl | /* evfsctuf */
|
1307 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_CONV(fsctuf); |
1308 | bd23cd45 | Blue Swirl | |
1309 | bd23cd45 | Blue Swirl | /* Single-precision floating-point arithmetic */
|
1310 | 8e703949 | Blue Swirl | static inline uint32_t efsadd(CPUPPCState *env, uint32_t op1, uint32_t op2) |
1311 | bd23cd45 | Blue Swirl | { |
1312 | bd23cd45 | Blue Swirl | CPU_FloatU u1, u2; |
1313 | bd23cd45 | Blue Swirl | |
1314 | bd23cd45 | Blue Swirl | u1.l = op1; |
1315 | bd23cd45 | Blue Swirl | u2.l = op2; |
1316 | bd23cd45 | Blue Swirl | u1.f = float32_add(u1.f, u2.f, &env->vec_status); |
1317 | bd23cd45 | Blue Swirl | return u1.l;
|
1318 | bd23cd45 | Blue Swirl | } |
1319 | bd23cd45 | Blue Swirl | |
1320 | 8e703949 | Blue Swirl | static inline uint32_t efssub(CPUPPCState *env, uint32_t op1, uint32_t op2) |
1321 | bd23cd45 | Blue Swirl | { |
1322 | bd23cd45 | Blue Swirl | CPU_FloatU u1, u2; |
1323 | bd23cd45 | Blue Swirl | |
1324 | bd23cd45 | Blue Swirl | u1.l = op1; |
1325 | bd23cd45 | Blue Swirl | u2.l = op2; |
1326 | bd23cd45 | Blue Swirl | u1.f = float32_sub(u1.f, u2.f, &env->vec_status); |
1327 | bd23cd45 | Blue Swirl | return u1.l;
|
1328 | bd23cd45 | Blue Swirl | } |
1329 | bd23cd45 | Blue Swirl | |
1330 | 8e703949 | Blue Swirl | static inline uint32_t efsmul(CPUPPCState *env, uint32_t op1, uint32_t op2) |
1331 | bd23cd45 | Blue Swirl | { |
1332 | bd23cd45 | Blue Swirl | CPU_FloatU u1, u2; |
1333 | bd23cd45 | Blue Swirl | |
1334 | bd23cd45 | Blue Swirl | u1.l = op1; |
1335 | bd23cd45 | Blue Swirl | u2.l = op2; |
1336 | bd23cd45 | Blue Swirl | u1.f = float32_mul(u1.f, u2.f, &env->vec_status); |
1337 | bd23cd45 | Blue Swirl | return u1.l;
|
1338 | bd23cd45 | Blue Swirl | } |
1339 | bd23cd45 | Blue Swirl | |
1340 | 8e703949 | Blue Swirl | static inline uint32_t efsdiv(CPUPPCState *env, uint32_t op1, uint32_t op2) |
1341 | bd23cd45 | Blue Swirl | { |
1342 | bd23cd45 | Blue Swirl | CPU_FloatU u1, u2; |
1343 | bd23cd45 | Blue Swirl | |
1344 | bd23cd45 | Blue Swirl | u1.l = op1; |
1345 | bd23cd45 | Blue Swirl | u2.l = op2; |
1346 | bd23cd45 | Blue Swirl | u1.f = float32_div(u1.f, u2.f, &env->vec_status); |
1347 | bd23cd45 | Blue Swirl | return u1.l;
|
1348 | bd23cd45 | Blue Swirl | } |
1349 | bd23cd45 | Blue Swirl | |
1350 | 8e703949 | Blue Swirl | #define HELPER_SPE_SINGLE_ARITH(name) \
|
1351 | 8e703949 | Blue Swirl | uint32_t helper_e##name(CPUPPCState *env, uint32_t op1, uint32_t op2) \ |
1352 | 8e703949 | Blue Swirl | { \ |
1353 | 8e703949 | Blue Swirl | return e##name(env, op1, op2); \ |
1354 | bd23cd45 | Blue Swirl | } |
1355 | bd23cd45 | Blue Swirl | /* efsadd */
|
1356 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_ARITH(fsadd); |
1357 | bd23cd45 | Blue Swirl | /* efssub */
|
1358 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_ARITH(fssub); |
1359 | bd23cd45 | Blue Swirl | /* efsmul */
|
1360 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_ARITH(fsmul); |
1361 | bd23cd45 | Blue Swirl | /* efsdiv */
|
1362 | bd23cd45 | Blue Swirl | HELPER_SPE_SINGLE_ARITH(fsdiv); |
1363 | bd23cd45 | Blue Swirl | |
1364 | bd23cd45 | Blue Swirl | #define HELPER_SPE_VECTOR_ARITH(name) \
|
1365 | 8e703949 | Blue Swirl | uint64_t helper_ev##name(CPUPPCState *env, uint64_t op1, uint64_t op2) \ |
1366 | bd23cd45 | Blue Swirl | { \ |
1367 | 8e703949 | Blue Swirl | return ((uint64_t)e##name(env, op1 >> 32, op2 >> 32) << 32) | \ |
1368 | 8e703949 | Blue Swirl | (uint64_t)e##name(env, op1, op2); \ |
1369 | bd23cd45 | Blue Swirl | } |
1370 | bd23cd45 | Blue Swirl | /* evfsadd */
|
1371 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_ARITH(fsadd); |
1372 | bd23cd45 | Blue Swirl | /* evfssub */
|
1373 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_ARITH(fssub); |
1374 | bd23cd45 | Blue Swirl | /* evfsmul */
|
1375 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_ARITH(fsmul); |
1376 | bd23cd45 | Blue Swirl | /* evfsdiv */
|
1377 | bd23cd45 | Blue Swirl | HELPER_SPE_VECTOR_ARITH(fsdiv); |
1378 | bd23cd45 | Blue Swirl | |
1379 | bd23cd45 | Blue Swirl | /* Single-precision floating-point comparisons */
|
1380 | 8e703949 | Blue Swirl | static inline uint32_t efscmplt(CPUPPCState *env, uint32_t op1, uint32_t op2) |
1381 | bd23cd45 | Blue Swirl | { |
1382 | bd23cd45 | Blue Swirl | CPU_FloatU u1, u2; |
1383 | bd23cd45 | Blue Swirl | |
1384 | bd23cd45 | Blue Swirl | u1.l = op1; |
1385 | bd23cd45 | Blue Swirl | u2.l = op2; |
1386 | bd23cd45 | Blue Swirl | return float32_lt(u1.f, u2.f, &env->vec_status) ? 4 : 0; |
1387 | bd23cd45 | Blue Swirl | } |
1388 | bd23cd45 | Blue Swirl | |
1389 | 8e703949 | Blue Swirl | static inline uint32_t efscmpgt(CPUPPCState *env, uint32_t op1, uint32_t op2) |
1390 | bd23cd45 | Blue Swirl | { |
1391 | bd23cd45 | Blue Swirl | CPU_FloatU u1, u2; |
1392 | bd23cd45 | Blue Swirl | |
1393 | bd23cd45 | Blue Swirl | u1.l = op1; |
1394 | bd23cd45 | Blue Swirl | u2.l = op2; |
1395 | bd23cd45 | Blue Swirl | return float32_le(u1.f, u2.f, &env->vec_status) ? 0 : 4; |
1396 | bd23cd45 | Blue Swirl | } |
1397 | bd23cd45 | Blue Swirl | |
1398 | 8e703949 | Blue Swirl | static inline uint32_t efscmpeq(CPUPPCState *env, uint32_t op1, uint32_t op2) |
1399 | bd23cd45 | Blue Swirl | { |
1400 | bd23cd45 | Blue Swirl | CPU_FloatU u1, u2; |
1401 | bd23cd45 | Blue Swirl | |
1402 | bd23cd45 | Blue Swirl | u1.l = op1; |
1403 | bd23cd45 | Blue Swirl | u2.l = op2; |
1404 | bd23cd45 | Blue Swirl | return float32_eq(u1.f, u2.f, &env->vec_status) ? 4 : 0; |
1405 | bd23cd45 | Blue Swirl | } |
1406 | bd23cd45 | Blue Swirl | |
1407 | 8e703949 | Blue Swirl | static inline uint32_t efststlt(CPUPPCState *env, uint32_t op1, uint32_t op2) |
1408 | bd23cd45 | Blue Swirl | { |
1409 | bd23cd45 | Blue Swirl | /* XXX: TODO: ignore special values (NaN, infinites, ...) */
|
1410 | 8e703949 | Blue Swirl | return efscmplt(env, op1, op2);
|
1411 | bd23cd45 | Blue Swirl | } |
1412 | bd23cd45 | Blue Swirl | |
1413 | 8e703949 | Blue Swirl | static inline uint32_t efststgt(CPUPPCState *env, uint32_t op1, uint32_t op2) |
1414 | bd23cd45 | Blue Swirl | { |
1415 | bd23cd45 | Blue Swirl | /* XXX: TODO: ignore special values (NaN, infinites, ...) */
|
1416 | 8e703949 | Blue Swirl | return efscmpgt(env, op1, op2);
|
1417 | bd23cd45 | Blue Swirl | } |
1418 | bd23cd45 | Blue Swirl | |
1419 | 8e703949 | Blue Swirl | static inline uint32_t efststeq(CPUPPCState *env, uint32_t op1, uint32_t op2) |
1420 | bd23cd45 | Blue Swirl | { |
1421 | bd23cd45 | Blue Swirl | /* XXX: TODO: ignore special values (NaN, infinites, ...) */
|
1422 | 8e703949 | Blue Swirl | return efscmpeq(env, op1, op2);
|
1423 | bd23cd45 | Blue Swirl | } |
1424 | bd23cd45 | Blue Swirl | |
1425 | 8e703949 | Blue Swirl | #define HELPER_SINGLE_SPE_CMP(name) \
|
1426 | 8e703949 | Blue Swirl | uint32_t helper_e##name(CPUPPCState *env, uint32_t op1, uint32_t op2) \ |
1427 | 8e703949 | Blue Swirl | { \ |
1428 | 8e703949 | Blue Swirl | return e##name(env, op1, op2) << 2; \ |
1429 | bd23cd45 | Blue Swirl | } |
1430 | bd23cd45 | Blue Swirl | /* efststlt */
|
1431 | bd23cd45 | Blue Swirl | HELPER_SINGLE_SPE_CMP(fststlt); |
1432 | bd23cd45 | Blue Swirl | /* efststgt */
|
1433 | bd23cd45 | Blue Swirl | HELPER_SINGLE_SPE_CMP(fststgt); |
1434 | bd23cd45 | Blue Swirl | /* efststeq */
|
1435 | bd23cd45 | Blue Swirl | HELPER_SINGLE_SPE_CMP(fststeq); |
1436 | bd23cd45 | Blue Swirl | /* efscmplt */
|
1437 | bd23cd45 | Blue Swirl | HELPER_SINGLE_SPE_CMP(fscmplt); |
1438 | bd23cd45 | Blue Swirl | /* efscmpgt */
|
1439 | bd23cd45 | Blue Swirl | HELPER_SINGLE_SPE_CMP(fscmpgt); |
1440 | bd23cd45 | Blue Swirl | /* efscmpeq */
|
1441 | bd23cd45 | Blue Swirl | HELPER_SINGLE_SPE_CMP(fscmpeq); |
1442 | bd23cd45 | Blue Swirl | |
1443 | bd23cd45 | Blue Swirl | static inline uint32_t evcmp_merge(int t0, int t1) |
1444 | bd23cd45 | Blue Swirl | { |
1445 | bd23cd45 | Blue Swirl | return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1); |
1446 | bd23cd45 | Blue Swirl | } |
1447 | bd23cd45 | Blue Swirl | |
1448 | bd23cd45 | Blue Swirl | #define HELPER_VECTOR_SPE_CMP(name) \
|
1449 | 8e703949 | Blue Swirl | uint32_t helper_ev##name(CPUPPCState *env, uint64_t op1, uint64_t op2) \ |
1450 | bd23cd45 | Blue Swirl | { \ |
1451 | 8e703949 | Blue Swirl | return evcmp_merge(e##name(env, op1 >> 32, op2 >> 32), \ |
1452 | 8e703949 | Blue Swirl | e##name(env, op1, op2)); \ |
1453 | bd23cd45 | Blue Swirl | } |
1454 | bd23cd45 | Blue Swirl | /* evfststlt */
|
1455 | bd23cd45 | Blue Swirl | HELPER_VECTOR_SPE_CMP(fststlt); |
1456 | bd23cd45 | Blue Swirl | /* evfststgt */
|
1457 | bd23cd45 | Blue Swirl | HELPER_VECTOR_SPE_CMP(fststgt); |
1458 | bd23cd45 | Blue Swirl | /* evfststeq */
|
1459 | bd23cd45 | Blue Swirl | HELPER_VECTOR_SPE_CMP(fststeq); |
1460 | bd23cd45 | Blue Swirl | /* evfscmplt */
|
1461 | bd23cd45 | Blue Swirl | HELPER_VECTOR_SPE_CMP(fscmplt); |
1462 | bd23cd45 | Blue Swirl | /* evfscmpgt */
|
1463 | bd23cd45 | Blue Swirl | HELPER_VECTOR_SPE_CMP(fscmpgt); |
1464 | bd23cd45 | Blue Swirl | /* evfscmpeq */
|
1465 | bd23cd45 | Blue Swirl | HELPER_VECTOR_SPE_CMP(fscmpeq); |
1466 | bd23cd45 | Blue Swirl | |
1467 | bd23cd45 | Blue Swirl | /* Double-precision floating-point conversion */
|
1468 | 8e703949 | Blue Swirl | uint64_t helper_efdcfsi(CPUPPCState *env, uint32_t val) |
1469 | bd23cd45 | Blue Swirl | { |
1470 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1471 | bd23cd45 | Blue Swirl | |
1472 | bd23cd45 | Blue Swirl | u.d = int32_to_float64(val, &env->vec_status); |
1473 | bd23cd45 | Blue Swirl | |
1474 | bd23cd45 | Blue Swirl | return u.ll;
|
1475 | bd23cd45 | Blue Swirl | } |
1476 | bd23cd45 | Blue Swirl | |
1477 | 8e703949 | Blue Swirl | uint64_t helper_efdcfsid(CPUPPCState *env, uint64_t val) |
1478 | bd23cd45 | Blue Swirl | { |
1479 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1480 | bd23cd45 | Blue Swirl | |
1481 | bd23cd45 | Blue Swirl | u.d = int64_to_float64(val, &env->vec_status); |
1482 | bd23cd45 | Blue Swirl | |
1483 | bd23cd45 | Blue Swirl | return u.ll;
|
1484 | bd23cd45 | Blue Swirl | } |
1485 | bd23cd45 | Blue Swirl | |
1486 | 8e703949 | Blue Swirl | uint64_t helper_efdcfui(CPUPPCState *env, uint32_t val) |
1487 | bd23cd45 | Blue Swirl | { |
1488 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1489 | bd23cd45 | Blue Swirl | |
1490 | bd23cd45 | Blue Swirl | u.d = uint32_to_float64(val, &env->vec_status); |
1491 | bd23cd45 | Blue Swirl | |
1492 | bd23cd45 | Blue Swirl | return u.ll;
|
1493 | bd23cd45 | Blue Swirl | } |
1494 | bd23cd45 | Blue Swirl | |
1495 | 8e703949 | Blue Swirl | uint64_t helper_efdcfuid(CPUPPCState *env, uint64_t val) |
1496 | bd23cd45 | Blue Swirl | { |
1497 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1498 | bd23cd45 | Blue Swirl | |
1499 | bd23cd45 | Blue Swirl | u.d = uint64_to_float64(val, &env->vec_status); |
1500 | bd23cd45 | Blue Swirl | |
1501 | bd23cd45 | Blue Swirl | return u.ll;
|
1502 | bd23cd45 | Blue Swirl | } |
1503 | bd23cd45 | Blue Swirl | |
1504 | 8e703949 | Blue Swirl | uint32_t helper_efdctsi(CPUPPCState *env, uint64_t val) |
1505 | bd23cd45 | Blue Swirl | { |
1506 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1507 | bd23cd45 | Blue Swirl | |
1508 | bd23cd45 | Blue Swirl | u.ll = val; |
1509 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1510 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(u.d))) {
|
1511 | bd23cd45 | Blue Swirl | return 0; |
1512 | bd23cd45 | Blue Swirl | } |
1513 | bd23cd45 | Blue Swirl | |
1514 | bd23cd45 | Blue Swirl | return float64_to_int32(u.d, &env->vec_status);
|
1515 | bd23cd45 | Blue Swirl | } |
1516 | bd23cd45 | Blue Swirl | |
1517 | 8e703949 | Blue Swirl | uint32_t helper_efdctui(CPUPPCState *env, uint64_t val) |
1518 | bd23cd45 | Blue Swirl | { |
1519 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1520 | bd23cd45 | Blue Swirl | |
1521 | bd23cd45 | Blue Swirl | u.ll = val; |
1522 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1523 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(u.d))) {
|
1524 | bd23cd45 | Blue Swirl | return 0; |
1525 | bd23cd45 | Blue Swirl | } |
1526 | bd23cd45 | Blue Swirl | |
1527 | bd23cd45 | Blue Swirl | return float64_to_uint32(u.d, &env->vec_status);
|
1528 | bd23cd45 | Blue Swirl | } |
1529 | bd23cd45 | Blue Swirl | |
1530 | 8e703949 | Blue Swirl | uint32_t helper_efdctsiz(CPUPPCState *env, uint64_t val) |
1531 | bd23cd45 | Blue Swirl | { |
1532 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1533 | bd23cd45 | Blue Swirl | |
1534 | bd23cd45 | Blue Swirl | u.ll = val; |
1535 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1536 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(u.d))) {
|
1537 | bd23cd45 | Blue Swirl | return 0; |
1538 | bd23cd45 | Blue Swirl | } |
1539 | bd23cd45 | Blue Swirl | |
1540 | bd23cd45 | Blue Swirl | return float64_to_int32_round_to_zero(u.d, &env->vec_status);
|
1541 | bd23cd45 | Blue Swirl | } |
1542 | bd23cd45 | Blue Swirl | |
1543 | 8e703949 | Blue Swirl | uint64_t helper_efdctsidz(CPUPPCState *env, uint64_t val) |
1544 | bd23cd45 | Blue Swirl | { |
1545 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1546 | bd23cd45 | Blue Swirl | |
1547 | bd23cd45 | Blue Swirl | u.ll = val; |
1548 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1549 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(u.d))) {
|
1550 | bd23cd45 | Blue Swirl | return 0; |
1551 | bd23cd45 | Blue Swirl | } |
1552 | bd23cd45 | Blue Swirl | |
1553 | bd23cd45 | Blue Swirl | return float64_to_int64_round_to_zero(u.d, &env->vec_status);
|
1554 | bd23cd45 | Blue Swirl | } |
1555 | bd23cd45 | Blue Swirl | |
1556 | 8e703949 | Blue Swirl | uint32_t helper_efdctuiz(CPUPPCState *env, uint64_t val) |
1557 | bd23cd45 | Blue Swirl | { |
1558 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1559 | bd23cd45 | Blue Swirl | |
1560 | bd23cd45 | Blue Swirl | u.ll = val; |
1561 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1562 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(u.d))) {
|
1563 | bd23cd45 | Blue Swirl | return 0; |
1564 | bd23cd45 | Blue Swirl | } |
1565 | bd23cd45 | Blue Swirl | |
1566 | bd23cd45 | Blue Swirl | return float64_to_uint32_round_to_zero(u.d, &env->vec_status);
|
1567 | bd23cd45 | Blue Swirl | } |
1568 | bd23cd45 | Blue Swirl | |
1569 | 8e703949 | Blue Swirl | uint64_t helper_efdctuidz(CPUPPCState *env, uint64_t val) |
1570 | bd23cd45 | Blue Swirl | { |
1571 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1572 | bd23cd45 | Blue Swirl | |
1573 | bd23cd45 | Blue Swirl | u.ll = val; |
1574 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1575 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(u.d))) {
|
1576 | bd23cd45 | Blue Swirl | return 0; |
1577 | bd23cd45 | Blue Swirl | } |
1578 | bd23cd45 | Blue Swirl | |
1579 | bd23cd45 | Blue Swirl | return float64_to_uint64_round_to_zero(u.d, &env->vec_status);
|
1580 | bd23cd45 | Blue Swirl | } |
1581 | bd23cd45 | Blue Swirl | |
1582 | 8e703949 | Blue Swirl | uint64_t helper_efdcfsf(CPUPPCState *env, uint32_t val) |
1583 | bd23cd45 | Blue Swirl | { |
1584 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1585 | bd23cd45 | Blue Swirl | float64 tmp; |
1586 | bd23cd45 | Blue Swirl | |
1587 | bd23cd45 | Blue Swirl | u.d = int32_to_float64(val, &env->vec_status); |
1588 | bd23cd45 | Blue Swirl | tmp = int64_to_float64(1ULL << 32, &env->vec_status); |
1589 | bd23cd45 | Blue Swirl | u.d = float64_div(u.d, tmp, &env->vec_status); |
1590 | bd23cd45 | Blue Swirl | |
1591 | bd23cd45 | Blue Swirl | return u.ll;
|
1592 | bd23cd45 | Blue Swirl | } |
1593 | bd23cd45 | Blue Swirl | |
1594 | 8e703949 | Blue Swirl | uint64_t helper_efdcfuf(CPUPPCState *env, uint32_t val) |
1595 | bd23cd45 | Blue Swirl | { |
1596 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1597 | bd23cd45 | Blue Swirl | float64 tmp; |
1598 | bd23cd45 | Blue Swirl | |
1599 | bd23cd45 | Blue Swirl | u.d = uint32_to_float64(val, &env->vec_status); |
1600 | bd23cd45 | Blue Swirl | tmp = int64_to_float64(1ULL << 32, &env->vec_status); |
1601 | bd23cd45 | Blue Swirl | u.d = float64_div(u.d, tmp, &env->vec_status); |
1602 | bd23cd45 | Blue Swirl | |
1603 | bd23cd45 | Blue Swirl | return u.ll;
|
1604 | bd23cd45 | Blue Swirl | } |
1605 | bd23cd45 | Blue Swirl | |
1606 | 8e703949 | Blue Swirl | uint32_t helper_efdctsf(CPUPPCState *env, uint64_t val) |
1607 | bd23cd45 | Blue Swirl | { |
1608 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1609 | bd23cd45 | Blue Swirl | float64 tmp; |
1610 | bd23cd45 | Blue Swirl | |
1611 | bd23cd45 | Blue Swirl | u.ll = val; |
1612 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1613 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(u.d))) {
|
1614 | bd23cd45 | Blue Swirl | return 0; |
1615 | bd23cd45 | Blue Swirl | } |
1616 | bd23cd45 | Blue Swirl | tmp = uint64_to_float64(1ULL << 32, &env->vec_status); |
1617 | bd23cd45 | Blue Swirl | u.d = float64_mul(u.d, tmp, &env->vec_status); |
1618 | bd23cd45 | Blue Swirl | |
1619 | bd23cd45 | Blue Swirl | return float64_to_int32(u.d, &env->vec_status);
|
1620 | bd23cd45 | Blue Swirl | } |
1621 | bd23cd45 | Blue Swirl | |
1622 | 8e703949 | Blue Swirl | uint32_t helper_efdctuf(CPUPPCState *env, uint64_t val) |
1623 | bd23cd45 | Blue Swirl | { |
1624 | bd23cd45 | Blue Swirl | CPU_DoubleU u; |
1625 | bd23cd45 | Blue Swirl | float64 tmp; |
1626 | bd23cd45 | Blue Swirl | |
1627 | bd23cd45 | Blue Swirl | u.ll = val; |
1628 | bd23cd45 | Blue Swirl | /* NaN are not treated the same way IEEE 754 does */
|
1629 | bd23cd45 | Blue Swirl | if (unlikely(float64_is_any_nan(u.d))) {
|
1630 | bd23cd45 | Blue Swirl | return 0; |
1631 | bd23cd45 | Blue Swirl | } |
1632 | bd23cd45 | Blue Swirl | tmp = uint64_to_float64(1ULL << 32, &env->vec_status); |
1633 | bd23cd45 | Blue Swirl | u.d = float64_mul(u.d, tmp, &env->vec_status); |
1634 | bd23cd45 | Blue Swirl | |
1635 | bd23cd45 | Blue Swirl | return float64_to_uint32(u.d, &env->vec_status);
|
1636 | bd23cd45 | Blue Swirl | } |
1637 | bd23cd45 | Blue Swirl | |
1638 | 8e703949 | Blue Swirl | uint32_t helper_efscfd(CPUPPCState *env, uint64_t val) |
1639 | bd23cd45 | Blue Swirl | { |
1640 | bd23cd45 | Blue Swirl | CPU_DoubleU u1; |
1641 | bd23cd45 | Blue Swirl | CPU_FloatU u2; |
1642 | bd23cd45 | Blue Swirl | |
1643 | bd23cd45 | Blue Swirl | u1.ll = val; |
1644 | bd23cd45 | Blue Swirl | u2.f = float64_to_float32(u1.d, &env->vec_status); |
1645 | bd23cd45 | Blue Swirl | |
1646 | bd23cd45 | Blue Swirl | return u2.l;
|
1647 | bd23cd45 | Blue Swirl | } |
1648 | bd23cd45 | Blue Swirl | |
1649 | 8e703949 | Blue Swirl | uint64_t helper_efdcfs(CPUPPCState *env, uint32_t val) |
1650 | bd23cd45 | Blue Swirl | { |
1651 | bd23cd45 | Blue Swirl | CPU_DoubleU u2; |
1652 | bd23cd45 | Blue Swirl | CPU_FloatU u1; |
1653 | bd23cd45 | Blue Swirl | |
1654 | bd23cd45 | Blue Swirl | u1.l = val; |
1655 | bd23cd45 | Blue Swirl | u2.d = float32_to_float64(u1.f, &env->vec_status); |
1656 | bd23cd45 | Blue Swirl | |
1657 | bd23cd45 | Blue Swirl | return u2.ll;
|
1658 | bd23cd45 | Blue Swirl | } |
1659 | bd23cd45 | Blue Swirl | |
1660 | bd23cd45 | Blue Swirl | /* Double precision fixed-point arithmetic */
|
1661 | 8e703949 | Blue Swirl | uint64_t helper_efdadd(CPUPPCState *env, uint64_t op1, uint64_t op2) |
1662 | bd23cd45 | Blue Swirl | { |
1663 | bd23cd45 | Blue Swirl | CPU_DoubleU u1, u2; |
1664 | bd23cd45 | Blue Swirl | |
1665 | bd23cd45 | Blue Swirl | u1.ll = op1; |
1666 | bd23cd45 | Blue Swirl | u2.ll = op2; |
1667 | bd23cd45 | Blue Swirl | u1.d = float64_add(u1.d, u2.d, &env->vec_status); |
1668 | bd23cd45 | Blue Swirl | return u1.ll;
|
1669 | bd23cd45 | Blue Swirl | } |
1670 | bd23cd45 | Blue Swirl | |
1671 | 8e703949 | Blue Swirl | uint64_t helper_efdsub(CPUPPCState *env, uint64_t op1, uint64_t op2) |
1672 | bd23cd45 | Blue Swirl | { |
1673 | bd23cd45 | Blue Swirl | CPU_DoubleU u1, u2; |
1674 | bd23cd45 | Blue Swirl | |
1675 | bd23cd45 | Blue Swirl | u1.ll = op1; |
1676 | bd23cd45 | Blue Swirl | u2.ll = op2; |
1677 | bd23cd45 | Blue Swirl | u1.d = float64_sub(u1.d, u2.d, &env->vec_status); |
1678 | bd23cd45 | Blue Swirl | return u1.ll;
|
1679 | bd23cd45 | Blue Swirl | } |
1680 | bd23cd45 | Blue Swirl | |
1681 | 8e703949 | Blue Swirl | uint64_t helper_efdmul(CPUPPCState *env, uint64_t op1, uint64_t op2) |
1682 | bd23cd45 | Blue Swirl | { |
1683 | bd23cd45 | Blue Swirl | CPU_DoubleU u1, u2; |
1684 | bd23cd45 | Blue Swirl | |
1685 | bd23cd45 | Blue Swirl | u1.ll = op1; |
1686 | bd23cd45 | Blue Swirl | u2.ll = op2; |
1687 | bd23cd45 | Blue Swirl | u1.d = float64_mul(u1.d, u2.d, &env->vec_status); |
1688 | bd23cd45 | Blue Swirl | return u1.ll;
|
1689 | bd23cd45 | Blue Swirl | } |
1690 | bd23cd45 | Blue Swirl | |
1691 | 8e703949 | Blue Swirl | uint64_t helper_efddiv(CPUPPCState *env, uint64_t op1, uint64_t op2) |
1692 | bd23cd45 | Blue Swirl | { |
1693 | bd23cd45 | Blue Swirl | CPU_DoubleU u1, u2; |
1694 | bd23cd45 | Blue Swirl | |
1695 | bd23cd45 | Blue Swirl | u1.ll = op1; |
1696 | bd23cd45 | Blue Swirl | u2.ll = op2; |
1697 | bd23cd45 | Blue Swirl | u1.d = float64_div(u1.d, u2.d, &env->vec_status); |
1698 | bd23cd45 | Blue Swirl | return u1.ll;
|
1699 | bd23cd45 | Blue Swirl | } |
1700 | bd23cd45 | Blue Swirl | |
1701 | bd23cd45 | Blue Swirl | /* Double precision floating point helpers */
|
1702 | 8e703949 | Blue Swirl | uint32_t helper_efdtstlt(CPUPPCState *env, uint64_t op1, uint64_t op2) |
1703 | bd23cd45 | Blue Swirl | { |
1704 | bd23cd45 | Blue Swirl | CPU_DoubleU u1, u2; |
1705 | bd23cd45 | Blue Swirl | |
1706 | bd23cd45 | Blue Swirl | u1.ll = op1; |
1707 | bd23cd45 | Blue Swirl | u2.ll = op2; |
1708 | bd23cd45 | Blue Swirl | return float64_lt(u1.d, u2.d, &env->vec_status) ? 4 : 0; |
1709 | bd23cd45 | Blue Swirl | } |
1710 | bd23cd45 | Blue Swirl | |
1711 | 8e703949 | Blue Swirl | uint32_t helper_efdtstgt(CPUPPCState *env, uint64_t op1, uint64_t op2) |
1712 | bd23cd45 | Blue Swirl | { |
1713 | bd23cd45 | Blue Swirl | CPU_DoubleU u1, u2; |
1714 | bd23cd45 | Blue Swirl | |
1715 | bd23cd45 | Blue Swirl | u1.ll = op1; |
1716 | bd23cd45 | Blue Swirl | u2.ll = op2; |
1717 | bd23cd45 | Blue Swirl | return float64_le(u1.d, u2.d, &env->vec_status) ? 0 : 4; |
1718 | bd23cd45 | Blue Swirl | } |
1719 | bd23cd45 | Blue Swirl | |
1720 | 8e703949 | Blue Swirl | uint32_t helper_efdtsteq(CPUPPCState *env, uint64_t op1, uint64_t op2) |
1721 | bd23cd45 | Blue Swirl | { |
1722 | bd23cd45 | Blue Swirl | CPU_DoubleU u1, u2; |
1723 | bd23cd45 | Blue Swirl | |
1724 | bd23cd45 | Blue Swirl | u1.ll = op1; |
1725 | bd23cd45 | Blue Swirl | u2.ll = op2; |
1726 | bd23cd45 | Blue Swirl | return float64_eq_quiet(u1.d, u2.d, &env->vec_status) ? 4 : 0; |
1727 | bd23cd45 | Blue Swirl | } |
1728 | bd23cd45 | Blue Swirl | |
1729 | 8e703949 | Blue Swirl | uint32_t helper_efdcmplt(CPUPPCState *env, uint64_t op1, uint64_t op2) |
1730 | bd23cd45 | Blue Swirl | { |
1731 | bd23cd45 | Blue Swirl | /* XXX: TODO: test special values (NaN, infinites, ...) */
|
1732 | 8e703949 | Blue Swirl | return helper_efdtstlt(env, op1, op2);
|
1733 | bd23cd45 | Blue Swirl | } |
1734 | bd23cd45 | Blue Swirl | |
1735 | 8e703949 | Blue Swirl | uint32_t helper_efdcmpgt(CPUPPCState *env, uint64_t op1, uint64_t op2) |
1736 | bd23cd45 | Blue Swirl | { |
1737 | bd23cd45 | Blue Swirl | /* XXX: TODO: test special values (NaN, infinites, ...) */
|
1738 | 8e703949 | Blue Swirl | return helper_efdtstgt(env, op1, op2);
|
1739 | bd23cd45 | Blue Swirl | } |
1740 | bd23cd45 | Blue Swirl | |
1741 | 8e703949 | Blue Swirl | uint32_t helper_efdcmpeq(CPUPPCState *env, uint64_t op1, uint64_t op2) |
1742 | bd23cd45 | Blue Swirl | { |
1743 | bd23cd45 | Blue Swirl | /* XXX: TODO: test special values (NaN, infinites, ...) */
|
1744 | 8e703949 | Blue Swirl | return helper_efdtsteq(env, op1, op2);
|
1745 | bd23cd45 | Blue Swirl | } |