master
c 3,314 lines 111 KB
Raw
1 /*
2 * x86 FPU, MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4/PNI helpers
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "qemu/osdep.h"
21 #include <math.h>
22 #include "cpu.h"
23 #include "tcg-cpu.h"
24 #include "exec/cputlb.h"
25 #include "accel/tcg/cpu-ldst.h"
26 #include "exec/helper-proto.h"
27 #include "fpu/softfloat.h"
28 #include "fpu/softfloat-macros.h"
29 #include "helper-tcg.h"
30 #include "access.h"
31
32 /* float macros */
33 #define FT0 (env->ft0)
34 #define ST0 (env->fpregs[env->fpstt].d)
35 #define ST(n) (env->fpregs[(env->fpstt + (n)) & 7].d)
36 #define ST1 ST(1)
37
38 #define FPU_RC_SHIFT 10
39 #define FPU_RC_MASK (3 << FPU_RC_SHIFT)
40 #define FPU_RC_NEAR 0x000
41 #define FPU_RC_DOWN 0x400
42 #define FPU_RC_UP 0x800
43 #define FPU_RC_CHOP 0xc00
44
45 #define MAXTAN 9223372036854775808.0
46
47 /* the following deal with x86 long double-precision numbers */
48 #define MAXEXPD 0x7fff
49 #define EXPBIAS 16383
50 #define EXPD(fp) (fp.l.upper & 0x7fff)
51 #define SIGND(fp) ((fp.l.upper) & 0x8000)
52 #define MANTD(fp) (fp.l.lower)
53 #define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
54
55 #define FPUS_IE (1 << 0)
56 #define FPUS_DE (1 << 1)
57 #define FPUS_ZE (1 << 2)
58 #define FPUS_OE (1 << 3)
59 #define FPUS_UE (1 << 4)
60 #define FPUS_PE (1 << 5)
61 #define FPUS_SF (1 << 6)
62 #define FPUS_SE (1 << 7)
63 #define FPUS_B (1 << 15)
64
65 #define FPUC_EM 0x3f
66
67 #define floatx80_lg2 make_floatx80(0x3ffd, 0x9a209a84fbcff799LL)
68 #define floatx80_lg2_d make_floatx80(0x3ffd, 0x9a209a84fbcff798LL)
69 #define floatx80_l2e make_floatx80(0x3fff, 0xb8aa3b295c17f0bcLL)
70 #define floatx80_l2e_d make_floatx80(0x3fff, 0xb8aa3b295c17f0bbLL)
71 #define floatx80_l2t make_floatx80(0x4000, 0xd49a784bcd1b8afeLL)
72 #define floatx80_l2t_u make_floatx80(0x4000, 0xd49a784bcd1b8affLL)
73 #define floatx80_ln2_d make_floatx80(0x3ffe, 0xb17217f7d1cf79abLL)
74 #define floatx80_pi_d make_floatx80(0x4000, 0xc90fdaa22168c234LL)
75
76 static inline void fpush(CPUX86State *env)
77 {
78 env->fpstt = (env->fpstt - 1) & 7;
79 env->fptags[env->fpstt] = 0; /* validate stack entry */
80 }
81
82 static inline void fpop(CPUX86State *env)
83 {
84 env->fptags[env->fpstt] = 1; /* invalidate stack entry */
85 env->fpstt = (env->fpstt + 1) & 7;
86 }
87
88 static floatx80 do_fldt(X86Access *ac, target_ulong ptr)
89 {
90 CPU_LDoubleU temp;
91
92 temp.l.lower = access_ldq(ac, ptr);
93 temp.l.upper = access_ldw(ac, ptr + 8);
94 return temp.d;
95 }
96
97 static void do_fstt(X86Access *ac, target_ulong ptr, floatx80 f)
98 {
99 CPU_LDoubleU temp;
100
101 temp.d = f;
102 access_stq(ac, ptr, temp.l.lower);
103 access_stw(ac, ptr + 8, temp.l.upper);
104 }
105
106 /* x87 FPU helpers */
107
108 static inline double floatx80_to_double(CPUX86State *env, floatx80 a)
109 {
110 union {
111 float64 f64;
112 double d;
113 } u;
114
115 u.f64 = floatx80_to_float64(a, &env->fp_status);
116 return u.d;
117 }
118
119 static inline floatx80 double_to_floatx80(CPUX86State *env, double a)
120 {
121 union {
122 float64 f64;
123 double d;
124 } u;
125
126 u.d = a;
127 return float64_to_floatx80(u.f64, &env->fp_status);
128 }
129
130 static void fpu_set_exception(CPUX86State *env, int mask)
131 {
132 env->fpus |= mask;
133 if (env->fpus & (~env->fpuc & FPUC_EM)) {
134 env->fpus |= FPUS_SE | FPUS_B;
135 }
136 }
137
138 void cpu_init_fp_statuses(CPUX86State *env)
139 {
140 /*
141 * Initialise the non-runtime-varying fields of the various
142 * float_status words to x86 behaviour. This must be called at
143 * CPU reset because the float_status words are in the
144 * "zeroed on reset" portion of the CPU state struct.
145 * Fields in float_status that vary under guest control are set
146 * via the codepath for setting that register, eg cpu_set_fpuc().
147 */
148 /*
149 * Use x87 NaN propagation rules:
150 * SNaN + QNaN => return the QNaN
151 * two SNaNs => return the one with the larger significand, silenced
152 * two QNaNs => return the one with the larger significand
153 * SNaN and a non-NaN => return the SNaN, silenced
154 * QNaN and a non-NaN => return the QNaN
155 *
156 * If we get down to comparing significands and they are the same,
157 * return the NaN with the positive sign bit (if any).
158 */
159 set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
160 /*
161 * TODO: These are incorrect: the x86 Software Developer's Manual vol 1
162 * section 4.8.3.5 "Operating on SNaNs and QNaNs" says that the
163 * "larger significand" behaviour is only used for x87 FPU operations.
164 * For SSE the required behaviour is to always return the first NaN,
165 * which is float_2nan_prop_ab.
166 *
167 * mmx_status is used only for the AMD 3DNow! instructions, which
168 * are documented in the "3DNow! Technology Manual" as not supporting
169 * NaNs or infinities as inputs. The result of passing two NaNs is
170 * documented as "undefined", so we can do what we choose.
171 * (Strictly there is some behaviour we don't implement correctly
172 * for these "unsupported" NaN and Inf values, like "NaN * 0 == 0".)
173 */
174 set_float_2nan_prop_rule(float_2nan_prop_x87, &env->mmx_status);
175 set_float_2nan_prop_rule(float_2nan_prop_x87, &env->sse_status);
176 /*
177 * Only SSE has multiply-add instructions. In the SDM Section 14.5.2
178 * "Fused-Multiply-ADD (FMA) Numeric Behavior" the NaN handling is
179 * specified -- for 0 * inf + NaN the input NaN is selected, and if
180 * there are multiple input NaNs they are selected in the order a, b, c.
181 * We also do not raise Invalid for the 0 * inf + (Q)NaN case.
182 */
183 set_float_infzeronan_rule(float_infzeronan_dnan_never |
184 float_infzeronan_suppress_invalid,
185 &env->sse_status);
186 set_float_3nan_prop_rule(float_3nan_prop_abc, &env->sse_status);
187 /* Default NaN: sign bit set, most significant frac bit set */
188 set_float_default_nan_pattern(0b11000000, &env->fp_status);
189 set_float_default_nan_pattern(0b11000000, &env->mmx_status);
190 set_float_default_nan_pattern(0b11000000, &env->sse_status);
191 /*
192 * x86 does flush-to-zero detection after rounding (the SDM
193 * section 10.2.3.3 on the FTZ bit of MXCSR says that we flush
194 * when we detect underflow, which x86 does after rounding).
195 */
196 set_float_ftz_detection(float_ftz_after_rounding, &env->fp_status);
197 set_float_ftz_detection(float_ftz_after_rounding, &env->mmx_status);
198 set_float_ftz_detection(float_ftz_after_rounding, &env->sse_status);
199 }
200
201 static inline int save_exception_flags(CPUX86State *env)
202 {
203 int old_flags = get_float_exception_flags(&env->fp_status);
204 set_float_exception_flags(0, &env->fp_status);
205 return old_flags;
206 }
207
208 static void merge_exception_flags(CPUX86State *env, int old_flags)
209 {
210 int new_flags = get_float_exception_flags(&env->fp_status);
211 float_raise(old_flags, &env->fp_status);
212 fpu_set_exception(env,
213 ((new_flags & float_flag_invalid ? FPUS_IE : 0) |
214 (new_flags & float_flag_divbyzero ? FPUS_ZE : 0) |
215 (new_flags & float_flag_overflow ? FPUS_OE : 0) |
216 (new_flags & float_flag_underflow ? FPUS_UE : 0) |
217 (new_flags & float_flag_inexact ? FPUS_PE : 0) |
218 (new_flags & float_flag_input_denormal_used ? FPUS_DE : 0)));
219 }
220
221 static inline floatx80 helper_fdiv(CPUX86State *env, floatx80 a, floatx80 b)
222 {
223 int old_flags = save_exception_flags(env);
224 floatx80 ret = floatx80_div(a, b, &env->fp_status);
225 merge_exception_flags(env, old_flags);
226 return ret;
227 }
228
229 static void fpu_raise_exception(CPUX86State *env, uintptr_t retaddr)
230 {
231 if (env->cr[0] & CR0_NE_MASK) {
232 raise_exception_ra(env, EXCP10_COPR, retaddr);
233 }
234 #if !defined(CONFIG_USER_ONLY)
235 else {
236 fpu_check_raise_ferr_irq(env);
237 }
238 #endif
239 }
240
241 void helper_flds_FT0(CPUX86State *env, uint32_t val)
242 {
243 int old_flags = save_exception_flags(env);
244 union {
245 float32 f;
246 uint32_t i;
247 } u;
248
249 u.i = val;
250 FT0 = float32_to_floatx80(u.f, &env->fp_status);
251 merge_exception_flags(env, old_flags);
252 }
253
254 void helper_fldl_FT0(CPUX86State *env, uint64_t val)
255 {
256 int old_flags = save_exception_flags(env);
257 union {
258 float64 f;
259 uint64_t i;
260 } u;
261
262 u.i = val;
263 FT0 = float64_to_floatx80(u.f, &env->fp_status);
264 merge_exception_flags(env, old_flags);
265 }
266
267 void helper_fildl_FT0(CPUX86State *env, int32_t val)
268 {
269 FT0 = int32_to_floatx80(val, &env->fp_status);
270 }
271
272 void helper_flds_ST0(CPUX86State *env, uint32_t val)
273 {
274 int old_flags = save_exception_flags(env);
275 int new_fpstt;
276 union {
277 float32 f;
278 uint32_t i;
279 } u;
280
281 new_fpstt = (env->fpstt - 1) & 7;
282 u.i = val;
283 env->fpregs[new_fpstt].d = float32_to_floatx80(u.f, &env->fp_status);
284 env->fpstt = new_fpstt;
285 env->fptags[new_fpstt] = 0; /* validate stack entry */
286 merge_exception_flags(env, old_flags);
287 }
288
289 void helper_fldl_ST0(CPUX86State *env, uint64_t val)
290 {
291 int old_flags = save_exception_flags(env);
292 int new_fpstt;
293 union {
294 float64 f;
295 uint64_t i;
296 } u;
297
298 new_fpstt = (env->fpstt - 1) & 7;
299 u.i = val;
300 env->fpregs[new_fpstt].d = float64_to_floatx80(u.f, &env->fp_status);
301 env->fpstt = new_fpstt;
302 env->fptags[new_fpstt] = 0; /* validate stack entry */
303 merge_exception_flags(env, old_flags);
304 }
305
306 static FloatX80RoundPrec tmp_maximise_precision(float_status *st)
307 {
308 FloatX80RoundPrec old = get_floatx80_rounding_precision(st);
309 set_floatx80_rounding_precision(floatx80_precision_x, st);
310 return old;
311 }
312
313 void helper_fildl_ST0(CPUX86State *env, int32_t val)
314 {
315 int new_fpstt;
316 FloatX80RoundPrec old = tmp_maximise_precision(&env->fp_status);
317
318 new_fpstt = (env->fpstt - 1) & 7;
319 env->fpregs[new_fpstt].d = int32_to_floatx80(val, &env->fp_status);
320 env->fpstt = new_fpstt;
321 env->fptags[new_fpstt] = 0; /* validate stack entry */
322
323 set_floatx80_rounding_precision(old, &env->fp_status);
324 }
325
326 void helper_fildll_ST0(CPUX86State *env, int64_t val)
327 {
328 int new_fpstt;
329 FloatX80RoundPrec old = tmp_maximise_precision(&env->fp_status);
330
331 new_fpstt = (env->fpstt - 1) & 7;
332 env->fpregs[new_fpstt].d = int64_to_floatx80(val, &env->fp_status);
333 env->fpstt = new_fpstt;
334 env->fptags[new_fpstt] = 0; /* validate stack entry */
335
336 set_floatx80_rounding_precision(old, &env->fp_status);
337 }
338
339 uint32_t helper_fsts_ST0(CPUX86State *env)
340 {
341 int old_flags = save_exception_flags(env);
342 union {
343 float32 f;
344 uint32_t i;
345 } u;
346
347 u.f = floatx80_to_float32(ST0, &env->fp_status);
348 merge_exception_flags(env, old_flags);
349 return u.i;
350 }
351
352 uint64_t helper_fstl_ST0(CPUX86State *env)
353 {
354 int old_flags = save_exception_flags(env);
355 union {
356 float64 f;
357 uint64_t i;
358 } u;
359
360 u.f = floatx80_to_float64(ST0, &env->fp_status);
361 merge_exception_flags(env, old_flags);
362 return u.i;
363 }
364
365 int32_t helper_fist_ST0(CPUX86State *env)
366 {
367 int old_flags = save_exception_flags(env);
368 int32_t val;
369
370 val = floatx80_to_int32(ST0, &env->fp_status);
371 if (val != (int16_t)val) {
372 set_float_exception_flags(float_flag_invalid, &env->fp_status);
373 val = -32768;
374 }
375 merge_exception_flags(env, old_flags);
376 return val;
377 }
378
379 int32_t helper_fistl_ST0(CPUX86State *env)
380 {
381 int old_flags = save_exception_flags(env);
382 int32_t val;
383
384 val = floatx80_to_int32(ST0, &env->fp_status);
385 if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) {
386 val = 0x80000000;
387 }
388 merge_exception_flags(env, old_flags);
389 return val;
390 }
391
392 int64_t helper_fistll_ST0(CPUX86State *env)
393 {
394 int old_flags = save_exception_flags(env);
395 int64_t val;
396
397 val = floatx80_to_int64(ST0, &env->fp_status);
398 if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) {
399 val = 0x8000000000000000ULL;
400 }
401 merge_exception_flags(env, old_flags);
402 return val;
403 }
404
405 int32_t helper_fistt_ST0(CPUX86State *env)
406 {
407 int old_flags = save_exception_flags(env);
408 int32_t val;
409
410 val = floatx80_to_int32_round_to_zero(ST0, &env->fp_status);
411 if (val != (int16_t)val) {
412 set_float_exception_flags(float_flag_invalid, &env->fp_status);
413 val = -32768;
414 }
415 merge_exception_flags(env, old_flags);
416 return val;
417 }
418
419 int32_t helper_fisttl_ST0(CPUX86State *env)
420 {
421 int old_flags = save_exception_flags(env);
422 int32_t val;
423
424 val = floatx80_to_int32_round_to_zero(ST0, &env->fp_status);
425 if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) {
426 val = 0x80000000;
427 }
428 merge_exception_flags(env, old_flags);
429 return val;
430 }
431
432 int64_t helper_fisttll_ST0(CPUX86State *env)
433 {
434 int old_flags = save_exception_flags(env);
435 int64_t val;
436
437 val = floatx80_to_int64_round_to_zero(ST0, &env->fp_status);
438 if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) {
439 val = 0x8000000000000000ULL;
440 }
441 merge_exception_flags(env, old_flags);
442 return val;
443 }
444
445 void helper_fldt_ST0(CPUX86State *env, target_ulong ptr)
446 {
447 int new_fpstt;
448 X86Access ac;
449
450 access_prepare(&ac, env, ptr, 10, MMU_DATA_LOAD, GETPC());
451
452 new_fpstt = (env->fpstt - 1) & 7;
453 env->fpregs[new_fpstt].d = do_fldt(&ac, ptr);
454 env->fpstt = new_fpstt;
455 env->fptags[new_fpstt] = 0; /* validate stack entry */
456 }
457
458 void helper_fstt_ST0(CPUX86State *env, target_ulong ptr)
459 {
460 X86Access ac;
461
462 access_prepare(&ac, env, ptr, 10, MMU_DATA_STORE, GETPC());
463 do_fstt(&ac, ptr, ST0);
464 }
465
466 void helper_fpush(CPUX86State *env)
467 {
468 fpush(env);
469 }
470
471 void helper_fpop(CPUX86State *env)
472 {
473 fpop(env);
474 }
475
476 void helper_fdecstp(CPUX86State *env)
477 {
478 env->fpstt = (env->fpstt - 1) & 7;
479 env->fpus &= ~0x4700;
480 }
481
482 void helper_fincstp(CPUX86State *env)
483 {
484 env->fpstt = (env->fpstt + 1) & 7;
485 env->fpus &= ~0x4700;
486 }
487
488 /* FPU move */
489
490 void helper_ffree_STN(CPUX86State *env, int st_index)
491 {
492 env->fptags[(env->fpstt + st_index) & 7] = 1;
493 }
494
495 void helper_fmov_ST0_FT0(CPUX86State *env)
496 {
497 ST0 = FT0;
498 }
499
500 void helper_fmov_FT0_STN(CPUX86State *env, int st_index)
501 {
502 FT0 = ST(st_index);
503 }
504
505 void helper_fmov_ST0_STN(CPUX86State *env, int st_index)
506 {
507 ST0 = ST(st_index);
508 }
509
510 void helper_fmov_STN_ST0(CPUX86State *env, int st_index)
511 {
512 ST(st_index) = ST0;
513 }
514
515 void helper_fxchg_ST0_STN(CPUX86State *env, int st_index)
516 {
517 floatx80 tmp;
518
519 tmp = ST(st_index);
520 ST(st_index) = ST0;
521 ST0 = tmp;
522 }
523
524 /* FPU operations */
525
526 static const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500};
527
528 void helper_fcom_ST0_FT0(CPUX86State *env)
529 {
530 int old_flags = save_exception_flags(env);
531 FloatRelation ret;
532
533 ret = floatx80_compare(ST0, FT0, &env->fp_status);
534 env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
535 merge_exception_flags(env, old_flags);
536 }
537
538 void helper_fucom_ST0_FT0(CPUX86State *env)
539 {
540 int old_flags = save_exception_flags(env);
541 FloatRelation ret;
542
543 ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
544 env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
545 merge_exception_flags(env, old_flags);
546 }
547
548 static const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C};
549
550 void helper_fcomi_ST0_FT0(CPUX86State *env)
551 {
552 int old_flags = save_exception_flags(env);
553 FloatRelation ret;
554
555 ret = floatx80_compare(ST0, FT0, &env->fp_status);
556 /* OF, SF, and AF are unconditionally cleared to 0 */
557 CC_SRC = fcomi_ccval[ret + 1];
558 CC_OP = CC_OP_EFLAGS;
559 merge_exception_flags(env, old_flags);
560 }
561
562 void helper_fucomi_ST0_FT0(CPUX86State *env)
563 {
564 int old_flags = save_exception_flags(env);
565 FloatRelation ret;
566
567 ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
568 /* OF, SF, and AF are unconditionally cleared to 0 */
569 CC_SRC = fcomi_ccval[ret + 1];
570 CC_OP = CC_OP_EFLAGS;
571 merge_exception_flags(env, old_flags);
572 }
573
574 void helper_fadd_ST0_FT0(CPUX86State *env)
575 {
576 int old_flags = save_exception_flags(env);
577 ST0 = floatx80_add(ST0, FT0, &env->fp_status);
578 merge_exception_flags(env, old_flags);
579 }
580
581 void helper_fmul_ST0_FT0(CPUX86State *env)
582 {
583 int old_flags = save_exception_flags(env);
584 ST0 = floatx80_mul(ST0, FT0, &env->fp_status);
585 merge_exception_flags(env, old_flags);
586 }
587
588 void helper_fsub_ST0_FT0(CPUX86State *env)
589 {
590 int old_flags = save_exception_flags(env);
591 ST0 = floatx80_sub(ST0, FT0, &env->fp_status);
592 merge_exception_flags(env, old_flags);
593 }
594
595 void helper_fsubr_ST0_FT0(CPUX86State *env)
596 {
597 int old_flags = save_exception_flags(env);
598 ST0 = floatx80_sub(FT0, ST0, &env->fp_status);
599 merge_exception_flags(env, old_flags);
600 }
601
602 void helper_fdiv_ST0_FT0(CPUX86State *env)
603 {
604 ST0 = helper_fdiv(env, ST0, FT0);
605 }
606
607 void helper_fdivr_ST0_FT0(CPUX86State *env)
608 {
609 ST0 = helper_fdiv(env, FT0, ST0);
610 }
611
612 /* fp operations between STN and ST0 */
613
614 void helper_fadd_STN_ST0(CPUX86State *env, int st_index)
615 {
616 int old_flags = save_exception_flags(env);
617 ST(st_index) = floatx80_add(ST(st_index), ST0, &env->fp_status);
618 merge_exception_flags(env, old_flags);
619 }
620
621 void helper_fmul_STN_ST0(CPUX86State *env, int st_index)
622 {
623 int old_flags = save_exception_flags(env);
624 ST(st_index) = floatx80_mul(ST(st_index), ST0, &env->fp_status);
625 merge_exception_flags(env, old_flags);
626 }
627
628 void helper_fsub_STN_ST0(CPUX86State *env, int st_index)
629 {
630 int old_flags = save_exception_flags(env);
631 ST(st_index) = floatx80_sub(ST(st_index), ST0, &env->fp_status);
632 merge_exception_flags(env, old_flags);
633 }
634
635 void helper_fsubr_STN_ST0(CPUX86State *env, int st_index)
636 {
637 int old_flags = save_exception_flags(env);
638 ST(st_index) = floatx80_sub(ST0, ST(st_index), &env->fp_status);
639 merge_exception_flags(env, old_flags);
640 }
641
642 void helper_fdiv_STN_ST0(CPUX86State *env, int st_index)
643 {
644 floatx80 *p;
645
646 p = &ST(st_index);
647 *p = helper_fdiv(env, *p, ST0);
648 }
649
650 void helper_fdivr_STN_ST0(CPUX86State *env, int st_index)
651 {
652 floatx80 *p;
653
654 p = &ST(st_index);
655 *p = helper_fdiv(env, ST0, *p);
656 }
657
658 /* misc FPU operations */
659 void helper_fchs_ST0(CPUX86State *env)
660 {
661 ST0 = floatx80_chs(ST0);
662 }
663
664 void helper_fabs_ST0(CPUX86State *env)
665 {
666 ST0 = floatx80_abs(ST0);
667 }
668
669 void helper_fld1_ST0(CPUX86State *env)
670 {
671 ST0 = floatx80_one;
672 }
673
674 void helper_fldl2t_ST0(CPUX86State *env)
675 {
676 switch (env->fpuc & FPU_RC_MASK) {
677 case FPU_RC_UP:
678 ST0 = floatx80_l2t_u;
679 break;
680 default:
681 ST0 = floatx80_l2t;
682 break;
683 }
684 }
685
686 void helper_fldl2e_ST0(CPUX86State *env)
687 {
688 switch (env->fpuc & FPU_RC_MASK) {
689 case FPU_RC_DOWN:
690 case FPU_RC_CHOP:
691 ST0 = floatx80_l2e_d;
692 break;
693 default:
694 ST0 = floatx80_l2e;
695 break;
696 }
697 }
698
699 void helper_fldpi_ST0(CPUX86State *env)
700 {
701 switch (env->fpuc & FPU_RC_MASK) {
702 case FPU_RC_DOWN:
703 case FPU_RC_CHOP:
704 ST0 = floatx80_pi_d;
705 break;
706 default:
707 ST0 = floatx80_pi;
708 break;
709 }
710 }
711
712 void helper_fldlg2_ST0(CPUX86State *env)
713 {
714 switch (env->fpuc & FPU_RC_MASK) {
715 case FPU_RC_DOWN:
716 case FPU_RC_CHOP:
717 ST0 = floatx80_lg2_d;
718 break;
719 default:
720 ST0 = floatx80_lg2;
721 break;
722 }
723 }
724
725 void helper_fldln2_ST0(CPUX86State *env)
726 {
727 switch (env->fpuc & FPU_RC_MASK) {
728 case FPU_RC_DOWN:
729 case FPU_RC_CHOP:
730 ST0 = floatx80_ln2_d;
731 break;
732 default:
733 ST0 = floatx80_ln2;
734 break;
735 }
736 }
737
738 void helper_fldz_ST0(CPUX86State *env)
739 {
740 ST0 = floatx80_zero;
741 }
742
743 void helper_fldz_FT0(CPUX86State *env)
744 {
745 FT0 = floatx80_zero;
746 }
747
748 uint32_t helper_fnstsw(CPUX86State *env)
749 {
750 return (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
751 }
752
753 uint32_t helper_fnstcw(CPUX86State *env)
754 {
755 return env->fpuc;
756 }
757
758 static void set_x86_rounding_mode(unsigned mode, float_status *status)
759 {
760 static FloatRoundMode x86_round_mode[4] = {
761 float_round_nearest_even,
762 float_round_down,
763 float_round_up,
764 float_round_to_zero
765 };
766 assert(mode < ARRAY_SIZE(x86_round_mode));
767 set_float_rounding_mode(x86_round_mode[mode], status);
768 }
769
770 void update_fp_status(CPUX86State *env)
771 {
772 int rnd_mode;
773 FloatX80RoundPrec rnd_prec;
774
775 /* set rounding mode */
776 rnd_mode = (env->fpuc & FPU_RC_MASK) >> FPU_RC_SHIFT;
777 set_x86_rounding_mode(rnd_mode, &env->fp_status);
778
779 switch ((env->fpuc >> 8) & 3) {
780 case 0:
781 rnd_prec = floatx80_precision_s;
782 break;
783 case 2:
784 rnd_prec = floatx80_precision_d;
785 break;
786 case 3:
787 default:
788 rnd_prec = floatx80_precision_x;
789 break;
790 }
791 set_floatx80_rounding_precision(rnd_prec, &env->fp_status);
792 }
793
794 void helper_fldcw(CPUX86State *env, uint32_t val)
795 {
796 cpu_set_fpuc(env, val);
797 }
798
799 void helper_fclex(CPUX86State *env)
800 {
801 env->fpus &= 0x7f00;
802 }
803
804 void helper_fwait(CPUX86State *env)
805 {
806 if (env->fpus & FPUS_SE) {
807 fpu_raise_exception(env, GETPC());
808 }
809 }
810
811 static void do_fninit(CPUX86State *env)
812 {
813 env->fpus = 0;
814 env->fpstt = 0;
815 env->fpcs = 0;
816 env->fpds = 0;
817 env->fpip = 0;
818 env->fpdp = 0;
819 cpu_set_fpuc(env, 0x37f);
820 env->fptags[0] = 1;
821 env->fptags[1] = 1;
822 env->fptags[2] = 1;
823 env->fptags[3] = 1;
824 env->fptags[4] = 1;
825 env->fptags[5] = 1;
826 env->fptags[6] = 1;
827 env->fptags[7] = 1;
828 }
829
830 void helper_fninit(CPUX86State *env)
831 {
832 do_fninit(env);
833 }
834
835 /* BCD ops */
836
837 void helper_fbld_ST0(CPUX86State *env, target_ulong ptr)
838 {
839 X86Access ac;
840 floatx80 tmp;
841 uint64_t val;
842 unsigned int v;
843 int i;
844
845 access_prepare(&ac, env, ptr, 10, MMU_DATA_LOAD, GETPC());
846
847 val = 0;
848 for (i = 8; i >= 0; i--) {
849 v = access_ldb(&ac, ptr + i);
850 val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
851 }
852 tmp = int64_to_floatx80(val, &env->fp_status);
853 if (access_ldb(&ac, ptr + 9) & 0x80) {
854 tmp = floatx80_chs(tmp);
855 }
856 fpush(env);
857 ST0 = tmp;
858 }
859
860 void helper_fbst_ST0(CPUX86State *env, target_ulong ptr)
861 {
862 int old_flags = save_exception_flags(env);
863 int v;
864 target_ulong mem_ref, mem_end;
865 int64_t val;
866 CPU_LDoubleU temp;
867 X86Access ac;
868
869 access_prepare(&ac, env, ptr, 10, MMU_DATA_STORE, GETPC());
870 temp.d = ST0;
871
872 val = floatx80_to_int64(ST0, &env->fp_status);
873 mem_ref = ptr;
874 if (val >= 1000000000000000000LL || val <= -1000000000000000000LL) {
875 set_float_exception_flags(float_flag_invalid, &env->fp_status);
876 while (mem_ref < ptr + 7) {
877 access_stb(&ac, mem_ref++, 0);
878 }
879 access_stb(&ac, mem_ref++, 0xc0);
880 access_stb(&ac, mem_ref++, 0xff);
881 access_stb(&ac, mem_ref++, 0xff);
882 merge_exception_flags(env, old_flags);
883 return;
884 }
885 mem_end = mem_ref + 9;
886 if (SIGND(temp)) {
887 access_stb(&ac, mem_end, 0x80);
888 val = -val;
889 } else {
890 access_stb(&ac, mem_end, 0x00);
891 }
892 while (mem_ref < mem_end) {
893 if (val == 0) {
894 break;
895 }
896 v = val % 100;
897 val = val / 100;
898 v = ((v / 10) << 4) | (v % 10);
899 access_stb(&ac, mem_ref++, v);
900 }
901 while (mem_ref < mem_end) {
902 access_stb(&ac, mem_ref++, 0);
903 }
904 merge_exception_flags(env, old_flags);
905 }
906
907 /* 128-bit significand of log(2). */
908 #define ln2_sig_high 0xb17217f7d1cf79abULL
909 #define ln2_sig_low 0xc9e3b39803f2f6afULL
910
911 /*
912 * Polynomial coefficients for an approximation to (2^x - 1) / x, on
913 * the interval [-1/64, 1/64].
914 */
915 #define f2xm1_coeff_0 make_floatx80(0x3ffe, 0xb17217f7d1cf79acULL)
916 #define f2xm1_coeff_0_low make_floatx80(0xbfbc, 0xd87edabf495b3762ULL)
917 #define f2xm1_coeff_1 make_floatx80(0x3ffc, 0xf5fdeffc162c7543ULL)
918 #define f2xm1_coeff_2 make_floatx80(0x3ffa, 0xe35846b82505fcc7ULL)
919 #define f2xm1_coeff_3 make_floatx80(0x3ff8, 0x9d955b7dd273b899ULL)
920 #define f2xm1_coeff_4 make_floatx80(0x3ff5, 0xaec3ff3c4ef4ac0cULL)
921 #define f2xm1_coeff_5 make_floatx80(0x3ff2, 0xa184897c3a7f0de9ULL)
922 #define f2xm1_coeff_6 make_floatx80(0x3fee, 0xffe634d0ec30d504ULL)
923 #define f2xm1_coeff_7 make_floatx80(0x3feb, 0xb160111d2db515e4ULL)
924
925 struct f2xm1_data {
926 /*
927 * A value very close to a multiple of 1/32, such that 2^t and 2^t - 1
928 * are very close to exact floatx80 values.
929 */
930 floatx80 t;
931 /* The value of 2^t. */
932 floatx80 exp2;
933 /* The value of 2^t - 1. */
934 floatx80 exp2m1;
935 };
936
937 static const struct f2xm1_data f2xm1_table[65] = {
938 { make_floatx80_init(0xbfff, 0x8000000000000000ULL),
939 make_floatx80_init(0x3ffe, 0x8000000000000000ULL),
940 make_floatx80_init(0xbffe, 0x8000000000000000ULL) },
941 { make_floatx80_init(0xbffe, 0xf800000000002e7eULL),
942 make_floatx80_init(0x3ffe, 0x82cd8698ac2b9160ULL),
943 make_floatx80_init(0xbffd, 0xfa64f2cea7a8dd40ULL) },
944 { make_floatx80_init(0xbffe, 0xefffffffffffe960ULL),
945 make_floatx80_init(0x3ffe, 0x85aac367cc488345ULL),
946 make_floatx80_init(0xbffd, 0xf4aa7930676ef976ULL) },
947 { make_floatx80_init(0xbffe, 0xe800000000006f10ULL),
948 make_floatx80_init(0x3ffe, 0x88980e8092da5c14ULL),
949 make_floatx80_init(0xbffd, 0xeecfe2feda4b47d8ULL) },
950 { make_floatx80_init(0xbffe, 0xe000000000008a45ULL),
951 make_floatx80_init(0x3ffe, 0x8b95c1e3ea8ba2a5ULL),
952 make_floatx80_init(0xbffd, 0xe8d47c382ae8bab6ULL) },
953 { make_floatx80_init(0xbffe, 0xd7ffffffffff8a9eULL),
954 make_floatx80_init(0x3ffe, 0x8ea4398b45cd8116ULL),
955 make_floatx80_init(0xbffd, 0xe2b78ce97464fdd4ULL) },
956 { make_floatx80_init(0xbffe, 0xd0000000000019a0ULL),
957 make_floatx80_init(0x3ffe, 0x91c3d373ab11b919ULL),
958 make_floatx80_init(0xbffd, 0xdc785918a9dc8dceULL) },
959 { make_floatx80_init(0xbffe, 0xc7ffffffffff14dfULL),
960 make_floatx80_init(0x3ffe, 0x94f4efa8fef76836ULL),
961 make_floatx80_init(0xbffd, 0xd61620ae02112f94ULL) },
962 { make_floatx80_init(0xbffe, 0xc000000000006530ULL),
963 make_floatx80_init(0x3ffe, 0x9837f0518db87fbbULL),
964 make_floatx80_init(0xbffd, 0xcf901f5ce48f008aULL) },
965 { make_floatx80_init(0xbffe, 0xb7ffffffffff1723ULL),
966 make_floatx80_init(0x3ffe, 0x9b8d39b9d54eb74cULL),
967 make_floatx80_init(0xbffd, 0xc8e58c8c55629168ULL) },
968 { make_floatx80_init(0xbffe, 0xb00000000000b5e1ULL),
969 make_floatx80_init(0x3ffe, 0x9ef5326091a0c366ULL),
970 make_floatx80_init(0xbffd, 0xc2159b3edcbe7934ULL) },
971 { make_floatx80_init(0xbffe, 0xa800000000006f8aULL),
972 make_floatx80_init(0x3ffe, 0xa27043030c49370aULL),
973 make_floatx80_init(0xbffd, 0xbb1f79f9e76d91ecULL) },
974 { make_floatx80_init(0xbffe, 0x9fffffffffff816aULL),
975 make_floatx80_init(0x3ffe, 0xa5fed6a9b15171cfULL),
976 make_floatx80_init(0xbffd, 0xb40252ac9d5d1c62ULL) },
977 { make_floatx80_init(0xbffe, 0x97ffffffffffb621ULL),
978 make_floatx80_init(0x3ffe, 0xa9a15ab4ea7c30e6ULL),
979 make_floatx80_init(0xbffd, 0xacbd4a962b079e34ULL) },
980 { make_floatx80_init(0xbffe, 0x8fffffffffff162bULL),
981 make_floatx80_init(0x3ffe, 0xad583eea42a1b886ULL),
982 make_floatx80_init(0xbffd, 0xa54f822b7abc8ef4ULL) },
983 { make_floatx80_init(0xbffe, 0x87ffffffffff4d34ULL),
984 make_floatx80_init(0x3ffe, 0xb123f581d2ac7b51ULL),
985 make_floatx80_init(0xbffd, 0x9db814fc5aa7095eULL) },
986 { make_floatx80_init(0xbffe, 0x800000000000227dULL),
987 make_floatx80_init(0x3ffe, 0xb504f333f9de539dULL),
988 make_floatx80_init(0xbffd, 0x95f619980c4358c6ULL) },
989 { make_floatx80_init(0xbffd, 0xefffffffffff3978ULL),
990 make_floatx80_init(0x3ffe, 0xb8fbaf4762fbd0a1ULL),
991 make_floatx80_init(0xbffd, 0x8e08a1713a085ebeULL) },
992 { make_floatx80_init(0xbffd, 0xe00000000000df81ULL),
993 make_floatx80_init(0x3ffe, 0xbd08a39f580bfd8cULL),
994 make_floatx80_init(0xbffd, 0x85eeb8c14fe804e8ULL) },
995 { make_floatx80_init(0xbffd, 0xd00000000000bccfULL),
996 make_floatx80_init(0x3ffe, 0xc12c4cca667062f6ULL),
997 make_floatx80_init(0xbffc, 0xfb4eccd6663e7428ULL) },
998 { make_floatx80_init(0xbffd, 0xc00000000000eff0ULL),
999 make_floatx80_init(0x3ffe, 0xc5672a1155069abeULL),
1000 make_floatx80_init(0xbffc, 0xea6357baabe59508ULL) },
1001 { make_floatx80_init(0xbffd, 0xb000000000000fe6ULL),
1002 make_floatx80_init(0x3ffe, 0xc9b9bd866e2f234bULL),
1003 make_floatx80_init(0xbffc, 0xd91909e6474372d4ULL) },
1004 { make_floatx80_init(0xbffd, 0x9fffffffffff2172ULL),
1005 make_floatx80_init(0x3ffe, 0xce248c151f84bf00ULL),
1006 make_floatx80_init(0xbffc, 0xc76dcfab81ed0400ULL) },
1007 { make_floatx80_init(0xbffd, 0x8fffffffffffafffULL),
1008 make_floatx80_init(0x3ffe, 0xd2a81d91f12afb2bULL),
1009 make_floatx80_init(0xbffc, 0xb55f89b83b541354ULL) },
1010 { make_floatx80_init(0xbffc, 0xffffffffffff81a3ULL),
1011 make_floatx80_init(0x3ffe, 0xd744fccad69d7d5eULL),
1012 make_floatx80_init(0xbffc, 0xa2ec0cd4a58a0a88ULL) },
1013 { make_floatx80_init(0xbffc, 0xdfffffffffff1568ULL),
1014 make_floatx80_init(0x3ffe, 0xdbfbb797daf25a44ULL),
1015 make_floatx80_init(0xbffc, 0x901121a0943696f0ULL) },
1016 { make_floatx80_init(0xbffc, 0xbfffffffffff68daULL),
1017 make_floatx80_init(0x3ffe, 0xe0ccdeec2a94f811ULL),
1018 make_floatx80_init(0xbffb, 0xf999089eab583f78ULL) },
1019 { make_floatx80_init(0xbffc, 0x9fffffffffff4690ULL),
1020 make_floatx80_init(0x3ffe, 0xe5b906e77c83657eULL),
1021 make_floatx80_init(0xbffb, 0xd237c8c41be4d410ULL) },
1022 { make_floatx80_init(0xbffb, 0xffffffffffff8aeeULL),
1023 make_floatx80_init(0x3ffe, 0xeac0c6e7dd24427cULL),
1024 make_floatx80_init(0xbffb, 0xa9f9c8c116ddec20ULL) },
1025 { make_floatx80_init(0xbffb, 0xbfffffffffff2d18ULL),
1026 make_floatx80_init(0x3ffe, 0xefe4b99bdcdb06ebULL),
1027 make_floatx80_init(0xbffb, 0x80da33211927c8a8ULL) },
1028 { make_floatx80_init(0xbffa, 0xffffffffffff8ccbULL),
1029 make_floatx80_init(0x3ffe, 0xf5257d152486d0f4ULL),
1030 make_floatx80_init(0xbffa, 0xada82eadb792f0c0ULL) },
1031 { make_floatx80_init(0xbff9, 0xffffffffffff11feULL),
1032 make_floatx80_init(0x3ffe, 0xfa83b2db722a0846ULL),
1033 make_floatx80_init(0xbff9, 0xaf89a491babef740ULL) },
1034 { floatx80_zero_init,
1035 make_floatx80_init(0x3fff, 0x8000000000000000ULL),
1036 floatx80_zero_init },
1037 { make_floatx80_init(0x3ff9, 0xffffffffffff2680ULL),
1038 make_floatx80_init(0x3fff, 0x82cd8698ac2b9f6fULL),
1039 make_floatx80_init(0x3ff9, 0xb361a62b0ae7dbc0ULL) },
1040 { make_floatx80_init(0x3ffb, 0x800000000000b500ULL),
1041 make_floatx80_init(0x3fff, 0x85aac367cc488345ULL),
1042 make_floatx80_init(0x3ffa, 0xb5586cf9891068a0ULL) },
1043 { make_floatx80_init(0x3ffb, 0xbfffffffffff4b67ULL),
1044 make_floatx80_init(0x3fff, 0x88980e8092da7cceULL),
1045 make_floatx80_init(0x3ffb, 0x8980e8092da7cce0ULL) },
1046 { make_floatx80_init(0x3ffb, 0xffffffffffffff57ULL),
1047 make_floatx80_init(0x3fff, 0x8b95c1e3ea8bd6dfULL),
1048 make_floatx80_init(0x3ffb, 0xb95c1e3ea8bd6df0ULL) },
1049 { make_floatx80_init(0x3ffc, 0x9fffffffffff811fULL),
1050 make_floatx80_init(0x3fff, 0x8ea4398b45cd4780ULL),
1051 make_floatx80_init(0x3ffb, 0xea4398b45cd47800ULL) },
1052 { make_floatx80_init(0x3ffc, 0xbfffffffffff9980ULL),
1053 make_floatx80_init(0x3fff, 0x91c3d373ab11b919ULL),
1054 make_floatx80_init(0x3ffc, 0x8e1e9b9d588dc8c8ULL) },
1055 { make_floatx80_init(0x3ffc, 0xdffffffffffff631ULL),
1056 make_floatx80_init(0x3fff, 0x94f4efa8fef70864ULL),
1057 make_floatx80_init(0x3ffc, 0xa7a77d47f7b84320ULL) },
1058 { make_floatx80_init(0x3ffc, 0xffffffffffff2499ULL),
1059 make_floatx80_init(0x3fff, 0x9837f0518db892d4ULL),
1060 make_floatx80_init(0x3ffc, 0xc1bf828c6dc496a0ULL) },
1061 { make_floatx80_init(0x3ffd, 0x8fffffffffff80fbULL),
1062 make_floatx80_init(0x3fff, 0x9b8d39b9d54e3a79ULL),
1063 make_floatx80_init(0x3ffc, 0xdc69cdceaa71d3c8ULL) },
1064 { make_floatx80_init(0x3ffd, 0x9fffffffffffbc23ULL),
1065 make_floatx80_init(0x3fff, 0x9ef5326091a10313ULL),
1066 make_floatx80_init(0x3ffc, 0xf7a993048d081898ULL) },
1067 { make_floatx80_init(0x3ffd, 0xafffffffffff20ecULL),
1068 make_floatx80_init(0x3fff, 0xa27043030c49370aULL),
1069 make_floatx80_init(0x3ffd, 0x89c10c0c3124dc28ULL) },
1070 { make_floatx80_init(0x3ffd, 0xc00000000000fd2cULL),
1071 make_floatx80_init(0x3fff, 0xa5fed6a9b15171cfULL),
1072 make_floatx80_init(0x3ffd, 0x97fb5aa6c545c73cULL) },
1073 { make_floatx80_init(0x3ffd, 0xd0000000000093beULL),
1074 make_floatx80_init(0x3fff, 0xa9a15ab4ea7c30e6ULL),
1075 make_floatx80_init(0x3ffd, 0xa6856ad3a9f0c398ULL) },
1076 { make_floatx80_init(0x3ffd, 0xe00000000000c2aeULL),
1077 make_floatx80_init(0x3fff, 0xad583eea42a17876ULL),
1078 make_floatx80_init(0x3ffd, 0xb560fba90a85e1d8ULL) },
1079 { make_floatx80_init(0x3ffd, 0xefffffffffff1e3fULL),
1080 make_floatx80_init(0x3fff, 0xb123f581d2abef6cULL),
1081 make_floatx80_init(0x3ffd, 0xc48fd6074aafbdb0ULL) },
1082 { make_floatx80_init(0x3ffd, 0xffffffffffff1c23ULL),
1083 make_floatx80_init(0x3fff, 0xb504f333f9de2cadULL),
1084 make_floatx80_init(0x3ffd, 0xd413cccfe778b2b4ULL) },
1085 { make_floatx80_init(0x3ffe, 0x8800000000006344ULL),
1086 make_floatx80_init(0x3fff, 0xb8fbaf4762fbd0a1ULL),
1087 make_floatx80_init(0x3ffd, 0xe3eebd1d8bef4284ULL) },
1088 { make_floatx80_init(0x3ffe, 0x9000000000005d67ULL),
1089 make_floatx80_init(0x3fff, 0xbd08a39f580c668dULL),
1090 make_floatx80_init(0x3ffd, 0xf4228e7d60319a34ULL) },
1091 { make_floatx80_init(0x3ffe, 0x9800000000009127ULL),
1092 make_floatx80_init(0x3fff, 0xc12c4cca6670e042ULL),
1093 make_floatx80_init(0x3ffe, 0x82589994cce1c084ULL) },
1094 { make_floatx80_init(0x3ffe, 0x9fffffffffff06f9ULL),
1095 make_floatx80_init(0x3fff, 0xc5672a11550655c3ULL),
1096 make_floatx80_init(0x3ffe, 0x8ace5422aa0cab86ULL) },
1097 { make_floatx80_init(0x3ffe, 0xa7fffffffffff80dULL),
1098 make_floatx80_init(0x3fff, 0xc9b9bd866e2f234bULL),
1099 make_floatx80_init(0x3ffe, 0x93737b0cdc5e4696ULL) },
1100 { make_floatx80_init(0x3ffe, 0xafffffffffff1470ULL),
1101 make_floatx80_init(0x3fff, 0xce248c151f83fd69ULL),
1102 make_floatx80_init(0x3ffe, 0x9c49182a3f07fad2ULL) },
1103 { make_floatx80_init(0x3ffe, 0xb800000000000e0aULL),
1104 make_floatx80_init(0x3fff, 0xd2a81d91f12aec5cULL),
1105 make_floatx80_init(0x3ffe, 0xa5503b23e255d8b8ULL) },
1106 { make_floatx80_init(0x3ffe, 0xc00000000000b7faULL),
1107 make_floatx80_init(0x3fff, 0xd744fccad69dd630ULL),
1108 make_floatx80_init(0x3ffe, 0xae89f995ad3bac60ULL) },
1109 { make_floatx80_init(0x3ffe, 0xc800000000003aa6ULL),
1110 make_floatx80_init(0x3fff, 0xdbfbb797daf25a44ULL),
1111 make_floatx80_init(0x3ffe, 0xb7f76f2fb5e4b488ULL) },
1112 { make_floatx80_init(0x3ffe, 0xd00000000000a6aeULL),
1113 make_floatx80_init(0x3fff, 0xe0ccdeec2a954685ULL),
1114 make_floatx80_init(0x3ffe, 0xc199bdd8552a8d0aULL) },
1115 { make_floatx80_init(0x3ffe, 0xd800000000004165ULL),
1116 make_floatx80_init(0x3fff, 0xe5b906e77c837155ULL),
1117 make_floatx80_init(0x3ffe, 0xcb720dcef906e2aaULL) },
1118 { make_floatx80_init(0x3ffe, 0xe00000000000582cULL),
1119 make_floatx80_init(0x3fff, 0xeac0c6e7dd24713aULL),
1120 make_floatx80_init(0x3ffe, 0xd5818dcfba48e274ULL) },
1121 { make_floatx80_init(0x3ffe, 0xe800000000001a5dULL),
1122 make_floatx80_init(0x3fff, 0xefe4b99bdcdb06ebULL),
1123 make_floatx80_init(0x3ffe, 0xdfc97337b9b60dd6ULL) },
1124 { make_floatx80_init(0x3ffe, 0xefffffffffffc1efULL),
1125 make_floatx80_init(0x3fff, 0xf5257d152486a2faULL),
1126 make_floatx80_init(0x3ffe, 0xea4afa2a490d45f4ULL) },
1127 { make_floatx80_init(0x3ffe, 0xf800000000001069ULL),
1128 make_floatx80_init(0x3fff, 0xfa83b2db722a0e5cULL),
1129 make_floatx80_init(0x3ffe, 0xf50765b6e4541cb8ULL) },
1130 { make_floatx80_init(0x3fff, 0x8000000000000000ULL),
1131 make_floatx80_init(0x4000, 0x8000000000000000ULL),
1132 make_floatx80_init(0x3fff, 0x8000000000000000ULL) },
1133 };
1134
1135 void helper_f2xm1(CPUX86State *env)
1136 {
1137 int old_flags = save_exception_flags(env);
1138 uint64_t sig = extractFloatx80Frac(ST0);
1139 int32_t exp = extractFloatx80Exp(ST0);
1140 bool sign = extractFloatx80Sign(ST0);
1141
1142 if (floatx80_invalid_encoding(ST0, &env->fp_status)) {
1143 float_raise(float_flag_invalid, &env->fp_status);
1144 ST0 = floatx80_default_nan(&env->fp_status);
1145 } else if (floatx80_is_any_nan(ST0)) {
1146 if (floatx80_is_signaling_nan(ST0, &env->fp_status)) {
1147 float_raise(float_flag_invalid, &env->fp_status);
1148 ST0 = floatx80_silence_nan(ST0, &env->fp_status);
1149 }
1150 } else if (exp > 0x3fff ||
1151 (exp == 0x3fff && sig != (0x8000000000000000ULL))) {
1152 /* Out of range for the instruction, treat as invalid. */
1153 float_raise(float_flag_invalid, &env->fp_status);
1154 ST0 = floatx80_default_nan(&env->fp_status);
1155 } else if (exp == 0x3fff) {
1156 /* Argument 1 or -1, exact result 1 or -0.5. */
1157 if (sign) {
1158 ST0 = make_floatx80(0xbffe, 0x8000000000000000ULL);
1159 }
1160 } else if (exp < 0x3fb0) {
1161 if (!floatx80_is_zero(ST0)) {
1162 /*
1163 * Multiplying the argument by an extra-precision version
1164 * of log(2) is sufficiently precise. Zero arguments are
1165 * returned unchanged.
1166 */
1167 uint64_t sig0, sig1, sig2;
1168 if (exp == 0) {
1169 normalizeFloatx80Subnormal(sig, &exp, &sig);
1170 }
1171 mul128By64To192(ln2_sig_high, ln2_sig_low, sig, &sig0, &sig1,
1172 &sig2);
1173 /* This result is inexact. */
1174 sig1 |= 1;
1175 ST0 = normalizeRoundAndPackFloatx80(floatx80_precision_x,
1176 sign, exp, sig0, sig1,
1177 &env->fp_status);
1178 }
1179 } else {
1180 floatx80 tmp, y, accum;
1181 bool asign, bsign;
1182 int32_t n, aexp, bexp;
1183 uint64_t asig0, asig1, asig2, bsig0, bsig1;
1184 FloatRoundMode save_mode = get_float_rounding_mode(&env->fp_status);
1185 FloatX80RoundPrec save_prec =
1186 get_floatx80_rounding_precision(&env->fp_status);
1187 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1188 set_floatx80_rounding_precision(floatx80_precision_x, &env->fp_status);
1189
1190 /* Find the nearest multiple of 1/32 to the argument. */
1191 tmp = floatx80_scalbn(ST0, 5, &env->fp_status);
1192 n = 32 + floatx80_to_int32(tmp, &env->fp_status);
1193 y = floatx80_sub(ST0, f2xm1_table[n].t, &env->fp_status);
1194
1195 if (floatx80_is_zero(y)) {
1196 /*
1197 * Use the value of 2^t - 1 from the table, to avoid
1198 * needing to special-case zero as a result of
1199 * multiplication below.
1200 */
1201 ST0 = f2xm1_table[n].t;
1202 set_float_exception_flags(float_flag_inexact, &env->fp_status);
1203 set_float_rounding_mode(save_mode, &env->fp_status);
1204 } else {
1205 /*
1206 * Compute the lower parts of a polynomial expansion for
1207 * (2^y - 1) / y.
1208 */
1209 accum = floatx80_mul(f2xm1_coeff_7, y, &env->fp_status);
1210 accum = floatx80_add(f2xm1_coeff_6, accum, &env->fp_status);
1211 accum = floatx80_mul(accum, y, &env->fp_status);
1212 accum = floatx80_add(f2xm1_coeff_5, accum, &env->fp_status);
1213 accum = floatx80_mul(accum, y, &env->fp_status);
1214 accum = floatx80_add(f2xm1_coeff_4, accum, &env->fp_status);
1215 accum = floatx80_mul(accum, y, &env->fp_status);
1216 accum = floatx80_add(f2xm1_coeff_3, accum, &env->fp_status);
1217 accum = floatx80_mul(accum, y, &env->fp_status);
1218 accum = floatx80_add(f2xm1_coeff_2, accum, &env->fp_status);
1219 accum = floatx80_mul(accum, y, &env->fp_status);
1220 accum = floatx80_add(f2xm1_coeff_1, accum, &env->fp_status);
1221 accum = floatx80_mul(accum, y, &env->fp_status);
1222 accum = floatx80_add(f2xm1_coeff_0_low, accum, &env->fp_status);
1223
1224 /*
1225 * The full polynomial expansion is f2xm1_coeff_0 + accum
1226 * (where accum has much lower magnitude, and so, in
1227 * particular, carry out of the addition is not possible).
1228 * (This expansion is only accurate to about 70 bits, not
1229 * 128 bits.)
1230 */
1231 aexp = extractFloatx80Exp(f2xm1_coeff_0);
1232 asign = extractFloatx80Sign(f2xm1_coeff_0);
1233 shift128RightJamming(extractFloatx80Frac(accum), 0,
1234 aexp - extractFloatx80Exp(accum),
1235 &asig0, &asig1);
1236 bsig0 = extractFloatx80Frac(f2xm1_coeff_0);
1237 bsig1 = 0;
1238 if (asign == extractFloatx80Sign(accum)) {
1239 add128(bsig0, bsig1, asig0, asig1, &asig0, &asig1);
1240 } else {
1241 sub128(bsig0, bsig1, asig0, asig1, &asig0, &asig1);
1242 }
1243 /* And thus compute an approximation to 2^y - 1. */
1244 mul128By64To192(asig0, asig1, extractFloatx80Frac(y),
1245 &asig0, &asig1, &asig2);
1246 aexp += extractFloatx80Exp(y) - 0x3ffe;
1247 asign ^= extractFloatx80Sign(y);
1248 if (n != 32) {
1249 /*
1250 * Multiply this by the precomputed value of 2^t and
1251 * add that of 2^t - 1.
1252 */
1253 mul128By64To192(asig0, asig1,
1254 extractFloatx80Frac(f2xm1_table[n].exp2),
1255 &asig0, &asig1, &asig2);
1256 aexp += extractFloatx80Exp(f2xm1_table[n].exp2) - 0x3ffe;
1257 bexp = extractFloatx80Exp(f2xm1_table[n].exp2m1);
1258 bsig0 = extractFloatx80Frac(f2xm1_table[n].exp2m1);
1259 bsig1 = 0;
1260 if (bexp < aexp) {
1261 shift128RightJamming(bsig0, bsig1, aexp - bexp,
1262 &bsig0, &bsig1);
1263 } else if (aexp < bexp) {
1264 shift128RightJamming(asig0, asig1, bexp - aexp,
1265 &asig0, &asig1);
1266 aexp = bexp;
1267 }
1268 /* The sign of 2^t - 1 is always that of the result. */
1269 bsign = extractFloatx80Sign(f2xm1_table[n].exp2m1);
1270 if (asign == bsign) {
1271 /* Avoid possible carry out of the addition. */
1272 shift128RightJamming(asig0, asig1, 1,
1273 &asig0, &asig1);
1274 shift128RightJamming(bsig0, bsig1, 1,
1275 &bsig0, &bsig1);
1276 ++aexp;
1277 add128(asig0, asig1, bsig0, bsig1, &asig0, &asig1);
1278 } else {
1279 sub128(bsig0, bsig1, asig0, asig1, &asig0, &asig1);
1280 asign = bsign;
1281 }
1282 }
1283 set_float_rounding_mode(save_mode, &env->fp_status);
1284 /* This result is inexact. */
1285 asig1 |= 1;
1286 ST0 = normalizeRoundAndPackFloatx80(floatx80_precision_x,
1287 asign, aexp, asig0, asig1,
1288 &env->fp_status);
1289 }
1290
1291 set_floatx80_rounding_precision(save_prec, &env->fp_status);
1292 }
1293 merge_exception_flags(env, old_flags);
1294 }
1295
1296 void helper_fptan(CPUX86State *env)
1297 {
1298 double fptemp = floatx80_to_double(env, ST0);
1299
1300 if ((fptemp > MAXTAN) || (fptemp < -MAXTAN)) {
1301 env->fpus |= 0x400;
1302 } else {
1303 fptemp = tan(fptemp);
1304 ST0 = double_to_floatx80(env, fptemp);
1305 fpush(env);
1306 ST0 = floatx80_one;
1307 env->fpus &= ~0x400; /* C2 <-- 0 */
1308 /* the above code is for |arg| < 2**52 only */
1309 }
1310 }
1311
1312 /* Values of pi/4, pi/2, 3pi/4 and pi, with 128-bit precision. */
1313 #define pi_4_exp 0x3ffe
1314 #define pi_4_sig_high 0xc90fdaa22168c234ULL
1315 #define pi_4_sig_low 0xc4c6628b80dc1cd1ULL
1316 #define pi_2_exp 0x3fff
1317 #define pi_2_sig_high 0xc90fdaa22168c234ULL
1318 #define pi_2_sig_low 0xc4c6628b80dc1cd1ULL
1319 #define pi_34_exp 0x4000
1320 #define pi_34_sig_high 0x96cbe3f9990e91a7ULL
1321 #define pi_34_sig_low 0x9394c9e8a0a5159dULL
1322 #define pi_exp 0x4000
1323 #define pi_sig_high 0xc90fdaa22168c234ULL
1324 #define pi_sig_low 0xc4c6628b80dc1cd1ULL
1325
1326 /*
1327 * Polynomial coefficients for an approximation to atan(x), with only
1328 * odd powers of x used, for x in the interval [-1/16, 1/16]. (Unlike
1329 * for some other approximations, no low part is needed for the first
1330 * coefficient here to achieve a sufficiently accurate result, because
1331 * the coefficient in this minimax approximation is very close to
1332 * exactly 1.)
1333 */
1334 #define fpatan_coeff_0 make_floatx80(0x3fff, 0x8000000000000000ULL)
1335 #define fpatan_coeff_1 make_floatx80(0xbffd, 0xaaaaaaaaaaaaaa43ULL)
1336 #define fpatan_coeff_2 make_floatx80(0x3ffc, 0xccccccccccbfe4f8ULL)
1337 #define fpatan_coeff_3 make_floatx80(0xbffc, 0x92492491fbab2e66ULL)
1338 #define fpatan_coeff_4 make_floatx80(0x3ffb, 0xe38e372881ea1e0bULL)
1339 #define fpatan_coeff_5 make_floatx80(0xbffb, 0xba2c0104bbdd0615ULL)
1340 #define fpatan_coeff_6 make_floatx80(0x3ffb, 0x9baf7ebf898b42efULL)
1341
1342 struct fpatan_data {
1343 /* High and low parts of atan(x). */
1344 floatx80 atan_high, atan_low;
1345 };
1346
1347 static const struct fpatan_data fpatan_table[9] = {
1348 { floatx80_zero_init,
1349 floatx80_zero_init },
1350 { make_floatx80_init(0x3ffb, 0xfeadd4d5617b6e33ULL),
1351 make_floatx80_init(0xbfb9, 0xdda19d8305ddc420ULL) },
1352 { make_floatx80_init(0x3ffc, 0xfadbafc96406eb15ULL),
1353 make_floatx80_init(0x3fbb, 0xdb8f3debef442fccULL) },
1354 { make_floatx80_init(0x3ffd, 0xb7b0ca0f26f78474ULL),
1355 make_floatx80_init(0xbfbc, 0xeab9bdba460376faULL) },
1356 { make_floatx80_init(0x3ffd, 0xed63382b0dda7b45ULL),
1357 make_floatx80_init(0x3fbc, 0xdfc88bd978751a06ULL) },
1358 { make_floatx80_init(0x3ffe, 0x8f005d5ef7f59f9bULL),
1359 make_floatx80_init(0x3fbd, 0xb906bc2ccb886e90ULL) },
1360 { make_floatx80_init(0x3ffe, 0xa4bc7d1934f70924ULL),
1361 make_floatx80_init(0x3fbb, 0xcd43f9522bed64f8ULL) },
1362 { make_floatx80_init(0x3ffe, 0xb8053e2bc2319e74ULL),
1363 make_floatx80_init(0xbfbc, 0xd3496ab7bd6eef0cULL) },
1364 { make_floatx80_init(0x3ffe, 0xc90fdaa22168c235ULL),
1365 make_floatx80_init(0xbfbc, 0xece675d1fc8f8cbcULL) },
1366 };
1367
1368 void helper_fpatan(CPUX86State *env)
1369 {
1370 int old_flags = save_exception_flags(env);
1371 uint64_t arg0_sig = extractFloatx80Frac(ST0);
1372 int32_t arg0_exp = extractFloatx80Exp(ST0);
1373 bool arg0_sign = extractFloatx80Sign(ST0);
1374 uint64_t arg1_sig = extractFloatx80Frac(ST1);
1375 int32_t arg1_exp = extractFloatx80Exp(ST1);
1376 bool arg1_sign = extractFloatx80Sign(ST1);
1377
1378 if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
1379 floatx80_invalid_encoding(ST1, &env->fp_status)) {
1380 float_raise(float_flag_invalid, &env->fp_status);
1381 ST1 = floatx80_default_nan(&env->fp_status);
1382 } else if (floatx80_is_signaling_nan(ST0, &env->fp_status)) {
1383 float_raise(float_flag_invalid, &env->fp_status);
1384 ST1 = floatx80_silence_nan(ST0, &env->fp_status);
1385 } else if (floatx80_is_signaling_nan(ST1, &env->fp_status)) {
1386 float_raise(float_flag_invalid, &env->fp_status);
1387 ST1 = floatx80_silence_nan(ST1, &env->fp_status);
1388 } else if (floatx80_is_any_nan(ST0)) {
1389 ST1 = ST0;
1390 } else if (floatx80_is_any_nan(ST1)) {
1391 /* Pass this NaN through. */
1392 } else if (floatx80_is_zero(ST1) && !arg0_sign) {
1393 /* Pass this zero through. */
1394 } else if (((floatx80_is_infinity(ST0, &env->fp_status) &&
1395 !floatx80_is_infinity(ST1, &env->fp_status)) ||
1396 arg0_exp - arg1_exp >= 80) &&
1397 !arg0_sign) {
1398 /*
1399 * Dividing ST1 by ST0 gives the correct result up to
1400 * rounding, and avoids spurious underflow exceptions that
1401 * might result from passing some small values through the
1402 * polynomial approximation, but if a finite nonzero result of
1403 * division is exact, the result of fpatan is still inexact
1404 * (and underflowing where appropriate).
1405 */
1406 FloatX80RoundPrec save_prec =
1407 get_floatx80_rounding_precision(&env->fp_status);
1408 set_floatx80_rounding_precision(floatx80_precision_x, &env->fp_status);
1409 ST1 = floatx80_div(ST1, ST0, &env->fp_status);
1410 set_floatx80_rounding_precision(save_prec, &env->fp_status);
1411 if (!floatx80_is_zero(ST1) &&
1412 !(get_float_exception_flags(&env->fp_status) &
1413 float_flag_inexact)) {
1414 /*
1415 * The mathematical result is very slightly closer to zero
1416 * than this exact result. Round a value with the
1417 * significand adjusted accordingly to get the correct
1418 * exceptions, and possibly an adjusted result depending
1419 * on the rounding mode.
1420 */
1421 uint64_t sig = extractFloatx80Frac(ST1);
1422 int32_t exp = extractFloatx80Exp(ST1);
1423 bool sign = extractFloatx80Sign(ST1);
1424 if (exp == 0) {
1425 normalizeFloatx80Subnormal(sig, &exp, &sig);
1426 }
1427 ST1 = normalizeRoundAndPackFloatx80(floatx80_precision_x,
1428 sign, exp, sig - 1,
1429 -1, &env->fp_status);
1430 }
1431 } else {
1432 /* The result is inexact. */
1433 bool rsign = arg1_sign;
1434 int32_t rexp;
1435 uint64_t rsig0, rsig1;
1436 if (floatx80_is_zero(ST1)) {
1437 /*
1438 * ST0 is negative. The result is pi with the sign of
1439 * ST1.
1440 */
1441 rexp = pi_exp;
1442 rsig0 = pi_sig_high;
1443 rsig1 = pi_sig_low;
1444 } else if (floatx80_is_infinity(ST1, &env->fp_status)) {
1445 if (floatx80_is_infinity(ST0, &env->fp_status)) {
1446 if (arg0_sign) {
1447 rexp = pi_34_exp;
1448 rsig0 = pi_34_sig_high;
1449 rsig1 = pi_34_sig_low;
1450 } else {
1451 rexp = pi_4_exp;
1452 rsig0 = pi_4_sig_high;
1453 rsig1 = pi_4_sig_low;
1454 }
1455 } else {
1456 rexp = pi_2_exp;
1457 rsig0 = pi_2_sig_high;
1458 rsig1 = pi_2_sig_low;
1459 }
1460 } else if (floatx80_is_zero(ST0) || arg1_exp - arg0_exp >= 80) {
1461 rexp = pi_2_exp;
1462 rsig0 = pi_2_sig_high;
1463 rsig1 = pi_2_sig_low;
1464 } else if (floatx80_is_infinity(ST0, &env->fp_status) ||
1465 arg0_exp - arg1_exp >= 80) {
1466 /* ST0 is negative. */
1467 rexp = pi_exp;
1468 rsig0 = pi_sig_high;
1469 rsig1 = pi_sig_low;
1470 } else {
1471 /*
1472 * ST0 and ST1 are finite, nonzero and with exponents not
1473 * too far apart.
1474 */
1475 int32_t adj_exp, num_exp, den_exp, xexp, yexp, n, texp, zexp, aexp;
1476 int32_t azexp, axexp;
1477 bool adj_sub, ysign, zsign;
1478 uint64_t adj_sig0, adj_sig1, num_sig, den_sig, xsig0, xsig1;
1479 uint64_t msig0, msig1, msig2, remsig0, remsig1, remsig2;
1480 uint64_t ysig0, ysig1, tsig, zsig0, zsig1, asig0, asig1;
1481 uint64_t azsig0, azsig1;
1482 uint64_t azsig2, azsig3, axsig0, axsig1;
1483 floatx80 x8;
1484 FloatRoundMode save_mode = get_float_rounding_mode(&env->fp_status);
1485 FloatX80RoundPrec save_prec =
1486 get_floatx80_rounding_precision(&env->fp_status);
1487 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1488 set_floatx80_rounding_precision(floatx80_precision_x,
1489 &env->fp_status);
1490
1491 if (arg0_exp == 0) {
1492 normalizeFloatx80Subnormal(arg0_sig, &arg0_exp, &arg0_sig);
1493 }
1494 if (arg1_exp == 0) {
1495 normalizeFloatx80Subnormal(arg1_sig, &arg1_exp, &arg1_sig);
1496 }
1497 if (arg0_exp > arg1_exp ||
1498 (arg0_exp == arg1_exp && arg0_sig >= arg1_sig)) {
1499 /* Work with abs(ST1) / abs(ST0). */
1500 num_exp = arg1_exp;
1501 num_sig = arg1_sig;
1502 den_exp = arg0_exp;
1503 den_sig = arg0_sig;
1504 if (arg0_sign) {
1505 /* The result is subtracted from pi. */
1506 adj_exp = pi_exp;
1507 adj_sig0 = pi_sig_high;
1508 adj_sig1 = pi_sig_low;
1509 adj_sub = true;
1510 } else {
1511 /* The result is used as-is. */
1512 adj_exp = 0;
1513 adj_sig0 = 0;
1514 adj_sig1 = 0;
1515 adj_sub = false;
1516 }
1517 } else {
1518 /* Work with abs(ST0) / abs(ST1). */
1519 num_exp = arg0_exp;
1520 num_sig = arg0_sig;
1521 den_exp = arg1_exp;
1522 den_sig = arg1_sig;
1523 /* The result is added to or subtracted from pi/2. */
1524 adj_exp = pi_2_exp;
1525 adj_sig0 = pi_2_sig_high;
1526 adj_sig1 = pi_2_sig_low;
1527 adj_sub = !arg0_sign;
1528 }
1529
1530 /*
1531 * Compute x = num/den, where 0 < x <= 1 and x is not too
1532 * small.
1533 */
1534 xexp = num_exp - den_exp + 0x3ffe;
1535 remsig0 = num_sig;
1536 remsig1 = 0;
1537 if (den_sig <= remsig0) {
1538 shift128Right(remsig0, remsig1, 1, &remsig0, &remsig1);
1539 ++xexp;
1540 }
1541 xsig0 = estimateDiv128To64(remsig0, remsig1, den_sig);
1542 mul64To128(den_sig, xsig0, &msig0, &msig1);
1543 sub128(remsig0, remsig1, msig0, msig1, &remsig0, &remsig1);
1544 while ((int64_t) remsig0 < 0) {
1545 --xsig0;
1546 add128(remsig0, remsig1, 0, den_sig, &remsig0, &remsig1);
1547 }
1548 xsig1 = estimateDiv128To64(remsig1, 0, den_sig);
1549 /*
1550 * No need to correct any estimation error in xsig1; even
1551 * with such error, it is accurate enough.
1552 */
1553
1554 /*
1555 * Split x as x = t + y, where t = n/8 is the nearest
1556 * multiple of 1/8 to x.
1557 */
1558 x8 = normalizeRoundAndPackFloatx80(floatx80_precision_x,
1559 false, xexp + 3, xsig0,
1560 xsig1, &env->fp_status);
1561 n = floatx80_to_int32(x8, &env->fp_status);
1562 if (n == 0) {
1563 ysign = false;
1564 yexp = xexp;
1565 ysig0 = xsig0;
1566 ysig1 = xsig1;
1567 texp = 0;
1568 tsig = 0;
1569 } else {
1570 int shift = clz32(n) + 32;
1571 texp = 0x403b - shift;
1572 tsig = n;
1573 tsig <<= shift;
1574 if (texp == xexp) {
1575 sub128(xsig0, xsig1, tsig, 0, &ysig0, &ysig1);
1576 if ((int64_t) ysig0 >= 0) {
1577 ysign = false;
1578 if (ysig0 == 0) {
1579 if (ysig1 == 0) {
1580 yexp = 0;
1581 } else {
1582 shift = clz64(ysig1) + 64;
1583 yexp = xexp - shift;
1584 shift128Left(ysig0, ysig1, shift,
1585 &ysig0, &ysig1);
1586 }
1587 } else {
1588 shift = clz64(ysig0);
1589 yexp = xexp - shift;
1590 shift128Left(ysig0, ysig1, shift, &ysig0, &ysig1);
1591 }
1592 } else {
1593 ysign = true;
1594 sub128(0, 0, ysig0, ysig1, &ysig0, &ysig1);
1595 if (ysig0 == 0) {
1596 shift = clz64(ysig1) + 64;
1597 } else {
1598 shift = clz64(ysig0);
1599 }
1600 yexp = xexp - shift;
1601 shift128Left(ysig0, ysig1, shift, &ysig0, &ysig1);
1602 }
1603 } else {
1604 /*
1605 * t's exponent must be greater than x's because t
1606 * is positive and the nearest multiple of 1/8 to
1607 * x, and if x has a greater exponent, the power
1608 * of 2 with that exponent is also a multiple of
1609 * 1/8.
1610 */
1611 uint64_t usig0, usig1;
1612 shift128RightJamming(xsig0, xsig1, texp - xexp,
1613 &usig0, &usig1);
1614 ysign = true;
1615 sub128(tsig, 0, usig0, usig1, &ysig0, &ysig1);
1616 if (ysig0 == 0) {
1617 shift = clz64(ysig1) + 64;
1618 } else {
1619 shift = clz64(ysig0);
1620 }
1621 yexp = texp - shift;
1622 shift128Left(ysig0, ysig1, shift, &ysig0, &ysig1);
1623 }
1624 }
1625
1626 /*
1627 * Compute z = y/(1+tx), so arctan(x) = arctan(t) +
1628 * arctan(z).
1629 */
1630 zsign = ysign;
1631 if (texp == 0 || yexp == 0) {
1632 zexp = yexp;
1633 zsig0 = ysig0;
1634 zsig1 = ysig1;
1635 } else {
1636 /*
1637 * t <= 1, x <= 1 and if both are 1 then y is 0, so tx < 1.
1638 */
1639 int32_t dexp = texp + xexp - 0x3ffe;
1640 uint64_t dsig0, dsig1, dsig2;
1641 mul128By64To192(xsig0, xsig1, tsig, &dsig0, &dsig1, &dsig2);
1642 /*
1643 * dexp <= 0x3fff (and if equal, dsig0 has a leading 0
1644 * bit). Add 1 to produce the denominator 1+tx.
1645 */
1646 shift128RightJamming(dsig0, dsig1, 0x3fff - dexp,
1647 &dsig0, &dsig1);
1648 dsig0 |= 0x8000000000000000ULL;
1649 zexp = yexp - 1;
1650 remsig0 = ysig0;
1651 remsig1 = ysig1;
1652 remsig2 = 0;
1653 if (dsig0 <= remsig0) {
1654 shift128Right(remsig0, remsig1, 1, &remsig0, &remsig1);
1655 ++zexp;
1656 }
1657 zsig0 = estimateDiv128To64(remsig0, remsig1, dsig0);
1658 mul128By64To192(dsig0, dsig1, zsig0, &msig0, &msig1, &msig2);
1659 sub192(remsig0, remsig1, remsig2, msig0, msig1, msig2,
1660 &remsig0, &remsig1, &remsig2);
1661 while ((int64_t) remsig0 < 0) {
1662 --zsig0;
1663 add192(remsig0, remsig1, remsig2, 0, dsig0, dsig1,
1664 &remsig0, &remsig1, &remsig2);
1665 }
1666 zsig1 = estimateDiv128To64(remsig1, remsig2, dsig0);
1667 /* No need to correct any estimation error in zsig1. */
1668 }
1669
1670 if (zexp == 0) {
1671 azexp = 0;
1672 azsig0 = 0;
1673 azsig1 = 0;
1674 } else {
1675 floatx80 z2, accum;
1676 uint64_t z2sig0, z2sig1, z2sig2, z2sig3;
1677 /* Compute z^2. */
1678 mul128To256(zsig0, zsig1, zsig0, zsig1,
1679 &z2sig0, &z2sig1, &z2sig2, &z2sig3);
1680 z2 = normalizeRoundAndPackFloatx80(floatx80_precision_x, false,
1681 zexp + zexp - 0x3ffe,
1682 z2sig0, z2sig1,
1683 &env->fp_status);
1684
1685 /* Compute the lower parts of the polynomial expansion. */
1686 accum = floatx80_mul(fpatan_coeff_6, z2, &env->fp_status);
1687 accum = floatx80_add(fpatan_coeff_5, accum, &env->fp_status);
1688 accum = floatx80_mul(accum, z2, &env->fp_status);
1689 accum = floatx80_add(fpatan_coeff_4, accum, &env->fp_status);
1690 accum = floatx80_mul(accum, z2, &env->fp_status);
1691 accum = floatx80_add(fpatan_coeff_3, accum, &env->fp_status);
1692 accum = floatx80_mul(accum, z2, &env->fp_status);
1693 accum = floatx80_add(fpatan_coeff_2, accum, &env->fp_status);
1694 accum = floatx80_mul(accum, z2, &env->fp_status);
1695 accum = floatx80_add(fpatan_coeff_1, accum, &env->fp_status);
1696 accum = floatx80_mul(accum, z2, &env->fp_status);
1697
1698 /*
1699 * The full polynomial expansion is z*(fpatan_coeff_0 + accum).
1700 * fpatan_coeff_0 is 1, and accum is negative and much smaller.
1701 */
1702 aexp = extractFloatx80Exp(fpatan_coeff_0);
1703 shift128RightJamming(extractFloatx80Frac(accum), 0,
1704 aexp - extractFloatx80Exp(accum),
1705 &asig0, &asig1);
1706 sub128(extractFloatx80Frac(fpatan_coeff_0), 0, asig0, asig1,
1707 &asig0, &asig1);
1708 /* Multiply by z to compute arctan(z). */
1709 azexp = aexp + zexp - 0x3ffe;
1710 mul128To256(asig0, asig1, zsig0, zsig1, &azsig0, &azsig1,
1711 &azsig2, &azsig3);
1712 }
1713
1714 /* Add arctan(t) (positive or zero) and arctan(z) (sign zsign). */
1715 if (texp == 0) {
1716 /* z is positive. */
1717 axexp = azexp;
1718 axsig0 = azsig0;
1719 axsig1 = azsig1;
1720 } else {
1721 bool low_sign = extractFloatx80Sign(fpatan_table[n].atan_low);
1722 int32_t low_exp = extractFloatx80Exp(fpatan_table[n].atan_low);
1723 uint64_t low_sig0 =
1724 extractFloatx80Frac(fpatan_table[n].atan_low);
1725 uint64_t low_sig1 = 0;
1726 axexp = extractFloatx80Exp(fpatan_table[n].atan_high);
1727 axsig0 = extractFloatx80Frac(fpatan_table[n].atan_high);
1728 axsig1 = 0;
1729 shift128RightJamming(low_sig0, low_sig1, axexp - low_exp,
1730 &low_sig0, &low_sig1);
1731 if (low_sign) {
1732 sub128(axsig0, axsig1, low_sig0, low_sig1,
1733 &axsig0, &axsig1);
1734 } else {
1735 add128(axsig0, axsig1, low_sig0, low_sig1,
1736 &axsig0, &axsig1);
1737 }
1738 if (azexp >= axexp) {
1739 shift128RightJamming(axsig0, axsig1, azexp - axexp + 1,
1740 &axsig0, &axsig1);
1741 axexp = azexp + 1;
1742 shift128RightJamming(azsig0, azsig1, 1,
1743 &azsig0, &azsig1);
1744 } else {
1745 shift128RightJamming(axsig0, axsig1, 1,
1746 &axsig0, &axsig1);
1747 shift128RightJamming(azsig0, azsig1, axexp - azexp + 1,
1748 &azsig0, &azsig1);
1749 ++axexp;
1750 }
1751 if (zsign) {
1752 sub128(axsig0, axsig1, azsig0, azsig1,
1753 &axsig0, &axsig1);
1754 } else {
1755 add128(axsig0, axsig1, azsig0, azsig1,
1756 &axsig0, &axsig1);
1757 }
1758 }
1759
1760 if (adj_exp == 0) {
1761 rexp = axexp;
1762 rsig0 = axsig0;
1763 rsig1 = axsig1;
1764 } else {
1765 /*
1766 * Add or subtract arctan(x) (exponent axexp,
1767 * significand axsig0 and axsig1, positive, not
1768 * necessarily normalized) to the number given by
1769 * adj_exp, adj_sig0 and adj_sig1, according to
1770 * adj_sub.
1771 */
1772 if (adj_exp >= axexp) {
1773 shift128RightJamming(axsig0, axsig1, adj_exp - axexp + 1,
1774 &axsig0, &axsig1);
1775 rexp = adj_exp + 1;
1776 shift128RightJamming(adj_sig0, adj_sig1, 1,
1777 &adj_sig0, &adj_sig1);
1778 } else {
1779 shift128RightJamming(axsig0, axsig1, 1,
1780 &axsig0, &axsig1);
1781 shift128RightJamming(adj_sig0, adj_sig1,
1782 axexp - adj_exp + 1,
1783 &adj_sig0, &adj_sig1);
1784 rexp = axexp + 1;
1785 }
1786 if (adj_sub) {
1787 sub128(adj_sig0, adj_sig1, axsig0, axsig1,
1788 &rsig0, &rsig1);
1789 } else {
1790 add128(adj_sig0, adj_sig1, axsig0, axsig1,
1791 &rsig0, &rsig1);
1792 }
1793 }
1794
1795 set_float_rounding_mode(save_mode, &env->fp_status);
1796 set_floatx80_rounding_precision(save_prec, &env->fp_status);
1797 }
1798 /* This result is inexact. */
1799 rsig1 |= 1;
1800 ST1 = normalizeRoundAndPackFloatx80(floatx80_precision_x, rsign, rexp,
1801 rsig0, rsig1, &env->fp_status);
1802 }
1803
1804 fpop(env);
1805 merge_exception_flags(env, old_flags);
1806 }
1807
1808 void helper_fxtract(CPUX86State *env)
1809 {
1810 int old_flags = save_exception_flags(env);
1811 CPU_LDoubleU temp;
1812
1813 temp.d = ST0;
1814
1815 if (floatx80_is_zero(ST0)) {
1816 /* Easy way to generate -inf and raising division by 0 exception */
1817 ST0 = floatx80_div(floatx80_chs(floatx80_one), floatx80_zero,
1818 &env->fp_status);
1819 fpush(env);
1820 ST0 = temp.d;
1821 } else if (floatx80_invalid_encoding(ST0, &env->fp_status)) {
1822 float_raise(float_flag_invalid, &env->fp_status);
1823 ST0 = floatx80_default_nan(&env->fp_status);
1824 fpush(env);
1825 ST0 = ST1;
1826 } else if (floatx80_is_any_nan(ST0)) {
1827 if (floatx80_is_signaling_nan(ST0, &env->fp_status)) {
1828 float_raise(float_flag_invalid, &env->fp_status);
1829 ST0 = floatx80_silence_nan(ST0, &env->fp_status);
1830 }
1831 fpush(env);
1832 ST0 = ST1;
1833 } else if (floatx80_is_infinity(ST0, &env->fp_status)) {
1834 fpush(env);
1835 ST0 = ST1;
1836 ST1 = floatx80_default_inf(0, &env->fp_status);
1837 } else {
1838 int expdif;
1839
1840 if (EXPD(temp) == 0) {
1841 int shift = clz64(temp.l.lower);
1842 temp.l.lower <<= shift;
1843 expdif = 1 - EXPBIAS - shift;
1844 float_raise(float_flag_input_denormal_flushed, &env->fp_status);
1845 } else {
1846 expdif = EXPD(temp) - EXPBIAS;
1847 }
1848 /* DP exponent bias */
1849 ST0 = int32_to_floatx80(expdif, &env->fp_status);
1850 fpush(env);
1851 BIASEXPONENT(temp);
1852 ST0 = temp.d;
1853 }
1854 merge_exception_flags(env, old_flags);
1855 }
1856
1857 static void helper_fprem_common(CPUX86State *env, bool mod)
1858 {
1859 int old_flags = save_exception_flags(env);
1860 uint64_t quotient;
1861 CPU_LDoubleU temp0, temp1;
1862 int exp0, exp1, expdiff;
1863
1864 temp0.d = ST0;
1865 temp1.d = ST1;
1866 exp0 = EXPD(temp0);
1867 exp1 = EXPD(temp1);
1868
1869 env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
1870 if (floatx80_is_zero(ST0) || floatx80_is_zero(ST1) ||
1871 exp0 == 0x7fff || exp1 == 0x7fff ||
1872 floatx80_invalid_encoding(ST0, &env->fp_status) ||
1873 floatx80_invalid_encoding(ST1, &env->fp_status)) {
1874 ST0 = floatx80_modrem(ST0, ST1, mod, &quotient, &env->fp_status);
1875 } else {
1876 if (exp0 == 0) {
1877 exp0 = 1 - clz64(temp0.l.lower);
1878 }
1879 if (exp1 == 0) {
1880 exp1 = 1 - clz64(temp1.l.lower);
1881 }
1882 expdiff = exp0 - exp1;
1883 if (expdiff < 64) {
1884 ST0 = floatx80_modrem(ST0, ST1, mod, &quotient, &env->fp_status);
1885 env->fpus |= (quotient & 0x4) << (8 - 2); /* (C0) <-- q2 */
1886 env->fpus |= (quotient & 0x2) << (14 - 1); /* (C3) <-- q1 */
1887 env->fpus |= (quotient & 0x1) << (9 - 0); /* (C1) <-- q0 */
1888 } else {
1889 /*
1890 * Partial remainder. This choice of how many bits to
1891 * process at once is specified in AMD instruction set
1892 * manuals, and empirically is followed by Intel
1893 * processors as well; it ensures that the final remainder
1894 * operation in a loop does produce the correct low three
1895 * bits of the quotient. AMD manuals specify that the
1896 * flags other than C2 are cleared, and empirically Intel
1897 * processors clear them as well.
1898 */
1899 int n = 32 + (expdiff % 32);
1900 temp1.d = floatx80_scalbn(temp1.d, expdiff - n, &env->fp_status);
1901 ST0 = floatx80_mod(ST0, temp1.d, &env->fp_status);
1902 env->fpus |= 0x400; /* C2 <-- 1 */
1903 }
1904 }
1905 merge_exception_flags(env, old_flags);
1906 }
1907
1908 void helper_fprem1(CPUX86State *env)
1909 {
1910 helper_fprem_common(env, false);
1911 }
1912
1913 void helper_fprem(CPUX86State *env)
1914 {
1915 helper_fprem_common(env, true);
1916 }
1917
1918 /* 128-bit significand of log2(e). */
1919 #define log2_e_sig_high 0xb8aa3b295c17f0bbULL
1920 #define log2_e_sig_low 0xbe87fed0691d3e89ULL
1921
1922 /*
1923 * Polynomial coefficients for an approximation to log2((1+x)/(1-x)),
1924 * with only odd powers of x used, for x in the interval [2*sqrt(2)-3,
1925 * 3-2*sqrt(2)], which corresponds to logarithms of numbers in the
1926 * interval [sqrt(2)/2, sqrt(2)].
1927 */
1928 #define fyl2x_coeff_0 make_floatx80(0x4000, 0xb8aa3b295c17f0bcULL)
1929 #define fyl2x_coeff_0_low make_floatx80(0xbfbf, 0x834972fe2d7bab1bULL)
1930 #define fyl2x_coeff_1 make_floatx80(0x3ffe, 0xf6384ee1d01febb8ULL)
1931 #define fyl2x_coeff_2 make_floatx80(0x3ffe, 0x93bb62877cdfa2e3ULL)
1932 #define fyl2x_coeff_3 make_floatx80(0x3ffd, 0xd30bb153d808f269ULL)
1933 #define fyl2x_coeff_4 make_floatx80(0x3ffd, 0xa42589eaf451499eULL)
1934 #define fyl2x_coeff_5 make_floatx80(0x3ffd, 0x864d42c0f8f17517ULL)
1935 #define fyl2x_coeff_6 make_floatx80(0x3ffc, 0xe3476578adf26272ULL)
1936 #define fyl2x_coeff_7 make_floatx80(0x3ffc, 0xc506c5f874e6d80fULL)
1937 #define fyl2x_coeff_8 make_floatx80(0x3ffc, 0xac5cf50cc57d6372ULL)
1938 #define fyl2x_coeff_9 make_floatx80(0x3ffc, 0xb1ed0066d971a103ULL)
1939
1940 /*
1941 * Compute an approximation of log2(1+arg), where 1+arg is in the
1942 * interval [sqrt(2)/2, sqrt(2)]. It is assumed that when this
1943 * function is called, rounding precision is set to 80 and the
1944 * round-to-nearest mode is in effect. arg must not be exactly zero,
1945 * and must not be so close to zero that underflow might occur.
1946 */
1947 static void helper_fyl2x_common(CPUX86State *env, floatx80 arg, int32_t *exp,
1948 uint64_t *sig0, uint64_t *sig1)
1949 {
1950 uint64_t arg0_sig = extractFloatx80Frac(arg);
1951 int32_t arg0_exp = extractFloatx80Exp(arg);
1952 bool arg0_sign = extractFloatx80Sign(arg);
1953 bool asign;
1954 int32_t dexp, texp, aexp;
1955 uint64_t dsig0, dsig1, tsig0, tsig1, rsig0, rsig1, rsig2;
1956 uint64_t msig0, msig1, msig2, t2sig0, t2sig1, t2sig2, t2sig3;
1957 uint64_t asig0, asig1, asig2, asig3, bsig0, bsig1;
1958 floatx80 t2, accum;
1959
1960 /*
1961 * Compute an approximation of arg/(2+arg), with extra precision,
1962 * as the argument to a polynomial approximation. The extra
1963 * precision is only needed for the first term of the
1964 * approximation, with subsequent terms being significantly
1965 * smaller; the approximation only uses odd exponents, and the
1966 * square of arg/(2+arg) is at most 17-12*sqrt(2) = 0.029....
1967 */
1968 if (arg0_sign) {
1969 dexp = 0x3fff;
1970 shift128RightJamming(arg0_sig, 0, dexp - arg0_exp, &dsig0, &dsig1);
1971 sub128(0, 0, dsig0, dsig1, &dsig0, &dsig1);
1972 } else {
1973 dexp = 0x4000;
1974 shift128RightJamming(arg0_sig, 0, dexp - arg0_exp, &dsig0, &dsig1);
1975 dsig0 |= 0x8000000000000000ULL;
1976 }
1977 texp = arg0_exp - dexp + 0x3ffe;
1978 rsig0 = arg0_sig;
1979 rsig1 = 0;
1980 rsig2 = 0;
1981 if (dsig0 <= rsig0) {
1982 shift128Right(rsig0, rsig1, 1, &rsig0, &rsig1);
1983 ++texp;
1984 }
1985 tsig0 = estimateDiv128To64(rsig0, rsig1, dsig0);
1986 mul128By64To192(dsig0, dsig1, tsig0, &msig0, &msig1, &msig2);
1987 sub192(rsig0, rsig1, rsig2, msig0, msig1, msig2,
1988 &rsig0, &rsig1, &rsig2);
1989 while ((int64_t) rsig0 < 0) {
1990 --tsig0;
1991 add192(rsig0, rsig1, rsig2, 0, dsig0, dsig1,
1992 &rsig0, &rsig1, &rsig2);
1993 }
1994 tsig1 = estimateDiv128To64(rsig1, rsig2, dsig0);
1995 /*
1996 * No need to correct any estimation error in tsig1; even with
1997 * such error, it is accurate enough. Now compute the square of
1998 * that approximation.
1999 */
2000 mul128To256(tsig0, tsig1, tsig0, tsig1,
2001 &t2sig0, &t2sig1, &t2sig2, &t2sig3);
2002 t2 = normalizeRoundAndPackFloatx80(floatx80_precision_x, false,
2003 texp + texp - 0x3ffe,
2004 t2sig0, t2sig1, &env->fp_status);
2005
2006 /* Compute the lower parts of the polynomial expansion. */
2007 accum = floatx80_mul(fyl2x_coeff_9, t2, &env->fp_status);
2008 accum = floatx80_add(fyl2x_coeff_8, accum, &env->fp_status);
2009 accum = floatx80_mul(accum, t2, &env->fp_status);
2010 accum = floatx80_add(fyl2x_coeff_7, accum, &env->fp_status);
2011 accum = floatx80_mul(accum, t2, &env->fp_status);
2012 accum = floatx80_add(fyl2x_coeff_6, accum, &env->fp_status);
2013 accum = floatx80_mul(accum, t2, &env->fp_status);
2014 accum = floatx80_add(fyl2x_coeff_5, accum, &env->fp_status);
2015 accum = floatx80_mul(accum, t2, &env->fp_status);
2016 accum = floatx80_add(fyl2x_coeff_4, accum, &env->fp_status);
2017 accum = floatx80_mul(accum, t2, &env->fp_status);
2018 accum = floatx80_add(fyl2x_coeff_3, accum, &env->fp_status);
2019 accum = floatx80_mul(accum, t2, &env->fp_status);
2020 accum = floatx80_add(fyl2x_coeff_2, accum, &env->fp_status);
2021 accum = floatx80_mul(accum, t2, &env->fp_status);
2022 accum = floatx80_add(fyl2x_coeff_1, accum, &env->fp_status);
2023 accum = floatx80_mul(accum, t2, &env->fp_status);
2024 accum = floatx80_add(fyl2x_coeff_0_low, accum, &env->fp_status);
2025
2026 /*
2027 * The full polynomial expansion is fyl2x_coeff_0 + accum (where
2028 * accum has much lower magnitude, and so, in particular, carry
2029 * out of the addition is not possible), multiplied by t. (This
2030 * expansion is only accurate to about 70 bits, not 128 bits.)
2031 */
2032 aexp = extractFloatx80Exp(fyl2x_coeff_0);
2033 asign = extractFloatx80Sign(fyl2x_coeff_0);
2034 shift128RightJamming(extractFloatx80Frac(accum), 0,
2035 aexp - extractFloatx80Exp(accum),
2036 &asig0, &asig1);
2037 bsig0 = extractFloatx80Frac(fyl2x_coeff_0);
2038 bsig1 = 0;
2039 if (asign == extractFloatx80Sign(accum)) {
2040 add128(bsig0, bsig1, asig0, asig1, &asig0, &asig1);
2041 } else {
2042 sub128(bsig0, bsig1, asig0, asig1, &asig0, &asig1);
2043 }
2044 /* Multiply by t to compute the required result. */
2045 mul128To256(asig0, asig1, tsig0, tsig1,
2046 &asig0, &asig1, &asig2, &asig3);
2047 aexp += texp - 0x3ffe;
2048 *exp = aexp;
2049 *sig0 = asig0;
2050 *sig1 = asig1;
2051 }
2052
2053 void helper_fyl2xp1(CPUX86State *env)
2054 {
2055 int old_flags = save_exception_flags(env);
2056 uint64_t arg0_sig = extractFloatx80Frac(ST0);
2057 int32_t arg0_exp = extractFloatx80Exp(ST0);
2058 bool arg0_sign = extractFloatx80Sign(ST0);
2059 uint64_t arg1_sig = extractFloatx80Frac(ST1);
2060 int32_t arg1_exp = extractFloatx80Exp(ST1);
2061 bool arg1_sign = extractFloatx80Sign(ST1);
2062
2063 if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
2064 floatx80_invalid_encoding(ST1, &env->fp_status)) {
2065 float_raise(float_flag_invalid, &env->fp_status);
2066 ST1 = floatx80_default_nan(&env->fp_status);
2067 } else if (floatx80_is_signaling_nan(ST0, &env->fp_status)) {
2068 float_raise(float_flag_invalid, &env->fp_status);
2069 ST1 = floatx80_silence_nan(ST0, &env->fp_status);
2070 } else if (floatx80_is_signaling_nan(ST1, &env->fp_status)) {
2071 float_raise(float_flag_invalid, &env->fp_status);
2072 ST1 = floatx80_silence_nan(ST1, &env->fp_status);
2073 } else if (floatx80_is_any_nan(ST0)) {
2074 ST1 = ST0;
2075 } else if (floatx80_is_any_nan(ST1)) {
2076 /* Pass this NaN through. */
2077 } else if (arg0_exp > 0x3ffd ||
2078 (arg0_exp == 0x3ffd && arg0_sig > (arg0_sign ?
2079 0x95f619980c4336f7ULL :
2080 0xd413cccfe7799211ULL))) {
2081 /*
2082 * Out of range for the instruction (ST0 must have absolute
2083 * value less than 1 - sqrt(2)/2 = 0.292..., according to
2084 * Intel manuals; AMD manuals allow a range from sqrt(2)/2 - 1
2085 * to sqrt(2) - 1, which we allow here), treat as invalid.
2086 */
2087 float_raise(float_flag_invalid, &env->fp_status);
2088 ST1 = floatx80_default_nan(&env->fp_status);
2089 } else if (floatx80_is_zero(ST0) || floatx80_is_zero(ST1) ||
2090 arg1_exp == 0x7fff) {
2091 /*
2092 * One argument is zero, or multiplying by infinity; correct
2093 * result is exact and can be obtained by multiplying the
2094 * arguments.
2095 */
2096 ST1 = floatx80_mul(ST0, ST1, &env->fp_status);
2097 } else if (arg0_exp < 0x3fb0) {
2098 /*
2099 * Multiplying both arguments and an extra-precision version
2100 * of log2(e) is sufficiently precise.
2101 */
2102 uint64_t sig0, sig1, sig2;
2103 int32_t exp;
2104 if (arg0_exp == 0) {
2105 normalizeFloatx80Subnormal(arg0_sig, &arg0_exp, &arg0_sig);
2106 }
2107 if (arg1_exp == 0) {
2108 normalizeFloatx80Subnormal(arg1_sig, &arg1_exp, &arg1_sig);
2109 }
2110 mul128By64To192(log2_e_sig_high, log2_e_sig_low, arg0_sig,
2111 &sig0, &sig1, &sig2);
2112 exp = arg0_exp + 1;
2113 mul128By64To192(sig0, sig1, arg1_sig, &sig0, &sig1, &sig2);
2114 exp += arg1_exp - 0x3ffe;
2115 /* This result is inexact. */
2116 sig1 |= 1;
2117 ST1 = normalizeRoundAndPackFloatx80(floatx80_precision_x,
2118 arg0_sign ^ arg1_sign, exp,
2119 sig0, sig1, &env->fp_status);
2120 } else {
2121 int32_t aexp;
2122 uint64_t asig0, asig1, asig2;
2123 FloatRoundMode save_mode = get_float_rounding_mode(&env->fp_status);
2124 FloatX80RoundPrec save_prec =
2125 get_floatx80_rounding_precision(&env->fp_status);
2126 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
2127 set_floatx80_rounding_precision(floatx80_precision_x, &env->fp_status);
2128
2129 helper_fyl2x_common(env, ST0, &aexp, &asig0, &asig1);
2130 /*
2131 * Multiply by the second argument to compute the required
2132 * result.
2133 */
2134 if (arg1_exp == 0) {
2135 normalizeFloatx80Subnormal(arg1_sig, &arg1_exp, &arg1_sig);
2136 }
2137 mul128By64To192(asig0, asig1, arg1_sig, &asig0, &asig1, &asig2);
2138 aexp += arg1_exp - 0x3ffe;
2139 /* This result is inexact. */
2140 asig1 |= 1;
2141 set_float_rounding_mode(save_mode, &env->fp_status);
2142 ST1 = normalizeRoundAndPackFloatx80(floatx80_precision_x,
2143 arg0_sign ^ arg1_sign, aexp,
2144 asig0, asig1, &env->fp_status);
2145 set_floatx80_rounding_precision(save_prec, &env->fp_status);
2146 }
2147 fpop(env);
2148 merge_exception_flags(env, old_flags);
2149 }
2150
2151 void helper_fyl2x(CPUX86State *env)
2152 {
2153 int old_flags = save_exception_flags(env);
2154 uint64_t arg0_sig = extractFloatx80Frac(ST0);
2155 int32_t arg0_exp = extractFloatx80Exp(ST0);
2156 bool arg0_sign = extractFloatx80Sign(ST0);
2157 uint64_t arg1_sig = extractFloatx80Frac(ST1);
2158 int32_t arg1_exp = extractFloatx80Exp(ST1);
2159 bool arg1_sign = extractFloatx80Sign(ST1);
2160
2161 if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
2162 floatx80_invalid_encoding(ST1, &env->fp_status)) {
2163 float_raise(float_flag_invalid, &env->fp_status);
2164 ST1 = floatx80_default_nan(&env->fp_status);
2165 } else if (floatx80_is_signaling_nan(ST0, &env->fp_status)) {
2166 float_raise(float_flag_invalid, &env->fp_status);
2167 ST1 = floatx80_silence_nan(ST0, &env->fp_status);
2168 } else if (floatx80_is_signaling_nan(ST1, &env->fp_status)) {
2169 float_raise(float_flag_invalid, &env->fp_status);
2170 ST1 = floatx80_silence_nan(ST1, &env->fp_status);
2171 } else if (floatx80_is_any_nan(ST0)) {
2172 ST1 = ST0;
2173 } else if (floatx80_is_any_nan(ST1)) {
2174 /* Pass this NaN through. */
2175 } else if (arg0_sign && !floatx80_is_zero(ST0)) {
2176 float_raise(float_flag_invalid, &env->fp_status);
2177 ST1 = floatx80_default_nan(&env->fp_status);
2178 } else if (floatx80_is_infinity(ST1, &env->fp_status)) {
2179 FloatRelation cmp = floatx80_compare(ST0, floatx80_one,
2180 &env->fp_status);
2181 switch (cmp) {
2182 case float_relation_less:
2183 ST1 = floatx80_chs(ST1);
2184 break;
2185 case float_relation_greater:
2186 /* Result is infinity of the same sign as ST1. */
2187 break;
2188 default:
2189 float_raise(float_flag_invalid, &env->fp_status);
2190 ST1 = floatx80_default_nan(&env->fp_status);
2191 break;
2192 }
2193 } else if (floatx80_is_infinity(ST0, &env->fp_status)) {
2194 if (floatx80_is_zero(ST1)) {
2195 float_raise(float_flag_invalid, &env->fp_status);
2196 ST1 = floatx80_default_nan(&env->fp_status);
2197 } else if (arg1_sign) {
2198 ST1 = floatx80_chs(ST0);
2199 } else {
2200 ST1 = ST0;
2201 }
2202 } else if (floatx80_is_zero(ST0)) {
2203 if (floatx80_is_zero(ST1)) {
2204 float_raise(float_flag_invalid, &env->fp_status);
2205 ST1 = floatx80_default_nan(&env->fp_status);
2206 } else {
2207 /* Result is infinity with opposite sign to ST1. */
2208 float_raise(float_flag_divbyzero, &env->fp_status);
2209 ST1 = make_floatx80(arg1_sign ? 0x7fff : 0xffff,
2210 0x8000000000000000ULL);
2211 }
2212 } else if (floatx80_is_zero(ST1)) {
2213 if (floatx80_lt(ST0, floatx80_one, &env->fp_status)) {
2214 ST1 = floatx80_chs(ST1);
2215 }
2216 /* Otherwise, ST1 is already the correct result. */
2217 } else if (floatx80_eq(ST0, floatx80_one, &env->fp_status)) {
2218 if (arg1_sign) {
2219 ST1 = floatx80_chs(floatx80_zero);
2220 } else {
2221 ST1 = floatx80_zero;
2222 }
2223 } else {
2224 int32_t int_exp;
2225 floatx80 arg0_m1;
2226 FloatRoundMode save_mode = get_float_rounding_mode(&env->fp_status);
2227 FloatX80RoundPrec save_prec =
2228 get_floatx80_rounding_precision(&env->fp_status);
2229 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
2230 set_floatx80_rounding_precision(floatx80_precision_x, &env->fp_status);
2231
2232 if (arg0_exp == 0) {
2233 normalizeFloatx80Subnormal(arg0_sig, &arg0_exp, &arg0_sig);
2234 }
2235 if (arg1_exp == 0) {
2236 normalizeFloatx80Subnormal(arg1_sig, &arg1_exp, &arg1_sig);
2237 }
2238 int_exp = arg0_exp - 0x3fff;
2239 if (arg0_sig > 0xb504f333f9de6484ULL) {
2240 ++int_exp;
2241 }
2242 arg0_m1 = floatx80_sub(floatx80_scalbn(ST0, -int_exp,
2243 &env->fp_status),
2244 floatx80_one, &env->fp_status);
2245 if (floatx80_is_zero(arg0_m1)) {
2246 /* Exact power of 2; multiply by ST1. */
2247 set_float_rounding_mode(save_mode, &env->fp_status);
2248 ST1 = floatx80_mul(int32_to_floatx80(int_exp, &env->fp_status),
2249 ST1, &env->fp_status);
2250 } else {
2251 bool asign = extractFloatx80Sign(arg0_m1);
2252 int32_t aexp;
2253 uint64_t asig0, asig1, asig2;
2254 helper_fyl2x_common(env, arg0_m1, &aexp, &asig0, &asig1);
2255 if (int_exp != 0) {
2256 bool isign = (int_exp < 0);
2257 int32_t iexp;
2258 uint64_t isig;
2259 int shift;
2260 int_exp = isign ? -int_exp : int_exp;
2261 shift = clz32(int_exp) + 32;
2262 isig = int_exp;
2263 isig <<= shift;
2264 iexp = 0x403e - shift;
2265 shift128RightJamming(asig0, asig1, iexp - aexp,
2266 &asig0, &asig1);
2267 if (asign == isign) {
2268 add128(isig, 0, asig0, asig1, &asig0, &asig1);
2269 } else {
2270 sub128(isig, 0, asig0, asig1, &asig0, &asig1);
2271 }
2272 aexp = iexp;
2273 asign = isign;
2274 }
2275 /*
2276 * Multiply by the second argument to compute the required
2277 * result.
2278 */
2279 if (arg1_exp == 0) {
2280 normalizeFloatx80Subnormal(arg1_sig, &arg1_exp, &arg1_sig);
2281 }
2282 mul128By64To192(asig0, asig1, arg1_sig, &asig0, &asig1, &asig2);
2283 aexp += arg1_exp - 0x3ffe;
2284 /* This result is inexact. */
2285 asig1 |= 1;
2286 set_float_rounding_mode(save_mode, &env->fp_status);
2287 ST1 = normalizeRoundAndPackFloatx80(floatx80_precision_x,
2288 asign ^ arg1_sign, aexp,
2289 asig0, asig1, &env->fp_status);
2290 }
2291
2292 set_floatx80_rounding_precision(save_prec, &env->fp_status);
2293 }
2294 fpop(env);
2295 merge_exception_flags(env, old_flags);
2296 }
2297
2298 void helper_fsqrt(CPUX86State *env)
2299 {
2300 int old_flags = save_exception_flags(env);
2301 if (floatx80_is_neg(ST0)) {
2302 env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
2303 env->fpus |= 0x400;
2304 }
2305 ST0 = floatx80_sqrt(ST0, &env->fp_status);
2306 merge_exception_flags(env, old_flags);
2307 }
2308
2309 void helper_fsincos(CPUX86State *env)
2310 {
2311 double fptemp = floatx80_to_double(env, ST0);
2312
2313 if ((fptemp > MAXTAN) || (fptemp < -MAXTAN)) {
2314 env->fpus |= 0x400;
2315 } else {
2316 ST0 = double_to_floatx80(env, sin(fptemp));
2317 fpush(env);
2318 ST0 = double_to_floatx80(env, cos(fptemp));
2319 env->fpus &= ~0x400; /* C2 <-- 0 */
2320 /* the above code is for |arg| < 2**63 only */
2321 }
2322 }
2323
2324 void helper_frndint(CPUX86State *env)
2325 {
2326 int old_flags = save_exception_flags(env);
2327 ST0 = floatx80_round_to_int(ST0, &env->fp_status);
2328 merge_exception_flags(env, old_flags);
2329 }
2330
2331 void helper_fscale(CPUX86State *env)
2332 {
2333 int old_flags = save_exception_flags(env);
2334 if (floatx80_invalid_encoding(ST1, &env->fp_status) ||
2335 floatx80_invalid_encoding(ST0, &env->fp_status)) {
2336 float_raise(float_flag_invalid, &env->fp_status);
2337 ST0 = floatx80_default_nan(&env->fp_status);
2338 } else if (floatx80_is_any_nan(ST1)) {
2339 if (floatx80_is_signaling_nan(ST0, &env->fp_status)) {
2340 float_raise(float_flag_invalid, &env->fp_status);
2341 }
2342 ST0 = ST1;
2343 if (floatx80_is_signaling_nan(ST0, &env->fp_status)) {
2344 float_raise(float_flag_invalid, &env->fp_status);
2345 ST0 = floatx80_silence_nan(ST0, &env->fp_status);
2346 }
2347 } else if (floatx80_is_infinity(ST1, &env->fp_status) &&
2348 !floatx80_invalid_encoding(ST0, &env->fp_status) &&
2349 !floatx80_is_any_nan(ST0)) {
2350 if (floatx80_is_neg(ST1)) {
2351 if (floatx80_is_infinity(ST0, &env->fp_status)) {
2352 float_raise(float_flag_invalid, &env->fp_status);
2353 ST0 = floatx80_default_nan(&env->fp_status);
2354 } else {
2355 ST0 = (floatx80_is_neg(ST0) ?
2356 floatx80_chs(floatx80_zero) :
2357 floatx80_zero);
2358 }
2359 } else {
2360 if (floatx80_is_zero(ST0)) {
2361 float_raise(float_flag_invalid, &env->fp_status);
2362 ST0 = floatx80_default_nan(&env->fp_status);
2363 } else {
2364 ST0 = floatx80_default_inf(floatx80_is_neg(ST0),
2365 &env->fp_status);
2366 }
2367 }
2368 } else {
2369 int n;
2370 FloatX80RoundPrec save = get_floatx80_rounding_precision(&env->fp_status);
2371 int save_flags = get_float_exception_flags(&env->fp_status);
2372 set_float_exception_flags(0, &env->fp_status);
2373 n = floatx80_to_int32_round_to_zero(ST1, &env->fp_status);
2374 set_float_exception_flags(save_flags, &env->fp_status);
2375 set_floatx80_rounding_precision(floatx80_precision_x, &env->fp_status);
2376 ST0 = floatx80_scalbn(ST0, n, &env->fp_status);
2377 set_floatx80_rounding_precision(save, &env->fp_status);
2378 }
2379 merge_exception_flags(env, old_flags);
2380 }
2381
2382 void helper_fsin(CPUX86State *env)
2383 {
2384 double fptemp = floatx80_to_double(env, ST0);
2385
2386 if ((fptemp > MAXTAN) || (fptemp < -MAXTAN)) {
2387 env->fpus |= 0x400;
2388 } else {
2389 ST0 = double_to_floatx80(env, sin(fptemp));
2390 env->fpus &= ~0x400; /* C2 <-- 0 */
2391 /* the above code is for |arg| < 2**53 only */
2392 }
2393 }
2394
2395 void helper_fcos(CPUX86State *env)
2396 {
2397 double fptemp = floatx80_to_double(env, ST0);
2398
2399 if ((fptemp > MAXTAN) || (fptemp < -MAXTAN)) {
2400 env->fpus |= 0x400;
2401 } else {
2402 ST0 = double_to_floatx80(env, cos(fptemp));
2403 env->fpus &= ~0x400; /* C2 <-- 0 */
2404 /* the above code is for |arg| < 2**63 only */
2405 }
2406 }
2407
2408 void helper_fxam_ST0(CPUX86State *env)
2409 {
2410 CPU_LDoubleU temp;
2411 int expdif;
2412
2413 temp.d = ST0;
2414
2415 env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
2416 if (SIGND(temp)) {
2417 env->fpus |= 0x200; /* C1 <-- 1 */
2418 }
2419
2420 if (env->fptags[env->fpstt]) {
2421 env->fpus |= 0x4100; /* Empty */
2422 return;
2423 }
2424
2425 expdif = EXPD(temp);
2426 if (expdif == MAXEXPD) {
2427 if (MANTD(temp) == 0x8000000000000000ULL) {
2428 env->fpus |= 0x500; /* Infinity */
2429 } else if (MANTD(temp) & 0x8000000000000000ULL) {
2430 env->fpus |= 0x100; /* NaN */
2431 }
2432 } else if (expdif == 0) {
2433 if (MANTD(temp) == 0) {
2434 env->fpus |= 0x4000; /* Zero */
2435 } else {
2436 env->fpus |= 0x4400; /* Denormal */
2437 }
2438 } else if (MANTD(temp) & 0x8000000000000000ULL) {
2439 env->fpus |= 0x400;
2440 }
2441 }
2442
2443 static void do_fstenv(X86Access *ac, target_ulong ptr, int data32)
2444 {
2445 CPUX86State *env = ac->env;
2446 int fpus, fptag, exp, i;
2447 uint64_t mant;
2448 CPU_LDoubleU tmp;
2449
2450 fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2451 fptag = 0;
2452 for (i = 7; i >= 0; i--) {
2453 fptag <<= 2;
2454 if (env->fptags[i]) {
2455 fptag |= 3;
2456 } else {
2457 tmp.d = env->fpregs[i].d;
2458 exp = EXPD(tmp);
2459 mant = MANTD(tmp);
2460 if (exp == 0 && mant == 0) {
2461 /* zero */
2462 fptag |= 1;
2463 } else if (exp == 0 || exp == MAXEXPD
2464 || (mant & (1LL << 63)) == 0) {
2465 /* NaNs, infinity, denormal */
2466 fptag |= 2;
2467 }
2468 }
2469 }
2470 if (data32) {
2471 /* 32 bit */
2472 access_stl(ac, ptr, env->fpuc);
2473 access_stl(ac, ptr + 4, fpus);
2474 access_stl(ac, ptr + 8, fptag);
2475 access_stl(ac, ptr + 12, env->fpip); /* fpip */
2476 access_stl(ac, ptr + 16, env->fpcs); /* fpcs */
2477 access_stl(ac, ptr + 20, env->fpdp); /* fpoo */
2478 access_stl(ac, ptr + 24, env->fpds); /* fpos */
2479 } else {
2480 /* 16 bit */
2481 access_stw(ac, ptr, env->fpuc);
2482 access_stw(ac, ptr + 2, fpus);
2483 access_stw(ac, ptr + 4, fptag);
2484 access_stw(ac, ptr + 6, env->fpip);
2485 access_stw(ac, ptr + 8, env->fpcs);
2486 access_stw(ac, ptr + 10, env->fpdp);
2487 access_stw(ac, ptr + 12, env->fpds);
2488 }
2489 }
2490
2491 void helper_fstenv(CPUX86State *env, target_ulong ptr, int data32)
2492 {
2493 X86Access ac;
2494
2495 access_prepare(&ac, env, ptr, 14 << data32, MMU_DATA_STORE, GETPC());
2496 do_fstenv(&ac, ptr, data32);
2497 }
2498
2499 static void cpu_set_fpus(CPUX86State *env, uint16_t fpus)
2500 {
2501 env->fpstt = (fpus >> 11) & 7;
2502 env->fpus = fpus & ~0x3800 & ~FPUS_B;
2503 env->fpus |= env->fpus & FPUS_SE ? FPUS_B : 0;
2504 #if !defined(CONFIG_USER_ONLY)
2505 if (!(env->fpus & FPUS_SE)) {
2506 /*
2507 * Here the processor deasserts FERR#; in response, the chipset deasserts
2508 * IGNNE#.
2509 */
2510 cpu_clear_ignne();
2511 }
2512 #endif
2513 }
2514
2515 static void do_fldenv(X86Access *ac, target_ulong ptr, int data32)
2516 {
2517 int i, fpus, fptag;
2518 CPUX86State *env = ac->env;
2519
2520 cpu_set_fpuc(env, access_ldw(ac, ptr));
2521 fpus = access_ldw(ac, ptr + (2 << data32));
2522 fptag = access_ldw(ac, ptr + (4 << data32));
2523
2524 cpu_set_fpus(env, fpus);
2525 for (i = 0; i < 8; i++) {
2526 env->fptags[i] = ((fptag & 3) == 3);
2527 fptag >>= 2;
2528 }
2529 }
2530
2531 void helper_fldenv(CPUX86State *env, target_ulong ptr, int data32)
2532 {
2533 X86Access ac;
2534
2535 access_prepare(&ac, env, ptr, 14 << data32, MMU_DATA_STORE, GETPC());
2536 do_fldenv(&ac, ptr, data32);
2537 }
2538
2539 static void do_fsave(X86Access *ac, target_ulong ptr, int data32)
2540 {
2541 CPUX86State *env = ac->env;
2542
2543 do_fstenv(ac, ptr, data32);
2544 ptr += 14 << data32;
2545
2546 for (int i = 0; i < 8; i++) {
2547 floatx80 tmp = ST(i);
2548 do_fstt(ac, ptr, tmp);
2549 ptr += 10;
2550 }
2551
2552 do_fninit(env);
2553 }
2554
2555 void helper_fsave(CPUX86State *env, target_ulong ptr, int data32)
2556 {
2557 int size = (14 << data32) + 80;
2558 X86Access ac;
2559
2560 access_prepare(&ac, env, ptr, size, MMU_DATA_STORE, GETPC());
2561 do_fsave(&ac, ptr, data32);
2562 }
2563
2564 static void do_frstor(X86Access *ac, target_ulong ptr, int data32)
2565 {
2566 CPUX86State *env = ac->env;
2567
2568 do_fldenv(ac, ptr, data32);
2569 ptr += 14 << data32;
2570
2571 for (int i = 0; i < 8; i++) {
2572 floatx80 tmp = do_fldt(ac, ptr);
2573 ST(i) = tmp;
2574 ptr += 10;
2575 }
2576 }
2577
2578 void helper_frstor(CPUX86State *env, target_ulong ptr, int data32)
2579 {
2580 int size = (14 << data32) + 80;
2581 X86Access ac;
2582
2583 access_prepare(&ac, env, ptr, size, MMU_DATA_LOAD, GETPC());
2584 do_frstor(&ac, ptr, data32);
2585 }
2586
2587 #define XO(X) offsetof(X86XSaveArea, X)
2588
2589 static void do_xsave_fpu(X86Access *ac, target_ulong ptr)
2590 {
2591 CPUX86State *env = ac->env;
2592 int fpus, fptag, i;
2593 target_ulong addr;
2594
2595 fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2596 fptag = 0;
2597 for (i = 0; i < 8; i++) {
2598 fptag |= (env->fptags[i] << i);
2599 }
2600
2601 access_stw(ac, ptr + XO(legacy.fcw), env->fpuc);
2602 access_stw(ac, ptr + XO(legacy.fsw), fpus);
2603 access_stw(ac, ptr + XO(legacy.ftw), fptag ^ 0xff);
2604
2605 /* In 32-bit mode this is eip, sel, dp, sel.
2606 In 64-bit mode this is rip, rdp.
2607 But in either case we don't write actual data, just zeros. */
2608 access_stq(ac, ptr + XO(legacy.fpip), 0); /* eip+sel; rip */
2609 access_stq(ac, ptr + XO(legacy.fpdp), 0); /* edp+sel; rdp */
2610
2611 addr = ptr + XO(legacy.fpregs);
2612
2613 for (i = 0; i < 8; i++) {
2614 floatx80 tmp = ST(i);
2615 do_fstt(ac, addr, tmp);
2616 addr += 16;
2617 }
2618 }
2619
2620 static void do_xsave_mxcsr(X86Access *ac, target_ulong ptr)
2621 {
2622 CPUX86State *env = ac->env;
2623
2624 update_mxcsr_from_sse_status(env);
2625 access_stl(ac, ptr + XO(legacy.mxcsr), env->mxcsr);
2626 access_stl(ac, ptr + XO(legacy.mxcsr_mask), 0x0000ffff);
2627 }
2628
2629 static void do_xsave_sse(X86Access *ac, target_ulong ptr)
2630 {
2631 CPUX86State *env = ac->env;
2632 int i, nb_xmm_regs;
2633 target_ulong addr;
2634
2635 if (env->hflags & HF_CS64_MASK) {
2636 nb_xmm_regs = 16;
2637 } else {
2638 nb_xmm_regs = 8;
2639 }
2640
2641 addr = ptr + XO(legacy.xmm_regs);
2642 for (i = 0; i < nb_xmm_regs; i++) {
2643 access_stq(ac, addr, env->xmm_regs[i].ZMM_Q(0));
2644 access_stq(ac, addr + 8, env->xmm_regs[i].ZMM_Q(1));
2645 addr += 16;
2646 }
2647 }
2648
2649 static void do_xsave_ymmh(X86Access *ac, target_ulong ptr)
2650 {
2651 CPUX86State *env = ac->env;
2652 int i, nb_xmm_regs;
2653
2654 if (env->hflags & HF_CS64_MASK) {
2655 nb_xmm_regs = 16;
2656 } else {
2657 nb_xmm_regs = 8;
2658 }
2659
2660 for (i = 0; i < nb_xmm_regs; i++, ptr += 16) {
2661 access_stq(ac, ptr, env->xmm_regs[i].ZMM_Q(2));
2662 access_stq(ac, ptr + 8, env->xmm_regs[i].ZMM_Q(3));
2663 }
2664 }
2665
2666 static void do_xsave_bndregs(X86Access *ac, target_ulong ptr)
2667 {
2668 CPUX86State *env = ac->env;
2669 target_ulong addr = ptr + offsetof(XSaveBNDREG, bnd_regs);
2670 int i;
2671
2672 for (i = 0; i < 4; i++, addr += 16) {
2673 access_stq(ac, addr, env->bnd_regs[i].lb);
2674 access_stq(ac, addr + 8, env->bnd_regs[i].ub);
2675 }
2676 }
2677
2678 static void do_xsave_bndcsr(X86Access *ac, target_ulong ptr)
2679 {
2680 CPUX86State *env = ac->env;
2681
2682 access_stq(ac, ptr + offsetof(XSaveBNDCSR, bndcsr.cfgu),
2683 env->bndcs_regs.cfgu);
2684 access_stq(ac, ptr + offsetof(XSaveBNDCSR, bndcsr.sts),
2685 env->bndcs_regs.sts);
2686 }
2687
2688 static void do_xsave_pkru(X86Access *ac, target_ulong ptr)
2689 {
2690 access_stq(ac, ptr, ac->env->pkru);
2691 }
2692
2693 static void do_fxsave(X86Access *ac, target_ulong ptr)
2694 {
2695 CPUX86State *env = ac->env;
2696
2697 do_xsave_fpu(ac, ptr);
2698 if (env->cr[4] & CR4_OSFXSR_MASK) {
2699 do_xsave_mxcsr(ac, ptr);
2700 /* Fast FXSAVE leaves out the XMM registers */
2701 if (!(env->efer & MSR_EFER_FFXSR)
2702 || (env->hflags & HF_CPL_MASK)
2703 || !(env->hflags & HF_LMA_MASK)) {
2704 do_xsave_sse(ac, ptr);
2705 }
2706 }
2707 }
2708
2709 void helper_fxsave(CPUX86State *env, target_ulong ptr)
2710 {
2711 uintptr_t ra = GETPC();
2712 X86Access ac;
2713
2714 /* The operand must be 16 byte aligned */
2715 if (ptr & 0xf) {
2716 raise_exception_ra(env, EXCP0D_GPF, ra);
2717 }
2718
2719 access_prepare(&ac, env, ptr, sizeof(X86LegacyXSaveArea),
2720 MMU_DATA_STORE, ra);
2721 do_fxsave(&ac, ptr);
2722 }
2723
2724 static uint64_t get_xinuse(CPUX86State *env)
2725 {
2726 uint64_t inuse = -1;
2727
2728 /* For the most part, we don't track XINUSE. We could calculate it
2729 here for all components, but it's probably less work to simply
2730 indicate in use. That said, the state of BNDREGS is important
2731 enough to track in HFLAGS, so we might as well use that here. */
2732 if ((env->hflags & HF_MPX_IU_MASK) == 0) {
2733 inuse &= ~XSTATE_BNDREGS_MASK;
2734 }
2735 return inuse;
2736 }
2737
2738 static void do_xsave_access(X86Access *ac, target_ulong ptr, uint64_t rfbm,
2739 uint64_t inuse, uint64_t opt)
2740 {
2741 uint64_t old_bv, new_bv;
2742
2743 if (opt & XSTATE_FP_MASK) {
2744 do_xsave_fpu(ac, ptr);
2745 }
2746 if (rfbm & XSTATE_SSE_MASK) {
2747 /* Note that saving MXCSR is not suppressed by XSAVEOPT. */
2748 do_xsave_mxcsr(ac, ptr);
2749 }
2750 if (opt & XSTATE_SSE_MASK) {
2751 do_xsave_sse(ac, ptr);
2752 }
2753 if (opt & XSTATE_YMM_MASK) {
2754 do_xsave_ymmh(ac, ptr + XO(avx_state));
2755 }
2756 if (opt & XSTATE_BNDREGS_MASK) {
2757 do_xsave_bndregs(ac, ptr + XO(bndreg_state));
2758 }
2759 if (opt & XSTATE_BNDCSR_MASK) {
2760 do_xsave_bndcsr(ac, ptr + XO(bndcsr_state));
2761 }
2762 if (opt & XSTATE_PKRU_MASK) {
2763 do_xsave_pkru(ac, ptr + XO(pkru_state));
2764 }
2765
2766 /* Update the XSTATE_BV field. */
2767 old_bv = access_ldq(ac, ptr + XO(header.xstate_bv));
2768 new_bv = (old_bv & ~rfbm) | (inuse & rfbm);
2769 access_stq(ac, ptr + XO(header.xstate_bv), new_bv);
2770 }
2771
2772 static void do_xsave_chk(CPUX86State *env, target_ulong ptr, uintptr_t ra)
2773 {
2774 /* The OS must have enabled XSAVE. */
2775 if (!(env->cr[4] & CR4_OSXSAVE_MASK)) {
2776 raise_exception_ra(env, EXCP06_ILLOP, ra);
2777 }
2778
2779 /* The operand must be 64 byte aligned. */
2780 if (ptr & 63) {
2781 raise_exception_ra(env, EXCP0D_GPF, ra);
2782 }
2783 }
2784
2785 static void do_xsave(CPUX86State *env, target_ulong ptr, uint64_t rfbm,
2786 uint64_t inuse, uint64_t opt, uintptr_t ra)
2787 {
2788 X86Access ac;
2789 unsigned size;
2790
2791 do_xsave_chk(env, ptr, ra);
2792
2793 /* Never save anything not enabled by XCR0. */
2794 rfbm &= env->xcr0;
2795 opt &= rfbm;
2796 size = xsave_area_size(opt, false);
2797
2798 access_prepare(&ac, env, ptr, size, MMU_DATA_STORE, ra);
2799 do_xsave_access(&ac, ptr, rfbm, inuse, opt);
2800 }
2801
2802 void helper_xsave(CPUX86State *env, target_ulong ptr, uint64_t rfbm)
2803 {
2804 do_xsave(env, ptr, rfbm, get_xinuse(env), rfbm, GETPC());
2805 }
2806
2807 void helper_xsaveopt(CPUX86State *env, target_ulong ptr, uint64_t rfbm)
2808 {
2809 uint64_t inuse = get_xinuse(env);
2810 do_xsave(env, ptr, rfbm, inuse, inuse, GETPC());
2811 }
2812
2813 static void do_xrstor_fpu(X86Access *ac, target_ulong ptr)
2814 {
2815 CPUX86State *env = ac->env;
2816 int i, fpuc, fpus, fptag;
2817 target_ulong addr;
2818
2819 fpuc = access_ldw(ac, ptr + XO(legacy.fcw));
2820 fpus = access_ldw(ac, ptr + XO(legacy.fsw));
2821 fptag = access_ldw(ac, ptr + XO(legacy.ftw));
2822 cpu_set_fpuc(env, fpuc);
2823 cpu_set_fpus(env, fpus);
2824
2825 fptag ^= 0xff;
2826 for (i = 0; i < 8; i++) {
2827 env->fptags[i] = ((fptag >> i) & 1);
2828 }
2829
2830 addr = ptr + XO(legacy.fpregs);
2831
2832 for (i = 0; i < 8; i++) {
2833 floatx80 tmp = do_fldt(ac, addr);
2834 ST(i) = tmp;
2835 addr += 16;
2836 }
2837 }
2838
2839 static void do_xrstor_mxcsr(X86Access *ac, target_ulong ptr)
2840 {
2841 CPUX86State *env = ac->env;
2842 cpu_set_mxcsr(env, access_ldl(ac, ptr + XO(legacy.mxcsr)));
2843 }
2844
2845 static void do_xrstor_sse(X86Access *ac, target_ulong ptr)
2846 {
2847 CPUX86State *env = ac->env;
2848 int i, nb_xmm_regs;
2849 target_ulong addr;
2850
2851 if (env->hflags & HF_CS64_MASK) {
2852 nb_xmm_regs = 16;
2853 } else {
2854 nb_xmm_regs = 8;
2855 }
2856
2857 addr = ptr + XO(legacy.xmm_regs);
2858 for (i = 0; i < nb_xmm_regs; i++) {
2859 env->xmm_regs[i].ZMM_Q(0) = access_ldq(ac, addr);
2860 env->xmm_regs[i].ZMM_Q(1) = access_ldq(ac, addr + 8);
2861 addr += 16;
2862 }
2863 }
2864
2865 static void do_clear_sse(CPUX86State *env)
2866 {
2867 int i, nb_xmm_regs;
2868
2869 if (env->hflags & HF_CS64_MASK) {
2870 nb_xmm_regs = 16;
2871 } else {
2872 nb_xmm_regs = 8;
2873 }
2874
2875 for (i = 0; i < nb_xmm_regs; i++) {
2876 env->xmm_regs[i].ZMM_Q(0) = 0;
2877 env->xmm_regs[i].ZMM_Q(1) = 0;
2878 }
2879 }
2880
2881 static void do_xrstor_ymmh(X86Access *ac, target_ulong ptr)
2882 {
2883 CPUX86State *env = ac->env;
2884 int i, nb_xmm_regs;
2885
2886 if (env->hflags & HF_CS64_MASK) {
2887 nb_xmm_regs = 16;
2888 } else {
2889 nb_xmm_regs = 8;
2890 }
2891
2892 for (i = 0; i < nb_xmm_regs; i++, ptr += 16) {
2893 env->xmm_regs[i].ZMM_Q(2) = access_ldq(ac, ptr);
2894 env->xmm_regs[i].ZMM_Q(3) = access_ldq(ac, ptr + 8);
2895 }
2896 }
2897
2898 static void do_clear_ymmh(CPUX86State *env)
2899 {
2900 int i, nb_xmm_regs;
2901
2902 if (env->hflags & HF_CS64_MASK) {
2903 nb_xmm_regs = 16;
2904 } else {
2905 nb_xmm_regs = 8;
2906 }
2907
2908 for (i = 0; i < nb_xmm_regs; i++) {
2909 env->xmm_regs[i].ZMM_Q(2) = 0;
2910 env->xmm_regs[i].ZMM_Q(3) = 0;
2911 }
2912 }
2913
2914 static void do_xrstor_bndregs(X86Access *ac, target_ulong ptr)
2915 {
2916 CPUX86State *env = ac->env;
2917 target_ulong addr = ptr + offsetof(XSaveBNDREG, bnd_regs);
2918 int i;
2919
2920 for (i = 0; i < 4; i++, addr += 16) {
2921 env->bnd_regs[i].lb = access_ldq(ac, addr);
2922 env->bnd_regs[i].ub = access_ldq(ac, addr + 8);
2923 }
2924 }
2925
2926 static void do_xrstor_bndcsr(X86Access *ac, target_ulong ptr)
2927 {
2928 CPUX86State *env = ac->env;
2929
2930 /* FIXME: Extend highest implemented bit of linear address. */
2931 env->bndcs_regs.cfgu
2932 = access_ldq(ac, ptr + offsetof(XSaveBNDCSR, bndcsr.cfgu));
2933 env->bndcs_regs.sts
2934 = access_ldq(ac, ptr + offsetof(XSaveBNDCSR, bndcsr.sts));
2935 }
2936
2937 static void do_xrstor_pkru(X86Access *ac, target_ulong ptr)
2938 {
2939 ac->env->pkru = access_ldq(ac, ptr);
2940 }
2941
2942 static void do_fxrstor(X86Access *ac, target_ulong ptr)
2943 {
2944 CPUX86State *env = ac->env;
2945
2946 do_xrstor_fpu(ac, ptr);
2947 if (env->cr[4] & CR4_OSFXSR_MASK) {
2948 do_xrstor_mxcsr(ac, ptr);
2949 /* Fast FXRSTOR leaves out the XMM registers */
2950 if (!(env->efer & MSR_EFER_FFXSR)
2951 || (env->hflags & HF_CPL_MASK)
2952 || !(env->hflags & HF_LMA_MASK)) {
2953 do_xrstor_sse(ac, ptr);
2954 }
2955 }
2956 }
2957
2958 void helper_fxrstor(CPUX86State *env, target_ulong ptr)
2959 {
2960 uintptr_t ra = GETPC();
2961 X86Access ac;
2962
2963 /* The operand must be 16 byte aligned */
2964 if (ptr & 0xf) {
2965 raise_exception_ra(env, EXCP0D_GPF, ra);
2966 }
2967
2968 access_prepare(&ac, env, ptr, sizeof(X86LegacyXSaveArea),
2969 MMU_DATA_LOAD, ra);
2970 do_fxrstor(&ac, ptr);
2971 }
2972
2973 static bool valid_xrstor_header(X86Access *ac, uint64_t *pxsbv,
2974 target_ulong ptr)
2975 {
2976 uint64_t xstate_bv, xcomp_bv, reserve0;
2977
2978 xstate_bv = access_ldq(ac, ptr + XO(header.xstate_bv));
2979 xcomp_bv = access_ldq(ac, ptr + XO(header.xcomp_bv));
2980 reserve0 = access_ldq(ac, ptr + XO(header.reserve0));
2981 *pxsbv = xstate_bv;
2982
2983 /*
2984 * XCOMP_BV bit 63 indicates compact form, which we do not support,
2985 * and thus must raise #GP. That leaves us in standard form.
2986 * In standard form, bytes 23:8 must be zero -- which is both
2987 * XCOMP_BV and the following 64-bit field.
2988 */
2989 if (xcomp_bv || reserve0) {
2990 return false;
2991 }
2992
2993 /* The XSTATE_BV field must not set bits not present in XCR0. */
2994 return (xstate_bv & ~ac->env->xcr0) == 0;
2995 }
2996
2997 static void do_xrstor(X86Access *ac, target_ulong ptr,
2998 uint64_t rfbm, uint64_t xstate_bv)
2999 {
3000 CPUX86State *env = ac->env;
3001
3002 if (rfbm & XSTATE_FP_MASK) {
3003 if (xstate_bv & XSTATE_FP_MASK) {
3004 do_xrstor_fpu(ac, ptr);
3005 } else {
3006 do_fninit(env);
3007 memset(env->fpregs, 0, sizeof(env->fpregs));
3008 }
3009 }
3010 if (rfbm & XSTATE_SSE_MASK) {
3011 /* Note that the standard form of XRSTOR loads MXCSR from memory
3012 whether or not the XSTATE_BV bit is set. */
3013 do_xrstor_mxcsr(ac, ptr);
3014 if (xstate_bv & XSTATE_SSE_MASK) {
3015 do_xrstor_sse(ac, ptr);
3016 } else {
3017 do_clear_sse(env);
3018 }
3019 }
3020 if (rfbm & XSTATE_YMM_MASK) {
3021 if (xstate_bv & XSTATE_YMM_MASK) {
3022 do_xrstor_ymmh(ac, ptr + XO(avx_state));
3023 } else {
3024 do_clear_ymmh(env);
3025 }
3026 }
3027 if (rfbm & XSTATE_BNDREGS_MASK) {
3028 if (xstate_bv & XSTATE_BNDREGS_MASK) {
3029 do_xrstor_bndregs(ac, ptr + XO(bndreg_state));
3030 env->hflags |= HF_MPX_IU_MASK;
3031 } else {
3032 memset(env->bnd_regs, 0, sizeof(env->bnd_regs));
3033 env->hflags &= ~HF_MPX_IU_MASK;
3034 }
3035 }
3036 if (rfbm & XSTATE_BNDCSR_MASK) {
3037 if (xstate_bv & XSTATE_BNDCSR_MASK) {
3038 do_xrstor_bndcsr(ac, ptr + XO(bndcsr_state));
3039 } else {
3040 memset(&env->bndcs_regs, 0, sizeof(env->bndcs_regs));
3041 }
3042 cpu_sync_bndcs_hflags(env);
3043 }
3044 if (rfbm & XSTATE_PKRU_MASK) {
3045 uint64_t old_pkru = env->pkru;
3046 if (xstate_bv & XSTATE_PKRU_MASK) {
3047 do_xrstor_pkru(ac, ptr + XO(pkru_state));
3048 } else {
3049 env->pkru = 0;
3050 }
3051 if (env->pkru != old_pkru) {
3052 CPUState *cs = env_cpu(env);
3053 tlb_flush(cs);
3054 }
3055 }
3056 }
3057
3058 #undef XO
3059
3060 void helper_xrstor(CPUX86State *env, target_ulong ptr, uint64_t rfbm)
3061 {
3062 uintptr_t ra = GETPC();
3063 X86Access ac;
3064 uint64_t xstate_bv;
3065 unsigned size, size_ext;
3066
3067 do_xsave_chk(env, ptr, ra);
3068
3069 /* Begin with just the minimum size to validate the header. */
3070 size = sizeof(X86LegacyXSaveArea) + sizeof(X86XSaveHeader);
3071 access_prepare(&ac, env, ptr, size, MMU_DATA_LOAD, ra);
3072 if (!valid_xrstor_header(&ac, &xstate_bv, ptr)) {
3073 raise_exception_ra(env, EXCP0D_GPF, ra);
3074 }
3075
3076 rfbm &= env->xcr0;
3077 size_ext = xsave_area_size(rfbm & xstate_bv, false);
3078 if (size < size_ext) {
3079 /* TODO: See if existing page probe has covered extra size. */
3080 access_prepare(&ac, env, ptr, size_ext, MMU_DATA_LOAD, ra);
3081 }
3082
3083 do_xrstor(&ac, ptr, rfbm, xstate_bv);
3084 }
3085
3086 #if defined(CONFIG_USER_ONLY)
3087 void cpu_x86_fsave(CPUX86State *env, void *host, size_t len)
3088 {
3089 X86Access ac = {
3090 .haddr1 = host,
3091 .size = 4 * 7 + 8 * 10,
3092 .env = env,
3093 };
3094
3095 assert(ac.size <= len);
3096 do_fsave(&ac, 0, true);
3097 }
3098
3099 void cpu_x86_frstor(CPUX86State *env, void *host, size_t len)
3100 {
3101 X86Access ac = {
3102 .haddr1 = host,
3103 .size = 4 * 7 + 8 * 10,
3104 .env = env,
3105 };
3106
3107 assert(ac.size <= len);
3108 do_frstor(&ac, 0, true);
3109 }
3110
3111 void cpu_x86_fxsave(CPUX86State *env, void *host, size_t len)
3112 {
3113 X86Access ac = {
3114 .haddr1 = host,
3115 .size = sizeof(X86LegacyXSaveArea),
3116 .env = env,
3117 };
3118
3119 assert(ac.size <= len);
3120 do_fxsave(&ac, 0);
3121 }
3122
3123 void cpu_x86_fxrstor(CPUX86State *env, void *host, size_t len)
3124 {
3125 X86Access ac = {
3126 .haddr1 = host,
3127 .size = sizeof(X86LegacyXSaveArea),
3128 .env = env,
3129 };
3130
3131 assert(ac.size <= len);
3132 do_fxrstor(&ac, 0);
3133 }
3134
3135 void cpu_x86_xsave(CPUX86State *env, void *host, size_t len, uint64_t rfbm)
3136 {
3137 X86Access ac = {
3138 .haddr1 = host,
3139 .env = env,
3140 };
3141
3142 /*
3143 * Since this is only called from user-level signal handling,
3144 * we should have done the job correctly there.
3145 */
3146 assert((rfbm & ~env->xcr0) == 0);
3147 ac.size = xsave_area_size(rfbm, false);
3148 assert(ac.size <= len);
3149 do_xsave_access(&ac, 0, rfbm, get_xinuse(env), rfbm);
3150 }
3151
3152 bool cpu_x86_xrstor(CPUX86State *env, void *host, size_t len, uint64_t rfbm)
3153 {
3154 X86Access ac = {
3155 .haddr1 = host,
3156 .env = env,
3157 };
3158 uint64_t xstate_bv;
3159
3160 /*
3161 * Since this is only called from user-level signal handling,
3162 * we should have done the job correctly there.
3163 */
3164 assert((rfbm & ~env->xcr0) == 0);
3165 ac.size = xsave_area_size(rfbm, false);
3166 assert(ac.size <= len);
3167
3168 if (!valid_xrstor_header(&ac, &xstate_bv, 0)) {
3169 return false;
3170 }
3171 do_xrstor(&ac, 0, rfbm, xstate_bv);
3172 return true;
3173 }
3174 #endif
3175
3176 uint64_t helper_xgetbv(CPUX86State *env, uint32_t ecx)
3177 {
3178 /* The OS must have enabled XSAVE. */
3179 if (!(env->cr[4] & CR4_OSXSAVE_MASK)) {
3180 raise_exception_ra(env, EXCP06_ILLOP, GETPC());
3181 }
3182
3183 switch (ecx) {
3184 case 0:
3185 return env->xcr0;
3186 case 1:
3187 if (env->features[FEAT_XSAVE] & CPUID_XSAVE_XGETBV1) {
3188 return env->xcr0 & get_xinuse(env);
3189 }
3190 break;
3191 }
3192 raise_exception_ra(env, EXCP0D_GPF, GETPC());
3193 }
3194
3195 void helper_xsetbv(CPUX86State *env, uint32_t ecx, uint64_t mask)
3196 {
3197 uint32_t dummy, ena_lo, ena_hi;
3198 uint64_t ena;
3199
3200 /* The OS must have enabled XSAVE. */
3201 if (!(env->cr[4] & CR4_OSXSAVE_MASK)) {
3202 raise_exception_ra(env, EXCP06_ILLOP, GETPC());
3203 }
3204
3205 /* Only XCR0 is defined at present; the FPU may not be disabled. */
3206 if (ecx != 0 || (mask & XSTATE_FP_MASK) == 0) {
3207 goto do_gpf;
3208 }
3209
3210 /* SSE can be disabled, but only if AVX is disabled too. */
3211 if ((mask & (XSTATE_SSE_MASK | XSTATE_YMM_MASK)) == XSTATE_YMM_MASK) {
3212 goto do_gpf;
3213 }
3214
3215 /* Disallow enabling unimplemented features. */
3216 cpu_x86_cpuid(env, 0x0d, 0, &ena_lo, &dummy, &dummy, &ena_hi);
3217 ena = ((uint64_t)ena_hi << 32) | ena_lo;
3218 if (mask & ~ena) {
3219 goto do_gpf;
3220 }
3221
3222 /* Disallow enabling only half of MPX. */
3223 if ((mask ^ (mask * (XSTATE_BNDCSR_MASK / XSTATE_BNDREGS_MASK)))
3224 & XSTATE_BNDCSR_MASK) {
3225 goto do_gpf;
3226 }
3227
3228 env->xcr0 = mask;
3229 cpu_sync_bndcs_hflags(env);
3230 cpu_sync_avx_hflag(env);
3231 return;
3232
3233 do_gpf:
3234 raise_exception_ra(env, EXCP0D_GPF, GETPC());
3235 }
3236
3237 /* MMX/SSE */
3238 /* XXX: optimize by storing fptt and fptags in the static cpu state */
3239
3240 #define SSE_DAZ 0x0040
3241 #define SSE_RC_SHIFT 13
3242 #define SSE_RC_MASK (3 << SSE_RC_SHIFT)
3243 #define SSE_FZ 0x8000
3244
3245 void update_mxcsr_status(CPUX86State *env)
3246 {
3247 uint32_t mxcsr = env->mxcsr;
3248 int rnd_type;
3249
3250 /* set rounding mode */
3251 rnd_type = (mxcsr & SSE_RC_MASK) >> SSE_RC_SHIFT;
3252 set_x86_rounding_mode(rnd_type, &env->sse_status);
3253
3254 /* Set exception flags. */
3255 set_float_exception_flags((mxcsr & FPUS_IE ? float_flag_invalid : 0) |
3256 (mxcsr & FPUS_DE ? float_flag_input_denormal_used : 0) |
3257 (mxcsr & FPUS_ZE ? float_flag_divbyzero : 0) |
3258 (mxcsr & FPUS_OE ? float_flag_overflow : 0) |
3259 (mxcsr & FPUS_UE ? float_flag_underflow : 0) |
3260 (mxcsr & FPUS_PE ? float_flag_inexact : 0),
3261 &env->sse_status);
3262
3263 /* set denormals are zero */
3264 set_flush_inputs_to_zero((mxcsr & SSE_DAZ) ? 1 : 0, &env->sse_status);
3265
3266 /* set flush to zero */
3267 set_flush_to_zero((mxcsr & SSE_FZ) ? 1 : 0, &env->sse_status);
3268 }
3269
3270 void update_mxcsr_from_sse_status(CPUX86State *env)
3271 {
3272 int flags = get_float_exception_flags(&env->sse_status);
3273 env->mxcsr |= ((flags & float_flag_invalid ? FPUS_IE : 0) |
3274 (flags & float_flag_input_denormal_used ? FPUS_DE : 0) |
3275 (flags & float_flag_divbyzero ? FPUS_ZE : 0) |
3276 (flags & float_flag_overflow ? FPUS_OE : 0) |
3277 (flags & float_flag_underflow ? FPUS_UE : 0) |
3278 (flags & float_flag_inexact ? FPUS_PE : 0) |
3279 (flags & float_flag_output_denormal_flushed ? FPUS_UE | FPUS_PE :
3280 0));
3281 }
3282
3283 void helper_update_mxcsr(CPUX86State *env)
3284 {
3285 update_mxcsr_from_sse_status(env);
3286 }
3287
3288 void helper_ldmxcsr(CPUX86State *env, uint32_t val)
3289 {
3290 cpu_set_mxcsr(env, val);
3291 }
3292
3293 void helper_enter_mmx(CPUX86State *env)
3294 {
3295 env->fpstt = 0;
3296 *(uint32_t *)(env->fptags) = 0;
3297 *(uint32_t *)(env->fptags + 4) = 0;
3298 }
3299
3300 void helper_emms(CPUX86State *env)
3301 {
3302 /* set to empty state */
3303 *(uint32_t *)(env->fptags) = 0x01010101;
3304 *(uint32_t *)(env->fptags + 4) = 0x01010101;
3305 }
3306
3307 #define SHIFT 0
3308 #include "ops_sse.h"
3309
3310 #define SHIFT 1
3311 #include "ops_sse.h"
3312
3313 #define SHIFT 2
3314 #include "ops_sse.h"