Commit 2d0e9143e2d6fc705cba6c27c221c5c9a7c81a29
1 parent
87f4827e
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
Showing
1 changed file
with
150 additions
and
0 deletions
helper-i386.c
| @@ -19,6 +19,62 @@ | @@ -19,6 +19,62 @@ | ||
| 19 | */ | 19 | */ |
| 20 | #include "exec-i386.h" | 20 | #include "exec-i386.h" |
| 21 | 21 | ||
| 22 | +const CPU86_LDouble f15rk[7] = | ||
| 23 | +{ | ||
| 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*/ | ||
| 31 | +}; | ||
| 32 | + | ||
| 33 | +/* thread support */ | ||
| 34 | + | ||
| 35 | +spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED; | ||
| 36 | + | ||
| 37 | +void cpu_lock(void) | ||
| 38 | +{ | ||
| 39 | + spin_lock(&global_cpu_lock); | ||
| 40 | +} | ||
| 41 | + | ||
| 42 | +void cpu_unlock(void) | ||
| 43 | +{ | ||
| 44 | + spin_unlock(&global_cpu_lock); | ||
| 45 | +} | ||
| 46 | + | ||
| 47 | +void cpu_loop_exit(void) | ||
| 48 | +{ | ||
| 49 | + /* NOTE: the register at this point must be saved by hand because | ||
| 50 | + longjmp restore them */ | ||
| 51 | +#ifdef reg_EAX | ||
| 52 | + env->regs[R_EAX] = EAX; | ||
| 53 | +#endif | ||
| 54 | +#ifdef reg_ECX | ||
| 55 | + env->regs[R_ECX] = ECX; | ||
| 56 | +#endif | ||
| 57 | +#ifdef reg_EDX | ||
| 58 | + env->regs[R_EDX] = EDX; | ||
| 59 | +#endif | ||
| 60 | +#ifdef reg_EBX | ||
| 61 | + env->regs[R_EBX] = EBX; | ||
| 62 | +#endif | ||
| 63 | +#ifdef reg_ESP | ||
| 64 | + env->regs[R_ESP] = ESP; | ||
| 65 | +#endif | ||
| 66 | +#ifdef reg_EBP | ||
| 67 | + env->regs[R_EBP] = EBP; | ||
| 68 | +#endif | ||
| 69 | +#ifdef reg_ESI | ||
| 70 | + env->regs[R_ESI] = ESI; | ||
| 71 | +#endif | ||
| 72 | +#ifdef reg_EDI | ||
| 73 | + env->regs[R_EDI] = EDI; | ||
| 74 | +#endif | ||
| 75 | + longjmp(env->jmp_env, 1); | ||
| 76 | +} | ||
| 77 | + | ||
| 22 | #if 0 | 78 | #if 0 |
| 23 | /* full interrupt support (only useful for real CPU emulation, not | 79 | /* full interrupt support (only useful for real CPU emulation, not |
| 24 | finished) - I won't do it any time soon, finish it if you want ! */ | 80 | finished) - I won't do it any time soon, finish it if you want ! */ |
| @@ -108,6 +164,82 @@ void raise_exception(int exception_index) | @@ -108,6 +164,82 @@ void raise_exception(int exception_index) | ||
| 108 | raise_interrupt(exception_index, 0, 0, 0); | 164 | raise_interrupt(exception_index, 0, 0, 0); |
| 109 | } | 165 | } |
| 110 | 166 | ||
| 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) | ||
| 171 | +{ | ||
| 172 | + *q_ptr = num / den; | ||
| 173 | + return num % den; | ||
| 174 | +} | ||
| 175 | + | ||
| 176 | +int32_t idiv64(int32_t *q_ptr, int64_t num, int32_t den) | ||
| 177 | +{ | ||
| 178 | + *q_ptr = num / den; | ||
| 179 | + return num % den; | ||
| 180 | +} | ||
| 181 | +#endif | ||
| 182 | + | ||
| 183 | +void helper_divl_EAX_T0(uint32_t eip) | ||
| 184 | +{ | ||
| 185 | + unsigned int den, q, r; | ||
| 186 | + uint64_t num; | ||
| 187 | + | ||
| 188 | + num = EAX | ((uint64_t)EDX << 32); | ||
| 189 | + den = T0; | ||
| 190 | + if (den == 0) { | ||
| 191 | + EIP = eip; | ||
| 192 | + raise_exception(EXCP00_DIVZ); | ||
| 193 | + } | ||
| 194 | +#ifdef BUGGY_GCC_DIV64 | ||
| 195 | + r = div64(&q, num, den); | ||
| 196 | +#else | ||
| 197 | + q = (num / den); | ||
| 198 | + r = (num % den); | ||
| 199 | +#endif | ||
| 200 | + EAX = q; | ||
| 201 | + EDX = r; | ||
| 202 | +} | ||
| 203 | + | ||
| 204 | +void helper_idivl_EAX_T0(uint32_t eip) | ||
| 205 | +{ | ||
| 206 | + int den, q, r; | ||
| 207 | + int64_t num; | ||
| 208 | + | ||
| 209 | + num = EAX | ((uint64_t)EDX << 32); | ||
| 210 | + den = T0; | ||
| 211 | + if (den == 0) { | ||
| 212 | + EIP = eip; | ||
| 213 | + raise_exception(EXCP00_DIVZ); | ||
| 214 | + } | ||
| 215 | +#ifdef BUGGY_GCC_DIV64 | ||
| 216 | + r = idiv64(&q, num, den); | ||
| 217 | +#else | ||
| 218 | + q = (num / den); | ||
| 219 | + r = (num % den); | ||
| 220 | +#endif | ||
| 221 | + EAX = q; | ||
| 222 | + EDX = r; | ||
| 223 | +} | ||
| 224 | + | ||
| 225 | +void helper_cmpxchg8b(void) | ||
| 226 | +{ | ||
| 227 | + uint64_t d; | ||
| 228 | + int eflags; | ||
| 229 | + | ||
| 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); | ||
| 234 | + eflags |= CC_Z; | ||
| 235 | + } else { | ||
| 236 | + EDX = d >> 32; | ||
| 237 | + EAX = d; | ||
| 238 | + eflags &= ~CC_Z; | ||
| 239 | + } | ||
| 240 | + CC_SRC = eflags; | ||
| 241 | +} | ||
| 242 | + | ||
| 111 | /* We simulate a pre-MMX pentium as in valgrind */ | 243 | /* We simulate a pre-MMX pentium as in valgrind */ |
| 112 | #define CPUID_FP87 (1 << 0) | 244 | #define CPUID_FP87 (1 << 0) |
| 113 | #define CPUID_VME (1 << 1) | 245 | #define CPUID_VME (1 << 1) |
| @@ -221,6 +353,24 @@ void load_seg(int seg_reg, int selector, unsigned cur_eip) | @@ -221,6 +353,24 @@ void load_seg(int seg_reg, int selector, unsigned cur_eip) | ||
| 221 | env->segs[seg_reg] = selector; | 353 | env->segs[seg_reg] = selector; |
| 222 | } | 354 | } |
| 223 | 355 | ||
| 356 | +/* rdtsc */ | ||
| 357 | +#ifndef __i386__ | ||
| 358 | +uint64_t emu_time; | ||
| 359 | +#endif | ||
| 360 | + | ||
| 361 | +void helper_rdtsc(void) | ||
| 362 | +{ | ||
| 363 | + uint64_t val; | ||
| 364 | +#ifdef __i386__ | ||
| 365 | + asm("rdtsc" : "=A" (val)); | ||
| 366 | +#else | ||
| 367 | + /* better than nothing: the time increases */ | ||
| 368 | + val = emu_time++; | ||
| 369 | +#endif | ||
| 370 | + EAX = val; | ||
| 371 | + EDX = val >> 32; | ||
| 372 | +} | ||
| 373 | + | ||
| 224 | void helper_lsl(void) | 374 | void helper_lsl(void) |
| 225 | { | 375 | { |
| 226 | unsigned int selector, limit; | 376 | unsigned int selector, limit; |