]> Git Repo - qemu.git/blob - target-i386/op.c
syscall insn fix
[qemu.git] / target-i386 / op.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
21 #define ASM_SOFTMMU
22 #include "exec.h"
23
24 /* n must be a constant to be efficient */
25 static inline target_long lshift(target_long x, int n)
26 {
27     if (n >= 0)
28         return x << n;
29     else
30         return x >> (-n);
31 }
32
33 /* we define the various pieces of code used by the JIT */
34
35 #define REG EAX
36 #define REGNAME _EAX
37 #include "opreg_template.h"
38 #undef REG
39 #undef REGNAME
40
41 #define REG ECX
42 #define REGNAME _ECX
43 #include "opreg_template.h"
44 #undef REG
45 #undef REGNAME
46
47 #define REG EDX
48 #define REGNAME _EDX
49 #include "opreg_template.h"
50 #undef REG
51 #undef REGNAME
52
53 #define REG EBX
54 #define REGNAME _EBX
55 #include "opreg_template.h"
56 #undef REG
57 #undef REGNAME
58
59 #define REG ESP
60 #define REGNAME _ESP
61 #include "opreg_template.h"
62 #undef REG
63 #undef REGNAME
64
65 #define REG EBP
66 #define REGNAME _EBP
67 #include "opreg_template.h"
68 #undef REG
69 #undef REGNAME
70
71 #define REG ESI
72 #define REGNAME _ESI
73 #include "opreg_template.h"
74 #undef REG
75 #undef REGNAME
76
77 #define REG EDI
78 #define REGNAME _EDI
79 #include "opreg_template.h"
80 #undef REG
81 #undef REGNAME
82
83 #ifdef TARGET_X86_64
84
85 #define REG (env->regs[8])
86 #define REGNAME _R8
87 #include "opreg_template.h"
88 #undef REG
89 #undef REGNAME
90
91 #define REG (env->regs[9])
92 #define REGNAME _R9
93 #include "opreg_template.h"
94 #undef REG
95 #undef REGNAME
96
97 #define REG (env->regs[10])
98 #define REGNAME _R10
99 #include "opreg_template.h"
100 #undef REG
101 #undef REGNAME
102
103 #define REG (env->regs[11])
104 #define REGNAME _R11
105 #include "opreg_template.h"
106 #undef REG
107 #undef REGNAME
108
109 #define REG (env->regs[12])
110 #define REGNAME _R12
111 #include "opreg_template.h"
112 #undef REG
113 #undef REGNAME
114
115 #define REG (env->regs[13])
116 #define REGNAME _R13
117 #include "opreg_template.h"
118 #undef REG
119 #undef REGNAME
120
121 #define REG (env->regs[14])
122 #define REGNAME _R14
123 #include "opreg_template.h"
124 #undef REG
125 #undef REGNAME
126
127 #define REG (env->regs[15])
128 #define REGNAME _R15
129 #include "opreg_template.h"
130 #undef REG
131 #undef REGNAME
132
133 #endif
134
135 /* operations with flags */
136
137 /* update flags with T0 and T1 (add/sub case) */
138 void OPPROTO op_update2_cc(void)
139 {
140     CC_SRC = T1;
141     CC_DST = T0;
142 }
143
144 /* update flags with T0 (logic operation case) */
145 void OPPROTO op_update1_cc(void)
146 {
147     CC_DST = T0;
148 }
149
150 void OPPROTO op_update_neg_cc(void)
151 {
152     CC_SRC = -T0;
153     CC_DST = T0;
154 }
155
156 void OPPROTO op_cmpl_T0_T1_cc(void)
157 {
158     CC_SRC = T1;
159     CC_DST = T0 - T1;
160 }
161
162 void OPPROTO op_update_inc_cc(void)
163 {
164     CC_SRC = cc_table[CC_OP].compute_c();
165     CC_DST = T0;
166 }
167
168 void OPPROTO op_testl_T0_T1_cc(void)
169 {
170     CC_DST = T0 & T1;
171 }
172
173 /* operations without flags */
174
175 void OPPROTO op_addl_T0_T1(void)
176 {
177     T0 += T1;
178 }
179
180 void OPPROTO op_orl_T0_T1(void)
181 {
182     T0 |= T1;
183 }
184
185 void OPPROTO op_andl_T0_T1(void)
186 {
187     T0 &= T1;
188 }
189
190 void OPPROTO op_subl_T0_T1(void)
191 {
192     T0 -= T1;
193 }
194
195 void OPPROTO op_xorl_T0_T1(void)
196 {
197     T0 ^= T1;
198 }
199
200 void OPPROTO op_negl_T0(void)
201 {
202     T0 = -T0;
203 }
204
205 void OPPROTO op_incl_T0(void)
206 {
207     T0++;
208 }
209
210 void OPPROTO op_decl_T0(void)
211 {
212     T0--;
213 }
214
215 void OPPROTO op_notl_T0(void)
216 {
217     T0 = ~T0;
218 }
219
220 void OPPROTO op_bswapl_T0(void)
221 {
222     T0 = bswap32(T0);
223 }
224
225 #ifdef TARGET_X86_64
226 void OPPROTO op_bswapq_T0(void)
227 {
228     T0 = bswap64(T0);
229 }
230 #endif
231
232 /* multiply/divide */
233
234 /* XXX: add eflags optimizations */
235 /* XXX: add non P4 style flags */
236
237 void OPPROTO op_mulb_AL_T0(void)
238 {
239     unsigned int res;
240     res = (uint8_t)EAX * (uint8_t)T0;
241     EAX = (EAX & ~0xffff) | res;
242     CC_DST = res;
243     CC_SRC = (res & 0xff00);
244 }
245
246 void OPPROTO op_imulb_AL_T0(void)
247 {
248     int res;
249     res = (int8_t)EAX * (int8_t)T0;
250     EAX = (EAX & ~0xffff) | (res & 0xffff);
251     CC_DST = res;
252     CC_SRC = (res != (int8_t)res);
253 }
254
255 void OPPROTO op_mulw_AX_T0(void)
256 {
257     unsigned int res;
258     res = (uint16_t)EAX * (uint16_t)T0;
259     EAX = (EAX & ~0xffff) | (res & 0xffff);
260     EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff);
261     CC_DST = res;
262     CC_SRC = res >> 16;
263 }
264
265 void OPPROTO op_imulw_AX_T0(void)
266 {
267     int res;
268     res = (int16_t)EAX * (int16_t)T0;
269     EAX = (EAX & ~0xffff) | (res & 0xffff);
270     EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff);
271     CC_DST = res;
272     CC_SRC = (res != (int16_t)res);
273 }
274
275 void OPPROTO op_mull_EAX_T0(void)
276 {
277     uint64_t res;
278     res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0);
279     EAX = (uint32_t)res;
280     EDX = (uint32_t)(res >> 32);
281     CC_DST = (uint32_t)res;
282     CC_SRC = (uint32_t)(res >> 32);
283 }
284
285 void OPPROTO op_imull_EAX_T0(void)
286 {
287     int64_t res;
288     res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T0);
289     EAX = res;
290     EDX = res >> 32;
291     CC_DST = res;
292     CC_SRC = (res != (int32_t)res);
293 }
294
295 void OPPROTO op_imulw_T0_T1(void)
296 {
297     int res;
298     res = (int16_t)T0 * (int16_t)T1;
299     T0 = res;
300     CC_DST = res;
301     CC_SRC = (res != (int16_t)res);
302 }
303
304 void OPPROTO op_imull_T0_T1(void)
305 {
306     int64_t res;
307     res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
308     T0 = res;
309     CC_DST = res;
310     CC_SRC = (res != (int32_t)res);
311 }
312
313 #ifdef TARGET_X86_64
314 void OPPROTO op_mulq_EAX_T0(void)
315 {
316     helper_mulq_EAX_T0();
317 }
318
319 void OPPROTO op_imulq_EAX_T0(void)
320 {
321     helper_imulq_EAX_T0();
322 }
323
324 void OPPROTO op_imulq_T0_T1(void)
325 {
326     helper_imulq_T0_T1();
327 }
328 #endif
329
330 /* division, flags are undefined */
331 /* XXX: add exceptions for overflow */
332
333 void OPPROTO op_divb_AL_T0(void)
334 {
335     unsigned int num, den, q, r;
336
337     num = (EAX & 0xffff);
338     den = (T0 & 0xff);
339     if (den == 0) {
340         raise_exception(EXCP00_DIVZ);
341     }
342     q = (num / den) & 0xff;
343     r = (num % den) & 0xff;
344     EAX = (EAX & ~0xffff) | (r << 8) | q;
345 }
346
347 void OPPROTO op_idivb_AL_T0(void)
348 {
349     int num, den, q, r;
350
351     num = (int16_t)EAX;
352     den = (int8_t)T0;
353     if (den == 0) {
354         raise_exception(EXCP00_DIVZ);
355     }
356     q = (num / den) & 0xff;
357     r = (num % den) & 0xff;
358     EAX = (EAX & ~0xffff) | (r << 8) | q;
359 }
360
361 void OPPROTO op_divw_AX_T0(void)
362 {
363     unsigned int num, den, q, r;
364
365     num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
366     den = (T0 & 0xffff);
367     if (den == 0) {
368         raise_exception(EXCP00_DIVZ);
369     }
370     q = (num / den) & 0xffff;
371     r = (num % den) & 0xffff;
372     EAX = (EAX & ~0xffff) | q;
373     EDX = (EDX & ~0xffff) | r;
374 }
375
376 void OPPROTO op_idivw_AX_T0(void)
377 {
378     int num, den, q, r;
379
380     num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
381     den = (int16_t)T0;
382     if (den == 0) {
383         raise_exception(EXCP00_DIVZ);
384     }
385     q = (num / den) & 0xffff;
386     r = (num % den) & 0xffff;
387     EAX = (EAX & ~0xffff) | q;
388     EDX = (EDX & ~0xffff) | r;
389 }
390
391 void OPPROTO op_divl_EAX_T0(void)
392 {
393     helper_divl_EAX_T0();
394 }
395
396 void OPPROTO op_idivl_EAX_T0(void)
397 {
398     helper_idivl_EAX_T0();
399 }
400
401 #ifdef TARGET_X86_64
402 void OPPROTO op_divq_EAX_T0(void)
403 {
404     helper_divq_EAX_T0();
405 }
406
407 void OPPROTO op_idivq_EAX_T0(void)
408 {
409     helper_idivq_EAX_T0();
410 }
411 #endif
412
413 /* constant load & misc op */
414
415 /* XXX: consistent names */
416 void OPPROTO op_movl_T0_imu(void)
417 {
418     T0 = (uint32_t)PARAM1;
419 }
420
421 void OPPROTO op_movl_T0_im(void)
422 {
423     T0 = (int32_t)PARAM1;
424 }
425
426 void OPPROTO op_addl_T0_im(void)
427 {
428     T0 += PARAM1;
429 }
430
431 void OPPROTO op_andl_T0_ffff(void)
432 {
433     T0 = T0 & 0xffff;
434 }
435
436 void OPPROTO op_andl_T0_im(void)
437 {
438     T0 = T0 & PARAM1;
439 }
440
441 void OPPROTO op_movl_T0_T1(void)
442 {
443     T0 = T1;
444 }
445
446 void OPPROTO op_movl_T1_imu(void)
447 {
448     T1 = (uint32_t)PARAM1;
449 }
450
451 void OPPROTO op_movl_T1_im(void)
452 {
453     T1 = (int32_t)PARAM1;
454 }
455
456 void OPPROTO op_addl_T1_im(void)
457 {
458     T1 += PARAM1;
459 }
460
461 void OPPROTO op_movl_T1_A0(void)
462 {
463     T1 = A0;
464 }
465
466 void OPPROTO op_movl_A0_im(void)
467 {
468     A0 = (uint32_t)PARAM1;
469 }
470
471 void OPPROTO op_addl_A0_im(void)
472 {
473     A0 = (uint32_t)(A0 + PARAM1);
474 }
475
476 void OPPROTO op_movl_A0_seg(void)
477 {
478     A0 = (uint32_t)*(target_ulong *)((char *)env + PARAM1);
479 }
480
481 void OPPROTO op_addl_A0_seg(void)
482 {
483     A0 = (uint32_t)(A0 + *(target_ulong *)((char *)env + PARAM1));
484 }
485
486 void OPPROTO op_addl_A0_AL(void)
487 {
488     A0 = (uint32_t)(A0 + (EAX & 0xff));
489 }
490
491 #ifdef WORDS_BIGENDIAN
492 typedef union UREG64 {
493     struct { uint16_t v3, v2, v1, v0; } w;
494     struct { uint32_t v1, v0; } l;
495     uint64_t q;
496 } UREG64;
497 #else
498 typedef union UREG64 {
499     struct { uint16_t v0, v1, v2, v3; } w;
500     struct { uint32_t v0, v1; } l;
501     uint64_t q;
502 } UREG64;
503 #endif
504
505 #ifdef TARGET_X86_64
506
507 #define PARAMQ1 \
508 ({\
509     UREG64 __p;\
510     __p.l.v1 = PARAM1;\
511     __p.l.v0 = PARAM2;\
512     __p.q;\
513 }) 
514
515 void OPPROTO op_movq_T0_im64(void)
516 {
517     T0 = PARAMQ1;
518 }
519
520 void OPPROTO op_movq_A0_im(void)
521 {
522     A0 = (int32_t)PARAM1;
523 }
524
525 void OPPROTO op_movq_A0_im64(void)
526 {
527     A0 = PARAMQ1;
528 }
529
530 void OPPROTO op_addq_A0_im(void)
531 {
532     A0 = (A0 + (int32_t)PARAM1);
533 }
534
535 void OPPROTO op_addq_A0_im64(void)
536 {
537     A0 = (A0 + PARAMQ1);
538 }
539
540 void OPPROTO op_movq_A0_seg(void)
541 {
542     A0 = *(target_ulong *)((char *)env + PARAM1);
543 }
544
545 void OPPROTO op_addq_A0_seg(void)
546 {
547     A0 += *(target_ulong *)((char *)env + PARAM1);
548 }
549
550 void OPPROTO op_addq_A0_AL(void)
551 {
552     A0 = (A0 + (EAX & 0xff));
553 }
554
555 #endif
556
557 void OPPROTO op_andl_A0_ffff(void)
558 {
559     A0 = A0 & 0xffff;
560 }
561
562 /* memory access */
563
564 #define MEMSUFFIX _raw
565 #include "ops_mem.h"
566
567 #if !defined(CONFIG_USER_ONLY)
568 #define MEMSUFFIX _kernel
569 #include "ops_mem.h"
570
571 #define MEMSUFFIX _user
572 #include "ops_mem.h"
573 #endif
574
575 /* indirect jump */
576
577 void OPPROTO op_jmp_T0(void)
578 {
579     EIP = T0;
580 }
581
582 void OPPROTO op_movl_eip_im(void)
583 {
584     EIP = (uint32_t)PARAM1;
585 }
586
587 #ifdef TARGET_X86_64
588 void OPPROTO op_movq_eip_im(void)
589 {
590     EIP = (int32_t)PARAM1;
591 }
592
593 void OPPROTO op_movq_eip_im64(void)
594 {
595     EIP = PARAMQ1;
596 }
597 #endif
598
599 void OPPROTO op_hlt(void)
600 {
601     env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
602     env->exception_index = EXCP_HLT;
603     cpu_loop_exit();
604 }
605
606 void OPPROTO op_debug(void)
607 {
608     env->exception_index = EXCP_DEBUG;
609     cpu_loop_exit();
610 }
611
612 void OPPROTO op_raise_interrupt(void)
613 {
614     int intno;
615     unsigned int next_eip;
616     intno = PARAM1;
617     next_eip = PARAM2;
618     raise_interrupt(intno, 1, 0, next_eip);
619 }
620
621 void OPPROTO op_raise_exception(void)
622 {
623     int exception_index;
624     exception_index = PARAM1;
625     raise_exception(exception_index);
626 }
627
628 void OPPROTO op_into(void)
629 {
630     int eflags;
631     eflags = cc_table[CC_OP].compute_all();
632     if (eflags & CC_O) {
633         raise_interrupt(EXCP04_INTO, 1, 0, PARAM1);
634     }
635     FORCE_RET();
636 }
637
638 void OPPROTO op_cli(void)
639 {
640     env->eflags &= ~IF_MASK;
641 }
642
643 void OPPROTO op_sti(void)
644 {
645     env->eflags |= IF_MASK;
646 }
647
648 void OPPROTO op_set_inhibit_irq(void)
649 {
650     env->hflags |= HF_INHIBIT_IRQ_MASK;
651 }
652
653 void OPPROTO op_reset_inhibit_irq(void)
654 {
655     env->hflags &= ~HF_INHIBIT_IRQ_MASK;
656 }
657
658 #if 0
659 /* vm86plus instructions */
660 void OPPROTO op_cli_vm(void)
661 {
662     env->eflags &= ~VIF_MASK;
663 }
664
665 void OPPROTO op_sti_vm(void)
666 {
667     env->eflags |= VIF_MASK;
668     if (env->eflags & VIP_MASK) {
669         EIP = PARAM1;
670         raise_exception(EXCP0D_GPF);
671     }
672     FORCE_RET();
673 }
674 #endif
675
676 void OPPROTO op_boundw(void)
677 {
678     int low, high, v;
679     low = ldsw(A0);
680     high = ldsw(A0 + 2);
681     v = (int16_t)T0;
682     if (v < low || v > high) {
683         raise_exception(EXCP05_BOUND);
684     }
685     FORCE_RET();
686 }
687
688 void OPPROTO op_boundl(void)
689 {
690     int low, high, v;
691     low = ldl(A0);
692     high = ldl(A0 + 4);
693     v = T0;
694     if (v < low || v > high) {
695         raise_exception(EXCP05_BOUND);
696     }
697     FORCE_RET();
698 }
699
700 void OPPROTO op_cmpxchg8b(void)
701 {
702     helper_cmpxchg8b();
703 }
704
705 void OPPROTO op_movl_T0_0(void)
706 {
707     T0 = 0;
708 }
709
710 void OPPROTO op_exit_tb(void)
711 {
712     EXIT_TB();
713 }
714
715 /* multiple size ops */
716
717 #define ldul ldl
718
719 #define SHIFT 0
720 #include "ops_template.h"
721 #undef SHIFT
722
723 #define SHIFT 1
724 #include "ops_template.h"
725 #undef SHIFT
726
727 #define SHIFT 2
728 #include "ops_template.h"
729 #undef SHIFT
730
731 #ifdef TARGET_X86_64
732
733 #define SHIFT 3
734 #include "ops_template.h"
735 #undef SHIFT
736
737 #endif
738
739 /* sign extend */
740
741 void OPPROTO op_movsbl_T0_T0(void)
742 {
743     T0 = (int8_t)T0;
744 }
745
746 void OPPROTO op_movzbl_T0_T0(void)
747 {
748     T0 = (uint8_t)T0;
749 }
750
751 void OPPROTO op_movswl_T0_T0(void)
752 {
753     T0 = (int16_t)T0;
754 }
755
756 void OPPROTO op_movslq_T0_T0(void)
757 {
758     T0 = (int32_t)T0;
759 }
760
761 void OPPROTO op_movzwl_T0_T0(void)
762 {
763     T0 = (uint16_t)T0;
764 }
765
766 void OPPROTO op_movswl_EAX_AX(void)
767 {
768     EAX = (int16_t)EAX;
769 }
770
771 #ifdef TARGET_X86_64
772 void OPPROTO op_movslq_RAX_EAX(void)
773 {
774     EAX = (int32_t)EAX;
775 }
776 #endif
777
778 void OPPROTO op_movsbw_AX_AL(void)
779 {
780     EAX = (EAX & ~0xffff) | ((int8_t)EAX & 0xffff);
781 }
782
783 void OPPROTO op_movslq_EDX_EAX(void)
784 {
785     EDX = (int32_t)EAX >> 31;
786 }
787
788 void OPPROTO op_movswl_DX_AX(void)
789 {
790     EDX = (EDX & ~0xffff) | (((int16_t)EAX >> 15) & 0xffff);
791 }
792
793 #ifdef TARGET_X86_64
794 void OPPROTO op_movsqo_RDX_RAX(void)
795 {
796     EDX = (int64_t)EAX >> 63;
797 }
798 #endif
799
800 /* string ops helpers */
801
802 void OPPROTO op_addl_ESI_T0(void)
803 {
804     ESI = (uint32_t)(ESI + T0);
805 }
806
807 void OPPROTO op_addw_ESI_T0(void)
808 {
809     ESI = (ESI & ~0xffff) | ((ESI + T0) & 0xffff);
810 }
811
812 void OPPROTO op_addl_EDI_T0(void)
813 {
814     EDI = (uint32_t)(EDI + T0);
815 }
816
817 void OPPROTO op_addw_EDI_T0(void)
818 {
819     EDI = (EDI & ~0xffff) | ((EDI + T0) & 0xffff);
820 }
821
822 void OPPROTO op_decl_ECX(void)
823 {
824     ECX = (uint32_t)(ECX - 1);
825 }
826
827 void OPPROTO op_decw_ECX(void)
828 {
829     ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff);
830 }
831
832 #ifdef TARGET_X86_64
833 void OPPROTO op_addq_ESI_T0(void)
834 {
835     ESI = (ESI + T0);
836 }
837
838 void OPPROTO op_addq_EDI_T0(void)
839 {
840     EDI = (EDI + T0);
841 }
842
843 void OPPROTO op_decq_ECX(void)
844 {
845     ECX--;
846 }
847 #endif
848
849 /* push/pop utils */
850
851 void op_addl_A0_SS(void)
852 {
853     A0 += (long)env->segs[R_SS].base;
854 }
855
856 void op_subl_A0_2(void)
857 {
858     A0 = (uint32_t)(A0 - 2);
859 }
860
861 void op_subl_A0_4(void)
862 {
863     A0 = (uint32_t)(A0 - 4);
864 }
865
866 void op_addl_ESP_4(void)
867 {
868     ESP = (uint32_t)(ESP + 4);
869 }
870
871 void op_addl_ESP_2(void)
872 {
873     ESP = (uint32_t)(ESP + 2);
874 }
875
876 void op_addw_ESP_4(void)
877 {
878     ESP = (ESP & ~0xffff) | ((ESP + 4) & 0xffff);
879 }
880
881 void op_addw_ESP_2(void)
882 {
883     ESP = (ESP & ~0xffff) | ((ESP + 2) & 0xffff);
884 }
885
886 void op_addl_ESP_im(void)
887 {
888     ESP = (uint32_t)(ESP + PARAM1);
889 }
890
891 void op_addw_ESP_im(void)
892 {
893     ESP = (ESP & ~0xffff) | ((ESP + PARAM1) & 0xffff);
894 }
895
896 #ifdef TARGET_X86_64
897 void op_subq_A0_8(void)
898 {
899     A0 -= 8;
900 }
901
902 void op_addq_ESP_8(void)
903 {
904     ESP += 8;
905 }
906
907 void op_addq_ESP_im(void)
908 {
909     ESP += PARAM1;
910 }
911 #endif
912
913 void OPPROTO op_rdtsc(void)
914 {
915     helper_rdtsc();
916 }
917
918 void OPPROTO op_cpuid(void)
919 {
920     helper_cpuid();
921 }
922
923 void OPPROTO op_enter_level(void)
924 {
925     helper_enter_level(PARAM1, PARAM2);
926 }
927
928 void OPPROTO op_sysenter(void)
929 {
930     helper_sysenter();
931 }
932
933 void OPPROTO op_sysexit(void)
934 {
935     helper_sysexit();
936 }
937
938 #ifdef TARGET_X86_64
939 void OPPROTO op_syscall(void)
940 {
941     helper_syscall(PARAM1);
942 }
943
944 void OPPROTO op_sysret(void)
945 {
946     helper_sysret(PARAM1);
947 }
948 #endif
949
950 void OPPROTO op_rdmsr(void)
951 {
952     helper_rdmsr();
953 }
954
955 void OPPROTO op_wrmsr(void)
956 {
957     helper_wrmsr();
958 }
959
960 /* bcd */
961
962 /* XXX: exception */
963 void OPPROTO op_aam(void)
964 {
965     int base = PARAM1;
966     int al, ah;
967     al = EAX & 0xff;
968     ah = al / base;
969     al = al % base;
970     EAX = (EAX & ~0xffff) | al | (ah << 8);
971     CC_DST = al;
972 }
973
974 void OPPROTO op_aad(void)
975 {
976     int base = PARAM1;
977     int al, ah;
978     al = EAX & 0xff;
979     ah = (EAX >> 8) & 0xff;
980     al = ((ah * base) + al) & 0xff;
981     EAX = (EAX & ~0xffff) | al;
982     CC_DST = al;
983 }
984
985 void OPPROTO op_aaa(void)
986 {
987     int icarry;
988     int al, ah, af;
989     int eflags;
990
991     eflags = cc_table[CC_OP].compute_all();
992     af = eflags & CC_A;
993     al = EAX & 0xff;
994     ah = (EAX >> 8) & 0xff;
995
996     icarry = (al > 0xf9);
997     if (((al & 0x0f) > 9 ) || af) {
998         al = (al + 6) & 0x0f;
999         ah = (ah + 1 + icarry) & 0xff;
1000         eflags |= CC_C | CC_A;
1001     } else {
1002         eflags &= ~(CC_C | CC_A);
1003         al &= 0x0f;
1004     }
1005     EAX = (EAX & ~0xffff) | al | (ah << 8);
1006     CC_SRC = eflags;
1007 }
1008
1009 void OPPROTO op_aas(void)
1010 {
1011     int icarry;
1012     int al, ah, af;
1013     int eflags;
1014
1015     eflags = cc_table[CC_OP].compute_all();
1016     af = eflags & CC_A;
1017     al = EAX & 0xff;
1018     ah = (EAX >> 8) & 0xff;
1019
1020     icarry = (al < 6);
1021     if (((al & 0x0f) > 9 ) || af) {
1022         al = (al - 6) & 0x0f;
1023         ah = (ah - 1 - icarry) & 0xff;
1024         eflags |= CC_C | CC_A;
1025     } else {
1026         eflags &= ~(CC_C | CC_A);
1027         al &= 0x0f;
1028     }
1029     EAX = (EAX & ~0xffff) | al | (ah << 8);
1030     CC_SRC = eflags;
1031 }
1032
1033 void OPPROTO op_daa(void)
1034 {
1035     int al, af, cf;
1036     int eflags;
1037
1038     eflags = cc_table[CC_OP].compute_all();
1039     cf = eflags & CC_C;
1040     af = eflags & CC_A;
1041     al = EAX & 0xff;
1042
1043     eflags = 0;
1044     if (((al & 0x0f) > 9 ) || af) {
1045         al = (al + 6) & 0xff;
1046         eflags |= CC_A;
1047     }
1048     if ((al > 0x9f) || cf) {
1049         al = (al + 0x60) & 0xff;
1050         eflags |= CC_C;
1051     }
1052     EAX = (EAX & ~0xff) | al;
1053     /* well, speed is not an issue here, so we compute the flags by hand */
1054     eflags |= (al == 0) << 6; /* zf */
1055     eflags |= parity_table[al]; /* pf */
1056     eflags |= (al & 0x80); /* sf */
1057     CC_SRC = eflags;
1058 }
1059
1060 void OPPROTO op_das(void)
1061 {
1062     int al, al1, af, cf;
1063     int eflags;
1064
1065     eflags = cc_table[CC_OP].compute_all();
1066     cf = eflags & CC_C;
1067     af = eflags & CC_A;
1068     al = EAX & 0xff;
1069
1070     eflags = 0;
1071     al1 = al;
1072     if (((al & 0x0f) > 9 ) || af) {
1073         eflags |= CC_A;
1074         if (al < 6 || cf)
1075             eflags |= CC_C;
1076         al = (al - 6) & 0xff;
1077     }
1078     if ((al1 > 0x99) || cf) {
1079         al = (al - 0x60) & 0xff;
1080         eflags |= CC_C;
1081     }
1082     EAX = (EAX & ~0xff) | al;
1083     /* well, speed is not an issue here, so we compute the flags by hand */
1084     eflags |= (al == 0) << 6; /* zf */
1085     eflags |= parity_table[al]; /* pf */
1086     eflags |= (al & 0x80); /* sf */
1087     CC_SRC = eflags;
1088 }
1089
1090 /* segment handling */
1091
1092 /* never use it with R_CS */
1093 void OPPROTO op_movl_seg_T0(void)
1094 {
1095     load_seg(PARAM1, T0);
1096 }
1097
1098 /* faster VM86 version */
1099 void OPPROTO op_movl_seg_T0_vm(void)
1100 {
1101     int selector;
1102     SegmentCache *sc;
1103     
1104     selector = T0 & 0xffff;
1105     /* env->segs[] access */
1106     sc = (SegmentCache *)((char *)env + PARAM1);
1107     sc->selector = selector;
1108     sc->base = (selector << 4);
1109 }
1110
1111 void OPPROTO op_movl_T0_seg(void)
1112 {
1113     T0 = env->segs[PARAM1].selector;
1114 }
1115
1116 void OPPROTO op_lsl(void)
1117 {
1118     helper_lsl();
1119 }
1120
1121 void OPPROTO op_lar(void)
1122 {
1123     helper_lar();
1124 }
1125
1126 void OPPROTO op_verr(void)
1127 {
1128     helper_verr();
1129 }
1130
1131 void OPPROTO op_verw(void)
1132 {
1133     helper_verw();
1134 }
1135
1136 void OPPROTO op_arpl(void)
1137 {
1138     if ((T0 & 3) < (T1 & 3)) {
1139         /* XXX: emulate bug or 0xff3f0000 oring as in bochs ? */
1140         T0 = (T0 & ~3) | (T1 & 3);
1141         T1 = CC_Z;
1142    } else {
1143         T1 = 0;
1144     }
1145     FORCE_RET();
1146 }
1147             
1148 void OPPROTO op_arpl_update(void)
1149 {
1150     int eflags;
1151     eflags = cc_table[CC_OP].compute_all();
1152     CC_SRC = (eflags & ~CC_Z) | T1;
1153 }
1154     
1155 /* T0: segment, T1:eip */
1156 void OPPROTO op_ljmp_protected_T0_T1(void)
1157 {
1158     helper_ljmp_protected_T0_T1(PARAM1);
1159 }
1160
1161 void OPPROTO op_lcall_real_T0_T1(void)
1162 {
1163     helper_lcall_real_T0_T1(PARAM1, PARAM2);
1164 }
1165
1166 void OPPROTO op_lcall_protected_T0_T1(void)
1167 {
1168     helper_lcall_protected_T0_T1(PARAM1, PARAM2);
1169 }
1170
1171 void OPPROTO op_iret_real(void)
1172 {
1173     helper_iret_real(PARAM1);
1174 }
1175
1176 void OPPROTO op_iret_protected(void)
1177 {
1178     helper_iret_protected(PARAM1, PARAM2);
1179 }
1180
1181 void OPPROTO op_lret_protected(void)
1182 {
1183     helper_lret_protected(PARAM1, PARAM2);
1184 }
1185
1186 void OPPROTO op_lldt_T0(void)
1187 {
1188     helper_lldt_T0();
1189 }
1190
1191 void OPPROTO op_ltr_T0(void)
1192 {
1193     helper_ltr_T0();
1194 }
1195
1196 /* CR registers access */
1197 void OPPROTO op_movl_crN_T0(void)
1198 {
1199     helper_movl_crN_T0(PARAM1);
1200 }
1201
1202 /* DR registers access */
1203 void OPPROTO op_movl_drN_T0(void)
1204 {
1205     helper_movl_drN_T0(PARAM1);
1206 }
1207
1208 void OPPROTO op_lmsw_T0(void)
1209 {
1210     /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
1211        if already set to one. */
1212     T0 = (env->cr[0] & ~0xe) | (T0 & 0xf);
1213     helper_movl_crN_T0(0);
1214 }
1215
1216 void OPPROTO op_invlpg_A0(void)
1217 {
1218     helper_invlpg(A0);
1219 }
1220
1221 void OPPROTO op_movl_T0_env(void)
1222 {
1223     T0 = *(uint32_t *)((char *)env + PARAM1);
1224 }
1225
1226 void OPPROTO op_movl_env_T0(void)
1227 {
1228     *(uint32_t *)((char *)env + PARAM1) = T0;
1229 }
1230
1231 void OPPROTO op_movl_env_T1(void)
1232 {
1233     *(uint32_t *)((char *)env + PARAM1) = T1;
1234 }
1235
1236 void OPPROTO op_movtl_T0_env(void)
1237 {
1238     T0 = *(target_ulong *)((char *)env + PARAM1);
1239 }
1240
1241 void OPPROTO op_movtl_env_T0(void)
1242 {
1243     *(target_ulong *)((char *)env + PARAM1) = T0;
1244 }
1245
1246 void OPPROTO op_movtl_T1_env(void)
1247 {
1248     T1 = *(target_ulong *)((char *)env + PARAM1);
1249 }
1250
1251 void OPPROTO op_movtl_env_T1(void)
1252 {
1253     *(target_ulong *)((char *)env + PARAM1) = T1;
1254 }
1255
1256 void OPPROTO op_clts(void)
1257 {
1258     env->cr[0] &= ~CR0_TS_MASK;
1259     env->hflags &= ~HF_TS_MASK;
1260 }
1261
1262 /* flags handling */
1263
1264 void OPPROTO op_goto_tb0(void)
1265 {
1266     GOTO_TB(op_goto_tb0, 0);
1267 }
1268
1269 void OPPROTO op_goto_tb1(void)
1270 {
1271     GOTO_TB(op_goto_tb1, 1);
1272 }
1273
1274 void OPPROTO op_jmp_label(void)
1275 {
1276     GOTO_LABEL_PARAM(1);
1277 }
1278
1279 void OPPROTO op_jnz_T0_label(void)
1280 {
1281     if (T0)
1282         GOTO_LABEL_PARAM(1);
1283 }
1284
1285 void OPPROTO op_jz_T0_label(void)
1286 {
1287     if (!T0)
1288         GOTO_LABEL_PARAM(1);
1289 }
1290
1291 /* slow set cases (compute x86 flags) */
1292 void OPPROTO op_seto_T0_cc(void)
1293 {
1294     int eflags;
1295     eflags = cc_table[CC_OP].compute_all();
1296     T0 = (eflags >> 11) & 1;
1297 }
1298
1299 void OPPROTO op_setb_T0_cc(void)
1300 {
1301     T0 = cc_table[CC_OP].compute_c();
1302 }
1303
1304 void OPPROTO op_setz_T0_cc(void)
1305 {
1306     int eflags;
1307     eflags = cc_table[CC_OP].compute_all();
1308     T0 = (eflags >> 6) & 1;
1309 }
1310
1311 void OPPROTO op_setbe_T0_cc(void)
1312 {
1313     int eflags;
1314     eflags = cc_table[CC_OP].compute_all();
1315     T0 = (eflags & (CC_Z | CC_C)) != 0;
1316 }
1317
1318 void OPPROTO op_sets_T0_cc(void)
1319 {
1320     int eflags;
1321     eflags = cc_table[CC_OP].compute_all();
1322     T0 = (eflags >> 7) & 1;
1323 }
1324
1325 void OPPROTO op_setp_T0_cc(void)
1326 {
1327     int eflags;
1328     eflags = cc_table[CC_OP].compute_all();
1329     T0 = (eflags >> 2) & 1;
1330 }
1331
1332 void OPPROTO op_setl_T0_cc(void)
1333 {
1334     int eflags;
1335     eflags = cc_table[CC_OP].compute_all();
1336     T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
1337 }
1338
1339 void OPPROTO op_setle_T0_cc(void)
1340 {
1341     int eflags;
1342     eflags = cc_table[CC_OP].compute_all();
1343     T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
1344 }
1345
1346 void OPPROTO op_xor_T0_1(void)
1347 {
1348     T0 ^= 1;
1349 }
1350
1351 void OPPROTO op_set_cc_op(void)
1352 {
1353     CC_OP = PARAM1;
1354 }
1355
1356 /* XXX: clear VIF/VIP in all ops ? */
1357
1358 void OPPROTO op_movl_eflags_T0(void)
1359 {
1360     load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK));
1361 }
1362
1363 void OPPROTO op_movw_eflags_T0(void)
1364 {
1365     load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff);
1366 }
1367
1368 void OPPROTO op_movl_eflags_T0_io(void)
1369 {
1370     load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK));
1371 }
1372
1373 void OPPROTO op_movw_eflags_T0_io(void)
1374 {
1375     load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff);
1376 }
1377
1378 void OPPROTO op_movl_eflags_T0_cpl0(void)
1379 {
1380     load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK));
1381 }
1382
1383 void OPPROTO op_movw_eflags_T0_cpl0(void)
1384 {
1385     load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff);
1386 }
1387
1388 #if 0
1389 /* vm86plus version */
1390 void OPPROTO op_movw_eflags_T0_vm(void)
1391 {
1392     int eflags;
1393     eflags = T0;
1394     CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1395     DF = 1 - (2 * ((eflags >> 10) & 1));
1396     /* we also update some system flags as in user mode */
1397     env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) |
1398         (eflags & FL_UPDATE_MASK16);
1399     if (eflags & IF_MASK) {
1400         env->eflags |= VIF_MASK;
1401         if (env->eflags & VIP_MASK) {
1402             EIP = PARAM1;
1403             raise_exception(EXCP0D_GPF);
1404         }
1405     }
1406     FORCE_RET();
1407 }
1408
1409 void OPPROTO op_movl_eflags_T0_vm(void)
1410 {
1411     int eflags;
1412     eflags = T0;
1413     CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1414     DF = 1 - (2 * ((eflags >> 10) & 1));
1415     /* we also update some system flags as in user mode */
1416     env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) |
1417         (eflags & FL_UPDATE_MASK32);
1418     if (eflags & IF_MASK) {
1419         env->eflags |= VIF_MASK;
1420         if (env->eflags & VIP_MASK) {
1421             EIP = PARAM1;
1422             raise_exception(EXCP0D_GPF);
1423         }
1424     }
1425     FORCE_RET();
1426 }
1427 #endif
1428
1429 /* XXX: compute only O flag */
1430 void OPPROTO op_movb_eflags_T0(void)
1431 {
1432     int of;
1433     of = cc_table[CC_OP].compute_all() & CC_O;
1434     CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of;
1435 }
1436
1437 void OPPROTO op_movl_T0_eflags(void)
1438 {
1439     int eflags;
1440     eflags = cc_table[CC_OP].compute_all();
1441     eflags |= (DF & DF_MASK);
1442     eflags |= env->eflags & ~(VM_MASK | RF_MASK);
1443     T0 = eflags;
1444 }
1445
1446 /* vm86plus version */
1447 #if 0
1448 void OPPROTO op_movl_T0_eflags_vm(void)
1449 {
1450     int eflags;
1451     eflags = cc_table[CC_OP].compute_all();
1452     eflags |= (DF & DF_MASK);
1453     eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK);
1454     if (env->eflags & VIF_MASK)
1455         eflags |= IF_MASK;
1456     T0 = eflags;
1457 }
1458 #endif
1459
1460 void OPPROTO op_cld(void)
1461 {
1462     DF = 1;
1463 }
1464
1465 void OPPROTO op_std(void)
1466 {
1467     DF = -1;
1468 }
1469
1470 void OPPROTO op_clc(void)
1471 {
1472     int eflags;
1473     eflags = cc_table[CC_OP].compute_all();
1474     eflags &= ~CC_C;
1475     CC_SRC = eflags;
1476 }
1477
1478 void OPPROTO op_stc(void)
1479 {
1480     int eflags;
1481     eflags = cc_table[CC_OP].compute_all();
1482     eflags |= CC_C;
1483     CC_SRC = eflags;
1484 }
1485
1486 void OPPROTO op_cmc(void)
1487 {
1488     int eflags;
1489     eflags = cc_table[CC_OP].compute_all();
1490     eflags ^= CC_C;
1491     CC_SRC = eflags;
1492 }
1493
1494 void OPPROTO op_salc(void)
1495 {
1496     int cf;
1497     cf = cc_table[CC_OP].compute_c();
1498     EAX = (EAX & ~0xff) | ((-cf) & 0xff);
1499 }
1500
1501 static int compute_all_eflags(void)
1502 {
1503     return CC_SRC;
1504 }
1505
1506 static int compute_c_eflags(void)
1507 {
1508     return CC_SRC & CC_C;
1509 }
1510
1511 CCTable cc_table[CC_OP_NB] = {
1512     [CC_OP_DYNAMIC] = { /* should never happen */ },
1513
1514     [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
1515
1516     [CC_OP_MULB] = { compute_all_mulb, compute_c_mull },
1517     [CC_OP_MULW] = { compute_all_mulw, compute_c_mull },
1518     [CC_OP_MULL] = { compute_all_mull, compute_c_mull },
1519
1520     [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
1521     [CC_OP_ADDW] = { compute_all_addw, compute_c_addw  },
1522     [CC_OP_ADDL] = { compute_all_addl, compute_c_addl  },
1523
1524     [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
1525     [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw  },
1526     [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl  },
1527
1528     [CC_OP_SUBB] = { compute_all_subb, compute_c_subb  },
1529     [CC_OP_SUBW] = { compute_all_subw, compute_c_subw  },
1530     [CC_OP_SUBL] = { compute_all_subl, compute_c_subl  },
1531     
1532     [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb  },
1533     [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw  },
1534     [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl  },
1535     
1536     [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
1537     [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
1538     [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
1539     
1540     [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
1541     [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
1542     [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
1543     
1544     [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
1545     [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
1546     [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
1547     
1548     [CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb },
1549     [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw },
1550     [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
1551
1552     [CC_OP_SARB] = { compute_all_sarb, compute_c_sarl },
1553     [CC_OP_SARW] = { compute_all_sarw, compute_c_sarl },
1554     [CC_OP_SARL] = { compute_all_sarl, compute_c_sarl },
1555
1556 #ifdef TARGET_X86_64
1557     [CC_OP_MULQ] = { compute_all_mulq, compute_c_mull },
1558
1559     [CC_OP_ADDQ] = { compute_all_addq, compute_c_addq  },
1560
1561     [CC_OP_ADCQ] = { compute_all_adcq, compute_c_adcq  },
1562
1563     [CC_OP_SUBQ] = { compute_all_subq, compute_c_subq  },
1564     
1565     [CC_OP_SBBQ] = { compute_all_sbbq, compute_c_sbbq  },
1566     
1567     [CC_OP_LOGICQ] = { compute_all_logicq, compute_c_logicq },
1568     
1569     [CC_OP_INCQ] = { compute_all_incq, compute_c_incl },
1570
1571     [CC_OP_DECQ] = { compute_all_decq, compute_c_incl },
1572
1573     [CC_OP_SHLQ] = { compute_all_shlq, compute_c_shlq },
1574
1575     [CC_OP_SARQ] = { compute_all_sarq, compute_c_sarl },
1576 #endif
1577 };
1578
1579 /* floating point support. Some of the code for complicated x87
1580    functions comes from the LGPL'ed x86 emulator found in the Willows
1581    TWIN windows emulator. */
1582
1583 #if defined(__powerpc__)
1584 extern CPU86_LDouble copysign(CPU86_LDouble, CPU86_LDouble);
1585
1586 /* correct (but slow) PowerPC rint() (glibc version is incorrect) */
1587 double qemu_rint(double x)
1588 {
1589     double y = 4503599627370496.0;
1590     if (fabs(x) >= y)
1591         return x;
1592     if (x < 0) 
1593         y = -y;
1594     y = (x + y) - y;
1595     if (y == 0.0)
1596         y = copysign(y, x);
1597     return y;
1598 }
1599
1600 #define rint qemu_rint
1601 #endif
1602
1603 /* fp load FT0 */
1604
1605 void OPPROTO op_flds_FT0_A0(void)
1606 {
1607 #ifdef USE_FP_CONVERT
1608     FP_CONVERT.i32 = ldl(A0);
1609     FT0 = FP_CONVERT.f;
1610 #else
1611     FT0 = ldfl(A0);
1612 #endif
1613 }
1614
1615 void OPPROTO op_fldl_FT0_A0(void)
1616 {
1617 #ifdef USE_FP_CONVERT
1618     FP_CONVERT.i64 = ldq(A0);
1619     FT0 = FP_CONVERT.d;
1620 #else
1621     FT0 = ldfq(A0);
1622 #endif
1623 }
1624
1625 /* helpers are needed to avoid static constant reference. XXX: find a better way */
1626 #ifdef USE_INT_TO_FLOAT_HELPERS
1627
1628 void helper_fild_FT0_A0(void)
1629 {
1630     FT0 = (CPU86_LDouble)ldsw(A0);
1631 }
1632
1633 void helper_fildl_FT0_A0(void)
1634 {
1635     FT0 = (CPU86_LDouble)((int32_t)ldl(A0));
1636 }
1637
1638 void helper_fildll_FT0_A0(void)
1639 {
1640     FT0 = (CPU86_LDouble)((int64_t)ldq(A0));
1641 }
1642
1643 void OPPROTO op_fild_FT0_A0(void)
1644 {
1645     helper_fild_FT0_A0();
1646 }
1647
1648 void OPPROTO op_fildl_FT0_A0(void)
1649 {
1650     helper_fildl_FT0_A0();
1651 }
1652
1653 void OPPROTO op_fildll_FT0_A0(void)
1654 {
1655     helper_fildll_FT0_A0();
1656 }
1657
1658 #else
1659
1660 void OPPROTO op_fild_FT0_A0(void)
1661 {
1662 #ifdef USE_FP_CONVERT
1663     FP_CONVERT.i32 = ldsw(A0);
1664     FT0 = (CPU86_LDouble)FP_CONVERT.i32;
1665 #else
1666     FT0 = (CPU86_LDouble)ldsw(A0);
1667 #endif
1668 }
1669
1670 void OPPROTO op_fildl_FT0_A0(void)
1671 {
1672 #ifdef USE_FP_CONVERT
1673     FP_CONVERT.i32 = (int32_t) ldl(A0);
1674     FT0 = (CPU86_LDouble)FP_CONVERT.i32;
1675 #else
1676     FT0 = (CPU86_LDouble)((int32_t)ldl(A0));
1677 #endif
1678 }
1679
1680 void OPPROTO op_fildll_FT0_A0(void)
1681 {
1682 #ifdef USE_FP_CONVERT
1683     FP_CONVERT.i64 = (int64_t) ldq(A0);
1684     FT0 = (CPU86_LDouble)FP_CONVERT.i64;
1685 #else
1686     FT0 = (CPU86_LDouble)((int64_t)ldq(A0));
1687 #endif
1688 }
1689 #endif
1690
1691 /* fp load ST0 */
1692
1693 void OPPROTO op_flds_ST0_A0(void)
1694 {
1695     int new_fpstt;
1696     new_fpstt = (env->fpstt - 1) & 7;
1697 #ifdef USE_FP_CONVERT
1698     FP_CONVERT.i32 = ldl(A0);
1699     env->fpregs[new_fpstt] = FP_CONVERT.f;
1700 #else
1701     env->fpregs[new_fpstt] = ldfl(A0);
1702 #endif
1703     env->fpstt = new_fpstt;
1704     env->fptags[new_fpstt] = 0; /* validate stack entry */
1705 }
1706
1707 void OPPROTO op_fldl_ST0_A0(void)
1708 {
1709     int new_fpstt;
1710     new_fpstt = (env->fpstt - 1) & 7;
1711 #ifdef USE_FP_CONVERT
1712     FP_CONVERT.i64 = ldq(A0);
1713     env->fpregs[new_fpstt] = FP_CONVERT.d;
1714 #else
1715     env->fpregs[new_fpstt] = ldfq(A0);
1716 #endif
1717     env->fpstt = new_fpstt;
1718     env->fptags[new_fpstt] = 0; /* validate stack entry */
1719 }
1720
1721 void OPPROTO op_fldt_ST0_A0(void)
1722 {
1723     helper_fldt_ST0_A0();
1724 }
1725
1726 /* helpers are needed to avoid static constant reference. XXX: find a better way */
1727 #ifdef USE_INT_TO_FLOAT_HELPERS
1728
1729 void helper_fild_ST0_A0(void)
1730 {
1731     int new_fpstt;
1732     new_fpstt = (env->fpstt - 1) & 7;
1733     env->fpregs[new_fpstt] = (CPU86_LDouble)ldsw(A0);
1734     env->fpstt = new_fpstt;
1735     env->fptags[new_fpstt] = 0; /* validate stack entry */
1736 }
1737
1738 void helper_fildl_ST0_A0(void)
1739 {
1740     int new_fpstt;
1741     new_fpstt = (env->fpstt - 1) & 7;
1742     env->fpregs[new_fpstt] = (CPU86_LDouble)((int32_t)ldl(A0));
1743     env->fpstt = new_fpstt;
1744     env->fptags[new_fpstt] = 0; /* validate stack entry */
1745 }
1746
1747 void helper_fildll_ST0_A0(void)
1748 {
1749     int new_fpstt;
1750     new_fpstt = (env->fpstt - 1) & 7;
1751     env->fpregs[new_fpstt] = (CPU86_LDouble)((int64_t)ldq(A0));
1752     env->fpstt = new_fpstt;
1753     env->fptags[new_fpstt] = 0; /* validate stack entry */
1754 }
1755
1756 void OPPROTO op_fild_ST0_A0(void)
1757 {
1758     helper_fild_ST0_A0();
1759 }
1760
1761 void OPPROTO op_fildl_ST0_A0(void)
1762 {
1763     helper_fildl_ST0_A0();
1764 }
1765
1766 void OPPROTO op_fildll_ST0_A0(void)
1767 {
1768     helper_fildll_ST0_A0();
1769 }
1770
1771 #else
1772
1773 void OPPROTO op_fild_ST0_A0(void)
1774 {
1775     int new_fpstt;
1776     new_fpstt = (env->fpstt - 1) & 7;
1777 #ifdef USE_FP_CONVERT
1778     FP_CONVERT.i32 = ldsw(A0);
1779     env->fpregs[new_fpstt] = (CPU86_LDouble)FP_CONVERT.i32;
1780 #else
1781     env->fpregs[new_fpstt] = (CPU86_LDouble)ldsw(A0);
1782 #endif
1783     env->fpstt = new_fpstt;
1784     env->fptags[new_fpstt] = 0; /* validate stack entry */
1785 }
1786
1787 void OPPROTO op_fildl_ST0_A0(void)
1788 {
1789     int new_fpstt;
1790     new_fpstt = (env->fpstt - 1) & 7;
1791 #ifdef USE_FP_CONVERT
1792     FP_CONVERT.i32 = (int32_t) ldl(A0);
1793     env->fpregs[new_fpstt] = (CPU86_LDouble)FP_CONVERT.i32;
1794 #else
1795     env->fpregs[new_fpstt] = (CPU86_LDouble)((int32_t)ldl(A0));
1796 #endif
1797     env->fpstt = new_fpstt;
1798     env->fptags[new_fpstt] = 0; /* validate stack entry */
1799 }
1800
1801 void OPPROTO op_fildll_ST0_A0(void)
1802 {
1803     int new_fpstt;
1804     new_fpstt = (env->fpstt - 1) & 7;
1805 #ifdef USE_FP_CONVERT
1806     FP_CONVERT.i64 = (int64_t) ldq(A0);
1807     env->fpregs[new_fpstt] = (CPU86_LDouble)FP_CONVERT.i64;
1808 #else
1809     env->fpregs[new_fpstt] = (CPU86_LDouble)((int64_t)ldq(A0));
1810 #endif
1811     env->fpstt = new_fpstt;
1812     env->fptags[new_fpstt] = 0; /* validate stack entry */
1813 }
1814
1815 #endif
1816
1817 /* fp store */
1818
1819 void OPPROTO op_fsts_ST0_A0(void)
1820 {
1821 #ifdef USE_FP_CONVERT
1822     FP_CONVERT.f = (float)ST0;
1823     stfl(A0, FP_CONVERT.f);
1824 #else
1825     stfl(A0, (float)ST0);
1826 #endif
1827 }
1828
1829 void OPPROTO op_fstl_ST0_A0(void)
1830 {
1831     stfq(A0, (double)ST0);
1832 }
1833
1834 void OPPROTO op_fstt_ST0_A0(void)
1835 {
1836     helper_fstt_ST0_A0();
1837 }
1838
1839 void OPPROTO op_fist_ST0_A0(void)
1840 {
1841 #if defined(__sparc__) && !defined(__sparc_v9__)
1842     register CPU86_LDouble d asm("o0");
1843 #else
1844     CPU86_LDouble d;
1845 #endif
1846     int val;
1847
1848     d = ST0;
1849     val = lrint(d);
1850     if (val != (int16_t)val)
1851         val = -32768;
1852     stw(A0, val);
1853 }
1854
1855 void OPPROTO op_fistl_ST0_A0(void)
1856 {
1857 #if defined(__sparc__) && !defined(__sparc_v9__)
1858     register CPU86_LDouble d asm("o0");
1859 #else
1860     CPU86_LDouble d;
1861 #endif
1862     int val;
1863
1864     d = ST0;
1865     val = lrint(d);
1866     stl(A0, val);
1867 }
1868
1869 void OPPROTO op_fistll_ST0_A0(void)
1870 {
1871 #if defined(__sparc__) && !defined(__sparc_v9__)
1872     register CPU86_LDouble d asm("o0");
1873 #else
1874     CPU86_LDouble d;
1875 #endif
1876     int64_t val;
1877
1878     d = ST0;
1879     val = llrint(d);
1880     stq(A0, val);
1881 }
1882
1883 void OPPROTO op_fbld_ST0_A0(void)
1884 {
1885     helper_fbld_ST0_A0();
1886 }
1887
1888 void OPPROTO op_fbst_ST0_A0(void)
1889 {
1890     helper_fbst_ST0_A0();
1891 }
1892
1893 /* FPU move */
1894
1895 void OPPROTO op_fpush(void)
1896 {
1897     fpush();
1898 }
1899
1900 void OPPROTO op_fpop(void)
1901 {
1902     fpop();
1903 }
1904
1905 void OPPROTO op_fdecstp(void)
1906 {
1907     env->fpstt = (env->fpstt - 1) & 7;
1908     env->fpus &= (~0x4700);
1909 }
1910
1911 void OPPROTO op_fincstp(void)
1912 {
1913     env->fpstt = (env->fpstt + 1) & 7;
1914     env->fpus &= (~0x4700);
1915 }
1916
1917 void OPPROTO op_ffree_STN(void)
1918 {
1919     env->fptags[(env->fpstt + PARAM1) & 7] = 1;
1920 }
1921
1922 void OPPROTO op_fmov_ST0_FT0(void)
1923 {
1924     ST0 = FT0;
1925 }
1926
1927 void OPPROTO op_fmov_FT0_STN(void)
1928 {
1929     FT0 = ST(PARAM1);
1930 }
1931
1932 void OPPROTO op_fmov_ST0_STN(void)
1933 {
1934     ST0 = ST(PARAM1);
1935 }
1936
1937 void OPPROTO op_fmov_STN_ST0(void)
1938 {
1939     ST(PARAM1) = ST0;
1940 }
1941
1942 void OPPROTO op_fxchg_ST0_STN(void)
1943 {
1944     CPU86_LDouble tmp;
1945     tmp = ST(PARAM1);
1946     ST(PARAM1) = ST0;
1947     ST0 = tmp;
1948 }
1949
1950 /* FPU operations */
1951
1952 /* XXX: handle nans */
1953 void OPPROTO op_fcom_ST0_FT0(void)
1954 {
1955     env->fpus &= (~0x4500);     /* (C3,C2,C0) <-- 000 */
1956     if (ST0 < FT0)
1957         env->fpus |= 0x100;     /* (C3,C2,C0) <-- 001 */
1958     else if (ST0 == FT0)
1959         env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
1960     FORCE_RET();
1961 }
1962
1963 /* XXX: handle nans */
1964 void OPPROTO op_fucom_ST0_FT0(void)
1965 {
1966     env->fpus &= (~0x4500);     /* (C3,C2,C0) <-- 000 */
1967     if (ST0 < FT0)
1968         env->fpus |= 0x100;     /* (C3,C2,C0) <-- 001 */
1969     else if (ST0 == FT0)
1970         env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
1971     FORCE_RET();
1972 }
1973
1974 /* XXX: handle nans */
1975 void OPPROTO op_fcomi_ST0_FT0(void)
1976 {
1977     int eflags;
1978     eflags = cc_table[CC_OP].compute_all();
1979     eflags &= ~(CC_Z | CC_P | CC_C);
1980     if (ST0 < FT0)
1981         eflags |= CC_C;
1982     else if (ST0 == FT0)
1983         eflags |= CC_Z;
1984     CC_SRC = eflags;
1985     FORCE_RET();
1986 }
1987
1988 /* XXX: handle nans */
1989 void OPPROTO op_fucomi_ST0_FT0(void)
1990 {
1991     int eflags;
1992     eflags = cc_table[CC_OP].compute_all();
1993     eflags &= ~(CC_Z | CC_P | CC_C);
1994     if (ST0 < FT0)
1995         eflags |= CC_C;
1996     else if (ST0 == FT0)
1997         eflags |= CC_Z;
1998     CC_SRC = eflags;
1999     FORCE_RET();
2000 }
2001
2002 void OPPROTO op_fcmov_ST0_STN_T0(void)
2003 {
2004     if (T0) {
2005         ST0 = ST(PARAM1);
2006     }
2007     FORCE_RET();
2008 }
2009
2010 void OPPROTO op_fadd_ST0_FT0(void)
2011 {
2012     ST0 += FT0;
2013 }
2014
2015 void OPPROTO op_fmul_ST0_FT0(void)
2016 {
2017     ST0 *= FT0;
2018 }
2019
2020 void OPPROTO op_fsub_ST0_FT0(void)
2021 {
2022     ST0 -= FT0;
2023 }
2024
2025 void OPPROTO op_fsubr_ST0_FT0(void)
2026 {
2027     ST0 = FT0 - ST0;
2028 }
2029
2030 void OPPROTO op_fdiv_ST0_FT0(void)
2031 {
2032     ST0 = helper_fdiv(ST0, FT0);
2033 }
2034
2035 void OPPROTO op_fdivr_ST0_FT0(void)
2036 {
2037     ST0 = helper_fdiv(FT0, ST0);
2038 }
2039
2040 /* fp operations between STN and ST0 */
2041
2042 void OPPROTO op_fadd_STN_ST0(void)
2043 {
2044     ST(PARAM1) += ST0;
2045 }
2046
2047 void OPPROTO op_fmul_STN_ST0(void)
2048 {
2049     ST(PARAM1) *= ST0;
2050 }
2051
2052 void OPPROTO op_fsub_STN_ST0(void)
2053 {
2054     ST(PARAM1) -= ST0;
2055 }
2056
2057 void OPPROTO op_fsubr_STN_ST0(void)
2058 {
2059     CPU86_LDouble *p;
2060     p = &ST(PARAM1);
2061     *p = ST0 - *p;
2062 }
2063
2064 void OPPROTO op_fdiv_STN_ST0(void)
2065 {
2066     CPU86_LDouble *p;
2067     p = &ST(PARAM1);
2068     *p = helper_fdiv(*p, ST0);
2069 }
2070
2071 void OPPROTO op_fdivr_STN_ST0(void)
2072 {
2073     CPU86_LDouble *p;
2074     p = &ST(PARAM1);
2075     *p = helper_fdiv(ST0, *p);
2076 }
2077
2078 /* misc FPU operations */
2079 void OPPROTO op_fchs_ST0(void)
2080 {
2081     ST0 = -ST0;
2082 }
2083
2084 void OPPROTO op_fabs_ST0(void)
2085 {
2086     ST0 = fabs(ST0);
2087 }
2088
2089 void OPPROTO op_fxam_ST0(void)
2090 {
2091     helper_fxam_ST0();
2092 }
2093
2094 void OPPROTO op_fld1_ST0(void)
2095 {
2096     ST0 = f15rk[1];
2097 }
2098
2099 void OPPROTO op_fldl2t_ST0(void)
2100 {
2101     ST0 = f15rk[6];
2102 }
2103
2104 void OPPROTO op_fldl2e_ST0(void)
2105 {
2106     ST0 = f15rk[5];
2107 }
2108
2109 void OPPROTO op_fldpi_ST0(void)
2110 {
2111     ST0 = f15rk[2];
2112 }
2113
2114 void OPPROTO op_fldlg2_ST0(void)
2115 {
2116     ST0 = f15rk[3];
2117 }
2118
2119 void OPPROTO op_fldln2_ST0(void)
2120 {
2121     ST0 = f15rk[4];
2122 }
2123
2124 void OPPROTO op_fldz_ST0(void)
2125 {
2126     ST0 = f15rk[0];
2127 }
2128
2129 void OPPROTO op_fldz_FT0(void)
2130 {
2131     FT0 = f15rk[0];
2132 }
2133
2134 /* associated heplers to reduce generated code length and to simplify
2135    relocation (FP constants are usually stored in .rodata section) */
2136
2137 void OPPROTO op_f2xm1(void)
2138 {
2139     helper_f2xm1();
2140 }
2141
2142 void OPPROTO op_fyl2x(void)
2143 {
2144     helper_fyl2x();
2145 }
2146
2147 void OPPROTO op_fptan(void)
2148 {
2149     helper_fptan();
2150 }
2151
2152 void OPPROTO op_fpatan(void)
2153 {
2154     helper_fpatan();
2155 }
2156
2157 void OPPROTO op_fxtract(void)
2158 {
2159     helper_fxtract();
2160 }
2161
2162 void OPPROTO op_fprem1(void)
2163 {
2164     helper_fprem1();
2165 }
2166
2167
2168 void OPPROTO op_fprem(void)
2169 {
2170     helper_fprem();
2171 }
2172
2173 void OPPROTO op_fyl2xp1(void)
2174 {
2175     helper_fyl2xp1();
2176 }
2177
2178 void OPPROTO op_fsqrt(void)
2179 {
2180     helper_fsqrt();
2181 }
2182
2183 void OPPROTO op_fsincos(void)
2184 {
2185     helper_fsincos();
2186 }
2187
2188 void OPPROTO op_frndint(void)
2189 {
2190     helper_frndint();
2191 }
2192
2193 void OPPROTO op_fscale(void)
2194 {
2195     helper_fscale();
2196 }
2197
2198 void OPPROTO op_fsin(void)
2199 {
2200     helper_fsin();
2201 }
2202
2203 void OPPROTO op_fcos(void)
2204 {
2205     helper_fcos();
2206 }
2207
2208 void OPPROTO op_fnstsw_A0(void)
2209 {
2210     int fpus;
2211     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2212     stw(A0, fpus);
2213 }
2214
2215 void OPPROTO op_fnstsw_EAX(void)
2216 {
2217     int fpus;
2218     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2219     EAX = (EAX & ~0xffff) | fpus;
2220 }
2221
2222 void OPPROTO op_fnstcw_A0(void)
2223 {
2224     stw(A0, env->fpuc);
2225 }
2226
2227 void OPPROTO op_fldcw_A0(void)
2228 {
2229     int rnd_type;
2230     env->fpuc = lduw(A0);
2231     /* set rounding mode */
2232     switch(env->fpuc & RC_MASK) {
2233     default:
2234     case RC_NEAR:
2235         rnd_type = FE_TONEAREST;
2236         break;
2237     case RC_DOWN:
2238         rnd_type = FE_DOWNWARD;
2239         break;
2240     case RC_UP:
2241         rnd_type = FE_UPWARD;
2242         break;
2243     case RC_CHOP:
2244         rnd_type = FE_TOWARDZERO;
2245         break;
2246     }
2247     fesetround(rnd_type);
2248 }
2249
2250 void OPPROTO op_fclex(void)
2251 {
2252     env->fpus &= 0x7f00;
2253 }
2254
2255 void OPPROTO op_fwait(void)
2256 {
2257     if (env->fpus & FPUS_SE)
2258         fpu_raise_exception();
2259     FORCE_RET();
2260 }
2261
2262 void OPPROTO op_fninit(void)
2263 {
2264     env->fpus = 0;
2265     env->fpstt = 0;
2266     env->fpuc = 0x37f;
2267     env->fptags[0] = 1;
2268     env->fptags[1] = 1;
2269     env->fptags[2] = 1;
2270     env->fptags[3] = 1;
2271     env->fptags[4] = 1;
2272     env->fptags[5] = 1;
2273     env->fptags[6] = 1;
2274     env->fptags[7] = 1;
2275 }
2276
2277 void OPPROTO op_fnstenv_A0(void)
2278 {
2279     helper_fstenv(A0, PARAM1);
2280 }
2281
2282 void OPPROTO op_fldenv_A0(void)
2283 {
2284     helper_fldenv(A0, PARAM1);
2285 }
2286
2287 void OPPROTO op_fnsave_A0(void)
2288 {
2289     helper_fsave(A0, PARAM1);
2290 }
2291
2292 void OPPROTO op_frstor_A0(void)
2293 {
2294     helper_frstor(A0, PARAM1);
2295 }
2296
2297 /* threading support */
2298 void OPPROTO op_lock(void)
2299 {
2300     cpu_lock();
2301 }
2302
2303 void OPPROTO op_unlock(void)
2304 {
2305     cpu_unlock();
2306 }
2307
2308 /* SSE support */
2309 static inline void memcpy16(void *d, void *s)
2310 {
2311     ((uint32_t *)d)[0] = ((uint32_t *)s)[0];
2312     ((uint32_t *)d)[1] = ((uint32_t *)s)[1];
2313     ((uint32_t *)d)[2] = ((uint32_t *)s)[2];
2314     ((uint32_t *)d)[3] = ((uint32_t *)s)[3];
2315 }
2316
2317 void OPPROTO op_movo(void)
2318 {
2319     /* XXX: badly generated code */
2320     XMMReg *d, *s;
2321     d = (XMMReg *)((char *)env + PARAM1);
2322     s = (XMMReg *)((char *)env + PARAM2);
2323     memcpy16(d, s);
2324 }
2325
2326 void OPPROTO op_fxsave_A0(void)
2327 {
2328     helper_fxsave(A0, PARAM1);
2329 }
2330
2331 void OPPROTO op_fxrstor_A0(void)
2332 {
2333     helper_fxrstor(A0, PARAM1);
2334 }
This page took 0.141558 seconds and 4 git commands to generate.