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; | ... | ... |