Annotation of qemu/target-alpha/fpu_helper.c, revision 1.1.1.1

1.1       root        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: 
                     27: void helper_setroundmode(CPUAlphaState *env, uint32_t val)
                     28: {
                     29:     set_float_rounding_mode(val, &FP_STATUS);
                     30: }
                     31: 
                     32: void helper_setflushzero(CPUAlphaState *env, uint32_t val)
                     33: {
                     34:     set_flush_to_zero(val, &FP_STATUS);
                     35: }
                     36: 
                     37: void helper_fp_exc_clear(CPUAlphaState *env)
                     38: {
                     39:     set_float_exception_flags(0, &FP_STATUS);
                     40: }
                     41: 
                     42: uint32_t helper_fp_exc_get(CPUAlphaState *env)
                     43: {
                     44:     return get_float_exception_flags(&FP_STATUS);
                     45: }
                     46: 
                     47: static 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.  */
                     76: void 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.  */
                     82: void 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.  */
                     93: void 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.  */
                    113: void 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) */
                    130: static 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: 
                    163: static 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: 
                    186: uint32_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: 
                    195: uint64_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: 
                    210: uint64_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: 
                    220: uint64_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: 
                    230: uint64_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: 
                    240: uint64_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: 
                    250: uint64_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) */
                    261: static 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: 
                    294: static 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: 
                    317: uint64_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: 
                    327: uint64_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: 
                    337: uint64_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: 
                    347: uint64_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: 
                    357: uint64_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: 
                    367: uint64_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: 
                    377: uint64_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.  */
                    390: static 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: 
                    414: static 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: 
                    421: static inline uint32_t s_to_float32_int(uint64_t a)
                    422: {
                    423:     return ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff);
                    424: }
                    425: 
                    426: static 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: 
                    433: uint32_t helper_s_to_memory(uint64_t a)
                    434: {
                    435:     return s_to_float32_int(a);
                    436: }
                    437: 
                    438: uint64_t helper_memory_to_s(uint32_t a)
                    439: {
                    440:     return float32_to_s_int(a);
                    441: }
                    442: 
                    443: uint64_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: 
                    453: uint64_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: 
                    463: uint64_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: 
                    473: uint64_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: 
                    483: uint64_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) */
                    494: static 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: 
                    502: static 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: 
                    510: uint64_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: 
                    520: uint64_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: 
                    530: uint64_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: 
                    540: uint64_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: 
                    550: uint64_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 */
                    560: uint64_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: 
                    574: uint64_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: 
                    588: uint64_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: 
                    602: uint64_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: 
                    616: uint64_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: 
                    630: uint64_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: 
                    644: uint64_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 */
                    659: uint64_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: 
                    669: uint64_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: 
                    679: uint64_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: 
                    691: static 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: 
                    774: uint64_t helper_cvttq(CPUAlphaState *env, uint64_t a)
                    775: {
                    776:     return inline_cvttq(env, a, FP_STATUS.float_rounding_mode, 1);
                    777: }
                    778: 
                    779: uint64_t helper_cvttq_c(CPUAlphaState *env, uint64_t a)
                    780: {
                    781:     return inline_cvttq(env, a, float_round_to_zero, 0);
                    782: }
                    783: 
                    784: uint64_t helper_cvttq_svic(CPUAlphaState *env, uint64_t a)
                    785: {
                    786:     return inline_cvttq(env, a, float_round_to_zero, 1);
                    787: }
                    788: 
                    789: uint64_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: 
                    795: uint64_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: 
                    801: uint64_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: 
                    811: uint64_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: 
                    817: uint64_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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.