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