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