Statistics
| Branch: | Revision:

root / op-i386.c @ 4b74fe1f

History | View | Annotate | Download (34.7 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 {
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
}