Revision 3ec9c4fc

b/exec-i386.h
190 190
#endif
191 191

  
192 192
#ifdef __alpha__
193
/* the symbols are considered non exported so a br immediate is generated */
194
#define __hidden __attribute__((visibility("hidden")))
195
#else
196
#define __hidden 
197
#endif
198

  
199
#ifdef __alpha__
193 200
/* Suggested by Richard Henderson. This will result in code like
194 201
        ldah $0,__op_param1($29)        !gprelhigh
195 202
        lda $0,__op_param1($0)          !gprellow
196 203
   We can then conveniently change $29 to $31 and adapt the offsets to
197 204
   emit the appropriate constant.  */
198
extern int __op_param1 __attribute__((visibility("hidden")));
199
extern int __op_param2 __attribute__((visibility("hidden")));
200
extern int __op_param3 __attribute__((visibility("hidden")));
205
extern int __op_param1 __hidden;
206
extern int __op_param2 __hidden;
207
extern int __op_param3 __hidden;
201 208
#define PARAM1 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_param1)); _r; })
202 209
#define PARAM2 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_param2)); _r; })
203 210
#define PARAM3 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_param3)); _r; })
......
220 227
extern CCTable cc_table[];
221 228

  
222 229
void load_seg(int seg_reg, int selector, unsigned cur_eip);
223
void cpu_lock(void);
224
void cpu_unlock(void);
230
void __hidden cpu_lock(void);
231
void __hidden cpu_unlock(void);
225 232
void raise_interrupt(int intno, int is_int, int error_code, 
226 233
                     unsigned int next_eip);
227 234
void raise_exception_err(int exception_index, int error_code);
228 235
void raise_exception(int exception_index);
229
void cpu_loop_exit(void);
236
void __hidden cpu_loop_exit(void);
230 237
void helper_fsave(uint8_t *ptr, int data32);
231 238
void helper_frstor(uint8_t *ptr, int data32);
232 239

  
233 240
void OPPROTO op_movl_eflags_T0(void);
234 241
void OPPROTO op_movl_T0_eflags(void);
242
void raise_interrupt(int intno, int is_int, int error_code, 
243
                     unsigned int next_eip);
244
void raise_exception_err(int exception_index, int error_code);
245
void raise_exception(int exception_index);
246
void helper_cpuid(void);
247
void helper_lsl(void);
248
void helper_lar(void);
249

  
250

  
251
#ifdef USE_X86LDOUBLE
252
/* use long double functions */
253
#define lrint lrintl
254
#define llrint llrintl
255
#define fabs fabsl
256
#define sin sinl
257
#define cos cosl
258
#define sqrt sqrtl
259
#define pow powl
260
#define log logl
261
#define tan tanl
262
#define atan2 atan2l
263
#define floor floorl
264
#define ceil ceill
265
#define rint rintl
266
#endif
267

  
268
extern int lrint(CPU86_LDouble x);
269
extern int64_t llrint(CPU86_LDouble x);
270
extern CPU86_LDouble fabs(CPU86_LDouble x);
271
extern CPU86_LDouble sin(CPU86_LDouble x);
272
extern CPU86_LDouble cos(CPU86_LDouble x);
273
extern CPU86_LDouble sqrt(CPU86_LDouble x);
274
extern CPU86_LDouble pow(CPU86_LDouble, CPU86_LDouble);
275
extern CPU86_LDouble log(CPU86_LDouble x);
276
extern CPU86_LDouble tan(CPU86_LDouble x);
277
extern CPU86_LDouble atan2(CPU86_LDouble, CPU86_LDouble);
278
extern CPU86_LDouble floor(CPU86_LDouble x);
279
extern CPU86_LDouble ceil(CPU86_LDouble x);
280
extern CPU86_LDouble rint(CPU86_LDouble x);
281

  
282
#define RC_MASK         0xc00
283
#define RC_NEAR		0x000
284
#define RC_DOWN		0x400
285
#define RC_UP		0x800
286
#define RC_CHOP		0xc00
287

  
288
#define MAXTAN 9223372036854775808.0
289

  
290
#ifdef USE_X86LDOUBLE
291

  
292
/* only for x86 */
293
typedef union {
294
    long double d;
295
    struct {
296
        unsigned long long lower;
297
        unsigned short upper;
298
    } l;
299
} CPU86_LDoubleU;
300

  
301
/* the following deal with x86 long double-precision numbers */
302
#define MAXEXPD 0x7fff
303
#define EXPBIAS 16383
304
#define EXPD(fp)	(fp.l.upper & 0x7fff)
305
#define SIGND(fp)	((fp.l.upper) & 0x8000)
306
#define MANTD(fp)       (fp.l.lower)
307
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
308

  
309
#else
310

  
311
typedef union {
312
    double d;
313
#ifndef WORDS_BIGENDIAN
314
    struct {
315
        uint32_t lower;
316
        int32_t upper;
317
    } l;
318
#else
319
    struct {
320
        int32_t upper;
321
        uint32_t lower;
322
    } l;
323
#endif
324
    int64_t ll;
325
} CPU86_LDoubleU;
326

  
327
/* the following deal with IEEE double-precision numbers */
328
#define MAXEXPD 0x7ff
329
#define EXPBIAS 1023
330
#define EXPD(fp)	(((fp.l.upper) >> 20) & 0x7FF)
331
#define SIGND(fp)	((fp.l.upper) & 0x80000000)
332
#define MANTD(fp)	(fp.ll & ((1LL << 52) - 1))
333
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20)
334
#endif
335

  
336
static inline void fpush(void)
337
{
338
    env->fpstt = (env->fpstt - 1) & 7;
339
    env->fptags[env->fpstt] = 0; /* validate stack entry */
340
}
341

  
342
static inline void fpop(void)
343
{
344
    env->fptags[env->fpstt] = 1; /* invvalidate stack entry */
345
    env->fpstt = (env->fpstt + 1) & 7;
346
}
347

  
348
#ifndef USE_X86LDOUBLE
349
static inline CPU86_LDouble helper_fldt(uint8_t *ptr)
350
{
351
    CPU86_LDoubleU temp;
352
    int upper, e;
353
    /* mantissa */
354
    upper = lduw(ptr + 8);
355
    /* XXX: handle overflow ? */
356
    e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
357
    e |= (upper >> 4) & 0x800; /* sign */
358
    temp.ll = ((ldq(ptr) >> 11) & ((1LL << 52) - 1)) | ((uint64_t)e << 52);
359
    return temp.d;
360
}
361

  
362
static inline void helper_fstt(CPU86_LDouble f, uint8_t *ptr)
363
{
364
    CPU86_LDoubleU temp;
365
    int e;
366
    temp.d = f;
367
    /* mantissa */
368
    stq(ptr, (MANTD(temp) << 11) | (1LL << 63));
369
    /* exponent + sign */
370
    e = EXPD(temp) - EXPBIAS + 16383;
371
    e |= SIGND(temp) >> 16;
372
    stw(ptr + 8, e);
373
}
374
#endif
375

  
376
void helper_fldt_ST0_A0(void);
377
void helper_fstt_ST0_A0(void);
378
void helper_fbld_ST0_A0(void);
379
void helper_fbst_ST0_A0(void);
380
void helper_f2xm1(void);
381
void helper_fyl2x(void);
382
void helper_fptan(void);
383
void helper_fpatan(void);
384
void helper_fxtract(void);
385
void helper_fprem1(void);
386
void helper_fprem(void);
387
void helper_fyl2xp1(void);
388
void helper_fsqrt(void);
389
void helper_fsincos(void);
390
void helper_frndint(void);
391
void helper_fscale(void);
392
void helper_fsin(void);
393
void helper_fcos(void);
394
void helper_fxam_ST0(void);
395
void helper_fstenv(uint8_t *ptr, int data32);
396
void helper_fldenv(uint8_t *ptr, int data32);
397
void helper_fsave(uint8_t *ptr, int data32);
398
void helper_frstor(uint8_t *ptr, int data32);
399

  
b/helper-i386.c
1
/*
2
 *  i386 helpers
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
#if 0
23
/* full interrupt support (only useful for real CPU emulation, not
24
   finished) - I won't do it any time soon, finish it if you want ! */
25
void raise_interrupt(int intno, int is_int, int error_code, 
26
                     unsigned int next_eip)
27
{
28
    SegmentDescriptorTable *dt;
29
    uint8_t *ptr;
30
    int type, dpl, cpl;
31
    uint32_t e1, e2;
32
    
33
    dt = &env->idt;
34
    if (intno * 8 + 7 > dt->limit)
35
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
36
    ptr = dt->base + intno * 8;
37
    e1 = ldl(ptr);
38
    e2 = ldl(ptr + 4);
39
    /* check gate type */
40
    type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
41
    switch(type) {
42
    case 5: /* task gate */
43
    case 6: /* 286 interrupt gate */
44
    case 7: /* 286 trap gate */
45
    case 14: /* 386 interrupt gate */
46
    case 15: /* 386 trap gate */
47
        break;
48
    default:
49
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
50
        break;
51
    }
52
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
53
    cpl = env->segs[R_CS] & 3;
54
    /* check privledge if software int */
55
    if (is_int && dpl < cpl)
56
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
57
    /* check valid bit */
58
    if (!(e2 & DESC_P_MASK))
59
        raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
60
}
61

  
62
#else
63

  
64
/*
65
 * is_int is TRUE if coming from the int instruction. next_eip is the
66
 * EIP value AFTER the interrupt instruction. It is only relevant if
67
 * is_int is TRUE.  
68
 */
69
void raise_interrupt(int intno, int is_int, int error_code, 
70
                     unsigned int next_eip)
71
{
72
    SegmentDescriptorTable *dt;
73
    uint8_t *ptr;
74
    int dpl, cpl;
75
    uint32_t e2;
76

  
77
    dt = &env->idt;
78
    ptr = dt->base + (intno * 8);
79
    e2 = ldl(ptr + 4);
80
    
81
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
82
    cpl = 3;
83
    /* check privledge if software int */
84
    if (is_int && dpl < cpl)
85
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
86

  
87
    /* Since we emulate only user space, we cannot do more than
88
       exiting the emulation with the suitable exception and error
89
       code */
90
    if (is_int)
91
        EIP = next_eip;
92
    env->exception_index = intno;
93
    env->error_code = error_code;
94

  
95
    cpu_loop_exit();
96
}
97

  
98
#endif
99

  
100
/* shortcuts to generate exceptions */
101
void raise_exception_err(int exception_index, int error_code)
102
{
103
    raise_interrupt(exception_index, 0, error_code, 0);
104
}
105

  
106
void raise_exception(int exception_index)
107
{
108
    raise_interrupt(exception_index, 0, 0, 0);
109
}
110

  
111
/* We simulate a pre-MMX pentium as in valgrind */
112
#define CPUID_FP87 (1 << 0)
113
#define CPUID_VME  (1 << 1)
114
#define CPUID_DE   (1 << 2)
115
#define CPUID_PSE  (1 << 3)
116
#define CPUID_TSC  (1 << 4)
117
#define CPUID_MSR  (1 << 5)
118
#define CPUID_PAE  (1 << 6)
119
#define CPUID_MCE  (1 << 7)
120
#define CPUID_CX8  (1 << 8)
121
#define CPUID_APIC (1 << 9)
122
#define CPUID_SEP  (1 << 11) /* sysenter/sysexit */
123
#define CPUID_MTRR (1 << 12)
124
#define CPUID_PGE  (1 << 13)
125
#define CPUID_MCA  (1 << 14)
126
#define CPUID_CMOV (1 << 15)
127
/* ... */
128
#define CPUID_MMX  (1 << 23)
129
#define CPUID_FXSR (1 << 24)
130
#define CPUID_SSE  (1 << 25)
131
#define CPUID_SSE2 (1 << 26)
132

  
133
void helper_cpuid(void)
134
{
135
    if (EAX == 0) {
136
        EAX = 1; /* max EAX index supported */
137
        EBX = 0x756e6547;
138
        ECX = 0x6c65746e;
139
        EDX = 0x49656e69;
140
    } else if (EAX == 1) {
141
        /* EAX = 1 info */
142
        EAX = 0x52b;
143
        EBX = 0;
144
        ECX = 0;
145
        EDX = CPUID_FP87 | CPUID_DE | CPUID_PSE |
146
            CPUID_TSC | CPUID_MSR | CPUID_MCE |
147
            CPUID_CX8;
148
    }
149
}
150

  
151
/* only works if protected mode and not VM86 */
152
void load_seg(int seg_reg, int selector, unsigned cur_eip)
153
{
154
    SegmentCache *sc;
155
    SegmentDescriptorTable *dt;
156
    int index;
157
    uint32_t e1, e2;
158
    uint8_t *ptr;
159

  
160
    sc = &env->seg_cache[seg_reg];
161
    if ((selector & 0xfffc) == 0) {
162
        /* null selector case */
163
        if (seg_reg == R_SS) {
164
            EIP = cur_eip;
165
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
166
        } else {
167
            /* XXX: each access should trigger an exception */
168
            sc->base = NULL;
169
            sc->limit = 0;
170
            sc->seg_32bit = 1;
171
        }
172
    } else {
173
        if (selector & 0x4)
174
            dt = &env->ldt;
175
        else
176
            dt = &env->gdt;
177
        index = selector & ~7;
178
        if ((index + 7) > dt->limit) {
179
            EIP = cur_eip;
180
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
181
        }
182
        ptr = dt->base + index;
183
        e1 = ldl(ptr);
184
        e2 = ldl(ptr + 4);
185
        if (!(e2 & DESC_S_MASK) ||
186
            (e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) {
187
            EIP = cur_eip;
188
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
189
        }
190

  
191
        if (seg_reg == R_SS) {
192
            if ((e2 & (DESC_CS_MASK | DESC_W_MASK)) == 0) {
193
                EIP = cur_eip;
194
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
195
            }
196
        } else {
197
            if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) {
198
                EIP = cur_eip;
199
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
200
            }
201
        }
202

  
203
        if (!(e2 & DESC_P_MASK)) {
204
            EIP = cur_eip;
205
            if (seg_reg == R_SS)
206
                raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
207
            else
208
                raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
209
        }
210
        
211
        sc->base = (void *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
212
        sc->limit = (e1 & 0xffff) | (e2 & 0x000f0000);
213
        if (e2 & (1 << 23))
214
            sc->limit = (sc->limit << 12) | 0xfff;
215
        sc->seg_32bit = (e2 >> 22) & 1;
216
#if 0
217
        fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n", 
218
                selector, (unsigned long)sc->base, sc->limit, sc->seg_32bit);
219
#endif
220
    }
221
    env->segs[seg_reg] = selector;
222
}
223

  
224
void helper_lsl(void)
225
{
226
    unsigned int selector, limit;
227
    SegmentDescriptorTable *dt;
228
    int index;
229
    uint32_t e1, e2;
230
    uint8_t *ptr;
231

  
232
    CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
233
    selector = T0 & 0xffff;
234
    if (selector & 0x4)
235
        dt = &env->ldt;
236
    else
237
        dt = &env->gdt;
238
    index = selector & ~7;
239
    if ((index + 7) > dt->limit)
240
        return;
241
    ptr = dt->base + index;
242
    e1 = ldl(ptr);
243
    e2 = ldl(ptr + 4);
244
    limit = (e1 & 0xffff) | (e2 & 0x000f0000);
245
    if (e2 & (1 << 23))
246
        limit = (limit << 12) | 0xfff;
247
    T1 = limit;
248
    CC_SRC |= CC_Z;
249
}
250

  
251
void helper_lar(void)
252
{
253
    unsigned int selector;
254
    SegmentDescriptorTable *dt;
255
    int index;
256
    uint32_t e2;
257
    uint8_t *ptr;
258

  
259
    CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
260
    selector = T0 & 0xffff;
261
    if (selector & 0x4)
262
        dt = &env->ldt;
263
    else
264
        dt = &env->gdt;
265
    index = selector & ~7;
266
    if ((index + 7) > dt->limit)
267
        return;
268
    ptr = dt->base + index;
269
    e2 = ldl(ptr + 4);
270
    T1 = e2 & 0x00f0ff00;
271
    CC_SRC |= CC_Z;
272
}
273

  
274
/* FPU helpers */
275

  
276
#ifndef USE_X86LDOUBLE
277
void helper_fldt_ST0_A0(void)
278
{
279
    ST0 = helper_fldt((uint8_t *)A0);
280
}
281

  
282
void helper_fstt_ST0_A0(void)
283
{
284
    helper_fstt(ST0, (uint8_t *)A0);
285
}
286
#endif
287

  
288
/* BCD ops */
289

  
290
#define MUL10(iv) ( iv + iv + (iv << 3) )
291

  
292
void helper_fbld_ST0_A0(void)
293
{
294
    uint8_t *seg;
295
    CPU86_LDouble fpsrcop;
296
    int m32i;
297
    unsigned int v;
298

  
299
    /* in this code, seg/m32i will be used as temporary ptr/int */
300
    seg = (uint8_t *)A0 + 8;
301
    v = ldub(seg--);
302
    /* XXX: raise exception */
303
    if (v != 0)
304
        return;
305
    v = ldub(seg--);
306
    /* XXX: raise exception */
307
    if ((v & 0xf0) != 0)
308
        return;
309
    m32i = v;  /* <-- d14 */
310
    v = ldub(seg--);
311
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d13 */
312
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d12 */
313
    v = ldub(seg--);
314
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d11 */
315
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d10 */
316
    v = ldub(seg--);
317
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d9 */
318
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d8 */
319
    fpsrcop = ((CPU86_LDouble)m32i) * 100000000.0;
320

  
321
    v = ldub(seg--);
322
    m32i = (v >> 4);  /* <-- d7 */
323
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d6 */
324
    v = ldub(seg--);
325
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d5 */
326
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d4 */
327
    v = ldub(seg--);
328
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d3 */
329
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d2 */
330
    v = ldub(seg);
331
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d1 */
332
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d0 */
333
    fpsrcop += ((CPU86_LDouble)m32i);
334
    if ( ldub(seg+9) & 0x80 )
335
        fpsrcop = -fpsrcop;
336
    ST0 = fpsrcop;
337
}
338

  
339
void helper_fbst_ST0_A0(void)
340
{
341
    CPU86_LDouble fptemp;
342
    CPU86_LDouble fpsrcop;
343
    int v;
344
    uint8_t *mem_ref, *mem_end;
345

  
346
    fpsrcop = rint(ST0);
347
    mem_ref = (uint8_t *)A0;
348
    mem_end = mem_ref + 8;
349
    if ( fpsrcop < 0.0 ) {
350
        stw(mem_end, 0x8000);
351
        fpsrcop = -fpsrcop;
352
    } else {
353
        stw(mem_end, 0x0000);
354
    }
355
    while (mem_ref < mem_end) {
356
        if (fpsrcop == 0.0)
357
            break;
358
        fptemp = floor(fpsrcop/10.0);
359
        v = ((int)(fpsrcop - fptemp*10.0));
360
        if  (fptemp == 0.0)  { 
361
            stb(mem_ref++, v); 
362
            break; 
363
        }
364
        fpsrcop = fptemp;
365
        fptemp = floor(fpsrcop/10.0);
366
        v |= (((int)(fpsrcop - fptemp*10.0)) << 4);
367
        stb(mem_ref++, v);
368
        fpsrcop = fptemp;
369
    }
370
    while (mem_ref < mem_end) {
371
        stb(mem_ref++, 0);
372
    }
373
}
374

  
375
void helper_f2xm1(void)
376
{
377
    ST0 = pow(2.0,ST0) - 1.0;
378
}
379

  
380
void helper_fyl2x(void)
381
{
382
    CPU86_LDouble fptemp;
383
    
384
    fptemp = ST0;
385
    if (fptemp>0.0){
386
        fptemp = log(fptemp)/log(2.0);	 /* log2(ST) */
387
        ST1 *= fptemp;
388
        fpop();
389
    } else { 
390
        env->fpus &= (~0x4700);
391
        env->fpus |= 0x400;
392
    }
393
}
394

  
395
void helper_fptan(void)
396
{
397
    CPU86_LDouble fptemp;
398

  
399
    fptemp = ST0;
400
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
401
        env->fpus |= 0x400;
402
    } else {
403
        ST0 = tan(fptemp);
404
        fpush();
405
        ST0 = 1.0;
406
        env->fpus &= (~0x400);  /* C2 <-- 0 */
407
        /* the above code is for  |arg| < 2**52 only */
408
    }
409
}
410

  
411
void helper_fpatan(void)
412
{
413
    CPU86_LDouble fptemp, fpsrcop;
414

  
415
    fpsrcop = ST1;
416
    fptemp = ST0;
417
    ST1 = atan2(fpsrcop,fptemp);
418
    fpop();
419
}
420

  
421
void helper_fxtract(void)
422
{
423
    CPU86_LDoubleU temp;
424
    unsigned int expdif;
425

  
426
    temp.d = ST0;
427
    expdif = EXPD(temp) - EXPBIAS;
428
    /*DP exponent bias*/
429
    ST0 = expdif;
430
    fpush();
431
    BIASEXPONENT(temp);
432
    ST0 = temp.d;
433
}
434

  
435
void helper_fprem1(void)
436
{
437
    CPU86_LDouble dblq, fpsrcop, fptemp;
438
    CPU86_LDoubleU fpsrcop1, fptemp1;
439
    int expdif;
440
    int q;
441

  
442
    fpsrcop = ST0;
443
    fptemp = ST1;
444
    fpsrcop1.d = fpsrcop;
445
    fptemp1.d = fptemp;
446
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
447
    if (expdif < 53) {
448
        dblq = fpsrcop / fptemp;
449
        dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
450
        ST0 = fpsrcop - fptemp*dblq;
451
        q = (int)dblq; /* cutting off top bits is assumed here */
452
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
453
				/* (C0,C1,C3) <-- (q2,q1,q0) */
454
        env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
455
        env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
456
        env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
457
    } else {
458
        env->fpus |= 0x400;  /* C2 <-- 1 */
459
        fptemp = pow(2.0, expdif-50);
460
        fpsrcop = (ST0 / ST1) / fptemp;
461
        /* fpsrcop = integer obtained by rounding to the nearest */
462
        fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
463
            floor(fpsrcop): ceil(fpsrcop);
464
        ST0 -= (ST1 * fpsrcop * fptemp);
465
    }
466
}
467

  
468
void helper_fprem(void)
469
{
470
    CPU86_LDouble dblq, fpsrcop, fptemp;
471
    CPU86_LDoubleU fpsrcop1, fptemp1;
472
    int expdif;
473
    int q;
474
    
475
    fpsrcop = ST0;
476
    fptemp = ST1;
477
    fpsrcop1.d = fpsrcop;
478
    fptemp1.d = fptemp;
479
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
480
    if ( expdif < 53 ) {
481
        dblq = fpsrcop / fptemp;
482
        dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
483
        ST0 = fpsrcop - fptemp*dblq;
484
        q = (int)dblq; /* cutting off top bits is assumed here */
485
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
486
				/* (C0,C1,C3) <-- (q2,q1,q0) */
487
        env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
488
        env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
489
        env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
490
    } else {
491
        env->fpus |= 0x400;  /* C2 <-- 1 */
492
        fptemp = pow(2.0, expdif-50);
493
        fpsrcop = (ST0 / ST1) / fptemp;
494
        /* fpsrcop = integer obtained by chopping */
495
        fpsrcop = (fpsrcop < 0.0)?
496
            -(floor(fabs(fpsrcop))): floor(fpsrcop);
497
        ST0 -= (ST1 * fpsrcop * fptemp);
498
    }
499
}
500

  
501
void helper_fyl2xp1(void)
502
{
503
    CPU86_LDouble fptemp;
504

  
505
    fptemp = ST0;
506
    if ((fptemp+1.0)>0.0) {
507
        fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
508
        ST1 *= fptemp;
509
        fpop();
510
    } else { 
511
        env->fpus &= (~0x4700);
512
        env->fpus |= 0x400;
513
    }
514
}
515

  
516
void helper_fsqrt(void)
517
{
518
    CPU86_LDouble fptemp;
519

  
520
    fptemp = ST0;
521
    if (fptemp<0.0) { 
522
        env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
523
        env->fpus |= 0x400;
524
    }
525
    ST0 = sqrt(fptemp);
526
}
527

  
528
void helper_fsincos(void)
529
{
530
    CPU86_LDouble fptemp;
531

  
532
    fptemp = ST0;
533
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
534
        env->fpus |= 0x400;
535
    } else {
536
        ST0 = sin(fptemp);
537
        fpush();
538
        ST0 = cos(fptemp);
539
        env->fpus &= (~0x400);  /* C2 <-- 0 */
540
        /* the above code is for  |arg| < 2**63 only */
541
    }
542
}
543

  
544
void helper_frndint(void)
545
{
546
    ST0 = rint(ST0);
547
}
548

  
549
void helper_fscale(void)
550
{
551
    CPU86_LDouble fpsrcop, fptemp;
552

  
553
    fpsrcop = 2.0;
554
    fptemp = pow(fpsrcop,ST1);
555
    ST0 *= fptemp;
556
}
557

  
558
void helper_fsin(void)
559
{
560
    CPU86_LDouble fptemp;
561

  
562
    fptemp = ST0;
563
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
564
        env->fpus |= 0x400;
565
    } else {
566
        ST0 = sin(fptemp);
567
        env->fpus &= (~0x400);  /* C2 <-- 0 */
568
        /* the above code is for  |arg| < 2**53 only */
569
    }
570
}
571

  
572
void helper_fcos(void)
573
{
574
    CPU86_LDouble fptemp;
575

  
576
    fptemp = ST0;
577
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
578
        env->fpus |= 0x400;
579
    } else {
580
        ST0 = cos(fptemp);
581
        env->fpus &= (~0x400);  /* C2 <-- 0 */
582
        /* the above code is for  |arg5 < 2**63 only */
583
    }
584
}
585

  
586
void helper_fxam_ST0(void)
587
{
588
    CPU86_LDoubleU temp;
589
    int expdif;
590

  
591
    temp.d = ST0;
592

  
593
    env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
594
    if (SIGND(temp))
595
        env->fpus |= 0x200; /* C1 <-- 1 */
596

  
597
    expdif = EXPD(temp);
598
    if (expdif == MAXEXPD) {
599
        if (MANTD(temp) == 0)
600
            env->fpus |=  0x500 /*Infinity*/;
601
        else
602
            env->fpus |=  0x100 /*NaN*/;
603
    } else if (expdif == 0) {
604
        if (MANTD(temp) == 0)
605
            env->fpus |=  0x4000 /*Zero*/;
606
        else
607
            env->fpus |= 0x4400 /*Denormal*/;
608
    } else {
609
        env->fpus |= 0x400;
610
    }
611
}
612

  
613
void helper_fstenv(uint8_t *ptr, int data32)
614
{
615
    int fpus, fptag, exp, i;
616
    uint64_t mant;
617
    CPU86_LDoubleU tmp;
618

  
619
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
620
    fptag = 0;
621
    for (i=7; i>=0; i--) {
622
	fptag <<= 2;
623
	if (env->fptags[i]) {
624
            fptag |= 3;
625
	} else {
626
            tmp.d = env->fpregs[i];
627
            exp = EXPD(tmp);
628
            mant = MANTD(tmp);
629
            if (exp == 0 && mant == 0) {
630
                /* zero */
631
	        fptag |= 1;
632
	    } else if (exp == 0 || exp == MAXEXPD
633
#ifdef USE_X86LDOUBLE
634
                       || (mant & (1LL << 63)) == 0
635
#endif
636
                       ) {
637
                /* NaNs, infinity, denormal */
638
                fptag |= 2;
639
            }
640
        }
641
    }
642
    if (data32) {
643
        /* 32 bit */
644
        stl(ptr, env->fpuc);
645
        stl(ptr + 4, fpus);
646
        stl(ptr + 8, fptag);
647
        stl(ptr + 12, 0);
648
        stl(ptr + 16, 0);
649
        stl(ptr + 20, 0);
650
        stl(ptr + 24, 0);
651
    } else {
652
        /* 16 bit */
653
        stw(ptr, env->fpuc);
654
        stw(ptr + 2, fpus);
655
        stw(ptr + 4, fptag);
656
        stw(ptr + 6, 0);
657
        stw(ptr + 8, 0);
658
        stw(ptr + 10, 0);
659
        stw(ptr + 12, 0);
660
    }
661
}
662

  
663
void helper_fldenv(uint8_t *ptr, int data32)
664
{
665
    int i, fpus, fptag;
666

  
667
    if (data32) {
668
	env->fpuc = lduw(ptr);
669
        fpus = lduw(ptr + 4);
670
        fptag = lduw(ptr + 8);
671
    }
672
    else {
673
	env->fpuc = lduw(ptr);
674
        fpus = lduw(ptr + 2);
675
        fptag = lduw(ptr + 4);
676
    }
677
    env->fpstt = (fpus >> 11) & 7;
678
    env->fpus = fpus & ~0x3800;
679
    for(i = 0;i < 7; i++) {
680
        env->fptags[i] = ((fptag & 3) == 3);
681
        fptag >>= 2;
682
    }
683
}
684

  
685
void helper_fsave(uint8_t *ptr, int data32)
686
{
687
    CPU86_LDouble tmp;
688
    int i;
689

  
690
    helper_fstenv(ptr, data32);
691

  
692
    ptr += (14 << data32);
693
    for(i = 0;i < 8; i++) {
694
        tmp = ST(i);
695
#ifdef USE_X86LDOUBLE
696
        *(long double *)ptr = tmp;
697
#else
698
        helper_fstt(tmp, ptr);
699
#endif        
700
        ptr += 10;
701
    }
702

  
703
    /* fninit */
704
    env->fpus = 0;
705
    env->fpstt = 0;
706
    env->fpuc = 0x37f;
707
    env->fptags[0] = 1;
708
    env->fptags[1] = 1;
709
    env->fptags[2] = 1;
710
    env->fptags[3] = 1;
711
    env->fptags[4] = 1;
712
    env->fptags[5] = 1;
713
    env->fptags[6] = 1;
714
    env->fptags[7] = 1;
715
}
716

  
717
void helper_frstor(uint8_t *ptr, int data32)
718
{
719
    CPU86_LDouble tmp;
720
    int i;
721

  
722
    helper_fldenv(ptr, data32);
723
    ptr += (14 << data32);
724

  
725
    for(i = 0;i < 8; i++) {
726
#ifdef USE_X86LDOUBLE
727
        tmp = *(long double *)ptr;
728
#else
729
        tmp = helper_fldt(ptr);
730
#endif        
731
        ST(i) = tmp;
732
        ptr += 10;
733
    }
734
}
735

  
b/op-i386.c
626 626
    EIP = PARAM1;
627 627
}
628 628

  
629
#if 0
630
/* full interrupt support (only useful for real CPU emulation, not
631
   finished) - I won't do it any time soon, finish it if you want ! */
632
void raise_interrupt(int intno, int is_int, int error_code, 
633
                     unsigned int next_eip)
634
{
635
    SegmentDescriptorTable *dt;
636
    uint8_t *ptr;
637
    int type, dpl, cpl;
638
    uint32_t e1, e2;
639
    
640
    dt = &env->idt;
641
    if (intno * 8 + 7 > dt->limit)
642
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
643
    ptr = dt->base + intno * 8;
644
    e1 = ldl(ptr);
645
    e2 = ldl(ptr + 4);
646
    /* check gate type */
647
    type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
648
    switch(type) {
649
    case 5: /* task gate */
650
    case 6: /* 286 interrupt gate */
651
    case 7: /* 286 trap gate */
652
    case 14: /* 386 interrupt gate */
653
    case 15: /* 386 trap gate */
654
        break;
655
    default:
656
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
657
        break;
658
    }
659
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
660
    cpl = env->segs[R_CS] & 3;
661
    /* check privledge if software int */
662
    if (is_int && dpl < cpl)
663
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
664
    /* check valid bit */
665
    if (!(e2 & DESC_P_MASK))
666
        raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
667
}
668

  
669
#else
670

  
671
/*
672
 * is_int is TRUE if coming from the int instruction. next_eip is the
673
 * EIP value AFTER the interrupt instruction. It is only relevant if
674
 * is_int is TRUE.  
675
 */
676
void raise_interrupt(int intno, int is_int, int error_code, 
677
                     unsigned int next_eip)
678
{
679
    SegmentDescriptorTable *dt;
680
    uint8_t *ptr;
681
    int dpl, cpl;
682
    uint32_t e2;
683

  
684
    dt = &env->idt;
685
    ptr = dt->base + (intno * 8);
686
    e2 = ldl(ptr + 4);
687
    
688
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
689
    cpl = 3;
690
    /* check privledge if software int */
691
    if (is_int && dpl < cpl)
692
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
693

  
694
    /* Since we emulate only user space, we cannot do more than
695
       exiting the emulation with the suitable exception and error
696
       code */
697
    if (is_int)
698
        EIP = next_eip;
699
    env->exception_index = intno;
700
    env->error_code = error_code;
701

  
702
    cpu_loop_exit();
703
}
704

  
705
#endif
706

  
707
/* shortcuts to generate exceptions */
708
void raise_exception_err(int exception_index, int error_code)
709
{
710
    raise_interrupt(exception_index, 0, error_code, 0);
711
}
712

  
713
void raise_exception(int exception_index)
714
{
715
    raise_interrupt(exception_index, 0, 0, 0);
716
}
717

  
718 629
void OPPROTO op_raise_interrupt(void)
719 630
{
720 631
    int intno;
......
833 744
#define JUMP_TB(tbparam, n, eip)\
834 745
do {\
835 746
    static void __attribute__((unused)) *__op_label ## n = &&label ## n;\
836
    goto *((TranslationBlock *)tbparam)->tb_next[n];\
747
    goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\
837 748
label ## n:\
838 749
    T0 = (long)(tbparam) + (n);\
839 750
    EIP = eip;\
......
1044 955
    EDX = val >> 32;
1045 956
}
1046 957

  
1047
/* We simulate a pre-MMX pentium as in valgrind */
1048
#define CPUID_FP87 (1 << 0)
1049
#define CPUID_VME  (1 << 1)
1050
#define CPUID_DE   (1 << 2)
1051
#define CPUID_PSE  (1 << 3)
1052
#define CPUID_TSC  (1 << 4)
1053
#define CPUID_MSR  (1 << 5)
1054
#define CPUID_PAE  (1 << 6)
1055
#define CPUID_MCE  (1 << 7)
1056
#define CPUID_CX8  (1 << 8)
1057
#define CPUID_APIC (1 << 9)
1058
#define CPUID_SEP  (1 << 11) /* sysenter/sysexit */
1059
#define CPUID_MTRR (1 << 12)
1060
#define CPUID_PGE  (1 << 13)
1061
#define CPUID_MCA  (1 << 14)
1062
#define CPUID_CMOV (1 << 15)
1063
/* ... */
1064
#define CPUID_MMX  (1 << 23)
1065
#define CPUID_FXSR (1 << 24)
1066
#define CPUID_SSE  (1 << 25)
1067
#define CPUID_SSE2 (1 << 26)
1068

  
1069
void helper_cpuid(void)
1070
{
1071
    if (EAX == 0) {
1072
        EAX = 1; /* max EAX index supported */
1073
        EBX = 0x756e6547;
1074
        ECX = 0x6c65746e;
1075
        EDX = 0x49656e69;
1076
    } else if (EAX == 1) {
1077
        /* EAX = 1 info */
1078
        EAX = 0x52b;
1079
        EBX = 0;
1080
        ECX = 0;
1081
        EDX = CPUID_FP87 | CPUID_DE | CPUID_PSE |
1082
            CPUID_TSC | CPUID_MSR | CPUID_MCE |
1083
            CPUID_CX8;
1084
    }
1085
}
1086

  
1087 958
void OPPROTO op_cpuid(void)
1088 959
{
1089 960
    helper_cpuid();
......
1221 1092

  
1222 1093
/* segment handling */
1223 1094

  
1224
/* only works if protected mode and not VM86 */
1225
void load_seg(int seg_reg, int selector, unsigned cur_eip)
1226
{
1227
    SegmentCache *sc;
1228
    SegmentDescriptorTable *dt;
1229
    int index;
1230
    uint32_t e1, e2;
1231
    uint8_t *ptr;
1232

  
1233
    sc = &env->seg_cache[seg_reg];
1234
    if ((selector & 0xfffc) == 0) {
1235
        /* null selector case */
1236
        if (seg_reg == R_SS) {
1237
            EIP = cur_eip;
1238
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1239
        } else {
1240
            /* XXX: each access should trigger an exception */
1241
            sc->base = NULL;
1242
            sc->limit = 0;
1243
            sc->seg_32bit = 1;
1244
        }
1245
    } else {
1246
        if (selector & 0x4)
1247
            dt = &env->ldt;
1248
        else
1249
            dt = &env->gdt;
1250
        index = selector & ~7;
1251
        if ((index + 7) > dt->limit) {
1252
            EIP = cur_eip;
1253
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1254
        }
1255
        ptr = dt->base + index;
1256
        e1 = ldl(ptr);
1257
        e2 = ldl(ptr + 4);
1258
        if (!(e2 & DESC_S_MASK) ||
1259
            (e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) {
1260
            EIP = cur_eip;
1261
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1262
        }
1263

  
1264
        if (seg_reg == R_SS) {
1265
            if ((e2 & (DESC_CS_MASK | DESC_W_MASK)) == 0) {
1266
                EIP = cur_eip;
1267
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1268
            }
1269
        } else {
1270
            if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) {
1271
                EIP = cur_eip;
1272
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1273
            }
1274
        }
1275

  
1276
        if (!(e2 & DESC_P_MASK)) {
1277
            EIP = cur_eip;
1278
            if (seg_reg == R_SS)
1279
                raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
1280
            else
1281
                raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1282
        }
1283
        
1284
        sc->base = (void *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
1285
        sc->limit = (e1 & 0xffff) | (e2 & 0x000f0000);
1286
        if (e2 & (1 << 23))
1287
            sc->limit = (sc->limit << 12) | 0xfff;
1288
        sc->seg_32bit = (e2 >> 22) & 1;
1289
#if 0
1290
        fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n", 
1291
                selector, (unsigned long)sc->base, sc->limit, sc->seg_32bit);
1292
#endif
1293
    }
1294
    env->segs[seg_reg] = selector;
1295
}
1296

  
1297 1095
void OPPROTO op_movl_seg_T0(void)
1298 1096
{
1299 1097
    load_seg(PARAM1, T0 & 0xffff, PARAM2);
......
1326 1124
    A0 += *(unsigned long *)((char *)env + PARAM1);
1327 1125
}
1328 1126

  
1329
void helper_lsl(void)
1330
{
1331
    unsigned int selector, limit;
1332
    SegmentDescriptorTable *dt;
1333
    int index;
1334
    uint32_t e1, e2;
1335
    uint8_t *ptr;
1336

  
1337
    CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
1338
    selector = T0 & 0xffff;
1339
    if (selector & 0x4)
1340
        dt = &env->ldt;
1341
    else
1342
        dt = &env->gdt;
1343
    index = selector & ~7;
1344
    if ((index + 7) > dt->limit)
1345
        return;
1346
    ptr = dt->base + index;
1347
    e1 = ldl(ptr);
1348
    e2 = ldl(ptr + 4);
1349
    limit = (e1 & 0xffff) | (e2 & 0x000f0000);
1350
    if (e2 & (1 << 23))
1351
        limit = (limit << 12) | 0xfff;
1352
    T1 = limit;
1353
    CC_SRC |= CC_Z;
1354
}
1355

  
1356 1127
void OPPROTO op_lsl(void)
1357 1128
{
1358 1129
    helper_lsl();
1359 1130
}
1360 1131

  
1361
void helper_lar(void)
1362
{
1363
    unsigned int selector;
1364
    SegmentDescriptorTable *dt;
1365
    int index;
1366
    uint32_t e2;
1367
    uint8_t *ptr;
1368

  
1369
    CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
1370
    selector = T0 & 0xffff;
1371
    if (selector & 0x4)
1372
        dt = &env->ldt;
1373
    else
1374
        dt = &env->gdt;
1375
    index = selector & ~7;
1376
    if ((index + 7) > dt->limit)
1377
        return;
1378
    ptr = dt->base + index;
1379
    e2 = ldl(ptr + 4);
1380
    T1 = e2 & 0x00f0ff00;
1381
    CC_SRC |= CC_Z;
1382
}
1383

  
1384 1132
void OPPROTO op_lar(void)
1385 1133
{
1386 1134
    helper_lar();
......
1678 1426
   functions comes from the LGPL'ed x86 emulator found in the Willows
1679 1427
   TWIN windows emulator. */
1680 1428

  
1681
#ifdef USE_X86LDOUBLE
1682
/* use long double functions */
1683
#define lrint lrintl
1684
#define llrint llrintl
1685
#define fabs fabsl
1686
#define sin sinl
1687
#define cos cosl
1688
#define sqrt sqrtl
1689
#define pow powl
1690
#define log logl
1691
#define tan tanl
1692
#define atan2 atan2l
1693
#define floor floorl
1694
#define ceil ceill
1695
#define rint rintl
1696
#endif
1697

  
1698
extern int lrint(CPU86_LDouble x);
1699
extern int64_t llrint(CPU86_LDouble x);
1700
extern CPU86_LDouble fabs(CPU86_LDouble x);
1701
extern CPU86_LDouble sin(CPU86_LDouble x);
1702
extern CPU86_LDouble cos(CPU86_LDouble x);
1703
extern CPU86_LDouble sqrt(CPU86_LDouble x);
1704
extern CPU86_LDouble pow(CPU86_LDouble, CPU86_LDouble);
1705
extern CPU86_LDouble log(CPU86_LDouble x);
1706
extern CPU86_LDouble tan(CPU86_LDouble x);
1707
extern CPU86_LDouble atan2(CPU86_LDouble, CPU86_LDouble);
1708
extern CPU86_LDouble floor(CPU86_LDouble x);
1709
extern CPU86_LDouble ceil(CPU86_LDouble x);
1710
extern CPU86_LDouble rint(CPU86_LDouble x);
1711

  
1712 1429
#if defined(__powerpc__)
1713 1430
extern CPU86_LDouble copysign(CPU86_LDouble, CPU86_LDouble);
1714 1431

  
......
1729 1446
#define rint qemu_rint
1730 1447
#endif
1731 1448

  
1732
#define RC_MASK         0xc00
1733
#define RC_NEAR		0x000
1734
#define RC_DOWN		0x400
1735
#define RC_UP		0x800
1736
#define RC_CHOP		0xc00
1737

  
1738
#define MAXTAN 9223372036854775808.0
1739

  
1740
#ifdef USE_X86LDOUBLE
1741

  
1742
/* only for x86 */
1743
typedef union {
1744
    long double d;
1745
    struct {
1746
        unsigned long long lower;
1747
        unsigned short upper;
1748
    } l;
1749
} CPU86_LDoubleU;
1750

  
1751
/* the following deal with x86 long double-precision numbers */
1752
#define MAXEXPD 0x7fff
1753
#define EXPBIAS 16383
1754
#define EXPD(fp)	(fp.l.upper & 0x7fff)
1755
#define SIGND(fp)	((fp.l.upper) & 0x8000)
1756
#define MANTD(fp)       (fp.l.lower)
1757
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
1758

  
1759
#else
1760

  
1761
typedef union {
1762
    double d;
1763
#ifndef WORDS_BIGENDIAN
1764
    struct {
1765
        uint32_t lower;
1766
        int32_t upper;
1767
    } l;
1768
#else
1769
    struct {
1770
        int32_t upper;
1771
        uint32_t lower;
1772
    } l;
1773
#endif
1774
    int64_t ll;
1775
} CPU86_LDoubleU;
1776

  
1777
/* the following deal with IEEE double-precision numbers */
1778
#define MAXEXPD 0x7ff
1779
#define EXPBIAS 1023
1780
#define EXPD(fp)	(((fp.l.upper) >> 20) & 0x7FF)
1781
#define SIGND(fp)	((fp.l.upper) & 0x80000000)
1782
#define MANTD(fp)	(fp.ll & ((1LL << 52) - 1))
1783
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20)
1784
#endif
1785

  
1786 1449
/* fp load FT0 */
1787 1450

  
1788 1451
void OPPROTO op_flds_FT0_A0(void)
......
1899 1562
    ST0 = *(long double *)A0;
1900 1563
}
1901 1564
#else
1902
static inline CPU86_LDouble helper_fldt(uint8_t *ptr)
1903
{
1904
    CPU86_LDoubleU temp;
1905
    int upper, e;
1906
    /* mantissa */
1907
    upper = lduw(ptr + 8);
1908
    /* XXX: handle overflow ? */
1909
    e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
1910
    e |= (upper >> 4) & 0x800; /* sign */
1911
    temp.ll = ((ldq(ptr) >> 11) & ((1LL << 52) - 1)) | ((uint64_t)e << 52);
1912
    return temp.d;
1913
}
1914

  
1915
void helper_fldt_ST0_A0(void)
1916
{
1917
    ST0 = helper_fldt((uint8_t *)A0);
1918
}
1919

  
1920 1565
void OPPROTO op_fldt_ST0_A0(void)
1921 1566
{
1922 1567
    helper_fldt_ST0_A0();
......
2013 1658
    *(long double *)A0 = ST0;
2014 1659
}
2015 1660
#else
2016

  
2017
static inline void helper_fstt(CPU86_LDouble f, uint8_t *ptr)
2018
{
2019
    CPU86_LDoubleU temp;
2020
    int e;
2021
    temp.d = f;
2022
    /* mantissa */
2023
    stq(ptr, (MANTD(temp) << 11) | (1LL << 63));
2024
    /* exponent + sign */
2025
    e = EXPD(temp) - EXPBIAS + 16383;
2026
    e |= SIGND(temp) >> 16;
2027
    stw(ptr + 8, e);
2028
}
2029

  
2030
void helper_fstt_ST0_A0(void)
2031
{
2032
    helper_fstt(ST0, (uint8_t *)A0);
2033
}
2034

  
2035 1661
void OPPROTO op_fstt_ST0_A0(void)
2036 1662
{
2037 1663
    helper_fstt_ST0_A0();
......
2080 1706
    stq((void *)A0, val);
2081 1707
}
2082 1708

  
2083
/* BCD ops */
2084

  
2085
#define MUL10(iv) ( iv + iv + (iv << 3) )
2086

  
2087
void helper_fbld_ST0_A0(void)
2088
{
2089
    uint8_t *seg;
2090
    CPU86_LDouble fpsrcop;
2091
    int m32i;
2092
    unsigned int v;
2093

  
2094
    /* in this code, seg/m32i will be used as temporary ptr/int */
2095
    seg = (uint8_t *)A0 + 8;
2096
    v = ldub(seg--);
2097
    /* XXX: raise exception */
2098
    if (v != 0)
2099
        return;
2100
    v = ldub(seg--);
2101
    /* XXX: raise exception */
2102
    if ((v & 0xf0) != 0)
2103
        return;
2104
    m32i = v;  /* <-- d14 */
2105
    v = ldub(seg--);
2106
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d13 */
2107
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d12 */
2108
    v = ldub(seg--);
2109
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d11 */
2110
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d10 */
2111
    v = ldub(seg--);
2112
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d9 */
2113
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d8 */
2114
    fpsrcop = ((CPU86_LDouble)m32i) * 100000000.0;
2115

  
2116
    v = ldub(seg--);
2117
    m32i = (v >> 4);  /* <-- d7 */
2118
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d6 */
2119
    v = ldub(seg--);
2120
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d5 */
2121
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d4 */
2122
    v = ldub(seg--);
2123
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d3 */
2124
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d2 */
2125
    v = ldub(seg);
2126
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d1 */
2127
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d0 */
2128
    fpsrcop += ((CPU86_LDouble)m32i);
2129
    if ( ldub(seg+9) & 0x80 )
2130
        fpsrcop = -fpsrcop;
2131
    ST0 = fpsrcop;
2132
}
2133

  
2134 1709
void OPPROTO op_fbld_ST0_A0(void)
2135 1710
{
2136 1711
    helper_fbld_ST0_A0();
2137 1712
}
2138 1713

  
2139
void helper_fbst_ST0_A0(void)
2140
{
2141
    CPU86_LDouble fptemp;
2142
    CPU86_LDouble fpsrcop;
2143
    int v;
2144
    uint8_t *mem_ref, *mem_end;
2145

  
2146
    fpsrcop = rint(ST0);
2147
    mem_ref = (uint8_t *)A0;
2148
    mem_end = mem_ref + 8;
2149
    if ( fpsrcop < 0.0 ) {
2150
        stw(mem_end, 0x8000);
2151
        fpsrcop = -fpsrcop;
2152
    } else {
2153
        stw(mem_end, 0x0000);
2154
    }
2155
    while (mem_ref < mem_end) {
2156
        if (fpsrcop == 0.0)
2157
            break;
2158
        fptemp = floor(fpsrcop/10.0);
2159
        v = ((int)(fpsrcop - fptemp*10.0));
2160
        if  (fptemp == 0.0)  { 
2161
            stb(mem_ref++, v); 
2162
            break; 
2163
        }
2164
        fpsrcop = fptemp;
2165
        fptemp = floor(fpsrcop/10.0);
2166
        v |= (((int)(fpsrcop - fptemp*10.0)) << 4);
2167
        stb(mem_ref++, v);
2168
        fpsrcop = fptemp;
2169
    }
2170
    while (mem_ref < mem_end) {
2171
        stb(mem_ref++, 0);
2172
    }
2173
}
2174

  
2175 1714
void OPPROTO op_fbst_ST0_A0(void)
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff