Statistics
| Branch: | Revision:

root / target-alpha / op_helper.c @ b1806c9e

History | View | Annotate | Download (23 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, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20

    
21
#include "exec.h"
22
#include "softfloat.h"
23

    
24
#include "op_helper.h"
25

    
26
#define MEMSUFFIX _raw
27
#include "op_helper_mem.h"
28

    
29
#if !defined(CONFIG_USER_ONLY)
30
#define MEMSUFFIX _kernel
31
#include "op_helper_mem.h"
32

    
33
#define MEMSUFFIX _executive
34
#include "op_helper_mem.h"
35

    
36
#define MEMSUFFIX _supervisor
37
#include "op_helper_mem.h"
38

    
39
#define MEMSUFFIX _user
40
#include "op_helper_mem.h"
41

    
42
/* This is used for pal modes */
43
#define MEMSUFFIX _data
44
#include "op_helper_mem.h"
45
#endif
46

    
47
void helper_tb_flush (void)
48
{
49
    tlb_flush(env, 1);
50
}
51

    
52
void cpu_dump_EA (target_ulong EA);
53
void helper_print_mem_EA (target_ulong EA)
54
{
55
    cpu_dump_EA(EA);
56
}
57

    
58
/*****************************************************************************/
59
/* Exceptions processing helpers */
60
void helper_excp (uint32_t excp, uint32_t error)
61
{
62
    env->exception_index = excp;
63
    env->error_code = error;
64
    cpu_loop_exit();
65
}
66

    
67
void helper_amask (void)
68
{
69
    switch (env->implver) {
70
    case IMPLVER_2106x:
71
        /* EV4, EV45, LCA, LCA45 & EV5 */
72
        break;
73
    case IMPLVER_21164:
74
    case IMPLVER_21264:
75
    case IMPLVER_21364:
76
        T0 &= ~env->amask;
77
        break;
78
    }
79
}
80

    
81
void helper_load_pcc (void)
82
{
83
    /* XXX: TODO */
84
    T0 = 0;
85
}
86

    
87
void helper_load_implver (void)
88
{
89
    T0 = env->implver;
90
}
91

    
92
void helper_load_fpcr (void)
93
{
94
    T0 = 0;
95
#ifdef CONFIG_SOFTFLOAT
96
    T0 |= env->fp_status.float_exception_flags << 52;
97
    if (env->fp_status.float_exception_flags)
98
        T0 |= 1ULL << 63;
99
    env->ipr[IPR_EXC_SUM] &= ~0x3E:
100
    env->ipr[IPR_EXC_SUM] |= env->fp_status.float_exception_flags << 1;
101
#endif
102
    switch (env->fp_status.float_rounding_mode) {
103
    case float_round_nearest_even:
104
        T0 |= 2ULL << 58;
105
        break;
106
    case float_round_down:
107
        T0 |= 1ULL << 58;
108
        break;
109
    case float_round_up:
110
        T0 |= 3ULL << 58;
111
        break;
112
    case float_round_to_zero:
113
        break;
114
    }
115
}
116

    
117
void helper_store_fpcr (void)
118
{
119
#ifdef CONFIG_SOFTFLOAT
120
    set_float_exception_flags((T0 >> 52) & 0x3F, &FP_STATUS);
121
#endif
122
    switch ((T0 >> 58) & 3) {
123
    case 0:
124
        set_float_rounding_mode(float_round_to_zero, &FP_STATUS);
125
        break;
126
    case 1:
127
        set_float_rounding_mode(float_round_down, &FP_STATUS);
128
        break;
129
    case 2:
130
        set_float_rounding_mode(float_round_nearest_even, &FP_STATUS);
131
        break;
132
    case 3:
133
        set_float_rounding_mode(float_round_up, &FP_STATUS);
134
        break;
135
    }
136
}
137

    
138
void helper_load_irf (void)
139
{
140
    /* XXX: TODO */
141
    T0 = 0;
142
}
143

    
144
void helper_set_irf (void)
145
{
146
    /* XXX: TODO */
147
}
148

    
149
void helper_clear_irf (void)
150
{
151
    /* XXX: TODO */
152
}
153

    
154
void helper_addqv (void)
155
{
156
    T2 = T0;
157
    T0 += T1;
158
    if (unlikely((T2 ^ T1 ^ (-1ULL)) & (T2 ^ T0) & (1ULL << 63))) {
159
        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
160
    }
161
}
162

    
163
void helper_addlv (void)
164
{
165
    T2 = T0;
166
    T0 = (uint32_t)(T0 + T1);
167
    if (unlikely((T2 ^ T1 ^ (-1UL)) & (T2 ^ T0) & (1UL << 31))) {
168
        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
169
    }
170
}
171

    
172
void helper_subqv (void)
173
{
174
    T2 = T0;
175
    T0 -= T1;
176
    if (unlikely(((~T2) ^ T0 ^ (-1ULL)) & ((~T2) ^ T1) & (1ULL << 63))) {
177
        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
178
    }
179
}
180

    
181
void helper_sublv (void)
182
{
183
    T2 = T0;
184
    T0 = (uint32_t)(T0 - T1);
185
    if (unlikely(((~T2) ^ T0 ^ (-1UL)) & ((~T2) ^ T1) & (1UL << 31))) {
186
        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
187
    }
188
}
189

    
190
void helper_mullv (void)
191
{
192
    int64_t res = (int64_t)T0 * (int64_t)T1;
193

    
194
    if (unlikely((int32_t)res != res)) {
195
        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
196
    }
197
    T0 = (int64_t)((int32_t)res);
198
}
199

    
200
void helper_mulqv ()
201
{
202
    uint64_t res, tmp0, tmp1;
203

    
204
    res = (T0 >> 32) * (T1 >> 32);
205
    tmp0 = ((T0 & 0xFFFFFFFF) * (T1 >> 32)) +
206
        ((T0 >> 32) * (T1 & 0xFFFFFFFF));
207
    tmp1 = (T0 & 0xFFFFFFFF) * (T1 & 0xFFFFFFFF);
208
    tmp0 += tmp1 >> 32;
209
    res += tmp0 >> 32;
210
    T0 *= T1;
211
    if (unlikely(res != 0)) {
212
        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
213
    }
214
}
215

    
216
void helper_umulh (void)
217
{
218
    uint64_t tmp0, tmp1;
219

    
220
    tmp0 = ((T0 & 0xFFFFFFFF) * (T1 >> 32)) +
221
        ((T0 >> 32) * (T1 & 0xFFFFFFFF));
222
    tmp1 = (T0 & 0xFFFFFFFF) * (T1 & 0xFFFFFFFF);
223
    tmp0 += tmp1 >> 32;
224
    T0 = (T0 >> 32) * (T0 >> 32);
225
    T0 += tmp0 >> 32;
226
}
227

    
228
void helper_ctpop (void)
229
{
230
    int n;
231

    
232
    for (n = 0; T0 != 0; n++)
233
        T0 = T0 ^ (T0 - 1);
234
    T0 = n;
235
}
236

    
237
void helper_ctlz (void)
238
{
239
    uint32_t op32;
240
    int n;
241

    
242
    n = 0;
243
    if (!(T0 & 0xFFFFFFFF00000000ULL)) {
244
        n += 32;
245
        T0 <<= 32;
246
    }
247
    /* Make it easier for 32 bits hosts */
248
    op32 = T0 >> 32;
249
    if (!(op32 & 0xFFFF0000UL)) {
250
        n += 16;
251
        op32 <<= 16;
252
    }
253
    if (!(op32 & 0xFF000000UL)) {
254
        n += 8;
255
        op32 <<= 8;
256
    }
257
    if (!(op32 & 0xF0000000UL)) {
258
        n += 4;
259
        op32 <<= 4;
260
    }
261
    if (!(op32 & 0xC0000000UL)) {
262
        n += 2;
263
        op32 <<= 2;
264
    }
265
    if (!(op32 & 0x80000000UL)) {
266
        n++;
267
        op32 <<= 1;
268
    }
269
    if (!(op32 & 0x80000000UL)) {
270
        n++;
271
    }
272
    T0 = n;
273
}
274

    
275
void helper_cttz (void)
276
{
277
    uint32_t op32;
278
    int n;
279

    
280
    n = 0;
281
    if (!(T0 & 0x00000000FFFFFFFFULL)) {
282
        n += 32;
283
        T0 >>= 32;
284
    }
285
    /* Make it easier for 32 bits hosts */
286
    op32 = T0;
287
    if (!(op32 & 0x0000FFFFUL)) {
288
        n += 16;
289
        op32 >>= 16;
290
    }
291
    if (!(op32 & 0x000000FFUL)) {
292
        n += 8;
293
        op32 >>= 8;
294
    }
295
    if (!(op32 & 0x0000000FUL)) {
296
        n += 4;
297
        op32 >>= 4;
298
    }
299
    if (!(op32 & 0x00000003UL)) {
300
        n += 2;
301
        op32 >>= 2;
302
    }
303
    if (!(op32 & 0x00000001UL)) {
304
        n++;
305
        op32 >>= 1;
306
    }
307
    if (!(op32 & 0x00000001UL)) {
308
        n++;
309
    }
310
    T0 = n;
311
}
312

    
313
static inline uint64_t byte_zap (uint64_t op, uint8_t mskb)
314
{
315
    uint64_t mask;
316

    
317
    mask = 0;
318
    mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL;
319
    mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL;
320
    mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL;
321
    mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL;
322
    mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL;
323
    mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL;
324
    mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL;
325
    mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL;
326

    
327
    return op & ~mask;
328
}
329

    
330
void helper_mskbl (void)
331
{
332
    T0 = byte_zap(T0, 0x01 << (T1 & 7));
333
}
334

    
335
void helper_extbl (void)
336
{
337
    T0 >>= (T1 & 7) * 8;
338
    T0 = byte_zap(T0, 0xFE);
339
}
340

    
341
void helper_insbl (void)
342
{
343
    T0 <<= (T1 & 7) * 8;
344
    T0 = byte_zap(T0, ~(0x01 << (T1 & 7)));
345
}
346

    
347
void helper_mskwl (void)
348
{
349
    T0 = byte_zap(T0, 0x03 << (T1 & 7));
350
}
351

    
352
void helper_extwl (void)
353
{
354
    T0 >>= (T1 & 7) * 8;
355
    T0 = byte_zap(T0, 0xFC);
356
}
357

    
358
void helper_inswl (void)
359
{
360
    T0 <<= (T1 & 7) * 8;
361
    T0 = byte_zap(T0, ~(0x03 << (T1 & 7)));
362
}
363

    
364
void helper_mskll (void)
365
{
366
    T0 = byte_zap(T0, 0x0F << (T1 & 7));
367
}
368

    
369
void helper_extll (void)
370
{
371
    T0 >>= (T1 & 7) * 8;
372
    T0 = byte_zap(T0, 0xF0);
373
}
374

    
375
void helper_insll (void)
376
{
377
    T0 <<= (T1 & 7) * 8;
378
    T0 = byte_zap(T0, ~(0x0F << (T1 & 7)));
379
}
380

    
381
void helper_zap (void)
382
{
383
    T0 = byte_zap(T0, T1);
384
}
385

    
386
void helper_zapnot (void)
387
{
388
    T0 = byte_zap(T0, ~T1);
389
}
390

    
391
void helper_mskql (void)
392
{
393
    T0 = byte_zap(T0, 0xFF << (T1 & 7));
394
}
395

    
396
void helper_extql (void)
397
{
398
    T0 >>= (T1 & 7) * 8;
399
    T0 = byte_zap(T0, 0x00);
400
}
401

    
402
void helper_insql (void)
403
{
404
    T0 <<= (T1 & 7) * 8;
405
    T0 = byte_zap(T0, ~(0xFF << (T1 & 7)));
406
}
407

    
408
void helper_mskwh (void)
409
{
410
    T0 = byte_zap(T0, (0x03 << (T1 & 7)) >> 8);
411
}
412

    
413
void helper_inswh (void)
414
{
415
    T0 >>= 64 - ((T1 & 7) * 8);
416
    T0 = byte_zap(T0, ~((0x03 << (T1 & 7)) >> 8));
417
}
418

    
419
void helper_extwh (void)
420
{
421
    T0 <<= 64 - ((T1 & 7) * 8);
422
    T0 = byte_zap(T0, ~0x07);
423
}
424

    
425
void helper_msklh (void)
426
{
427
    T0 = byte_zap(T0, (0x0F << (T1 & 7)) >> 8);
428
}
429

    
430
void helper_inslh (void)
431
{
432
    T0 >>= 64 - ((T1 & 7) * 8);
433
    T0 = byte_zap(T0, ~((0x0F << (T1 & 7)) >> 8));
434
}
435

    
436
void helper_extlh (void)
437
{
438
    T0 <<= 64 - ((T1 & 7) * 8);
439
    T0 = byte_zap(T0, ~0x0F);
440
}
441

    
442
void helper_mskqh (void)
443
{
444
    T0 = byte_zap(T0, (0xFF << (T1 & 7)) >> 8);
445
}
446

    
447
void helper_insqh (void)
448
{
449
    T0 >>= 64 - ((T1 & 7) * 8);
450
    T0 = byte_zap(T0, ~((0xFF << (T1 & 7)) >> 8));
451
}
452

    
453
void helper_extqh (void)
454
{
455
    T0 <<= 64 - ((T1 & 7) * 8);
456
    T0 = byte_zap(T0, 0x00);
457
}
458

    
459
void helper_cmpbge (void)
460
{
461
    uint8_t opa, opb, res;
462
    int i;
463

    
464
    res = 0;
465
    for (i = 0; i < 7; i++) {
466
        opa = T0 >> (i * 8);
467
        opb = T1 >> (i * 8);
468
        if (opa >= opb)
469
            res |= 1 << i;
470
    }
471
    T0 = res;
472
}
473

    
474
void helper_cmov_fir (int freg)
475
{
476
    if (FT0 != 0)
477
        env->fir[freg] = FT1;
478
}
479

    
480
void helper_sqrts (void)
481
{
482
    FT0 = float32_sqrt(FT0, &FP_STATUS);
483
}
484

    
485
void helper_cpys (void)
486
{
487
    union {
488
        double d;
489
        uint64_t i;
490
    } p, q, r;
491

    
492
    p.d = FT0;
493
    q.d = FT1;
494
    r.i = p.i & 0x8000000000000000ULL;
495
    r.i |= q.i & ~0x8000000000000000ULL;
496
    FT0 = r.d;
497
}
498

    
499
void helper_cpysn (void)
500
{
501
    union {
502
        double d;
503
        uint64_t i;
504
    } p, q, r;
505

    
506
    p.d = FT0;
507
    q.d = FT1;
508
    r.i = (~p.i) & 0x8000000000000000ULL;
509
    r.i |= q.i & ~0x8000000000000000ULL;
510
    FT0 = r.d;
511
}
512

    
513
void helper_cpyse (void)
514
{
515
    union {
516
        double d;
517
        uint64_t i;
518
    } p, q, r;
519

    
520
    p.d = FT0;
521
    q.d = FT1;
522
    r.i = p.i & 0xFFF0000000000000ULL;
523
    r.i |= q.i & ~0xFFF0000000000000ULL;
524
    FT0 = r.d;
525
}
526

    
527
void helper_itofs (void)
528
{
529
    union {
530
        double d;
531
        uint64_t i;
532
    } p;
533

    
534
    p.d = FT0;
535
    FT0 = int64_to_float32(p.i, &FP_STATUS);
536
}
537

    
538
void helper_ftois (void)
539
{
540
    union {
541
        double d;
542
        uint64_t i;
543
    } p;
544

    
545
    p.i = float32_to_int64(FT0, &FP_STATUS);
546
    FT0 = p.d;
547
}
548

    
549
void helper_sqrtt (void)
550
{
551
    FT0 = float64_sqrt(FT0, &FP_STATUS);
552
}
553

    
554
void helper_cmptun (void)
555
{
556
    union {
557
        double d;
558
        uint64_t i;
559
    } p;
560

    
561
    p.i = 0;
562
    if (float64_is_nan(FT0) || float64_is_nan(FT1))
563
        p.i = 0x4000000000000000ULL;
564
    FT0 = p.d;
565
}
566

    
567
void helper_cmpteq (void)
568
{
569
    union {
570
        double d;
571
        uint64_t i;
572
    } p;
573

    
574
    p.i = 0;
575
    if (float64_eq(FT0, FT1, &FP_STATUS))
576
        p.i = 0x4000000000000000ULL;
577
    FT0 = p.d;
578
}
579

    
580
void helper_cmptle (void)
581
{
582
    union {
583
        double d;
584
        uint64_t i;
585
    } p;
586

    
587
    p.i = 0;
588
    if (float64_le(FT0, FT1, &FP_STATUS))
589
        p.i = 0x4000000000000000ULL;
590
    FT0 = p.d;
591
}
592

    
593
void helper_cmptlt (void)
594
{
595
    union {
596
        double d;
597
        uint64_t i;
598
    } p;
599

    
600
    p.i = 0;
601
    if (float64_lt(FT0, FT1, &FP_STATUS))
602
        p.i = 0x4000000000000000ULL;
603
    FT0 = p.d;
604
}
605

    
606
void helper_itoft (void)
607
{
608
    union {
609
        double d;
610
        uint64_t i;
611
    } p;
612

    
613
    p.d = FT0;
614
    FT0 = int64_to_float64(p.i, &FP_STATUS);
615
}
616

    
617
void helper_ftoit (void)
618
{
619
    union {
620
        double d;
621
        uint64_t i;
622
    } p;
623

    
624
    p.i = float64_to_int64(FT0, &FP_STATUS);
625
    FT0 = p.d;
626
}
627

    
628
static int vaxf_is_valid (float ff)
629
{
630
    union {
631
        float f;
632
        uint32_t i;
633
    } p;
634
    uint32_t exp, mant;
635

    
636
    p.f = ff;
637
    exp = (p.i >> 23) & 0xFF;
638
    mant = p.i & 0x007FFFFF;
639
    if (exp == 0 && ((p.i & 0x80000000) || mant != 0)) {
640
        /* Reserved operands / Dirty zero */
641
        return 0;
642
    }
643

    
644
    return 1;
645
}
646

    
647
static float vaxf_to_ieee32 (float ff)
648
{
649
    union {
650
        float f;
651
        uint32_t i;
652
    } p;
653
    uint32_t exp;
654

    
655
    p.f = ff;
656
    exp = (p.i >> 23) & 0xFF;
657
    if (exp < 3) {
658
        /* Underflow */
659
        p.f = 0.0;
660
    } else {
661
        p.f *= 0.25;
662
    }
663

    
664
    return p.f;
665
}
666

    
667
static float ieee32_to_vaxf (float fi)
668
{
669
    union {
670
        float f;
671
        uint32_t i;
672
    } p;
673
    uint32_t exp, mant;
674

    
675
    p.f = fi;
676
    exp = (p.i >> 23) & 0xFF;
677
    mant = p.i & 0x007FFFFF;
678
    if (exp == 255) {
679
        /* NaN or infinity */
680
        p.i = 1;
681
    } else if (exp == 0) {
682
        if (mant == 0) {
683
            /* Zero */
684
            p.i = 0;
685
        } else {
686
            /* Denormalized */
687
            p.f *= 2.0;
688
        }
689
    } else {
690
        if (exp >= 253) {
691
            /* Overflow */
692
            p.i = 1;
693
        } else {
694
            p.f *= 4.0;
695
        }
696
    }
697

    
698
    return p.f;
699
}
700

    
701
void helper_addf (void)
702
{
703
    float ft0, ft1, ft2;
704

    
705
    if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
706
        /* XXX: TODO */
707
    }
708
    ft0 = vaxf_to_ieee32(FT0);
709
    ft1 = vaxf_to_ieee32(FT1);
710
    ft2 = float32_add(ft0, ft1, &FP_STATUS);
711
    FT0 = ieee32_to_vaxf(ft2);
712
}
713

    
714
void helper_subf (void)
715
{
716
    float ft0, ft1, ft2;
717

    
718
    if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
719
        /* XXX: TODO */
720
    }
721
    ft0 = vaxf_to_ieee32(FT0);
722
    ft1 = vaxf_to_ieee32(FT1);
723
    ft2 = float32_sub(ft0, ft1, &FP_STATUS);
724
    FT0 = ieee32_to_vaxf(ft2);
725
}
726

    
727
void helper_mulf (void)
728
{
729
    float ft0, ft1, ft2;
730

    
731
    if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
732
        /* XXX: TODO */
733
    }
734
    ft0 = vaxf_to_ieee32(FT0);
735
    ft1 = vaxf_to_ieee32(FT1);
736
    ft2 = float32_mul(ft0, ft1, &FP_STATUS);
737
    FT0 = ieee32_to_vaxf(ft2);
738
}
739

    
740
void helper_divf (void)
741
{
742
    float ft0, ft1, ft2;
743

    
744
    if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
745
        /* XXX: TODO */
746
    }
747
    ft0 = vaxf_to_ieee32(FT0);
748
    ft1 = vaxf_to_ieee32(FT1);
749
    ft2 = float32_div(ft0, ft1, &FP_STATUS);
750
    FT0 = ieee32_to_vaxf(ft2);
751
}
752

    
753
void helper_sqrtf (void)
754
{
755
    float ft0, ft1;
756

    
757
    if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
758
        /* XXX: TODO */
759
    }
760
    ft0 = vaxf_to_ieee32(FT0);
761
    ft1 = float32_sqrt(ft0, &FP_STATUS);
762
    FT0 = ieee32_to_vaxf(ft1);
763
}
764

    
765
void helper_itoff (void)
766
{
767
    /* XXX: TODO */
768
}
769

    
770
static int vaxg_is_valid (double ff)
771
{
772
    union {
773
        double f;
774
        uint64_t i;
775
    } p;
776
    uint64_t exp, mant;
777

    
778
    p.f = ff;
779
    exp = (p.i >> 52) & 0x7FF;
780
    mant = p.i & 0x000FFFFFFFFFFFFFULL;
781
    if (exp == 0 && ((p.i & 0x8000000000000000ULL) || mant != 0)) {
782
        /* Reserved operands / Dirty zero */
783
        return 0;
784
    }
785

    
786
    return 1;
787
}
788

    
789
static double vaxg_to_ieee64 (double fg)
790
{
791
    union {
792
        double f;
793
        uint64_t i;
794
    } p;
795
    uint32_t exp;
796

    
797
    p.f = fg;
798
    exp = (p.i >> 52) & 0x7FF;
799
    if (exp < 3) {
800
        /* Underflow */
801
        p.f = 0.0;
802
    } else {
803
        p.f *= 0.25;
804
    }
805

    
806
    return p.f;
807
}
808

    
809
static double ieee64_to_vaxg (double fi)
810
{
811
    union {
812
        double f;
813
        uint64_t i;
814
    } p;
815
    uint64_t mant;
816
    uint32_t exp;
817

    
818
    p.f = fi;
819
    exp = (p.i >> 52) & 0x7FF;
820
    mant = p.i & 0x000FFFFFFFFFFFFFULL;
821
    if (exp == 255) {
822
        /* NaN or infinity */
823
        p.i = 1; /* VAX dirty zero */
824
    } else if (exp == 0) {
825
        if (mant == 0) {
826
            /* Zero */
827
            p.i = 0;
828
        } else {
829
            /* Denormalized */
830
            p.f *= 2.0;
831
        }
832
    } else {
833
        if (exp >= 2045) {
834
            /* Overflow */
835
            p.i = 1; /* VAX dirty zero */
836
        } else {
837
            p.f *= 4.0;
838
        }
839
    }
840

    
841
    return p.f;
842
}
843

    
844
void helper_addg (void)
845
{
846
    double ft0, ft1, ft2;
847

    
848
    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
849
        /* XXX: TODO */
850
    }
851
    ft0 = vaxg_to_ieee64(FT0);
852
    ft1 = vaxg_to_ieee64(FT1);
853
    ft2 = float64_add(ft0, ft1, &FP_STATUS);
854
    FT0 = ieee64_to_vaxg(ft2);
855
}
856

    
857
void helper_subg (void)
858
{
859
    double ft0, ft1, ft2;
860

    
861
    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
862
        /* XXX: TODO */
863
    }
864
    ft0 = vaxg_to_ieee64(FT0);
865
    ft1 = vaxg_to_ieee64(FT1);
866
    ft2 = float64_sub(ft0, ft1, &FP_STATUS);
867
    FT0 = ieee64_to_vaxg(ft2);
868
}
869

    
870
void helper_mulg (void)
871
{
872
    double ft0, ft1, ft2;
873

    
874
    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
875
        /* XXX: TODO */
876
    }
877
    ft0 = vaxg_to_ieee64(FT0);
878
    ft1 = vaxg_to_ieee64(FT1);
879
    ft2 = float64_mul(ft0, ft1, &FP_STATUS);
880
    FT0 = ieee64_to_vaxg(ft2);
881
}
882

    
883
void helper_divg (void)
884
{
885
    double ft0, ft1, ft2;
886

    
887
    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
888
        /* XXX: TODO */
889
    }
890
    ft0 = vaxg_to_ieee64(FT0);
891
    ft1 = vaxg_to_ieee64(FT1);
892
    ft2 = float64_div(ft0, ft1, &FP_STATUS);
893
    FT0 = ieee64_to_vaxg(ft2);
894
}
895

    
896
void helper_sqrtg (void)
897
{
898
    double ft0, ft1;
899

    
900
    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
901
        /* XXX: TODO */
902
    }
903
    ft0 = vaxg_to_ieee64(FT0);
904
    ft1 = float64_sqrt(ft0, &FP_STATUS);
905
    FT0 = ieee64_to_vaxg(ft1);
906
}
907

    
908
void helper_cmpgeq (void)
909
{
910
    union {
911
        double d;
912
        uint64_t u;
913
    } p;
914
    double ft0, ft1;
915

    
916
    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
917
        /* XXX: TODO */
918
    }
919
    ft0 = vaxg_to_ieee64(FT0);
920
    ft1 = vaxg_to_ieee64(FT1);
921
    p.u = 0;
922
    if (float64_eq(ft0, ft1, &FP_STATUS))
923
        p.u = 0x4000000000000000ULL;
924
    FT0 = p.d;
925
}
926

    
927
void helper_cmpglt (void)
928
{
929
    union {
930
        double d;
931
        uint64_t u;
932
    } p;
933
    double ft0, ft1;
934

    
935
    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
936
        /* XXX: TODO */
937
    }
938
    ft0 = vaxg_to_ieee64(FT0);
939
    ft1 = vaxg_to_ieee64(FT1);
940
    p.u = 0;
941
    if (float64_lt(ft0, ft1, &FP_STATUS))
942
        p.u = 0x4000000000000000ULL;
943
    FT0 = p.d;
944
}
945

    
946
void helper_cmpgle (void)
947
{
948
    union {
949
        double d;
950
        uint64_t u;
951
    } p;
952
    double ft0, ft1;
953

    
954
    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
955
        /* XXX: TODO */
956
    }
957
    ft0 = vaxg_to_ieee64(FT0);
958
    ft1 = vaxg_to_ieee64(FT1);
959
    p.u = 0;
960
    if (float64_le(ft0, ft1, &FP_STATUS))
961
        p.u = 0x4000000000000000ULL;
962
    FT0 = p.d;
963
}
964

    
965
void helper_cvtqs (void)
966
{
967
    union {
968
        double d;
969
        uint64_t u;
970
    } p;
971

    
972
    p.d = FT0;
973
    FT0 = (float)p.u;
974
}
975

    
976
void helper_cvttq (void)
977
{
978
    union {
979
        double d;
980
        uint64_t u;
981
    } p;
982

    
983
    p.u = FT0;
984
    FT0 = p.d;
985
}
986

    
987
void helper_cvtqt (void)
988
{
989
    union {
990
        double d;
991
        uint64_t u;
992
    } p;
993

    
994
    p.d = FT0;
995
    FT0 = p.u;
996
}
997

    
998
void helper_cvtqf (void)
999
{
1000
    union {
1001
        double d;
1002
        uint64_t u;
1003
    } p;
1004

    
1005
    p.d = FT0;
1006
    FT0 = ieee32_to_vaxf(p.u);
1007
}
1008

    
1009
void helper_cvtgf (void)
1010
{
1011
    double ft0;
1012

    
1013
    ft0 = vaxg_to_ieee64(FT0);
1014
    FT0 = ieee32_to_vaxf(ft0);
1015
}
1016

    
1017
void helper_cvtgd (void)
1018
{
1019
    /* XXX: TODO */
1020
}
1021

    
1022
void helper_cvtgq (void)
1023
{
1024
    union {
1025
        double d;
1026
        uint64_t u;
1027
    } p;
1028

    
1029
    p.u = vaxg_to_ieee64(FT0);
1030
    FT0 = p.d;
1031
}
1032

    
1033
void helper_cvtqg (void)
1034
{
1035
    union {
1036
        double d;
1037
        uint64_t u;
1038
    } p;
1039

    
1040
    p.d = FT0;
1041
    FT0 = ieee64_to_vaxg(p.u);
1042
}
1043

    
1044
void helper_cvtdg (void)
1045
{
1046
    /* XXX: TODO */
1047
}
1048

    
1049
void helper_cvtlq (void)
1050
{
1051
    union {
1052
        double d;
1053
        uint64_t u;
1054
    } p, q;
1055

    
1056
    p.d = FT0;
1057
    q.u = (p.u >> 29) & 0x3FFFFFFF;
1058
    q.u |= (p.u >> 32);
1059
    q.u = (int64_t)((int32_t)q.u);
1060
    FT0 = q.d;
1061
}
1062

    
1063
static inline void __helper_cvtql (int s, int v)
1064
{
1065
    union {
1066
        double d;
1067
        uint64_t u;
1068
    } p, q;
1069

    
1070
    p.d = FT0;
1071
    q.u = ((uint64_t)(p.u & 0xC0000000)) << 32;
1072
    q.u |= ((uint64_t)(p.u & 0x7FFFFFFF)) << 29;
1073
    FT0 = q.d;
1074
    if (v && (int64_t)((int32_t)p.u) != (int64_t)p.u) {
1075
        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
1076
    }
1077
    if (s) {
1078
        /* TODO */
1079
    }
1080
}
1081

    
1082
void helper_cvtql (void)
1083
{
1084
    __helper_cvtql(0, 0);
1085
}
1086

    
1087
void helper_cvtqlv (void)
1088
{
1089
    __helper_cvtql(0, 1);
1090
}
1091

    
1092
void helper_cvtqlsv (void)
1093
{
1094
    __helper_cvtql(1, 1);
1095
}
1096

    
1097
void helper_cmpfeq (void)
1098
{
1099
    if (float64_eq(FT0, FT1, &FP_STATUS))
1100
        T0 = 1;
1101
    else
1102
        T0 = 0;
1103
}
1104

    
1105
void helper_cmpfne (void)
1106
{
1107
    if (float64_eq(FT0, FT1, &FP_STATUS))
1108
        T0 = 0;
1109
    else
1110
        T0 = 1;
1111
}
1112

    
1113
void helper_cmpflt (void)
1114
{
1115
    if (float64_lt(FT0, FT1, &FP_STATUS))
1116
        T0 = 1;
1117
    else
1118
        T0 = 0;
1119
}
1120

    
1121
void helper_cmpfle (void)
1122
{
1123
    if (float64_lt(FT0, FT1, &FP_STATUS))
1124
        T0 = 1;
1125
    else
1126
        T0 = 0;
1127
}
1128

    
1129
void helper_cmpfgt (void)
1130
{
1131
    if (float64_le(FT0, FT1, &FP_STATUS))
1132
        T0 = 0;
1133
    else
1134
        T0 = 1;
1135
}
1136

    
1137
void helper_cmpfge (void)
1138
{
1139
    if (float64_lt(FT0, FT1, &FP_STATUS))
1140
        T0 = 0;
1141
    else
1142
        T0 = 1;
1143
}
1144

    
1145
#if !defined (CONFIG_USER_ONLY)
1146
void helper_mfpr (int iprn)
1147
{
1148
    uint64_t val;
1149

    
1150
    if (cpu_alpha_mfpr(env, iprn, &val) == 0)
1151
        T0 = val;
1152
}
1153

    
1154
void helper_mtpr (int iprn)
1155
{
1156
    cpu_alpha_mtpr(env, iprn, T0, NULL);
1157
}
1158
#endif
1159

    
1160
/*****************************************************************************/
1161
/* Softmmu support */
1162
#if !defined (CONFIG_USER_ONLY)
1163

    
1164
#define GETPC() (__builtin_return_address(0))
1165

    
1166
/* XXX: the two following helpers are pure hacks.
1167
 *      Hopefully, we emulate the PALcode, then we should never see
1168
 *      HW_LD / HW_ST instructions.
1169
 */
1170
void helper_ld_phys_to_virt (void)
1171
{
1172
    uint64_t tlb_addr, physaddr;
1173
    int index, mmu_idx;
1174
    void *retaddr;
1175

    
1176
    mmu_idx = cpu_mmu_index(env);
1177
    index = (T0 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1178
 redo:
1179
    tlb_addr = env->tlb_table[mmu_idx][index].addr_read;
1180
    if ((T0 & TARGET_PAGE_MASK) ==
1181
        (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1182
        physaddr = T0 + env->tlb_table[mmu_idx][index].addend;
1183
    } else {
1184
        /* the page is not in the TLB : fill it */
1185
        retaddr = GETPC();
1186
        tlb_fill(T0, 0, mmu_idx, retaddr);
1187
        goto redo;
1188
    }
1189
    T0 = physaddr;
1190
}
1191

    
1192
void helper_st_phys_to_virt (void)
1193
{
1194
    uint64_t tlb_addr, physaddr;
1195
    int index, mmu_idx;
1196
    void *retaddr;
1197

    
1198
    mmu_idx = cpu_mmu_index(env);
1199
    index = (T0 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1200
 redo:
1201
    tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
1202
    if ((T0 & TARGET_PAGE_MASK) ==
1203
        (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1204
        physaddr = T0 + env->tlb_table[mmu_idx][index].addend;
1205
    } else {
1206
        /* the page is not in the TLB : fill it */
1207
        retaddr = GETPC();
1208
        tlb_fill(T0, 1, mmu_idx, retaddr);
1209
        goto redo;
1210
    }
1211
    T0 = physaddr;
1212
}
1213

    
1214
#define MMUSUFFIX _mmu
1215

    
1216
#define SHIFT 0
1217
#include "softmmu_template.h"
1218

    
1219
#define SHIFT 1
1220
#include "softmmu_template.h"
1221

    
1222
#define SHIFT 2
1223
#include "softmmu_template.h"
1224

    
1225
#define SHIFT 3
1226
#include "softmmu_template.h"
1227

    
1228
/* try to fill the TLB and return an exception if error. If retaddr is
1229
   NULL, it means that the function was called in C code (i.e. not
1230
   from generated code or from helper.c) */
1231
/* XXX: fix it to restore all registers */
1232
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1233
{
1234
    TranslationBlock *tb;
1235
    CPUState *saved_env;
1236
    target_phys_addr_t pc;
1237
    int ret;
1238

    
1239
    /* XXX: hack to restore env in all cases, even if not called from
1240
       generated code */
1241
    saved_env = env;
1242
    env = cpu_single_env;
1243
    ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1244
    if (!likely(ret == 0)) {
1245
        if (likely(retaddr)) {
1246
            /* now we have a real cpu fault */
1247
            pc = (target_phys_addr_t)retaddr;
1248
            tb = tb_find_pc(pc);
1249
            if (likely(tb)) {
1250
                /* the PC is inside the translated code. It means that we have
1251
                   a virtual CPU fault */
1252
                cpu_restore_state(tb, env, pc, NULL);
1253
            }
1254
        }
1255
        /* Exception index and error code are already set */
1256
        cpu_loop_exit();
1257
    }
1258
    env = saved_env;
1259
}
1260

    
1261
#endif