source: trunk/packages/xen-3.1/xen-3.1/tools/ioemu/target-i386/op.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

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