2 * x86 FPU, MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4/PNI helpers
4 * Copyright (c) 2003 Fabrice Bellard
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 of the License, or (at your option) any later version.
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.
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/>.
20 #include "qemu/osdep.h"
23 #include "exec/helper-proto.h"
24 #include "qemu/host-utils.h"
25 #include "exec/exec-all.h"
26 #include "exec/cpu_ldst.h"
27 #include "fpu/softfloat.h"
29 #define FPU_RC_MASK 0xc00
30 #define FPU_RC_NEAR 0x000
31 #define FPU_RC_DOWN 0x400
32 #define FPU_RC_UP 0x800
33 #define FPU_RC_CHOP 0xc00
35 #define MAXTAN 9223372036854775808.0
37 /* the following deal with x86 long double-precision numbers */
38 #define MAXEXPD 0x7fff
40 #define EXPD(fp) (fp.l.upper & 0x7fff)
41 #define SIGND(fp) ((fp.l.upper) & 0x8000)
42 #define MANTD(fp) (fp.l.lower)
43 #define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
45 #define FPUS_IE (1 << 0)
46 #define FPUS_DE (1 << 1)
47 #define FPUS_ZE (1 << 2)
48 #define FPUS_OE (1 << 3)
49 #define FPUS_UE (1 << 4)
50 #define FPUS_PE (1 << 5)
51 #define FPUS_SF (1 << 6)
52 #define FPUS_SE (1 << 7)
53 #define FPUS_B (1 << 15)
57 #define floatx80_lg2 make_floatx80(0x3ffd, 0x9a209a84fbcff799LL)
58 #define floatx80_l2e make_floatx80(0x3fff, 0xb8aa3b295c17f0bcLL)
59 #define floatx80_l2t make_floatx80(0x4000, 0xd49a784bcd1b8afeLL)
61 static inline void fpush(CPUX86State
*env
)
63 env
->fpstt
= (env
->fpstt
- 1) & 7;
64 env
->fptags
[env
->fpstt
] = 0; /* validate stack entry */
67 static inline void fpop(CPUX86State
*env
)
69 env
->fptags
[env
->fpstt
] = 1; /* invalidate stack entry */
70 env
->fpstt
= (env
->fpstt
+ 1) & 7;
73 static inline floatx80
helper_fldt(CPUX86State
*env
, target_ulong ptr
,
78 temp
.l
.lower
= cpu_ldq_data_ra(env
, ptr
, retaddr
);
79 temp
.l
.upper
= cpu_lduw_data_ra(env
, ptr
+ 8, retaddr
);
83 static inline void helper_fstt(CPUX86State
*env
, floatx80 f
, target_ulong ptr
,
89 cpu_stq_data_ra(env
, ptr
, temp
.l
.lower
, retaddr
);
90 cpu_stw_data_ra(env
, ptr
+ 8, temp
.l
.upper
, retaddr
);
95 static inline double floatx80_to_double(CPUX86State
*env
, floatx80 a
)
102 u
.f64
= floatx80_to_float64(a
, &env
->fp_status
);
106 static inline floatx80
double_to_floatx80(CPUX86State
*env
, double a
)
114 return float64_to_floatx80(u
.f64
, &env
->fp_status
);
117 static void fpu_set_exception(CPUX86State
*env
, int mask
)
120 if (env
->fpus
& (~env
->fpuc
& FPUC_EM
)) {
121 env
->fpus
|= FPUS_SE
| FPUS_B
;
125 static inline floatx80
helper_fdiv(CPUX86State
*env
, floatx80 a
, floatx80 b
)
127 if (floatx80_is_zero(b
)) {
128 fpu_set_exception(env
, FPUS_ZE
);
130 return floatx80_div(a
, b
, &env
->fp_status
);
133 static void fpu_raise_exception(CPUX86State
*env
, uintptr_t retaddr
)
135 if (env
->cr
[0] & CR0_NE_MASK
) {
136 raise_exception_ra(env
, EXCP10_COPR
, retaddr
);
138 #if !defined(CONFIG_USER_ONLY)
145 void helper_flds_FT0(CPUX86State
*env
, uint32_t val
)
153 FT0
= float32_to_floatx80(u
.f
, &env
->fp_status
);
156 void helper_fldl_FT0(CPUX86State
*env
, uint64_t val
)
164 FT0
= float64_to_floatx80(u
.f
, &env
->fp_status
);
167 void helper_fildl_FT0(CPUX86State
*env
, int32_t val
)
169 FT0
= int32_to_floatx80(val
, &env
->fp_status
);
172 void helper_flds_ST0(CPUX86State
*env
, uint32_t val
)
180 new_fpstt
= (env
->fpstt
- 1) & 7;
182 env
->fpregs
[new_fpstt
].d
= float32_to_floatx80(u
.f
, &env
->fp_status
);
183 env
->fpstt
= new_fpstt
;
184 env
->fptags
[new_fpstt
] = 0; /* validate stack entry */
187 void helper_fldl_ST0(CPUX86State
*env
, uint64_t val
)
195 new_fpstt
= (env
->fpstt
- 1) & 7;
197 env
->fpregs
[new_fpstt
].d
= float64_to_floatx80(u
.f
, &env
->fp_status
);
198 env
->fpstt
= new_fpstt
;
199 env
->fptags
[new_fpstt
] = 0; /* validate stack entry */
202 void helper_fildl_ST0(CPUX86State
*env
, int32_t val
)
206 new_fpstt
= (env
->fpstt
- 1) & 7;
207 env
->fpregs
[new_fpstt
].d
= int32_to_floatx80(val
, &env
->fp_status
);
208 env
->fpstt
= new_fpstt
;
209 env
->fptags
[new_fpstt
] = 0; /* validate stack entry */
212 void helper_fildll_ST0(CPUX86State
*env
, int64_t val
)
216 new_fpstt
= (env
->fpstt
- 1) & 7;
217 env
->fpregs
[new_fpstt
].d
= int64_to_floatx80(val
, &env
->fp_status
);
218 env
->fpstt
= new_fpstt
;
219 env
->fptags
[new_fpstt
] = 0; /* validate stack entry */
222 uint32_t helper_fsts_ST0(CPUX86State
*env
)
229 u
.f
= floatx80_to_float32(ST0
, &env
->fp_status
);
233 uint64_t helper_fstl_ST0(CPUX86State
*env
)
240 u
.f
= floatx80_to_float64(ST0
, &env
->fp_status
);
244 int32_t helper_fist_ST0(CPUX86State
*env
)
248 val
= floatx80_to_int32(ST0
, &env
->fp_status
);
249 if (val
!= (int16_t)val
) {
255 int32_t helper_fistl_ST0(CPUX86State
*env
)
258 signed char old_exp_flags
;
260 old_exp_flags
= get_float_exception_flags(&env
->fp_status
);
261 set_float_exception_flags(0, &env
->fp_status
);
263 val
= floatx80_to_int32(ST0
, &env
->fp_status
);
264 if (get_float_exception_flags(&env
->fp_status
) & float_flag_invalid
) {
267 set_float_exception_flags(get_float_exception_flags(&env
->fp_status
)
268 | old_exp_flags
, &env
->fp_status
);
272 int64_t helper_fistll_ST0(CPUX86State
*env
)
275 signed char old_exp_flags
;
277 old_exp_flags
= get_float_exception_flags(&env
->fp_status
);
278 set_float_exception_flags(0, &env
->fp_status
);
280 val
= floatx80_to_int64(ST0
, &env
->fp_status
);
281 if (get_float_exception_flags(&env
->fp_status
) & float_flag_invalid
) {
282 val
= 0x8000000000000000ULL
;
284 set_float_exception_flags(get_float_exception_flags(&env
->fp_status
)
285 | old_exp_flags
, &env
->fp_status
);
289 int32_t helper_fistt_ST0(CPUX86State
*env
)
293 val
= floatx80_to_int32_round_to_zero(ST0
, &env
->fp_status
);
294 if (val
!= (int16_t)val
) {
300 int32_t helper_fisttl_ST0(CPUX86State
*env
)
302 return floatx80_to_int32_round_to_zero(ST0
, &env
->fp_status
);
305 int64_t helper_fisttll_ST0(CPUX86State
*env
)
307 return floatx80_to_int64_round_to_zero(ST0
, &env
->fp_status
);
310 void helper_fldt_ST0(CPUX86State
*env
, target_ulong ptr
)
314 new_fpstt
= (env
->fpstt
- 1) & 7;
315 env
->fpregs
[new_fpstt
].d
= helper_fldt(env
, ptr
, GETPC());
316 env
->fpstt
= new_fpstt
;
317 env
->fptags
[new_fpstt
] = 0; /* validate stack entry */
320 void helper_fstt_ST0(CPUX86State
*env
, target_ulong ptr
)
322 helper_fstt(env
, ST0
, ptr
, GETPC());
325 void helper_fpush(CPUX86State
*env
)
330 void helper_fpop(CPUX86State
*env
)
335 void helper_fdecstp(CPUX86State
*env
)
337 env
->fpstt
= (env
->fpstt
- 1) & 7;
338 env
->fpus
&= ~0x4700;
341 void helper_fincstp(CPUX86State
*env
)
343 env
->fpstt
= (env
->fpstt
+ 1) & 7;
344 env
->fpus
&= ~0x4700;
349 void helper_ffree_STN(CPUX86State
*env
, int st_index
)
351 env
->fptags
[(env
->fpstt
+ st_index
) & 7] = 1;
354 void helper_fmov_ST0_FT0(CPUX86State
*env
)
359 void helper_fmov_FT0_STN(CPUX86State
*env
, int st_index
)
364 void helper_fmov_ST0_STN(CPUX86State
*env
, int st_index
)
369 void helper_fmov_STN_ST0(CPUX86State
*env
, int st_index
)
374 void helper_fxchg_ST0_STN(CPUX86State
*env
, int st_index
)
385 static const int fcom_ccval
[4] = {0x0100, 0x4000, 0x0000, 0x4500};
387 void helper_fcom_ST0_FT0(CPUX86State
*env
)
391 ret
= floatx80_compare(ST0
, FT0
, &env
->fp_status
);
392 env
->fpus
= (env
->fpus
& ~0x4500) | fcom_ccval
[ret
+ 1];
395 void helper_fucom_ST0_FT0(CPUX86State
*env
)
399 ret
= floatx80_compare_quiet(ST0
, FT0
, &env
->fp_status
);
400 env
->fpus
= (env
->fpus
& ~0x4500) | fcom_ccval
[ret
+ 1];
403 static const int fcomi_ccval
[4] = {CC_C
, CC_Z
, 0, CC_Z
| CC_P
| CC_C
};
405 void helper_fcomi_ST0_FT0(CPUX86State
*env
)
410 ret
= floatx80_compare(ST0
, FT0
, &env
->fp_status
);
411 eflags
= cpu_cc_compute_all(env
, CC_OP
);
412 eflags
= (eflags
& ~(CC_Z
| CC_P
| CC_C
)) | fcomi_ccval
[ret
+ 1];
416 void helper_fucomi_ST0_FT0(CPUX86State
*env
)
421 ret
= floatx80_compare_quiet(ST0
, FT0
, &env
->fp_status
);
422 eflags
= cpu_cc_compute_all(env
, CC_OP
);
423 eflags
= (eflags
& ~(CC_Z
| CC_P
| CC_C
)) | fcomi_ccval
[ret
+ 1];
427 void helper_fadd_ST0_FT0(CPUX86State
*env
)
429 ST0
= floatx80_add(ST0
, FT0
, &env
->fp_status
);
432 void helper_fmul_ST0_FT0(CPUX86State
*env
)
434 ST0
= floatx80_mul(ST0
, FT0
, &env
->fp_status
);
437 void helper_fsub_ST0_FT0(CPUX86State
*env
)
439 ST0
= floatx80_sub(ST0
, FT0
, &env
->fp_status
);
442 void helper_fsubr_ST0_FT0(CPUX86State
*env
)
444 ST0
= floatx80_sub(FT0
, ST0
, &env
->fp_status
);
447 void helper_fdiv_ST0_FT0(CPUX86State
*env
)
449 ST0
= helper_fdiv(env
, ST0
, FT0
);
452 void helper_fdivr_ST0_FT0(CPUX86State
*env
)
454 ST0
= helper_fdiv(env
, FT0
, ST0
);
457 /* fp operations between STN and ST0 */
459 void helper_fadd_STN_ST0(CPUX86State
*env
, int st_index
)
461 ST(st_index
) = floatx80_add(ST(st_index
), ST0
, &env
->fp_status
);
464 void helper_fmul_STN_ST0(CPUX86State
*env
, int st_index
)
466 ST(st_index
) = floatx80_mul(ST(st_index
), ST0
, &env
->fp_status
);
469 void helper_fsub_STN_ST0(CPUX86State
*env
, int st_index
)
471 ST(st_index
) = floatx80_sub(ST(st_index
), ST0
, &env
->fp_status
);
474 void helper_fsubr_STN_ST0(CPUX86State
*env
, int st_index
)
476 ST(st_index
) = floatx80_sub(ST0
, ST(st_index
), &env
->fp_status
);
479 void helper_fdiv_STN_ST0(CPUX86State
*env
, int st_index
)
484 *p
= helper_fdiv(env
, *p
, ST0
);
487 void helper_fdivr_STN_ST0(CPUX86State
*env
, int st_index
)
492 *p
= helper_fdiv(env
, ST0
, *p
);
495 /* misc FPU operations */
496 void helper_fchs_ST0(CPUX86State
*env
)
498 ST0
= floatx80_chs(ST0
);
501 void helper_fabs_ST0(CPUX86State
*env
)
503 ST0
= floatx80_abs(ST0
);
506 void helper_fld1_ST0(CPUX86State
*env
)
511 void helper_fldl2t_ST0(CPUX86State
*env
)
516 void helper_fldl2e_ST0(CPUX86State
*env
)
521 void helper_fldpi_ST0(CPUX86State
*env
)
526 void helper_fldlg2_ST0(CPUX86State
*env
)
531 void helper_fldln2_ST0(CPUX86State
*env
)
536 void helper_fldz_ST0(CPUX86State
*env
)
541 void helper_fldz_FT0(CPUX86State
*env
)
546 uint32_t helper_fnstsw(CPUX86State
*env
)
548 return (env
->fpus
& ~0x3800) | (env
->fpstt
& 0x7) << 11;
551 uint32_t helper_fnstcw(CPUX86State
*env
)
556 void update_fp_status(CPUX86State
*env
)
560 /* set rounding mode */
561 switch (env
->fpuc
& FPU_RC_MASK
) {
564 rnd_type
= float_round_nearest_even
;
567 rnd_type
= float_round_down
;
570 rnd_type
= float_round_up
;
573 rnd_type
= float_round_to_zero
;
576 set_float_rounding_mode(rnd_type
, &env
->fp_status
);
577 switch ((env
->fpuc
>> 8) & 3) {
589 set_floatx80_rounding_precision(rnd_type
, &env
->fp_status
);
592 void helper_fldcw(CPUX86State
*env
, uint32_t val
)
594 cpu_set_fpuc(env
, val
);
597 void helper_fclex(CPUX86State
*env
)
602 void helper_fwait(CPUX86State
*env
)
604 if (env
->fpus
& FPUS_SE
) {
605 fpu_raise_exception(env
, GETPC());
609 void helper_fninit(CPUX86State
*env
)
613 cpu_set_fpuc(env
, 0x37f);
626 void helper_fbld_ST0(CPUX86State
*env
, target_ulong ptr
)
634 for (i
= 8; i
>= 0; i
--) {
635 v
= cpu_ldub_data_ra(env
, ptr
+ i
, GETPC());
636 val
= (val
* 100) + ((v
>> 4) * 10) + (v
& 0xf);
638 tmp
= int64_to_floatx80(val
, &env
->fp_status
);
639 if (cpu_ldub_data_ra(env
, ptr
+ 9, GETPC()) & 0x80) {
640 tmp
= floatx80_chs(tmp
);
646 void helper_fbst_ST0(CPUX86State
*env
, target_ulong ptr
)
649 target_ulong mem_ref
, mem_end
;
652 val
= floatx80_to_int64(ST0
, &env
->fp_status
);
654 mem_end
= mem_ref
+ 9;
656 cpu_stb_data_ra(env
, mem_end
, 0x80, GETPC());
659 cpu_stb_data_ra(env
, mem_end
, 0x00, GETPC());
661 while (mem_ref
< mem_end
) {
667 v
= ((v
/ 10) << 4) | (v
% 10);
668 cpu_stb_data_ra(env
, mem_ref
++, v
, GETPC());
670 while (mem_ref
< mem_end
) {
671 cpu_stb_data_ra(env
, mem_ref
++, 0, GETPC());
675 void helper_f2xm1(CPUX86State
*env
)
677 double val
= floatx80_to_double(env
, ST0
);
679 val
= pow(2.0, val
) - 1.0;
680 ST0
= double_to_floatx80(env
, val
);
683 void helper_fyl2x(CPUX86State
*env
)
685 double fptemp
= floatx80_to_double(env
, ST0
);
688 fptemp
= log(fptemp
) / log(2.0); /* log2(ST) */
689 fptemp
*= floatx80_to_double(env
, ST1
);
690 ST1
= double_to_floatx80(env
, fptemp
);
693 env
->fpus
&= ~0x4700;
698 void helper_fptan(CPUX86State
*env
)
700 double fptemp
= floatx80_to_double(env
, ST0
);
702 if ((fptemp
> MAXTAN
) || (fptemp
< -MAXTAN
)) {
705 fptemp
= tan(fptemp
);
706 ST0
= double_to_floatx80(env
, fptemp
);
709 env
->fpus
&= ~0x400; /* C2 <-- 0 */
710 /* the above code is for |arg| < 2**52 only */
714 void helper_fpatan(CPUX86State
*env
)
716 double fptemp
, fpsrcop
;
718 fpsrcop
= floatx80_to_double(env
, ST1
);
719 fptemp
= floatx80_to_double(env
, ST0
);
720 ST1
= double_to_floatx80(env
, atan2(fpsrcop
, fptemp
));
724 void helper_fxtract(CPUX86State
*env
)
730 if (floatx80_is_zero(ST0
)) {
731 /* Easy way to generate -inf and raising division by 0 exception */
732 ST0
= floatx80_div(floatx80_chs(floatx80_one
), floatx80_zero
,
739 expdif
= EXPD(temp
) - EXPBIAS
;
740 /* DP exponent bias */
741 ST0
= int32_to_floatx80(expdif
, &env
->fp_status
);
748 void helper_fprem1(CPUX86State
*env
)
750 double st0
, st1
, dblq
, fpsrcop
, fptemp
;
751 CPU_LDoubleU fpsrcop1
, fptemp1
;
753 signed long long int q
;
755 st0
= floatx80_to_double(env
, ST0
);
756 st1
= floatx80_to_double(env
, ST1
);
758 if (isinf(st0
) || isnan(st0
) || isnan(st1
) || (st1
== 0.0)) {
759 ST0
= double_to_floatx80(env
, 0.0 / 0.0); /* NaN */
760 env
->fpus
&= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
768 expdif
= EXPD(fpsrcop1
) - EXPD(fptemp1
);
771 /* optimisation? taken from the AMD docs */
772 env
->fpus
&= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
773 /* ST0 is unchanged */
778 dblq
= fpsrcop
/ fptemp
;
779 /* round dblq towards nearest integer */
781 st0
= fpsrcop
- fptemp
* dblq
;
783 /* convert dblq to q by truncating towards zero */
785 q
= (signed long long int)(-dblq
);
787 q
= (signed long long int)dblq
;
790 env
->fpus
&= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
791 /* (C0,C3,C1) <-- (q2,q1,q0) */
792 env
->fpus
|= (q
& 0x4) << (8 - 2); /* (C0) <-- q2 */
793 env
->fpus
|= (q
& 0x2) << (14 - 1); /* (C3) <-- q1 */
794 env
->fpus
|= (q
& 0x1) << (9 - 0); /* (C1) <-- q0 */
796 env
->fpus
|= 0x400; /* C2 <-- 1 */
797 fptemp
= pow(2.0, expdif
- 50);
798 fpsrcop
= (st0
/ st1
) / fptemp
;
799 /* fpsrcop = integer obtained by chopping */
800 fpsrcop
= (fpsrcop
< 0.0) ?
801 -(floor(fabs(fpsrcop
))) : floor(fpsrcop
);
802 st0
-= (st1
* fpsrcop
* fptemp
);
804 ST0
= double_to_floatx80(env
, st0
);
807 void helper_fprem(CPUX86State
*env
)
809 double st0
, st1
, dblq
, fpsrcop
, fptemp
;
810 CPU_LDoubleU fpsrcop1
, fptemp1
;
812 signed long long int q
;
814 st0
= floatx80_to_double(env
, ST0
);
815 st1
= floatx80_to_double(env
, ST1
);
817 if (isinf(st0
) || isnan(st0
) || isnan(st1
) || (st1
== 0.0)) {
818 ST0
= double_to_floatx80(env
, 0.0 / 0.0); /* NaN */
819 env
->fpus
&= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
827 expdif
= EXPD(fpsrcop1
) - EXPD(fptemp1
);
830 /* optimisation? taken from the AMD docs */
831 env
->fpus
&= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
832 /* ST0 is unchanged */
837 dblq
= fpsrcop
/ fptemp
; /* ST0 / ST1 */
838 /* round dblq towards zero */
839 dblq
= (dblq
< 0.0) ? ceil(dblq
) : floor(dblq
);
840 st0
= fpsrcop
- fptemp
* dblq
; /* fpsrcop is ST0 */
842 /* convert dblq to q by truncating towards zero */
844 q
= (signed long long int)(-dblq
);
846 q
= (signed long long int)dblq
;
849 env
->fpus
&= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
850 /* (C0,C3,C1) <-- (q2,q1,q0) */
851 env
->fpus
|= (q
& 0x4) << (8 - 2); /* (C0) <-- q2 */
852 env
->fpus
|= (q
& 0x2) << (14 - 1); /* (C3) <-- q1 */
853 env
->fpus
|= (q
& 0x1) << (9 - 0); /* (C1) <-- q0 */
855 int N
= 32 + (expdif
% 32); /* as per AMD docs */
857 env
->fpus
|= 0x400; /* C2 <-- 1 */
858 fptemp
= pow(2.0, (double)(expdif
- N
));
859 fpsrcop
= (st0
/ st1
) / fptemp
;
860 /* fpsrcop = integer obtained by chopping */
861 fpsrcop
= (fpsrcop
< 0.0) ?
862 -(floor(fabs(fpsrcop
))) : floor(fpsrcop
);
863 st0
-= (st1
* fpsrcop
* fptemp
);
865 ST0
= double_to_floatx80(env
, st0
);
868 void helper_fyl2xp1(CPUX86State
*env
)
870 double fptemp
= floatx80_to_double(env
, ST0
);
872 if ((fptemp
+ 1.0) > 0.0) {
873 fptemp
= log(fptemp
+ 1.0) / log(2.0); /* log2(ST + 1.0) */
874 fptemp
*= floatx80_to_double(env
, ST1
);
875 ST1
= double_to_floatx80(env
, fptemp
);
878 env
->fpus
&= ~0x4700;
883 void helper_fsqrt(CPUX86State
*env
)
885 if (floatx80_is_neg(ST0
)) {
886 env
->fpus
&= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
889 ST0
= floatx80_sqrt(ST0
, &env
->fp_status
);
892 void helper_fsincos(CPUX86State
*env
)
894 double fptemp
= floatx80_to_double(env
, ST0
);
896 if ((fptemp
> MAXTAN
) || (fptemp
< -MAXTAN
)) {
899 ST0
= double_to_floatx80(env
, sin(fptemp
));
901 ST0
= double_to_floatx80(env
, cos(fptemp
));
902 env
->fpus
&= ~0x400; /* C2 <-- 0 */
903 /* the above code is for |arg| < 2**63 only */
907 void helper_frndint(CPUX86State
*env
)
909 ST0
= floatx80_round_to_int(ST0
, &env
->fp_status
);
912 void helper_fscale(CPUX86State
*env
)
914 if (floatx80_is_any_nan(ST1
)) {
917 int n
= floatx80_to_int32_round_to_zero(ST1
, &env
->fp_status
);
918 ST0
= floatx80_scalbn(ST0
, n
, &env
->fp_status
);
922 void helper_fsin(CPUX86State
*env
)
924 double fptemp
= floatx80_to_double(env
, ST0
);
926 if ((fptemp
> MAXTAN
) || (fptemp
< -MAXTAN
)) {
929 ST0
= double_to_floatx80(env
, sin(fptemp
));
930 env
->fpus
&= ~0x400; /* C2 <-- 0 */
931 /* the above code is for |arg| < 2**53 only */
935 void helper_fcos(CPUX86State
*env
)
937 double fptemp
= floatx80_to_double(env
, ST0
);
939 if ((fptemp
> MAXTAN
) || (fptemp
< -MAXTAN
)) {
942 ST0
= double_to_floatx80(env
, cos(fptemp
));
943 env
->fpus
&= ~0x400; /* C2 <-- 0 */
944 /* the above code is for |arg| < 2**63 only */
948 void helper_fxam_ST0(CPUX86State
*env
)
955 env
->fpus
&= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
957 env
->fpus
|= 0x200; /* C1 <-- 1 */
960 /* XXX: test fptags too */
962 if (expdif
== MAXEXPD
) {
963 if (MANTD(temp
) == 0x8000000000000000ULL
) {
964 env
->fpus
|= 0x500; /* Infinity */
966 env
->fpus
|= 0x100; /* NaN */
968 } else if (expdif
== 0) {
969 if (MANTD(temp
) == 0) {
970 env
->fpus
|= 0x4000; /* Zero */
972 env
->fpus
|= 0x4400; /* Denormal */
979 static void do_fstenv(CPUX86State
*env
, target_ulong ptr
, int data32
,
982 int fpus
, fptag
, exp
, i
;
986 fpus
= (env
->fpus
& ~0x3800) | (env
->fpstt
& 0x7) << 11;
988 for (i
= 7; i
>= 0; i
--) {
990 if (env
->fptags
[i
]) {
993 tmp
.d
= env
->fpregs
[i
].d
;
996 if (exp
== 0 && mant
== 0) {
999 } else if (exp
== 0 || exp
== MAXEXPD
1000 || (mant
& (1LL << 63)) == 0) {
1001 /* NaNs, infinity, denormal */
1008 cpu_stl_data_ra(env
, ptr
, env
->fpuc
, retaddr
);
1009 cpu_stl_data_ra(env
, ptr
+ 4, fpus
, retaddr
);
1010 cpu_stl_data_ra(env
, ptr
+ 8, fptag
, retaddr
);
1011 cpu_stl_data_ra(env
, ptr
+ 12, 0, retaddr
); /* fpip */
1012 cpu_stl_data_ra(env
, ptr
+ 16, 0, retaddr
); /* fpcs */
1013 cpu_stl_data_ra(env
, ptr
+ 20, 0, retaddr
); /* fpoo */
1014 cpu_stl_data_ra(env
, ptr
+ 24, 0, retaddr
); /* fpos */
1017 cpu_stw_data_ra(env
, ptr
, env
->fpuc
, retaddr
);
1018 cpu_stw_data_ra(env
, ptr
+ 2, fpus
, retaddr
);
1019 cpu_stw_data_ra(env
, ptr
+ 4, fptag
, retaddr
);
1020 cpu_stw_data_ra(env
, ptr
+ 6, 0, retaddr
);
1021 cpu_stw_data_ra(env
, ptr
+ 8, 0, retaddr
);
1022 cpu_stw_data_ra(env
, ptr
+ 10, 0, retaddr
);
1023 cpu_stw_data_ra(env
, ptr
+ 12, 0, retaddr
);
1027 void helper_fstenv(CPUX86State
*env
, target_ulong ptr
, int data32
)
1029 do_fstenv(env
, ptr
, data32
, GETPC());
1032 static void do_fldenv(CPUX86State
*env
, target_ulong ptr
, int data32
,
1038 cpu_set_fpuc(env
, cpu_lduw_data_ra(env
, ptr
, retaddr
));
1039 fpus
= cpu_lduw_data_ra(env
, ptr
+ 4, retaddr
);
1040 fptag
= cpu_lduw_data_ra(env
, ptr
+ 8, retaddr
);
1042 cpu_set_fpuc(env
, cpu_lduw_data_ra(env
, ptr
, retaddr
));
1043 fpus
= cpu_lduw_data_ra(env
, ptr
+ 2, retaddr
);
1044 fptag
= cpu_lduw_data_ra(env
, ptr
+ 4, retaddr
);
1046 env
->fpstt
= (fpus
>> 11) & 7;
1047 env
->fpus
= fpus
& ~0x3800;
1048 for (i
= 0; i
< 8; i
++) {
1049 env
->fptags
[i
] = ((fptag
& 3) == 3);
1054 void helper_fldenv(CPUX86State
*env
, target_ulong ptr
, int data32
)
1056 do_fldenv(env
, ptr
, data32
, GETPC());
1059 void helper_fsave(CPUX86State
*env
, target_ulong ptr
, int data32
)
1064 do_fstenv(env
, ptr
, data32
, GETPC());
1066 ptr
+= (14 << data32
);
1067 for (i
= 0; i
< 8; i
++) {
1069 helper_fstt(env
, tmp
, ptr
, GETPC());
1076 cpu_set_fpuc(env
, 0x37f);
1087 void helper_frstor(CPUX86State
*env
, target_ulong ptr
, int data32
)
1092 do_fldenv(env
, ptr
, data32
, GETPC());
1093 ptr
+= (14 << data32
);
1095 for (i
= 0; i
< 8; i
++) {
1096 tmp
= helper_fldt(env
, ptr
, GETPC());
1102 #if defined(CONFIG_USER_ONLY)
1103 void cpu_x86_fsave(CPUX86State
*env
, target_ulong ptr
, int data32
)
1105 helper_fsave(env
, ptr
, data32
);
1108 void cpu_x86_frstor(CPUX86State
*env
, target_ulong ptr
, int data32
)
1110 helper_frstor(env
, ptr
, data32
);
1114 #define XO(X) offsetof(X86XSaveArea, X)
1116 static void do_xsave_fpu(CPUX86State
*env
, target_ulong ptr
, uintptr_t ra
)
1121 fpus
= (env
->fpus
& ~0x3800) | (env
->fpstt
& 0x7) << 11;
1123 for (i
= 0; i
< 8; i
++) {
1124 fptag
|= (env
->fptags
[i
] << i
);
1127 cpu_stw_data_ra(env
, ptr
+ XO(legacy
.fcw
), env
->fpuc
, ra
);
1128 cpu_stw_data_ra(env
, ptr
+ XO(legacy
.fsw
), fpus
, ra
);
1129 cpu_stw_data_ra(env
, ptr
+ XO(legacy
.ftw
), fptag
^ 0xff, ra
);
1131 /* In 32-bit mode this is eip, sel, dp, sel.
1132 In 64-bit mode this is rip, rdp.
1133 But in either case we don't write actual data, just zeros. */
1134 cpu_stq_data_ra(env
, ptr
+ XO(legacy
.fpip
), 0, ra
); /* eip+sel; rip */
1135 cpu_stq_data_ra(env
, ptr
+ XO(legacy
.fpdp
), 0, ra
); /* edp+sel; rdp */
1137 addr
= ptr
+ XO(legacy
.fpregs
);
1138 for (i
= 0; i
< 8; i
++) {
1139 floatx80 tmp
= ST(i
);
1140 helper_fstt(env
, tmp
, addr
, ra
);
1145 static void do_xsave_mxcsr(CPUX86State
*env
, target_ulong ptr
, uintptr_t ra
)
1147 cpu_stl_data_ra(env
, ptr
+ XO(legacy
.mxcsr
), env
->mxcsr
, ra
);
1148 cpu_stl_data_ra(env
, ptr
+ XO(legacy
.mxcsr_mask
), 0x0000ffff, ra
);
1151 static void do_xsave_sse(CPUX86State
*env
, target_ulong ptr
, uintptr_t ra
)
1156 if (env
->hflags
& HF_CS64_MASK
) {
1162 addr
= ptr
+ XO(legacy
.xmm_regs
);
1163 for (i
= 0; i
< nb_xmm_regs
; i
++) {
1164 cpu_stq_data_ra(env
, addr
, env
->xmm_regs
[i
].ZMM_Q(0), ra
);
1165 cpu_stq_data_ra(env
, addr
+ 8, env
->xmm_regs
[i
].ZMM_Q(1), ra
);
1170 static void do_xsave_bndregs(CPUX86State
*env
, target_ulong ptr
, uintptr_t ra
)
1172 target_ulong addr
= ptr
+ offsetof(XSaveBNDREG
, bnd_regs
);
1175 for (i
= 0; i
< 4; i
++, addr
+= 16) {
1176 cpu_stq_data_ra(env
, addr
, env
->bnd_regs
[i
].lb
, ra
);
1177 cpu_stq_data_ra(env
, addr
+ 8, env
->bnd_regs
[i
].ub
, ra
);
1181 static void do_xsave_bndcsr(CPUX86State
*env
, target_ulong ptr
, uintptr_t ra
)
1183 cpu_stq_data_ra(env
, ptr
+ offsetof(XSaveBNDCSR
, bndcsr
.cfgu
),
1184 env
->bndcs_regs
.cfgu
, ra
);
1185 cpu_stq_data_ra(env
, ptr
+ offsetof(XSaveBNDCSR
, bndcsr
.sts
),
1186 env
->bndcs_regs
.sts
, ra
);
1189 static void do_xsave_pkru(CPUX86State
*env
, target_ulong ptr
, uintptr_t ra
)
1191 cpu_stq_data_ra(env
, ptr
, env
->pkru
, ra
);
1194 void helper_fxsave(CPUX86State
*env
, target_ulong ptr
)
1196 uintptr_t ra
= GETPC();
1198 /* The operand must be 16 byte aligned */
1200 raise_exception_ra(env
, EXCP0D_GPF
, ra
);
1203 do_xsave_fpu(env
, ptr
, ra
);
1205 if (env
->cr
[4] & CR4_OSFXSR_MASK
) {
1206 do_xsave_mxcsr(env
, ptr
, ra
);
1207 /* Fast FXSAVE leaves out the XMM registers */
1208 if (!(env
->efer
& MSR_EFER_FFXSR
)
1209 || (env
->hflags
& HF_CPL_MASK
)
1210 || !(env
->hflags
& HF_LMA_MASK
)) {
1211 do_xsave_sse(env
, ptr
, ra
);
1216 static uint64_t get_xinuse(CPUX86State
*env
)
1218 uint64_t inuse
= -1;
1220 /* For the most part, we don't track XINUSE. We could calculate it
1221 here for all components, but it's probably less work to simply
1222 indicate in use. That said, the state of BNDREGS is important
1223 enough to track in HFLAGS, so we might as well use that here. */
1224 if ((env
->hflags
& HF_MPX_IU_MASK
) == 0) {
1225 inuse
&= ~XSTATE_BNDREGS_MASK
;
1230 static void do_xsave(CPUX86State
*env
, target_ulong ptr
, uint64_t rfbm
,
1231 uint64_t inuse
, uint64_t opt
, uintptr_t ra
)
1233 uint64_t old_bv
, new_bv
;
1235 /* The OS must have enabled XSAVE. */
1236 if (!(env
->cr
[4] & CR4_OSXSAVE_MASK
)) {
1237 raise_exception_ra(env
, EXCP06_ILLOP
, ra
);
1240 /* The operand must be 64 byte aligned. */
1242 raise_exception_ra(env
, EXCP0D_GPF
, ra
);
1245 /* Never save anything not enabled by XCR0. */
1249 if (opt
& XSTATE_FP_MASK
) {
1250 do_xsave_fpu(env
, ptr
, ra
);
1252 if (rfbm
& XSTATE_SSE_MASK
) {
1253 /* Note that saving MXCSR is not suppressed by XSAVEOPT. */
1254 do_xsave_mxcsr(env
, ptr
, ra
);
1256 if (opt
& XSTATE_SSE_MASK
) {
1257 do_xsave_sse(env
, ptr
, ra
);
1259 if (opt
& XSTATE_BNDREGS_MASK
) {
1260 do_xsave_bndregs(env
, ptr
+ XO(bndreg_state
), ra
);
1262 if (opt
& XSTATE_BNDCSR_MASK
) {
1263 do_xsave_bndcsr(env
, ptr
+ XO(bndcsr_state
), ra
);
1265 if (opt
& XSTATE_PKRU_MASK
) {
1266 do_xsave_pkru(env
, ptr
+ XO(pkru_state
), ra
);
1269 /* Update the XSTATE_BV field. */
1270 old_bv
= cpu_ldq_data_ra(env
, ptr
+ XO(header
.xstate_bv
), ra
);
1271 new_bv
= (old_bv
& ~rfbm
) | (inuse
& rfbm
);
1272 cpu_stq_data_ra(env
, ptr
+ XO(header
.xstate_bv
), new_bv
, ra
);
1275 void helper_xsave(CPUX86State
*env
, target_ulong ptr
, uint64_t rfbm
)
1277 do_xsave(env
, ptr
, rfbm
, get_xinuse(env
), -1, GETPC());
1280 void helper_xsaveopt(CPUX86State
*env
, target_ulong ptr
, uint64_t rfbm
)
1282 uint64_t inuse
= get_xinuse(env
);
1283 do_xsave(env
, ptr
, rfbm
, inuse
, inuse
, GETPC());
1286 static void do_xrstor_fpu(CPUX86State
*env
, target_ulong ptr
, uintptr_t ra
)
1288 int i
, fpuc
, fpus
, fptag
;
1291 fpuc
= cpu_lduw_data_ra(env
, ptr
+ XO(legacy
.fcw
), ra
);
1292 fpus
= cpu_lduw_data_ra(env
, ptr
+ XO(legacy
.fsw
), ra
);
1293 fptag
= cpu_lduw_data_ra(env
, ptr
+ XO(legacy
.ftw
), ra
);
1294 cpu_set_fpuc(env
, fpuc
);
1295 env
->fpstt
= (fpus
>> 11) & 7;
1296 env
->fpus
= fpus
& ~0x3800;
1298 for (i
= 0; i
< 8; i
++) {
1299 env
->fptags
[i
] = ((fptag
>> i
) & 1);
1302 addr
= ptr
+ XO(legacy
.fpregs
);
1303 for (i
= 0; i
< 8; i
++) {
1304 floatx80 tmp
= helper_fldt(env
, addr
, ra
);
1310 static void do_xrstor_mxcsr(CPUX86State
*env
, target_ulong ptr
, uintptr_t ra
)
1312 cpu_set_mxcsr(env
, cpu_ldl_data_ra(env
, ptr
+ XO(legacy
.mxcsr
), ra
));
1315 static void do_xrstor_sse(CPUX86State
*env
, target_ulong ptr
, uintptr_t ra
)
1320 if (env
->hflags
& HF_CS64_MASK
) {
1326 addr
= ptr
+ XO(legacy
.xmm_regs
);
1327 for (i
= 0; i
< nb_xmm_regs
; i
++) {
1328 env
->xmm_regs
[i
].ZMM_Q(0) = cpu_ldq_data_ra(env
, addr
, ra
);
1329 env
->xmm_regs
[i
].ZMM_Q(1) = cpu_ldq_data_ra(env
, addr
+ 8, ra
);
1334 static void do_xrstor_bndregs(CPUX86State
*env
, target_ulong ptr
, uintptr_t ra
)
1336 target_ulong addr
= ptr
+ offsetof(XSaveBNDREG
, bnd_regs
);
1339 for (i
= 0; i
< 4; i
++, addr
+= 16) {
1340 env
->bnd_regs
[i
].lb
= cpu_ldq_data_ra(env
, addr
, ra
);
1341 env
->bnd_regs
[i
].ub
= cpu_ldq_data_ra(env
, addr
+ 8, ra
);
1345 static void do_xrstor_bndcsr(CPUX86State
*env
, target_ulong ptr
, uintptr_t ra
)
1347 /* FIXME: Extend highest implemented bit of linear address. */
1348 env
->bndcs_regs
.cfgu
1349 = cpu_ldq_data_ra(env
, ptr
+ offsetof(XSaveBNDCSR
, bndcsr
.cfgu
), ra
);
1351 = cpu_ldq_data_ra(env
, ptr
+ offsetof(XSaveBNDCSR
, bndcsr
.sts
), ra
);
1354 static void do_xrstor_pkru(CPUX86State
*env
, target_ulong ptr
, uintptr_t ra
)
1356 env
->pkru
= cpu_ldq_data_ra(env
, ptr
, ra
);
1359 void helper_fxrstor(CPUX86State
*env
, target_ulong ptr
)
1361 uintptr_t ra
= GETPC();
1363 /* The operand must be 16 byte aligned */
1365 raise_exception_ra(env
, EXCP0D_GPF
, ra
);
1368 do_xrstor_fpu(env
, ptr
, ra
);
1370 if (env
->cr
[4] & CR4_OSFXSR_MASK
) {
1371 do_xrstor_mxcsr(env
, ptr
, ra
);
1372 /* Fast FXRSTOR leaves out the XMM registers */
1373 if (!(env
->efer
& MSR_EFER_FFXSR
)
1374 || (env
->hflags
& HF_CPL_MASK
)
1375 || !(env
->hflags
& HF_LMA_MASK
)) {
1376 do_xrstor_sse(env
, ptr
, ra
);
1381 #if defined(CONFIG_USER_ONLY)
1382 void cpu_x86_fxsave(CPUX86State
*env
, target_ulong ptr
)
1384 helper_fxsave(env
, ptr
);
1387 void cpu_x86_fxrstor(CPUX86State
*env
, target_ulong ptr
)
1389 helper_fxrstor(env
, ptr
);
1393 void helper_xrstor(CPUX86State
*env
, target_ulong ptr
, uint64_t rfbm
)
1395 uintptr_t ra
= GETPC();
1396 uint64_t xstate_bv
, xcomp_bv
, reserve0
;
1400 /* The OS must have enabled XSAVE. */
1401 if (!(env
->cr
[4] & CR4_OSXSAVE_MASK
)) {
1402 raise_exception_ra(env
, EXCP06_ILLOP
, ra
);
1405 /* The operand must be 64 byte aligned. */
1407 raise_exception_ra(env
, EXCP0D_GPF
, ra
);
1410 xstate_bv
= cpu_ldq_data_ra(env
, ptr
+ XO(header
.xstate_bv
), ra
);
1412 if ((int64_t)xstate_bv
< 0) {
1413 /* FIXME: Compact form. */
1414 raise_exception_ra(env
, EXCP0D_GPF
, ra
);
1417 /* Standard form. */
1419 /* The XSTATE_BV field must not set bits not present in XCR0. */
1420 if (xstate_bv
& ~env
->xcr0
) {
1421 raise_exception_ra(env
, EXCP0D_GPF
, ra
);
1424 /* The XCOMP_BV field must be zero. Note that, as of the April 2016
1425 revision, the description of the XSAVE Header (Vol 1, Sec 13.4.2)
1426 describes only XCOMP_BV, but the description of the standard form
1427 of XRSTOR (Vol 1, Sec 13.8.1) checks bytes 23:8 for zero, which
1428 includes the next 64-bit field. */
1429 xcomp_bv
= cpu_ldq_data_ra(env
, ptr
+ XO(header
.xcomp_bv
), ra
);
1430 reserve0
= cpu_ldq_data_ra(env
, ptr
+ XO(header
.reserve0
), ra
);
1431 if (xcomp_bv
|| reserve0
) {
1432 raise_exception_ra(env
, EXCP0D_GPF
, ra
);
1435 if (rfbm
& XSTATE_FP_MASK
) {
1436 if (xstate_bv
& XSTATE_FP_MASK
) {
1437 do_xrstor_fpu(env
, ptr
, ra
);
1440 memset(env
->fpregs
, 0, sizeof(env
->fpregs
));
1443 if (rfbm
& XSTATE_SSE_MASK
) {
1444 /* Note that the standard form of XRSTOR loads MXCSR from memory
1445 whether or not the XSTATE_BV bit is set. */
1446 do_xrstor_mxcsr(env
, ptr
, ra
);
1447 if (xstate_bv
& XSTATE_SSE_MASK
) {
1448 do_xrstor_sse(env
, ptr
, ra
);
1450 /* ??? When AVX is implemented, we may have to be more
1451 selective in the clearing. */
1452 memset(env
->xmm_regs
, 0, sizeof(env
->xmm_regs
));
1455 if (rfbm
& XSTATE_BNDREGS_MASK
) {
1456 if (xstate_bv
& XSTATE_BNDREGS_MASK
) {
1457 do_xrstor_bndregs(env
, ptr
+ XO(bndreg_state
), ra
);
1458 env
->hflags
|= HF_MPX_IU_MASK
;
1460 memset(env
->bnd_regs
, 0, sizeof(env
->bnd_regs
));
1461 env
->hflags
&= ~HF_MPX_IU_MASK
;
1464 if (rfbm
& XSTATE_BNDCSR_MASK
) {
1465 if (xstate_bv
& XSTATE_BNDCSR_MASK
) {
1466 do_xrstor_bndcsr(env
, ptr
+ XO(bndcsr_state
), ra
);
1468 memset(&env
->bndcs_regs
, 0, sizeof(env
->bndcs_regs
));
1470 cpu_sync_bndcs_hflags(env
);
1472 if (rfbm
& XSTATE_PKRU_MASK
) {
1473 uint64_t old_pkru
= env
->pkru
;
1474 if (xstate_bv
& XSTATE_PKRU_MASK
) {
1475 do_xrstor_pkru(env
, ptr
+ XO(pkru_state
), ra
);
1479 if (env
->pkru
!= old_pkru
) {
1480 CPUState
*cs
= CPU(x86_env_get_cpu(env
));
1488 uint64_t helper_xgetbv(CPUX86State
*env
, uint32_t ecx
)
1490 /* The OS must have enabled XSAVE. */
1491 if (!(env
->cr
[4] & CR4_OSXSAVE_MASK
)) {
1492 raise_exception_ra(env
, EXCP06_ILLOP
, GETPC());
1499 if (env
->features
[FEAT_XSAVE
] & CPUID_XSAVE_XGETBV1
) {
1500 return env
->xcr0
& get_xinuse(env
);
1504 raise_exception_ra(env
, EXCP0D_GPF
, GETPC());
1507 void helper_xsetbv(CPUX86State
*env
, uint32_t ecx
, uint64_t mask
)
1509 uint32_t dummy
, ena_lo
, ena_hi
;
1512 /* The OS must have enabled XSAVE. */
1513 if (!(env
->cr
[4] & CR4_OSXSAVE_MASK
)) {
1514 raise_exception_ra(env
, EXCP06_ILLOP
, GETPC());
1517 /* Only XCR0 is defined at present; the FPU may not be disabled. */
1518 if (ecx
!= 0 || (mask
& XSTATE_FP_MASK
) == 0) {
1522 /* Disallow enabling unimplemented features. */
1523 cpu_x86_cpuid(env
, 0x0d, 0, &ena_lo
, &dummy
, &dummy
, &ena_hi
);
1524 ena
= ((uint64_t)ena_hi
<< 32) | ena_lo
;
1529 /* Disallow enabling only half of MPX. */
1530 if ((mask
^ (mask
* (XSTATE_BNDCSR_MASK
/ XSTATE_BNDREGS_MASK
)))
1531 & XSTATE_BNDCSR_MASK
) {
1536 cpu_sync_bndcs_hflags(env
);
1540 raise_exception_ra(env
, EXCP0D_GPF
, GETPC());
1544 /* XXX: optimize by storing fptt and fptags in the static cpu state */
1546 #define SSE_DAZ 0x0040
1547 #define SSE_RC_MASK 0x6000
1548 #define SSE_RC_NEAR 0x0000
1549 #define SSE_RC_DOWN 0x2000
1550 #define SSE_RC_UP 0x4000
1551 #define SSE_RC_CHOP 0x6000
1552 #define SSE_FZ 0x8000
1554 void update_mxcsr_status(CPUX86State
*env
)
1556 uint32_t mxcsr
= env
->mxcsr
;
1559 /* set rounding mode */
1560 switch (mxcsr
& SSE_RC_MASK
) {
1563 rnd_type
= float_round_nearest_even
;
1566 rnd_type
= float_round_down
;
1569 rnd_type
= float_round_up
;
1572 rnd_type
= float_round_to_zero
;
1575 set_float_rounding_mode(rnd_type
, &env
->sse_status
);
1577 /* set denormals are zero */
1578 set_flush_inputs_to_zero((mxcsr
& SSE_DAZ
) ? 1 : 0, &env
->sse_status
);
1580 /* set flush to zero */
1581 set_flush_to_zero((mxcsr
& SSE_FZ
) ? 1 : 0, &env
->fp_status
);
1584 void helper_ldmxcsr(CPUX86State
*env
, uint32_t val
)
1586 cpu_set_mxcsr(env
, val
);
1589 void helper_enter_mmx(CPUX86State
*env
)
1592 *(uint32_t *)(env
->fptags
) = 0;
1593 *(uint32_t *)(env
->fptags
+ 4) = 0;
1596 void helper_emms(CPUX86State
*env
)
1598 /* set to empty state */
1599 *(uint32_t *)(env
->fptags
) = 0x01010101;
1600 *(uint32_t *)(env
->fptags
+ 4) = 0x01010101;
1604 void helper_movq(CPUX86State
*env
, void *d
, void *s
)
1606 *(uint64_t *)d
= *(uint64_t *)s
;
1610 #include "ops_sse.h"
1613 #include "ops_sse.h"