root / op-i386.c @ 1017ebe9
History | View | Annotate | Download (38.9 kB)
1 |
#define DEBUG_EXEC
|
---|---|
2 |
|
3 |
typedef unsigned char uint8_t; |
4 |
typedef unsigned short uint16_t; |
5 |
typedef unsigned int uint32_t; |
6 |
typedef unsigned long long uint64_t; |
7 |
|
8 |
typedef signed char int8_t; |
9 |
typedef signed short int16_t; |
10 |
typedef signed int int32_t; |
11 |
typedef signed long long int64_t; |
12 |
|
13 |
#define bswap32(x) \
|
14 |
({ \ |
15 |
uint32_t __x = (x); \ |
16 |
((uint32_t)( \ |
17 |
(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ |
18 |
(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ |
19 |
(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ |
20 |
(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \ |
21 |
}) |
22 |
|
23 |
#define NULL 0 |
24 |
#include <fenv.h> |
25 |
|
26 |
typedef struct FILE FILE; |
27 |
extern FILE *logfile;
|
28 |
extern int loglevel; |
29 |
extern int fprintf(FILE *, const char *, ...); |
30 |
|
31 |
#ifdef __i386__
|
32 |
register unsigned int T0 asm("ebx"); |
33 |
register unsigned int T1 asm("esi"); |
34 |
register unsigned int A0 asm("edi"); |
35 |
register struct CPUX86State *env asm("ebp"); |
36 |
#endif
|
37 |
#ifdef __powerpc__
|
38 |
register unsigned int T0 asm("r24"); |
39 |
register unsigned int T1 asm("r25"); |
40 |
register unsigned int A0 asm("r26"); |
41 |
register struct CPUX86State *env asm("r27"); |
42 |
#endif
|
43 |
#ifdef __arm__
|
44 |
register unsigned int T0 asm("r4"); |
45 |
register unsigned int T1 asm("r5"); |
46 |
register unsigned int A0 asm("r6"); |
47 |
register struct CPUX86State *env asm("r7"); |
48 |
#endif
|
49 |
#ifdef __mips__
|
50 |
register unsigned int T0 asm("s0"); |
51 |
register unsigned int T1 asm("s1"); |
52 |
register unsigned int A0 asm("s2"); |
53 |
register struct CPUX86State *env asm("s3"); |
54 |
#endif
|
55 |
#ifdef __sparc__
|
56 |
register unsigned int T0 asm("l0"); |
57 |
register unsigned int T1 asm("l1"); |
58 |
register unsigned int A0 asm("l2"); |
59 |
register struct CPUX86State *env asm("l3"); |
60 |
#endif
|
61 |
|
62 |
/* force GCC to generate only one epilog at the end of the function */
|
63 |
#define FORCE_RET() asm volatile (""); |
64 |
|
65 |
#ifndef OPPROTO
|
66 |
#define OPPROTO
|
67 |
#endif
|
68 |
|
69 |
#define xglue(x, y) x ## y |
70 |
#define glue(x, y) xglue(x, y)
|
71 |
|
72 |
#define EAX (env->regs[R_EAX])
|
73 |
#define ECX (env->regs[R_ECX])
|
74 |
#define EDX (env->regs[R_EDX])
|
75 |
#define EBX (env->regs[R_EBX])
|
76 |
#define ESP (env->regs[R_ESP])
|
77 |
#define EBP (env->regs[R_EBP])
|
78 |
#define ESI (env->regs[R_ESI])
|
79 |
#define EDI (env->regs[R_EDI])
|
80 |
#define PC (env->pc)
|
81 |
#define DF (env->df)
|
82 |
|
83 |
#define CC_SRC (env->cc_src)
|
84 |
#define CC_DST (env->cc_dst)
|
85 |
#define CC_OP (env->cc_op)
|
86 |
|
87 |
/* float macros */
|
88 |
#define FT0 (env->ft0)
|
89 |
#define ST0 (env->fpregs[env->fpstt])
|
90 |
#define ST(n) (env->fpregs[(env->fpstt + (n)) & 7]) |
91 |
#define ST1 ST(1) |
92 |
|
93 |
extern int __op_param1, __op_param2, __op_param3; |
94 |
#define PARAM1 ((long)(&__op_param1)) |
95 |
#define PARAM2 ((long)(&__op_param2)) |
96 |
#define PARAM3 ((long)(&__op_param3)) |
97 |
|
98 |
#include "cpu-i386.h" |
99 |
|
100 |
typedef struct CCTable { |
101 |
int (*compute_all)(void); /* return all the flags */ |
102 |
int (*compute_c)(void); /* return the C flag */ |
103 |
} CCTable; |
104 |
|
105 |
/* NOTE: data are not static to force relocation generation by GCC */
|
106 |
extern CCTable cc_table[];
|
107 |
|
108 |
uint8_t parity_table[256] = {
|
109 |
CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, |
110 |
0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, |
111 |
0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, |
112 |
CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, |
113 |
0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, |
114 |
CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, |
115 |
CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, |
116 |
0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, |
117 |
0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, |
118 |
CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, |
119 |
CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, |
120 |
0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, |
121 |
CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, |
122 |
0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, |
123 |
0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, |
124 |
CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, |
125 |
0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, |
126 |
CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, |
127 |
CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, |
128 |
0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, |
129 |
CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, |
130 |
0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, |
131 |
0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, |
132 |
CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, |
133 |
CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, |
134 |
0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, |
135 |
0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, |
136 |
CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, |
137 |
0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, |
138 |
CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, |
139 |
CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, |
140 |
0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, |
141 |
}; |
142 |
|
143 |
/* modulo 17 table */
|
144 |
const uint8_t rclw_table[32] = { |
145 |
0, 1, 2, 3, 4, 5, 6, 7, |
146 |
8, 9,10,11,12,13,14,15, |
147 |
16, 0, 1, 2, 3, 4, 5, 6, |
148 |
7, 8, 9,10,11,12,13,14, |
149 |
}; |
150 |
|
151 |
/* modulo 9 table */
|
152 |
const uint8_t rclb_table[32] = { |
153 |
0, 1, 2, 3, 4, 5, 6, 7, |
154 |
8, 0, 1, 2, 3, 4, 5, 6, |
155 |
7, 8, 0, 1, 2, 3, 4, 5, |
156 |
6, 7, 8, 0, 1, 2, 3, 4, |
157 |
}; |
158 |
|
159 |
#ifdef USE_X86LDOUBLE
|
160 |
/* an array of Intel 80-bit FP constants, to be loaded via integer ops */
|
161 |
typedef unsigned short f15ld[5]; |
162 |
const f15ld f15rk[] =
|
163 |
{ |
164 |
/*0*/ {0x0000,0x0000,0x0000,0x0000,0x0000}, |
165 |
/*1*/ {0x0000,0x0000,0x0000,0x8000,0x3fff}, |
166 |
/*pi*/ {0xc235,0x2168,0xdaa2,0xc90f,0x4000}, |
167 |
/*lg2*/ {0xf799,0xfbcf,0x9a84,0x9a20,0x3ffd}, |
168 |
/*ln2*/ {0x79ac,0xd1cf,0x17f7,0xb172,0x3ffe}, |
169 |
/*l2e*/ {0xf0bc,0x5c17,0x3b29,0xb8aa,0x3fff}, |
170 |
/*l2t*/ {0x8afe,0xcd1b,0x784b,0xd49a,0x4000} |
171 |
}; |
172 |
#else
|
173 |
/* the same, 64-bit version */
|
174 |
typedef unsigned short f15ld[4]; |
175 |
const f15ld f15rk[] =
|
176 |
{ |
177 |
#ifndef WORDS_BIGENDIAN
|
178 |
/*0*/ {0x0000,0x0000,0x0000,0x0000}, |
179 |
/*1*/ {0x0000,0x0000,0x0000,0x3ff0}, |
180 |
/*pi*/ {0x2d18,0x5444,0x21fb,0x4009}, |
181 |
/*lg2*/ {0x79ff,0x509f,0x4413,0x3fd3}, |
182 |
/*ln2*/ {0x39ef,0xfefa,0x2e42,0x3fe6}, |
183 |
/*l2e*/ {0x82fe,0x652b,0x1547,0x3ff7}, |
184 |
/*l2t*/ {0xa371,0x0979,0x934f,0x400a} |
185 |
#else
|
186 |
/*0*/ {0x0000,0x0000,0x0000,0x0000}, |
187 |
/*1*/ {0x3ff0,0x0000,0x0000,0x0000}, |
188 |
/*pi*/ {0x4009,0x21fb,0x5444,0x2d18}, |
189 |
/*lg2*/ {0x3fd3,0x4413,0x509f,0x79ff}, |
190 |
/*ln2*/ {0x3fe6,0x2e42,0xfefa,0x39ef}, |
191 |
/*l2e*/ {0x3ff7,0x1547,0x652b,0x82fe}, |
192 |
/*l2t*/ {0x400a,0x934f,0x0979,0xa371} |
193 |
#endif
|
194 |
}; |
195 |
#endif
|
196 |
|
197 |
/* n must be a constant to be efficient */
|
198 |
static inline int lshift(int x, int n) |
199 |
{ |
200 |
if (n >= 0) |
201 |
return x << n;
|
202 |
else
|
203 |
return x >> (-n);
|
204 |
} |
205 |
|
206 |
/* exception support */
|
207 |
/* NOTE: not static to force relocation generation by GCC */
|
208 |
void raise_exception(int exception_index) |
209 |
{ |
210 |
env->exception_index = exception_index; |
211 |
longjmp(env->jmp_env, 1);
|
212 |
} |
213 |
|
214 |
/* we define the various pieces of code used by the JIT */
|
215 |
|
216 |
#define REG EAX
|
217 |
#define REGNAME _EAX
|
218 |
#include "opreg_template.h" |
219 |
#undef REG
|
220 |
#undef REGNAME
|
221 |
|
222 |
#define REG ECX
|
223 |
#define REGNAME _ECX
|
224 |
#include "opreg_template.h" |
225 |
#undef REG
|
226 |
#undef REGNAME
|
227 |
|
228 |
#define REG EDX
|
229 |
#define REGNAME _EDX
|
230 |
#include "opreg_template.h" |
231 |
#undef REG
|
232 |
#undef REGNAME
|
233 |
|
234 |
#define REG EBX
|
235 |
#define REGNAME _EBX
|
236 |
#include "opreg_template.h" |
237 |
#undef REG
|
238 |
#undef REGNAME
|
239 |
|
240 |
#define REG ESP
|
241 |
#define REGNAME _ESP
|
242 |
#include "opreg_template.h" |
243 |
#undef REG
|
244 |
#undef REGNAME
|
245 |
|
246 |
#define REG EBP
|
247 |
#define REGNAME _EBP
|
248 |
#include "opreg_template.h" |
249 |
#undef REG
|
250 |
#undef REGNAME
|
251 |
|
252 |
#define REG ESI
|
253 |
#define REGNAME _ESI
|
254 |
#include "opreg_template.h" |
255 |
#undef REG
|
256 |
#undef REGNAME
|
257 |
|
258 |
#define REG EDI
|
259 |
#define REGNAME _EDI
|
260 |
#include "opreg_template.h" |
261 |
#undef REG
|
262 |
#undef REGNAME
|
263 |
|
264 |
/* operations */
|
265 |
|
266 |
void OPPROTO op_addl_T0_T1_cc(void) |
267 |
{ |
268 |
CC_SRC = T0; |
269 |
T0 += T1; |
270 |
CC_DST = T0; |
271 |
} |
272 |
|
273 |
void OPPROTO op_orl_T0_T1_cc(void) |
274 |
{ |
275 |
T0 |= T1; |
276 |
CC_DST = T0; |
277 |
} |
278 |
|
279 |
void OPPROTO op_andl_T0_T1_cc(void) |
280 |
{ |
281 |
T0 &= T1; |
282 |
CC_DST = T0; |
283 |
} |
284 |
|
285 |
void OPPROTO op_subl_T0_T1_cc(void) |
286 |
{ |
287 |
CC_SRC = T0; |
288 |
T0 -= T1; |
289 |
CC_DST = T0; |
290 |
} |
291 |
|
292 |
void OPPROTO op_xorl_T0_T1_cc(void) |
293 |
{ |
294 |
T0 ^= T1; |
295 |
CC_DST = T0; |
296 |
} |
297 |
|
298 |
void OPPROTO op_cmpl_T0_T1_cc(void) |
299 |
{ |
300 |
CC_SRC = T0; |
301 |
CC_DST = T0 - T1; |
302 |
} |
303 |
|
304 |
void OPPROTO op_notl_T0(void) |
305 |
{ |
306 |
T0 = ~T0; |
307 |
} |
308 |
|
309 |
void OPPROTO op_negl_T0_cc(void) |
310 |
{ |
311 |
CC_SRC = 0;
|
312 |
T0 = -T0; |
313 |
CC_DST = T0; |
314 |
} |
315 |
|
316 |
void OPPROTO op_incl_T0_cc(void) |
317 |
{ |
318 |
CC_SRC = cc_table[CC_OP].compute_c(); |
319 |
T0++; |
320 |
CC_DST = T0; |
321 |
} |
322 |
|
323 |
void OPPROTO op_decl_T0_cc(void) |
324 |
{ |
325 |
CC_SRC = cc_table[CC_OP].compute_c(); |
326 |
T0--; |
327 |
CC_DST = T0; |
328 |
} |
329 |
|
330 |
void OPPROTO op_testl_T0_T1_cc(void) |
331 |
{ |
332 |
CC_DST = T0 & T1; |
333 |
} |
334 |
|
335 |
void OPPROTO op_bswapl_T0(void) |
336 |
{ |
337 |
T0 = bswap32(T0); |
338 |
} |
339 |
|
340 |
/* multiply/divide */
|
341 |
void OPPROTO op_mulb_AL_T0(void) |
342 |
{ |
343 |
unsigned int res; |
344 |
res = (uint8_t)EAX * (uint8_t)T0; |
345 |
EAX = (EAX & 0xffff0000) | res;
|
346 |
CC_SRC = (res & 0xff00);
|
347 |
} |
348 |
|
349 |
void OPPROTO op_imulb_AL_T0(void) |
350 |
{ |
351 |
int res;
|
352 |
res = (int8_t)EAX * (int8_t)T0; |
353 |
EAX = (EAX & 0xffff0000) | (res & 0xffff); |
354 |
CC_SRC = (res != (int8_t)res); |
355 |
} |
356 |
|
357 |
void OPPROTO op_mulw_AX_T0(void) |
358 |
{ |
359 |
unsigned int res; |
360 |
res = (uint16_t)EAX * (uint16_t)T0; |
361 |
EAX = (EAX & 0xffff0000) | (res & 0xffff); |
362 |
EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff); |
363 |
CC_SRC = res >> 16;
|
364 |
} |
365 |
|
366 |
void OPPROTO op_imulw_AX_T0(void) |
367 |
{ |
368 |
int res;
|
369 |
res = (int16_t)EAX * (int16_t)T0; |
370 |
EAX = (EAX & 0xffff0000) | (res & 0xffff); |
371 |
EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff); |
372 |
CC_SRC = (res != (int16_t)res); |
373 |
} |
374 |
|
375 |
void OPPROTO op_mull_EAX_T0(void) |
376 |
{ |
377 |
uint64_t res; |
378 |
res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0); |
379 |
EAX = res; |
380 |
EDX = res >> 32;
|
381 |
CC_SRC = res >> 32;
|
382 |
} |
383 |
|
384 |
void OPPROTO op_imull_EAX_T0(void) |
385 |
{ |
386 |
int64_t res; |
387 |
res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T0); |
388 |
EAX = res; |
389 |
EDX = res >> 32;
|
390 |
CC_SRC = (res != (int32_t)res); |
391 |
} |
392 |
|
393 |
void OPPROTO op_imulw_T0_T1(void) |
394 |
{ |
395 |
int res;
|
396 |
res = (int16_t)T0 * (int16_t)T1; |
397 |
T0 = res; |
398 |
CC_SRC = (res != (int16_t)res); |
399 |
} |
400 |
|
401 |
void OPPROTO op_imull_T0_T1(void) |
402 |
{ |
403 |
int64_t res; |
404 |
res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1); |
405 |
T0 = res; |
406 |
CC_SRC = (res != (int32_t)res); |
407 |
} |
408 |
|
409 |
/* division, flags are undefined */
|
410 |
/* XXX: add exceptions for overflow & div by zero */
|
411 |
void OPPROTO op_divb_AL_T0(void) |
412 |
{ |
413 |
unsigned int num, den, q, r; |
414 |
|
415 |
num = (EAX & 0xffff);
|
416 |
den = (T0 & 0xff);
|
417 |
q = (num / den) & 0xff;
|
418 |
r = (num % den) & 0xff;
|
419 |
EAX = (EAX & 0xffff0000) | (r << 8) | q; |
420 |
} |
421 |
|
422 |
void OPPROTO op_idivb_AL_T0(void) |
423 |
{ |
424 |
int num, den, q, r;
|
425 |
|
426 |
num = (int16_t)EAX; |
427 |
den = (int8_t)T0; |
428 |
q = (num / den) & 0xff;
|
429 |
r = (num % den) & 0xff;
|
430 |
EAX = (EAX & 0xffff0000) | (r << 8) | q; |
431 |
} |
432 |
|
433 |
void OPPROTO op_divw_AX_T0(void) |
434 |
{ |
435 |
unsigned int num, den, q, r; |
436 |
|
437 |
num = (EAX & 0xffff) | ((EDX & 0xffff) << 16); |
438 |
den = (T0 & 0xffff);
|
439 |
q = (num / den) & 0xffff;
|
440 |
r = (num % den) & 0xffff;
|
441 |
EAX = (EAX & 0xffff0000) | q;
|
442 |
EDX = (EDX & 0xffff0000) | r;
|
443 |
} |
444 |
|
445 |
void OPPROTO op_idivw_AX_T0(void) |
446 |
{ |
447 |
int num, den, q, r;
|
448 |
|
449 |
num = (EAX & 0xffff) | ((EDX & 0xffff) << 16); |
450 |
den = (int16_t)T0; |
451 |
q = (num / den) & 0xffff;
|
452 |
r = (num % den) & 0xffff;
|
453 |
EAX = (EAX & 0xffff0000) | q;
|
454 |
EDX = (EDX & 0xffff0000) | r;
|
455 |
} |
456 |
|
457 |
void OPPROTO op_divl_EAX_T0(void) |
458 |
{ |
459 |
unsigned int den, q, r; |
460 |
uint64_t num; |
461 |
|
462 |
num = EAX | ((uint64_t)EDX << 32);
|
463 |
den = T0; |
464 |
q = (num / den); |
465 |
r = (num % den); |
466 |
EAX = q; |
467 |
EDX = r; |
468 |
} |
469 |
|
470 |
void OPPROTO op_idivl_EAX_T0(void) |
471 |
{ |
472 |
int den, q, r;
|
473 |
int64_t num; |
474 |
|
475 |
num = EAX | ((uint64_t)EDX << 32);
|
476 |
den = T0; |
477 |
q = (num / den); |
478 |
r = (num % den); |
479 |
EAX = q; |
480 |
EDX = r; |
481 |
} |
482 |
|
483 |
/* constant load */
|
484 |
|
485 |
void OPPROTO op_movl_T0_im(void) |
486 |
{ |
487 |
T0 = PARAM1; |
488 |
} |
489 |
|
490 |
void OPPROTO op_movl_T1_im(void) |
491 |
{ |
492 |
T1 = PARAM1; |
493 |
} |
494 |
|
495 |
void OPPROTO op_movl_A0_im(void) |
496 |
{ |
497 |
A0 = PARAM1; |
498 |
} |
499 |
|
500 |
void OPPROTO op_addl_A0_im(void) |
501 |
{ |
502 |
A0 += PARAM1; |
503 |
} |
504 |
|
505 |
void OPPROTO op_andl_A0_ffff(void) |
506 |
{ |
507 |
A0 = A0 & 0xffff;
|
508 |
} |
509 |
|
510 |
/* memory access */
|
511 |
|
512 |
void OPPROTO op_ldub_T0_A0(void) |
513 |
{ |
514 |
T0 = ldub((uint8_t *)A0); |
515 |
} |
516 |
|
517 |
void OPPROTO op_ldsb_T0_A0(void) |
518 |
{ |
519 |
T0 = ldsb((int8_t *)A0); |
520 |
} |
521 |
|
522 |
void OPPROTO op_lduw_T0_A0(void) |
523 |
{ |
524 |
T0 = lduw((uint8_t *)A0); |
525 |
} |
526 |
|
527 |
void OPPROTO op_ldsw_T0_A0(void) |
528 |
{ |
529 |
T0 = ldsw((int8_t *)A0); |
530 |
} |
531 |
|
532 |
void OPPROTO op_ldl_T0_A0(void) |
533 |
{ |
534 |
T0 = ldl((uint8_t *)A0); |
535 |
} |
536 |
|
537 |
void OPPROTO op_ldub_T1_A0(void) |
538 |
{ |
539 |
T1 = ldub((uint8_t *)A0); |
540 |
} |
541 |
|
542 |
void OPPROTO op_ldsb_T1_A0(void) |
543 |
{ |
544 |
T1 = ldsb((int8_t *)A0); |
545 |
} |
546 |
|
547 |
void OPPROTO op_lduw_T1_A0(void) |
548 |
{ |
549 |
T1 = lduw((uint8_t *)A0); |
550 |
} |
551 |
|
552 |
void OPPROTO op_ldsw_T1_A0(void) |
553 |
{ |
554 |
T1 = ldsw((int8_t *)A0); |
555 |
} |
556 |
|
557 |
void OPPROTO op_ldl_T1_A0(void) |
558 |
{ |
559 |
T1 = ldl((uint8_t *)A0); |
560 |
} |
561 |
|
562 |
void OPPROTO op_stb_T0_A0(void) |
563 |
{ |
564 |
stb((uint8_t *)A0, T0); |
565 |
} |
566 |
|
567 |
void OPPROTO op_stw_T0_A0(void) |
568 |
{ |
569 |
stw((uint8_t *)A0, T0); |
570 |
} |
571 |
|
572 |
void OPPROTO op_stl_T0_A0(void) |
573 |
{ |
574 |
stl((uint8_t *)A0, T0); |
575 |
} |
576 |
|
577 |
/* used for bit operations */
|
578 |
|
579 |
void OPPROTO op_add_bitw_A0_T1(void) |
580 |
{ |
581 |
A0 += ((int32_t)T1 >> 4) << 1; |
582 |
} |
583 |
|
584 |
void OPPROTO op_add_bitl_A0_T1(void) |
585 |
{ |
586 |
A0 += ((int32_t)T1 >> 5) << 2; |
587 |
} |
588 |
|
589 |
/* indirect jump */
|
590 |
|
591 |
void OPPROTO op_jmp_T0(void) |
592 |
{ |
593 |
PC = T0; |
594 |
} |
595 |
|
596 |
void OPPROTO op_jmp_im(void) |
597 |
{ |
598 |
PC = PARAM1; |
599 |
} |
600 |
|
601 |
void OPPROTO op_int_im(void) |
602 |
{ |
603 |
PC = PARAM1; |
604 |
raise_exception(EXCP0D_GPF); |
605 |
} |
606 |
|
607 |
void OPPROTO op_int3(void) |
608 |
{ |
609 |
PC = PARAM1; |
610 |
raise_exception(EXCP03_INT3); |
611 |
} |
612 |
|
613 |
void OPPROTO op_into(void) |
614 |
{ |
615 |
int eflags;
|
616 |
eflags = cc_table[CC_OP].compute_all(); |
617 |
if (eflags & CC_O) {
|
618 |
PC = PARAM1; |
619 |
raise_exception(EXCP04_INTO); |
620 |
} else {
|
621 |
PC = PARAM2; |
622 |
} |
623 |
} |
624 |
|
625 |
/* string ops */
|
626 |
|
627 |
#define ldul ldl
|
628 |
|
629 |
#define SHIFT 0 |
630 |
#include "ops_template.h" |
631 |
#undef SHIFT
|
632 |
|
633 |
#define SHIFT 1 |
634 |
#include "ops_template.h" |
635 |
#undef SHIFT
|
636 |
|
637 |
#define SHIFT 2 |
638 |
#include "ops_template.h" |
639 |
#undef SHIFT
|
640 |
|
641 |
/* sign extend */
|
642 |
|
643 |
void OPPROTO op_movsbl_T0_T0(void) |
644 |
{ |
645 |
T0 = (int8_t)T0; |
646 |
} |
647 |
|
648 |
void OPPROTO op_movzbl_T0_T0(void) |
649 |
{ |
650 |
T0 = (uint8_t)T0; |
651 |
} |
652 |
|
653 |
void OPPROTO op_movswl_T0_T0(void) |
654 |
{ |
655 |
T0 = (int16_t)T0; |
656 |
} |
657 |
|
658 |
void OPPROTO op_movzwl_T0_T0(void) |
659 |
{ |
660 |
T0 = (uint16_t)T0; |
661 |
} |
662 |
|
663 |
void OPPROTO op_movswl_EAX_AX(void) |
664 |
{ |
665 |
EAX = (int16_t)EAX; |
666 |
} |
667 |
|
668 |
void OPPROTO op_movsbw_AX_AL(void) |
669 |
{ |
670 |
EAX = (EAX & 0xffff0000) | ((int8_t)EAX & 0xffff); |
671 |
} |
672 |
|
673 |
void OPPROTO op_movslq_EDX_EAX(void) |
674 |
{ |
675 |
EDX = (int32_t)EAX >> 31;
|
676 |
} |
677 |
|
678 |
void OPPROTO op_movswl_DX_AX(void) |
679 |
{ |
680 |
EDX = (EDX & 0xffff0000) | (((int16_t)EAX >> 15) & 0xffff); |
681 |
} |
682 |
|
683 |
/* push/pop */
|
684 |
/* XXX: add 16 bit operand/16 bit seg variants */
|
685 |
|
686 |
void op_pushl_T0(void) |
687 |
{ |
688 |
uint32_t offset; |
689 |
offset = ESP - 4;
|
690 |
stl((void *)offset, T0);
|
691 |
/* modify ESP after to handle exceptions correctly */
|
692 |
ESP = offset; |
693 |
} |
694 |
|
695 |
void op_pushl_T1(void) |
696 |
{ |
697 |
uint32_t offset; |
698 |
offset = ESP - 4;
|
699 |
stl((void *)offset, T1);
|
700 |
/* modify ESP after to handle exceptions correctly */
|
701 |
ESP = offset; |
702 |
} |
703 |
|
704 |
void op_popl_T0(void) |
705 |
{ |
706 |
T0 = ldl((void *)ESP);
|
707 |
ESP += 4;
|
708 |
} |
709 |
|
710 |
void op_addl_ESP_im(void) |
711 |
{ |
712 |
ESP += PARAM1; |
713 |
} |
714 |
|
715 |
/* flags handling */
|
716 |
|
717 |
/* slow jumps cases (compute x86 flags) */
|
718 |
void OPPROTO op_jo_cc(void) |
719 |
{ |
720 |
int eflags;
|
721 |
eflags = cc_table[CC_OP].compute_all(); |
722 |
if (eflags & CC_O)
|
723 |
PC = PARAM1; |
724 |
else
|
725 |
PC = PARAM2; |
726 |
FORCE_RET(); |
727 |
} |
728 |
|
729 |
void OPPROTO op_jb_cc(void) |
730 |
{ |
731 |
if (cc_table[CC_OP].compute_c())
|
732 |
PC = PARAM1; |
733 |
else
|
734 |
PC = PARAM2; |
735 |
FORCE_RET(); |
736 |
} |
737 |
|
738 |
void OPPROTO op_jz_cc(void) |
739 |
{ |
740 |
int eflags;
|
741 |
eflags = cc_table[CC_OP].compute_all(); |
742 |
if (eflags & CC_Z)
|
743 |
PC = PARAM1; |
744 |
else
|
745 |
PC = PARAM2; |
746 |
FORCE_RET(); |
747 |
} |
748 |
|
749 |
void OPPROTO op_jbe_cc(void) |
750 |
{ |
751 |
int eflags;
|
752 |
eflags = cc_table[CC_OP].compute_all(); |
753 |
if (eflags & (CC_Z | CC_C))
|
754 |
PC = PARAM1; |
755 |
else
|
756 |
PC = PARAM2; |
757 |
FORCE_RET(); |
758 |
} |
759 |
|
760 |
void OPPROTO op_js_cc(void) |
761 |
{ |
762 |
int eflags;
|
763 |
eflags = cc_table[CC_OP].compute_all(); |
764 |
if (eflags & CC_S)
|
765 |
PC = PARAM1; |
766 |
else
|
767 |
PC = PARAM2; |
768 |
FORCE_RET(); |
769 |
} |
770 |
|
771 |
void OPPROTO op_jp_cc(void) |
772 |
{ |
773 |
int eflags;
|
774 |
eflags = cc_table[CC_OP].compute_all(); |
775 |
if (eflags & CC_P)
|
776 |
PC = PARAM1; |
777 |
else
|
778 |
PC = PARAM2; |
779 |
FORCE_RET(); |
780 |
} |
781 |
|
782 |
void OPPROTO op_jl_cc(void) |
783 |
{ |
784 |
int eflags;
|
785 |
eflags = cc_table[CC_OP].compute_all(); |
786 |
if ((eflags ^ (eflags >> 4)) & 0x80) |
787 |
PC = PARAM1; |
788 |
else
|
789 |
PC = PARAM2; |
790 |
FORCE_RET(); |
791 |
} |
792 |
|
793 |
void OPPROTO op_jle_cc(void) |
794 |
{ |
795 |
int eflags;
|
796 |
eflags = cc_table[CC_OP].compute_all(); |
797 |
if (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) |
798 |
PC = PARAM1; |
799 |
else
|
800 |
PC = PARAM2; |
801 |
FORCE_RET(); |
802 |
} |
803 |
|
804 |
/* slow set cases (compute x86 flags) */
|
805 |
void OPPROTO op_seto_T0_cc(void) |
806 |
{ |
807 |
int eflags;
|
808 |
eflags = cc_table[CC_OP].compute_all(); |
809 |
T0 = (eflags >> 11) & 1; |
810 |
} |
811 |
|
812 |
void OPPROTO op_setb_T0_cc(void) |
813 |
{ |
814 |
T0 = cc_table[CC_OP].compute_c(); |
815 |
} |
816 |
|
817 |
void OPPROTO op_setz_T0_cc(void) |
818 |
{ |
819 |
int eflags;
|
820 |
eflags = cc_table[CC_OP].compute_all(); |
821 |
T0 = (eflags >> 6) & 1; |
822 |
} |
823 |
|
824 |
void OPPROTO op_setbe_T0_cc(void) |
825 |
{ |
826 |
int eflags;
|
827 |
eflags = cc_table[CC_OP].compute_all(); |
828 |
T0 = (eflags & (CC_Z | CC_C)) != 0;
|
829 |
} |
830 |
|
831 |
void OPPROTO op_sets_T0_cc(void) |
832 |
{ |
833 |
int eflags;
|
834 |
eflags = cc_table[CC_OP].compute_all(); |
835 |
T0 = (eflags >> 7) & 1; |
836 |
} |
837 |
|
838 |
void OPPROTO op_setp_T0_cc(void) |
839 |
{ |
840 |
int eflags;
|
841 |
eflags = cc_table[CC_OP].compute_all(); |
842 |
T0 = (eflags >> 2) & 1; |
843 |
} |
844 |
|
845 |
void OPPROTO op_setl_T0_cc(void) |
846 |
{ |
847 |
int eflags;
|
848 |
eflags = cc_table[CC_OP].compute_all(); |
849 |
T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1; |
850 |
} |
851 |
|
852 |
void OPPROTO op_setle_T0_cc(void) |
853 |
{ |
854 |
int eflags;
|
855 |
eflags = cc_table[CC_OP].compute_all(); |
856 |
T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0; |
857 |
} |
858 |
|
859 |
void OPPROTO op_xor_T0_1(void) |
860 |
{ |
861 |
T0 ^= 1;
|
862 |
} |
863 |
|
864 |
void OPPROTO op_set_cc_op(void) |
865 |
{ |
866 |
CC_OP = PARAM1; |
867 |
} |
868 |
|
869 |
void OPPROTO op_movl_eflags_T0(void) |
870 |
{ |
871 |
CC_SRC = T0; |
872 |
DF = 1 - (2 * ((T0 >> 10) & 1)); |
873 |
} |
874 |
|
875 |
/* XXX: compute only O flag */
|
876 |
void OPPROTO op_movb_eflags_T0(void) |
877 |
{ |
878 |
int of;
|
879 |
of = cc_table[CC_OP].compute_all() & CC_O; |
880 |
CC_SRC = T0 | of; |
881 |
} |
882 |
|
883 |
void OPPROTO op_movl_T0_eflags(void) |
884 |
{ |
885 |
T0 = cc_table[CC_OP].compute_all(); |
886 |
T0 |= (DF & DIRECTION_FLAG); |
887 |
} |
888 |
|
889 |
void OPPROTO op_cld(void) |
890 |
{ |
891 |
DF = 1;
|
892 |
} |
893 |
|
894 |
void OPPROTO op_std(void) |
895 |
{ |
896 |
DF = -1;
|
897 |
} |
898 |
|
899 |
void OPPROTO op_clc(void) |
900 |
{ |
901 |
int eflags;
|
902 |
eflags = cc_table[CC_OP].compute_all(); |
903 |
eflags &= ~CC_C; |
904 |
CC_SRC = eflags; |
905 |
} |
906 |
|
907 |
void OPPROTO op_stc(void) |
908 |
{ |
909 |
int eflags;
|
910 |
eflags = cc_table[CC_OP].compute_all(); |
911 |
eflags |= CC_C; |
912 |
CC_SRC = eflags; |
913 |
} |
914 |
|
915 |
void OPPROTO op_cmc(void) |
916 |
{ |
917 |
int eflags;
|
918 |
eflags = cc_table[CC_OP].compute_all(); |
919 |
eflags ^= CC_C; |
920 |
CC_SRC = eflags; |
921 |
} |
922 |
|
923 |
static int compute_all_eflags(void) |
924 |
{ |
925 |
return CC_SRC;
|
926 |
} |
927 |
|
928 |
static int compute_c_eflags(void) |
929 |
{ |
930 |
return CC_SRC & CC_C;
|
931 |
} |
932 |
|
933 |
static int compute_c_mul(void) |
934 |
{ |
935 |
int cf;
|
936 |
cf = (CC_SRC != 0);
|
937 |
return cf;
|
938 |
} |
939 |
|
940 |
static int compute_all_mul(void) |
941 |
{ |
942 |
int cf, pf, af, zf, sf, of;
|
943 |
cf = (CC_SRC != 0);
|
944 |
pf = 0; /* undefined */ |
945 |
af = 0; /* undefined */ |
946 |
zf = 0; /* undefined */ |
947 |
sf = 0; /* undefined */ |
948 |
of = cf << 11;
|
949 |
return cf | pf | af | zf | sf | of;
|
950 |
} |
951 |
|
952 |
CCTable cc_table[CC_OP_NB] = { |
953 |
[CC_OP_DYNAMIC] = { /* should never happen */ },
|
954 |
|
955 |
[CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags }, |
956 |
|
957 |
[CC_OP_MUL] = { compute_all_mul, compute_c_mul }, |
958 |
|
959 |
[CC_OP_ADDB] = { compute_all_addb, compute_c_addb }, |
960 |
[CC_OP_ADDW] = { compute_all_addw, compute_c_addw }, |
961 |
[CC_OP_ADDL] = { compute_all_addl, compute_c_addl }, |
962 |
|
963 |
[CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb }, |
964 |
[CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw }, |
965 |
[CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl }, |
966 |
|
967 |
[CC_OP_SUBB] = { compute_all_subb, compute_c_subb }, |
968 |
[CC_OP_SUBW] = { compute_all_subw, compute_c_subw }, |
969 |
[CC_OP_SUBL] = { compute_all_subl, compute_c_subl }, |
970 |
|
971 |
[CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb }, |
972 |
[CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw }, |
973 |
[CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl }, |
974 |
|
975 |
[CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb }, |
976 |
[CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw }, |
977 |
[CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl }, |
978 |
|
979 |
[CC_OP_INCB] = { compute_all_incb, compute_c_incl }, |
980 |
[CC_OP_INCW] = { compute_all_incw, compute_c_incl }, |
981 |
[CC_OP_INCL] = { compute_all_incl, compute_c_incl }, |
982 |
|
983 |
[CC_OP_DECB] = { compute_all_decb, compute_c_incl }, |
984 |
[CC_OP_DECW] = { compute_all_decw, compute_c_incl }, |
985 |
[CC_OP_DECL] = { compute_all_decl, compute_c_incl }, |
986 |
|
987 |
[CC_OP_SHLB] = { compute_all_shlb, compute_c_shll }, |
988 |
[CC_OP_SHLW] = { compute_all_shlw, compute_c_shll }, |
989 |
[CC_OP_SHLL] = { compute_all_shll, compute_c_shll }, |
990 |
|
991 |
[CC_OP_SARB] = { compute_all_sarb, compute_c_shll }, |
992 |
[CC_OP_SARW] = { compute_all_sarw, compute_c_shll }, |
993 |
[CC_OP_SARL] = { compute_all_sarl, compute_c_shll }, |
994 |
}; |
995 |
|
996 |
/* floating point support */
|
997 |
|
998 |
#ifdef USE_X86LDOUBLE
|
999 |
/* use long double functions */
|
1000 |
#define lrint lrintl
|
1001 |
#define llrint llrintl
|
1002 |
#define fabs fabsl
|
1003 |
#define sin sinl
|
1004 |
#define cos cosl
|
1005 |
#define sqrt sqrtl
|
1006 |
#define pow powl
|
1007 |
#define log logl
|
1008 |
#define tan tanl
|
1009 |
#define atan2 atan2l
|
1010 |
#define floor floorl
|
1011 |
#define ceil ceill
|
1012 |
#define rint rintl
|
1013 |
#endif
|
1014 |
|
1015 |
extern int lrint(CPU86_LDouble x); |
1016 |
extern int64_t llrint(CPU86_LDouble x);
|
1017 |
extern CPU86_LDouble fabs(CPU86_LDouble x);
|
1018 |
extern CPU86_LDouble sin(CPU86_LDouble x);
|
1019 |
extern CPU86_LDouble cos(CPU86_LDouble x);
|
1020 |
extern CPU86_LDouble sqrt(CPU86_LDouble x);
|
1021 |
extern CPU86_LDouble pow(CPU86_LDouble, CPU86_LDouble);
|
1022 |
extern CPU86_LDouble log(CPU86_LDouble x);
|
1023 |
extern CPU86_LDouble tan(CPU86_LDouble x);
|
1024 |
extern CPU86_LDouble atan2(CPU86_LDouble, CPU86_LDouble);
|
1025 |
extern CPU86_LDouble floor(CPU86_LDouble x);
|
1026 |
extern CPU86_LDouble ceil(CPU86_LDouble x);
|
1027 |
extern CPU86_LDouble rint(CPU86_LDouble x);
|
1028 |
|
1029 |
#define RC_MASK 0xc00 |
1030 |
#define RC_NEAR 0x000 |
1031 |
#define RC_DOWN 0x400 |
1032 |
#define RC_UP 0x800 |
1033 |
#define RC_CHOP 0xc00 |
1034 |
|
1035 |
#define MAXTAN 9223372036854775808.0 |
1036 |
|
1037 |
#ifdef USE_X86LDOUBLE
|
1038 |
|
1039 |
/* only for x86 */
|
1040 |
typedef union { |
1041 |
long double d; |
1042 |
struct {
|
1043 |
unsigned long long lower; |
1044 |
unsigned short upper; |
1045 |
} l; |
1046 |
} CPU86_LDoubleU; |
1047 |
|
1048 |
/* the following deal with x86 long double-precision numbers */
|
1049 |
#define MAXEXPD 0x7fff |
1050 |
#define EXPBIAS 16383 |
1051 |
#define EXPD(fp) (fp.l.upper & 0x7fff) |
1052 |
#define SIGND(fp) ((fp.l.upper) & 0x8000) |
1053 |
#define MANTD(fp) (fp.l.lower)
|
1054 |
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS |
1055 |
|
1056 |
#else
|
1057 |
|
1058 |
typedef union { |
1059 |
double d;
|
1060 |
#ifndef WORDS_BIGENDIAN
|
1061 |
struct {
|
1062 |
unsigned long lower; |
1063 |
long upper;
|
1064 |
} l; |
1065 |
#else
|
1066 |
struct {
|
1067 |
long upper;
|
1068 |
unsigned long lower; |
1069 |
} l; |
1070 |
#endif
|
1071 |
long long ll; |
1072 |
} CPU86_LDoubleU; |
1073 |
|
1074 |
/* the following deal with IEEE double-precision numbers */
|
1075 |
#define MAXEXPD 0x7ff |
1076 |
#define EXPBIAS 1023 |
1077 |
#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF) |
1078 |
#define SIGND(fp) ((fp.l.upper) & 0x80000000) |
1079 |
#define MANTD(fp) (fp.ll & ((1LL << 52) - 1)) |
1080 |
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20) |
1081 |
#endif
|
1082 |
|
1083 |
/* fp load FT0 */
|
1084 |
|
1085 |
void OPPROTO op_flds_FT0_A0(void) |
1086 |
{ |
1087 |
FT0 = ldfl((void *)A0);
|
1088 |
} |
1089 |
|
1090 |
void OPPROTO op_fldl_FT0_A0(void) |
1091 |
{ |
1092 |
FT0 = ldfq((void *)A0);
|
1093 |
} |
1094 |
|
1095 |
void OPPROTO op_fild_FT0_A0(void) |
1096 |
{ |
1097 |
FT0 = (CPU86_LDouble)ldsw((void *)A0);
|
1098 |
} |
1099 |
|
1100 |
void OPPROTO op_fildl_FT0_A0(void) |
1101 |
{ |
1102 |
FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
|
1103 |
} |
1104 |
|
1105 |
void OPPROTO op_fildll_FT0_A0(void) |
1106 |
{ |
1107 |
FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
|
1108 |
} |
1109 |
|
1110 |
/* fp load ST0 */
|
1111 |
|
1112 |
void OPPROTO op_flds_ST0_A0(void) |
1113 |
{ |
1114 |
ST0 = ldfl((void *)A0);
|
1115 |
} |
1116 |
|
1117 |
void OPPROTO op_fldl_ST0_A0(void) |
1118 |
{ |
1119 |
ST0 = ldfq((void *)A0);
|
1120 |
} |
1121 |
|
1122 |
#ifdef USE_X86LDOUBLE
|
1123 |
void OPPROTO op_fldt_ST0_A0(void) |
1124 |
{ |
1125 |
ST0 = *(long double *)A0; |
1126 |
} |
1127 |
#else
|
1128 |
void helper_fldt_ST0_A0(void) |
1129 |
{ |
1130 |
CPU86_LDoubleU temp; |
1131 |
int upper, e;
|
1132 |
/* mantissa */
|
1133 |
upper = lduw((uint8_t *)A0 + 8);
|
1134 |
/* XXX: handle overflow ? */
|
1135 |
e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */ |
1136 |
e |= (upper >> 4) & 0x800; /* sign */ |
1137 |
temp.ll = ((ldq((void *)A0) >> 11) & ((1LL << 52) - 1)) | ((uint64_t)e << 52); |
1138 |
ST0 = temp.d; |
1139 |
} |
1140 |
|
1141 |
void OPPROTO op_fldt_ST0_A0(void) |
1142 |
{ |
1143 |
helper_fldt_ST0_A0(); |
1144 |
} |
1145 |
#endif
|
1146 |
|
1147 |
void OPPROTO op_fild_ST0_A0(void) |
1148 |
{ |
1149 |
ST0 = (CPU86_LDouble)ldsw((void *)A0);
|
1150 |
} |
1151 |
|
1152 |
void OPPROTO op_fildl_ST0_A0(void) |
1153 |
{ |
1154 |
ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
|
1155 |
} |
1156 |
|
1157 |
void OPPROTO op_fildll_ST0_A0(void) |
1158 |
{ |
1159 |
ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
|
1160 |
} |
1161 |
|
1162 |
/* fp store */
|
1163 |
|
1164 |
void OPPROTO op_fsts_ST0_A0(void) |
1165 |
{ |
1166 |
stfl((void *)A0, (float)ST0); |
1167 |
} |
1168 |
|
1169 |
void OPPROTO op_fstl_ST0_A0(void) |
1170 |
{ |
1171 |
stfq((void *)A0, (double)ST0); |
1172 |
} |
1173 |
|
1174 |
#ifdef USE_X86LDOUBLE
|
1175 |
void OPPROTO op_fstt_ST0_A0(void) |
1176 |
{ |
1177 |
*(long double *)A0 = ST0; |
1178 |
} |
1179 |
#else
|
1180 |
void helper_fstt_ST0_A0(void) |
1181 |
{ |
1182 |
CPU86_LDoubleU temp; |
1183 |
int e;
|
1184 |
temp.d = ST0; |
1185 |
/* mantissa */
|
1186 |
stq((void *)A0, (MANTD(temp) << 11) | (1LL << 63)); |
1187 |
/* exponent + sign */
|
1188 |
e = EXPD(temp) - EXPBIAS + 16383;
|
1189 |
e |= SIGND(temp) >> 16;
|
1190 |
stw((uint8_t *)A0 + 8, e);
|
1191 |
} |
1192 |
|
1193 |
void OPPROTO op_fstt_ST0_A0(void) |
1194 |
{ |
1195 |
helper_fstt_ST0_A0(); |
1196 |
} |
1197 |
#endif
|
1198 |
|
1199 |
void OPPROTO op_fist_ST0_A0(void) |
1200 |
{ |
1201 |
int val;
|
1202 |
val = lrint(ST0); |
1203 |
stw((void *)A0, val);
|
1204 |
} |
1205 |
|
1206 |
void OPPROTO op_fistl_ST0_A0(void) |
1207 |
{ |
1208 |
int val;
|
1209 |
val = lrint(ST0); |
1210 |
stl((void *)A0, val);
|
1211 |
} |
1212 |
|
1213 |
void OPPROTO op_fistll_ST0_A0(void) |
1214 |
{ |
1215 |
int64_t val; |
1216 |
val = llrint(ST0); |
1217 |
stq((void *)A0, val);
|
1218 |
} |
1219 |
|
1220 |
/* BCD ops */
|
1221 |
|
1222 |
#define MUL10(iv) ( iv + iv + (iv << 3) ) |
1223 |
|
1224 |
void helper_fbld_ST0_A0(void) |
1225 |
{ |
1226 |
uint8_t *seg; |
1227 |
CPU86_LDouble fpsrcop; |
1228 |
int m32i;
|
1229 |
unsigned int v; |
1230 |
|
1231 |
/* in this code, seg/m32i will be used as temporary ptr/int */
|
1232 |
seg = (uint8_t *)A0 + 8;
|
1233 |
v = ldub(seg--); |
1234 |
/* XXX: raise exception */
|
1235 |
if (v != 0) |
1236 |
return;
|
1237 |
v = ldub(seg--); |
1238 |
/* XXX: raise exception */
|
1239 |
if ((v & 0xf0) != 0) |
1240 |
return;
|
1241 |
m32i = v; /* <-- d14 */
|
1242 |
v = ldub(seg--); |
1243 |
m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d13 */ |
1244 |
m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d12 */ |
1245 |
v = ldub(seg--); |
1246 |
m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d11 */ |
1247 |
m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d10 */ |
1248 |
v = ldub(seg--); |
1249 |
m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d9 */ |
1250 |
m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d8 */ |
1251 |
fpsrcop = ((CPU86_LDouble)m32i) * 100000000.0; |
1252 |
|
1253 |
v = ldub(seg--); |
1254 |
m32i = (v >> 4); /* <-- d7 */ |
1255 |
m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d6 */ |
1256 |
v = ldub(seg--); |
1257 |
m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d5 */ |
1258 |
m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d4 */ |
1259 |
v = ldub(seg--); |
1260 |
m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d3 */ |
1261 |
m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d2 */ |
1262 |
v = ldub(seg); |
1263 |
m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d1 */ |
1264 |
m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d0 */ |
1265 |
fpsrcop += ((CPU86_LDouble)m32i); |
1266 |
if ( ldub(seg+9) & 0x80 ) |
1267 |
fpsrcop = -fpsrcop; |
1268 |
ST0 = fpsrcop; |
1269 |
} |
1270 |
|
1271 |
void OPPROTO op_fbld_ST0_A0(void) |
1272 |
{ |
1273 |
helper_fbld_ST0_A0(); |
1274 |
} |
1275 |
|
1276 |
void helper_fbst_ST0_A0(void) |
1277 |
{ |
1278 |
CPU86_LDouble fptemp; |
1279 |
CPU86_LDouble fpsrcop; |
1280 |
int v;
|
1281 |
uint8_t *mem_ref, *mem_end; |
1282 |
|
1283 |
fpsrcop = rint(ST0); |
1284 |
mem_ref = (uint8_t *)A0; |
1285 |
mem_end = mem_ref + 8;
|
1286 |
if ( fpsrcop < 0.0 ) { |
1287 |
stw(mem_end, 0x8000);
|
1288 |
fpsrcop = -fpsrcop; |
1289 |
} else {
|
1290 |
stw(mem_end, 0x0000);
|
1291 |
} |
1292 |
while (mem_ref < mem_end) {
|
1293 |
if (fpsrcop == 0.0) |
1294 |
break;
|
1295 |
fptemp = floor(fpsrcop/10.0); |
1296 |
v = ((int)(fpsrcop - fptemp*10.0)); |
1297 |
if (fptemp == 0.0) { |
1298 |
stb(mem_ref++, v); |
1299 |
break;
|
1300 |
} |
1301 |
fpsrcop = fptemp; |
1302 |
fptemp = floor(fpsrcop/10.0); |
1303 |
v |= (((int)(fpsrcop - fptemp*10.0)) << 4); |
1304 |
stb(mem_ref++, v); |
1305 |
fpsrcop = fptemp; |
1306 |
} |
1307 |
while (mem_ref < mem_end) {
|
1308 |
stb(mem_ref++, 0);
|
1309 |
} |
1310 |
} |
1311 |
|
1312 |
void OPPROTO op_fbst_ST0_A0(void) |
1313 |
{ |
1314 |
helper_fbst_ST0_A0(); |
1315 |
} |
1316 |
|
1317 |
/* FPU move */
|
1318 |
|
1319 |
static inline void fpush(void) |
1320 |
{ |
1321 |
env->fpstt = (env->fpstt - 1) & 7; |
1322 |
env->fptags[env->fpstt] = 0; /* validate stack entry */ |
1323 |
} |
1324 |
|
1325 |
static inline void fpop(void) |
1326 |
{ |
1327 |
env->fptags[env->fpstt] = 1; /* invvalidate stack entry */ |
1328 |
env->fpstt = (env->fpstt + 1) & 7; |
1329 |
} |
1330 |
|
1331 |
void OPPROTO op_fpush(void) |
1332 |
{ |
1333 |
fpush(); |
1334 |
} |
1335 |
|
1336 |
void OPPROTO op_fpop(void) |
1337 |
{ |
1338 |
fpop(); |
1339 |
} |
1340 |
|
1341 |
void OPPROTO op_fdecstp(void) |
1342 |
{ |
1343 |
env->fpstt = (env->fpstt - 1) & 7; |
1344 |
env->fpus &= (~0x4700);
|
1345 |
} |
1346 |
|
1347 |
void OPPROTO op_fincstp(void) |
1348 |
{ |
1349 |
env->fpstt = (env->fpstt + 1) & 7; |
1350 |
env->fpus &= (~0x4700);
|
1351 |
} |
1352 |
|
1353 |
void OPPROTO op_fmov_ST0_FT0(void) |
1354 |
{ |
1355 |
ST0 = FT0; |
1356 |
} |
1357 |
|
1358 |
void OPPROTO op_fmov_FT0_STN(void) |
1359 |
{ |
1360 |
FT0 = ST(PARAM1); |
1361 |
} |
1362 |
|
1363 |
void OPPROTO op_fmov_ST0_STN(void) |
1364 |
{ |
1365 |
ST0 = ST(PARAM1); |
1366 |
} |
1367 |
|
1368 |
void OPPROTO op_fmov_STN_ST0(void) |
1369 |
{ |
1370 |
ST(PARAM1) = ST0; |
1371 |
} |
1372 |
|
1373 |
void OPPROTO op_fxchg_ST0_STN(void) |
1374 |
{ |
1375 |
CPU86_LDouble tmp; |
1376 |
tmp = ST(PARAM1); |
1377 |
ST(PARAM1) = ST0; |
1378 |
ST0 = tmp; |
1379 |
} |
1380 |
|
1381 |
/* FPU operations */
|
1382 |
|
1383 |
/* XXX: handle nans */
|
1384 |
void OPPROTO op_fcom_ST0_FT0(void) |
1385 |
{ |
1386 |
env->fpus &= (~0x4500); /* (C3,C2,C0) <-- 000 */ |
1387 |
if (ST0 < FT0)
|
1388 |
env->fpus |= 0x100; /* (C3,C2,C0) <-- 001 */ |
1389 |
else if (ST0 == FT0) |
1390 |
env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */ |
1391 |
FORCE_RET(); |
1392 |
} |
1393 |
|
1394 |
/* XXX: handle nans */
|
1395 |
void OPPROTO op_fucom_ST0_FT0(void) |
1396 |
{ |
1397 |
env->fpus &= (~0x4500); /* (C3,C2,C0) <-- 000 */ |
1398 |
if (ST0 < FT0)
|
1399 |
env->fpus |= 0x100; /* (C3,C2,C0) <-- 001 */ |
1400 |
else if (ST0 == FT0) |
1401 |
env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */ |
1402 |
FORCE_RET(); |
1403 |
} |
1404 |
|
1405 |
void OPPROTO op_fadd_ST0_FT0(void) |
1406 |
{ |
1407 |
ST0 += FT0; |
1408 |
} |
1409 |
|
1410 |
void OPPROTO op_fmul_ST0_FT0(void) |
1411 |
{ |
1412 |
ST0 *= FT0; |
1413 |
} |
1414 |
|
1415 |
void OPPROTO op_fsub_ST0_FT0(void) |
1416 |
{ |
1417 |
ST0 -= FT0; |
1418 |
} |
1419 |
|
1420 |
void OPPROTO op_fsubr_ST0_FT0(void) |
1421 |
{ |
1422 |
ST0 = FT0 - ST0; |
1423 |
} |
1424 |
|
1425 |
void OPPROTO op_fdiv_ST0_FT0(void) |
1426 |
{ |
1427 |
ST0 /= FT0; |
1428 |
} |
1429 |
|
1430 |
void OPPROTO op_fdivr_ST0_FT0(void) |
1431 |
{ |
1432 |
ST0 = FT0 / ST0; |
1433 |
} |
1434 |
|
1435 |
/* fp operations between STN and ST0 */
|
1436 |
|
1437 |
void OPPROTO op_fadd_STN_ST0(void) |
1438 |
{ |
1439 |
ST(PARAM1) += ST0; |
1440 |
} |
1441 |
|
1442 |
void OPPROTO op_fmul_STN_ST0(void) |
1443 |
{ |
1444 |
ST(PARAM1) *= ST0; |
1445 |
} |
1446 |
|
1447 |
void OPPROTO op_fsub_STN_ST0(void) |
1448 |
{ |
1449 |
ST(PARAM1) -= ST0; |
1450 |
} |
1451 |
|
1452 |
void OPPROTO op_fsubr_STN_ST0(void) |
1453 |
{ |
1454 |
CPU86_LDouble *p; |
1455 |
p = &ST(PARAM1); |
1456 |
*p = ST0 - *p; |
1457 |
} |
1458 |
|
1459 |
void OPPROTO op_fdiv_STN_ST0(void) |
1460 |
{ |
1461 |
ST(PARAM1) /= ST0; |
1462 |
} |
1463 |
|
1464 |
void OPPROTO op_fdivr_STN_ST0(void) |
1465 |
{ |
1466 |
CPU86_LDouble *p; |
1467 |
p = &ST(PARAM1); |
1468 |
*p = ST0 / *p; |
1469 |
} |
1470 |
|
1471 |
/* misc FPU operations */
|
1472 |
void OPPROTO op_fchs_ST0(void) |
1473 |
{ |
1474 |
ST0 = -ST0; |
1475 |
} |
1476 |
|
1477 |
void OPPROTO op_fabs_ST0(void) |
1478 |
{ |
1479 |
ST0 = fabs(ST0); |
1480 |
} |
1481 |
|
1482 |
void helper_fxam_ST0(void) |
1483 |
{ |
1484 |
CPU86_LDoubleU temp; |
1485 |
int expdif;
|
1486 |
|
1487 |
temp.d = ST0; |
1488 |
|
1489 |
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */ |
1490 |
if (SIGND(temp))
|
1491 |
env->fpus |= 0x200; /* C1 <-- 1 */ |
1492 |
|
1493 |
expdif = EXPD(temp); |
1494 |
if (expdif == MAXEXPD) {
|
1495 |
if (MANTD(temp) == 0) |
1496 |
env->fpus |= 0x500 /*Infinity*/; |
1497 |
else
|
1498 |
env->fpus |= 0x100 /*NaN*/; |
1499 |
} else if (expdif == 0) { |
1500 |
if (MANTD(temp) == 0) |
1501 |
env->fpus |= 0x4000 /*Zero*/; |
1502 |
else
|
1503 |
env->fpus |= 0x4400 /*Denormal*/; |
1504 |
} else {
|
1505 |
env->fpus |= 0x400;
|
1506 |
} |
1507 |
} |
1508 |
|
1509 |
void OPPROTO op_fxam_ST0(void) |
1510 |
{ |
1511 |
helper_fxam_ST0(); |
1512 |
} |
1513 |
|
1514 |
void OPPROTO op_fld1_ST0(void) |
1515 |
{ |
1516 |
ST0 = *(CPU86_LDouble *)&f15rk[1];
|
1517 |
} |
1518 |
|
1519 |
void OPPROTO op_fldl2t_ST0(void) |
1520 |
{ |
1521 |
ST0 = *(CPU86_LDouble *)&f15rk[6];
|
1522 |
} |
1523 |
|
1524 |
void OPPROTO op_fldl2e_ST0(void) |
1525 |
{ |
1526 |
ST0 = *(CPU86_LDouble *)&f15rk[5];
|
1527 |
} |
1528 |
|
1529 |
void OPPROTO op_fldpi_ST0(void) |
1530 |
{ |
1531 |
ST0 = *(CPU86_LDouble *)&f15rk[2];
|
1532 |
} |
1533 |
|
1534 |
void OPPROTO op_fldlg2_ST0(void) |
1535 |
{ |
1536 |
ST0 = *(CPU86_LDouble *)&f15rk[3];
|
1537 |
} |
1538 |
|
1539 |
void OPPROTO op_fldln2_ST0(void) |
1540 |
{ |
1541 |
ST0 = *(CPU86_LDouble *)&f15rk[4];
|
1542 |
} |
1543 |
|
1544 |
void OPPROTO op_fldz_ST0(void) |
1545 |
{ |
1546 |
ST0 = *(CPU86_LDouble *)&f15rk[0];
|
1547 |
} |
1548 |
|
1549 |
void OPPROTO op_fldz_FT0(void) |
1550 |
{ |
1551 |
ST0 = *(CPU86_LDouble *)&f15rk[0];
|
1552 |
} |
1553 |
|
1554 |
void helper_f2xm1(void) |
1555 |
{ |
1556 |
ST0 = pow(2.0,ST0) - 1.0; |
1557 |
} |
1558 |
|
1559 |
void helper_fyl2x(void) |
1560 |
{ |
1561 |
CPU86_LDouble fptemp; |
1562 |
|
1563 |
fptemp = ST0; |
1564 |
if (fptemp>0.0){ |
1565 |
fptemp = log(fptemp)/log(2.0); /* log2(ST) */ |
1566 |
ST1 *= fptemp; |
1567 |
fpop(); |
1568 |
} else {
|
1569 |
env->fpus &= (~0x4700);
|
1570 |
env->fpus |= 0x400;
|
1571 |
} |
1572 |
} |
1573 |
|
1574 |
void helper_fptan(void) |
1575 |
{ |
1576 |
CPU86_LDouble fptemp; |
1577 |
|
1578 |
fptemp = ST0; |
1579 |
if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
|
1580 |
env->fpus |= 0x400;
|
1581 |
} else {
|
1582 |
ST0 = tan(fptemp); |
1583 |
fpush(); |
1584 |
ST0 = 1.0; |
1585 |
env->fpus &= (~0x400); /* C2 <-- 0 */ |
1586 |
/* the above code is for |arg| < 2**52 only */
|
1587 |
} |
1588 |
} |
1589 |
|
1590 |
void helper_fpatan(void) |
1591 |
{ |
1592 |
CPU86_LDouble fptemp, fpsrcop; |
1593 |
|
1594 |
fpsrcop = ST1; |
1595 |
fptemp = ST0; |
1596 |
ST1 = atan2(fpsrcop,fptemp); |
1597 |
fpop(); |
1598 |
} |
1599 |
|
1600 |
void helper_fxtract(void) |
1601 |
{ |
1602 |
CPU86_LDoubleU temp; |
1603 |
unsigned int expdif; |
1604 |
|
1605 |
temp.d = ST0; |
1606 |
expdif = EXPD(temp) - EXPBIAS; |
1607 |
/*DP exponent bias*/
|
1608 |
ST0 = expdif; |
1609 |
fpush(); |
1610 |
BIASEXPONENT(temp); |
1611 |
ST0 = temp.d; |
1612 |
} |
1613 |
|
1614 |
void helper_fprem1(void) |
1615 |
{ |
1616 |
CPU86_LDouble dblq, fpsrcop, fptemp; |
1617 |
CPU86_LDoubleU fpsrcop1, fptemp1; |
1618 |
int expdif;
|
1619 |
int q;
|
1620 |
|
1621 |
fpsrcop = ST0; |
1622 |
fptemp = ST1; |
1623 |
fpsrcop1.d = fpsrcop; |
1624 |
fptemp1.d = fptemp; |
1625 |
expdif = EXPD(fpsrcop1) - EXPD(fptemp1); |
1626 |
if (expdif < 53) { |
1627 |
dblq = fpsrcop / fptemp; |
1628 |
dblq = (dblq < 0.0)? ceil(dblq): floor(dblq); |
1629 |
ST0 = fpsrcop - fptemp*dblq; |
1630 |
q = (int)dblq; /* cutting off top bits is assumed here */ |
1631 |
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */ |
1632 |
/* (C0,C1,C3) <-- (q2,q1,q0) */
|
1633 |
env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */ |
1634 |
env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */ |
1635 |
env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */ |
1636 |
} else {
|
1637 |
env->fpus |= 0x400; /* C2 <-- 1 */ |
1638 |
fptemp = pow(2.0, expdif-50); |
1639 |
fpsrcop = (ST0 / ST1) / fptemp; |
1640 |
/* fpsrcop = integer obtained by rounding to the nearest */
|
1641 |
fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)? |
1642 |
floor(fpsrcop): ceil(fpsrcop); |
1643 |
ST0 -= (ST1 * fpsrcop * fptemp); |
1644 |
} |
1645 |
} |
1646 |
|
1647 |
void helper_fprem(void) |
1648 |
{ |
1649 |
CPU86_LDouble dblq, fpsrcop, fptemp; |
1650 |
CPU86_LDoubleU fpsrcop1, fptemp1; |
1651 |
int expdif;
|
1652 |
int q;
|
1653 |
|
1654 |
fpsrcop = ST0; |
1655 |
fptemp = ST1; |
1656 |
fpsrcop1.d = fpsrcop; |
1657 |
fptemp1.d = fptemp; |
1658 |
expdif = EXPD(fpsrcop1) - EXPD(fptemp1); |
1659 |
if ( expdif < 53 ) { |
1660 |
dblq = fpsrcop / fptemp; |
1661 |
dblq = (dblq < 0.0)? ceil(dblq): floor(dblq); |
1662 |
ST0 = fpsrcop - fptemp*dblq; |
1663 |
q = (int)dblq; /* cutting off top bits is assumed here */ |
1664 |
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */ |
1665 |
/* (C0,C1,C3) <-- (q2,q1,q0) */
|
1666 |
env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */ |
1667 |
env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */ |
1668 |
env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */ |
1669 |
} else {
|
1670 |
env->fpus |= 0x400; /* C2 <-- 1 */ |
1671 |
fptemp = pow(2.0, expdif-50); |
1672 |
fpsrcop = (ST0 / ST1) / fptemp; |
1673 |
/* fpsrcop = integer obtained by chopping */
|
1674 |
fpsrcop = (fpsrcop < 0.0)? |
1675 |
-(floor(fabs(fpsrcop))): floor(fpsrcop); |
1676 |
ST0 -= (ST1 * fpsrcop * fptemp); |
1677 |
} |
1678 |
} |
1679 |
|
1680 |
void helper_fyl2xp1(void) |
1681 |
{ |
1682 |
CPU86_LDouble fptemp; |
1683 |
|
1684 |
fptemp = ST0; |
1685 |
if ((fptemp+1.0)>0.0) { |
1686 |
fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */ |
1687 |
ST1 *= fptemp; |
1688 |
fpop(); |
1689 |
} else {
|
1690 |
env->fpus &= (~0x4700);
|
1691 |
env->fpus |= 0x400;
|
1692 |
} |
1693 |
} |
1694 |
|
1695 |
void helper_fsqrt(void) |
1696 |
{ |
1697 |
CPU86_LDouble fptemp; |
1698 |
|
1699 |
fptemp = ST0; |
1700 |
if (fptemp<0.0) { |
1701 |
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */ |
1702 |
env->fpus |= 0x400;
|
1703 |
} |
1704 |
ST0 = sqrt(fptemp); |
1705 |
} |
1706 |
|
1707 |
void helper_fsincos(void) |
1708 |
{ |
1709 |
CPU86_LDouble fptemp; |
1710 |
|
1711 |
fptemp = ST0; |
1712 |
if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
|
1713 |
env->fpus |= 0x400;
|
1714 |
} else {
|
1715 |
ST0 = sin(fptemp); |
1716 |
fpush(); |
1717 |
ST0 = cos(fptemp); |
1718 |
env->fpus &= (~0x400); /* C2 <-- 0 */ |
1719 |
/* the above code is for |arg| < 2**63 only */
|
1720 |
} |
1721 |
} |
1722 |
|
1723 |
void helper_frndint(void) |
1724 |
{ |
1725 |
ST0 = rint(ST0); |
1726 |
} |
1727 |
|
1728 |
void helper_fscale(void) |
1729 |
{ |
1730 |
CPU86_LDouble fpsrcop, fptemp; |
1731 |
|
1732 |
fpsrcop = 2.0; |
1733 |
fptemp = pow(fpsrcop,ST1); |
1734 |
ST0 *= fptemp; |
1735 |
} |
1736 |
|
1737 |
void helper_fsin(void) |
1738 |
{ |
1739 |
CPU86_LDouble fptemp; |
1740 |
|
1741 |
fptemp = ST0; |
1742 |
if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
|
1743 |
env->fpus |= 0x400;
|
1744 |
} else {
|
1745 |
ST0 = sin(fptemp); |
1746 |
env->fpus &= (~0x400); /* C2 <-- 0 */ |
1747 |
/* the above code is for |arg| < 2**53 only */
|
1748 |
} |
1749 |
} |
1750 |
|
1751 |
void helper_fcos(void) |
1752 |
{ |
1753 |
CPU86_LDouble fptemp; |
1754 |
|
1755 |
fptemp = ST0; |
1756 |
if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
|
1757 |
env->fpus |= 0x400;
|
1758 |
} else {
|
1759 |
ST0 = cos(fptemp); |
1760 |
env->fpus &= (~0x400); /* C2 <-- 0 */ |
1761 |
/* the above code is for |arg5 < 2**63 only */
|
1762 |
} |
1763 |
} |
1764 |
|
1765 |
/* associated heplers to reduce generated code length and to simplify
|
1766 |
relocation (FP constants are usually stored in .rodata section) */
|
1767 |
|
1768 |
void OPPROTO op_f2xm1(void) |
1769 |
{ |
1770 |
helper_f2xm1(); |
1771 |
} |
1772 |
|
1773 |
void OPPROTO op_fyl2x(void) |
1774 |
{ |
1775 |
helper_fyl2x(); |
1776 |
} |
1777 |
|
1778 |
void OPPROTO op_fptan(void) |
1779 |
{ |
1780 |
helper_fptan(); |
1781 |
} |
1782 |
|
1783 |
void OPPROTO op_fpatan(void) |
1784 |
{ |
1785 |
helper_fpatan(); |
1786 |
} |
1787 |
|
1788 |
void OPPROTO op_fxtract(void) |
1789 |
{ |
1790 |
helper_fxtract(); |
1791 |
} |
1792 |
|
1793 |
void OPPROTO op_fprem1(void) |
1794 |
{ |
1795 |
helper_fprem1(); |
1796 |
} |
1797 |
|
1798 |
|
1799 |
void OPPROTO op_fprem(void) |
1800 |
{ |
1801 |
helper_fprem(); |
1802 |
} |
1803 |
|
1804 |
void OPPROTO op_fyl2xp1(void) |
1805 |
{ |
1806 |
helper_fyl2xp1(); |
1807 |
} |
1808 |
|
1809 |
void OPPROTO op_fsqrt(void) |
1810 |
{ |
1811 |
helper_fsqrt(); |
1812 |
} |
1813 |
|
1814 |
void OPPROTO op_fsincos(void) |
1815 |
{ |
1816 |
helper_fsincos(); |
1817 |
} |
1818 |
|
1819 |
void OPPROTO op_frndint(void) |
1820 |
{ |
1821 |
helper_frndint(); |
1822 |
} |
1823 |
|
1824 |
void OPPROTO op_fscale(void) |
1825 |
{ |
1826 |
helper_fscale(); |
1827 |
} |
1828 |
|
1829 |
void OPPROTO op_fsin(void) |
1830 |
{ |
1831 |
helper_fsin(); |
1832 |
} |
1833 |
|
1834 |
void OPPROTO op_fcos(void) |
1835 |
{ |
1836 |
helper_fcos(); |
1837 |
} |
1838 |
|
1839 |
void OPPROTO op_fnstsw_A0(void) |
1840 |
{ |
1841 |
int fpus;
|
1842 |
fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; |
1843 |
stw((void *)A0, fpus);
|
1844 |
} |
1845 |
|
1846 |
void OPPROTO op_fnstsw_EAX(void) |
1847 |
{ |
1848 |
int fpus;
|
1849 |
fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; |
1850 |
EAX = (EAX & 0xffff0000) | fpus;
|
1851 |
} |
1852 |
|
1853 |
void OPPROTO op_fnstcw_A0(void) |
1854 |
{ |
1855 |
stw((void *)A0, env->fpuc);
|
1856 |
} |
1857 |
|
1858 |
void OPPROTO op_fldcw_A0(void) |
1859 |
{ |
1860 |
int rnd_type;
|
1861 |
env->fpuc = lduw((void *)A0);
|
1862 |
/* set rounding mode */
|
1863 |
switch(env->fpuc & RC_MASK) {
|
1864 |
default:
|
1865 |
case RC_NEAR:
|
1866 |
rnd_type = FE_TONEAREST; |
1867 |
break;
|
1868 |
case RC_DOWN:
|
1869 |
rnd_type = FE_DOWNWARD; |
1870 |
break;
|
1871 |
case RC_UP:
|
1872 |
rnd_type = FE_UPWARD; |
1873 |
break;
|
1874 |
case RC_CHOP:
|
1875 |
rnd_type = FE_TOWARDZERO; |
1876 |
break;
|
1877 |
} |
1878 |
fesetround(rnd_type); |
1879 |
} |
1880 |
|
1881 |
/* main execution loop */
|
1882 |
uint8_t code_gen_buffer[65536];
|
1883 |
|
1884 |
#ifdef DEBUG_EXEC
|
1885 |
static const char *cc_op_str[] = { |
1886 |
"DYNAMIC",
|
1887 |
"EFLAGS",
|
1888 |
"MUL",
|
1889 |
"ADDB",
|
1890 |
"ADDW",
|
1891 |
"ADDL",
|
1892 |
"ADCB",
|
1893 |
"ADCW",
|
1894 |
"ADCL",
|
1895 |
"SUBB",
|
1896 |
"SUBW",
|
1897 |
"SUBL",
|
1898 |
"SBBB",
|
1899 |
"SBBW",
|
1900 |
"SBBL",
|
1901 |
"LOGICB",
|
1902 |
"LOGICW",
|
1903 |
"LOGICL",
|
1904 |
"INCB",
|
1905 |
"INCW",
|
1906 |
"INCL",
|
1907 |
"DECB",
|
1908 |
"DECW",
|
1909 |
"DECL",
|
1910 |
"SHLB",
|
1911 |
"SHLW",
|
1912 |
"SHLL",
|
1913 |
"SARB",
|
1914 |
"SARW",
|
1915 |
"SARL",
|
1916 |
}; |
1917 |
#endif
|
1918 |
|
1919 |
int cpu_x86_exec(CPUX86State *env1)
|
1920 |
{ |
1921 |
int saved_T0, saved_T1, saved_A0;
|
1922 |
CPUX86State *saved_env; |
1923 |
int code_gen_size, ret;
|
1924 |
void (*gen_func)(void); |
1925 |
|
1926 |
/* first we save global registers */
|
1927 |
saved_T0 = T0; |
1928 |
saved_T1 = T1; |
1929 |
saved_A0 = A0; |
1930 |
saved_env = env; |
1931 |
env = env1; |
1932 |
|
1933 |
/* prepare setjmp context for exception handling */
|
1934 |
if (setjmp(env->jmp_env) == 0) { |
1935 |
for(;;) {
|
1936 |
#ifdef DEBUG_EXEC
|
1937 |
if (loglevel) {
|
1938 |
int eflags;
|
1939 |
eflags = cc_table[CC_OP].compute_all(); |
1940 |
eflags |= (DF & DIRECTION_FLAG); |
1941 |
fprintf(logfile, |
1942 |
"EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n"
|
1943 |
"ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n"
|
1944 |
"CCS=%08x CCD=%08x CCO=%-8s EFL=%c%c%c%c%c%c%c\n",
|
1945 |
env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], |
1946 |
env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], |
1947 |
env->cc_src, env->cc_dst, cc_op_str[env->cc_op], |
1948 |
eflags & DIRECTION_FLAG ? 'D' : '-', |
1949 |
eflags & CC_O ? 'O' : '-', |
1950 |
eflags & CC_S ? 'S' : '-', |
1951 |
eflags & CC_Z ? 'Z' : '-', |
1952 |
eflags & CC_A ? 'A' : '-', |
1953 |
eflags & CC_P ? 'P' : '-', |
1954 |
eflags & CC_C ? 'C' : '-' |
1955 |
); |
1956 |
#if 1 |
1957 |
fprintf(logfile, "ST0=%f ST1=%f ST2=%f ST3=%f\n",
|
1958 |
(double)ST0, (double)ST1, (double)ST(2), (double)ST(3)); |
1959 |
#endif
|
1960 |
} |
1961 |
#endif
|
1962 |
cpu_x86_gen_code(code_gen_buffer, sizeof(code_gen_buffer),
|
1963 |
&code_gen_size, (uint8_t *)env->pc); |
1964 |
/* execute the generated code */
|
1965 |
gen_func = (void *)code_gen_buffer;
|
1966 |
gen_func(); |
1967 |
} |
1968 |
} |
1969 |
ret = env->exception_index; |
1970 |
|
1971 |
/* restore global registers */
|
1972 |
T0 = saved_T0; |
1973 |
T1 = saved_T1; |
1974 |
A0 = saved_A0; |
1975 |
env = saved_env; |
1976 |
return ret;
|
1977 |
} |