cocoa: Provide central qemu_main() prototype
[qemu/opensuse.git] / target-alpha / op_helper.c
blobd33271958fe2295ff38e4f20076eb1294cc756a1
1 /*
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/>.
20 #include "exec.h"
21 #include "host-utils.h"
22 #include "softfloat.h"
23 #include "helper.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;
35 cpu_loop_exit();
38 static void do_restore_state(void *retaddr)
40 unsigned long pc = (unsigned long)retaddr;
42 if (pc) {
43 TranslationBlock *tb = tb_find_pc(pc);
44 if (tb) {
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());
56 cpu_loop_exit();
59 static void QEMU_NORETURN arith_excp(int exc, uint64_t mask)
61 env->trap_arg0 = exc;
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));
74 #else
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();
78 #endif
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)
93 uint64_t tmp = op1;
94 op1 += op2;
95 if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) {
96 arith_excp(EXC_M_IOV, 0);
98 return op1;
101 uint64_t helper_addlv (uint64_t op1, uint64_t op2)
103 uint64_t tmp = op1;
104 op1 = (uint32_t)(op1 + op2);
105 if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) {
106 arith_excp(EXC_M_IOV, 0);
108 return op1;
111 uint64_t helper_subqv (uint64_t op1, uint64_t op2)
113 uint64_t res;
114 res = op1 - op2;
115 if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) {
116 arith_excp(EXC_M_IOV, 0);
118 return res;
121 uint64_t helper_sublv (uint64_t op1, uint64_t op2)
123 uint32_t res;
124 res = op1 - op2;
125 if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) {
126 arith_excp(EXC_M_IOV, 0);
128 return res;
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)
143 uint64_t tl, th;
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);
150 return tl;
153 uint64_t helper_umulh (uint64_t op1, uint64_t op2)
155 uint64_t tl, th;
157 mulu64(&tl, &th, op1, op2);
158 return th;
161 uint64_t helper_ctpop (uint64_t arg)
163 return ctpop64(arg);
166 uint64_t helper_ctlz (uint64_t arg)
168 return clz64(arg);
171 uint64_t helper_cttz (uint64_t arg)
173 return ctz64(arg);
176 static inline uint64_t byte_zap(uint64_t op, uint8_t mskb)
178 uint64_t mask;
180 mask = 0;
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;
190 return op & ~mask;
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;
206 int i;
208 res = 0;
209 for (i = 0; i < 8; i++) {
210 opa = op1 >> (i * 8);
211 opb = op2 >> (i * 8);
212 if (opa >= opb)
213 res |= 1 << i;
215 return res;
218 uint64_t helper_minub8 (uint64_t op1, uint64_t op2)
220 uint64_t res = 0;
221 uint8_t opa, opb, opr;
222 int i;
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);
230 return res;
233 uint64_t helper_minsb8 (uint64_t op1, uint64_t op2)
235 uint64_t res = 0;
236 int8_t opa, opb;
237 uint8_t opr;
238 int i;
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);
246 return res;
249 uint64_t helper_minuw4 (uint64_t op1, uint64_t op2)
251 uint64_t res = 0;
252 uint16_t opa, opb, opr;
253 int i;
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);
261 return res;
264 uint64_t helper_minsw4 (uint64_t op1, uint64_t op2)
266 uint64_t res = 0;
267 int16_t opa, opb;
268 uint16_t opr;
269 int i;
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);
277 return res;
280 uint64_t helper_maxub8 (uint64_t op1, uint64_t op2)
282 uint64_t res = 0;
283 uint8_t opa, opb, opr;
284 int i;
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);
292 return res;
295 uint64_t helper_maxsb8 (uint64_t op1, uint64_t op2)
297 uint64_t res = 0;
298 int8_t opa, opb;
299 uint8_t opr;
300 int i;
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);
308 return res;
311 uint64_t helper_maxuw4 (uint64_t op1, uint64_t op2)
313 uint64_t res = 0;
314 uint16_t opa, opb, opr;
315 int i;
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);
323 return res;
326 uint64_t helper_maxsw4 (uint64_t op1, uint64_t op2)
328 uint64_t res = 0;
329 int16_t opa, opb;
330 uint16_t opr;
331 int i;
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);
339 return res;
342 uint64_t helper_perr (uint64_t op1, uint64_t op2)
344 uint64_t res = 0;
345 uint8_t opa, opb, opr;
346 int i;
348 for (i = 0; i < 8; ++i) {
349 opa = op1 >> (i * 8);
350 opb = op2 >> (i * 8);
351 if (opa >= opb)
352 opr = opa - opb;
353 else
354 opr = opb - opa;
355 res += opr;
357 return res;
360 uint64_t helper_pklb (uint64_t op1)
362 return (op1 & 0xff) | ((op1 >> 24) & 0xff00);
365 uint64_t helper_pkwb (uint64_t op1)
367 return ((op1 & 0xff)
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)
380 return ((op1 & 0xff)
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
410 doesn't apply. */
411 void helper_fp_exc_raise(uint32_t exc, uint32_t regno)
413 if (exc) {
414 uint32_t hw_exc = 0;
416 if (exc & float_flag_invalid) {
417 hw_exc |= EXC_M_INV;
419 if (exc & float_flag_divbyzero) {
420 hw_exc |= EXC_M_DZE;
422 if (exc & float_flag_overflow) {
423 hw_exc |= EXC_M_FOV;
425 if (exc & float_flag_underflow) {
426 hw_exc |= EXC_M_UNF;
428 if (exc & float_flag_inexact) {
429 hw_exc |= EXC_M_INE;
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)
439 if (exc) {
440 env->fpcr_exc_status |= exc;
442 exc &= ~env->fpcr_exc_mask;
443 if (exc) {
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;
456 if (exp == 0) {
457 if (frac != 0) {
458 /* If DNZ is set flush denormals to zero on input. */
459 if (env->fpcr_dnz) {
460 val &= 1ull << 63;
461 } else {
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);
472 return val;
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;
481 if (exp == 0) {
482 if (frac != 0) {
483 /* If DNZ is set flush denormals to zero on input. */
484 if (env->fpcr_dnz) {
485 val &= 1ull << 63;
486 } else {
487 arith_excp(EXC_M_UNF, 0);
490 } else if (exp == 0x7ff && frac) {
491 /* NaN. */
492 arith_excp(EXC_M_INV, 0);
494 return val;
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)
502 if (env->fpcr_dnz) {
503 uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
504 if (exp == 0) {
505 val &= 1ull << 63;
508 return val;
511 /* F floating (VAX) */
512 static inline uint64_t float32_to_f(float32 fa)
514 uint64_t r, exp, mant, sig;
515 CPU_FloatU a;
517 a.f = fa;
518 sig = ((uint64_t)a.l & 0x80000000) << 32;
519 exp = (a.l >> 23) & 0xff;
520 mant = ((uint64_t)a.l & 0x007fffff) << 29;
522 if (exp == 255) {
523 /* NaN or infinity */
524 r = 1; /* VAX dirty zero */
525 } else if (exp == 0) {
526 if (mant == 0) {
527 /* Zero */
528 r = 0;
529 } else {
530 /* Denormalized */
531 r = sig | ((exp + 1) << 52) | mant;
533 } else {
534 if (exp >= 253) {
535 /* Overflow */
536 r = 1; /* VAX dirty zero */
537 } else {
538 r = sig | ((exp + 2) << 52);
542 return r;
545 static inline float32 f_to_float32(uint64_t a)
547 uint32_t exp, mant_sig;
548 CPU_FloatU r;
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);
558 if (exp < 3) {
559 /* Underflow */
560 r.l = 0;
561 } else {
562 r.l = ((exp - 2) << 23) | mant_sig;
565 return r.f;
568 uint32_t helper_f_to_memory (uint64_t a)
570 uint32_t r;
571 r = (a & 0x00001fffe0000000ull) >> 13;
572 r |= (a & 0x07ffe00000000000ull) >> 45;
573 r |= (a & 0xc000000000000000ull) >> 48;
574 return r;
577 uint64_t helper_memory_to_f (uint32_t a)
579 uint64_t r;
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))
584 r |= 0x7ll << 59;
585 return r;
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)
593 float32 fa, fb, fr;
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)
603 float32 fa, fb, fr;
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)
613 float32 fa, fb, fr;
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)
623 float32 fa, fb, fr;
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)
633 float32 ft, fr;
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;
645 CPU_DoubleU a;
647 a.d = fa;
648 sig = a.ll & 0x8000000000000000ull;
649 exp = (a.ll >> 52) & 0x7ff;
650 mant = a.ll & 0x000fffffffffffffull;
652 if (exp == 2047) {
653 /* NaN or infinity */
654 r = 1; /* VAX dirty zero */
655 } else if (exp == 0) {
656 if (mant == 0) {
657 /* Zero */
658 r = 0;
659 } else {
660 /* Denormalized */
661 r = sig | ((exp + 1) << 52) | mant;
663 } else {
664 if (exp >= 2045) {
665 /* Overflow */
666 r = 1; /* VAX dirty zero */
667 } else {
668 r = sig | ((exp + 2) << 52);
672 return r;
675 static inline float64 g_to_float64(uint64_t a)
677 uint64_t exp, mant_sig;
678 CPU_DoubleU r;
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);
688 if (exp < 3) {
689 /* Underflow */
690 r.ll = 0;
691 } else {
692 r.ll = ((exp - 2) << 52) | mant_sig;
695 return r.d;
698 uint64_t helper_g_to_memory (uint64_t a)
700 uint64_t r;
701 r = (a & 0x000000000000ffffull) << 48;
702 r |= (a & 0x00000000ffff0000ull) << 16;
703 r |= (a & 0x0000ffff00000000ull) >> 16;
704 r |= (a & 0xffff000000000000ull) >> 48;
705 return r;
708 uint64_t helper_memory_to_g (uint64_t a)
710 uint64_t r;
711 r = (a & 0x000000000000ffffull) << 48;
712 r |= (a & 0x00000000ffff0000ull) << 16;
713 r |= (a & 0x0000ffff00000000ull) >> 16;
714 r |= (a & 0xffff000000000000ull) >> 48;
715 return r;
718 uint64_t helper_addg (uint64_t a, uint64_t b)
720 float64 fa, fb, fr;
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)
730 float64 fa, fb, fr;
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)
740 float64 fa, fb, fr;
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)
750 float64 fa, fb, fr;
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)
760 float64 fa, fr;
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;
777 uint32_t exp;
779 exp = (exp_msb << 10) | exp_low;
780 if (exp_msb) {
781 if (exp_low == 0x7f)
782 exp = 0x7ff;
783 } else {
784 if (exp_low != 0x00)
785 exp |= 0x380;
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)
795 CPU_FloatU a;
796 a.f = 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)
807 CPU_FloatU r;
808 r.l = s_to_float32_int(a);
809 return r.f;
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)
824 float32 fa, fb, fr;
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)
834 float32 fa, fb, fr;
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)
844 float32 fa, fb, fr;
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)
854 float32 fa, fb, fr;
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)
864 float32 fa, fr;
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 */
876 CPU_DoubleU r;
877 r.ll = a;
878 return r.d;
881 static inline uint64_t float64_to_t(float64 fa)
883 /* Memory format is the same as float64 */
884 CPU_DoubleU r;
885 r.d = fa;
886 return r.ll;
889 uint64_t helper_addt (uint64_t a, uint64_t b)
891 float64 fa, fb, fr;
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)
901 float64 fa, fb, fr;
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)
911 float64 fa, fb, fr;
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)
921 float64 fa, fb, fr;
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)
931 float64 fa, fr;
933 fa = t_to_float64(a);
934 fr = float64_sqrt(fa, &FP_STATUS);
935 return float64_to_t(fr);
938 /* Comparisons */
939 uint64_t helper_cmptun (uint64_t a, uint64_t b)
941 float64 fa, fb;
943 fa = t_to_float64(a);
944 fb = t_to_float64(b);
946 if (float64_unordered_quiet(fa, fb, &FP_STATUS)) {
947 return 0x4000000000000000ULL;
948 } else {
949 return 0;
953 uint64_t helper_cmpteq(uint64_t a, uint64_t b)
955 float64 fa, fb;
957 fa = t_to_float64(a);
958 fb = t_to_float64(b);
960 if (float64_eq_quiet(fa, fb, &FP_STATUS))
961 return 0x4000000000000000ULL;
962 else
963 return 0;
966 uint64_t helper_cmptle(uint64_t a, uint64_t b)
968 float64 fa, fb;
970 fa = t_to_float64(a);
971 fb = t_to_float64(b);
973 if (float64_le(fa, fb, &FP_STATUS))
974 return 0x4000000000000000ULL;
975 else
976 return 0;
979 uint64_t helper_cmptlt(uint64_t a, uint64_t b)
981 float64 fa, fb;
983 fa = t_to_float64(a);
984 fb = t_to_float64(b);
986 if (float64_lt(fa, fb, &FP_STATUS))
987 return 0x4000000000000000ULL;
988 else
989 return 0;
992 uint64_t helper_cmpgeq(uint64_t a, uint64_t b)
994 float64 fa, fb;
996 fa = g_to_float64(a);
997 fb = g_to_float64(b);
999 if (float64_eq_quiet(fa, fb, &FP_STATUS))
1000 return 0x4000000000000000ULL;
1001 else
1002 return 0;
1005 uint64_t helper_cmpgle(uint64_t a, uint64_t b)
1007 float64 fa, fb;
1009 fa = g_to_float64(a);
1010 fb = g_to_float64(b);
1012 if (float64_le(fa, fb, &FP_STATUS))
1013 return 0x4000000000000000ULL;
1014 else
1015 return 0;
1018 uint64_t helper_cmpglt(uint64_t a, uint64_t b)
1020 float64 fa, fb;
1022 fa = g_to_float64(a);
1023 fb = g_to_float64(b);
1025 if (float64_lt(fa, fb, &FP_STATUS))
1026 return 0x4000000000000000ULL;
1027 else
1028 return 0;
1031 /* Floating point format conversion */
1032 uint64_t helper_cvtts (uint64_t a)
1034 float64 fa;
1035 float32 fr;
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)
1044 float32 fa;
1045 float64 fr;
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;
1068 int shift;
1070 sign = (a >> 63);
1071 exp = (uint32_t)(a >> 52) & 0x7ff;
1072 frac = a & 0xfffffffffffffull;
1074 if (exp == 0) {
1075 if (unlikely(frac != 0)) {
1076 goto do_underflow;
1078 } else if (exp == 0x7ff) {
1079 exc = (frac ? float_flag_invalid : VI ? float_flag_overflow : 0);
1080 } else {
1081 /* Restore implicit bit. */
1082 frac |= 0x10000000000000ull;
1084 shift = exp - 1023 - 52;
1085 if (shift >= 0) {
1086 /* In this case the number is so large that we must shift
1087 the fraction left. There is no rounding to do. */
1088 if (shift < 63) {
1089 ret = frac << shift;
1090 if (VI && (ret >> shift) != frac) {
1091 exc = float_flag_overflow;
1094 } else {
1095 uint64_t round;
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. */
1102 shift = -shift;
1103 if (shift < 63) {
1104 ret = frac >> shift;
1105 round = frac << (64 - shift);
1106 } else {
1107 /* The exponent is so small we shift out everything.
1108 Leave a sticky bit for proper rounding below. */
1109 do_underflow:
1110 round = 1;
1113 if (round) {
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. */
1119 ret += (ret & 1);
1120 } else if (round > (1ull << 63)) {
1121 ret += 1;
1123 break;
1124 case float_round_to_zero:
1125 break;
1126 case float_round_up:
1127 ret += 1 - sign;
1128 break;
1129 case float_round_down:
1130 ret += sign;
1131 break;
1135 if (sign) {
1136 ret = -ret;
1139 if (unlikely(exc)) {
1140 float_raise(exc, &FP_STATUS);
1143 return ret;
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)
1175 float64 fa;
1176 float32 fr;
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)
1191 float64 fr;
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)
1200 env->pc = a & ~3;
1201 env->intr_flag = 0;
1202 env->lock_addr = -1;
1203 if ((a & 1) == 0) {
1204 env->pal_mode = 0;
1205 swap_shadow_regs(env);
1209 void helper_tbia(void)
1211 tlb_flush(env, 1);
1214 void helper_tbis(uint64_t p)
1216 tlb_flush_page(env, p);
1218 #endif
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)
1230 return ldq_phys(p);
1233 uint64_t helper_ldl_l_phys(uint64_t p)
1235 env->lock_addr = p;
1236 return env->lock_value = (int32_t)ldl_phys(p);
1239 uint64_t helper_ldq_l_phys(uint64_t p)
1241 env->lock_addr = p;
1242 return env->lock_value = ldl_phys(p);
1245 void helper_stl_phys(uint64_t p, uint64_t v)
1247 stl_phys(p, v);
1250 void helper_stq_phys(uint64_t p, uint64_t v)
1252 stq_phys(p, v);
1255 uint64_t helper_stl_c_phys(uint64_t p, uint64_t v)
1257 uint64_t ret = 0;
1259 if (p == env->lock_addr) {
1260 int32_t old = ldl_phys(p);
1261 if (old == (int32_t)env->lock_value) {
1262 stl_phys(p, v);
1263 ret = 1;
1266 env->lock_addr = -1;
1268 return ret;
1271 uint64_t helper_stq_c_phys(uint64_t p, uint64_t v)
1273 uint64_t ret = 0;
1275 if (p == env->lock_addr) {
1276 uint64_t old = ldq_phys(p);
1277 if (old == env->lock_value) {
1278 stq_phys(p, v);
1279 ret = 1;
1282 env->lock_addr = -1;
1284 return ret;
1287 static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write,
1288 int is_user, void *retaddr)
1290 uint64_t pc;
1291 uint32_t insn;
1293 do_restore_state(retaddr);
1295 pc = env->pc;
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
1315 #define SHIFT 0
1316 #include "softmmu_template.h"
1318 #define SHIFT 1
1319 #include "softmmu_template.h"
1321 #define SHIFT 2
1322 #include "softmmu_template.h"
1324 #define SHIFT 3
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;
1334 int ret;
1336 /* XXX: hack to restore env in all cases, even if not called from
1337 generated code */
1338 saved_env = env;
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 */
1344 cpu_loop_exit();
1346 env = saved_env;
1348 #endif