Generate micro-ops for Alpha executive and supervisor modes.
[qemu] / target-alpha / op_helper.c
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