Statistics
| Branch: | Revision:

root / target-alpha / op_helper.c @ 50eb6e5c

History | View | Annotate | Download (25.4 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

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

    
34
uint64_t helper_load_pcc (void)
35
{
36
    /* XXX: TODO */
37
    return 0;
38
}
39

    
40
uint64_t helper_load_fpcr (void)
41
{
42
    return cpu_alpha_load_fpcr (env);
43
}
44

    
45
void helper_store_fpcr (uint64_t val)
46
{
47
    cpu_alpha_store_fpcr (env, val);
48
}
49

    
50
static spinlock_t intr_cpu_lock = SPIN_LOCK_UNLOCKED;
51

    
52
uint64_t helper_rs(void)
53
{
54
    uint64_t tmp;
55

    
56
    spin_lock(&intr_cpu_lock);
57
    tmp = env->intr_flag;
58
    env->intr_flag = 1;
59
    spin_unlock(&intr_cpu_lock);
60

    
61
    return tmp;
62
}
63

    
64
uint64_t helper_rc(void)
65
{
66
    uint64_t tmp;
67

    
68
    spin_lock(&intr_cpu_lock);
69
    tmp = env->intr_flag;
70
    env->intr_flag = 0;
71
    spin_unlock(&intr_cpu_lock);
72

    
73
    return tmp;
74
}
75

    
76
uint64_t helper_addqv (uint64_t op1, uint64_t op2)
77
{
78
    uint64_t tmp = op1;
79
    op1 += op2;
80
    if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) {
81
        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
82
    }
83
    return op1;
84
}
85

    
86
uint64_t helper_addlv (uint64_t op1, uint64_t op2)
87
{
88
    uint64_t tmp = op1;
89
    op1 = (uint32_t)(op1 + op2);
90
    if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) {
91
        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
92
    }
93
    return op1;
94
}
95

    
96
uint64_t helper_subqv (uint64_t op1, uint64_t op2)
97
{
98
    uint64_t res;
99
    res = op1 - op2;
100
    if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) {
101
        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
102
    }
103
    return res;
104
}
105

    
106
uint64_t helper_sublv (uint64_t op1, uint64_t op2)
107
{
108
    uint32_t res;
109
    res = op1 - op2;
110
    if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) {
111
        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
112
    }
113
    return res;
114
}
115

    
116
uint64_t helper_mullv (uint64_t op1, uint64_t op2)
117
{
118
    int64_t res = (int64_t)op1 * (int64_t)op2;
119

    
120
    if (unlikely((int32_t)res != res)) {
121
        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
122
    }
123
    return (int64_t)((int32_t)res);
124
}
125

    
126
uint64_t helper_mulqv (uint64_t op1, uint64_t op2)
127
{
128
    uint64_t tl, th;
129

    
130
    muls64(&tl, &th, op1, op2);
131
    /* If th != 0 && th != -1, then we had an overflow */
132
    if (unlikely((th + 1) > 1)) {
133
        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
134
    }
135
    return tl;
136
}
137

    
138
uint64_t helper_umulh (uint64_t op1, uint64_t op2)
139
{
140
    uint64_t tl, th;
141

    
142
    mulu64(&tl, &th, op1, op2);
143
    return th;
144
}
145

    
146
uint64_t helper_ctpop (uint64_t arg)
147
{
148
    return ctpop64(arg);
149
}
150

    
151
uint64_t helper_ctlz (uint64_t arg)
152
{
153
    return clz64(arg);
154
}
155

    
156
uint64_t helper_cttz (uint64_t arg)
157
{
158
    return ctz64(arg);
159
}
160

    
161
static inline uint64_t byte_zap(uint64_t op, uint8_t mskb)
162
{
163
    uint64_t mask;
164

    
165
    mask = 0;
166
    mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL;
167
    mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL;
168
    mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL;
169
    mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL;
170
    mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL;
171
    mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL;
172
    mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL;
173
    mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL;
174

    
175
    return op & ~mask;
176
}
177

    
178
uint64_t helper_zap(uint64_t val, uint64_t mask)
179
{
180
    return byte_zap(val, mask);
181
}
182

    
183
uint64_t helper_zapnot(uint64_t val, uint64_t mask)
184
{
185
    return byte_zap(val, ~mask);
186
}
187

    
188
uint64_t helper_cmpbge (uint64_t op1, uint64_t op2)
189
{
190
    uint8_t opa, opb, res;
191
    int i;
192

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

    
203
uint64_t helper_minub8 (uint64_t op1, uint64_t op2)
204
{
205
    uint64_t res = 0;
206
    uint8_t opa, opb, 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_minsb8 (uint64_t op1, uint64_t op2)
219
{
220
    uint64_t res = 0;
221
    int8_t opa, opb;
222
    uint8_t opr;
223
    int i;
224

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

    
234
uint64_t helper_minuw4 (uint64_t op1, uint64_t op2)
235
{
236
    uint64_t res = 0;
237
    uint16_t opa, opb, 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_minsw4 (uint64_t op1, uint64_t op2)
250
{
251
    uint64_t res = 0;
252
    int16_t opa, opb;
253
    uint16_t opr;
254
    int i;
255

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

    
265
uint64_t helper_maxub8 (uint64_t op1, uint64_t op2)
266
{
267
    uint64_t res = 0;
268
    uint8_t opa, opb, 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_maxsb8 (uint64_t op1, uint64_t op2)
281
{
282
    uint64_t res = 0;
283
    int8_t opa, opb;
284
    uint8_t opr;
285
    int i;
286

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

    
296
uint64_t helper_maxuw4 (uint64_t op1, uint64_t op2)
297
{
298
    uint64_t res = 0;
299
    uint16_t opa, opb, 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_maxsw4 (uint64_t op1, uint64_t op2)
312
{
313
    uint64_t res = 0;
314
    int16_t opa, opb;
315
    uint16_t opr;
316
    int i;
317

    
318
    for (i = 0; i < 4; ++i) {
319
        opa = op1 >> (i * 16);
320
        opb = op2 >> (i * 16);
321
        opr = opa > opb ? opa : opb;
322
        res |= (uint64_t)opr << (i * 16);
323
    }
324
    return res;
325
}
326

    
327
uint64_t helper_perr (uint64_t op1, uint64_t op2)
328
{
329
    uint64_t res = 0;
330
    uint8_t opa, opb, opr;
331
    int i;
332

    
333
    for (i = 0; i < 8; ++i) {
334
        opa = op1 >> (i * 8);
335
        opb = op2 >> (i * 8);
336
        if (opa >= opb)
337
            opr = opa - opb;
338
        else
339
            opr = opb - opa;
340
        res += opr;
341
    }
342
    return res;
343
}
344

    
345
uint64_t helper_pklb (uint64_t op1)
346
{
347
    return (op1 & 0xff) | ((op1 >> 24) & 0xff00);
348
}
349

    
350
uint64_t helper_pkwb (uint64_t op1)
351
{
352
    return ((op1 & 0xff)
353
            | ((op1 >> 8) & 0xff00)
354
            | ((op1 >> 16) & 0xff0000)
355
            | ((op1 >> 24) & 0xff000000));
356
}
357

    
358
uint64_t helper_unpkbl (uint64_t op1)
359
{
360
    return (op1 & 0xff) | ((op1 & 0xff00) << 24);
361
}
362

    
363
uint64_t helper_unpkbw (uint64_t op1)
364
{
365
    return ((op1 & 0xff)
366
            | ((op1 & 0xff00) << 8)
367
            | ((op1 & 0xff0000) << 16)
368
            | ((op1 & 0xff000000) << 24));
369
}
370

    
371
/* Floating point helpers */
372

    
373
/* F floating (VAX) */
374
static inline uint64_t float32_to_f(float32 fa)
375
{
376
    uint64_t r, exp, mant, sig;
377
    CPU_FloatU a;
378

    
379
    a.f = fa;
380
    sig = ((uint64_t)a.l & 0x80000000) << 32;
381
    exp = (a.l >> 23) & 0xff;
382
    mant = ((uint64_t)a.l & 0x007fffff) << 29;
383

    
384
    if (exp == 255) {
385
        /* NaN or infinity */
386
        r = 1; /* VAX dirty zero */
387
    } else if (exp == 0) {
388
        if (mant == 0) {
389
            /* Zero */
390
            r = 0;
391
        } else {
392
            /* Denormalized */
393
            r = sig | ((exp + 1) << 52) | mant;
394
        }
395
    } else {
396
        if (exp >= 253) {
397
            /* Overflow */
398
            r = 1; /* VAX dirty zero */
399
        } else {
400
            r = sig | ((exp + 2) << 52);
401
        }
402
    }
403

    
404
    return r;
405
}
406

    
407
static inline float32 f_to_float32(uint64_t a)
408
{
409
    uint32_t exp, mant_sig;
410
    CPU_FloatU r;
411

    
412
    exp = ((a >> 55) & 0x80) | ((a >> 52) & 0x7f);
413
    mant_sig = ((a >> 32) & 0x80000000) | ((a >> 29) & 0x007fffff);
414

    
415
    if (unlikely(!exp && mant_sig)) {
416
        /* Reserved operands / Dirty zero */
417
        helper_excp(EXCP_OPCDEC, 0);
418
    }
419

    
420
    if (exp < 3) {
421
        /* Underflow */
422
        r.l = 0;
423
    } else {
424
        r.l = ((exp - 2) << 23) | mant_sig;
425
    }
426

    
427
    return r.f;
428
}
429

    
430
uint32_t helper_f_to_memory (uint64_t a)
431
{
432
    uint32_t r;
433
    r =  (a & 0x00001fffe0000000ull) >> 13;
434
    r |= (a & 0x07ffe00000000000ull) >> 45;
435
    r |= (a & 0xc000000000000000ull) >> 48;
436
    return r;
437
}
438

    
439
uint64_t helper_memory_to_f (uint32_t a)
440
{
441
    uint64_t r;
442
    r =  ((uint64_t)(a & 0x0000c000)) << 48;
443
    r |= ((uint64_t)(a & 0x003fffff)) << 45;
444
    r |= ((uint64_t)(a & 0xffff0000)) << 13;
445
    if (!(a & 0x00004000))
446
        r |= 0x7ll << 59;
447
    return r;
448
}
449

    
450
uint64_t helper_addf (uint64_t a, uint64_t b)
451
{
452
    float32 fa, fb, fr;
453

    
454
    fa = f_to_float32(a);
455
    fb = f_to_float32(b);
456
    fr = float32_add(fa, fb, &FP_STATUS);
457
    return float32_to_f(fr);
458
}
459

    
460
uint64_t helper_subf (uint64_t a, uint64_t b)
461
{
462
    float32 fa, fb, fr;
463

    
464
    fa = f_to_float32(a);
465
    fb = f_to_float32(b);
466
    fr = float32_sub(fa, fb, &FP_STATUS);
467
    return float32_to_f(fr);
468
}
469

    
470
uint64_t helper_mulf (uint64_t a, uint64_t b)
471
{
472
    float32 fa, fb, fr;
473

    
474
    fa = f_to_float32(a);
475
    fb = f_to_float32(b);
476
    fr = float32_mul(fa, fb, &FP_STATUS);
477
    return float32_to_f(fr);
478
}
479

    
480
uint64_t helper_divf (uint64_t a, uint64_t b)
481
{
482
    float32 fa, fb, fr;
483

    
484
    fa = f_to_float32(a);
485
    fb = f_to_float32(b);
486
    fr = float32_div(fa, fb, &FP_STATUS);
487
    return float32_to_f(fr);
488
}
489

    
490
uint64_t helper_sqrtf (uint64_t t)
491
{
492
    float32 ft, fr;
493

    
494
    ft = f_to_float32(t);
495
    fr = float32_sqrt(ft, &FP_STATUS);
496
    return float32_to_f(fr);
497
}
498

    
499

    
500
/* G floating (VAX) */
501
static inline uint64_t float64_to_g(float64 fa)
502
{
503
    uint64_t r, exp, mant, sig;
504
    CPU_DoubleU a;
505

    
506
    a.d = fa;
507
    sig = a.ll & 0x8000000000000000ull;
508
    exp = (a.ll >> 52) & 0x7ff;
509
    mant = a.ll & 0x000fffffffffffffull;
510

    
511
    if (exp == 2047) {
512
        /* NaN or infinity */
513
        r = 1; /* VAX dirty zero */
514
    } else if (exp == 0) {
515
        if (mant == 0) {
516
            /* Zero */
517
            r = 0;
518
        } else {
519
            /* Denormalized */
520
            r = sig | ((exp + 1) << 52) | mant;
521
        }
522
    } else {
523
        if (exp >= 2045) {
524
            /* Overflow */
525
            r = 1; /* VAX dirty zero */
526
        } else {
527
            r = sig | ((exp + 2) << 52);
528
        }
529
    }
530

    
531
    return r;
532
}
533

    
534
static inline float64 g_to_float64(uint64_t a)
535
{
536
    uint64_t exp, mant_sig;
537
    CPU_DoubleU r;
538

    
539
    exp = (a >> 52) & 0x7ff;
540
    mant_sig = a & 0x800fffffffffffffull;
541

    
542
    if (!exp && mant_sig) {
543
        /* Reserved operands / Dirty zero */
544
        helper_excp(EXCP_OPCDEC, 0);
545
    }
546

    
547
    if (exp < 3) {
548
        /* Underflow */
549
        r.ll = 0;
550
    } else {
551
        r.ll = ((exp - 2) << 52) | mant_sig;
552
    }
553

    
554
    return r.d;
555
}
556

    
557
uint64_t helper_g_to_memory (uint64_t a)
558
{
559
    uint64_t r;
560
    r =  (a & 0x000000000000ffffull) << 48;
561
    r |= (a & 0x00000000ffff0000ull) << 16;
562
    r |= (a & 0x0000ffff00000000ull) >> 16;
563
    r |= (a & 0xffff000000000000ull) >> 48;
564
    return r;
565
}
566

    
567
uint64_t helper_memory_to_g (uint64_t a)
568
{
569
    uint64_t r;
570
    r =  (a & 0x000000000000ffffull) << 48;
571
    r |= (a & 0x00000000ffff0000ull) << 16;
572
    r |= (a & 0x0000ffff00000000ull) >> 16;
573
    r |= (a & 0xffff000000000000ull) >> 48;
574
    return r;
575
}
576

    
577
uint64_t helper_addg (uint64_t a, uint64_t b)
578
{
579
    float64 fa, fb, fr;
580

    
581
    fa = g_to_float64(a);
582
    fb = g_to_float64(b);
583
    fr = float64_add(fa, fb, &FP_STATUS);
584
    return float64_to_g(fr);
585
}
586

    
587
uint64_t helper_subg (uint64_t a, uint64_t b)
588
{
589
    float64 fa, fb, fr;
590

    
591
    fa = g_to_float64(a);
592
    fb = g_to_float64(b);
593
    fr = float64_sub(fa, fb, &FP_STATUS);
594
    return float64_to_g(fr);
595
}
596

    
597
uint64_t helper_mulg (uint64_t a, uint64_t b)
598
{
599
    float64 fa, fb, fr;
600

    
601
    fa = g_to_float64(a);
602
    fb = g_to_float64(b);
603
    fr = float64_mul(fa, fb, &FP_STATUS);
604
    return float64_to_g(fr);
605
}
606

    
607
uint64_t helper_divg (uint64_t a, uint64_t b)
608
{
609
    float64 fa, fb, fr;
610

    
611
    fa = g_to_float64(a);
612
    fb = g_to_float64(b);
613
    fr = float64_div(fa, fb, &FP_STATUS);
614
    return float64_to_g(fr);
615
}
616

    
617
uint64_t helper_sqrtg (uint64_t a)
618
{
619
    float64 fa, fr;
620

    
621
    fa = g_to_float64(a);
622
    fr = float64_sqrt(fa, &FP_STATUS);
623
    return float64_to_g(fr);
624
}
625

    
626

    
627
/* S floating (single) */
628
static inline uint64_t float32_to_s(float32 fa)
629
{
630
    CPU_FloatU a;
631
    uint64_t r;
632

    
633
    a.f = fa;
634

    
635
    r = (((uint64_t)(a.l & 0xc0000000)) << 32) | (((uint64_t)(a.l & 0x3fffffff)) << 29);
636
    if (((a.l & 0x7f800000) != 0x7f800000) && (!(a.l & 0x40000000)))
637
        r |= 0x7ll << 59;
638
    return r;
639
}
640

    
641
static inline float32 s_to_float32(uint64_t a)
642
{
643
    CPU_FloatU r;
644
    r.l = ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff);
645
    return r.f;
646
}
647

    
648
uint32_t helper_s_to_memory (uint64_t a)
649
{
650
    /* Memory format is the same as float32 */
651
    float32 fa = s_to_float32(a);
652
    return *(uint32_t*)(&fa);
653
}
654

    
655
uint64_t helper_memory_to_s (uint32_t a)
656
{
657
    /* Memory format is the same as float32 */
658
    return float32_to_s(*(float32*)(&a));
659
}
660

    
661
uint64_t helper_adds (uint64_t a, uint64_t b)
662
{
663
    float32 fa, fb, fr;
664

    
665
    fa = s_to_float32(a);
666
    fb = s_to_float32(b);
667
    fr = float32_add(fa, fb, &FP_STATUS);
668
    return float32_to_s(fr);
669
}
670

    
671
uint64_t helper_subs (uint64_t a, uint64_t b)
672
{
673
    float32 fa, fb, fr;
674

    
675
    fa = s_to_float32(a);
676
    fb = s_to_float32(b);
677
    fr = float32_sub(fa, fb, &FP_STATUS);
678
    return float32_to_s(fr);
679
}
680

    
681
uint64_t helper_muls (uint64_t a, uint64_t b)
682
{
683
    float32 fa, fb, fr;
684

    
685
    fa = s_to_float32(a);
686
    fb = s_to_float32(b);
687
    fr = float32_mul(fa, fb, &FP_STATUS);
688
    return float32_to_s(fr);
689
}
690

    
691
uint64_t helper_divs (uint64_t a, uint64_t b)
692
{
693
    float32 fa, fb, fr;
694

    
695
    fa = s_to_float32(a);
696
    fb = s_to_float32(b);
697
    fr = float32_div(fa, fb, &FP_STATUS);
698
    return float32_to_s(fr);
699
}
700

    
701
uint64_t helper_sqrts (uint64_t a)
702
{
703
    float32 fa, fr;
704

    
705
    fa = s_to_float32(a);
706
    fr = float32_sqrt(fa, &FP_STATUS);
707
    return float32_to_s(fr);
708
}
709

    
710

    
711
/* T floating (double) */
712
static inline float64 t_to_float64(uint64_t a)
713
{
714
    /* Memory format is the same as float64 */
715
    CPU_DoubleU r;
716
    r.ll = a;
717
    return r.d;
718
}
719

    
720
static inline uint64_t float64_to_t(float64 fa)
721
{
722
    /* Memory format is the same as float64 */
723
    CPU_DoubleU r;
724
    r.d = fa;
725
    return r.ll;
726
}
727

    
728
uint64_t helper_addt (uint64_t a, uint64_t b)
729
{
730
    float64 fa, fb, fr;
731

    
732
    fa = t_to_float64(a);
733
    fb = t_to_float64(b);
734
    fr = float64_add(fa, fb, &FP_STATUS);
735
    return float64_to_t(fr);
736
}
737

    
738
uint64_t helper_subt (uint64_t a, uint64_t b)
739
{
740
    float64 fa, fb, fr;
741

    
742
    fa = t_to_float64(a);
743
    fb = t_to_float64(b);
744
    fr = float64_sub(fa, fb, &FP_STATUS);
745
    return float64_to_t(fr);
746
}
747

    
748
uint64_t helper_mult (uint64_t a, uint64_t b)
749
{
750
    float64 fa, fb, fr;
751

    
752
    fa = t_to_float64(a);
753
    fb = t_to_float64(b);
754
    fr = float64_mul(fa, fb, &FP_STATUS);
755
    return float64_to_t(fr);
756
}
757

    
758
uint64_t helper_divt (uint64_t a, uint64_t b)
759
{
760
    float64 fa, fb, fr;
761

    
762
    fa = t_to_float64(a);
763
    fb = t_to_float64(b);
764
    fr = float64_div(fa, fb, &FP_STATUS);
765
    return float64_to_t(fr);
766
}
767

    
768
uint64_t helper_sqrtt (uint64_t a)
769
{
770
    float64 fa, fr;
771

    
772
    fa = t_to_float64(a);
773
    fr = float64_sqrt(fa, &FP_STATUS);
774
    return float64_to_t(fr);
775
}
776

    
777

    
778
/* Sign copy */
779
uint64_t helper_cpys(uint64_t a, uint64_t b)
780
{
781
    return (a & 0x8000000000000000ULL) | (b & ~0x8000000000000000ULL);
782
}
783

    
784
uint64_t helper_cpysn(uint64_t a, uint64_t b)
785
{
786
    return ((~a) & 0x8000000000000000ULL) | (b & ~0x8000000000000000ULL);
787
}
788

    
789
uint64_t helper_cpyse(uint64_t a, uint64_t b)
790
{
791
    return (a & 0xFFF0000000000000ULL) | (b & ~0xFFF0000000000000ULL);
792
}
793

    
794

    
795
/* Comparisons */
796
uint64_t helper_cmptun (uint64_t a, uint64_t b)
797
{
798
    float64 fa, fb;
799

    
800
    fa = t_to_float64(a);
801
    fb = t_to_float64(b);
802

    
803
    if (float64_is_nan(fa) || float64_is_nan(fb))
804
        return 0x4000000000000000ULL;
805
    else
806
        return 0;
807
}
808

    
809
uint64_t helper_cmpteq(uint64_t a, uint64_t b)
810
{
811
    float64 fa, fb;
812

    
813
    fa = t_to_float64(a);
814
    fb = t_to_float64(b);
815

    
816
    if (float64_eq(fa, fb, &FP_STATUS))
817
        return 0x4000000000000000ULL;
818
    else
819
        return 0;
820
}
821

    
822
uint64_t helper_cmptle(uint64_t a, uint64_t b)
823
{
824
    float64 fa, fb;
825

    
826
    fa = t_to_float64(a);
827
    fb = t_to_float64(b);
828

    
829
    if (float64_le(fa, fb, &FP_STATUS))
830
        return 0x4000000000000000ULL;
831
    else
832
        return 0;
833
}
834

    
835
uint64_t helper_cmptlt(uint64_t a, uint64_t b)
836
{
837
    float64 fa, fb;
838

    
839
    fa = t_to_float64(a);
840
    fb = t_to_float64(b);
841

    
842
    if (float64_lt(fa, fb, &FP_STATUS))
843
        return 0x4000000000000000ULL;
844
    else
845
        return 0;
846
}
847

    
848
uint64_t helper_cmpgeq(uint64_t a, uint64_t b)
849
{
850
    float64 fa, fb;
851

    
852
    fa = g_to_float64(a);
853
    fb = g_to_float64(b);
854

    
855
    if (float64_eq(fa, fb, &FP_STATUS))
856
        return 0x4000000000000000ULL;
857
    else
858
        return 0;
859
}
860

    
861
uint64_t helper_cmpgle(uint64_t a, uint64_t b)
862
{
863
    float64 fa, fb;
864

    
865
    fa = g_to_float64(a);
866
    fb = g_to_float64(b);
867

    
868
    if (float64_le(fa, fb, &FP_STATUS))
869
        return 0x4000000000000000ULL;
870
    else
871
        return 0;
872
}
873

    
874
uint64_t helper_cmpglt(uint64_t a, uint64_t b)
875
{
876
    float64 fa, fb;
877

    
878
    fa = g_to_float64(a);
879
    fb = g_to_float64(b);
880

    
881
    if (float64_lt(fa, fb, &FP_STATUS))
882
        return 0x4000000000000000ULL;
883
    else
884
        return 0;
885
}
886

    
887
uint64_t helper_cmpfeq (uint64_t a)
888
{
889
    return !(a & 0x7FFFFFFFFFFFFFFFULL);
890
}
891

    
892
uint64_t helper_cmpfne (uint64_t a)
893
{
894
    return (a & 0x7FFFFFFFFFFFFFFFULL);
895
}
896

    
897
uint64_t helper_cmpflt (uint64_t a)
898
{
899
    return (a & 0x8000000000000000ULL) && (a & 0x7FFFFFFFFFFFFFFFULL);
900
}
901

    
902
uint64_t helper_cmpfle (uint64_t a)
903
{
904
    return (a & 0x8000000000000000ULL) || !(a & 0x7FFFFFFFFFFFFFFFULL);
905
}
906

    
907
uint64_t helper_cmpfgt (uint64_t a)
908
{
909
    return !(a & 0x8000000000000000ULL) && (a & 0x7FFFFFFFFFFFFFFFULL);
910
}
911

    
912
uint64_t helper_cmpfge (uint64_t a)
913
{
914
    return !(a & 0x8000000000000000ULL) || !(a & 0x7FFFFFFFFFFFFFFFULL);
915
}
916

    
917

    
918
/* Floating point format conversion */
919
uint64_t helper_cvtts (uint64_t a)
920
{
921
    float64 fa;
922
    float32 fr;
923

    
924
    fa = t_to_float64(a);
925
    fr = float64_to_float32(fa, &FP_STATUS);
926
    return float32_to_s(fr);
927
}
928

    
929
uint64_t helper_cvtst (uint64_t a)
930
{
931
    float32 fa;
932
    float64 fr;
933

    
934
    fa = s_to_float32(a);
935
    fr = float32_to_float64(fa, &FP_STATUS);
936
    return float64_to_t(fr);
937
}
938

    
939
uint64_t helper_cvtqs (uint64_t a)
940
{
941
    float32 fr = int64_to_float32(a, &FP_STATUS);
942
    return float32_to_s(fr);
943
}
944

    
945
uint64_t helper_cvttq (uint64_t a)
946
{
947
    float64 fa = t_to_float64(a);
948
    return float64_to_int64_round_to_zero(fa, &FP_STATUS);
949
}
950

    
951
uint64_t helper_cvtqt (uint64_t a)
952
{
953
    float64 fr = int64_to_float64(a, &FP_STATUS);
954
    return float64_to_t(fr);
955
}
956

    
957
uint64_t helper_cvtqf (uint64_t a)
958
{
959
    float32 fr = int64_to_float32(a, &FP_STATUS);
960
    return float32_to_f(fr);
961
}
962

    
963
uint64_t helper_cvtgf (uint64_t a)
964
{
965
    float64 fa;
966
    float32 fr;
967

    
968
    fa = g_to_float64(a);
969
    fr = float64_to_float32(fa, &FP_STATUS);
970
    return float32_to_f(fr);
971
}
972

    
973
uint64_t helper_cvtgq (uint64_t a)
974
{
975
    float64 fa = g_to_float64(a);
976
    return float64_to_int64_round_to_zero(fa, &FP_STATUS);
977
}
978

    
979
uint64_t helper_cvtqg (uint64_t a)
980
{
981
    float64 fr;
982
    fr = int64_to_float64(a, &FP_STATUS);
983
    return float64_to_g(fr);
984
}
985

    
986
uint64_t helper_cvtlq (uint64_t a)
987
{
988
    return (int64_t)((int32_t)((a >> 32) | ((a >> 29) & 0x3FFFFFFF)));
989
}
990

    
991
static inline uint64_t __helper_cvtql(uint64_t a, int s, int v)
992
{
993
    uint64_t r;
994

    
995
    r = ((uint64_t)(a & 0xC0000000)) << 32;
996
    r |= ((uint64_t)(a & 0x7FFFFFFF)) << 29;
997

    
998
    if (v && (int64_t)((int32_t)r) != (int64_t)r) {
999
        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
1000
    }
1001
    if (s) {
1002
        /* TODO */
1003
    }
1004
    return r;
1005
}
1006

    
1007
uint64_t helper_cvtql (uint64_t a)
1008
{
1009
    return __helper_cvtql(a, 0, 0);
1010
}
1011

    
1012
uint64_t helper_cvtqlv (uint64_t a)
1013
{
1014
    return __helper_cvtql(a, 0, 1);
1015
}
1016

    
1017
uint64_t helper_cvtqlsv (uint64_t a)
1018
{
1019
    return __helper_cvtql(a, 1, 1);
1020
}
1021

    
1022
/* PALcode support special instructions */
1023
#if !defined (CONFIG_USER_ONLY)
1024
void helper_hw_rei (void)
1025
{
1026
    env->pc = env->ipr[IPR_EXC_ADDR] & ~3;
1027
    env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
1028
    /* XXX: re-enable interrupts and memory mapping */
1029
}
1030

    
1031
void helper_hw_ret (uint64_t a)
1032
{
1033
    env->pc = a & ~3;
1034
    env->ipr[IPR_EXC_ADDR] = a & 1;
1035
    /* XXX: re-enable interrupts and memory mapping */
1036
}
1037

    
1038
uint64_t helper_mfpr (int iprn, uint64_t val)
1039
{
1040
    uint64_t tmp;
1041

    
1042
    if (cpu_alpha_mfpr(env, iprn, &tmp) == 0)
1043
        val = tmp;
1044

    
1045
    return val;
1046
}
1047

    
1048
void helper_mtpr (int iprn, uint64_t val)
1049
{
1050
    cpu_alpha_mtpr(env, iprn, val, NULL);
1051
}
1052

    
1053
void helper_set_alt_mode (void)
1054
{
1055
    env->saved_mode = env->ps & 0xC;
1056
    env->ps = (env->ps & ~0xC) | (env->ipr[IPR_ALT_MODE] & 0xC);
1057
}
1058

    
1059
void helper_restore_mode (void)
1060
{
1061
    env->ps = (env->ps & ~0xC) | env->saved_mode;
1062
}
1063

    
1064
#endif
1065

    
1066
/*****************************************************************************/
1067
/* Softmmu support */
1068
#if !defined (CONFIG_USER_ONLY)
1069

    
1070
/* XXX: the two following helpers are pure hacks.
1071
 *      Hopefully, we emulate the PALcode, then we should never see
1072
 *      HW_LD / HW_ST instructions.
1073
 */
1074
uint64_t helper_ld_virt_to_phys (uint64_t virtaddr)
1075
{
1076
    uint64_t tlb_addr, physaddr;
1077
    int index, mmu_idx;
1078
    void *retaddr;
1079

    
1080
    mmu_idx = cpu_mmu_index(env);
1081
    index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1082
 redo:
1083
    tlb_addr = env->tlb_table[mmu_idx][index].addr_read;
1084
    if ((virtaddr & TARGET_PAGE_MASK) ==
1085
        (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1086
        physaddr = virtaddr + env->tlb_table[mmu_idx][index].addend;
1087
    } else {
1088
        /* the page is not in the TLB : fill it */
1089
        retaddr = GETPC();
1090
        tlb_fill(virtaddr, 0, mmu_idx, retaddr);
1091
        goto redo;
1092
    }
1093
    return physaddr;
1094
}
1095

    
1096
uint64_t helper_st_virt_to_phys (uint64_t virtaddr)
1097
{
1098
    uint64_t tlb_addr, physaddr;
1099
    int index, mmu_idx;
1100
    void *retaddr;
1101

    
1102
    mmu_idx = cpu_mmu_index(env);
1103
    index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1104
 redo:
1105
    tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
1106
    if ((virtaddr & TARGET_PAGE_MASK) ==
1107
        (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1108
        physaddr = virtaddr + env->tlb_table[mmu_idx][index].addend;
1109
    } else {
1110
        /* the page is not in the TLB : fill it */
1111
        retaddr = GETPC();
1112
        tlb_fill(virtaddr, 1, mmu_idx, retaddr);
1113
        goto redo;
1114
    }
1115
    return physaddr;
1116
}
1117

    
1118
void helper_ldl_raw(uint64_t t0, uint64_t t1)
1119
{
1120
    ldl_raw(t1, t0);
1121
}
1122

    
1123
void helper_ldq_raw(uint64_t t0, uint64_t t1)
1124
{
1125
    ldq_raw(t1, t0);
1126
}
1127

    
1128
void helper_ldl_l_raw(uint64_t t0, uint64_t t1)
1129
{
1130
    env->lock = t1;
1131
    ldl_raw(t1, t0);
1132
}
1133

    
1134
void helper_ldq_l_raw(uint64_t t0, uint64_t t1)
1135
{
1136
    env->lock = t1;
1137
    ldl_raw(t1, t0);
1138
}
1139

    
1140
void helper_ldl_kernel(uint64_t t0, uint64_t t1)
1141
{
1142
    ldl_kernel(t1, t0);
1143
}
1144

    
1145
void helper_ldq_kernel(uint64_t t0, uint64_t t1)
1146
{
1147
    ldq_kernel(t1, t0);
1148
}
1149

    
1150
void helper_ldl_data(uint64_t t0, uint64_t t1)
1151
{
1152
    ldl_data(t1, t0);
1153
}
1154

    
1155
void helper_ldq_data(uint64_t t0, uint64_t t1)
1156
{
1157
    ldq_data(t1, t0);
1158
}
1159

    
1160
void helper_stl_raw(uint64_t t0, uint64_t t1)
1161
{
1162
    stl_raw(t1, t0);
1163
}
1164

    
1165
void helper_stq_raw(uint64_t t0, uint64_t t1)
1166
{
1167
    stq_raw(t1, t0);
1168
}
1169

    
1170
uint64_t helper_stl_c_raw(uint64_t t0, uint64_t t1)
1171
{
1172
    uint64_t ret;
1173

    
1174
    if (t1 == env->lock) {
1175
        stl_raw(t1, t0);
1176
        ret = 0;
1177
    } else
1178
        ret = 1;
1179

    
1180
    env->lock = 1;
1181

    
1182
    return ret;
1183
}
1184

    
1185
uint64_t helper_stq_c_raw(uint64_t t0, uint64_t t1)
1186
{
1187
    uint64_t ret;
1188

    
1189
    if (t1 == env->lock) {
1190
        stq_raw(t1, t0);
1191
        ret = 0;
1192
    } else
1193
        ret = 1;
1194

    
1195
    env->lock = 1;
1196

    
1197
    return ret;
1198
}
1199

    
1200
#define MMUSUFFIX _mmu
1201

    
1202
#define SHIFT 0
1203
#include "softmmu_template.h"
1204

    
1205
#define SHIFT 1
1206
#include "softmmu_template.h"
1207

    
1208
#define SHIFT 2
1209
#include "softmmu_template.h"
1210

    
1211
#define SHIFT 3
1212
#include "softmmu_template.h"
1213

    
1214
/* try to fill the TLB and return an exception if error. If retaddr is
1215
   NULL, it means that the function was called in C code (i.e. not
1216
   from generated code or from helper.c) */
1217
/* XXX: fix it to restore all registers */
1218
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1219
{
1220
    TranslationBlock *tb;
1221
    CPUState *saved_env;
1222
    unsigned long pc;
1223
    int ret;
1224

    
1225
    /* XXX: hack to restore env in all cases, even if not called from
1226
       generated code */
1227
    saved_env = env;
1228
    env = cpu_single_env;
1229
    ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1230
    if (!likely(ret == 0)) {
1231
        if (likely(retaddr)) {
1232
            /* now we have a real cpu fault */
1233
            pc = (unsigned long)retaddr;
1234
            tb = tb_find_pc(pc);
1235
            if (likely(tb)) {
1236
                /* the PC is inside the translated code. It means that we have
1237
                   a virtual CPU fault */
1238
                cpu_restore_state(tb, env, pc, NULL);
1239
            }
1240
        }
1241
        /* Exception index and error code are already set */
1242
        cpu_loop_exit();
1243
    }
1244
    env = saved_env;
1245
}
1246

    
1247
#endif