Statistics
| Branch: | Revision:

root / op-i386.c @ 586314f2

History | View | Annotate | Download (32.4 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 NULL 0
14

    
15
typedef struct FILE FILE;
16
extern FILE *logfile;
17
extern int loglevel;
18
extern int fprintf(FILE *, const char *, ...);
19

    
20
#ifdef __i386__
21
register int T0 asm("esi");
22
register int T1 asm("ebx");
23
register int A0 asm("edi");
24
register struct CPUX86State *env asm("ebp");
25
#define FORCE_RET() asm volatile ("ret");
26
#endif
27
#ifdef __powerpc__
28
register int T0 asm("r24");
29
register int T1 asm("r25");
30
register int A0 asm("r26");
31
register struct CPUX86State *env asm("r27");
32
#define FORCE_RET() asm volatile ("blr");
33
#endif
34
#ifdef __arm__
35
register int T0 asm("r4");
36
register int T1 asm("r5");
37
register int A0 asm("r6");
38
register struct CPUX86State *env asm("r7");
39
#define FORCE_RET() asm volatile ("mov pc, lr");
40
#endif
41
#ifdef __mips__
42
register int T0 asm("s0");
43
register int T1 asm("s1");
44
register int A0 asm("s2");
45
register struct CPUX86State *env asm("s3");
46
#define FORCE_RET() asm volatile ("jr $31");
47
#endif
48
#ifdef __sparc__
49
register int T0 asm("l0");
50
register int T1 asm("l1");
51
register int A0 asm("l2");
52
register struct CPUX86State *env asm("l3");
53
#define FORCE_RET() asm volatile ("retl ; nop");
54
#endif
55

    
56
#ifndef OPPROTO
57
#define OPPROTO
58
#endif
59

    
60
#define xglue(x, y) x ## y
61
#define glue(x, y) xglue(x, y)
62

    
63
#define EAX (env->regs[R_EAX])
64
#define ECX (env->regs[R_ECX])
65
#define EDX (env->regs[R_EDX])
66
#define EBX (env->regs[R_EBX])
67
#define ESP (env->regs[R_ESP])
68
#define EBP (env->regs[R_EBP])
69
#define ESI (env->regs[R_ESI])
70
#define EDI (env->regs[R_EDI])
71
#define PC  (env->pc)
72
#define DF  (env->df)
73

    
74
#define CC_SRC (env->cc_src)
75
#define CC_DST (env->cc_dst)
76
#define CC_OP  (env->cc_op)
77

    
78
/* float macros */
79
#define FT0    (env->ft0)
80
#define ST0    (env->fpregs[env->fpstt])
81
#define ST(n)  (env->fpregs[(env->fpstt + (n)) & 7])
82
#define ST1    ST(1)
83

    
84
extern int __op_param1, __op_param2, __op_param3;
85
#define PARAM1 ((long)(&__op_param1))
86
#define PARAM2 ((long)(&__op_param2))
87
#define PARAM3 ((long)(&__op_param3))
88

    
89
#include "cpu-i386.h"
90

    
91
typedef struct CCTable {
92
    int (*compute_all)(void); /* return all the flags */
93
    int (*compute_c)(void);  /* return the C flag */
94
} CCTable;
95

    
96
/* NOTE: data are not static to force relocation generation by GCC */
97
extern CCTable cc_table[];
98

    
99
uint8_t parity_table[256] = {
100
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
101
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
102
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
103
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
104
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
105
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
106
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
107
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
108
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
109
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
110
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
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
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
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
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
118
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
119
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
120
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
121
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
122
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
123
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
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
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
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
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
131
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
132
};
133

    
134
/* modulo 17 table */
135
const uint8_t rclw_table[32] = {
136
    0, 1, 2, 3, 4, 5, 6, 7, 
137
    8, 9,10,11,12,13,14,15,
138
   16, 0, 1, 2, 3, 4, 5, 6,
139
    7, 8, 9,10,11,12,13,14,
140
};
141

    
142
/* modulo 9 table */
143
const uint8_t rclb_table[32] = {
144
    0, 1, 2, 3, 4, 5, 6, 7, 
145
    8, 0, 1, 2, 3, 4, 5, 6,
146
    7, 8, 0, 1, 2, 3, 4, 5, 
147
    6, 7, 8, 0, 1, 2, 3, 4,
148
};
149

    
150
#ifdef USE_X86LDOUBLE
151
/* an array of Intel 80-bit FP constants, to be loaded via integer ops */
152
typedef unsigned short f15ld[5];
153
const f15ld f15rk[] =
154
{
155
/*0*/        {0x0000,0x0000,0x0000,0x0000,0x0000},
156
/*1*/        {0x0000,0x0000,0x0000,0x8000,0x3fff},
157
/*pi*/        {0xc235,0x2168,0xdaa2,0xc90f,0x4000},
158
/*lg2*/        {0xf799,0xfbcf,0x9a84,0x9a20,0x3ffd},
159
/*ln2*/        {0x79ac,0xd1cf,0x17f7,0xb172,0x3ffe},
160
/*l2e*/        {0xf0bc,0x5c17,0x3b29,0xb8aa,0x3fff},
161
/*l2t*/        {0x8afe,0xcd1b,0x784b,0xd49a,0x4000}
162
};
163
#else
164
/* the same, 64-bit version */
165
typedef unsigned short f15ld[4];
166
const f15ld f15rk[] =
167
{
168
#ifndef WORDS_BIGENDIAN
169
/*0*/        {0x0000,0x0000,0x0000,0x0000},
170
/*1*/        {0x0000,0x0000,0x0000,0x3ff0},
171
/*pi*/        {0x2d18,0x5444,0x21fb,0x4009},
172
/*lg2*/        {0x79ff,0x509f,0x4413,0x3fd3},
173
/*ln2*/        {0x39ef,0xfefa,0x2e42,0x3fe6},
174
/*l2e*/        {0x82fe,0x652b,0x1547,0x3ff7},
175
/*l2t*/        {0xa371,0x0979,0x934f,0x400a}
176
#else
177
/*0*/   {0x0000,0x0000,0x0000,0x0000},
178
/*1*/   {0x3ff0,0x0000,0x0000,0x0000},
179
/*pi*/  {0x4009,0x21fb,0x5444,0x2d18},
180
/*lg2*/        {0x3fd3,0x4413,0x509f,0x79ff},
181
/*ln2*/        {0x3fe6,0x2e42,0xfefa,0x39ef},
182
/*l2e*/        {0x3ff7,0x1547,0x652b,0x82fe},
183
/*l2t*/        {0x400a,0x934f,0x0979,0xa371}
184
#endif
185
};
186
#endif
187
    
188
/* n must be a constant to be efficient */
189
static inline int lshift(int x, int n)
190
{
191
    if (n >= 0)
192
        return x << n;
193
    else
194
        return x >> (-n);
195
}
196

    
197
/* exception support */
198
/* NOTE: not static to force relocation generation by GCC */
199
void raise_exception(int exception_index)
200
{
201
    env->exception_index = exception_index;
202
    longjmp(env->jmp_env, 1);
203
}
204

    
205
/* we define the various pieces of code used by the JIT */
206

    
207
#define REG EAX
208
#define REGNAME _EAX
209
#include "opreg_template.h"
210
#undef REG
211
#undef REGNAME
212

    
213
#define REG ECX
214
#define REGNAME _ECX
215
#include "opreg_template.h"
216
#undef REG
217
#undef REGNAME
218

    
219
#define REG EDX
220
#define REGNAME _EDX
221
#include "opreg_template.h"
222
#undef REG
223
#undef REGNAME
224

    
225
#define REG EBX
226
#define REGNAME _EBX
227
#include "opreg_template.h"
228
#undef REG
229
#undef REGNAME
230

    
231
#define REG ESP
232
#define REGNAME _ESP
233
#include "opreg_template.h"
234
#undef REG
235
#undef REGNAME
236

    
237
#define REG EBP
238
#define REGNAME _EBP
239
#include "opreg_template.h"
240
#undef REG
241
#undef REGNAME
242

    
243
#define REG ESI
244
#define REGNAME _ESI
245
#include "opreg_template.h"
246
#undef REG
247
#undef REGNAME
248

    
249
#define REG EDI
250
#define REGNAME _EDI
251
#include "opreg_template.h"
252
#undef REG
253
#undef REGNAME
254

    
255
/* operations */
256

    
257
void OPPROTO op_addl_T0_T1_cc(void)
258
{
259
    CC_SRC = T0;
260
    T0 += T1;
261
    CC_DST = T0;
262
}
263

    
264
void OPPROTO op_orl_T0_T1_cc(void)
265
{
266
    T0 |= T1;
267
    CC_DST = T0;
268
}
269

    
270
void OPPROTO op_adcl_T0_T1_cc(void)
271
{
272
    CC_SRC = T0;
273
    T0 = T0 + T1 + cc_table[CC_OP].compute_c();
274
    CC_DST = T0;
275
}
276

    
277
void OPPROTO op_sbbl_T0_T1_cc(void)
278
{
279
    CC_SRC = T0;
280
    T0 = T0 - T1 - cc_table[CC_OP].compute_c();
281
    CC_DST = T0;
282
}
283

    
284
void OPPROTO op_andl_T0_T1_cc(void)
285
{
286
    T0 &= T1;
287
    CC_DST = T0;
288
}
289

    
290
void OPPROTO op_subl_T0_T1_cc(void)
291
{
292
    CC_SRC = T0;
293
    T0 -= T1;
294
    CC_DST = T0;
295
}
296

    
297
void OPPROTO op_xorl_T0_T1_cc(void)
298
{
299
    T0 ^= T1;
300
    CC_DST = T0;
301
}
302

    
303
void OPPROTO op_cmpl_T0_T1_cc(void)
304
{
305
    CC_SRC = T0;
306
    CC_DST = T0 - T1;
307
}
308

    
309
void OPPROTO op_notl_T0(void)
310
{
311
    T0 = ~T0;
312
}
313

    
314
void OPPROTO op_negl_T0_cc(void)
315
{
316
    CC_SRC = 0;
317
    T0 = -T0;
318
    CC_DST = T0;
319
}
320

    
321
void OPPROTO op_incl_T0_cc(void)
322
{
323
    T0++;
324
    CC_DST = T0;
325
}
326

    
327
void OPPROTO op_decl_T0_cc(void)
328
{
329
    T0--;
330
    CC_DST = T0;
331
}
332

    
333
void OPPROTO op_testl_T0_T1_cc(void)
334
{
335
    CC_DST = T0 & T1;
336
}
337

    
338
/* multiply/divide */
339
void OPPROTO op_mulb_AL_T0(void)
340
{
341
    unsigned int res;
342
    res = (uint8_t)EAX * (uint8_t)T0;
343
    EAX = (EAX & 0xffff0000) | res;
344
    CC_SRC = (res & 0xff00);
345
}
346

    
347
void OPPROTO op_imulb_AL_T0(void)
348
{
349
    int res;
350
    res = (int8_t)EAX * (int8_t)T0;
351
    EAX = (EAX & 0xffff0000) | (res & 0xffff);
352
    CC_SRC = (res != (int8_t)res);
353
}
354

    
355
void OPPROTO op_mulw_AX_T0(void)
356
{
357
    unsigned int res;
358
    res = (uint16_t)EAX * (uint16_t)T0;
359
    EAX = (EAX & 0xffff0000) | (res & 0xffff);
360
    EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff);
361
    CC_SRC = res >> 16;
362
}
363

    
364
void OPPROTO op_imulw_AX_T0(void)
365
{
366
    int res;
367
    res = (int16_t)EAX * (int16_t)T0;
368
    EAX = (EAX & 0xffff0000) | (res & 0xffff);
369
    EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff);
370
    CC_SRC = (res != (int16_t)res);
371
}
372

    
373
void OPPROTO op_mull_EAX_T0(void)
374
{
375
    uint64_t res;
376
    res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0);
377
    EAX = res;
378
    EDX = res >> 32;
379
    CC_SRC = res >> 32;
380
}
381

    
382
void OPPROTO op_imull_EAX_T0(void)
383
{
384
    int64_t res;
385
    res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T0);
386
    EAX = res;
387
    EDX = res >> 32;
388
    CC_SRC = (res != (int32_t)res);
389
}
390

    
391
void OPPROTO op_imulw_T0_T1(void)
392
{
393
    int res;
394
    res = (int16_t)T0 * (int16_t)T1;
395
    T0 = res;
396
    CC_SRC = (res != (int16_t)res);
397
}
398

    
399
void OPPROTO op_imull_T0_T1(void)
400
{
401
    int64_t res;
402
    res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T1);
403
    T0 = res;
404
    CC_SRC = (res != (int32_t)res);
405
}
406

    
407
/* division, flags are undefined */
408
/* XXX: add exceptions for overflow & div by zero */
409
void OPPROTO op_divb_AL_T0(void)
410
{
411
    unsigned int num, den, q, r;
412

    
413
    num = (EAX & 0xffff);
414
    den = (T0 & 0xff);
415
    q = (num / den) & 0xff;
416
    r = (num % den) & 0xff;
417
    EAX = (EAX & 0xffff0000) | (r << 8) | q;
418
}
419

    
420
void OPPROTO op_idivb_AL_T0(void)
421
{
422
    int num, den, q, r;
423

    
424
    num = (int16_t)EAX;
425
    den = (int8_t)T0;
426
    q = (num / den) & 0xff;
427
    r = (num % den) & 0xff;
428
    EAX = (EAX & 0xffff0000) | (r << 8) | q;
429
}
430

    
431
void OPPROTO op_divw_AX_T0(void)
432
{
433
    unsigned int num, den, q, r;
434

    
435
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
436
    den = (T0 & 0xffff);
437
    q = (num / den) & 0xffff;
438
    r = (num % den) & 0xffff;
439
    EAX = (EAX & 0xffff0000) | q;
440
    EDX = (EDX & 0xffff0000) | r;
441
}
442

    
443
void OPPROTO op_idivw_AX_T0(void)
444
{
445
    int num, den, q, r;
446

    
447
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
448
    den = (int16_t)T0;
449
    q = (num / den) & 0xffff;
450
    r = (num % den) & 0xffff;
451
    EAX = (EAX & 0xffff0000) | q;
452
    EDX = (EDX & 0xffff0000) | r;
453
}
454

    
455
void OPPROTO op_divl_EAX_T0(void)
456
{
457
    unsigned int den, q, r;
458
    uint64_t num;
459
    
460
    num = EAX | ((uint64_t)EDX << 32);
461
    den = T0;
462
    q = (num / den);
463
    r = (num % den);
464
    EAX = q;
465
    EDX = r;
466
}
467

    
468
void OPPROTO op_idivl_EAX_T0(void)
469
{
470
    int den, q, r;
471
    int16_t num;
472
    
473
    num = EAX | ((uint64_t)EDX << 32);
474
    den = (int16_t)T0;
475
    q = (num / den);
476
    r = (num % den);
477
    EAX = q;
478
    EDX = r;
479
}
480

    
481
/* constant load */
482

    
483
void OPPROTO op_movl_T0_im(void)
484
{
485
    T0 = PARAM1;
486
}
487

    
488
void OPPROTO op_movl_T1_im(void)
489
{
490
    T1 = PARAM1;
491
}
492

    
493
void OPPROTO op_movl_A0_im(void)
494
{
495
    A0 = PARAM1;
496
}
497

    
498
/* memory access */
499

    
500
void OPPROTO op_ldub_T0_A0(void)
501
{
502
    T0 = ldub((uint8_t *)A0);
503
}
504

    
505
void OPPROTO op_ldsb_T0_A0(void)
506
{
507
    T0 = ldsb((int8_t *)A0);
508
}
509

    
510
void OPPROTO op_lduw_T0_A0(void)
511
{
512
    T0 = lduw((uint8_t *)A0);
513
}
514

    
515
void OPPROTO op_ldsw_T0_A0(void)
516
{
517
    T0 = ldsw((int8_t *)A0);
518
}
519

    
520
void OPPROTO op_ldl_T0_A0(void)
521
{
522
    T0 = ldl((uint8_t *)A0);
523
}
524

    
525
void OPPROTO op_ldub_T1_A0(void)
526
{
527
    T1 = ldub((uint8_t *)A0);
528
}
529

    
530
void OPPROTO op_ldsb_T1_A0(void)
531
{
532
    T1 = ldsb((int8_t *)A0);
533
}
534

    
535
void OPPROTO op_lduw_T1_A0(void)
536
{
537
    T1 = lduw((uint8_t *)A0);
538
}
539

    
540
void OPPROTO op_ldsw_T1_A0(void)
541
{
542
    T1 = ldsw((int8_t *)A0);
543
}
544

    
545
void OPPROTO op_ldl_T1_A0(void)
546
{
547
    T1 = ldl((uint8_t *)A0);
548
}
549

    
550
void OPPROTO op_stb_T0_A0(void)
551
{
552
    stb((uint8_t *)A0, T0);
553
}
554

    
555
void OPPROTO op_stw_T0_A0(void)
556
{
557
    stw((uint8_t *)A0, T0);
558
}
559

    
560
void OPPROTO op_stl_T0_A0(void)
561
{
562
    stl((uint8_t *)A0, T0);
563
}
564

    
565
/* jumps */
566

    
567
/* indirect jump */
568

    
569
void OPPROTO op_jmp_T0(void)
570
{
571
    PC = T0;
572
}
573

    
574
void OPPROTO op_jmp_im(void)
575
{
576
    PC = PARAM1;
577
}
578

    
579
void OPPROTO op_int_im(void)
580
{
581
    PC = PARAM1;
582
    raise_exception(EXCP0D_GPF);
583
}
584

    
585
void OPPROTO op_int3(void)
586
{
587
    PC = PARAM1;
588
    raise_exception(EXCP03_INT3);
589
}
590

    
591
void OPPROTO op_into(void)
592
{
593
    int eflags;
594
    eflags = cc_table[CC_OP].compute_all();
595
    if (eflags & CC_O) {
596
        PC = PARAM1;
597
        raise_exception(EXCP04_INTO);
598
    } else {
599
        PC = PARAM2;
600
    }
601
}
602

    
603
/* string ops */
604

    
605
#define ldul ldl
606

    
607
#define SHIFT 0
608
#include "ops_template.h"
609
#undef SHIFT
610

    
611
#define SHIFT 1
612
#include "ops_template.h"
613
#undef SHIFT
614

    
615
#define SHIFT 2
616
#include "ops_template.h"
617
#undef SHIFT
618

    
619
/* sign extend */
620

    
621
void OPPROTO op_movsbl_T0_T0(void)
622
{
623
    T0 = (int8_t)T0;
624
}
625

    
626
void OPPROTO op_movzbl_T0_T0(void)
627
{
628
    T0 = (uint8_t)T0;
629
}
630

    
631
void OPPROTO op_movswl_T0_T0(void)
632
{
633
    T0 = (int16_t)T0;
634
}
635

    
636
void OPPROTO op_movzwl_T0_T0(void)
637
{
638
    T0 = (uint16_t)T0;
639
}
640

    
641
void OPPROTO op_movswl_EAX_AX(void)
642
{
643
    EAX = (int16_t)EAX;
644
}
645

    
646
void OPPROTO op_movsbw_AX_AL(void)
647
{
648
    EAX = (EAX & 0xffff0000) | ((int8_t)EAX & 0xffff);
649
}
650

    
651
void OPPROTO op_movslq_EDX_EAX(void)
652
{
653
    EDX = (int32_t)EAX >> 31;
654
}
655

    
656
void OPPROTO op_movswl_DX_AX(void)
657
{
658
    EDX = (EDX & 0xffff0000) | (((int16_t)EAX >> 15) & 0xffff);
659
}
660

    
661
/* push/pop */
662
/* XXX: add 16 bit operand/16 bit seg variants */
663

    
664
void op_pushl_T0(void)
665
{
666
    uint32_t offset;
667
    offset = ESP - 4;
668
    stl((void *)offset, T0);
669
    /* modify ESP after to handle exceptions correctly */
670
    ESP = offset;
671
}
672

    
673
void op_pushl_T1(void)
674
{
675
    uint32_t offset;
676
    offset = ESP - 4;
677
    stl((void *)offset, T1);
678
    /* modify ESP after to handle exceptions correctly */
679
    ESP = offset;
680
}
681

    
682
void op_popl_T0(void)
683
{
684
    T0 = ldl((void *)ESP);
685
    ESP += 4;
686
}
687

    
688
void op_addl_ESP_im(void)
689
{
690
    ESP += PARAM1;
691
}
692

    
693
/* flags handling */
694

    
695
/* slow jumps cases (compute x86 flags) */
696
void OPPROTO op_jo_cc(void)
697
{
698
    int eflags;
699
    eflags = cc_table[CC_OP].compute_all();
700
    if (eflags & CC_O)
701
        PC = PARAM1;
702
    else
703
        PC = PARAM2;
704
    FORCE_RET();
705
}
706

    
707
void OPPROTO op_jb_cc(void)
708
{
709
    if (cc_table[CC_OP].compute_c())
710
        PC = PARAM1;
711
    else
712
        PC = PARAM2;
713
    FORCE_RET();
714
}
715

    
716
void OPPROTO op_jz_cc(void)
717
{
718
    int eflags;
719
    eflags = cc_table[CC_OP].compute_all();
720
    if (eflags & CC_Z)
721
        PC = PARAM1;
722
    else
723
        PC = PARAM2;
724
    FORCE_RET();
725
}
726

    
727
void OPPROTO op_jbe_cc(void)
728
{
729
    int eflags;
730
    eflags = cc_table[CC_OP].compute_all();
731
    if (eflags & (CC_Z | CC_C))
732
        PC = PARAM1;
733
    else
734
        PC = PARAM2;
735
    FORCE_RET();
736
}
737

    
738
void OPPROTO op_js_cc(void)
739
{
740
    int eflags;
741
    eflags = cc_table[CC_OP].compute_all();
742
    if (eflags & CC_S)
743
        PC = PARAM1;
744
    else
745
        PC = PARAM2;
746
    FORCE_RET();
747
}
748

    
749
void OPPROTO op_jp_cc(void)
750
{
751
    int eflags;
752
    eflags = cc_table[CC_OP].compute_all();
753
    if (eflags & CC_P)
754
        PC = PARAM1;
755
    else
756
        PC = PARAM2;
757
    FORCE_RET();
758
}
759

    
760
void OPPROTO op_jl_cc(void)
761
{
762
    int eflags;
763
    eflags = cc_table[CC_OP].compute_all();
764
    if ((eflags ^ (eflags >> 4)) & 0x80)
765
        PC = PARAM1;
766
    else
767
        PC = PARAM2;
768
    FORCE_RET();
769
}
770

    
771
void OPPROTO op_jle_cc(void)
772
{
773
    int eflags;
774
    eflags = cc_table[CC_OP].compute_all();
775
    if (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z))
776
        PC = PARAM1;
777
    else
778
        PC = PARAM2;
779
    FORCE_RET();
780
}
781

    
782
/* slow set cases (compute x86 flags) */
783
void OPPROTO op_seto_T0_cc(void)
784
{
785
    int eflags;
786
    eflags = cc_table[CC_OP].compute_all();
787
    T0 = (eflags >> 11) & 1;
788
}
789

    
790
void OPPROTO op_setb_T0_cc(void)
791
{
792
    T0 = cc_table[CC_OP].compute_c();
793
}
794

    
795
void OPPROTO op_setz_T0_cc(void)
796
{
797
    int eflags;
798
    eflags = cc_table[CC_OP].compute_all();
799
    T0 = (eflags >> 6) & 1;
800
}
801

    
802
void OPPROTO op_setbe_T0_cc(void)
803
{
804
    int eflags;
805
    eflags = cc_table[CC_OP].compute_all();
806
    T0 = (eflags & (CC_Z | CC_C)) != 0;
807
}
808

    
809
void OPPROTO op_sets_T0_cc(void)
810
{
811
    int eflags;
812
    eflags = cc_table[CC_OP].compute_all();
813
    T0 = (eflags >> 7) & 1;
814
}
815

    
816
void OPPROTO op_setp_T0_cc(void)
817
{
818
    int eflags;
819
    eflags = cc_table[CC_OP].compute_all();
820
    T0 = (eflags >> 2) & 1;
821
}
822

    
823
void OPPROTO op_setl_T0_cc(void)
824
{
825
    int eflags;
826
    eflags = cc_table[CC_OP].compute_all();
827
    T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
828
}
829

    
830
void OPPROTO op_setle_T0_cc(void)
831
{
832
    int eflags;
833
    eflags = cc_table[CC_OP].compute_all();
834
    T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
835
}
836

    
837
void OPPROTO op_xor_T0_1(void)
838
{
839
    T0 ^= 1;
840
}
841

    
842
void OPPROTO op_set_cc_op(void)
843
{
844
    CC_OP = PARAM1;
845
}
846

    
847
void OPPROTO op_movl_eflags_T0(void)
848
{
849
    CC_SRC = T0;
850
    DF = 1 - (2 * ((T0 >> 10) & 1));
851
}
852

    
853
/* XXX: compute only O flag */
854
void OPPROTO op_movb_eflags_T0(void)
855
{
856
    int of;
857
    of = cc_table[CC_OP].compute_all() & CC_O;
858
    CC_SRC = T0 | of;
859
}
860

    
861
void OPPROTO op_movl_T0_eflags(void)
862
{
863
    T0 = cc_table[CC_OP].compute_all();
864
    T0 |= (DF & DIRECTION_FLAG);
865
}
866

    
867
void OPPROTO op_cld(void)
868
{
869
    DF = 1;
870
}
871

    
872
void OPPROTO op_std(void)
873
{
874
    DF = -1;
875
}
876

    
877
void OPPROTO op_clc(void)
878
{
879
    int eflags;
880
    eflags = cc_table[CC_OP].compute_all();
881
    eflags &= ~CC_C;
882
    CC_SRC = eflags;
883
}
884

    
885
void OPPROTO op_stc(void)
886
{
887
    int eflags;
888
    eflags = cc_table[CC_OP].compute_all();
889
    eflags |= CC_C;
890
    CC_SRC = eflags;
891
}
892

    
893
void OPPROTO op_cmc(void)
894
{
895
    int eflags;
896
    eflags = cc_table[CC_OP].compute_all();
897
    eflags ^= CC_C;
898
    CC_SRC = eflags;
899
}
900

    
901
static int compute_all_eflags(void)
902
{
903
    return CC_SRC;
904
}
905

    
906
static int compute_c_eflags(void)
907
{
908
    return CC_SRC & CC_C;
909
}
910

    
911
static int compute_c_mul(void)
912
{
913
    int cf;
914
    cf = (CC_SRC != 0);
915
    return cf;
916
}
917

    
918
static int compute_all_mul(void)
919
{
920
    int cf, pf, af, zf, sf, of;
921
    cf = (CC_SRC != 0);
922
    pf = 0; /* undefined */
923
    af = 0; /* undefined */
924
    zf = 0; /* undefined */
925
    sf = 0; /* undefined */
926
    of = cf << 11;
927
    return cf | pf | af | zf | sf | of;
928
}
929
    
930
CCTable cc_table[CC_OP_NB] = {
931
    [CC_OP_DYNAMIC] = { /* should never happen */ },
932

    
933
    [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
934

    
935
    [CC_OP_MUL] = { compute_all_mul, compute_c_mul },
936

    
937
    [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
938
    [CC_OP_ADDW] = { compute_all_addw, compute_c_addw  },
939
    [CC_OP_ADDL] = { compute_all_addl, compute_c_addl  },
940

    
941
    [CC_OP_SUBB] = { compute_all_subb, compute_c_subb  },
942
    [CC_OP_SUBW] = { compute_all_subw, compute_c_subw  },
943
    [CC_OP_SUBL] = { compute_all_subl, compute_c_subl  },
944
    
945
    [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
946
    [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
947
    [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
948
    
949
    [CC_OP_INCB] = { compute_all_incb, compute_c_incb },
950
    [CC_OP_INCW] = { compute_all_incw, compute_c_incw },
951
    [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
952
    
953
    [CC_OP_DECB] = { compute_all_decb, compute_c_incb },
954
    [CC_OP_DECW] = { compute_all_decw, compute_c_incw },
955
    [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
956
    
957
    [CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb },
958
    [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw },
959
    [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
960
};
961

    
962
/* floating point support */
963

    
964
#ifdef USE_X86LDOUBLE
965
/* use long double functions */
966
#define lrint lrintl
967
#define llrint llrintl
968
#define fabs fabsl
969
#define sin sinl
970
#define cos cosl
971
#define sqrt sqrtl
972
#define pow powl
973
#define log logl
974
#define tan tanl
975
#define atan2 atan2l
976
#define floor floorl
977
#define ceil ceill
978
#define rint rintl
979
#endif
980

    
981
extern int lrint(CPU86_LDouble x);
982
extern int64_t llrint(CPU86_LDouble x);
983
extern CPU86_LDouble fabs(CPU86_LDouble x);
984
extern CPU86_LDouble sin(CPU86_LDouble x);
985
extern CPU86_LDouble cos(CPU86_LDouble x);
986
extern CPU86_LDouble sqrt(CPU86_LDouble x);
987
extern CPU86_LDouble pow(CPU86_LDouble, CPU86_LDouble);
988
extern CPU86_LDouble log(CPU86_LDouble x);
989
extern CPU86_LDouble tan(CPU86_LDouble x);
990
extern CPU86_LDouble atan2(CPU86_LDouble, CPU86_LDouble);
991
extern CPU86_LDouble floor(CPU86_LDouble x);
992
extern CPU86_LDouble ceil(CPU86_LDouble x);
993
extern CPU86_LDouble rint(CPU86_LDouble x);
994

    
995
#define RC_MASK         0xc00
996
#define RC_NEAR                0x000
997
#define RC_DOWN                0x400
998
#define RC_UP                0x800
999
#define RC_CHOP                0xc00
1000

    
1001
#define MAXTAN 9223372036854775808.0
1002

    
1003
#ifdef USE_X86LDOUBLE
1004

    
1005
/* only for x86 */
1006
typedef union {
1007
    long double d;
1008
    struct {
1009
        unsigned long long lower;
1010
        unsigned short upper;
1011
    } l;
1012
} CPU86_LDoubleU;
1013

    
1014
/* the following deal with x86 long double-precision numbers */
1015
#define MAXEXPD 0x7fff
1016
#define EXPBIAS 16383
1017
#define EXPD(fp)        (fp.l.upper & 0x7fff)
1018
#define SIGND(fp)        ((fp.l.upper) & 0x8000)
1019
#define MANTD(fp)       (fp.l.lower)
1020
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
1021

    
1022
#else
1023

    
1024
typedef {
1025
    double d;
1026
#ifndef WORDS_BIGENDIAN
1027
    struct {
1028
        unsigned long lower;
1029
        long upper;
1030
    } l;
1031
#else
1032
    struct {
1033
        long upper;
1034
        unsigned long lower;
1035
    } l;
1036
#endif
1037
    long long ll;
1038
} CPU86_LDoubleU;
1039

    
1040
/* the following deal with IEEE double-precision numbers */
1041
#define MAXEXPD 0x7ff
1042
#define EXPBIAS 1023
1043
#define EXPD(fp)        (((fp.l.upper) >> 20) & 0x7FF)
1044
#define SIGND(fp)        ((fp.l.upper) & 0x80000000)
1045
#define MANTD(fp)        (fp.ll & ((1LL << 52) - 1))
1046
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20)
1047
#endif
1048

    
1049
/* fp load FT0 */
1050

    
1051
void OPPROTO op_flds_FT0_A0(void)
1052
{
1053
    FT0 = ldfl((void *)A0);
1054
}
1055

    
1056
void OPPROTO op_fldl_FT0_A0(void)
1057
{
1058
    FT0 = ldfq((void *)A0);
1059
}
1060

    
1061
void OPPROTO op_fild_FT0_A0(void)
1062
{
1063
    FT0 = (CPU86_LDouble)ldsw((void *)A0);
1064
}
1065

    
1066
void OPPROTO op_fildl_FT0_A0(void)
1067
{
1068
    FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1069
}
1070

    
1071
void OPPROTO op_fildll_FT0_A0(void)
1072
{
1073
    FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1074
}
1075

    
1076
/* fp load ST0 */
1077

    
1078
void OPPROTO op_flds_ST0_A0(void)
1079
{
1080
    ST0 = ldfl((void *)A0);
1081
}
1082

    
1083
void OPPROTO op_fldl_ST0_A0(void)
1084
{
1085
    ST0 = ldfq((void *)A0);
1086
}
1087

    
1088
void OPPROTO op_fild_ST0_A0(void)
1089
{
1090
    ST0 = (CPU86_LDouble)ldsw((void *)A0);
1091
}
1092

    
1093
void OPPROTO op_fildl_ST0_A0(void)
1094
{
1095
    ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1096
}
1097

    
1098
void OPPROTO op_fildll_ST0_A0(void)
1099
{
1100
    ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1101
}
1102

    
1103
/* fp store */
1104

    
1105
void OPPROTO op_fsts_ST0_A0(void)
1106
{
1107
    stfl((void *)A0, (float)ST0);
1108
}
1109

    
1110
void OPPROTO op_fstl_ST0_A0(void)
1111
{
1112
    ST0 = ldfq((void *)A0);
1113
}
1114

    
1115
void OPPROTO op_fist_ST0_A0(void)
1116
{
1117
    int val;
1118
    val = lrint(ST0);
1119
    stw((void *)A0, val);
1120
}
1121

    
1122
void OPPROTO op_fistl_ST0_A0(void)
1123
{
1124
    int val;
1125
    val = lrint(ST0);
1126
    stl((void *)A0, val);
1127
}
1128

    
1129
void OPPROTO op_fistll_ST0_A0(void)
1130
{
1131
    int64_t val;
1132
    val = llrint(ST0);
1133
    stq((void *)A0, val);
1134
}
1135

    
1136
/* FPU move */
1137

    
1138
static inline void fpush(void)
1139
{
1140
    env->fpstt = (env->fpstt - 1) & 7;
1141
    env->fptags[env->fpstt] = 0; /* validate stack entry */
1142
}
1143

    
1144
static inline void fpop(void)
1145
{
1146
    env->fptags[env->fpstt] = 1; /* invvalidate stack entry */
1147
    env->fpstt = (env->fpstt + 1) & 7;
1148
}
1149

    
1150
void OPPROTO op_fpush(void)
1151
{
1152
    fpush();
1153
}
1154

    
1155
void OPPROTO op_fpop(void)
1156
{
1157
    fpop();
1158
}
1159

    
1160
void OPPROTO op_fdecstp(void)
1161
{
1162
    env->fpstt = (env->fpstt - 1) & 7;
1163
    env->fpus &= (~0x4700);
1164
}
1165

    
1166
void OPPROTO op_fincstp(void)
1167
{
1168
    env->fpstt = (env->fpstt + 1) & 7;
1169
    env->fpus &= (~0x4700);
1170
}
1171

    
1172
void OPPROTO op_fmov_ST0_FT0(void)
1173
{
1174
    ST0 = FT0;
1175
}
1176

    
1177
void OPPROTO op_fmov_FT0_STN(void)
1178
{
1179
    FT0 = ST(PARAM1);
1180
}
1181

    
1182
void OPPROTO op_fmov_ST0_STN(void)
1183
{
1184
    ST0 = ST(PARAM1);
1185
}
1186

    
1187
void OPPROTO op_fmov_STN_ST0(void)
1188
{
1189
    ST(PARAM1) = ST0;
1190
}
1191

    
1192
void OPPROTO op_fxchg_ST0_STN(void)
1193
{
1194
    CPU86_LDouble tmp;
1195
    tmp = ST(PARAM1);
1196
    ST(PARAM1) = ST0;
1197
    ST0 = tmp;
1198
}
1199

    
1200
/* FPU operations */
1201

    
1202
/* XXX: handle nans */
1203
void OPPROTO op_fcom_ST0_FT0(void)
1204
{
1205
    env->fpus &= (~0x4500);        /* (C3,C2,C0) <-- 000 */
1206
    if (ST0 < FT0)
1207
        env->fpus |= 0x100;        /* (C3,C2,C0) <-- 001 */
1208
    else if (ST0 == FT0)
1209
        env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
1210
    FORCE_RET();
1211
}
1212

    
1213
void OPPROTO op_fadd_ST0_FT0(void)
1214
{
1215
    ST0 += FT0;
1216
}
1217

    
1218
void OPPROTO op_fmul_ST0_FT0(void)
1219
{
1220
    ST0 *= FT0;
1221
}
1222

    
1223
void OPPROTO op_fsub_ST0_FT0(void)
1224
{
1225
    ST0 -= FT0;
1226
}
1227

    
1228
void OPPROTO op_fsubr_ST0_FT0(void)
1229
{
1230
    ST0 = FT0 - ST0;
1231
}
1232

    
1233
void OPPROTO op_fdiv_ST0_FT0(void)
1234
{
1235
    ST0 /= FT0;
1236
}
1237

    
1238
void OPPROTO op_fdivr_ST0_FT0(void)
1239
{
1240
    ST0 = FT0 / ST0;
1241
}
1242

    
1243
/* fp operations between STN and ST0 */
1244

    
1245
void OPPROTO op_fadd_STN_ST0(void)
1246
{
1247
    ST(PARAM1) += ST0;
1248
}
1249

    
1250
void OPPROTO op_fmul_STN_ST0(void)
1251
{
1252
    ST(PARAM1) *= ST0;
1253
}
1254

    
1255
void OPPROTO op_fsub_STN_ST0(void)
1256
{
1257
    ST(PARAM1) -= ST0;
1258
}
1259

    
1260
void OPPROTO op_fsubr_STN_ST0(void)
1261
{
1262
    CPU86_LDouble *p;
1263
    p = &ST(PARAM1);
1264
    *p = ST0 - *p;
1265
}
1266

    
1267
void OPPROTO op_fdiv_STN_ST0(void)
1268
{
1269
    ST(PARAM1) /= ST0;
1270
}
1271

    
1272
void OPPROTO op_fdivr_STN_ST0(void)
1273
{
1274
    CPU86_LDouble *p;
1275
    p = &ST(PARAM1);
1276
    *p = ST0 / *p;
1277
}
1278

    
1279
/* misc FPU operations */
1280
void OPPROTO op_fchs_ST0(void)
1281
{
1282
    ST0 = -ST0;
1283
}
1284

    
1285
void OPPROTO op_fabs_ST0(void)
1286
{
1287
    ST0 = fabs(ST0);
1288
}
1289

    
1290
void OPPROTO op_fxam_ST0(void)
1291
{
1292
    CPU86_LDoubleU temp;
1293
    int expdif;
1294

    
1295
    temp.d = ST0;
1296

    
1297
    env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
1298
    if (SIGND(temp))
1299
        env->fpus |= 0x200; /* C1 <-- 1 */
1300

    
1301
    expdif = EXPD(temp);
1302
    if (expdif == MAXEXPD) {
1303
        if (MANTD(temp) == 0)
1304
            env->fpus |=  0x500 /*Infinity*/;
1305
        else
1306
            env->fpus |=  0x100 /*NaN*/;
1307
    } else if (expdif == 0) {
1308
        if (MANTD(temp) == 0)
1309
            env->fpus |=  0x4000 /*Zero*/;
1310
        else
1311
            env->fpus |= 0x4400 /*Denormal*/;
1312
    } else {
1313
        env->fpus |= 0x400;
1314
    }
1315
    FORCE_RET();
1316
}
1317

    
1318
void OPPROTO op_fld1_ST0(void)
1319
{
1320
    ST0 = *(CPU86_LDouble *)&f15rk[1];
1321
}
1322

    
1323
void OPPROTO op_fld2t_ST0(void)
1324
{
1325
    ST0 = *(CPU86_LDouble *)&f15rk[6];
1326
}
1327

    
1328
void OPPROTO op_fld2e_ST0(void)
1329
{
1330
    ST0 = *(CPU86_LDouble *)&f15rk[5];
1331
}
1332

    
1333
void OPPROTO op_fldpi_ST0(void)
1334
{
1335
    ST0 = *(CPU86_LDouble *)&f15rk[2];
1336
}
1337

    
1338
void OPPROTO op_fldlg2_ST0(void)
1339
{
1340
    ST0 = *(CPU86_LDouble *)&f15rk[3];
1341
}
1342

    
1343
void OPPROTO op_fldln2_ST0(void)
1344
{
1345
    ST0 = *(CPU86_LDouble *)&f15rk[4];
1346
}
1347

    
1348
void OPPROTO op_fldz_ST0(void)
1349
{
1350
    ST0 = *(CPU86_LDouble *)&f15rk[0];
1351
}
1352

    
1353
void OPPROTO op_fldz_FT0(void)
1354
{
1355
    ST0 = *(CPU86_LDouble *)&f15rk[0];
1356
}
1357

    
1358
void helper_f2xm1(void)
1359
{
1360
    ST0 = pow(2.0,ST0) - 1.0;
1361
}
1362

    
1363
void helper_fyl2x(void)
1364
{
1365
    CPU86_LDouble fptemp;
1366
    
1367
    fptemp = ST0;
1368
    if (fptemp>0.0){
1369
        fptemp = log(fptemp)/log(2.0);         /* log2(ST) */
1370
        ST1 *= fptemp;
1371
        fpop();
1372
    } else { 
1373
        env->fpus &= (~0x4700);
1374
        env->fpus |= 0x400;
1375
    }
1376
}
1377

    
1378
void helper_fptan(void)
1379
{
1380
    CPU86_LDouble fptemp;
1381

    
1382
    fptemp = ST0;
1383
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1384
        env->fpus |= 0x400;
1385
    } else {
1386
        ST0 = tan(fptemp);
1387
        fpush();
1388
        ST0 = 1.0;
1389
        env->fpus &= (~0x400);  /* C2 <-- 0 */
1390
        /* the above code is for  |arg| < 2**52 only */
1391
    }
1392
}
1393

    
1394
void helper_fpatan(void)
1395
{
1396
    CPU86_LDouble fptemp, fpsrcop;
1397

    
1398
    fpsrcop = ST1;
1399
    fptemp = ST0;
1400
    ST1 = atan2(fpsrcop,fptemp);
1401
    fpop();
1402
}
1403

    
1404
void helper_fxtract(void)
1405
{
1406
    CPU86_LDoubleU temp;
1407
    unsigned int expdif;
1408

    
1409
    temp.d = ST0;
1410
    expdif = EXPD(temp) - EXPBIAS;
1411
    /*DP exponent bias*/
1412
    ST0 = expdif;
1413
    fpush();
1414
    BIASEXPONENT(temp);
1415
    ST0 = temp.d;
1416
}
1417

    
1418
void helper_fprem1(void)
1419
{
1420
    CPU86_LDouble dblq, fpsrcop, fptemp;
1421
    CPU86_LDoubleU fpsrcop1, fptemp1;
1422
    int expdif;
1423
    int q;
1424

    
1425
    fpsrcop = ST0;
1426
    fptemp = ST1;
1427
    fpsrcop1.d = fpsrcop;
1428
    fptemp1.d = fptemp;
1429
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
1430
    if (expdif < 53) {
1431
        dblq = fpsrcop / fptemp;
1432
        dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
1433
        ST0 = fpsrcop - fptemp*dblq;
1434
        q = (int)dblq; /* cutting off top bits is assumed here */
1435
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1436
                                /* (C0,C1,C3) <-- (q2,q1,q0) */
1437
        env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
1438
        env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
1439
        env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
1440
    } else {
1441
        env->fpus |= 0x400;  /* C2 <-- 1 */
1442
        fptemp = pow(2.0, expdif-50);
1443
        fpsrcop = (ST0 / ST1) / fptemp;
1444
        /* fpsrcop = integer obtained by rounding to the nearest */
1445
        fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
1446
            floor(fpsrcop): ceil(fpsrcop);
1447
        ST0 -= (ST1 * fpsrcop * fptemp);
1448
    }
1449
}
1450

    
1451
void helper_fprem(void)
1452
{
1453
    CPU86_LDouble dblq, fpsrcop, fptemp;
1454
    CPU86_LDoubleU fpsrcop1, fptemp1;
1455
    int expdif;
1456
    int q;
1457
    
1458
    fpsrcop = ST0;
1459
    fptemp = ST1;
1460
    fpsrcop1.d = fpsrcop;
1461
    fptemp1.d = fptemp;
1462
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
1463
    if ( expdif < 53 ) {
1464
        dblq = fpsrcop / fptemp;
1465
        dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
1466
        ST0 = fpsrcop - fptemp*dblq;
1467
        q = (int)dblq; /* cutting off top bits is assumed here */
1468
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1469
                                /* (C0,C1,C3) <-- (q2,q1,q0) */
1470
        env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
1471
        env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
1472
        env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
1473
    } else {
1474
        env->fpus |= 0x400;  /* C2 <-- 1 */
1475
        fptemp = pow(2.0, expdif-50);
1476
        fpsrcop = (ST0 / ST1) / fptemp;
1477
        /* fpsrcop = integer obtained by chopping */
1478
        fpsrcop = (fpsrcop < 0.0)?
1479
            -(floor(fabs(fpsrcop))): floor(fpsrcop);
1480
        ST0 -= (ST1 * fpsrcop * fptemp);
1481
    }
1482
}
1483

    
1484
void helper_fyl2xp1(void)
1485
{
1486
    CPU86_LDouble fptemp;
1487

    
1488
    fptemp = ST0;
1489
    if ((fptemp+1.0)>0.0) {
1490
        fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
1491
        ST1 *= fptemp;
1492
        fpop();
1493
    } else { 
1494
        env->fpus &= (~0x4700);
1495
        env->fpus |= 0x400;
1496
    }
1497
}
1498

    
1499
void helper_fsqrt(void)
1500
{
1501
    CPU86_LDouble fptemp;
1502

    
1503
    fptemp = ST0;
1504
    if (fptemp<0.0) { 
1505
        env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
1506
        env->fpus |= 0x400;
1507
    }
1508
    ST0 = sqrt(fptemp);
1509
}
1510

    
1511
void helper_fsincos(void)
1512
{
1513
    CPU86_LDouble fptemp;
1514

    
1515
    fptemp = ST0;
1516
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1517
        env->fpus |= 0x400;
1518
    } else {
1519
        ST0 = sin(fptemp);
1520
        fpush();
1521
        ST0 = cos(fptemp);
1522
        env->fpus &= (~0x400);  /* C2 <-- 0 */
1523
        /* the above code is for  |arg| < 2**63 only */
1524
    }
1525
}
1526

    
1527
void helper_frndint(void)
1528
{
1529
    ST0 = rint(ST0);
1530
}
1531

    
1532
void helper_fscale(void)
1533
{
1534
    CPU86_LDouble fpsrcop, fptemp;
1535

    
1536
    fpsrcop = 2.0;
1537
    fptemp = pow(fpsrcop,ST1);
1538
    ST0 *= fptemp;
1539
}
1540

    
1541
void helper_fsin(void)
1542
{
1543
    CPU86_LDouble fptemp;
1544

    
1545
    fptemp = ST0;
1546
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1547
        env->fpus |= 0x400;
1548
    } else {
1549
        ST0 = sin(fptemp);
1550
        env->fpus &= (~0x400);  /* C2 <-- 0 */
1551
        /* the above code is for  |arg| < 2**53 only */
1552
    }
1553
}
1554

    
1555
void helper_fcos(void)
1556
{
1557
    CPU86_LDouble fptemp;
1558

    
1559
    fptemp = ST0;
1560
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1561
        env->fpus |= 0x400;
1562
    } else {
1563
        ST0 = cos(fptemp);
1564
        env->fpus &= (~0x400);  /* C2 <-- 0 */
1565
        /* the above code is for  |arg5 < 2**63 only */
1566
    }
1567
}
1568

    
1569
/* associated heplers to reduce generated code length and to simplify
1570
   relocation (FP constants are usually stored in .rodata section) */
1571

    
1572
void OPPROTO op_f2xm1(void)
1573
{
1574
    helper_f2xm1();
1575
}
1576

    
1577
void OPPROTO op_fyl2x(void)
1578
{
1579
    helper_fyl2x();
1580
}
1581

    
1582
void OPPROTO op_fptan(void)
1583
{
1584
    helper_fptan();
1585
}
1586

    
1587
void OPPROTO op_fpatan(void)
1588
{
1589
    helper_fpatan();
1590
}
1591

    
1592
void OPPROTO op_fxtract(void)
1593
{
1594
    helper_fxtract();
1595
}
1596

    
1597
void OPPROTO op_fprem1(void)
1598
{
1599
    helper_fprem1();
1600
}
1601

    
1602

    
1603
void OPPROTO op_fprem(void)
1604
{
1605
    helper_fprem();
1606
}
1607

    
1608
void OPPROTO op_fyl2xp1(void)
1609
{
1610
    helper_fyl2xp1();
1611
}
1612

    
1613
void OPPROTO op_fsqrt(void)
1614
{
1615
    helper_fsqrt();
1616
}
1617

    
1618
void OPPROTO op_fsincos(void)
1619
{
1620
    helper_fsincos();
1621
}
1622

    
1623
void OPPROTO op_frndint(void)
1624
{
1625
    helper_frndint();
1626
}
1627

    
1628
void OPPROTO op_fscale(void)
1629
{
1630
    helper_fscale();
1631
}
1632

    
1633
void OPPROTO op_fsin(void)
1634
{
1635
    helper_fsin();
1636
}
1637

    
1638
void OPPROTO op_fcos(void)
1639
{
1640
    helper_fcos();
1641
}
1642

    
1643
/* main execution loop */
1644
uint8_t code_gen_buffer[65536];
1645

    
1646
#ifdef DEBUG_EXEC
1647
static const char *cc_op_str[] = {
1648
    "DYNAMIC",
1649
    "EFLAGS",
1650
    "MUL",
1651
    "ADDB",
1652
    "ADDW",
1653
    "ADDL",
1654
    "SUBB",
1655
    "SUBW",
1656
    "SUBL",
1657
    "LOGICB",
1658
    "LOGICW",
1659
    "LOGICL",
1660
    "INCB",
1661
    "INCW",
1662
    "INCL",
1663
    "DECB",
1664
    "DECW",
1665
    "DECL",
1666
    "SHLB",
1667
    "SHLW",
1668
    "SHLL",
1669
};
1670
#endif
1671

    
1672
int cpu_x86_exec(CPUX86State *env1)
1673
{
1674
    int saved_T0, saved_T1, saved_A0;
1675
    CPUX86State *saved_env;
1676
    int code_gen_size, ret;
1677
    void (*gen_func)(void);
1678

    
1679
    /* first we save global registers */
1680
    saved_T0 = T0;
1681
    saved_T1 = T1;
1682
    saved_A0 = A0;
1683
    saved_env = env;
1684
    env = env1;
1685
    
1686
    /* prepare setjmp context for exception handling */
1687
    if (setjmp(env->jmp_env) == 0) {
1688
        for(;;) {
1689
#ifdef DEBUG_EXEC
1690
            if (loglevel) {
1691
                fprintf(logfile, 
1692
                        "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n"
1693
                        "ESI=%08x ESI=%08X EBP=%08x ESP=%08x\n"
1694
                        "CCS=%08x CCD=%08x CCOP=%s\n",
1695
                        env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 
1696
                        env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 
1697
                        env->cc_src, env->cc_dst, cc_op_str[env->cc_op]);
1698
            }
1699
#endif
1700
            cpu_x86_gen_code(code_gen_buffer, &code_gen_size, (uint8_t *)env->pc);
1701
            /* execute the generated code */
1702
            gen_func = (void *)code_gen_buffer;
1703
            gen_func();
1704
        }
1705
    }
1706
    ret = env->exception_index;
1707

    
1708
    /* restore global registers */
1709
    T0 = saved_T0;
1710
    T1 = saved_T1;
1711
    A0 = saved_A0;
1712
    env = saved_env;
1713
    return ret;
1714
}