blob: b091aa842a33cc409591836902294ba66b5eb806 [file] [log] [blame]
Richard Henderson4a58aed2012-03-24 09:51:09 -07001/*
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"
Richard Henderson2ef61752014-04-07 22:31:41 -070021#include "exec/helper-proto.h"
Paolo Bonzini6b4c3052012-10-24 13:12:00 +020022#include "fpu/softfloat.h"
Richard Henderson4a58aed2012-03-24 09:51:09 -070023
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
Richard Hendersonf3d3aad2014-08-08 12:17:07 -100037#define CONVERT_BIT(X, SRC, DST) \
38 (SRC > DST ? (X) / (SRC / DST) & (DST) : ((X) & SRC) * (DST / SRC))
39
40static uint32_t soft_to_fpcr_exc(CPUAlphaState *env)
Richard Henderson4a58aed2012-03-24 09:51:09 -070041{
Richard Hendersonf3d3aad2014-08-08 12:17:07 -100042 uint8_t exc = get_float_exception_flags(&FP_STATUS);
43 uint32_t ret = 0;
44
45 if (unlikely(exc)) {
46 set_float_exception_flags(0, &FP_STATUS);
47 ret |= CONVERT_BIT(exc, float_flag_invalid, FPCR_INV);
48 ret |= CONVERT_BIT(exc, float_flag_divbyzero, FPCR_DZE);
49 ret |= CONVERT_BIT(exc, float_flag_overflow, FPCR_OVF);
50 ret |= CONVERT_BIT(exc, float_flag_underflow, FPCR_UNF);
51 ret |= CONVERT_BIT(exc, float_flag_inexact, FPCR_INE);
52 }
53
54 return ret;
Richard Henderson4a58aed2012-03-24 09:51:09 -070055}
56
Richard Hendersonf3d3aad2014-08-08 12:17:07 -100057static void fp_exc_raise1(CPUAlphaState *env, uintptr_t retaddr,
Richard Hendersonf6b6b7b2014-06-30 09:53:46 -070058 uint32_t exc, uint32_t regno, uint32_t hw_exc)
Richard Henderson4a58aed2012-03-24 09:51:09 -070059{
Richard Henderson471d4932014-06-28 11:08:28 -070060 hw_exc |= CONVERT_BIT(exc, FPCR_INV, EXC_M_INV);
61 hw_exc |= CONVERT_BIT(exc, FPCR_DZE, EXC_M_DZE);
62 hw_exc |= CONVERT_BIT(exc, FPCR_OVF, EXC_M_FOV);
63 hw_exc |= CONVERT_BIT(exc, FPCR_UNF, EXC_M_UNF);
64 hw_exc |= CONVERT_BIT(exc, FPCR_INE, EXC_M_INE);
65 hw_exc |= CONVERT_BIT(exc, FPCR_IOV, EXC_M_IOV);
Richard Henderson4a58aed2012-03-24 09:51:09 -070066
Richard Henderson471d4932014-06-28 11:08:28 -070067 arith_excp(env, retaddr, hw_exc, 1ull << regno);
Richard Henderson4a58aed2012-03-24 09:51:09 -070068}
69
70/* Raise exceptions for ieee fp insns without software completion.
71 In that case there are no exceptions that don't trap; the mask
72 doesn't apply. */
Richard Hendersonf3d3aad2014-08-08 12:17:07 -100073void helper_fp_exc_raise(CPUAlphaState *env, uint32_t ignore, uint32_t regno)
Richard Henderson4a58aed2012-03-24 09:51:09 -070074{
Richard Henderson471d4932014-06-28 11:08:28 -070075 uint32_t exc = env->error_code;
76 if (exc) {
77 env->fpcr |= exc;
78 exc &= ~ignore;
79 if (exc) {
Richard Hendersonf6b6b7b2014-06-30 09:53:46 -070080 fp_exc_raise1(env, GETPC(), exc, regno, 0);
Richard Henderson471d4932014-06-28 11:08:28 -070081 }
82 }
Richard Henderson4a58aed2012-03-24 09:51:09 -070083}
84
85/* Raise exceptions for ieee fp insns with software completion. */
Richard Hendersonf3d3aad2014-08-08 12:17:07 -100086void helper_fp_exc_raise_s(CPUAlphaState *env, uint32_t ignore, uint32_t regno)
Richard Henderson4a58aed2012-03-24 09:51:09 -070087{
Richard Hendersonf3d3aad2014-08-08 12:17:07 -100088 uint32_t exc = env->error_code & ~ignore;
Richard Henderson4a58aed2012-03-24 09:51:09 -070089 if (exc) {
Richard Hendersonf3d3aad2014-08-08 12:17:07 -100090 env->fpcr |= exc;
Richard Henderson471d4932014-06-28 11:08:28 -070091 exc &= ~ignore;
92 if (exc) {
93 exc &= env->fpcr_exc_enable;
Richard Hendersonf6b6b7b2014-06-30 09:53:46 -070094 fp_exc_raise1(env, GETPC(), exc, regno, EXC_M_SWC);
Richard Henderson471d4932014-06-28 11:08:28 -070095 }
Richard Henderson4a58aed2012-03-24 09:51:09 -070096 }
97}
98
Richard Henderson74343402012-03-24 09:51:14 -070099/* Input handing without software completion. Trap for all
100 non-finite numbers. */
101void helper_ieee_input(CPUAlphaState *env, uint64_t val)
Richard Henderson4a58aed2012-03-24 09:51:09 -0700102{
103 uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
104 uint64_t frac = val & 0xfffffffffffffull;
105
106 if (exp == 0) {
Richard Hendersonb99e8062014-07-08 10:11:06 -0700107 /* Denormals without /S raise an exception. */
108 if (frac != 0) {
109 arith_excp(env, GETPC(), EXC_M_INV, 0);
Richard Henderson4a58aed2012-03-24 09:51:09 -0700110 }
111 } else if (exp == 0x7ff) {
112 /* Infinity or NaN. */
Richard Hendersonb99e8062014-07-08 10:11:06 -0700113 env->fpcr |= FPCR_INV;
114 arith_excp(env, GETPC(), EXC_M_INV, 0);
Richard Henderson4a58aed2012-03-24 09:51:09 -0700115 }
Richard Henderson4a58aed2012-03-24 09:51:09 -0700116}
117
118/* Similar, but does not trap for infinities. Used for comparisons. */
Richard Henderson74343402012-03-24 09:51:14 -0700119void helper_ieee_input_cmp(CPUAlphaState *env, uint64_t val)
Richard Henderson4a58aed2012-03-24 09:51:09 -0700120{
121 uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
122 uint64_t frac = val & 0xfffffffffffffull;
123
124 if (exp == 0) {
Richard Hendersonb99e8062014-07-08 10:11:06 -0700125 /* Denormals without /S raise an exception. */
126 if (frac != 0) {
127 arith_excp(env, GETPC(), EXC_M_INV, 0);
Richard Henderson4a58aed2012-03-24 09:51:09 -0700128 }
129 } else if (exp == 0x7ff && frac) {
130 /* NaN. */
Richard Hendersonb99e8062014-07-08 10:11:06 -0700131 env->fpcr |= FPCR_INV;
Richard Henderson4a58aed2012-03-24 09:51:09 -0700132 arith_excp(env, GETPC(), EXC_M_INV, 0);
133 }
Richard Henderson4a58aed2012-03-24 09:51:09 -0700134}
135
Richard Hendersonb99e8062014-07-08 10:11:06 -0700136/* Input handing with software completion. Trap for denorms, unless DNZ
137 is set. If we try to support DNOD (which none of the produced hardware
138 did, AFAICS), we'll need to suppress the trap when FPCR.DNOD is set;
139 then the code downstream of that will need to cope with denorms sans
140 flush_input_to_zero. Most of it should work sanely, but there's
141 nothing to compare with. */
142void helper_ieee_input_s(CPUAlphaState *env, uint64_t val)
143{
144 if (unlikely(2 * val - 1 < 0x1fffffffffffffull)
145 && !env->fp_status.flush_inputs_to_zero) {
146 arith_excp(env, GETPC(), EXC_M_INV | EXC_M_SWC, 0);
147 }
148}
Richard Henderson4a58aed2012-03-24 09:51:09 -0700149
150/* S floating (single) */
151
152/* Taken from linux/arch/alpha/kernel/traps.c, s_mem_to_reg. */
153static inline uint64_t float32_to_s_int(uint32_t fi)
154{
155 uint32_t frac = fi & 0x7fffff;
156 uint32_t sign = fi >> 31;
157 uint32_t exp_msb = (fi >> 30) & 1;
158 uint32_t exp_low = (fi >> 23) & 0x7f;
159 uint32_t exp;
160
161 exp = (exp_msb << 10) | exp_low;
162 if (exp_msb) {
163 if (exp_low == 0x7f) {
164 exp = 0x7ff;
165 }
166 } else {
167 if (exp_low != 0x00) {
168 exp |= 0x380;
169 }
170 }
171
172 return (((uint64_t)sign << 63)
173 | ((uint64_t)exp << 52)
174 | ((uint64_t)frac << 29));
175}
176
177static inline uint64_t float32_to_s(float32 fa)
178{
179 CPU_FloatU a;
180 a.f = fa;
181 return float32_to_s_int(a.l);
182}
183
184static inline uint32_t s_to_float32_int(uint64_t a)
185{
186 return ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff);
187}
188
189static inline float32 s_to_float32(uint64_t a)
190{
191 CPU_FloatU r;
192 r.l = s_to_float32_int(a);
193 return r.f;
194}
195
196uint32_t helper_s_to_memory(uint64_t a)
197{
198 return s_to_float32_int(a);
199}
200
201uint64_t helper_memory_to_s(uint32_t a)
202{
203 return float32_to_s_int(a);
204}
205
206uint64_t helper_adds(CPUAlphaState *env, uint64_t a, uint64_t b)
207{
208 float32 fa, fb, fr;
209
210 fa = s_to_float32(a);
211 fb = s_to_float32(b);
212 fr = float32_add(fa, fb, &FP_STATUS);
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000213 env->error_code = soft_to_fpcr_exc(env);
214
Richard Henderson4a58aed2012-03-24 09:51:09 -0700215 return float32_to_s(fr);
216}
217
218uint64_t helper_subs(CPUAlphaState *env, uint64_t a, uint64_t b)
219{
220 float32 fa, fb, fr;
221
222 fa = s_to_float32(a);
223 fb = s_to_float32(b);
224 fr = float32_sub(fa, fb, &FP_STATUS);
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000225 env->error_code = soft_to_fpcr_exc(env);
226
Richard Henderson4a58aed2012-03-24 09:51:09 -0700227 return float32_to_s(fr);
228}
229
230uint64_t helper_muls(CPUAlphaState *env, uint64_t a, uint64_t b)
231{
232 float32 fa, fb, fr;
233
234 fa = s_to_float32(a);
235 fb = s_to_float32(b);
236 fr = float32_mul(fa, fb, &FP_STATUS);
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000237 env->error_code = soft_to_fpcr_exc(env);
238
Richard Henderson4a58aed2012-03-24 09:51:09 -0700239 return float32_to_s(fr);
240}
241
242uint64_t helper_divs(CPUAlphaState *env, uint64_t a, uint64_t b)
243{
244 float32 fa, fb, fr;
245
246 fa = s_to_float32(a);
247 fb = s_to_float32(b);
248 fr = float32_div(fa, fb, &FP_STATUS);
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000249 env->error_code = soft_to_fpcr_exc(env);
250
Richard Henderson4a58aed2012-03-24 09:51:09 -0700251 return float32_to_s(fr);
252}
253
254uint64_t helper_sqrts(CPUAlphaState *env, uint64_t a)
255{
256 float32 fa, fr;
257
258 fa = s_to_float32(a);
259 fr = float32_sqrt(fa, &FP_STATUS);
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000260 env->error_code = soft_to_fpcr_exc(env);
261
Richard Henderson4a58aed2012-03-24 09:51:09 -0700262 return float32_to_s(fr);
263}
264
265
266/* T floating (double) */
267static inline float64 t_to_float64(uint64_t a)
268{
269 /* Memory format is the same as float64 */
270 CPU_DoubleU r;
271 r.ll = a;
272 return r.d;
273}
274
275static inline uint64_t float64_to_t(float64 fa)
276{
277 /* Memory format is the same as float64 */
278 CPU_DoubleU r;
279 r.d = fa;
280 return r.ll;
281}
282
283uint64_t helper_addt(CPUAlphaState *env, uint64_t a, uint64_t b)
284{
285 float64 fa, fb, fr;
286
287 fa = t_to_float64(a);
288 fb = t_to_float64(b);
289 fr = float64_add(fa, fb, &FP_STATUS);
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000290 env->error_code = soft_to_fpcr_exc(env);
291
Richard Henderson4a58aed2012-03-24 09:51:09 -0700292 return float64_to_t(fr);
293}
294
295uint64_t helper_subt(CPUAlphaState *env, uint64_t a, uint64_t b)
296{
297 float64 fa, fb, fr;
298
299 fa = t_to_float64(a);
300 fb = t_to_float64(b);
301 fr = float64_sub(fa, fb, &FP_STATUS);
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000302 env->error_code = soft_to_fpcr_exc(env);
303
Richard Henderson4a58aed2012-03-24 09:51:09 -0700304 return float64_to_t(fr);
305}
306
307uint64_t helper_mult(CPUAlphaState *env, uint64_t a, uint64_t b)
308{
309 float64 fa, fb, fr;
310
311 fa = t_to_float64(a);
312 fb = t_to_float64(b);
313 fr = float64_mul(fa, fb, &FP_STATUS);
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000314 env->error_code = soft_to_fpcr_exc(env);
315
Richard Henderson4a58aed2012-03-24 09:51:09 -0700316 return float64_to_t(fr);
317}
318
319uint64_t helper_divt(CPUAlphaState *env, uint64_t a, uint64_t b)
320{
321 float64 fa, fb, fr;
322
323 fa = t_to_float64(a);
324 fb = t_to_float64(b);
325 fr = float64_div(fa, fb, &FP_STATUS);
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000326 env->error_code = soft_to_fpcr_exc(env);
327
Richard Henderson4a58aed2012-03-24 09:51:09 -0700328 return float64_to_t(fr);
329}
330
331uint64_t helper_sqrtt(CPUAlphaState *env, uint64_t a)
332{
333 float64 fa, fr;
334
335 fa = t_to_float64(a);
336 fr = float64_sqrt(fa, &FP_STATUS);
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000337 env->error_code = soft_to_fpcr_exc(env);
338
Richard Henderson4a58aed2012-03-24 09:51:09 -0700339 return float64_to_t(fr);
340}
341
342/* Comparisons */
343uint64_t helper_cmptun(CPUAlphaState *env, uint64_t a, uint64_t b)
344{
345 float64 fa, fb;
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000346 uint64_t ret = 0;
Richard Henderson4a58aed2012-03-24 09:51:09 -0700347
348 fa = t_to_float64(a);
349 fb = t_to_float64(b);
350
351 if (float64_unordered_quiet(fa, fb, &FP_STATUS)) {
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000352 ret = 0x4000000000000000ULL;
Richard Henderson4a58aed2012-03-24 09:51:09 -0700353 }
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000354 env->error_code = soft_to_fpcr_exc(env);
355
356 return ret;
Richard Henderson4a58aed2012-03-24 09:51:09 -0700357}
358
359uint64_t helper_cmpteq(CPUAlphaState *env, uint64_t a, uint64_t b)
360{
361 float64 fa, fb;
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000362 uint64_t ret = 0;
Richard Henderson4a58aed2012-03-24 09:51:09 -0700363
364 fa = t_to_float64(a);
365 fb = t_to_float64(b);
366
367 if (float64_eq_quiet(fa, fb, &FP_STATUS)) {
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000368 ret = 0x4000000000000000ULL;
Richard Henderson4a58aed2012-03-24 09:51:09 -0700369 }
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000370 env->error_code = soft_to_fpcr_exc(env);
371
372 return ret;
Richard Henderson4a58aed2012-03-24 09:51:09 -0700373}
374
375uint64_t helper_cmptle(CPUAlphaState *env, uint64_t a, uint64_t b)
376{
377 float64 fa, fb;
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000378 uint64_t ret = 0;
Richard Henderson4a58aed2012-03-24 09:51:09 -0700379
380 fa = t_to_float64(a);
381 fb = t_to_float64(b);
382
383 if (float64_le(fa, fb, &FP_STATUS)) {
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000384 ret = 0x4000000000000000ULL;
Richard Henderson4a58aed2012-03-24 09:51:09 -0700385 }
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000386 env->error_code = soft_to_fpcr_exc(env);
387
388 return ret;
Richard Henderson4a58aed2012-03-24 09:51:09 -0700389}
390
391uint64_t helper_cmptlt(CPUAlphaState *env, uint64_t a, uint64_t b)
392{
393 float64 fa, fb;
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000394 uint64_t ret = 0;
Richard Henderson4a58aed2012-03-24 09:51:09 -0700395
396 fa = t_to_float64(a);
397 fb = t_to_float64(b);
398
399 if (float64_lt(fa, fb, &FP_STATUS)) {
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000400 ret = 0x4000000000000000ULL;
Richard Henderson4a58aed2012-03-24 09:51:09 -0700401 }
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000402 env->error_code = soft_to_fpcr_exc(env);
403
404 return ret;
Richard Henderson4a58aed2012-03-24 09:51:09 -0700405}
406
Richard Henderson4a58aed2012-03-24 09:51:09 -0700407/* Floating point format conversion */
408uint64_t helper_cvtts(CPUAlphaState *env, uint64_t a)
409{
410 float64 fa;
411 float32 fr;
412
413 fa = t_to_float64(a);
414 fr = float64_to_float32(fa, &FP_STATUS);
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000415 env->error_code = soft_to_fpcr_exc(env);
416
Richard Henderson4a58aed2012-03-24 09:51:09 -0700417 return float32_to_s(fr);
418}
419
420uint64_t helper_cvtst(CPUAlphaState *env, uint64_t a)
421{
422 float32 fa;
423 float64 fr;
424
425 fa = s_to_float32(a);
426 fr = float32_to_float64(fa, &FP_STATUS);
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000427 env->error_code = soft_to_fpcr_exc(env);
428
Richard Henderson4a58aed2012-03-24 09:51:09 -0700429 return float64_to_t(fr);
430}
431
432uint64_t helper_cvtqs(CPUAlphaState *env, uint64_t a)
433{
434 float32 fr = int64_to_float32(a, &FP_STATUS);
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000435 env->error_code = soft_to_fpcr_exc(env);
436
Richard Henderson4a58aed2012-03-24 09:51:09 -0700437 return float32_to_s(fr);
438}
439
440/* Implement float64 to uint64 conversion without saturation -- we must
441 supply the truncated result. This behaviour is used by the compiler
Richard Hendersonc24a8a02014-06-28 12:57:03 -0700442 to get unsigned conversion for free with the same instruction. */
Richard Henderson4a58aed2012-03-24 09:51:09 -0700443
Richard Hendersonc24a8a02014-06-28 12:57:03 -0700444static uint64_t do_cvttq(CPUAlphaState *env, uint64_t a, int roundmode)
Richard Henderson4a58aed2012-03-24 09:51:09 -0700445{
446 uint64_t frac, ret = 0;
447 uint32_t exp, sign, exc = 0;
448 int shift;
449
450 sign = (a >> 63);
451 exp = (uint32_t)(a >> 52) & 0x7ff;
452 frac = a & 0xfffffffffffffull;
453
454 if (exp == 0) {
Richard Henderson4ed069a2014-07-08 10:14:09 -0700455 if (unlikely(frac != 0) && !env->fp_status.flush_inputs_to_zero) {
Richard Henderson4a58aed2012-03-24 09:51:09 -0700456 goto do_underflow;
457 }
458 } else if (exp == 0x7ff) {
Richard Henderson7b4dde82014-07-03 12:37:59 -0700459 exc = FPCR_INV;
Richard Henderson4a58aed2012-03-24 09:51:09 -0700460 } else {
461 /* Restore implicit bit. */
462 frac |= 0x10000000000000ull;
463
464 shift = exp - 1023 - 52;
465 if (shift >= 0) {
466 /* In this case the number is so large that we must shift
467 the fraction left. There is no rounding to do. */
Richard Henderson7f2e4002014-07-03 12:36:34 -0700468 if (shift < 64) {
Richard Henderson4a58aed2012-03-24 09:51:09 -0700469 ret = frac << shift;
Richard Henderson7f2e4002014-07-03 12:36:34 -0700470 }
471 /* Check for overflow. Note the special case of -0x1p63. */
472 if (shift >= 11 && a != 0xC3E0000000000000ull) {
473 exc = FPCR_IOV | FPCR_INE;
Richard Henderson4a58aed2012-03-24 09:51:09 -0700474 }
475 } else {
476 uint64_t round;
477
478 /* In this case the number is smaller than the fraction as
479 represented by the 52 bit number. Here we must think
480 about rounding the result. Handle this by shifting the
481 fractional part of the number into the high bits of ROUND.
482 This will let us efficiently handle round-to-nearest. */
483 shift = -shift;
484 if (shift < 63) {
485 ret = frac >> shift;
486 round = frac << (64 - shift);
487 } else {
488 /* The exponent is so small we shift out everything.
489 Leave a sticky bit for proper rounding below. */
490 do_underflow:
491 round = 1;
492 }
493
494 if (round) {
Richard Hendersonc24a8a02014-06-28 12:57:03 -0700495 exc = FPCR_INE;
Richard Henderson4a58aed2012-03-24 09:51:09 -0700496 switch (roundmode) {
497 case float_round_nearest_even:
498 if (round == (1ull << 63)) {
499 /* Fraction is exactly 0.5; round to even. */
500 ret += (ret & 1);
501 } else if (round > (1ull << 63)) {
502 ret += 1;
503 }
504 break;
505 case float_round_to_zero:
506 break;
507 case float_round_up:
508 ret += 1 - sign;
509 break;
510 case float_round_down:
511 ret += sign;
512 break;
513 }
514 }
515 }
516 if (sign) {
517 ret = -ret;
518 }
519 }
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000520 env->error_code = exc;
Richard Henderson4a58aed2012-03-24 09:51:09 -0700521
522 return ret;
523}
524
525uint64_t helper_cvttq(CPUAlphaState *env, uint64_t a)
526{
Richard Hendersonc24a8a02014-06-28 12:57:03 -0700527 return do_cvttq(env, a, FP_STATUS.float_rounding_mode);
Richard Henderson4a58aed2012-03-24 09:51:09 -0700528}
529
530uint64_t helper_cvttq_c(CPUAlphaState *env, uint64_t a)
531{
Richard Hendersonc24a8a02014-06-28 12:57:03 -0700532 return do_cvttq(env, a, float_round_to_zero);
Richard Henderson4a58aed2012-03-24 09:51:09 -0700533}
534
535uint64_t helper_cvtqt(CPUAlphaState *env, uint64_t a)
536{
537 float64 fr = int64_to_float64(a, &FP_STATUS);
Richard Hendersonf3d3aad2014-08-08 12:17:07 -1000538 env->error_code = soft_to_fpcr_exc(env);
Richard Henderson4a58aed2012-03-24 09:51:09 -0700539 return float64_to_t(fr);
540}
541
Richard Henderson57a808b2014-07-08 10:42:55 -0700542uint64_t helper_cvtql(CPUAlphaState *env, uint64_t val)
Richard Hendersone8d8fef2014-03-19 13:07:14 -0700543{
Richard Henderson57a808b2014-07-08 10:42:55 -0700544 uint32_t exc = 0;
Richard Hendersone8d8fef2014-03-19 13:07:14 -0700545 if (val != (int32_t)val) {
Richard Henderson57a808b2014-07-08 10:42:55 -0700546 exc = FPCR_IOV | FPCR_INE;
Richard Hendersone8d8fef2014-03-19 13:07:14 -0700547 }
Richard Henderson57a808b2014-07-08 10:42:55 -0700548 env->error_code = exc;
549
550 return ((val & 0xc0000000) << 32) | ((val & 0x3fffffff) << 29);
Richard Hendersone8d8fef2014-03-19 13:07:14 -0700551}