Statistics
| Branch: | Revision:

root / op-i386.c @ 3ef693a0

History | View | Annotate | Download (42.8 kB)

1
/*
2
 *  i386 micro operations
3
 * 
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library 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 GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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
/* we define the various pieces of code used by the JIT */
123

    
124
#define REG EAX
125
#define REGNAME _EAX
126
#include "opreg_template.h"
127
#undef REG
128
#undef REGNAME
129

    
130
#define REG ECX
131
#define REGNAME _ECX
132
#include "opreg_template.h"
133
#undef REG
134
#undef REGNAME
135

    
136
#define REG EDX
137
#define REGNAME _EDX
138
#include "opreg_template.h"
139
#undef REG
140
#undef REGNAME
141

    
142
#define REG EBX
143
#define REGNAME _EBX
144
#include "opreg_template.h"
145
#undef REG
146
#undef REGNAME
147

    
148
#define REG ESP
149
#define REGNAME _ESP
150
#include "opreg_template.h"
151
#undef REG
152
#undef REGNAME
153

    
154
#define REG EBP
155
#define REGNAME _EBP
156
#include "opreg_template.h"
157
#undef REG
158
#undef REGNAME
159

    
160
#define REG ESI
161
#define REGNAME _ESI
162
#include "opreg_template.h"
163
#undef REG
164
#undef REGNAME
165

    
166
#define REG EDI
167
#define REGNAME _EDI
168
#include "opreg_template.h"
169
#undef REG
170
#undef REGNAME
171

    
172
/* operations with flags */
173

    
174
void OPPROTO op_addl_T0_T1_cc(void)
175
{
176
    CC_SRC = T0;
177
    T0 += T1;
178
    CC_DST = T0;
179
}
180

    
181
void OPPROTO op_orl_T0_T1_cc(void)
182
{
183
    T0 |= T1;
184
    CC_DST = T0;
185
}
186

    
187
void OPPROTO op_andl_T0_T1_cc(void)
188
{
189
    T0 &= T1;
190
    CC_DST = T0;
191
}
192

    
193
void OPPROTO op_subl_T0_T1_cc(void)
194
{
195
    CC_SRC = T0;
196
    T0 -= T1;
197
    CC_DST = T0;
198
}
199

    
200
void OPPROTO op_xorl_T0_T1_cc(void)
201
{
202
    T0 ^= T1;
203
    CC_DST = T0;
204
}
205

    
206
void OPPROTO op_cmpl_T0_T1_cc(void)
207
{
208
    CC_SRC = T0;
209
    CC_DST = T0 - T1;
210
}
211

    
212
void OPPROTO op_negl_T0_cc(void)
213
{
214
    CC_SRC = 0;
215
    T0 = -T0;
216
    CC_DST = T0;
217
}
218

    
219
void OPPROTO op_incl_T0_cc(void)
220
{
221
    CC_SRC = cc_table[CC_OP].compute_c();
222
    T0++;
223
    CC_DST = T0;
224
}
225

    
226
void OPPROTO op_decl_T0_cc(void)
227
{
228
    CC_SRC = cc_table[CC_OP].compute_c();
229
    T0--;
230
    CC_DST = T0;
231
}
232

    
233
void OPPROTO op_testl_T0_T1_cc(void)
234
{
235
    CC_DST = T0 & T1;
236
}
237

    
238
/* operations without flags */
239

    
240
void OPPROTO op_addl_T0_T1(void)
241
{
242
    T0 += T1;
243
}
244

    
245
void OPPROTO op_orl_T0_T1(void)
246
{
247
    T0 |= T1;
248
}
249

    
250
void OPPROTO op_andl_T0_T1(void)
251
{
252
    T0 &= T1;
253
}
254

    
255
void OPPROTO op_subl_T0_T1(void)
256
{
257
    T0 -= T1;
258
}
259

    
260
void OPPROTO op_xorl_T0_T1(void)
261
{
262
    T0 ^= T1;
263
}
264

    
265
void OPPROTO op_negl_T0(void)
266
{
267
    T0 = -T0;
268
}
269

    
270
void OPPROTO op_incl_T0(void)
271
{
272
    T0++;
273
}
274

    
275
void OPPROTO op_decl_T0(void)
276
{
277
    T0--;
278
}
279

    
280
void OPPROTO op_notl_T0(void)
281
{
282
    T0 = ~T0;
283
}
284

    
285
void OPPROTO op_bswapl_T0(void)
286
{
287
    T0 = bswap32(T0);
288
}
289

    
290
/* multiply/divide */
291
void OPPROTO op_mulb_AL_T0(void)
292
{
293
    unsigned int res;
294
    res = (uint8_t)EAX * (uint8_t)T0;
295
    EAX = (EAX & 0xffff0000) | res;
296
    CC_SRC = (res & 0xff00);
297
}
298

    
299
void OPPROTO op_imulb_AL_T0(void)
300
{
301
    int res;
302
    res = (int8_t)EAX * (int8_t)T0;
303
    EAX = (EAX & 0xffff0000) | (res & 0xffff);
304
    CC_SRC = (res != (int8_t)res);
305
}
306

    
307
void OPPROTO op_mulw_AX_T0(void)
308
{
309
    unsigned int res;
310
    res = (uint16_t)EAX * (uint16_t)T0;
311
    EAX = (EAX & 0xffff0000) | (res & 0xffff);
312
    EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff);
313
    CC_SRC = res >> 16;
314
}
315

    
316
void OPPROTO op_imulw_AX_T0(void)
317
{
318
    int res;
319
    res = (int16_t)EAX * (int16_t)T0;
320
    EAX = (EAX & 0xffff0000) | (res & 0xffff);
321
    EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff);
322
    CC_SRC = (res != (int16_t)res);
323
}
324

    
325
void OPPROTO op_mull_EAX_T0(void)
326
{
327
    uint64_t res;
328
    res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0);
329
    EAX = res;
330
    EDX = res >> 32;
331
    CC_SRC = res >> 32;
332
}
333

    
334
void OPPROTO op_imull_EAX_T0(void)
335
{
336
    int64_t res;
337
    res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T0);
338
    EAX = res;
339
    EDX = res >> 32;
340
    CC_SRC = (res != (int32_t)res);
341
}
342

    
343
void OPPROTO op_imulw_T0_T1(void)
344
{
345
    int res;
346
    res = (int16_t)T0 * (int16_t)T1;
347
    T0 = res;
348
    CC_SRC = (res != (int16_t)res);
349
}
350

    
351
void OPPROTO op_imull_T0_T1(void)
352
{
353
    int64_t res;
354
    res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
355
    T0 = res;
356
    CC_SRC = (res != (int32_t)res);
357
}
358

    
359
/* division, flags are undefined */
360
/* XXX: add exceptions for overflow */
361
void OPPROTO op_divb_AL_T0(void)
362
{
363
    unsigned int num, den, q, r;
364

    
365
    num = (EAX & 0xffff);
366
    den = (T0 & 0xff);
367
    if (den == 0)
368
        raise_exception(EXCP00_DIVZ);
369
    q = (num / den) & 0xff;
370
    r = (num % den) & 0xff;
371
    EAX = (EAX & 0xffff0000) | (r << 8) | q;
372
}
373

    
374
void OPPROTO op_idivb_AL_T0(void)
375
{
376
    int num, den, q, r;
377

    
378
    num = (int16_t)EAX;
379
    den = (int8_t)T0;
380
    if (den == 0)
381
        raise_exception(EXCP00_DIVZ);
382
    q = (num / den) & 0xff;
383
    r = (num % den) & 0xff;
384
    EAX = (EAX & 0xffff0000) | (r << 8) | q;
385
}
386

    
387
void OPPROTO op_divw_AX_T0(void)
388
{
389
    unsigned int num, den, q, r;
390

    
391
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
392
    den = (T0 & 0xffff);
393
    if (den == 0)
394
        raise_exception(EXCP00_DIVZ);
395
    q = (num / den) & 0xffff;
396
    r = (num % den) & 0xffff;
397
    EAX = (EAX & 0xffff0000) | q;
398
    EDX = (EDX & 0xffff0000) | r;
399
}
400

    
401
void OPPROTO op_idivw_AX_T0(void)
402
{
403
    int num, den, q, r;
404

    
405
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
406
    den = (int16_t)T0;
407
    if (den == 0)
408
        raise_exception(EXCP00_DIVZ);
409
    q = (num / den) & 0xffff;
410
    r = (num % den) & 0xffff;
411
    EAX = (EAX & 0xffff0000) | q;
412
    EDX = (EDX & 0xffff0000) | r;
413
}
414

    
415
void OPPROTO op_divl_EAX_T0(void)
416
{
417
    unsigned int den, q, r;
418
    uint64_t num;
419
    
420
    num = EAX | ((uint64_t)EDX << 32);
421
    den = T0;
422
    if (den == 0)
423
        raise_exception(EXCP00_DIVZ);
424
    q = (num / den);
425
    r = (num % den);
426
    EAX = q;
427
    EDX = r;
428
}
429

    
430
void OPPROTO op_idivl_EAX_T0(void)
431
{
432
    int den, q, r;
433
    int64_t num;
434
    
435
    num = EAX | ((uint64_t)EDX << 32);
436
    den = T0;
437
    if (den == 0)
438
        raise_exception(EXCP00_DIVZ);
439
    q = (num / den);
440
    r = (num % den);
441
    EAX = q;
442
    EDX = r;
443
}
444

    
445
/* constant load & misc op */
446

    
447
void OPPROTO op_movl_T0_im(void)
448
{
449
    T0 = PARAM1;
450
}
451

    
452
void OPPROTO op_addl_T0_im(void)
453
{
454
    T0 += PARAM1;
455
}
456

    
457
void OPPROTO op_andl_T0_ffff(void)
458
{
459
    T0 = T0 & 0xffff;
460
}
461

    
462
void OPPROTO op_movl_T0_T1(void)
463
{
464
    T0 = T1;
465
}
466

    
467
void OPPROTO op_movl_T1_im(void)
468
{
469
    T1 = PARAM1;
470
}
471

    
472
void OPPROTO op_addl_T1_im(void)
473
{
474
    T1 += PARAM1;
475
}
476

    
477
void OPPROTO op_movl_T1_A0(void)
478
{
479
    T1 = A0;
480
}
481

    
482
void OPPROTO op_movl_A0_im(void)
483
{
484
    A0 = PARAM1;
485
}
486

    
487
void OPPROTO op_addl_A0_im(void)
488
{
489
    A0 += PARAM1;
490
}
491

    
492
void OPPROTO op_andl_A0_ffff(void)
493
{
494
    A0 = A0 & 0xffff;
495
}
496

    
497
/* memory access */
498

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

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

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

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

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

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

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

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

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

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

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

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

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

    
564
/* used for bit operations */
565

    
566
void OPPROTO op_add_bitw_A0_T1(void)
567
{
568
    A0 += ((int32_t)T1 >> 4) << 1;
569
}
570

    
571
void OPPROTO op_add_bitl_A0_T1(void)
572
{
573
    A0 += ((int32_t)T1 >> 5) << 2;
574
}
575

    
576
/* indirect jump */
577

    
578
void OPPROTO op_jmp_T0(void)
579
{
580
    EIP = T0;
581
}
582

    
583
void OPPROTO op_jmp_im(void)
584
{
585
    EIP = PARAM1;
586
}
587

    
588
void OPPROTO op_int_im(void)
589
{
590
    EIP = PARAM1;
591
    raise_exception(EXCP0D_GPF);
592
}
593

    
594
void OPPROTO op_int3(void)
595
{
596
    EIP = PARAM1;
597
    raise_exception(EXCP03_INT3);
598
}
599

    
600
void OPPROTO op_into(void)
601
{
602
    int eflags;
603
    eflags = cc_table[CC_OP].compute_all();
604
    if (eflags & CC_O) {
605
        EIP = PARAM1;
606
        raise_exception(EXCP04_INTO);
607
    } else {
608
        EIP = PARAM2;
609
    }
610
}
611

    
612
/* string ops */
613

    
614
#define ldul ldl
615

    
616
#define SHIFT 0
617
#include "ops_template.h"
618
#undef SHIFT
619

    
620
#define SHIFT 1
621
#include "ops_template.h"
622
#undef SHIFT
623

    
624
#define SHIFT 2
625
#include "ops_template.h"
626
#undef SHIFT
627

    
628
/* sign extend */
629

    
630
void OPPROTO op_movsbl_T0_T0(void)
631
{
632
    T0 = (int8_t)T0;
633
}
634

    
635
void OPPROTO op_movzbl_T0_T0(void)
636
{
637
    T0 = (uint8_t)T0;
638
}
639

    
640
void OPPROTO op_movswl_T0_T0(void)
641
{
642
    T0 = (int16_t)T0;
643
}
644

    
645
void OPPROTO op_movzwl_T0_T0(void)
646
{
647
    T0 = (uint16_t)T0;
648
}
649

    
650
void OPPROTO op_movswl_EAX_AX(void)
651
{
652
    EAX = (int16_t)EAX;
653
}
654

    
655
void OPPROTO op_movsbw_AX_AL(void)
656
{
657
    EAX = (EAX & 0xffff0000) | ((int8_t)EAX & 0xffff);
658
}
659

    
660
void OPPROTO op_movslq_EDX_EAX(void)
661
{
662
    EDX = (int32_t)EAX >> 31;
663
}
664

    
665
void OPPROTO op_movswl_DX_AX(void)
666
{
667
    EDX = (EDX & 0xffff0000) | (((int16_t)EAX >> 15) & 0xffff);
668
}
669

    
670
/* push/pop */
671

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

    
681
void op_pushw_T0(void)
682
{
683
    uint32_t offset;
684
    offset = ESP - 2;
685
    stw((void *)offset, T0);
686
    /* modify ESP after to handle exceptions correctly */
687
    ESP = offset;
688
}
689

    
690
void op_pushl_ss32_T0(void)
691
{
692
    uint32_t offset;
693
    offset = ESP - 4;
694
    stl(env->seg_cache[R_SS].base + offset, T0);
695
    /* modify ESP after to handle exceptions correctly */
696
    ESP = offset;
697
}
698

    
699
void op_pushw_ss32_T0(void)
700
{
701
    uint32_t offset;
702
    offset = ESP - 2;
703
    stw(env->seg_cache[R_SS].base + offset, T0);
704
    /* modify ESP after to handle exceptions correctly */
705
    ESP = offset;
706
}
707

    
708
void op_pushl_ss16_T0(void)
709
{
710
    uint32_t offset;
711
    offset = (ESP - 4) & 0xffff;
712
    stl(env->seg_cache[R_SS].base + offset, T0);
713
    /* modify ESP after to handle exceptions correctly */
714
    ESP = (ESP & ~0xffff) | offset;
715
}
716

    
717
void op_pushw_ss16_T0(void)
718
{
719
    uint32_t offset;
720
    offset = (ESP - 2) & 0xffff;
721
    stw(env->seg_cache[R_SS].base + offset, T0);
722
    /* modify ESP after to handle exceptions correctly */
723
    ESP = (ESP & ~0xffff) | offset;
724
}
725

    
726
/* NOTE: ESP update is done after */
727
void op_popl_T0(void)
728
{
729
    T0 = ldl((void *)ESP);
730
}
731

    
732
void op_popw_T0(void)
733
{
734
    T0 = lduw((void *)ESP);
735
}
736

    
737
void op_popl_ss32_T0(void)
738
{
739
    T0 = ldl(env->seg_cache[R_SS].base + ESP);
740
}
741

    
742
void op_popw_ss32_T0(void)
743
{
744
    T0 = lduw(env->seg_cache[R_SS].base + ESP);
745
}
746

    
747
void op_popl_ss16_T0(void)
748
{
749
    T0 = ldl(env->seg_cache[R_SS].base + (ESP & 0xffff));
750
}
751

    
752
void op_popw_ss16_T0(void)
753
{
754
    T0 = lduw(env->seg_cache[R_SS].base + (ESP & 0xffff));
755
}
756

    
757
void op_addl_ESP_4(void)
758
{
759
    ESP += 4;
760
}
761

    
762
void op_addl_ESP_2(void)
763
{
764
    ESP += 2;
765
}
766

    
767
void op_addw_ESP_4(void)
768
{
769
    ESP = (ESP & ~0xffff) | ((ESP + 4) & 0xffff);
770
}
771

    
772
void op_addw_ESP_2(void)
773
{
774
    ESP = (ESP & ~0xffff) | ((ESP + 2) & 0xffff);
775
}
776

    
777
void op_addl_ESP_im(void)
778
{
779
    ESP += PARAM1;
780
}
781

    
782
void op_addw_ESP_im(void)
783
{
784
    ESP = (ESP & ~0xffff) | ((ESP + PARAM1) & 0xffff);
785
}
786

    
787
/* rdtsc */
788
#ifndef __i386__
789
uint64_t emu_time;
790
#endif
791
void op_rdtsc(void)
792
{
793
    uint64_t val;
794
#ifdef __i386__
795
    asm("rdtsc" : "=A" (val));
796
#else
797
    /* better than nothing: the time increases */
798
    val = emu_time++;
799
#endif
800
    EAX = val;
801
    EDX = val >> 32;
802
}
803

    
804
/* bcd */
805

    
806
/* XXX: exception */
807
void OPPROTO op_aam(void)
808
{
809
    int base = PARAM1;
810
    int al, ah;
811
    al = EAX & 0xff;
812
    ah = al / base;
813
    al = al % base;
814
    EAX = (EAX & ~0xffff) | al | (ah << 8);
815
    CC_DST = al;
816
}
817

    
818
void OPPROTO op_aad(void)
819
{
820
    int base = PARAM1;
821
    int al, ah;
822
    al = EAX & 0xff;
823
    ah = (EAX >> 8) & 0xff;
824
    al = ((ah * base) + al) & 0xff;
825
    EAX = (EAX & ~0xffff) | al;
826
    CC_DST = al;
827
}
828

    
829
void OPPROTO op_aaa(void)
830
{
831
    int icarry;
832
    int al, ah, af;
833
    int eflags;
834

    
835
    eflags = cc_table[CC_OP].compute_all();
836
    af = eflags & CC_A;
837
    al = EAX & 0xff;
838
    ah = (EAX >> 8) & 0xff;
839

    
840
    icarry = (al > 0xf9);
841
    if (((al & 0x0f) > 9 ) || af) {
842
        al = (al + 6) & 0x0f;
843
        ah = (ah + 1 + icarry) & 0xff;
844
        eflags |= CC_C | CC_A;
845
    } else {
846
        eflags &= ~(CC_C | CC_A);
847
        al &= 0x0f;
848
    }
849
    EAX = (EAX & ~0xffff) | al | (ah << 8);
850
    CC_SRC = eflags;
851
}
852

    
853
void OPPROTO op_aas(void)
854
{
855
    int icarry;
856
    int al, ah, af;
857
    int eflags;
858

    
859
    eflags = cc_table[CC_OP].compute_all();
860
    af = eflags & CC_A;
861
    al = EAX & 0xff;
862
    ah = (EAX >> 8) & 0xff;
863

    
864
    icarry = (al < 6);
865
    if (((al & 0x0f) > 9 ) || af) {
866
        al = (al - 6) & 0x0f;
867
        ah = (ah - 1 - icarry) & 0xff;
868
        eflags |= CC_C | CC_A;
869
    } else {
870
        eflags &= ~(CC_C | CC_A);
871
        al &= 0x0f;
872
    }
873
    EAX = (EAX & ~0xffff) | al | (ah << 8);
874
    CC_SRC = eflags;
875
}
876

    
877
void OPPROTO op_daa(void)
878
{
879
    int al, af, cf;
880
    int eflags;
881

    
882
    eflags = cc_table[CC_OP].compute_all();
883
    cf = eflags & CC_C;
884
    af = eflags & CC_A;
885
    al = EAX & 0xff;
886

    
887
    eflags = 0;
888
    if (((al & 0x0f) > 9 ) || af) {
889
        al = (al + 6) & 0xff;
890
        eflags |= CC_A;
891
    }
892
    if ((al > 0x9f) || cf) {
893
        al = (al + 0x60) & 0xff;
894
        eflags |= CC_C;
895
    }
896
    EAX = (EAX & ~0xff) | al;
897
    /* well, speed is not an issue here, so we compute the flags by hand */
898
    eflags |= (al == 0) << 6; /* zf */
899
    eflags |= parity_table[al]; /* pf */
900
    eflags |= (al & 0x80); /* sf */
901
    CC_SRC = eflags;
902
}
903

    
904
void OPPROTO op_das(void)
905
{
906
    int al, al1, af, cf;
907
    int eflags;
908

    
909
    eflags = cc_table[CC_OP].compute_all();
910
    cf = eflags & CC_C;
911
    af = eflags & CC_A;
912
    al = EAX & 0xff;
913

    
914
    eflags = 0;
915
    al1 = al;
916
    if (((al & 0x0f) > 9 ) || af) {
917
        eflags |= CC_A;
918
        if (al < 6 || cf)
919
            eflags |= CC_C;
920
        al = (al - 6) & 0xff;
921
    }
922
    if ((al1 > 0x99) || cf) {
923
        al = (al - 0x60) & 0xff;
924
        eflags |= CC_C;
925
    }
926
    EAX = (EAX & ~0xff) | al;
927
    /* well, speed is not an issue here, so we compute the flags by hand */
928
    eflags |= (al == 0) << 6; /* zf */
929
    eflags |= parity_table[al]; /* pf */
930
    eflags |= (al & 0x80); /* sf */
931
    CC_SRC = eflags;
932
}
933

    
934
/* segment handling */
935

    
936
void load_seg(int seg_reg, int selector)
937
{
938
    SegmentCache *sc;
939
    SegmentDescriptorTable *dt;
940
    int index;
941
    uint32_t e1, e2;
942
    uint8_t *ptr;
943

    
944
    env->segs[seg_reg] = selector;
945
    sc = &env->seg_cache[seg_reg];
946
    if (env->vm86) {
947
        sc->base = (void *)(selector << 4);
948
        sc->limit = 0xffff;
949
        sc->seg_32bit = 0;
950
    } else {
951
        if (selector & 0x4)
952
            dt = &env->ldt;
953
        else
954
            dt = &env->gdt;
955
        index = selector & ~7;
956
        if ((index + 7) > dt->limit)
957
            raise_exception(EXCP0D_GPF);
958
        ptr = dt->base + index;
959
        e1 = ldl(ptr);
960
        e2 = ldl(ptr + 4);
961
        sc->base = (void *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
962
        sc->limit = (e1 & 0xffff) | (e2 & 0x000f0000);
963
        if (e2 & (1 << 23))
964
            sc->limit = (sc->limit << 12) | 0xfff;
965
        sc->seg_32bit = (e2 >> 22) & 1;
966
#if 0
967
        fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n", 
968
                selector, (unsigned long)sc->base, sc->limit, sc->seg_32bit);
969
#endif
970
    }
971
}
972

    
973
void OPPROTO op_movl_seg_T0(void)
974
{
975
    load_seg(PARAM1, T0 & 0xffff);
976
}
977

    
978
void OPPROTO op_movl_T0_seg(void)
979
{
980
    T0 = env->segs[PARAM1];
981
}
982

    
983
void OPPROTO op_addl_A0_seg(void)
984
{
985
    A0 += *(unsigned long *)((char *)env + PARAM1);
986
}
987

    
988
/* flags handling */
989

    
990
/* slow jumps cases (compute x86 flags) */
991
void OPPROTO op_jo_cc(void)
992
{
993
    int eflags;
994
    eflags = cc_table[CC_OP].compute_all();
995
    if (eflags & CC_O)
996
        EIP = PARAM1;
997
    else
998
        EIP = PARAM2;
999
    FORCE_RET();
1000
}
1001

    
1002
void OPPROTO op_jb_cc(void)
1003
{
1004
    if (cc_table[CC_OP].compute_c())
1005
        EIP = PARAM1;
1006
    else
1007
        EIP = PARAM2;
1008
    FORCE_RET();
1009
}
1010

    
1011
void OPPROTO op_jz_cc(void)
1012
{
1013
    int eflags;
1014
    eflags = cc_table[CC_OP].compute_all();
1015
    if (eflags & CC_Z)
1016
        EIP = PARAM1;
1017
    else
1018
        EIP = PARAM2;
1019
    FORCE_RET();
1020
}
1021

    
1022
void OPPROTO op_jbe_cc(void)
1023
{
1024
    int eflags;
1025
    eflags = cc_table[CC_OP].compute_all();
1026
    if (eflags & (CC_Z | CC_C))
1027
        EIP = PARAM1;
1028
    else
1029
        EIP = PARAM2;
1030
    FORCE_RET();
1031
}
1032

    
1033
void OPPROTO op_js_cc(void)
1034
{
1035
    int eflags;
1036
    eflags = cc_table[CC_OP].compute_all();
1037
    if (eflags & CC_S)
1038
        EIP = PARAM1;
1039
    else
1040
        EIP = PARAM2;
1041
    FORCE_RET();
1042
}
1043

    
1044
void OPPROTO op_jp_cc(void)
1045
{
1046
    int eflags;
1047
    eflags = cc_table[CC_OP].compute_all();
1048
    if (eflags & CC_P)
1049
        EIP = PARAM1;
1050
    else
1051
        EIP = PARAM2;
1052
    FORCE_RET();
1053
}
1054

    
1055
void OPPROTO op_jl_cc(void)
1056
{
1057
    int eflags;
1058
    eflags = cc_table[CC_OP].compute_all();
1059
    if ((eflags ^ (eflags >> 4)) & 0x80)
1060
        EIP = PARAM1;
1061
    else
1062
        EIP = PARAM2;
1063
    FORCE_RET();
1064
}
1065

    
1066
void OPPROTO op_jle_cc(void)
1067
{
1068
    int eflags;
1069
    eflags = cc_table[CC_OP].compute_all();
1070
    if (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z))
1071
        EIP = PARAM1;
1072
    else
1073
        EIP = PARAM2;
1074
    FORCE_RET();
1075
}
1076

    
1077
/* slow set cases (compute x86 flags) */
1078
void OPPROTO op_seto_T0_cc(void)
1079
{
1080
    int eflags;
1081
    eflags = cc_table[CC_OP].compute_all();
1082
    T0 = (eflags >> 11) & 1;
1083
}
1084

    
1085
void OPPROTO op_setb_T0_cc(void)
1086
{
1087
    T0 = cc_table[CC_OP].compute_c();
1088
}
1089

    
1090
void OPPROTO op_setz_T0_cc(void)
1091
{
1092
    int eflags;
1093
    eflags = cc_table[CC_OP].compute_all();
1094
    T0 = (eflags >> 6) & 1;
1095
}
1096

    
1097
void OPPROTO op_setbe_T0_cc(void)
1098
{
1099
    int eflags;
1100
    eflags = cc_table[CC_OP].compute_all();
1101
    T0 = (eflags & (CC_Z | CC_C)) != 0;
1102
}
1103

    
1104
void OPPROTO op_sets_T0_cc(void)
1105
{
1106
    int eflags;
1107
    eflags = cc_table[CC_OP].compute_all();
1108
    T0 = (eflags >> 7) & 1;
1109
}
1110

    
1111
void OPPROTO op_setp_T0_cc(void)
1112
{
1113
    int eflags;
1114
    eflags = cc_table[CC_OP].compute_all();
1115
    T0 = (eflags >> 2) & 1;
1116
}
1117

    
1118
void OPPROTO op_setl_T0_cc(void)
1119
{
1120
    int eflags;
1121
    eflags = cc_table[CC_OP].compute_all();
1122
    T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
1123
}
1124

    
1125
void OPPROTO op_setle_T0_cc(void)
1126
{
1127
    int eflags;
1128
    eflags = cc_table[CC_OP].compute_all();
1129
    T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
1130
}
1131

    
1132
void OPPROTO op_xor_T0_1(void)
1133
{
1134
    T0 ^= 1;
1135
}
1136

    
1137
void OPPROTO op_set_cc_op(void)
1138
{
1139
    CC_OP = PARAM1;
1140
}
1141

    
1142
void OPPROTO op_movl_eflags_T0(void)
1143
{
1144
    CC_SRC = T0;
1145
    DF = 1 - (2 * ((T0 >> 10) & 1));
1146
}
1147

    
1148
/* XXX: compute only O flag */
1149
void OPPROTO op_movb_eflags_T0(void)
1150
{
1151
    int of;
1152
    of = cc_table[CC_OP].compute_all() & CC_O;
1153
    CC_SRC = T0 | of;
1154
}
1155

    
1156
void OPPROTO op_movl_T0_eflags(void)
1157
{
1158
    T0 = cc_table[CC_OP].compute_all();
1159
    T0 |= (DF & DIRECTION_FLAG);
1160
}
1161

    
1162
void OPPROTO op_cld(void)
1163
{
1164
    DF = 1;
1165
}
1166

    
1167
void OPPROTO op_std(void)
1168
{
1169
    DF = -1;
1170
}
1171

    
1172
void OPPROTO op_clc(void)
1173
{
1174
    int eflags;
1175
    eflags = cc_table[CC_OP].compute_all();
1176
    eflags &= ~CC_C;
1177
    CC_SRC = eflags;
1178
}
1179

    
1180
void OPPROTO op_stc(void)
1181
{
1182
    int eflags;
1183
    eflags = cc_table[CC_OP].compute_all();
1184
    eflags |= CC_C;
1185
    CC_SRC = eflags;
1186
}
1187

    
1188
void OPPROTO op_cmc(void)
1189
{
1190
    int eflags;
1191
    eflags = cc_table[CC_OP].compute_all();
1192
    eflags ^= CC_C;
1193
    CC_SRC = eflags;
1194
}
1195

    
1196
void OPPROTO op_salc(void)
1197
{
1198
    int cf;
1199
    cf = cc_table[CC_OP].compute_c();
1200
    EAX = (EAX & ~0xff) | ((-cf) & 0xff);
1201
}
1202

    
1203
static int compute_all_eflags(void)
1204
{
1205
    return CC_SRC;
1206
}
1207

    
1208
static int compute_c_eflags(void)
1209
{
1210
    return CC_SRC & CC_C;
1211
}
1212

    
1213
static int compute_c_mul(void)
1214
{
1215
    int cf;
1216
    cf = (CC_SRC != 0);
1217
    return cf;
1218
}
1219

    
1220
static int compute_all_mul(void)
1221
{
1222
    int cf, pf, af, zf, sf, of;
1223
    cf = (CC_SRC != 0);
1224
    pf = 0; /* undefined */
1225
    af = 0; /* undefined */
1226
    zf = 0; /* undefined */
1227
    sf = 0; /* undefined */
1228
    of = cf << 11;
1229
    return cf | pf | af | zf | sf | of;
1230
}
1231
    
1232
CCTable cc_table[CC_OP_NB] = {
1233
    [CC_OP_DYNAMIC] = { /* should never happen */ },
1234

    
1235
    [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
1236

    
1237
    [CC_OP_MUL] = { compute_all_mul, compute_c_mul },
1238

    
1239
    [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
1240
    [CC_OP_ADDW] = { compute_all_addw, compute_c_addw  },
1241
    [CC_OP_ADDL] = { compute_all_addl, compute_c_addl  },
1242

    
1243
    [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
1244
    [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw  },
1245
    [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl  },
1246

    
1247
    [CC_OP_SUBB] = { compute_all_subb, compute_c_subb  },
1248
    [CC_OP_SUBW] = { compute_all_subw, compute_c_subw  },
1249
    [CC_OP_SUBL] = { compute_all_subl, compute_c_subl  },
1250
    
1251
    [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb  },
1252
    [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw  },
1253
    [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl  },
1254
    
1255
    [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
1256
    [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
1257
    [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
1258
    
1259
    [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
1260
    [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
1261
    [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
1262
    
1263
    [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
1264
    [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
1265
    [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
1266
    
1267
    [CC_OP_SHLB] = { compute_all_shlb, compute_c_shll },
1268
    [CC_OP_SHLW] = { compute_all_shlw, compute_c_shll },
1269
    [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
1270

    
1271
    [CC_OP_SARB] = { compute_all_sarb, compute_c_shll },
1272
    [CC_OP_SARW] = { compute_all_sarw, compute_c_shll },
1273
    [CC_OP_SARL] = { compute_all_sarl, compute_c_shll },
1274
};
1275

    
1276
/* floating point support */
1277

    
1278
#ifdef USE_X86LDOUBLE
1279
/* use long double functions */
1280
#define lrint lrintl
1281
#define llrint llrintl
1282
#define fabs fabsl
1283
#define sin sinl
1284
#define cos cosl
1285
#define sqrt sqrtl
1286
#define pow powl
1287
#define log logl
1288
#define tan tanl
1289
#define atan2 atan2l
1290
#define floor floorl
1291
#define ceil ceill
1292
#define rint rintl
1293
#endif
1294

    
1295
extern int lrint(CPU86_LDouble x);
1296
extern int64_t llrint(CPU86_LDouble x);
1297
extern CPU86_LDouble fabs(CPU86_LDouble x);
1298
extern CPU86_LDouble sin(CPU86_LDouble x);
1299
extern CPU86_LDouble cos(CPU86_LDouble x);
1300
extern CPU86_LDouble sqrt(CPU86_LDouble x);
1301
extern CPU86_LDouble pow(CPU86_LDouble, CPU86_LDouble);
1302
extern CPU86_LDouble log(CPU86_LDouble x);
1303
extern CPU86_LDouble tan(CPU86_LDouble x);
1304
extern CPU86_LDouble atan2(CPU86_LDouble, CPU86_LDouble);
1305
extern CPU86_LDouble floor(CPU86_LDouble x);
1306
extern CPU86_LDouble ceil(CPU86_LDouble x);
1307
extern CPU86_LDouble rint(CPU86_LDouble x);
1308

    
1309
#define RC_MASK         0xc00
1310
#define RC_NEAR                0x000
1311
#define RC_DOWN                0x400
1312
#define RC_UP                0x800
1313
#define RC_CHOP                0xc00
1314

    
1315
#define MAXTAN 9223372036854775808.0
1316

    
1317
#ifdef USE_X86LDOUBLE
1318

    
1319
/* only for x86 */
1320
typedef union {
1321
    long double d;
1322
    struct {
1323
        unsigned long long lower;
1324
        unsigned short upper;
1325
    } l;
1326
} CPU86_LDoubleU;
1327

    
1328
/* the following deal with x86 long double-precision numbers */
1329
#define MAXEXPD 0x7fff
1330
#define EXPBIAS 16383
1331
#define EXPD(fp)        (fp.l.upper & 0x7fff)
1332
#define SIGND(fp)        ((fp.l.upper) & 0x8000)
1333
#define MANTD(fp)       (fp.l.lower)
1334
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
1335

    
1336
#else
1337

    
1338
typedef union {
1339
    double d;
1340
#ifndef WORDS_BIGENDIAN
1341
    struct {
1342
        unsigned long lower;
1343
        long upper;
1344
    } l;
1345
#else
1346
    struct {
1347
        long upper;
1348
        unsigned long lower;
1349
    } l;
1350
#endif
1351
    long long ll;
1352
} CPU86_LDoubleU;
1353

    
1354
/* the following deal with IEEE double-precision numbers */
1355
#define MAXEXPD 0x7ff
1356
#define EXPBIAS 1023
1357
#define EXPD(fp)        (((fp.l.upper) >> 20) & 0x7FF)
1358
#define SIGND(fp)        ((fp.l.upper) & 0x80000000)
1359
#define MANTD(fp)        (fp.ll & ((1LL << 52) - 1))
1360
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20)
1361
#endif
1362

    
1363
/* fp load FT0 */
1364

    
1365
void OPPROTO op_flds_FT0_A0(void)
1366
{
1367
    FT0 = ldfl((void *)A0);
1368
}
1369

    
1370
void OPPROTO op_fldl_FT0_A0(void)
1371
{
1372
    FT0 = ldfq((void *)A0);
1373
}
1374

    
1375
/* helpers are needed to avoid static constant reference. XXX: find a better way */
1376
#ifdef USE_INT_TO_FLOAT_HELPERS
1377

    
1378
void helper_fild_FT0_A0(void)
1379
{
1380
    FT0 = (CPU86_LDouble)ldsw((void *)A0);
1381
}
1382

    
1383
void helper_fildl_FT0_A0(void)
1384
{
1385
    FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1386
}
1387

    
1388
void helper_fildll_FT0_A0(void)
1389
{
1390
    FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1391
}
1392

    
1393
void OPPROTO op_fild_FT0_A0(void)
1394
{
1395
    helper_fild_FT0_A0();
1396
}
1397

    
1398
void OPPROTO op_fildl_FT0_A0(void)
1399
{
1400
    helper_fildl_FT0_A0();
1401
}
1402

    
1403
void OPPROTO op_fildll_FT0_A0(void)
1404
{
1405
    helper_fildll_FT0_A0();
1406
}
1407

    
1408
#else
1409

    
1410
void OPPROTO op_fild_FT0_A0(void)
1411
{
1412
    FT0 = (CPU86_LDouble)ldsw((void *)A0);
1413
}
1414

    
1415
void OPPROTO op_fildl_FT0_A0(void)
1416
{
1417
    FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1418
}
1419

    
1420
void OPPROTO op_fildll_FT0_A0(void)
1421
{
1422
    FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1423
}
1424
#endif
1425

    
1426
/* fp load ST0 */
1427

    
1428
void OPPROTO op_flds_ST0_A0(void)
1429
{
1430
    ST0 = ldfl((void *)A0);
1431
}
1432

    
1433
void OPPROTO op_fldl_ST0_A0(void)
1434
{
1435
    ST0 = ldfq((void *)A0);
1436
}
1437

    
1438
#ifdef USE_X86LDOUBLE
1439
void OPPROTO op_fldt_ST0_A0(void)
1440
{
1441
    ST0 = *(long double *)A0;
1442
}
1443
#else
1444
void helper_fldt_ST0_A0(void)
1445
{
1446
    CPU86_LDoubleU temp;
1447
    int upper, e;
1448
    /* mantissa */
1449
    upper = lduw((uint8_t *)A0 + 8);
1450
    /* XXX: handle overflow ? */
1451
    e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
1452
    e |= (upper >> 4) & 0x800; /* sign */
1453
    temp.ll = ((ldq((void *)A0) >> 11) & ((1LL << 52) - 1)) | ((uint64_t)e << 52);
1454
    ST0 = temp.d;
1455
}
1456

    
1457
void OPPROTO op_fldt_ST0_A0(void)
1458
{
1459
    helper_fldt_ST0_A0();
1460
}
1461
#endif
1462

    
1463
/* helpers are needed to avoid static constant reference. XXX: find a better way */
1464
#ifdef USE_INT_TO_FLOAT_HELPERS
1465

    
1466
void helper_fild_ST0_A0(void)
1467
{
1468
    ST0 = (CPU86_LDouble)ldsw((void *)A0);
1469
}
1470

    
1471
void helper_fildl_ST0_A0(void)
1472
{
1473
    ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1474
}
1475

    
1476
void helper_fildll_ST0_A0(void)
1477
{
1478
    ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1479
}
1480

    
1481
void OPPROTO op_fild_ST0_A0(void)
1482
{
1483
    helper_fild_ST0_A0();
1484
}
1485

    
1486
void OPPROTO op_fildl_ST0_A0(void)
1487
{
1488
    helper_fildl_ST0_A0();
1489
}
1490

    
1491
void OPPROTO op_fildll_ST0_A0(void)
1492
{
1493
    helper_fildll_ST0_A0();
1494
}
1495

    
1496
#else
1497

    
1498
void OPPROTO op_fild_ST0_A0(void)
1499
{
1500
    ST0 = (CPU86_LDouble)ldsw((void *)A0);
1501
}
1502

    
1503
void OPPROTO op_fildl_ST0_A0(void)
1504
{
1505
    ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1506
}
1507

    
1508
void OPPROTO op_fildll_ST0_A0(void)
1509
{
1510
    ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1511
}
1512

    
1513
#endif
1514

    
1515
/* fp store */
1516

    
1517
void OPPROTO op_fsts_ST0_A0(void)
1518
{
1519
    stfl((void *)A0, (float)ST0);
1520
}
1521

    
1522
void OPPROTO op_fstl_ST0_A0(void)
1523
{
1524
    stfq((void *)A0, (double)ST0);
1525
}
1526

    
1527
#ifdef USE_X86LDOUBLE
1528
void OPPROTO op_fstt_ST0_A0(void)
1529
{
1530
    *(long double *)A0 = ST0;
1531
}
1532
#else
1533
void helper_fstt_ST0_A0(void)
1534
{
1535
    CPU86_LDoubleU temp;
1536
    int e;
1537
    temp.d = ST0;
1538
    /* mantissa */
1539
    stq((void *)A0, (MANTD(temp) << 11) | (1LL << 63));
1540
    /* exponent + sign */
1541
    e = EXPD(temp) - EXPBIAS + 16383;
1542
    e |= SIGND(temp) >> 16;
1543
    stw((uint8_t *)A0 + 8, e);
1544
}
1545

    
1546
void OPPROTO op_fstt_ST0_A0(void)
1547
{
1548
    helper_fstt_ST0_A0();
1549
}
1550
#endif
1551

    
1552
void OPPROTO op_fist_ST0_A0(void)
1553
{
1554
    int val;
1555
    val = lrint(ST0);
1556
    stw((void *)A0, val);
1557
}
1558

    
1559
void OPPROTO op_fistl_ST0_A0(void)
1560
{
1561
    int val;
1562
    val = lrint(ST0);
1563
    stl((void *)A0, val);
1564
}
1565

    
1566
void OPPROTO op_fistll_ST0_A0(void)
1567
{
1568
    int64_t val;
1569
    val = llrint(ST0);
1570
    stq((void *)A0, val);
1571
}
1572

    
1573
/* BCD ops */
1574

    
1575
#define MUL10(iv) ( iv + iv + (iv << 3) )
1576

    
1577
void helper_fbld_ST0_A0(void)
1578
{
1579
    uint8_t *seg;
1580
    CPU86_LDouble fpsrcop;
1581
    int m32i;
1582
    unsigned int v;
1583

    
1584
    /* in this code, seg/m32i will be used as temporary ptr/int */
1585
    seg = (uint8_t *)A0 + 8;
1586
    v = ldub(seg--);
1587
    /* XXX: raise exception */
1588
    if (v != 0)
1589
        return;
1590
    v = ldub(seg--);
1591
    /* XXX: raise exception */
1592
    if ((v & 0xf0) != 0)
1593
        return;
1594
    m32i = v;  /* <-- d14 */
1595
    v = ldub(seg--);
1596
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d13 */
1597
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d12 */
1598
    v = ldub(seg--);
1599
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d11 */
1600
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d10 */
1601
    v = ldub(seg--);
1602
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d9 */
1603
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d8 */
1604
    fpsrcop = ((CPU86_LDouble)m32i) * 100000000.0;
1605

    
1606
    v = ldub(seg--);
1607
    m32i = (v >> 4);  /* <-- d7 */
1608
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d6 */
1609
    v = ldub(seg--);
1610
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d5 */
1611
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d4 */
1612
    v = ldub(seg--);
1613
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d3 */
1614
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d2 */
1615
    v = ldub(seg);
1616
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d1 */
1617
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d0 */
1618
    fpsrcop += ((CPU86_LDouble)m32i);
1619
    if ( ldub(seg+9) & 0x80 )
1620
        fpsrcop = -fpsrcop;
1621
    ST0 = fpsrcop;
1622
}
1623

    
1624
void OPPROTO op_fbld_ST0_A0(void)
1625
{
1626
    helper_fbld_ST0_A0();
1627
}
1628

    
1629
void helper_fbst_ST0_A0(void)
1630
{
1631
    CPU86_LDouble fptemp;
1632
    CPU86_LDouble fpsrcop;
1633
    int v;
1634
    uint8_t *mem_ref, *mem_end;
1635

    
1636
    fpsrcop = rint(ST0);
1637
    mem_ref = (uint8_t *)A0;
1638
    mem_end = mem_ref + 8;
1639
    if ( fpsrcop < 0.0 ) {
1640
        stw(mem_end, 0x8000);
1641
        fpsrcop = -fpsrcop;
1642
    } else {
1643
        stw(mem_end, 0x0000);
1644
    }
1645
    while (mem_ref < mem_end) {
1646
        if (fpsrcop == 0.0)
1647
            break;
1648
        fptemp = floor(fpsrcop/10.0);
1649
        v = ((int)(fpsrcop - fptemp*10.0));
1650
        if  (fptemp == 0.0)  { 
1651
            stb(mem_ref++, v); 
1652
            break; 
1653
        }
1654
        fpsrcop = fptemp;
1655
        fptemp = floor(fpsrcop/10.0);
1656
        v |= (((int)(fpsrcop - fptemp*10.0)) << 4);
1657
        stb(mem_ref++, v);
1658
        fpsrcop = fptemp;
1659
    }
1660
    while (mem_ref < mem_end) {
1661
        stb(mem_ref++, 0);
1662
    }
1663
}
1664

    
1665
void OPPROTO op_fbst_ST0_A0(void)
1666
{
1667
    helper_fbst_ST0_A0();
1668
}
1669

    
1670
/* FPU move */
1671

    
1672
static inline void fpush(void)
1673
{
1674
    env->fpstt = (env->fpstt - 1) & 7;
1675
    env->fptags[env->fpstt] = 0; /* validate stack entry */
1676
}
1677

    
1678
static inline void fpop(void)
1679
{
1680
    env->fptags[env->fpstt] = 1; /* invvalidate stack entry */
1681
    env->fpstt = (env->fpstt + 1) & 7;
1682
}
1683

    
1684
void OPPROTO op_fpush(void)
1685
{
1686
    fpush();
1687
}
1688

    
1689
void OPPROTO op_fpop(void)
1690
{
1691
    fpop();
1692
}
1693

    
1694
void OPPROTO op_fdecstp(void)
1695
{
1696
    env->fpstt = (env->fpstt - 1) & 7;
1697
    env->fpus &= (~0x4700);
1698
}
1699

    
1700
void OPPROTO op_fincstp(void)
1701
{
1702
    env->fpstt = (env->fpstt + 1) & 7;
1703
    env->fpus &= (~0x4700);
1704
}
1705

    
1706
void OPPROTO op_fmov_ST0_FT0(void)
1707
{
1708
    ST0 = FT0;
1709
}
1710

    
1711
void OPPROTO op_fmov_FT0_STN(void)
1712
{
1713
    FT0 = ST(PARAM1);
1714
}
1715

    
1716
void OPPROTO op_fmov_ST0_STN(void)
1717
{
1718
    ST0 = ST(PARAM1);
1719
}
1720

    
1721
void OPPROTO op_fmov_STN_ST0(void)
1722
{
1723
    ST(PARAM1) = ST0;
1724
}
1725

    
1726
void OPPROTO op_fxchg_ST0_STN(void)
1727
{
1728
    CPU86_LDouble tmp;
1729
    tmp = ST(PARAM1);
1730
    ST(PARAM1) = ST0;
1731
    ST0 = tmp;
1732
}
1733

    
1734
/* FPU operations */
1735

    
1736
/* XXX: handle nans */
1737
void OPPROTO op_fcom_ST0_FT0(void)
1738
{
1739
    env->fpus &= (~0x4500);        /* (C3,C2,C0) <-- 000 */
1740
    if (ST0 < FT0)
1741
        env->fpus |= 0x100;        /* (C3,C2,C0) <-- 001 */
1742
    else if (ST0 == FT0)
1743
        env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
1744
    FORCE_RET();
1745
}
1746

    
1747
/* XXX: handle nans */
1748
void OPPROTO op_fucom_ST0_FT0(void)
1749
{
1750
    env->fpus &= (~0x4500);        /* (C3,C2,C0) <-- 000 */
1751
    if (ST0 < FT0)
1752
        env->fpus |= 0x100;        /* (C3,C2,C0) <-- 001 */
1753
    else if (ST0 == FT0)
1754
        env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
1755
    FORCE_RET();
1756
}
1757

    
1758
void OPPROTO op_fadd_ST0_FT0(void)
1759
{
1760
    ST0 += FT0;
1761
}
1762

    
1763
void OPPROTO op_fmul_ST0_FT0(void)
1764
{
1765
    ST0 *= FT0;
1766
}
1767

    
1768
void OPPROTO op_fsub_ST0_FT0(void)
1769
{
1770
    ST0 -= FT0;
1771
}
1772

    
1773
void OPPROTO op_fsubr_ST0_FT0(void)
1774
{
1775
    ST0 = FT0 - ST0;
1776
}
1777

    
1778
void OPPROTO op_fdiv_ST0_FT0(void)
1779
{
1780
    ST0 /= FT0;
1781
}
1782

    
1783
void OPPROTO op_fdivr_ST0_FT0(void)
1784
{
1785
    ST0 = FT0 / ST0;
1786
}
1787

    
1788
/* fp operations between STN and ST0 */
1789

    
1790
void OPPROTO op_fadd_STN_ST0(void)
1791
{
1792
    ST(PARAM1) += ST0;
1793
}
1794

    
1795
void OPPROTO op_fmul_STN_ST0(void)
1796
{
1797
    ST(PARAM1) *= ST0;
1798
}
1799

    
1800
void OPPROTO op_fsub_STN_ST0(void)
1801
{
1802
    ST(PARAM1) -= ST0;
1803
}
1804

    
1805
void OPPROTO op_fsubr_STN_ST0(void)
1806
{
1807
    CPU86_LDouble *p;
1808
    p = &ST(PARAM1);
1809
    *p = ST0 - *p;
1810
}
1811

    
1812
void OPPROTO op_fdiv_STN_ST0(void)
1813
{
1814
    ST(PARAM1) /= ST0;
1815
}
1816

    
1817
void OPPROTO op_fdivr_STN_ST0(void)
1818
{
1819
    CPU86_LDouble *p;
1820
    p = &ST(PARAM1);
1821
    *p = ST0 / *p;
1822
}
1823

    
1824
/* misc FPU operations */
1825
void OPPROTO op_fchs_ST0(void)
1826
{
1827
    ST0 = -ST0;
1828
}
1829

    
1830
void OPPROTO op_fabs_ST0(void)
1831
{
1832
    ST0 = fabs(ST0);
1833
}
1834

    
1835
void helper_fxam_ST0(void)
1836
{
1837
    CPU86_LDoubleU temp;
1838
    int expdif;
1839

    
1840
    temp.d = ST0;
1841

    
1842
    env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
1843
    if (SIGND(temp))
1844
        env->fpus |= 0x200; /* C1 <-- 1 */
1845

    
1846
    expdif = EXPD(temp);
1847
    if (expdif == MAXEXPD) {
1848
        if (MANTD(temp) == 0)
1849
            env->fpus |=  0x500 /*Infinity*/;
1850
        else
1851
            env->fpus |=  0x100 /*NaN*/;
1852
    } else if (expdif == 0) {
1853
        if (MANTD(temp) == 0)
1854
            env->fpus |=  0x4000 /*Zero*/;
1855
        else
1856
            env->fpus |= 0x4400 /*Denormal*/;
1857
    } else {
1858
        env->fpus |= 0x400;
1859
    }
1860
}
1861

    
1862
void OPPROTO op_fxam_ST0(void)
1863
{
1864
    helper_fxam_ST0();
1865
}
1866

    
1867
void OPPROTO op_fld1_ST0(void)
1868
{
1869
    ST0 = *(CPU86_LDouble *)&f15rk[1];
1870
}
1871

    
1872
void OPPROTO op_fldl2t_ST0(void)
1873
{
1874
    ST0 = *(CPU86_LDouble *)&f15rk[6];
1875
}
1876

    
1877
void OPPROTO op_fldl2e_ST0(void)
1878
{
1879
    ST0 = *(CPU86_LDouble *)&f15rk[5];
1880
}
1881

    
1882
void OPPROTO op_fldpi_ST0(void)
1883
{
1884
    ST0 = *(CPU86_LDouble *)&f15rk[2];
1885
}
1886

    
1887
void OPPROTO op_fldlg2_ST0(void)
1888
{
1889
    ST0 = *(CPU86_LDouble *)&f15rk[3];
1890
}
1891

    
1892
void OPPROTO op_fldln2_ST0(void)
1893
{
1894
    ST0 = *(CPU86_LDouble *)&f15rk[4];
1895
}
1896

    
1897
void OPPROTO op_fldz_ST0(void)
1898
{
1899
    ST0 = *(CPU86_LDouble *)&f15rk[0];
1900
}
1901

    
1902
void OPPROTO op_fldz_FT0(void)
1903
{
1904
    ST0 = *(CPU86_LDouble *)&f15rk[0];
1905
}
1906

    
1907
void helper_f2xm1(void)
1908
{
1909
    ST0 = pow(2.0,ST0) - 1.0;
1910
}
1911

    
1912
void helper_fyl2x(void)
1913
{
1914
    CPU86_LDouble fptemp;
1915
    
1916
    fptemp = ST0;
1917
    if (fptemp>0.0){
1918
        fptemp = log(fptemp)/log(2.0);         /* log2(ST) */
1919
        ST1 *= fptemp;
1920
        fpop();
1921
    } else { 
1922
        env->fpus &= (~0x4700);
1923
        env->fpus |= 0x400;
1924
    }
1925
}
1926

    
1927
void helper_fptan(void)
1928
{
1929
    CPU86_LDouble fptemp;
1930

    
1931
    fptemp = ST0;
1932
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1933
        env->fpus |= 0x400;
1934
    } else {
1935
        ST0 = tan(fptemp);
1936
        fpush();
1937
        ST0 = 1.0;
1938
        env->fpus &= (~0x400);  /* C2 <-- 0 */
1939
        /* the above code is for  |arg| < 2**52 only */
1940
    }
1941
}
1942

    
1943
void helper_fpatan(void)
1944
{
1945
    CPU86_LDouble fptemp, fpsrcop;
1946

    
1947
    fpsrcop = ST1;
1948
    fptemp = ST0;
1949
    ST1 = atan2(fpsrcop,fptemp);
1950
    fpop();
1951
}
1952

    
1953
void helper_fxtract(void)
1954
{
1955
    CPU86_LDoubleU temp;
1956
    unsigned int expdif;
1957

    
1958
    temp.d = ST0;
1959
    expdif = EXPD(temp) - EXPBIAS;
1960
    /*DP exponent bias*/
1961
    ST0 = expdif;
1962
    fpush();
1963
    BIASEXPONENT(temp);
1964
    ST0 = temp.d;
1965
}
1966

    
1967
void helper_fprem1(void)
1968
{
1969
    CPU86_LDouble dblq, fpsrcop, fptemp;
1970
    CPU86_LDoubleU fpsrcop1, fptemp1;
1971
    int expdif;
1972
    int q;
1973

    
1974
    fpsrcop = ST0;
1975
    fptemp = ST1;
1976
    fpsrcop1.d = fpsrcop;
1977
    fptemp1.d = fptemp;
1978
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
1979
    if (expdif < 53) {
1980
        dblq = fpsrcop / fptemp;
1981
        dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
1982
        ST0 = fpsrcop - fptemp*dblq;
1983
        q = (int)dblq; /* cutting off top bits is assumed here */
1984
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1985
                                /* (C0,C1,C3) <-- (q2,q1,q0) */
1986
        env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
1987
        env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
1988
        env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
1989
    } else {
1990
        env->fpus |= 0x400;  /* C2 <-- 1 */
1991
        fptemp = pow(2.0, expdif-50);
1992
        fpsrcop = (ST0 / ST1) / fptemp;
1993
        /* fpsrcop = integer obtained by rounding to the nearest */
1994
        fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
1995
            floor(fpsrcop): ceil(fpsrcop);
1996
        ST0 -= (ST1 * fpsrcop * fptemp);
1997
    }
1998
}
1999

    
2000
void helper_fprem(void)
2001
{
2002
    CPU86_LDouble dblq, fpsrcop, fptemp;
2003
    CPU86_LDoubleU fpsrcop1, fptemp1;
2004
    int expdif;
2005
    int q;
2006
    
2007
    fpsrcop = ST0;
2008
    fptemp = ST1;
2009
    fpsrcop1.d = fpsrcop;
2010
    fptemp1.d = fptemp;
2011
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
2012
    if ( expdif < 53 ) {
2013
        dblq = fpsrcop / fptemp;
2014
        dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
2015
        ST0 = fpsrcop - fptemp*dblq;
2016
        q = (int)dblq; /* cutting off top bits is assumed here */
2017
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
2018
                                /* (C0,C1,C3) <-- (q2,q1,q0) */
2019
        env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
2020
        env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
2021
        env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
2022
    } else {
2023
        env->fpus |= 0x400;  /* C2 <-- 1 */
2024
        fptemp = pow(2.0, expdif-50);
2025
        fpsrcop = (ST0 / ST1) / fptemp;
2026
        /* fpsrcop = integer obtained by chopping */
2027
        fpsrcop = (fpsrcop < 0.0)?
2028
            -(floor(fabs(fpsrcop))): floor(fpsrcop);
2029
        ST0 -= (ST1 * fpsrcop * fptemp);
2030
    }
2031
}
2032

    
2033
void helper_fyl2xp1(void)
2034
{
2035
    CPU86_LDouble fptemp;
2036

    
2037
    fptemp = ST0;
2038
    if ((fptemp+1.0)>0.0) {
2039
        fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
2040
        ST1 *= fptemp;
2041
        fpop();
2042
    } else { 
2043
        env->fpus &= (~0x4700);
2044
        env->fpus |= 0x400;
2045
    }
2046
}
2047

    
2048
void helper_fsqrt(void)
2049
{
2050
    CPU86_LDouble fptemp;
2051

    
2052
    fptemp = ST0;
2053
    if (fptemp<0.0) { 
2054
        env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
2055
        env->fpus |= 0x400;
2056
    }
2057
    ST0 = sqrt(fptemp);
2058
}
2059

    
2060
void helper_fsincos(void)
2061
{
2062
    CPU86_LDouble fptemp;
2063

    
2064
    fptemp = ST0;
2065
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2066
        env->fpus |= 0x400;
2067
    } else {
2068
        ST0 = sin(fptemp);
2069
        fpush();
2070
        ST0 = cos(fptemp);
2071
        env->fpus &= (~0x400);  /* C2 <-- 0 */
2072
        /* the above code is for  |arg| < 2**63 only */
2073
    }
2074
}
2075

    
2076
void helper_frndint(void)
2077
{
2078
    ST0 = rint(ST0);
2079
}
2080

    
2081
void helper_fscale(void)
2082
{
2083
    CPU86_LDouble fpsrcop, fptemp;
2084

    
2085
    fpsrcop = 2.0;
2086
    fptemp = pow(fpsrcop,ST1);
2087
    ST0 *= fptemp;
2088
}
2089

    
2090
void helper_fsin(void)
2091
{
2092
    CPU86_LDouble fptemp;
2093

    
2094
    fptemp = ST0;
2095
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2096
        env->fpus |= 0x400;
2097
    } else {
2098
        ST0 = sin(fptemp);
2099
        env->fpus &= (~0x400);  /* C2 <-- 0 */
2100
        /* the above code is for  |arg| < 2**53 only */
2101
    }
2102
}
2103

    
2104
void helper_fcos(void)
2105
{
2106
    CPU86_LDouble fptemp;
2107

    
2108
    fptemp = ST0;
2109
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2110
        env->fpus |= 0x400;
2111
    } else {
2112
        ST0 = cos(fptemp);
2113
        env->fpus &= (~0x400);  /* C2 <-- 0 */
2114
        /* the above code is for  |arg5 < 2**63 only */
2115
    }
2116
}
2117

    
2118
/* associated heplers to reduce generated code length and to simplify
2119
   relocation (FP constants are usually stored in .rodata section) */
2120

    
2121
void OPPROTO op_f2xm1(void)
2122
{
2123
    helper_f2xm1();
2124
}
2125

    
2126
void OPPROTO op_fyl2x(void)
2127
{
2128
    helper_fyl2x();
2129
}
2130

    
2131
void OPPROTO op_fptan(void)
2132
{
2133
    helper_fptan();
2134
}
2135

    
2136
void OPPROTO op_fpatan(void)
2137
{
2138
    helper_fpatan();
2139
}
2140

    
2141
void OPPROTO op_fxtract(void)
2142
{
2143
    helper_fxtract();
2144
}
2145

    
2146
void OPPROTO op_fprem1(void)
2147
{
2148
    helper_fprem1();
2149
}
2150

    
2151

    
2152
void OPPROTO op_fprem(void)
2153
{
2154
    helper_fprem();
2155
}
2156

    
2157
void OPPROTO op_fyl2xp1(void)
2158
{
2159
    helper_fyl2xp1();
2160
}
2161

    
2162
void OPPROTO op_fsqrt(void)
2163
{
2164
    helper_fsqrt();
2165
}
2166

    
2167
void OPPROTO op_fsincos(void)
2168
{
2169
    helper_fsincos();
2170
}
2171

    
2172
void OPPROTO op_frndint(void)
2173
{
2174
    helper_frndint();
2175
}
2176

    
2177
void OPPROTO op_fscale(void)
2178
{
2179
    helper_fscale();
2180
}
2181

    
2182
void OPPROTO op_fsin(void)
2183
{
2184
    helper_fsin();
2185
}
2186

    
2187
void OPPROTO op_fcos(void)
2188
{
2189
    helper_fcos();
2190
}
2191

    
2192
void OPPROTO op_fnstsw_A0(void)
2193
{
2194
    int fpus;
2195
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2196
    stw((void *)A0, fpus);
2197
}
2198

    
2199
void OPPROTO op_fnstsw_EAX(void)
2200
{
2201
    int fpus;
2202
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2203
    EAX = (EAX & 0xffff0000) | fpus;
2204
}
2205

    
2206
void OPPROTO op_fnstcw_A0(void)
2207
{
2208
    stw((void *)A0, env->fpuc);
2209
}
2210

    
2211
void OPPROTO op_fldcw_A0(void)
2212
{
2213
    int rnd_type;
2214
    env->fpuc = lduw((void *)A0);
2215
    /* set rounding mode */
2216
    switch(env->fpuc & RC_MASK) {
2217
    default:
2218
    case RC_NEAR:
2219
        rnd_type = FE_TONEAREST;
2220
        break;
2221
    case RC_DOWN:
2222
        rnd_type = FE_DOWNWARD;
2223
        break;
2224
    case RC_UP:
2225
        rnd_type = FE_UPWARD;
2226
        break;
2227
    case RC_CHOP:
2228
        rnd_type = FE_TOWARDZERO;
2229
        break;
2230
    }
2231
    fesetround(rnd_type);
2232
}
2233

    
2234
void OPPROTO op_fclex(void)
2235
{
2236
    env->fpus &= 0x7f00;
2237
}
2238

    
2239
void OPPROTO op_fninit(void)
2240
{
2241
    env->fpus = 0;
2242
    env->fpstt = 0;
2243
    env->fpuc = 0x37f;
2244
    env->fptags[0] = 1;
2245
    env->fptags[1] = 1;
2246
    env->fptags[2] = 1;
2247
    env->fptags[3] = 1;
2248
    env->fptags[4] = 1;
2249
    env->fptags[5] = 1;
2250
    env->fptags[6] = 1;
2251
    env->fptags[7] = 1;
2252
}
2253

    
2254
/* threading support */
2255
void OPPROTO op_lock(void)
2256
{
2257
    cpu_lock();
2258
}
2259

    
2260
void OPPROTO op_unlock(void)
2261
{
2262
    cpu_unlock();
2263
}