Revision d7582078

b/target-i386/Makefile.objs
1 1
obj-y += translate.o op_helper.o helper.o cpu.o
2
obj-y += excp_helper.o fpu_helper.o cc_helper.o
2
obj-y += excp_helper.o fpu_helper.o cc_helper.o int_helper.o
3 3
obj-$(CONFIG_SOFTMMU) += machine.o arch_memory_mapping.o arch_dump.o
4 4
obj-$(CONFIG_KVM) += kvm.o hyperv.o
5 5
obj-$(CONFIG_LINUX_USER) += ioport-user.o
......
8 8
$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
9 9
$(obj)/fpu_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
10 10
$(obj)/cc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
11
$(obj)/int_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
b/target-i386/int_helper.c
1
/*
2
 *  x86 integer 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, see <http://www.gnu.org/licenses/>.
18
 */
19

  
20
#include "cpu.h"
21
#include "dyngen-exec.h"
22
#include "host-utils.h"
23
#include "helper.h"
24

  
25
//#define DEBUG_MULDIV
26

  
27
/* modulo 9 table */
28
static const uint8_t rclb_table[32] = {
29
    0, 1, 2, 3, 4, 5, 6, 7,
30
    8, 0, 1, 2, 3, 4, 5, 6,
31
    7, 8, 0, 1, 2, 3, 4, 5,
32
    6, 7, 8, 0, 1, 2, 3, 4,
33
};
34

  
35
/* modulo 17 table */
36
static const uint8_t rclw_table[32] = {
37
    0, 1, 2, 3, 4, 5, 6, 7,
38
    8, 9, 10, 11, 12, 13, 14, 15,
39
    16, 0, 1, 2, 3, 4, 5, 6,
40
    7, 8, 9, 10, 11, 12, 13, 14,
41
};
42

  
43
/* division, flags are undefined */
44

  
45
void helper_divb_AL(target_ulong t0)
46
{
47
    unsigned int num, den, q, r;
48

  
49
    num = (EAX & 0xffff);
50
    den = (t0 & 0xff);
51
    if (den == 0) {
52
        raise_exception(env, EXCP00_DIVZ);
53
    }
54
    q = (num / den);
55
    if (q > 0xff) {
56
        raise_exception(env, EXCP00_DIVZ);
57
    }
58
    q &= 0xff;
59
    r = (num % den) & 0xff;
60
    EAX = (EAX & ~0xffff) | (r << 8) | q;
61
}
62

  
63
void helper_idivb_AL(target_ulong t0)
64
{
65
    int num, den, q, r;
66

  
67
    num = (int16_t)EAX;
68
    den = (int8_t)t0;
69
    if (den == 0) {
70
        raise_exception(env, EXCP00_DIVZ);
71
    }
72
    q = (num / den);
73
    if (q != (int8_t)q) {
74
        raise_exception(env, EXCP00_DIVZ);
75
    }
76
    q &= 0xff;
77
    r = (num % den) & 0xff;
78
    EAX = (EAX & ~0xffff) | (r << 8) | q;
79
}
80

  
81
void helper_divw_AX(target_ulong t0)
82
{
83
    unsigned int num, den, q, r;
84

  
85
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
86
    den = (t0 & 0xffff);
87
    if (den == 0) {
88
        raise_exception(env, EXCP00_DIVZ);
89
    }
90
    q = (num / den);
91
    if (q > 0xffff) {
92
        raise_exception(env, EXCP00_DIVZ);
93
    }
94
    q &= 0xffff;
95
    r = (num % den) & 0xffff;
96
    EAX = (EAX & ~0xffff) | q;
97
    EDX = (EDX & ~0xffff) | r;
98
}
99

  
100
void helper_idivw_AX(target_ulong t0)
101
{
102
    int num, den, q, r;
103

  
104
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
105
    den = (int16_t)t0;
106
    if (den == 0) {
107
        raise_exception(env, EXCP00_DIVZ);
108
    }
109
    q = (num / den);
110
    if (q != (int16_t)q) {
111
        raise_exception(env, EXCP00_DIVZ);
112
    }
113
    q &= 0xffff;
114
    r = (num % den) & 0xffff;
115
    EAX = (EAX & ~0xffff) | q;
116
    EDX = (EDX & ~0xffff) | r;
117
}
118

  
119
void helper_divl_EAX(target_ulong t0)
120
{
121
    unsigned int den, r;
122
    uint64_t num, q;
123

  
124
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
125
    den = t0;
126
    if (den == 0) {
127
        raise_exception(env, EXCP00_DIVZ);
128
    }
129
    q = (num / den);
130
    r = (num % den);
131
    if (q > 0xffffffff) {
132
        raise_exception(env, EXCP00_DIVZ);
133
    }
134
    EAX = (uint32_t)q;
135
    EDX = (uint32_t)r;
136
}
137

  
138
void helper_idivl_EAX(target_ulong t0)
139
{
140
    int den, r;
141
    int64_t num, q;
142

  
143
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
144
    den = t0;
145
    if (den == 0) {
146
        raise_exception(env, EXCP00_DIVZ);
147
    }
148
    q = (num / den);
149
    r = (num % den);
150
    if (q != (int32_t)q) {
151
        raise_exception(env, EXCP00_DIVZ);
152
    }
153
    EAX = (uint32_t)q;
154
    EDX = (uint32_t)r;
155
}
156

  
157
/* bcd */
158

  
159
/* XXX: exception */
160
void helper_aam(int base)
161
{
162
    int al, ah;
163

  
164
    al = EAX & 0xff;
165
    ah = al / base;
166
    al = al % base;
167
    EAX = (EAX & ~0xffff) | al | (ah << 8);
168
    CC_DST = al;
169
}
170

  
171
void helper_aad(int base)
172
{
173
    int al, ah;
174

  
175
    al = EAX & 0xff;
176
    ah = (EAX >> 8) & 0xff;
177
    al = ((ah * base) + al) & 0xff;
178
    EAX = (EAX & ~0xffff) | al;
179
    CC_DST = al;
180
}
181

  
182
void helper_aaa(void)
183
{
184
    int icarry;
185
    int al, ah, af;
186
    int eflags;
187

  
188
    eflags = helper_cc_compute_all(CC_OP);
189
    af = eflags & CC_A;
190
    al = EAX & 0xff;
191
    ah = (EAX >> 8) & 0xff;
192

  
193
    icarry = (al > 0xf9);
194
    if (((al & 0x0f) > 9) || af) {
195
        al = (al + 6) & 0x0f;
196
        ah = (ah + 1 + icarry) & 0xff;
197
        eflags |= CC_C | CC_A;
198
    } else {
199
        eflags &= ~(CC_C | CC_A);
200
        al &= 0x0f;
201
    }
202
    EAX = (EAX & ~0xffff) | al | (ah << 8);
203
    CC_SRC = eflags;
204
}
205

  
206
void helper_aas(void)
207
{
208
    int icarry;
209
    int al, ah, af;
210
    int eflags;
211

  
212
    eflags = helper_cc_compute_all(CC_OP);
213
    af = eflags & CC_A;
214
    al = EAX & 0xff;
215
    ah = (EAX >> 8) & 0xff;
216

  
217
    icarry = (al < 6);
218
    if (((al & 0x0f) > 9) || af) {
219
        al = (al - 6) & 0x0f;
220
        ah = (ah - 1 - icarry) & 0xff;
221
        eflags |= CC_C | CC_A;
222
    } else {
223
        eflags &= ~(CC_C | CC_A);
224
        al &= 0x0f;
225
    }
226
    EAX = (EAX & ~0xffff) | al | (ah << 8);
227
    CC_SRC = eflags;
228
}
229

  
230
void helper_daa(void)
231
{
232
    int old_al, al, af, cf;
233
    int eflags;
234

  
235
    eflags = helper_cc_compute_all(CC_OP);
236
    cf = eflags & CC_C;
237
    af = eflags & CC_A;
238
    old_al = al = EAX & 0xff;
239

  
240
    eflags = 0;
241
    if (((al & 0x0f) > 9) || af) {
242
        al = (al + 6) & 0xff;
243
        eflags |= CC_A;
244
    }
245
    if ((old_al > 0x99) || cf) {
246
        al = (al + 0x60) & 0xff;
247
        eflags |= CC_C;
248
    }
249
    EAX = (EAX & ~0xff) | al;
250
    /* well, speed is not an issue here, so we compute the flags by hand */
251
    eflags |= (al == 0) << 6; /* zf */
252
    eflags |= parity_table[al]; /* pf */
253
    eflags |= (al & 0x80); /* sf */
254
    CC_SRC = eflags;
255
}
256

  
257
void helper_das(void)
258
{
259
    int al, al1, af, cf;
260
    int eflags;
261

  
262
    eflags = helper_cc_compute_all(CC_OP);
263
    cf = eflags & CC_C;
264
    af = eflags & CC_A;
265
    al = EAX & 0xff;
266

  
267
    eflags = 0;
268
    al1 = al;
269
    if (((al & 0x0f) > 9) || af) {
270
        eflags |= CC_A;
271
        if (al < 6 || cf) {
272
            eflags |= CC_C;
273
        }
274
        al = (al - 6) & 0xff;
275
    }
276
    if ((al1 > 0x99) || cf) {
277
        al = (al - 0x60) & 0xff;
278
        eflags |= CC_C;
279
    }
280
    EAX = (EAX & ~0xff) | al;
281
    /* well, speed is not an issue here, so we compute the flags by hand */
282
    eflags |= (al == 0) << 6; /* zf */
283
    eflags |= parity_table[al]; /* pf */
284
    eflags |= (al & 0x80); /* sf */
285
    CC_SRC = eflags;
286
}
287

  
288
#ifdef TARGET_X86_64
289
static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
290
{
291
    *plow += a;
292
    /* carry test */
293
    if (*plow < a) {
294
        (*phigh)++;
295
    }
296
    *phigh += b;
297
}
298

  
299
static void neg128(uint64_t *plow, uint64_t *phigh)
300
{
301
    *plow = ~*plow;
302
    *phigh = ~*phigh;
303
    add128(plow, phigh, 1, 0);
304
}
305

  
306
/* return TRUE if overflow */
307
static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
308
{
309
    uint64_t q, r, a1, a0;
310
    int i, qb, ab;
311

  
312
    a0 = *plow;
313
    a1 = *phigh;
314
    if (a1 == 0) {
315
        q = a0 / b;
316
        r = a0 % b;
317
        *plow = q;
318
        *phigh = r;
319
    } else {
320
        if (a1 >= b) {
321
            return 1;
322
        }
323
        /* XXX: use a better algorithm */
324
        for (i = 0; i < 64; i++) {
325
            ab = a1 >> 63;
326
            a1 = (a1 << 1) | (a0 >> 63);
327
            if (ab || a1 >= b) {
328
                a1 -= b;
329
                qb = 1;
330
            } else {
331
                qb = 0;
332
            }
333
            a0 = (a0 << 1) | qb;
334
        }
335
#if defined(DEBUG_MULDIV)
336
        printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64
337
               ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n",
338
               *phigh, *plow, b, a0, a1);
339
#endif
340
        *plow = a0;
341
        *phigh = a1;
342
    }
343
    return 0;
344
}
345

  
346
/* return TRUE if overflow */
347
static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b)
348
{
349
    int sa, sb;
350

  
351
    sa = ((int64_t)*phigh < 0);
352
    if (sa) {
353
        neg128(plow, phigh);
354
    }
355
    sb = (b < 0);
356
    if (sb) {
357
        b = -b;
358
    }
359
    if (div64(plow, phigh, b) != 0) {
360
        return 1;
361
    }
362
    if (sa ^ sb) {
363
        if (*plow > (1ULL << 63)) {
364
            return 1;
365
        }
366
        *plow = -*plow;
367
    } else {
368
        if (*plow >= (1ULL << 63)) {
369
            return 1;
370
        }
371
    }
372
    if (sa) {
373
        *phigh = -*phigh;
374
    }
375
    return 0;
376
}
377

  
378
void helper_mulq_EAX_T0(target_ulong t0)
379
{
380
    uint64_t r0, r1;
381

  
382
    mulu64(&r0, &r1, EAX, t0);
383
    EAX = r0;
384
    EDX = r1;
385
    CC_DST = r0;
386
    CC_SRC = r1;
387
}
388

  
389
void helper_imulq_EAX_T0(target_ulong t0)
390
{
391
    uint64_t r0, r1;
392

  
393
    muls64(&r0, &r1, EAX, t0);
394
    EAX = r0;
395
    EDX = r1;
396
    CC_DST = r0;
397
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
398
}
399

  
400
target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1)
401
{
402
    uint64_t r0, r1;
403

  
404
    muls64(&r0, &r1, t0, t1);
405
    CC_DST = r0;
406
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
407
    return r0;
408
}
409

  
410
void helper_divq_EAX(target_ulong t0)
411
{
412
    uint64_t r0, r1;
413

  
414
    if (t0 == 0) {
415
        raise_exception(env, EXCP00_DIVZ);
416
    }
417
    r0 = EAX;
418
    r1 = EDX;
419
    if (div64(&r0, &r1, t0)) {
420
        raise_exception(env, EXCP00_DIVZ);
421
    }
422
    EAX = r0;
423
    EDX = r1;
424
}
425

  
426
void helper_idivq_EAX(target_ulong t0)
427
{
428
    uint64_t r0, r1;
429

  
430
    if (t0 == 0) {
431
        raise_exception(env, EXCP00_DIVZ);
432
    }
433
    r0 = EAX;
434
    r1 = EDX;
435
    if (idiv64(&r0, &r1, t0)) {
436
        raise_exception(env, EXCP00_DIVZ);
437
    }
438
    EAX = r0;
439
    EDX = r1;
440
}
441
#endif
442

  
443
/* bit operations */
444
target_ulong helper_bsf(target_ulong t0)
445
{
446
    int count;
447
    target_ulong res;
448

  
449
    res = t0;
450
    count = 0;
451
    while ((res & 1) == 0) {
452
        count++;
453
        res >>= 1;
454
    }
455
    return count;
456
}
457

  
458
target_ulong helper_lzcnt(target_ulong t0, int wordsize)
459
{
460
    int count;
461
    target_ulong res, mask;
462

  
463
    if (wordsize > 0 && t0 == 0) {
464
        return wordsize;
465
    }
466
    res = t0;
467
    count = TARGET_LONG_BITS - 1;
468
    mask = (target_ulong)1 << (TARGET_LONG_BITS - 1);
469
    while ((res & mask) == 0) {
470
        count--;
471
        res <<= 1;
472
    }
473
    if (wordsize > 0) {
474
        return wordsize - 1 - count;
475
    }
476
    return count;
477
}
478

  
479
target_ulong helper_bsr(target_ulong t0)
480
{
481
    return helper_lzcnt(t0, 0);
482
}
483

  
484
#define SHIFT 0
485
#include "shift_helper_template.h"
486
#undef SHIFT
487

  
488
#define SHIFT 1
489
#include "shift_helper_template.h"
490
#undef SHIFT
491

  
492
#define SHIFT 2
493
#include "shift_helper_template.h"
494
#undef SHIFT
495

  
496
#ifdef TARGET_X86_64
497
#define SHIFT 3
498
#include "shift_helper_template.h"
499
#undef SHIFT
500
#endif
b/target-i386/op_helper.c
19 19

  
20 20
#include "cpu.h"
21 21
#include "dyngen-exec.h"
22
#include "host-utils.h"
23 22
#include "ioport.h"
24 23
#include "qemu-log.h"
25 24
#include "cpu-defs.h"
......
30 29
#endif /* !defined(CONFIG_USER_ONLY) */
31 30

  
32 31
//#define DEBUG_PCALL
33
//#define DEBUG_MULDIV
34 32

  
35 33
#ifdef DEBUG_PCALL
36 34
# define LOG_PCALL(...) qemu_log_mask(CPU_LOG_PCALL, ## __VA_ARGS__)
......
41 39
# define LOG_PCALL_STATE(env) do { } while (0)
42 40
#endif
43 41

  
44
/* modulo 17 table */
45
static const uint8_t rclw_table[32] = {
46
    0, 1, 2, 3, 4, 5, 6, 7,
47
    8, 9, 10, 11, 12, 13, 14, 15,
48
    16, 0, 1, 2, 3, 4, 5, 6,
49
    7, 8, 9, 10, 11, 12, 13, 14,
50
};
51

  
52
/* modulo 9 table */
53
static const uint8_t rclb_table[32] = {
54
    0, 1, 2, 3, 4, 5, 6, 7,
55
    8, 0, 1, 2, 3, 4, 5, 6,
56
    7, 8, 0, 1, 2, 3, 4, 5,
57
    6, 7, 8, 0, 1, 2, 3, 4,
58
};
59

  
60 42
/* broken thread support */
61 43

  
62 44
static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
......
1656 1638

  
1657 1639
#endif /* !CONFIG_USER_ONLY */
1658 1640

  
1659

  
1660
/* division, flags are undefined */
1661

  
1662
void helper_divb_AL(target_ulong t0)
1663
{
1664
    unsigned int num, den, q, r;
1665

  
1666
    num = (EAX & 0xffff);
1667
    den = (t0 & 0xff);
1668
    if (den == 0) {
1669
        raise_exception(env, EXCP00_DIVZ);
1670
    }
1671
    q = (num / den);
1672
    if (q > 0xff) {
1673
        raise_exception(env, EXCP00_DIVZ);
1674
    }
1675
    q &= 0xff;
1676
    r = (num % den) & 0xff;
1677
    EAX = (EAX & ~0xffff) | (r << 8) | q;
1678
}
1679

  
1680
void helper_idivb_AL(target_ulong t0)
1681
{
1682
    int num, den, q, r;
1683

  
1684
    num = (int16_t)EAX;
1685
    den = (int8_t)t0;
1686
    if (den == 0) {
1687
        raise_exception(env, EXCP00_DIVZ);
1688
    }
1689
    q = (num / den);
1690
    if (q != (int8_t)q) {
1691
        raise_exception(env, EXCP00_DIVZ);
1692
    }
1693
    q &= 0xff;
1694
    r = (num % den) & 0xff;
1695
    EAX = (EAX & ~0xffff) | (r << 8) | q;
1696
}
1697

  
1698
void helper_divw_AX(target_ulong t0)
1699
{
1700
    unsigned int num, den, q, r;
1701

  
1702
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1703
    den = (t0 & 0xffff);
1704
    if (den == 0) {
1705
        raise_exception(env, EXCP00_DIVZ);
1706
    }
1707
    q = (num / den);
1708
    if (q > 0xffff) {
1709
        raise_exception(env, EXCP00_DIVZ);
1710
    }
1711
    q &= 0xffff;
1712
    r = (num % den) & 0xffff;
1713
    EAX = (EAX & ~0xffff) | q;
1714
    EDX = (EDX & ~0xffff) | r;
1715
}
1716

  
1717
void helper_idivw_AX(target_ulong t0)
1718
{
1719
    int num, den, q, r;
1720

  
1721
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1722
    den = (int16_t)t0;
1723
    if (den == 0) {
1724
        raise_exception(env, EXCP00_DIVZ);
1725
    }
1726
    q = (num / den);
1727
    if (q != (int16_t)q) {
1728
        raise_exception(env, EXCP00_DIVZ);
1729
    }
1730
    q &= 0xffff;
1731
    r = (num % den) & 0xffff;
1732
    EAX = (EAX & ~0xffff) | q;
1733
    EDX = (EDX & ~0xffff) | r;
1734
}
1735

  
1736
void helper_divl_EAX(target_ulong t0)
1737
{
1738
    unsigned int den, r;
1739
    uint64_t num, q;
1740

  
1741
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1742
    den = t0;
1743
    if (den == 0) {
1744
        raise_exception(env, EXCP00_DIVZ);
1745
    }
1746
    q = (num / den);
1747
    r = (num % den);
1748
    if (q > 0xffffffff) {
1749
        raise_exception(env, EXCP00_DIVZ);
1750
    }
1751
    EAX = (uint32_t)q;
1752
    EDX = (uint32_t)r;
1753
}
1754

  
1755
void helper_idivl_EAX(target_ulong t0)
1756
{
1757
    int den, r;
1758
    int64_t num, q;
1759

  
1760
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1761
    den = t0;
1762
    if (den == 0) {
1763
        raise_exception(env, EXCP00_DIVZ);
1764
    }
1765
    q = (num / den);
1766
    r = (num % den);
1767
    if (q != (int32_t)q) {
1768
        raise_exception(env, EXCP00_DIVZ);
1769
    }
1770
    EAX = (uint32_t)q;
1771
    EDX = (uint32_t)r;
1772
}
1773

  
1774
/* bcd */
1775

  
1776
/* XXX: exception */
1777
void helper_aam(int base)
1778
{
1779
    int al, ah;
1780

  
1781
    al = EAX & 0xff;
1782
    ah = al / base;
1783
    al = al % base;
1784
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1785
    CC_DST = al;
1786
}
1787

  
1788
void helper_aad(int base)
1789
{
1790
    int al, ah;
1791

  
1792
    al = EAX & 0xff;
1793
    ah = (EAX >> 8) & 0xff;
1794
    al = ((ah * base) + al) & 0xff;
1795
    EAX = (EAX & ~0xffff) | al;
1796
    CC_DST = al;
1797
}
1798

  
1799
void helper_aaa(void)
1800
{
1801
    int icarry;
1802
    int al, ah, af;
1803
    int eflags;
1804

  
1805
    eflags = helper_cc_compute_all(CC_OP);
1806
    af = eflags & CC_A;
1807
    al = EAX & 0xff;
1808
    ah = (EAX >> 8) & 0xff;
1809

  
1810
    icarry = (al > 0xf9);
1811
    if (((al & 0x0f) > 9) || af) {
1812
        al = (al + 6) & 0x0f;
1813
        ah = (ah + 1 + icarry) & 0xff;
1814
        eflags |= CC_C | CC_A;
1815
    } else {
1816
        eflags &= ~(CC_C | CC_A);
1817
        al &= 0x0f;
1818
    }
1819
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1820
    CC_SRC = eflags;
1821
}
1822

  
1823
void helper_aas(void)
1824
{
1825
    int icarry;
1826
    int al, ah, af;
1827
    int eflags;
1828

  
1829
    eflags = helper_cc_compute_all(CC_OP);
1830
    af = eflags & CC_A;
1831
    al = EAX & 0xff;
1832
    ah = (EAX >> 8) & 0xff;
1833

  
1834
    icarry = (al < 6);
1835
    if (((al & 0x0f) > 9) || af) {
1836
        al = (al - 6) & 0x0f;
1837
        ah = (ah - 1 - icarry) & 0xff;
1838
        eflags |= CC_C | CC_A;
1839
    } else {
1840
        eflags &= ~(CC_C | CC_A);
1841
        al &= 0x0f;
1842
    }
1843
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1844
    CC_SRC = eflags;
1845
}
1846

  
1847
void helper_daa(void)
1848
{
1849
    int old_al, al, af, cf;
1850
    int eflags;
1851

  
1852
    eflags = helper_cc_compute_all(CC_OP);
1853
    cf = eflags & CC_C;
1854
    af = eflags & CC_A;
1855
    old_al = al = EAX & 0xff;
1856

  
1857
    eflags = 0;
1858
    if (((al & 0x0f) > 9) || af) {
1859
        al = (al + 6) & 0xff;
1860
        eflags |= CC_A;
1861
    }
1862
    if ((old_al > 0x99) || cf) {
1863
        al = (al + 0x60) & 0xff;
1864
        eflags |= CC_C;
1865
    }
1866
    EAX = (EAX & ~0xff) | al;
1867
    /* well, speed is not an issue here, so we compute the flags by hand */
1868
    eflags |= (al == 0) << 6; /* zf */
1869
    eflags |= parity_table[al]; /* pf */
1870
    eflags |= (al & 0x80); /* sf */
1871
    CC_SRC = eflags;
1872
}
1873

  
1874
void helper_das(void)
1875
{
1876
    int al, al1, af, cf;
1877
    int eflags;
1878

  
1879
    eflags = helper_cc_compute_all(CC_OP);
1880
    cf = eflags & CC_C;
1881
    af = eflags & CC_A;
1882
    al = EAX & 0xff;
1883

  
1884
    eflags = 0;
1885
    al1 = al;
1886
    if (((al & 0x0f) > 9) || af) {
1887
        eflags |= CC_A;
1888
        if (al < 6 || cf) {
1889
            eflags |= CC_C;
1890
        }
1891
        al = (al - 6) & 0xff;
1892
    }
1893
    if ((al1 > 0x99) || cf) {
1894
        al = (al - 0x60) & 0xff;
1895
        eflags |= CC_C;
1896
    }
1897
    EAX = (EAX & ~0xff) | al;
1898
    /* well, speed is not an issue here, so we compute the flags by hand */
1899
    eflags |= (al == 0) << 6; /* zf */
1900
    eflags |= parity_table[al]; /* pf */
1901
    eflags |= (al & 0x80); /* sf */
1902
    CC_SRC = eflags;
1903
}
1904

  
1905 1641
void helper_into(int next_eip_addend)
1906 1642
{
1907 1643
    int eflags;
......
3614 3350
}
3615 3351
#endif
3616 3352

  
3617
#ifdef TARGET_X86_64
3618
static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
3619
{
3620
    *plow += a;
3621
    /* carry test */
3622
    if (*plow < a) {
3623
        (*phigh)++;
3624
    }
3625
    *phigh += b;
3626
}
3627

  
3628
static void neg128(uint64_t *plow, uint64_t *phigh)
3629
{
3630
    *plow = ~*plow;
3631
    *phigh = ~*phigh;
3632
    add128(plow, phigh, 1, 0);
3633
}
3634

  
3635
/* return TRUE if overflow */
3636
static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
3637
{
3638
    uint64_t q, r, a1, a0;
3639
    int i, qb, ab;
3640

  
3641
    a0 = *plow;
3642
    a1 = *phigh;
3643
    if (a1 == 0) {
3644
        q = a0 / b;
3645
        r = a0 % b;
3646
        *plow = q;
3647
        *phigh = r;
3648
    } else {
3649
        if (a1 >= b) {
3650
            return 1;
3651
        }
3652
        /* XXX: use a better algorithm */
3653
        for (i = 0; i < 64; i++) {
3654
            ab = a1 >> 63;
3655
            a1 = (a1 << 1) | (a0 >> 63);
3656
            if (ab || a1 >= b) {
3657
                a1 -= b;
3658
                qb = 1;
3659
            } else {
3660
                qb = 0;
3661
            }
3662
            a0 = (a0 << 1) | qb;
3663
        }
3664
#if defined(DEBUG_MULDIV)
3665
        printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64
3666
               ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n",
3667
               *phigh, *plow, b, a0, a1);
3668
#endif
3669
        *plow = a0;
3670
        *phigh = a1;
3671
    }
3672
    return 0;
3673
}
3674

  
3675
/* return TRUE if overflow */
3676
static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b)
3677
{
3678
    int sa, sb;
3679

  
3680
    sa = ((int64_t)*phigh < 0);
3681
    if (sa) {
3682
        neg128(plow, phigh);
3683
    }
3684
    sb = (b < 0);
3685
    if (sb) {
3686
        b = -b;
3687
    }
3688
    if (div64(plow, phigh, b) != 0) {
3689
        return 1;
3690
    }
3691
    if (sa ^ sb) {
3692
        if (*plow > (1ULL << 63)) {
3693
            return 1;
3694
        }
3695
        *plow = -*plow;
3696
    } else {
3697
        if (*plow >= (1ULL << 63)) {
3698
            return 1;
3699
        }
3700
    }
3701
    if (sa) {
3702
        *phigh = -*phigh;
3703
    }
3704
    return 0;
3705
}
3706

  
3707
void helper_mulq_EAX_T0(target_ulong t0)
3708
{
3709
    uint64_t r0, r1;
3710

  
3711
    mulu64(&r0, &r1, EAX, t0);
3712
    EAX = r0;
3713
    EDX = r1;
3714
    CC_DST = r0;
3715
    CC_SRC = r1;
3716
}
3717

  
3718
void helper_imulq_EAX_T0(target_ulong t0)
3719
{
3720
    uint64_t r0, r1;
3721

  
3722
    muls64(&r0, &r1, EAX, t0);
3723
    EAX = r0;
3724
    EDX = r1;
3725
    CC_DST = r0;
3726
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
3727
}
3728

  
3729
target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1)
3730
{
3731
    uint64_t r0, r1;
3732

  
3733
    muls64(&r0, &r1, t0, t1);
3734
    CC_DST = r0;
3735
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
3736
    return r0;
3737
}
3738

  
3739
void helper_divq_EAX(target_ulong t0)
3740
{
3741
    uint64_t r0, r1;
3742

  
3743
    if (t0 == 0) {
3744
        raise_exception(env, EXCP00_DIVZ);
3745
    }
3746
    r0 = EAX;
3747
    r1 = EDX;
3748
    if (div64(&r0, &r1, t0)) {
3749
        raise_exception(env, EXCP00_DIVZ);
3750
    }
3751
    EAX = r0;
3752
    EDX = r1;
3753
}
3754

  
3755
void helper_idivq_EAX(target_ulong t0)
3756
{
3757
    uint64_t r0, r1;
3758

  
3759
    if (t0 == 0) {
3760
        raise_exception(env, EXCP00_DIVZ);
3761
    }
3762
    r0 = EAX;
3763
    r1 = EDX;
3764
    if (idiv64(&r0, &r1, t0)) {
3765
        raise_exception(env, EXCP00_DIVZ);
3766
    }
3767
    EAX = r0;
3768
    EDX = r1;
3769
}
3770
#endif
3771

  
3772 3353
static void do_hlt(void)
3773 3354
{
3774 3355
    env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
......
4583 4164
}
4584 4165

  
4585 4166
#endif
4586

  
4587
#define SHIFT 0
4588
#include "shift_helper_template.h"
4589
#undef SHIFT
4590

  
4591
#define SHIFT 1
4592
#include "shift_helper_template.h"
4593
#undef SHIFT
4594

  
4595
#define SHIFT 2
4596
#include "shift_helper_template.h"
4597
#undef SHIFT
4598

  
4599
#ifdef TARGET_X86_64
4600
#define SHIFT 3
4601
#include "shift_helper_template.h"
4602
#undef SHIFT
4603
#endif
4604

  
4605
/* bit operations */
4606
target_ulong helper_bsf(target_ulong t0)
4607
{
4608
    int count;
4609
    target_ulong res;
4610

  
4611
    res = t0;
4612
    count = 0;
4613
    while ((res & 1) == 0) {
4614
        count++;
4615
        res >>= 1;
4616
    }
4617
    return count;
4618
}
4619

  
4620
target_ulong helper_lzcnt(target_ulong t0, int wordsize)
4621
{
4622
    int count;
4623
    target_ulong res, mask;
4624

  
4625
    if (wordsize > 0 && t0 == 0) {
4626
        return wordsize;
4627
    }
4628
    res = t0;
4629
    count = TARGET_LONG_BITS - 1;
4630
    mask = (target_ulong)1 << (TARGET_LONG_BITS - 1);
4631
    while ((res & mask) == 0) {
4632
        count--;
4633
        res <<= 1;
4634
    }
4635
    if (wordsize > 0) {
4636
        return wordsize - 1 - count;
4637
    }
4638
    return count;
4639
}
4640

  
4641
target_ulong helper_bsr(target_ulong t0)
4642
{
4643
    return helper_lzcnt(t0, 0);
4644
}

Also available in: Unified diff