aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-06-09 15:25:54 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-06-09 15:25:54 +0000
commit2d0e9143e2d6fc705cba6c27c221c5c9a7c81a29 (patch)
treef8048bfb9e440db301ae01516dff0bb1a68d574d
parent87f4827e1dc49d5d4d26ffca9ef15a33a325c676 (diff)
more code moved to helpers - sipmplified x86 float constants definitions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@217 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r--helper-i386.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/helper-i386.c b/helper-i386.c
index 5f3040bf27..293d46af80 100644
--- a/helper-i386.c
+++ b/helper-i386.c
@@ -19,6 +19,62 @@
*/
#include "exec-i386.h"
+const CPU86_LDouble f15rk[7] =
+{
+ 0.00000000000000000000L,
+ 1.00000000000000000000L,
+ 3.14159265358979323851L, /*pi*/
+ 0.30102999566398119523L, /*lg2*/
+ 0.69314718055994530943L, /*ln2*/
+ 1.44269504088896340739L, /*l2e*/
+ 3.32192809488736234781L, /*l2t*/
+};
+
+/* thread support */
+
+spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
+
+void cpu_lock(void)
+{
+ spin_lock(&global_cpu_lock);
+}
+
+void cpu_unlock(void)
+{
+ spin_unlock(&global_cpu_lock);
+}
+
+void cpu_loop_exit(void)
+{
+ /* NOTE: the register at this point must be saved by hand because
+ longjmp restore them */
+#ifdef reg_EAX
+ env->regs[R_EAX] = EAX;
+#endif
+#ifdef reg_ECX
+ env->regs[R_ECX] = ECX;
+#endif
+#ifdef reg_EDX
+ env->regs[R_EDX] = EDX;
+#endif
+#ifdef reg_EBX
+ env->regs[R_EBX] = EBX;
+#endif
+#ifdef reg_ESP
+ env->regs[R_ESP] = ESP;
+#endif
+#ifdef reg_EBP
+ env->regs[R_EBP] = EBP;
+#endif
+#ifdef reg_ESI
+ env->regs[R_ESI] = ESI;
+#endif
+#ifdef reg_EDI
+ env->regs[R_EDI] = EDI;
+#endif
+ longjmp(env->jmp_env, 1);
+}
+
#if 0
/* full interrupt support (only useful for real CPU emulation, not
finished) - I won't do it any time soon, finish it if you want ! */
@@ -108,6 +164,82 @@ void raise_exception(int exception_index)
raise_interrupt(exception_index, 0, 0, 0);
}
+#ifdef BUGGY_GCC_DIV64
+/* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we
+ call it from another function */
+uint32_t div64(uint32_t *q_ptr, uint64_t num, uint32_t den)
+{
+ *q_ptr = num / den;
+ return num % den;
+}
+
+int32_t idiv64(int32_t *q_ptr, int64_t num, int32_t den)
+{
+ *q_ptr = num / den;
+ return num % den;
+}
+#endif
+
+void helper_divl_EAX_T0(uint32_t eip)
+{
+ unsigned int den, q, r;
+ uint64_t num;
+
+ num = EAX | ((uint64_t)EDX << 32);
+ den = T0;
+ if (den == 0) {
+ EIP = eip;
+ raise_exception(EXCP00_DIVZ);
+ }
+#ifdef BUGGY_GCC_DIV64
+ r = div64(&q, num, den);
+#else
+ q = (num / den);
+ r = (num % den);
+#endif
+ EAX = q;
+ EDX = r;
+}
+
+void helper_idivl_EAX_T0(uint32_t eip)
+{
+ int den, q, r;
+ int64_t num;
+
+ num = EAX | ((uint64_t)EDX << 32);
+ den = T0;
+ if (den == 0) {
+ EIP = eip;
+ raise_exception(EXCP00_DIVZ);
+ }
+#ifdef BUGGY_GCC_DIV64
+ r = idiv64(&q, num, den);
+#else
+ q = (num / den);
+ r = (num % den);
+#endif
+ EAX = q;
+ EDX = r;
+}
+
+void helper_cmpxchg8b(void)
+{
+ uint64_t d;
+ int eflags;
+
+ eflags = cc_table[CC_OP].compute_all();
+ d = ldq((uint8_t *)A0);
+ if (d == (((uint64_t)EDX << 32) | EAX)) {
+ stq((uint8_t *)A0, ((uint64_t)ECX << 32) | EBX);
+ eflags |= CC_Z;
+ } else {
+ EDX = d >> 32;
+ EAX = d;
+ eflags &= ~CC_Z;
+ }
+ CC_SRC = eflags;
+}
+
/* We simulate a pre-MMX pentium as in valgrind */
#define CPUID_FP87 (1 << 0)
#define CPUID_VME (1 << 1)
@@ -221,6 +353,24 @@ void load_seg(int seg_reg, int selector, unsigned cur_eip)
env->segs[seg_reg] = selector;
}
+/* rdtsc */
+#ifndef __i386__
+uint64_t emu_time;
+#endif
+
+void helper_rdtsc(void)
+{
+ uint64_t val;
+#ifdef __i386__
+ asm("rdtsc" : "=A" (val));
+#else
+ /* better than nothing: the time increases */
+ val = emu_time++;
+#endif
+ EAX = val;
+ EDX = val >> 32;
+}
+
void helper_lsl(void)
{
unsigned int selector, limit;