VirtualBox

source: vbox/trunk/src/recompiler/target-i386/op.c@ 18661

最後變更 在這個檔案從18661是 14411,由 vboxsync 提交於 16 年 前

RDTSCP support added. Enabled only for AMD-V guests.

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette