target-alpha: convert arith2 instructions to TCG
[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 "host-utils.h"
23 #include "softfloat.h"
24
25 #include "op_helper.h"
26
27 #define MEMSUFFIX _raw
28 #include "op_helper_mem.h"
29
30 #if !defined(CONFIG_USER_ONLY)
31 #define MEMSUFFIX _kernel
32 #include "op_helper_mem.h"
33
34 #define MEMSUFFIX _executive
35 #include "op_helper_mem.h"
36
37 #define MEMSUFFIX _supervisor
38 #include "op_helper_mem.h"
39
40 #define MEMSUFFIX _user
41 #include "op_helper_mem.h"
42
43 /* This is used for pal modes */
44 #define MEMSUFFIX _data
45 #include "op_helper_mem.h"
46 #endif
47
48 void helper_tb_flush (void)
49 {
50     tlb_flush(env, 1);
51 }
52
53 void cpu_dump_EA (target_ulong EA);
54 void helper_print_mem_EA (target_ulong EA)
55 {
56     cpu_dump_EA(EA);
57 }
58
59 /*****************************************************************************/
60 /* Exceptions processing helpers */
61 void helper_excp (uint32_t excp, uint32_t error)
62 {
63     env->exception_index = excp;
64     env->error_code = error;
65     cpu_loop_exit();
66 }
67
68 uint64_t helper_amask (uint64_t arg)
69 {
70     switch (env->implver) {
71     case IMPLVER_2106x:
72         /* EV4, EV45, LCA, LCA45 & EV5 */
73         break;
74     case IMPLVER_21164:
75     case IMPLVER_21264:
76     case IMPLVER_21364:
77         arg &= ~env->amask;
78         break;
79     }
80     return arg;
81 }
82
83 void helper_load_pcc (void)
84 {
85     /* XXX: TODO */
86     T0 = 0;
87 }
88
89 void helper_load_implver (void)
90 {
91     T0 = env->implver;
92 }
93
94 void helper_load_fpcr (void)
95 {
96     T0 = 0;
97 #ifdef CONFIG_SOFTFLOAT
98     T0 |= env->fp_status.float_exception_flags << 52;
99     if (env->fp_status.float_exception_flags)
100         T0 |= 1ULL << 63;
101     env->ipr[IPR_EXC_SUM] &= ~0x3E:
102     env->ipr[IPR_EXC_SUM] |= env->fp_status.float_exception_flags << 1;
103 #endif
104     switch (env->fp_status.float_rounding_mode) {
105     case float_round_nearest_even:
106         T0 |= 2ULL << 58;
107         break;
108     case float_round_down:
109         T0 |= 1ULL << 58;
110         break;
111     case float_round_up:
112         T0 |= 3ULL << 58;
113         break;
114     case float_round_to_zero:
115         break;
116     }
117 }
118
119 void helper_store_fpcr (void)
120 {
121 #ifdef CONFIG_SOFTFLOAT
122     set_float_exception_flags((T0 >> 52) & 0x3F, &FP_STATUS);
123 #endif
124     switch ((T0 >> 58) & 3) {
125     case 0:
126         set_float_rounding_mode(float_round_to_zero, &FP_STATUS);
127         break;
128     case 1:
129         set_float_rounding_mode(float_round_down, &FP_STATUS);
130         break;
131     case 2:
132         set_float_rounding_mode(float_round_nearest_even, &FP_STATUS);
133         break;
134     case 3:
135         set_float_rounding_mode(float_round_up, &FP_STATUS);
136         break;
137     }
138 }
139
140 void helper_load_irf (void)
141 {
142     /* XXX: TODO */
143     T0 = 0;
144 }
145
146 void helper_set_irf (void)
147 {
148     /* XXX: TODO */
149 }
150
151 void helper_clear_irf (void)
152 {
153     /* XXX: TODO */
154 }
155
156 void helper_addqv (void)
157 {
158     T2 = T0;
159     T0 += T1;
160     if (unlikely((T2 ^ T1 ^ (-1ULL)) & (T2 ^ T0) & (1ULL << 63))) {
161         helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
162     }
163 }
164
165 void helper_addlv (void)
166 {
167     T2 = T0;
168     T0 = (uint32_t)(T0 + T1);
169     if (unlikely((T2 ^ T1 ^ (-1UL)) & (T2 ^ T0) & (1UL << 31))) {
170         helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
171     }
172 }
173
174 void helper_subqv (void)
175 {
176     T2 = T0;
177     T0 -= T1;
178     if (unlikely(((~T2) ^ T0 ^ (-1ULL)) & ((~T2) ^ T1) & (1ULL << 63))) {
179         helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
180     }
181 }
182
183 void helper_sublv (void)
184 {
185     T2 = T0;
186     T0 = (uint32_t)(T0 - T1);
187     if (unlikely(((~T2) ^ T0 ^ (-1UL)) & ((~T2) ^ T1) & (1UL << 31))) {
188         helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
189     }
190 }
191
192 void helper_mullv (void)
193 {
194     int64_t res = (int64_t)T0 * (int64_t)T1;
195
196     if (unlikely((int32_t)res != res)) {
197         helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
198     }
199     T0 = (int64_t)((int32_t)res);
200 }
201
202 void helper_mulqv ()
203 {
204     uint64_t tl, th;
205
206     muls64(&tl, &th, T0, T1);
207     /* If th != 0 && th != -1, then we had an overflow */
208     if (unlikely((th + 1) > 1)) {
209         helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
210     }
211     T0 = tl;
212 }
213
214 uint64_t helper_ctpop (uint64_t arg)
215 {
216     return ctpop64(arg);
217 }
218
219 uint64_t helper_ctlz (uint64_t arg)
220 {
221     return clz64(arg);
222 }
223
224 uint64_t helper_cttz (uint64_t arg)
225 {
226     return ctz64(arg);
227 }
228
229 static always_inline uint64_t byte_zap (uint64_t op, uint8_t mskb)
230 {
231     uint64_t mask;
232
233     mask = 0;
234     mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL;
235     mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL;
236     mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL;
237     mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL;
238     mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL;
239     mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL;
240     mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL;
241     mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL;
242
243     return op & ~mask;
244 }
245
246 void helper_mskbl (void)
247 {
248     T0 = byte_zap(T0, 0x01 << (T1 & 7));
249 }
250
251 void helper_extbl (void)
252 {
253     T0 >>= (T1 & 7) * 8;
254     T0 = byte_zap(T0, 0xFE);
255 }
256
257 void helper_insbl (void)
258 {
259     T0 <<= (T1 & 7) * 8;
260     T0 = byte_zap(T0, ~(0x01 << (T1 & 7)));
261 }
262
263 void helper_mskwl (void)
264 {
265     T0 = byte_zap(T0, 0x03 << (T1 & 7));
266 }
267
268 void helper_extwl (void)
269 {
270     T0 >>= (T1 & 7) * 8;
271     T0 = byte_zap(T0, 0xFC);
272 }
273
274 void helper_inswl (void)
275 {
276     T0 <<= (T1 & 7) * 8;
277     T0 = byte_zap(T0, ~(0x03 << (T1 & 7)));
278 }
279
280 void helper_mskll (void)
281 {
282     T0 = byte_zap(T0, 0x0F << (T1 & 7));
283 }
284
285 void helper_extll (void)
286 {
287     T0 >>= (T1 & 7) * 8;
288     T0 = byte_zap(T0, 0xF0);
289 }
290
291 void helper_insll (void)
292 {
293     T0 <<= (T1 & 7) * 8;
294     T0 = byte_zap(T0, ~(0x0F << (T1 & 7)));
295 }
296
297 void helper_zap (void)
298 {
299     T0 = byte_zap(T0, T1);
300 }
301
302 void helper_zapnot (void)
303 {
304     T0 = byte_zap(T0, ~T1);
305 }
306
307 void helper_mskql (void)
308 {
309     T0 = byte_zap(T0, 0xFF << (T1 & 7));
310 }
311
312 void helper_extql (void)
313 {
314     T0 >>= (T1 & 7) * 8;
315     T0 = byte_zap(T0, 0x00);
316 }
317
318 void helper_insql (void)
319 {
320     T0 <<= (T1 & 7) * 8;
321     T0 = byte_zap(T0, ~(0xFF << (T1 & 7)));
322 }
323
324 void helper_mskwh (void)
325 {
326     T0 = byte_zap(T0, (0x03 << (T1 & 7)) >> 8);
327 }
328
329 void helper_inswh (void)
330 {
331     T0 >>= 64 - ((T1 & 7) * 8);
332     T0 = byte_zap(T0, ~((0x03 << (T1 & 7)) >> 8));
333 }
334
335 void helper_extwh (void)
336 {
337     T0 <<= 64 - ((T1 & 7) * 8);
338     T0 = byte_zap(T0, ~0x07);
339 }
340
341 void helper_msklh (void)
342 {
343     T0 = byte_zap(T0, (0x0F << (T1 & 7)) >> 8);
344 }
345
346 void helper_inslh (void)
347 {
348     T0 >>= 64 - ((T1 & 7) * 8);
349     T0 = byte_zap(T0, ~((0x0F << (T1 & 7)) >> 8));
350 }
351
352 void helper_extlh (void)
353 {
354     T0 <<= 64 - ((T1 & 7) * 8);
355     T0 = byte_zap(T0, ~0x0F);
356 }
357
358 void helper_mskqh (void)
359 {
360     T0 = byte_zap(T0, (0xFF << (T1 & 7)) >> 8);
361 }
362
363 void helper_insqh (void)
364 {
365     T0 >>= 64 - ((T1 & 7) * 8);
366     T0 = byte_zap(T0, ~((0xFF << (T1 & 7)) >> 8));
367 }
368
369 void helper_extqh (void)
370 {
371     T0 <<= 64 - ((T1 & 7) * 8);
372     T0 = byte_zap(T0, 0x00);
373 }
374
375 void helper_cmpbge (void)
376 {
377     uint8_t opa, opb, res;
378     int i;
379
380     res = 0;
381     for (i = 0; i < 7; i++) {
382         opa = T0 >> (i * 8);
383         opb = T1 >> (i * 8);
384         if (opa >= opb)
385             res |= 1 << i;
386     }
387     T0 = res;
388 }
389
390 void helper_cmov_fir (int freg)
391 {
392     if (FT0 != 0)
393         env->fir[freg] = FT1;
394 }
395
396 void helper_sqrts (void)
397 {
398     FT0 = float32_sqrt(FT0, &FP_STATUS);
399 }
400
401 void helper_cpys (void)
402 {
403     union {
404         double d;
405         uint64_t i;
406     } p, q, r;
407
408     p.d = FT0;
409     q.d = FT1;
410     r.i = p.i & 0x8000000000000000ULL;
411     r.i |= q.i & ~0x8000000000000000ULL;
412     FT0 = r.d;
413 }
414
415 void helper_cpysn (void)
416 {
417     union {
418         double d;
419         uint64_t i;
420     } p, q, r;
421
422     p.d = FT0;
423     q.d = FT1;
424     r.i = (~p.i) & 0x8000000000000000ULL;
425     r.i |= q.i & ~0x8000000000000000ULL;
426     FT0 = r.d;
427 }
428
429 void helper_cpyse (void)
430 {
431     union {
432         double d;
433         uint64_t i;
434     } p, q, r;
435
436     p.d = FT0;
437     q.d = FT1;
438     r.i = p.i & 0xFFF0000000000000ULL;
439     r.i |= q.i & ~0xFFF0000000000000ULL;
440     FT0 = r.d;
441 }
442
443 void helper_itofs (void)
444 {
445     union {
446         double d;
447         uint64_t i;
448     } p;
449
450     p.d = FT0;
451     FT0 = int64_to_float32(p.i, &FP_STATUS);
452 }
453
454 void helper_ftois (void)
455 {
456     union {
457         double d;
458         uint64_t i;
459     } p;
460
461     p.i = float32_to_int64(FT0, &FP_STATUS);
462     FT0 = p.d;
463 }
464
465 void helper_sqrtt (void)
466 {
467     FT0 = float64_sqrt(FT0, &FP_STATUS);
468 }
469
470 void helper_cmptun (void)
471 {
472     union {
473         double d;
474         uint64_t i;
475     } p;
476
477     p.i = 0;
478     if (float64_is_nan(FT0) || float64_is_nan(FT1))
479         p.i = 0x4000000000000000ULL;
480     FT0 = p.d;
481 }
482
483 void helper_cmpteq (void)
484 {
485     union {
486         double d;
487         uint64_t i;
488     } p;
489
490     p.i = 0;
491     if (float64_eq(FT0, FT1, &FP_STATUS))
492         p.i = 0x4000000000000000ULL;
493     FT0 = p.d;
494 }
495
496 void helper_cmptle (void)
497 {
498     union {
499         double d;
500         uint64_t i;
501     } p;
502
503     p.i = 0;
504     if (float64_le(FT0, FT1, &FP_STATUS))
505         p.i = 0x4000000000000000ULL;
506     FT0 = p.d;
507 }
508
509 void helper_cmptlt (void)
510 {
511     union {
512         double d;
513         uint64_t i;
514     } p;
515
516     p.i = 0;
517     if (float64_lt(FT0, FT1, &FP_STATUS))
518         p.i = 0x4000000000000000ULL;
519     FT0 = p.d;
520 }
521
522 void helper_itoft (void)
523 {
524     union {
525         double d;
526         uint64_t i;
527     } p;
528
529     p.d = FT0;
530     FT0 = int64_to_float64(p.i, &FP_STATUS);
531 }
532
533 void helper_ftoit (void)
534 {
535     union {
536         double d;
537         uint64_t i;
538     } p;
539
540     p.i = float64_to_int64(FT0, &FP_STATUS);
541     FT0 = p.d;
542 }
543
544 static always_inline int vaxf_is_valid (float ff)
545 {
546     union {
547         float f;
548         uint32_t i;
549     } p;
550     uint32_t exp, mant;
551
552     p.f = ff;
553     exp = (p.i >> 23) & 0xFF;
554     mant = p.i & 0x007FFFFF;
555     if (exp == 0 && ((p.i & 0x80000000) || mant != 0)) {
556         /* Reserved operands / Dirty zero */
557         return 0;
558     }
559
560     return 1;
561 }
562
563 static always_inline float vaxf_to_ieee32 (float ff)
564 {
565     union {
566         float f;
567         uint32_t i;
568     } p;
569     uint32_t exp;
570
571     p.f = ff;
572     exp = (p.i >> 23) & 0xFF;
573     if (exp < 3) {
574         /* Underflow */
575         p.f = 0.0;
576     } else {
577         p.f *= 0.25;
578     }
579
580     return p.f;
581 }
582
583 static always_inline float ieee32_to_vaxf (float fi)
584 {
585     union {
586         float f;
587         uint32_t i;
588     } p;
589     uint32_t exp, mant;
590
591     p.f = fi;
592     exp = (p.i >> 23) & 0xFF;
593     mant = p.i & 0x007FFFFF;
594     if (exp == 255) {
595         /* NaN or infinity */
596         p.i = 1;
597     } else if (exp == 0) {
598         if (mant == 0) {
599             /* Zero */
600             p.i = 0;
601         } else {
602             /* Denormalized */
603             p.f *= 2.0;
604         }
605     } else {
606         if (exp >= 253) {
607             /* Overflow */
608             p.i = 1;
609         } else {
610             p.f *= 4.0;
611         }
612     }
613
614     return p.f;
615 }
616
617 void helper_addf (void)
618 {
619     float ft0, ft1, ft2;
620
621     if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
622         /* XXX: TODO */
623     }
624     ft0 = vaxf_to_ieee32(FT0);
625     ft1 = vaxf_to_ieee32(FT1);
626     ft2 = float32_add(ft0, ft1, &FP_STATUS);
627     FT0 = ieee32_to_vaxf(ft2);
628 }
629
630 void helper_subf (void)
631 {
632     float ft0, ft1, ft2;
633
634     if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
635         /* XXX: TODO */
636     }
637     ft0 = vaxf_to_ieee32(FT0);
638     ft1 = vaxf_to_ieee32(FT1);
639     ft2 = float32_sub(ft0, ft1, &FP_STATUS);
640     FT0 = ieee32_to_vaxf(ft2);
641 }
642
643 void helper_mulf (void)
644 {
645     float ft0, ft1, ft2;
646
647     if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
648         /* XXX: TODO */
649     }
650     ft0 = vaxf_to_ieee32(FT0);
651     ft1 = vaxf_to_ieee32(FT1);
652     ft2 = float32_mul(ft0, ft1, &FP_STATUS);
653     FT0 = ieee32_to_vaxf(ft2);
654 }
655
656 void helper_divf (void)
657 {
658     float ft0, ft1, ft2;
659
660     if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
661         /* XXX: TODO */
662     }
663     ft0 = vaxf_to_ieee32(FT0);
664     ft1 = vaxf_to_ieee32(FT1);
665     ft2 = float32_div(ft0, ft1, &FP_STATUS);
666     FT0 = ieee32_to_vaxf(ft2);
667 }
668
669 void helper_sqrtf (void)
670 {
671     float ft0, ft1;
672
673     if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
674         /* XXX: TODO */
675     }
676     ft0 = vaxf_to_ieee32(FT0);
677     ft1 = float32_sqrt(ft0, &FP_STATUS);
678     FT0 = ieee32_to_vaxf(ft1);
679 }
680
681 void helper_itoff (void)
682 {
683     /* XXX: TODO */
684 }
685
686 static always_inline int vaxg_is_valid (double ff)
687 {
688     union {
689         double f;
690         uint64_t i;
691     } p;
692     uint64_t exp, mant;
693
694     p.f = ff;
695     exp = (p.i >> 52) & 0x7FF;
696     mant = p.i & 0x000FFFFFFFFFFFFFULL;
697     if (exp == 0 && ((p.i & 0x8000000000000000ULL) || mant != 0)) {
698         /* Reserved operands / Dirty zero */
699         return 0;
700     }
701
702     return 1;
703 }
704
705 static always_inline double vaxg_to_ieee64 (double fg)
706 {
707     union {
708         double f;
709         uint64_t i;
710     } p;
711     uint32_t exp;
712
713     p.f = fg;
714     exp = (p.i >> 52) & 0x7FF;
715     if (exp < 3) {
716         /* Underflow */
717         p.f = 0.0;
718     } else {
719         p.f *= 0.25;
720     }
721
722     return p.f;
723 }
724
725 static always_inline double ieee64_to_vaxg (double fi)
726 {
727     union {
728         double f;
729         uint64_t i;
730     } p;
731     uint64_t mant;
732     uint32_t exp;
733
734     p.f = fi;
735     exp = (p.i >> 52) & 0x7FF;
736     mant = p.i & 0x000FFFFFFFFFFFFFULL;
737     if (exp == 255) {
738         /* NaN or infinity */
739         p.i = 1; /* VAX dirty zero */
740     } else if (exp == 0) {
741         if (mant == 0) {
742             /* Zero */
743             p.i = 0;
744         } else {
745             /* Denormalized */
746             p.f *= 2.0;
747         }
748     } else {
749         if (exp >= 2045) {
750             /* Overflow */
751             p.i = 1; /* VAX dirty zero */
752         } else {
753             p.f *= 4.0;
754         }
755     }
756
757     return p.f;
758 }
759
760 void helper_addg (void)
761 {
762     double ft0, ft1, ft2;
763
764     if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
765         /* XXX: TODO */
766     }
767     ft0 = vaxg_to_ieee64(FT0);
768     ft1 = vaxg_to_ieee64(FT1);
769     ft2 = float64_add(ft0, ft1, &FP_STATUS);
770     FT0 = ieee64_to_vaxg(ft2);
771 }
772
773 void helper_subg (void)
774 {
775     double ft0, ft1, ft2;
776
777     if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
778         /* XXX: TODO */
779     }
780     ft0 = vaxg_to_ieee64(FT0);
781     ft1 = vaxg_to_ieee64(FT1);
782     ft2 = float64_sub(ft0, ft1, &FP_STATUS);
783     FT0 = ieee64_to_vaxg(ft2);
784 }
785
786 void helper_mulg (void)
787 {
788     double ft0, ft1, ft2;
789
790     if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
791         /* XXX: TODO */
792     }
793     ft0 = vaxg_to_ieee64(FT0);
794     ft1 = vaxg_to_ieee64(FT1);
795     ft2 = float64_mul(ft0, ft1, &FP_STATUS);
796     FT0 = ieee64_to_vaxg(ft2);
797 }
798
799 void helper_divg (void)
800 {
801     double ft0, ft1, ft2;
802
803     if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
804         /* XXX: TODO */
805     }
806     ft0 = vaxg_to_ieee64(FT0);
807     ft1 = vaxg_to_ieee64(FT1);
808     ft2 = float64_div(ft0, ft1, &FP_STATUS);
809     FT0 = ieee64_to_vaxg(ft2);
810 }
811
812 void helper_sqrtg (void)
813 {
814     double ft0, ft1;
815
816     if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
817         /* XXX: TODO */
818     }
819     ft0 = vaxg_to_ieee64(FT0);
820     ft1 = float64_sqrt(ft0, &FP_STATUS);
821     FT0 = ieee64_to_vaxg(ft1);
822 }
823
824 void helper_cmpgeq (void)
825 {
826     union {
827         double d;
828         uint64_t u;
829     } p;
830     double ft0, ft1;
831
832     if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
833         /* XXX: TODO */
834     }
835     ft0 = vaxg_to_ieee64(FT0);
836     ft1 = vaxg_to_ieee64(FT1);
837     p.u = 0;
838     if (float64_eq(ft0, ft1, &FP_STATUS))
839         p.u = 0x4000000000000000ULL;
840     FT0 = p.d;
841 }
842
843 void helper_cmpglt (void)
844 {
845     union {
846         double d;
847         uint64_t u;
848     } p;
849     double ft0, ft1;
850
851     if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
852         /* XXX: TODO */
853     }
854     ft0 = vaxg_to_ieee64(FT0);
855     ft1 = vaxg_to_ieee64(FT1);
856     p.u = 0;
857     if (float64_lt(ft0, ft1, &FP_STATUS))
858         p.u = 0x4000000000000000ULL;
859     FT0 = p.d;
860 }
861
862 void helper_cmpgle (void)
863 {
864     union {
865         double d;
866         uint64_t u;
867     } p;
868     double ft0, ft1;
869
870     if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
871         /* XXX: TODO */
872     }
873     ft0 = vaxg_to_ieee64(FT0);
874     ft1 = vaxg_to_ieee64(FT1);
875     p.u = 0;
876     if (float64_le(ft0, ft1, &FP_STATUS))
877         p.u = 0x4000000000000000ULL;
878     FT0 = p.d;
879 }
880
881 void helper_cvtqs (void)
882 {
883     union {
884         double d;
885         uint64_t u;
886     } p;
887
888     p.d = FT0;
889     FT0 = (float)p.u;
890 }
891
892 void helper_cvttq (void)
893 {
894     union {
895         double d;
896         uint64_t u;
897     } p;
898
899     p.u = FT0;
900     FT0 = p.d;
901 }
902
903 void helper_cvtqt (void)
904 {
905     union {
906         double d;
907         uint64_t u;
908     } p;
909
910     p.d = FT0;
911     FT0 = p.u;
912 }
913
914 void helper_cvtqf (void)
915 {
916     union {
917         double d;
918         uint64_t u;
919     } p;
920
921     p.d = FT0;
922     FT0 = ieee32_to_vaxf(p.u);
923 }
924
925 void helper_cvtgf (void)
926 {
927     double ft0;
928
929     ft0 = vaxg_to_ieee64(FT0);
930     FT0 = ieee32_to_vaxf(ft0);
931 }
932
933 void helper_cvtgd (void)
934 {
935     /* XXX: TODO */
936 }
937
938 void helper_cvtgq (void)
939 {
940     union {
941         double d;
942         uint64_t u;
943     } p;
944
945     p.u = vaxg_to_ieee64(FT0);
946     FT0 = p.d;
947 }
948
949 void helper_cvtqg (void)
950 {
951     union {
952         double d;
953         uint64_t u;
954     } p;
955
956     p.d = FT0;
957     FT0 = ieee64_to_vaxg(p.u);
958 }
959
960 void helper_cvtdg (void)
961 {
962     /* XXX: TODO */
963 }
964
965 void helper_cvtlq (void)
966 {
967     union {
968         double d;
969         uint64_t u;
970     } p, q;
971
972     p.d = FT0;
973     q.u = (p.u >> 29) & 0x3FFFFFFF;
974     q.u |= (p.u >> 32);
975     q.u = (int64_t)((int32_t)q.u);
976     FT0 = q.d;
977 }
978
979 static always_inline void __helper_cvtql (int s, int v)
980 {
981     union {
982         double d;
983         uint64_t u;
984     } p, q;
985
986     p.d = FT0;
987     q.u = ((uint64_t)(p.u & 0xC0000000)) << 32;
988     q.u |= ((uint64_t)(p.u & 0x7FFFFFFF)) << 29;
989     FT0 = q.d;
990     if (v && (int64_t)((int32_t)p.u) != (int64_t)p.u) {
991         helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
992     }
993     if (s) {
994         /* TODO */
995     }
996 }
997
998 void helper_cvtql (void)
999 {
1000     __helper_cvtql(0, 0);
1001 }
1002
1003 void helper_cvtqlv (void)
1004 {
1005     __helper_cvtql(0, 1);
1006 }
1007
1008 void helper_cvtqlsv (void)
1009 {
1010     __helper_cvtql(1, 1);
1011 }
1012
1013 void helper_cmpfeq (void)
1014 {
1015     if (float64_eq(FT0, FT1, &FP_STATUS))
1016         T0 = 1;
1017     else
1018         T0 = 0;
1019 }
1020
1021 void helper_cmpfne (void)
1022 {
1023     if (float64_eq(FT0, FT1, &FP_STATUS))
1024         T0 = 0;
1025     else
1026         T0 = 1;
1027 }
1028
1029 void helper_cmpflt (void)
1030 {
1031     if (float64_lt(FT0, FT1, &FP_STATUS))
1032         T0 = 1;
1033     else
1034         T0 = 0;
1035 }
1036
1037 void helper_cmpfle (void)
1038 {
1039     if (float64_lt(FT0, FT1, &FP_STATUS))
1040         T0 = 1;
1041     else
1042         T0 = 0;
1043 }
1044
1045 void helper_cmpfgt (void)
1046 {
1047     if (float64_le(FT0, FT1, &FP_STATUS))
1048         T0 = 0;
1049     else
1050         T0 = 1;
1051 }
1052
1053 void helper_cmpfge (void)
1054 {
1055     if (float64_lt(FT0, FT1, &FP_STATUS))
1056         T0 = 0;
1057     else
1058         T0 = 1;
1059 }
1060
1061 #if !defined (CONFIG_USER_ONLY)
1062 void helper_mfpr (int iprn)
1063 {
1064     uint64_t val;
1065
1066     if (cpu_alpha_mfpr(env, iprn, &val) == 0)
1067         T0 = val;
1068 }
1069
1070 void helper_mtpr (int iprn)
1071 {
1072     cpu_alpha_mtpr(env, iprn, T0, NULL);
1073 }
1074 #endif
1075
1076 #if defined(HOST_SPARC) || defined(HOST_SPARC64)
1077 void helper_reset_FT0 (void)
1078 {
1079     FT0 = 0;
1080 }
1081
1082 void helper_reset_FT1 (void)
1083 {
1084     FT1 = 0;
1085 }
1086
1087 void helper_reset_FT2 (void)
1088 {
1089     FT2 = 0;
1090 }
1091 #endif
1092
1093 /*****************************************************************************/
1094 /* Softmmu support */
1095 #if !defined (CONFIG_USER_ONLY)
1096
1097 /* XXX: the two following helpers are pure hacks.
1098  *      Hopefully, we emulate the PALcode, then we should never see
1099  *      HW_LD / HW_ST instructions.
1100  */
1101 void helper_ld_phys_to_virt (void)
1102 {
1103     uint64_t tlb_addr, physaddr;
1104     int index, mmu_idx;
1105     void *retaddr;
1106
1107     mmu_idx = cpu_mmu_index(env);
1108     index = (T0 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1109  redo:
1110     tlb_addr = env->tlb_table[mmu_idx][index].addr_read;
1111     if ((T0 & TARGET_PAGE_MASK) ==
1112         (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1113         physaddr = T0 + env->tlb_table[mmu_idx][index].addend;
1114     } else {
1115         /* the page is not in the TLB : fill it */
1116         retaddr = GETPC();
1117         tlb_fill(T0, 0, mmu_idx, retaddr);
1118         goto redo;
1119     }
1120     T0 = physaddr;
1121 }
1122
1123 void helper_st_phys_to_virt (void)
1124 {
1125     uint64_t tlb_addr, physaddr;
1126     int index, mmu_idx;
1127     void *retaddr;
1128
1129     mmu_idx = cpu_mmu_index(env);
1130     index = (T0 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1131  redo:
1132     tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
1133     if ((T0 & TARGET_PAGE_MASK) ==
1134         (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1135         physaddr = T0 + env->tlb_table[mmu_idx][index].addend;
1136     } else {
1137         /* the page is not in the TLB : fill it */
1138         retaddr = GETPC();
1139         tlb_fill(T0, 1, mmu_idx, retaddr);
1140         goto redo;
1141     }
1142     T0 = physaddr;
1143 }
1144
1145 #define MMUSUFFIX _mmu
1146
1147 #define SHIFT 0
1148 #include "softmmu_template.h"
1149
1150 #define SHIFT 1
1151 #include "softmmu_template.h"
1152
1153 #define SHIFT 2
1154 #include "softmmu_template.h"
1155
1156 #define SHIFT 3
1157 #include "softmmu_template.h"
1158
1159 /* try to fill the TLB and return an exception if error. If retaddr is
1160    NULL, it means that the function was called in C code (i.e. not
1161    from generated code or from helper.c) */
1162 /* XXX: fix it to restore all registers */
1163 void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1164 {
1165     TranslationBlock *tb;
1166     CPUState *saved_env;
1167     unsigned long pc;
1168     int ret;
1169
1170     /* XXX: hack to restore env in all cases, even if not called from
1171        generated code */
1172     saved_env = env;
1173     env = cpu_single_env;
1174     ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1175     if (!likely(ret == 0)) {
1176         if (likely(retaddr)) {
1177             /* now we have a real cpu fault */
1178             pc = (unsigned long)retaddr;
1179             tb = tb_find_pc(pc);
1180             if (likely(tb)) {
1181                 /* the PC is inside the translated code. It means that we have
1182                    a virtual CPU fault */
1183                 cpu_restore_state(tb, env, pc, NULL);
1184             }
1185         }
1186         /* Exception index and error code are already set */
1187         cpu_loop_exit();
1188     }
1189     env = saved_env;
1190 }
1191
1192 #endif