]> Git Repo - qemu.git/blame - target-i386/fpu_helper.c
x86: avoid AREG0 for FPU helpers
[qemu.git] / target-i386 / fpu_helper.c
CommitLineData
f299f437
BS
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 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 <math.h>
21#include "cpu.h"
f299f437
BS
22#include "helper.h"
23
f299f437
BS
24#define FPU_RC_MASK 0xc00
25#define FPU_RC_NEAR 0x000
26#define FPU_RC_DOWN 0x400
27#define FPU_RC_UP 0x800
28#define FPU_RC_CHOP 0xc00
29
30#define MAXTAN 9223372036854775808.0
31
32/* the following deal with x86 long double-precision numbers */
33#define MAXEXPD 0x7fff
34#define EXPBIAS 16383
35#define EXPD(fp) (fp.l.upper & 0x7fff)
36#define SIGND(fp) ((fp.l.upper) & 0x8000)
37#define MANTD(fp) (fp.l.lower)
38#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
39
40#define FPUS_IE (1 << 0)
41#define FPUS_DE (1 << 1)
42#define FPUS_ZE (1 << 2)
43#define FPUS_OE (1 << 3)
44#define FPUS_UE (1 << 4)
45#define FPUS_PE (1 << 5)
46#define FPUS_SF (1 << 6)
47#define FPUS_SE (1 << 7)
48#define FPUS_B (1 << 15)
49
50#define FPUC_EM 0x3f
51
52#define floatx80_lg2 make_floatx80(0x3ffd, 0x9a209a84fbcff799LL)
53#define floatx80_l2e make_floatx80(0x3fff, 0xb8aa3b295c17f0bcLL)
54#define floatx80_l2t make_floatx80(0x4000, 0xd49a784bcd1b8afeLL)
55
d3eb5eae 56static inline void fpush(CPUX86State *env)
f299f437
BS
57{
58 env->fpstt = (env->fpstt - 1) & 7;
59 env->fptags[env->fpstt] = 0; /* validate stack entry */
60}
61
d3eb5eae 62static inline void fpop(CPUX86State *env)
f299f437
BS
63{
64 env->fptags[env->fpstt] = 1; /* invalidate stack entry */
65 env->fpstt = (env->fpstt + 1) & 7;
66}
67
d3eb5eae 68static inline floatx80 helper_fldt(CPUX86State *env, target_ulong ptr)
f299f437
BS
69{
70 CPU_LDoubleU temp;
71
d3eb5eae
BS
72 temp.l.lower = cpu_ldq_data(env, ptr);
73 temp.l.upper = cpu_lduw_data(env, ptr + 8);
f299f437
BS
74 return temp.d;
75}
76
d3eb5eae 77static inline void helper_fstt(CPUX86State *env, floatx80 f, target_ulong ptr)
f299f437
BS
78{
79 CPU_LDoubleU temp;
80
81 temp.d = f;
d3eb5eae
BS
82 cpu_stq_data(env, ptr, temp.l.lower);
83 cpu_stw_data(env, ptr + 8, temp.l.upper);
f299f437
BS
84}
85
86/* x87 FPU helpers */
87
d3eb5eae 88static inline double floatx80_to_double(CPUX86State *env, floatx80 a)
f299f437
BS
89{
90 union {
91 float64 f64;
92 double d;
93 } u;
94
95 u.f64 = floatx80_to_float64(a, &env->fp_status);
96 return u.d;
97}
98
d3eb5eae 99static inline floatx80 double_to_floatx80(CPUX86State *env, double a)
f299f437
BS
100{
101 union {
102 float64 f64;
103 double d;
104 } u;
105
106 u.d = a;
107 return float64_to_floatx80(u.f64, &env->fp_status);
108}
109
d3eb5eae 110static void fpu_set_exception(CPUX86State *env, int mask)
f299f437
BS
111{
112 env->fpus |= mask;
113 if (env->fpus & (~env->fpuc & FPUC_EM)) {
114 env->fpus |= FPUS_SE | FPUS_B;
115 }
116}
117
d3eb5eae 118static inline floatx80 helper_fdiv(CPUX86State *env, floatx80 a, floatx80 b)
f299f437
BS
119{
120 if (floatx80_is_zero(b)) {
d3eb5eae 121 fpu_set_exception(env, FPUS_ZE);
f299f437
BS
122 }
123 return floatx80_div(a, b, &env->fp_status);
124}
125
d3eb5eae 126static void fpu_raise_exception(CPUX86State *env)
f299f437
BS
127{
128 if (env->cr[0] & CR0_NE_MASK) {
129 raise_exception(env, EXCP10_COPR);
130 }
131#if !defined(CONFIG_USER_ONLY)
132 else {
133 cpu_set_ferr(env);
134 }
135#endif
136}
137
d3eb5eae 138void helper_flds_FT0(CPUX86State *env, uint32_t val)
f299f437
BS
139{
140 union {
141 float32 f;
142 uint32_t i;
143 } u;
144
145 u.i = val;
146 FT0 = float32_to_floatx80(u.f, &env->fp_status);
147}
148
d3eb5eae 149void helper_fldl_FT0(CPUX86State *env, uint64_t val)
f299f437
BS
150{
151 union {
152 float64 f;
153 uint64_t i;
154 } u;
155
156 u.i = val;
157 FT0 = float64_to_floatx80(u.f, &env->fp_status);
158}
159
d3eb5eae 160void helper_fildl_FT0(CPUX86State *env, int32_t val)
f299f437
BS
161{
162 FT0 = int32_to_floatx80(val, &env->fp_status);
163}
164
d3eb5eae 165void helper_flds_ST0(CPUX86State *env, uint32_t val)
f299f437
BS
166{
167 int new_fpstt;
168 union {
169 float32 f;
170 uint32_t i;
171 } u;
172
173 new_fpstt = (env->fpstt - 1) & 7;
174 u.i = val;
175 env->fpregs[new_fpstt].d = float32_to_floatx80(u.f, &env->fp_status);
176 env->fpstt = new_fpstt;
177 env->fptags[new_fpstt] = 0; /* validate stack entry */
178}
179
d3eb5eae 180void helper_fldl_ST0(CPUX86State *env, uint64_t val)
f299f437
BS
181{
182 int new_fpstt;
183 union {
184 float64 f;
185 uint64_t i;
186 } u;
187
188 new_fpstt = (env->fpstt - 1) & 7;
189 u.i = val;
190 env->fpregs[new_fpstt].d = float64_to_floatx80(u.f, &env->fp_status);
191 env->fpstt = new_fpstt;
192 env->fptags[new_fpstt] = 0; /* validate stack entry */
193}
194
d3eb5eae 195void helper_fildl_ST0(CPUX86State *env, int32_t val)
f299f437
BS
196{
197 int new_fpstt;
198
199 new_fpstt = (env->fpstt - 1) & 7;
200 env->fpregs[new_fpstt].d = int32_to_floatx80(val, &env->fp_status);
201 env->fpstt = new_fpstt;
202 env->fptags[new_fpstt] = 0; /* validate stack entry */
203}
204
d3eb5eae 205void helper_fildll_ST0(CPUX86State *env, int64_t val)
f299f437
BS
206{
207 int new_fpstt;
208
209 new_fpstt = (env->fpstt - 1) & 7;
210 env->fpregs[new_fpstt].d = int64_to_floatx80(val, &env->fp_status);
211 env->fpstt = new_fpstt;
212 env->fptags[new_fpstt] = 0; /* validate stack entry */
213}
214
d3eb5eae 215uint32_t helper_fsts_ST0(CPUX86State *env)
f299f437
BS
216{
217 union {
218 float32 f;
219 uint32_t i;
220 } u;
221
222 u.f = floatx80_to_float32(ST0, &env->fp_status);
223 return u.i;
224}
225
d3eb5eae 226uint64_t helper_fstl_ST0(CPUX86State *env)
f299f437
BS
227{
228 union {
229 float64 f;
230 uint64_t i;
231 } u;
232
233 u.f = floatx80_to_float64(ST0, &env->fp_status);
234 return u.i;
235}
236
d3eb5eae 237int32_t helper_fist_ST0(CPUX86State *env)
f299f437
BS
238{
239 int32_t val;
240
241 val = floatx80_to_int32(ST0, &env->fp_status);
242 if (val != (int16_t)val) {
243 val = -32768;
244 }
245 return val;
246}
247
d3eb5eae 248int32_t helper_fistl_ST0(CPUX86State *env)
f299f437
BS
249{
250 int32_t val;
251
252 val = floatx80_to_int32(ST0, &env->fp_status);
253 return val;
254}
255
d3eb5eae 256int64_t helper_fistll_ST0(CPUX86State *env)
f299f437
BS
257{
258 int64_t val;
259
260 val = floatx80_to_int64(ST0, &env->fp_status);
261 return val;
262}
263
d3eb5eae 264int32_t helper_fistt_ST0(CPUX86State *env)
f299f437
BS
265{
266 int32_t val;
267
268 val = floatx80_to_int32_round_to_zero(ST0, &env->fp_status);
269 if (val != (int16_t)val) {
270 val = -32768;
271 }
272 return val;
273}
274
d3eb5eae 275int32_t helper_fisttl_ST0(CPUX86State *env)
f299f437
BS
276{
277 int32_t val;
278
279 val = floatx80_to_int32_round_to_zero(ST0, &env->fp_status);
280 return val;
281}
282
d3eb5eae 283int64_t helper_fisttll_ST0(CPUX86State *env)
f299f437
BS
284{
285 int64_t val;
286
287 val = floatx80_to_int64_round_to_zero(ST0, &env->fp_status);
288 return val;
289}
290
d3eb5eae 291void helper_fldt_ST0(CPUX86State *env, target_ulong ptr)
f299f437
BS
292{
293 int new_fpstt;
294
295 new_fpstt = (env->fpstt - 1) & 7;
d3eb5eae 296 env->fpregs[new_fpstt].d = helper_fldt(env, ptr);
f299f437
BS
297 env->fpstt = new_fpstt;
298 env->fptags[new_fpstt] = 0; /* validate stack entry */
299}
300
d3eb5eae 301void helper_fstt_ST0(CPUX86State *env, target_ulong ptr)
f299f437 302{
d3eb5eae 303 helper_fstt(env, ST0, ptr);
f299f437
BS
304}
305
d3eb5eae 306void helper_fpush(CPUX86State *env)
f299f437 307{
d3eb5eae 308 fpush(env);
f299f437
BS
309}
310
d3eb5eae 311void helper_fpop(CPUX86State *env)
f299f437 312{
d3eb5eae 313 fpop(env);
f299f437
BS
314}
315
d3eb5eae 316void helper_fdecstp(CPUX86State *env)
f299f437
BS
317{
318 env->fpstt = (env->fpstt - 1) & 7;
319 env->fpus &= ~0x4700;
320}
321
d3eb5eae 322void helper_fincstp(CPUX86State *env)
f299f437
BS
323{
324 env->fpstt = (env->fpstt + 1) & 7;
325 env->fpus &= ~0x4700;
326}
327
328/* FPU move */
329
d3eb5eae 330void helper_ffree_STN(CPUX86State *env, int st_index)
f299f437
BS
331{
332 env->fptags[(env->fpstt + st_index) & 7] = 1;
333}
334
d3eb5eae 335void helper_fmov_ST0_FT0(CPUX86State *env)
f299f437
BS
336{
337 ST0 = FT0;
338}
339
d3eb5eae 340void helper_fmov_FT0_STN(CPUX86State *env, int st_index)
f299f437
BS
341{
342 FT0 = ST(st_index);
343}
344
d3eb5eae 345void helper_fmov_ST0_STN(CPUX86State *env, int st_index)
f299f437
BS
346{
347 ST0 = ST(st_index);
348}
349
d3eb5eae 350void helper_fmov_STN_ST0(CPUX86State *env, int st_index)
f299f437
BS
351{
352 ST(st_index) = ST0;
353}
354
d3eb5eae 355void helper_fxchg_ST0_STN(CPUX86State *env, int st_index)
f299f437
BS
356{
357 floatx80 tmp;
358
359 tmp = ST(st_index);
360 ST(st_index) = ST0;
361 ST0 = tmp;
362}
363
364/* FPU operations */
365
366static const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500};
367
d3eb5eae 368void helper_fcom_ST0_FT0(CPUX86State *env)
f299f437
BS
369{
370 int ret;
371
372 ret = floatx80_compare(ST0, FT0, &env->fp_status);
373 env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
374}
375
d3eb5eae 376void helper_fucom_ST0_FT0(CPUX86State *env)
f299f437
BS
377{
378 int ret;
379
380 ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
381 env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
382}
383
384static const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C};
385
d3eb5eae 386void helper_fcomi_ST0_FT0(CPUX86State *env)
f299f437
BS
387{
388 int eflags;
389 int ret;
390
391 ret = floatx80_compare(ST0, FT0, &env->fp_status);
d3eb5eae 392 eflags = cpu_cc_compute_all(env, CC_OP);
f299f437
BS
393 eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
394 CC_SRC = eflags;
395}
396
d3eb5eae 397void helper_fucomi_ST0_FT0(CPUX86State *env)
f299f437
BS
398{
399 int eflags;
400 int ret;
401
402 ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
d3eb5eae 403 eflags = cpu_cc_compute_all(env, CC_OP);
f299f437
BS
404 eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
405 CC_SRC = eflags;
406}
407
d3eb5eae 408void helper_fadd_ST0_FT0(CPUX86State *env)
f299f437
BS
409{
410 ST0 = floatx80_add(ST0, FT0, &env->fp_status);
411}
412
d3eb5eae 413void helper_fmul_ST0_FT0(CPUX86State *env)
f299f437
BS
414{
415 ST0 = floatx80_mul(ST0, FT0, &env->fp_status);
416}
417
d3eb5eae 418void helper_fsub_ST0_FT0(CPUX86State *env)
f299f437
BS
419{
420 ST0 = floatx80_sub(ST0, FT0, &env->fp_status);
421}
422
d3eb5eae 423void helper_fsubr_ST0_FT0(CPUX86State *env)
f299f437
BS
424{
425 ST0 = floatx80_sub(FT0, ST0, &env->fp_status);
426}
427
d3eb5eae 428void helper_fdiv_ST0_FT0(CPUX86State *env)
f299f437 429{
d3eb5eae 430 ST0 = helper_fdiv(env, ST0, FT0);
f299f437
BS
431}
432
d3eb5eae 433void helper_fdivr_ST0_FT0(CPUX86State *env)
f299f437 434{
d3eb5eae 435 ST0 = helper_fdiv(env, FT0, ST0);
f299f437
BS
436}
437
438/* fp operations between STN and ST0 */
439
d3eb5eae 440void helper_fadd_STN_ST0(CPUX86State *env, int st_index)
f299f437
BS
441{
442 ST(st_index) = floatx80_add(ST(st_index), ST0, &env->fp_status);
443}
444
d3eb5eae 445void helper_fmul_STN_ST0(CPUX86State *env, int st_index)
f299f437
BS
446{
447 ST(st_index) = floatx80_mul(ST(st_index), ST0, &env->fp_status);
448}
449
d3eb5eae 450void helper_fsub_STN_ST0(CPUX86State *env, int st_index)
f299f437
BS
451{
452 ST(st_index) = floatx80_sub(ST(st_index), ST0, &env->fp_status);
453}
454
d3eb5eae 455void helper_fsubr_STN_ST0(CPUX86State *env, int st_index)
f299f437
BS
456{
457 ST(st_index) = floatx80_sub(ST0, ST(st_index), &env->fp_status);
458}
459
d3eb5eae 460void helper_fdiv_STN_ST0(CPUX86State *env, int st_index)
f299f437
BS
461{
462 floatx80 *p;
463
464 p = &ST(st_index);
d3eb5eae 465 *p = helper_fdiv(env, *p, ST0);
f299f437
BS
466}
467
d3eb5eae 468void helper_fdivr_STN_ST0(CPUX86State *env, int st_index)
f299f437
BS
469{
470 floatx80 *p;
471
472 p = &ST(st_index);
d3eb5eae 473 *p = helper_fdiv(env, ST0, *p);
f299f437
BS
474}
475
476/* misc FPU operations */
d3eb5eae 477void helper_fchs_ST0(CPUX86State *env)
f299f437
BS
478{
479 ST0 = floatx80_chs(ST0);
480}
481
d3eb5eae 482void helper_fabs_ST0(CPUX86State *env)
f299f437
BS
483{
484 ST0 = floatx80_abs(ST0);
485}
486
d3eb5eae 487void helper_fld1_ST0(CPUX86State *env)
f299f437
BS
488{
489 ST0 = floatx80_one;
490}
491
d3eb5eae 492void helper_fldl2t_ST0(CPUX86State *env)
f299f437
BS
493{
494 ST0 = floatx80_l2t;
495}
496
d3eb5eae 497void helper_fldl2e_ST0(CPUX86State *env)
f299f437
BS
498{
499 ST0 = floatx80_l2e;
500}
501
d3eb5eae 502void helper_fldpi_ST0(CPUX86State *env)
f299f437
BS
503{
504 ST0 = floatx80_pi;
505}
506
d3eb5eae 507void helper_fldlg2_ST0(CPUX86State *env)
f299f437
BS
508{
509 ST0 = floatx80_lg2;
510}
511
d3eb5eae 512void helper_fldln2_ST0(CPUX86State *env)
f299f437
BS
513{
514 ST0 = floatx80_ln2;
515}
516
d3eb5eae 517void helper_fldz_ST0(CPUX86State *env)
f299f437
BS
518{
519 ST0 = floatx80_zero;
520}
521
d3eb5eae 522void helper_fldz_FT0(CPUX86State *env)
f299f437
BS
523{
524 FT0 = floatx80_zero;
525}
526
d3eb5eae 527uint32_t helper_fnstsw(CPUX86State *env)
f299f437
BS
528{
529 return (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
530}
531
d3eb5eae 532uint32_t helper_fnstcw(CPUX86State *env)
f299f437
BS
533{
534 return env->fpuc;
535}
536
d3eb5eae 537static void update_fp_status(CPUX86State *env)
f299f437
BS
538{
539 int rnd_type;
540
541 /* set rounding mode */
542 switch (env->fpuc & FPU_RC_MASK) {
543 default:
544 case FPU_RC_NEAR:
545 rnd_type = float_round_nearest_even;
546 break;
547 case FPU_RC_DOWN:
548 rnd_type = float_round_down;
549 break;
550 case FPU_RC_UP:
551 rnd_type = float_round_up;
552 break;
553 case FPU_RC_CHOP:
554 rnd_type = float_round_to_zero;
555 break;
556 }
557 set_float_rounding_mode(rnd_type, &env->fp_status);
558 switch ((env->fpuc >> 8) & 3) {
559 case 0:
560 rnd_type = 32;
561 break;
562 case 2:
563 rnd_type = 64;
564 break;
565 case 3:
566 default:
567 rnd_type = 80;
568 break;
569 }
570 set_floatx80_rounding_precision(rnd_type, &env->fp_status);
571}
572
d3eb5eae 573void helper_fldcw(CPUX86State *env, uint32_t val)
f299f437
BS
574{
575 env->fpuc = val;
d3eb5eae 576 update_fp_status(env);
f299f437
BS
577}
578
d3eb5eae 579void helper_fclex(CPUX86State *env)
f299f437
BS
580{
581 env->fpus &= 0x7f00;
582}
583
d3eb5eae 584void helper_fwait(CPUX86State *env)
f299f437
BS
585{
586 if (env->fpus & FPUS_SE) {
d3eb5eae 587 fpu_raise_exception(env);
f299f437
BS
588 }
589}
590
d3eb5eae 591void helper_fninit(CPUX86State *env)
f299f437
BS
592{
593 env->fpus = 0;
594 env->fpstt = 0;
595 env->fpuc = 0x37f;
596 env->fptags[0] = 1;
597 env->fptags[1] = 1;
598 env->fptags[2] = 1;
599 env->fptags[3] = 1;
600 env->fptags[4] = 1;
601 env->fptags[5] = 1;
602 env->fptags[6] = 1;
603 env->fptags[7] = 1;
604}
605
606/* BCD ops */
607
d3eb5eae 608void helper_fbld_ST0(CPUX86State *env, target_ulong ptr)
f299f437
BS
609{
610 floatx80 tmp;
611 uint64_t val;
612 unsigned int v;
613 int i;
614
615 val = 0;
616 for (i = 8; i >= 0; i--) {
d3eb5eae 617 v = cpu_ldub_data(env, ptr + i);
f299f437
BS
618 val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
619 }
620 tmp = int64_to_floatx80(val, &env->fp_status);
d3eb5eae 621 if (cpu_ldub_data(env, ptr + 9) & 0x80) {
f299f437
BS
622 floatx80_chs(tmp);
623 }
d3eb5eae 624 fpush(env);
f299f437
BS
625 ST0 = tmp;
626}
627
d3eb5eae 628void helper_fbst_ST0(CPUX86State *env, target_ulong ptr)
f299f437
BS
629{
630 int v;
631 target_ulong mem_ref, mem_end;
632 int64_t val;
633
634 val = floatx80_to_int64(ST0, &env->fp_status);
635 mem_ref = ptr;
636 mem_end = mem_ref + 9;
637 if (val < 0) {
d3eb5eae 638 cpu_stb_data(env, mem_end, 0x80);
f299f437
BS
639 val = -val;
640 } else {
d3eb5eae 641 cpu_stb_data(env, mem_end, 0x00);
f299f437
BS
642 }
643 while (mem_ref < mem_end) {
644 if (val == 0) {
645 break;
646 }
647 v = val % 100;
648 val = val / 100;
649 v = ((v / 10) << 4) | (v % 10);
d3eb5eae 650 cpu_stb_data(env, mem_ref++, v);
f299f437
BS
651 }
652 while (mem_ref < mem_end) {
d3eb5eae 653 cpu_stb_data(env, mem_ref++, 0);
f299f437
BS
654 }
655}
656
d3eb5eae 657void helper_f2xm1(CPUX86State *env)
f299f437 658{
d3eb5eae 659 double val = floatx80_to_double(env, ST0);
f299f437
BS
660
661 val = pow(2.0, val) - 1.0;
d3eb5eae 662 ST0 = double_to_floatx80(env, val);
f299f437
BS
663}
664
d3eb5eae 665void helper_fyl2x(CPUX86State *env)
f299f437 666{
d3eb5eae 667 double fptemp = floatx80_to_double(env, ST0);
f299f437
BS
668
669 if (fptemp > 0.0) {
670 fptemp = log(fptemp) / log(2.0); /* log2(ST) */
d3eb5eae
BS
671 fptemp *= floatx80_to_double(env, ST1);
672 ST1 = double_to_floatx80(env, fptemp);
673 fpop(env);
f299f437
BS
674 } else {
675 env->fpus &= ~0x4700;
676 env->fpus |= 0x400;
677 }
678}
679
d3eb5eae 680void helper_fptan(CPUX86State *env)
f299f437 681{
d3eb5eae 682 double fptemp = floatx80_to_double(env, ST0);
f299f437
BS
683
684 if ((fptemp > MAXTAN) || (fptemp < -MAXTAN)) {
685 env->fpus |= 0x400;
686 } else {
687 fptemp = tan(fptemp);
d3eb5eae
BS
688 ST0 = double_to_floatx80(env, fptemp);
689 fpush(env);
f299f437
BS
690 ST0 = floatx80_one;
691 env->fpus &= ~0x400; /* C2 <-- 0 */
692 /* the above code is for |arg| < 2**52 only */
693 }
694}
695
d3eb5eae 696void helper_fpatan(CPUX86State *env)
f299f437
BS
697{
698 double fptemp, fpsrcop;
699
d3eb5eae
BS
700 fpsrcop = floatx80_to_double(env, ST1);
701 fptemp = floatx80_to_double(env, ST0);
702 ST1 = double_to_floatx80(env, atan2(fpsrcop, fptemp));
703 fpop(env);
f299f437
BS
704}
705
d3eb5eae 706void helper_fxtract(CPUX86State *env)
f299f437
BS
707{
708 CPU_LDoubleU temp;
709
710 temp.d = ST0;
711
712 if (floatx80_is_zero(ST0)) {
713 /* Easy way to generate -inf and raising division by 0 exception */
714 ST0 = floatx80_div(floatx80_chs(floatx80_one), floatx80_zero,
715 &env->fp_status);
d3eb5eae 716 fpush(env);
f299f437
BS
717 ST0 = temp.d;
718 } else {
719 int expdif;
720
721 expdif = EXPD(temp) - EXPBIAS;
722 /* DP exponent bias */
723 ST0 = int32_to_floatx80(expdif, &env->fp_status);
d3eb5eae 724 fpush(env);
f299f437
BS
725 BIASEXPONENT(temp);
726 ST0 = temp.d;
727 }
728}
729
d3eb5eae 730void helper_fprem1(CPUX86State *env)
f299f437
BS
731{
732 double st0, st1, dblq, fpsrcop, fptemp;
733 CPU_LDoubleU fpsrcop1, fptemp1;
734 int expdif;
735 signed long long int q;
736
d3eb5eae
BS
737 st0 = floatx80_to_double(env, ST0);
738 st1 = floatx80_to_double(env, ST1);
f299f437
BS
739
740 if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) {
d3eb5eae 741 ST0 = double_to_floatx80(env, 0.0 / 0.0); /* NaN */
f299f437
BS
742 env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
743 return;
744 }
745
746 fpsrcop = st0;
747 fptemp = st1;
748 fpsrcop1.d = ST0;
749 fptemp1.d = ST1;
750 expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
751
752 if (expdif < 0) {
753 /* optimisation? taken from the AMD docs */
754 env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
755 /* ST0 is unchanged */
756 return;
757 }
758
759 if (expdif < 53) {
760 dblq = fpsrcop / fptemp;
761 /* round dblq towards nearest integer */
762 dblq = rint(dblq);
763 st0 = fpsrcop - fptemp * dblq;
764
765 /* convert dblq to q by truncating towards zero */
766 if (dblq < 0.0) {
767 q = (signed long long int)(-dblq);
768 } else {
769 q = (signed long long int)dblq;
770 }
771
772 env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
773 /* (C0,C3,C1) <-- (q2,q1,q0) */
774 env->fpus |= (q & 0x4) << (8 - 2); /* (C0) <-- q2 */
775 env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
776 env->fpus |= (q & 0x1) << (9 - 0); /* (C1) <-- q0 */
777 } else {
778 env->fpus |= 0x400; /* C2 <-- 1 */
779 fptemp = pow(2.0, expdif - 50);
780 fpsrcop = (st0 / st1) / fptemp;
781 /* fpsrcop = integer obtained by chopping */
782 fpsrcop = (fpsrcop < 0.0) ?
783 -(floor(fabs(fpsrcop))) : floor(fpsrcop);
784 st0 -= (st1 * fpsrcop * fptemp);
785 }
d3eb5eae 786 ST0 = double_to_floatx80(env, st0);
f299f437
BS
787}
788
d3eb5eae 789void helper_fprem(CPUX86State *env)
f299f437
BS
790{
791 double st0, st1, dblq, fpsrcop, fptemp;
792 CPU_LDoubleU fpsrcop1, fptemp1;
793 int expdif;
794 signed long long int q;
795
d3eb5eae
BS
796 st0 = floatx80_to_double(env, ST0);
797 st1 = floatx80_to_double(env, ST1);
f299f437
BS
798
799 if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) {
d3eb5eae 800 ST0 = double_to_floatx80(env, 0.0 / 0.0); /* NaN */
f299f437
BS
801 env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
802 return;
803 }
804
805 fpsrcop = st0;
806 fptemp = st1;
807 fpsrcop1.d = ST0;
808 fptemp1.d = ST1;
809 expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
810
811 if (expdif < 0) {
812 /* optimisation? taken from the AMD docs */
813 env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
814 /* ST0 is unchanged */
815 return;
816 }
817
818 if (expdif < 53) {
819 dblq = fpsrcop / fptemp; /* ST0 / ST1 */
820 /* round dblq towards zero */
821 dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq);
822 st0 = fpsrcop - fptemp * dblq; /* fpsrcop is ST0 */
823
824 /* convert dblq to q by truncating towards zero */
825 if (dblq < 0.0) {
826 q = (signed long long int)(-dblq);
827 } else {
828 q = (signed long long int)dblq;
829 }
830
831 env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
832 /* (C0,C3,C1) <-- (q2,q1,q0) */
833 env->fpus |= (q & 0x4) << (8 - 2); /* (C0) <-- q2 */
834 env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
835 env->fpus |= (q & 0x1) << (9 - 0); /* (C1) <-- q0 */
836 } else {
837 int N = 32 + (expdif % 32); /* as per AMD docs */
838
839 env->fpus |= 0x400; /* C2 <-- 1 */
840 fptemp = pow(2.0, (double)(expdif - N));
841 fpsrcop = (st0 / st1) / fptemp;
842 /* fpsrcop = integer obtained by chopping */
843 fpsrcop = (fpsrcop < 0.0) ?
844 -(floor(fabs(fpsrcop))) : floor(fpsrcop);
845 st0 -= (st1 * fpsrcop * fptemp);
846 }
d3eb5eae 847 ST0 = double_to_floatx80(env, st0);
f299f437
BS
848}
849
d3eb5eae 850void helper_fyl2xp1(CPUX86State *env)
f299f437 851{
d3eb5eae 852 double fptemp = floatx80_to_double(env, ST0);
f299f437
BS
853
854 if ((fptemp + 1.0) > 0.0) {
855 fptemp = log(fptemp + 1.0) / log(2.0); /* log2(ST + 1.0) */
d3eb5eae
BS
856 fptemp *= floatx80_to_double(env, ST1);
857 ST1 = double_to_floatx80(env, fptemp);
858 fpop(env);
f299f437
BS
859 } else {
860 env->fpus &= ~0x4700;
861 env->fpus |= 0x400;
862 }
863}
864
d3eb5eae 865void helper_fsqrt(CPUX86State *env)
f299f437
BS
866{
867 if (floatx80_is_neg(ST0)) {
868 env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
869 env->fpus |= 0x400;
870 }
871 ST0 = floatx80_sqrt(ST0, &env->fp_status);
872}
873
d3eb5eae 874void helper_fsincos(CPUX86State *env)
f299f437 875{
d3eb5eae 876 double fptemp = floatx80_to_double(env, ST0);
f299f437
BS
877
878 if ((fptemp > MAXTAN) || (fptemp < -MAXTAN)) {
879 env->fpus |= 0x400;
880 } else {
d3eb5eae
BS
881 ST0 = double_to_floatx80(env, sin(fptemp));
882 fpush(env);
883 ST0 = double_to_floatx80(env, cos(fptemp));
f299f437
BS
884 env->fpus &= ~0x400; /* C2 <-- 0 */
885 /* the above code is for |arg| < 2**63 only */
886 }
887}
888
d3eb5eae 889void helper_frndint(CPUX86State *env)
f299f437
BS
890{
891 ST0 = floatx80_round_to_int(ST0, &env->fp_status);
892}
893
d3eb5eae 894void helper_fscale(CPUX86State *env)
f299f437
BS
895{
896 if (floatx80_is_any_nan(ST1)) {
897 ST0 = ST1;
898 } else {
899 int n = floatx80_to_int32_round_to_zero(ST1, &env->fp_status);
900 ST0 = floatx80_scalbn(ST0, n, &env->fp_status);
901 }
902}
903
d3eb5eae 904void helper_fsin(CPUX86State *env)
f299f437 905{
d3eb5eae 906 double fptemp = floatx80_to_double(env, ST0);
f299f437
BS
907
908 if ((fptemp > MAXTAN) || (fptemp < -MAXTAN)) {
909 env->fpus |= 0x400;
910 } else {
d3eb5eae 911 ST0 = double_to_floatx80(env, sin(fptemp));
f299f437
BS
912 env->fpus &= ~0x400; /* C2 <-- 0 */
913 /* the above code is for |arg| < 2**53 only */
914 }
915}
916
d3eb5eae 917void helper_fcos(CPUX86State *env)
f299f437 918{
d3eb5eae 919 double fptemp = floatx80_to_double(env, ST0);
f299f437
BS
920
921 if ((fptemp > MAXTAN) || (fptemp < -MAXTAN)) {
922 env->fpus |= 0x400;
923 } else {
d3eb5eae 924 ST0 = double_to_floatx80(env, cos(fptemp));
f299f437
BS
925 env->fpus &= ~0x400; /* C2 <-- 0 */
926 /* the above code is for |arg| < 2**63 only */
927 }
928}
929
d3eb5eae 930void helper_fxam_ST0(CPUX86State *env)
f299f437
BS
931{
932 CPU_LDoubleU temp;
933 int expdif;
934
935 temp.d = ST0;
936
937 env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
938 if (SIGND(temp)) {
939 env->fpus |= 0x200; /* C1 <-- 1 */
940 }
941
942 /* XXX: test fptags too */
943 expdif = EXPD(temp);
944 if (expdif == MAXEXPD) {
945 if (MANTD(temp) == 0x8000000000000000ULL) {
946 env->fpus |= 0x500; /* Infinity */
947 } else {
948 env->fpus |= 0x100; /* NaN */
949 }
950 } else if (expdif == 0) {
951 if (MANTD(temp) == 0) {
952 env->fpus |= 0x4000; /* Zero */
953 } else {
954 env->fpus |= 0x4400; /* Denormal */
955 }
956 } else {
957 env->fpus |= 0x400;
958 }
959}
960
d3eb5eae 961void helper_fstenv(CPUX86State *env, target_ulong ptr, int data32)
f299f437
BS
962{
963 int fpus, fptag, exp, i;
964 uint64_t mant;
965 CPU_LDoubleU tmp;
966
967 fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
968 fptag = 0;
969 for (i = 7; i >= 0; i--) {
970 fptag <<= 2;
971 if (env->fptags[i]) {
972 fptag |= 3;
973 } else {
974 tmp.d = env->fpregs[i].d;
975 exp = EXPD(tmp);
976 mant = MANTD(tmp);
977 if (exp == 0 && mant == 0) {
978 /* zero */
979 fptag |= 1;
980 } else if (exp == 0 || exp == MAXEXPD
981 || (mant & (1LL << 63)) == 0) {
982 /* NaNs, infinity, denormal */
983 fptag |= 2;
984 }
985 }
986 }
987 if (data32) {
988 /* 32 bit */
d3eb5eae
BS
989 cpu_stl_data(env, ptr, env->fpuc);
990 cpu_stl_data(env, ptr + 4, fpus);
991 cpu_stl_data(env, ptr + 8, fptag);
992 cpu_stl_data(env, ptr + 12, 0); /* fpip */
993 cpu_stl_data(env, ptr + 16, 0); /* fpcs */
994 cpu_stl_data(env, ptr + 20, 0); /* fpoo */
995 cpu_stl_data(env, ptr + 24, 0); /* fpos */
f299f437
BS
996 } else {
997 /* 16 bit */
d3eb5eae
BS
998 cpu_stw_data(env, ptr, env->fpuc);
999 cpu_stw_data(env, ptr + 2, fpus);
1000 cpu_stw_data(env, ptr + 4, fptag);
1001 cpu_stw_data(env, ptr + 6, 0);
1002 cpu_stw_data(env, ptr + 8, 0);
1003 cpu_stw_data(env, ptr + 10, 0);
1004 cpu_stw_data(env, ptr + 12, 0);
f299f437
BS
1005 }
1006}
1007
d3eb5eae 1008void helper_fldenv(CPUX86State *env, target_ulong ptr, int data32)
f299f437
BS
1009{
1010 int i, fpus, fptag;
1011
1012 if (data32) {
d3eb5eae
BS
1013 env->fpuc = cpu_lduw_data(env, ptr);
1014 fpus = cpu_lduw_data(env, ptr + 4);
1015 fptag = cpu_lduw_data(env, ptr + 8);
f299f437 1016 } else {
d3eb5eae
BS
1017 env->fpuc = cpu_lduw_data(env, ptr);
1018 fpus = cpu_lduw_data(env, ptr + 2);
1019 fptag = cpu_lduw_data(env, ptr + 4);
f299f437
BS
1020 }
1021 env->fpstt = (fpus >> 11) & 7;
1022 env->fpus = fpus & ~0x3800;
1023 for (i = 0; i < 8; i++) {
1024 env->fptags[i] = ((fptag & 3) == 3);
1025 fptag >>= 2;
1026 }
1027}
1028
d3eb5eae 1029void helper_fsave(CPUX86State *env, target_ulong ptr, int data32)
f299f437
BS
1030{
1031 floatx80 tmp;
1032 int i;
1033
d3eb5eae 1034 helper_fstenv(env, ptr, data32);
f299f437
BS
1035
1036 ptr += (14 << data32);
1037 for (i = 0; i < 8; i++) {
1038 tmp = ST(i);
d3eb5eae 1039 helper_fstt(env, tmp, ptr);
f299f437
BS
1040 ptr += 10;
1041 }
1042
1043 /* fninit */
1044 env->fpus = 0;
1045 env->fpstt = 0;
1046 env->fpuc = 0x37f;
1047 env->fptags[0] = 1;
1048 env->fptags[1] = 1;
1049 env->fptags[2] = 1;
1050 env->fptags[3] = 1;
1051 env->fptags[4] = 1;
1052 env->fptags[5] = 1;
1053 env->fptags[6] = 1;
1054 env->fptags[7] = 1;
1055}
1056
d3eb5eae 1057void helper_frstor(CPUX86State *env, target_ulong ptr, int data32)
f299f437
BS
1058{
1059 floatx80 tmp;
1060 int i;
1061
d3eb5eae 1062 helper_fldenv(env, ptr, data32);
f299f437
BS
1063 ptr += (14 << data32);
1064
1065 for (i = 0; i < 8; i++) {
d3eb5eae 1066 tmp = helper_fldt(env, ptr);
f299f437
BS
1067 ST(i) = tmp;
1068 ptr += 10;
1069 }
1070}
1071
1072#if defined(CONFIG_USER_ONLY)
d3eb5eae 1073void cpu_x86_fsave(CPUX86State *env, target_ulong ptr, int data32)
f299f437 1074{
d3eb5eae 1075 helper_fsave(env, ptr, data32);
f299f437
BS
1076}
1077
d3eb5eae 1078void cpu_x86_frstor(CPUX86State *env, target_ulong ptr, int data32)
f299f437 1079{
d3eb5eae 1080 helper_frstor(env, ptr, data32);
f299f437
BS
1081}
1082#endif
1083
d3eb5eae 1084void helper_fxsave(CPUX86State *env, target_ulong ptr, int data64)
f299f437
BS
1085{
1086 int fpus, fptag, i, nb_xmm_regs;
1087 floatx80 tmp;
1088 target_ulong addr;
1089
1090 /* The operand must be 16 byte aligned */
1091 if (ptr & 0xf) {
1092 raise_exception(env, EXCP0D_GPF);
1093 }
1094
1095 fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
1096 fptag = 0;
1097 for (i = 0; i < 8; i++) {
1098 fptag |= (env->fptags[i] << i);
1099 }
d3eb5eae
BS
1100 cpu_stw_data(env, ptr, env->fpuc);
1101 cpu_stw_data(env, ptr + 2, fpus);
1102 cpu_stw_data(env, ptr + 4, fptag ^ 0xff);
f299f437
BS
1103#ifdef TARGET_X86_64
1104 if (data64) {
d3eb5eae
BS
1105 cpu_stq_data(env, ptr + 0x08, 0); /* rip */
1106 cpu_stq_data(env, ptr + 0x10, 0); /* rdp */
f299f437
BS
1107 } else
1108#endif
1109 {
d3eb5eae
BS
1110 cpu_stl_data(env, ptr + 0x08, 0); /* eip */
1111 cpu_stl_data(env, ptr + 0x0c, 0); /* sel */
1112 cpu_stl_data(env, ptr + 0x10, 0); /* dp */
1113 cpu_stl_data(env, ptr + 0x14, 0); /* sel */
f299f437
BS
1114 }
1115
1116 addr = ptr + 0x20;
1117 for (i = 0; i < 8; i++) {
1118 tmp = ST(i);
d3eb5eae 1119 helper_fstt(env, tmp, addr);
f299f437
BS
1120 addr += 16;
1121 }
1122
1123 if (env->cr[4] & CR4_OSFXSR_MASK) {
1124 /* XXX: finish it */
d3eb5eae
BS
1125 cpu_stl_data(env, ptr + 0x18, env->mxcsr); /* mxcsr */
1126 cpu_stl_data(env, ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */
f299f437
BS
1127 if (env->hflags & HF_CS64_MASK) {
1128 nb_xmm_regs = 16;
1129 } else {
1130 nb_xmm_regs = 8;
1131 }
1132 addr = ptr + 0xa0;
1133 /* Fast FXSAVE leaves out the XMM registers */
1134 if (!(env->efer & MSR_EFER_FFXSR)
1135 || (env->hflags & HF_CPL_MASK)
1136 || !(env->hflags & HF_LMA_MASK)) {
1137 for (i = 0; i < nb_xmm_regs; i++) {
d3eb5eae
BS
1138 cpu_stq_data(env, addr, env->xmm_regs[i].XMM_Q(0));
1139 cpu_stq_data(env, addr + 8, env->xmm_regs[i].XMM_Q(1));
f299f437
BS
1140 addr += 16;
1141 }
1142 }
1143 }
1144}
1145
d3eb5eae 1146void helper_fxrstor(CPUX86State *env, target_ulong ptr, int data64)
f299f437
BS
1147{
1148 int i, fpus, fptag, nb_xmm_regs;
1149 floatx80 tmp;
1150 target_ulong addr;
1151
1152 /* The operand must be 16 byte aligned */
1153 if (ptr & 0xf) {
1154 raise_exception(env, EXCP0D_GPF);
1155 }
1156
d3eb5eae
BS
1157 env->fpuc = cpu_lduw_data(env, ptr);
1158 fpus = cpu_lduw_data(env, ptr + 2);
1159 fptag = cpu_lduw_data(env, ptr + 4);
f299f437
BS
1160 env->fpstt = (fpus >> 11) & 7;
1161 env->fpus = fpus & ~0x3800;
1162 fptag ^= 0xff;
1163 for (i = 0; i < 8; i++) {
1164 env->fptags[i] = ((fptag >> i) & 1);
1165 }
1166
1167 addr = ptr + 0x20;
1168 for (i = 0; i < 8; i++) {
d3eb5eae 1169 tmp = helper_fldt(env, addr);
f299f437
BS
1170 ST(i) = tmp;
1171 addr += 16;
1172 }
1173
1174 if (env->cr[4] & CR4_OSFXSR_MASK) {
1175 /* XXX: finish it */
d3eb5eae
BS
1176 env->mxcsr = cpu_ldl_data(env, ptr + 0x18);
1177 /* cpu_ldl_data(env, ptr + 0x1c); */
f299f437
BS
1178 if (env->hflags & HF_CS64_MASK) {
1179 nb_xmm_regs = 16;
1180 } else {
1181 nb_xmm_regs = 8;
1182 }
1183 addr = ptr + 0xa0;
1184 /* Fast FXRESTORE leaves out the XMM registers */
1185 if (!(env->efer & MSR_EFER_FFXSR)
1186 || (env->hflags & HF_CPL_MASK)
1187 || !(env->hflags & HF_LMA_MASK)) {
1188 for (i = 0; i < nb_xmm_regs; i++) {
d3eb5eae
BS
1189 env->xmm_regs[i].XMM_Q(0) = cpu_ldq_data(env, addr);
1190 env->xmm_regs[i].XMM_Q(1) = cpu_ldq_data(env, addr + 8);
f299f437
BS
1191 addr += 16;
1192 }
1193 }
1194 }
1195}
1196
1197void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f)
1198{
1199 CPU_LDoubleU temp;
1200
1201 temp.d = f;
1202 *pmant = temp.l.lower;
1203 *pexp = temp.l.upper;
1204}
1205
1206floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper)
1207{
1208 CPU_LDoubleU temp;
1209
1210 temp.l.upper = upper;
1211 temp.l.lower = mant;
1212 return temp.d;
1213}
1214
1215/* MMX/SSE */
1216/* XXX: optimize by storing fptt and fptags in the static cpu state */
1217
1218#define SSE_DAZ 0x0040
1219#define SSE_RC_MASK 0x6000
1220#define SSE_RC_NEAR 0x0000
1221#define SSE_RC_DOWN 0x2000
1222#define SSE_RC_UP 0x4000
1223#define SSE_RC_CHOP 0x6000
1224#define SSE_FZ 0x8000
1225
d3eb5eae 1226static void update_sse_status(CPUX86State *env)
f299f437
BS
1227{
1228 int rnd_type;
1229
1230 /* set rounding mode */
1231 switch (env->mxcsr & SSE_RC_MASK) {
1232 default:
1233 case SSE_RC_NEAR:
1234 rnd_type = float_round_nearest_even;
1235 break;
1236 case SSE_RC_DOWN:
1237 rnd_type = float_round_down;
1238 break;
1239 case SSE_RC_UP:
1240 rnd_type = float_round_up;
1241 break;
1242 case SSE_RC_CHOP:
1243 rnd_type = float_round_to_zero;
1244 break;
1245 }
1246 set_float_rounding_mode(rnd_type, &env->sse_status);
1247
1248 /* set denormals are zero */
1249 set_flush_inputs_to_zero((env->mxcsr & SSE_DAZ) ? 1 : 0, &env->sse_status);
1250
1251 /* set flush to zero */
1252 set_flush_to_zero((env->mxcsr & SSE_FZ) ? 1 : 0, &env->fp_status);
1253}
1254
d3eb5eae 1255void helper_ldmxcsr(CPUX86State *env, uint32_t val)
f299f437
BS
1256{
1257 env->mxcsr = val;
d3eb5eae 1258 update_sse_status(env);
f299f437
BS
1259}
1260
d3eb5eae 1261void helper_enter_mmx(CPUX86State *env)
f299f437
BS
1262{
1263 env->fpstt = 0;
1264 *(uint32_t *)(env->fptags) = 0;
1265 *(uint32_t *)(env->fptags + 4) = 0;
1266}
1267
d3eb5eae 1268void helper_emms(CPUX86State *env)
f299f437
BS
1269{
1270 /* set to empty state */
1271 *(uint32_t *)(env->fptags) = 0x01010101;
1272 *(uint32_t *)(env->fptags + 4) = 0x01010101;
1273}
1274
1275/* XXX: suppress */
d3eb5eae 1276void helper_movq(CPUX86State *env, void *d, void *s)
f299f437
BS
1277{
1278 *(uint64_t *)d = *(uint64_t *)s;
1279}
1280
1281#define SHIFT 0
1282#include "ops_sse.h"
1283
1284#define SHIFT 1
1285#include "ops_sse.h"
This page took 0.208866 seconds and 4 git commands to generate.