Statistics
| Branch: | Revision:

root / target-alpha / op_helper.c @ b5f1aa64

History | View | Annotate | Download (28.1 kB)

1
/*
2
 *  Alpha emulation cpu micro-operations helpers for qemu.
3
 *
4
 *  Copyright (c) 2007 Jocelyn Mayer
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 "exec.h"
21
#include "host-utils.h"
22
#include "softfloat.h"
23
#include "helper.h"
24
#include "qemu-timer.h"
25

    
26
/*****************************************************************************/
27
/* Exceptions processing helpers */
28
void QEMU_NORETURN helper_excp (int excp, int error)
29
{
30
    env->exception_index = excp;
31
    env->error_code = error;
32
    cpu_loop_exit();
33
}
34

    
35
static void QEMU_NORETURN arith_excp(int exc, uint64_t mask)
36
{
37
    env->exception_index = EXCP_ARITH;
38
    env->error_code = 0;
39
    env->trap_arg0 = exc;
40
    env->trap_arg1 = mask;
41
    cpu_loop_exit();
42
}
43

    
44
uint64_t helper_load_pcc (void)
45
{
46
    /* ??? This isn't a timer for which we have any rate info.  */
47
    return (uint32_t)cpu_get_real_ticks();
48
}
49

    
50
uint64_t helper_load_fpcr (void)
51
{
52
    return cpu_alpha_load_fpcr (env);
53
}
54

    
55
void helper_store_fpcr (uint64_t val)
56
{
57
    cpu_alpha_store_fpcr (env, val);
58
}
59

    
60
uint64_t helper_addqv (uint64_t op1, uint64_t op2)
61
{
62
    uint64_t tmp = op1;
63
    op1 += op2;
64
    if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) {
65
        arith_excp(EXC_M_IOV, 0);
66
    }
67
    return op1;
68
}
69

    
70
uint64_t helper_addlv (uint64_t op1, uint64_t op2)
71
{
72
    uint64_t tmp = op1;
73
    op1 = (uint32_t)(op1 + op2);
74
    if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) {
75
        arith_excp(EXC_M_IOV, 0);
76
    }
77
    return op1;
78
}
79

    
80
uint64_t helper_subqv (uint64_t op1, uint64_t op2)
81
{
82
    uint64_t res;
83
    res = op1 - op2;
84
    if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) {
85
        arith_excp(EXC_M_IOV, 0);
86
    }
87
    return res;
88
}
89

    
90
uint64_t helper_sublv (uint64_t op1, uint64_t op2)
91
{
92
    uint32_t res;
93
    res = op1 - op2;
94
    if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) {
95
        arith_excp(EXC_M_IOV, 0);
96
    }
97
    return res;
98
}
99

    
100
uint64_t helper_mullv (uint64_t op1, uint64_t op2)
101
{
102
    int64_t res = (int64_t)op1 * (int64_t)op2;
103

    
104
    if (unlikely((int32_t)res != res)) {
105
        arith_excp(EXC_M_IOV, 0);
106
    }
107
    return (int64_t)((int32_t)res);
108
}
109

    
110
uint64_t helper_mulqv (uint64_t op1, uint64_t op2)
111
{
112
    uint64_t tl, th;
113

    
114
    muls64(&tl, &th, op1, op2);
115
    /* If th != 0 && th != -1, then we had an overflow */
116
    if (unlikely((th + 1) > 1)) {
117
        arith_excp(EXC_M_IOV, 0);
118
    }
119
    return tl;
120
}
121

    
122
uint64_t helper_umulh (uint64_t op1, uint64_t op2)
123
{
124
    uint64_t tl, th;
125

    
126
    mulu64(&tl, &th, op1, op2);
127
    return th;
128
}
129

    
130
uint64_t helper_ctpop (uint64_t arg)
131
{
132
    return ctpop64(arg);
133
}
134

    
135
uint64_t helper_ctlz (uint64_t arg)
136
{
137
    return clz64(arg);
138
}
139

    
140
uint64_t helper_cttz (uint64_t arg)
141
{
142
    return ctz64(arg);
143
}
144

    
145
static inline uint64_t byte_zap(uint64_t op, uint8_t mskb)
146
{
147
    uint64_t mask;
148

    
149
    mask = 0;
150
    mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL;
151
    mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL;
152
    mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL;
153
    mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL;
154
    mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL;
155
    mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL;
156
    mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL;
157
    mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL;
158

    
159
    return op & ~mask;
160
}
161

    
162
uint64_t helper_zap(uint64_t val, uint64_t mask)
163
{
164
    return byte_zap(val, mask);
165
}
166

    
167
uint64_t helper_zapnot(uint64_t val, uint64_t mask)
168
{
169
    return byte_zap(val, ~mask);
170
}
171

    
172
uint64_t helper_cmpbge (uint64_t op1, uint64_t op2)
173
{
174
    uint8_t opa, opb, res;
175
    int i;
176

    
177
    res = 0;
178
    for (i = 0; i < 8; i++) {
179
        opa = op1 >> (i * 8);
180
        opb = op2 >> (i * 8);
181
        if (opa >= opb)
182
            res |= 1 << i;
183
    }
184
    return res;
185
}
186

    
187
uint64_t helper_minub8 (uint64_t op1, uint64_t op2)
188
{
189
    uint64_t res = 0;
190
    uint8_t opa, opb, opr;
191
    int i;
192

    
193
    for (i = 0; i < 8; ++i) {
194
        opa = op1 >> (i * 8);
195
        opb = op2 >> (i * 8);
196
        opr = opa < opb ? opa : opb;
197
        res |= (uint64_t)opr << (i * 8);
198
    }
199
    return res;
200
}
201

    
202
uint64_t helper_minsb8 (uint64_t op1, uint64_t op2)
203
{
204
    uint64_t res = 0;
205
    int8_t opa, opb;
206
    uint8_t opr;
207
    int i;
208

    
209
    for (i = 0; i < 8; ++i) {
210
        opa = op1 >> (i * 8);
211
        opb = op2 >> (i * 8);
212
        opr = opa < opb ? opa : opb;
213
        res |= (uint64_t)opr << (i * 8);
214
    }
215
    return res;
216
}
217

    
218
uint64_t helper_minuw4 (uint64_t op1, uint64_t op2)
219
{
220
    uint64_t res = 0;
221
    uint16_t opa, opb, opr;
222
    int i;
223

    
224
    for (i = 0; i < 4; ++i) {
225
        opa = op1 >> (i * 16);
226
        opb = op2 >> (i * 16);
227
        opr = opa < opb ? opa : opb;
228
        res |= (uint64_t)opr << (i * 16);
229
    }
230
    return res;
231
}
232

    
233
uint64_t helper_minsw4 (uint64_t op1, uint64_t op2)
234
{
235
    uint64_t res = 0;
236
    int16_t opa, opb;
237
    uint16_t opr;
238
    int i;
239

    
240
    for (i = 0; i < 4; ++i) {
241
        opa = op1 >> (i * 16);
242
        opb = op2 >> (i * 16);
243
        opr = opa < opb ? opa : opb;
244
        res |= (uint64_t)opr << (i * 16);
245
    }
246
    return res;
247
}
248

    
249
uint64_t helper_maxub8 (uint64_t op1, uint64_t op2)
250
{
251
    uint64_t res = 0;
252
    uint8_t opa, opb, opr;
253
    int i;
254

    
255
    for (i = 0; i < 8; ++i) {
256
        opa = op1 >> (i * 8);
257
        opb = op2 >> (i * 8);
258
        opr = opa > opb ? opa : opb;
259
        res |= (uint64_t)opr << (i * 8);
260
    }
261
    return res;
262
}
263

    
264
uint64_t helper_maxsb8 (uint64_t op1, uint64_t op2)
265
{
266
    uint64_t res = 0;
267
    int8_t opa, opb;
268
    uint8_t opr;
269
    int i;
270

    
271
    for (i = 0; i < 8; ++i) {
272
        opa = op1 >> (i * 8);
273
        opb = op2 >> (i * 8);
274
        opr = opa > opb ? opa : opb;
275
        res |= (uint64_t)opr << (i * 8);
276
    }
277
    return res;
278
}
279

    
280
uint64_t helper_maxuw4 (uint64_t op1, uint64_t op2)
281
{
282
    uint64_t res = 0;
283
    uint16_t opa, opb, opr;
284
    int i;
285

    
286
    for (i = 0; i < 4; ++i) {
287
        opa = op1 >> (i * 16);
288
        opb = op2 >> (i * 16);
289
        opr = opa > opb ? opa : opb;
290
        res |= (uint64_t)opr << (i * 16);
291
    }
292
    return res;
293
}
294

    
295
uint64_t helper_maxsw4 (uint64_t op1, uint64_t op2)
296
{
297
    uint64_t res = 0;
298
    int16_t opa, opb;
299
    uint16_t opr;
300
    int i;
301

    
302
    for (i = 0; i < 4; ++i) {
303
        opa = op1 >> (i * 16);
304
        opb = op2 >> (i * 16);
305
        opr = opa > opb ? opa : opb;
306
        res |= (uint64_t)opr << (i * 16);
307
    }
308
    return res;
309
}
310

    
311
uint64_t helper_perr (uint64_t op1, uint64_t op2)
312
{
313
    uint64_t res = 0;
314
    uint8_t opa, opb, opr;
315
    int i;
316

    
317
    for (i = 0; i < 8; ++i) {
318
        opa = op1 >> (i * 8);
319
        opb = op2 >> (i * 8);
320
        if (opa >= opb)
321
            opr = opa - opb;
322
        else
323
            opr = opb - opa;
324
        res += opr;
325
    }
326
    return res;
327
}
328

    
329
uint64_t helper_pklb (uint64_t op1)
330
{
331
    return (op1 & 0xff) | ((op1 >> 24) & 0xff00);
332
}
333

    
334
uint64_t helper_pkwb (uint64_t op1)
335
{
336
    return ((op1 & 0xff)
337
            | ((op1 >> 8) & 0xff00)
338
            | ((op1 >> 16) & 0xff0000)
339
            | ((op1 >> 24) & 0xff000000));
340
}
341

    
342
uint64_t helper_unpkbl (uint64_t op1)
343
{
344
    return (op1 & 0xff) | ((op1 & 0xff00) << 24);
345
}
346

    
347
uint64_t helper_unpkbw (uint64_t op1)
348
{
349
    return ((op1 & 0xff)
350
            | ((op1 & 0xff00) << 8)
351
            | ((op1 & 0xff0000) << 16)
352
            | ((op1 & 0xff000000) << 24));
353
}
354

    
355
/* Floating point helpers */
356

    
357
void helper_setroundmode (uint32_t val)
358
{
359
    set_float_rounding_mode(val, &FP_STATUS);
360
}
361

    
362
void helper_setflushzero (uint32_t val)
363
{
364
    set_flush_to_zero(val, &FP_STATUS);
365
}
366

    
367
void helper_fp_exc_clear (void)
368
{
369
    set_float_exception_flags(0, &FP_STATUS);
370
}
371

    
372
uint32_t helper_fp_exc_get (void)
373
{
374
    return get_float_exception_flags(&FP_STATUS);
375
}
376

    
377
/* Raise exceptions for ieee fp insns without software completion.
378
   In that case there are no exceptions that don't trap; the mask
379
   doesn't apply.  */
380
void helper_fp_exc_raise(uint32_t exc, uint32_t regno)
381
{
382
    if (exc) {
383
        uint32_t hw_exc = 0;
384

    
385
        if (exc & float_flag_invalid) {
386
            hw_exc |= EXC_M_INV;
387
        }
388
        if (exc & float_flag_divbyzero) {
389
            hw_exc |= EXC_M_DZE;
390
        }
391
        if (exc & float_flag_overflow) {
392
            hw_exc |= EXC_M_FOV;
393
        }
394
        if (exc & float_flag_underflow) {
395
            hw_exc |= EXC_M_UNF;
396
        }
397
        if (exc & float_flag_inexact) {
398
            hw_exc |= EXC_M_INE;
399
        }
400

    
401
        arith_excp(hw_exc, 1ull << regno);
402
    }
403
}
404

    
405
/* Raise exceptions for ieee fp insns with software completion.  */
406
void helper_fp_exc_raise_s(uint32_t exc, uint32_t regno)
407
{
408
    if (exc) {
409
        env->fpcr_exc_status |= exc;
410

    
411
        exc &= ~env->fpcr_exc_mask;
412
        if (exc) {
413
            helper_fp_exc_raise(exc, regno);
414
        }
415
    }
416
}
417

    
418
/* Input remapping without software completion.  Handle denormal-map-to-zero
419
   and trap for all other non-finite numbers.  */
420
uint64_t helper_ieee_input(uint64_t val)
421
{
422
    uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
423
    uint64_t frac = val & 0xfffffffffffffull;
424

    
425
    if (exp == 0) {
426
        if (frac != 0) {
427
            /* If DNZ is set flush denormals to zero on input.  */
428
            if (env->fpcr_dnz) {
429
                val &= 1ull << 63;
430
            } else {
431
                arith_excp(EXC_M_UNF, 0);
432
            }
433
        }
434
    } else if (exp == 0x7ff) {
435
        /* Infinity or NaN.  */
436
        /* ??? I'm not sure these exception bit flags are correct.  I do
437
           know that the Linux kernel, at least, doesn't rely on them and
438
           just emulates the insn to figure out what exception to use.  */
439
        arith_excp(frac ? EXC_M_INV : EXC_M_FOV, 0);
440
    }
441
    return val;
442
}
443

    
444
/* Similar, but does not trap for infinities.  Used for comparisons.  */
445
uint64_t helper_ieee_input_cmp(uint64_t val)
446
{
447
    uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
448
    uint64_t frac = val & 0xfffffffffffffull;
449

    
450
    if (exp == 0) {
451
        if (frac != 0) {
452
            /* If DNZ is set flush denormals to zero on input.  */
453
            if (env->fpcr_dnz) {
454
                val &= 1ull << 63;
455
            } else {
456
                arith_excp(EXC_M_UNF, 0);
457
            }
458
        }
459
    } else if (exp == 0x7ff && frac) {
460
        /* NaN.  */
461
        arith_excp(EXC_M_INV, 0);
462
    }
463
    return val;
464
}
465

    
466
/* Input remapping with software completion enabled.  All we have to do
467
   is handle denormal-map-to-zero; all other inputs get exceptions as
468
   needed from the actual operation.  */
469
uint64_t helper_ieee_input_s(uint64_t val)
470
{
471
    if (env->fpcr_dnz) {
472
        uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
473
        if (exp == 0) {
474
            val &= 1ull << 63;
475
        }
476
    }
477
    return val;
478
}
479

    
480
/* F floating (VAX) */
481
static inline uint64_t float32_to_f(float32 fa)
482
{
483
    uint64_t r, exp, mant, sig;
484
    CPU_FloatU a;
485

    
486
    a.f = fa;
487
    sig = ((uint64_t)a.l & 0x80000000) << 32;
488
    exp = (a.l >> 23) & 0xff;
489
    mant = ((uint64_t)a.l & 0x007fffff) << 29;
490

    
491
    if (exp == 255) {
492
        /* NaN or infinity */
493
        r = 1; /* VAX dirty zero */
494
    } else if (exp == 0) {
495
        if (mant == 0) {
496
            /* Zero */
497
            r = 0;
498
        } else {
499
            /* Denormalized */
500
            r = sig | ((exp + 1) << 52) | mant;
501
        }
502
    } else {
503
        if (exp >= 253) {
504
            /* Overflow */
505
            r = 1; /* VAX dirty zero */
506
        } else {
507
            r = sig | ((exp + 2) << 52);
508
        }
509
    }
510

    
511
    return r;
512
}
513

    
514
static inline float32 f_to_float32(uint64_t a)
515
{
516
    uint32_t exp, mant_sig;
517
    CPU_FloatU r;
518

    
519
    exp = ((a >> 55) & 0x80) | ((a >> 52) & 0x7f);
520
    mant_sig = ((a >> 32) & 0x80000000) | ((a >> 29) & 0x007fffff);
521

    
522
    if (unlikely(!exp && mant_sig)) {
523
        /* Reserved operands / Dirty zero */
524
        helper_excp(EXCP_OPCDEC, 0);
525
    }
526

    
527
    if (exp < 3) {
528
        /* Underflow */
529
        r.l = 0;
530
    } else {
531
        r.l = ((exp - 2) << 23) | mant_sig;
532
    }
533

    
534
    return r.f;
535
}
536

    
537
uint32_t helper_f_to_memory (uint64_t a)
538
{
539
    uint32_t r;
540
    r =  (a & 0x00001fffe0000000ull) >> 13;
541
    r |= (a & 0x07ffe00000000000ull) >> 45;
542
    r |= (a & 0xc000000000000000ull) >> 48;
543
    return r;
544
}
545

    
546
uint64_t helper_memory_to_f (uint32_t a)
547
{
548
    uint64_t r;
549
    r =  ((uint64_t)(a & 0x0000c000)) << 48;
550
    r |= ((uint64_t)(a & 0x003fffff)) << 45;
551
    r |= ((uint64_t)(a & 0xffff0000)) << 13;
552
    if (!(a & 0x00004000))
553
        r |= 0x7ll << 59;
554
    return r;
555
}
556

    
557
/* ??? Emulating VAX arithmetic with IEEE arithmetic is wrong.  We should
558
   either implement VAX arithmetic properly or just signal invalid opcode.  */
559

    
560
uint64_t helper_addf (uint64_t a, uint64_t b)
561
{
562
    float32 fa, fb, fr;
563

    
564
    fa = f_to_float32(a);
565
    fb = f_to_float32(b);
566
    fr = float32_add(fa, fb, &FP_STATUS);
567
    return float32_to_f(fr);
568
}
569

    
570
uint64_t helper_subf (uint64_t a, uint64_t b)
571
{
572
    float32 fa, fb, fr;
573

    
574
    fa = f_to_float32(a);
575
    fb = f_to_float32(b);
576
    fr = float32_sub(fa, fb, &FP_STATUS);
577
    return float32_to_f(fr);
578
}
579

    
580
uint64_t helper_mulf (uint64_t a, uint64_t b)
581
{
582
    float32 fa, fb, fr;
583

    
584
    fa = f_to_float32(a);
585
    fb = f_to_float32(b);
586
    fr = float32_mul(fa, fb, &FP_STATUS);
587
    return float32_to_f(fr);
588
}
589

    
590
uint64_t helper_divf (uint64_t a, uint64_t b)
591
{
592
    float32 fa, fb, fr;
593

    
594
    fa = f_to_float32(a);
595
    fb = f_to_float32(b);
596
    fr = float32_div(fa, fb, &FP_STATUS);
597
    return float32_to_f(fr);
598
}
599

    
600
uint64_t helper_sqrtf (uint64_t t)
601
{
602
    float32 ft, fr;
603

    
604
    ft = f_to_float32(t);
605
    fr = float32_sqrt(ft, &FP_STATUS);
606
    return float32_to_f(fr);
607
}
608

    
609

    
610
/* G floating (VAX) */
611
static inline uint64_t float64_to_g(float64 fa)
612
{
613
    uint64_t r, exp, mant, sig;
614
    CPU_DoubleU a;
615

    
616
    a.d = fa;
617
    sig = a.ll & 0x8000000000000000ull;
618
    exp = (a.ll >> 52) & 0x7ff;
619
    mant = a.ll & 0x000fffffffffffffull;
620

    
621
    if (exp == 2047) {
622
        /* NaN or infinity */
623
        r = 1; /* VAX dirty zero */
624
    } else if (exp == 0) {
625
        if (mant == 0) {
626
            /* Zero */
627
            r = 0;
628
        } else {
629
            /* Denormalized */
630
            r = sig | ((exp + 1) << 52) | mant;
631
        }
632
    } else {
633
        if (exp >= 2045) {
634
            /* Overflow */
635
            r = 1; /* VAX dirty zero */
636
        } else {
637
            r = sig | ((exp + 2) << 52);
638
        }
639
    }
640

    
641
    return r;
642
}
643

    
644
static inline float64 g_to_float64(uint64_t a)
645
{
646
    uint64_t exp, mant_sig;
647
    CPU_DoubleU r;
648

    
649
    exp = (a >> 52) & 0x7ff;
650
    mant_sig = a & 0x800fffffffffffffull;
651

    
652
    if (!exp && mant_sig) {
653
        /* Reserved operands / Dirty zero */
654
        helper_excp(EXCP_OPCDEC, 0);
655
    }
656

    
657
    if (exp < 3) {
658
        /* Underflow */
659
        r.ll = 0;
660
    } else {
661
        r.ll = ((exp - 2) << 52) | mant_sig;
662
    }
663

    
664
    return r.d;
665
}
666

    
667
uint64_t helper_g_to_memory (uint64_t a)
668
{
669
    uint64_t r;
670
    r =  (a & 0x000000000000ffffull) << 48;
671
    r |= (a & 0x00000000ffff0000ull) << 16;
672
    r |= (a & 0x0000ffff00000000ull) >> 16;
673
    r |= (a & 0xffff000000000000ull) >> 48;
674
    return r;
675
}
676

    
677
uint64_t helper_memory_to_g (uint64_t a)
678
{
679
    uint64_t r;
680
    r =  (a & 0x000000000000ffffull) << 48;
681
    r |= (a & 0x00000000ffff0000ull) << 16;
682
    r |= (a & 0x0000ffff00000000ull) >> 16;
683
    r |= (a & 0xffff000000000000ull) >> 48;
684
    return r;
685
}
686

    
687
uint64_t helper_addg (uint64_t a, uint64_t b)
688
{
689
    float64 fa, fb, fr;
690

    
691
    fa = g_to_float64(a);
692
    fb = g_to_float64(b);
693
    fr = float64_add(fa, fb, &FP_STATUS);
694
    return float64_to_g(fr);
695
}
696

    
697
uint64_t helper_subg (uint64_t a, uint64_t b)
698
{
699
    float64 fa, fb, fr;
700

    
701
    fa = g_to_float64(a);
702
    fb = g_to_float64(b);
703
    fr = float64_sub(fa, fb, &FP_STATUS);
704
    return float64_to_g(fr);
705
}
706

    
707
uint64_t helper_mulg (uint64_t a, uint64_t b)
708
{
709
    float64 fa, fb, fr;
710

    
711
    fa = g_to_float64(a);
712
    fb = g_to_float64(b);
713
    fr = float64_mul(fa, fb, &FP_STATUS);
714
    return float64_to_g(fr);
715
}
716

    
717
uint64_t helper_divg (uint64_t a, uint64_t b)
718
{
719
    float64 fa, fb, fr;
720

    
721
    fa = g_to_float64(a);
722
    fb = g_to_float64(b);
723
    fr = float64_div(fa, fb, &FP_STATUS);
724
    return float64_to_g(fr);
725
}
726

    
727
uint64_t helper_sqrtg (uint64_t a)
728
{
729
    float64 fa, fr;
730

    
731
    fa = g_to_float64(a);
732
    fr = float64_sqrt(fa, &FP_STATUS);
733
    return float64_to_g(fr);
734
}
735

    
736

    
737
/* S floating (single) */
738

    
739
/* Taken from linux/arch/alpha/kernel/traps.c, s_mem_to_reg.  */
740
static inline uint64_t float32_to_s_int(uint32_t fi)
741
{
742
    uint32_t frac = fi & 0x7fffff;
743
    uint32_t sign = fi >> 31;
744
    uint32_t exp_msb = (fi >> 30) & 1;
745
    uint32_t exp_low = (fi >> 23) & 0x7f;
746
    uint32_t exp;
747

    
748
    exp = (exp_msb << 10) | exp_low;
749
    if (exp_msb) {
750
        if (exp_low == 0x7f)
751
            exp = 0x7ff;
752
    } else {
753
        if (exp_low != 0x00)
754
            exp |= 0x380;
755
    }
756

    
757
    return (((uint64_t)sign << 63)
758
            | ((uint64_t)exp << 52)
759
            | ((uint64_t)frac << 29));
760
}
761

    
762
static inline uint64_t float32_to_s(float32 fa)
763
{
764
    CPU_FloatU a;
765
    a.f = fa;
766
    return float32_to_s_int(a.l);
767
}
768

    
769
static inline uint32_t s_to_float32_int(uint64_t a)
770
{
771
    return ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff);
772
}
773

    
774
static inline float32 s_to_float32(uint64_t a)
775
{
776
    CPU_FloatU r;
777
    r.l = s_to_float32_int(a);
778
    return r.f;
779
}
780

    
781
uint32_t helper_s_to_memory (uint64_t a)
782
{
783
    return s_to_float32_int(a);
784
}
785

    
786
uint64_t helper_memory_to_s (uint32_t a)
787
{
788
    return float32_to_s_int(a);
789
}
790

    
791
uint64_t helper_adds (uint64_t a, uint64_t b)
792
{
793
    float32 fa, fb, fr;
794

    
795
    fa = s_to_float32(a);
796
    fb = s_to_float32(b);
797
    fr = float32_add(fa, fb, &FP_STATUS);
798
    return float32_to_s(fr);
799
}
800

    
801
uint64_t helper_subs (uint64_t a, uint64_t b)
802
{
803
    float32 fa, fb, fr;
804

    
805
    fa = s_to_float32(a);
806
    fb = s_to_float32(b);
807
    fr = float32_sub(fa, fb, &FP_STATUS);
808
    return float32_to_s(fr);
809
}
810

    
811
uint64_t helper_muls (uint64_t a, uint64_t b)
812
{
813
    float32 fa, fb, fr;
814

    
815
    fa = s_to_float32(a);
816
    fb = s_to_float32(b);
817
    fr = float32_mul(fa, fb, &FP_STATUS);
818
    return float32_to_s(fr);
819
}
820

    
821
uint64_t helper_divs (uint64_t a, uint64_t b)
822
{
823
    float32 fa, fb, fr;
824

    
825
    fa = s_to_float32(a);
826
    fb = s_to_float32(b);
827
    fr = float32_div(fa, fb, &FP_STATUS);
828
    return float32_to_s(fr);
829
}
830

    
831
uint64_t helper_sqrts (uint64_t a)
832
{
833
    float32 fa, fr;
834

    
835
    fa = s_to_float32(a);
836
    fr = float32_sqrt(fa, &FP_STATUS);
837
    return float32_to_s(fr);
838
}
839

    
840

    
841
/* T floating (double) */
842
static inline float64 t_to_float64(uint64_t a)
843
{
844
    /* Memory format is the same as float64 */
845
    CPU_DoubleU r;
846
    r.ll = a;
847
    return r.d;
848
}
849

    
850
static inline uint64_t float64_to_t(float64 fa)
851
{
852
    /* Memory format is the same as float64 */
853
    CPU_DoubleU r;
854
    r.d = fa;
855
    return r.ll;
856
}
857

    
858
uint64_t helper_addt (uint64_t a, uint64_t b)
859
{
860
    float64 fa, fb, fr;
861

    
862
    fa = t_to_float64(a);
863
    fb = t_to_float64(b);
864
    fr = float64_add(fa, fb, &FP_STATUS);
865
    return float64_to_t(fr);
866
}
867

    
868
uint64_t helper_subt (uint64_t a, uint64_t b)
869
{
870
    float64 fa, fb, fr;
871

    
872
    fa = t_to_float64(a);
873
    fb = t_to_float64(b);
874
    fr = float64_sub(fa, fb, &FP_STATUS);
875
    return float64_to_t(fr);
876
}
877

    
878
uint64_t helper_mult (uint64_t a, uint64_t b)
879
{
880
    float64 fa, fb, fr;
881

    
882
    fa = t_to_float64(a);
883
    fb = t_to_float64(b);
884
    fr = float64_mul(fa, fb, &FP_STATUS);
885
    return float64_to_t(fr);
886
}
887

    
888
uint64_t helper_divt (uint64_t a, uint64_t b)
889
{
890
    float64 fa, fb, fr;
891

    
892
    fa = t_to_float64(a);
893
    fb = t_to_float64(b);
894
    fr = float64_div(fa, fb, &FP_STATUS);
895
    return float64_to_t(fr);
896
}
897

    
898
uint64_t helper_sqrtt (uint64_t a)
899
{
900
    float64 fa, fr;
901

    
902
    fa = t_to_float64(a);
903
    fr = float64_sqrt(fa, &FP_STATUS);
904
    return float64_to_t(fr);
905
}
906

    
907
/* Comparisons */
908
uint64_t helper_cmptun (uint64_t a, uint64_t b)
909
{
910
    float64 fa, fb;
911

    
912
    fa = t_to_float64(a);
913
    fb = t_to_float64(b);
914

    
915
    if (float64_unordered_quiet(fa, fb, &FP_STATUS)) {
916
        return 0x4000000000000000ULL;
917
    } else {
918
        return 0;
919
    }
920
}
921

    
922
uint64_t helper_cmpteq(uint64_t a, uint64_t b)
923
{
924
    float64 fa, fb;
925

    
926
    fa = t_to_float64(a);
927
    fb = t_to_float64(b);
928

    
929
    if (float64_eq_quiet(fa, fb, &FP_STATUS))
930
        return 0x4000000000000000ULL;
931
    else
932
        return 0;
933
}
934

    
935
uint64_t helper_cmptle(uint64_t a, uint64_t b)
936
{
937
    float64 fa, fb;
938

    
939
    fa = t_to_float64(a);
940
    fb = t_to_float64(b);
941

    
942
    if (float64_le(fa, fb, &FP_STATUS))
943
        return 0x4000000000000000ULL;
944
    else
945
        return 0;
946
}
947

    
948
uint64_t helper_cmptlt(uint64_t a, uint64_t b)
949
{
950
    float64 fa, fb;
951

    
952
    fa = t_to_float64(a);
953
    fb = t_to_float64(b);
954

    
955
    if (float64_lt(fa, fb, &FP_STATUS))
956
        return 0x4000000000000000ULL;
957
    else
958
        return 0;
959
}
960

    
961
uint64_t helper_cmpgeq(uint64_t a, uint64_t b)
962
{
963
    float64 fa, fb;
964

    
965
    fa = g_to_float64(a);
966
    fb = g_to_float64(b);
967

    
968
    if (float64_eq_quiet(fa, fb, &FP_STATUS))
969
        return 0x4000000000000000ULL;
970
    else
971
        return 0;
972
}
973

    
974
uint64_t helper_cmpgle(uint64_t a, uint64_t b)
975
{
976
    float64 fa, fb;
977

    
978
    fa = g_to_float64(a);
979
    fb = g_to_float64(b);
980

    
981
    if (float64_le(fa, fb, &FP_STATUS))
982
        return 0x4000000000000000ULL;
983
    else
984
        return 0;
985
}
986

    
987
uint64_t helper_cmpglt(uint64_t a, uint64_t b)
988
{
989
    float64 fa, fb;
990

    
991
    fa = g_to_float64(a);
992
    fb = g_to_float64(b);
993

    
994
    if (float64_lt(fa, fb, &FP_STATUS))
995
        return 0x4000000000000000ULL;
996
    else
997
        return 0;
998
}
999

    
1000
/* Floating point format conversion */
1001
uint64_t helper_cvtts (uint64_t a)
1002
{
1003
    float64 fa;
1004
    float32 fr;
1005

    
1006
    fa = t_to_float64(a);
1007
    fr = float64_to_float32(fa, &FP_STATUS);
1008
    return float32_to_s(fr);
1009
}
1010

    
1011
uint64_t helper_cvtst (uint64_t a)
1012
{
1013
    float32 fa;
1014
    float64 fr;
1015

    
1016
    fa = s_to_float32(a);
1017
    fr = float32_to_float64(fa, &FP_STATUS);
1018
    return float64_to_t(fr);
1019
}
1020

    
1021
uint64_t helper_cvtqs (uint64_t a)
1022
{
1023
    float32 fr = int64_to_float32(a, &FP_STATUS);
1024
    return float32_to_s(fr);
1025
}
1026

    
1027
/* Implement float64 to uint64 conversion without saturation -- we must
1028
   supply the truncated result.  This behaviour is used by the compiler
1029
   to get unsigned conversion for free with the same instruction.
1030

1031
   The VI flag is set when overflow or inexact exceptions should be raised.  */
1032

    
1033
static inline uint64_t helper_cvttq_internal(uint64_t a, int roundmode, int VI)
1034
{
1035
    uint64_t frac, ret = 0;
1036
    uint32_t exp, sign, exc = 0;
1037
    int shift;
1038

    
1039
    sign = (a >> 63);
1040
    exp = (uint32_t)(a >> 52) & 0x7ff;
1041
    frac = a & 0xfffffffffffffull;
1042

    
1043
    if (exp == 0) {
1044
        if (unlikely(frac != 0)) {
1045
            goto do_underflow;
1046
        }
1047
    } else if (exp == 0x7ff) {
1048
        exc = (frac ? float_flag_invalid : VI ? float_flag_overflow : 0);
1049
    } else {
1050
        /* Restore implicit bit.  */
1051
        frac |= 0x10000000000000ull;
1052

    
1053
        shift = exp - 1023 - 52;
1054
        if (shift >= 0) {
1055
            /* In this case the number is so large that we must shift
1056
               the fraction left.  There is no rounding to do.  */
1057
            if (shift < 63) {
1058
                ret = frac << shift;
1059
                if (VI && (ret >> shift) != frac) {
1060
                    exc = float_flag_overflow;
1061
                }
1062
            }
1063
        } else {
1064
            uint64_t round;
1065

    
1066
            /* In this case the number is smaller than the fraction as
1067
               represented by the 52 bit number.  Here we must think
1068
               about rounding the result.  Handle this by shifting the
1069
               fractional part of the number into the high bits of ROUND.
1070
               This will let us efficiently handle round-to-nearest.  */
1071
            shift = -shift;
1072
            if (shift < 63) {
1073
                ret = frac >> shift;
1074
                round = frac << (64 - shift);
1075
            } else {
1076
                /* The exponent is so small we shift out everything.
1077
                   Leave a sticky bit for proper rounding below.  */
1078
            do_underflow:
1079
                round = 1;
1080
            }
1081

    
1082
            if (round) {
1083
                exc = (VI ? float_flag_inexact : 0);
1084
                switch (roundmode) {
1085
                case float_round_nearest_even:
1086
                    if (round == (1ull << 63)) {
1087
                        /* Fraction is exactly 0.5; round to even.  */
1088
                        ret += (ret & 1);
1089
                    } else if (round > (1ull << 63)) {
1090
                        ret += 1;
1091
                    }
1092
                    break;
1093
                case float_round_to_zero:
1094
                    break;
1095
                case float_round_up:
1096
                    ret += 1 - sign;
1097
                    break;
1098
                case float_round_down:
1099
                    ret += sign;
1100
                    break;
1101
                }
1102
            }
1103
        }
1104
        if (sign) {
1105
            ret = -ret;
1106
        }
1107
    }
1108
    if (unlikely(exc)) {
1109
        float_raise(exc, &FP_STATUS);
1110
    }
1111

    
1112
    return ret;
1113
}
1114

    
1115
uint64_t helper_cvttq(uint64_t a)
1116
{
1117
    return helper_cvttq_internal(a, FP_STATUS.float_rounding_mode, 1);
1118
}
1119

    
1120
uint64_t helper_cvttq_c(uint64_t a)
1121
{
1122
    return helper_cvttq_internal(a, float_round_to_zero, 0);
1123
}
1124

    
1125
uint64_t helper_cvttq_svic(uint64_t a)
1126
{
1127
    return helper_cvttq_internal(a, float_round_to_zero, 1);
1128
}
1129

    
1130
uint64_t helper_cvtqt (uint64_t a)
1131
{
1132
    float64 fr = int64_to_float64(a, &FP_STATUS);
1133
    return float64_to_t(fr);
1134
}
1135

    
1136
uint64_t helper_cvtqf (uint64_t a)
1137
{
1138
    float32 fr = int64_to_float32(a, &FP_STATUS);
1139
    return float32_to_f(fr);
1140
}
1141

    
1142
uint64_t helper_cvtgf (uint64_t a)
1143
{
1144
    float64 fa;
1145
    float32 fr;
1146

    
1147
    fa = g_to_float64(a);
1148
    fr = float64_to_float32(fa, &FP_STATUS);
1149
    return float32_to_f(fr);
1150
}
1151

    
1152
uint64_t helper_cvtgq (uint64_t a)
1153
{
1154
    float64 fa = g_to_float64(a);
1155
    return float64_to_int64_round_to_zero(fa, &FP_STATUS);
1156
}
1157

    
1158
uint64_t helper_cvtqg (uint64_t a)
1159
{
1160
    float64 fr;
1161
    fr = int64_to_float64(a, &FP_STATUS);
1162
    return float64_to_g(fr);
1163
}
1164

    
1165
/* PALcode support special instructions */
1166
#if !defined (CONFIG_USER_ONLY)
1167
void helper_hw_ret (uint64_t a)
1168
{
1169
    env->pc = a & ~3;
1170
    env->pal_mode = a & 1;
1171
    env->intr_flag = 0;
1172
    env->lock_addr = -1;
1173
}
1174
#endif
1175

    
1176
/*****************************************************************************/
1177
/* Softmmu support */
1178
#if !defined (CONFIG_USER_ONLY)
1179
uint64_t helper_ldl_phys(uint64_t p)
1180
{
1181
    return (int32_t)ldl_phys(p);
1182
}
1183

    
1184
uint64_t helper_ldq_phys(uint64_t p)
1185
{
1186
    return ldq_phys(p);
1187
}
1188

    
1189
uint64_t helper_ldl_l_phys(uint64_t p)
1190
{
1191
    env->lock_addr = p;
1192
    return env->lock_value = (int32_t)ldl_phys(p);
1193
}
1194

    
1195
uint64_t helper_ldq_l_phys(uint64_t p)
1196
{
1197
    env->lock_addr = p;
1198
    return env->lock_value = ldl_phys(p);
1199
}
1200

    
1201
void helper_stl_phys(uint64_t p, uint64_t v)
1202
{
1203
    stl_phys(p, v);
1204
}
1205

    
1206
void helper_stq_phys(uint64_t p, uint64_t v)
1207
{
1208
    stq_phys(p, v);
1209
}
1210

    
1211
uint64_t helper_stl_c_phys(uint64_t p, uint64_t v)
1212
{
1213
    uint64_t ret = 0;
1214

    
1215
    if (p == env->lock_addr) {
1216
        int32_t old = ldl_phys(p);
1217
        if (old == (int32_t)env->lock_value) {
1218
            stl_phys(p, v);
1219
            ret = 1;
1220
        }
1221
    }
1222
    env->lock_addr = -1;
1223

    
1224
    return ret;
1225
}
1226

    
1227
uint64_t helper_stq_c_phys(uint64_t p, uint64_t v)
1228
{
1229
    uint64_t ret = 0;
1230

    
1231
    if (p == env->lock_addr) {
1232
        uint64_t old = ldq_phys(p);
1233
        if (old == env->lock_value) {
1234
            stq_phys(p, v);
1235
            ret = 1;
1236
        }
1237
    }
1238
    env->lock_addr = -1;
1239

    
1240
    return ret;
1241
}
1242

    
1243
#define MMUSUFFIX _mmu
1244

    
1245
#define SHIFT 0
1246
#include "softmmu_template.h"
1247

    
1248
#define SHIFT 1
1249
#include "softmmu_template.h"
1250

    
1251
#define SHIFT 2
1252
#include "softmmu_template.h"
1253

    
1254
#define SHIFT 3
1255
#include "softmmu_template.h"
1256

    
1257
/* try to fill the TLB and return an exception if error. If retaddr is
1258
   NULL, it means that the function was called in C code (i.e. not
1259
   from generated code or from helper.c) */
1260
/* XXX: fix it to restore all registers */
1261
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1262
{
1263
    TranslationBlock *tb;
1264
    CPUState *saved_env;
1265
    unsigned long pc;
1266
    int ret;
1267

    
1268
    /* XXX: hack to restore env in all cases, even if not called from
1269
       generated code */
1270
    saved_env = env;
1271
    env = cpu_single_env;
1272
    ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1273
    if (!likely(ret == 0)) {
1274
        if (likely(retaddr)) {
1275
            /* now we have a real cpu fault */
1276
            pc = (unsigned long)retaddr;
1277
            tb = tb_find_pc(pc);
1278
            if (likely(tb)) {
1279
                /* the PC is inside the translated code. It means that we have
1280
                   a virtual CPU fault */
1281
                cpu_restore_state(tb, env, pc);
1282
            }
1283
        }
1284
        /* Exception index and error code are already set */
1285
        cpu_loop_exit();
1286
    }
1287
    env = saved_env;
1288
}
1289

    
1290
#endif