]> git.proxmox.com Git - mirror_qemu.git/blob - target-i386/op.c
x86_64 target support
[mirror_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();
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 }