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 | 19 | */ |
| 20 | 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 | 78 | #if 0 |
| 23 | 79 | /* full interrupt support (only useful for real CPU emulation, not |
| 24 | 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 | 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 | 243 | /* We simulate a pre-MMX pentium as in valgrind */ |
| 112 | 244 | #define CPUID_FP87 (1 << 0) |
| 113 | 245 | #define CPUID_VME (1 << 1) |
| ... | ... | @@ -221,6 +353,24 @@ void load_seg(int seg_reg, int selector, unsigned cur_eip) |
| 221 | 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 | 374 | void helper_lsl(void) |
| 225 | 375 | { |
| 226 | 376 | unsigned int selector, limit; | ... | ... |