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