Statistics
| Branch: | Revision:

root / op-i386.c @ 1017ebe9

History | View | Annotate | Download (38.9 kB)

1
#define DEBUG_EXEC
2

    
3
typedef unsigned char uint8_t;
4
typedef unsigned short uint16_t;
5
typedef unsigned int uint32_t;
6
typedef unsigned long long uint64_t;
7

    
8
typedef signed char int8_t;
9
typedef signed short int16_t;
10
typedef signed int int32_t;
11
typedef signed long long int64_t;
12

    
13
#define bswap32(x) \
14
({ \
15
        uint32_t __x = (x); \
16
        ((uint32_t)( \
17
                (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
18
                (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
19
                (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
20
                (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
21
})
22

    
23
#define NULL 0
24
#include <fenv.h>
25

    
26
typedef struct FILE FILE;
27
extern FILE *logfile;
28
extern int loglevel;
29
extern int fprintf(FILE *, const char *, ...);
30

    
31
#ifdef __i386__
32
register unsigned int T0 asm("ebx");
33
register unsigned int T1 asm("esi");
34
register unsigned int A0 asm("edi");
35
register struct CPUX86State *env asm("ebp");
36
#endif
37
#ifdef __powerpc__
38
register unsigned int T0 asm("r24");
39
register unsigned int T1 asm("r25");
40
register unsigned int A0 asm("r26");
41
register struct CPUX86State *env asm("r27");
42
#endif
43
#ifdef __arm__
44
register unsigned int T0 asm("r4");
45
register unsigned int T1 asm("r5");
46
register unsigned int A0 asm("r6");
47
register struct CPUX86State *env asm("r7");
48
#endif
49
#ifdef __mips__
50
register unsigned int T0 asm("s0");
51
register unsigned int T1 asm("s1");
52
register unsigned int A0 asm("s2");
53
register struct CPUX86State *env asm("s3");
54
#endif
55
#ifdef __sparc__
56
register unsigned int T0 asm("l0");
57
register unsigned int T1 asm("l1");
58
register unsigned int A0 asm("l2");
59
register struct CPUX86State *env asm("l3");
60
#endif
61

    
62
/* force GCC to generate only one epilog at the end of the function */
63
#define FORCE_RET() asm volatile ("");
64

    
65
#ifndef OPPROTO
66
#define OPPROTO
67
#endif
68

    
69
#define xglue(x, y) x ## y
70
#define glue(x, y) xglue(x, y)
71

    
72
#define EAX (env->regs[R_EAX])
73
#define ECX (env->regs[R_ECX])
74
#define EDX (env->regs[R_EDX])
75
#define EBX (env->regs[R_EBX])
76
#define ESP (env->regs[R_ESP])
77
#define EBP (env->regs[R_EBP])
78
#define ESI (env->regs[R_ESI])
79
#define EDI (env->regs[R_EDI])
80
#define PC  (env->pc)
81
#define DF  (env->df)
82

    
83
#define CC_SRC (env->cc_src)
84
#define CC_DST (env->cc_dst)
85
#define CC_OP  (env->cc_op)
86

    
87
/* float macros */
88
#define FT0    (env->ft0)
89
#define ST0    (env->fpregs[env->fpstt])
90
#define ST(n)  (env->fpregs[(env->fpstt + (n)) & 7])
91
#define ST1    ST(1)
92

    
93
extern int __op_param1, __op_param2, __op_param3;
94
#define PARAM1 ((long)(&__op_param1))
95
#define PARAM2 ((long)(&__op_param2))
96
#define PARAM3 ((long)(&__op_param3))
97

    
98
#include "cpu-i386.h"
99

    
100
typedef struct CCTable {
101
    int (*compute_all)(void); /* return all the flags */
102
    int (*compute_c)(void);  /* return the C flag */
103
} CCTable;
104

    
105
/* NOTE: data are not static to force relocation generation by GCC */
106
extern CCTable cc_table[];
107

    
108
uint8_t parity_table[256] = {
109
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
110
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
111
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
112
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
113
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
114
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
115
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
116
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
117
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
118
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
119
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
120
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
121
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
122
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
123
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
124
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
125
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
126
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
127
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
128
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
129
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
130
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
131
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
132
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
133
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
134
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
135
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
136
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
137
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
138
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
139
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
140
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
141
};
142

    
143
/* modulo 17 table */
144
const uint8_t rclw_table[32] = {
145
    0, 1, 2, 3, 4, 5, 6, 7, 
146
    8, 9,10,11,12,13,14,15,
147
   16, 0, 1, 2, 3, 4, 5, 6,
148
    7, 8, 9,10,11,12,13,14,
149
};
150

    
151
/* modulo 9 table */
152
const uint8_t rclb_table[32] = {
153
    0, 1, 2, 3, 4, 5, 6, 7, 
154
    8, 0, 1, 2, 3, 4, 5, 6,
155
    7, 8, 0, 1, 2, 3, 4, 5, 
156
    6, 7, 8, 0, 1, 2, 3, 4,
157
};
158

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

    
206
/* exception support */
207
/* NOTE: not static to force relocation generation by GCC */
208
void raise_exception(int exception_index)
209
{
210
    env->exception_index = exception_index;
211
    longjmp(env->jmp_env, 1);
212
}
213

    
214
/* we define the various pieces of code used by the JIT */
215

    
216
#define REG EAX
217
#define REGNAME _EAX
218
#include "opreg_template.h"
219
#undef REG
220
#undef REGNAME
221

    
222
#define REG ECX
223
#define REGNAME _ECX
224
#include "opreg_template.h"
225
#undef REG
226
#undef REGNAME
227

    
228
#define REG EDX
229
#define REGNAME _EDX
230
#include "opreg_template.h"
231
#undef REG
232
#undef REGNAME
233

    
234
#define REG EBX
235
#define REGNAME _EBX
236
#include "opreg_template.h"
237
#undef REG
238
#undef REGNAME
239

    
240
#define REG ESP
241
#define REGNAME _ESP
242
#include "opreg_template.h"
243
#undef REG
244
#undef REGNAME
245

    
246
#define REG EBP
247
#define REGNAME _EBP
248
#include "opreg_template.h"
249
#undef REG
250
#undef REGNAME
251

    
252
#define REG ESI
253
#define REGNAME _ESI
254
#include "opreg_template.h"
255
#undef REG
256
#undef REGNAME
257

    
258
#define REG EDI
259
#define REGNAME _EDI
260
#include "opreg_template.h"
261
#undef REG
262
#undef REGNAME
263

    
264
/* operations */
265

    
266
void OPPROTO op_addl_T0_T1_cc(void)
267
{
268
    CC_SRC = T0;
269
    T0 += T1;
270
    CC_DST = T0;
271
}
272

    
273
void OPPROTO op_orl_T0_T1_cc(void)
274
{
275
    T0 |= T1;
276
    CC_DST = T0;
277
}
278

    
279
void OPPROTO op_andl_T0_T1_cc(void)
280
{
281
    T0 &= T1;
282
    CC_DST = T0;
283
}
284

    
285
void OPPROTO op_subl_T0_T1_cc(void)
286
{
287
    CC_SRC = T0;
288
    T0 -= T1;
289
    CC_DST = T0;
290
}
291

    
292
void OPPROTO op_xorl_T0_T1_cc(void)
293
{
294
    T0 ^= T1;
295
    CC_DST = T0;
296
}
297

    
298
void OPPROTO op_cmpl_T0_T1_cc(void)
299
{
300
    CC_SRC = T0;
301
    CC_DST = T0 - T1;
302
}
303

    
304
void OPPROTO op_notl_T0(void)
305
{
306
    T0 = ~T0;
307
}
308

    
309
void OPPROTO op_negl_T0_cc(void)
310
{
311
    CC_SRC = 0;
312
    T0 = -T0;
313
    CC_DST = T0;
314
}
315

    
316
void OPPROTO op_incl_T0_cc(void)
317
{
318
    CC_SRC = cc_table[CC_OP].compute_c();
319
    T0++;
320
    CC_DST = T0;
321
}
322

    
323
void OPPROTO op_decl_T0_cc(void)
324
{
325
    CC_SRC = cc_table[CC_OP].compute_c();
326
    T0--;
327
    CC_DST = T0;
328
}
329

    
330
void OPPROTO op_testl_T0_T1_cc(void)
331
{
332
    CC_DST = T0 & T1;
333
}
334

    
335
void OPPROTO op_bswapl_T0(void)
336
{
337
    T0 = bswap32(T0);
338
}
339

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

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

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

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

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

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

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

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

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

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

    
422
void OPPROTO op_idivb_AL_T0(void)
423
{
424
    int num, den, q, r;
425

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

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

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

    
445
void OPPROTO op_idivw_AX_T0(void)
446
{
447
    int num, den, q, r;
448

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

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

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

    
483
/* constant load */
484

    
485
void OPPROTO op_movl_T0_im(void)
486
{
487
    T0 = PARAM1;
488
}
489

    
490
void OPPROTO op_movl_T1_im(void)
491
{
492
    T1 = PARAM1;
493
}
494

    
495
void OPPROTO op_movl_A0_im(void)
496
{
497
    A0 = PARAM1;
498
}
499

    
500
void OPPROTO op_addl_A0_im(void)
501
{
502
    A0 += PARAM1;
503
}
504

    
505
void OPPROTO op_andl_A0_ffff(void)
506
{
507
    A0 = A0 & 0xffff;
508
}
509

    
510
/* memory access */
511

    
512
void OPPROTO op_ldub_T0_A0(void)
513
{
514
    T0 = ldub((uint8_t *)A0);
515
}
516

    
517
void OPPROTO op_ldsb_T0_A0(void)
518
{
519
    T0 = ldsb((int8_t *)A0);
520
}
521

    
522
void OPPROTO op_lduw_T0_A0(void)
523
{
524
    T0 = lduw((uint8_t *)A0);
525
}
526

    
527
void OPPROTO op_ldsw_T0_A0(void)
528
{
529
    T0 = ldsw((int8_t *)A0);
530
}
531

    
532
void OPPROTO op_ldl_T0_A0(void)
533
{
534
    T0 = ldl((uint8_t *)A0);
535
}
536

    
537
void OPPROTO op_ldub_T1_A0(void)
538
{
539
    T1 = ldub((uint8_t *)A0);
540
}
541

    
542
void OPPROTO op_ldsb_T1_A0(void)
543
{
544
    T1 = ldsb((int8_t *)A0);
545
}
546

    
547
void OPPROTO op_lduw_T1_A0(void)
548
{
549
    T1 = lduw((uint8_t *)A0);
550
}
551

    
552
void OPPROTO op_ldsw_T1_A0(void)
553
{
554
    T1 = ldsw((int8_t *)A0);
555
}
556

    
557
void OPPROTO op_ldl_T1_A0(void)
558
{
559
    T1 = ldl((uint8_t *)A0);
560
}
561

    
562
void OPPROTO op_stb_T0_A0(void)
563
{
564
    stb((uint8_t *)A0, T0);
565
}
566

    
567
void OPPROTO op_stw_T0_A0(void)
568
{
569
    stw((uint8_t *)A0, T0);
570
}
571

    
572
void OPPROTO op_stl_T0_A0(void)
573
{
574
    stl((uint8_t *)A0, T0);
575
}
576

    
577
/* used for bit operations */
578

    
579
void OPPROTO op_add_bitw_A0_T1(void)
580
{
581
    A0 += ((int32_t)T1 >> 4) << 1;
582
}
583

    
584
void OPPROTO op_add_bitl_A0_T1(void)
585
{
586
    A0 += ((int32_t)T1 >> 5) << 2;
587
}
588

    
589
/* indirect jump */
590

    
591
void OPPROTO op_jmp_T0(void)
592
{
593
    PC = T0;
594
}
595

    
596
void OPPROTO op_jmp_im(void)
597
{
598
    PC = PARAM1;
599
}
600

    
601
void OPPROTO op_int_im(void)
602
{
603
    PC = PARAM1;
604
    raise_exception(EXCP0D_GPF);
605
}
606

    
607
void OPPROTO op_int3(void)
608
{
609
    PC = PARAM1;
610
    raise_exception(EXCP03_INT3);
611
}
612

    
613
void OPPROTO op_into(void)
614
{
615
    int eflags;
616
    eflags = cc_table[CC_OP].compute_all();
617
    if (eflags & CC_O) {
618
        PC = PARAM1;
619
        raise_exception(EXCP04_INTO);
620
    } else {
621
        PC = PARAM2;
622
    }
623
}
624

    
625
/* string ops */
626

    
627
#define ldul ldl
628

    
629
#define SHIFT 0
630
#include "ops_template.h"
631
#undef SHIFT
632

    
633
#define SHIFT 1
634
#include "ops_template.h"
635
#undef SHIFT
636

    
637
#define SHIFT 2
638
#include "ops_template.h"
639
#undef SHIFT
640

    
641
/* sign extend */
642

    
643
void OPPROTO op_movsbl_T0_T0(void)
644
{
645
    T0 = (int8_t)T0;
646
}
647

    
648
void OPPROTO op_movzbl_T0_T0(void)
649
{
650
    T0 = (uint8_t)T0;
651
}
652

    
653
void OPPROTO op_movswl_T0_T0(void)
654
{
655
    T0 = (int16_t)T0;
656
}
657

    
658
void OPPROTO op_movzwl_T0_T0(void)
659
{
660
    T0 = (uint16_t)T0;
661
}
662

    
663
void OPPROTO op_movswl_EAX_AX(void)
664
{
665
    EAX = (int16_t)EAX;
666
}
667

    
668
void OPPROTO op_movsbw_AX_AL(void)
669
{
670
    EAX = (EAX & 0xffff0000) | ((int8_t)EAX & 0xffff);
671
}
672

    
673
void OPPROTO op_movslq_EDX_EAX(void)
674
{
675
    EDX = (int32_t)EAX >> 31;
676
}
677

    
678
void OPPROTO op_movswl_DX_AX(void)
679
{
680
    EDX = (EDX & 0xffff0000) | (((int16_t)EAX >> 15) & 0xffff);
681
}
682

    
683
/* push/pop */
684
/* XXX: add 16 bit operand/16 bit seg variants */
685

    
686
void op_pushl_T0(void)
687
{
688
    uint32_t offset;
689
    offset = ESP - 4;
690
    stl((void *)offset, T0);
691
    /* modify ESP after to handle exceptions correctly */
692
    ESP = offset;
693
}
694

    
695
void op_pushl_T1(void)
696
{
697
    uint32_t offset;
698
    offset = ESP - 4;
699
    stl((void *)offset, T1);
700
    /* modify ESP after to handle exceptions correctly */
701
    ESP = offset;
702
}
703

    
704
void op_popl_T0(void)
705
{
706
    T0 = ldl((void *)ESP);
707
    ESP += 4;
708
}
709

    
710
void op_addl_ESP_im(void)
711
{
712
    ESP += PARAM1;
713
}
714

    
715
/* flags handling */
716

    
717
/* slow jumps cases (compute x86 flags) */
718
void OPPROTO op_jo_cc(void)
719
{
720
    int eflags;
721
    eflags = cc_table[CC_OP].compute_all();
722
    if (eflags & CC_O)
723
        PC = PARAM1;
724
    else
725
        PC = PARAM2;
726
    FORCE_RET();
727
}
728

    
729
void OPPROTO op_jb_cc(void)
730
{
731
    if (cc_table[CC_OP].compute_c())
732
        PC = PARAM1;
733
    else
734
        PC = PARAM2;
735
    FORCE_RET();
736
}
737

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

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

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

    
771
void OPPROTO op_jp_cc(void)
772
{
773
    int eflags;
774
    eflags = cc_table[CC_OP].compute_all();
775
    if (eflags & CC_P)
776
        PC = PARAM1;
777
    else
778
        PC = PARAM2;
779
    FORCE_RET();
780
}
781

    
782
void OPPROTO op_jl_cc(void)
783
{
784
    int eflags;
785
    eflags = cc_table[CC_OP].compute_all();
786
    if ((eflags ^ (eflags >> 4)) & 0x80)
787
        PC = PARAM1;
788
    else
789
        PC = PARAM2;
790
    FORCE_RET();
791
}
792

    
793
void OPPROTO op_jle_cc(void)
794
{
795
    int eflags;
796
    eflags = cc_table[CC_OP].compute_all();
797
    if (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z))
798
        PC = PARAM1;
799
    else
800
        PC = PARAM2;
801
    FORCE_RET();
802
}
803

    
804
/* slow set cases (compute x86 flags) */
805
void OPPROTO op_seto_T0_cc(void)
806
{
807
    int eflags;
808
    eflags = cc_table[CC_OP].compute_all();
809
    T0 = (eflags >> 11) & 1;
810
}
811

    
812
void OPPROTO op_setb_T0_cc(void)
813
{
814
    T0 = cc_table[CC_OP].compute_c();
815
}
816

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

    
824
void OPPROTO op_setbe_T0_cc(void)
825
{
826
    int eflags;
827
    eflags = cc_table[CC_OP].compute_all();
828
    T0 = (eflags & (CC_Z | CC_C)) != 0;
829
}
830

    
831
void OPPROTO op_sets_T0_cc(void)
832
{
833
    int eflags;
834
    eflags = cc_table[CC_OP].compute_all();
835
    T0 = (eflags >> 7) & 1;
836
}
837

    
838
void OPPROTO op_setp_T0_cc(void)
839
{
840
    int eflags;
841
    eflags = cc_table[CC_OP].compute_all();
842
    T0 = (eflags >> 2) & 1;
843
}
844

    
845
void OPPROTO op_setl_T0_cc(void)
846
{
847
    int eflags;
848
    eflags = cc_table[CC_OP].compute_all();
849
    T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
850
}
851

    
852
void OPPROTO op_setle_T0_cc(void)
853
{
854
    int eflags;
855
    eflags = cc_table[CC_OP].compute_all();
856
    T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
857
}
858

    
859
void OPPROTO op_xor_T0_1(void)
860
{
861
    T0 ^= 1;
862
}
863

    
864
void OPPROTO op_set_cc_op(void)
865
{
866
    CC_OP = PARAM1;
867
}
868

    
869
void OPPROTO op_movl_eflags_T0(void)
870
{
871
    CC_SRC = T0;
872
    DF = 1 - (2 * ((T0 >> 10) & 1));
873
}
874

    
875
/* XXX: compute only O flag */
876
void OPPROTO op_movb_eflags_T0(void)
877
{
878
    int of;
879
    of = cc_table[CC_OP].compute_all() & CC_O;
880
    CC_SRC = T0 | of;
881
}
882

    
883
void OPPROTO op_movl_T0_eflags(void)
884
{
885
    T0 = cc_table[CC_OP].compute_all();
886
    T0 |= (DF & DIRECTION_FLAG);
887
}
888

    
889
void OPPROTO op_cld(void)
890
{
891
    DF = 1;
892
}
893

    
894
void OPPROTO op_std(void)
895
{
896
    DF = -1;
897
}
898

    
899
void OPPROTO op_clc(void)
900
{
901
    int eflags;
902
    eflags = cc_table[CC_OP].compute_all();
903
    eflags &= ~CC_C;
904
    CC_SRC = eflags;
905
}
906

    
907
void OPPROTO op_stc(void)
908
{
909
    int eflags;
910
    eflags = cc_table[CC_OP].compute_all();
911
    eflags |= CC_C;
912
    CC_SRC = eflags;
913
}
914

    
915
void OPPROTO op_cmc(void)
916
{
917
    int eflags;
918
    eflags = cc_table[CC_OP].compute_all();
919
    eflags ^= CC_C;
920
    CC_SRC = eflags;
921
}
922

    
923
static int compute_all_eflags(void)
924
{
925
    return CC_SRC;
926
}
927

    
928
static int compute_c_eflags(void)
929
{
930
    return CC_SRC & CC_C;
931
}
932

    
933
static int compute_c_mul(void)
934
{
935
    int cf;
936
    cf = (CC_SRC != 0);
937
    return cf;
938
}
939

    
940
static int compute_all_mul(void)
941
{
942
    int cf, pf, af, zf, sf, of;
943
    cf = (CC_SRC != 0);
944
    pf = 0; /* undefined */
945
    af = 0; /* undefined */
946
    zf = 0; /* undefined */
947
    sf = 0; /* undefined */
948
    of = cf << 11;
949
    return cf | pf | af | zf | sf | of;
950
}
951
    
952
CCTable cc_table[CC_OP_NB] = {
953
    [CC_OP_DYNAMIC] = { /* should never happen */ },
954

    
955
    [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
956

    
957
    [CC_OP_MUL] = { compute_all_mul, compute_c_mul },
958

    
959
    [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
960
    [CC_OP_ADDW] = { compute_all_addw, compute_c_addw  },
961
    [CC_OP_ADDL] = { compute_all_addl, compute_c_addl  },
962

    
963
    [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
964
    [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw  },
965
    [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl  },
966

    
967
    [CC_OP_SUBB] = { compute_all_subb, compute_c_subb  },
968
    [CC_OP_SUBW] = { compute_all_subw, compute_c_subw  },
969
    [CC_OP_SUBL] = { compute_all_subl, compute_c_subl  },
970
    
971
    [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb  },
972
    [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw  },
973
    [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl  },
974
    
975
    [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
976
    [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
977
    [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
978
    
979
    [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
980
    [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
981
    [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
982
    
983
    [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
984
    [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
985
    [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
986
    
987
    [CC_OP_SHLB] = { compute_all_shlb, compute_c_shll },
988
    [CC_OP_SHLW] = { compute_all_shlw, compute_c_shll },
989
    [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
990

    
991
    [CC_OP_SARB] = { compute_all_sarb, compute_c_shll },
992
    [CC_OP_SARW] = { compute_all_sarw, compute_c_shll },
993
    [CC_OP_SARL] = { compute_all_sarl, compute_c_shll },
994
};
995

    
996
/* floating point support */
997

    
998
#ifdef USE_X86LDOUBLE
999
/* use long double functions */
1000
#define lrint lrintl
1001
#define llrint llrintl
1002
#define fabs fabsl
1003
#define sin sinl
1004
#define cos cosl
1005
#define sqrt sqrtl
1006
#define pow powl
1007
#define log logl
1008
#define tan tanl
1009
#define atan2 atan2l
1010
#define floor floorl
1011
#define ceil ceill
1012
#define rint rintl
1013
#endif
1014

    
1015
extern int lrint(CPU86_LDouble x);
1016
extern int64_t llrint(CPU86_LDouble x);
1017
extern CPU86_LDouble fabs(CPU86_LDouble x);
1018
extern CPU86_LDouble sin(CPU86_LDouble x);
1019
extern CPU86_LDouble cos(CPU86_LDouble x);
1020
extern CPU86_LDouble sqrt(CPU86_LDouble x);
1021
extern CPU86_LDouble pow(CPU86_LDouble, CPU86_LDouble);
1022
extern CPU86_LDouble log(CPU86_LDouble x);
1023
extern CPU86_LDouble tan(CPU86_LDouble x);
1024
extern CPU86_LDouble atan2(CPU86_LDouble, CPU86_LDouble);
1025
extern CPU86_LDouble floor(CPU86_LDouble x);
1026
extern CPU86_LDouble ceil(CPU86_LDouble x);
1027
extern CPU86_LDouble rint(CPU86_LDouble x);
1028

    
1029
#define RC_MASK         0xc00
1030
#define RC_NEAR                0x000
1031
#define RC_DOWN                0x400
1032
#define RC_UP                0x800
1033
#define RC_CHOP                0xc00
1034

    
1035
#define MAXTAN 9223372036854775808.0
1036

    
1037
#ifdef USE_X86LDOUBLE
1038

    
1039
/* only for x86 */
1040
typedef union {
1041
    long double d;
1042
    struct {
1043
        unsigned long long lower;
1044
        unsigned short upper;
1045
    } l;
1046
} CPU86_LDoubleU;
1047

    
1048
/* the following deal with x86 long double-precision numbers */
1049
#define MAXEXPD 0x7fff
1050
#define EXPBIAS 16383
1051
#define EXPD(fp)        (fp.l.upper & 0x7fff)
1052
#define SIGND(fp)        ((fp.l.upper) & 0x8000)
1053
#define MANTD(fp)       (fp.l.lower)
1054
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
1055

    
1056
#else
1057

    
1058
typedef union {
1059
    double d;
1060
#ifndef WORDS_BIGENDIAN
1061
    struct {
1062
        unsigned long lower;
1063
        long upper;
1064
    } l;
1065
#else
1066
    struct {
1067
        long upper;
1068
        unsigned long lower;
1069
    } l;
1070
#endif
1071
    long long ll;
1072
} CPU86_LDoubleU;
1073

    
1074
/* the following deal with IEEE double-precision numbers */
1075
#define MAXEXPD 0x7ff
1076
#define EXPBIAS 1023
1077
#define EXPD(fp)        (((fp.l.upper) >> 20) & 0x7FF)
1078
#define SIGND(fp)        ((fp.l.upper) & 0x80000000)
1079
#define MANTD(fp)        (fp.ll & ((1LL << 52) - 1))
1080
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20)
1081
#endif
1082

    
1083
/* fp load FT0 */
1084

    
1085
void OPPROTO op_flds_FT0_A0(void)
1086
{
1087
    FT0 = ldfl((void *)A0);
1088
}
1089

    
1090
void OPPROTO op_fldl_FT0_A0(void)
1091
{
1092
    FT0 = ldfq((void *)A0);
1093
}
1094

    
1095
void OPPROTO op_fild_FT0_A0(void)
1096
{
1097
    FT0 = (CPU86_LDouble)ldsw((void *)A0);
1098
}
1099

    
1100
void OPPROTO op_fildl_FT0_A0(void)
1101
{
1102
    FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1103
}
1104

    
1105
void OPPROTO op_fildll_FT0_A0(void)
1106
{
1107
    FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1108
}
1109

    
1110
/* fp load ST0 */
1111

    
1112
void OPPROTO op_flds_ST0_A0(void)
1113
{
1114
    ST0 = ldfl((void *)A0);
1115
}
1116

    
1117
void OPPROTO op_fldl_ST0_A0(void)
1118
{
1119
    ST0 = ldfq((void *)A0);
1120
}
1121

    
1122
#ifdef USE_X86LDOUBLE
1123
void OPPROTO op_fldt_ST0_A0(void)
1124
{
1125
    ST0 = *(long double *)A0;
1126
}
1127
#else
1128
void helper_fldt_ST0_A0(void)
1129
{
1130
    CPU86_LDoubleU temp;
1131
    int upper, e;
1132
    /* mantissa */
1133
    upper = lduw((uint8_t *)A0 + 8);
1134
    /* XXX: handle overflow ? */
1135
    e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
1136
    e |= (upper >> 4) & 0x800; /* sign */
1137
    temp.ll = ((ldq((void *)A0) >> 11) & ((1LL << 52) - 1)) | ((uint64_t)e << 52);
1138
    ST0 = temp.d;
1139
}
1140

    
1141
void OPPROTO op_fldt_ST0_A0(void)
1142
{
1143
    helper_fldt_ST0_A0();
1144
}
1145
#endif
1146

    
1147
void OPPROTO op_fild_ST0_A0(void)
1148
{
1149
    ST0 = (CPU86_LDouble)ldsw((void *)A0);
1150
}
1151

    
1152
void OPPROTO op_fildl_ST0_A0(void)
1153
{
1154
    ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1155
}
1156

    
1157
void OPPROTO op_fildll_ST0_A0(void)
1158
{
1159
    ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1160
}
1161

    
1162
/* fp store */
1163

    
1164
void OPPROTO op_fsts_ST0_A0(void)
1165
{
1166
    stfl((void *)A0, (float)ST0);
1167
}
1168

    
1169
void OPPROTO op_fstl_ST0_A0(void)
1170
{
1171
    stfq((void *)A0, (double)ST0);
1172
}
1173

    
1174
#ifdef USE_X86LDOUBLE
1175
void OPPROTO op_fstt_ST0_A0(void)
1176
{
1177
    *(long double *)A0 = ST0;
1178
}
1179
#else
1180
void helper_fstt_ST0_A0(void)
1181
{
1182
    CPU86_LDoubleU temp;
1183
    int e;
1184
    temp.d = ST0;
1185
    /* mantissa */
1186
    stq((void *)A0, (MANTD(temp) << 11) | (1LL << 63));
1187
    /* exponent + sign */
1188
    e = EXPD(temp) - EXPBIAS + 16383;
1189
    e |= SIGND(temp) >> 16;
1190
    stw((uint8_t *)A0 + 8, e);
1191
}
1192

    
1193
void OPPROTO op_fstt_ST0_A0(void)
1194
{
1195
    helper_fstt_ST0_A0();
1196
}
1197
#endif
1198

    
1199
void OPPROTO op_fist_ST0_A0(void)
1200
{
1201
    int val;
1202
    val = lrint(ST0);
1203
    stw((void *)A0, val);
1204
}
1205

    
1206
void OPPROTO op_fistl_ST0_A0(void)
1207
{
1208
    int val;
1209
    val = lrint(ST0);
1210
    stl((void *)A0, val);
1211
}
1212

    
1213
void OPPROTO op_fistll_ST0_A0(void)
1214
{
1215
    int64_t val;
1216
    val = llrint(ST0);
1217
    stq((void *)A0, val);
1218
}
1219

    
1220
/* BCD ops */
1221

    
1222
#define MUL10(iv) ( iv + iv + (iv << 3) )
1223

    
1224
void helper_fbld_ST0_A0(void)
1225
{
1226
    uint8_t *seg;
1227
    CPU86_LDouble fpsrcop;
1228
    int m32i;
1229
    unsigned int v;
1230

    
1231
    /* in this code, seg/m32i will be used as temporary ptr/int */
1232
    seg = (uint8_t *)A0 + 8;
1233
    v = ldub(seg--);
1234
    /* XXX: raise exception */
1235
    if (v != 0)
1236
        return;
1237
    v = ldub(seg--);
1238
    /* XXX: raise exception */
1239
    if ((v & 0xf0) != 0)
1240
        return;
1241
    m32i = v;  /* <-- d14 */
1242
    v = ldub(seg--);
1243
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d13 */
1244
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d12 */
1245
    v = ldub(seg--);
1246
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d11 */
1247
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d10 */
1248
    v = ldub(seg--);
1249
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d9 */
1250
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d8 */
1251
    fpsrcop = ((CPU86_LDouble)m32i) * 100000000.0;
1252

    
1253
    v = ldub(seg--);
1254
    m32i = (v >> 4);  /* <-- d7 */
1255
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d6 */
1256
    v = ldub(seg--);
1257
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d5 */
1258
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d4 */
1259
    v = ldub(seg--);
1260
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d3 */
1261
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d2 */
1262
    v = ldub(seg);
1263
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d1 */
1264
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d0 */
1265
    fpsrcop += ((CPU86_LDouble)m32i);
1266
    if ( ldub(seg+9) & 0x80 )
1267
        fpsrcop = -fpsrcop;
1268
    ST0 = fpsrcop;
1269
}
1270

    
1271
void OPPROTO op_fbld_ST0_A0(void)
1272
{
1273
    helper_fbld_ST0_A0();
1274
}
1275

    
1276
void helper_fbst_ST0_A0(void)
1277
{
1278
    CPU86_LDouble fptemp;
1279
    CPU86_LDouble fpsrcop;
1280
    int v;
1281
    uint8_t *mem_ref, *mem_end;
1282

    
1283
    fpsrcop = rint(ST0);
1284
    mem_ref = (uint8_t *)A0;
1285
    mem_end = mem_ref + 8;
1286
    if ( fpsrcop < 0.0 ) {
1287
        stw(mem_end, 0x8000);
1288
        fpsrcop = -fpsrcop;
1289
    } else {
1290
        stw(mem_end, 0x0000);
1291
    }
1292
    while (mem_ref < mem_end) {
1293
        if (fpsrcop == 0.0)
1294
            break;
1295
        fptemp = floor(fpsrcop/10.0);
1296
        v = ((int)(fpsrcop - fptemp*10.0));
1297
        if  (fptemp == 0.0)  { 
1298
            stb(mem_ref++, v); 
1299
            break; 
1300
        }
1301
        fpsrcop = fptemp;
1302
        fptemp = floor(fpsrcop/10.0);
1303
        v |= (((int)(fpsrcop - fptemp*10.0)) << 4);
1304
        stb(mem_ref++, v);
1305
        fpsrcop = fptemp;
1306
    }
1307
    while (mem_ref < mem_end) {
1308
        stb(mem_ref++, 0);
1309
    }
1310
}
1311

    
1312
void OPPROTO op_fbst_ST0_A0(void)
1313
{
1314
    helper_fbst_ST0_A0();
1315
}
1316

    
1317
/* FPU move */
1318

    
1319
static inline void fpush(void)
1320
{
1321
    env->fpstt = (env->fpstt - 1) & 7;
1322
    env->fptags[env->fpstt] = 0; /* validate stack entry */
1323
}
1324

    
1325
static inline void fpop(void)
1326
{
1327
    env->fptags[env->fpstt] = 1; /* invvalidate stack entry */
1328
    env->fpstt = (env->fpstt + 1) & 7;
1329
}
1330

    
1331
void OPPROTO op_fpush(void)
1332
{
1333
    fpush();
1334
}
1335

    
1336
void OPPROTO op_fpop(void)
1337
{
1338
    fpop();
1339
}
1340

    
1341
void OPPROTO op_fdecstp(void)
1342
{
1343
    env->fpstt = (env->fpstt - 1) & 7;
1344
    env->fpus &= (~0x4700);
1345
}
1346

    
1347
void OPPROTO op_fincstp(void)
1348
{
1349
    env->fpstt = (env->fpstt + 1) & 7;
1350
    env->fpus &= (~0x4700);
1351
}
1352

    
1353
void OPPROTO op_fmov_ST0_FT0(void)
1354
{
1355
    ST0 = FT0;
1356
}
1357

    
1358
void OPPROTO op_fmov_FT0_STN(void)
1359
{
1360
    FT0 = ST(PARAM1);
1361
}
1362

    
1363
void OPPROTO op_fmov_ST0_STN(void)
1364
{
1365
    ST0 = ST(PARAM1);
1366
}
1367

    
1368
void OPPROTO op_fmov_STN_ST0(void)
1369
{
1370
    ST(PARAM1) = ST0;
1371
}
1372

    
1373
void OPPROTO op_fxchg_ST0_STN(void)
1374
{
1375
    CPU86_LDouble tmp;
1376
    tmp = ST(PARAM1);
1377
    ST(PARAM1) = ST0;
1378
    ST0 = tmp;
1379
}
1380

    
1381
/* FPU operations */
1382

    
1383
/* XXX: handle nans */
1384
void OPPROTO op_fcom_ST0_FT0(void)
1385
{
1386
    env->fpus &= (~0x4500);        /* (C3,C2,C0) <-- 000 */
1387
    if (ST0 < FT0)
1388
        env->fpus |= 0x100;        /* (C3,C2,C0) <-- 001 */
1389
    else if (ST0 == FT0)
1390
        env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
1391
    FORCE_RET();
1392
}
1393

    
1394
/* XXX: handle nans */
1395
void OPPROTO op_fucom_ST0_FT0(void)
1396
{
1397
    env->fpus &= (~0x4500);        /* (C3,C2,C0) <-- 000 */
1398
    if (ST0 < FT0)
1399
        env->fpus |= 0x100;        /* (C3,C2,C0) <-- 001 */
1400
    else if (ST0 == FT0)
1401
        env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
1402
    FORCE_RET();
1403
}
1404

    
1405
void OPPROTO op_fadd_ST0_FT0(void)
1406
{
1407
    ST0 += FT0;
1408
}
1409

    
1410
void OPPROTO op_fmul_ST0_FT0(void)
1411
{
1412
    ST0 *= FT0;
1413
}
1414

    
1415
void OPPROTO op_fsub_ST0_FT0(void)
1416
{
1417
    ST0 -= FT0;
1418
}
1419

    
1420
void OPPROTO op_fsubr_ST0_FT0(void)
1421
{
1422
    ST0 = FT0 - ST0;
1423
}
1424

    
1425
void OPPROTO op_fdiv_ST0_FT0(void)
1426
{
1427
    ST0 /= FT0;
1428
}
1429

    
1430
void OPPROTO op_fdivr_ST0_FT0(void)
1431
{
1432
    ST0 = FT0 / ST0;
1433
}
1434

    
1435
/* fp operations between STN and ST0 */
1436

    
1437
void OPPROTO op_fadd_STN_ST0(void)
1438
{
1439
    ST(PARAM1) += ST0;
1440
}
1441

    
1442
void OPPROTO op_fmul_STN_ST0(void)
1443
{
1444
    ST(PARAM1) *= ST0;
1445
}
1446

    
1447
void OPPROTO op_fsub_STN_ST0(void)
1448
{
1449
    ST(PARAM1) -= ST0;
1450
}
1451

    
1452
void OPPROTO op_fsubr_STN_ST0(void)
1453
{
1454
    CPU86_LDouble *p;
1455
    p = &ST(PARAM1);
1456
    *p = ST0 - *p;
1457
}
1458

    
1459
void OPPROTO op_fdiv_STN_ST0(void)
1460
{
1461
    ST(PARAM1) /= ST0;
1462
}
1463

    
1464
void OPPROTO op_fdivr_STN_ST0(void)
1465
{
1466
    CPU86_LDouble *p;
1467
    p = &ST(PARAM1);
1468
    *p = ST0 / *p;
1469
}
1470

    
1471
/* misc FPU operations */
1472
void OPPROTO op_fchs_ST0(void)
1473
{
1474
    ST0 = -ST0;
1475
}
1476

    
1477
void OPPROTO op_fabs_ST0(void)
1478
{
1479
    ST0 = fabs(ST0);
1480
}
1481

    
1482
void helper_fxam_ST0(void)
1483
{
1484
    CPU86_LDoubleU temp;
1485
    int expdif;
1486

    
1487
    temp.d = ST0;
1488

    
1489
    env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
1490
    if (SIGND(temp))
1491
        env->fpus |= 0x200; /* C1 <-- 1 */
1492

    
1493
    expdif = EXPD(temp);
1494
    if (expdif == MAXEXPD) {
1495
        if (MANTD(temp) == 0)
1496
            env->fpus |=  0x500 /*Infinity*/;
1497
        else
1498
            env->fpus |=  0x100 /*NaN*/;
1499
    } else if (expdif == 0) {
1500
        if (MANTD(temp) == 0)
1501
            env->fpus |=  0x4000 /*Zero*/;
1502
        else
1503
            env->fpus |= 0x4400 /*Denormal*/;
1504
    } else {
1505
        env->fpus |= 0x400;
1506
    }
1507
}
1508

    
1509
void OPPROTO op_fxam_ST0(void)
1510
{
1511
    helper_fxam_ST0();
1512
}
1513

    
1514
void OPPROTO op_fld1_ST0(void)
1515
{
1516
    ST0 = *(CPU86_LDouble *)&f15rk[1];
1517
}
1518

    
1519
void OPPROTO op_fldl2t_ST0(void)
1520
{
1521
    ST0 = *(CPU86_LDouble *)&f15rk[6];
1522
}
1523

    
1524
void OPPROTO op_fldl2e_ST0(void)
1525
{
1526
    ST0 = *(CPU86_LDouble *)&f15rk[5];
1527
}
1528

    
1529
void OPPROTO op_fldpi_ST0(void)
1530
{
1531
    ST0 = *(CPU86_LDouble *)&f15rk[2];
1532
}
1533

    
1534
void OPPROTO op_fldlg2_ST0(void)
1535
{
1536
    ST0 = *(CPU86_LDouble *)&f15rk[3];
1537
}
1538

    
1539
void OPPROTO op_fldln2_ST0(void)
1540
{
1541
    ST0 = *(CPU86_LDouble *)&f15rk[4];
1542
}
1543

    
1544
void OPPROTO op_fldz_ST0(void)
1545
{
1546
    ST0 = *(CPU86_LDouble *)&f15rk[0];
1547
}
1548

    
1549
void OPPROTO op_fldz_FT0(void)
1550
{
1551
    ST0 = *(CPU86_LDouble *)&f15rk[0];
1552
}
1553

    
1554
void helper_f2xm1(void)
1555
{
1556
    ST0 = pow(2.0,ST0) - 1.0;
1557
}
1558

    
1559
void helper_fyl2x(void)
1560
{
1561
    CPU86_LDouble fptemp;
1562
    
1563
    fptemp = ST0;
1564
    if (fptemp>0.0){
1565
        fptemp = log(fptemp)/log(2.0);         /* log2(ST) */
1566
        ST1 *= fptemp;
1567
        fpop();
1568
    } else { 
1569
        env->fpus &= (~0x4700);
1570
        env->fpus |= 0x400;
1571
    }
1572
}
1573

    
1574
void helper_fptan(void)
1575
{
1576
    CPU86_LDouble fptemp;
1577

    
1578
    fptemp = ST0;
1579
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1580
        env->fpus |= 0x400;
1581
    } else {
1582
        ST0 = tan(fptemp);
1583
        fpush();
1584
        ST0 = 1.0;
1585
        env->fpus &= (~0x400);  /* C2 <-- 0 */
1586
        /* the above code is for  |arg| < 2**52 only */
1587
    }
1588
}
1589

    
1590
void helper_fpatan(void)
1591
{
1592
    CPU86_LDouble fptemp, fpsrcop;
1593

    
1594
    fpsrcop = ST1;
1595
    fptemp = ST0;
1596
    ST1 = atan2(fpsrcop,fptemp);
1597
    fpop();
1598
}
1599

    
1600
void helper_fxtract(void)
1601
{
1602
    CPU86_LDoubleU temp;
1603
    unsigned int expdif;
1604

    
1605
    temp.d = ST0;
1606
    expdif = EXPD(temp) - EXPBIAS;
1607
    /*DP exponent bias*/
1608
    ST0 = expdif;
1609
    fpush();
1610
    BIASEXPONENT(temp);
1611
    ST0 = temp.d;
1612
}
1613

    
1614
void helper_fprem1(void)
1615
{
1616
    CPU86_LDouble dblq, fpsrcop, fptemp;
1617
    CPU86_LDoubleU fpsrcop1, fptemp1;
1618
    int expdif;
1619
    int q;
1620

    
1621
    fpsrcop = ST0;
1622
    fptemp = ST1;
1623
    fpsrcop1.d = fpsrcop;
1624
    fptemp1.d = fptemp;
1625
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
1626
    if (expdif < 53) {
1627
        dblq = fpsrcop / fptemp;
1628
        dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
1629
        ST0 = fpsrcop - fptemp*dblq;
1630
        q = (int)dblq; /* cutting off top bits is assumed here */
1631
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1632
                                /* (C0,C1,C3) <-- (q2,q1,q0) */
1633
        env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
1634
        env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
1635
        env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
1636
    } else {
1637
        env->fpus |= 0x400;  /* C2 <-- 1 */
1638
        fptemp = pow(2.0, expdif-50);
1639
        fpsrcop = (ST0 / ST1) / fptemp;
1640
        /* fpsrcop = integer obtained by rounding to the nearest */
1641
        fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
1642
            floor(fpsrcop): ceil(fpsrcop);
1643
        ST0 -= (ST1 * fpsrcop * fptemp);
1644
    }
1645
}
1646

    
1647
void helper_fprem(void)
1648
{
1649
    CPU86_LDouble dblq, fpsrcop, fptemp;
1650
    CPU86_LDoubleU fpsrcop1, fptemp1;
1651
    int expdif;
1652
    int q;
1653
    
1654
    fpsrcop = ST0;
1655
    fptemp = ST1;
1656
    fpsrcop1.d = fpsrcop;
1657
    fptemp1.d = fptemp;
1658
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
1659
    if ( expdif < 53 ) {
1660
        dblq = fpsrcop / fptemp;
1661
        dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
1662
        ST0 = fpsrcop - fptemp*dblq;
1663
        q = (int)dblq; /* cutting off top bits is assumed here */
1664
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1665
                                /* (C0,C1,C3) <-- (q2,q1,q0) */
1666
        env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
1667
        env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
1668
        env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
1669
    } else {
1670
        env->fpus |= 0x400;  /* C2 <-- 1 */
1671
        fptemp = pow(2.0, expdif-50);
1672
        fpsrcop = (ST0 / ST1) / fptemp;
1673
        /* fpsrcop = integer obtained by chopping */
1674
        fpsrcop = (fpsrcop < 0.0)?
1675
            -(floor(fabs(fpsrcop))): floor(fpsrcop);
1676
        ST0 -= (ST1 * fpsrcop * fptemp);
1677
    }
1678
}
1679

    
1680
void helper_fyl2xp1(void)
1681
{
1682
    CPU86_LDouble fptemp;
1683

    
1684
    fptemp = ST0;
1685
    if ((fptemp+1.0)>0.0) {
1686
        fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
1687
        ST1 *= fptemp;
1688
        fpop();
1689
    } else { 
1690
        env->fpus &= (~0x4700);
1691
        env->fpus |= 0x400;
1692
    }
1693
}
1694

    
1695
void helper_fsqrt(void)
1696
{
1697
    CPU86_LDouble fptemp;
1698

    
1699
    fptemp = ST0;
1700
    if (fptemp<0.0) { 
1701
        env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
1702
        env->fpus |= 0x400;
1703
    }
1704
    ST0 = sqrt(fptemp);
1705
}
1706

    
1707
void helper_fsincos(void)
1708
{
1709
    CPU86_LDouble fptemp;
1710

    
1711
    fptemp = ST0;
1712
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1713
        env->fpus |= 0x400;
1714
    } else {
1715
        ST0 = sin(fptemp);
1716
        fpush();
1717
        ST0 = cos(fptemp);
1718
        env->fpus &= (~0x400);  /* C2 <-- 0 */
1719
        /* the above code is for  |arg| < 2**63 only */
1720
    }
1721
}
1722

    
1723
void helper_frndint(void)
1724
{
1725
    ST0 = rint(ST0);
1726
}
1727

    
1728
void helper_fscale(void)
1729
{
1730
    CPU86_LDouble fpsrcop, fptemp;
1731

    
1732
    fpsrcop = 2.0;
1733
    fptemp = pow(fpsrcop,ST1);
1734
    ST0 *= fptemp;
1735
}
1736

    
1737
void helper_fsin(void)
1738
{
1739
    CPU86_LDouble fptemp;
1740

    
1741
    fptemp = ST0;
1742
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1743
        env->fpus |= 0x400;
1744
    } else {
1745
        ST0 = sin(fptemp);
1746
        env->fpus &= (~0x400);  /* C2 <-- 0 */
1747
        /* the above code is for  |arg| < 2**53 only */
1748
    }
1749
}
1750

    
1751
void helper_fcos(void)
1752
{
1753
    CPU86_LDouble fptemp;
1754

    
1755
    fptemp = ST0;
1756
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1757
        env->fpus |= 0x400;
1758
    } else {
1759
        ST0 = cos(fptemp);
1760
        env->fpus &= (~0x400);  /* C2 <-- 0 */
1761
        /* the above code is for  |arg5 < 2**63 only */
1762
    }
1763
}
1764

    
1765
/* associated heplers to reduce generated code length and to simplify
1766
   relocation (FP constants are usually stored in .rodata section) */
1767

    
1768
void OPPROTO op_f2xm1(void)
1769
{
1770
    helper_f2xm1();
1771
}
1772

    
1773
void OPPROTO op_fyl2x(void)
1774
{
1775
    helper_fyl2x();
1776
}
1777

    
1778
void OPPROTO op_fptan(void)
1779
{
1780
    helper_fptan();
1781
}
1782

    
1783
void OPPROTO op_fpatan(void)
1784
{
1785
    helper_fpatan();
1786
}
1787

    
1788
void OPPROTO op_fxtract(void)
1789
{
1790
    helper_fxtract();
1791
}
1792

    
1793
void OPPROTO op_fprem1(void)
1794
{
1795
    helper_fprem1();
1796
}
1797

    
1798

    
1799
void OPPROTO op_fprem(void)
1800
{
1801
    helper_fprem();
1802
}
1803

    
1804
void OPPROTO op_fyl2xp1(void)
1805
{
1806
    helper_fyl2xp1();
1807
}
1808

    
1809
void OPPROTO op_fsqrt(void)
1810
{
1811
    helper_fsqrt();
1812
}
1813

    
1814
void OPPROTO op_fsincos(void)
1815
{
1816
    helper_fsincos();
1817
}
1818

    
1819
void OPPROTO op_frndint(void)
1820
{
1821
    helper_frndint();
1822
}
1823

    
1824
void OPPROTO op_fscale(void)
1825
{
1826
    helper_fscale();
1827
}
1828

    
1829
void OPPROTO op_fsin(void)
1830
{
1831
    helper_fsin();
1832
}
1833

    
1834
void OPPROTO op_fcos(void)
1835
{
1836
    helper_fcos();
1837
}
1838

    
1839
void OPPROTO op_fnstsw_A0(void)
1840
{
1841
    int fpus;
1842
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
1843
    stw((void *)A0, fpus);
1844
}
1845

    
1846
void OPPROTO op_fnstsw_EAX(void)
1847
{
1848
    int fpus;
1849
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
1850
    EAX = (EAX & 0xffff0000) | fpus;
1851
}
1852

    
1853
void OPPROTO op_fnstcw_A0(void)
1854
{
1855
    stw((void *)A0, env->fpuc);
1856
}
1857

    
1858
void OPPROTO op_fldcw_A0(void)
1859
{
1860
    int rnd_type;
1861
    env->fpuc = lduw((void *)A0);
1862
    /* set rounding mode */
1863
    switch(env->fpuc & RC_MASK) {
1864
    default:
1865
    case RC_NEAR:
1866
        rnd_type = FE_TONEAREST;
1867
        break;
1868
    case RC_DOWN:
1869
        rnd_type = FE_DOWNWARD;
1870
        break;
1871
    case RC_UP:
1872
        rnd_type = FE_UPWARD;
1873
        break;
1874
    case RC_CHOP:
1875
        rnd_type = FE_TOWARDZERO;
1876
        break;
1877
    }
1878
    fesetround(rnd_type);
1879
}
1880

    
1881
/* main execution loop */
1882
uint8_t code_gen_buffer[65536];
1883

    
1884
#ifdef DEBUG_EXEC
1885
static const char *cc_op_str[] = {
1886
    "DYNAMIC",
1887
    "EFLAGS",
1888
    "MUL",
1889
    "ADDB",
1890
    "ADDW",
1891
    "ADDL",
1892
    "ADCB",
1893
    "ADCW",
1894
    "ADCL",
1895
    "SUBB",
1896
    "SUBW",
1897
    "SUBL",
1898
    "SBBB",
1899
    "SBBW",
1900
    "SBBL",
1901
    "LOGICB",
1902
    "LOGICW",
1903
    "LOGICL",
1904
    "INCB",
1905
    "INCW",
1906
    "INCL",
1907
    "DECB",
1908
    "DECW",
1909
    "DECL",
1910
    "SHLB",
1911
    "SHLW",
1912
    "SHLL",
1913
    "SARB",
1914
    "SARW",
1915
    "SARL",
1916
};
1917
#endif
1918

    
1919
int cpu_x86_exec(CPUX86State *env1)
1920
{
1921
    int saved_T0, saved_T1, saved_A0;
1922
    CPUX86State *saved_env;
1923
    int code_gen_size, ret;
1924
    void (*gen_func)(void);
1925

    
1926
    /* first we save global registers */
1927
    saved_T0 = T0;
1928
    saved_T1 = T1;
1929
    saved_A0 = A0;
1930
    saved_env = env;
1931
    env = env1;
1932
    
1933
    /* prepare setjmp context for exception handling */
1934
    if (setjmp(env->jmp_env) == 0) {
1935
        for(;;) {
1936
#ifdef DEBUG_EXEC
1937
            if (loglevel) {
1938
                int eflags;
1939
                eflags = cc_table[CC_OP].compute_all();
1940
                eflags |= (DF & DIRECTION_FLAG);
1941
                fprintf(logfile, 
1942
                        "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n"
1943
                        "ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n"
1944
                        "CCS=%08x CCD=%08x CCO=%-8s EFL=%c%c%c%c%c%c%c\n",
1945
                        env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 
1946
                        env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 
1947
                        env->cc_src, env->cc_dst, cc_op_str[env->cc_op],
1948
                        eflags & DIRECTION_FLAG ? 'D' : '-',
1949
                        eflags & CC_O ? 'O' : '-',
1950
                        eflags & CC_S ? 'S' : '-',
1951
                        eflags & CC_Z ? 'Z' : '-',
1952
                        eflags & CC_A ? 'A' : '-',
1953
                        eflags & CC_P ? 'P' : '-',
1954
                        eflags & CC_C ? 'C' : '-'
1955
                        );
1956
#if 1
1957
                fprintf(logfile, "ST0=%f ST1=%f ST2=%f ST3=%f\n", 
1958
                        (double)ST0, (double)ST1, (double)ST(2), (double)ST(3));
1959
#endif
1960
            }
1961
#endif
1962
            cpu_x86_gen_code(code_gen_buffer, sizeof(code_gen_buffer), 
1963
                             &code_gen_size, (uint8_t *)env->pc);
1964
            /* execute the generated code */
1965
            gen_func = (void *)code_gen_buffer;
1966
            gen_func();
1967
        }
1968
    }
1969
    ret = env->exception_index;
1970

    
1971
    /* restore global registers */
1972
    T0 = saved_T0;
1973
    T1 = saved_T1;
1974
    A0 = saved_A0;
1975
    env = saved_env;
1976
    return ret;
1977
}