]> git.proxmox.com Git - qemu.git/blob - op-i386.c
many fixes
[qemu.git] / op-i386.c
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 {
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 void OPPROTO op_fild_ST0_A0(void)
1123 {
1124 ST0 = (CPU86_LDouble)ldsw((void *)A0);
1125 }
1126
1127 void OPPROTO op_fildl_ST0_A0(void)
1128 {
1129 ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1130 }
1131
1132 void OPPROTO op_fildll_ST0_A0(void)
1133 {
1134 ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1135 }
1136
1137 /* fp store */
1138
1139 void OPPROTO op_fsts_ST0_A0(void)
1140 {
1141 stfl((void *)A0, (float)ST0);
1142 }
1143
1144 void OPPROTO op_fstl_ST0_A0(void)
1145 {
1146 ST0 = ldfq((void *)A0);
1147 }
1148
1149 void OPPROTO op_fist_ST0_A0(void)
1150 {
1151 int val;
1152 val = lrint(ST0);
1153 stw((void *)A0, val);
1154 }
1155
1156 void OPPROTO op_fistl_ST0_A0(void)
1157 {
1158 int val;
1159 val = lrint(ST0);
1160 stl((void *)A0, val);
1161 }
1162
1163 void OPPROTO op_fistll_ST0_A0(void)
1164 {
1165 int64_t val;
1166 val = llrint(ST0);
1167 stq((void *)A0, val);
1168 }
1169
1170 /* FPU move */
1171
1172 static inline void fpush(void)
1173 {
1174 env->fpstt = (env->fpstt - 1) & 7;
1175 env->fptags[env->fpstt] = 0; /* validate stack entry */
1176 }
1177
1178 static inline void fpop(void)
1179 {
1180 env->fptags[env->fpstt] = 1; /* invvalidate stack entry */
1181 env->fpstt = (env->fpstt + 1) & 7;
1182 }
1183
1184 void OPPROTO op_fpush(void)
1185 {
1186 fpush();
1187 }
1188
1189 void OPPROTO op_fpop(void)
1190 {
1191 fpop();
1192 }
1193
1194 void OPPROTO op_fdecstp(void)
1195 {
1196 env->fpstt = (env->fpstt - 1) & 7;
1197 env->fpus &= (~0x4700);
1198 }
1199
1200 void OPPROTO op_fincstp(void)
1201 {
1202 env->fpstt = (env->fpstt + 1) & 7;
1203 env->fpus &= (~0x4700);
1204 }
1205
1206 void OPPROTO op_fmov_ST0_FT0(void)
1207 {
1208 ST0 = FT0;
1209 }
1210
1211 void OPPROTO op_fmov_FT0_STN(void)
1212 {
1213 FT0 = ST(PARAM1);
1214 }
1215
1216 void OPPROTO op_fmov_ST0_STN(void)
1217 {
1218 ST0 = ST(PARAM1);
1219 }
1220
1221 void OPPROTO op_fmov_STN_ST0(void)
1222 {
1223 ST(PARAM1) = ST0;
1224 }
1225
1226 void OPPROTO op_fxchg_ST0_STN(void)
1227 {
1228 CPU86_LDouble tmp;
1229 tmp = ST(PARAM1);
1230 ST(PARAM1) = ST0;
1231 ST0 = tmp;
1232 }
1233
1234 /* FPU operations */
1235
1236 /* XXX: handle nans */
1237 void OPPROTO op_fcom_ST0_FT0(void)
1238 {
1239 env->fpus &= (~0x4500); /* (C3,C2,C0) <-- 000 */
1240 if (ST0 < FT0)
1241 env->fpus |= 0x100; /* (C3,C2,C0) <-- 001 */
1242 else if (ST0 == FT0)
1243 env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
1244 FORCE_RET();
1245 }
1246
1247 void OPPROTO op_fadd_ST0_FT0(void)
1248 {
1249 ST0 += FT0;
1250 }
1251
1252 void OPPROTO op_fmul_ST0_FT0(void)
1253 {
1254 ST0 *= FT0;
1255 }
1256
1257 void OPPROTO op_fsub_ST0_FT0(void)
1258 {
1259 ST0 -= FT0;
1260 }
1261
1262 void OPPROTO op_fsubr_ST0_FT0(void)
1263 {
1264 ST0 = FT0 - ST0;
1265 }
1266
1267 void OPPROTO op_fdiv_ST0_FT0(void)
1268 {
1269 ST0 /= FT0;
1270 }
1271
1272 void OPPROTO op_fdivr_ST0_FT0(void)
1273 {
1274 ST0 = FT0 / ST0;
1275 }
1276
1277 /* fp operations between STN and ST0 */
1278
1279 void OPPROTO op_fadd_STN_ST0(void)
1280 {
1281 ST(PARAM1) += ST0;
1282 }
1283
1284 void OPPROTO op_fmul_STN_ST0(void)
1285 {
1286 ST(PARAM1) *= ST0;
1287 }
1288
1289 void OPPROTO op_fsub_STN_ST0(void)
1290 {
1291 ST(PARAM1) -= ST0;
1292 }
1293
1294 void OPPROTO op_fsubr_STN_ST0(void)
1295 {
1296 CPU86_LDouble *p;
1297 p = &ST(PARAM1);
1298 *p = ST0 - *p;
1299 }
1300
1301 void OPPROTO op_fdiv_STN_ST0(void)
1302 {
1303 ST(PARAM1) /= ST0;
1304 }
1305
1306 void OPPROTO op_fdivr_STN_ST0(void)
1307 {
1308 CPU86_LDouble *p;
1309 p = &ST(PARAM1);
1310 *p = ST0 / *p;
1311 }
1312
1313 /* misc FPU operations */
1314 void OPPROTO op_fchs_ST0(void)
1315 {
1316 ST0 = -ST0;
1317 }
1318
1319 void OPPROTO op_fabs_ST0(void)
1320 {
1321 ST0 = fabs(ST0);
1322 }
1323
1324 void OPPROTO op_fxam_ST0(void)
1325 {
1326 CPU86_LDoubleU temp;
1327 int expdif;
1328
1329 temp.d = ST0;
1330
1331 env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1332 if (SIGND(temp))
1333 env->fpus |= 0x200; /* C1 <-- 1 */
1334
1335 expdif = EXPD(temp);
1336 if (expdif == MAXEXPD) {
1337 if (MANTD(temp) == 0)
1338 env->fpus |= 0x500 /*Infinity*/;
1339 else
1340 env->fpus |= 0x100 /*NaN*/;
1341 } else if (expdif == 0) {
1342 if (MANTD(temp) == 0)
1343 env->fpus |= 0x4000 /*Zero*/;
1344 else
1345 env->fpus |= 0x4400 /*Denormal*/;
1346 } else {
1347 env->fpus |= 0x400;
1348 }
1349 FORCE_RET();
1350 }
1351
1352 void OPPROTO op_fld1_ST0(void)
1353 {
1354 ST0 = *(CPU86_LDouble *)&f15rk[1];
1355 }
1356
1357 void OPPROTO op_fld2t_ST0(void)
1358 {
1359 ST0 = *(CPU86_LDouble *)&f15rk[6];
1360 }
1361
1362 void OPPROTO op_fld2e_ST0(void)
1363 {
1364 ST0 = *(CPU86_LDouble *)&f15rk[5];
1365 }
1366
1367 void OPPROTO op_fldpi_ST0(void)
1368 {
1369 ST0 = *(CPU86_LDouble *)&f15rk[2];
1370 }
1371
1372 void OPPROTO op_fldlg2_ST0(void)
1373 {
1374 ST0 = *(CPU86_LDouble *)&f15rk[3];
1375 }
1376
1377 void OPPROTO op_fldln2_ST0(void)
1378 {
1379 ST0 = *(CPU86_LDouble *)&f15rk[4];
1380 }
1381
1382 void OPPROTO op_fldz_ST0(void)
1383 {
1384 ST0 = *(CPU86_LDouble *)&f15rk[0];
1385 }
1386
1387 void OPPROTO op_fldz_FT0(void)
1388 {
1389 ST0 = *(CPU86_LDouble *)&f15rk[0];
1390 }
1391
1392 void helper_f2xm1(void)
1393 {
1394 ST0 = pow(2.0,ST0) - 1.0;
1395 }
1396
1397 void helper_fyl2x(void)
1398 {
1399 CPU86_LDouble fptemp;
1400
1401 fptemp = ST0;
1402 if (fptemp>0.0){
1403 fptemp = log(fptemp)/log(2.0); /* log2(ST) */
1404 ST1 *= fptemp;
1405 fpop();
1406 } else {
1407 env->fpus &= (~0x4700);
1408 env->fpus |= 0x400;
1409 }
1410 }
1411
1412 void helper_fptan(void)
1413 {
1414 CPU86_LDouble fptemp;
1415
1416 fptemp = ST0;
1417 if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1418 env->fpus |= 0x400;
1419 } else {
1420 ST0 = tan(fptemp);
1421 fpush();
1422 ST0 = 1.0;
1423 env->fpus &= (~0x400); /* C2 <-- 0 */
1424 /* the above code is for |arg| < 2**52 only */
1425 }
1426 }
1427
1428 void helper_fpatan(void)
1429 {
1430 CPU86_LDouble fptemp, fpsrcop;
1431
1432 fpsrcop = ST1;
1433 fptemp = ST0;
1434 ST1 = atan2(fpsrcop,fptemp);
1435 fpop();
1436 }
1437
1438 void helper_fxtract(void)
1439 {
1440 CPU86_LDoubleU temp;
1441 unsigned int expdif;
1442
1443 temp.d = ST0;
1444 expdif = EXPD(temp) - EXPBIAS;
1445 /*DP exponent bias*/
1446 ST0 = expdif;
1447 fpush();
1448 BIASEXPONENT(temp);
1449 ST0 = temp.d;
1450 }
1451
1452 void helper_fprem1(void)
1453 {
1454 CPU86_LDouble dblq, fpsrcop, fptemp;
1455 CPU86_LDoubleU fpsrcop1, fptemp1;
1456 int expdif;
1457 int q;
1458
1459 fpsrcop = ST0;
1460 fptemp = ST1;
1461 fpsrcop1.d = fpsrcop;
1462 fptemp1.d = fptemp;
1463 expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
1464 if (expdif < 53) {
1465 dblq = fpsrcop / fptemp;
1466 dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
1467 ST0 = fpsrcop - fptemp*dblq;
1468 q = (int)dblq; /* cutting off top bits is assumed here */
1469 env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1470 /* (C0,C1,C3) <-- (q2,q1,q0) */
1471 env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
1472 env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
1473 env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
1474 } else {
1475 env->fpus |= 0x400; /* C2 <-- 1 */
1476 fptemp = pow(2.0, expdif-50);
1477 fpsrcop = (ST0 / ST1) / fptemp;
1478 /* fpsrcop = integer obtained by rounding to the nearest */
1479 fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
1480 floor(fpsrcop): ceil(fpsrcop);
1481 ST0 -= (ST1 * fpsrcop * fptemp);
1482 }
1483 }
1484
1485 void helper_fprem(void)
1486 {
1487 CPU86_LDouble dblq, fpsrcop, fptemp;
1488 CPU86_LDoubleU fpsrcop1, fptemp1;
1489 int expdif;
1490 int q;
1491
1492 fpsrcop = ST0;
1493 fptemp = ST1;
1494 fpsrcop1.d = fpsrcop;
1495 fptemp1.d = fptemp;
1496 expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
1497 if ( expdif < 53 ) {
1498 dblq = fpsrcop / fptemp;
1499 dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
1500 ST0 = fpsrcop - fptemp*dblq;
1501 q = (int)dblq; /* cutting off top bits is assumed here */
1502 env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1503 /* (C0,C1,C3) <-- (q2,q1,q0) */
1504 env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
1505 env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
1506 env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
1507 } else {
1508 env->fpus |= 0x400; /* C2 <-- 1 */
1509 fptemp = pow(2.0, expdif-50);
1510 fpsrcop = (ST0 / ST1) / fptemp;
1511 /* fpsrcop = integer obtained by chopping */
1512 fpsrcop = (fpsrcop < 0.0)?
1513 -(floor(fabs(fpsrcop))): floor(fpsrcop);
1514 ST0 -= (ST1 * fpsrcop * fptemp);
1515 }
1516 }
1517
1518 void helper_fyl2xp1(void)
1519 {
1520 CPU86_LDouble fptemp;
1521
1522 fptemp = ST0;
1523 if ((fptemp+1.0)>0.0) {
1524 fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
1525 ST1 *= fptemp;
1526 fpop();
1527 } else {
1528 env->fpus &= (~0x4700);
1529 env->fpus |= 0x400;
1530 }
1531 }
1532
1533 void helper_fsqrt(void)
1534 {
1535 CPU86_LDouble fptemp;
1536
1537 fptemp = ST0;
1538 if (fptemp<0.0) {
1539 env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1540 env->fpus |= 0x400;
1541 }
1542 ST0 = sqrt(fptemp);
1543 }
1544
1545 void helper_fsincos(void)
1546 {
1547 CPU86_LDouble fptemp;
1548
1549 fptemp = ST0;
1550 if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1551 env->fpus |= 0x400;
1552 } else {
1553 ST0 = sin(fptemp);
1554 fpush();
1555 ST0 = cos(fptemp);
1556 env->fpus &= (~0x400); /* C2 <-- 0 */
1557 /* the above code is for |arg| < 2**63 only */
1558 }
1559 }
1560
1561 void helper_frndint(void)
1562 {
1563 ST0 = rint(ST0);
1564 }
1565
1566 void helper_fscale(void)
1567 {
1568 CPU86_LDouble fpsrcop, fptemp;
1569
1570 fpsrcop = 2.0;
1571 fptemp = pow(fpsrcop,ST1);
1572 ST0 *= fptemp;
1573 }
1574
1575 void helper_fsin(void)
1576 {
1577 CPU86_LDouble fptemp;
1578
1579 fptemp = ST0;
1580 if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1581 env->fpus |= 0x400;
1582 } else {
1583 ST0 = sin(fptemp);
1584 env->fpus &= (~0x400); /* C2 <-- 0 */
1585 /* the above code is for |arg| < 2**53 only */
1586 }
1587 }
1588
1589 void helper_fcos(void)
1590 {
1591 CPU86_LDouble fptemp;
1592
1593 fptemp = ST0;
1594 if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1595 env->fpus |= 0x400;
1596 } else {
1597 ST0 = cos(fptemp);
1598 env->fpus &= (~0x400); /* C2 <-- 0 */
1599 /* the above code is for |arg5 < 2**63 only */
1600 }
1601 }
1602
1603 /* associated heplers to reduce generated code length and to simplify
1604 relocation (FP constants are usually stored in .rodata section) */
1605
1606 void OPPROTO op_f2xm1(void)
1607 {
1608 helper_f2xm1();
1609 }
1610
1611 void OPPROTO op_fyl2x(void)
1612 {
1613 helper_fyl2x();
1614 }
1615
1616 void OPPROTO op_fptan(void)
1617 {
1618 helper_fptan();
1619 }
1620
1621 void OPPROTO op_fpatan(void)
1622 {
1623 helper_fpatan();
1624 }
1625
1626 void OPPROTO op_fxtract(void)
1627 {
1628 helper_fxtract();
1629 }
1630
1631 void OPPROTO op_fprem1(void)
1632 {
1633 helper_fprem1();
1634 }
1635
1636
1637 void OPPROTO op_fprem(void)
1638 {
1639 helper_fprem();
1640 }
1641
1642 void OPPROTO op_fyl2xp1(void)
1643 {
1644 helper_fyl2xp1();
1645 }
1646
1647 void OPPROTO op_fsqrt(void)
1648 {
1649 helper_fsqrt();
1650 }
1651
1652 void OPPROTO op_fsincos(void)
1653 {
1654 helper_fsincos();
1655 }
1656
1657 void OPPROTO op_frndint(void)
1658 {
1659 helper_frndint();
1660 }
1661
1662 void OPPROTO op_fscale(void)
1663 {
1664 helper_fscale();
1665 }
1666
1667 void OPPROTO op_fsin(void)
1668 {
1669 helper_fsin();
1670 }
1671
1672 void OPPROTO op_fcos(void)
1673 {
1674 helper_fcos();
1675 }
1676
1677 void OPPROTO op_fnstsw_A0(void)
1678 {
1679 int fpus;
1680 fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
1681 stw((void *)A0, fpus);
1682 }
1683
1684 void OPPROTO op_fnstcw_A0(void)
1685 {
1686 stw((void *)A0, env->fpuc);
1687 }
1688
1689 void OPPROTO op_fldcw_A0(void)
1690 {
1691 int rnd_type;
1692 env->fpuc = lduw((void *)A0);
1693 /* set rounding mode */
1694 switch(env->fpuc & RC_MASK) {
1695 default:
1696 case RC_NEAR:
1697 rnd_type = FE_TONEAREST;
1698 break;
1699 case RC_DOWN:
1700 rnd_type = FE_DOWNWARD;
1701 break;
1702 case RC_UP:
1703 rnd_type = FE_UPWARD;
1704 break;
1705 case RC_CHOP:
1706 rnd_type = FE_TOWARDZERO;
1707 break;
1708 }
1709 fesetround(rnd_type);
1710 }
1711
1712 /* main execution loop */
1713 uint8_t code_gen_buffer[65536];
1714
1715 #ifdef DEBUG_EXEC
1716 static const char *cc_op_str[] = {
1717 "DYNAMIC",
1718 "EFLAGS",
1719 "MUL",
1720 "ADDB",
1721 "ADDW",
1722 "ADDL",
1723 "ADCB",
1724 "ADCW",
1725 "ADCL",
1726 "SUBB",
1727 "SUBW",
1728 "SUBL",
1729 "SBBB",
1730 "SBBW",
1731 "SBBL",
1732 "LOGICB",
1733 "LOGICW",
1734 "LOGICL",
1735 "INCB",
1736 "INCW",
1737 "INCL",
1738 "DECB",
1739 "DECW",
1740 "DECL",
1741 "SHLB",
1742 "SHLW",
1743 "SHLL",
1744 "SARB",
1745 "SARW",
1746 "SARL",
1747 };
1748 #endif
1749
1750 int cpu_x86_exec(CPUX86State *env1)
1751 {
1752 int saved_T0, saved_T1, saved_A0;
1753 CPUX86State *saved_env;
1754 int code_gen_size, ret;
1755 void (*gen_func)(void);
1756
1757 /* first we save global registers */
1758 saved_T0 = T0;
1759 saved_T1 = T1;
1760 saved_A0 = A0;
1761 saved_env = env;
1762 env = env1;
1763
1764 /* prepare setjmp context for exception handling */
1765 if (setjmp(env->jmp_env) == 0) {
1766 for(;;) {
1767 #ifdef DEBUG_EXEC
1768 if (loglevel) {
1769 int eflags;
1770 eflags = cc_table[CC_OP].compute_all();
1771 eflags |= (DF & DIRECTION_FLAG);
1772 fprintf(logfile,
1773 "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n"
1774 "ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n"
1775 "CCS=%08x CCD=%08x CCO=%-8s EFL=%c%c%c%c%c%c%c\n",
1776 env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX],
1777 env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP],
1778 env->cc_src, env->cc_dst, cc_op_str[env->cc_op],
1779 eflags & DIRECTION_FLAG ? 'D' : '-',
1780 eflags & CC_O ? 'O' : '-',
1781 eflags & CC_S ? 'S' : '-',
1782 eflags & CC_Z ? 'Z' : '-',
1783 eflags & CC_A ? 'A' : '-',
1784 eflags & CC_P ? 'P' : '-',
1785 eflags & CC_C ? 'C' : '-'
1786 );
1787 }
1788 #endif
1789 cpu_x86_gen_code(code_gen_buffer, &code_gen_size, (uint8_t *)env->pc);
1790 /* execute the generated code */
1791 gen_func = (void *)code_gen_buffer;
1792 gen_func();
1793 }
1794 }
1795 ret = env->exception_index;
1796
1797 /* restore global registers */
1798 T0 = saved_T0;
1799 T1 = saved_T1;
1800 A0 = saved_A0;
1801 env = saved_env;
1802 return ret;
1803 }