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