better vm86 support - added iret - fixed push/pop fs/gs
[qemu] / op-i386.c
1 /*
2  *  i386 micro operations
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, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include "exec-i386.h"
21
22 /* NOTE: data are not static to force relocation generation by GCC */
23
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,
57 };
58
59 /* modulo 17 table */
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,
65 };
66
67 /* modulo 9 table */
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,
73 };
74
75 #ifdef USE_X86LDOUBLE
76 /* an array of Intel 80-bit FP constants, to be loaded via integer ops */
77 typedef unsigned short f15ld[5];
78 const f15ld f15rk[] =
79 {
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}
87 };
88 #else
89 /* the same, 64-bit version */
90 typedef unsigned short f15ld[4];
91 const f15ld f15rk[] =
92 {
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}
101 #else
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}
109 #endif
110 };
111 #endif
112     
113 /* n must be a constant to be efficient */
114 static inline int lshift(int x, int n)
115 {
116     if (n >= 0)
117         return x << n;
118     else
119         return x >> (-n);
120 }
121
122 /* we define the various pieces of code used by the JIT */
123
124 #define REG EAX
125 #define REGNAME _EAX
126 #include "opreg_template.h"
127 #undef REG
128 #undef REGNAME
129
130 #define REG ECX
131 #define REGNAME _ECX
132 #include "opreg_template.h"
133 #undef REG
134 #undef REGNAME
135
136 #define REG EDX
137 #define REGNAME _EDX
138 #include "opreg_template.h"
139 #undef REG
140 #undef REGNAME
141
142 #define REG EBX
143 #define REGNAME _EBX
144 #include "opreg_template.h"
145 #undef REG
146 #undef REGNAME
147
148 #define REG ESP
149 #define REGNAME _ESP
150 #include "opreg_template.h"
151 #undef REG
152 #undef REGNAME
153
154 #define REG EBP
155 #define REGNAME _EBP
156 #include "opreg_template.h"
157 #undef REG
158 #undef REGNAME
159
160 #define REG ESI
161 #define REGNAME _ESI
162 #include "opreg_template.h"
163 #undef REG
164 #undef REGNAME
165
166 #define REG EDI
167 #define REGNAME _EDI
168 #include "opreg_template.h"
169 #undef REG
170 #undef REGNAME
171
172 /* operations with flags */
173
174 void OPPROTO op_addl_T0_T1_cc(void)
175 {
176     CC_SRC = T0;
177     T0 += T1;
178     CC_DST = T0;
179 }
180
181 void OPPROTO op_orl_T0_T1_cc(void)
182 {
183     T0 |= T1;
184     CC_DST = T0;
185 }
186
187 void OPPROTO op_andl_T0_T1_cc(void)
188 {
189     T0 &= T1;
190     CC_DST = T0;
191 }
192
193 void OPPROTO op_subl_T0_T1_cc(void)
194 {
195     CC_SRC = T0;
196     T0 -= T1;
197     CC_DST = T0;
198 }
199
200 void OPPROTO op_xorl_T0_T1_cc(void)
201 {
202     T0 ^= T1;
203     CC_DST = T0;
204 }
205
206 void OPPROTO op_cmpl_T0_T1_cc(void)
207 {
208     CC_SRC = T0;
209     CC_DST = T0 - T1;
210 }
211
212 void OPPROTO op_negl_T0_cc(void)
213 {
214     CC_SRC = 0;
215     T0 = -T0;
216     CC_DST = T0;
217 }
218
219 void OPPROTO op_incl_T0_cc(void)
220 {
221     CC_SRC = cc_table[CC_OP].compute_c();
222     T0++;
223     CC_DST = T0;
224 }
225
226 void OPPROTO op_decl_T0_cc(void)
227 {
228     CC_SRC = cc_table[CC_OP].compute_c();
229     T0--;
230     CC_DST = T0;
231 }
232
233 void OPPROTO op_testl_T0_T1_cc(void)
234 {
235     CC_DST = T0 & T1;
236 }
237
238 /* operations without flags */
239
240 void OPPROTO op_addl_T0_T1(void)
241 {
242     T0 += T1;
243 }
244
245 void OPPROTO op_orl_T0_T1(void)
246 {
247     T0 |= T1;
248 }
249
250 void OPPROTO op_andl_T0_T1(void)
251 {
252     T0 &= T1;
253 }
254
255 void OPPROTO op_subl_T0_T1(void)
256 {
257     T0 -= T1;
258 }
259
260 void OPPROTO op_xorl_T0_T1(void)
261 {
262     T0 ^= T1;
263 }
264
265 void OPPROTO op_negl_T0(void)
266 {
267     T0 = -T0;
268 }
269
270 void OPPROTO op_incl_T0(void)
271 {
272     T0++;
273 }
274
275 void OPPROTO op_decl_T0(void)
276 {
277     T0--;
278 }
279
280 void OPPROTO op_notl_T0(void)
281 {
282     T0 = ~T0;
283 }
284
285 void OPPROTO op_bswapl_T0(void)
286 {
287     T0 = bswap32(T0);
288 }
289
290 /* multiply/divide */
291 void OPPROTO op_mulb_AL_T0(void)
292 {
293     unsigned int res;
294     res = (uint8_t)EAX * (uint8_t)T0;
295     EAX = (EAX & 0xffff0000) | res;
296     CC_SRC = (res & 0xff00);
297 }
298
299 void OPPROTO op_imulb_AL_T0(void)
300 {
301     int res;
302     res = (int8_t)EAX * (int8_t)T0;
303     EAX = (EAX & 0xffff0000) | (res & 0xffff);
304     CC_SRC = (res != (int8_t)res);
305 }
306
307 void OPPROTO op_mulw_AX_T0(void)
308 {
309     unsigned int res;
310     res = (uint16_t)EAX * (uint16_t)T0;
311     EAX = (EAX & 0xffff0000) | (res & 0xffff);
312     EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff);
313     CC_SRC = res >> 16;
314 }
315
316 void OPPROTO op_imulw_AX_T0(void)
317 {
318     int res;
319     res = (int16_t)EAX * (int16_t)T0;
320     EAX = (EAX & 0xffff0000) | (res & 0xffff);
321     EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff);
322     CC_SRC = (res != (int16_t)res);
323 }
324
325 void OPPROTO op_mull_EAX_T0(void)
326 {
327     uint64_t res;
328     res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0);
329     EAX = res;
330     EDX = res >> 32;
331     CC_SRC = res >> 32;
332 }
333
334 void OPPROTO op_imull_EAX_T0(void)
335 {
336     int64_t res;
337     res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T0);
338     EAX = res;
339     EDX = res >> 32;
340     CC_SRC = (res != (int32_t)res);
341 }
342
343 void OPPROTO op_imulw_T0_T1(void)
344 {
345     int res;
346     res = (int16_t)T0 * (int16_t)T1;
347     T0 = res;
348     CC_SRC = (res != (int16_t)res);
349 }
350
351 void OPPROTO op_imull_T0_T1(void)
352 {
353     int64_t res;
354     res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
355     T0 = res;
356     CC_SRC = (res != (int32_t)res);
357 }
358
359 /* division, flags are undefined */
360 /* XXX: add exceptions for overflow */
361 void OPPROTO op_divb_AL_T0(void)
362 {
363     unsigned int num, den, q, r;
364
365     num = (EAX & 0xffff);
366     den = (T0 & 0xff);
367     if (den == 0)
368         raise_exception(EXCP00_DIVZ);
369     q = (num / den) & 0xff;
370     r = (num % den) & 0xff;
371     EAX = (EAX & 0xffff0000) | (r << 8) | q;
372 }
373
374 void OPPROTO op_idivb_AL_T0(void)
375 {
376     int num, den, q, r;
377
378     num = (int16_t)EAX;
379     den = (int8_t)T0;
380     if (den == 0)
381         raise_exception(EXCP00_DIVZ);
382     q = (num / den) & 0xff;
383     r = (num % den) & 0xff;
384     EAX = (EAX & 0xffff0000) | (r << 8) | q;
385 }
386
387 void OPPROTO op_divw_AX_T0(void)
388 {
389     unsigned int num, den, q, r;
390
391     num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
392     den = (T0 & 0xffff);
393     if (den == 0)
394         raise_exception(EXCP00_DIVZ);
395     q = (num / den) & 0xffff;
396     r = (num % den) & 0xffff;
397     EAX = (EAX & 0xffff0000) | q;
398     EDX = (EDX & 0xffff0000) | r;
399 }
400
401 void OPPROTO op_idivw_AX_T0(void)
402 {
403     int num, den, q, r;
404
405     num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
406     den = (int16_t)T0;
407     if (den == 0)
408         raise_exception(EXCP00_DIVZ);
409     q = (num / den) & 0xffff;
410     r = (num % den) & 0xffff;
411     EAX = (EAX & 0xffff0000) | q;
412     EDX = (EDX & 0xffff0000) | r;
413 }
414
415 void OPPROTO op_divl_EAX_T0(void)
416 {
417     unsigned int den, q, r;
418     uint64_t num;
419     
420     num = EAX | ((uint64_t)EDX << 32);
421     den = T0;
422     if (den == 0)
423         raise_exception(EXCP00_DIVZ);
424     q = (num / den);
425     r = (num % den);
426     EAX = q;
427     EDX = r;
428 }
429
430 void OPPROTO op_idivl_EAX_T0(void)
431 {
432     int den, q, r;
433     int64_t num;
434     
435     num = EAX | ((uint64_t)EDX << 32);
436     den = T0;
437     if (den == 0)
438         raise_exception(EXCP00_DIVZ);
439     q = (num / den);
440     r = (num % den);
441     EAX = q;
442     EDX = r;
443 }
444
445 /* constant load & misc op */
446
447 void OPPROTO op_movl_T0_im(void)
448 {
449     T0 = PARAM1;
450 }
451
452 void OPPROTO op_addl_T0_im(void)
453 {
454     T0 += PARAM1;
455 }
456
457 void OPPROTO op_andl_T0_ffff(void)
458 {
459     T0 = T0 & 0xffff;
460 }
461
462 void OPPROTO op_movl_T0_T1(void)
463 {
464     T0 = T1;
465 }
466
467 void OPPROTO op_movl_T1_im(void)
468 {
469     T1 = PARAM1;
470 }
471
472 void OPPROTO op_addl_T1_im(void)
473 {
474     T1 += PARAM1;
475 }
476
477 void OPPROTO op_movl_T1_A0(void)
478 {
479     T1 = A0;
480 }
481
482 void OPPROTO op_movl_A0_im(void)
483 {
484     A0 = PARAM1;
485 }
486
487 void OPPROTO op_addl_A0_im(void)
488 {
489     A0 += PARAM1;
490 }
491
492 void OPPROTO op_addl_A0_AL(void)
493 {
494     A0 += (EAX & 0xff);
495 }
496
497 void OPPROTO op_andl_A0_ffff(void)
498 {
499     A0 = A0 & 0xffff;
500 }
501
502 /* memory access */
503
504 void OPPROTO op_ldub_T0_A0(void)
505 {
506     T0 = ldub((uint8_t *)A0);
507 }
508
509 void OPPROTO op_ldsb_T0_A0(void)
510 {
511     T0 = ldsb((int8_t *)A0);
512 }
513
514 void OPPROTO op_lduw_T0_A0(void)
515 {
516     T0 = lduw((uint8_t *)A0);
517 }
518
519 void OPPROTO op_ldsw_T0_A0(void)
520 {
521     T0 = ldsw((int8_t *)A0);
522 }
523
524 void OPPROTO op_ldl_T0_A0(void)
525 {
526     T0 = ldl((uint8_t *)A0);
527 }
528
529 void OPPROTO op_ldub_T1_A0(void)
530 {
531     T1 = ldub((uint8_t *)A0);
532 }
533
534 void OPPROTO op_ldsb_T1_A0(void)
535 {
536     T1 = ldsb((int8_t *)A0);
537 }
538
539 void OPPROTO op_lduw_T1_A0(void)
540 {
541     T1 = lduw((uint8_t *)A0);
542 }
543
544 void OPPROTO op_ldsw_T1_A0(void)
545 {
546     T1 = ldsw((int8_t *)A0);
547 }
548
549 void OPPROTO op_ldl_T1_A0(void)
550 {
551     T1 = ldl((uint8_t *)A0);
552 }
553
554 void OPPROTO op_stb_T0_A0(void)
555 {
556     stb((uint8_t *)A0, T0);
557 }
558
559 void OPPROTO op_stw_T0_A0(void)
560 {
561     stw((uint8_t *)A0, T0);
562 }
563
564 void OPPROTO op_stl_T0_A0(void)
565 {
566     stl((uint8_t *)A0, T0);
567 }
568
569 /* used for bit operations */
570
571 void OPPROTO op_add_bitw_A0_T1(void)
572 {
573     A0 += ((int32_t)T1 >> 4) << 1;
574 }
575
576 void OPPROTO op_add_bitl_A0_T1(void)
577 {
578     A0 += ((int32_t)T1 >> 5) << 2;
579 }
580
581 /* indirect jump */
582
583 void OPPROTO op_jmp_T0(void)
584 {
585     EIP = T0;
586 }
587
588 void OPPROTO op_jmp_im(void)
589 {
590     EIP = PARAM1;
591 }
592
593 void OPPROTO op_int_im(void)
594 {
595     EIP = PARAM1;
596     raise_exception(EXCP0D_GPF);
597 }
598
599 void OPPROTO op_int3(void)
600 {
601     EIP = PARAM1;
602     raise_exception(EXCP03_INT3);
603 }
604
605 void OPPROTO op_into(void)
606 {
607     int eflags;
608     eflags = cc_table[CC_OP].compute_all();
609     if (eflags & CC_O) {
610         raise_exception(EXCP04_INTO);
611     }
612 }
613
614 /* XXX: add IOPL/CPL tests */
615 void OPPROTO op_cli(void)
616 {
617     raise_exception(EXCP0D_GPF);
618 }
619
620 /* XXX: add IOPL/CPL tests */
621 void OPPROTO op_sti(void)
622 {
623     raise_exception(EXCP0D_GPF);
624 }
625
626 /* vm86plus instructions */
627
628 void OPPROTO op_cli_vm(void)
629 {
630     env->eflags &= ~VIF_MASK;
631 }
632
633 void OPPROTO op_sti_vm(void)
634 {
635     env->eflags |= VIF_MASK;
636     if (env->eflags & VIP_MASK) {
637         EIP = PARAM1;
638         raise_exception(EXCP0D_GPF);
639     }
640     FORCE_RET();
641 }
642
643 void OPPROTO op_boundw(void)
644 {
645     int low, high, v;
646     low = ldsw((uint8_t *)A0);
647     high = ldsw((uint8_t *)A0 + 2);
648     v = (int16_t)T0;
649     if (v < low || v > high)
650         raise_exception(EXCP05_BOUND);
651     FORCE_RET();
652 }
653
654 void OPPROTO op_boundl(void)
655 {
656     int low, high, v;
657     low = ldl((uint8_t *)A0);
658     high = ldl((uint8_t *)A0 + 4);
659     v = T0;
660     if (v < low || v > high)
661         raise_exception(EXCP05_BOUND);
662     FORCE_RET();
663 }
664
665 void OPPROTO op_cmpxchg8b(void)
666 {
667     uint64_t d;
668     int eflags;
669
670     eflags = cc_table[CC_OP].compute_all();
671     d = ldq((uint8_t *)A0);
672     if (d == (((uint64_t)EDX << 32) | EAX)) {
673         stq((uint8_t *)A0, ((uint64_t)ECX << 32) | EBX);
674         eflags |= CC_Z;
675     } else {
676         EDX = d >> 32;
677         EAX = d;
678         eflags &= ~CC_Z;
679     }
680     CC_SRC = eflags;
681     FORCE_RET();
682 }
683
684 /* string ops */
685
686 #define ldul ldl
687
688 #define SHIFT 0
689 #include "ops_template.h"
690 #undef SHIFT
691
692 #define SHIFT 1
693 #include "ops_template.h"
694 #undef SHIFT
695
696 #define SHIFT 2
697 #include "ops_template.h"
698 #undef SHIFT
699
700 /* sign extend */
701
702 void OPPROTO op_movsbl_T0_T0(void)
703 {
704     T0 = (int8_t)T0;
705 }
706
707 void OPPROTO op_movzbl_T0_T0(void)
708 {
709     T0 = (uint8_t)T0;
710 }
711
712 void OPPROTO op_movswl_T0_T0(void)
713 {
714     T0 = (int16_t)T0;
715 }
716
717 void OPPROTO op_movzwl_T0_T0(void)
718 {
719     T0 = (uint16_t)T0;
720 }
721
722 void OPPROTO op_movswl_EAX_AX(void)
723 {
724     EAX = (int16_t)EAX;
725 }
726
727 void OPPROTO op_movsbw_AX_AL(void)
728 {
729     EAX = (EAX & 0xffff0000) | ((int8_t)EAX & 0xffff);
730 }
731
732 void OPPROTO op_movslq_EDX_EAX(void)
733 {
734     EDX = (int32_t)EAX >> 31;
735 }
736
737 void OPPROTO op_movswl_DX_AX(void)
738 {
739     EDX = (EDX & 0xffff0000) | (((int16_t)EAX >> 15) & 0xffff);
740 }
741
742 /* push/pop */
743
744 void op_pushl_T0(void)
745 {
746     uint32_t offset;
747     offset = ESP - 4;
748     stl((void *)offset, T0);
749     /* modify ESP after to handle exceptions correctly */
750     ESP = offset;
751 }
752
753 void op_pushw_T0(void)
754 {
755     uint32_t offset;
756     offset = ESP - 2;
757     stw((void *)offset, T0);
758     /* modify ESP after to handle exceptions correctly */
759     ESP = offset;
760 }
761
762 void op_pushl_ss32_T0(void)
763 {
764     uint32_t offset;
765     offset = ESP - 4;
766     stl(env->seg_cache[R_SS].base + offset, T0);
767     /* modify ESP after to handle exceptions correctly */
768     ESP = offset;
769 }
770
771 void op_pushw_ss32_T0(void)
772 {
773     uint32_t offset;
774     offset = ESP - 2;
775     stw(env->seg_cache[R_SS].base + offset, T0);
776     /* modify ESP after to handle exceptions correctly */
777     ESP = offset;
778 }
779
780 void op_pushl_ss16_T0(void)
781 {
782     uint32_t offset;
783     offset = (ESP - 4) & 0xffff;
784     stl(env->seg_cache[R_SS].base + offset, T0);
785     /* modify ESP after to handle exceptions correctly */
786     ESP = (ESP & ~0xffff) | offset;
787 }
788
789 void op_pushw_ss16_T0(void)
790 {
791     uint32_t offset;
792     offset = (ESP - 2) & 0xffff;
793     stw(env->seg_cache[R_SS].base + offset, T0);
794     /* modify ESP after to handle exceptions correctly */
795     ESP = (ESP & ~0xffff) | offset;
796 }
797
798 /* NOTE: ESP update is done after */
799 void op_popl_T0(void)
800 {
801     T0 = ldl((void *)ESP);
802 }
803
804 void op_popw_T0(void)
805 {
806     T0 = lduw((void *)ESP);
807 }
808
809 void op_popl_ss32_T0(void)
810 {
811     T0 = ldl(env->seg_cache[R_SS].base + ESP);
812 }
813
814 void op_popw_ss32_T0(void)
815 {
816     T0 = lduw(env->seg_cache[R_SS].base + ESP);
817 }
818
819 void op_popl_ss16_T0(void)
820 {
821     T0 = ldl(env->seg_cache[R_SS].base + (ESP & 0xffff));
822 }
823
824 void op_popw_ss16_T0(void)
825 {
826     T0 = lduw(env->seg_cache[R_SS].base + (ESP & 0xffff));
827 }
828
829 void op_addl_ESP_4(void)
830 {
831     ESP += 4;
832 }
833
834 void op_addl_ESP_2(void)
835 {
836     ESP += 2;
837 }
838
839 void op_addw_ESP_4(void)
840 {
841     ESP = (ESP & ~0xffff) | ((ESP + 4) & 0xffff);
842 }
843
844 void op_addw_ESP_2(void)
845 {
846     ESP = (ESP & ~0xffff) | ((ESP + 2) & 0xffff);
847 }
848
849 void op_addl_ESP_im(void)
850 {
851     ESP += PARAM1;
852 }
853
854 void op_addw_ESP_im(void)
855 {
856     ESP = (ESP & ~0xffff) | ((ESP + PARAM1) & 0xffff);
857 }
858
859 /* rdtsc */
860 #ifndef __i386__
861 uint64_t emu_time;
862 #endif
863
864 void OPPROTO op_rdtsc(void)
865 {
866     uint64_t val;
867 #ifdef __i386__
868     asm("rdtsc" : "=A" (val));
869 #else
870     /* better than nothing: the time increases */
871     val = emu_time++;
872 #endif
873     EAX = val;
874     EDX = val >> 32;
875 }
876
877 /* We simulate a pre-MMX pentium as in valgrind */
878 #define CPUID_FP87 (1 << 0)
879 #define CPUID_VME  (1 << 1)
880 #define CPUID_DE   (1 << 2)
881 #define CPUID_PSE  (1 << 3)
882 #define CPUID_TSC  (1 << 4)
883 #define CPUID_MSR  (1 << 5)
884 #define CPUID_PAE  (1 << 6)
885 #define CPUID_MCE  (1 << 7)
886 #define CPUID_CX8  (1 << 8)
887 #define CPUID_APIC (1 << 9)
888 #define CPUID_SEP  (1 << 11) /* sysenter/sysexit */
889 #define CPUID_MTRR (1 << 12)
890 #define CPUID_PGE  (1 << 13)
891 #define CPUID_MCA  (1 << 14)
892 #define CPUID_CMOV (1 << 15)
893 /* ... */
894 #define CPUID_MMX  (1 << 23)
895 #define CPUID_FXSR (1 << 24)
896 #define CPUID_SSE  (1 << 25)
897 #define CPUID_SSE2 (1 << 26)
898
899 void helper_cpuid(void)
900 {
901     if (EAX == 0) {
902         EAX = 1; /* max EAX index supported */
903         EBX = 0x756e6547;
904         ECX = 0x6c65746e;
905         EDX = 0x49656e69;
906     } else {
907         /* EAX = 1 info */
908         EAX = 0x52b;
909         EBX = 0;
910         ECX = 0;
911         EDX = CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE |
912             CPUID_TSC | CPUID_MSR | CPUID_MCE |
913             CPUID_CX8;
914     }
915 }
916
917 void OPPROTO op_cpuid(void)
918 {
919     helper_cpuid();
920 }
921
922 /* bcd */
923
924 /* XXX: exception */
925 void OPPROTO op_aam(void)
926 {
927     int base = PARAM1;
928     int al, ah;
929     al = EAX & 0xff;
930     ah = al / base;
931     al = al % base;
932     EAX = (EAX & ~0xffff) | al | (ah << 8);
933     CC_DST = al;
934 }
935
936 void OPPROTO op_aad(void)
937 {
938     int base = PARAM1;
939     int al, ah;
940     al = EAX & 0xff;
941     ah = (EAX >> 8) & 0xff;
942     al = ((ah * base) + al) & 0xff;
943     EAX = (EAX & ~0xffff) | al;
944     CC_DST = al;
945 }
946
947 void OPPROTO op_aaa(void)
948 {
949     int icarry;
950     int al, ah, af;
951     int eflags;
952
953     eflags = cc_table[CC_OP].compute_all();
954     af = eflags & CC_A;
955     al = EAX & 0xff;
956     ah = (EAX >> 8) & 0xff;
957
958     icarry = (al > 0xf9);
959     if (((al & 0x0f) > 9 ) || af) {
960         al = (al + 6) & 0x0f;
961         ah = (ah + 1 + icarry) & 0xff;
962         eflags |= CC_C | CC_A;
963     } else {
964         eflags &= ~(CC_C | CC_A);
965         al &= 0x0f;
966     }
967     EAX = (EAX & ~0xffff) | al | (ah << 8);
968     CC_SRC = eflags;
969 }
970
971 void OPPROTO op_aas(void)
972 {
973     int icarry;
974     int al, ah, af;
975     int eflags;
976
977     eflags = cc_table[CC_OP].compute_all();
978     af = eflags & CC_A;
979     al = EAX & 0xff;
980     ah = (EAX >> 8) & 0xff;
981
982     icarry = (al < 6);
983     if (((al & 0x0f) > 9 ) || af) {
984         al = (al - 6) & 0x0f;
985         ah = (ah - 1 - icarry) & 0xff;
986         eflags |= CC_C | CC_A;
987     } else {
988         eflags &= ~(CC_C | CC_A);
989         al &= 0x0f;
990     }
991     EAX = (EAX & ~0xffff) | al | (ah << 8);
992     CC_SRC = eflags;
993 }
994
995 void OPPROTO op_daa(void)
996 {
997     int al, af, cf;
998     int eflags;
999
1000     eflags = cc_table[CC_OP].compute_all();
1001     cf = eflags & CC_C;
1002     af = eflags & CC_A;
1003     al = EAX & 0xff;
1004
1005     eflags = 0;
1006     if (((al & 0x0f) > 9 ) || af) {
1007         al = (al + 6) & 0xff;
1008         eflags |= CC_A;
1009     }
1010     if ((al > 0x9f) || cf) {
1011         al = (al + 0x60) & 0xff;
1012         eflags |= CC_C;
1013     }
1014     EAX = (EAX & ~0xff) | al;
1015     /* well, speed is not an issue here, so we compute the flags by hand */
1016     eflags |= (al == 0) << 6; /* zf */
1017     eflags |= parity_table[al]; /* pf */
1018     eflags |= (al & 0x80); /* sf */
1019     CC_SRC = eflags;
1020 }
1021
1022 void OPPROTO op_das(void)
1023 {
1024     int al, al1, af, cf;
1025     int eflags;
1026
1027     eflags = cc_table[CC_OP].compute_all();
1028     cf = eflags & CC_C;
1029     af = eflags & CC_A;
1030     al = EAX & 0xff;
1031
1032     eflags = 0;
1033     al1 = al;
1034     if (((al & 0x0f) > 9 ) || af) {
1035         eflags |= CC_A;
1036         if (al < 6 || cf)
1037             eflags |= CC_C;
1038         al = (al - 6) & 0xff;
1039     }
1040     if ((al1 > 0x99) || cf) {
1041         al = (al - 0x60) & 0xff;
1042         eflags |= CC_C;
1043     }
1044     EAX = (EAX & ~0xff) | al;
1045     /* well, speed is not an issue here, so we compute the flags by hand */
1046     eflags |= (al == 0) << 6; /* zf */
1047     eflags |= parity_table[al]; /* pf */
1048     eflags |= (al & 0x80); /* sf */
1049     CC_SRC = eflags;
1050 }
1051
1052 /* segment handling */
1053
1054 /* XXX: use static VM86 information */
1055 void load_seg(int seg_reg, int selector)
1056 {
1057     SegmentCache *sc;
1058     SegmentDescriptorTable *dt;
1059     int index;
1060     uint32_t e1, e2;
1061     uint8_t *ptr;
1062
1063     env->segs[seg_reg] = selector;
1064     sc = &env->seg_cache[seg_reg];
1065     if (env->eflags & VM_MASK) {
1066         sc->base = (void *)(selector << 4);
1067         sc->limit = 0xffff;
1068         sc->seg_32bit = 0;
1069     } else {
1070         if (selector & 0x4)
1071             dt = &env->ldt;
1072         else
1073             dt = &env->gdt;
1074         index = selector & ~7;
1075         if ((index + 7) > dt->limit)
1076             raise_exception(EXCP0D_GPF);
1077         ptr = dt->base + index;
1078         e1 = ldl(ptr);
1079         e2 = ldl(ptr + 4);
1080         sc->base = (void *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
1081         sc->limit = (e1 & 0xffff) | (e2 & 0x000f0000);
1082         if (e2 & (1 << 23))
1083             sc->limit = (sc->limit << 12) | 0xfff;
1084         sc->seg_32bit = (e2 >> 22) & 1;
1085 #if 0
1086         fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n", 
1087                 selector, (unsigned long)sc->base, sc->limit, sc->seg_32bit);
1088 #endif
1089     }
1090 }
1091
1092 void OPPROTO op_movl_seg_T0(void)
1093 {
1094     load_seg(PARAM1, T0 & 0xffff);
1095 }
1096
1097 void OPPROTO op_movl_T0_seg(void)
1098 {
1099     T0 = env->segs[PARAM1];
1100 }
1101
1102 void OPPROTO op_movl_A0_seg(void)
1103 {
1104     A0 = *(unsigned long *)((char *)env + PARAM1);
1105 }
1106
1107 void OPPROTO op_addl_A0_seg(void)
1108 {
1109     A0 += *(unsigned long *)((char *)env + PARAM1);
1110 }
1111
1112 /* flags handling */
1113
1114 /* slow jumps cases (compute x86 flags) */
1115 void OPPROTO op_jo_cc(void)
1116 {
1117     int eflags;
1118     eflags = cc_table[CC_OP].compute_all();
1119     if (eflags & CC_O)
1120         EIP = PARAM1;
1121     else
1122         EIP = PARAM2;
1123     FORCE_RET();
1124 }
1125
1126 void OPPROTO op_jb_cc(void)
1127 {
1128     if (cc_table[CC_OP].compute_c())
1129         EIP = PARAM1;
1130     else
1131         EIP = PARAM2;
1132     FORCE_RET();
1133 }
1134
1135 void OPPROTO op_jz_cc(void)
1136 {
1137     int eflags;
1138     eflags = cc_table[CC_OP].compute_all();
1139     if (eflags & CC_Z)
1140         EIP = PARAM1;
1141     else
1142         EIP = PARAM2;
1143     FORCE_RET();
1144 }
1145
1146 void OPPROTO op_jbe_cc(void)
1147 {
1148     int eflags;
1149     eflags = cc_table[CC_OP].compute_all();
1150     if (eflags & (CC_Z | CC_C))
1151         EIP = PARAM1;
1152     else
1153         EIP = PARAM2;
1154     FORCE_RET();
1155 }
1156
1157 void OPPROTO op_js_cc(void)
1158 {
1159     int eflags;
1160     eflags = cc_table[CC_OP].compute_all();
1161     if (eflags & CC_S)
1162         EIP = PARAM1;
1163     else
1164         EIP = PARAM2;
1165     FORCE_RET();
1166 }
1167
1168 void OPPROTO op_jp_cc(void)
1169 {
1170     int eflags;
1171     eflags = cc_table[CC_OP].compute_all();
1172     if (eflags & CC_P)
1173         EIP = PARAM1;
1174     else
1175         EIP = PARAM2;
1176     FORCE_RET();
1177 }
1178
1179 void OPPROTO op_jl_cc(void)
1180 {
1181     int eflags;
1182     eflags = cc_table[CC_OP].compute_all();
1183     if ((eflags ^ (eflags >> 4)) & 0x80)
1184         EIP = PARAM1;
1185     else
1186         EIP = PARAM2;
1187     FORCE_RET();
1188 }
1189
1190 void OPPROTO op_jle_cc(void)
1191 {
1192     int eflags;
1193     eflags = cc_table[CC_OP].compute_all();
1194     if (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z))
1195         EIP = PARAM1;
1196     else
1197         EIP = PARAM2;
1198     FORCE_RET();
1199 }
1200
1201 /* slow set cases (compute x86 flags) */
1202 void OPPROTO op_seto_T0_cc(void)
1203 {
1204     int eflags;
1205     eflags = cc_table[CC_OP].compute_all();
1206     T0 = (eflags >> 11) & 1;
1207 }
1208
1209 void OPPROTO op_setb_T0_cc(void)
1210 {
1211     T0 = cc_table[CC_OP].compute_c();
1212 }
1213
1214 void OPPROTO op_setz_T0_cc(void)
1215 {
1216     int eflags;
1217     eflags = cc_table[CC_OP].compute_all();
1218     T0 = (eflags >> 6) & 1;
1219 }
1220
1221 void OPPROTO op_setbe_T0_cc(void)
1222 {
1223     int eflags;
1224     eflags = cc_table[CC_OP].compute_all();
1225     T0 = (eflags & (CC_Z | CC_C)) != 0;
1226 }
1227
1228 void OPPROTO op_sets_T0_cc(void)
1229 {
1230     int eflags;
1231     eflags = cc_table[CC_OP].compute_all();
1232     T0 = (eflags >> 7) & 1;
1233 }
1234
1235 void OPPROTO op_setp_T0_cc(void)
1236 {
1237     int eflags;
1238     eflags = cc_table[CC_OP].compute_all();
1239     T0 = (eflags >> 2) & 1;
1240 }
1241
1242 void OPPROTO op_setl_T0_cc(void)
1243 {
1244     int eflags;
1245     eflags = cc_table[CC_OP].compute_all();
1246     T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
1247 }
1248
1249 void OPPROTO op_setle_T0_cc(void)
1250 {
1251     int eflags;
1252     eflags = cc_table[CC_OP].compute_all();
1253     T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
1254 }
1255
1256 void OPPROTO op_xor_T0_1(void)
1257 {
1258     T0 ^= 1;
1259 }
1260
1261 void OPPROTO op_set_cc_op(void)
1262 {
1263     CC_OP = PARAM1;
1264 }
1265
1266 #define FL_UPDATE_MASK32 (TF_MASK | AC_MASK | ID_MASK)
1267 #define FL_UPDATE_MASK16 (TF_MASK)
1268
1269 void OPPROTO op_movl_eflags_T0(void)
1270 {
1271     int eflags;
1272     eflags = T0;
1273     CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1274     DF = 1 - (2 * ((eflags >> 10) & 1));
1275     /* we also update some system flags as in user mode */
1276     env->eflags = (env->eflags & ~FL_UPDATE_MASK32) | (eflags & FL_UPDATE_MASK32);
1277 }
1278
1279 void OPPROTO op_movw_eflags_T0(void)
1280 {
1281     int eflags;
1282     eflags = T0;
1283     CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1284     DF = 1 - (2 * ((eflags >> 10) & 1));
1285     /* we also update some system flags as in user mode */
1286     env->eflags = (env->eflags & ~FL_UPDATE_MASK16) | (eflags & FL_UPDATE_MASK16);
1287 }
1288
1289 /* vm86 version */
1290 void OPPROTO op_movw_eflags_T0_vm(void)
1291 {
1292     int eflags;
1293     eflags = T0;
1294     CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1295     DF = 1 - (2 * ((eflags >> 10) & 1));
1296     /* we also update some system flags as in user mode */
1297     env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) |
1298         (eflags & FL_UPDATE_MASK16);
1299     if (eflags & IF_MASK) {
1300         env->eflags |= VIF_MASK;
1301         if (env->eflags & VIP_MASK) {
1302             EIP = PARAM1;
1303             raise_exception(EXCP0D_GPF);
1304         }
1305     }
1306     FORCE_RET();
1307 }
1308
1309 void OPPROTO op_movl_eflags_T0_vm(void)
1310 {
1311     int eflags;
1312     eflags = T0;
1313     CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1314     DF = 1 - (2 * ((eflags >> 10) & 1));
1315     /* we also update some system flags as in user mode */
1316     env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) |
1317         (eflags & FL_UPDATE_MASK32);
1318     if (eflags & IF_MASK) {
1319         env->eflags |= VIF_MASK;
1320         if (env->eflags & VIP_MASK) {
1321             EIP = PARAM1;
1322             raise_exception(EXCP0D_GPF);
1323         }
1324     }
1325     FORCE_RET();
1326 }
1327
1328 /* XXX: compute only O flag */
1329 void OPPROTO op_movb_eflags_T0(void)
1330 {
1331     int of;
1332     of = cc_table[CC_OP].compute_all() & CC_O;
1333     CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of;
1334 }
1335
1336 void OPPROTO op_movl_T0_eflags(void)
1337 {
1338     int eflags;
1339     eflags = cc_table[CC_OP].compute_all();
1340     eflags |= (DF & DF_MASK);
1341     eflags |= env->eflags & ~(VM_MASK | RF_MASK);
1342     T0 = eflags;
1343 }
1344
1345 /* vm86 version */
1346 void OPPROTO op_movl_T0_eflags_vm(void)
1347 {
1348     int eflags;
1349     eflags = cc_table[CC_OP].compute_all();
1350     eflags |= (DF & DF_MASK);
1351     eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK);
1352     if (env->eflags & VIF_MASK)
1353         eflags |= IF_MASK;
1354     T0 = eflags;
1355 }
1356
1357 void OPPROTO op_cld(void)
1358 {
1359     DF = 1;
1360 }
1361
1362 void OPPROTO op_std(void)
1363 {
1364     DF = -1;
1365 }
1366
1367 void OPPROTO op_clc(void)
1368 {
1369     int eflags;
1370     eflags = cc_table[CC_OP].compute_all();
1371     eflags &= ~CC_C;
1372     CC_SRC = eflags;
1373 }
1374
1375 void OPPROTO op_stc(void)
1376 {
1377     int eflags;
1378     eflags = cc_table[CC_OP].compute_all();
1379     eflags |= CC_C;
1380     CC_SRC = eflags;
1381 }
1382
1383 void OPPROTO op_cmc(void)
1384 {
1385     int eflags;
1386     eflags = cc_table[CC_OP].compute_all();
1387     eflags ^= CC_C;
1388     CC_SRC = eflags;
1389 }
1390
1391 void OPPROTO op_salc(void)
1392 {
1393     int cf;
1394     cf = cc_table[CC_OP].compute_c();
1395     EAX = (EAX & ~0xff) | ((-cf) & 0xff);
1396 }
1397
1398 static int compute_all_eflags(void)
1399 {
1400     return CC_SRC;
1401 }
1402
1403 static int compute_c_eflags(void)
1404 {
1405     return CC_SRC & CC_C;
1406 }
1407
1408 static int compute_c_mul(void)
1409 {
1410     int cf;
1411     cf = (CC_SRC != 0);
1412     return cf;
1413 }
1414
1415 static int compute_all_mul(void)
1416 {
1417     int cf, pf, af, zf, sf, of;
1418     cf = (CC_SRC != 0);
1419     pf = 0; /* undefined */
1420     af = 0; /* undefined */
1421     zf = 0; /* undefined */
1422     sf = 0; /* undefined */
1423     of = cf << 11;
1424     return cf | pf | af | zf | sf | of;
1425 }
1426     
1427 CCTable cc_table[CC_OP_NB] = {
1428     [CC_OP_DYNAMIC] = { /* should never happen */ },
1429
1430     [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
1431
1432     [CC_OP_MUL] = { compute_all_mul, compute_c_mul },
1433
1434     [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
1435     [CC_OP_ADDW] = { compute_all_addw, compute_c_addw  },
1436     [CC_OP_ADDL] = { compute_all_addl, compute_c_addl  },
1437
1438     [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
1439     [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw  },
1440     [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl  },
1441
1442     [CC_OP_SUBB] = { compute_all_subb, compute_c_subb  },
1443     [CC_OP_SUBW] = { compute_all_subw, compute_c_subw  },
1444     [CC_OP_SUBL] = { compute_all_subl, compute_c_subl  },
1445     
1446     [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb  },
1447     [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw  },
1448     [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl  },
1449     
1450     [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
1451     [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
1452     [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
1453     
1454     [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
1455     [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
1456     [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
1457     
1458     [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
1459     [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
1460     [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
1461     
1462     [CC_OP_SHLB] = { compute_all_shlb, compute_c_shll },
1463     [CC_OP_SHLW] = { compute_all_shlw, compute_c_shll },
1464     [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
1465
1466     [CC_OP_SARB] = { compute_all_sarb, compute_c_shll },
1467     [CC_OP_SARW] = { compute_all_sarw, compute_c_shll },
1468     [CC_OP_SARL] = { compute_all_sarl, compute_c_shll },
1469 };
1470
1471 /* floating point support. Some of the code for complicated x87
1472    functions comes from the LGPL'ed x86 emulator found in the Willows
1473    TWIN windows emulator. */
1474
1475 #ifdef USE_X86LDOUBLE
1476 /* use long double functions */
1477 #define lrint lrintl
1478 #define llrint llrintl
1479 #define fabs fabsl
1480 #define sin sinl
1481 #define cos cosl
1482 #define sqrt sqrtl
1483 #define pow powl
1484 #define log logl
1485 #define tan tanl
1486 #define atan2 atan2l
1487 #define floor floorl
1488 #define ceil ceill
1489 #define rint rintl
1490 #endif
1491
1492 extern int lrint(CPU86_LDouble x);
1493 extern int64_t llrint(CPU86_LDouble x);
1494 extern CPU86_LDouble fabs(CPU86_LDouble x);
1495 extern CPU86_LDouble sin(CPU86_LDouble x);
1496 extern CPU86_LDouble cos(CPU86_LDouble x);
1497 extern CPU86_LDouble sqrt(CPU86_LDouble x);
1498 extern CPU86_LDouble pow(CPU86_LDouble, CPU86_LDouble);
1499 extern CPU86_LDouble log(CPU86_LDouble x);
1500 extern CPU86_LDouble tan(CPU86_LDouble x);
1501 extern CPU86_LDouble atan2(CPU86_LDouble, CPU86_LDouble);
1502 extern CPU86_LDouble floor(CPU86_LDouble x);
1503 extern CPU86_LDouble ceil(CPU86_LDouble x);
1504 extern CPU86_LDouble rint(CPU86_LDouble x);
1505
1506 #define RC_MASK         0xc00
1507 #define RC_NEAR         0x000
1508 #define RC_DOWN         0x400
1509 #define RC_UP           0x800
1510 #define RC_CHOP         0xc00
1511
1512 #define MAXTAN 9223372036854775808.0
1513
1514 #ifdef USE_X86LDOUBLE
1515
1516 /* only for x86 */
1517 typedef union {
1518     long double d;
1519     struct {
1520         unsigned long long lower;
1521         unsigned short upper;
1522     } l;
1523 } CPU86_LDoubleU;
1524
1525 /* the following deal with x86 long double-precision numbers */
1526 #define MAXEXPD 0x7fff
1527 #define EXPBIAS 16383
1528 #define EXPD(fp)        (fp.l.upper & 0x7fff)
1529 #define SIGND(fp)       ((fp.l.upper) & 0x8000)
1530 #define MANTD(fp)       (fp.l.lower)
1531 #define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
1532
1533 #else
1534
1535 typedef union {
1536     double d;
1537 #ifndef WORDS_BIGENDIAN
1538     struct {
1539         unsigned long lower;
1540         long upper;
1541     } l;
1542 #else
1543     struct {
1544         long upper;
1545         unsigned long lower;
1546     } l;
1547 #endif
1548     long long ll;
1549 } CPU86_LDoubleU;
1550
1551 /* the following deal with IEEE double-precision numbers */
1552 #define MAXEXPD 0x7ff
1553 #define EXPBIAS 1023
1554 #define EXPD(fp)        (((fp.l.upper) >> 20) & 0x7FF)
1555 #define SIGND(fp)       ((fp.l.upper) & 0x80000000)
1556 #define MANTD(fp)       (fp.ll & ((1LL << 52) - 1))
1557 #define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20)
1558 #endif
1559
1560 /* fp load FT0 */
1561
1562 void OPPROTO op_flds_FT0_A0(void)
1563 {
1564     FT0 = ldfl((void *)A0);
1565 }
1566
1567 void OPPROTO op_fldl_FT0_A0(void)
1568 {
1569     FT0 = ldfq((void *)A0);
1570 }
1571
1572 /* helpers are needed to avoid static constant reference. XXX: find a better way */
1573 #ifdef USE_INT_TO_FLOAT_HELPERS
1574
1575 void helper_fild_FT0_A0(void)
1576 {
1577     FT0 = (CPU86_LDouble)ldsw((void *)A0);
1578 }
1579
1580 void helper_fildl_FT0_A0(void)
1581 {
1582     FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1583 }
1584
1585 void helper_fildll_FT0_A0(void)
1586 {
1587     FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1588 }
1589
1590 void OPPROTO op_fild_FT0_A0(void)
1591 {
1592     helper_fild_FT0_A0();
1593 }
1594
1595 void OPPROTO op_fildl_FT0_A0(void)
1596 {
1597     helper_fildl_FT0_A0();
1598 }
1599
1600 void OPPROTO op_fildll_FT0_A0(void)
1601 {
1602     helper_fildll_FT0_A0();
1603 }
1604
1605 #else
1606
1607 void OPPROTO op_fild_FT0_A0(void)
1608 {
1609     FT0 = (CPU86_LDouble)ldsw((void *)A0);
1610 }
1611
1612 void OPPROTO op_fildl_FT0_A0(void)
1613 {
1614     FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1615 }
1616
1617 void OPPROTO op_fildll_FT0_A0(void)
1618 {
1619     FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1620 }
1621 #endif
1622
1623 /* fp load ST0 */
1624
1625 void OPPROTO op_flds_ST0_A0(void)
1626 {
1627     ST0 = ldfl((void *)A0);
1628 }
1629
1630 void OPPROTO op_fldl_ST0_A0(void)
1631 {
1632     ST0 = ldfq((void *)A0);
1633 }
1634
1635 #ifdef USE_X86LDOUBLE
1636 void OPPROTO op_fldt_ST0_A0(void)
1637 {
1638     ST0 = *(long double *)A0;
1639 }
1640 #else
1641 void helper_fldt_ST0_A0(void)
1642 {
1643     CPU86_LDoubleU temp;
1644     int upper, e;
1645     /* mantissa */
1646     upper = lduw((uint8_t *)A0 + 8);
1647     /* XXX: handle overflow ? */
1648     e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
1649     e |= (upper >> 4) & 0x800; /* sign */
1650     temp.ll = ((ldq((void *)A0) >> 11) & ((1LL << 52) - 1)) | ((uint64_t)e << 52);
1651     ST0 = temp.d;
1652 }
1653
1654 void OPPROTO op_fldt_ST0_A0(void)
1655 {
1656     helper_fldt_ST0_A0();
1657 }
1658 #endif
1659
1660 /* helpers are needed to avoid static constant reference. XXX: find a better way */
1661 #ifdef USE_INT_TO_FLOAT_HELPERS
1662
1663 void helper_fild_ST0_A0(void)
1664 {
1665     ST0 = (CPU86_LDouble)ldsw((void *)A0);
1666 }
1667
1668 void helper_fildl_ST0_A0(void)
1669 {
1670     ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1671 }
1672
1673 void helper_fildll_ST0_A0(void)
1674 {
1675     ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1676 }
1677
1678 void OPPROTO op_fild_ST0_A0(void)
1679 {
1680     helper_fild_ST0_A0();
1681 }
1682
1683 void OPPROTO op_fildl_ST0_A0(void)
1684 {
1685     helper_fildl_ST0_A0();
1686 }
1687
1688 void OPPROTO op_fildll_ST0_A0(void)
1689 {
1690     helper_fildll_ST0_A0();
1691 }
1692
1693 #else
1694
1695 void OPPROTO op_fild_ST0_A0(void)
1696 {
1697     ST0 = (CPU86_LDouble)ldsw((void *)A0);
1698 }
1699
1700 void OPPROTO op_fildl_ST0_A0(void)
1701 {
1702     ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1703 }
1704
1705 void OPPROTO op_fildll_ST0_A0(void)
1706 {
1707     ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1708 }
1709
1710 #endif
1711
1712 /* fp store */
1713
1714 void OPPROTO op_fsts_ST0_A0(void)
1715 {
1716     stfl((void *)A0, (float)ST0);
1717 }
1718
1719 void OPPROTO op_fstl_ST0_A0(void)
1720 {
1721     stfq((void *)A0, (double)ST0);
1722 }
1723
1724 #ifdef USE_X86LDOUBLE
1725 void OPPROTO op_fstt_ST0_A0(void)
1726 {
1727     *(long double *)A0 = ST0;
1728 }
1729 #else
1730 void helper_fstt_ST0_A0(void)
1731 {
1732     CPU86_LDoubleU temp;
1733     int e;
1734     temp.d = ST0;
1735     /* mantissa */
1736     stq((void *)A0, (MANTD(temp) << 11) | (1LL << 63));
1737     /* exponent + sign */
1738     e = EXPD(temp) - EXPBIAS + 16383;
1739     e |= SIGND(temp) >> 16;
1740     stw((uint8_t *)A0 + 8, e);
1741 }
1742
1743 void OPPROTO op_fstt_ST0_A0(void)
1744 {
1745     helper_fstt_ST0_A0();
1746 }
1747 #endif
1748
1749 void OPPROTO op_fist_ST0_A0(void)
1750 {
1751     int val;
1752     val = lrint(ST0);
1753     stw((void *)A0, val);
1754 }
1755
1756 void OPPROTO op_fistl_ST0_A0(void)
1757 {
1758     int val;
1759     val = lrint(ST0);
1760     stl((void *)A0, val);
1761 }
1762
1763 void OPPROTO op_fistll_ST0_A0(void)
1764 {
1765     int64_t val;
1766     val = llrint(ST0);
1767     stq((void *)A0, val);
1768 }
1769
1770 /* BCD ops */
1771
1772 #define MUL10(iv) ( iv + iv + (iv << 3) )
1773
1774 void helper_fbld_ST0_A0(void)
1775 {
1776     uint8_t *seg;
1777     CPU86_LDouble fpsrcop;
1778     int m32i;
1779     unsigned int v;
1780
1781     /* in this code, seg/m32i will be used as temporary ptr/int */
1782     seg = (uint8_t *)A0 + 8;
1783     v = ldub(seg--);
1784     /* XXX: raise exception */
1785     if (v != 0)
1786         return;
1787     v = ldub(seg--);
1788     /* XXX: raise exception */
1789     if ((v & 0xf0) != 0)
1790         return;
1791     m32i = v;  /* <-- d14 */
1792     v = ldub(seg--);
1793     m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d13 */
1794     m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d12 */
1795     v = ldub(seg--);
1796     m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d11 */
1797     m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d10 */
1798     v = ldub(seg--);
1799     m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d9 */
1800     m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d8 */
1801     fpsrcop = ((CPU86_LDouble)m32i) * 100000000.0;
1802
1803     v = ldub(seg--);
1804     m32i = (v >> 4);  /* <-- d7 */
1805     m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d6 */
1806     v = ldub(seg--);
1807     m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d5 */
1808     m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d4 */
1809     v = ldub(seg--);
1810     m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d3 */
1811     m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d2 */
1812     v = ldub(seg);
1813     m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d1 */
1814     m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d0 */
1815     fpsrcop += ((CPU86_LDouble)m32i);
1816     if ( ldub(seg+9) & 0x80 )
1817         fpsrcop = -fpsrcop;
1818     ST0 = fpsrcop;
1819 }
1820
1821 void OPPROTO op_fbld_ST0_A0(void)
1822 {
1823     helper_fbld_ST0_A0();
1824 }
1825
1826 void helper_fbst_ST0_A0(void)
1827 {
1828     CPU86_LDouble fptemp;
1829     CPU86_LDouble fpsrcop;
1830     int v;
1831     uint8_t *mem_ref, *mem_end;
1832
1833     fpsrcop = rint(ST0);
1834     mem_ref = (uint8_t *)A0;
1835     mem_end = mem_ref + 8;
1836     if ( fpsrcop < 0.0 ) {
1837         stw(mem_end, 0x8000);
1838         fpsrcop = -fpsrcop;
1839     } else {
1840         stw(mem_end, 0x0000);
1841     }
1842     while (mem_ref < mem_end) {
1843         if (fpsrcop == 0.0)
1844             break;
1845         fptemp = floor(fpsrcop/10.0);
1846         v = ((int)(fpsrcop - fptemp*10.0));
1847         if  (fptemp == 0.0)  { 
1848             stb(mem_ref++, v); 
1849             break; 
1850         }
1851         fpsrcop = fptemp;
1852         fptemp = floor(fpsrcop/10.0);
1853         v |= (((int)(fpsrcop - fptemp*10.0)) << 4);
1854         stb(mem_ref++, v);
1855         fpsrcop = fptemp;
1856     }
1857     while (mem_ref < mem_end) {
1858         stb(mem_ref++, 0);
1859     }
1860 }
1861
1862 void OPPROTO op_fbst_ST0_A0(void)
1863 {
1864     helper_fbst_ST0_A0();
1865 }
1866
1867 /* FPU move */
1868
1869 static inline void fpush(void)
1870 {
1871     env->fpstt = (env->fpstt - 1) & 7;
1872     env->fptags[env->fpstt] = 0; /* validate stack entry */
1873 }
1874
1875 static inline void fpop(void)
1876 {
1877     env->fptags[env->fpstt] = 1; /* invvalidate stack entry */
1878     env->fpstt = (env->fpstt + 1) & 7;
1879 }
1880
1881 void OPPROTO op_fpush(void)
1882 {
1883     fpush();
1884 }
1885
1886 void OPPROTO op_fpop(void)
1887 {
1888     fpop();
1889 }
1890
1891 void OPPROTO op_fdecstp(void)
1892 {
1893     env->fpstt = (env->fpstt - 1) & 7;
1894     env->fpus &= (~0x4700);
1895 }
1896
1897 void OPPROTO op_fincstp(void)
1898 {
1899     env->fpstt = (env->fpstt + 1) & 7;
1900     env->fpus &= (~0x4700);
1901 }
1902
1903 void OPPROTO op_fmov_ST0_FT0(void)
1904 {
1905     ST0 = FT0;
1906 }
1907
1908 void OPPROTO op_fmov_FT0_STN(void)
1909 {
1910     FT0 = ST(PARAM1);
1911 }
1912
1913 void OPPROTO op_fmov_ST0_STN(void)
1914 {
1915     ST0 = ST(PARAM1);
1916 }
1917
1918 void OPPROTO op_fmov_STN_ST0(void)
1919 {
1920     ST(PARAM1) = ST0;
1921 }
1922
1923 void OPPROTO op_fxchg_ST0_STN(void)
1924 {
1925     CPU86_LDouble tmp;
1926     tmp = ST(PARAM1);
1927     ST(PARAM1) = ST0;
1928     ST0 = tmp;
1929 }
1930
1931 /* FPU operations */
1932
1933 /* XXX: handle nans */
1934 void OPPROTO op_fcom_ST0_FT0(void)
1935 {
1936     env->fpus &= (~0x4500);     /* (C3,C2,C0) <-- 000 */
1937     if (ST0 < FT0)
1938         env->fpus |= 0x100;     /* (C3,C2,C0) <-- 001 */
1939     else if (ST0 == FT0)
1940         env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
1941     FORCE_RET();
1942 }
1943
1944 /* XXX: handle nans */
1945 void OPPROTO op_fucom_ST0_FT0(void)
1946 {
1947     env->fpus &= (~0x4500);     /* (C3,C2,C0) <-- 000 */
1948     if (ST0 < FT0)
1949         env->fpus |= 0x100;     /* (C3,C2,C0) <-- 001 */
1950     else if (ST0 == FT0)
1951         env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
1952     FORCE_RET();
1953 }
1954
1955 void OPPROTO op_fadd_ST0_FT0(void)
1956 {
1957     ST0 += FT0;
1958 }
1959
1960 void OPPROTO op_fmul_ST0_FT0(void)
1961 {
1962     ST0 *= FT0;
1963 }
1964
1965 void OPPROTO op_fsub_ST0_FT0(void)
1966 {
1967     ST0 -= FT0;
1968 }
1969
1970 void OPPROTO op_fsubr_ST0_FT0(void)
1971 {
1972     ST0 = FT0 - ST0;
1973 }
1974
1975 void OPPROTO op_fdiv_ST0_FT0(void)
1976 {
1977     ST0 /= FT0;
1978 }
1979
1980 void OPPROTO op_fdivr_ST0_FT0(void)
1981 {
1982     ST0 = FT0 / ST0;
1983 }
1984
1985 /* fp operations between STN and ST0 */
1986
1987 void OPPROTO op_fadd_STN_ST0(void)
1988 {
1989     ST(PARAM1) += ST0;
1990 }
1991
1992 void OPPROTO op_fmul_STN_ST0(void)
1993 {
1994     ST(PARAM1) *= ST0;
1995 }
1996
1997 void OPPROTO op_fsub_STN_ST0(void)
1998 {
1999     ST(PARAM1) -= ST0;
2000 }
2001
2002 void OPPROTO op_fsubr_STN_ST0(void)
2003 {
2004     CPU86_LDouble *p;
2005     p = &ST(PARAM1);
2006     *p = ST0 - *p;
2007 }
2008
2009 void OPPROTO op_fdiv_STN_ST0(void)
2010 {
2011     ST(PARAM1) /= ST0;
2012 }
2013
2014 void OPPROTO op_fdivr_STN_ST0(void)
2015 {
2016     CPU86_LDouble *p;
2017     p = &ST(PARAM1);
2018     *p = ST0 / *p;
2019 }
2020
2021 /* misc FPU operations */
2022 void OPPROTO op_fchs_ST0(void)
2023 {
2024     ST0 = -ST0;
2025 }
2026
2027 void OPPROTO op_fabs_ST0(void)
2028 {
2029     ST0 = fabs(ST0);
2030 }
2031
2032 void helper_fxam_ST0(void)
2033 {
2034     CPU86_LDoubleU temp;
2035     int expdif;
2036
2037     temp.d = ST0;
2038
2039     env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
2040     if (SIGND(temp))
2041         env->fpus |= 0x200; /* C1 <-- 1 */
2042
2043     expdif = EXPD(temp);
2044     if (expdif == MAXEXPD) {
2045         if (MANTD(temp) == 0)
2046             env->fpus |=  0x500 /*Infinity*/;
2047         else
2048             env->fpus |=  0x100 /*NaN*/;
2049     } else if (expdif == 0) {
2050         if (MANTD(temp) == 0)
2051             env->fpus |=  0x4000 /*Zero*/;
2052         else
2053             env->fpus |= 0x4400 /*Denormal*/;
2054     } else {
2055         env->fpus |= 0x400;
2056     }
2057 }
2058
2059 void OPPROTO op_fxam_ST0(void)
2060 {
2061     helper_fxam_ST0();
2062 }
2063
2064 void OPPROTO op_fld1_ST0(void)
2065 {
2066     ST0 = *(CPU86_LDouble *)&f15rk[1];
2067 }
2068
2069 void OPPROTO op_fldl2t_ST0(void)
2070 {
2071     ST0 = *(CPU86_LDouble *)&f15rk[6];
2072 }
2073
2074 void OPPROTO op_fldl2e_ST0(void)
2075 {
2076     ST0 = *(CPU86_LDouble *)&f15rk[5];
2077 }
2078
2079 void OPPROTO op_fldpi_ST0(void)
2080 {
2081     ST0 = *(CPU86_LDouble *)&f15rk[2];
2082 }
2083
2084 void OPPROTO op_fldlg2_ST0(void)
2085 {
2086     ST0 = *(CPU86_LDouble *)&f15rk[3];
2087 }
2088
2089 void OPPROTO op_fldln2_ST0(void)
2090 {
2091     ST0 = *(CPU86_LDouble *)&f15rk[4];
2092 }
2093
2094 void OPPROTO op_fldz_ST0(void)
2095 {
2096     ST0 = *(CPU86_LDouble *)&f15rk[0];
2097 }
2098
2099 void OPPROTO op_fldz_FT0(void)
2100 {
2101     ST0 = *(CPU86_LDouble *)&f15rk[0];
2102 }
2103
2104 void helper_f2xm1(void)
2105 {
2106     ST0 = pow(2.0,ST0) - 1.0;
2107 }
2108
2109 void helper_fyl2x(void)
2110 {
2111     CPU86_LDouble fptemp;
2112     
2113     fptemp = ST0;
2114     if (fptemp>0.0){
2115         fptemp = log(fptemp)/log(2.0);   /* log2(ST) */
2116         ST1 *= fptemp;
2117         fpop();
2118     } else { 
2119         env->fpus &= (~0x4700);
2120         env->fpus |= 0x400;
2121     }
2122 }
2123
2124 void helper_fptan(void)
2125 {
2126     CPU86_LDouble fptemp;
2127
2128     fptemp = ST0;
2129     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2130         env->fpus |= 0x400;
2131     } else {
2132         ST0 = tan(fptemp);
2133         fpush();
2134         ST0 = 1.0;
2135         env->fpus &= (~0x400);  /* C2 <-- 0 */
2136         /* the above code is for  |arg| < 2**52 only */
2137     }
2138 }
2139
2140 void helper_fpatan(void)
2141 {
2142     CPU86_LDouble fptemp, fpsrcop;
2143
2144     fpsrcop = ST1;
2145     fptemp = ST0;
2146     ST1 = atan2(fpsrcop,fptemp);
2147     fpop();
2148 }
2149
2150 void helper_fxtract(void)
2151 {
2152     CPU86_LDoubleU temp;
2153     unsigned int expdif;
2154
2155     temp.d = ST0;
2156     expdif = EXPD(temp) - EXPBIAS;
2157     /*DP exponent bias*/
2158     ST0 = expdif;
2159     fpush();
2160     BIASEXPONENT(temp);
2161     ST0 = temp.d;
2162 }
2163
2164 void helper_fprem1(void)
2165 {
2166     CPU86_LDouble dblq, fpsrcop, fptemp;
2167     CPU86_LDoubleU fpsrcop1, fptemp1;
2168     int expdif;
2169     int q;
2170
2171     fpsrcop = ST0;
2172     fptemp = ST1;
2173     fpsrcop1.d = fpsrcop;
2174     fptemp1.d = fptemp;
2175     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
2176     if (expdif < 53) {
2177         dblq = fpsrcop / fptemp;
2178         dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
2179         ST0 = fpsrcop - fptemp*dblq;
2180         q = (int)dblq; /* cutting off top bits is assumed here */
2181         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
2182                                 /* (C0,C1,C3) <-- (q2,q1,q0) */
2183         env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
2184         env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
2185         env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
2186     } else {
2187         env->fpus |= 0x400;  /* C2 <-- 1 */
2188         fptemp = pow(2.0, expdif-50);
2189         fpsrcop = (ST0 / ST1) / fptemp;
2190         /* fpsrcop = integer obtained by rounding to the nearest */
2191         fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
2192             floor(fpsrcop): ceil(fpsrcop);
2193         ST0 -= (ST1 * fpsrcop * fptemp);
2194     }
2195 }
2196
2197 void helper_fprem(void)
2198 {
2199     CPU86_LDouble dblq, fpsrcop, fptemp;
2200     CPU86_LDoubleU fpsrcop1, fptemp1;
2201     int expdif;
2202     int q;
2203     
2204     fpsrcop = ST0;
2205     fptemp = ST1;
2206     fpsrcop1.d = fpsrcop;
2207     fptemp1.d = fptemp;
2208     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
2209     if ( expdif < 53 ) {
2210         dblq = fpsrcop / fptemp;
2211         dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
2212         ST0 = fpsrcop - fptemp*dblq;
2213         q = (int)dblq; /* cutting off top bits is assumed here */
2214         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
2215                                 /* (C0,C1,C3) <-- (q2,q1,q0) */
2216         env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
2217         env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
2218         env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
2219     } else {
2220         env->fpus |= 0x400;  /* C2 <-- 1 */
2221         fptemp = pow(2.0, expdif-50);
2222         fpsrcop = (ST0 / ST1) / fptemp;
2223         /* fpsrcop = integer obtained by chopping */
2224         fpsrcop = (fpsrcop < 0.0)?
2225             -(floor(fabs(fpsrcop))): floor(fpsrcop);
2226         ST0 -= (ST1 * fpsrcop * fptemp);
2227     }
2228 }
2229
2230 void helper_fyl2xp1(void)
2231 {
2232     CPU86_LDouble fptemp;
2233
2234     fptemp = ST0;
2235     if ((fptemp+1.0)>0.0) {
2236         fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
2237         ST1 *= fptemp;
2238         fpop();
2239     } else { 
2240         env->fpus &= (~0x4700);
2241         env->fpus |= 0x400;
2242     }
2243 }
2244
2245 void helper_fsqrt(void)
2246 {
2247     CPU86_LDouble fptemp;
2248
2249     fptemp = ST0;
2250     if (fptemp<0.0) { 
2251         env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
2252         env->fpus |= 0x400;
2253     }
2254     ST0 = sqrt(fptemp);
2255 }
2256
2257 void helper_fsincos(void)
2258 {
2259     CPU86_LDouble fptemp;
2260
2261     fptemp = ST0;
2262     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2263         env->fpus |= 0x400;
2264     } else {
2265         ST0 = sin(fptemp);
2266         fpush();
2267         ST0 = cos(fptemp);
2268         env->fpus &= (~0x400);  /* C2 <-- 0 */
2269         /* the above code is for  |arg| < 2**63 only */
2270     }
2271 }
2272
2273 void helper_frndint(void)
2274 {
2275     ST0 = rint(ST0);
2276 }
2277
2278 void helper_fscale(void)
2279 {
2280     CPU86_LDouble fpsrcop, fptemp;
2281
2282     fpsrcop = 2.0;
2283     fptemp = pow(fpsrcop,ST1);
2284     ST0 *= fptemp;
2285 }
2286
2287 void helper_fsin(void)
2288 {
2289     CPU86_LDouble fptemp;
2290
2291     fptemp = ST0;
2292     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2293         env->fpus |= 0x400;
2294     } else {
2295         ST0 = sin(fptemp);
2296         env->fpus &= (~0x400);  /* C2 <-- 0 */
2297         /* the above code is for  |arg| < 2**53 only */
2298     }
2299 }
2300
2301 void helper_fcos(void)
2302 {
2303     CPU86_LDouble fptemp;
2304
2305     fptemp = ST0;
2306     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2307         env->fpus |= 0x400;
2308     } else {
2309         ST0 = cos(fptemp);
2310         env->fpus &= (~0x400);  /* C2 <-- 0 */
2311         /* the above code is for  |arg5 < 2**63 only */
2312     }
2313 }
2314
2315 /* associated heplers to reduce generated code length and to simplify
2316    relocation (FP constants are usually stored in .rodata section) */
2317
2318 void OPPROTO op_f2xm1(void)
2319 {
2320     helper_f2xm1();
2321 }
2322
2323 void OPPROTO op_fyl2x(void)
2324 {
2325     helper_fyl2x();
2326 }
2327
2328 void OPPROTO op_fptan(void)
2329 {
2330     helper_fptan();
2331 }
2332
2333 void OPPROTO op_fpatan(void)
2334 {
2335     helper_fpatan();
2336 }
2337
2338 void OPPROTO op_fxtract(void)
2339 {
2340     helper_fxtract();
2341 }
2342
2343 void OPPROTO op_fprem1(void)
2344 {
2345     helper_fprem1();
2346 }
2347
2348
2349 void OPPROTO op_fprem(void)
2350 {
2351     helper_fprem();
2352 }
2353
2354 void OPPROTO op_fyl2xp1(void)
2355 {
2356     helper_fyl2xp1();
2357 }
2358
2359 void OPPROTO op_fsqrt(void)
2360 {
2361     helper_fsqrt();
2362 }
2363
2364 void OPPROTO op_fsincos(void)
2365 {
2366     helper_fsincos();
2367 }
2368
2369 void OPPROTO op_frndint(void)
2370 {
2371     helper_frndint();
2372 }
2373
2374 void OPPROTO op_fscale(void)
2375 {
2376     helper_fscale();
2377 }
2378
2379 void OPPROTO op_fsin(void)
2380 {
2381     helper_fsin();
2382 }
2383
2384 void OPPROTO op_fcos(void)
2385 {
2386     helper_fcos();
2387 }
2388
2389 void OPPROTO op_fnstsw_A0(void)
2390 {
2391     int fpus;
2392     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2393     stw((void *)A0, fpus);
2394 }
2395
2396 void OPPROTO op_fnstsw_EAX(void)
2397 {
2398     int fpus;
2399     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2400     EAX = (EAX & 0xffff0000) | fpus;
2401 }
2402
2403 void OPPROTO op_fnstcw_A0(void)
2404 {
2405     stw((void *)A0, env->fpuc);
2406 }
2407
2408 void OPPROTO op_fldcw_A0(void)
2409 {
2410     int rnd_type;
2411     env->fpuc = lduw((void *)A0);
2412     /* set rounding mode */
2413     switch(env->fpuc & RC_MASK) {
2414     default:
2415     case RC_NEAR:
2416         rnd_type = FE_TONEAREST;
2417         break;
2418     case RC_DOWN:
2419         rnd_type = FE_DOWNWARD;
2420         break;
2421     case RC_UP:
2422         rnd_type = FE_UPWARD;
2423         break;
2424     case RC_CHOP:
2425         rnd_type = FE_TOWARDZERO;
2426         break;
2427     }
2428     fesetround(rnd_type);
2429 }
2430
2431 void OPPROTO op_fclex(void)
2432 {
2433     env->fpus &= 0x7f00;
2434 }
2435
2436 void OPPROTO op_fninit(void)
2437 {
2438     env->fpus = 0;
2439     env->fpstt = 0;
2440     env->fpuc = 0x37f;
2441     env->fptags[0] = 1;
2442     env->fptags[1] = 1;
2443     env->fptags[2] = 1;
2444     env->fptags[3] = 1;
2445     env->fptags[4] = 1;
2446     env->fptags[5] = 1;
2447     env->fptags[6] = 1;
2448     env->fptags[7] = 1;
2449 }
2450
2451 /* threading support */
2452 void OPPROTO op_lock(void)
2453 {
2454     cpu_lock();
2455 }
2456
2457 void OPPROTO op_unlock(void)
2458 {
2459     cpu_unlock();
2460 }