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