VirtualBox

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

Last change on this file since 13735 was 13449, checked in by vboxsync, 16 years ago

Fixed default flags for selector register loads in real and V86 mode

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

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