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