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