VirtualBox

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

Last change on this file since 509 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
File size: 43.5 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#if 0
724/* vm86plus instructions */
725void OPPROTO op_cli_vm(void)
726{
727 env->eflags &= ~VIF_MASK;
728}
729
730void OPPROTO op_sti_vm(void)
731{
732 env->eflags |= VIF_MASK;
733 if (env->eflags & VIP_MASK) {
734 EIP = PARAM1;
735 raise_exception(EXCP0D_GPF);
736 }
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
1466void OPPROTO op_movl_eflags_T0(void)
1467{
1468 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK));
1469}
1470
1471void OPPROTO op_movw_eflags_T0(void)
1472{
1473 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff);
1474}
1475
1476void OPPROTO op_movl_eflags_T0_io(void)
1477{
1478 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK));
1479}
1480
1481void OPPROTO op_movw_eflags_T0_io(void)
1482{
1483 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff);
1484}
1485
1486void OPPROTO op_movl_eflags_T0_cpl0(void)
1487{
1488 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK));
1489}
1490
1491void OPPROTO op_movw_eflags_T0_cpl0(void)
1492{
1493 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff);
1494}
1495
1496#if 0
1497/* vm86plus version */
1498void OPPROTO op_movw_eflags_T0_vm(void)
1499{
1500 int eflags;
1501 eflags = T0;
1502 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1503 DF = 1 - (2 * ((eflags >> 10) & 1));
1504 /* we also update some system flags as in user mode */
1505 env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) |
1506 (eflags & FL_UPDATE_MASK16);
1507 if (eflags & IF_MASK) {
1508 env->eflags |= VIF_MASK;
1509 if (env->eflags & VIP_MASK) {
1510 EIP = PARAM1;
1511 raise_exception(EXCP0D_GPF);
1512 }
1513 }
1514 FORCE_RET();
1515}
1516
1517void OPPROTO op_movl_eflags_T0_vm(void)
1518{
1519 int eflags;
1520 eflags = T0;
1521 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1522 DF = 1 - (2 * ((eflags >> 10) & 1));
1523 /* we also update some system flags as in user mode */
1524 env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) |
1525 (eflags & FL_UPDATE_MASK32);
1526 if (eflags & IF_MASK) {
1527 env->eflags |= VIF_MASK;
1528 if (env->eflags & VIP_MASK) {
1529 EIP = PARAM1;
1530 raise_exception(EXCP0D_GPF);
1531 }
1532 }
1533 FORCE_RET();
1534}
1535#endif
1536
1537/* XXX: compute only O flag */
1538void OPPROTO op_movb_eflags_T0(void)
1539{
1540 int of;
1541 of = cc_table[CC_OP].compute_all() & CC_O;
1542 CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of;
1543}
1544
1545void OPPROTO op_movl_T0_eflags(void)
1546{
1547 int eflags;
1548 eflags = cc_table[CC_OP].compute_all();
1549 eflags |= (DF & DF_MASK);
1550 eflags |= env->eflags & ~(VM_MASK | RF_MASK);
1551 T0 = eflags;
1552}
1553
1554/* vm86plus version */
1555#if 0
1556void OPPROTO op_movl_T0_eflags_vm(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 | IF_MASK);
1562 if (env->eflags & VIF_MASK)
1563 eflags |= IF_MASK;
1564 T0 = eflags;
1565}
1566#endif
1567
1568void OPPROTO op_cld(void)
1569{
1570 DF = 1;
1571}
1572
1573void OPPROTO op_std(void)
1574{
1575 DF = -1;
1576}
1577
1578void OPPROTO op_clc(void)
1579{
1580 int eflags;
1581 eflags = cc_table[CC_OP].compute_all();
1582 eflags &= ~CC_C;
1583 CC_SRC = eflags;
1584}
1585
1586void OPPROTO op_stc(void)
1587{
1588 int eflags;
1589 eflags = cc_table[CC_OP].compute_all();
1590 eflags |= CC_C;
1591 CC_SRC = eflags;
1592}
1593
1594void OPPROTO op_cmc(void)
1595{
1596 int eflags;
1597 eflags = cc_table[CC_OP].compute_all();
1598 eflags ^= CC_C;
1599 CC_SRC = eflags;
1600}
1601
1602void OPPROTO op_salc(void)
1603{
1604 int cf;
1605 cf = cc_table[CC_OP].compute_c();
1606 EAX = (EAX & ~0xff) | ((-cf) & 0xff);
1607}
1608
1609static int compute_all_eflags(void)
1610{
1611 return CC_SRC;
1612}
1613
1614static int compute_c_eflags(void)
1615{
1616 return CC_SRC & CC_C;
1617}
1618
1619CCTable cc_table[CC_OP_NB] = {
1620 [CC_OP_DYNAMIC] = { /* should never happen */ },
1621
1622 [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
1623
1624 [CC_OP_MULB] = { compute_all_mulb, compute_c_mull },
1625 [CC_OP_MULW] = { compute_all_mulw, compute_c_mull },
1626 [CC_OP_MULL] = { compute_all_mull, compute_c_mull },
1627
1628 [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
1629 [CC_OP_ADDW] = { compute_all_addw, compute_c_addw },
1630 [CC_OP_ADDL] = { compute_all_addl, compute_c_addl },
1631
1632 [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
1633 [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw },
1634 [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl },
1635
1636 [CC_OP_SUBB] = { compute_all_subb, compute_c_subb },
1637 [CC_OP_SUBW] = { compute_all_subw, compute_c_subw },
1638 [CC_OP_SUBL] = { compute_all_subl, compute_c_subl },
1639
1640 [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb },
1641 [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw },
1642 [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl },
1643
1644 [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
1645 [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
1646 [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
1647
1648 [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
1649 [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
1650 [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
1651
1652 [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
1653 [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
1654 [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
1655
1656 [CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb },
1657 [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw },
1658 [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
1659
1660 [CC_OP_SARB] = { compute_all_sarb, compute_c_sarl },
1661 [CC_OP_SARW] = { compute_all_sarw, compute_c_sarl },
1662 [CC_OP_SARL] = { compute_all_sarl, compute_c_sarl },
1663
1664#ifdef TARGET_X86_64
1665 [CC_OP_MULQ] = { compute_all_mulq, compute_c_mull },
1666
1667 [CC_OP_ADDQ] = { compute_all_addq, compute_c_addq },
1668
1669 [CC_OP_ADCQ] = { compute_all_adcq, compute_c_adcq },
1670
1671 [CC_OP_SUBQ] = { compute_all_subq, compute_c_subq },
1672
1673 [CC_OP_SBBQ] = { compute_all_sbbq, compute_c_sbbq },
1674
1675 [CC_OP_LOGICQ] = { compute_all_logicq, compute_c_logicq },
1676
1677 [CC_OP_INCQ] = { compute_all_incq, compute_c_incl },
1678
1679 [CC_OP_DECQ] = { compute_all_decq, compute_c_incl },
1680
1681 [CC_OP_SHLQ] = { compute_all_shlq, compute_c_shlq },
1682
1683 [CC_OP_SARQ] = { compute_all_sarq, compute_c_sarl },
1684#endif
1685};
1686
1687/* floating point support. Some of the code for complicated x87
1688 functions comes from the LGPL'ed x86 emulator found in the Willows
1689 TWIN windows emulator. */
1690
1691/* fp load FT0 */
1692
1693void OPPROTO op_flds_FT0_A0(void)
1694{
1695#ifdef USE_FP_CONVERT
1696 FP_CONVERT.i32 = ldl(A0);
1697 FT0 = FP_CONVERT.f;
1698#else
1699 FT0 = ldfl(A0);
1700#endif
1701}
1702
1703void OPPROTO op_fldl_FT0_A0(void)
1704{
1705#ifdef USE_FP_CONVERT
1706 FP_CONVERT.i64 = ldq(A0);
1707 FT0 = FP_CONVERT.d;
1708#else
1709 FT0 = ldfq(A0);
1710#endif
1711}
1712
1713/* helpers are needed to avoid static constant reference. XXX: find a better way */
1714#ifdef USE_INT_TO_FLOAT_HELPERS
1715
1716void helper_fild_FT0_A0(void)
1717{
1718 FT0 = (CPU86_LDouble)ldsw(A0);
1719}
1720
1721void helper_fildl_FT0_A0(void)
1722{
1723 FT0 = (CPU86_LDouble)((int32_t)ldl(A0));
1724}
1725
1726void helper_fildll_FT0_A0(void)
1727{
1728 FT0 = (CPU86_LDouble)((int64_t)ldq(A0));
1729}
1730
1731void OPPROTO op_fild_FT0_A0(void)
1732{
1733 helper_fild_FT0_A0();
1734}
1735
1736void OPPROTO op_fildl_FT0_A0(void)
1737{
1738 helper_fildl_FT0_A0();
1739}
1740
1741void OPPROTO op_fildll_FT0_A0(void)
1742{
1743 helper_fildll_FT0_A0();
1744}
1745
1746#else
1747
1748void OPPROTO op_fild_FT0_A0(void)
1749{
1750#ifdef USE_FP_CONVERT
1751 FP_CONVERT.i32 = ldsw(A0);
1752 FT0 = (CPU86_LDouble)FP_CONVERT.i32;
1753#else
1754 FT0 = (CPU86_LDouble)ldsw(A0);
1755#endif
1756}
1757
1758void OPPROTO op_fildl_FT0_A0(void)
1759{
1760#ifdef USE_FP_CONVERT
1761 FP_CONVERT.i32 = (int32_t) ldl(A0);
1762 FT0 = (CPU86_LDouble)FP_CONVERT.i32;
1763#else
1764 FT0 = (CPU86_LDouble)((int32_t)ldl(A0));
1765#endif
1766}
1767
1768void OPPROTO op_fildll_FT0_A0(void)
1769{
1770#ifdef USE_FP_CONVERT
1771 FP_CONVERT.i64 = (int64_t) ldq(A0);
1772 FT0 = (CPU86_LDouble)FP_CONVERT.i64;
1773#else
1774 FT0 = (CPU86_LDouble)((int64_t)ldq(A0));
1775#endif
1776}
1777#endif
1778
1779/* fp load ST0 */
1780
1781void OPPROTO op_flds_ST0_A0(void)
1782{
1783 int new_fpstt;
1784 new_fpstt = (env->fpstt - 1) & 7;
1785#ifdef USE_FP_CONVERT
1786 FP_CONVERT.i32 = ldl(A0);
1787 env->fpregs[new_fpstt].d = FP_CONVERT.f;
1788#else
1789 env->fpregs[new_fpstt].d = ldfl(A0);
1790#endif
1791 env->fpstt = new_fpstt;
1792 env->fptags[new_fpstt] = 0; /* validate stack entry */
1793}
1794
1795void OPPROTO op_fldl_ST0_A0(void)
1796{
1797 int new_fpstt;
1798 new_fpstt = (env->fpstt - 1) & 7;
1799#ifdef USE_FP_CONVERT
1800 FP_CONVERT.i64 = ldq(A0);
1801 env->fpregs[new_fpstt].d = FP_CONVERT.d;
1802#else
1803 env->fpregs[new_fpstt].d = ldfq(A0);
1804#endif
1805 env->fpstt = new_fpstt;
1806 env->fptags[new_fpstt] = 0; /* validate stack entry */
1807}
1808
1809void OPPROTO op_fldt_ST0_A0(void)
1810{
1811 helper_fldt_ST0_A0();
1812}
1813
1814/* helpers are needed to avoid static constant reference. XXX: find a better way */
1815#ifdef USE_INT_TO_FLOAT_HELPERS
1816
1817void helper_fild_ST0_A0(void)
1818{
1819 int new_fpstt;
1820 new_fpstt = (env->fpstt - 1) & 7;
1821 env->fpregs[new_fpstt].d = (CPU86_LDouble)ldsw(A0);
1822 env->fpstt = new_fpstt;
1823 env->fptags[new_fpstt] = 0; /* validate stack entry */
1824}
1825
1826void helper_fildl_ST0_A0(void)
1827{
1828 int new_fpstt;
1829 new_fpstt = (env->fpstt - 1) & 7;
1830 env->fpregs[new_fpstt].d = (CPU86_LDouble)((int32_t)ldl(A0));
1831 env->fpstt = new_fpstt;
1832 env->fptags[new_fpstt] = 0; /* validate stack entry */
1833}
1834
1835void helper_fildll_ST0_A0(void)
1836{
1837 int new_fpstt;
1838 new_fpstt = (env->fpstt - 1) & 7;
1839 env->fpregs[new_fpstt].d = (CPU86_LDouble)((int64_t)ldq(A0));
1840 env->fpstt = new_fpstt;
1841 env->fptags[new_fpstt] = 0; /* validate stack entry */
1842}
1843
1844void OPPROTO op_fild_ST0_A0(void)
1845{
1846 helper_fild_ST0_A0();
1847}
1848
1849void OPPROTO op_fildl_ST0_A0(void)
1850{
1851 helper_fildl_ST0_A0();
1852}
1853
1854void OPPROTO op_fildll_ST0_A0(void)
1855{
1856 helper_fildll_ST0_A0();
1857}
1858
1859#else
1860
1861void OPPROTO op_fild_ST0_A0(void)
1862{
1863 int new_fpstt;
1864 new_fpstt = (env->fpstt - 1) & 7;
1865#ifdef USE_FP_CONVERT
1866 FP_CONVERT.i32 = ldsw(A0);
1867 env->fpregs[new_fpstt].d = (CPU86_LDouble)FP_CONVERT.i32;
1868#else
1869 env->fpregs[new_fpstt].d = (CPU86_LDouble)ldsw(A0);
1870#endif
1871 env->fpstt = new_fpstt;
1872 env->fptags[new_fpstt] = 0; /* validate stack entry */
1873}
1874
1875void OPPROTO op_fildl_ST0_A0(void)
1876{
1877 int new_fpstt;
1878 new_fpstt = (env->fpstt - 1) & 7;
1879#ifdef USE_FP_CONVERT
1880 FP_CONVERT.i32 = (int32_t) ldl(A0);
1881 env->fpregs[new_fpstt].d = (CPU86_LDouble)FP_CONVERT.i32;
1882#else
1883 env->fpregs[new_fpstt].d = (CPU86_LDouble)((int32_t)ldl(A0));
1884#endif
1885 env->fpstt = new_fpstt;
1886 env->fptags[new_fpstt] = 0; /* validate stack entry */
1887}
1888
1889void OPPROTO op_fildll_ST0_A0(void)
1890{
1891 int new_fpstt;
1892 new_fpstt = (env->fpstt - 1) & 7;
1893#ifdef USE_FP_CONVERT
1894 FP_CONVERT.i64 = (int64_t) ldq(A0);
1895 env->fpregs[new_fpstt].d = (CPU86_LDouble)FP_CONVERT.i64;
1896#else
1897 env->fpregs[new_fpstt].d = (CPU86_LDouble)((int64_t)ldq(A0));
1898#endif
1899 env->fpstt = new_fpstt;
1900 env->fptags[new_fpstt] = 0; /* validate stack entry */
1901}
1902
1903#endif
1904
1905/* fp store */
1906
1907void OPPROTO op_fsts_ST0_A0(void)
1908{
1909#ifdef USE_FP_CONVERT
1910 FP_CONVERT.f = (float)ST0;
1911 stfl(A0, FP_CONVERT.f);
1912#else
1913 stfl(A0, (float)ST0);
1914#endif
1915 FORCE_RET();
1916}
1917
1918void OPPROTO op_fstl_ST0_A0(void)
1919{
1920 stfq(A0, (double)ST0);
1921 FORCE_RET();
1922}
1923
1924void OPPROTO op_fstt_ST0_A0(void)
1925{
1926 helper_fstt_ST0_A0();
1927}
1928
1929void OPPROTO op_fist_ST0_A0(void)
1930{
1931#if defined(__sparc__) && !defined(__sparc_v9__)
1932 register CPU86_LDouble d asm("o0");
1933#else
1934 CPU86_LDouble d;
1935#endif
1936 int val;
1937
1938 d = ST0;
1939 val = lrint(d);
1940 if (val != (int16_t)val)
1941 val = -32768;
1942 stw(A0, val);
1943 FORCE_RET();
1944}
1945
1946void OPPROTO op_fistl_ST0_A0(void)
1947{
1948#if defined(__sparc__) && !defined(__sparc_v9__)
1949 register CPU86_LDouble d asm("o0");
1950#else
1951 CPU86_LDouble d;
1952#endif
1953 int val;
1954
1955 d = ST0;
1956 val = lrint(d);
1957 stl(A0, val);
1958 FORCE_RET();
1959}
1960
1961void OPPROTO op_fistll_ST0_A0(void)
1962{
1963#if defined(__sparc__) && !defined(__sparc_v9__)
1964 register CPU86_LDouble d asm("o0");
1965#else
1966 CPU86_LDouble d;
1967#endif
1968 int64_t val;
1969
1970 d = ST0;
1971 val = llrint(d);
1972 stq(A0, val);
1973 FORCE_RET();
1974}
1975
1976void OPPROTO op_fbld_ST0_A0(void)
1977{
1978 helper_fbld_ST0_A0();
1979}
1980
1981void OPPROTO op_fbst_ST0_A0(void)
1982{
1983 helper_fbst_ST0_A0();
1984}
1985
1986/* FPU move */
1987
1988void OPPROTO op_fpush(void)
1989{
1990 fpush();
1991}
1992
1993void OPPROTO op_fpop(void)
1994{
1995 fpop();
1996}
1997
1998void OPPROTO op_fdecstp(void)
1999{
2000 env->fpstt = (env->fpstt - 1) & 7;
2001 env->fpus &= (~0x4700);
2002}
2003
2004void OPPROTO op_fincstp(void)
2005{
2006 env->fpstt = (env->fpstt + 1) & 7;
2007 env->fpus &= (~0x4700);
2008}
2009
2010void OPPROTO op_ffree_STN(void)
2011{
2012 env->fptags[(env->fpstt + PARAM1) & 7] = 1;
2013}
2014
2015void OPPROTO op_fmov_ST0_FT0(void)
2016{
2017 ST0 = FT0;
2018}
2019
2020void OPPROTO op_fmov_FT0_STN(void)
2021{
2022 FT0 = ST(PARAM1);
2023}
2024
2025void OPPROTO op_fmov_ST0_STN(void)
2026{
2027 ST0 = ST(PARAM1);
2028}
2029
2030void OPPROTO op_fmov_STN_ST0(void)
2031{
2032 ST(PARAM1) = ST0;
2033}
2034
2035void OPPROTO op_fxchg_ST0_STN(void)
2036{
2037 CPU86_LDouble tmp;
2038 tmp = ST(PARAM1);
2039 ST(PARAM1) = ST0;
2040 ST0 = tmp;
2041}
2042
2043/* FPU operations */
2044
2045/* XXX: handle nans */
2046void OPPROTO op_fcom_ST0_FT0(void)
2047{
2048 env->fpus &= (~0x4500); /* (C3,C2,C0) <-- 000 */
2049 if (ST0 < FT0)
2050 env->fpus |= 0x100; /* (C3,C2,C0) <-- 001 */
2051 else if (ST0 == FT0)
2052 env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
2053 FORCE_RET();
2054}
2055
2056/* XXX: handle nans */
2057void OPPROTO op_fucom_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_fcomi_ST0_FT0(void)
2069{
2070 int eflags;
2071 eflags = cc_table[CC_OP].compute_all();
2072 eflags &= ~(CC_Z | CC_P | CC_C);
2073 if (ST0 < FT0)
2074 eflags |= CC_C;
2075 else if (ST0 == FT0)
2076 eflags |= CC_Z;
2077 CC_SRC = eflags;
2078 FORCE_RET();
2079}
2080
2081/* XXX: handle nans */
2082void OPPROTO op_fucomi_ST0_FT0(void)
2083{
2084 int eflags;
2085 eflags = cc_table[CC_OP].compute_all();
2086 eflags &= ~(CC_Z | CC_P | CC_C);
2087 if (ST0 < FT0)
2088 eflags |= CC_C;
2089 else if (ST0 == FT0)
2090 eflags |= CC_Z;
2091 CC_SRC = eflags;
2092 FORCE_RET();
2093}
2094
2095void OPPROTO op_fcmov_ST0_STN_T0(void)
2096{
2097 if (T0) {
2098 ST0 = ST(PARAM1);
2099 }
2100 FORCE_RET();
2101}
2102
2103void OPPROTO op_fadd_ST0_FT0(void)
2104{
2105 ST0 += FT0;
2106}
2107
2108void OPPROTO op_fmul_ST0_FT0(void)
2109{
2110 ST0 *= FT0;
2111}
2112
2113void OPPROTO op_fsub_ST0_FT0(void)
2114{
2115 ST0 -= FT0;
2116}
2117
2118void OPPROTO op_fsubr_ST0_FT0(void)
2119{
2120 ST0 = FT0 - ST0;
2121}
2122
2123void OPPROTO op_fdiv_ST0_FT0(void)
2124{
2125 ST0 = helper_fdiv(ST0, FT0);
2126}
2127
2128void OPPROTO op_fdivr_ST0_FT0(void)
2129{
2130 ST0 = helper_fdiv(FT0, ST0);
2131}
2132
2133/* fp operations between STN and ST0 */
2134
2135void OPPROTO op_fadd_STN_ST0(void)
2136{
2137 ST(PARAM1) += ST0;
2138}
2139
2140void OPPROTO op_fmul_STN_ST0(void)
2141{
2142 ST(PARAM1) *= ST0;
2143}
2144
2145void OPPROTO op_fsub_STN_ST0(void)
2146{
2147 ST(PARAM1) -= ST0;
2148}
2149
2150void OPPROTO op_fsubr_STN_ST0(void)
2151{
2152 CPU86_LDouble *p;
2153 p = &ST(PARAM1);
2154 *p = ST0 - *p;
2155}
2156
2157void OPPROTO op_fdiv_STN_ST0(void)
2158{
2159 CPU86_LDouble *p;
2160 p = &ST(PARAM1);
2161 *p = helper_fdiv(*p, ST0);
2162}
2163
2164void OPPROTO op_fdivr_STN_ST0(void)
2165{
2166 CPU86_LDouble *p;
2167 p = &ST(PARAM1);
2168 *p = helper_fdiv(ST0, *p);
2169}
2170
2171/* misc FPU operations */
2172void OPPROTO op_fchs_ST0(void)
2173{
2174 ST0 = -ST0;
2175}
2176
2177void OPPROTO op_fabs_ST0(void)
2178{
2179 ST0 = fabs(ST0);
2180}
2181
2182void OPPROTO op_fxam_ST0(void)
2183{
2184 helper_fxam_ST0();
2185}
2186
2187void OPPROTO op_fld1_ST0(void)
2188{
2189 ST0 = f15rk[1];
2190}
2191
2192void OPPROTO op_fldl2t_ST0(void)
2193{
2194 ST0 = f15rk[6];
2195}
2196
2197void OPPROTO op_fldl2e_ST0(void)
2198{
2199 ST0 = f15rk[5];
2200}
2201
2202void OPPROTO op_fldpi_ST0(void)
2203{
2204 ST0 = f15rk[2];
2205}
2206
2207void OPPROTO op_fldlg2_ST0(void)
2208{
2209 ST0 = f15rk[3];
2210}
2211
2212void OPPROTO op_fldln2_ST0(void)
2213{
2214 ST0 = f15rk[4];
2215}
2216
2217void OPPROTO op_fldz_ST0(void)
2218{
2219 ST0 = f15rk[0];
2220}
2221
2222void OPPROTO op_fldz_FT0(void)
2223{
2224 FT0 = f15rk[0];
2225}
2226
2227/* associated heplers to reduce generated code length and to simplify
2228 relocation (FP constants are usually stored in .rodata section) */
2229
2230void OPPROTO op_f2xm1(void)
2231{
2232 helper_f2xm1();
2233}
2234
2235void OPPROTO op_fyl2x(void)
2236{
2237 helper_fyl2x();
2238}
2239
2240void OPPROTO op_fptan(void)
2241{
2242 helper_fptan();
2243}
2244
2245void OPPROTO op_fpatan(void)
2246{
2247 helper_fpatan();
2248}
2249
2250void OPPROTO op_fxtract(void)
2251{
2252 helper_fxtract();
2253}
2254
2255void OPPROTO op_fprem1(void)
2256{
2257 helper_fprem1();
2258}
2259
2260
2261void OPPROTO op_fprem(void)
2262{
2263 helper_fprem();
2264}
2265
2266void OPPROTO op_fyl2xp1(void)
2267{
2268 helper_fyl2xp1();
2269}
2270
2271void OPPROTO op_fsqrt(void)
2272{
2273 helper_fsqrt();
2274}
2275
2276void OPPROTO op_fsincos(void)
2277{
2278 helper_fsincos();
2279}
2280
2281void OPPROTO op_frndint(void)
2282{
2283 helper_frndint();
2284}
2285
2286void OPPROTO op_fscale(void)
2287{
2288 helper_fscale();
2289}
2290
2291void OPPROTO op_fsin(void)
2292{
2293 helper_fsin();
2294}
2295
2296void OPPROTO op_fcos(void)
2297{
2298 helper_fcos();
2299}
2300
2301void OPPROTO op_fnstsw_A0(void)
2302{
2303 int fpus;
2304 fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2305 stw(A0, fpus);
2306 FORCE_RET();
2307}
2308
2309void OPPROTO op_fnstsw_EAX(void)
2310{
2311 int fpus;
2312 fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2313 EAX = (EAX & ~0xffff) | fpus;
2314}
2315
2316void OPPROTO op_fnstcw_A0(void)
2317{
2318 stw(A0, env->fpuc);
2319 FORCE_RET();
2320}
2321
2322void OPPROTO op_fldcw_A0(void)
2323{
2324 int rnd_type;
2325 env->fpuc = lduw(A0);
2326 /* set rounding mode */
2327 switch(env->fpuc & RC_MASK) {
2328 default:
2329 case RC_NEAR:
2330 rnd_type = FE_TONEAREST;
2331 break;
2332 case RC_DOWN:
2333 rnd_type = FE_DOWNWARD;
2334 break;
2335 case RC_UP:
2336 rnd_type = FE_UPWARD;
2337 break;
2338 case RC_CHOP:
2339 rnd_type = FE_TOWARDZERO;
2340 break;
2341 }
2342 fesetround(rnd_type);
2343}
2344
2345void OPPROTO op_fclex(void)
2346{
2347 env->fpus &= 0x7f00;
2348}
2349
2350void OPPROTO op_fwait(void)
2351{
2352 if (env->fpus & FPUS_SE)
2353 fpu_raise_exception();
2354 FORCE_RET();
2355}
2356
2357void OPPROTO op_fninit(void)
2358{
2359 env->fpus = 0;
2360 env->fpstt = 0;
2361 env->fpuc = 0x37f;
2362 env->fptags[0] = 1;
2363 env->fptags[1] = 1;
2364 env->fptags[2] = 1;
2365 env->fptags[3] = 1;
2366 env->fptags[4] = 1;
2367 env->fptags[5] = 1;
2368 env->fptags[6] = 1;
2369 env->fptags[7] = 1;
2370}
2371
2372void OPPROTO op_fnstenv_A0(void)
2373{
2374 helper_fstenv(A0, PARAM1);
2375}
2376
2377void OPPROTO op_fldenv_A0(void)
2378{
2379 helper_fldenv(A0, PARAM1);
2380}
2381
2382void OPPROTO op_fnsave_A0(void)
2383{
2384 helper_fsave(A0, PARAM1);
2385}
2386
2387void OPPROTO op_frstor_A0(void)
2388{
2389 helper_frstor(A0, PARAM1);
2390}
2391
2392/* threading support */
2393void OPPROTO op_lock(void)
2394{
2395 cpu_lock();
2396}
2397
2398void OPPROTO op_unlock(void)
2399{
2400 cpu_unlock();
2401}
2402
2403/* SSE support */
2404static inline void memcpy16(void *d, void *s)
2405{
2406 ((uint32_t *)d)[0] = ((uint32_t *)s)[0];
2407 ((uint32_t *)d)[1] = ((uint32_t *)s)[1];
2408 ((uint32_t *)d)[2] = ((uint32_t *)s)[2];
2409 ((uint32_t *)d)[3] = ((uint32_t *)s)[3];
2410}
2411
2412void OPPROTO op_movo(void)
2413{
2414 /* XXX: badly generated code */
2415 XMMReg *d, *s;
2416 d = (XMMReg *)((char *)env + PARAM1);
2417 s = (XMMReg *)((char *)env + PARAM2);
2418 memcpy16(d, s);
2419}
2420
2421void OPPROTO op_movq(void)
2422{
2423 uint64_t *d, *s;
2424 d = (uint64_t *)((char *)env + PARAM1);
2425 s = (uint64_t *)((char *)env + PARAM2);
2426 *d = *s;
2427}
2428
2429void OPPROTO op_movl(void)
2430{
2431 uint32_t *d, *s;
2432 d = (uint32_t *)((char *)env + PARAM1);
2433 s = (uint32_t *)((char *)env + PARAM2);
2434 *d = *s;
2435}
2436
2437void OPPROTO op_movq_env_0(void)
2438{
2439 uint64_t *d;
2440 d = (uint64_t *)((char *)env + PARAM1);
2441 *d = 0;
2442}
2443
2444void OPPROTO op_fxsave_A0(void)
2445{
2446 helper_fxsave(A0, PARAM1);
2447}
2448
2449void OPPROTO op_fxrstor_A0(void)
2450{
2451 helper_fxrstor(A0, PARAM1);
2452}
2453
2454/* XXX: optimize by storing fptt and fptags in the static cpu state */
2455void OPPROTO op_enter_mmx(void)
2456{
2457 env->fpstt = 0;
2458 *(uint32_t *)(env->fptags) = 0;
2459 *(uint32_t *)(env->fptags + 4) = 0;
2460}
2461
2462void OPPROTO op_emms(void)
2463{
2464 /* set to empty state */
2465 *(uint32_t *)(env->fptags) = 0x01010101;
2466 *(uint32_t *)(env->fptags + 4) = 0x01010101;
2467}
2468
2469#define SHIFT 0
2470#include "ops_sse.h"
2471
2472#define SHIFT 1
2473#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