4 * Copyright (c) 2003 Fabrice Bellard
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.
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.
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
20 #include "exec-i386.h"
22 const CPU86_LDouble f15rk[7] =
24 0.00000000000000000000L,
25 1.00000000000000000000L,
26 3.14159265358979323851L, /*pi*/
27 0.30102999566398119523L, /*lg2*/
28 0.69314718055994530943L, /*ln2*/
29 1.44269504088896340739L, /*l2e*/
30 3.32192809488736234781L, /*l2t*/
35 spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
39 spin_lock(&global_cpu_lock);
44 spin_unlock(&global_cpu_lock);
47 void cpu_loop_exit(void)
49 /* NOTE: the register at this point must be saved by hand because
50 longjmp restore them */
52 env->regs[R_EAX] = EAX;
55 env->regs[R_ECX] = ECX;
58 env->regs[R_EDX] = EDX;
61 env->regs[R_EBX] = EBX;
64 env->regs[R_ESP] = ESP;
67 env->regs[R_EBP] = EBP;
70 env->regs[R_ESI] = ESI;
73 env->regs[R_EDI] = EDI;
75 longjmp(env->jmp_env, 1);
79 /* full interrupt support (only useful for real CPU emulation, not
80 finished) - I won't do it any time soon, finish it if you want ! */
81 void raise_interrupt(int intno, int is_int, int error_code,
82 unsigned int next_eip)
84 SegmentDescriptorTable *dt;
90 if (intno * 8 + 7 > dt->limit)
91 raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
92 ptr = dt->base + intno * 8;
96 type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
98 case 5: /* task gate */
99 case 6: /* 286 interrupt gate */
100 case 7: /* 286 trap gate */
101 case 14: /* 386 interrupt gate */
102 case 15: /* 386 trap gate */
105 raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
108 dpl = (e2 >> DESC_DPL_SHIFT) & 3;
109 cpl = env->segs[R_CS] & 3;
110 /* check privledge if software int */
111 if (is_int && dpl < cpl)
112 raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
113 /* check valid bit */
114 if (!(e2 & DESC_P_MASK))
115 raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
121 * is_int is TRUE if coming from the int instruction. next_eip is the
122 * EIP value AFTER the interrupt instruction. It is only relevant if
125 void raise_interrupt(int intno, int is_int, int error_code,
126 unsigned int next_eip)
128 SegmentDescriptorTable *dt;
134 ptr = dt->base + (intno * 8);
137 dpl = (e2 >> DESC_DPL_SHIFT) & 3;
139 /* check privledge if software int */
140 if (is_int && dpl < cpl)
141 raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
143 /* Since we emulate only user space, we cannot do more than
144 exiting the emulation with the suitable exception and error
148 env->exception_index = intno;
149 env->error_code = error_code;
156 /* shortcuts to generate exceptions */
157 void raise_exception_err(int exception_index, int error_code)
159 raise_interrupt(exception_index, 0, error_code, 0);
162 void raise_exception(int exception_index)
164 raise_interrupt(exception_index, 0, 0, 0);
167 #ifdef BUGGY_GCC_DIV64
168 /* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we
169 call it from another function */
170 uint32_t div64(uint32_t *q_ptr, uint64_t num, uint32_t den)
176 int32_t idiv64(int32_t *q_ptr, int64_t num, int32_t den)
183 void helper_divl_EAX_T0(uint32_t eip)
185 unsigned int den, q, r;
188 num = EAX | ((uint64_t)EDX << 32);
192 raise_exception(EXCP00_DIVZ);
194 #ifdef BUGGY_GCC_DIV64
195 r = div64(&q, num, den);
204 void helper_idivl_EAX_T0(uint32_t eip)
209 num = EAX | ((uint64_t)EDX << 32);
213 raise_exception(EXCP00_DIVZ);
215 #ifdef BUGGY_GCC_DIV64
216 r = idiv64(&q, num, den);
225 void helper_cmpxchg8b(void)
230 eflags = cc_table[CC_OP].compute_all();
231 d = ldq((uint8_t *)A0);
232 if (d == (((uint64_t)EDX << 32) | EAX)) {
233 stq((uint8_t *)A0, ((uint64_t)ECX << 32) | EBX);
243 /* We simulate a pre-MMX pentium as in valgrind */
244 #define CPUID_FP87 (1 << 0)
245 #define CPUID_VME (1 << 1)
246 #define CPUID_DE (1 << 2)
247 #define CPUID_PSE (1 << 3)
248 #define CPUID_TSC (1 << 4)
249 #define CPUID_MSR (1 << 5)
250 #define CPUID_PAE (1 << 6)
251 #define CPUID_MCE (1 << 7)
252 #define CPUID_CX8 (1 << 8)
253 #define CPUID_APIC (1 << 9)
254 #define CPUID_SEP (1 << 11) /* sysenter/sysexit */
255 #define CPUID_MTRR (1 << 12)
256 #define CPUID_PGE (1 << 13)
257 #define CPUID_MCA (1 << 14)
258 #define CPUID_CMOV (1 << 15)
260 #define CPUID_MMX (1 << 23)
261 #define CPUID_FXSR (1 << 24)
262 #define CPUID_SSE (1 << 25)
263 #define CPUID_SSE2 (1 << 26)
265 void helper_cpuid(void)
268 EAX = 1; /* max EAX index supported */
272 } else if (EAX == 1) {
277 EDX = CPUID_FP87 | CPUID_DE | CPUID_PSE |
278 CPUID_TSC | CPUID_MSR | CPUID_MCE |
283 /* only works if protected mode and not VM86 */
284 void load_seg(int seg_reg, int selector, unsigned cur_eip)
287 SegmentDescriptorTable *dt;
292 sc = &env->seg_cache[seg_reg];
293 if ((selector & 0xfffc) == 0) {
294 /* null selector case */
295 if (seg_reg == R_SS) {
297 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
299 /* XXX: each access should trigger an exception */
309 index = selector & ~7;
310 if ((index + 7) > dt->limit) {
312 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
314 ptr = dt->base + index;
317 if (!(e2 & DESC_S_MASK) ||
318 (e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) {
320 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
323 if (seg_reg == R_SS) {
324 if ((e2 & (DESC_CS_MASK | DESC_W_MASK)) == 0) {
326 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
329 if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) {
331 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
335 if (!(e2 & DESC_P_MASK)) {
338 raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
340 raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
343 sc->base = (void *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
344 sc->limit = (e1 & 0xffff) | (e2 & 0x000f0000);
346 sc->limit = (sc->limit << 12) | 0xfff;
347 sc->seg_32bit = (e2 >> 22) & 1;
349 fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n",
350 selector, (unsigned long)sc->base, sc->limit, sc->seg_32bit);
353 env->segs[seg_reg] = selector;
361 void helper_rdtsc(void)
365 asm("rdtsc" : "=A" (val));
367 /* better than nothing: the time increases */
374 void helper_lsl(void)
376 unsigned int selector, limit;
377 SegmentDescriptorTable *dt;
382 CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
383 selector = T0 & 0xffff;
388 index = selector & ~7;
389 if ((index + 7) > dt->limit)
391 ptr = dt->base + index;
394 limit = (e1 & 0xffff) | (e2 & 0x000f0000);
396 limit = (limit << 12) | 0xfff;
401 void helper_lar(void)
403 unsigned int selector;
404 SegmentDescriptorTable *dt;
409 CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
410 selector = T0 & 0xffff;
415 index = selector & ~7;
416 if ((index + 7) > dt->limit)
418 ptr = dt->base + index;
420 T1 = e2 & 0x00f0ff00;
426 #ifndef USE_X86LDOUBLE
427 void helper_fldt_ST0_A0(void)
429 ST0 = helper_fldt((uint8_t *)A0);
432 void helper_fstt_ST0_A0(void)
434 helper_fstt(ST0, (uint8_t *)A0);
440 #define MUL10(iv) ( iv + iv + (iv << 3) )
442 void helper_fbld_ST0_A0(void)
445 CPU86_LDouble fpsrcop;
449 /* in this code, seg/m32i will be used as temporary ptr/int */
450 seg = (uint8_t *)A0 + 8;
452 /* XXX: raise exception */
456 /* XXX: raise exception */
459 m32i = v; /* <-- d14 */
461 m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d13 */
462 m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d12 */
464 m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d11 */
465 m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d10 */
467 m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d9 */
468 m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d8 */
469 fpsrcop = ((CPU86_LDouble)m32i) * 100000000.0;
472 m32i = (v >> 4); /* <-- d7 */
473 m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d6 */
475 m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d5 */
476 m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d4 */
478 m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d3 */
479 m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d2 */
481 m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d1 */
482 m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d0 */
483 fpsrcop += ((CPU86_LDouble)m32i);
484 if ( ldub(seg+9) & 0x80 )
489 void helper_fbst_ST0_A0(void)
491 CPU86_LDouble fptemp;
492 CPU86_LDouble fpsrcop;
494 uint8_t *mem_ref, *mem_end;
497 mem_ref = (uint8_t *)A0;
498 mem_end = mem_ref + 8;
499 if ( fpsrcop < 0.0 ) {
500 stw(mem_end, 0x8000);
503 stw(mem_end, 0x0000);
505 while (mem_ref < mem_end) {
508 fptemp = floor(fpsrcop/10.0);
509 v = ((int)(fpsrcop - fptemp*10.0));
515 fptemp = floor(fpsrcop/10.0);
516 v |= (((int)(fpsrcop - fptemp*10.0)) << 4);
520 while (mem_ref < mem_end) {
525 void helper_f2xm1(void)
527 ST0 = pow(2.0,ST0) - 1.0;
530 void helper_fyl2x(void)
532 CPU86_LDouble fptemp;
536 fptemp = log(fptemp)/log(2.0); /* log2(ST) */
540 env->fpus &= (~0x4700);
545 void helper_fptan(void)
547 CPU86_LDouble fptemp;
550 if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
556 env->fpus &= (~0x400); /* C2 <-- 0 */
557 /* the above code is for |arg| < 2**52 only */
561 void helper_fpatan(void)
563 CPU86_LDouble fptemp, fpsrcop;
567 ST1 = atan2(fpsrcop,fptemp);
571 void helper_fxtract(void)
577 expdif = EXPD(temp) - EXPBIAS;
585 void helper_fprem1(void)
587 CPU86_LDouble dblq, fpsrcop, fptemp;
588 CPU86_LDoubleU fpsrcop1, fptemp1;
594 fpsrcop1.d = fpsrcop;
596 expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
598 dblq = fpsrcop / fptemp;
599 dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
600 ST0 = fpsrcop - fptemp*dblq;
601 q = (int)dblq; /* cutting off top bits is assumed here */
602 env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
603 /* (C0,C1,C3) <-- (q2,q1,q0) */
604 env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
605 env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
606 env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
608 env->fpus |= 0x400; /* C2 <-- 1 */
609 fptemp = pow(2.0, expdif-50);
610 fpsrcop = (ST0 / ST1) / fptemp;
611 /* fpsrcop = integer obtained by rounding to the nearest */
612 fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
613 floor(fpsrcop): ceil(fpsrcop);
614 ST0 -= (ST1 * fpsrcop * fptemp);
618 void helper_fprem(void)
620 CPU86_LDouble dblq, fpsrcop, fptemp;
621 CPU86_LDoubleU fpsrcop1, fptemp1;
627 fpsrcop1.d = fpsrcop;
629 expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
631 dblq = fpsrcop / fptemp;
632 dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
633 ST0 = fpsrcop - fptemp*dblq;
634 q = (int)dblq; /* cutting off top bits is assumed here */
635 env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
636 /* (C0,C1,C3) <-- (q2,q1,q0) */
637 env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
638 env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
639 env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
641 env->fpus |= 0x400; /* C2 <-- 1 */
642 fptemp = pow(2.0, expdif-50);
643 fpsrcop = (ST0 / ST1) / fptemp;
644 /* fpsrcop = integer obtained by chopping */
645 fpsrcop = (fpsrcop < 0.0)?
646 -(floor(fabs(fpsrcop))): floor(fpsrcop);
647 ST0 -= (ST1 * fpsrcop * fptemp);
651 void helper_fyl2xp1(void)
653 CPU86_LDouble fptemp;
656 if ((fptemp+1.0)>0.0) {
657 fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
661 env->fpus &= (~0x4700);
666 void helper_fsqrt(void)
668 CPU86_LDouble fptemp;
672 env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
678 void helper_fsincos(void)
680 CPU86_LDouble fptemp;
683 if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
689 env->fpus &= (~0x400); /* C2 <-- 0 */
690 /* the above code is for |arg| < 2**63 only */
694 void helper_frndint(void)
699 void helper_fscale(void)
701 CPU86_LDouble fpsrcop, fptemp;
704 fptemp = pow(fpsrcop,ST1);
708 void helper_fsin(void)
710 CPU86_LDouble fptemp;
713 if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
717 env->fpus &= (~0x400); /* C2 <-- 0 */
718 /* the above code is for |arg| < 2**53 only */
722 void helper_fcos(void)
724 CPU86_LDouble fptemp;
727 if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
731 env->fpus &= (~0x400); /* C2 <-- 0 */
732 /* the above code is for |arg5 < 2**63 only */
736 void helper_fxam_ST0(void)
743 env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
745 env->fpus |= 0x200; /* C1 <-- 1 */
748 if (expdif == MAXEXPD) {
749 if (MANTD(temp) == 0)
750 env->fpus |= 0x500 /*Infinity*/;
752 env->fpus |= 0x100 /*NaN*/;
753 } else if (expdif == 0) {
754 if (MANTD(temp) == 0)
755 env->fpus |= 0x4000 /*Zero*/;
757 env->fpus |= 0x4400 /*Denormal*/;
763 void helper_fstenv(uint8_t *ptr, int data32)
765 int fpus, fptag, exp, i;
769 fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
771 for (i=7; i>=0; i--) {
773 if (env->fptags[i]) {
776 tmp.d = env->fpregs[i];
779 if (exp == 0 && mant == 0) {
782 } else if (exp == 0 || exp == MAXEXPD
783 #ifdef USE_X86LDOUBLE
784 || (mant & (1LL << 63)) == 0
787 /* NaNs, infinity, denormal */
813 void helper_fldenv(uint8_t *ptr, int data32)
818 env->fpuc = lduw(ptr);
819 fpus = lduw(ptr + 4);
820 fptag = lduw(ptr + 8);
823 env->fpuc = lduw(ptr);
824 fpus = lduw(ptr + 2);
825 fptag = lduw(ptr + 4);
827 env->fpstt = (fpus >> 11) & 7;
828 env->fpus = fpus & ~0x3800;
829 for(i = 0;i < 7; i++) {
830 env->fptags[i] = ((fptag & 3) == 3);
835 void helper_fsave(uint8_t *ptr, int data32)
840 helper_fstenv(ptr, data32);
842 ptr += (14 << data32);
843 for(i = 0;i < 8; i++) {
845 #ifdef USE_X86LDOUBLE
846 *(long double *)ptr = tmp;
848 helper_fstt(tmp, ptr);
867 void helper_frstor(uint8_t *ptr, int data32)
872 helper_fldenv(ptr, data32);
873 ptr += (14 << data32);
875 for(i = 0;i < 8; i++) {
876 #ifdef USE_X86LDOUBLE
877 tmp = *(long double *)ptr;
879 tmp = helper_fldt(ptr);