VirtualBox

source: vbox/trunk/src/recompiler_new/target-i386/op.c@ 13236

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

All: license header changes for 2.0 (OSE headers, add Sun GPL/LGPL disclaimer)

  • 屬性 svn:eol-style 設為 native
檔案大小: 46.5 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
1058void OPPROTO op_cpuid(void)
1059{
1060 helper_cpuid();
1061}
1062
1063void OPPROTO op_enter_level(void)
1064{
1065 helper_enter_level(PARAM1, PARAM2);
1066}
1067
1068#ifdef TARGET_X86_64
1069void OPPROTO op_enter64_level(void)
1070{
1071 helper_enter64_level(PARAM1, PARAM2);
1072}
1073#endif
1074
1075void OPPROTO op_sysenter(void)
1076{
1077 helper_sysenter();
1078}
1079
1080void OPPROTO op_sysexit(void)
1081{
1082 helper_sysexit();
1083}
1084
1085#ifdef TARGET_X86_64
1086void OPPROTO op_syscall(void)
1087{
1088 helper_syscall(PARAM1);
1089}
1090
1091void OPPROTO op_sysret(void)
1092{
1093 helper_sysret(PARAM1);
1094}
1095#endif
1096
1097void OPPROTO op_rdmsr(void)
1098{
1099 helper_rdmsr();
1100}
1101
1102void OPPROTO op_wrmsr(void)
1103{
1104 helper_wrmsr();
1105}
1106
1107/* bcd */
1108
1109/* XXX: exception */
1110void OPPROTO op_aam(void)
1111{
1112 int base = PARAM1;
1113 int al, ah;
1114 al = EAX & 0xff;
1115 ah = al / base;
1116 al = al % base;
1117 EAX = (EAX & ~0xffff) | al | (ah << 8);
1118 CC_DST = al;
1119}
1120
1121void OPPROTO op_aad(void)
1122{
1123 int base = PARAM1;
1124 int al, ah;
1125 al = EAX & 0xff;
1126 ah = (EAX >> 8) & 0xff;
1127 al = ((ah * base) + al) & 0xff;
1128 EAX = (EAX & ~0xffff) | al;
1129 CC_DST = al;
1130}
1131
1132void OPPROTO op_aaa(void)
1133{
1134 int icarry;
1135 int al, ah, af;
1136 int eflags;
1137
1138 eflags = cc_table[CC_OP].compute_all();
1139 af = eflags & CC_A;
1140 al = EAX & 0xff;
1141 ah = (EAX >> 8) & 0xff;
1142
1143 icarry = (al > 0xf9);
1144 if (((al & 0x0f) > 9 ) || af) {
1145 al = (al + 6) & 0x0f;
1146 ah = (ah + 1 + icarry) & 0xff;
1147 eflags |= CC_C | CC_A;
1148 } else {
1149 eflags &= ~(CC_C | CC_A);
1150 al &= 0x0f;
1151 }
1152 EAX = (EAX & ~0xffff) | al | (ah << 8);
1153 CC_SRC = eflags;
1154 FORCE_RET();
1155}
1156
1157void OPPROTO op_aas(void)
1158{
1159 int icarry;
1160 int al, ah, af;
1161 int eflags;
1162
1163 eflags = cc_table[CC_OP].compute_all();
1164 af = eflags & CC_A;
1165 al = EAX & 0xff;
1166 ah = (EAX >> 8) & 0xff;
1167
1168 icarry = (al < 6);
1169 if (((al & 0x0f) > 9 ) || af) {
1170 al = (al - 6) & 0x0f;
1171 ah = (ah - 1 - icarry) & 0xff;
1172 eflags |= CC_C | CC_A;
1173 } else {
1174 eflags &= ~(CC_C | CC_A);
1175 al &= 0x0f;
1176 }
1177 EAX = (EAX & ~0xffff) | al | (ah << 8);
1178 CC_SRC = eflags;
1179 FORCE_RET();
1180}
1181
1182void OPPROTO op_daa(void)
1183{
1184 int al, af, cf;
1185 int eflags;
1186
1187 eflags = cc_table[CC_OP].compute_all();
1188 cf = eflags & CC_C;
1189 af = eflags & CC_A;
1190 al = EAX & 0xff;
1191
1192 eflags = 0;
1193 if (((al & 0x0f) > 9 ) || af) {
1194 al = (al + 6) & 0xff;
1195 eflags |= CC_A;
1196 }
1197 if ((al > 0x9f) || cf) {
1198 al = (al + 0x60) & 0xff;
1199 eflags |= CC_C;
1200 }
1201 EAX = (EAX & ~0xff) | al;
1202 /* well, speed is not an issue here, so we compute the flags by hand */
1203 eflags |= (al == 0) << 6; /* zf */
1204 eflags |= parity_table[al]; /* pf */
1205 eflags |= (al & 0x80); /* sf */
1206 CC_SRC = eflags;
1207 FORCE_RET();
1208}
1209
1210void OPPROTO op_das(void)
1211{
1212 int al, al1, af, cf;
1213 int eflags;
1214
1215 eflags = cc_table[CC_OP].compute_all();
1216 cf = eflags & CC_C;
1217 af = eflags & CC_A;
1218 al = EAX & 0xff;
1219
1220 eflags = 0;
1221 al1 = al;
1222 if (((al & 0x0f) > 9 ) || af) {
1223 eflags |= CC_A;
1224 if (al < 6 || cf)
1225 eflags |= CC_C;
1226 al = (al - 6) & 0xff;
1227 }
1228 if ((al1 > 0x99) || cf) {
1229 al = (al - 0x60) & 0xff;
1230 eflags |= CC_C;
1231 }
1232 EAX = (EAX & ~0xff) | al;
1233 /* well, speed is not an issue here, so we compute the flags by hand */
1234 eflags |= (al == 0) << 6; /* zf */
1235 eflags |= parity_table[al]; /* pf */
1236 eflags |= (al & 0x80); /* sf */
1237 CC_SRC = eflags;
1238 FORCE_RET();
1239}
1240
1241/* segment handling */
1242
1243/* never use it with R_CS */
1244void OPPROTO op_movl_seg_T0(void)
1245{
1246 load_seg(PARAM1, T0);
1247}
1248
1249/* faster VM86 version */
1250void OPPROTO op_movl_seg_T0_vm(void)
1251{
1252 int selector;
1253 SegmentCache *sc;
1254
1255 selector = T0 & 0xffff;
1256 /* env->segs[] access */
1257 sc = (SegmentCache *)((char *)env + PARAM1);
1258 sc->selector = selector;
1259 sc->base = (selector << 4);
1260#ifdef VBOX
1261 sc->flags = 0; /* clear attributes */
1262#endif
1263}
1264
1265void OPPROTO op_movl_T0_seg(void)
1266{
1267 T0 = env->segs[PARAM1].selector;
1268}
1269
1270void OPPROTO op_lsl(void)
1271{
1272 helper_lsl();
1273}
1274
1275void OPPROTO op_lar(void)
1276{
1277 helper_lar();
1278}
1279
1280void OPPROTO op_verr(void)
1281{
1282 helper_verr();
1283}
1284
1285void OPPROTO op_verw(void)
1286{
1287 helper_verw();
1288}
1289
1290void OPPROTO op_arpl(void)
1291{
1292 if ((T0 & 3) < (T1 & 3)) {
1293 /* XXX: emulate bug or 0xff3f0000 oring as in bochs ? */
1294 T0 = (T0 & ~3) | (T1 & 3);
1295 T1 = CC_Z;
1296 } else {
1297 T1 = 0;
1298 }
1299 FORCE_RET();
1300}
1301
1302void OPPROTO op_arpl_update(void)
1303{
1304 int eflags;
1305 eflags = cc_table[CC_OP].compute_all();
1306 CC_SRC = (eflags & ~CC_Z) | T1;
1307}
1308
1309/* T0: segment, T1:eip */
1310void OPPROTO op_ljmp_protected_T0_T1(void)
1311{
1312 helper_ljmp_protected_T0_T1(PARAM1);
1313}
1314
1315void OPPROTO op_lcall_real_T0_T1(void)
1316{
1317 helper_lcall_real_T0_T1(PARAM1, PARAM2);
1318}
1319
1320void OPPROTO op_lcall_protected_T0_T1(void)
1321{
1322 helper_lcall_protected_T0_T1(PARAM1, PARAM2);
1323}
1324
1325void OPPROTO op_iret_real(void)
1326{
1327 helper_iret_real(PARAM1);
1328}
1329
1330void OPPROTO op_iret_protected(void)
1331{
1332 helper_iret_protected(PARAM1, PARAM2);
1333}
1334
1335void OPPROTO op_lret_protected(void)
1336{
1337 helper_lret_protected(PARAM1, PARAM2);
1338}
1339
1340void OPPROTO op_lldt_T0(void)
1341{
1342 helper_lldt_T0();
1343}
1344
1345void OPPROTO op_ltr_T0(void)
1346{
1347 helper_ltr_T0();
1348}
1349
1350/* CR registers access */
1351void OPPROTO op_movl_crN_T0(void)
1352{
1353 helper_movl_crN_T0(PARAM1);
1354}
1355
1356#if !defined(CONFIG_USER_ONLY)
1357void OPPROTO op_movtl_T0_cr8(void)
1358{
1359 T0 = cpu_get_apic_tpr(env);
1360}
1361#endif
1362
1363/* DR registers access */
1364void OPPROTO op_movl_drN_T0(void)
1365{
1366 helper_movl_drN_T0(PARAM1);
1367}
1368
1369void OPPROTO op_lmsw_T0(void)
1370{
1371 /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
1372 if already set to one. */
1373 T0 = (env->cr[0] & ~0xe) | (T0 & 0xf);
1374 helper_movl_crN_T0(0);
1375}
1376
1377void OPPROTO op_invlpg_A0(void)
1378{
1379 helper_invlpg(A0);
1380}
1381
1382void OPPROTO op_movl_T0_env(void)
1383{
1384 T0 = *(uint32_t *)((char *)env + PARAM1);
1385}
1386
1387void OPPROTO op_movl_env_T0(void)
1388{
1389 *(uint32_t *)((char *)env + PARAM1) = T0;
1390}
1391
1392void OPPROTO op_movl_env_T1(void)
1393{
1394 *(uint32_t *)((char *)env + PARAM1) = T1;
1395}
1396
1397void OPPROTO op_movtl_T0_env(void)
1398{
1399 T0 = *(target_ulong *)((char *)env + PARAM1);
1400}
1401
1402void OPPROTO op_movtl_env_T0(void)
1403{
1404 *(target_ulong *)((char *)env + PARAM1) = T0;
1405}
1406
1407void OPPROTO op_movtl_T1_env(void)
1408{
1409 T1 = *(target_ulong *)((char *)env + PARAM1);
1410}
1411
1412void OPPROTO op_movtl_env_T1(void)
1413{
1414 *(target_ulong *)((char *)env + PARAM1) = T1;
1415}
1416
1417void OPPROTO op_clts(void)
1418{
1419 env->cr[0] &= ~CR0_TS_MASK;
1420 env->hflags &= ~HF_TS_MASK;
1421}
1422
1423/* flags handling */
1424
1425void OPPROTO op_goto_tb0(void)
1426{
1427 GOTO_TB(op_goto_tb0, PARAM1, 0);
1428}
1429
1430void OPPROTO op_goto_tb1(void)
1431{
1432 GOTO_TB(op_goto_tb1, PARAM1, 1);
1433}
1434
1435void OPPROTO op_jmp_label(void)
1436{
1437 GOTO_LABEL_PARAM(1);
1438}
1439
1440void OPPROTO op_jnz_T0_label(void)
1441{
1442 if (T0)
1443 GOTO_LABEL_PARAM(1);
1444 FORCE_RET();
1445}
1446
1447void OPPROTO op_jz_T0_label(void)
1448{
1449 if (!T0)
1450 GOTO_LABEL_PARAM(1);
1451 FORCE_RET();
1452}
1453
1454/* slow set cases (compute x86 flags) */
1455void OPPROTO op_seto_T0_cc(void)
1456{
1457 int eflags;
1458 eflags = cc_table[CC_OP].compute_all();
1459 T0 = (eflags >> 11) & 1;
1460}
1461
1462void OPPROTO op_setb_T0_cc(void)
1463{
1464 T0 = cc_table[CC_OP].compute_c();
1465}
1466
1467void OPPROTO op_setz_T0_cc(void)
1468{
1469 int eflags;
1470 eflags = cc_table[CC_OP].compute_all();
1471 T0 = (eflags >> 6) & 1;
1472}
1473
1474void OPPROTO op_setbe_T0_cc(void)
1475{
1476 int eflags;
1477 eflags = cc_table[CC_OP].compute_all();
1478 T0 = (eflags & (CC_Z | CC_C)) != 0;
1479}
1480
1481void OPPROTO op_sets_T0_cc(void)
1482{
1483 int eflags;
1484 eflags = cc_table[CC_OP].compute_all();
1485 T0 = (eflags >> 7) & 1;
1486}
1487
1488void OPPROTO op_setp_T0_cc(void)
1489{
1490 int eflags;
1491 eflags = cc_table[CC_OP].compute_all();
1492 T0 = (eflags >> 2) & 1;
1493}
1494
1495void OPPROTO op_setl_T0_cc(void)
1496{
1497 int eflags;
1498 eflags = cc_table[CC_OP].compute_all();
1499 T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
1500}
1501
1502void OPPROTO op_setle_T0_cc(void)
1503{
1504 int eflags;
1505 eflags = cc_table[CC_OP].compute_all();
1506 T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
1507}
1508
1509void OPPROTO op_xor_T0_1(void)
1510{
1511 T0 ^= 1;
1512}
1513
1514void OPPROTO op_set_cc_op(void)
1515{
1516 CC_OP = PARAM1;
1517}
1518
1519void OPPROTO op_mov_T0_cc(void)
1520{
1521 T0 = cc_table[CC_OP].compute_all();
1522}
1523
1524/* XXX: clear VIF/VIP in all ops ? */
1525#ifdef VBOX
1526/* XXX: AMD docs say they remain unchanged. */
1527#endif
1528
1529void OPPROTO op_movl_eflags_T0(void)
1530{
1531 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK));
1532}
1533
1534void OPPROTO op_movw_eflags_T0(void)
1535{
1536 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff);
1537}
1538
1539void OPPROTO op_movl_eflags_T0_io(void)
1540{
1541 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK));
1542}
1543
1544void OPPROTO op_movw_eflags_T0_io(void)
1545{
1546 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff);
1547}
1548
1549void OPPROTO op_movl_eflags_T0_cpl0(void)
1550{
1551 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK));
1552}
1553
1554void OPPROTO op_movw_eflags_T0_cpl0(void)
1555{
1556 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff);
1557}
1558
1559#ifndef VBOX
1560#if 0
1561/* vm86plus version */
1562void OPPROTO op_movw_eflags_T0_vm(void)
1563{
1564 int eflags;
1565 eflags = T0;
1566 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1567 DF = 1 - (2 * ((eflags >> 10) & 1));
1568 /* we also update some system flags as in user mode */
1569 env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) |
1570 (eflags & FL_UPDATE_MASK16);
1571 if (eflags & IF_MASK) {
1572 env->eflags |= VIF_MASK;
1573 if (env->eflags & VIP_MASK) {
1574 EIP = PARAM1;
1575 raise_exception(EXCP0D_GPF);
1576 }
1577 }
1578 FORCE_RET();
1579}
1580
1581void OPPROTO op_movl_eflags_T0_vm(void)
1582{
1583 int eflags;
1584 eflags = T0;
1585 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1586 DF = 1 - (2 * ((eflags >> 10) & 1));
1587 /* we also update some system flags as in user mode */
1588 env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) |
1589 (eflags & FL_UPDATE_MASK32);
1590 if (eflags & IF_MASK) {
1591 env->eflags |= VIF_MASK;
1592 if (env->eflags & VIP_MASK) {
1593 EIP = PARAM1;
1594 raise_exception(EXCP0D_GPF);
1595 }
1596 }
1597 FORCE_RET();
1598}
1599#endif
1600
1601#else /* VBOX */
1602/* IOPL != 3, CR4.VME=1 */
1603void OPPROTO op_movw_eflags_T0_vme(void)
1604{
1605 unsigned int new_eflags = T0;
1606
1607 /* if virtual interrupt pending and (virtual) interrupts will be enabled -> #GP */
1608 /* if TF will be set -> #GP */
1609 if ( ((new_eflags & IF_MASK) && (env->eflags & VIP_MASK))
1610 || (new_eflags & TF_MASK)) {
1611 raise_exception(EXCP0D_GPF);
1612 } else {
1613 load_eflags(new_eflags, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff);
1614
1615 if (new_eflags & IF_MASK) {
1616 env->eflags |= VIF_MASK;
1617 } else {
1618 env->eflags &= ~VIF_MASK;
1619 }
1620 }
1621
1622 FORCE_RET();
1623}
1624#endif /* VBOX */
1625
1626/* XXX: compute only O flag */
1627void OPPROTO op_movb_eflags_T0(void)
1628{
1629 int of;
1630 of = cc_table[CC_OP].compute_all() & CC_O;
1631 CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of;
1632}
1633
1634void OPPROTO op_movl_T0_eflags(void)
1635{
1636 int eflags;
1637 eflags = cc_table[CC_OP].compute_all();
1638 eflags |= (DF & DF_MASK);
1639 eflags |= env->eflags & ~(VM_MASK | RF_MASK);
1640 T0 = eflags;
1641}
1642
1643/* vm86plus version */
1644#ifdef VBOX /* #if 0 */
1645void OPPROTO op_movl_T0_eflags_vme(void)
1646{
1647 int eflags;
1648 eflags = cc_table[CC_OP].compute_all();
1649 eflags |= (DF & DF_MASK);
1650 eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK);
1651 if (env->eflags & VIF_MASK)
1652 eflags |= IF_MASK;
1653 T0 = eflags;
1654}
1655#endif /* VBOX / 0 */
1656
1657void OPPROTO op_cld(void)
1658{
1659 DF = 1;
1660}
1661
1662void OPPROTO op_std(void)
1663{
1664 DF = -1;
1665}
1666
1667void OPPROTO op_clc(void)
1668{
1669 int eflags;
1670 eflags = cc_table[CC_OP].compute_all();
1671 eflags &= ~CC_C;
1672 CC_SRC = eflags;
1673}
1674
1675void OPPROTO op_stc(void)
1676{
1677 int eflags;
1678 eflags = cc_table[CC_OP].compute_all();
1679 eflags |= CC_C;
1680 CC_SRC = eflags;
1681}
1682
1683void OPPROTO op_cmc(void)
1684{
1685 int eflags;
1686 eflags = cc_table[CC_OP].compute_all();
1687 eflags ^= CC_C;
1688 CC_SRC = eflags;
1689}
1690
1691void OPPROTO op_salc(void)
1692{
1693 int cf;
1694 cf = cc_table[CC_OP].compute_c();
1695 EAX = (EAX & ~0xff) | ((-cf) & 0xff);
1696}
1697
1698static int compute_all_eflags(void)
1699{
1700 return CC_SRC;
1701}
1702
1703static int compute_c_eflags(void)
1704{
1705 return CC_SRC & CC_C;
1706}
1707
1708CCTable cc_table[CC_OP_NB] = {
1709 [CC_OP_DYNAMIC] = { /* should never happen */ },
1710
1711 [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
1712
1713 [CC_OP_MULB] = { compute_all_mulb, compute_c_mull },
1714 [CC_OP_MULW] = { compute_all_mulw, compute_c_mull },
1715 [CC_OP_MULL] = { compute_all_mull, compute_c_mull },
1716
1717 [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
1718 [CC_OP_ADDW] = { compute_all_addw, compute_c_addw },
1719 [CC_OP_ADDL] = { compute_all_addl, compute_c_addl },
1720
1721 [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
1722 [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw },
1723 [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl },
1724
1725 [CC_OP_SUBB] = { compute_all_subb, compute_c_subb },
1726 [CC_OP_SUBW] = { compute_all_subw, compute_c_subw },
1727 [CC_OP_SUBL] = { compute_all_subl, compute_c_subl },
1728
1729 [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb },
1730 [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw },
1731 [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl },
1732
1733 [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
1734 [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
1735 [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
1736
1737 [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
1738 [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
1739 [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
1740
1741 [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
1742 [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
1743 [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
1744
1745 [CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb },
1746 [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw },
1747 [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
1748
1749 [CC_OP_SARB] = { compute_all_sarb, compute_c_sarl },
1750 [CC_OP_SARW] = { compute_all_sarw, compute_c_sarl },
1751 [CC_OP_SARL] = { compute_all_sarl, compute_c_sarl },
1752
1753#ifdef TARGET_X86_64
1754 [CC_OP_MULQ] = { compute_all_mulq, compute_c_mull },
1755
1756 [CC_OP_ADDQ] = { compute_all_addq, compute_c_addq },
1757
1758 [CC_OP_ADCQ] = { compute_all_adcq, compute_c_adcq },
1759
1760 [CC_OP_SUBQ] = { compute_all_subq, compute_c_subq },
1761
1762 [CC_OP_SBBQ] = { compute_all_sbbq, compute_c_sbbq },
1763
1764 [CC_OP_LOGICQ] = { compute_all_logicq, compute_c_logicq },
1765
1766 [CC_OP_INCQ] = { compute_all_incq, compute_c_incl },
1767
1768 [CC_OP_DECQ] = { compute_all_decq, compute_c_incl },
1769
1770 [CC_OP_SHLQ] = { compute_all_shlq, compute_c_shlq },
1771
1772 [CC_OP_SARQ] = { compute_all_sarq, compute_c_sarl },
1773#endif
1774};
1775
1776/* floating point support. Some of the code for complicated x87
1777 functions comes from the LGPL'ed x86 emulator found in the Willows
1778 TWIN windows emulator. */
1779
1780/* fp load FT0 */
1781
1782void OPPROTO op_flds_FT0_A0(void)
1783{
1784#ifdef USE_FP_CONVERT
1785 FP_CONVERT.i32 = ldl(A0);
1786 FT0 = FP_CONVERT.f;
1787#else
1788 FT0 = ldfl(A0);
1789#endif
1790}
1791
1792void OPPROTO op_fldl_FT0_A0(void)
1793{
1794#ifdef USE_FP_CONVERT
1795 FP_CONVERT.i64 = ldq(A0);
1796 FT0 = FP_CONVERT.d;
1797#else
1798 FT0 = ldfq(A0);
1799#endif
1800}
1801
1802/* helpers are needed to avoid static constant reference. XXX: find a better way */
1803#ifdef USE_INT_TO_FLOAT_HELPERS
1804
1805void helper_fild_FT0_A0(void)
1806{
1807 FT0 = (CPU86_LDouble)ldsw(A0);
1808}
1809
1810void helper_fildl_FT0_A0(void)
1811{
1812 FT0 = (CPU86_LDouble)((int32_t)ldl(A0));
1813}
1814
1815void helper_fildll_FT0_A0(void)
1816{
1817 FT0 = (CPU86_LDouble)((int64_t)ldq(A0));
1818}
1819
1820void OPPROTO op_fild_FT0_A0(void)
1821{
1822 helper_fild_FT0_A0();
1823}
1824
1825void OPPROTO op_fildl_FT0_A0(void)
1826{
1827 helper_fildl_FT0_A0();
1828}
1829
1830void OPPROTO op_fildll_FT0_A0(void)
1831{
1832 helper_fildll_FT0_A0();
1833}
1834
1835#else
1836
1837void OPPROTO op_fild_FT0_A0(void)
1838{
1839#ifdef USE_FP_CONVERT
1840 FP_CONVERT.i32 = ldsw(A0);
1841 FT0 = (CPU86_LDouble)FP_CONVERT.i32;
1842#else
1843 FT0 = (CPU86_LDouble)ldsw(A0);
1844#endif
1845}
1846
1847void OPPROTO op_fildl_FT0_A0(void)
1848{
1849#ifdef USE_FP_CONVERT
1850 FP_CONVERT.i32 = (int32_t) ldl(A0);
1851 FT0 = (CPU86_LDouble)FP_CONVERT.i32;
1852#else
1853 FT0 = (CPU86_LDouble)((int32_t)ldl(A0));
1854#endif
1855}
1856
1857void OPPROTO op_fildll_FT0_A0(void)
1858{
1859#ifdef USE_FP_CONVERT
1860 FP_CONVERT.i64 = (int64_t) ldq(A0);
1861 FT0 = (CPU86_LDouble)FP_CONVERT.i64;
1862#else
1863 FT0 = (CPU86_LDouble)((int64_t)ldq(A0));
1864#endif
1865}
1866#endif
1867
1868/* fp load ST0 */
1869
1870void OPPROTO op_flds_ST0_A0(void)
1871{
1872 int new_fpstt;
1873 new_fpstt = (env->fpstt - 1) & 7;
1874#ifdef USE_FP_CONVERT
1875 FP_CONVERT.i32 = ldl(A0);
1876 env->fpregs[new_fpstt].d = FP_CONVERT.f;
1877#else
1878 env->fpregs[new_fpstt].d = ldfl(A0);
1879#endif
1880 env->fpstt = new_fpstt;
1881 env->fptags[new_fpstt] = 0; /* validate stack entry */
1882}
1883
1884void OPPROTO op_fldl_ST0_A0(void)
1885{
1886 int new_fpstt;
1887 new_fpstt = (env->fpstt - 1) & 7;
1888#ifdef USE_FP_CONVERT
1889 FP_CONVERT.i64 = ldq(A0);
1890 env->fpregs[new_fpstt].d = FP_CONVERT.d;
1891#else
1892 env->fpregs[new_fpstt].d = ldfq(A0);
1893#endif
1894 env->fpstt = new_fpstt;
1895 env->fptags[new_fpstt] = 0; /* validate stack entry */
1896}
1897
1898void OPPROTO op_fldt_ST0_A0(void)
1899{
1900 helper_fldt_ST0_A0();
1901}
1902
1903/* helpers are needed to avoid static constant reference. XXX: find a better way */
1904#ifdef USE_INT_TO_FLOAT_HELPERS
1905
1906void helper_fild_ST0_A0(void)
1907{
1908 int new_fpstt;
1909 new_fpstt = (env->fpstt - 1) & 7;
1910 env->fpregs[new_fpstt].d = (CPU86_LDouble)ldsw(A0);
1911 env->fpstt = new_fpstt;
1912 env->fptags[new_fpstt] = 0; /* validate stack entry */
1913}
1914
1915void helper_fildl_ST0_A0(void)
1916{
1917 int new_fpstt;
1918 new_fpstt = (env->fpstt - 1) & 7;
1919 env->fpregs[new_fpstt].d = (CPU86_LDouble)((int32_t)ldl(A0));
1920 env->fpstt = new_fpstt;
1921 env->fptags[new_fpstt] = 0; /* validate stack entry */
1922}
1923
1924void helper_fildll_ST0_A0(void)
1925{
1926 int new_fpstt;
1927 new_fpstt = (env->fpstt - 1) & 7;
1928 env->fpregs[new_fpstt].d = (CPU86_LDouble)((int64_t)ldq(A0));
1929 env->fpstt = new_fpstt;
1930 env->fptags[new_fpstt] = 0; /* validate stack entry */
1931}
1932
1933void OPPROTO op_fild_ST0_A0(void)
1934{
1935 helper_fild_ST0_A0();
1936}
1937
1938void OPPROTO op_fildl_ST0_A0(void)
1939{
1940 helper_fildl_ST0_A0();
1941}
1942
1943void OPPROTO op_fildll_ST0_A0(void)
1944{
1945 helper_fildll_ST0_A0();
1946}
1947
1948#else
1949
1950void OPPROTO op_fild_ST0_A0(void)
1951{
1952 int new_fpstt;
1953 new_fpstt = (env->fpstt - 1) & 7;
1954#ifdef USE_FP_CONVERT
1955 FP_CONVERT.i32 = ldsw(A0);
1956 env->fpregs[new_fpstt].d = (CPU86_LDouble)FP_CONVERT.i32;
1957#else
1958 env->fpregs[new_fpstt].d = (CPU86_LDouble)ldsw(A0);
1959#endif
1960 env->fpstt = new_fpstt;
1961 env->fptags[new_fpstt] = 0; /* validate stack entry */
1962}
1963
1964void OPPROTO op_fildl_ST0_A0(void)
1965{
1966 int new_fpstt;
1967 new_fpstt = (env->fpstt - 1) & 7;
1968#ifdef USE_FP_CONVERT
1969 FP_CONVERT.i32 = (int32_t) ldl(A0);
1970 env->fpregs[new_fpstt].d = (CPU86_LDouble)FP_CONVERT.i32;
1971#else
1972 env->fpregs[new_fpstt].d = (CPU86_LDouble)((int32_t)ldl(A0));
1973#endif
1974 env->fpstt = new_fpstt;
1975 env->fptags[new_fpstt] = 0; /* validate stack entry */
1976}
1977
1978void OPPROTO op_fildll_ST0_A0(void)
1979{
1980 int new_fpstt;
1981 new_fpstt = (env->fpstt - 1) & 7;
1982#ifdef USE_FP_CONVERT
1983 FP_CONVERT.i64 = (int64_t) ldq(A0);
1984 env->fpregs[new_fpstt].d = (CPU86_LDouble)FP_CONVERT.i64;
1985#else
1986 env->fpregs[new_fpstt].d = (CPU86_LDouble)((int64_t)ldq(A0));
1987#endif
1988 env->fpstt = new_fpstt;
1989 env->fptags[new_fpstt] = 0; /* validate stack entry */
1990}
1991
1992#endif
1993
1994/* fp store */
1995
1996void OPPROTO op_fsts_ST0_A0(void)
1997{
1998#ifdef USE_FP_CONVERT
1999 FP_CONVERT.f = (float)ST0;
2000 stfl(A0, FP_CONVERT.f);
2001#else
2002 stfl(A0, (float)ST0);
2003#endif
2004 FORCE_RET();
2005}
2006
2007void OPPROTO op_fstl_ST0_A0(void)
2008{
2009 stfq(A0, (double)ST0);
2010 FORCE_RET();
2011}
2012
2013void OPPROTO op_fstt_ST0_A0(void)
2014{
2015 helper_fstt_ST0_A0();
2016}
2017
2018void OPPROTO op_fist_ST0_A0(void)
2019{
2020#if defined(__sparc__) && !defined(__sparc_v9__)
2021 register CPU86_LDouble d asm("o0");
2022#else
2023 CPU86_LDouble d;
2024#endif
2025 int val;
2026
2027 d = ST0;
2028 val = floatx_to_int32(d, &env->fp_status);
2029 if (val != (int16_t)val)
2030 val = -32768;
2031 stw(A0, val);
2032 FORCE_RET();
2033}
2034
2035void OPPROTO op_fistl_ST0_A0(void)
2036{
2037#if defined(__sparc__) && !defined(__sparc_v9__)
2038 register CPU86_LDouble d asm("o0");
2039#else
2040 CPU86_LDouble d;
2041#endif
2042 int val;
2043
2044 d = ST0;
2045 val = floatx_to_int32(d, &env->fp_status);
2046 stl(A0, val);
2047 FORCE_RET();
2048}
2049
2050void OPPROTO op_fistll_ST0_A0(void)
2051{
2052#if defined(__sparc__) && !defined(__sparc_v9__)
2053 register CPU86_LDouble d asm("o0");
2054#else
2055 CPU86_LDouble d;
2056#endif
2057 int64_t val;
2058
2059 d = ST0;
2060 val = floatx_to_int64(d, &env->fp_status);
2061 stq(A0, val);
2062 FORCE_RET();
2063}
2064
2065void OPPROTO op_fistt_ST0_A0(void)
2066{
2067#if defined(__sparc__) && !defined(__sparc_v9__)
2068 register CPU86_LDouble d asm("o0");
2069#else
2070 CPU86_LDouble d;
2071#endif
2072 int val;
2073
2074 d = ST0;
2075 val = floatx_to_int32_round_to_zero(d, &env->fp_status);
2076 if (val != (int16_t)val)
2077 val = -32768;
2078 stw(A0, val);
2079 FORCE_RET();
2080}
2081
2082void OPPROTO op_fisttl_ST0_A0(void)
2083{
2084#if defined(__sparc__) && !defined(__sparc_v9__)
2085 register CPU86_LDouble d asm("o0");
2086#else
2087 CPU86_LDouble d;
2088#endif
2089 int val;
2090
2091 d = ST0;
2092 val = floatx_to_int32_round_to_zero(d, &env->fp_status);
2093 stl(A0, val);
2094 FORCE_RET();
2095}
2096
2097void OPPROTO op_fisttll_ST0_A0(void)
2098{
2099#if defined(__sparc__) && !defined(__sparc_v9__)
2100 register CPU86_LDouble d asm("o0");
2101#else
2102 CPU86_LDouble d;
2103#endif
2104 int64_t val;
2105
2106 d = ST0;
2107 val = floatx_to_int64_round_to_zero(d, &env->fp_status);
2108 stq(A0, val);
2109 FORCE_RET();
2110}
2111
2112void OPPROTO op_fbld_ST0_A0(void)
2113{
2114 helper_fbld_ST0_A0();
2115}
2116
2117void OPPROTO op_fbst_ST0_A0(void)
2118{
2119 helper_fbst_ST0_A0();
2120}
2121
2122/* FPU move */
2123
2124void OPPROTO op_fpush(void)
2125{
2126 fpush();
2127}
2128
2129void OPPROTO op_fpop(void)
2130{
2131 fpop();
2132}
2133
2134void OPPROTO op_fdecstp(void)
2135{
2136 env->fpstt = (env->fpstt - 1) & 7;
2137 env->fpus &= (~0x4700);
2138}
2139
2140void OPPROTO op_fincstp(void)
2141{
2142 env->fpstt = (env->fpstt + 1) & 7;
2143 env->fpus &= (~0x4700);
2144}
2145
2146void OPPROTO op_ffree_STN(void)
2147{
2148 env->fptags[(env->fpstt + PARAM1) & 7] = 1;
2149}
2150
2151void OPPROTO op_fmov_ST0_FT0(void)
2152{
2153 ST0 = FT0;
2154}
2155
2156void OPPROTO op_fmov_FT0_STN(void)
2157{
2158 FT0 = ST(PARAM1);
2159}
2160
2161void OPPROTO op_fmov_ST0_STN(void)
2162{
2163 ST0 = ST(PARAM1);
2164}
2165
2166void OPPROTO op_fmov_STN_ST0(void)
2167{
2168 ST(PARAM1) = ST0;
2169}
2170
2171void OPPROTO op_fxchg_ST0_STN(void)
2172{
2173 CPU86_LDouble tmp;
2174 tmp = ST(PARAM1);
2175 ST(PARAM1) = ST0;
2176 ST0 = tmp;
2177}
2178
2179/* FPU operations */
2180
2181const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500};
2182
2183void OPPROTO op_fcom_ST0_FT0(void)
2184{
2185 int ret;
2186
2187 ret = floatx_compare(ST0, FT0, &env->fp_status);
2188 env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
2189 FORCE_RET();
2190}
2191
2192void OPPROTO op_fucom_ST0_FT0(void)
2193{
2194 int ret;
2195
2196 ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
2197 env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret+ 1];
2198 FORCE_RET();
2199}
2200
2201const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C};
2202
2203void OPPROTO op_fcomi_ST0_FT0(void)
2204{
2205 int eflags;
2206 int ret;
2207
2208 ret = floatx_compare(ST0, FT0, &env->fp_status);
2209 eflags = cc_table[CC_OP].compute_all();
2210 eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
2211 CC_SRC = eflags;
2212 FORCE_RET();
2213}
2214
2215void OPPROTO op_fucomi_ST0_FT0(void)
2216{
2217 int eflags;
2218 int ret;
2219
2220 ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
2221 eflags = cc_table[CC_OP].compute_all();
2222 eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
2223 CC_SRC = eflags;
2224 FORCE_RET();
2225}
2226
2227void OPPROTO op_fcmov_ST0_STN_T0(void)
2228{
2229 if (T0) {
2230 ST0 = ST(PARAM1);
2231 }
2232 FORCE_RET();
2233}
2234
2235void OPPROTO op_fadd_ST0_FT0(void)
2236{
2237 ST0 += FT0;
2238}
2239
2240void OPPROTO op_fmul_ST0_FT0(void)
2241{
2242 ST0 *= FT0;
2243}
2244
2245void OPPROTO op_fsub_ST0_FT0(void)
2246{
2247 ST0 -= FT0;
2248}
2249
2250void OPPROTO op_fsubr_ST0_FT0(void)
2251{
2252 ST0 = FT0 - ST0;
2253}
2254
2255void OPPROTO op_fdiv_ST0_FT0(void)
2256{
2257 ST0 = helper_fdiv(ST0, FT0);
2258}
2259
2260void OPPROTO op_fdivr_ST0_FT0(void)
2261{
2262 ST0 = helper_fdiv(FT0, ST0);
2263}
2264
2265/* fp operations between STN and ST0 */
2266
2267void OPPROTO op_fadd_STN_ST0(void)
2268{
2269 ST(PARAM1) += ST0;
2270}
2271
2272void OPPROTO op_fmul_STN_ST0(void)
2273{
2274 ST(PARAM1) *= ST0;
2275}
2276
2277void OPPROTO op_fsub_STN_ST0(void)
2278{
2279 ST(PARAM1) -= ST0;
2280}
2281
2282void OPPROTO op_fsubr_STN_ST0(void)
2283{
2284 CPU86_LDouble *p;
2285 p = &ST(PARAM1);
2286 *p = ST0 - *p;
2287}
2288
2289void OPPROTO op_fdiv_STN_ST0(void)
2290{
2291 CPU86_LDouble *p;
2292 p = &ST(PARAM1);
2293 *p = helper_fdiv(*p, ST0);
2294}
2295
2296void OPPROTO op_fdivr_STN_ST0(void)
2297{
2298 CPU86_LDouble *p;
2299 p = &ST(PARAM1);
2300 *p = helper_fdiv(ST0, *p);
2301}
2302
2303/* misc FPU operations */
2304void OPPROTO op_fchs_ST0(void)
2305{
2306 ST0 = floatx_chs(ST0);
2307}
2308
2309void OPPROTO op_fabs_ST0(void)
2310{
2311 ST0 = floatx_abs(ST0);
2312}
2313
2314void OPPROTO op_fxam_ST0(void)
2315{
2316 helper_fxam_ST0();
2317}
2318
2319void OPPROTO op_fld1_ST0(void)
2320{
2321 ST0 = f15rk[1];
2322}
2323
2324void OPPROTO op_fldl2t_ST0(void)
2325{
2326 ST0 = f15rk[6];
2327}
2328
2329void OPPROTO op_fldl2e_ST0(void)
2330{
2331 ST0 = f15rk[5];
2332}
2333
2334void OPPROTO op_fldpi_ST0(void)
2335{
2336 ST0 = f15rk[2];
2337}
2338
2339void OPPROTO op_fldlg2_ST0(void)
2340{
2341 ST0 = f15rk[3];
2342}
2343
2344void OPPROTO op_fldln2_ST0(void)
2345{
2346 ST0 = f15rk[4];
2347}
2348
2349void OPPROTO op_fldz_ST0(void)
2350{
2351 ST0 = f15rk[0];
2352}
2353
2354void OPPROTO op_fldz_FT0(void)
2355{
2356 FT0 = f15rk[0];
2357}
2358
2359/* associated heplers to reduce generated code length and to simplify
2360 relocation (FP constants are usually stored in .rodata section) */
2361
2362void OPPROTO op_f2xm1(void)
2363{
2364 helper_f2xm1();
2365}
2366
2367void OPPROTO op_fyl2x(void)
2368{
2369 helper_fyl2x();
2370}
2371
2372void OPPROTO op_fptan(void)
2373{
2374 helper_fptan();
2375}
2376
2377void OPPROTO op_fpatan(void)
2378{
2379 helper_fpatan();
2380}
2381
2382void OPPROTO op_fxtract(void)
2383{
2384 helper_fxtract();
2385}
2386
2387void OPPROTO op_fprem1(void)
2388{
2389 helper_fprem1();
2390}
2391
2392
2393void OPPROTO op_fprem(void)
2394{
2395 helper_fprem();
2396}
2397
2398void OPPROTO op_fyl2xp1(void)
2399{
2400 helper_fyl2xp1();
2401}
2402
2403void OPPROTO op_fsqrt(void)
2404{
2405 helper_fsqrt();
2406}
2407
2408void OPPROTO op_fsincos(void)
2409{
2410 helper_fsincos();
2411}
2412
2413void OPPROTO op_frndint(void)
2414{
2415 helper_frndint();
2416}
2417
2418void OPPROTO op_fscale(void)
2419{
2420 helper_fscale();
2421}
2422
2423void OPPROTO op_fsin(void)
2424{
2425 helper_fsin();
2426}
2427
2428void OPPROTO op_fcos(void)
2429{
2430 helper_fcos();
2431}
2432
2433void OPPROTO op_fnstsw_A0(void)
2434{
2435 int fpus;
2436 fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2437 stw(A0, fpus);
2438 FORCE_RET();
2439}
2440
2441void OPPROTO op_fnstsw_EAX(void)
2442{
2443 int fpus;
2444 fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2445 EAX = (EAX & ~0xffff) | fpus;
2446}
2447
2448void OPPROTO op_fnstcw_A0(void)
2449{
2450 stw(A0, env->fpuc);
2451 FORCE_RET();
2452}
2453
2454void OPPROTO op_fldcw_A0(void)
2455{
2456 env->fpuc = lduw(A0);
2457 update_fp_status();
2458}
2459
2460void OPPROTO op_fclex(void)
2461{
2462 env->fpus &= 0x7f00;
2463}
2464
2465void OPPROTO op_fwait(void)
2466{
2467 if (env->fpus & FPUS_SE)
2468 fpu_raise_exception();
2469 FORCE_RET();
2470}
2471
2472void OPPROTO op_fninit(void)
2473{
2474 env->fpus = 0;
2475 env->fpstt = 0;
2476 env->fpuc = 0x37f;
2477 env->fptags[0] = 1;
2478 env->fptags[1] = 1;
2479 env->fptags[2] = 1;
2480 env->fptags[3] = 1;
2481 env->fptags[4] = 1;
2482 env->fptags[5] = 1;
2483 env->fptags[6] = 1;
2484 env->fptags[7] = 1;
2485}
2486
2487void OPPROTO op_fnstenv_A0(void)
2488{
2489 helper_fstenv(A0, PARAM1);
2490}
2491
2492void OPPROTO op_fldenv_A0(void)
2493{
2494 helper_fldenv(A0, PARAM1);
2495}
2496
2497void OPPROTO op_fnsave_A0(void)
2498{
2499 helper_fsave(A0, PARAM1);
2500}
2501
2502void OPPROTO op_frstor_A0(void)
2503{
2504 helper_frstor(A0, PARAM1);
2505}
2506
2507/* threading support */
2508void OPPROTO op_lock(void)
2509{
2510 cpu_lock();
2511}
2512
2513void OPPROTO op_unlock(void)
2514{
2515 cpu_unlock();
2516}
2517
2518/* SSE support */
2519static inline void memcpy16(void *d, void *s)
2520{
2521 ((uint32_t *)d)[0] = ((uint32_t *)s)[0];
2522 ((uint32_t *)d)[1] = ((uint32_t *)s)[1];
2523 ((uint32_t *)d)[2] = ((uint32_t *)s)[2];
2524 ((uint32_t *)d)[3] = ((uint32_t *)s)[3];
2525}
2526
2527void OPPROTO op_movo(void)
2528{
2529 /* XXX: badly generated code */
2530 XMMReg *d, *s;
2531 d = (XMMReg *)((char *)env + PARAM1);
2532 s = (XMMReg *)((char *)env + PARAM2);
2533 memcpy16(d, s);
2534}
2535
2536void OPPROTO op_movq(void)
2537{
2538 uint64_t *d, *s;
2539 d = (uint64_t *)((char *)env + PARAM1);
2540 s = (uint64_t *)((char *)env + PARAM2);
2541 *d = *s;
2542}
2543
2544void OPPROTO op_movl(void)
2545{
2546 uint32_t *d, *s;
2547 d = (uint32_t *)((char *)env + PARAM1);
2548 s = (uint32_t *)((char *)env + PARAM2);
2549 *d = *s;
2550}
2551
2552void OPPROTO op_movq_env_0(void)
2553{
2554 uint64_t *d;
2555 d = (uint64_t *)((char *)env + PARAM1);
2556 *d = 0;
2557}
2558
2559void OPPROTO op_fxsave_A0(void)
2560{
2561 helper_fxsave(A0, PARAM1);
2562}
2563
2564void OPPROTO op_fxrstor_A0(void)
2565{
2566 helper_fxrstor(A0, PARAM1);
2567}
2568
2569/* XXX: optimize by storing fptt and fptags in the static cpu state */
2570void OPPROTO op_enter_mmx(void)
2571{
2572 env->fpstt = 0;
2573 *(uint32_t *)(env->fptags) = 0;
2574 *(uint32_t *)(env->fptags + 4) = 0;
2575}
2576
2577void OPPROTO op_emms(void)
2578{
2579 /* set to empty state */
2580 *(uint32_t *)(env->fptags) = 0x01010101;
2581 *(uint32_t *)(env->fptags + 4) = 0x01010101;
2582}
2583
2584#define SHIFT 0
2585#include "ops_sse.h"
2586
2587#define SHIFT 1
2588#include "ops_sse.h"
2589
2590#ifdef VBOX
2591/* Instantiate the structure signatures. */
2592# define REM_STRUCT_OP 1
2593# include "../Sun/structs.h"
2594#endif
2595
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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