VirtualBox

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

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

Support VME in guests. (v86 extensions)

  • Property svn:eol-style set to native
File size: 43.8 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 T0 = bswap64(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 {
496 sync_seg(env, idx, env->segs[idx].newselector);
497 }
498 A0 = (uint32_t)env->segs[idx].base;
499#else
500 A0 = (uint32_t)*(target_ulong *)((char *)env + PARAM1);
501#endif
502}
503
504void OPPROTO op_addl_A0_seg(void)
505{
506#ifdef VBOX
507 uint32_t idx = (PARAM1 - offsetof(CPUX86State,segs[0].base)) / sizeof(SegmentCache);
508
509 if (env->segs[idx].newselector && !(env->eflags & VM_MASK))
510 {
511 sync_seg(env, idx, env->segs[idx].newselector);
512 }
513 A0 = (uint32_t)(A0 + env->segs[idx].base);
514#else
515 A0 = (uint32_t)(A0 + *(target_ulong *)((char *)env + PARAM1));
516#endif
517}
518
519void OPPROTO op_addl_A0_AL(void)
520{
521 A0 = (uint32_t)(A0 + (EAX & 0xff));
522}
523
524#ifdef WORDS_BIGENDIAN
525typedef union UREG64 {
526 struct { uint16_t v3, v2, v1, v0; } w;
527 struct { uint32_t v1, v0; } l;
528 uint64_t q;
529} UREG64;
530#else
531typedef union UREG64 {
532 struct { uint16_t v0, v1, v2, v3; } w;
533 struct { uint32_t v0, v1; } l;
534 uint64_t q;
535} UREG64;
536#endif
537
538#ifdef TARGET_X86_64
539
540#define PARAMQ1 \
541({\
542 UREG64 __p;\
543 __p.l.v1 = PARAM1;\
544 __p.l.v0 = PARAM2;\
545 __p.q;\
546})
547
548void OPPROTO op_movq_T0_im64(void)
549{
550 T0 = PARAMQ1;
551}
552
553void OPPROTO op_movq_T1_im64(void)
554{
555 T1 = PARAMQ1;
556}
557
558void OPPROTO op_movq_A0_im(void)
559{
560 A0 = (int32_t)PARAM1;
561}
562
563void OPPROTO op_movq_A0_im64(void)
564{
565 A0 = PARAMQ1;
566}
567
568void OPPROTO op_addq_A0_im(void)
569{
570 A0 = (A0 + (int32_t)PARAM1);
571}
572
573void OPPROTO op_addq_A0_im64(void)
574{
575 A0 = (A0 + PARAMQ1);
576}
577
578void OPPROTO op_movq_A0_seg(void)
579{
580#ifdef VBOX
581 uint32_t idx = (PARAM1 - offsetof(CPUX86State,segs[0].base)) / sizeof(SegmentCache);
582
583 if (env->segs[idx].newselector && !(env->eflags & VM_MASK))
584 {
585 sync_seg(env, idx, env->segs[idx].newselector);
586 }
587 A0 = (target_ulong)env->segs[idx].base;
588#else
589 A0 = *(target_ulong *)((char *)env + PARAM1);
590#endif
591}
592
593void OPPROTO op_addq_A0_seg(void)
594{
595#ifdef VBOX
596 uint32_t idx = (PARAM1 - offsetof(CPUX86State,segs[0].base)) / sizeof(SegmentCache);
597
598 if (env->segs[idx].newselector && !(env->eflags & VM_MASK))
599 {
600 sync_seg(env, idx, env->segs[idx].newselector);
601 }
602 A0 += (target_ulong)env->segs[idx].base;
603#else
604 A0 += *(target_ulong *)((char *)env + PARAM1);
605#endif
606}
607
608void OPPROTO op_addq_A0_AL(void)
609{
610 A0 = (A0 + (EAX & 0xff));
611}
612
613#endif
614
615void OPPROTO op_andl_A0_ffff(void)
616{
617 A0 = A0 & 0xffff;
618}
619
620/* memory access */
621
622#define MEMSUFFIX _raw
623#include "ops_mem.h"
624
625#if !defined(CONFIG_USER_ONLY)
626#define MEMSUFFIX _kernel
627#include "ops_mem.h"
628
629#define MEMSUFFIX _user
630#include "ops_mem.h"
631#endif
632
633/* indirect jump */
634
635void OPPROTO op_jmp_T0(void)
636{
637 EIP = T0;
638}
639
640void OPPROTO op_movl_eip_im(void)
641{
642 EIP = (uint32_t)PARAM1;
643}
644
645#ifdef TARGET_X86_64
646void OPPROTO op_movq_eip_im(void)
647{
648 EIP = (int32_t)PARAM1;
649}
650
651void OPPROTO op_movq_eip_im64(void)
652{
653 EIP = PARAMQ1;
654}
655#endif
656
657void OPPROTO op_hlt(void)
658{
659 helper_hlt();
660}
661
662void OPPROTO op_monitor(void)
663{
664 helper_monitor();
665}
666
667void OPPROTO op_mwait(void)
668{
669 helper_mwait();
670}
671
672void OPPROTO op_debug(void)
673{
674 env->exception_index = EXCP_DEBUG;
675 cpu_loop_exit();
676}
677
678void OPPROTO op_raise_interrupt(void)
679{
680 int intno, next_eip_addend;
681 intno = PARAM1;
682 next_eip_addend = PARAM2;
683 raise_interrupt(intno, 1, 0, next_eip_addend);
684}
685
686void OPPROTO op_raise_exception(void)
687{
688 int exception_index;
689 exception_index = PARAM1;
690 raise_exception(exception_index);
691}
692
693void OPPROTO op_into(void)
694{
695 int eflags;
696 eflags = cc_table[CC_OP].compute_all();
697 if (eflags & CC_O) {
698 raise_interrupt(EXCP04_INTO, 1, 0, PARAM1);
699 }
700 FORCE_RET();
701}
702
703void OPPROTO op_cli(void)
704{
705 env->eflags &= ~IF_MASK;
706}
707
708void OPPROTO op_sti(void)
709{
710 env->eflags |= IF_MASK;
711}
712
713void OPPROTO op_set_inhibit_irq(void)
714{
715 env->hflags |= HF_INHIBIT_IRQ_MASK;
716}
717
718void OPPROTO op_reset_inhibit_irq(void)
719{
720 env->hflags &= ~HF_INHIBIT_IRQ_MASK;
721}
722
723#ifdef VBOX
724/* vm86plus instructions */
725void OPPROTO op_cli_vme(void)
726{
727 env->eflags &= ~VIF_MASK;
728}
729
730void OPPROTO op_sti_vme(void)
731{
732 /* First check, then change eflags according to the AMD manual */
733 if (env->eflags & VIP_MASK) {
734 raise_exception(EXCP0D_GPF);
735 }
736 env->eflags |= VIF_MASK;
737 FORCE_RET();
738}
739#endif
740
741void OPPROTO op_boundw(void)
742{
743 int low, high, v;
744 low = ldsw(A0);
745 high = ldsw(A0 + 2);
746 v = (int16_t)T0;
747 if (v < low || v > high) {
748 raise_exception(EXCP05_BOUND);
749 }
750 FORCE_RET();
751}
752
753void OPPROTO op_boundl(void)
754{
755 int low, high, v;
756 low = ldl(A0);
757 high = ldl(A0 + 4);
758 v = T0;
759 if (v < low || v > high) {
760 raise_exception(EXCP05_BOUND);
761 }
762 FORCE_RET();
763}
764
765void OPPROTO op_cmpxchg8b(void)
766{
767 helper_cmpxchg8b();
768}
769
770void OPPROTO op_movl_T0_0(void)
771{
772 T0 = 0;
773}
774
775#ifdef VBOX
776
777/** @todo Ugly: Exit current TB to process an external interrupt request */
778#define CPU_INTERRUPT_EXTERNAL_EXIT 0x0200 /* also defined in cpu-all.h!! */
779#define CPU_INTERRUPT_EXTERNAL_HARD 0x0400 /* also defined in cpu-all.h!! */
780#define CPU_INTERRUPT_EXTERNAL_TIMER 0x0800 /* also defined in cpu-all.h!! */
781#define CPU_INTERRUPT_EXTERNAL_DMA 0x1000 /* also defined in cpu-all.h!! */
782
783void OPPROTO op_check_external_event(void)
784{
785 if ( (env->interrupt_request & ( CPU_INTERRUPT_EXTERNAL_EXIT
786 | CPU_INTERRUPT_EXTERNAL_TIMER
787 | CPU_INTERRUPT_EXTERNAL_DMA))
788 || ( (env->interrupt_request & CPU_INTERRUPT_EXTERNAL_HARD)
789 && (env->eflags & IF_MASK)
790 && !(env->hflags & HF_INHIBIT_IRQ_MASK) ) )
791 {
792 helper_external_event();
793 }
794}
795#endif /* VBOX */
796
797void OPPROTO op_exit_tb(void)
798{
799 EXIT_TB();
800}
801
802/* multiple size ops */
803
804#define ldul ldl
805
806#define SHIFT 0
807#include "ops_template.h"
808#undef SHIFT
809
810#define SHIFT 1
811#include "ops_template.h"
812#undef SHIFT
813
814#define SHIFT 2
815#include "ops_template.h"
816#undef SHIFT
817
818#ifdef TARGET_X86_64
819
820#define SHIFT 3
821#include "ops_template.h"
822#undef SHIFT
823
824#endif
825
826/* sign extend */
827
828void OPPROTO op_movsbl_T0_T0(void)
829{
830 T0 = (int8_t)T0;
831}
832
833void OPPROTO op_movzbl_T0_T0(void)
834{
835 T0 = (uint8_t)T0;
836}
837
838void OPPROTO op_movswl_T0_T0(void)
839{
840 T0 = (int16_t)T0;
841}
842
843void OPPROTO op_movzwl_T0_T0(void)
844{
845 T0 = (uint16_t)T0;
846}
847
848void OPPROTO op_movswl_EAX_AX(void)
849{
850 EAX = (int16_t)EAX;
851}
852
853#ifdef TARGET_X86_64
854void OPPROTO op_movslq_T0_T0(void)
855{
856 T0 = (int32_t)T0;
857}
858
859void OPPROTO op_movslq_RAX_EAX(void)
860{
861 EAX = (int32_t)EAX;
862}
863#endif
864
865void OPPROTO op_movsbw_AX_AL(void)
866{
867 EAX = (EAX & ~0xffff) | ((int8_t)EAX & 0xffff);
868}
869
870void OPPROTO op_movslq_EDX_EAX(void)
871{
872 EDX = (int32_t)EAX >> 31;
873}
874
875void OPPROTO op_movswl_DX_AX(void)
876{
877 EDX = (EDX & ~0xffff) | (((int16_t)EAX >> 15) & 0xffff);
878}
879
880#ifdef TARGET_X86_64
881void OPPROTO op_movsqo_RDX_RAX(void)
882{
883 EDX = (int64_t)EAX >> 63;
884}
885#endif
886
887/* string ops helpers */
888
889void OPPROTO op_addl_ESI_T0(void)
890{
891 ESI = (uint32_t)(ESI + T0);
892}
893
894void OPPROTO op_addw_ESI_T0(void)
895{
896 ESI = (ESI & ~0xffff) | ((ESI + T0) & 0xffff);
897}
898
899void OPPROTO op_addl_EDI_T0(void)
900{
901 EDI = (uint32_t)(EDI + T0);
902}
903
904void OPPROTO op_addw_EDI_T0(void)
905{
906 EDI = (EDI & ~0xffff) | ((EDI + T0) & 0xffff);
907}
908
909void OPPROTO op_decl_ECX(void)
910{
911 ECX = (uint32_t)(ECX - 1);
912}
913
914void OPPROTO op_decw_ECX(void)
915{
916 ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff);
917}
918
919#ifdef TARGET_X86_64
920void OPPROTO op_addq_ESI_T0(void)
921{
922 ESI = (ESI + T0);
923}
924
925void OPPROTO op_addq_EDI_T0(void)
926{
927 EDI = (EDI + T0);
928}
929
930void OPPROTO op_decq_ECX(void)
931{
932 ECX--;
933}
934#endif
935
936/* push/pop utils */
937
938void op_addl_A0_SS(void)
939{
940 A0 += (long)env->segs[R_SS].base;
941}
942
943void op_subl_A0_2(void)
944{
945 A0 = (uint32_t)(A0 - 2);
946}
947
948void op_subl_A0_4(void)
949{
950 A0 = (uint32_t)(A0 - 4);
951}
952
953void op_addl_ESP_4(void)
954{
955 ESP = (uint32_t)(ESP + 4);
956}
957
958void op_addl_ESP_2(void)
959{
960 ESP = (uint32_t)(ESP + 2);
961}
962
963void op_addw_ESP_4(void)
964{
965 ESP = (ESP & ~0xffff) | ((ESP + 4) & 0xffff);
966}
967
968void op_addw_ESP_2(void)
969{
970 ESP = (ESP & ~0xffff) | ((ESP + 2) & 0xffff);
971}
972
973void op_addl_ESP_im(void)
974{
975 ESP = (uint32_t)(ESP + PARAM1);
976}
977
978void op_addw_ESP_im(void)
979{
980 ESP = (ESP & ~0xffff) | ((ESP + PARAM1) & 0xffff);
981}
982
983#ifdef TARGET_X86_64
984void op_subq_A0_8(void)
985{
986 A0 -= 8;
987}
988
989void op_addq_ESP_8(void)
990{
991 ESP += 8;
992}
993
994void op_addq_ESP_im(void)
995{
996 ESP += PARAM1;
997}
998#endif
999
1000void OPPROTO op_rdtsc(void)
1001{
1002 helper_rdtsc();
1003}
1004
1005void OPPROTO op_cpuid(void)
1006{
1007 helper_cpuid();
1008}
1009
1010void OPPROTO op_enter_level(void)
1011{
1012 helper_enter_level(PARAM1, PARAM2);
1013}
1014
1015void OPPROTO op_sysenter(void)
1016{
1017 helper_sysenter();
1018}
1019
1020void OPPROTO op_sysexit(void)
1021{
1022 helper_sysexit();
1023}
1024
1025#ifdef TARGET_X86_64
1026void OPPROTO op_syscall(void)
1027{
1028 helper_syscall(PARAM1);
1029}
1030
1031void OPPROTO op_sysret(void)
1032{
1033 helper_sysret(PARAM1);
1034}
1035#endif
1036
1037void OPPROTO op_rdmsr(void)
1038{
1039 helper_rdmsr();
1040}
1041
1042void OPPROTO op_wrmsr(void)
1043{
1044 helper_wrmsr();
1045}
1046
1047/* bcd */
1048
1049/* XXX: exception */
1050void OPPROTO op_aam(void)
1051{
1052 int base = PARAM1;
1053 int al, ah;
1054 al = EAX & 0xff;
1055 ah = al / base;
1056 al = al % base;
1057 EAX = (EAX & ~0xffff) | al | (ah << 8);
1058 CC_DST = al;
1059}
1060
1061void OPPROTO op_aad(void)
1062{
1063 int base = PARAM1;
1064 int al, ah;
1065 al = EAX & 0xff;
1066 ah = (EAX >> 8) & 0xff;
1067 al = ((ah * base) + al) & 0xff;
1068 EAX = (EAX & ~0xffff) | al;
1069 CC_DST = al;
1070}
1071
1072void OPPROTO op_aaa(void)
1073{
1074 int icarry;
1075 int al, ah, af;
1076 int eflags;
1077
1078 eflags = cc_table[CC_OP].compute_all();
1079 af = eflags & CC_A;
1080 al = EAX & 0xff;
1081 ah = (EAX >> 8) & 0xff;
1082
1083 icarry = (al > 0xf9);
1084 if (((al & 0x0f) > 9 ) || af) {
1085 al = (al + 6) & 0x0f;
1086 ah = (ah + 1 + icarry) & 0xff;
1087 eflags |= CC_C | CC_A;
1088 } else {
1089 eflags &= ~(CC_C | CC_A);
1090 al &= 0x0f;
1091 }
1092 EAX = (EAX & ~0xffff) | al | (ah << 8);
1093 CC_SRC = eflags;
1094 FORCE_RET();
1095}
1096
1097void OPPROTO op_aas(void)
1098{
1099 int icarry;
1100 int al, ah, af;
1101 int eflags;
1102
1103 eflags = cc_table[CC_OP].compute_all();
1104 af = eflags & CC_A;
1105 al = EAX & 0xff;
1106 ah = (EAX >> 8) & 0xff;
1107
1108 icarry = (al < 6);
1109 if (((al & 0x0f) > 9 ) || af) {
1110 al = (al - 6) & 0x0f;
1111 ah = (ah - 1 - icarry) & 0xff;
1112 eflags |= CC_C | CC_A;
1113 } else {
1114 eflags &= ~(CC_C | CC_A);
1115 al &= 0x0f;
1116 }
1117 EAX = (EAX & ~0xffff) | al | (ah << 8);
1118 CC_SRC = eflags;
1119 FORCE_RET();
1120}
1121
1122void OPPROTO op_daa(void)
1123{
1124 int al, af, cf;
1125 int eflags;
1126
1127 eflags = cc_table[CC_OP].compute_all();
1128 cf = eflags & CC_C;
1129 af = eflags & CC_A;
1130 al = EAX & 0xff;
1131
1132 eflags = 0;
1133 if (((al & 0x0f) > 9 ) || af) {
1134 al = (al + 6) & 0xff;
1135 eflags |= CC_A;
1136 }
1137 if ((al > 0x9f) || cf) {
1138 al = (al + 0x60) & 0xff;
1139 eflags |= CC_C;
1140 }
1141 EAX = (EAX & ~0xff) | al;
1142 /* well, speed is not an issue here, so we compute the flags by hand */
1143 eflags |= (al == 0) << 6; /* zf */
1144 eflags |= parity_table[al]; /* pf */
1145 eflags |= (al & 0x80); /* sf */
1146 CC_SRC = eflags;
1147 FORCE_RET();
1148}
1149
1150void OPPROTO op_das(void)
1151{
1152 int al, al1, af, cf;
1153 int eflags;
1154
1155 eflags = cc_table[CC_OP].compute_all();
1156 cf = eflags & CC_C;
1157 af = eflags & CC_A;
1158 al = EAX & 0xff;
1159
1160 eflags = 0;
1161 al1 = al;
1162 if (((al & 0x0f) > 9 ) || af) {
1163 eflags |= CC_A;
1164 if (al < 6 || cf)
1165 eflags |= CC_C;
1166 al = (al - 6) & 0xff;
1167 }
1168 if ((al1 > 0x99) || cf) {
1169 al = (al - 0x60) & 0xff;
1170 eflags |= CC_C;
1171 }
1172 EAX = (EAX & ~0xff) | al;
1173 /* well, speed is not an issue here, so we compute the flags by hand */
1174 eflags |= (al == 0) << 6; /* zf */
1175 eflags |= parity_table[al]; /* pf */
1176 eflags |= (al & 0x80); /* sf */
1177 CC_SRC = eflags;
1178 FORCE_RET();
1179}
1180
1181/* segment handling */
1182
1183/* never use it with R_CS */
1184void OPPROTO op_movl_seg_T0(void)
1185{
1186 load_seg(PARAM1, T0);
1187}
1188
1189/* faster VM86 version */
1190void OPPROTO op_movl_seg_T0_vm(void)
1191{
1192 int selector;
1193 SegmentCache *sc;
1194
1195 selector = T0 & 0xffff;
1196 /* env->segs[] access */
1197 sc = (SegmentCache *)((char *)env + PARAM1);
1198 sc->selector = selector;
1199 sc->base = (selector << 4);
1200#ifdef VBOX
1201 sc->flags = 0; /* clear attributes */
1202#endif
1203}
1204
1205void OPPROTO op_movl_T0_seg(void)
1206{
1207 T0 = env->segs[PARAM1].selector;
1208}
1209
1210void OPPROTO op_lsl(void)
1211{
1212 helper_lsl();
1213}
1214
1215void OPPROTO op_lar(void)
1216{
1217 helper_lar();
1218}
1219
1220void OPPROTO op_verr(void)
1221{
1222 helper_verr();
1223}
1224
1225void OPPROTO op_verw(void)
1226{
1227 helper_verw();
1228}
1229
1230void OPPROTO op_arpl(void)
1231{
1232 if ((T0 & 3) < (T1 & 3)) {
1233 /* XXX: emulate bug or 0xff3f0000 oring as in bochs ? */
1234 T0 = (T0 & ~3) | (T1 & 3);
1235 T1 = CC_Z;
1236 } else {
1237 T1 = 0;
1238 }
1239 FORCE_RET();
1240}
1241
1242void OPPROTO op_arpl_update(void)
1243{
1244 int eflags;
1245 eflags = cc_table[CC_OP].compute_all();
1246 CC_SRC = (eflags & ~CC_Z) | T1;
1247}
1248
1249/* T0: segment, T1:eip */
1250void OPPROTO op_ljmp_protected_T0_T1(void)
1251{
1252 helper_ljmp_protected_T0_T1(PARAM1);
1253}
1254
1255void OPPROTO op_lcall_real_T0_T1(void)
1256{
1257 helper_lcall_real_T0_T1(PARAM1, PARAM2);
1258}
1259
1260void OPPROTO op_lcall_protected_T0_T1(void)
1261{
1262 helper_lcall_protected_T0_T1(PARAM1, PARAM2);
1263}
1264
1265void OPPROTO op_iret_real(void)
1266{
1267 helper_iret_real(PARAM1);
1268}
1269
1270void OPPROTO op_iret_protected(void)
1271{
1272 helper_iret_protected(PARAM1, PARAM2);
1273}
1274
1275void OPPROTO op_lret_protected(void)
1276{
1277 helper_lret_protected(PARAM1, PARAM2);
1278}
1279
1280void OPPROTO op_lldt_T0(void)
1281{
1282 helper_lldt_T0();
1283}
1284
1285void OPPROTO op_ltr_T0(void)
1286{
1287 helper_ltr_T0();
1288}
1289
1290/* CR registers access */
1291void OPPROTO op_movl_crN_T0(void)
1292{
1293 helper_movl_crN_T0(PARAM1);
1294}
1295
1296#if !defined(CONFIG_USER_ONLY)
1297void OPPROTO op_movtl_T0_cr8(void)
1298{
1299 T0 = cpu_get_apic_tpr(env);
1300}
1301#endif
1302
1303/* DR registers access */
1304void OPPROTO op_movl_drN_T0(void)
1305{
1306 helper_movl_drN_T0(PARAM1);
1307}
1308
1309void OPPROTO op_lmsw_T0(void)
1310{
1311 /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
1312 if already set to one. */
1313 T0 = (env->cr[0] & ~0xe) | (T0 & 0xf);
1314 helper_movl_crN_T0(0);
1315}
1316
1317void OPPROTO op_invlpg_A0(void)
1318{
1319 helper_invlpg(A0);
1320}
1321
1322void OPPROTO op_movl_T0_env(void)
1323{
1324 T0 = *(uint32_t *)((char *)env + PARAM1);
1325}
1326
1327void OPPROTO op_movl_env_T0(void)
1328{
1329 *(uint32_t *)((char *)env + PARAM1) = T0;
1330}
1331
1332void OPPROTO op_movl_env_T1(void)
1333{
1334 *(uint32_t *)((char *)env + PARAM1) = T1;
1335}
1336
1337void OPPROTO op_movtl_T0_env(void)
1338{
1339 T0 = *(target_ulong *)((char *)env + PARAM1);
1340}
1341
1342void OPPROTO op_movtl_env_T0(void)
1343{
1344 *(target_ulong *)((char *)env + PARAM1) = T0;
1345}
1346
1347void OPPROTO op_movtl_T1_env(void)
1348{
1349 T1 = *(target_ulong *)((char *)env + PARAM1);
1350}
1351
1352void OPPROTO op_movtl_env_T1(void)
1353{
1354 *(target_ulong *)((char *)env + PARAM1) = T1;
1355}
1356
1357void OPPROTO op_clts(void)
1358{
1359 env->cr[0] &= ~CR0_TS_MASK;
1360 env->hflags &= ~HF_TS_MASK;
1361}
1362
1363/* flags handling */
1364
1365void OPPROTO op_goto_tb0(void)
1366{
1367 GOTO_TB(op_goto_tb0, PARAM1, 0);
1368}
1369
1370void OPPROTO op_goto_tb1(void)
1371{
1372 GOTO_TB(op_goto_tb1, PARAM1, 1);
1373}
1374
1375void OPPROTO op_jmp_label(void)
1376{
1377 GOTO_LABEL_PARAM(1);
1378}
1379
1380void OPPROTO op_jnz_T0_label(void)
1381{
1382 if (T0)
1383 GOTO_LABEL_PARAM(1);
1384 FORCE_RET();
1385}
1386
1387void OPPROTO op_jz_T0_label(void)
1388{
1389 if (!T0)
1390 GOTO_LABEL_PARAM(1);
1391 FORCE_RET();
1392}
1393
1394/* slow set cases (compute x86 flags) */
1395void OPPROTO op_seto_T0_cc(void)
1396{
1397 int eflags;
1398 eflags = cc_table[CC_OP].compute_all();
1399 T0 = (eflags >> 11) & 1;
1400}
1401
1402void OPPROTO op_setb_T0_cc(void)
1403{
1404 T0 = cc_table[CC_OP].compute_c();
1405}
1406
1407void OPPROTO op_setz_T0_cc(void)
1408{
1409 int eflags;
1410 eflags = cc_table[CC_OP].compute_all();
1411 T0 = (eflags >> 6) & 1;
1412}
1413
1414void OPPROTO op_setbe_T0_cc(void)
1415{
1416 int eflags;
1417 eflags = cc_table[CC_OP].compute_all();
1418 T0 = (eflags & (CC_Z | CC_C)) != 0;
1419}
1420
1421void OPPROTO op_sets_T0_cc(void)
1422{
1423 int eflags;
1424 eflags = cc_table[CC_OP].compute_all();
1425 T0 = (eflags >> 7) & 1;
1426}
1427
1428void OPPROTO op_setp_T0_cc(void)
1429{
1430 int eflags;
1431 eflags = cc_table[CC_OP].compute_all();
1432 T0 = (eflags >> 2) & 1;
1433}
1434
1435void OPPROTO op_setl_T0_cc(void)
1436{
1437 int eflags;
1438 eflags = cc_table[CC_OP].compute_all();
1439 T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
1440}
1441
1442void OPPROTO op_setle_T0_cc(void)
1443{
1444 int eflags;
1445 eflags = cc_table[CC_OP].compute_all();
1446 T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
1447}
1448
1449void OPPROTO op_xor_T0_1(void)
1450{
1451 T0 ^= 1;
1452}
1453
1454void OPPROTO op_set_cc_op(void)
1455{
1456 CC_OP = PARAM1;
1457}
1458
1459void OPPROTO op_mov_T0_cc(void)
1460{
1461 T0 = cc_table[CC_OP].compute_all();
1462}
1463
1464/* XXX: clear VIF/VIP in all ops ? */
1465#ifdef VBOX
1466/* XXX: AMD docs say they remain unchanged. */
1467#endif
1468
1469void OPPROTO op_movl_eflags_T0(void)
1470{
1471 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK));
1472}
1473
1474void OPPROTO op_movw_eflags_T0(void)
1475{
1476 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff);
1477}
1478
1479void OPPROTO op_movl_eflags_T0_io(void)
1480{
1481 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK));
1482}
1483
1484void OPPROTO op_movw_eflags_T0_io(void)
1485{
1486 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff);
1487}
1488
1489void OPPROTO op_movl_eflags_T0_cpl0(void)
1490{
1491 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK));
1492}
1493
1494void OPPROTO op_movw_eflags_T0_cpl0(void)
1495{
1496 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff);
1497}
1498
1499/* vm86plus version */
1500#ifdef VBOX
1501/* IOPL != 3, CR4.VME=1 */
1502void OPPROTO op_movw_eflags_T0_vme(void)
1503{
1504 unsigned int new_eflags = T0;
1505
1506 /* if virtual interrupt pending and (virtual) interrupts will be enabled -> #GP */
1507 /* if TF will be set -> #GP */
1508 if ( ((new_eflags & IF_MASK) && (env->eflags & VIP_MASK))
1509 || (new_eflags & TF_MASK))
1510 {
1511 raise_exception(EXCP0D_GPF);
1512 }
1513 else
1514 {
1515 load_eflags(new_eflags, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff);
1516
1517 if (new_eflags & IF_MASK)
1518 env->eflags |= VIF_MASK;
1519 else
1520 env->eflags &= ~VIF_MASK;
1521 }
1522
1523 FORCE_RET();
1524}
1525#endif
1526
1527#if 0
1528void OPPROTO op_movl_eflags_T0_vm(void)
1529{
1530 int eflags;
1531 eflags = T0;
1532 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1533 DF = 1 - (2 * ((eflags >> 10) & 1));
1534 /* we also update some system flags as in user mode */
1535 env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) |
1536 (eflags & FL_UPDATE_MASK32);
1537 if (eflags & IF_MASK) {
1538 env->eflags |= VIF_MASK;
1539 if (env->eflags & VIP_MASK) {
1540 EIP = PARAM1;
1541 raise_exception(EXCP0D_GPF);
1542 }
1543 }
1544 FORCE_RET();
1545}
1546#endif
1547
1548/* XXX: compute only O flag */
1549void OPPROTO op_movb_eflags_T0(void)
1550{
1551 int of;
1552 of = cc_table[CC_OP].compute_all() & CC_O;
1553 CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of;
1554}
1555
1556void OPPROTO op_movl_T0_eflags(void)
1557{
1558 int eflags;
1559 eflags = cc_table[CC_OP].compute_all();
1560 eflags |= (DF & DF_MASK);
1561 eflags |= env->eflags & ~(VM_MASK | RF_MASK);
1562 T0 = eflags;
1563}
1564
1565/* vm86plus version */
1566#ifdef VBOX
1567void OPPROTO op_movl_T0_eflags_vme(void)
1568{
1569 int eflags;
1570 eflags = cc_table[CC_OP].compute_all();
1571 eflags |= (DF & DF_MASK);
1572 eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK);
1573 if (env->eflags & VIF_MASK)
1574 eflags |= IF_MASK;
1575 T0 = eflags;
1576}
1577#endif
1578
1579void OPPROTO op_cld(void)
1580{
1581 DF = 1;
1582}
1583
1584void OPPROTO op_std(void)
1585{
1586 DF = -1;
1587}
1588
1589void OPPROTO op_clc(void)
1590{
1591 int eflags;
1592 eflags = cc_table[CC_OP].compute_all();
1593 eflags &= ~CC_C;
1594 CC_SRC = eflags;
1595}
1596
1597void OPPROTO op_stc(void)
1598{
1599 int eflags;
1600 eflags = cc_table[CC_OP].compute_all();
1601 eflags |= CC_C;
1602 CC_SRC = eflags;
1603}
1604
1605void OPPROTO op_cmc(void)
1606{
1607 int eflags;
1608 eflags = cc_table[CC_OP].compute_all();
1609 eflags ^= CC_C;
1610 CC_SRC = eflags;
1611}
1612
1613void OPPROTO op_salc(void)
1614{
1615 int cf;
1616 cf = cc_table[CC_OP].compute_c();
1617 EAX = (EAX & ~0xff) | ((-cf) & 0xff);
1618}
1619
1620static int compute_all_eflags(void)
1621{
1622 return CC_SRC;
1623}
1624
1625static int compute_c_eflags(void)
1626{
1627 return CC_SRC & CC_C;
1628}
1629
1630CCTable cc_table[CC_OP_NB] = {
1631 [CC_OP_DYNAMIC] = { /* should never happen */ },
1632
1633 [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
1634
1635 [CC_OP_MULB] = { compute_all_mulb, compute_c_mull },
1636 [CC_OP_MULW] = { compute_all_mulw, compute_c_mull },
1637 [CC_OP_MULL] = { compute_all_mull, compute_c_mull },
1638
1639 [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
1640 [CC_OP_ADDW] = { compute_all_addw, compute_c_addw },
1641 [CC_OP_ADDL] = { compute_all_addl, compute_c_addl },
1642
1643 [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
1644 [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw },
1645 [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl },
1646
1647 [CC_OP_SUBB] = { compute_all_subb, compute_c_subb },
1648 [CC_OP_SUBW] = { compute_all_subw, compute_c_subw },
1649 [CC_OP_SUBL] = { compute_all_subl, compute_c_subl },
1650
1651 [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb },
1652 [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw },
1653 [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl },
1654
1655 [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
1656 [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
1657 [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
1658
1659 [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
1660 [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
1661 [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
1662
1663 [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
1664 [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
1665 [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
1666
1667 [CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb },
1668 [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw },
1669 [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
1670
1671 [CC_OP_SARB] = { compute_all_sarb, compute_c_sarl },
1672 [CC_OP_SARW] = { compute_all_sarw, compute_c_sarl },
1673 [CC_OP_SARL] = { compute_all_sarl, compute_c_sarl },
1674
1675#ifdef TARGET_X86_64
1676 [CC_OP_MULQ] = { compute_all_mulq, compute_c_mull },
1677
1678 [CC_OP_ADDQ] = { compute_all_addq, compute_c_addq },
1679
1680 [CC_OP_ADCQ] = { compute_all_adcq, compute_c_adcq },
1681
1682 [CC_OP_SUBQ] = { compute_all_subq, compute_c_subq },
1683
1684 [CC_OP_SBBQ] = { compute_all_sbbq, compute_c_sbbq },
1685
1686 [CC_OP_LOGICQ] = { compute_all_logicq, compute_c_logicq },
1687
1688 [CC_OP_INCQ] = { compute_all_incq, compute_c_incl },
1689
1690 [CC_OP_DECQ] = { compute_all_decq, compute_c_incl },
1691
1692 [CC_OP_SHLQ] = { compute_all_shlq, compute_c_shlq },
1693
1694 [CC_OP_SARQ] = { compute_all_sarq, compute_c_sarl },
1695#endif
1696};
1697
1698/* floating point support. Some of the code for complicated x87
1699 functions comes from the LGPL'ed x86 emulator found in the Willows
1700 TWIN windows emulator. */
1701
1702/* fp load FT0 */
1703
1704void OPPROTO op_flds_FT0_A0(void)
1705{
1706#ifdef USE_FP_CONVERT
1707 FP_CONVERT.i32 = ldl(A0);
1708 FT0 = FP_CONVERT.f;
1709#else
1710 FT0 = ldfl(A0);
1711#endif
1712}
1713
1714void OPPROTO op_fldl_FT0_A0(void)
1715{
1716#ifdef USE_FP_CONVERT
1717 FP_CONVERT.i64 = ldq(A0);
1718 FT0 = FP_CONVERT.d;
1719#else
1720 FT0 = ldfq(A0);
1721#endif
1722}
1723
1724/* helpers are needed to avoid static constant reference. XXX: find a better way */
1725#ifdef USE_INT_TO_FLOAT_HELPERS
1726
1727void helper_fild_FT0_A0(void)
1728{
1729 FT0 = (CPU86_LDouble)ldsw(A0);
1730}
1731
1732void helper_fildl_FT0_A0(void)
1733{
1734 FT0 = (CPU86_LDouble)((int32_t)ldl(A0));
1735}
1736
1737void helper_fildll_FT0_A0(void)
1738{
1739 FT0 = (CPU86_LDouble)((int64_t)ldq(A0));
1740}
1741
1742void OPPROTO op_fild_FT0_A0(void)
1743{
1744 helper_fild_FT0_A0();
1745}
1746
1747void OPPROTO op_fildl_FT0_A0(void)
1748{
1749 helper_fildl_FT0_A0();
1750}
1751
1752void OPPROTO op_fildll_FT0_A0(void)
1753{
1754 helper_fildll_FT0_A0();
1755}
1756
1757#else
1758
1759void OPPROTO op_fild_FT0_A0(void)
1760{
1761#ifdef USE_FP_CONVERT
1762 FP_CONVERT.i32 = ldsw(A0);
1763 FT0 = (CPU86_LDouble)FP_CONVERT.i32;
1764#else
1765 FT0 = (CPU86_LDouble)ldsw(A0);
1766#endif
1767}
1768
1769void OPPROTO op_fildl_FT0_A0(void)
1770{
1771#ifdef USE_FP_CONVERT
1772 FP_CONVERT.i32 = (int32_t) ldl(A0);
1773 FT0 = (CPU86_LDouble)FP_CONVERT.i32;
1774#else
1775 FT0 = (CPU86_LDouble)((int32_t)ldl(A0));
1776#endif
1777}
1778
1779void OPPROTO op_fildll_FT0_A0(void)
1780{
1781#ifdef USE_FP_CONVERT
1782 FP_CONVERT.i64 = (int64_t) ldq(A0);
1783 FT0 = (CPU86_LDouble)FP_CONVERT.i64;
1784#else
1785 FT0 = (CPU86_LDouble)((int64_t)ldq(A0));
1786#endif
1787}
1788#endif
1789
1790/* fp load ST0 */
1791
1792void OPPROTO op_flds_ST0_A0(void)
1793{
1794 int new_fpstt;
1795 new_fpstt = (env->fpstt - 1) & 7;
1796#ifdef USE_FP_CONVERT
1797 FP_CONVERT.i32 = ldl(A0);
1798 env->fpregs[new_fpstt].d = FP_CONVERT.f;
1799#else
1800 env->fpregs[new_fpstt].d = ldfl(A0);
1801#endif
1802 env->fpstt = new_fpstt;
1803 env->fptags[new_fpstt] = 0; /* validate stack entry */
1804}
1805
1806void OPPROTO op_fldl_ST0_A0(void)
1807{
1808 int new_fpstt;
1809 new_fpstt = (env->fpstt - 1) & 7;
1810#ifdef USE_FP_CONVERT
1811 FP_CONVERT.i64 = ldq(A0);
1812 env->fpregs[new_fpstt].d = FP_CONVERT.d;
1813#else
1814 env->fpregs[new_fpstt].d = ldfq(A0);
1815#endif
1816 env->fpstt = new_fpstt;
1817 env->fptags[new_fpstt] = 0; /* validate stack entry */
1818}
1819
1820void OPPROTO op_fldt_ST0_A0(void)
1821{
1822 helper_fldt_ST0_A0();
1823}
1824
1825/* helpers are needed to avoid static constant reference. XXX: find a better way */
1826#ifdef USE_INT_TO_FLOAT_HELPERS
1827
1828void helper_fild_ST0_A0(void)
1829{
1830 int new_fpstt;
1831 new_fpstt = (env->fpstt - 1) & 7;
1832 env->fpregs[new_fpstt].d = (CPU86_LDouble)ldsw(A0);
1833 env->fpstt = new_fpstt;
1834 env->fptags[new_fpstt] = 0; /* validate stack entry */
1835}
1836
1837void helper_fildl_ST0_A0(void)
1838{
1839 int new_fpstt;
1840 new_fpstt = (env->fpstt - 1) & 7;
1841 env->fpregs[new_fpstt].d = (CPU86_LDouble)((int32_t)ldl(A0));
1842 env->fpstt = new_fpstt;
1843 env->fptags[new_fpstt] = 0; /* validate stack entry */
1844}
1845
1846void helper_fildll_ST0_A0(void)
1847{
1848 int new_fpstt;
1849 new_fpstt = (env->fpstt - 1) & 7;
1850 env->fpregs[new_fpstt].d = (CPU86_LDouble)((int64_t)ldq(A0));
1851 env->fpstt = new_fpstt;
1852 env->fptags[new_fpstt] = 0; /* validate stack entry */
1853}
1854
1855void OPPROTO op_fild_ST0_A0(void)
1856{
1857 helper_fild_ST0_A0();
1858}
1859
1860void OPPROTO op_fildl_ST0_A0(void)
1861{
1862 helper_fildl_ST0_A0();
1863}
1864
1865void OPPROTO op_fildll_ST0_A0(void)
1866{
1867 helper_fildll_ST0_A0();
1868}
1869
1870#else
1871
1872void OPPROTO op_fild_ST0_A0(void)
1873{
1874 int new_fpstt;
1875 new_fpstt = (env->fpstt - 1) & 7;
1876#ifdef USE_FP_CONVERT
1877 FP_CONVERT.i32 = ldsw(A0);
1878 env->fpregs[new_fpstt].d = (CPU86_LDouble)FP_CONVERT.i32;
1879#else
1880 env->fpregs[new_fpstt].d = (CPU86_LDouble)ldsw(A0);
1881#endif
1882 env->fpstt = new_fpstt;
1883 env->fptags[new_fpstt] = 0; /* validate stack entry */
1884}
1885
1886void OPPROTO op_fildl_ST0_A0(void)
1887{
1888 int new_fpstt;
1889 new_fpstt = (env->fpstt - 1) & 7;
1890#ifdef USE_FP_CONVERT
1891 FP_CONVERT.i32 = (int32_t) ldl(A0);
1892 env->fpregs[new_fpstt].d = (CPU86_LDouble)FP_CONVERT.i32;
1893#else
1894 env->fpregs[new_fpstt].d = (CPU86_LDouble)((int32_t)ldl(A0));
1895#endif
1896 env->fpstt = new_fpstt;
1897 env->fptags[new_fpstt] = 0; /* validate stack entry */
1898}
1899
1900void OPPROTO op_fildll_ST0_A0(void)
1901{
1902 int new_fpstt;
1903 new_fpstt = (env->fpstt - 1) & 7;
1904#ifdef USE_FP_CONVERT
1905 FP_CONVERT.i64 = (int64_t) ldq(A0);
1906 env->fpregs[new_fpstt].d = (CPU86_LDouble)FP_CONVERT.i64;
1907#else
1908 env->fpregs[new_fpstt].d = (CPU86_LDouble)((int64_t)ldq(A0));
1909#endif
1910 env->fpstt = new_fpstt;
1911 env->fptags[new_fpstt] = 0; /* validate stack entry */
1912}
1913
1914#endif
1915
1916/* fp store */
1917
1918void OPPROTO op_fsts_ST0_A0(void)
1919{
1920#ifdef USE_FP_CONVERT
1921 FP_CONVERT.f = (float)ST0;
1922 stfl(A0, FP_CONVERT.f);
1923#else
1924 stfl(A0, (float)ST0);
1925#endif
1926 FORCE_RET();
1927}
1928
1929void OPPROTO op_fstl_ST0_A0(void)
1930{
1931 stfq(A0, (double)ST0);
1932 FORCE_RET();
1933}
1934
1935void OPPROTO op_fstt_ST0_A0(void)
1936{
1937 helper_fstt_ST0_A0();
1938}
1939
1940void OPPROTO op_fist_ST0_A0(void)
1941{
1942#if defined(__sparc__) && !defined(__sparc_v9__)
1943 register CPU86_LDouble d asm("o0");
1944#else
1945 CPU86_LDouble d;
1946#endif
1947 int val;
1948
1949 d = ST0;
1950 val = lrint(d);
1951 if (val != (int16_t)val)
1952 val = -32768;
1953 stw(A0, val);
1954 FORCE_RET();
1955}
1956
1957void OPPROTO op_fistl_ST0_A0(void)
1958{
1959#if defined(__sparc__) && !defined(__sparc_v9__)
1960 register CPU86_LDouble d asm("o0");
1961#else
1962 CPU86_LDouble d;
1963#endif
1964 int val;
1965
1966 d = ST0;
1967 val = lrint(d);
1968 stl(A0, val);
1969 FORCE_RET();
1970}
1971
1972void OPPROTO op_fistll_ST0_A0(void)
1973{
1974#if defined(__sparc__) && !defined(__sparc_v9__)
1975 register CPU86_LDouble d asm("o0");
1976#else
1977 CPU86_LDouble d;
1978#endif
1979 int64_t val;
1980
1981 d = ST0;
1982 val = llrint(d);
1983 stq(A0, val);
1984 FORCE_RET();
1985}
1986
1987void OPPROTO op_fbld_ST0_A0(void)
1988{
1989 helper_fbld_ST0_A0();
1990}
1991
1992void OPPROTO op_fbst_ST0_A0(void)
1993{
1994 helper_fbst_ST0_A0();
1995}
1996
1997/* FPU move */
1998
1999void OPPROTO op_fpush(void)
2000{
2001 fpush();
2002}
2003
2004void OPPROTO op_fpop(void)
2005{
2006 fpop();
2007}
2008
2009void OPPROTO op_fdecstp(void)
2010{
2011 env->fpstt = (env->fpstt - 1) & 7;
2012 env->fpus &= (~0x4700);
2013}
2014
2015void OPPROTO op_fincstp(void)
2016{
2017 env->fpstt = (env->fpstt + 1) & 7;
2018 env->fpus &= (~0x4700);
2019}
2020
2021void OPPROTO op_ffree_STN(void)
2022{
2023 env->fptags[(env->fpstt + PARAM1) & 7] = 1;
2024}
2025
2026void OPPROTO op_fmov_ST0_FT0(void)
2027{
2028 ST0 = FT0;
2029}
2030
2031void OPPROTO op_fmov_FT0_STN(void)
2032{
2033 FT0 = ST(PARAM1);
2034}
2035
2036void OPPROTO op_fmov_ST0_STN(void)
2037{
2038 ST0 = ST(PARAM1);
2039}
2040
2041void OPPROTO op_fmov_STN_ST0(void)
2042{
2043 ST(PARAM1) = ST0;
2044}
2045
2046void OPPROTO op_fxchg_ST0_STN(void)
2047{
2048 CPU86_LDouble tmp;
2049 tmp = ST(PARAM1);
2050 ST(PARAM1) = ST0;
2051 ST0 = tmp;
2052}
2053
2054/* FPU operations */
2055
2056/* XXX: handle nans */
2057void OPPROTO op_fcom_ST0_FT0(void)
2058{
2059 env->fpus &= (~0x4500); /* (C3,C2,C0) <-- 000 */
2060 if (ST0 < FT0)
2061 env->fpus |= 0x100; /* (C3,C2,C0) <-- 001 */
2062 else if (ST0 == FT0)
2063 env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
2064 FORCE_RET();
2065}
2066
2067/* XXX: handle nans */
2068void OPPROTO op_fucom_ST0_FT0(void)
2069{
2070 env->fpus &= (~0x4500); /* (C3,C2,C0) <-- 000 */
2071 if (ST0 < FT0)
2072 env->fpus |= 0x100; /* (C3,C2,C0) <-- 001 */
2073 else if (ST0 == FT0)
2074 env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
2075 FORCE_RET();
2076}
2077
2078/* XXX: handle nans */
2079void OPPROTO op_fcomi_ST0_FT0(void)
2080{
2081 int eflags;
2082 eflags = cc_table[CC_OP].compute_all();
2083 eflags &= ~(CC_Z | CC_P | CC_C);
2084 if (ST0 < FT0)
2085 eflags |= CC_C;
2086 else if (ST0 == FT0)
2087 eflags |= CC_Z;
2088 CC_SRC = eflags;
2089 FORCE_RET();
2090}
2091
2092/* XXX: handle nans */
2093void OPPROTO op_fucomi_ST0_FT0(void)
2094{
2095 int eflags;
2096 eflags = cc_table[CC_OP].compute_all();
2097 eflags &= ~(CC_Z | CC_P | CC_C);
2098 if (ST0 < FT0)
2099 eflags |= CC_C;
2100 else if (ST0 == FT0)
2101 eflags |= CC_Z;
2102 CC_SRC = eflags;
2103 FORCE_RET();
2104}
2105
2106void OPPROTO op_fcmov_ST0_STN_T0(void)
2107{
2108 if (T0) {
2109 ST0 = ST(PARAM1);
2110 }
2111 FORCE_RET();
2112}
2113
2114void OPPROTO op_fadd_ST0_FT0(void)
2115{
2116 ST0 += FT0;
2117}
2118
2119void OPPROTO op_fmul_ST0_FT0(void)
2120{
2121 ST0 *= FT0;
2122}
2123
2124void OPPROTO op_fsub_ST0_FT0(void)
2125{
2126 ST0 -= FT0;
2127}
2128
2129void OPPROTO op_fsubr_ST0_FT0(void)
2130{
2131 ST0 = FT0 - ST0;
2132}
2133
2134void OPPROTO op_fdiv_ST0_FT0(void)
2135{
2136 ST0 = helper_fdiv(ST0, FT0);
2137}
2138
2139void OPPROTO op_fdivr_ST0_FT0(void)
2140{
2141 ST0 = helper_fdiv(FT0, ST0);
2142}
2143
2144/* fp operations between STN and ST0 */
2145
2146void OPPROTO op_fadd_STN_ST0(void)
2147{
2148 ST(PARAM1) += ST0;
2149}
2150
2151void OPPROTO op_fmul_STN_ST0(void)
2152{
2153 ST(PARAM1) *= ST0;
2154}
2155
2156void OPPROTO op_fsub_STN_ST0(void)
2157{
2158 ST(PARAM1) -= ST0;
2159}
2160
2161void OPPROTO op_fsubr_STN_ST0(void)
2162{
2163 CPU86_LDouble *p;
2164 p = &ST(PARAM1);
2165 *p = ST0 - *p;
2166}
2167
2168void OPPROTO op_fdiv_STN_ST0(void)
2169{
2170 CPU86_LDouble *p;
2171 p = &ST(PARAM1);
2172 *p = helper_fdiv(*p, ST0);
2173}
2174
2175void OPPROTO op_fdivr_STN_ST0(void)
2176{
2177 CPU86_LDouble *p;
2178 p = &ST(PARAM1);
2179 *p = helper_fdiv(ST0, *p);
2180}
2181
2182/* misc FPU operations */
2183void OPPROTO op_fchs_ST0(void)
2184{
2185 ST0 = -ST0;
2186}
2187
2188void OPPROTO op_fabs_ST0(void)
2189{
2190 ST0 = fabs(ST0);
2191}
2192
2193void OPPROTO op_fxam_ST0(void)
2194{
2195 helper_fxam_ST0();
2196}
2197
2198void OPPROTO op_fld1_ST0(void)
2199{
2200 ST0 = f15rk[1];
2201}
2202
2203void OPPROTO op_fldl2t_ST0(void)
2204{
2205 ST0 = f15rk[6];
2206}
2207
2208void OPPROTO op_fldl2e_ST0(void)
2209{
2210 ST0 = f15rk[5];
2211}
2212
2213void OPPROTO op_fldpi_ST0(void)
2214{
2215 ST0 = f15rk[2];
2216}
2217
2218void OPPROTO op_fldlg2_ST0(void)
2219{
2220 ST0 = f15rk[3];
2221}
2222
2223void OPPROTO op_fldln2_ST0(void)
2224{
2225 ST0 = f15rk[4];
2226}
2227
2228void OPPROTO op_fldz_ST0(void)
2229{
2230 ST0 = f15rk[0];
2231}
2232
2233void OPPROTO op_fldz_FT0(void)
2234{
2235 FT0 = f15rk[0];
2236}
2237
2238/* associated heplers to reduce generated code length and to simplify
2239 relocation (FP constants are usually stored in .rodata section) */
2240
2241void OPPROTO op_f2xm1(void)
2242{
2243 helper_f2xm1();
2244}
2245
2246void OPPROTO op_fyl2x(void)
2247{
2248 helper_fyl2x();
2249}
2250
2251void OPPROTO op_fptan(void)
2252{
2253 helper_fptan();
2254}
2255
2256void OPPROTO op_fpatan(void)
2257{
2258 helper_fpatan();
2259}
2260
2261void OPPROTO op_fxtract(void)
2262{
2263 helper_fxtract();
2264}
2265
2266void OPPROTO op_fprem1(void)
2267{
2268 helper_fprem1();
2269}
2270
2271
2272void OPPROTO op_fprem(void)
2273{
2274 helper_fprem();
2275}
2276
2277void OPPROTO op_fyl2xp1(void)
2278{
2279 helper_fyl2xp1();
2280}
2281
2282void OPPROTO op_fsqrt(void)
2283{
2284 helper_fsqrt();
2285}
2286
2287void OPPROTO op_fsincos(void)
2288{
2289 helper_fsincos();
2290}
2291
2292void OPPROTO op_frndint(void)
2293{
2294 helper_frndint();
2295}
2296
2297void OPPROTO op_fscale(void)
2298{
2299 helper_fscale();
2300}
2301
2302void OPPROTO op_fsin(void)
2303{
2304 helper_fsin();
2305}
2306
2307void OPPROTO op_fcos(void)
2308{
2309 helper_fcos();
2310}
2311
2312void OPPROTO op_fnstsw_A0(void)
2313{
2314 int fpus;
2315 fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2316 stw(A0, fpus);
2317 FORCE_RET();
2318}
2319
2320void OPPROTO op_fnstsw_EAX(void)
2321{
2322 int fpus;
2323 fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2324 EAX = (EAX & ~0xffff) | fpus;
2325}
2326
2327void OPPROTO op_fnstcw_A0(void)
2328{
2329 stw(A0, env->fpuc);
2330 FORCE_RET();
2331}
2332
2333void OPPROTO op_fldcw_A0(void)
2334{
2335 int rnd_type;
2336 env->fpuc = lduw(A0);
2337 /* set rounding mode */
2338 switch(env->fpuc & RC_MASK) {
2339 default:
2340 case RC_NEAR:
2341 rnd_type = FE_TONEAREST;
2342 break;
2343 case RC_DOWN:
2344 rnd_type = FE_DOWNWARD;
2345 break;
2346 case RC_UP:
2347 rnd_type = FE_UPWARD;
2348 break;
2349 case RC_CHOP:
2350 rnd_type = FE_TOWARDZERO;
2351 break;
2352 }
2353 fesetround(rnd_type);
2354}
2355
2356void OPPROTO op_fclex(void)
2357{
2358 env->fpus &= 0x7f00;
2359}
2360
2361void OPPROTO op_fwait(void)
2362{
2363 if (env->fpus & FPUS_SE)
2364 fpu_raise_exception();
2365 FORCE_RET();
2366}
2367
2368void OPPROTO op_fninit(void)
2369{
2370 env->fpus = 0;
2371 env->fpstt = 0;
2372 env->fpuc = 0x37f;
2373 env->fptags[0] = 1;
2374 env->fptags[1] = 1;
2375 env->fptags[2] = 1;
2376 env->fptags[3] = 1;
2377 env->fptags[4] = 1;
2378 env->fptags[5] = 1;
2379 env->fptags[6] = 1;
2380 env->fptags[7] = 1;
2381}
2382
2383void OPPROTO op_fnstenv_A0(void)
2384{
2385 helper_fstenv(A0, PARAM1);
2386}
2387
2388void OPPROTO op_fldenv_A0(void)
2389{
2390 helper_fldenv(A0, PARAM1);
2391}
2392
2393void OPPROTO op_fnsave_A0(void)
2394{
2395 helper_fsave(A0, PARAM1);
2396}
2397
2398void OPPROTO op_frstor_A0(void)
2399{
2400 helper_frstor(A0, PARAM1);
2401}
2402
2403/* threading support */
2404void OPPROTO op_lock(void)
2405{
2406 cpu_lock();
2407}
2408
2409void OPPROTO op_unlock(void)
2410{
2411 cpu_unlock();
2412}
2413
2414/* SSE support */
2415static inline void memcpy16(void *d, void *s)
2416{
2417 ((uint32_t *)d)[0] = ((uint32_t *)s)[0];
2418 ((uint32_t *)d)[1] = ((uint32_t *)s)[1];
2419 ((uint32_t *)d)[2] = ((uint32_t *)s)[2];
2420 ((uint32_t *)d)[3] = ((uint32_t *)s)[3];
2421}
2422
2423void OPPROTO op_movo(void)
2424{
2425 /* XXX: badly generated code */
2426 XMMReg *d, *s;
2427 d = (XMMReg *)((char *)env + PARAM1);
2428 s = (XMMReg *)((char *)env + PARAM2);
2429 memcpy16(d, s);
2430}
2431
2432void OPPROTO op_movq(void)
2433{
2434 uint64_t *d, *s;
2435 d = (uint64_t *)((char *)env + PARAM1);
2436 s = (uint64_t *)((char *)env + PARAM2);
2437 *d = *s;
2438}
2439
2440void OPPROTO op_movl(void)
2441{
2442 uint32_t *d, *s;
2443 d = (uint32_t *)((char *)env + PARAM1);
2444 s = (uint32_t *)((char *)env + PARAM2);
2445 *d = *s;
2446}
2447
2448void OPPROTO op_movq_env_0(void)
2449{
2450 uint64_t *d;
2451 d = (uint64_t *)((char *)env + PARAM1);
2452 *d = 0;
2453}
2454
2455void OPPROTO op_fxsave_A0(void)
2456{
2457 helper_fxsave(A0, PARAM1);
2458}
2459
2460void OPPROTO op_fxrstor_A0(void)
2461{
2462 helper_fxrstor(A0, PARAM1);
2463}
2464
2465/* XXX: optimize by storing fptt and fptags in the static cpu state */
2466void OPPROTO op_enter_mmx(void)
2467{
2468 env->fpstt = 0;
2469 *(uint32_t *)(env->fptags) = 0;
2470 *(uint32_t *)(env->fptags + 4) = 0;
2471}
2472
2473void OPPROTO op_emms(void)
2474{
2475 /* set to empty state */
2476 *(uint32_t *)(env->fptags) = 0x01010101;
2477 *(uint32_t *)(env->fptags + 4) = 0x01010101;
2478}
2479
2480#define SHIFT 0
2481#include "ops_sse.h"
2482
2483#define SHIFT 1
2484#include "ops_sse.h"
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