Annotation of qemu/target-sparc/fop_helper.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * FPU op helpers
                      3:  *
                      4:  *  Copyright (c) 2003-2005 Fabrice Bellard
                      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: 
                     23: #define QT0 (env->qt0)
                     24: #define QT1 (env->qt1)
                     25: 
                     26: static void check_ieee_exceptions(CPUState *env)
                     27: {
                     28:     target_ulong status;
                     29: 
                     30:     status = get_float_exception_flags(&env->fp_status);
                     31:     if (status) {
                     32:         /* Copy IEEE 754 flags into FSR */
                     33:         if (status & float_flag_invalid) {
                     34:             env->fsr |= FSR_NVC;
                     35:         }
                     36:         if (status & float_flag_overflow) {
                     37:             env->fsr |= FSR_OFC;
                     38:         }
                     39:         if (status & float_flag_underflow) {
                     40:             env->fsr |= FSR_UFC;
                     41:         }
                     42:         if (status & float_flag_divbyzero) {
                     43:             env->fsr |= FSR_DZC;
                     44:         }
                     45:         if (status & float_flag_inexact) {
                     46:             env->fsr |= FSR_NXC;
                     47:         }
                     48: 
                     49:         if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
                     50:             /* Unmasked exception, generate a trap */
                     51:             env->fsr |= FSR_FTT_IEEE_EXCP;
                     52:             helper_raise_exception(env, TT_FP_EXCP);
                     53:         } else {
                     54:             /* Accumulate exceptions */
                     55:             env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
                     56:         }
                     57:     }
                     58: }
                     59: 
                     60: static inline void clear_float_exceptions(CPUState *env)
                     61: {
                     62:     set_float_exception_flags(0, &env->fp_status);
                     63: }
                     64: 
                     65: #define F_HELPER(name, p) void helper_f##name##p(CPUState *env)
                     66: 
                     67: #define F_BINOP(name)                                           \
                     68:     float32 helper_f ## name ## s (CPUState *env, float32 src1, \
                     69:                                    float32 src2)                \
                     70:     {                                                           \
                     71:         float32 ret;                                            \
                     72:         clear_float_exceptions(env);                            \
                     73:         ret = float32_ ## name (src1, src2, &env->fp_status);   \
                     74:         check_ieee_exceptions(env);                             \
                     75:         return ret;                                             \
                     76:     }                                                           \
                     77:     float64 helper_f ## name ## d (CPUState * env, float64 src1,\
                     78:                                    float64 src2)                \
                     79:     {                                                           \
                     80:         float64 ret;                                            \
                     81:         clear_float_exceptions(env);                            \
                     82:         ret = float64_ ## name (src1, src2, &env->fp_status);   \
                     83:         check_ieee_exceptions(env);                             \
                     84:         return ret;                                             \
                     85:     }                                                           \
                     86:     F_HELPER(name, q)                                           \
                     87:     {                                                           \
                     88:         clear_float_exceptions(env);                            \
                     89:         QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
                     90:         check_ieee_exceptions(env);                             \
                     91:     }
                     92: 
                     93: F_BINOP(add);
                     94: F_BINOP(sub);
                     95: F_BINOP(mul);
                     96: F_BINOP(div);
                     97: #undef F_BINOP
                     98: 
                     99: float64 helper_fsmuld(CPUState *env, float32 src1, float32 src2)
                    100: {
                    101:     float64 ret;
                    102:     clear_float_exceptions(env);
                    103:     ret = float64_mul(float32_to_float64(src1, &env->fp_status),
                    104:                       float32_to_float64(src2, &env->fp_status),
                    105:                       &env->fp_status);
                    106:     check_ieee_exceptions(env);
                    107:     return ret;
                    108: }
                    109: 
                    110: void helper_fdmulq(CPUState *env, float64 src1, float64 src2)
                    111: {
                    112:     clear_float_exceptions(env);
                    113:     QT0 = float128_mul(float64_to_float128(src1, &env->fp_status),
                    114:                        float64_to_float128(src2, &env->fp_status),
                    115:                        &env->fp_status);
                    116:     check_ieee_exceptions(env);
                    117: }
                    118: 
                    119: float32 helper_fnegs(float32 src)
                    120: {
                    121:     return float32_chs(src);
                    122: }
                    123: 
                    124: #ifdef TARGET_SPARC64
                    125: float64 helper_fnegd(float64 src)
                    126: {
                    127:     return float64_chs(src);
                    128: }
                    129: 
                    130: F_HELPER(neg, q)
                    131: {
                    132:     QT0 = float128_chs(QT1);
                    133: }
                    134: #endif
                    135: 
                    136: /* Integer to float conversion.  */
                    137: float32 helper_fitos(CPUState *env, int32_t src)
                    138: {
                    139:     /* Inexact error possible converting int to float.  */
                    140:     float32 ret;
                    141:     clear_float_exceptions(env);
                    142:     ret = int32_to_float32(src, &env->fp_status);
                    143:     check_ieee_exceptions(env);
                    144:     return ret;
                    145: }
                    146: 
                    147: float64 helper_fitod(CPUState *env, int32_t src)
                    148: {
                    149:     /* No possible exceptions converting int to double.  */
                    150:     return int32_to_float64(src, &env->fp_status);
                    151: }
                    152: 
                    153: void helper_fitoq(CPUState *env, int32_t src)
                    154: {
                    155:     /* No possible exceptions converting int to long double.  */
                    156:     QT0 = int32_to_float128(src, &env->fp_status);
                    157: }
                    158: 
                    159: #ifdef TARGET_SPARC64
                    160: float32 helper_fxtos(CPUState *env, int64_t src)
                    161: {
                    162:     float32 ret;
                    163:     clear_float_exceptions(env);
                    164:     ret = int64_to_float32(src, &env->fp_status);
                    165:     check_ieee_exceptions(env);
                    166:     return ret;
                    167: }
                    168: 
                    169: float64 helper_fxtod(CPUState *env, int64_t src)
                    170: {
                    171:     float64 ret;
                    172:     clear_float_exceptions(env);
                    173:     ret = int64_to_float64(src, &env->fp_status);
                    174:     check_ieee_exceptions(env);
                    175:     return ret;
                    176: }
                    177: 
                    178: void helper_fxtoq(CPUState *env, int64_t src)
                    179: {
                    180:     /* No possible exceptions converting long long to long double.  */
                    181:     QT0 = int64_to_float128(src, &env->fp_status);
                    182: }
                    183: #endif
                    184: #undef F_HELPER
                    185: 
                    186: /* floating point conversion */
                    187: float32 helper_fdtos(CPUState *env, float64 src)
                    188: {
                    189:     float32 ret;
                    190:     clear_float_exceptions(env);
                    191:     ret = float64_to_float32(src, &env->fp_status);
                    192:     check_ieee_exceptions(env);
                    193:     return ret;
                    194: }
                    195: 
                    196: float64 helper_fstod(CPUState *env, float32 src)
                    197: {
                    198:     float64 ret;
                    199:     clear_float_exceptions(env);
                    200:     ret = float32_to_float64(src, &env->fp_status);
                    201:     check_ieee_exceptions(env);
                    202:     return ret;
                    203: }
                    204: 
                    205: float32 helper_fqtos(CPUState *env)
                    206: {
                    207:     float32 ret;
                    208:     clear_float_exceptions(env);
                    209:     ret = float128_to_float32(QT1, &env->fp_status);
                    210:     check_ieee_exceptions(env);
                    211:     return ret;
                    212: }
                    213: 
                    214: void helper_fstoq(CPUState *env, float32 src)
                    215: {
                    216:     clear_float_exceptions(env);
                    217:     QT0 = float32_to_float128(src, &env->fp_status);
                    218:     check_ieee_exceptions(env);
                    219: }
                    220: 
                    221: float64 helper_fqtod(CPUState *env)
                    222: {
                    223:     float64 ret;
                    224:     clear_float_exceptions(env);
                    225:     ret = float128_to_float64(QT1, &env->fp_status);
                    226:     check_ieee_exceptions(env);
                    227:     return ret;
                    228: }
                    229: 
                    230: void helper_fdtoq(CPUState *env, float64 src)
                    231: {
                    232:     clear_float_exceptions(env);
                    233:     QT0 = float64_to_float128(src, &env->fp_status);
                    234:     check_ieee_exceptions(env);
                    235: }
                    236: 
                    237: /* Float to integer conversion.  */
                    238: int32_t helper_fstoi(CPUState *env, float32 src)
                    239: {
                    240:     int32_t ret;
                    241:     clear_float_exceptions(env);
                    242:     ret = float32_to_int32_round_to_zero(src, &env->fp_status);
                    243:     check_ieee_exceptions(env);
                    244:     return ret;
                    245: }
                    246: 
                    247: int32_t helper_fdtoi(CPUState *env, float64 src)
                    248: {
                    249:     int32_t ret;
                    250:     clear_float_exceptions(env);
                    251:     ret = float64_to_int32_round_to_zero(src, &env->fp_status);
                    252:     check_ieee_exceptions(env);
                    253:     return ret;
                    254: }
                    255: 
                    256: int32_t helper_fqtoi(CPUState *env)
                    257: {
                    258:     int32_t ret;
                    259:     clear_float_exceptions(env);
                    260:     ret = float128_to_int32_round_to_zero(QT1, &env->fp_status);
                    261:     check_ieee_exceptions(env);
                    262:     return ret;
                    263: }
                    264: 
                    265: #ifdef TARGET_SPARC64
                    266: int64_t helper_fstox(CPUState *env, float32 src)
                    267: {
                    268:     int64_t ret;
                    269:     clear_float_exceptions(env);
                    270:     ret = float32_to_int64_round_to_zero(src, &env->fp_status);
                    271:     check_ieee_exceptions(env);
                    272:     return ret;
                    273: }
                    274: 
                    275: int64_t helper_fdtox(CPUState *env, float64 src)
                    276: {
                    277:     int64_t ret;
                    278:     clear_float_exceptions(env);
                    279:     ret = float64_to_int64_round_to_zero(src, &env->fp_status);
                    280:     check_ieee_exceptions(env);
                    281:     return ret;
                    282: }
                    283: 
                    284: int64_t helper_fqtox(CPUState *env)
                    285: {
                    286:     int64_t ret;
                    287:     clear_float_exceptions(env);
                    288:     ret = float128_to_int64_round_to_zero(QT1, &env->fp_status);
                    289:     check_ieee_exceptions(env);
                    290:     return ret;
                    291: }
                    292: #endif
                    293: 
                    294: float32 helper_fabss(float32 src)
                    295: {
                    296:     return float32_abs(src);
                    297: }
                    298: 
                    299: #ifdef TARGET_SPARC64
                    300: float64 helper_fabsd(float64 src)
                    301: {
                    302:     return float64_abs(src);
                    303: }
                    304: 
                    305: void helper_fabsq(CPUState *env)
                    306: {
                    307:     QT0 = float128_abs(QT1);
                    308: }
                    309: #endif
                    310: 
                    311: float32 helper_fsqrts(CPUState *env, float32 src)
                    312: {
                    313:     float32 ret;
                    314:     clear_float_exceptions(env);
                    315:     ret = float32_sqrt(src, &env->fp_status);
                    316:     check_ieee_exceptions(env);
                    317:     return ret;
                    318: }
                    319: 
                    320: float64 helper_fsqrtd(CPUState *env, float64 src)
                    321: {
                    322:     float64 ret;
                    323:     clear_float_exceptions(env);
                    324:     ret = float64_sqrt(src, &env->fp_status);
                    325:     check_ieee_exceptions(env);
                    326:     return ret;
                    327: }
                    328: 
                    329: void helper_fsqrtq(CPUState *env)
                    330: {
                    331:     clear_float_exceptions(env);
                    332:     QT0 = float128_sqrt(QT1, &env->fp_status);
                    333:     check_ieee_exceptions(env);
                    334: }
                    335: 
                    336: #define GEN_FCMP(name, size, reg1, reg2, FS, E)                         \
                    337:     void glue(helper_, name) (CPUState *env)                            \
                    338:     {                                                                   \
                    339:         env->fsr &= FSR_FTT_NMASK;                                      \
                    340:         if (E && (glue(size, _is_any_nan)(reg1) ||                      \
                    341:                   glue(size, _is_any_nan)(reg2)) &&                     \
                    342:             (env->fsr & FSR_NVM)) {                                     \
                    343:             env->fsr |= FSR_NVC;                                        \
                    344:             env->fsr |= FSR_FTT_IEEE_EXCP;                              \
                    345:             helper_raise_exception(env, TT_FP_EXCP);                    \
                    346:         }                                                               \
                    347:         switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
                    348:         case float_relation_unordered:                                  \
                    349:             if ((env->fsr & FSR_NVM)) {                                 \
                    350:                 env->fsr |= FSR_NVC;                                    \
                    351:                 env->fsr |= FSR_FTT_IEEE_EXCP;                          \
                    352:                 helper_raise_exception(env, TT_FP_EXCP);                \
                    353:             } else {                                                    \
                    354:                 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);             \
                    355:                 env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS;                \
                    356:                 env->fsr |= FSR_NVA;                                    \
                    357:             }                                                           \
                    358:             break;                                                      \
                    359:         case float_relation_less:                                       \
                    360:             env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
                    361:             env->fsr |= FSR_FCC0 << FS;                                 \
                    362:             break;                                                      \
                    363:         case float_relation_greater:                                    \
                    364:             env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
                    365:             env->fsr |= FSR_FCC1 << FS;                                 \
                    366:             break;                                                      \
                    367:         default:                                                        \
                    368:             env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
                    369:             break;                                                      \
                    370:         }                                                               \
                    371:     }
                    372: #define GEN_FCMP_T(name, size, FS, E)                                   \
                    373:     void glue(helper_, name)(CPUState *env, size src1, size src2)       \
                    374:     {                                                                   \
                    375:         env->fsr &= FSR_FTT_NMASK;                                      \
                    376:         if (E && (glue(size, _is_any_nan)(src1) ||                      \
                    377:                   glue(size, _is_any_nan)(src2)) &&                     \
                    378:             (env->fsr & FSR_NVM)) {                                     \
                    379:             env->fsr |= FSR_NVC;                                        \
                    380:             env->fsr |= FSR_FTT_IEEE_EXCP;                              \
                    381:             helper_raise_exception(env, TT_FP_EXCP);                    \
                    382:         }                                                               \
                    383:         switch (glue(size, _compare) (src1, src2, &env->fp_status)) {   \
                    384:         case float_relation_unordered:                                  \
                    385:             if ((env->fsr & FSR_NVM)) {                                 \
                    386:                 env->fsr |= FSR_NVC;                                    \
                    387:                 env->fsr |= FSR_FTT_IEEE_EXCP;                          \
                    388:                 helper_raise_exception(env, TT_FP_EXCP);                \
                    389:             } else {                                                    \
                    390:                 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);             \
                    391:                 env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS;                \
                    392:                 env->fsr |= FSR_NVA;                                    \
                    393:             }                                                           \
                    394:             break;                                                      \
                    395:         case float_relation_less:                                       \
                    396:             env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
                    397:             env->fsr |= FSR_FCC0 << FS;                                 \
                    398:             break;                                                      \
                    399:         case float_relation_greater:                                    \
                    400:             env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
                    401:             env->fsr |= FSR_FCC1 << FS;                                 \
                    402:             break;                                                      \
                    403:         default:                                                        \
                    404:             env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
                    405:             break;                                                      \
                    406:         }                                                               \
                    407:     }
                    408: 
                    409: GEN_FCMP_T(fcmps, float32, 0, 0);
                    410: GEN_FCMP_T(fcmpd, float64, 0, 0);
                    411: 
                    412: GEN_FCMP_T(fcmpes, float32, 0, 1);
                    413: GEN_FCMP_T(fcmped, float64, 0, 1);
                    414: 
                    415: GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
                    416: GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
                    417: 
                    418: #ifdef TARGET_SPARC64
                    419: GEN_FCMP_T(fcmps_fcc1, float32, 22, 0);
                    420: GEN_FCMP_T(fcmpd_fcc1, float64, 22, 0);
                    421: GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
                    422: 
                    423: GEN_FCMP_T(fcmps_fcc2, float32, 24, 0);
                    424: GEN_FCMP_T(fcmpd_fcc2, float64, 24, 0);
                    425: GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
                    426: 
                    427: GEN_FCMP_T(fcmps_fcc3, float32, 26, 0);
                    428: GEN_FCMP_T(fcmpd_fcc3, float64, 26, 0);
                    429: GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
                    430: 
                    431: GEN_FCMP_T(fcmpes_fcc1, float32, 22, 1);
                    432: GEN_FCMP_T(fcmped_fcc1, float64, 22, 1);
                    433: GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
                    434: 
                    435: GEN_FCMP_T(fcmpes_fcc2, float32, 24, 1);
                    436: GEN_FCMP_T(fcmped_fcc2, float64, 24, 1);
                    437: GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
                    438: 
                    439: GEN_FCMP_T(fcmpes_fcc3, float32, 26, 1);
                    440: GEN_FCMP_T(fcmped_fcc3, float64, 26, 1);
                    441: GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
                    442: #endif
                    443: #undef GEN_FCMP_T
                    444: #undef GEN_FCMP
                    445: 
                    446: static inline void set_fsr(CPUState *env)
                    447: {
                    448:     int rnd_mode;
                    449: 
                    450:     switch (env->fsr & FSR_RD_MASK) {
                    451:     case FSR_RD_NEAREST:
                    452:         rnd_mode = float_round_nearest_even;
                    453:         break;
                    454:     default:
                    455:     case FSR_RD_ZERO:
                    456:         rnd_mode = float_round_to_zero;
                    457:         break;
                    458:     case FSR_RD_POS:
                    459:         rnd_mode = float_round_up;
                    460:         break;
                    461:     case FSR_RD_NEG:
                    462:         rnd_mode = float_round_down;
                    463:         break;
                    464:     }
                    465:     set_float_rounding_mode(rnd_mode, &env->fp_status);
                    466: }
                    467: 
                    468: void helper_ldfsr(CPUState *env, uint32_t new_fsr)
                    469: {
                    470:     env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
                    471:     set_fsr(env);
                    472: }
                    473: 
                    474: #ifdef TARGET_SPARC64
                    475: void helper_ldxfsr(CPUState *env, uint64_t new_fsr)
                    476: {
                    477:     env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
                    478:     set_fsr(env);
                    479: }
                    480: #endif

unix.superglobalmegacorp.com

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