]>
git.proxmox.com Git - qemu.git/blob - op-i386.c
503fb88edec1e907610f8f07e1d677fae4676471
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 env
->exception_index
= exception_index
;
127 longjmp(env
->jmp_env
, 1);
130 /* we define the various pieces of code used by the JIT */
134 #include "opreg_template.h"
140 #include "opreg_template.h"
146 #include "opreg_template.h"
152 #include "opreg_template.h"
158 #include "opreg_template.h"
164 #include "opreg_template.h"
170 #include "opreg_template.h"
176 #include "opreg_template.h"
182 void OPPROTO
op_addl_T0_T1_cc(void)
189 void OPPROTO
op_orl_T0_T1_cc(void)
195 void OPPROTO
op_andl_T0_T1_cc(void)
201 void OPPROTO
op_subl_T0_T1_cc(void)
208 void OPPROTO
op_xorl_T0_T1_cc(void)
214 void OPPROTO
op_cmpl_T0_T1_cc(void)
220 void OPPROTO
op_notl_T0(void)
225 void OPPROTO
op_negl_T0_cc(void)
232 void OPPROTO
op_incl_T0_cc(void)
234 CC_SRC
= cc_table
[CC_OP
].compute_c();
239 void OPPROTO
op_decl_T0_cc(void)
241 CC_SRC
= cc_table
[CC_OP
].compute_c();
246 void OPPROTO
op_testl_T0_T1_cc(void)
251 void OPPROTO
op_bswapl_T0(void)
256 /* multiply/divide */
257 void OPPROTO
op_mulb_AL_T0(void)
260 res
= (uint8_t)EAX
* (uint8_t)T0
;
261 EAX
= (EAX
& 0xffff0000) | res
;
262 CC_SRC
= (res
& 0xff00);
265 void OPPROTO
op_imulb_AL_T0(void)
268 res
= (int8_t)EAX
* (int8_t)T0
;
269 EAX
= (EAX
& 0xffff0000) | (res
& 0xffff);
270 CC_SRC
= (res
!= (int8_t)res
);
273 void OPPROTO
op_mulw_AX_T0(void)
276 res
= (uint16_t)EAX
* (uint16_t)T0
;
277 EAX
= (EAX
& 0xffff0000) | (res
& 0xffff);
278 EDX
= (EDX
& 0xffff0000) | ((res
>> 16) & 0xffff);
282 void OPPROTO
op_imulw_AX_T0(void)
285 res
= (int16_t)EAX
* (int16_t)T0
;
286 EAX
= (EAX
& 0xffff0000) | (res
& 0xffff);
287 EDX
= (EDX
& 0xffff0000) | ((res
>> 16) & 0xffff);
288 CC_SRC
= (res
!= (int16_t)res
);
291 void OPPROTO
op_mull_EAX_T0(void)
294 res
= (uint64_t)((uint32_t)EAX
) * (uint64_t)((uint32_t)T0
);
300 void OPPROTO
op_imull_EAX_T0(void)
303 res
= (int64_t)((int32_t)EAX
) * (int64_t)((int32_t)T0
);
306 CC_SRC
= (res
!= (int32_t)res
);
309 void OPPROTO
op_imulw_T0_T1(void)
312 res
= (int16_t)T0
* (int16_t)T1
;
314 CC_SRC
= (res
!= (int16_t)res
);
317 void OPPROTO
op_imull_T0_T1(void)
320 res
= (int64_t)((int32_t)T0
) * (int64_t)((int32_t)T1
);
322 CC_SRC
= (res
!= (int32_t)res
);
325 /* division, flags are undefined */
326 /* XXX: add exceptions for overflow & div by zero */
327 void OPPROTO
op_divb_AL_T0(void)
329 unsigned int num
, den
, q
, r
;
331 num
= (EAX
& 0xffff);
333 q
= (num
/ den
) & 0xff;
334 r
= (num
% den
) & 0xff;
335 EAX
= (EAX
& 0xffff0000) | (r
<< 8) | q
;
338 void OPPROTO
op_idivb_AL_T0(void)
344 q
= (num
/ den
) & 0xff;
345 r
= (num
% den
) & 0xff;
346 EAX
= (EAX
& 0xffff0000) | (r
<< 8) | q
;
349 void OPPROTO
op_divw_AX_T0(void)
351 unsigned int num
, den
, q
, r
;
353 num
= (EAX
& 0xffff) | ((EDX
& 0xffff) << 16);
355 q
= (num
/ den
) & 0xffff;
356 r
= (num
% den
) & 0xffff;
357 EAX
= (EAX
& 0xffff0000) | q
;
358 EDX
= (EDX
& 0xffff0000) | r
;
361 void OPPROTO
op_idivw_AX_T0(void)
365 num
= (EAX
& 0xffff) | ((EDX
& 0xffff) << 16);
367 q
= (num
/ den
) & 0xffff;
368 r
= (num
% den
) & 0xffff;
369 EAX
= (EAX
& 0xffff0000) | q
;
370 EDX
= (EDX
& 0xffff0000) | r
;
373 void OPPROTO
op_divl_EAX_T0(void)
375 unsigned int den
, q
, r
;
378 num
= EAX
| ((uint64_t)EDX
<< 32);
386 void OPPROTO
op_idivl_EAX_T0(void)
391 num
= EAX
| ((uint64_t)EDX
<< 32);
401 void OPPROTO
op_movl_T0_im(void)
406 void OPPROTO
op_movl_T1_im(void)
411 void OPPROTO
op_movl_A0_im(void)
416 void OPPROTO
op_addl_A0_im(void)
421 void OPPROTO
op_andl_A0_ffff(void)
428 void OPPROTO
op_ldub_T0_A0(void)
430 T0
= ldub((uint8_t *)A0
);
433 void OPPROTO
op_ldsb_T0_A0(void)
435 T0
= ldsb((int8_t *)A0
);
438 void OPPROTO
op_lduw_T0_A0(void)
440 T0
= lduw((uint8_t *)A0
);
443 void OPPROTO
op_ldsw_T0_A0(void)
445 T0
= ldsw((int8_t *)A0
);
448 void OPPROTO
op_ldl_T0_A0(void)
450 T0
= ldl((uint8_t *)A0
);
453 void OPPROTO
op_ldub_T1_A0(void)
455 T1
= ldub((uint8_t *)A0
);
458 void OPPROTO
op_ldsb_T1_A0(void)
460 T1
= ldsb((int8_t *)A0
);
463 void OPPROTO
op_lduw_T1_A0(void)
465 T1
= lduw((uint8_t *)A0
);
468 void OPPROTO
op_ldsw_T1_A0(void)
470 T1
= ldsw((int8_t *)A0
);
473 void OPPROTO
op_ldl_T1_A0(void)
475 T1
= ldl((uint8_t *)A0
);
478 void OPPROTO
op_stb_T0_A0(void)
480 stb((uint8_t *)A0
, T0
);
483 void OPPROTO
op_stw_T0_A0(void)
485 stw((uint8_t *)A0
, T0
);
488 void OPPROTO
op_stl_T0_A0(void)
490 stl((uint8_t *)A0
, T0
);
493 /* used for bit operations */
495 void OPPROTO
op_add_bitw_A0_T1(void)
497 A0
+= ((int32_t)T1
>> 4) << 1;
500 void OPPROTO
op_add_bitl_A0_T1(void)
502 A0
+= ((int32_t)T1
>> 5) << 2;
507 void OPPROTO
op_jmp_T0(void)
512 void OPPROTO
op_jmp_im(void)
517 void OPPROTO
op_int_im(void)
520 raise_exception(EXCP0D_GPF
);
523 void OPPROTO
op_int3(void)
526 raise_exception(EXCP03_INT3
);
529 void OPPROTO
op_into(void)
532 eflags
= cc_table
[CC_OP
].compute_all();
535 raise_exception(EXCP04_INTO
);
546 #include "ops_template.h"
550 #include "ops_template.h"
554 #include "ops_template.h"
559 void OPPROTO
op_movsbl_T0_T0(void)
564 void OPPROTO
op_movzbl_T0_T0(void)
569 void OPPROTO
op_movswl_T0_T0(void)
574 void OPPROTO
op_movzwl_T0_T0(void)
579 void OPPROTO
op_movswl_EAX_AX(void)
584 void OPPROTO
op_movsbw_AX_AL(void)
586 EAX
= (EAX
& 0xffff0000) | ((int8_t)EAX
& 0xffff);
589 void OPPROTO
op_movslq_EDX_EAX(void)
591 EDX
= (int32_t)EAX
>> 31;
594 void OPPROTO
op_movswl_DX_AX(void)
596 EDX
= (EDX
& 0xffff0000) | (((int16_t)EAX
>> 15) & 0xffff);
600 /* XXX: add 16 bit operand/16 bit seg variants */
602 void op_pushl_T0(void)
606 stl((void *)offset
, T0
);
607 /* modify ESP after to handle exceptions correctly */
611 void op_pushl_T1(void)
615 stl((void *)offset
, T1
);
616 /* modify ESP after to handle exceptions correctly */
620 void op_popl_T0(void)
622 T0
= ldl((void *)ESP
);
626 void op_addl_ESP_im(void)
634 sp
= (void *)(ESP
- 32);
643 ESP
= (unsigned long)sp
;
649 sp
= (void *)(ESP
- 16);
658 ESP
= (unsigned long)sp
;
672 ESP
= (unsigned long)sp
+ 32;
686 ESP
= (unsigned long)sp
+ 16;
691 unsigned int bp
, frame_temp
, level
;
698 frame_temp
= (unsigned int)sp
;
722 asm("rdtsc" : "=A" (val
));
724 /* better than nothing: the time increases */
734 void OPPROTO
op_aam(void)
741 EAX
= (EAX
& ~0xffff) | al
| (ah
<< 8);
745 void OPPROTO
op_aad(void)
750 ah
= (EAX
>> 8) & 0xff;
751 al
= ((ah
* base
) + al
) & 0xff;
752 EAX
= (EAX
& ~0xffff) | al
;
756 void OPPROTO
op_aaa(void)
762 eflags
= cc_table
[CC_OP
].compute_all();
765 ah
= (EAX
>> 8) & 0xff;
767 icarry
= (al
> 0xf9);
768 if (((al
& 0x0f) > 9 ) || af
) {
769 al
= (al
+ 6) & 0x0f;
770 ah
= (ah
+ 1 + icarry
) & 0xff;
771 eflags
|= CC_C
| CC_A
;
773 eflags
&= ~(CC_C
| CC_A
);
776 EAX
= (EAX
& ~0xffff) | al
| (ah
<< 8);
780 void OPPROTO
op_aas(void)
786 eflags
= cc_table
[CC_OP
].compute_all();
789 ah
= (EAX
>> 8) & 0xff;
792 if (((al
& 0x0f) > 9 ) || af
) {
793 al
= (al
- 6) & 0x0f;
794 ah
= (ah
- 1 - icarry
) & 0xff;
795 eflags
|= CC_C
| CC_A
;
797 eflags
&= ~(CC_C
| CC_A
);
800 EAX
= (EAX
& ~0xffff) | al
| (ah
<< 8);
804 void OPPROTO
op_daa(void)
809 eflags
= cc_table
[CC_OP
].compute_all();
815 if (((al
& 0x0f) > 9 ) || af
) {
816 al
= (al
+ 6) & 0xff;
819 if ((al
> 0x9f) || cf
) {
820 al
= (al
+ 0x60) & 0xff;
823 EAX
= (EAX
& ~0xff) | al
;
824 /* well, speed is not an issue here, so we compute the flags by hand */
825 eflags
|= (al
== 0) << 6; /* zf */
826 eflags
|= parity_table
[al
]; /* pf */
827 eflags
|= (al
& 0x80); /* sf */
831 void OPPROTO
op_das(void)
836 eflags
= cc_table
[CC_OP
].compute_all();
843 if (((al
& 0x0f) > 9 ) || af
) {
847 al
= (al
- 6) & 0xff;
849 if ((al1
> 0x99) || cf
) {
850 al
= (al
- 0x60) & 0xff;
853 EAX
= (EAX
& ~0xff) | al
;
854 /* well, speed is not an issue here, so we compute the flags by hand */
855 eflags
|= (al
== 0) << 6; /* zf */
856 eflags
|= parity_table
[al
]; /* pf */
857 eflags
|= (al
& 0x80); /* sf */
861 /* segment handling */
863 void load_seg(int seg_reg
, int selector
)
866 SegmentDescriptorTable
*dt
;
871 env
->segs
[seg_reg
] = selector
;
872 sc
= &env
->seg_cache
[seg_reg
];
874 sc
->base
= (void *)(selector
<< 4);
882 index
= selector
& ~7;
883 if ((index
+ 7) > dt
->limit
)
884 raise_exception(EXCP0D_GPF
);
885 ptr
= dt
->base
+ index
;
888 sc
->base
= (void *)((e1
>> 16) | ((e2
& 0xff) << 16) | (e2
& 0xff000000));
889 sc
->limit
= (e1
& 0xffff) | (e2
& 0x000f0000);
891 sc
->limit
= (sc
->limit
<< 12) | 0xfff;
892 sc
->seg_32bit
= (e2
>> 22) & 1;
894 fprintf(logfile
, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n",
895 selector
, (unsigned long)sc
->base
, sc
->limit
, sc
->seg_32bit
);
900 void OPPROTO
op_movl_seg_T0(void)
902 load_seg(PARAM1
, T0
& 0xffff);
905 void OPPROTO
op_movl_T0_seg(void)
907 T0
= env
->segs
[PARAM1
];
910 void OPPROTO
op_addl_A0_seg(void)
912 A0
+= *(unsigned long *)((char *)env
+ PARAM1
);
917 /* slow jumps cases (compute x86 flags) */
918 void OPPROTO
op_jo_cc(void)
921 eflags
= cc_table
[CC_OP
].compute_all();
929 void OPPROTO
op_jb_cc(void)
931 if (cc_table
[CC_OP
].compute_c())
938 void OPPROTO
op_jz_cc(void)
941 eflags
= cc_table
[CC_OP
].compute_all();
949 void OPPROTO
op_jbe_cc(void)
952 eflags
= cc_table
[CC_OP
].compute_all();
953 if (eflags
& (CC_Z
| CC_C
))
960 void OPPROTO
op_js_cc(void)
963 eflags
= cc_table
[CC_OP
].compute_all();
971 void OPPROTO
op_jp_cc(void)
974 eflags
= cc_table
[CC_OP
].compute_all();
982 void OPPROTO
op_jl_cc(void)
985 eflags
= cc_table
[CC_OP
].compute_all();
986 if ((eflags
^ (eflags
>> 4)) & 0x80)
993 void OPPROTO
op_jle_cc(void)
996 eflags
= cc_table
[CC_OP
].compute_all();
997 if (((eflags
^ (eflags
>> 4)) & 0x80) || (eflags
& CC_Z
))
1004 /* slow set cases (compute x86 flags) */
1005 void OPPROTO
op_seto_T0_cc(void)
1008 eflags
= cc_table
[CC_OP
].compute_all();
1009 T0
= (eflags
>> 11) & 1;
1012 void OPPROTO
op_setb_T0_cc(void)
1014 T0
= cc_table
[CC_OP
].compute_c();
1017 void OPPROTO
op_setz_T0_cc(void)
1020 eflags
= cc_table
[CC_OP
].compute_all();
1021 T0
= (eflags
>> 6) & 1;
1024 void OPPROTO
op_setbe_T0_cc(void)
1027 eflags
= cc_table
[CC_OP
].compute_all();
1028 T0
= (eflags
& (CC_Z
| CC_C
)) != 0;
1031 void OPPROTO
op_sets_T0_cc(void)
1034 eflags
= cc_table
[CC_OP
].compute_all();
1035 T0
= (eflags
>> 7) & 1;
1038 void OPPROTO
op_setp_T0_cc(void)
1041 eflags
= cc_table
[CC_OP
].compute_all();
1042 T0
= (eflags
>> 2) & 1;
1045 void OPPROTO
op_setl_T0_cc(void)
1048 eflags
= cc_table
[CC_OP
].compute_all();
1049 T0
= ((eflags
^ (eflags
>> 4)) >> 7) & 1;
1052 void OPPROTO
op_setle_T0_cc(void)
1055 eflags
= cc_table
[CC_OP
].compute_all();
1056 T0
= (((eflags
^ (eflags
>> 4)) & 0x80) || (eflags
& CC_Z
)) != 0;
1059 void OPPROTO
op_xor_T0_1(void)
1064 void OPPROTO
op_set_cc_op(void)
1069 void OPPROTO
op_movl_eflags_T0(void)
1072 DF
= 1 - (2 * ((T0
>> 10) & 1));
1075 /* XXX: compute only O flag */
1076 void OPPROTO
op_movb_eflags_T0(void)
1079 of
= cc_table
[CC_OP
].compute_all() & CC_O
;
1083 void OPPROTO
op_movl_T0_eflags(void)
1085 T0
= cc_table
[CC_OP
].compute_all();
1086 T0
|= (DF
& DIRECTION_FLAG
);
1089 void OPPROTO
op_cld(void)
1094 void OPPROTO
op_std(void)
1099 void OPPROTO
op_clc(void)
1102 eflags
= cc_table
[CC_OP
].compute_all();
1107 void OPPROTO
op_stc(void)
1110 eflags
= cc_table
[CC_OP
].compute_all();
1115 void OPPROTO
op_cmc(void)
1118 eflags
= cc_table
[CC_OP
].compute_all();
1123 void OPPROTO
op_salc(void)
1126 cf
= cc_table
[CC_OP
].compute_c();
1127 EAX
= (EAX
& ~0xff) | ((-cf
) & 0xff);
1130 static int compute_all_eflags(void)
1135 static int compute_c_eflags(void)
1137 return CC_SRC
& CC_C
;
1140 static int compute_c_mul(void)
1147 static int compute_all_mul(void)
1149 int cf
, pf
, af
, zf
, sf
, of
;
1151 pf
= 0; /* undefined */
1152 af
= 0; /* undefined */
1153 zf
= 0; /* undefined */
1154 sf
= 0; /* undefined */
1156 return cf
| pf
| af
| zf
| sf
| of
;
1159 CCTable cc_table
[CC_OP_NB
] = {
1160 [CC_OP_DYNAMIC
] = { /* should never happen */ },
1162 [CC_OP_EFLAGS
] = { compute_all_eflags
, compute_c_eflags
},
1164 [CC_OP_MUL
] = { compute_all_mul
, compute_c_mul
},
1166 [CC_OP_ADDB
] = { compute_all_addb
, compute_c_addb
},
1167 [CC_OP_ADDW
] = { compute_all_addw
, compute_c_addw
},
1168 [CC_OP_ADDL
] = { compute_all_addl
, compute_c_addl
},
1170 [CC_OP_ADCB
] = { compute_all_adcb
, compute_c_adcb
},
1171 [CC_OP_ADCW
] = { compute_all_adcw
, compute_c_adcw
},
1172 [CC_OP_ADCL
] = { compute_all_adcl
, compute_c_adcl
},
1174 [CC_OP_SUBB
] = { compute_all_subb
, compute_c_subb
},
1175 [CC_OP_SUBW
] = { compute_all_subw
, compute_c_subw
},
1176 [CC_OP_SUBL
] = { compute_all_subl
, compute_c_subl
},
1178 [CC_OP_SBBB
] = { compute_all_sbbb
, compute_c_sbbb
},
1179 [CC_OP_SBBW
] = { compute_all_sbbw
, compute_c_sbbw
},
1180 [CC_OP_SBBL
] = { compute_all_sbbl
, compute_c_sbbl
},
1182 [CC_OP_LOGICB
] = { compute_all_logicb
, compute_c_logicb
},
1183 [CC_OP_LOGICW
] = { compute_all_logicw
, compute_c_logicw
},
1184 [CC_OP_LOGICL
] = { compute_all_logicl
, compute_c_logicl
},
1186 [CC_OP_INCB
] = { compute_all_incb
, compute_c_incl
},
1187 [CC_OP_INCW
] = { compute_all_incw
, compute_c_incl
},
1188 [CC_OP_INCL
] = { compute_all_incl
, compute_c_incl
},
1190 [CC_OP_DECB
] = { compute_all_decb
, compute_c_incl
},
1191 [CC_OP_DECW
] = { compute_all_decw
, compute_c_incl
},
1192 [CC_OP_DECL
] = { compute_all_decl
, compute_c_incl
},
1194 [CC_OP_SHLB
] = { compute_all_shlb
, compute_c_shll
},
1195 [CC_OP_SHLW
] = { compute_all_shlw
, compute_c_shll
},
1196 [CC_OP_SHLL
] = { compute_all_shll
, compute_c_shll
},
1198 [CC_OP_SARB
] = { compute_all_sarb
, compute_c_shll
},
1199 [CC_OP_SARW
] = { compute_all_sarw
, compute_c_shll
},
1200 [CC_OP_SARL
] = { compute_all_sarl
, compute_c_shll
},
1203 /* floating point support */
1205 #ifdef USE_X86LDOUBLE
1206 /* use long double functions */
1207 #define lrint lrintl
1208 #define llrint llrintl
1216 #define atan2 atan2l
1217 #define floor floorl
1222 extern int lrint(CPU86_LDouble x
);
1223 extern int64_t llrint(CPU86_LDouble x
);
1224 extern CPU86_LDouble
fabs(CPU86_LDouble x
);
1225 extern CPU86_LDouble
sin(CPU86_LDouble x
);
1226 extern CPU86_LDouble
cos(CPU86_LDouble x
);
1227 extern CPU86_LDouble
sqrt(CPU86_LDouble x
);
1228 extern CPU86_LDouble
pow(CPU86_LDouble
, CPU86_LDouble
);
1229 extern CPU86_LDouble
log(CPU86_LDouble x
);
1230 extern CPU86_LDouble
tan(CPU86_LDouble x
);
1231 extern CPU86_LDouble
atan2(CPU86_LDouble
, CPU86_LDouble
);
1232 extern CPU86_LDouble
floor(CPU86_LDouble x
);
1233 extern CPU86_LDouble
ceil(CPU86_LDouble x
);
1234 extern CPU86_LDouble
rint(CPU86_LDouble x
);
1236 #define RC_MASK 0xc00
1237 #define RC_NEAR 0x000
1238 #define RC_DOWN 0x400
1240 #define RC_CHOP 0xc00
1242 #define MAXTAN 9223372036854775808.0
1244 #ifdef USE_X86LDOUBLE
1250 unsigned long long lower
;
1251 unsigned short upper
;
1255 /* the following deal with x86 long double-precision numbers */
1256 #define MAXEXPD 0x7fff
1257 #define EXPBIAS 16383
1258 #define EXPD(fp) (fp.l.upper & 0x7fff)
1259 #define SIGND(fp) ((fp.l.upper) & 0x8000)
1260 #define MANTD(fp) (fp.l.lower)
1261 #define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
1267 #ifndef WORDS_BIGENDIAN
1269 unsigned long lower
;
1275 unsigned long lower
;
1281 /* the following deal with IEEE double-precision numbers */
1282 #define MAXEXPD 0x7ff
1283 #define EXPBIAS 1023
1284 #define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF)
1285 #define SIGND(fp) ((fp.l.upper) & 0x80000000)
1286 #define MANTD(fp) (fp.ll & ((1LL << 52) - 1))
1287 #define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20)
1292 void OPPROTO
op_flds_FT0_A0(void)
1294 FT0
= ldfl((void *)A0
);
1297 void OPPROTO
op_fldl_FT0_A0(void)
1299 FT0
= ldfq((void *)A0
);
1302 void OPPROTO
op_fild_FT0_A0(void)
1304 FT0
= (CPU86_LDouble
)ldsw((void *)A0
);
1307 void OPPROTO
op_fildl_FT0_A0(void)
1309 FT0
= (CPU86_LDouble
)((int32_t)ldl((void *)A0
));
1312 void OPPROTO
op_fildll_FT0_A0(void)
1314 FT0
= (CPU86_LDouble
)((int64_t)ldq((void *)A0
));
1319 void OPPROTO
op_flds_ST0_A0(void)
1321 ST0
= ldfl((void *)A0
);
1324 void OPPROTO
op_fldl_ST0_A0(void)
1326 ST0
= ldfq((void *)A0
);
1329 #ifdef USE_X86LDOUBLE
1330 void OPPROTO
op_fldt_ST0_A0(void)
1332 ST0
= *(long double *)A0
;
1335 void helper_fldt_ST0_A0(void)
1337 CPU86_LDoubleU temp
;
1340 upper
= lduw((uint8_t *)A0
+ 8);
1341 /* XXX: handle overflow ? */
1342 e
= (upper
& 0x7fff) - 16383 + EXPBIAS
; /* exponent */
1343 e
|= (upper
>> 4) & 0x800; /* sign */
1344 temp
.ll
= ((ldq((void *)A0
) >> 11) & ((1LL << 52) - 1)) | ((uint64_t)e
<< 52);
1348 void OPPROTO
op_fldt_ST0_A0(void)
1350 helper_fldt_ST0_A0();
1354 void OPPROTO
op_fild_ST0_A0(void)
1356 ST0
= (CPU86_LDouble
)ldsw((void *)A0
);
1359 void OPPROTO
op_fildl_ST0_A0(void)
1361 ST0
= (CPU86_LDouble
)((int32_t)ldl((void *)A0
));
1364 void OPPROTO
op_fildll_ST0_A0(void)
1366 ST0
= (CPU86_LDouble
)((int64_t)ldq((void *)A0
));
1371 void OPPROTO
op_fsts_ST0_A0(void)
1373 stfl((void *)A0
, (float)ST0
);
1376 void OPPROTO
op_fstl_ST0_A0(void)
1378 stfq((void *)A0
, (double)ST0
);
1381 #ifdef USE_X86LDOUBLE
1382 void OPPROTO
op_fstt_ST0_A0(void)
1384 *(long double *)A0
= ST0
;
1387 void helper_fstt_ST0_A0(void)
1389 CPU86_LDoubleU temp
;
1393 stq((void *)A0
, (MANTD(temp
) << 11) | (1LL << 63));
1394 /* exponent + sign */
1395 e
= EXPD(temp
) - EXPBIAS
+ 16383;
1396 e
|= SIGND(temp
) >> 16;
1397 stw((uint8_t *)A0
+ 8, e
);
1400 void OPPROTO
op_fstt_ST0_A0(void)
1402 helper_fstt_ST0_A0();
1406 void OPPROTO
op_fist_ST0_A0(void)
1410 stw((void *)A0
, val
);
1413 void OPPROTO
op_fistl_ST0_A0(void)
1417 stl((void *)A0
, val
);
1420 void OPPROTO
op_fistll_ST0_A0(void)
1424 stq((void *)A0
, val
);
1429 #define MUL10(iv) ( iv + iv + (iv << 3) )
1431 void helper_fbld_ST0_A0(void)
1434 CPU86_LDouble fpsrcop
;
1438 /* in this code, seg/m32i will be used as temporary ptr/int */
1439 seg
= (uint8_t *)A0
+ 8;
1441 /* XXX: raise exception */
1445 /* XXX: raise exception */
1446 if ((v
& 0xf0) != 0)
1448 m32i
= v
; /* <-- d14 */
1450 m32i
= MUL10(m32i
) + (v
>> 4); /* <-- val * 10 + d13 */
1451 m32i
= MUL10(m32i
) + (v
& 0xf); /* <-- val * 10 + d12 */
1453 m32i
= MUL10(m32i
) + (v
>> 4); /* <-- val * 10 + d11 */
1454 m32i
= MUL10(m32i
) + (v
& 0xf); /* <-- val * 10 + d10 */
1456 m32i
= MUL10(m32i
) + (v
>> 4); /* <-- val * 10 + d9 */
1457 m32i
= MUL10(m32i
) + (v
& 0xf); /* <-- val * 10 + d8 */
1458 fpsrcop
= ((CPU86_LDouble
)m32i
) * 100000000.0;
1461 m32i
= (v
>> 4); /* <-- d7 */
1462 m32i
= MUL10(m32i
) + (v
& 0xf); /* <-- val * 10 + d6 */
1464 m32i
= MUL10(m32i
) + (v
>> 4); /* <-- val * 10 + d5 */
1465 m32i
= MUL10(m32i
) + (v
& 0xf); /* <-- val * 10 + d4 */
1467 m32i
= MUL10(m32i
) + (v
>> 4); /* <-- val * 10 + d3 */
1468 m32i
= MUL10(m32i
) + (v
& 0xf); /* <-- val * 10 + d2 */
1470 m32i
= MUL10(m32i
) + (v
>> 4); /* <-- val * 10 + d1 */
1471 m32i
= MUL10(m32i
) + (v
& 0xf); /* <-- val * 10 + d0 */
1472 fpsrcop
+= ((CPU86_LDouble
)m32i
);
1473 if ( ldub(seg
+9) & 0x80 )
1478 void OPPROTO
op_fbld_ST0_A0(void)
1480 helper_fbld_ST0_A0();
1483 void helper_fbst_ST0_A0(void)
1485 CPU86_LDouble fptemp
;
1486 CPU86_LDouble fpsrcop
;
1488 uint8_t *mem_ref
, *mem_end
;
1490 fpsrcop
= rint(ST0
);
1491 mem_ref
= (uint8_t *)A0
;
1492 mem_end
= mem_ref
+ 8;
1493 if ( fpsrcop
< 0.0 ) {
1494 stw(mem_end
, 0x8000);
1497 stw(mem_end
, 0x0000);
1499 while (mem_ref
< mem_end
) {
1502 fptemp
= floor(fpsrcop
/10.0);
1503 v
= ((int)(fpsrcop
- fptemp
*10.0));
1504 if (fptemp
== 0.0) {
1509 fptemp
= floor(fpsrcop
/10.0);
1510 v
|= (((int)(fpsrcop
- fptemp
*10.0)) << 4);
1514 while (mem_ref
< mem_end
) {
1519 void OPPROTO
op_fbst_ST0_A0(void)
1521 helper_fbst_ST0_A0();
1526 static inline void fpush(void)
1528 env
->fpstt
= (env
->fpstt
- 1) & 7;
1529 env
->fptags
[env
->fpstt
] = 0; /* validate stack entry */
1532 static inline void fpop(void)
1534 env
->fptags
[env
->fpstt
] = 1; /* invvalidate stack entry */
1535 env
->fpstt
= (env
->fpstt
+ 1) & 7;
1538 void OPPROTO
op_fpush(void)
1543 void OPPROTO
op_fpop(void)
1548 void OPPROTO
op_fdecstp(void)
1550 env
->fpstt
= (env
->fpstt
- 1) & 7;
1551 env
->fpus
&= (~0x4700);
1554 void OPPROTO
op_fincstp(void)
1556 env
->fpstt
= (env
->fpstt
+ 1) & 7;
1557 env
->fpus
&= (~0x4700);
1560 void OPPROTO
op_fmov_ST0_FT0(void)
1565 void OPPROTO
op_fmov_FT0_STN(void)
1570 void OPPROTO
op_fmov_ST0_STN(void)
1575 void OPPROTO
op_fmov_STN_ST0(void)
1580 void OPPROTO
op_fxchg_ST0_STN(void)
1588 /* FPU operations */
1590 /* XXX: handle nans */
1591 void OPPROTO
op_fcom_ST0_FT0(void)
1593 env
->fpus
&= (~0x4500); /* (C3,C2,C0) <-- 000 */
1595 env
->fpus
|= 0x100; /* (C3,C2,C0) <-- 001 */
1596 else if (ST0
== FT0
)
1597 env
->fpus
|= 0x4000; /* (C3,C2,C0) <-- 100 */
1601 /* XXX: handle nans */
1602 void OPPROTO
op_fucom_ST0_FT0(void)
1604 env
->fpus
&= (~0x4500); /* (C3,C2,C0) <-- 000 */
1606 env
->fpus
|= 0x100; /* (C3,C2,C0) <-- 001 */
1607 else if (ST0
== FT0
)
1608 env
->fpus
|= 0x4000; /* (C3,C2,C0) <-- 100 */
1612 void OPPROTO
op_fadd_ST0_FT0(void)
1617 void OPPROTO
op_fmul_ST0_FT0(void)
1622 void OPPROTO
op_fsub_ST0_FT0(void)
1627 void OPPROTO
op_fsubr_ST0_FT0(void)
1632 void OPPROTO
op_fdiv_ST0_FT0(void)
1637 void OPPROTO
op_fdivr_ST0_FT0(void)
1642 /* fp operations between STN and ST0 */
1644 void OPPROTO
op_fadd_STN_ST0(void)
1649 void OPPROTO
op_fmul_STN_ST0(void)
1654 void OPPROTO
op_fsub_STN_ST0(void)
1659 void OPPROTO
op_fsubr_STN_ST0(void)
1666 void OPPROTO
op_fdiv_STN_ST0(void)
1671 void OPPROTO
op_fdivr_STN_ST0(void)
1678 /* misc FPU operations */
1679 void OPPROTO
op_fchs_ST0(void)
1684 void OPPROTO
op_fabs_ST0(void)
1689 void helper_fxam_ST0(void)
1691 CPU86_LDoubleU temp
;
1696 env
->fpus
&= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1698 env
->fpus
|= 0x200; /* C1 <-- 1 */
1700 expdif
= EXPD(temp
);
1701 if (expdif
== MAXEXPD
) {
1702 if (MANTD(temp
) == 0)
1703 env
->fpus
|= 0x500 /*Infinity*/;
1705 env
->fpus
|= 0x100 /*NaN*/;
1706 } else if (expdif
== 0) {
1707 if (MANTD(temp
) == 0)
1708 env
->fpus
|= 0x4000 /*Zero*/;
1710 env
->fpus
|= 0x4400 /*Denormal*/;
1716 void OPPROTO
op_fxam_ST0(void)
1721 void OPPROTO
op_fld1_ST0(void)
1723 ST0
= *(CPU86_LDouble
*)&f15rk
[1];
1726 void OPPROTO
op_fldl2t_ST0(void)
1728 ST0
= *(CPU86_LDouble
*)&f15rk
[6];
1731 void OPPROTO
op_fldl2e_ST0(void)
1733 ST0
= *(CPU86_LDouble
*)&f15rk
[5];
1736 void OPPROTO
op_fldpi_ST0(void)
1738 ST0
= *(CPU86_LDouble
*)&f15rk
[2];
1741 void OPPROTO
op_fldlg2_ST0(void)
1743 ST0
= *(CPU86_LDouble
*)&f15rk
[3];
1746 void OPPROTO
op_fldln2_ST0(void)
1748 ST0
= *(CPU86_LDouble
*)&f15rk
[4];
1751 void OPPROTO
op_fldz_ST0(void)
1753 ST0
= *(CPU86_LDouble
*)&f15rk
[0];
1756 void OPPROTO
op_fldz_FT0(void)
1758 ST0
= *(CPU86_LDouble
*)&f15rk
[0];
1761 void helper_f2xm1(void)
1763 ST0
= pow(2.0,ST0
) - 1.0;
1766 void helper_fyl2x(void)
1768 CPU86_LDouble fptemp
;
1772 fptemp
= log(fptemp
)/log(2.0); /* log2(ST) */
1776 env
->fpus
&= (~0x4700);
1781 void helper_fptan(void)
1783 CPU86_LDouble fptemp
;
1786 if((fptemp
> MAXTAN
)||(fptemp
< -MAXTAN
)) {
1792 env
->fpus
&= (~0x400); /* C2 <-- 0 */
1793 /* the above code is for |arg| < 2**52 only */
1797 void helper_fpatan(void)
1799 CPU86_LDouble fptemp
, fpsrcop
;
1803 ST1
= atan2(fpsrcop
,fptemp
);
1807 void helper_fxtract(void)
1809 CPU86_LDoubleU temp
;
1810 unsigned int expdif
;
1813 expdif
= EXPD(temp
) - EXPBIAS
;
1814 /*DP exponent bias*/
1821 void helper_fprem1(void)
1823 CPU86_LDouble dblq
, fpsrcop
, fptemp
;
1824 CPU86_LDoubleU fpsrcop1
, fptemp1
;
1830 fpsrcop1
.d
= fpsrcop
;
1832 expdif
= EXPD(fpsrcop1
) - EXPD(fptemp1
);
1834 dblq
= fpsrcop
/ fptemp
;
1835 dblq
= (dblq
< 0.0)? ceil(dblq
): floor(dblq
);
1836 ST0
= fpsrcop
- fptemp
*dblq
;
1837 q
= (int)dblq
; /* cutting off top bits is assumed here */
1838 env
->fpus
&= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1839 /* (C0,C1,C3) <-- (q2,q1,q0) */
1840 env
->fpus
|= (q
&0x4) << 6; /* (C0) <-- q2 */
1841 env
->fpus
|= (q
&0x2) << 8; /* (C1) <-- q1 */
1842 env
->fpus
|= (q
&0x1) << 14; /* (C3) <-- q0 */
1844 env
->fpus
|= 0x400; /* C2 <-- 1 */
1845 fptemp
= pow(2.0, expdif
-50);
1846 fpsrcop
= (ST0
/ ST1
) / fptemp
;
1847 /* fpsrcop = integer obtained by rounding to the nearest */
1848 fpsrcop
= (fpsrcop
-floor(fpsrcop
) < ceil(fpsrcop
)-fpsrcop
)?
1849 floor(fpsrcop
): ceil(fpsrcop
);
1850 ST0
-= (ST1
* fpsrcop
* fptemp
);
1854 void helper_fprem(void)
1856 CPU86_LDouble dblq
, fpsrcop
, fptemp
;
1857 CPU86_LDoubleU fpsrcop1
, fptemp1
;
1863 fpsrcop1
.d
= fpsrcop
;
1865 expdif
= EXPD(fpsrcop1
) - EXPD(fptemp1
);
1866 if ( expdif
< 53 ) {
1867 dblq
= fpsrcop
/ fptemp
;
1868 dblq
= (dblq
< 0.0)? ceil(dblq
): floor(dblq
);
1869 ST0
= fpsrcop
- fptemp
*dblq
;
1870 q
= (int)dblq
; /* cutting off top bits is assumed here */
1871 env
->fpus
&= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1872 /* (C0,C1,C3) <-- (q2,q1,q0) */
1873 env
->fpus
|= (q
&0x4) << 6; /* (C0) <-- q2 */
1874 env
->fpus
|= (q
&0x2) << 8; /* (C1) <-- q1 */
1875 env
->fpus
|= (q
&0x1) << 14; /* (C3) <-- q0 */
1877 env
->fpus
|= 0x400; /* C2 <-- 1 */
1878 fptemp
= pow(2.0, expdif
-50);
1879 fpsrcop
= (ST0
/ ST1
) / fptemp
;
1880 /* fpsrcop = integer obtained by chopping */
1881 fpsrcop
= (fpsrcop
< 0.0)?
1882 -(floor(fabs(fpsrcop
))): floor(fpsrcop
);
1883 ST0
-= (ST1
* fpsrcop
* fptemp
);
1887 void helper_fyl2xp1(void)
1889 CPU86_LDouble fptemp
;
1892 if ((fptemp
+1.0)>0.0) {
1893 fptemp
= log(fptemp
+1.0) / log(2.0); /* log2(ST+1.0) */
1897 env
->fpus
&= (~0x4700);
1902 void helper_fsqrt(void)
1904 CPU86_LDouble fptemp
;
1908 env
->fpus
&= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1914 void helper_fsincos(void)
1916 CPU86_LDouble fptemp
;
1919 if ((fptemp
> MAXTAN
)||(fptemp
< -MAXTAN
)) {
1925 env
->fpus
&= (~0x400); /* C2 <-- 0 */
1926 /* the above code is for |arg| < 2**63 only */
1930 void helper_frndint(void)
1935 void helper_fscale(void)
1937 CPU86_LDouble fpsrcop
, fptemp
;
1940 fptemp
= pow(fpsrcop
,ST1
);
1944 void helper_fsin(void)
1946 CPU86_LDouble fptemp
;
1949 if ((fptemp
> MAXTAN
)||(fptemp
< -MAXTAN
)) {
1953 env
->fpus
&= (~0x400); /* C2 <-- 0 */
1954 /* the above code is for |arg| < 2**53 only */
1958 void helper_fcos(void)
1960 CPU86_LDouble fptemp
;
1963 if((fptemp
> MAXTAN
)||(fptemp
< -MAXTAN
)) {
1967 env
->fpus
&= (~0x400); /* C2 <-- 0 */
1968 /* the above code is for |arg5 < 2**63 only */
1972 /* associated heplers to reduce generated code length and to simplify
1973 relocation (FP constants are usually stored in .rodata section) */
1975 void OPPROTO
op_f2xm1(void)
1980 void OPPROTO
op_fyl2x(void)
1985 void OPPROTO
op_fptan(void)
1990 void OPPROTO
op_fpatan(void)
1995 void OPPROTO
op_fxtract(void)
2000 void OPPROTO
op_fprem1(void)
2006 void OPPROTO
op_fprem(void)
2011 void OPPROTO
op_fyl2xp1(void)
2016 void OPPROTO
op_fsqrt(void)
2021 void OPPROTO
op_fsincos(void)
2026 void OPPROTO
op_frndint(void)
2031 void OPPROTO
op_fscale(void)
2036 void OPPROTO
op_fsin(void)
2041 void OPPROTO
op_fcos(void)
2046 void OPPROTO
op_fnstsw_A0(void)
2049 fpus
= (env
->fpus
& ~0x3800) | (env
->fpstt
& 0x7) << 11;
2050 stw((void *)A0
, fpus
);
2053 void OPPROTO
op_fnstsw_EAX(void)
2056 fpus
= (env
->fpus
& ~0x3800) | (env
->fpstt
& 0x7) << 11;
2057 EAX
= (EAX
& 0xffff0000) | fpus
;
2060 void OPPROTO
op_fnstcw_A0(void)
2062 stw((void *)A0
, env
->fpuc
);
2065 void OPPROTO
op_fldcw_A0(void)
2068 env
->fpuc
= lduw((void *)A0
);
2069 /* set rounding mode */
2070 switch(env
->fpuc
& RC_MASK
) {
2073 rnd_type
= FE_TONEAREST
;
2076 rnd_type
= FE_DOWNWARD
;
2079 rnd_type
= FE_UPWARD
;
2082 rnd_type
= FE_TOWARDZERO
;
2085 fesetround(rnd_type
);