Statistics
| Branch: | Revision:

root / op-i386.c @ 7d13299d

History | View | Annotate | Download (34.4 kB)

1
/*
2
 *  i386 micro operations
3
 * 
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, write to the Free Software
18
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
 */
20
#include "exec-i386.h"
21

    
22
/* NOTE: data are not static to force relocation generation by GCC */
23

    
24
uint8_t parity_table[256] = {
25
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
26
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
27
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
28
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
29
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
30
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
31
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
32
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
33
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
34
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
35
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
36
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
37
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
38
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
39
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
40
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
41
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
42
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
43
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
44
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
45
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
46
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
47
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
48
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
49
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
50
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
51
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
52
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
53
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
54
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
55
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
56
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
57
};
58

    
59
/* modulo 17 table */
60
const uint8_t rclw_table[32] = {
61
    0, 1, 2, 3, 4, 5, 6, 7, 
62
    8, 9,10,11,12,13,14,15,
63
   16, 0, 1, 2, 3, 4, 5, 6,
64
    7, 8, 9,10,11,12,13,14,
65
};
66

    
67
/* modulo 9 table */
68
const uint8_t rclb_table[32] = {
69
    0, 1, 2, 3, 4, 5, 6, 7, 
70
    8, 0, 1, 2, 3, 4, 5, 6,
71
    7, 8, 0, 1, 2, 3, 4, 5, 
72
    6, 7, 8, 0, 1, 2, 3, 4,
73
};
74

    
75
#ifdef USE_X86LDOUBLE
76
/* an array of Intel 80-bit FP constants, to be loaded via integer ops */
77
typedef unsigned short f15ld[5];
78
const f15ld f15rk[] =
79
{
80
/*0*/        {0x0000,0x0000,0x0000,0x0000,0x0000},
81
/*1*/        {0x0000,0x0000,0x0000,0x8000,0x3fff},
82
/*pi*/        {0xc235,0x2168,0xdaa2,0xc90f,0x4000},
83
/*lg2*/        {0xf799,0xfbcf,0x9a84,0x9a20,0x3ffd},
84
/*ln2*/        {0x79ac,0xd1cf,0x17f7,0xb172,0x3ffe},
85
/*l2e*/        {0xf0bc,0x5c17,0x3b29,0xb8aa,0x3fff},
86
/*l2t*/        {0x8afe,0xcd1b,0x784b,0xd49a,0x4000}
87
};
88
#else
89
/* the same, 64-bit version */
90
typedef unsigned short f15ld[4];
91
const f15ld f15rk[] =
92
{
93
#ifndef WORDS_BIGENDIAN
94
/*0*/        {0x0000,0x0000,0x0000,0x0000},
95
/*1*/        {0x0000,0x0000,0x0000,0x3ff0},
96
/*pi*/        {0x2d18,0x5444,0x21fb,0x4009},
97
/*lg2*/        {0x79ff,0x509f,0x4413,0x3fd3},
98
/*ln2*/        {0x39ef,0xfefa,0x2e42,0x3fe6},
99
/*l2e*/        {0x82fe,0x652b,0x1547,0x3ff7},
100
/*l2t*/        {0xa371,0x0979,0x934f,0x400a}
101
#else
102
/*0*/   {0x0000,0x0000,0x0000,0x0000},
103
/*1*/   {0x3ff0,0x0000,0x0000,0x0000},
104
/*pi*/  {0x4009,0x21fb,0x5444,0x2d18},
105
/*lg2*/        {0x3fd3,0x4413,0x509f,0x79ff},
106
/*ln2*/        {0x3fe6,0x2e42,0xfefa,0x39ef},
107
/*l2e*/        {0x3ff7,0x1547,0x652b,0x82fe},
108
/*l2t*/        {0x400a,0x934f,0x0979,0xa371}
109
#endif
110
};
111
#endif
112
    
113
/* n must be a constant to be efficient */
114
static inline int lshift(int x, int n)
115
{
116
    if (n >= 0)
117
        return x << n;
118
    else
119
        return x >> (-n);
120
}
121

    
122
/* exception support */
123
/* NOTE: not static to force relocation generation by GCC */
124
void raise_exception(int exception_index)
125
{
126
    env->exception_index = exception_index;
127
    longjmp(env->jmp_env, 1);
128
}
129

    
130
/* we define the various pieces of code used by the JIT */
131

    
132
#define REG EAX
133
#define REGNAME _EAX
134
#include "opreg_template.h"
135
#undef REG
136
#undef REGNAME
137

    
138
#define REG ECX
139
#define REGNAME _ECX
140
#include "opreg_template.h"
141
#undef REG
142
#undef REGNAME
143

    
144
#define REG EDX
145
#define REGNAME _EDX
146
#include "opreg_template.h"
147
#undef REG
148
#undef REGNAME
149

    
150
#define REG EBX
151
#define REGNAME _EBX
152
#include "opreg_template.h"
153
#undef REG
154
#undef REGNAME
155

    
156
#define REG ESP
157
#define REGNAME _ESP
158
#include "opreg_template.h"
159
#undef REG
160
#undef REGNAME
161

    
162
#define REG EBP
163
#define REGNAME _EBP
164
#include "opreg_template.h"
165
#undef REG
166
#undef REGNAME
167

    
168
#define REG ESI
169
#define REGNAME _ESI
170
#include "opreg_template.h"
171
#undef REG
172
#undef REGNAME
173

    
174
#define REG EDI
175
#define REGNAME _EDI
176
#include "opreg_template.h"
177
#undef REG
178
#undef REGNAME
179

    
180
/* operations */
181

    
182
void OPPROTO op_addl_T0_T1_cc(void)
183
{
184
    CC_SRC = T0;
185
    T0 += T1;
186
    CC_DST = T0;
187
}
188

    
189
void OPPROTO op_orl_T0_T1_cc(void)
190
{
191
    T0 |= T1;
192
    CC_DST = T0;
193
}
194

    
195
void OPPROTO op_andl_T0_T1_cc(void)
196
{
197
    T0 &= T1;
198
    CC_DST = T0;
199
}
200

    
201
void OPPROTO op_subl_T0_T1_cc(void)
202
{
203
    CC_SRC = T0;
204
    T0 -= T1;
205
    CC_DST = T0;
206
}
207

    
208
void OPPROTO op_xorl_T0_T1_cc(void)
209
{
210
    T0 ^= T1;
211
    CC_DST = T0;
212
}
213

    
214
void OPPROTO op_cmpl_T0_T1_cc(void)
215
{
216
    CC_SRC = T0;
217
    CC_DST = T0 - T1;
218
}
219

    
220
void OPPROTO op_notl_T0(void)
221
{
222
    T0 = ~T0;
223
}
224

    
225
void OPPROTO op_negl_T0_cc(void)
226
{
227
    CC_SRC = 0;
228
    T0 = -T0;
229
    CC_DST = T0;
230
}
231

    
232
void OPPROTO op_incl_T0_cc(void)
233
{
234
    CC_SRC = cc_table[CC_OP].compute_c();
235
    T0++;
236
    CC_DST = T0;
237
}
238

    
239
void OPPROTO op_decl_T0_cc(void)
240
{
241
    CC_SRC = cc_table[CC_OP].compute_c();
242
    T0--;
243
    CC_DST = T0;
244
}
245

    
246
void OPPROTO op_testl_T0_T1_cc(void)
247
{
248
    CC_DST = T0 & T1;
249
}
250

    
251
void OPPROTO op_bswapl_T0(void)
252
{
253
    T0 = bswap32(T0);
254
}
255

    
256
/* multiply/divide */
257
void OPPROTO op_mulb_AL_T0(void)
258
{
259
    unsigned int res;
260
    res = (uint8_t)EAX * (uint8_t)T0;
261
    EAX = (EAX & 0xffff0000) | res;
262
    CC_SRC = (res & 0xff00);
263
}
264

    
265
void OPPROTO op_imulb_AL_T0(void)
266
{
267
    int res;
268
    res = (int8_t)EAX * (int8_t)T0;
269
    EAX = (EAX & 0xffff0000) | (res & 0xffff);
270
    CC_SRC = (res != (int8_t)res);
271
}
272

    
273
void OPPROTO op_mulw_AX_T0(void)
274
{
275
    unsigned int res;
276
    res = (uint16_t)EAX * (uint16_t)T0;
277
    EAX = (EAX & 0xffff0000) | (res & 0xffff);
278
    EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff);
279
    CC_SRC = res >> 16;
280
}
281

    
282
void OPPROTO op_imulw_AX_T0(void)
283
{
284
    int res;
285
    res = (int16_t)EAX * (int16_t)T0;
286
    EAX = (EAX & 0xffff0000) | (res & 0xffff);
287
    EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff);
288
    CC_SRC = (res != (int16_t)res);
289
}
290

    
291
void OPPROTO op_mull_EAX_T0(void)
292
{
293
    uint64_t res;
294
    res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0);
295
    EAX = res;
296
    EDX = res >> 32;
297
    CC_SRC = res >> 32;
298
}
299

    
300
void OPPROTO op_imull_EAX_T0(void)
301
{
302
    int64_t res;
303
    res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T0);
304
    EAX = res;
305
    EDX = res >> 32;
306
    CC_SRC = (res != (int32_t)res);
307
}
308

    
309
void OPPROTO op_imulw_T0_T1(void)
310
{
311
    int res;
312
    res = (int16_t)T0 * (int16_t)T1;
313
    T0 = res;
314
    CC_SRC = (res != (int16_t)res);
315
}
316

    
317
void OPPROTO op_imull_T0_T1(void)
318
{
319
    int64_t res;
320
    res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
321
    T0 = res;
322
    CC_SRC = (res != (int32_t)res);
323
}
324

    
325
/* division, flags are undefined */
326
/* XXX: add exceptions for overflow & div by zero */
327
void OPPROTO op_divb_AL_T0(void)
328
{
329
    unsigned int num, den, q, r;
330

    
331
    num = (EAX & 0xffff);
332
    den = (T0 & 0xff);
333
    q = (num / den) & 0xff;
334
    r = (num % den) & 0xff;
335
    EAX = (EAX & 0xffff0000) | (r << 8) | q;
336
}
337

    
338
void OPPROTO op_idivb_AL_T0(void)
339
{
340
    int num, den, q, r;
341

    
342
    num = (int16_t)EAX;
343
    den = (int8_t)T0;
344
    q = (num / den) & 0xff;
345
    r = (num % den) & 0xff;
346
    EAX = (EAX & 0xffff0000) | (r << 8) | q;
347
}
348

    
349
void OPPROTO op_divw_AX_T0(void)
350
{
351
    unsigned int num, den, q, r;
352

    
353
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
354
    den = (T0 & 0xffff);
355
    q = (num / den) & 0xffff;
356
    r = (num % den) & 0xffff;
357
    EAX = (EAX & 0xffff0000) | q;
358
    EDX = (EDX & 0xffff0000) | r;
359
}
360

    
361
void OPPROTO op_idivw_AX_T0(void)
362
{
363
    int num, den, q, r;
364

    
365
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
366
    den = (int16_t)T0;
367
    q = (num / den) & 0xffff;
368
    r = (num % den) & 0xffff;
369
    EAX = (EAX & 0xffff0000) | q;
370
    EDX = (EDX & 0xffff0000) | r;
371
}
372

    
373
void OPPROTO op_divl_EAX_T0(void)
374
{
375
    unsigned int den, q, r;
376
    uint64_t num;
377
    
378
    num = EAX | ((uint64_t)EDX << 32);
379
    den = T0;
380
    q = (num / den);
381
    r = (num % den);
382
    EAX = q;
383
    EDX = r;
384
}
385

    
386
void OPPROTO op_idivl_EAX_T0(void)
387
{
388
    int den, q, r;
389
    int64_t num;
390
    
391
    num = EAX | ((uint64_t)EDX << 32);
392
    den = T0;
393
    q = (num / den);
394
    r = (num % den);
395
    EAX = q;
396
    EDX = r;
397
}
398

    
399
/* constant load */
400

    
401
void OPPROTO op_movl_T0_im(void)
402
{
403
    T0 = PARAM1;
404
}
405

    
406
void OPPROTO op_movl_T1_im(void)
407
{
408
    T1 = PARAM1;
409
}
410

    
411
void OPPROTO op_movl_A0_im(void)
412
{
413
    A0 = PARAM1;
414
}
415

    
416
void OPPROTO op_addl_A0_im(void)
417
{
418
    A0 += PARAM1;
419
}
420

    
421
void OPPROTO op_andl_A0_ffff(void)
422
{
423
    A0 = A0 & 0xffff;
424
}
425

    
426
/* memory access */
427

    
428
void OPPROTO op_ldub_T0_A0(void)
429
{
430
    T0 = ldub((uint8_t *)A0);
431
}
432

    
433
void OPPROTO op_ldsb_T0_A0(void)
434
{
435
    T0 = ldsb((int8_t *)A0);
436
}
437

    
438
void OPPROTO op_lduw_T0_A0(void)
439
{
440
    T0 = lduw((uint8_t *)A0);
441
}
442

    
443
void OPPROTO op_ldsw_T0_A0(void)
444
{
445
    T0 = ldsw((int8_t *)A0);
446
}
447

    
448
void OPPROTO op_ldl_T0_A0(void)
449
{
450
    T0 = ldl((uint8_t *)A0);
451
}
452

    
453
void OPPROTO op_ldub_T1_A0(void)
454
{
455
    T1 = ldub((uint8_t *)A0);
456
}
457

    
458
void OPPROTO op_ldsb_T1_A0(void)
459
{
460
    T1 = ldsb((int8_t *)A0);
461
}
462

    
463
void OPPROTO op_lduw_T1_A0(void)
464
{
465
    T1 = lduw((uint8_t *)A0);
466
}
467

    
468
void OPPROTO op_ldsw_T1_A0(void)
469
{
470
    T1 = ldsw((int8_t *)A0);
471
}
472

    
473
void OPPROTO op_ldl_T1_A0(void)
474
{
475
    T1 = ldl((uint8_t *)A0);
476
}
477

    
478
void OPPROTO op_stb_T0_A0(void)
479
{
480
    stb((uint8_t *)A0, T0);
481
}
482

    
483
void OPPROTO op_stw_T0_A0(void)
484
{
485
    stw((uint8_t *)A0, T0);
486
}
487

    
488
void OPPROTO op_stl_T0_A0(void)
489
{
490
    stl((uint8_t *)A0, T0);
491
}
492

    
493
/* used for bit operations */
494

    
495
void OPPROTO op_add_bitw_A0_T1(void)
496
{
497
    A0 += ((int32_t)T1 >> 4) << 1;
498
}
499

    
500
void OPPROTO op_add_bitl_A0_T1(void)
501
{
502
    A0 += ((int32_t)T1 >> 5) << 2;
503
}
504

    
505
/* indirect jump */
506

    
507
void OPPROTO op_jmp_T0(void)
508
{
509
    PC = T0;
510
}
511

    
512
void OPPROTO op_jmp_im(void)
513
{
514
    PC = PARAM1;
515
}
516

    
517
void OPPROTO op_int_im(void)
518
{
519
    PC = PARAM1;
520
    raise_exception(EXCP0D_GPF);
521
}
522

    
523
void OPPROTO op_int3(void)
524
{
525
    PC = PARAM1;
526
    raise_exception(EXCP03_INT3);
527
}
528

    
529
void OPPROTO op_into(void)
530
{
531
    int eflags;
532
    eflags = cc_table[CC_OP].compute_all();
533
    if (eflags & CC_O) {
534
        PC = PARAM1;
535
        raise_exception(EXCP04_INTO);
536
    } else {
537
        PC = PARAM2;
538
    }
539
}
540

    
541
/* string ops */
542

    
543
#define ldul ldl
544

    
545
#define SHIFT 0
546
#include "ops_template.h"
547
#undef SHIFT
548

    
549
#define SHIFT 1
550
#include "ops_template.h"
551
#undef SHIFT
552

    
553
#define SHIFT 2
554
#include "ops_template.h"
555
#undef SHIFT
556

    
557
/* sign extend */
558

    
559
void OPPROTO op_movsbl_T0_T0(void)
560
{
561
    T0 = (int8_t)T0;
562
}
563

    
564
void OPPROTO op_movzbl_T0_T0(void)
565
{
566
    T0 = (uint8_t)T0;
567
}
568

    
569
void OPPROTO op_movswl_T0_T0(void)
570
{
571
    T0 = (int16_t)T0;
572
}
573

    
574
void OPPROTO op_movzwl_T0_T0(void)
575
{
576
    T0 = (uint16_t)T0;
577
}
578

    
579
void OPPROTO op_movswl_EAX_AX(void)
580
{
581
    EAX = (int16_t)EAX;
582
}
583

    
584
void OPPROTO op_movsbw_AX_AL(void)
585
{
586
    EAX = (EAX & 0xffff0000) | ((int8_t)EAX & 0xffff);
587
}
588

    
589
void OPPROTO op_movslq_EDX_EAX(void)
590
{
591
    EDX = (int32_t)EAX >> 31;
592
}
593

    
594
void OPPROTO op_movswl_DX_AX(void)
595
{
596
    EDX = (EDX & 0xffff0000) | (((int16_t)EAX >> 15) & 0xffff);
597
}
598

    
599
/* push/pop */
600
/* XXX: add 16 bit operand/16 bit seg variants */
601

    
602
void op_pushl_T0(void)
603
{
604
    uint32_t offset;
605
    offset = ESP - 4;
606
    stl((void *)offset, T0);
607
    /* modify ESP after to handle exceptions correctly */
608
    ESP = offset;
609
}
610

    
611
void op_pushl_T1(void)
612
{
613
    uint32_t offset;
614
    offset = ESP - 4;
615
    stl((void *)offset, T1);
616
    /* modify ESP after to handle exceptions correctly */
617
    ESP = offset;
618
}
619

    
620
void op_popl_T0(void)
621
{
622
    T0 = ldl((void *)ESP);
623
    ESP += 4;
624
}
625

    
626
void op_addl_ESP_im(void)
627
{
628
    ESP += PARAM1;
629
}
630

    
631
/* flags handling */
632

    
633
/* slow jumps cases (compute x86 flags) */
634
void OPPROTO op_jo_cc(void)
635
{
636
    int eflags;
637
    eflags = cc_table[CC_OP].compute_all();
638
    if (eflags & CC_O)
639
        PC = PARAM1;
640
    else
641
        PC = PARAM2;
642
    FORCE_RET();
643
}
644

    
645
void OPPROTO op_jb_cc(void)
646
{
647
    if (cc_table[CC_OP].compute_c())
648
        PC = PARAM1;
649
    else
650
        PC = PARAM2;
651
    FORCE_RET();
652
}
653

    
654
void OPPROTO op_jz_cc(void)
655
{
656
    int eflags;
657
    eflags = cc_table[CC_OP].compute_all();
658
    if (eflags & CC_Z)
659
        PC = PARAM1;
660
    else
661
        PC = PARAM2;
662
    FORCE_RET();
663
}
664

    
665
void OPPROTO op_jbe_cc(void)
666
{
667
    int eflags;
668
    eflags = cc_table[CC_OP].compute_all();
669
    if (eflags & (CC_Z | CC_C))
670
        PC = PARAM1;
671
    else
672
        PC = PARAM2;
673
    FORCE_RET();
674
}
675

    
676
void OPPROTO op_js_cc(void)
677
{
678
    int eflags;
679
    eflags = cc_table[CC_OP].compute_all();
680
    if (eflags & CC_S)
681
        PC = PARAM1;
682
    else
683
        PC = PARAM2;
684
    FORCE_RET();
685
}
686

    
687
void OPPROTO op_jp_cc(void)
688
{
689
    int eflags;
690
    eflags = cc_table[CC_OP].compute_all();
691
    if (eflags & CC_P)
692
        PC = PARAM1;
693
    else
694
        PC = PARAM2;
695
    FORCE_RET();
696
}
697

    
698
void OPPROTO op_jl_cc(void)
699
{
700
    int eflags;
701
    eflags = cc_table[CC_OP].compute_all();
702
    if ((eflags ^ (eflags >> 4)) & 0x80)
703
        PC = PARAM1;
704
    else
705
        PC = PARAM2;
706
    FORCE_RET();
707
}
708

    
709
void OPPROTO op_jle_cc(void)
710
{
711
    int eflags;
712
    eflags = cc_table[CC_OP].compute_all();
713
    if (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z))
714
        PC = PARAM1;
715
    else
716
        PC = PARAM2;
717
    FORCE_RET();
718
}
719

    
720
/* slow set cases (compute x86 flags) */
721
void OPPROTO op_seto_T0_cc(void)
722
{
723
    int eflags;
724
    eflags = cc_table[CC_OP].compute_all();
725
    T0 = (eflags >> 11) & 1;
726
}
727

    
728
void OPPROTO op_setb_T0_cc(void)
729
{
730
    T0 = cc_table[CC_OP].compute_c();
731
}
732

    
733
void OPPROTO op_setz_T0_cc(void)
734
{
735
    int eflags;
736
    eflags = cc_table[CC_OP].compute_all();
737
    T0 = (eflags >> 6) & 1;
738
}
739

    
740
void OPPROTO op_setbe_T0_cc(void)
741
{
742
    int eflags;
743
    eflags = cc_table[CC_OP].compute_all();
744
    T0 = (eflags & (CC_Z | CC_C)) != 0;
745
}
746

    
747
void OPPROTO op_sets_T0_cc(void)
748
{
749
    int eflags;
750
    eflags = cc_table[CC_OP].compute_all();
751
    T0 = (eflags >> 7) & 1;
752
}
753

    
754
void OPPROTO op_setp_T0_cc(void)
755
{
756
    int eflags;
757
    eflags = cc_table[CC_OP].compute_all();
758
    T0 = (eflags >> 2) & 1;
759
}
760

    
761
void OPPROTO op_setl_T0_cc(void)
762
{
763
    int eflags;
764
    eflags = cc_table[CC_OP].compute_all();
765
    T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
766
}
767

    
768
void OPPROTO op_setle_T0_cc(void)
769
{
770
    int eflags;
771
    eflags = cc_table[CC_OP].compute_all();
772
    T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
773
}
774

    
775
void OPPROTO op_xor_T0_1(void)
776
{
777
    T0 ^= 1;
778
}
779

    
780
void OPPROTO op_set_cc_op(void)
781
{
782
    CC_OP = PARAM1;
783
}
784

    
785
void OPPROTO op_movl_eflags_T0(void)
786
{
787
    CC_SRC = T0;
788
    DF = 1 - (2 * ((T0 >> 10) & 1));
789
}
790

    
791
/* XXX: compute only O flag */
792
void OPPROTO op_movb_eflags_T0(void)
793
{
794
    int of;
795
    of = cc_table[CC_OP].compute_all() & CC_O;
796
    CC_SRC = T0 | of;
797
}
798

    
799
void OPPROTO op_movl_T0_eflags(void)
800
{
801
    T0 = cc_table[CC_OP].compute_all();
802
    T0 |= (DF & DIRECTION_FLAG);
803
}
804

    
805
void OPPROTO op_cld(void)
806
{
807
    DF = 1;
808
}
809

    
810
void OPPROTO op_std(void)
811
{
812
    DF = -1;
813
}
814

    
815
void OPPROTO op_clc(void)
816
{
817
    int eflags;
818
    eflags = cc_table[CC_OP].compute_all();
819
    eflags &= ~CC_C;
820
    CC_SRC = eflags;
821
}
822

    
823
void OPPROTO op_stc(void)
824
{
825
    int eflags;
826
    eflags = cc_table[CC_OP].compute_all();
827
    eflags |= CC_C;
828
    CC_SRC = eflags;
829
}
830

    
831
void OPPROTO op_cmc(void)
832
{
833
    int eflags;
834
    eflags = cc_table[CC_OP].compute_all();
835
    eflags ^= CC_C;
836
    CC_SRC = eflags;
837
}
838

    
839
static int compute_all_eflags(void)
840
{
841
    return CC_SRC;
842
}
843

    
844
static int compute_c_eflags(void)
845
{
846
    return CC_SRC & CC_C;
847
}
848

    
849
static int compute_c_mul(void)
850
{
851
    int cf;
852
    cf = (CC_SRC != 0);
853
    return cf;
854
}
855

    
856
static int compute_all_mul(void)
857
{
858
    int cf, pf, af, zf, sf, of;
859
    cf = (CC_SRC != 0);
860
    pf = 0; /* undefined */
861
    af = 0; /* undefined */
862
    zf = 0; /* undefined */
863
    sf = 0; /* undefined */
864
    of = cf << 11;
865
    return cf | pf | af | zf | sf | of;
866
}
867
    
868
CCTable cc_table[CC_OP_NB] = {
869
    [CC_OP_DYNAMIC] = { /* should never happen */ },
870

    
871
    [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
872

    
873
    [CC_OP_MUL] = { compute_all_mul, compute_c_mul },
874

    
875
    [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
876
    [CC_OP_ADDW] = { compute_all_addw, compute_c_addw  },
877
    [CC_OP_ADDL] = { compute_all_addl, compute_c_addl  },
878

    
879
    [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
880
    [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw  },
881
    [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl  },
882

    
883
    [CC_OP_SUBB] = { compute_all_subb, compute_c_subb  },
884
    [CC_OP_SUBW] = { compute_all_subw, compute_c_subw  },
885
    [CC_OP_SUBL] = { compute_all_subl, compute_c_subl  },
886
    
887
    [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb  },
888
    [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw  },
889
    [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl  },
890
    
891
    [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
892
    [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
893
    [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
894
    
895
    [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
896
    [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
897
    [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
898
    
899
    [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
900
    [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
901
    [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
902
    
903
    [CC_OP_SHLB] = { compute_all_shlb, compute_c_shll },
904
    [CC_OP_SHLW] = { compute_all_shlw, compute_c_shll },
905
    [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
906

    
907
    [CC_OP_SARB] = { compute_all_sarb, compute_c_shll },
908
    [CC_OP_SARW] = { compute_all_sarw, compute_c_shll },
909
    [CC_OP_SARL] = { compute_all_sarl, compute_c_shll },
910
};
911

    
912
/* floating point support */
913

    
914
#ifdef USE_X86LDOUBLE
915
/* use long double functions */
916
#define lrint lrintl
917
#define llrint llrintl
918
#define fabs fabsl
919
#define sin sinl
920
#define cos cosl
921
#define sqrt sqrtl
922
#define pow powl
923
#define log logl
924
#define tan tanl
925
#define atan2 atan2l
926
#define floor floorl
927
#define ceil ceill
928
#define rint rintl
929
#endif
930

    
931
extern int lrint(CPU86_LDouble x);
932
extern int64_t llrint(CPU86_LDouble x);
933
extern CPU86_LDouble fabs(CPU86_LDouble x);
934
extern CPU86_LDouble sin(CPU86_LDouble x);
935
extern CPU86_LDouble cos(CPU86_LDouble x);
936
extern CPU86_LDouble sqrt(CPU86_LDouble x);
937
extern CPU86_LDouble pow(CPU86_LDouble, CPU86_LDouble);
938
extern CPU86_LDouble log(CPU86_LDouble x);
939
extern CPU86_LDouble tan(CPU86_LDouble x);
940
extern CPU86_LDouble atan2(CPU86_LDouble, CPU86_LDouble);
941
extern CPU86_LDouble floor(CPU86_LDouble x);
942
extern CPU86_LDouble ceil(CPU86_LDouble x);
943
extern CPU86_LDouble rint(CPU86_LDouble x);
944

    
945
#define RC_MASK         0xc00
946
#define RC_NEAR                0x000
947
#define RC_DOWN                0x400
948
#define RC_UP                0x800
949
#define RC_CHOP                0xc00
950

    
951
#define MAXTAN 9223372036854775808.0
952

    
953
#ifdef USE_X86LDOUBLE
954

    
955
/* only for x86 */
956
typedef union {
957
    long double d;
958
    struct {
959
        unsigned long long lower;
960
        unsigned short upper;
961
    } l;
962
} CPU86_LDoubleU;
963

    
964
/* the following deal with x86 long double-precision numbers */
965
#define MAXEXPD 0x7fff
966
#define EXPBIAS 16383
967
#define EXPD(fp)        (fp.l.upper & 0x7fff)
968
#define SIGND(fp)        ((fp.l.upper) & 0x8000)
969
#define MANTD(fp)       (fp.l.lower)
970
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
971

    
972
#else
973

    
974
typedef union {
975
    double d;
976
#ifndef WORDS_BIGENDIAN
977
    struct {
978
        unsigned long lower;
979
        long upper;
980
    } l;
981
#else
982
    struct {
983
        long upper;
984
        unsigned long lower;
985
    } l;
986
#endif
987
    long long ll;
988
} CPU86_LDoubleU;
989

    
990
/* the following deal with IEEE double-precision numbers */
991
#define MAXEXPD 0x7ff
992
#define EXPBIAS 1023
993
#define EXPD(fp)        (((fp.l.upper) >> 20) & 0x7FF)
994
#define SIGND(fp)        ((fp.l.upper) & 0x80000000)
995
#define MANTD(fp)        (fp.ll & ((1LL << 52) - 1))
996
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20)
997
#endif
998

    
999
/* fp load FT0 */
1000

    
1001
void OPPROTO op_flds_FT0_A0(void)
1002
{
1003
    FT0 = ldfl((void *)A0);
1004
}
1005

    
1006
void OPPROTO op_fldl_FT0_A0(void)
1007
{
1008
    FT0 = ldfq((void *)A0);
1009
}
1010

    
1011
void OPPROTO op_fild_FT0_A0(void)
1012
{
1013
    FT0 = (CPU86_LDouble)ldsw((void *)A0);
1014
}
1015

    
1016
void OPPROTO op_fildl_FT0_A0(void)
1017
{
1018
    FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1019
}
1020

    
1021
void OPPROTO op_fildll_FT0_A0(void)
1022
{
1023
    FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1024
}
1025

    
1026
/* fp load ST0 */
1027

    
1028
void OPPROTO op_flds_ST0_A0(void)
1029
{
1030
    ST0 = ldfl((void *)A0);
1031
}
1032

    
1033
void OPPROTO op_fldl_ST0_A0(void)
1034
{
1035
    ST0 = ldfq((void *)A0);
1036
}
1037

    
1038
#ifdef USE_X86LDOUBLE
1039
void OPPROTO op_fldt_ST0_A0(void)
1040
{
1041
    ST0 = *(long double *)A0;
1042
}
1043
#else
1044
void helper_fldt_ST0_A0(void)
1045
{
1046
    CPU86_LDoubleU temp;
1047
    int upper, e;
1048
    /* mantissa */
1049
    upper = lduw((uint8_t *)A0 + 8);
1050
    /* XXX: handle overflow ? */
1051
    e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
1052
    e |= (upper >> 4) & 0x800; /* sign */
1053
    temp.ll = ((ldq((void *)A0) >> 11) & ((1LL << 52) - 1)) | ((uint64_t)e << 52);
1054
    ST0 = temp.d;
1055
}
1056

    
1057
void OPPROTO op_fldt_ST0_A0(void)
1058
{
1059
    helper_fldt_ST0_A0();
1060
}
1061
#endif
1062

    
1063
void OPPROTO op_fild_ST0_A0(void)
1064
{
1065
    ST0 = (CPU86_LDouble)ldsw((void *)A0);
1066
}
1067

    
1068
void OPPROTO op_fildl_ST0_A0(void)
1069
{
1070
    ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1071
}
1072

    
1073
void OPPROTO op_fildll_ST0_A0(void)
1074
{
1075
    ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1076
}
1077

    
1078
/* fp store */
1079

    
1080
void OPPROTO op_fsts_ST0_A0(void)
1081
{
1082
    stfl((void *)A0, (float)ST0);
1083
}
1084

    
1085
void OPPROTO op_fstl_ST0_A0(void)
1086
{
1087
    stfq((void *)A0, (double)ST0);
1088
}
1089

    
1090
#ifdef USE_X86LDOUBLE
1091
void OPPROTO op_fstt_ST0_A0(void)
1092
{
1093
    *(long double *)A0 = ST0;
1094
}
1095
#else
1096
void helper_fstt_ST0_A0(void)
1097
{
1098
    CPU86_LDoubleU temp;
1099
    int e;
1100
    temp.d = ST0;
1101
    /* mantissa */
1102
    stq((void *)A0, (MANTD(temp) << 11) | (1LL << 63));
1103
    /* exponent + sign */
1104
    e = EXPD(temp) - EXPBIAS + 16383;
1105
    e |= SIGND(temp) >> 16;
1106
    stw((uint8_t *)A0 + 8, e);
1107
}
1108

    
1109
void OPPROTO op_fstt_ST0_A0(void)
1110
{
1111
    helper_fstt_ST0_A0();
1112
}
1113
#endif
1114

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

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

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

    
1136
/* BCD ops */
1137

    
1138
#define MUL10(iv) ( iv + iv + (iv << 3) )
1139

    
1140
void helper_fbld_ST0_A0(void)
1141
{
1142
    uint8_t *seg;
1143
    CPU86_LDouble fpsrcop;
1144
    int m32i;
1145
    unsigned int v;
1146

    
1147
    /* in this code, seg/m32i will be used as temporary ptr/int */
1148
    seg = (uint8_t *)A0 + 8;
1149
    v = ldub(seg--);
1150
    /* XXX: raise exception */
1151
    if (v != 0)
1152
        return;
1153
    v = ldub(seg--);
1154
    /* XXX: raise exception */
1155
    if ((v & 0xf0) != 0)
1156
        return;
1157
    m32i = v;  /* <-- d14 */
1158
    v = ldub(seg--);
1159
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d13 */
1160
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d12 */
1161
    v = ldub(seg--);
1162
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d11 */
1163
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d10 */
1164
    v = ldub(seg--);
1165
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d9 */
1166
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d8 */
1167
    fpsrcop = ((CPU86_LDouble)m32i) * 100000000.0;
1168

    
1169
    v = ldub(seg--);
1170
    m32i = (v >> 4);  /* <-- d7 */
1171
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d6 */
1172
    v = ldub(seg--);
1173
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d5 */
1174
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d4 */
1175
    v = ldub(seg--);
1176
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d3 */
1177
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d2 */
1178
    v = ldub(seg);
1179
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d1 */
1180
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d0 */
1181
    fpsrcop += ((CPU86_LDouble)m32i);
1182
    if ( ldub(seg+9) & 0x80 )
1183
        fpsrcop = -fpsrcop;
1184
    ST0 = fpsrcop;
1185
}
1186

    
1187
void OPPROTO op_fbld_ST0_A0(void)
1188
{
1189
    helper_fbld_ST0_A0();
1190
}
1191

    
1192
void helper_fbst_ST0_A0(void)
1193
{
1194
    CPU86_LDouble fptemp;
1195
    CPU86_LDouble fpsrcop;
1196
    int v;
1197
    uint8_t *mem_ref, *mem_end;
1198

    
1199
    fpsrcop = rint(ST0);
1200
    mem_ref = (uint8_t *)A0;
1201
    mem_end = mem_ref + 8;
1202
    if ( fpsrcop < 0.0 ) {
1203
        stw(mem_end, 0x8000);
1204
        fpsrcop = -fpsrcop;
1205
    } else {
1206
        stw(mem_end, 0x0000);
1207
    }
1208
    while (mem_ref < mem_end) {
1209
        if (fpsrcop == 0.0)
1210
            break;
1211
        fptemp = floor(fpsrcop/10.0);
1212
        v = ((int)(fpsrcop - fptemp*10.0));
1213
        if  (fptemp == 0.0)  { 
1214
            stb(mem_ref++, v); 
1215
            break; 
1216
        }
1217
        fpsrcop = fptemp;
1218
        fptemp = floor(fpsrcop/10.0);
1219
        v |= (((int)(fpsrcop - fptemp*10.0)) << 4);
1220
        stb(mem_ref++, v);
1221
        fpsrcop = fptemp;
1222
    }
1223
    while (mem_ref < mem_end) {
1224
        stb(mem_ref++, 0);
1225
    }
1226
}
1227

    
1228
void OPPROTO op_fbst_ST0_A0(void)
1229
{
1230
    helper_fbst_ST0_A0();
1231
}
1232

    
1233
/* FPU move */
1234

    
1235
static inline void fpush(void)
1236
{
1237
    env->fpstt = (env->fpstt - 1) & 7;
1238
    env->fptags[env->fpstt] = 0; /* validate stack entry */
1239
}
1240

    
1241
static inline void fpop(void)
1242
{
1243
    env->fptags[env->fpstt] = 1; /* invvalidate stack entry */
1244
    env->fpstt = (env->fpstt + 1) & 7;
1245
}
1246

    
1247
void OPPROTO op_fpush(void)
1248
{
1249
    fpush();
1250
}
1251

    
1252
void OPPROTO op_fpop(void)
1253
{
1254
    fpop();
1255
}
1256

    
1257
void OPPROTO op_fdecstp(void)
1258
{
1259
    env->fpstt = (env->fpstt - 1) & 7;
1260
    env->fpus &= (~0x4700);
1261
}
1262

    
1263
void OPPROTO op_fincstp(void)
1264
{
1265
    env->fpstt = (env->fpstt + 1) & 7;
1266
    env->fpus &= (~0x4700);
1267
}
1268

    
1269
void OPPROTO op_fmov_ST0_FT0(void)
1270
{
1271
    ST0 = FT0;
1272
}
1273

    
1274
void OPPROTO op_fmov_FT0_STN(void)
1275
{
1276
    FT0 = ST(PARAM1);
1277
}
1278

    
1279
void OPPROTO op_fmov_ST0_STN(void)
1280
{
1281
    ST0 = ST(PARAM1);
1282
}
1283

    
1284
void OPPROTO op_fmov_STN_ST0(void)
1285
{
1286
    ST(PARAM1) = ST0;
1287
}
1288

    
1289
void OPPROTO op_fxchg_ST0_STN(void)
1290
{
1291
    CPU86_LDouble tmp;
1292
    tmp = ST(PARAM1);
1293
    ST(PARAM1) = ST0;
1294
    ST0 = tmp;
1295
}
1296

    
1297
/* FPU operations */
1298

    
1299
/* XXX: handle nans */
1300
void OPPROTO op_fcom_ST0_FT0(void)
1301
{
1302
    env->fpus &= (~0x4500);        /* (C3,C2,C0) <-- 000 */
1303
    if (ST0 < FT0)
1304
        env->fpus |= 0x100;        /* (C3,C2,C0) <-- 001 */
1305
    else if (ST0 == FT0)
1306
        env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
1307
    FORCE_RET();
1308
}
1309

    
1310
/* XXX: handle nans */
1311
void OPPROTO op_fucom_ST0_FT0(void)
1312
{
1313
    env->fpus &= (~0x4500);        /* (C3,C2,C0) <-- 000 */
1314
    if (ST0 < FT0)
1315
        env->fpus |= 0x100;        /* (C3,C2,C0) <-- 001 */
1316
    else if (ST0 == FT0)
1317
        env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
1318
    FORCE_RET();
1319
}
1320

    
1321
void OPPROTO op_fadd_ST0_FT0(void)
1322
{
1323
    ST0 += FT0;
1324
}
1325

    
1326
void OPPROTO op_fmul_ST0_FT0(void)
1327
{
1328
    ST0 *= FT0;
1329
}
1330

    
1331
void OPPROTO op_fsub_ST0_FT0(void)
1332
{
1333
    ST0 -= FT0;
1334
}
1335

    
1336
void OPPROTO op_fsubr_ST0_FT0(void)
1337
{
1338
    ST0 = FT0 - ST0;
1339
}
1340

    
1341
void OPPROTO op_fdiv_ST0_FT0(void)
1342
{
1343
    ST0 /= FT0;
1344
}
1345

    
1346
void OPPROTO op_fdivr_ST0_FT0(void)
1347
{
1348
    ST0 = FT0 / ST0;
1349
}
1350

    
1351
/* fp operations between STN and ST0 */
1352

    
1353
void OPPROTO op_fadd_STN_ST0(void)
1354
{
1355
    ST(PARAM1) += ST0;
1356
}
1357

    
1358
void OPPROTO op_fmul_STN_ST0(void)
1359
{
1360
    ST(PARAM1) *= ST0;
1361
}
1362

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

    
1368
void OPPROTO op_fsubr_STN_ST0(void)
1369
{
1370
    CPU86_LDouble *p;
1371
    p = &ST(PARAM1);
1372
    *p = ST0 - *p;
1373
}
1374

    
1375
void OPPROTO op_fdiv_STN_ST0(void)
1376
{
1377
    ST(PARAM1) /= ST0;
1378
}
1379

    
1380
void OPPROTO op_fdivr_STN_ST0(void)
1381
{
1382
    CPU86_LDouble *p;
1383
    p = &ST(PARAM1);
1384
    *p = ST0 / *p;
1385
}
1386

    
1387
/* misc FPU operations */
1388
void OPPROTO op_fchs_ST0(void)
1389
{
1390
    ST0 = -ST0;
1391
}
1392

    
1393
void OPPROTO op_fabs_ST0(void)
1394
{
1395
    ST0 = fabs(ST0);
1396
}
1397

    
1398
void helper_fxam_ST0(void)
1399
{
1400
    CPU86_LDoubleU temp;
1401
    int expdif;
1402

    
1403
    temp.d = ST0;
1404

    
1405
    env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
1406
    if (SIGND(temp))
1407
        env->fpus |= 0x200; /* C1 <-- 1 */
1408

    
1409
    expdif = EXPD(temp);
1410
    if (expdif == MAXEXPD) {
1411
        if (MANTD(temp) == 0)
1412
            env->fpus |=  0x500 /*Infinity*/;
1413
        else
1414
            env->fpus |=  0x100 /*NaN*/;
1415
    } else if (expdif == 0) {
1416
        if (MANTD(temp) == 0)
1417
            env->fpus |=  0x4000 /*Zero*/;
1418
        else
1419
            env->fpus |= 0x4400 /*Denormal*/;
1420
    } else {
1421
        env->fpus |= 0x400;
1422
    }
1423
}
1424

    
1425
void OPPROTO op_fxam_ST0(void)
1426
{
1427
    helper_fxam_ST0();
1428
}
1429

    
1430
void OPPROTO op_fld1_ST0(void)
1431
{
1432
    ST0 = *(CPU86_LDouble *)&f15rk[1];
1433
}
1434

    
1435
void OPPROTO op_fldl2t_ST0(void)
1436
{
1437
    ST0 = *(CPU86_LDouble *)&f15rk[6];
1438
}
1439

    
1440
void OPPROTO op_fldl2e_ST0(void)
1441
{
1442
    ST0 = *(CPU86_LDouble *)&f15rk[5];
1443
}
1444

    
1445
void OPPROTO op_fldpi_ST0(void)
1446
{
1447
    ST0 = *(CPU86_LDouble *)&f15rk[2];
1448
}
1449

    
1450
void OPPROTO op_fldlg2_ST0(void)
1451
{
1452
    ST0 = *(CPU86_LDouble *)&f15rk[3];
1453
}
1454

    
1455
void OPPROTO op_fldln2_ST0(void)
1456
{
1457
    ST0 = *(CPU86_LDouble *)&f15rk[4];
1458
}
1459

    
1460
void OPPROTO op_fldz_ST0(void)
1461
{
1462
    ST0 = *(CPU86_LDouble *)&f15rk[0];
1463
}
1464

    
1465
void OPPROTO op_fldz_FT0(void)
1466
{
1467
    ST0 = *(CPU86_LDouble *)&f15rk[0];
1468
}
1469

    
1470
void helper_f2xm1(void)
1471
{
1472
    ST0 = pow(2.0,ST0) - 1.0;
1473
}
1474

    
1475
void helper_fyl2x(void)
1476
{
1477
    CPU86_LDouble fptemp;
1478
    
1479
    fptemp = ST0;
1480
    if (fptemp>0.0){
1481
        fptemp = log(fptemp)/log(2.0);         /* log2(ST) */
1482
        ST1 *= fptemp;
1483
        fpop();
1484
    } else { 
1485
        env->fpus &= (~0x4700);
1486
        env->fpus |= 0x400;
1487
    }
1488
}
1489

    
1490
void helper_fptan(void)
1491
{
1492
    CPU86_LDouble fptemp;
1493

    
1494
    fptemp = ST0;
1495
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1496
        env->fpus |= 0x400;
1497
    } else {
1498
        ST0 = tan(fptemp);
1499
        fpush();
1500
        ST0 = 1.0;
1501
        env->fpus &= (~0x400);  /* C2 <-- 0 */
1502
        /* the above code is for  |arg| < 2**52 only */
1503
    }
1504
}
1505

    
1506
void helper_fpatan(void)
1507
{
1508
    CPU86_LDouble fptemp, fpsrcop;
1509

    
1510
    fpsrcop = ST1;
1511
    fptemp = ST0;
1512
    ST1 = atan2(fpsrcop,fptemp);
1513
    fpop();
1514
}
1515

    
1516
void helper_fxtract(void)
1517
{
1518
    CPU86_LDoubleU temp;
1519
    unsigned int expdif;
1520

    
1521
    temp.d = ST0;
1522
    expdif = EXPD(temp) - EXPBIAS;
1523
    /*DP exponent bias*/
1524
    ST0 = expdif;
1525
    fpush();
1526
    BIASEXPONENT(temp);
1527
    ST0 = temp.d;
1528
}
1529

    
1530
void helper_fprem1(void)
1531
{
1532
    CPU86_LDouble dblq, fpsrcop, fptemp;
1533
    CPU86_LDoubleU fpsrcop1, fptemp1;
1534
    int expdif;
1535
    int q;
1536

    
1537
    fpsrcop = ST0;
1538
    fptemp = ST1;
1539
    fpsrcop1.d = fpsrcop;
1540
    fptemp1.d = fptemp;
1541
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
1542
    if (expdif < 53) {
1543
        dblq = fpsrcop / fptemp;
1544
        dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
1545
        ST0 = fpsrcop - fptemp*dblq;
1546
        q = (int)dblq; /* cutting off top bits is assumed here */
1547
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1548
                                /* (C0,C1,C3) <-- (q2,q1,q0) */
1549
        env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
1550
        env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
1551
        env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
1552
    } else {
1553
        env->fpus |= 0x400;  /* C2 <-- 1 */
1554
        fptemp = pow(2.0, expdif-50);
1555
        fpsrcop = (ST0 / ST1) / fptemp;
1556
        /* fpsrcop = integer obtained by rounding to the nearest */
1557
        fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
1558
            floor(fpsrcop): ceil(fpsrcop);
1559
        ST0 -= (ST1 * fpsrcop * fptemp);
1560
    }
1561
}
1562

    
1563
void helper_fprem(void)
1564
{
1565
    CPU86_LDouble dblq, fpsrcop, fptemp;
1566
    CPU86_LDoubleU fpsrcop1, fptemp1;
1567
    int expdif;
1568
    int q;
1569
    
1570
    fpsrcop = ST0;
1571
    fptemp = ST1;
1572
    fpsrcop1.d = fpsrcop;
1573
    fptemp1.d = fptemp;
1574
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
1575
    if ( expdif < 53 ) {
1576
        dblq = fpsrcop / fptemp;
1577
        dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
1578
        ST0 = fpsrcop - fptemp*dblq;
1579
        q = (int)dblq; /* cutting off top bits is assumed here */
1580
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1581
                                /* (C0,C1,C3) <-- (q2,q1,q0) */
1582
        env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
1583
        env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
1584
        env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
1585
    } else {
1586
        env->fpus |= 0x400;  /* C2 <-- 1 */
1587
        fptemp = pow(2.0, expdif-50);
1588
        fpsrcop = (ST0 / ST1) / fptemp;
1589
        /* fpsrcop = integer obtained by chopping */
1590
        fpsrcop = (fpsrcop < 0.0)?
1591
            -(floor(fabs(fpsrcop))): floor(fpsrcop);
1592
        ST0 -= (ST1 * fpsrcop * fptemp);
1593
    }
1594
}
1595

    
1596
void helper_fyl2xp1(void)
1597
{
1598
    CPU86_LDouble fptemp;
1599

    
1600
    fptemp = ST0;
1601
    if ((fptemp+1.0)>0.0) {
1602
        fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
1603
        ST1 *= fptemp;
1604
        fpop();
1605
    } else { 
1606
        env->fpus &= (~0x4700);
1607
        env->fpus |= 0x400;
1608
    }
1609
}
1610

    
1611
void helper_fsqrt(void)
1612
{
1613
    CPU86_LDouble fptemp;
1614

    
1615
    fptemp = ST0;
1616
    if (fptemp<0.0) { 
1617
        env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
1618
        env->fpus |= 0x400;
1619
    }
1620
    ST0 = sqrt(fptemp);
1621
}
1622

    
1623
void helper_fsincos(void)
1624
{
1625
    CPU86_LDouble fptemp;
1626

    
1627
    fptemp = ST0;
1628
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1629
        env->fpus |= 0x400;
1630
    } else {
1631
        ST0 = sin(fptemp);
1632
        fpush();
1633
        ST0 = cos(fptemp);
1634
        env->fpus &= (~0x400);  /* C2 <-- 0 */
1635
        /* the above code is for  |arg| < 2**63 only */
1636
    }
1637
}
1638

    
1639
void helper_frndint(void)
1640
{
1641
    ST0 = rint(ST0);
1642
}
1643

    
1644
void helper_fscale(void)
1645
{
1646
    CPU86_LDouble fpsrcop, fptemp;
1647

    
1648
    fpsrcop = 2.0;
1649
    fptemp = pow(fpsrcop,ST1);
1650
    ST0 *= fptemp;
1651
}
1652

    
1653
void helper_fsin(void)
1654
{
1655
    CPU86_LDouble fptemp;
1656

    
1657
    fptemp = ST0;
1658
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1659
        env->fpus |= 0x400;
1660
    } else {
1661
        ST0 = sin(fptemp);
1662
        env->fpus &= (~0x400);  /* C2 <-- 0 */
1663
        /* the above code is for  |arg| < 2**53 only */
1664
    }
1665
}
1666

    
1667
void helper_fcos(void)
1668
{
1669
    CPU86_LDouble fptemp;
1670

    
1671
    fptemp = ST0;
1672
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1673
        env->fpus |= 0x400;
1674
    } else {
1675
        ST0 = cos(fptemp);
1676
        env->fpus &= (~0x400);  /* C2 <-- 0 */
1677
        /* the above code is for  |arg5 < 2**63 only */
1678
    }
1679
}
1680

    
1681
/* associated heplers to reduce generated code length and to simplify
1682
   relocation (FP constants are usually stored in .rodata section) */
1683

    
1684
void OPPROTO op_f2xm1(void)
1685
{
1686
    helper_f2xm1();
1687
}
1688

    
1689
void OPPROTO op_fyl2x(void)
1690
{
1691
    helper_fyl2x();
1692
}
1693

    
1694
void OPPROTO op_fptan(void)
1695
{
1696
    helper_fptan();
1697
}
1698

    
1699
void OPPROTO op_fpatan(void)
1700
{
1701
    helper_fpatan();
1702
}
1703

    
1704
void OPPROTO op_fxtract(void)
1705
{
1706
    helper_fxtract();
1707
}
1708

    
1709
void OPPROTO op_fprem1(void)
1710
{
1711
    helper_fprem1();
1712
}
1713

    
1714

    
1715
void OPPROTO op_fprem(void)
1716
{
1717
    helper_fprem();
1718
}
1719

    
1720
void OPPROTO op_fyl2xp1(void)
1721
{
1722
    helper_fyl2xp1();
1723
}
1724

    
1725
void OPPROTO op_fsqrt(void)
1726
{
1727
    helper_fsqrt();
1728
}
1729

    
1730
void OPPROTO op_fsincos(void)
1731
{
1732
    helper_fsincos();
1733
}
1734

    
1735
void OPPROTO op_frndint(void)
1736
{
1737
    helper_frndint();
1738
}
1739

    
1740
void OPPROTO op_fscale(void)
1741
{
1742
    helper_fscale();
1743
}
1744

    
1745
void OPPROTO op_fsin(void)
1746
{
1747
    helper_fsin();
1748
}
1749

    
1750
void OPPROTO op_fcos(void)
1751
{
1752
    helper_fcos();
1753
}
1754

    
1755
void OPPROTO op_fnstsw_A0(void)
1756
{
1757
    int fpus;
1758
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
1759
    stw((void *)A0, fpus);
1760
}
1761

    
1762
void OPPROTO op_fnstsw_EAX(void)
1763
{
1764
    int fpus;
1765
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
1766
    EAX = (EAX & 0xffff0000) | fpus;
1767
}
1768

    
1769
void OPPROTO op_fnstcw_A0(void)
1770
{
1771
    stw((void *)A0, env->fpuc);
1772
}
1773

    
1774
void OPPROTO op_fldcw_A0(void)
1775
{
1776
    int rnd_type;
1777
    env->fpuc = lduw((void *)A0);
1778
    /* set rounding mode */
1779
    switch(env->fpuc & RC_MASK) {
1780
    default:
1781
    case RC_NEAR:
1782
        rnd_type = FE_TONEAREST;
1783
        break;
1784
    case RC_DOWN:
1785
        rnd_type = FE_DOWNWARD;
1786
        break;
1787
    case RC_UP:
1788
        rnd_type = FE_UPWARD;
1789
        break;
1790
    case RC_CHOP:
1791
        rnd_type = FE_TOWARDZERO;
1792
        break;
1793
    }
1794
    fesetround(rnd_type);
1795
}
1796