2 * Alpha emulation cpu micro-operations helpers for qemu.
4 * Copyright (c) 2007 Jocelyn Mayer
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.
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.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "host-utils.h"
22 #include "softfloat.h"
24 #include "qemu-timer.h"
26 /*****************************************************************************/
27 /* Exceptions processing helpers */
29 /* This should only be called from translate, via gen_excp.
30 We expect that ENV->PC has already been updated. */
31 void QEMU_NORETURN
helper_excp(int excp
, int error
)
33 env
->exception_index
= excp
;
34 env
->error_code
= error
;
38 static void do_restore_state(void *retaddr
)
40 unsigned long pc
= (unsigned long)retaddr
;
43 TranslationBlock
*tb
= tb_find_pc(pc
);
45 cpu_restore_state(tb
, env
, pc
);
50 /* This may be called from any of the helpers to set up EXCEPTION_INDEX. */
51 static void QEMU_NORETURN
dynamic_excp(int excp
, int error
)
53 env
->exception_index
= excp
;
54 env
->error_code
= error
;
55 do_restore_state(GETPC());
59 static void QEMU_NORETURN
arith_excp(int exc
, uint64_t mask
)
62 env
->trap_arg1
= mask
;
63 dynamic_excp(EXCP_ARITH
, 0);
66 uint64_t helper_load_pcc (void)
68 #ifndef CONFIG_USER_ONLY
69 /* In system mode we have access to a decent high-resolution clock.
70 In order to make OS-level time accounting work with the RPCC,
71 present it with a well-timed clock fixed at 250MHz. */
72 return (((uint64_t)env
->pcc_ofs
<< 32)
73 | (uint32_t)(qemu_get_clock_ns(vm_clock
) >> 2));
75 /* In user-mode, vm_clock doesn't exist. Just pass through the host cpu
76 clock ticks. Also, don't bother taking PCC_OFS into account. */
77 return (uint32_t)cpu_get_real_ticks();
81 uint64_t helper_load_fpcr (void)
83 return cpu_alpha_load_fpcr (env
);
86 void helper_store_fpcr (uint64_t val
)
88 cpu_alpha_store_fpcr (env
, val
);
91 uint64_t helper_addqv (uint64_t op1
, uint64_t op2
)
95 if (unlikely((tmp
^ op2
^ (-1ULL)) & (tmp
^ op1
) & (1ULL << 63))) {
96 arith_excp(EXC_M_IOV
, 0);
101 uint64_t helper_addlv (uint64_t op1
, uint64_t op2
)
104 op1
= (uint32_t)(op1
+ op2
);
105 if (unlikely((tmp
^ op2
^ (-1UL)) & (tmp
^ op1
) & (1UL << 31))) {
106 arith_excp(EXC_M_IOV
, 0);
111 uint64_t helper_subqv (uint64_t op1
, uint64_t op2
)
115 if (unlikely((op1
^ op2
) & (res
^ op1
) & (1ULL << 63))) {
116 arith_excp(EXC_M_IOV
, 0);
121 uint64_t helper_sublv (uint64_t op1
, uint64_t op2
)
125 if (unlikely((op1
^ op2
) & (res
^ op1
) & (1UL << 31))) {
126 arith_excp(EXC_M_IOV
, 0);
131 uint64_t helper_mullv (uint64_t op1
, uint64_t op2
)
133 int64_t res
= (int64_t)op1
* (int64_t)op2
;
135 if (unlikely((int32_t)res
!= res
)) {
136 arith_excp(EXC_M_IOV
, 0);
138 return (int64_t)((int32_t)res
);
141 uint64_t helper_mulqv (uint64_t op1
, uint64_t op2
)
145 muls64(&tl
, &th
, op1
, op2
);
146 /* If th != 0 && th != -1, then we had an overflow */
147 if (unlikely((th
+ 1) > 1)) {
148 arith_excp(EXC_M_IOV
, 0);
153 uint64_t helper_umulh (uint64_t op1
, uint64_t op2
)
157 mulu64(&tl
, &th
, op1
, op2
);
161 uint64_t helper_ctpop (uint64_t arg
)
166 uint64_t helper_ctlz (uint64_t arg
)
171 uint64_t helper_cttz (uint64_t arg
)
176 static inline uint64_t byte_zap(uint64_t op
, uint8_t mskb
)
181 mask
|= ((mskb
>> 0) & 1) * 0x00000000000000FFULL
;
182 mask
|= ((mskb
>> 1) & 1) * 0x000000000000FF00ULL
;
183 mask
|= ((mskb
>> 2) & 1) * 0x0000000000FF0000ULL
;
184 mask
|= ((mskb
>> 3) & 1) * 0x00000000FF000000ULL
;
185 mask
|= ((mskb
>> 4) & 1) * 0x000000FF00000000ULL
;
186 mask
|= ((mskb
>> 5) & 1) * 0x0000FF0000000000ULL
;
187 mask
|= ((mskb
>> 6) & 1) * 0x00FF000000000000ULL
;
188 mask
|= ((mskb
>> 7) & 1) * 0xFF00000000000000ULL
;
193 uint64_t helper_zap(uint64_t val
, uint64_t mask
)
195 return byte_zap(val
, mask
);
198 uint64_t helper_zapnot(uint64_t val
, uint64_t mask
)
200 return byte_zap(val
, ~mask
);
203 uint64_t helper_cmpbge (uint64_t op1
, uint64_t op2
)
205 uint8_t opa
, opb
, res
;
209 for (i
= 0; i
< 8; i
++) {
210 opa
= op1
>> (i
* 8);
211 opb
= op2
>> (i
* 8);
218 uint64_t helper_minub8 (uint64_t op1
, uint64_t op2
)
221 uint8_t opa
, opb
, opr
;
224 for (i
= 0; i
< 8; ++i
) {
225 opa
= op1
>> (i
* 8);
226 opb
= op2
>> (i
* 8);
227 opr
= opa
< opb
? opa
: opb
;
228 res
|= (uint64_t)opr
<< (i
* 8);
233 uint64_t helper_minsb8 (uint64_t op1
, uint64_t op2
)
240 for (i
= 0; i
< 8; ++i
) {
241 opa
= op1
>> (i
* 8);
242 opb
= op2
>> (i
* 8);
243 opr
= opa
< opb
? opa
: opb
;
244 res
|= (uint64_t)opr
<< (i
* 8);
249 uint64_t helper_minuw4 (uint64_t op1
, uint64_t op2
)
252 uint16_t opa
, opb
, opr
;
255 for (i
= 0; i
< 4; ++i
) {
256 opa
= op1
>> (i
* 16);
257 opb
= op2
>> (i
* 16);
258 opr
= opa
< opb
? opa
: opb
;
259 res
|= (uint64_t)opr
<< (i
* 16);
264 uint64_t helper_minsw4 (uint64_t op1
, uint64_t op2
)
271 for (i
= 0; i
< 4; ++i
) {
272 opa
= op1
>> (i
* 16);
273 opb
= op2
>> (i
* 16);
274 opr
= opa
< opb
? opa
: opb
;
275 res
|= (uint64_t)opr
<< (i
* 16);
280 uint64_t helper_maxub8 (uint64_t op1
, uint64_t op2
)
283 uint8_t opa
, opb
, opr
;
286 for (i
= 0; i
< 8; ++i
) {
287 opa
= op1
>> (i
* 8);
288 opb
= op2
>> (i
* 8);
289 opr
= opa
> opb
? opa
: opb
;
290 res
|= (uint64_t)opr
<< (i
* 8);
295 uint64_t helper_maxsb8 (uint64_t op1
, uint64_t op2
)
302 for (i
= 0; i
< 8; ++i
) {
303 opa
= op1
>> (i
* 8);
304 opb
= op2
>> (i
* 8);
305 opr
= opa
> opb
? opa
: opb
;
306 res
|= (uint64_t)opr
<< (i
* 8);
311 uint64_t helper_maxuw4 (uint64_t op1
, uint64_t op2
)
314 uint16_t opa
, opb
, opr
;
317 for (i
= 0; i
< 4; ++i
) {
318 opa
= op1
>> (i
* 16);
319 opb
= op2
>> (i
* 16);
320 opr
= opa
> opb
? opa
: opb
;
321 res
|= (uint64_t)opr
<< (i
* 16);
326 uint64_t helper_maxsw4 (uint64_t op1
, uint64_t op2
)
333 for (i
= 0; i
< 4; ++i
) {
334 opa
= op1
>> (i
* 16);
335 opb
= op2
>> (i
* 16);
336 opr
= opa
> opb
? opa
: opb
;
337 res
|= (uint64_t)opr
<< (i
* 16);
342 uint64_t helper_perr (uint64_t op1
, uint64_t op2
)
345 uint8_t opa
, opb
, opr
;
348 for (i
= 0; i
< 8; ++i
) {
349 opa
= op1
>> (i
* 8);
350 opb
= op2
>> (i
* 8);
360 uint64_t helper_pklb (uint64_t op1
)
362 return (op1
& 0xff) | ((op1
>> 24) & 0xff00);
365 uint64_t helper_pkwb (uint64_t op1
)
368 | ((op1
>> 8) & 0xff00)
369 | ((op1
>> 16) & 0xff0000)
370 | ((op1
>> 24) & 0xff000000));
373 uint64_t helper_unpkbl (uint64_t op1
)
375 return (op1
& 0xff) | ((op1
& 0xff00) << 24);
378 uint64_t helper_unpkbw (uint64_t op1
)
381 | ((op1
& 0xff00) << 8)
382 | ((op1
& 0xff0000) << 16)
383 | ((op1
& 0xff000000) << 24));
386 /* Floating point helpers */
388 void helper_setroundmode (uint32_t val
)
390 set_float_rounding_mode(val
, &FP_STATUS
);
393 void helper_setflushzero (uint32_t val
)
395 set_flush_to_zero(val
, &FP_STATUS
);
398 void helper_fp_exc_clear (void)
400 set_float_exception_flags(0, &FP_STATUS
);
403 uint32_t helper_fp_exc_get (void)
405 return get_float_exception_flags(&FP_STATUS
);
408 /* Raise exceptions for ieee fp insns without software completion.
409 In that case there are no exceptions that don't trap; the mask
411 void helper_fp_exc_raise(uint32_t exc
, uint32_t regno
)
416 if (exc
& float_flag_invalid
) {
419 if (exc
& float_flag_divbyzero
) {
422 if (exc
& float_flag_overflow
) {
425 if (exc
& float_flag_underflow
) {
428 if (exc
& float_flag_inexact
) {
432 arith_excp(hw_exc
, 1ull << regno
);
436 /* Raise exceptions for ieee fp insns with software completion. */
437 void helper_fp_exc_raise_s(uint32_t exc
, uint32_t regno
)
440 env
->fpcr_exc_status
|= exc
;
442 exc
&= ~env
->fpcr_exc_mask
;
444 helper_fp_exc_raise(exc
, regno
);
449 /* Input remapping without software completion. Handle denormal-map-to-zero
450 and trap for all other non-finite numbers. */
451 uint64_t helper_ieee_input(uint64_t val
)
453 uint32_t exp
= (uint32_t)(val
>> 52) & 0x7ff;
454 uint64_t frac
= val
& 0xfffffffffffffull
;
458 /* If DNZ is set flush denormals to zero on input. */
462 arith_excp(EXC_M_UNF
, 0);
465 } else if (exp
== 0x7ff) {
466 /* Infinity or NaN. */
467 /* ??? I'm not sure these exception bit flags are correct. I do
468 know that the Linux kernel, at least, doesn't rely on them and
469 just emulates the insn to figure out what exception to use. */
470 arith_excp(frac
? EXC_M_INV
: EXC_M_FOV
, 0);
475 /* Similar, but does not trap for infinities. Used for comparisons. */
476 uint64_t helper_ieee_input_cmp(uint64_t val
)
478 uint32_t exp
= (uint32_t)(val
>> 52) & 0x7ff;
479 uint64_t frac
= val
& 0xfffffffffffffull
;
483 /* If DNZ is set flush denormals to zero on input. */
487 arith_excp(EXC_M_UNF
, 0);
490 } else if (exp
== 0x7ff && frac
) {
492 arith_excp(EXC_M_INV
, 0);
497 /* Input remapping with software completion enabled. All we have to do
498 is handle denormal-map-to-zero; all other inputs get exceptions as
499 needed from the actual operation. */
500 uint64_t helper_ieee_input_s(uint64_t val
)
503 uint32_t exp
= (uint32_t)(val
>> 52) & 0x7ff;
511 /* F floating (VAX) */
512 static inline uint64_t float32_to_f(float32 fa
)
514 uint64_t r
, exp
, mant
, sig
;
518 sig
= ((uint64_t)a
.l
& 0x80000000) << 32;
519 exp
= (a
.l
>> 23) & 0xff;
520 mant
= ((uint64_t)a
.l
& 0x007fffff) << 29;
523 /* NaN or infinity */
524 r
= 1; /* VAX dirty zero */
525 } else if (exp
== 0) {
531 r
= sig
| ((exp
+ 1) << 52) | mant
;
536 r
= 1; /* VAX dirty zero */
538 r
= sig
| ((exp
+ 2) << 52);
545 static inline float32
f_to_float32(uint64_t a
)
547 uint32_t exp
, mant_sig
;
550 exp
= ((a
>> 55) & 0x80) | ((a
>> 52) & 0x7f);
551 mant_sig
= ((a
>> 32) & 0x80000000) | ((a
>> 29) & 0x007fffff);
553 if (unlikely(!exp
&& mant_sig
)) {
554 /* Reserved operands / Dirty zero */
555 dynamic_excp(EXCP_OPCDEC
, 0);
562 r
.l
= ((exp
- 2) << 23) | mant_sig
;
568 uint32_t helper_f_to_memory (uint64_t a
)
571 r
= (a
& 0x00001fffe0000000ull
) >> 13;
572 r
|= (a
& 0x07ffe00000000000ull
) >> 45;
573 r
|= (a
& 0xc000000000000000ull
) >> 48;
577 uint64_t helper_memory_to_f (uint32_t a
)
580 r
= ((uint64_t)(a
& 0x0000c000)) << 48;
581 r
|= ((uint64_t)(a
& 0x003fffff)) << 45;
582 r
|= ((uint64_t)(a
& 0xffff0000)) << 13;
583 if (!(a
& 0x00004000))
588 /* ??? Emulating VAX arithmetic with IEEE arithmetic is wrong. We should
589 either implement VAX arithmetic properly or just signal invalid opcode. */
591 uint64_t helper_addf (uint64_t a
, uint64_t b
)
595 fa
= f_to_float32(a
);
596 fb
= f_to_float32(b
);
597 fr
= float32_add(fa
, fb
, &FP_STATUS
);
598 return float32_to_f(fr
);
601 uint64_t helper_subf (uint64_t a
, uint64_t b
)
605 fa
= f_to_float32(a
);
606 fb
= f_to_float32(b
);
607 fr
= float32_sub(fa
, fb
, &FP_STATUS
);
608 return float32_to_f(fr
);
611 uint64_t helper_mulf (uint64_t a
, uint64_t b
)
615 fa
= f_to_float32(a
);
616 fb
= f_to_float32(b
);
617 fr
= float32_mul(fa
, fb
, &FP_STATUS
);
618 return float32_to_f(fr
);
621 uint64_t helper_divf (uint64_t a
, uint64_t b
)
625 fa
= f_to_float32(a
);
626 fb
= f_to_float32(b
);
627 fr
= float32_div(fa
, fb
, &FP_STATUS
);
628 return float32_to_f(fr
);
631 uint64_t helper_sqrtf (uint64_t t
)
635 ft
= f_to_float32(t
);
636 fr
= float32_sqrt(ft
, &FP_STATUS
);
637 return float32_to_f(fr
);
641 /* G floating (VAX) */
642 static inline uint64_t float64_to_g(float64 fa
)
644 uint64_t r
, exp
, mant
, sig
;
648 sig
= a
.ll
& 0x8000000000000000ull
;
649 exp
= (a
.ll
>> 52) & 0x7ff;
650 mant
= a
.ll
& 0x000fffffffffffffull
;
653 /* NaN or infinity */
654 r
= 1; /* VAX dirty zero */
655 } else if (exp
== 0) {
661 r
= sig
| ((exp
+ 1) << 52) | mant
;
666 r
= 1; /* VAX dirty zero */
668 r
= sig
| ((exp
+ 2) << 52);
675 static inline float64
g_to_float64(uint64_t a
)
677 uint64_t exp
, mant_sig
;
680 exp
= (a
>> 52) & 0x7ff;
681 mant_sig
= a
& 0x800fffffffffffffull
;
683 if (!exp
&& mant_sig
) {
684 /* Reserved operands / Dirty zero */
685 dynamic_excp(EXCP_OPCDEC
, 0);
692 r
.ll
= ((exp
- 2) << 52) | mant_sig
;
698 uint64_t helper_g_to_memory (uint64_t a
)
701 r
= (a
& 0x000000000000ffffull
) << 48;
702 r
|= (a
& 0x00000000ffff0000ull
) << 16;
703 r
|= (a
& 0x0000ffff00000000ull
) >> 16;
704 r
|= (a
& 0xffff000000000000ull
) >> 48;
708 uint64_t helper_memory_to_g (uint64_t a
)
711 r
= (a
& 0x000000000000ffffull
) << 48;
712 r
|= (a
& 0x00000000ffff0000ull
) << 16;
713 r
|= (a
& 0x0000ffff00000000ull
) >> 16;
714 r
|= (a
& 0xffff000000000000ull
) >> 48;
718 uint64_t helper_addg (uint64_t a
, uint64_t b
)
722 fa
= g_to_float64(a
);
723 fb
= g_to_float64(b
);
724 fr
= float64_add(fa
, fb
, &FP_STATUS
);
725 return float64_to_g(fr
);
728 uint64_t helper_subg (uint64_t a
, uint64_t b
)
732 fa
= g_to_float64(a
);
733 fb
= g_to_float64(b
);
734 fr
= float64_sub(fa
, fb
, &FP_STATUS
);
735 return float64_to_g(fr
);
738 uint64_t helper_mulg (uint64_t a
, uint64_t b
)
742 fa
= g_to_float64(a
);
743 fb
= g_to_float64(b
);
744 fr
= float64_mul(fa
, fb
, &FP_STATUS
);
745 return float64_to_g(fr
);
748 uint64_t helper_divg (uint64_t a
, uint64_t b
)
752 fa
= g_to_float64(a
);
753 fb
= g_to_float64(b
);
754 fr
= float64_div(fa
, fb
, &FP_STATUS
);
755 return float64_to_g(fr
);
758 uint64_t helper_sqrtg (uint64_t a
)
762 fa
= g_to_float64(a
);
763 fr
= float64_sqrt(fa
, &FP_STATUS
);
764 return float64_to_g(fr
);
768 /* S floating (single) */
770 /* Taken from linux/arch/alpha/kernel/traps.c, s_mem_to_reg. */
771 static inline uint64_t float32_to_s_int(uint32_t fi
)
773 uint32_t frac
= fi
& 0x7fffff;
774 uint32_t sign
= fi
>> 31;
775 uint32_t exp_msb
= (fi
>> 30) & 1;
776 uint32_t exp_low
= (fi
>> 23) & 0x7f;
779 exp
= (exp_msb
<< 10) | exp_low
;
788 return (((uint64_t)sign
<< 63)
789 | ((uint64_t)exp
<< 52)
790 | ((uint64_t)frac
<< 29));
793 static inline uint64_t float32_to_s(float32 fa
)
797 return float32_to_s_int(a
.l
);
800 static inline uint32_t s_to_float32_int(uint64_t a
)
802 return ((a
>> 32) & 0xc0000000) | ((a
>> 29) & 0x3fffffff);
805 static inline float32
s_to_float32(uint64_t a
)
808 r
.l
= s_to_float32_int(a
);
812 uint32_t helper_s_to_memory (uint64_t a
)
814 return s_to_float32_int(a
);
817 uint64_t helper_memory_to_s (uint32_t a
)
819 return float32_to_s_int(a
);
822 uint64_t helper_adds (uint64_t a
, uint64_t b
)
826 fa
= s_to_float32(a
);
827 fb
= s_to_float32(b
);
828 fr
= float32_add(fa
, fb
, &FP_STATUS
);
829 return float32_to_s(fr
);
832 uint64_t helper_subs (uint64_t a
, uint64_t b
)
836 fa
= s_to_float32(a
);
837 fb
= s_to_float32(b
);
838 fr
= float32_sub(fa
, fb
, &FP_STATUS
);
839 return float32_to_s(fr
);
842 uint64_t helper_muls (uint64_t a
, uint64_t b
)
846 fa
= s_to_float32(a
);
847 fb
= s_to_float32(b
);
848 fr
= float32_mul(fa
, fb
, &FP_STATUS
);
849 return float32_to_s(fr
);
852 uint64_t helper_divs (uint64_t a
, uint64_t b
)
856 fa
= s_to_float32(a
);
857 fb
= s_to_float32(b
);
858 fr
= float32_div(fa
, fb
, &FP_STATUS
);
859 return float32_to_s(fr
);
862 uint64_t helper_sqrts (uint64_t a
)
866 fa
= s_to_float32(a
);
867 fr
= float32_sqrt(fa
, &FP_STATUS
);
868 return float32_to_s(fr
);
872 /* T floating (double) */
873 static inline float64
t_to_float64(uint64_t a
)
875 /* Memory format is the same as float64 */
881 static inline uint64_t float64_to_t(float64 fa
)
883 /* Memory format is the same as float64 */
889 uint64_t helper_addt (uint64_t a
, uint64_t b
)
893 fa
= t_to_float64(a
);
894 fb
= t_to_float64(b
);
895 fr
= float64_add(fa
, fb
, &FP_STATUS
);
896 return float64_to_t(fr
);
899 uint64_t helper_subt (uint64_t a
, uint64_t b
)
903 fa
= t_to_float64(a
);
904 fb
= t_to_float64(b
);
905 fr
= float64_sub(fa
, fb
, &FP_STATUS
);
906 return float64_to_t(fr
);
909 uint64_t helper_mult (uint64_t a
, uint64_t b
)
913 fa
= t_to_float64(a
);
914 fb
= t_to_float64(b
);
915 fr
= float64_mul(fa
, fb
, &FP_STATUS
);
916 return float64_to_t(fr
);
919 uint64_t helper_divt (uint64_t a
, uint64_t b
)
923 fa
= t_to_float64(a
);
924 fb
= t_to_float64(b
);
925 fr
= float64_div(fa
, fb
, &FP_STATUS
);
926 return float64_to_t(fr
);
929 uint64_t helper_sqrtt (uint64_t a
)
933 fa
= t_to_float64(a
);
934 fr
= float64_sqrt(fa
, &FP_STATUS
);
935 return float64_to_t(fr
);
939 uint64_t helper_cmptun (uint64_t a
, uint64_t b
)
943 fa
= t_to_float64(a
);
944 fb
= t_to_float64(b
);
946 if (float64_unordered_quiet(fa
, fb
, &FP_STATUS
)) {
947 return 0x4000000000000000ULL
;
953 uint64_t helper_cmpteq(uint64_t a
, uint64_t b
)
957 fa
= t_to_float64(a
);
958 fb
= t_to_float64(b
);
960 if (float64_eq_quiet(fa
, fb
, &FP_STATUS
))
961 return 0x4000000000000000ULL
;
966 uint64_t helper_cmptle(uint64_t a
, uint64_t b
)
970 fa
= t_to_float64(a
);
971 fb
= t_to_float64(b
);
973 if (float64_le(fa
, fb
, &FP_STATUS
))
974 return 0x4000000000000000ULL
;
979 uint64_t helper_cmptlt(uint64_t a
, uint64_t b
)
983 fa
= t_to_float64(a
);
984 fb
= t_to_float64(b
);
986 if (float64_lt(fa
, fb
, &FP_STATUS
))
987 return 0x4000000000000000ULL
;
992 uint64_t helper_cmpgeq(uint64_t a
, uint64_t b
)
996 fa
= g_to_float64(a
);
997 fb
= g_to_float64(b
);
999 if (float64_eq_quiet(fa
, fb
, &FP_STATUS
))
1000 return 0x4000000000000000ULL
;
1005 uint64_t helper_cmpgle(uint64_t a
, uint64_t b
)
1009 fa
= g_to_float64(a
);
1010 fb
= g_to_float64(b
);
1012 if (float64_le(fa
, fb
, &FP_STATUS
))
1013 return 0x4000000000000000ULL
;
1018 uint64_t helper_cmpglt(uint64_t a
, uint64_t b
)
1022 fa
= g_to_float64(a
);
1023 fb
= g_to_float64(b
);
1025 if (float64_lt(fa
, fb
, &FP_STATUS
))
1026 return 0x4000000000000000ULL
;
1031 /* Floating point format conversion */
1032 uint64_t helper_cvtts (uint64_t a
)
1037 fa
= t_to_float64(a
);
1038 fr
= float64_to_float32(fa
, &FP_STATUS
);
1039 return float32_to_s(fr
);
1042 uint64_t helper_cvtst (uint64_t a
)
1047 fa
= s_to_float32(a
);
1048 fr
= float32_to_float64(fa
, &FP_STATUS
);
1049 return float64_to_t(fr
);
1052 uint64_t helper_cvtqs (uint64_t a
)
1054 float32 fr
= int64_to_float32(a
, &FP_STATUS
);
1055 return float32_to_s(fr
);
1058 /* Implement float64 to uint64 conversion without saturation -- we must
1059 supply the truncated result. This behaviour is used by the compiler
1060 to get unsigned conversion for free with the same instruction.
1062 The VI flag is set when overflow or inexact exceptions should be raised. */
1064 static inline uint64_t helper_cvttq_internal(uint64_t a
, int roundmode
, int VI
)
1066 uint64_t frac
, ret
= 0;
1067 uint32_t exp
, sign
, exc
= 0;
1071 exp
= (uint32_t)(a
>> 52) & 0x7ff;
1072 frac
= a
& 0xfffffffffffffull
;
1075 if (unlikely(frac
!= 0)) {
1078 } else if (exp
== 0x7ff) {
1079 exc
= (frac
? float_flag_invalid
: VI
? float_flag_overflow
: 0);
1081 /* Restore implicit bit. */
1082 frac
|= 0x10000000000000ull
;
1084 shift
= exp
- 1023 - 52;
1086 /* In this case the number is so large that we must shift
1087 the fraction left. There is no rounding to do. */
1089 ret
= frac
<< shift
;
1090 if (VI
&& (ret
>> shift
) != frac
) {
1091 exc
= float_flag_overflow
;
1097 /* In this case the number is smaller than the fraction as
1098 represented by the 52 bit number. Here we must think
1099 about rounding the result. Handle this by shifting the
1100 fractional part of the number into the high bits of ROUND.
1101 This will let us efficiently handle round-to-nearest. */
1104 ret
= frac
>> shift
;
1105 round
= frac
<< (64 - shift
);
1107 /* The exponent is so small we shift out everything.
1108 Leave a sticky bit for proper rounding below. */
1114 exc
= (VI
? float_flag_inexact
: 0);
1115 switch (roundmode
) {
1116 case float_round_nearest_even
:
1117 if (round
== (1ull << 63)) {
1118 /* Fraction is exactly 0.5; round to even. */
1120 } else if (round
> (1ull << 63)) {
1124 case float_round_to_zero
:
1126 case float_round_up
:
1129 case float_round_down
:
1139 if (unlikely(exc
)) {
1140 float_raise(exc
, &FP_STATUS
);
1146 uint64_t helper_cvttq(uint64_t a
)
1148 return helper_cvttq_internal(a
, FP_STATUS
.float_rounding_mode
, 1);
1151 uint64_t helper_cvttq_c(uint64_t a
)
1153 return helper_cvttq_internal(a
, float_round_to_zero
, 0);
1156 uint64_t helper_cvttq_svic(uint64_t a
)
1158 return helper_cvttq_internal(a
, float_round_to_zero
, 1);
1161 uint64_t helper_cvtqt (uint64_t a
)
1163 float64 fr
= int64_to_float64(a
, &FP_STATUS
);
1164 return float64_to_t(fr
);
1167 uint64_t helper_cvtqf (uint64_t a
)
1169 float32 fr
= int64_to_float32(a
, &FP_STATUS
);
1170 return float32_to_f(fr
);
1173 uint64_t helper_cvtgf (uint64_t a
)
1178 fa
= g_to_float64(a
);
1179 fr
= float64_to_float32(fa
, &FP_STATUS
);
1180 return float32_to_f(fr
);
1183 uint64_t helper_cvtgq (uint64_t a
)
1185 float64 fa
= g_to_float64(a
);
1186 return float64_to_int64_round_to_zero(fa
, &FP_STATUS
);
1189 uint64_t helper_cvtqg (uint64_t a
)
1192 fr
= int64_to_float64(a
, &FP_STATUS
);
1193 return float64_to_g(fr
);
1196 /* PALcode support special instructions */
1197 #if !defined (CONFIG_USER_ONLY)
1198 void helper_hw_ret (uint64_t a
)
1202 env
->lock_addr
= -1;
1205 swap_shadow_regs(env
);
1209 void helper_tbia(void)
1214 void helper_tbis(uint64_t p
)
1216 tlb_flush_page(env
, p
);
1220 /*****************************************************************************/
1221 /* Softmmu support */
1222 #if !defined (CONFIG_USER_ONLY)
1223 uint64_t helper_ldl_phys(uint64_t p
)
1225 return (int32_t)ldl_phys(p
);
1228 uint64_t helper_ldq_phys(uint64_t p
)
1233 uint64_t helper_ldl_l_phys(uint64_t p
)
1236 return env
->lock_value
= (int32_t)ldl_phys(p
);
1239 uint64_t helper_ldq_l_phys(uint64_t p
)
1242 return env
->lock_value
= ldl_phys(p
);
1245 void helper_stl_phys(uint64_t p
, uint64_t v
)
1250 void helper_stq_phys(uint64_t p
, uint64_t v
)
1255 uint64_t helper_stl_c_phys(uint64_t p
, uint64_t v
)
1259 if (p
== env
->lock_addr
) {
1260 int32_t old
= ldl_phys(p
);
1261 if (old
== (int32_t)env
->lock_value
) {
1266 env
->lock_addr
= -1;
1271 uint64_t helper_stq_c_phys(uint64_t p
, uint64_t v
)
1275 if (p
== env
->lock_addr
) {
1276 uint64_t old
= ldq_phys(p
);
1277 if (old
== env
->lock_value
) {
1282 env
->lock_addr
= -1;
1287 static void QEMU_NORETURN
do_unaligned_access(target_ulong addr
, int is_write
,
1288 int is_user
, void *retaddr
)
1293 do_restore_state(retaddr
);
1296 insn
= ldl_code(pc
);
1298 env
->trap_arg0
= addr
;
1299 env
->trap_arg1
= insn
>> 26; /* opcode */
1300 env
->trap_arg2
= (insn
>> 21) & 31; /* dest regno */
1301 helper_excp(EXCP_UNALIGN
, 0);
1304 void QEMU_NORETURN
do_unassigned_access(target_phys_addr_t addr
, int is_write
,
1305 int is_exec
, int unused
, int size
)
1307 env
->trap_arg0
= addr
;
1308 env
->trap_arg1
= is_write
;
1309 dynamic_excp(EXCP_MCHK
, 0);
1312 #define MMUSUFFIX _mmu
1313 #define ALIGNED_ONLY
1316 #include "softmmu_template.h"
1319 #include "softmmu_template.h"
1322 #include "softmmu_template.h"
1325 #include "softmmu_template.h"
1327 /* try to fill the TLB and return an exception if error. If retaddr is
1328 NULL, it means that the function was called in C code (i.e. not
1329 from generated code or from helper.c) */
1330 /* XXX: fix it to restore all registers */
1331 void tlb_fill (target_ulong addr
, int is_write
, int mmu_idx
, void *retaddr
)
1333 CPUState
*saved_env
;
1336 /* XXX: hack to restore env in all cases, even if not called from
1339 env
= cpu_single_env
;
1340 ret
= cpu_alpha_handle_mmu_fault(env
, addr
, is_write
, mmu_idx
, 1);
1341 if (unlikely(ret
!= 0)) {
1342 do_restore_state(retaddr
);
1343 /* Exception index and error code are already set */