VirtualBox

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

Last change on this file since 4672 was 2841, checked in by vboxsync, 18 years ago

Added comments about Solaris

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