]>
git.proxmox.com Git - qemu.git/blob - op-i386.c
2 * i386 micro operations
4 * Copyright (c) 2003 Fabrice Bellard
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "exec-i386.h"
22 /* NOTE: data are not static to force relocation generation by GCC */
24 uint8_t parity_table
[256] = {
25 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
26 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
27 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
28 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
29 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
30 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
31 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
32 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
33 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
34 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
35 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
36 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
37 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
38 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
39 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
40 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
41 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
42 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
43 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
44 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
45 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
46 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
47 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
48 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
49 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
50 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
51 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
52 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
53 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
54 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
55 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
56 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
60 const uint8_t rclw_table
[32] = {
61 0, 1, 2, 3, 4, 5, 6, 7,
62 8, 9,10,11,12,13,14,15,
63 16, 0, 1, 2, 3, 4, 5, 6,
64 7, 8, 9,10,11,12,13,14,
68 const uint8_t rclb_table
[32] = {
69 0, 1, 2, 3, 4, 5, 6, 7,
70 8, 0, 1, 2, 3, 4, 5, 6,
71 7, 8, 0, 1, 2, 3, 4, 5,
72 6, 7, 8, 0, 1, 2, 3, 4,
76 /* an array of Intel 80-bit FP constants, to be loaded via integer ops */
77 typedef unsigned short f15ld
[5];
80 /*0*/ {0x0000,0x0000,0x0000,0x0000,0x0000},
81 /*1*/ {0x0000,0x0000,0x0000,0x8000,0x3fff},
82 /*pi*/ {0xc235,0x2168,0xdaa2,0xc90f,0x4000},
83 /*lg2*/ {0xf799,0xfbcf,0x9a84,0x9a20,0x3ffd},
84 /*ln2*/ {0x79ac,0xd1cf,0x17f7,0xb172,0x3ffe},
85 /*l2e*/ {0xf0bc,0x5c17,0x3b29,0xb8aa,0x3fff},
86 /*l2t*/ {0x8afe,0xcd1b,0x784b,0xd49a,0x4000}
89 /* the same, 64-bit version */
90 typedef unsigned short f15ld
[4];
93 #ifndef WORDS_BIGENDIAN
94 /*0*/ {0x0000,0x0000,0x0000,0x0000},
95 /*1*/ {0x0000,0x0000,0x0000,0x3ff0},
96 /*pi*/ {0x2d18,0x5444,0x21fb,0x4009},
97 /*lg2*/ {0x79ff,0x509f,0x4413,0x3fd3},
98 /*ln2*/ {0x39ef,0xfefa,0x2e42,0x3fe6},
99 /*l2e*/ {0x82fe,0x652b,0x1547,0x3ff7},
100 /*l2t*/ {0xa371,0x0979,0x934f,0x400a}
102 /*0*/ {0x0000,0x0000,0x0000,0x0000},
103 /*1*/ {0x3ff0,0x0000,0x0000,0x0000},
104 /*pi*/ {0x4009,0x21fb,0x5444,0x2d18},
105 /*lg2*/ {0x3fd3,0x4413,0x509f,0x79ff},
106 /*ln2*/ {0x3fe6,0x2e42,0xfefa,0x39ef},
107 /*l2e*/ {0x3ff7,0x1547,0x652b,0x82fe},
108 /*l2t*/ {0x400a,0x934f,0x0979,0xa371}
113 /* n must be a constant to be efficient */
114 static inline int lshift(int x
, int n
)
122 /* exception support */
123 /* NOTE: not static to force relocation generation by GCC */
124 void raise_exception(int exception_index
)
126 /* NOTE: the register at this point must be saved by hand because
127 longjmp restore them */
129 env
->regs
[R_EAX
] = EAX
;
132 env
->regs
[R_ECX
] = ECX
;
135 env
->regs
[R_EDX
] = EDX
;
138 env
->regs
[R_EBX
] = EBX
;
141 env
->regs
[R_ESP
] = ESP
;
144 env
->regs
[R_EBP
] = EBP
;
147 env
->regs
[R_ESI
] = ESI
;
150 env
->regs
[R_EDI
] = EDI
;
152 env
->exception_index
= exception_index
;
153 longjmp(env
->jmp_env
, 1);
156 /* we define the various pieces of code used by the JIT */
160 #include "opreg_template.h"
166 #include "opreg_template.h"
172 #include "opreg_template.h"
178 #include "opreg_template.h"
184 #include "opreg_template.h"
190 #include "opreg_template.h"
196 #include "opreg_template.h"
202 #include "opreg_template.h"
206 /* operations with flags */
208 void OPPROTO
op_addl_T0_T1_cc(void)
215 void OPPROTO
op_orl_T0_T1_cc(void)
221 void OPPROTO
op_andl_T0_T1_cc(void)
227 void OPPROTO
op_subl_T0_T1_cc(void)
234 void OPPROTO
op_xorl_T0_T1_cc(void)
240 void OPPROTO
op_cmpl_T0_T1_cc(void)
246 void OPPROTO
op_negl_T0_cc(void)
253 void OPPROTO
op_incl_T0_cc(void)
255 CC_SRC
= cc_table
[CC_OP
].compute_c();
260 void OPPROTO
op_decl_T0_cc(void)
262 CC_SRC
= cc_table
[CC_OP
].compute_c();
267 void OPPROTO
op_testl_T0_T1_cc(void)
272 /* operations without flags */
274 void OPPROTO
op_addl_T0_T1(void)
279 void OPPROTO
op_orl_T0_T1(void)
284 void OPPROTO
op_andl_T0_T1(void)
289 void OPPROTO
op_subl_T0_T1(void)
294 void OPPROTO
op_xorl_T0_T1(void)
299 void OPPROTO
op_negl_T0(void)
304 void OPPROTO
op_incl_T0(void)
309 void OPPROTO
op_decl_T0(void)
314 void OPPROTO
op_notl_T0(void)
319 void OPPROTO
op_bswapl_T0(void)
324 /* multiply/divide */
325 void OPPROTO
op_mulb_AL_T0(void)
328 res
= (uint8_t)EAX
* (uint8_t)T0
;
329 EAX
= (EAX
& 0xffff0000) | res
;
330 CC_SRC
= (res
& 0xff00);
333 void OPPROTO
op_imulb_AL_T0(void)
336 res
= (int8_t)EAX
* (int8_t)T0
;
337 EAX
= (EAX
& 0xffff0000) | (res
& 0xffff);
338 CC_SRC
= (res
!= (int8_t)res
);
341 void OPPROTO
op_mulw_AX_T0(void)
344 res
= (uint16_t)EAX
* (uint16_t)T0
;
345 EAX
= (EAX
& 0xffff0000) | (res
& 0xffff);
346 EDX
= (EDX
& 0xffff0000) | ((res
>> 16) & 0xffff);
350 void OPPROTO
op_imulw_AX_T0(void)
353 res
= (int16_t)EAX
* (int16_t)T0
;
354 EAX
= (EAX
& 0xffff0000) | (res
& 0xffff);
355 EDX
= (EDX
& 0xffff0000) | ((res
>> 16) & 0xffff);
356 CC_SRC
= (res
!= (int16_t)res
);
359 void OPPROTO
op_mull_EAX_T0(void)
362 res
= (uint64_t)((uint32_t)EAX
) * (uint64_t)((uint32_t)T0
);
368 void OPPROTO
op_imull_EAX_T0(void)
371 res
= (int64_t)((int32_t)EAX
) * (int64_t)((int32_t)T0
);
374 CC_SRC
= (res
!= (int32_t)res
);
377 void OPPROTO
op_imulw_T0_T1(void)
380 res
= (int16_t)T0
* (int16_t)T1
;
382 CC_SRC
= (res
!= (int16_t)res
);
385 void OPPROTO
op_imull_T0_T1(void)
388 res
= (int64_t)((int32_t)T0
) * (int64_t)((int32_t)T1
);
390 CC_SRC
= (res
!= (int32_t)res
);
393 /* division, flags are undefined */
394 /* XXX: add exceptions for overflow & div by zero */
395 void OPPROTO
op_divb_AL_T0(void)
397 unsigned int num
, den
, q
, r
;
399 num
= (EAX
& 0xffff);
401 q
= (num
/ den
) & 0xff;
402 r
= (num
% den
) & 0xff;
403 EAX
= (EAX
& 0xffff0000) | (r
<< 8) | q
;
406 void OPPROTO
op_idivb_AL_T0(void)
412 q
= (num
/ den
) & 0xff;
413 r
= (num
% den
) & 0xff;
414 EAX
= (EAX
& 0xffff0000) | (r
<< 8) | q
;
417 void OPPROTO
op_divw_AX_T0(void)
419 unsigned int num
, den
, q
, r
;
421 num
= (EAX
& 0xffff) | ((EDX
& 0xffff) << 16);
423 q
= (num
/ den
) & 0xffff;
424 r
= (num
% den
) & 0xffff;
425 EAX
= (EAX
& 0xffff0000) | q
;
426 EDX
= (EDX
& 0xffff0000) | r
;
429 void OPPROTO
op_idivw_AX_T0(void)
433 num
= (EAX
& 0xffff) | ((EDX
& 0xffff) << 16);
435 q
= (num
/ den
) & 0xffff;
436 r
= (num
% den
) & 0xffff;
437 EAX
= (EAX
& 0xffff0000) | q
;
438 EDX
= (EDX
& 0xffff0000) | r
;
441 void OPPROTO
op_divl_EAX_T0(void)
443 unsigned int den
, q
, r
;
446 num
= EAX
| ((uint64_t)EDX
<< 32);
454 void OPPROTO
op_idivl_EAX_T0(void)
459 num
= EAX
| ((uint64_t)EDX
<< 32);
469 void OPPROTO
op_movl_T0_im(void)
474 void OPPROTO
op_movl_T1_im(void)
479 void OPPROTO
op_movl_A0_im(void)
484 void OPPROTO
op_addl_A0_im(void)
489 void OPPROTO
op_andl_A0_ffff(void)
496 void OPPROTO
op_ldub_T0_A0(void)
498 T0
= ldub((uint8_t *)A0
);
501 void OPPROTO
op_ldsb_T0_A0(void)
503 T0
= ldsb((int8_t *)A0
);
506 void OPPROTO
op_lduw_T0_A0(void)
508 T0
= lduw((uint8_t *)A0
);
511 void OPPROTO
op_ldsw_T0_A0(void)
513 T0
= ldsw((int8_t *)A0
);
516 void OPPROTO
op_ldl_T0_A0(void)
518 T0
= ldl((uint8_t *)A0
);
521 void OPPROTO
op_ldub_T1_A0(void)
523 T1
= ldub((uint8_t *)A0
);
526 void OPPROTO
op_ldsb_T1_A0(void)
528 T1
= ldsb((int8_t *)A0
);
531 void OPPROTO
op_lduw_T1_A0(void)
533 T1
= lduw((uint8_t *)A0
);
536 void OPPROTO
op_ldsw_T1_A0(void)
538 T1
= ldsw((int8_t *)A0
);
541 void OPPROTO
op_ldl_T1_A0(void)
543 T1
= ldl((uint8_t *)A0
);
546 void OPPROTO
op_stb_T0_A0(void)
548 stb((uint8_t *)A0
, T0
);
551 void OPPROTO
op_stw_T0_A0(void)
553 stw((uint8_t *)A0
, T0
);
556 void OPPROTO
op_stl_T0_A0(void)
558 stl((uint8_t *)A0
, T0
);
561 /* used for bit operations */
563 void OPPROTO
op_add_bitw_A0_T1(void)
565 A0
+= ((int32_t)T1
>> 4) << 1;
568 void OPPROTO
op_add_bitl_A0_T1(void)
570 A0
+= ((int32_t)T1
>> 5) << 2;
575 void OPPROTO
op_jmp_T0(void)
580 void OPPROTO
op_jmp_im(void)
585 void OPPROTO
op_int_im(void)
588 raise_exception(EXCP0D_GPF
);
591 void OPPROTO
op_int3(void)
594 raise_exception(EXCP03_INT3
);
597 void OPPROTO
op_into(void)
600 eflags
= cc_table
[CC_OP
].compute_all();
603 raise_exception(EXCP04_INTO
);
614 #include "ops_template.h"
618 #include "ops_template.h"
622 #include "ops_template.h"
627 void OPPROTO
op_movsbl_T0_T0(void)
632 void OPPROTO
op_movzbl_T0_T0(void)
637 void OPPROTO
op_movswl_T0_T0(void)
642 void OPPROTO
op_movzwl_T0_T0(void)
647 void OPPROTO
op_movswl_EAX_AX(void)
652 void OPPROTO
op_movsbw_AX_AL(void)
654 EAX
= (EAX
& 0xffff0000) | ((int8_t)EAX
& 0xffff);
657 void OPPROTO
op_movslq_EDX_EAX(void)
659 EDX
= (int32_t)EAX
>> 31;
662 void OPPROTO
op_movswl_DX_AX(void)
664 EDX
= (EDX
& 0xffff0000) | (((int16_t)EAX
>> 15) & 0xffff);
668 /* XXX: add 16 bit operand/16 bit seg variants */
670 void op_pushl_T0(void)
674 stl((void *)offset
, T0
);
675 /* modify ESP after to handle exceptions correctly */
679 void op_pushl_T1(void)
683 stl((void *)offset
, T1
);
684 /* modify ESP after to handle exceptions correctly */
688 void op_popl_T0(void)
690 T0
= ldl((void *)ESP
);
694 void op_addl_ESP_im(void)
702 sp
= (void *)(ESP
- 32);
711 ESP
= (unsigned long)sp
;
717 sp
= (void *)(ESP
- 16);
726 ESP
= (unsigned long)sp
;
740 ESP
= (unsigned long)sp
+ 32;
754 ESP
= (unsigned long)sp
+ 16;
759 unsigned int bp
, frame_temp
, level
;
766 frame_temp
= (unsigned int)sp
;
790 asm("rdtsc" : "=A" (val
));
792 /* better than nothing: the time increases */
802 void OPPROTO
op_aam(void)
809 EAX
= (EAX
& ~0xffff) | al
| (ah
<< 8);
813 void OPPROTO
op_aad(void)
818 ah
= (EAX
>> 8) & 0xff;
819 al
= ((ah
* base
) + al
) & 0xff;
820 EAX
= (EAX
& ~0xffff) | al
;
824 void OPPROTO
op_aaa(void)
830 eflags
= cc_table
[CC_OP
].compute_all();
833 ah
= (EAX
>> 8) & 0xff;
835 icarry
= (al
> 0xf9);
836 if (((al
& 0x0f) > 9 ) || af
) {
837 al
= (al
+ 6) & 0x0f;
838 ah
= (ah
+ 1 + icarry
) & 0xff;
839 eflags
|= CC_C
| CC_A
;
841 eflags
&= ~(CC_C
| CC_A
);
844 EAX
= (EAX
& ~0xffff) | al
| (ah
<< 8);
848 void OPPROTO
op_aas(void)
854 eflags
= cc_table
[CC_OP
].compute_all();
857 ah
= (EAX
>> 8) & 0xff;
860 if (((al
& 0x0f) > 9 ) || af
) {
861 al
= (al
- 6) & 0x0f;
862 ah
= (ah
- 1 - icarry
) & 0xff;
863 eflags
|= CC_C
| CC_A
;
865 eflags
&= ~(CC_C
| CC_A
);
868 EAX
= (EAX
& ~0xffff) | al
| (ah
<< 8);
872 void OPPROTO
op_daa(void)
877 eflags
= cc_table
[CC_OP
].compute_all();
883 if (((al
& 0x0f) > 9 ) || af
) {
884 al
= (al
+ 6) & 0xff;
887 if ((al
> 0x9f) || cf
) {
888 al
= (al
+ 0x60) & 0xff;
891 EAX
= (EAX
& ~0xff) | al
;
892 /* well, speed is not an issue here, so we compute the flags by hand */
893 eflags
|= (al
== 0) << 6; /* zf */
894 eflags
|= parity_table
[al
]; /* pf */
895 eflags
|= (al
& 0x80); /* sf */
899 void OPPROTO
op_das(void)
904 eflags
= cc_table
[CC_OP
].compute_all();
911 if (((al
& 0x0f) > 9 ) || af
) {
915 al
= (al
- 6) & 0xff;
917 if ((al1
> 0x99) || cf
) {
918 al
= (al
- 0x60) & 0xff;
921 EAX
= (EAX
& ~0xff) | al
;
922 /* well, speed is not an issue here, so we compute the flags by hand */
923 eflags
|= (al
== 0) << 6; /* zf */
924 eflags
|= parity_table
[al
]; /* pf */
925 eflags
|= (al
& 0x80); /* sf */
929 /* segment handling */
931 void load_seg(int seg_reg
, int selector
)
934 SegmentDescriptorTable
*dt
;
939 env
->segs
[seg_reg
] = selector
;
940 sc
= &env
->seg_cache
[seg_reg
];
942 sc
->base
= (void *)(selector
<< 4);
950 index
= selector
& ~7;
951 if ((index
+ 7) > dt
->limit
)
952 raise_exception(EXCP0D_GPF
);
953 ptr
= dt
->base
+ index
;
956 sc
->base
= (void *)((e1
>> 16) | ((e2
& 0xff) << 16) | (e2
& 0xff000000));
957 sc
->limit
= (e1
& 0xffff) | (e2
& 0x000f0000);
959 sc
->limit
= (sc
->limit
<< 12) | 0xfff;
960 sc
->seg_32bit
= (e2
>> 22) & 1;
962 fprintf(logfile
, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n",
963 selector
, (unsigned long)sc
->base
, sc
->limit
, sc
->seg_32bit
);
968 void OPPROTO
op_movl_seg_T0(void)
970 load_seg(PARAM1
, T0
& 0xffff);
973 void OPPROTO
op_movl_T0_seg(void)
975 T0
= env
->segs
[PARAM1
];
978 void OPPROTO
op_addl_A0_seg(void)
980 A0
+= *(unsigned long *)((char *)env
+ PARAM1
);
985 /* slow jumps cases (compute x86 flags) */
986 void OPPROTO
op_jo_cc(void)
989 eflags
= cc_table
[CC_OP
].compute_all();
997 void OPPROTO
op_jb_cc(void)
999 if (cc_table
[CC_OP
].compute_c())
1006 void OPPROTO
op_jz_cc(void)
1009 eflags
= cc_table
[CC_OP
].compute_all();
1017 void OPPROTO
op_jbe_cc(void)
1020 eflags
= cc_table
[CC_OP
].compute_all();
1021 if (eflags
& (CC_Z
| CC_C
))
1028 void OPPROTO
op_js_cc(void)
1031 eflags
= cc_table
[CC_OP
].compute_all();
1039 void OPPROTO
op_jp_cc(void)
1042 eflags
= cc_table
[CC_OP
].compute_all();
1050 void OPPROTO
op_jl_cc(void)
1053 eflags
= cc_table
[CC_OP
].compute_all();
1054 if ((eflags
^ (eflags
>> 4)) & 0x80)
1061 void OPPROTO
op_jle_cc(void)
1064 eflags
= cc_table
[CC_OP
].compute_all();
1065 if (((eflags
^ (eflags
>> 4)) & 0x80) || (eflags
& CC_Z
))
1072 /* slow set cases (compute x86 flags) */
1073 void OPPROTO
op_seto_T0_cc(void)
1076 eflags
= cc_table
[CC_OP
].compute_all();
1077 T0
= (eflags
>> 11) & 1;
1080 void OPPROTO
op_setb_T0_cc(void)
1082 T0
= cc_table
[CC_OP
].compute_c();
1085 void OPPROTO
op_setz_T0_cc(void)
1088 eflags
= cc_table
[CC_OP
].compute_all();
1089 T0
= (eflags
>> 6) & 1;
1092 void OPPROTO
op_setbe_T0_cc(void)
1095 eflags
= cc_table
[CC_OP
].compute_all();
1096 T0
= (eflags
& (CC_Z
| CC_C
)) != 0;
1099 void OPPROTO
op_sets_T0_cc(void)
1102 eflags
= cc_table
[CC_OP
].compute_all();
1103 T0
= (eflags
>> 7) & 1;
1106 void OPPROTO
op_setp_T0_cc(void)
1109 eflags
= cc_table
[CC_OP
].compute_all();
1110 T0
= (eflags
>> 2) & 1;
1113 void OPPROTO
op_setl_T0_cc(void)
1116 eflags
= cc_table
[CC_OP
].compute_all();
1117 T0
= ((eflags
^ (eflags
>> 4)) >> 7) & 1;
1120 void OPPROTO
op_setle_T0_cc(void)
1123 eflags
= cc_table
[CC_OP
].compute_all();
1124 T0
= (((eflags
^ (eflags
>> 4)) & 0x80) || (eflags
& CC_Z
)) != 0;
1127 void OPPROTO
op_xor_T0_1(void)
1132 void OPPROTO
op_set_cc_op(void)
1137 void OPPROTO
op_movl_eflags_T0(void)
1140 DF
= 1 - (2 * ((T0
>> 10) & 1));
1143 /* XXX: compute only O flag */
1144 void OPPROTO
op_movb_eflags_T0(void)
1147 of
= cc_table
[CC_OP
].compute_all() & CC_O
;
1151 void OPPROTO
op_movl_T0_eflags(void)
1153 T0
= cc_table
[CC_OP
].compute_all();
1154 T0
|= (DF
& DIRECTION_FLAG
);
1157 void OPPROTO
op_cld(void)
1162 void OPPROTO
op_std(void)
1167 void OPPROTO
op_clc(void)
1170 eflags
= cc_table
[CC_OP
].compute_all();
1175 void OPPROTO
op_stc(void)
1178 eflags
= cc_table
[CC_OP
].compute_all();
1183 void OPPROTO
op_cmc(void)
1186 eflags
= cc_table
[CC_OP
].compute_all();
1191 void OPPROTO
op_salc(void)
1194 cf
= cc_table
[CC_OP
].compute_c();
1195 EAX
= (EAX
& ~0xff) | ((-cf
) & 0xff);
1198 static int compute_all_eflags(void)
1203 static int compute_c_eflags(void)
1205 return CC_SRC
& CC_C
;
1208 static int compute_c_mul(void)
1215 static int compute_all_mul(void)
1217 int cf
, pf
, af
, zf
, sf
, of
;
1219 pf
= 0; /* undefined */
1220 af
= 0; /* undefined */
1221 zf
= 0; /* undefined */
1222 sf
= 0; /* undefined */
1224 return cf
| pf
| af
| zf
| sf
| of
;
1227 CCTable cc_table
[CC_OP_NB
] = {
1228 [CC_OP_DYNAMIC
] = { /* should never happen */ },
1230 [CC_OP_EFLAGS
] = { compute_all_eflags
, compute_c_eflags
},
1232 [CC_OP_MUL
] = { compute_all_mul
, compute_c_mul
},
1234 [CC_OP_ADDB
] = { compute_all_addb
, compute_c_addb
},
1235 [CC_OP_ADDW
] = { compute_all_addw
, compute_c_addw
},
1236 [CC_OP_ADDL
] = { compute_all_addl
, compute_c_addl
},
1238 [CC_OP_ADCB
] = { compute_all_adcb
, compute_c_adcb
},
1239 [CC_OP_ADCW
] = { compute_all_adcw
, compute_c_adcw
},
1240 [CC_OP_ADCL
] = { compute_all_adcl
, compute_c_adcl
},
1242 [CC_OP_SUBB
] = { compute_all_subb
, compute_c_subb
},
1243 [CC_OP_SUBW
] = { compute_all_subw
, compute_c_subw
},
1244 [CC_OP_SUBL
] = { compute_all_subl
, compute_c_subl
},
1246 [CC_OP_SBBB
] = { compute_all_sbbb
, compute_c_sbbb
},
1247 [CC_OP_SBBW
] = { compute_all_sbbw
, compute_c_sbbw
},
1248 [CC_OP_SBBL
] = { compute_all_sbbl
, compute_c_sbbl
},
1250 [CC_OP_LOGICB
] = { compute_all_logicb
, compute_c_logicb
},
1251 [CC_OP_LOGICW
] = { compute_all_logicw
, compute_c_logicw
},
1252 [CC_OP_LOGICL
] = { compute_all_logicl
, compute_c_logicl
},
1254 [CC_OP_INCB
] = { compute_all_incb
, compute_c_incl
},
1255 [CC_OP_INCW
] = { compute_all_incw
, compute_c_incl
},
1256 [CC_OP_INCL
] = { compute_all_incl
, compute_c_incl
},
1258 [CC_OP_DECB
] = { compute_all_decb
, compute_c_incl
},
1259 [CC_OP_DECW
] = { compute_all_decw
, compute_c_incl
},
1260 [CC_OP_DECL
] = { compute_all_decl
, compute_c_incl
},
1262 [CC_OP_SHLB
] = { compute_all_shlb
, compute_c_shll
},
1263 [CC_OP_SHLW
] = { compute_all_shlw
, compute_c_shll
},
1264 [CC_OP_SHLL
] = { compute_all_shll
, compute_c_shll
},
1266 [CC_OP_SARB
] = { compute_all_sarb
, compute_c_shll
},
1267 [CC_OP_SARW
] = { compute_all_sarw
, compute_c_shll
},
1268 [CC_OP_SARL
] = { compute_all_sarl
, compute_c_shll
},
1271 /* floating point support */
1273 #ifdef USE_X86LDOUBLE
1274 /* use long double functions */
1275 #define lrint lrintl
1276 #define llrint llrintl
1284 #define atan2 atan2l
1285 #define floor floorl
1290 extern int lrint(CPU86_LDouble x
);
1291 extern int64_t llrint(CPU86_LDouble x
);
1292 extern CPU86_LDouble
fabs(CPU86_LDouble x
);
1293 extern CPU86_LDouble
sin(CPU86_LDouble x
);
1294 extern CPU86_LDouble
cos(CPU86_LDouble x
);
1295 extern CPU86_LDouble
sqrt(CPU86_LDouble x
);
1296 extern CPU86_LDouble
pow(CPU86_LDouble
, CPU86_LDouble
);
1297 extern CPU86_LDouble
log(CPU86_LDouble x
);
1298 extern CPU86_LDouble
tan(CPU86_LDouble x
);
1299 extern CPU86_LDouble
atan2(CPU86_LDouble
, CPU86_LDouble
);
1300 extern CPU86_LDouble
floor(CPU86_LDouble x
);
1301 extern CPU86_LDouble
ceil(CPU86_LDouble x
);
1302 extern CPU86_LDouble
rint(CPU86_LDouble x
);
1304 #define RC_MASK 0xc00
1305 #define RC_NEAR 0x000
1306 #define RC_DOWN 0x400
1308 #define RC_CHOP 0xc00
1310 #define MAXTAN 9223372036854775808.0
1312 #ifdef USE_X86LDOUBLE
1318 unsigned long long lower
;
1319 unsigned short upper
;
1323 /* the following deal with x86 long double-precision numbers */
1324 #define MAXEXPD 0x7fff
1325 #define EXPBIAS 16383
1326 #define EXPD(fp) (fp.l.upper & 0x7fff)
1327 #define SIGND(fp) ((fp.l.upper) & 0x8000)
1328 #define MANTD(fp) (fp.l.lower)
1329 #define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
1335 #ifndef WORDS_BIGENDIAN
1337 unsigned long lower
;
1343 unsigned long lower
;
1349 /* the following deal with IEEE double-precision numbers */
1350 #define MAXEXPD 0x7ff
1351 #define EXPBIAS 1023
1352 #define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF)
1353 #define SIGND(fp) ((fp.l.upper) & 0x80000000)
1354 #define MANTD(fp) (fp.ll & ((1LL << 52) - 1))
1355 #define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20)
1360 void OPPROTO
op_flds_FT0_A0(void)
1362 FT0
= ldfl((void *)A0
);
1365 void OPPROTO
op_fldl_FT0_A0(void)
1367 FT0
= ldfq((void *)A0
);
1370 /* helpers are needed to avoid static constant reference. XXX: find a better way */
1371 #ifdef USE_INT_TO_FLOAT_HELPERS
1373 void helper_fild_FT0_A0(void)
1375 FT0
= (CPU86_LDouble
)ldsw((void *)A0
);
1378 void helper_fildl_FT0_A0(void)
1380 FT0
= (CPU86_LDouble
)((int32_t)ldl((void *)A0
));
1383 void helper_fildll_FT0_A0(void)
1385 FT0
= (CPU86_LDouble
)((int64_t)ldq((void *)A0
));
1388 void OPPROTO
op_fild_FT0_A0(void)
1390 helper_fild_FT0_A0();
1393 void OPPROTO
op_fildl_FT0_A0(void)
1395 helper_fildl_FT0_A0();
1398 void OPPROTO
op_fildll_FT0_A0(void)
1400 helper_fildll_FT0_A0();
1405 void OPPROTO
op_fild_FT0_A0(void)
1407 FT0
= (CPU86_LDouble
)ldsw((void *)A0
);
1410 void OPPROTO
op_fildl_FT0_A0(void)
1412 FT0
= (CPU86_LDouble
)((int32_t)ldl((void *)A0
));
1415 void OPPROTO
op_fildll_FT0_A0(void)
1417 FT0
= (CPU86_LDouble
)((int64_t)ldq((void *)A0
));
1423 void OPPROTO
op_flds_ST0_A0(void)
1425 ST0
= ldfl((void *)A0
);
1428 void OPPROTO
op_fldl_ST0_A0(void)
1430 ST0
= ldfq((void *)A0
);
1433 #ifdef USE_X86LDOUBLE
1434 void OPPROTO
op_fldt_ST0_A0(void)
1436 ST0
= *(long double *)A0
;
1439 void helper_fldt_ST0_A0(void)
1441 CPU86_LDoubleU temp
;
1444 upper
= lduw((uint8_t *)A0
+ 8);
1445 /* XXX: handle overflow ? */
1446 e
= (upper
& 0x7fff) - 16383 + EXPBIAS
; /* exponent */
1447 e
|= (upper
>> 4) & 0x800; /* sign */
1448 temp
.ll
= ((ldq((void *)A0
) >> 11) & ((1LL << 52) - 1)) | ((uint64_t)e
<< 52);
1452 void OPPROTO
op_fldt_ST0_A0(void)
1454 helper_fldt_ST0_A0();
1458 /* helpers are needed to avoid static constant reference. XXX: find a better way */
1459 #ifdef USE_INT_TO_FLOAT_HELPERS
1461 void helper_fild_ST0_A0(void)
1463 ST0
= (CPU86_LDouble
)ldsw((void *)A0
);
1466 void helper_fildl_ST0_A0(void)
1468 ST0
= (CPU86_LDouble
)((int32_t)ldl((void *)A0
));
1471 void helper_fildll_ST0_A0(void)
1473 ST0
= (CPU86_LDouble
)((int64_t)ldq((void *)A0
));
1476 void OPPROTO
op_fild_ST0_A0(void)
1478 helper_fild_ST0_A0();
1481 void OPPROTO
op_fildl_ST0_A0(void)
1483 helper_fildl_ST0_A0();
1486 void OPPROTO
op_fildll_ST0_A0(void)
1488 helper_fildll_ST0_A0();
1493 void OPPROTO
op_fild_ST0_A0(void)
1495 ST0
= (CPU86_LDouble
)ldsw((void *)A0
);
1498 void OPPROTO
op_fildl_ST0_A0(void)
1500 ST0
= (CPU86_LDouble
)((int32_t)ldl((void *)A0
));
1503 void OPPROTO
op_fildll_ST0_A0(void)
1505 ST0
= (CPU86_LDouble
)((int64_t)ldq((void *)A0
));
1512 void OPPROTO
op_fsts_ST0_A0(void)
1514 stfl((void *)A0
, (float)ST0
);
1517 void OPPROTO
op_fstl_ST0_A0(void)
1519 stfq((void *)A0
, (double)ST0
);
1522 #ifdef USE_X86LDOUBLE
1523 void OPPROTO
op_fstt_ST0_A0(void)
1525 *(long double *)A0
= ST0
;
1528 void helper_fstt_ST0_A0(void)
1530 CPU86_LDoubleU temp
;
1534 stq((void *)A0
, (MANTD(temp
) << 11) | (1LL << 63));
1535 /* exponent + sign */
1536 e
= EXPD(temp
) - EXPBIAS
+ 16383;
1537 e
|= SIGND(temp
) >> 16;
1538 stw((uint8_t *)A0
+ 8, e
);
1541 void OPPROTO
op_fstt_ST0_A0(void)
1543 helper_fstt_ST0_A0();
1547 void OPPROTO
op_fist_ST0_A0(void)
1551 stw((void *)A0
, val
);
1554 void OPPROTO
op_fistl_ST0_A0(void)
1558 stl((void *)A0
, val
);
1561 void OPPROTO
op_fistll_ST0_A0(void)
1565 stq((void *)A0
, val
);
1570 #define MUL10(iv) ( iv + iv + (iv << 3) )
1572 void helper_fbld_ST0_A0(void)
1575 CPU86_LDouble fpsrcop
;
1579 /* in this code, seg/m32i will be used as temporary ptr/int */
1580 seg
= (uint8_t *)A0
+ 8;
1582 /* XXX: raise exception */
1586 /* XXX: raise exception */
1587 if ((v
& 0xf0) != 0)
1589 m32i
= v
; /* <-- d14 */
1591 m32i
= MUL10(m32i
) + (v
>> 4); /* <-- val * 10 + d13 */
1592 m32i
= MUL10(m32i
) + (v
& 0xf); /* <-- val * 10 + d12 */
1594 m32i
= MUL10(m32i
) + (v
>> 4); /* <-- val * 10 + d11 */
1595 m32i
= MUL10(m32i
) + (v
& 0xf); /* <-- val * 10 + d10 */
1597 m32i
= MUL10(m32i
) + (v
>> 4); /* <-- val * 10 + d9 */
1598 m32i
= MUL10(m32i
) + (v
& 0xf); /* <-- val * 10 + d8 */
1599 fpsrcop
= ((CPU86_LDouble
)m32i
) * 100000000.0;
1602 m32i
= (v
>> 4); /* <-- d7 */
1603 m32i
= MUL10(m32i
) + (v
& 0xf); /* <-- val * 10 + d6 */
1605 m32i
= MUL10(m32i
) + (v
>> 4); /* <-- val * 10 + d5 */
1606 m32i
= MUL10(m32i
) + (v
& 0xf); /* <-- val * 10 + d4 */
1608 m32i
= MUL10(m32i
) + (v
>> 4); /* <-- val * 10 + d3 */
1609 m32i
= MUL10(m32i
) + (v
& 0xf); /* <-- val * 10 + d2 */
1611 m32i
= MUL10(m32i
) + (v
>> 4); /* <-- val * 10 + d1 */
1612 m32i
= MUL10(m32i
) + (v
& 0xf); /* <-- val * 10 + d0 */
1613 fpsrcop
+= ((CPU86_LDouble
)m32i
);
1614 if ( ldub(seg
+9) & 0x80 )
1619 void OPPROTO
op_fbld_ST0_A0(void)
1621 helper_fbld_ST0_A0();
1624 void helper_fbst_ST0_A0(void)
1626 CPU86_LDouble fptemp
;
1627 CPU86_LDouble fpsrcop
;
1629 uint8_t *mem_ref
, *mem_end
;
1631 fpsrcop
= rint(ST0
);
1632 mem_ref
= (uint8_t *)A0
;
1633 mem_end
= mem_ref
+ 8;
1634 if ( fpsrcop
< 0.0 ) {
1635 stw(mem_end
, 0x8000);
1638 stw(mem_end
, 0x0000);
1640 while (mem_ref
< mem_end
) {
1643 fptemp
= floor(fpsrcop
/10.0);
1644 v
= ((int)(fpsrcop
- fptemp
*10.0));
1645 if (fptemp
== 0.0) {
1650 fptemp
= floor(fpsrcop
/10.0);
1651 v
|= (((int)(fpsrcop
- fptemp
*10.0)) << 4);
1655 while (mem_ref
< mem_end
) {
1660 void OPPROTO
op_fbst_ST0_A0(void)
1662 helper_fbst_ST0_A0();
1667 static inline void fpush(void)
1669 env
->fpstt
= (env
->fpstt
- 1) & 7;
1670 env
->fptags
[env
->fpstt
] = 0; /* validate stack entry */
1673 static inline void fpop(void)
1675 env
->fptags
[env
->fpstt
] = 1; /* invvalidate stack entry */
1676 env
->fpstt
= (env
->fpstt
+ 1) & 7;
1679 void OPPROTO
op_fpush(void)
1684 void OPPROTO
op_fpop(void)
1689 void OPPROTO
op_fdecstp(void)
1691 env
->fpstt
= (env
->fpstt
- 1) & 7;
1692 env
->fpus
&= (~0x4700);
1695 void OPPROTO
op_fincstp(void)
1697 env
->fpstt
= (env
->fpstt
+ 1) & 7;
1698 env
->fpus
&= (~0x4700);
1701 void OPPROTO
op_fmov_ST0_FT0(void)
1706 void OPPROTO
op_fmov_FT0_STN(void)
1711 void OPPROTO
op_fmov_ST0_STN(void)
1716 void OPPROTO
op_fmov_STN_ST0(void)
1721 void OPPROTO
op_fxchg_ST0_STN(void)
1729 /* FPU operations */
1731 /* XXX: handle nans */
1732 void OPPROTO
op_fcom_ST0_FT0(void)
1734 env
->fpus
&= (~0x4500); /* (C3,C2,C0) <-- 000 */
1736 env
->fpus
|= 0x100; /* (C3,C2,C0) <-- 001 */
1737 else if (ST0
== FT0
)
1738 env
->fpus
|= 0x4000; /* (C3,C2,C0) <-- 100 */
1742 /* XXX: handle nans */
1743 void OPPROTO
op_fucom_ST0_FT0(void)
1745 env
->fpus
&= (~0x4500); /* (C3,C2,C0) <-- 000 */
1747 env
->fpus
|= 0x100; /* (C3,C2,C0) <-- 001 */
1748 else if (ST0
== FT0
)
1749 env
->fpus
|= 0x4000; /* (C3,C2,C0) <-- 100 */
1753 void OPPROTO
op_fadd_ST0_FT0(void)
1758 void OPPROTO
op_fmul_ST0_FT0(void)
1763 void OPPROTO
op_fsub_ST0_FT0(void)
1768 void OPPROTO
op_fsubr_ST0_FT0(void)
1773 void OPPROTO
op_fdiv_ST0_FT0(void)
1778 void OPPROTO
op_fdivr_ST0_FT0(void)
1783 /* fp operations between STN and ST0 */
1785 void OPPROTO
op_fadd_STN_ST0(void)
1790 void OPPROTO
op_fmul_STN_ST0(void)
1795 void OPPROTO
op_fsub_STN_ST0(void)
1800 void OPPROTO
op_fsubr_STN_ST0(void)
1807 void OPPROTO
op_fdiv_STN_ST0(void)
1812 void OPPROTO
op_fdivr_STN_ST0(void)
1819 /* misc FPU operations */
1820 void OPPROTO
op_fchs_ST0(void)
1825 void OPPROTO
op_fabs_ST0(void)
1830 void helper_fxam_ST0(void)
1832 CPU86_LDoubleU temp
;
1837 env
->fpus
&= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1839 env
->fpus
|= 0x200; /* C1 <-- 1 */
1841 expdif
= EXPD(temp
);
1842 if (expdif
== MAXEXPD
) {
1843 if (MANTD(temp
) == 0)
1844 env
->fpus
|= 0x500 /*Infinity*/;
1846 env
->fpus
|= 0x100 /*NaN*/;
1847 } else if (expdif
== 0) {
1848 if (MANTD(temp
) == 0)
1849 env
->fpus
|= 0x4000 /*Zero*/;
1851 env
->fpus
|= 0x4400 /*Denormal*/;
1857 void OPPROTO
op_fxam_ST0(void)
1862 void OPPROTO
op_fld1_ST0(void)
1864 ST0
= *(CPU86_LDouble
*)&f15rk
[1];
1867 void OPPROTO
op_fldl2t_ST0(void)
1869 ST0
= *(CPU86_LDouble
*)&f15rk
[6];
1872 void OPPROTO
op_fldl2e_ST0(void)
1874 ST0
= *(CPU86_LDouble
*)&f15rk
[5];
1877 void OPPROTO
op_fldpi_ST0(void)
1879 ST0
= *(CPU86_LDouble
*)&f15rk
[2];
1882 void OPPROTO
op_fldlg2_ST0(void)
1884 ST0
= *(CPU86_LDouble
*)&f15rk
[3];
1887 void OPPROTO
op_fldln2_ST0(void)
1889 ST0
= *(CPU86_LDouble
*)&f15rk
[4];
1892 void OPPROTO
op_fldz_ST0(void)
1894 ST0
= *(CPU86_LDouble
*)&f15rk
[0];
1897 void OPPROTO
op_fldz_FT0(void)
1899 ST0
= *(CPU86_LDouble
*)&f15rk
[0];
1902 void helper_f2xm1(void)
1904 ST0
= pow(2.0,ST0
) - 1.0;
1907 void helper_fyl2x(void)
1909 CPU86_LDouble fptemp
;
1913 fptemp
= log(fptemp
)/log(2.0); /* log2(ST) */
1917 env
->fpus
&= (~0x4700);
1922 void helper_fptan(void)
1924 CPU86_LDouble fptemp
;
1927 if((fptemp
> MAXTAN
)||(fptemp
< -MAXTAN
)) {
1933 env
->fpus
&= (~0x400); /* C2 <-- 0 */
1934 /* the above code is for |arg| < 2**52 only */
1938 void helper_fpatan(void)
1940 CPU86_LDouble fptemp
, fpsrcop
;
1944 ST1
= atan2(fpsrcop
,fptemp
);
1948 void helper_fxtract(void)
1950 CPU86_LDoubleU temp
;
1951 unsigned int expdif
;
1954 expdif
= EXPD(temp
) - EXPBIAS
;
1955 /*DP exponent bias*/
1962 void helper_fprem1(void)
1964 CPU86_LDouble dblq
, fpsrcop
, fptemp
;
1965 CPU86_LDoubleU fpsrcop1
, fptemp1
;
1971 fpsrcop1
.d
= fpsrcop
;
1973 expdif
= EXPD(fpsrcop1
) - EXPD(fptemp1
);
1975 dblq
= fpsrcop
/ fptemp
;
1976 dblq
= (dblq
< 0.0)? ceil(dblq
): floor(dblq
);
1977 ST0
= fpsrcop
- fptemp
*dblq
;
1978 q
= (int)dblq
; /* cutting off top bits is assumed here */
1979 env
->fpus
&= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1980 /* (C0,C1,C3) <-- (q2,q1,q0) */
1981 env
->fpus
|= (q
&0x4) << 6; /* (C0) <-- q2 */
1982 env
->fpus
|= (q
&0x2) << 8; /* (C1) <-- q1 */
1983 env
->fpus
|= (q
&0x1) << 14; /* (C3) <-- q0 */
1985 env
->fpus
|= 0x400; /* C2 <-- 1 */
1986 fptemp
= pow(2.0, expdif
-50);
1987 fpsrcop
= (ST0
/ ST1
) / fptemp
;
1988 /* fpsrcop = integer obtained by rounding to the nearest */
1989 fpsrcop
= (fpsrcop
-floor(fpsrcop
) < ceil(fpsrcop
)-fpsrcop
)?
1990 floor(fpsrcop
): ceil(fpsrcop
);
1991 ST0
-= (ST1
* fpsrcop
* fptemp
);
1995 void helper_fprem(void)
1997 CPU86_LDouble dblq
, fpsrcop
, fptemp
;
1998 CPU86_LDoubleU fpsrcop1
, fptemp1
;
2004 fpsrcop1
.d
= fpsrcop
;
2006 expdif
= EXPD(fpsrcop1
) - EXPD(fptemp1
);
2007 if ( expdif
< 53 ) {
2008 dblq
= fpsrcop
/ fptemp
;
2009 dblq
= (dblq
< 0.0)? ceil(dblq
): floor(dblq
);
2010 ST0
= fpsrcop
- fptemp
*dblq
;
2011 q
= (int)dblq
; /* cutting off top bits is assumed here */
2012 env
->fpus
&= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
2013 /* (C0,C1,C3) <-- (q2,q1,q0) */
2014 env
->fpus
|= (q
&0x4) << 6; /* (C0) <-- q2 */
2015 env
->fpus
|= (q
&0x2) << 8; /* (C1) <-- q1 */
2016 env
->fpus
|= (q
&0x1) << 14; /* (C3) <-- q0 */
2018 env
->fpus
|= 0x400; /* C2 <-- 1 */
2019 fptemp
= pow(2.0, expdif
-50);
2020 fpsrcop
= (ST0
/ ST1
) / fptemp
;
2021 /* fpsrcop = integer obtained by chopping */
2022 fpsrcop
= (fpsrcop
< 0.0)?
2023 -(floor(fabs(fpsrcop
))): floor(fpsrcop
);
2024 ST0
-= (ST1
* fpsrcop
* fptemp
);
2028 void helper_fyl2xp1(void)
2030 CPU86_LDouble fptemp
;
2033 if ((fptemp
+1.0)>0.0) {
2034 fptemp
= log(fptemp
+1.0) / log(2.0); /* log2(ST+1.0) */
2038 env
->fpus
&= (~0x4700);
2043 void helper_fsqrt(void)
2045 CPU86_LDouble fptemp
;
2049 env
->fpus
&= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
2055 void helper_fsincos(void)
2057 CPU86_LDouble fptemp
;
2060 if ((fptemp
> MAXTAN
)||(fptemp
< -MAXTAN
)) {
2066 env
->fpus
&= (~0x400); /* C2 <-- 0 */
2067 /* the above code is for |arg| < 2**63 only */
2071 void helper_frndint(void)
2076 void helper_fscale(void)
2078 CPU86_LDouble fpsrcop
, fptemp
;
2081 fptemp
= pow(fpsrcop
,ST1
);
2085 void helper_fsin(void)
2087 CPU86_LDouble fptemp
;
2090 if ((fptemp
> MAXTAN
)||(fptemp
< -MAXTAN
)) {
2094 env
->fpus
&= (~0x400); /* C2 <-- 0 */
2095 /* the above code is for |arg| < 2**53 only */
2099 void helper_fcos(void)
2101 CPU86_LDouble fptemp
;
2104 if((fptemp
> MAXTAN
)||(fptemp
< -MAXTAN
)) {
2108 env
->fpus
&= (~0x400); /* C2 <-- 0 */
2109 /* the above code is for |arg5 < 2**63 only */
2113 /* associated heplers to reduce generated code length and to simplify
2114 relocation (FP constants are usually stored in .rodata section) */
2116 void OPPROTO
op_f2xm1(void)
2121 void OPPROTO
op_fyl2x(void)
2126 void OPPROTO
op_fptan(void)
2131 void OPPROTO
op_fpatan(void)
2136 void OPPROTO
op_fxtract(void)
2141 void OPPROTO
op_fprem1(void)
2147 void OPPROTO
op_fprem(void)
2152 void OPPROTO
op_fyl2xp1(void)
2157 void OPPROTO
op_fsqrt(void)
2162 void OPPROTO
op_fsincos(void)
2167 void OPPROTO
op_frndint(void)
2172 void OPPROTO
op_fscale(void)
2177 void OPPROTO
op_fsin(void)
2182 void OPPROTO
op_fcos(void)
2187 void OPPROTO
op_fnstsw_A0(void)
2190 fpus
= (env
->fpus
& ~0x3800) | (env
->fpstt
& 0x7) << 11;
2191 stw((void *)A0
, fpus
);
2194 void OPPROTO
op_fnstsw_EAX(void)
2197 fpus
= (env
->fpus
& ~0x3800) | (env
->fpstt
& 0x7) << 11;
2198 EAX
= (EAX
& 0xffff0000) | fpus
;
2201 void OPPROTO
op_fnstcw_A0(void)
2203 stw((void *)A0
, env
->fpuc
);
2206 void OPPROTO
op_fldcw_A0(void)
2209 env
->fpuc
= lduw((void *)A0
);
2210 /* set rounding mode */
2211 switch(env
->fpuc
& RC_MASK
) {
2214 rnd_type
= FE_TONEAREST
;
2217 rnd_type
= FE_DOWNWARD
;
2220 rnd_type
= FE_UPWARD
;
2223 rnd_type
= FE_TOWARDZERO
;
2226 fesetround(rnd_type
);
2229 void OPPROTO
op_fclex(void)
2231 env
->fpus
&= 0x7f00;
2234 void OPPROTO
op_fninit(void)