more precise float rounding tests
[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 uint8_t parity_table[256] = {
23     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
24     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
25     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
26     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
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     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
30     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
31     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
32     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
33     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
34     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
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     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
38     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
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     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
42     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
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     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
46     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
47     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
48     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
49     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
50     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
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     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
54     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
55 };
56
57 /* modulo 17 table */
58 const uint8_t rclw_table[32] = {
59     0, 1, 2, 3, 4, 5, 6, 7, 
60     8, 9,10,11,12,13,14,15,
61    16, 0, 1, 2, 3, 4, 5, 6,
62     7, 8, 9,10,11,12,13,14,
63 };
64
65 /* modulo 9 table */
66 const uint8_t rclb_table[32] = {
67     0, 1, 2, 3, 4, 5, 6, 7, 
68     8, 0, 1, 2, 3, 4, 5, 6,
69     7, 8, 0, 1, 2, 3, 4, 5, 
70     6, 7, 8, 0, 1, 2, 3, 4,
71 };
72
73 /* n must be a constant to be efficient */
74 static inline int lshift(int x, int n)
75 {
76     if (n >= 0)
77         return x << n;
78     else
79         return x >> (-n);
80 }
81
82 /* we define the various pieces of code used by the JIT */
83
84 #define REG EAX
85 #define REGNAME _EAX
86 #include "opreg_template.h"
87 #undef REG
88 #undef REGNAME
89
90 #define REG ECX
91 #define REGNAME _ECX
92 #include "opreg_template.h"
93 #undef REG
94 #undef REGNAME
95
96 #define REG EDX
97 #define REGNAME _EDX
98 #include "opreg_template.h"
99 #undef REG
100 #undef REGNAME
101
102 #define REG EBX
103 #define REGNAME _EBX
104 #include "opreg_template.h"
105 #undef REG
106 #undef REGNAME
107
108 #define REG ESP
109 #define REGNAME _ESP
110 #include "opreg_template.h"
111 #undef REG
112 #undef REGNAME
113
114 #define REG EBP
115 #define REGNAME _EBP
116 #include "opreg_template.h"
117 #undef REG
118 #undef REGNAME
119
120 #define REG ESI
121 #define REGNAME _ESI
122 #include "opreg_template.h"
123 #undef REG
124 #undef REGNAME
125
126 #define REG EDI
127 #define REGNAME _EDI
128 #include "opreg_template.h"
129 #undef REG
130 #undef REGNAME
131
132 /* operations with flags */
133
134 void OPPROTO op_addl_T0_T1_cc(void)
135 {
136     CC_SRC = T0;
137     T0 += T1;
138     CC_DST = T0;
139 }
140
141 void OPPROTO op_orl_T0_T1_cc(void)
142 {
143     T0 |= T1;
144     CC_DST = T0;
145 }
146
147 void OPPROTO op_andl_T0_T1_cc(void)
148 {
149     T0 &= T1;
150     CC_DST = T0;
151 }
152
153 void OPPROTO op_subl_T0_T1_cc(void)
154 {
155     CC_SRC = T0;
156     T0 -= T1;
157     CC_DST = T0;
158 }
159
160 void OPPROTO op_xorl_T0_T1_cc(void)
161 {
162     T0 ^= T1;
163     CC_DST = T0;
164 }
165
166 void OPPROTO op_cmpl_T0_T1_cc(void)
167 {
168     CC_SRC = T0;
169     CC_DST = T0 - T1;
170 }
171
172 void OPPROTO op_negl_T0_cc(void)
173 {
174     CC_SRC = 0;
175     T0 = -T0;
176     CC_DST = T0;
177 }
178
179 void OPPROTO op_incl_T0_cc(void)
180 {
181     CC_SRC = cc_table[CC_OP].compute_c();
182     T0++;
183     CC_DST = T0;
184 }
185
186 void OPPROTO op_decl_T0_cc(void)
187 {
188     CC_SRC = cc_table[CC_OP].compute_c();
189     T0--;
190     CC_DST = T0;
191 }
192
193 void OPPROTO op_testl_T0_T1_cc(void)
194 {
195     CC_DST = T0 & T1;
196 }
197
198 /* operations without flags */
199
200 void OPPROTO op_addl_T0_T1(void)
201 {
202     T0 += T1;
203 }
204
205 void OPPROTO op_orl_T0_T1(void)
206 {
207     T0 |= T1;
208 }
209
210 void OPPROTO op_andl_T0_T1(void)
211 {
212     T0 &= T1;
213 }
214
215 void OPPROTO op_subl_T0_T1(void)
216 {
217     T0 -= T1;
218 }
219
220 void OPPROTO op_xorl_T0_T1(void)
221 {
222     T0 ^= T1;
223 }
224
225 void OPPROTO op_negl_T0(void)
226 {
227     T0 = -T0;
228 }
229
230 void OPPROTO op_incl_T0(void)
231 {
232     T0++;
233 }
234
235 void OPPROTO op_decl_T0(void)
236 {
237     T0--;
238 }
239
240 void OPPROTO op_notl_T0(void)
241 {
242     T0 = ~T0;
243 }
244
245 void OPPROTO op_bswapl_T0(void)
246 {
247     T0 = bswap32(T0);
248 }
249
250 /* multiply/divide */
251 void OPPROTO op_mulb_AL_T0(void)
252 {
253     unsigned int res;
254     res = (uint8_t)EAX * (uint8_t)T0;
255     EAX = (EAX & 0xffff0000) | res;
256     CC_SRC = (res & 0xff00);
257 }
258
259 void OPPROTO op_imulb_AL_T0(void)
260 {
261     int res;
262     res = (int8_t)EAX * (int8_t)T0;
263     EAX = (EAX & 0xffff0000) | (res & 0xffff);
264     CC_SRC = (res != (int8_t)res);
265 }
266
267 void OPPROTO op_mulw_AX_T0(void)
268 {
269     unsigned int res;
270     res = (uint16_t)EAX * (uint16_t)T0;
271     EAX = (EAX & 0xffff0000) | (res & 0xffff);
272     EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff);
273     CC_SRC = res >> 16;
274 }
275
276 void OPPROTO op_imulw_AX_T0(void)
277 {
278     int res;
279     res = (int16_t)EAX * (int16_t)T0;
280     EAX = (EAX & 0xffff0000) | (res & 0xffff);
281     EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff);
282     CC_SRC = (res != (int16_t)res);
283 }
284
285 void OPPROTO op_mull_EAX_T0(void)
286 {
287     uint64_t res;
288     res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0);
289     EAX = res;
290     EDX = res >> 32;
291     CC_SRC = res >> 32;
292 }
293
294 void OPPROTO op_imull_EAX_T0(void)
295 {
296     int64_t res;
297     res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T0);
298     EAX = res;
299     EDX = res >> 32;
300     CC_SRC = (res != (int32_t)res);
301 }
302
303 void OPPROTO op_imulw_T0_T1(void)
304 {
305     int res;
306     res = (int16_t)T0 * (int16_t)T1;
307     T0 = res;
308     CC_SRC = (res != (int16_t)res);
309 }
310
311 void OPPROTO op_imull_T0_T1(void)
312 {
313     int64_t res;
314     res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
315     T0 = res;
316     CC_SRC = (res != (int32_t)res);
317 }
318
319 /* division, flags are undefined */
320 /* XXX: add exceptions for overflow */
321
322 void OPPROTO op_divb_AL_T0(void)
323 {
324     unsigned int num, den, q, r;
325
326     num = (EAX & 0xffff);
327     den = (T0 & 0xff);
328     if (den == 0) {
329         EIP = PARAM1;
330         raise_exception(EXCP00_DIVZ);
331     }
332     q = (num / den) & 0xff;
333     r = (num % den) & 0xff;
334     EAX = (EAX & 0xffff0000) | (r << 8) | q;
335 }
336
337 void OPPROTO op_idivb_AL_T0(void)
338 {
339     int num, den, q, r;
340
341     num = (int16_t)EAX;
342     den = (int8_t)T0;
343     if (den == 0) {
344         EIP = PARAM1;
345         raise_exception(EXCP00_DIVZ);
346     }
347     q = (num / den) & 0xff;
348     r = (num % den) & 0xff;
349     EAX = (EAX & 0xffff0000) | (r << 8) | q;
350 }
351
352 void OPPROTO op_divw_AX_T0(void)
353 {
354     unsigned int num, den, q, r;
355
356     num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
357     den = (T0 & 0xffff);
358     if (den == 0) {
359         EIP = PARAM1;
360         raise_exception(EXCP00_DIVZ);
361     }
362     q = (num / den) & 0xffff;
363     r = (num % den) & 0xffff;
364     EAX = (EAX & 0xffff0000) | q;
365     EDX = (EDX & 0xffff0000) | r;
366 }
367
368 void OPPROTO op_idivw_AX_T0(void)
369 {
370     int num, den, q, r;
371
372     num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
373     den = (int16_t)T0;
374     if (den == 0) {
375         EIP = PARAM1;
376         raise_exception(EXCP00_DIVZ);
377     }
378     q = (num / den) & 0xffff;
379     r = (num % den) & 0xffff;
380     EAX = (EAX & 0xffff0000) | q;
381     EDX = (EDX & 0xffff0000) | r;
382 }
383
384 void OPPROTO op_divl_EAX_T0(void)
385 {
386     helper_divl_EAX_T0(PARAM1);
387 }
388
389 void OPPROTO op_idivl_EAX_T0(void)
390 {
391     helper_idivl_EAX_T0(PARAM1);
392 }
393
394 /* constant load & misc op */
395
396 void OPPROTO op_movl_T0_im(void)
397 {
398     T0 = PARAM1;
399 }
400
401 void OPPROTO op_addl_T0_im(void)
402 {
403     T0 += PARAM1;
404 }
405
406 void OPPROTO op_andl_T0_ffff(void)
407 {
408     T0 = T0 & 0xffff;
409 }
410
411 void OPPROTO op_movl_T0_T1(void)
412 {
413     T0 = T1;
414 }
415
416 void OPPROTO op_movl_T1_im(void)
417 {
418     T1 = PARAM1;
419 }
420
421 void OPPROTO op_addl_T1_im(void)
422 {
423     T1 += PARAM1;
424 }
425
426 void OPPROTO op_movl_T1_A0(void)
427 {
428     T1 = A0;
429 }
430
431 void OPPROTO op_movl_A0_im(void)
432 {
433     A0 = PARAM1;
434 }
435
436 void OPPROTO op_addl_A0_im(void)
437 {
438     A0 += PARAM1;
439 }
440
441 void OPPROTO op_addl_A0_AL(void)
442 {
443     A0 += (EAX & 0xff);
444 }
445
446 void OPPROTO op_andl_A0_ffff(void)
447 {
448     A0 = A0 & 0xffff;
449 }
450
451 /* memory access */
452
453 void OPPROTO op_ldub_T0_A0(void)
454 {
455     T0 = ldub((uint8_t *)A0);
456 }
457
458 void OPPROTO op_ldsb_T0_A0(void)
459 {
460     T0 = ldsb((int8_t *)A0);
461 }
462
463 void OPPROTO op_lduw_T0_A0(void)
464 {
465     T0 = lduw((uint8_t *)A0);
466 }
467
468 void OPPROTO op_ldsw_T0_A0(void)
469 {
470     T0 = ldsw((int8_t *)A0);
471 }
472
473 void OPPROTO op_ldl_T0_A0(void)
474 {
475     T0 = ldl((uint8_t *)A0);
476 }
477
478 void OPPROTO op_ldub_T1_A0(void)
479 {
480     T1 = ldub((uint8_t *)A0);
481 }
482
483 void OPPROTO op_ldsb_T1_A0(void)
484 {
485     T1 = ldsb((int8_t *)A0);
486 }
487
488 void OPPROTO op_lduw_T1_A0(void)
489 {
490     T1 = lduw((uint8_t *)A0);
491 }
492
493 void OPPROTO op_ldsw_T1_A0(void)
494 {
495     T1 = ldsw((int8_t *)A0);
496 }
497
498 void OPPROTO op_ldl_T1_A0(void)
499 {
500     T1 = ldl((uint8_t *)A0);
501 }
502
503 void OPPROTO op_stb_T0_A0(void)
504 {
505     stb((uint8_t *)A0, T0);
506 }
507
508 void OPPROTO op_stw_T0_A0(void)
509 {
510     stw((uint8_t *)A0, T0);
511 }
512
513 void OPPROTO op_stl_T0_A0(void)
514 {
515     stl((uint8_t *)A0, T0);
516 }
517
518 /* used for bit operations */
519
520 void OPPROTO op_add_bitw_A0_T1(void)
521 {
522     A0 += ((int32_t)T1 >> 4) << 1;
523 }
524
525 void OPPROTO op_add_bitl_A0_T1(void)
526 {
527     A0 += ((int32_t)T1 >> 5) << 2;
528 }
529
530 /* indirect jump */
531
532 void OPPROTO op_jmp_T0(void)
533 {
534     EIP = T0;
535 }
536
537 void OPPROTO op_jmp_im(void)
538 {
539     EIP = PARAM1;
540 }
541
542 void OPPROTO op_raise_interrupt(void)
543 {
544     int intno;
545     unsigned int next_eip;
546     intno = PARAM1;
547     next_eip = PARAM2;
548     raise_interrupt(intno, 1, 0, next_eip);
549 }
550
551 void OPPROTO op_raise_exception(void)
552 {
553     int exception_index;
554     exception_index = PARAM1;
555     raise_exception(exception_index);
556 }
557
558 void OPPROTO op_into(void)
559 {
560     int eflags;
561     eflags = cc_table[CC_OP].compute_all();
562     if (eflags & CC_O) {
563         raise_interrupt(EXCP04_INTO, 1, 0, PARAM1);
564     }
565     FORCE_RET();
566 }
567
568 void OPPROTO op_cli(void)
569 {
570     env->eflags &= ~IF_MASK;
571 }
572
573 void OPPROTO op_sti(void)
574 {
575     env->eflags |= IF_MASK;
576 }
577
578 #if 0
579 /* vm86plus instructions */
580 void OPPROTO op_cli_vm(void)
581 {
582     env->eflags &= ~VIF_MASK;
583 }
584
585 void OPPROTO op_sti_vm(void)
586 {
587     env->eflags |= VIF_MASK;
588     if (env->eflags & VIP_MASK) {
589         EIP = PARAM1;
590         raise_exception(EXCP0D_GPF);
591     }
592     FORCE_RET();
593 }
594 #endif
595
596 void OPPROTO op_boundw(void)
597 {
598     int low, high, v;
599     low = ldsw((uint8_t *)A0);
600     high = ldsw((uint8_t *)A0 + 2);
601     v = (int16_t)T0;
602     if (v < low || v > high) {
603         EIP = PARAM1;
604         raise_exception(EXCP05_BOUND);
605     }
606     FORCE_RET();
607 }
608
609 void OPPROTO op_boundl(void)
610 {
611     int low, high, v;
612     low = ldl((uint8_t *)A0);
613     high = ldl((uint8_t *)A0 + 4);
614     v = T0;
615     if (v < low || v > high) {
616         EIP = PARAM1;
617         raise_exception(EXCP05_BOUND);
618     }
619     FORCE_RET();
620 }
621
622 void OPPROTO op_cmpxchg8b(void)
623 {
624     helper_cmpxchg8b();
625 }
626
627 #if defined(__powerpc__)
628
629 /* on PowerPC we patch the jump instruction directly */
630 #define JUMP_TB(tbparam, n, eip)\
631 do {\
632     static void __attribute__((unused)) *__op_label ## n = &&label ## n;\
633     asm volatile ("b %0" : : "i" (&__op_jmp ## n));\
634 label ## n:\
635     T0 = (long)(tbparam) + (n);\
636     EIP = eip;\
637 } while (0)
638
639 #else
640
641 /* jump to next block operations (more portable code, does not need
642    cache flushing, but slower because of indirect jump) */
643 #define JUMP_TB(tbparam, n, eip)\
644 do {\
645     static void __attribute__((unused)) *__op_label ## n = &&label ## n;\
646     goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\
647 label ## n:\
648     T0 = (long)(tbparam) + (n);\
649     EIP = eip;\
650 } while (0)
651
652 #endif
653
654 void OPPROTO op_jmp_tb_next(void)
655 {
656     JUMP_TB(PARAM1, 0, PARAM2);
657 }
658
659 void OPPROTO op_movl_T0_0(void)
660 {
661     T0 = 0;
662 }
663
664 /* multiple size ops */
665
666 #define ldul ldl
667
668 #define SHIFT 0
669 #include "ops_template.h"
670 #undef SHIFT
671
672 #define SHIFT 1
673 #include "ops_template.h"
674 #undef SHIFT
675
676 #define SHIFT 2
677 #include "ops_template.h"
678 #undef SHIFT
679
680 /* sign extend */
681
682 void OPPROTO op_movsbl_T0_T0(void)
683 {
684     T0 = (int8_t)T0;
685 }
686
687 void OPPROTO op_movzbl_T0_T0(void)
688 {
689     T0 = (uint8_t)T0;
690 }
691
692 void OPPROTO op_movswl_T0_T0(void)
693 {
694     T0 = (int16_t)T0;
695 }
696
697 void OPPROTO op_movzwl_T0_T0(void)
698 {
699     T0 = (uint16_t)T0;
700 }
701
702 void OPPROTO op_movswl_EAX_AX(void)
703 {
704     EAX = (int16_t)EAX;
705 }
706
707 void OPPROTO op_movsbw_AX_AL(void)
708 {
709     EAX = (EAX & 0xffff0000) | ((int8_t)EAX & 0xffff);
710 }
711
712 void OPPROTO op_movslq_EDX_EAX(void)
713 {
714     EDX = (int32_t)EAX >> 31;
715 }
716
717 void OPPROTO op_movswl_DX_AX(void)
718 {
719     EDX = (EDX & 0xffff0000) | (((int16_t)EAX >> 15) & 0xffff);
720 }
721
722 /* push/pop */
723
724 void op_pushl_T0(void)
725 {
726     uint32_t offset;
727     offset = ESP - 4;
728     stl((void *)offset, T0);
729     /* modify ESP after to handle exceptions correctly */
730     ESP = offset;
731 }
732
733 void op_pushw_T0(void)
734 {
735     uint32_t offset;
736     offset = ESP - 2;
737     stw((void *)offset, T0);
738     /* modify ESP after to handle exceptions correctly */
739     ESP = offset;
740 }
741
742 void op_pushl_ss32_T0(void)
743 {
744     uint32_t offset;
745     offset = ESP - 4;
746     stl(env->seg_cache[R_SS].base + offset, T0);
747     /* modify ESP after to handle exceptions correctly */
748     ESP = offset;
749 }
750
751 void op_pushw_ss32_T0(void)
752 {
753     uint32_t offset;
754     offset = ESP - 2;
755     stw(env->seg_cache[R_SS].base + offset, T0);
756     /* modify ESP after to handle exceptions correctly */
757     ESP = offset;
758 }
759
760 void op_pushl_ss16_T0(void)
761 {
762     uint32_t offset;
763     offset = (ESP - 4) & 0xffff;
764     stl(env->seg_cache[R_SS].base + offset, T0);
765     /* modify ESP after to handle exceptions correctly */
766     ESP = (ESP & ~0xffff) | offset;
767 }
768
769 void op_pushw_ss16_T0(void)
770 {
771     uint32_t offset;
772     offset = (ESP - 2) & 0xffff;
773     stw(env->seg_cache[R_SS].base + offset, T0);
774     /* modify ESP after to handle exceptions correctly */
775     ESP = (ESP & ~0xffff) | offset;
776 }
777
778 /* NOTE: ESP update is done after */
779 void op_popl_T0(void)
780 {
781     T0 = ldl((void *)ESP);
782 }
783
784 void op_popw_T0(void)
785 {
786     T0 = lduw((void *)ESP);
787 }
788
789 void op_popl_ss32_T0(void)
790 {
791     T0 = ldl(env->seg_cache[R_SS].base + ESP);
792 }
793
794 void op_popw_ss32_T0(void)
795 {
796     T0 = lduw(env->seg_cache[R_SS].base + ESP);
797 }
798
799 void op_popl_ss16_T0(void)
800 {
801     T0 = ldl(env->seg_cache[R_SS].base + (ESP & 0xffff));
802 }
803
804 void op_popw_ss16_T0(void)
805 {
806     T0 = lduw(env->seg_cache[R_SS].base + (ESP & 0xffff));
807 }
808
809 void op_addl_ESP_4(void)
810 {
811     ESP += 4;
812 }
813
814 void op_addl_ESP_2(void)
815 {
816     ESP += 2;
817 }
818
819 void op_addw_ESP_4(void)
820 {
821     ESP = (ESP & ~0xffff) | ((ESP + 4) & 0xffff);
822 }
823
824 void op_addw_ESP_2(void)
825 {
826     ESP = (ESP & ~0xffff) | ((ESP + 2) & 0xffff);
827 }
828
829 void op_addl_ESP_im(void)
830 {
831     ESP += PARAM1;
832 }
833
834 void op_addw_ESP_im(void)
835 {
836     ESP = (ESP & ~0xffff) | ((ESP + PARAM1) & 0xffff);
837 }
838
839 void OPPROTO op_rdtsc(void)
840 {
841     helper_rdtsc();
842 }
843
844 void OPPROTO op_cpuid(void)
845 {
846     helper_cpuid();
847 }
848
849 /* bcd */
850
851 /* XXX: exception */
852 void OPPROTO op_aam(void)
853 {
854     int base = PARAM1;
855     int al, ah;
856     al = EAX & 0xff;
857     ah = al / base;
858     al = al % base;
859     EAX = (EAX & ~0xffff) | al | (ah << 8);
860     CC_DST = al;
861 }
862
863 void OPPROTO op_aad(void)
864 {
865     int base = PARAM1;
866     int al, ah;
867     al = EAX & 0xff;
868     ah = (EAX >> 8) & 0xff;
869     al = ((ah * base) + al) & 0xff;
870     EAX = (EAX & ~0xffff) | al;
871     CC_DST = al;
872 }
873
874 void OPPROTO op_aaa(void)
875 {
876     int icarry;
877     int al, ah, af;
878     int eflags;
879
880     eflags = cc_table[CC_OP].compute_all();
881     af = eflags & CC_A;
882     al = EAX & 0xff;
883     ah = (EAX >> 8) & 0xff;
884
885     icarry = (al > 0xf9);
886     if (((al & 0x0f) > 9 ) || af) {
887         al = (al + 6) & 0x0f;
888         ah = (ah + 1 + icarry) & 0xff;
889         eflags |= CC_C | CC_A;
890     } else {
891         eflags &= ~(CC_C | CC_A);
892         al &= 0x0f;
893     }
894     EAX = (EAX & ~0xffff) | al | (ah << 8);
895     CC_SRC = eflags;
896 }
897
898 void OPPROTO op_aas(void)
899 {
900     int icarry;
901     int al, ah, af;
902     int eflags;
903
904     eflags = cc_table[CC_OP].compute_all();
905     af = eflags & CC_A;
906     al = EAX & 0xff;
907     ah = (EAX >> 8) & 0xff;
908
909     icarry = (al < 6);
910     if (((al & 0x0f) > 9 ) || af) {
911         al = (al - 6) & 0x0f;
912         ah = (ah - 1 - icarry) & 0xff;
913         eflags |= CC_C | CC_A;
914     } else {
915         eflags &= ~(CC_C | CC_A);
916         al &= 0x0f;
917     }
918     EAX = (EAX & ~0xffff) | al | (ah << 8);
919     CC_SRC = eflags;
920 }
921
922 void OPPROTO op_daa(void)
923 {
924     int al, af, cf;
925     int eflags;
926
927     eflags = cc_table[CC_OP].compute_all();
928     cf = eflags & CC_C;
929     af = eflags & CC_A;
930     al = EAX & 0xff;
931
932     eflags = 0;
933     if (((al & 0x0f) > 9 ) || af) {
934         al = (al + 6) & 0xff;
935         eflags |= CC_A;
936     }
937     if ((al > 0x9f) || cf) {
938         al = (al + 0x60) & 0xff;
939         eflags |= CC_C;
940     }
941     EAX = (EAX & ~0xff) | al;
942     /* well, speed is not an issue here, so we compute the flags by hand */
943     eflags |= (al == 0) << 6; /* zf */
944     eflags |= parity_table[al]; /* pf */
945     eflags |= (al & 0x80); /* sf */
946     CC_SRC = eflags;
947 }
948
949 void OPPROTO op_das(void)
950 {
951     int al, al1, af, cf;
952     int eflags;
953
954     eflags = cc_table[CC_OP].compute_all();
955     cf = eflags & CC_C;
956     af = eflags & CC_A;
957     al = EAX & 0xff;
958
959     eflags = 0;
960     al1 = al;
961     if (((al & 0x0f) > 9 ) || af) {
962         eflags |= CC_A;
963         if (al < 6 || cf)
964             eflags |= CC_C;
965         al = (al - 6) & 0xff;
966     }
967     if ((al1 > 0x99) || cf) {
968         al = (al - 0x60) & 0xff;
969         eflags |= CC_C;
970     }
971     EAX = (EAX & ~0xff) | al;
972     /* well, speed is not an issue here, so we compute the flags by hand */
973     eflags |= (al == 0) << 6; /* zf */
974     eflags |= parity_table[al]; /* pf */
975     eflags |= (al & 0x80); /* sf */
976     CC_SRC = eflags;
977 }
978
979 /* segment handling */
980
981 void OPPROTO op_movl_seg_T0(void)
982 {
983     load_seg(PARAM1, T0 & 0xffff, PARAM2);
984 }
985
986 /* faster VM86 version */
987 void OPPROTO op_movl_seg_T0_vm(void)
988 {
989     int selector;
990     
991     selector = T0 & 0xffff;
992     /* env->segs[] access */
993     *(uint32_t *)((char *)env + PARAM1) = selector;
994     /* env->seg_cache[] access */
995     ((SegmentCache *)((char *)env + PARAM2))->base = (void *)(selector << 4);
996 }
997
998 void OPPROTO op_movl_T0_seg(void)
999 {
1000     T0 = env->segs[PARAM1];
1001 }
1002
1003 void OPPROTO op_movl_A0_seg(void)
1004 {
1005     A0 = *(unsigned long *)((char *)env + PARAM1);
1006 }
1007
1008 void OPPROTO op_addl_A0_seg(void)
1009 {
1010     A0 += *(unsigned long *)((char *)env + PARAM1);
1011 }
1012
1013 void OPPROTO op_lsl(void)
1014 {
1015     helper_lsl();
1016 }
1017
1018 void OPPROTO op_lar(void)
1019 {
1020     helper_lar();
1021 }
1022
1023 /* flags handling */
1024
1025 /* slow jumps cases : in order to avoid calling a function with a
1026    pointer (which can generate a stack frame on PowerPC), we use
1027    op_setcc to set T0 and then call op_jcc. */
1028 void OPPROTO op_jcc(void)
1029 {
1030     if (T0)
1031         JUMP_TB(PARAM1, 0, PARAM2);
1032     else
1033         JUMP_TB(PARAM1, 1, PARAM3);
1034     FORCE_RET();
1035 }
1036
1037 /* slow set cases (compute x86 flags) */
1038 void OPPROTO op_seto_T0_cc(void)
1039 {
1040     int eflags;
1041     eflags = cc_table[CC_OP].compute_all();
1042     T0 = (eflags >> 11) & 1;
1043 }
1044
1045 void OPPROTO op_setb_T0_cc(void)
1046 {
1047     T0 = cc_table[CC_OP].compute_c();
1048 }
1049
1050 void OPPROTO op_setz_T0_cc(void)
1051 {
1052     int eflags;
1053     eflags = cc_table[CC_OP].compute_all();
1054     T0 = (eflags >> 6) & 1;
1055 }
1056
1057 void OPPROTO op_setbe_T0_cc(void)
1058 {
1059     int eflags;
1060     eflags = cc_table[CC_OP].compute_all();
1061     T0 = (eflags & (CC_Z | CC_C)) != 0;
1062 }
1063
1064 void OPPROTO op_sets_T0_cc(void)
1065 {
1066     int eflags;
1067     eflags = cc_table[CC_OP].compute_all();
1068     T0 = (eflags >> 7) & 1;
1069 }
1070
1071 void OPPROTO op_setp_T0_cc(void)
1072 {
1073     int eflags;
1074     eflags = cc_table[CC_OP].compute_all();
1075     T0 = (eflags >> 2) & 1;
1076 }
1077
1078 void OPPROTO op_setl_T0_cc(void)
1079 {
1080     int eflags;
1081     eflags = cc_table[CC_OP].compute_all();
1082     T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
1083 }
1084
1085 void OPPROTO op_setle_T0_cc(void)
1086 {
1087     int eflags;
1088     eflags = cc_table[CC_OP].compute_all();
1089     T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
1090 }
1091
1092 void OPPROTO op_xor_T0_1(void)
1093 {
1094     T0 ^= 1;
1095 }
1096
1097 void OPPROTO op_set_cc_op(void)
1098 {
1099     CC_OP = PARAM1;
1100 }
1101
1102 #define FL_UPDATE_MASK32 (TF_MASK | AC_MASK | ID_MASK)
1103 #define FL_UPDATE_MASK16 (TF_MASK)
1104
1105 void OPPROTO op_movl_eflags_T0(void)
1106 {
1107     int eflags;
1108     eflags = T0;
1109     CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1110     DF = 1 - (2 * ((eflags >> 10) & 1));
1111     /* we also update some system flags as in user mode */
1112     env->eflags = (env->eflags & ~FL_UPDATE_MASK32) | (eflags & FL_UPDATE_MASK32);
1113 }
1114
1115 void OPPROTO op_movw_eflags_T0(void)
1116 {
1117     int eflags;
1118     eflags = T0;
1119     CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1120     DF = 1 - (2 * ((eflags >> 10) & 1));
1121     /* we also update some system flags as in user mode */
1122     env->eflags = (env->eflags & ~FL_UPDATE_MASK16) | (eflags & FL_UPDATE_MASK16);
1123 }
1124
1125 #if 0
1126 /* vm86plus version */
1127 void OPPROTO op_movw_eflags_T0_vm(void)
1128 {
1129     int eflags;
1130     eflags = T0;
1131     CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1132     DF = 1 - (2 * ((eflags >> 10) & 1));
1133     /* we also update some system flags as in user mode */
1134     env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) |
1135         (eflags & FL_UPDATE_MASK16);
1136     if (eflags & IF_MASK) {
1137         env->eflags |= VIF_MASK;
1138         if (env->eflags & VIP_MASK) {
1139             EIP = PARAM1;
1140             raise_exception(EXCP0D_GPF);
1141         }
1142     }
1143     FORCE_RET();
1144 }
1145
1146 void OPPROTO op_movl_eflags_T0_vm(void)
1147 {
1148     int eflags;
1149     eflags = T0;
1150     CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1151     DF = 1 - (2 * ((eflags >> 10) & 1));
1152     /* we also update some system flags as in user mode */
1153     env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) |
1154         (eflags & FL_UPDATE_MASK32);
1155     if (eflags & IF_MASK) {
1156         env->eflags |= VIF_MASK;
1157         if (env->eflags & VIP_MASK) {
1158             EIP = PARAM1;
1159             raise_exception(EXCP0D_GPF);
1160         }
1161     }
1162     FORCE_RET();
1163 }
1164 #endif
1165
1166 /* XXX: compute only O flag */
1167 void OPPROTO op_movb_eflags_T0(void)
1168 {
1169     int of;
1170     of = cc_table[CC_OP].compute_all() & CC_O;
1171     CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of;
1172 }
1173
1174 void OPPROTO op_movl_T0_eflags(void)
1175 {
1176     int eflags;
1177     eflags = cc_table[CC_OP].compute_all();
1178     eflags |= (DF & DF_MASK);
1179     eflags |= env->eflags & ~(VM_MASK | RF_MASK);
1180     T0 = eflags;
1181 }
1182
1183 /* vm86plus version */
1184 #if 0
1185 void OPPROTO op_movl_T0_eflags_vm(void)
1186 {
1187     int eflags;
1188     eflags = cc_table[CC_OP].compute_all();
1189     eflags |= (DF & DF_MASK);
1190     eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK);
1191     if (env->eflags & VIF_MASK)
1192         eflags |= IF_MASK;
1193     T0 = eflags;
1194 }
1195 #endif
1196
1197 void OPPROTO op_cld(void)
1198 {
1199     DF = 1;
1200 }
1201
1202 void OPPROTO op_std(void)
1203 {
1204     DF = -1;
1205 }
1206
1207 void OPPROTO op_clc(void)
1208 {
1209     int eflags;
1210     eflags = cc_table[CC_OP].compute_all();
1211     eflags &= ~CC_C;
1212     CC_SRC = eflags;
1213 }
1214
1215 void OPPROTO op_stc(void)
1216 {
1217     int eflags;
1218     eflags = cc_table[CC_OP].compute_all();
1219     eflags |= CC_C;
1220     CC_SRC = eflags;
1221 }
1222
1223 void OPPROTO op_cmc(void)
1224 {
1225     int eflags;
1226     eflags = cc_table[CC_OP].compute_all();
1227     eflags ^= CC_C;
1228     CC_SRC = eflags;
1229 }
1230
1231 void OPPROTO op_salc(void)
1232 {
1233     int cf;
1234     cf = cc_table[CC_OP].compute_c();
1235     EAX = (EAX & ~0xff) | ((-cf) & 0xff);
1236 }
1237
1238 static int compute_all_eflags(void)
1239 {
1240     return CC_SRC;
1241 }
1242
1243 static int compute_c_eflags(void)
1244 {
1245     return CC_SRC & CC_C;
1246 }
1247
1248 static int compute_c_mul(void)
1249 {
1250     int cf;
1251     cf = (CC_SRC != 0);
1252     return cf;
1253 }
1254
1255 static int compute_all_mul(void)
1256 {
1257     int cf, pf, af, zf, sf, of;
1258     cf = (CC_SRC != 0);
1259     pf = 0; /* undefined */
1260     af = 0; /* undefined */
1261     zf = 0; /* undefined */
1262     sf = 0; /* undefined */
1263     of = cf << 11;
1264     return cf | pf | af | zf | sf | of;
1265 }
1266     
1267 CCTable cc_table[CC_OP_NB] = {
1268     [CC_OP_DYNAMIC] = { /* should never happen */ },
1269
1270     [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
1271
1272     [CC_OP_MUL] = { compute_all_mul, compute_c_mul },
1273
1274     [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
1275     [CC_OP_ADDW] = { compute_all_addw, compute_c_addw  },
1276     [CC_OP_ADDL] = { compute_all_addl, compute_c_addl  },
1277
1278     [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
1279     [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw  },
1280     [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl  },
1281
1282     [CC_OP_SUBB] = { compute_all_subb, compute_c_subb  },
1283     [CC_OP_SUBW] = { compute_all_subw, compute_c_subw  },
1284     [CC_OP_SUBL] = { compute_all_subl, compute_c_subl  },
1285     
1286     [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb  },
1287     [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw  },
1288     [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl  },
1289     
1290     [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
1291     [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
1292     [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
1293     
1294     [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
1295     [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
1296     [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
1297     
1298     [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
1299     [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
1300     [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
1301     
1302     [CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb },
1303     [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw },
1304     [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
1305
1306     [CC_OP_SARB] = { compute_all_sarb, compute_c_sarl },
1307     [CC_OP_SARW] = { compute_all_sarw, compute_c_sarl },
1308     [CC_OP_SARL] = { compute_all_sarl, compute_c_sarl },
1309 };
1310
1311 /* floating point support. Some of the code for complicated x87
1312    functions comes from the LGPL'ed x86 emulator found in the Willows
1313    TWIN windows emulator. */
1314
1315 #if defined(__powerpc__)
1316 extern CPU86_LDouble copysign(CPU86_LDouble, CPU86_LDouble);
1317
1318 /* correct (but slow) PowerPC rint() (glibc version is incorrect) */
1319 double qemu_rint(double x)
1320 {
1321     double y = 4503599627370496.0;
1322     if (fabs(x) >= y)
1323         return x;
1324     if (x < 0) 
1325         y = -y;
1326     y = (x + y) - y;
1327     if (y == 0.0)
1328         y = copysign(y, x);
1329     return y;
1330 }
1331
1332 #define rint qemu_rint
1333 #endif
1334
1335 /* fp load FT0 */
1336
1337 void OPPROTO op_flds_FT0_A0(void)
1338 {
1339 #ifdef USE_FP_CONVERT
1340     FP_CONVERT.i32 = ldl((void *)A0);
1341     FT0 = FP_CONVERT.f;
1342 #else
1343     FT0 = ldfl((void *)A0);
1344 #endif
1345 }
1346
1347 void OPPROTO op_fldl_FT0_A0(void)
1348 {
1349 #ifdef USE_FP_CONVERT
1350     FP_CONVERT.i64 = ldq((void *)A0);
1351     FT0 = FP_CONVERT.d;
1352 #else
1353     FT0 = ldfq((void *)A0);
1354 #endif
1355 }
1356
1357 /* helpers are needed to avoid static constant reference. XXX: find a better way */
1358 #ifdef USE_INT_TO_FLOAT_HELPERS
1359
1360 void helper_fild_FT0_A0(void)
1361 {
1362     FT0 = (CPU86_LDouble)ldsw((void *)A0);
1363 }
1364
1365 void helper_fildl_FT0_A0(void)
1366 {
1367     FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1368 }
1369
1370 void helper_fildll_FT0_A0(void)
1371 {
1372     FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1373 }
1374
1375 void OPPROTO op_fild_FT0_A0(void)
1376 {
1377     helper_fild_FT0_A0();
1378 }
1379
1380 void OPPROTO op_fildl_FT0_A0(void)
1381 {
1382     helper_fildl_FT0_A0();
1383 }
1384
1385 void OPPROTO op_fildll_FT0_A0(void)
1386 {
1387     helper_fildll_FT0_A0();
1388 }
1389
1390 #else
1391
1392 void OPPROTO op_fild_FT0_A0(void)
1393 {
1394 #ifdef USE_FP_CONVERT
1395     FP_CONVERT.i32 = ldsw((void *)A0);
1396     FT0 = (CPU86_LDouble)FP_CONVERT.i32;
1397 #else
1398     FT0 = (CPU86_LDouble)ldsw((void *)A0);
1399 #endif
1400 }
1401
1402 void OPPROTO op_fildl_FT0_A0(void)
1403 {
1404 #ifdef USE_FP_CONVERT
1405     FP_CONVERT.i32 = (int32_t) ldl((void *)A0);
1406     FT0 = (CPU86_LDouble)FP_CONVERT.i32;
1407 #else
1408     FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1409 #endif
1410 }
1411
1412 void OPPROTO op_fildll_FT0_A0(void)
1413 {
1414 #ifdef USE_FP_CONVERT
1415     FP_CONVERT.i64 = (int64_t) ldq((void *)A0);
1416     FT0 = (CPU86_LDouble)FP_CONVERT.i64;
1417 #else
1418     FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1419 #endif
1420 }
1421 #endif
1422
1423 /* fp load ST0 */
1424
1425 void OPPROTO op_flds_ST0_A0(void)
1426 {
1427 #ifdef USE_FP_CONVERT
1428     FP_CONVERT.i32 = ldl((void *)A0);
1429     ST0 = FP_CONVERT.f;
1430 #else
1431     ST0 = ldfl((void *)A0);
1432 #endif
1433 }
1434
1435 void OPPROTO op_fldl_ST0_A0(void)
1436 {
1437 #ifdef USE_FP_CONVERT
1438     FP_CONVERT.i64 = ldq((void *)A0);
1439     ST0 = FP_CONVERT.d;
1440 #else
1441     ST0 = ldfq((void *)A0);
1442 #endif
1443 }
1444
1445 #ifdef USE_X86LDOUBLE
1446 void OPPROTO op_fldt_ST0_A0(void)
1447 {
1448     ST0 = *(long double *)A0;
1449 }
1450 #else
1451 void OPPROTO op_fldt_ST0_A0(void)
1452 {
1453     helper_fldt_ST0_A0();
1454 }
1455 #endif
1456
1457 /* helpers are needed to avoid static constant reference. XXX: find a better way */
1458 #ifdef USE_INT_TO_FLOAT_HELPERS
1459
1460 void helper_fild_ST0_A0(void)
1461 {
1462     ST0 = (CPU86_LDouble)ldsw((void *)A0);
1463 }
1464
1465 void helper_fildl_ST0_A0(void)
1466 {
1467     ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1468 }
1469
1470 void helper_fildll_ST0_A0(void)
1471 {
1472     ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1473 }
1474
1475 void OPPROTO op_fild_ST0_A0(void)
1476 {
1477     helper_fild_ST0_A0();
1478 }
1479
1480 void OPPROTO op_fildl_ST0_A0(void)
1481 {
1482     helper_fildl_ST0_A0();
1483 }
1484
1485 void OPPROTO op_fildll_ST0_A0(void)
1486 {
1487     helper_fildll_ST0_A0();
1488 }
1489
1490 #else
1491
1492 void OPPROTO op_fild_ST0_A0(void)
1493 {
1494 #ifdef USE_FP_CONVERT
1495     FP_CONVERT.i32 = ldsw((void *)A0);
1496     ST0 = (CPU86_LDouble)FP_CONVERT.i32;
1497 #else
1498     ST0 = (CPU86_LDouble)ldsw((void *)A0);
1499 #endif
1500 }
1501
1502 void OPPROTO op_fildl_ST0_A0(void)
1503 {
1504 #ifdef USE_FP_CONVERT
1505     FP_CONVERT.i32 = (int32_t) ldl((void *)A0);
1506     ST0 = (CPU86_LDouble)FP_CONVERT.i32;
1507 #else
1508     ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1509 #endif
1510 }
1511
1512 void OPPROTO op_fildll_ST0_A0(void)
1513 {
1514 #ifdef USE_FP_CONVERT
1515     FP_CONVERT.i64 = (int64_t) ldq((void *)A0);
1516     ST0 = (CPU86_LDouble)FP_CONVERT.i64;
1517 #else
1518     ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1519 #endif
1520 }
1521
1522 #endif
1523
1524 /* fp store */
1525
1526 void OPPROTO op_fsts_ST0_A0(void)
1527 {
1528 #ifdef USE_FP_CONVERT
1529     FP_CONVERT.f = (float)ST0;
1530     stfl((void *)A0, FP_CONVERT.f);
1531 #else
1532     stfl((void *)A0, (float)ST0);
1533 #endif
1534 }
1535
1536 void OPPROTO op_fstl_ST0_A0(void)
1537 {
1538     stfq((void *)A0, (double)ST0);
1539 }
1540
1541 #ifdef USE_X86LDOUBLE
1542 void OPPROTO op_fstt_ST0_A0(void)
1543 {
1544     *(long double *)A0 = ST0;
1545 }
1546 #else
1547 void OPPROTO op_fstt_ST0_A0(void)
1548 {
1549     helper_fstt_ST0_A0();
1550 }
1551 #endif
1552
1553 void OPPROTO op_fist_ST0_A0(void)
1554 {
1555 #if defined(__sparc__) && !defined(__sparc_v9__)
1556     register CPU86_LDouble d asm("o0");
1557 #else
1558     CPU86_LDouble d;
1559 #endif
1560     int val;
1561
1562     d = ST0;
1563     val = lrint(d);
1564     stw((void *)A0, val);
1565 }
1566
1567 void OPPROTO op_fistl_ST0_A0(void)
1568 {
1569 #if defined(__sparc__) && !defined(__sparc_v9__)
1570     register CPU86_LDouble d asm("o0");
1571 #else
1572     CPU86_LDouble d;
1573 #endif
1574     int val;
1575
1576     d = ST0;
1577     val = lrint(d);
1578     stl((void *)A0, val);
1579 }
1580
1581 void OPPROTO op_fistll_ST0_A0(void)
1582 {
1583 #if defined(__sparc__) && !defined(__sparc_v9__)
1584     register CPU86_LDouble d asm("o0");
1585 #else
1586     CPU86_LDouble d;
1587 #endif
1588     int64_t val;
1589
1590     d = ST0;
1591     val = llrint(d);
1592     stq((void *)A0, val);
1593 }
1594
1595 void OPPROTO op_fbld_ST0_A0(void)
1596 {
1597     helper_fbld_ST0_A0();
1598 }
1599
1600 void OPPROTO op_fbst_ST0_A0(void)
1601 {
1602     helper_fbst_ST0_A0();
1603 }
1604
1605 /* FPU move */
1606
1607 void OPPROTO op_fpush(void)
1608 {
1609     fpush();
1610 }
1611
1612 void OPPROTO op_fpop(void)
1613 {
1614     fpop();
1615 }
1616
1617 void OPPROTO op_fdecstp(void)
1618 {
1619     env->fpstt = (env->fpstt - 1) & 7;
1620     env->fpus &= (~0x4700);
1621 }
1622
1623 void OPPROTO op_fincstp(void)
1624 {
1625     env->fpstt = (env->fpstt + 1) & 7;
1626     env->fpus &= (~0x4700);
1627 }
1628
1629 void OPPROTO op_fmov_ST0_FT0(void)
1630 {
1631     ST0 = FT0;
1632 }
1633
1634 void OPPROTO op_fmov_FT0_STN(void)
1635 {
1636     FT0 = ST(PARAM1);
1637 }
1638
1639 void OPPROTO op_fmov_ST0_STN(void)
1640 {
1641     ST0 = ST(PARAM1);
1642 }
1643
1644 void OPPROTO op_fmov_STN_ST0(void)
1645 {
1646     ST(PARAM1) = ST0;
1647 }
1648
1649 void OPPROTO op_fxchg_ST0_STN(void)
1650 {
1651     CPU86_LDouble tmp;
1652     tmp = ST(PARAM1);
1653     ST(PARAM1) = ST0;
1654     ST0 = tmp;
1655 }
1656
1657 /* FPU operations */
1658
1659 /* XXX: handle nans */
1660 void OPPROTO op_fcom_ST0_FT0(void)
1661 {
1662     env->fpus &= (~0x4500);     /* (C3,C2,C0) <-- 000 */
1663     if (ST0 < FT0)
1664         env->fpus |= 0x100;     /* (C3,C2,C0) <-- 001 */
1665     else if (ST0 == FT0)
1666         env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
1667     FORCE_RET();
1668 }
1669
1670 /* XXX: handle nans */
1671 void OPPROTO op_fucom_ST0_FT0(void)
1672 {
1673     env->fpus &= (~0x4500);     /* (C3,C2,C0) <-- 000 */
1674     if (ST0 < FT0)
1675         env->fpus |= 0x100;     /* (C3,C2,C0) <-- 001 */
1676     else if (ST0 == FT0)
1677         env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
1678     FORCE_RET();
1679 }
1680
1681 /* XXX: handle nans */
1682 void OPPROTO op_fcomi_ST0_FT0(void)
1683 {
1684     int eflags;
1685     eflags = cc_table[CC_OP].compute_all();
1686     eflags &= ~(CC_Z | CC_P | CC_C);
1687     if (ST0 < FT0)
1688         eflags |= CC_C;
1689     else if (ST0 == FT0)
1690         eflags |= CC_Z;
1691     CC_SRC = eflags;
1692     FORCE_RET();
1693 }
1694
1695 /* XXX: handle nans */
1696 void OPPROTO op_fucomi_ST0_FT0(void)
1697 {
1698     int eflags;
1699     eflags = cc_table[CC_OP].compute_all();
1700     eflags &= ~(CC_Z | CC_P | CC_C);
1701     if (ST0 < FT0)
1702         eflags |= CC_C;
1703     else if (ST0 == FT0)
1704         eflags |= CC_Z;
1705     CC_SRC = eflags;
1706     FORCE_RET();
1707 }
1708
1709 void OPPROTO op_fadd_ST0_FT0(void)
1710 {
1711     ST0 += FT0;
1712 }
1713
1714 void OPPROTO op_fmul_ST0_FT0(void)
1715 {
1716     ST0 *= FT0;
1717 }
1718
1719 void OPPROTO op_fsub_ST0_FT0(void)
1720 {
1721     ST0 -= FT0;
1722 }
1723
1724 void OPPROTO op_fsubr_ST0_FT0(void)
1725 {
1726     ST0 = FT0 - ST0;
1727 }
1728
1729 void OPPROTO op_fdiv_ST0_FT0(void)
1730 {
1731     ST0 /= FT0;
1732 }
1733
1734 void OPPROTO op_fdivr_ST0_FT0(void)
1735 {
1736     ST0 = FT0 / ST0;
1737 }
1738
1739 /* fp operations between STN and ST0 */
1740
1741 void OPPROTO op_fadd_STN_ST0(void)
1742 {
1743     ST(PARAM1) += ST0;
1744 }
1745
1746 void OPPROTO op_fmul_STN_ST0(void)
1747 {
1748     ST(PARAM1) *= ST0;
1749 }
1750
1751 void OPPROTO op_fsub_STN_ST0(void)
1752 {
1753     ST(PARAM1) -= ST0;
1754 }
1755
1756 void OPPROTO op_fsubr_STN_ST0(void)
1757 {
1758     CPU86_LDouble *p;
1759     p = &ST(PARAM1);
1760     *p = ST0 - *p;
1761 }
1762
1763 void OPPROTO op_fdiv_STN_ST0(void)
1764 {
1765     ST(PARAM1) /= ST0;
1766 }
1767
1768 void OPPROTO op_fdivr_STN_ST0(void)
1769 {
1770     CPU86_LDouble *p;
1771     p = &ST(PARAM1);
1772     *p = ST0 / *p;
1773 }
1774
1775 /* misc FPU operations */
1776 void OPPROTO op_fchs_ST0(void)
1777 {
1778     ST0 = -ST0;
1779 }
1780
1781 void OPPROTO op_fabs_ST0(void)
1782 {
1783     ST0 = fabs(ST0);
1784 }
1785
1786 void OPPROTO op_fxam_ST0(void)
1787 {
1788     helper_fxam_ST0();
1789 }
1790
1791 void OPPROTO op_fld1_ST0(void)
1792 {
1793     ST0 = f15rk[1];
1794 }
1795
1796 void OPPROTO op_fldl2t_ST0(void)
1797 {
1798     ST0 = f15rk[6];
1799 }
1800
1801 void OPPROTO op_fldl2e_ST0(void)
1802 {
1803     ST0 = f15rk[5];
1804 }
1805
1806 void OPPROTO op_fldpi_ST0(void)
1807 {
1808     ST0 = f15rk[2];
1809 }
1810
1811 void OPPROTO op_fldlg2_ST0(void)
1812 {
1813     ST0 = f15rk[3];
1814 }
1815
1816 void OPPROTO op_fldln2_ST0(void)
1817 {
1818     ST0 = f15rk[4];
1819 }
1820
1821 void OPPROTO op_fldz_ST0(void)
1822 {
1823     ST0 = f15rk[0];
1824 }
1825
1826 void OPPROTO op_fldz_FT0(void)
1827 {
1828     ST0 = f15rk[0];
1829 }
1830
1831 /* associated heplers to reduce generated code length and to simplify
1832    relocation (FP constants are usually stored in .rodata section) */
1833
1834 void OPPROTO op_f2xm1(void)
1835 {
1836     helper_f2xm1();
1837 }
1838
1839 void OPPROTO op_fyl2x(void)
1840 {
1841     helper_fyl2x();
1842 }
1843
1844 void OPPROTO op_fptan(void)
1845 {
1846     helper_fptan();
1847 }
1848
1849 void OPPROTO op_fpatan(void)
1850 {
1851     helper_fpatan();
1852 }
1853
1854 void OPPROTO op_fxtract(void)
1855 {
1856     helper_fxtract();
1857 }
1858
1859 void OPPROTO op_fprem1(void)
1860 {
1861     helper_fprem1();
1862 }
1863
1864
1865 void OPPROTO op_fprem(void)
1866 {
1867     helper_fprem();
1868 }
1869
1870 void OPPROTO op_fyl2xp1(void)
1871 {
1872     helper_fyl2xp1();
1873 }
1874
1875 void OPPROTO op_fsqrt(void)
1876 {
1877     helper_fsqrt();
1878 }
1879
1880 void OPPROTO op_fsincos(void)
1881 {
1882     helper_fsincos();
1883 }
1884
1885 void OPPROTO op_frndint(void)
1886 {
1887     helper_frndint();
1888 }
1889
1890 void OPPROTO op_fscale(void)
1891 {
1892     helper_fscale();
1893 }
1894
1895 void OPPROTO op_fsin(void)
1896 {
1897     helper_fsin();
1898 }
1899
1900 void OPPROTO op_fcos(void)
1901 {
1902     helper_fcos();
1903 }
1904
1905 void OPPROTO op_fnstsw_A0(void)
1906 {
1907     int fpus;
1908     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
1909     stw((void *)A0, fpus);
1910 }
1911
1912 void OPPROTO op_fnstsw_EAX(void)
1913 {
1914     int fpus;
1915     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
1916     EAX = (EAX & 0xffff0000) | fpus;
1917 }
1918
1919 void OPPROTO op_fnstcw_A0(void)
1920 {
1921     stw((void *)A0, env->fpuc);
1922 }
1923
1924 void OPPROTO op_fldcw_A0(void)
1925 {
1926     int rnd_type;
1927     env->fpuc = lduw((void *)A0);
1928     /* set rounding mode */
1929     switch(env->fpuc & RC_MASK) {
1930     default:
1931     case RC_NEAR:
1932         rnd_type = FE_TONEAREST;
1933         break;
1934     case RC_DOWN:
1935         rnd_type = FE_DOWNWARD;
1936         break;
1937     case RC_UP:
1938         rnd_type = FE_UPWARD;
1939         break;
1940     case RC_CHOP:
1941         rnd_type = FE_TOWARDZERO;
1942         break;
1943     }
1944     fesetround(rnd_type);
1945 }
1946
1947 void OPPROTO op_fclex(void)
1948 {
1949     env->fpus &= 0x7f00;
1950 }
1951
1952 void OPPROTO op_fninit(void)
1953 {
1954     env->fpus = 0;
1955     env->fpstt = 0;
1956     env->fpuc = 0x37f;
1957     env->fptags[0] = 1;
1958     env->fptags[1] = 1;
1959     env->fptags[2] = 1;
1960     env->fptags[3] = 1;
1961     env->fptags[4] = 1;
1962     env->fptags[5] = 1;
1963     env->fptags[6] = 1;
1964     env->fptags[7] = 1;
1965 }
1966
1967 void OPPROTO op_fnstenv_A0(void)
1968 {
1969     helper_fstenv((uint8_t *)A0, PARAM1);
1970 }
1971
1972 void OPPROTO op_fldenv_A0(void)
1973 {
1974     helper_fldenv((uint8_t *)A0, PARAM1);
1975 }
1976
1977 void OPPROTO op_fnsave_A0(void)
1978 {
1979     helper_fsave((uint8_t *)A0, PARAM1);
1980 }
1981
1982 void OPPROTO op_frstor_A0(void)
1983 {
1984     helper_frstor((uint8_t *)A0, PARAM1);
1985 }
1986
1987 /* threading support */
1988 void OPPROTO op_lock(void)
1989 {
1990     cpu_lock();
1991 }
1992
1993 void OPPROTO op_unlock(void)
1994 {
1995     cpu_unlock();
1996 }
1997