]> git.proxmox.com Git - qemu.git/blame - target-alpha/fpu_helper.c
target-alpha: Move floating-point helpers to fpu_helper.c.
[qemu.git] / target-alpha / fpu_helper.c
CommitLineData
4a58aedf
RH
1/*
2 * Helpers for floating point instructions.
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, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "cpu.h"
21#include "helper.h"
22#include "softfloat.h"
23
24#define FP_STATUS (env->fp_status)
25
26
27void helper_setroundmode(CPUAlphaState *env, uint32_t val)
28{
29 set_float_rounding_mode(val, &FP_STATUS);
30}
31
32void helper_setflushzero(CPUAlphaState *env, uint32_t val)
33{
34 set_flush_to_zero(val, &FP_STATUS);
35}
36
37void helper_fp_exc_clear(CPUAlphaState *env)
38{
39 set_float_exception_flags(0, &FP_STATUS);
40}
41
42uint32_t helper_fp_exc_get(CPUAlphaState *env)
43{
44 return get_float_exception_flags(&FP_STATUS);
45}
46
47static inline void inline_fp_exc_raise(CPUAlphaState *env, void *retaddr,
48 uint32_t exc, uint32_t regno)
49{
50 if (exc) {
51 uint32_t hw_exc = 0;
52
53 if (exc & float_flag_invalid) {
54 hw_exc |= EXC_M_INV;
55 }
56 if (exc & float_flag_divbyzero) {
57 hw_exc |= EXC_M_DZE;
58 }
59 if (exc & float_flag_overflow) {
60 hw_exc |= EXC_M_FOV;
61 }
62 if (exc & float_flag_underflow) {
63 hw_exc |= EXC_M_UNF;
64 }
65 if (exc & float_flag_inexact) {
66 hw_exc |= EXC_M_INE;
67 }
68
69 arith_excp(env, retaddr, hw_exc, 1ull << regno);
70 }
71}
72
73/* Raise exceptions for ieee fp insns without software completion.
74 In that case there are no exceptions that don't trap; the mask
75 doesn't apply. */
76void helper_fp_exc_raise(CPUAlphaState *env, uint32_t exc, uint32_t regno)
77{
78 inline_fp_exc_raise(env, GETPC(), exc, regno);
79}
80
81/* Raise exceptions for ieee fp insns with software completion. */
82void helper_fp_exc_raise_s(CPUAlphaState *env, uint32_t exc, uint32_t regno)
83{
84 if (exc) {
85 env->fpcr_exc_status |= exc;
86 exc &= ~env->fpcr_exc_mask;
87 inline_fp_exc_raise(env, GETPC(), exc, regno);
88 }
89}
90
91/* Input remapping without software completion. Handle denormal-map-to-zero
92 and trap for all other non-finite numbers. */
93uint64_t helper_ieee_input(CPUAlphaState *env, uint64_t val)
94{
95 uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
96 uint64_t frac = val & 0xfffffffffffffull;
97
98 if (exp == 0) {
99 if (frac != 0) {
100 /* If DNZ is set flush denormals to zero on input. */
101 if (env->fpcr_dnz) {
102 val &= 1ull << 63;
103 } else {
104 arith_excp(env, GETPC(), EXC_M_UNF, 0);
105 }
106 }
107 } else if (exp == 0x7ff) {
108 /* Infinity or NaN. */
109 /* ??? I'm not sure these exception bit flags are correct. I do
110 know that the Linux kernel, at least, doesn't rely on them and
111 just emulates the insn to figure out what exception to use. */
112 arith_excp(env, GETPC(), frac ? EXC_M_INV : EXC_M_FOV, 0);
113 }
114 return val;
115}
116
117/* Similar, but does not trap for infinities. Used for comparisons. */
118uint64_t helper_ieee_input_cmp(CPUAlphaState *env, uint64_t val)
119{
120 uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
121 uint64_t frac = val & 0xfffffffffffffull;
122
123 if (exp == 0) {
124 if (frac != 0) {
125 /* If DNZ is set flush denormals to zero on input. */
126 if (env->fpcr_dnz) {
127 val &= 1ull << 63;
128 } else {
129 arith_excp(env, GETPC(), EXC_M_UNF, 0);
130 }
131 }
132 } else if (exp == 0x7ff && frac) {
133 /* NaN. */
134 arith_excp(env, GETPC(), EXC_M_INV, 0);
135 }
136 return val;
137}
138
139/* Input remapping with software completion enabled. All we have to do
140 is handle denormal-map-to-zero; all other inputs get exceptions as
141 needed from the actual operation. */
142uint64_t helper_ieee_input_s(CPUAlphaState *env, uint64_t val)
143{
144 if (env->fpcr_dnz) {
145 uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
146 if (exp == 0) {
147 val &= 1ull << 63;
148 }
149 }
150 return val;
151}
152
153/* F floating (VAX) */
154static uint64_t float32_to_f(float32 fa)
155{
156 uint64_t r, exp, mant, sig;
157 CPU_FloatU a;
158
159 a.f = fa;
160 sig = ((uint64_t)a.l & 0x80000000) << 32;
161 exp = (a.l >> 23) & 0xff;
162 mant = ((uint64_t)a.l & 0x007fffff) << 29;
163
164 if (exp == 255) {
165 /* NaN or infinity */
166 r = 1; /* VAX dirty zero */
167 } else if (exp == 0) {
168 if (mant == 0) {
169 /* Zero */
170 r = 0;
171 } else {
172 /* Denormalized */
173 r = sig | ((exp + 1) << 52) | mant;
174 }
175 } else {
176 if (exp >= 253) {
177 /* Overflow */
178 r = 1; /* VAX dirty zero */
179 } else {
180 r = sig | ((exp + 2) << 52);
181 }
182 }
183
184 return r;
185}
186
187static float32 f_to_float32(CPUAlphaState *env, void *retaddr, uint64_t a)
188{
189 uint32_t exp, mant_sig;
190 CPU_FloatU r;
191
192 exp = ((a >> 55) & 0x80) | ((a >> 52) & 0x7f);
193 mant_sig = ((a >> 32) & 0x80000000) | ((a >> 29) & 0x007fffff);
194
195 if (unlikely(!exp && mant_sig)) {
196 /* Reserved operands / Dirty zero */
197 dynamic_excp(env, retaddr, EXCP_OPCDEC, 0);
198 }
199
200 if (exp < 3) {
201 /* Underflow */
202 r.l = 0;
203 } else {
204 r.l = ((exp - 2) << 23) | mant_sig;
205 }
206
207 return r.f;
208}
209
210uint32_t helper_f_to_memory(uint64_t a)
211{
212 uint32_t r;
213 r = (a & 0x00001fffe0000000ull) >> 13;
214 r |= (a & 0x07ffe00000000000ull) >> 45;
215 r |= (a & 0xc000000000000000ull) >> 48;
216 return r;
217}
218
219uint64_t helper_memory_to_f(uint32_t a)
220{
221 uint64_t r;
222 r = ((uint64_t)(a & 0x0000c000)) << 48;
223 r |= ((uint64_t)(a & 0x003fffff)) << 45;
224 r |= ((uint64_t)(a & 0xffff0000)) << 13;
225 if (!(a & 0x00004000)) {
226 r |= 0x7ll << 59;
227 }
228 return r;
229}
230
231/* ??? Emulating VAX arithmetic with IEEE arithmetic is wrong. We should
232 either implement VAX arithmetic properly or just signal invalid opcode. */
233
234uint64_t helper_addf(CPUAlphaState *env, uint64_t a, uint64_t b)
235{
236 float32 fa, fb, fr;
237
238 fa = f_to_float32(env, GETPC(), a);
239 fb = f_to_float32(env, GETPC(), b);
240 fr = float32_add(fa, fb, &FP_STATUS);
241 return float32_to_f(fr);
242}
243
244uint64_t helper_subf(CPUAlphaState *env, uint64_t a, uint64_t b)
245{
246 float32 fa, fb, fr;
247
248 fa = f_to_float32(env, GETPC(), a);
249 fb = f_to_float32(env, GETPC(), b);
250 fr = float32_sub(fa, fb, &FP_STATUS);
251 return float32_to_f(fr);
252}
253
254uint64_t helper_mulf(CPUAlphaState *env, uint64_t a, uint64_t b)
255{
256 float32 fa, fb, fr;
257
258 fa = f_to_float32(env, GETPC(), a);
259 fb = f_to_float32(env, GETPC(), b);
260 fr = float32_mul(fa, fb, &FP_STATUS);
261 return float32_to_f(fr);
262}
263
264uint64_t helper_divf(CPUAlphaState *env, uint64_t a, uint64_t b)
265{
266 float32 fa, fb, fr;
267
268 fa = f_to_float32(env, GETPC(), a);
269 fb = f_to_float32(env, GETPC(), b);
270 fr = float32_div(fa, fb, &FP_STATUS);
271 return float32_to_f(fr);
272}
273
274uint64_t helper_sqrtf(CPUAlphaState *env, uint64_t t)
275{
276 float32 ft, fr;
277
278 ft = f_to_float32(env, GETPC(), t);
279 fr = float32_sqrt(ft, &FP_STATUS);
280 return float32_to_f(fr);
281}
282
283
284/* G floating (VAX) */
285static uint64_t float64_to_g(float64 fa)
286{
287 uint64_t r, exp, mant, sig;
288 CPU_DoubleU a;
289
290 a.d = fa;
291 sig = a.ll & 0x8000000000000000ull;
292 exp = (a.ll >> 52) & 0x7ff;
293 mant = a.ll & 0x000fffffffffffffull;
294
295 if (exp == 2047) {
296 /* NaN or infinity */
297 r = 1; /* VAX dirty zero */
298 } else if (exp == 0) {
299 if (mant == 0) {
300 /* Zero */
301 r = 0;
302 } else {
303 /* Denormalized */
304 r = sig | ((exp + 1) << 52) | mant;
305 }
306 } else {
307 if (exp >= 2045) {
308 /* Overflow */
309 r = 1; /* VAX dirty zero */
310 } else {
311 r = sig | ((exp + 2) << 52);
312 }
313 }
314
315 return r;
316}
317
318static float64 g_to_float64(CPUAlphaState *env, void *retaddr, uint64_t a)
319{
320 uint64_t exp, mant_sig;
321 CPU_DoubleU r;
322
323 exp = (a >> 52) & 0x7ff;
324 mant_sig = a & 0x800fffffffffffffull;
325
326 if (!exp && mant_sig) {
327 /* Reserved operands / Dirty zero */
328 dynamic_excp(env, retaddr, EXCP_OPCDEC, 0);
329 }
330
331 if (exp < 3) {
332 /* Underflow */
333 r.ll = 0;
334 } else {
335 r.ll = ((exp - 2) << 52) | mant_sig;
336 }
337
338 return r.d;
339}
340
341uint64_t helper_g_to_memory(uint64_t a)
342{
343 uint64_t r;
344 r = (a & 0x000000000000ffffull) << 48;
345 r |= (a & 0x00000000ffff0000ull) << 16;
346 r |= (a & 0x0000ffff00000000ull) >> 16;
347 r |= (a & 0xffff000000000000ull) >> 48;
348 return r;
349}
350
351uint64_t helper_memory_to_g(uint64_t a)
352{
353 uint64_t r;
354 r = (a & 0x000000000000ffffull) << 48;
355 r |= (a & 0x00000000ffff0000ull) << 16;
356 r |= (a & 0x0000ffff00000000ull) >> 16;
357 r |= (a & 0xffff000000000000ull) >> 48;
358 return r;
359}
360
361uint64_t helper_addg(CPUAlphaState *env, uint64_t a, uint64_t b)
362{
363 float64 fa, fb, fr;
364
365 fa = g_to_float64(env, GETPC(), a);
366 fb = g_to_float64(env, GETPC(), b);
367 fr = float64_add(fa, fb, &FP_STATUS);
368 return float64_to_g(fr);
369}
370
371uint64_t helper_subg(CPUAlphaState *env, uint64_t a, uint64_t b)
372{
373 float64 fa, fb, fr;
374
375 fa = g_to_float64(env, GETPC(), a);
376 fb = g_to_float64(env, GETPC(), b);
377 fr = float64_sub(fa, fb, &FP_STATUS);
378 return float64_to_g(fr);
379}
380
381uint64_t helper_mulg(CPUAlphaState *env, uint64_t a, uint64_t b)
382{
383 float64 fa, fb, fr;
384
385 fa = g_to_float64(env, GETPC(), a);
386 fb = g_to_float64(env, GETPC(), b);
387 fr = float64_mul(fa, fb, &FP_STATUS);
388 return float64_to_g(fr);
389}
390
391uint64_t helper_divg(CPUAlphaState *env, uint64_t a, uint64_t b)
392{
393 float64 fa, fb, fr;
394
395 fa = g_to_float64(env, GETPC(), a);
396 fb = g_to_float64(env, GETPC(), b);
397 fr = float64_div(fa, fb, &FP_STATUS);
398 return float64_to_g(fr);
399}
400
401uint64_t helper_sqrtg(CPUAlphaState *env, uint64_t a)
402{
403 float64 fa, fr;
404
405 fa = g_to_float64(env, GETPC(), a);
406 fr = float64_sqrt(fa, &FP_STATUS);
407 return float64_to_g(fr);
408}
409
410
411/* S floating (single) */
412
413/* Taken from linux/arch/alpha/kernel/traps.c, s_mem_to_reg. */
414static inline uint64_t float32_to_s_int(uint32_t fi)
415{
416 uint32_t frac = fi & 0x7fffff;
417 uint32_t sign = fi >> 31;
418 uint32_t exp_msb = (fi >> 30) & 1;
419 uint32_t exp_low = (fi >> 23) & 0x7f;
420 uint32_t exp;
421
422 exp = (exp_msb << 10) | exp_low;
423 if (exp_msb) {
424 if (exp_low == 0x7f) {
425 exp = 0x7ff;
426 }
427 } else {
428 if (exp_low != 0x00) {
429 exp |= 0x380;
430 }
431 }
432
433 return (((uint64_t)sign << 63)
434 | ((uint64_t)exp << 52)
435 | ((uint64_t)frac << 29));
436}
437
438static inline uint64_t float32_to_s(float32 fa)
439{
440 CPU_FloatU a;
441 a.f = fa;
442 return float32_to_s_int(a.l);
443}
444
445static inline uint32_t s_to_float32_int(uint64_t a)
446{
447 return ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff);
448}
449
450static inline float32 s_to_float32(uint64_t a)
451{
452 CPU_FloatU r;
453 r.l = s_to_float32_int(a);
454 return r.f;
455}
456
457uint32_t helper_s_to_memory(uint64_t a)
458{
459 return s_to_float32_int(a);
460}
461
462uint64_t helper_memory_to_s(uint32_t a)
463{
464 return float32_to_s_int(a);
465}
466
467uint64_t helper_adds(CPUAlphaState *env, uint64_t a, uint64_t b)
468{
469 float32 fa, fb, fr;
470
471 fa = s_to_float32(a);
472 fb = s_to_float32(b);
473 fr = float32_add(fa, fb, &FP_STATUS);
474 return float32_to_s(fr);
475}
476
477uint64_t helper_subs(CPUAlphaState *env, uint64_t a, uint64_t b)
478{
479 float32 fa, fb, fr;
480
481 fa = s_to_float32(a);
482 fb = s_to_float32(b);
483 fr = float32_sub(fa, fb, &FP_STATUS);
484 return float32_to_s(fr);
485}
486
487uint64_t helper_muls(CPUAlphaState *env, uint64_t a, uint64_t b)
488{
489 float32 fa, fb, fr;
490
491 fa = s_to_float32(a);
492 fb = s_to_float32(b);
493 fr = float32_mul(fa, fb, &FP_STATUS);
494 return float32_to_s(fr);
495}
496
497uint64_t helper_divs(CPUAlphaState *env, uint64_t a, uint64_t b)
498{
499 float32 fa, fb, fr;
500
501 fa = s_to_float32(a);
502 fb = s_to_float32(b);
503 fr = float32_div(fa, fb, &FP_STATUS);
504 return float32_to_s(fr);
505}
506
507uint64_t helper_sqrts(CPUAlphaState *env, uint64_t a)
508{
509 float32 fa, fr;
510
511 fa = s_to_float32(a);
512 fr = float32_sqrt(fa, &FP_STATUS);
513 return float32_to_s(fr);
514}
515
516
517/* T floating (double) */
518static inline float64 t_to_float64(uint64_t a)
519{
520 /* Memory format is the same as float64 */
521 CPU_DoubleU r;
522 r.ll = a;
523 return r.d;
524}
525
526static inline uint64_t float64_to_t(float64 fa)
527{
528 /* Memory format is the same as float64 */
529 CPU_DoubleU r;
530 r.d = fa;
531 return r.ll;
532}
533
534uint64_t helper_addt(CPUAlphaState *env, uint64_t a, uint64_t b)
535{
536 float64 fa, fb, fr;
537
538 fa = t_to_float64(a);
539 fb = t_to_float64(b);
540 fr = float64_add(fa, fb, &FP_STATUS);
541 return float64_to_t(fr);
542}
543
544uint64_t helper_subt(CPUAlphaState *env, uint64_t a, uint64_t b)
545{
546 float64 fa, fb, fr;
547
548 fa = t_to_float64(a);
549 fb = t_to_float64(b);
550 fr = float64_sub(fa, fb, &FP_STATUS);
551 return float64_to_t(fr);
552}
553
554uint64_t helper_mult(CPUAlphaState *env, uint64_t a, uint64_t b)
555{
556 float64 fa, fb, fr;
557
558 fa = t_to_float64(a);
559 fb = t_to_float64(b);
560 fr = float64_mul(fa, fb, &FP_STATUS);
561 return float64_to_t(fr);
562}
563
564uint64_t helper_divt(CPUAlphaState *env, uint64_t a, uint64_t b)
565{
566 float64 fa, fb, fr;
567
568 fa = t_to_float64(a);
569 fb = t_to_float64(b);
570 fr = float64_div(fa, fb, &FP_STATUS);
571 return float64_to_t(fr);
572}
573
574uint64_t helper_sqrtt(CPUAlphaState *env, uint64_t a)
575{
576 float64 fa, fr;
577
578 fa = t_to_float64(a);
579 fr = float64_sqrt(fa, &FP_STATUS);
580 return float64_to_t(fr);
581}
582
583/* Comparisons */
584uint64_t helper_cmptun(CPUAlphaState *env, uint64_t a, uint64_t b)
585{
586 float64 fa, fb;
587
588 fa = t_to_float64(a);
589 fb = t_to_float64(b);
590
591 if (float64_unordered_quiet(fa, fb, &FP_STATUS)) {
592 return 0x4000000000000000ULL;
593 } else {
594 return 0;
595 }
596}
597
598uint64_t helper_cmpteq(CPUAlphaState *env, uint64_t a, uint64_t b)
599{
600 float64 fa, fb;
601
602 fa = t_to_float64(a);
603 fb = t_to_float64(b);
604
605 if (float64_eq_quiet(fa, fb, &FP_STATUS)) {
606 return 0x4000000000000000ULL;
607 } else {
608 return 0;
609 }
610}
611
612uint64_t helper_cmptle(CPUAlphaState *env, uint64_t a, uint64_t b)
613{
614 float64 fa, fb;
615
616 fa = t_to_float64(a);
617 fb = t_to_float64(b);
618
619 if (float64_le(fa, fb, &FP_STATUS)) {
620 return 0x4000000000000000ULL;
621 } else {
622 return 0;
623 }
624}
625
626uint64_t helper_cmptlt(CPUAlphaState *env, uint64_t a, uint64_t b)
627{
628 float64 fa, fb;
629
630 fa = t_to_float64(a);
631 fb = t_to_float64(b);
632
633 if (float64_lt(fa, fb, &FP_STATUS)) {
634 return 0x4000000000000000ULL;
635 } else {
636 return 0;
637 }
638}
639
640uint64_t helper_cmpgeq(CPUAlphaState *env, uint64_t a, uint64_t b)
641{
642 float64 fa, fb;
643
644 fa = g_to_float64(env, GETPC(), a);
645 fb = g_to_float64(env, GETPC(), b);
646
647 if (float64_eq_quiet(fa, fb, &FP_STATUS)) {
648 return 0x4000000000000000ULL;
649 } else {
650 return 0;
651 }
652}
653
654uint64_t helper_cmpgle(CPUAlphaState *env, uint64_t a, uint64_t b)
655{
656 float64 fa, fb;
657
658 fa = g_to_float64(env, GETPC(), a);
659 fb = g_to_float64(env, GETPC(), b);
660
661 if (float64_le(fa, fb, &FP_STATUS)) {
662 return 0x4000000000000000ULL;
663 } else {
664 return 0;
665 }
666}
667
668uint64_t helper_cmpglt(CPUAlphaState *env, uint64_t a, uint64_t b)
669{
670 float64 fa, fb;
671
672 fa = g_to_float64(env, GETPC(), a);
673 fb = g_to_float64(env, GETPC(), b);
674
675 if (float64_lt(fa, fb, &FP_STATUS)) {
676 return 0x4000000000000000ULL;
677 } else {
678 return 0;
679 }
680}
681
682/* Floating point format conversion */
683uint64_t helper_cvtts(CPUAlphaState *env, uint64_t a)
684{
685 float64 fa;
686 float32 fr;
687
688 fa = t_to_float64(a);
689 fr = float64_to_float32(fa, &FP_STATUS);
690 return float32_to_s(fr);
691}
692
693uint64_t helper_cvtst(CPUAlphaState *env, uint64_t a)
694{
695 float32 fa;
696 float64 fr;
697
698 fa = s_to_float32(a);
699 fr = float32_to_float64(fa, &FP_STATUS);
700 return float64_to_t(fr);
701}
702
703uint64_t helper_cvtqs(CPUAlphaState *env, uint64_t a)
704{
705 float32 fr = int64_to_float32(a, &FP_STATUS);
706 return float32_to_s(fr);
707}
708
709/* Implement float64 to uint64 conversion without saturation -- we must
710 supply the truncated result. This behaviour is used by the compiler
711 to get unsigned conversion for free with the same instruction.
712
713 The VI flag is set when overflow or inexact exceptions should be raised. */
714
715static inline uint64_t inline_cvttq(CPUAlphaState *env, uint64_t a,
716 int roundmode, int VI)
717{
718 uint64_t frac, ret = 0;
719 uint32_t exp, sign, exc = 0;
720 int shift;
721
722 sign = (a >> 63);
723 exp = (uint32_t)(a >> 52) & 0x7ff;
724 frac = a & 0xfffffffffffffull;
725
726 if (exp == 0) {
727 if (unlikely(frac != 0)) {
728 goto do_underflow;
729 }
730 } else if (exp == 0x7ff) {
731 exc = (frac ? float_flag_invalid : VI ? float_flag_overflow : 0);
732 } else {
733 /* Restore implicit bit. */
734 frac |= 0x10000000000000ull;
735
736 shift = exp - 1023 - 52;
737 if (shift >= 0) {
738 /* In this case the number is so large that we must shift
739 the fraction left. There is no rounding to do. */
740 if (shift < 63) {
741 ret = frac << shift;
742 if (VI && (ret >> shift) != frac) {
743 exc = float_flag_overflow;
744 }
745 }
746 } else {
747 uint64_t round;
748
749 /* In this case the number is smaller than the fraction as
750 represented by the 52 bit number. Here we must think
751 about rounding the result. Handle this by shifting the
752 fractional part of the number into the high bits of ROUND.
753 This will let us efficiently handle round-to-nearest. */
754 shift = -shift;
755 if (shift < 63) {
756 ret = frac >> shift;
757 round = frac << (64 - shift);
758 } else {
759 /* The exponent is so small we shift out everything.
760 Leave a sticky bit for proper rounding below. */
761 do_underflow:
762 round = 1;
763 }
764
765 if (round) {
766 exc = (VI ? float_flag_inexact : 0);
767 switch (roundmode) {
768 case float_round_nearest_even:
769 if (round == (1ull << 63)) {
770 /* Fraction is exactly 0.5; round to even. */
771 ret += (ret & 1);
772 } else if (round > (1ull << 63)) {
773 ret += 1;
774 }
775 break;
776 case float_round_to_zero:
777 break;
778 case float_round_up:
779 ret += 1 - sign;
780 break;
781 case float_round_down:
782 ret += sign;
783 break;
784 }
785 }
786 }
787 if (sign) {
788 ret = -ret;
789 }
790 }
791 if (unlikely(exc)) {
792 float_raise(exc, &FP_STATUS);
793 }
794
795 return ret;
796}
797
798uint64_t helper_cvttq(CPUAlphaState *env, uint64_t a)
799{
800 return inline_cvttq(env, a, FP_STATUS.float_rounding_mode, 1);
801}
802
803uint64_t helper_cvttq_c(CPUAlphaState *env, uint64_t a)
804{
805 return inline_cvttq(env, a, float_round_to_zero, 0);
806}
807
808uint64_t helper_cvttq_svic(CPUAlphaState *env, uint64_t a)
809{
810 return inline_cvttq(env, a, float_round_to_zero, 1);
811}
812
813uint64_t helper_cvtqt(CPUAlphaState *env, uint64_t a)
814{
815 float64 fr = int64_to_float64(a, &FP_STATUS);
816 return float64_to_t(fr);
817}
818
819uint64_t helper_cvtqf(CPUAlphaState *env, uint64_t a)
820{
821 float32 fr = int64_to_float32(a, &FP_STATUS);
822 return float32_to_f(fr);
823}
824
825uint64_t helper_cvtgf(CPUAlphaState *env, uint64_t a)
826{
827 float64 fa;
828 float32 fr;
829
830 fa = g_to_float64(env, GETPC(), a);
831 fr = float64_to_float32(fa, &FP_STATUS);
832 return float32_to_f(fr);
833}
834
835uint64_t helper_cvtgq(CPUAlphaState *env, uint64_t a)
836{
837 float64 fa = g_to_float64(env, GETPC(), a);
838 return float64_to_int64_round_to_zero(fa, &FP_STATUS);
839}
840
841uint64_t helper_cvtqg(CPUAlphaState *env, uint64_t a)
842{
843 float64 fr;
844 fr = int64_to_float64(a, &FP_STATUS);
845 return float64_to_g(fr);
846}