Annotation of qemu/target-alpha/op_helper.c, revision 1.1.1.8

1.1       root        1: /*
                      2:  *  Alpha emulation cpu micro-operations helpers for qemu.
                      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
1.1.1.3   root       17:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1       root       18:  */
                     19: 
                     20: #include "exec.h"
                     21: #include "host-utils.h"
                     22: #include "softfloat.h"
1.1.1.2   root       23: #include "helper.h"
1.1.1.6   root       24: #include "qemu-timer.h"
1.1       root       25: 
                     26: /*****************************************************************************/
                     27: /* Exceptions processing helpers */
1.1.1.8 ! root       28: 
        !            29: /* This should only be called from translate, via gen_excp.
        !            30:    We expect that ENV->PC has already been updated.  */
        !            31: void QEMU_NORETURN helper_excp(int excp, int error)
1.1       root       32: {
                     33:     env->exception_index = excp;
                     34:     env->error_code = error;
1.1.1.8 ! root       35:     cpu_loop_exit(env);
        !            36: }
        !            37: 
        !            38: static void do_restore_state(void *retaddr)
        !            39: {
        !            40:     unsigned long pc = (unsigned long)retaddr;
        !            41: 
        !            42:     if (pc) {
        !            43:         TranslationBlock *tb = tb_find_pc(pc);
        !            44:         if (tb) {
        !            45:             cpu_restore_state(tb, env, pc);
        !            46:         }
        !            47:     }
        !            48: }
        !            49: 
        !            50: /* This may be called from any of the helpers to set up EXCEPTION_INDEX.  */
        !            51: static void QEMU_NORETURN dynamic_excp(int excp, int error)
        !            52: {
        !            53:     env->exception_index = excp;
        !            54:     env->error_code = error;
        !            55:     do_restore_state(GETPC());
        !            56:     cpu_loop_exit(env);
        !            57: }
        !            58: 
        !            59: static void QEMU_NORETURN arith_excp(int exc, uint64_t mask)
        !            60: {
        !            61:     env->trap_arg0 = exc;
        !            62:     env->trap_arg1 = mask;
        !            63:     dynamic_excp(EXCP_ARITH, 0);
1.1       root       64: }
                     65: 
1.1.1.2   root       66: uint64_t helper_load_pcc (void)
1.1       root       67: {
1.1.1.8 ! root       68: #ifndef CONFIG_USER_ONLY
        !            69:     /* In system mode we have access to a decent high-resolution clock.
        !            70:        In order to make OS-level time accounting work with the RPCC,
        !            71:        present it with a well-timed clock fixed at 250MHz.  */
        !            72:     return (((uint64_t)env->pcc_ofs << 32)
        !            73:             | (uint32_t)(qemu_get_clock_ns(vm_clock) >> 2));
        !            74: #else
        !            75:     /* In user-mode, vm_clock doesn't exist.  Just pass through the host cpu
        !            76:        clock ticks.  Also, don't bother taking PCC_OFS into account.  */
1.1.1.6   root       77:     return (uint32_t)cpu_get_real_ticks();
1.1.1.8 ! root       78: #endif
1.1       root       79: }
                     80: 
1.1.1.2   root       81: uint64_t helper_load_fpcr (void)
1.1       root       82: {
1.1.1.6   root       83:     return cpu_alpha_load_fpcr (env);
1.1       root       84: }
                     85: 
1.1.1.2   root       86: void helper_store_fpcr (uint64_t val)
1.1       root       87: {
1.1.1.6   root       88:     cpu_alpha_store_fpcr (env, val);
1.1       root       89: }
                     90: 
1.1.1.2   root       91: uint64_t helper_addqv (uint64_t op1, uint64_t op2)
1.1       root       92: {
1.1.1.2   root       93:     uint64_t tmp = op1;
                     94:     op1 += op2;
                     95:     if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) {
1.1.1.8 ! root       96:         arith_excp(EXC_M_IOV, 0);
1.1       root       97:     }
1.1.1.2   root       98:     return op1;
1.1       root       99: }
                    100: 
1.1.1.2   root      101: uint64_t helper_addlv (uint64_t op1, uint64_t op2)
1.1       root      102: {
1.1.1.2   root      103:     uint64_t tmp = op1;
                    104:     op1 = (uint32_t)(op1 + op2);
                    105:     if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) {
1.1.1.8 ! root      106:         arith_excp(EXC_M_IOV, 0);
1.1       root      107:     }
1.1.1.2   root      108:     return op1;
1.1       root      109: }
                    110: 
1.1.1.2   root      111: uint64_t helper_subqv (uint64_t op1, uint64_t op2)
1.1       root      112: {
1.1.1.3   root      113:     uint64_t res;
                    114:     res = op1 - op2;
                    115:     if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) {
1.1.1.8 ! root      116:         arith_excp(EXC_M_IOV, 0);
1.1       root      117:     }
1.1.1.3   root      118:     return res;
1.1       root      119: }
                    120: 
1.1.1.2   root      121: uint64_t helper_sublv (uint64_t op1, uint64_t op2)
1.1       root      122: {
1.1.1.3   root      123:     uint32_t res;
                    124:     res = op1 - op2;
                    125:     if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) {
1.1.1.8 ! root      126:         arith_excp(EXC_M_IOV, 0);
1.1       root      127:     }
1.1.1.3   root      128:     return res;
1.1       root      129: }
                    130: 
1.1.1.2   root      131: uint64_t helper_mullv (uint64_t op1, uint64_t op2)
1.1       root      132: {
1.1.1.2   root      133:     int64_t res = (int64_t)op1 * (int64_t)op2;
1.1       root      134: 
                    135:     if (unlikely((int32_t)res != res)) {
1.1.1.8 ! root      136:         arith_excp(EXC_M_IOV, 0);
1.1       root      137:     }
1.1.1.2   root      138:     return (int64_t)((int32_t)res);
1.1       root      139: }
                    140: 
1.1.1.2   root      141: uint64_t helper_mulqv (uint64_t op1, uint64_t op2)
1.1       root      142: {
                    143:     uint64_t tl, th;
                    144: 
1.1.1.2   root      145:     muls64(&tl, &th, op1, op2);
1.1       root      146:     /* If th != 0 && th != -1, then we had an overflow */
                    147:     if (unlikely((th + 1) > 1)) {
1.1.1.8 ! root      148:         arith_excp(EXC_M_IOV, 0);
1.1       root      149:     }
1.1.1.2   root      150:     return tl;
1.1       root      151: }
                    152: 
1.1.1.2   root      153: uint64_t helper_umulh (uint64_t op1, uint64_t op2)
1.1       root      154: {
1.1.1.2   root      155:     uint64_t tl, th;
                    156: 
                    157:     mulu64(&tl, &th, op1, op2);
                    158:     return th;
1.1       root      159: }
                    160: 
1.1.1.2   root      161: uint64_t helper_ctpop (uint64_t arg)
1.1       root      162: {
1.1.1.2   root      163:     return ctpop64(arg);
1.1       root      164: }
                    165: 
1.1.1.2   root      166: uint64_t helper_ctlz (uint64_t arg)
1.1       root      167: {
1.1.1.2   root      168:     return clz64(arg);
                    169: }
                    170: 
                    171: uint64_t helper_cttz (uint64_t arg)
                    172: {
                    173:     return ctz64(arg);
1.1       root      174: }
                    175: 
1.1.1.4   root      176: static inline uint64_t byte_zap(uint64_t op, uint8_t mskb)
1.1       root      177: {
                    178:     uint64_t mask;
                    179: 
                    180:     mask = 0;
                    181:     mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL;
                    182:     mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL;
                    183:     mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL;
                    184:     mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL;
                    185:     mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL;
                    186:     mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL;
                    187:     mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL;
                    188:     mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL;
                    189: 
                    190:     return op & ~mask;
                    191: }
                    192: 
1.1.1.6   root      193: uint64_t helper_zap(uint64_t val, uint64_t mask)
1.1       root      194: {
1.1.1.6   root      195:     return byte_zap(val, mask);
1.1       root      196: }
                    197: 
1.1.1.6   root      198: uint64_t helper_zapnot(uint64_t val, uint64_t mask)
1.1       root      199: {
1.1.1.6   root      200:     return byte_zap(val, ~mask);
1.1       root      201: }
                    202: 
1.1.1.6   root      203: uint64_t helper_cmpbge (uint64_t op1, uint64_t op2)
1.1       root      204: {
1.1.1.6   root      205:     uint8_t opa, opb, res;
                    206:     int i;
                    207: 
                    208:     res = 0;
                    209:     for (i = 0; i < 8; i++) {
                    210:         opa = op1 >> (i * 8);
                    211:         opb = op2 >> (i * 8);
                    212:         if (opa >= opb)
                    213:             res |= 1 << i;
                    214:     }
                    215:     return res;
1.1       root      216: }
                    217: 
1.1.1.6   root      218: uint64_t helper_minub8 (uint64_t op1, uint64_t op2)
1.1       root      219: {
1.1.1.6   root      220:     uint64_t res = 0;
                    221:     uint8_t opa, opb, opr;
                    222:     int i;
                    223: 
                    224:     for (i = 0; i < 8; ++i) {
                    225:         opa = op1 >> (i * 8);
                    226:         opb = op2 >> (i * 8);
                    227:         opr = opa < opb ? opa : opb;
                    228:         res |= (uint64_t)opr << (i * 8);
                    229:     }
                    230:     return res;
1.1       root      231: }
                    232: 
1.1.1.6   root      233: uint64_t helper_minsb8 (uint64_t op1, uint64_t op2)
1.1       root      234: {
1.1.1.6   root      235:     uint64_t res = 0;
                    236:     int8_t opa, opb;
                    237:     uint8_t opr;
                    238:     int i;
                    239: 
                    240:     for (i = 0; i < 8; ++i) {
                    241:         opa = op1 >> (i * 8);
                    242:         opb = op2 >> (i * 8);
                    243:         opr = opa < opb ? opa : opb;
                    244:         res |= (uint64_t)opr << (i * 8);
                    245:     }
                    246:     return res;
1.1       root      247: }
                    248: 
1.1.1.6   root      249: uint64_t helper_minuw4 (uint64_t op1, uint64_t op2)
1.1       root      250: {
1.1.1.6   root      251:     uint64_t res = 0;
                    252:     uint16_t opa, opb, opr;
                    253:     int i;
                    254: 
                    255:     for (i = 0; i < 4; ++i) {
                    256:         opa = op1 >> (i * 16);
                    257:         opb = op2 >> (i * 16);
                    258:         opr = opa < opb ? opa : opb;
                    259:         res |= (uint64_t)opr << (i * 16);
                    260:     }
                    261:     return res;
1.1       root      262: }
                    263: 
1.1.1.6   root      264: uint64_t helper_minsw4 (uint64_t op1, uint64_t op2)
1.1       root      265: {
1.1.1.6   root      266:     uint64_t res = 0;
                    267:     int16_t opa, opb;
                    268:     uint16_t opr;
                    269:     int i;
                    270: 
                    271:     for (i = 0; i < 4; ++i) {
                    272:         opa = op1 >> (i * 16);
                    273:         opb = op2 >> (i * 16);
                    274:         opr = opa < opb ? opa : opb;
                    275:         res |= (uint64_t)opr << (i * 16);
                    276:     }
                    277:     return res;
1.1       root      278: }
                    279: 
1.1.1.6   root      280: uint64_t helper_maxub8 (uint64_t op1, uint64_t op2)
1.1       root      281: {
1.1.1.6   root      282:     uint64_t res = 0;
                    283:     uint8_t opa, opb, opr;
                    284:     int i;
                    285: 
                    286:     for (i = 0; i < 8; ++i) {
                    287:         opa = op1 >> (i * 8);
                    288:         opb = op2 >> (i * 8);
                    289:         opr = opa > opb ? opa : opb;
                    290:         res |= (uint64_t)opr << (i * 8);
                    291:     }
                    292:     return res;
1.1       root      293: }
                    294: 
1.1.1.6   root      295: uint64_t helper_maxsb8 (uint64_t op1, uint64_t op2)
1.1       root      296: {
1.1.1.6   root      297:     uint64_t res = 0;
                    298:     int8_t opa, opb;
                    299:     uint8_t opr;
                    300:     int i;
                    301: 
                    302:     for (i = 0; i < 8; ++i) {
                    303:         opa = op1 >> (i * 8);
                    304:         opb = op2 >> (i * 8);
                    305:         opr = opa > opb ? opa : opb;
                    306:         res |= (uint64_t)opr << (i * 8);
                    307:     }
                    308:     return res;
1.1       root      309: }
                    310: 
1.1.1.6   root      311: uint64_t helper_maxuw4 (uint64_t op1, uint64_t op2)
1.1       root      312: {
1.1.1.6   root      313:     uint64_t res = 0;
                    314:     uint16_t opa, opb, opr;
                    315:     int i;
                    316: 
                    317:     for (i = 0; i < 4; ++i) {
                    318:         opa = op1 >> (i * 16);
                    319:         opb = op2 >> (i * 16);
                    320:         opr = opa > opb ? opa : opb;
                    321:         res |= (uint64_t)opr << (i * 16);
                    322:     }
                    323:     return res;
1.1       root      324: }
                    325: 
1.1.1.6   root      326: uint64_t helper_maxsw4 (uint64_t op1, uint64_t op2)
1.1       root      327: {
1.1.1.6   root      328:     uint64_t res = 0;
                    329:     int16_t opa, opb;
                    330:     uint16_t opr;
                    331:     int i;
                    332: 
                    333:     for (i = 0; i < 4; ++i) {
                    334:         opa = op1 >> (i * 16);
                    335:         opb = op2 >> (i * 16);
                    336:         opr = opa > opb ? opa : opb;
                    337:         res |= (uint64_t)opr << (i * 16);
                    338:     }
                    339:     return res;
1.1       root      340: }
                    341: 
1.1.1.6   root      342: uint64_t helper_perr (uint64_t op1, uint64_t op2)
1.1       root      343: {
1.1.1.6   root      344:     uint64_t res = 0;
                    345:     uint8_t opa, opb, opr;
                    346:     int i;
                    347: 
                    348:     for (i = 0; i < 8; ++i) {
                    349:         opa = op1 >> (i * 8);
                    350:         opb = op2 >> (i * 8);
                    351:         if (opa >= opb)
                    352:             opr = opa - opb;
                    353:         else
                    354:             opr = opb - opa;
                    355:         res += opr;
                    356:     }
                    357:     return res;
1.1       root      358: }
                    359: 
1.1.1.6   root      360: uint64_t helper_pklb (uint64_t op1)
1.1       root      361: {
1.1.1.6   root      362:     return (op1 & 0xff) | ((op1 >> 24) & 0xff00);
1.1       root      363: }
                    364: 
1.1.1.6   root      365: uint64_t helper_pkwb (uint64_t op1)
1.1       root      366: {
1.1.1.6   root      367:     return ((op1 & 0xff)
                    368:             | ((op1 >> 8) & 0xff00)
                    369:             | ((op1 >> 16) & 0xff0000)
                    370:             | ((op1 >> 24) & 0xff000000));
1.1       root      371: }
                    372: 
1.1.1.6   root      373: uint64_t helper_unpkbl (uint64_t op1)
1.1       root      374: {
1.1.1.6   root      375:     return (op1 & 0xff) | ((op1 & 0xff00) << 24);
1.1       root      376: }
                    377: 
1.1.1.6   root      378: uint64_t helper_unpkbw (uint64_t op1)
1.1       root      379: {
1.1.1.6   root      380:     return ((op1 & 0xff)
                    381:             | ((op1 & 0xff00) << 8)
                    382:             | ((op1 & 0xff0000) << 16)
                    383:             | ((op1 & 0xff000000) << 24));
1.1       root      384: }
                    385: 
1.1.1.6   root      386: /* Floating point helpers */
                    387: 
                    388: void helper_setroundmode (uint32_t val)
1.1       root      389: {
1.1.1.6   root      390:     set_float_rounding_mode(val, &FP_STATUS);
                    391: }
1.1       root      392: 
1.1.1.6   root      393: void helper_setflushzero (uint32_t val)
                    394: {
                    395:     set_flush_to_zero(val, &FP_STATUS);
                    396: }
                    397: 
                    398: void helper_fp_exc_clear (void)
                    399: {
                    400:     set_float_exception_flags(0, &FP_STATUS);
                    401: }
                    402: 
                    403: uint32_t helper_fp_exc_get (void)
                    404: {
                    405:     return get_float_exception_flags(&FP_STATUS);
                    406: }
                    407: 
                    408: /* Raise exceptions for ieee fp insns without software completion.
                    409:    In that case there are no exceptions that don't trap; the mask
                    410:    doesn't apply.  */
                    411: void helper_fp_exc_raise(uint32_t exc, uint32_t regno)
                    412: {
                    413:     if (exc) {
                    414:         uint32_t hw_exc = 0;
                    415: 
                    416:         if (exc & float_flag_invalid) {
                    417:             hw_exc |= EXC_M_INV;
                    418:         }
                    419:         if (exc & float_flag_divbyzero) {
                    420:             hw_exc |= EXC_M_DZE;
                    421:         }
                    422:         if (exc & float_flag_overflow) {
                    423:             hw_exc |= EXC_M_FOV;
                    424:         }
                    425:         if (exc & float_flag_underflow) {
                    426:             hw_exc |= EXC_M_UNF;
                    427:         }
                    428:         if (exc & float_flag_inexact) {
                    429:             hw_exc |= EXC_M_INE;
                    430:         }
1.1.1.8 ! root      431: 
        !           432:         arith_excp(hw_exc, 1ull << regno);
1.1.1.2   root      433:     }
1.1       root      434: }
                    435: 
1.1.1.6   root      436: /* Raise exceptions for ieee fp insns with software completion.  */
                    437: void helper_fp_exc_raise_s(uint32_t exc, uint32_t regno)
                    438: {
                    439:     if (exc) {
                    440:         env->fpcr_exc_status |= exc;
                    441: 
                    442:         exc &= ~env->fpcr_exc_mask;
                    443:         if (exc) {
                    444:             helper_fp_exc_raise(exc, regno);
                    445:         }
                    446:     }
                    447: }
                    448: 
                    449: /* Input remapping without software completion.  Handle denormal-map-to-zero
                    450:    and trap for all other non-finite numbers.  */
                    451: uint64_t helper_ieee_input(uint64_t val)
                    452: {
                    453:     uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
                    454:     uint64_t frac = val & 0xfffffffffffffull;
                    455: 
                    456:     if (exp == 0) {
                    457:         if (frac != 0) {
                    458:             /* If DNZ is set flush denormals to zero on input.  */
                    459:             if (env->fpcr_dnz) {
                    460:                 val &= 1ull << 63;
                    461:             } else {
1.1.1.8 ! root      462:                 arith_excp(EXC_M_UNF, 0);
1.1.1.6   root      463:             }
                    464:         }
                    465:     } else if (exp == 0x7ff) {
                    466:         /* Infinity or NaN.  */
                    467:         /* ??? I'm not sure these exception bit flags are correct.  I do
                    468:            know that the Linux kernel, at least, doesn't rely on them and
                    469:            just emulates the insn to figure out what exception to use.  */
1.1.1.8 ! root      470:         arith_excp(frac ? EXC_M_INV : EXC_M_FOV, 0);
1.1.1.6   root      471:     }
                    472:     return val;
                    473: }
                    474: 
                    475: /* Similar, but does not trap for infinities.  Used for comparisons.  */
                    476: uint64_t helper_ieee_input_cmp(uint64_t val)
                    477: {
                    478:     uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
                    479:     uint64_t frac = val & 0xfffffffffffffull;
                    480: 
                    481:     if (exp == 0) {
                    482:         if (frac != 0) {
                    483:             /* If DNZ is set flush denormals to zero on input.  */
                    484:             if (env->fpcr_dnz) {
                    485:                 val &= 1ull << 63;
                    486:             } else {
1.1.1.8 ! root      487:                 arith_excp(EXC_M_UNF, 0);
1.1.1.6   root      488:             }
                    489:         }
                    490:     } else if (exp == 0x7ff && frac) {
                    491:         /* NaN.  */
1.1.1.8 ! root      492:         arith_excp(EXC_M_INV, 0);
1.1.1.6   root      493:     }
                    494:     return val;
                    495: }
                    496: 
                    497: /* Input remapping with software completion enabled.  All we have to do
                    498:    is handle denormal-map-to-zero; all other inputs get exceptions as
                    499:    needed from the actual operation.  */
                    500: uint64_t helper_ieee_input_s(uint64_t val)
                    501: {
                    502:     if (env->fpcr_dnz) {
                    503:         uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
                    504:         if (exp == 0) {
                    505:             val &= 1ull << 63;
                    506:         }
                    507:     }
                    508:     return val;
                    509: }
1.1       root      510: 
1.1.1.2   root      511: /* F floating (VAX) */
1.1.1.4   root      512: static inline uint64_t float32_to_f(float32 fa)
1.1       root      513: {
1.1.1.2   root      514:     uint64_t r, exp, mant, sig;
                    515:     CPU_FloatU a;
                    516: 
                    517:     a.f = fa;
                    518:     sig = ((uint64_t)a.l & 0x80000000) << 32;
                    519:     exp = (a.l >> 23) & 0xff;
                    520:     mant = ((uint64_t)a.l & 0x007fffff) << 29;
                    521: 
                    522:     if (exp == 255) {
                    523:         /* NaN or infinity */
                    524:         r = 1; /* VAX dirty zero */
                    525:     } else if (exp == 0) {
                    526:         if (mant == 0) {
                    527:             /* Zero */
                    528:             r = 0;
                    529:         } else {
                    530:             /* Denormalized */
                    531:             r = sig | ((exp + 1) << 52) | mant;
                    532:         }
                    533:     } else {
                    534:         if (exp >= 253) {
                    535:             /* Overflow */
                    536:             r = 1; /* VAX dirty zero */
                    537:         } else {
                    538:             r = sig | ((exp + 2) << 52);
                    539:         }
                    540:     }
                    541: 
                    542:     return r;
1.1       root      543: }
                    544: 
1.1.1.4   root      545: static inline float32 f_to_float32(uint64_t a)
1.1       root      546: {
1.1.1.2   root      547:     uint32_t exp, mant_sig;
                    548:     CPU_FloatU r;
                    549: 
                    550:     exp = ((a >> 55) & 0x80) | ((a >> 52) & 0x7f);
                    551:     mant_sig = ((a >> 32) & 0x80000000) | ((a >> 29) & 0x007fffff);
                    552: 
                    553:     if (unlikely(!exp && mant_sig)) {
                    554:         /* Reserved operands / Dirty zero */
1.1.1.8 ! root      555:         dynamic_excp(EXCP_OPCDEC, 0);
1.1.1.2   root      556:     }
                    557: 
                    558:     if (exp < 3) {
                    559:         /* Underflow */
                    560:         r.l = 0;
                    561:     } else {
                    562:         r.l = ((exp - 2) << 23) | mant_sig;
                    563:     }
                    564: 
                    565:     return r.f;
1.1       root      566: }
                    567: 
1.1.1.2   root      568: uint32_t helper_f_to_memory (uint64_t a)
1.1       root      569: {
1.1.1.2   root      570:     uint32_t r;
                    571:     r =  (a & 0x00001fffe0000000ull) >> 13;
                    572:     r |= (a & 0x07ffe00000000000ull) >> 45;
                    573:     r |= (a & 0xc000000000000000ull) >> 48;
                    574:     return r;
1.1       root      575: }
                    576: 
1.1.1.2   root      577: uint64_t helper_memory_to_f (uint32_t a)
1.1       root      578: {
1.1.1.2   root      579:     uint64_t r;
                    580:     r =  ((uint64_t)(a & 0x0000c000)) << 48;
                    581:     r |= ((uint64_t)(a & 0x003fffff)) << 45;
                    582:     r |= ((uint64_t)(a & 0xffff0000)) << 13;
                    583:     if (!(a & 0x00004000))
                    584:         r |= 0x7ll << 59;
                    585:     return r;
1.1       root      586: }
                    587: 
1.1.1.6   root      588: /* ??? Emulating VAX arithmetic with IEEE arithmetic is wrong.  We should
                    589:    either implement VAX arithmetic properly or just signal invalid opcode.  */
                    590: 
1.1.1.2   root      591: uint64_t helper_addf (uint64_t a, uint64_t b)
1.1       root      592: {
1.1.1.2   root      593:     float32 fa, fb, fr;
1.1       root      594: 
1.1.1.2   root      595:     fa = f_to_float32(a);
                    596:     fb = f_to_float32(b);
                    597:     fr = float32_add(fa, fb, &FP_STATUS);
                    598:     return float32_to_f(fr);
1.1       root      599: }
                    600: 
1.1.1.2   root      601: uint64_t helper_subf (uint64_t a, uint64_t b)
1.1       root      602: {
1.1.1.2   root      603:     float32 fa, fb, fr;
1.1       root      604: 
1.1.1.2   root      605:     fa = f_to_float32(a);
                    606:     fb = f_to_float32(b);
                    607:     fr = float32_sub(fa, fb, &FP_STATUS);
                    608:     return float32_to_f(fr);
1.1       root      609: }
                    610: 
1.1.1.2   root      611: uint64_t helper_mulf (uint64_t a, uint64_t b)
1.1       root      612: {
1.1.1.2   root      613:     float32 fa, fb, fr;
1.1       root      614: 
1.1.1.2   root      615:     fa = f_to_float32(a);
                    616:     fb = f_to_float32(b);
                    617:     fr = float32_mul(fa, fb, &FP_STATUS);
                    618:     return float32_to_f(fr);
1.1       root      619: }
                    620: 
1.1.1.2   root      621: uint64_t helper_divf (uint64_t a, uint64_t b)
1.1       root      622: {
1.1.1.2   root      623:     float32 fa, fb, fr;
1.1       root      624: 
1.1.1.2   root      625:     fa = f_to_float32(a);
                    626:     fb = f_to_float32(b);
                    627:     fr = float32_div(fa, fb, &FP_STATUS);
                    628:     return float32_to_f(fr);
1.1       root      629: }
                    630: 
1.1.1.2   root      631: uint64_t helper_sqrtf (uint64_t t)
1.1       root      632: {
1.1.1.2   root      633:     float32 ft, fr;
1.1       root      634: 
1.1.1.2   root      635:     ft = f_to_float32(t);
                    636:     fr = float32_sqrt(ft, &FP_STATUS);
                    637:     return float32_to_f(fr);
1.1       root      638: }
                    639: 
1.1.1.2   root      640: 
                    641: /* G floating (VAX) */
1.1.1.4   root      642: static inline uint64_t float64_to_g(float64 fa)
1.1       root      643: {
1.1.1.2   root      644:     uint64_t r, exp, mant, sig;
                    645:     CPU_DoubleU a;
                    646: 
                    647:     a.d = fa;
                    648:     sig = a.ll & 0x8000000000000000ull;
                    649:     exp = (a.ll >> 52) & 0x7ff;
                    650:     mant = a.ll & 0x000fffffffffffffull;
                    651: 
                    652:     if (exp == 2047) {
                    653:         /* NaN or infinity */
                    654:         r = 1; /* VAX dirty zero */
                    655:     } else if (exp == 0) {
                    656:         if (mant == 0) {
                    657:             /* Zero */
                    658:             r = 0;
                    659:         } else {
                    660:             /* Denormalized */
                    661:             r = sig | ((exp + 1) << 52) | mant;
                    662:         }
                    663:     } else {
                    664:         if (exp >= 2045) {
                    665:             /* Overflow */
                    666:             r = 1; /* VAX dirty zero */
                    667:         } else {
                    668:             r = sig | ((exp + 2) << 52);
                    669:         }
                    670:     }
1.1       root      671: 
1.1.1.2   root      672:     return r;
1.1       root      673: }
                    674: 
1.1.1.4   root      675: static inline float64 g_to_float64(uint64_t a)
1.1       root      676: {
1.1.1.2   root      677:     uint64_t exp, mant_sig;
                    678:     CPU_DoubleU r;
                    679: 
                    680:     exp = (a >> 52) & 0x7ff;
                    681:     mant_sig = a & 0x800fffffffffffffull;
                    682: 
                    683:     if (!exp && mant_sig) {
                    684:         /* Reserved operands / Dirty zero */
1.1.1.8 ! root      685:         dynamic_excp(EXCP_OPCDEC, 0);
1.1.1.2   root      686:     }
1.1       root      687: 
1.1.1.2   root      688:     if (exp < 3) {
                    689:         /* Underflow */
                    690:         r.ll = 0;
                    691:     } else {
                    692:         r.ll = ((exp - 2) << 52) | mant_sig;
                    693:     }
                    694: 
                    695:     return r.d;
1.1       root      696: }
                    697: 
1.1.1.2   root      698: uint64_t helper_g_to_memory (uint64_t a)
1.1       root      699: {
1.1.1.2   root      700:     uint64_t r;
                    701:     r =  (a & 0x000000000000ffffull) << 48;
                    702:     r |= (a & 0x00000000ffff0000ull) << 16;
                    703:     r |= (a & 0x0000ffff00000000ull) >> 16;
                    704:     r |= (a & 0xffff000000000000ull) >> 48;
                    705:     return r;
1.1       root      706: }
                    707: 
1.1.1.2   root      708: uint64_t helper_memory_to_g (uint64_t a)
1.1       root      709: {
1.1.1.2   root      710:     uint64_t r;
                    711:     r =  (a & 0x000000000000ffffull) << 48;
                    712:     r |= (a & 0x00000000ffff0000ull) << 16;
                    713:     r |= (a & 0x0000ffff00000000ull) >> 16;
                    714:     r |= (a & 0xffff000000000000ull) >> 48;
                    715:     return r;
1.1       root      716: }
                    717: 
1.1.1.2   root      718: uint64_t helper_addg (uint64_t a, uint64_t b)
1.1       root      719: {
1.1.1.2   root      720:     float64 fa, fb, fr;
1.1       root      721: 
1.1.1.2   root      722:     fa = g_to_float64(a);
                    723:     fb = g_to_float64(b);
                    724:     fr = float64_add(fa, fb, &FP_STATUS);
                    725:     return float64_to_g(fr);
1.1       root      726: }
                    727: 
1.1.1.2   root      728: uint64_t helper_subg (uint64_t a, uint64_t b)
1.1       root      729: {
1.1.1.2   root      730:     float64 fa, fb, fr;
1.1       root      731: 
1.1.1.2   root      732:     fa = g_to_float64(a);
                    733:     fb = g_to_float64(b);
                    734:     fr = float64_sub(fa, fb, &FP_STATUS);
                    735:     return float64_to_g(fr);
1.1       root      736: }
                    737: 
1.1.1.2   root      738: uint64_t helper_mulg (uint64_t a, uint64_t b)
1.1       root      739: {
1.1.1.2   root      740:     float64 fa, fb, fr;
1.1       root      741: 
1.1.1.2   root      742:     fa = g_to_float64(a);
                    743:     fb = g_to_float64(b);
                    744:     fr = float64_mul(fa, fb, &FP_STATUS);
                    745:     return float64_to_g(fr);
1.1       root      746: }
                    747: 
1.1.1.2   root      748: uint64_t helper_divg (uint64_t a, uint64_t b)
1.1       root      749: {
1.1.1.2   root      750:     float64 fa, fb, fr;
1.1       root      751: 
1.1.1.2   root      752:     fa = g_to_float64(a);
                    753:     fb = g_to_float64(b);
                    754:     fr = float64_div(fa, fb, &FP_STATUS);
                    755:     return float64_to_g(fr);
1.1       root      756: }
                    757: 
1.1.1.2   root      758: uint64_t helper_sqrtg (uint64_t a)
1.1       root      759: {
1.1.1.2   root      760:     float64 fa, fr;
1.1       root      761: 
1.1.1.2   root      762:     fa = g_to_float64(a);
                    763:     fr = float64_sqrt(fa, &FP_STATUS);
                    764:     return float64_to_g(fr);
1.1       root      765: }
                    766: 
1.1.1.2   root      767: 
                    768: /* S floating (single) */
1.1.1.6   root      769: 
                    770: /* Taken from linux/arch/alpha/kernel/traps.c, s_mem_to_reg.  */
                    771: static inline uint64_t float32_to_s_int(uint32_t fi)
                    772: {
                    773:     uint32_t frac = fi & 0x7fffff;
                    774:     uint32_t sign = fi >> 31;
                    775:     uint32_t exp_msb = (fi >> 30) & 1;
                    776:     uint32_t exp_low = (fi >> 23) & 0x7f;
                    777:     uint32_t exp;
                    778: 
                    779:     exp = (exp_msb << 10) | exp_low;
                    780:     if (exp_msb) {
                    781:         if (exp_low == 0x7f)
                    782:             exp = 0x7ff;
                    783:     } else {
                    784:         if (exp_low != 0x00)
                    785:             exp |= 0x380;
                    786:     }
                    787: 
                    788:     return (((uint64_t)sign << 63)
                    789:             | ((uint64_t)exp << 52)
                    790:             | ((uint64_t)frac << 29));
                    791: }
                    792: 
1.1.1.4   root      793: static inline uint64_t float32_to_s(float32 fa)
1.1       root      794: {
1.1.1.2   root      795:     CPU_FloatU a;
                    796:     a.f = fa;
1.1.1.6   root      797:     return float32_to_s_int(a.l);
                    798: }
1.1       root      799: 
1.1.1.6   root      800: static inline uint32_t s_to_float32_int(uint64_t a)
                    801: {
                    802:     return ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff);
1.1       root      803: }
                    804: 
1.1.1.4   root      805: static inline float32 s_to_float32(uint64_t a)
1.1       root      806: {
1.1.1.2   root      807:     CPU_FloatU r;
1.1.1.6   root      808:     r.l = s_to_float32_int(a);
1.1.1.2   root      809:     return r.f;
                    810: }
1.1       root      811: 
1.1.1.2   root      812: uint32_t helper_s_to_memory (uint64_t a)
                    813: {
1.1.1.6   root      814:     return s_to_float32_int(a);
1.1       root      815: }
                    816: 
1.1.1.2   root      817: uint64_t helper_memory_to_s (uint32_t a)
1.1       root      818: {
1.1.1.6   root      819:     return float32_to_s_int(a);
1.1.1.2   root      820: }
1.1       root      821: 
1.1.1.2   root      822: uint64_t helper_adds (uint64_t a, uint64_t b)
                    823: {
                    824:     float32 fa, fb, fr;
1.1       root      825: 
1.1.1.2   root      826:     fa = s_to_float32(a);
                    827:     fb = s_to_float32(b);
                    828:     fr = float32_add(fa, fb, &FP_STATUS);
                    829:     return float32_to_s(fr);
1.1       root      830: }
                    831: 
1.1.1.2   root      832: uint64_t helper_subs (uint64_t a, uint64_t b)
1.1       root      833: {
1.1.1.2   root      834:     float32 fa, fb, fr;
1.1       root      835: 
1.1.1.2   root      836:     fa = s_to_float32(a);
                    837:     fb = s_to_float32(b);
                    838:     fr = float32_sub(fa, fb, &FP_STATUS);
                    839:     return float32_to_s(fr);
1.1       root      840: }
                    841: 
1.1.1.2   root      842: uint64_t helper_muls (uint64_t a, uint64_t b)
1.1       root      843: {
1.1.1.2   root      844:     float32 fa, fb, fr;
1.1       root      845: 
1.1.1.2   root      846:     fa = s_to_float32(a);
                    847:     fb = s_to_float32(b);
                    848:     fr = float32_mul(fa, fb, &FP_STATUS);
                    849:     return float32_to_s(fr);
1.1       root      850: }
                    851: 
1.1.1.2   root      852: uint64_t helper_divs (uint64_t a, uint64_t b)
1.1       root      853: {
1.1.1.2   root      854:     float32 fa, fb, fr;
1.1       root      855: 
1.1.1.2   root      856:     fa = s_to_float32(a);
                    857:     fb = s_to_float32(b);
                    858:     fr = float32_div(fa, fb, &FP_STATUS);
                    859:     return float32_to_s(fr);
1.1       root      860: }
                    861: 
1.1.1.2   root      862: uint64_t helper_sqrts (uint64_t a)
1.1       root      863: {
1.1.1.2   root      864:     float32 fa, fr;
1.1       root      865: 
1.1.1.2   root      866:     fa = s_to_float32(a);
                    867:     fr = float32_sqrt(fa, &FP_STATUS);
                    868:     return float32_to_s(fr);
1.1       root      869: }
                    870: 
                    871: 
1.1.1.2   root      872: /* T floating (double) */
1.1.1.4   root      873: static inline float64 t_to_float64(uint64_t a)
1.1.1.2   root      874: {
                    875:     /* Memory format is the same as float64 */
                    876:     CPU_DoubleU r;
                    877:     r.ll = a;
                    878:     return r.d;
1.1       root      879: }
                    880: 
1.1.1.4   root      881: static inline uint64_t float64_to_t(float64 fa)
1.1       root      882: {
1.1.1.2   root      883:     /* Memory format is the same as float64 */
                    884:     CPU_DoubleU r;
                    885:     r.d = fa;
                    886:     return r.ll;
1.1       root      887: }
                    888: 
1.1.1.2   root      889: uint64_t helper_addt (uint64_t a, uint64_t b)
1.1       root      890: {
1.1.1.2   root      891:     float64 fa, fb, fr;
1.1       root      892: 
1.1.1.2   root      893:     fa = t_to_float64(a);
                    894:     fb = t_to_float64(b);
                    895:     fr = float64_add(fa, fb, &FP_STATUS);
                    896:     return float64_to_t(fr);
1.1       root      897: }
                    898: 
1.1.1.2   root      899: uint64_t helper_subt (uint64_t a, uint64_t b)
1.1       root      900: {
1.1.1.2   root      901:     float64 fa, fb, fr;
1.1       root      902: 
1.1.1.2   root      903:     fa = t_to_float64(a);
                    904:     fb = t_to_float64(b);
                    905:     fr = float64_sub(fa, fb, &FP_STATUS);
                    906:     return float64_to_t(fr);
1.1       root      907: }
                    908: 
1.1.1.2   root      909: uint64_t helper_mult (uint64_t a, uint64_t b)
1.1       root      910: {
1.1.1.2   root      911:     float64 fa, fb, fr;
1.1       root      912: 
1.1.1.2   root      913:     fa = t_to_float64(a);
                    914:     fb = t_to_float64(b);
                    915:     fr = float64_mul(fa, fb, &FP_STATUS);
                    916:     return float64_to_t(fr);
1.1       root      917: }
                    918: 
1.1.1.2   root      919: uint64_t helper_divt (uint64_t a, uint64_t b)
1.1       root      920: {
1.1.1.2   root      921:     float64 fa, fb, fr;
1.1       root      922: 
1.1.1.2   root      923:     fa = t_to_float64(a);
                    924:     fb = t_to_float64(b);
                    925:     fr = float64_div(fa, fb, &FP_STATUS);
                    926:     return float64_to_t(fr);
1.1       root      927: }
                    928: 
1.1.1.2   root      929: uint64_t helper_sqrtt (uint64_t a)
1.1       root      930: {
1.1.1.2   root      931:     float64 fa, fr;
1.1       root      932: 
1.1.1.2   root      933:     fa = t_to_float64(a);
                    934:     fr = float64_sqrt(fa, &FP_STATUS);
                    935:     return float64_to_t(fr);
1.1       root      936: }
                    937: 
1.1.1.2   root      938: /* Comparisons */
                    939: uint64_t helper_cmptun (uint64_t a, uint64_t b)
1.1       root      940: {
1.1.1.2   root      941:     float64 fa, fb;
1.1       root      942: 
1.1.1.2   root      943:     fa = t_to_float64(a);
                    944:     fb = t_to_float64(b);
                    945: 
1.1.1.8 ! root      946:     if (float64_unordered_quiet(fa, fb, &FP_STATUS)) {
1.1.1.2   root      947:         return 0x4000000000000000ULL;
1.1.1.8 ! root      948:     } else {
1.1.1.2   root      949:         return 0;
1.1.1.8 ! root      950:     }
1.1       root      951: }
                    952: 
1.1.1.2   root      953: uint64_t helper_cmpteq(uint64_t a, uint64_t b)
1.1       root      954: {
1.1.1.2   root      955:     float64 fa, fb;
1.1       root      956: 
1.1.1.2   root      957:     fa = t_to_float64(a);
                    958:     fb = t_to_float64(b);
                    959: 
1.1.1.8 ! root      960:     if (float64_eq_quiet(fa, fb, &FP_STATUS))
1.1.1.2   root      961:         return 0x4000000000000000ULL;
                    962:     else
                    963:         return 0;
1.1       root      964: }
                    965: 
1.1.1.2   root      966: uint64_t helper_cmptle(uint64_t a, uint64_t b)
1.1       root      967: {
1.1.1.2   root      968:     float64 fa, fb;
1.1       root      969: 
1.1.1.2   root      970:     fa = t_to_float64(a);
                    971:     fb = t_to_float64(b);
                    972: 
                    973:     if (float64_le(fa, fb, &FP_STATUS))
                    974:         return 0x4000000000000000ULL;
                    975:     else
                    976:         return 0;
1.1       root      977: }
                    978: 
1.1.1.2   root      979: uint64_t helper_cmptlt(uint64_t a, uint64_t b)
1.1       root      980: {
1.1.1.2   root      981:     float64 fa, fb;
1.1       root      982: 
1.1.1.2   root      983:     fa = t_to_float64(a);
                    984:     fb = t_to_float64(b);
                    985: 
                    986:     if (float64_lt(fa, fb, &FP_STATUS))
                    987:         return 0x4000000000000000ULL;
                    988:     else
                    989:         return 0;
1.1       root      990: }
                    991: 
1.1.1.2   root      992: uint64_t helper_cmpgeq(uint64_t a, uint64_t b)
1.1       root      993: {
1.1.1.2   root      994:     float64 fa, fb;
                    995: 
                    996:     fa = g_to_float64(a);
                    997:     fb = g_to_float64(b);
1.1       root      998: 
1.1.1.8 ! root      999:     if (float64_eq_quiet(fa, fb, &FP_STATUS))
1.1.1.2   root     1000:         return 0x4000000000000000ULL;
                   1001:     else
                   1002:         return 0;
1.1       root     1003: }
                   1004: 
1.1.1.2   root     1005: uint64_t helper_cmpgle(uint64_t a, uint64_t b)
1.1       root     1006: {
1.1.1.2   root     1007:     float64 fa, fb;
1.1       root     1008: 
1.1.1.2   root     1009:     fa = g_to_float64(a);
                   1010:     fb = g_to_float64(b);
                   1011: 
                   1012:     if (float64_le(fa, fb, &FP_STATUS))
                   1013:         return 0x4000000000000000ULL;
                   1014:     else
                   1015:         return 0;
1.1       root     1016: }
                   1017: 
1.1.1.2   root     1018: uint64_t helper_cmpglt(uint64_t a, uint64_t b)
1.1       root     1019: {
1.1.1.2   root     1020:     float64 fa, fb;
                   1021: 
                   1022:     fa = g_to_float64(a);
                   1023:     fb = g_to_float64(b);
1.1       root     1024: 
1.1.1.2   root     1025:     if (float64_lt(fa, fb, &FP_STATUS))
                   1026:         return 0x4000000000000000ULL;
                   1027:     else
                   1028:         return 0;
1.1       root     1029: }
                   1030: 
1.1.1.2   root     1031: /* Floating point format conversion */
                   1032: uint64_t helper_cvtts (uint64_t a)
                   1033: {
                   1034:     float64 fa;
                   1035:     float32 fr;
                   1036: 
                   1037:     fa = t_to_float64(a);
                   1038:     fr = float64_to_float32(fa, &FP_STATUS);
                   1039:     return float32_to_s(fr);
1.1       root     1040: }
                   1041: 
1.1.1.2   root     1042: uint64_t helper_cvtst (uint64_t a)
1.1       root     1043: {
1.1.1.2   root     1044:     float32 fa;
                   1045:     float64 fr;
1.1       root     1046: 
1.1.1.2   root     1047:     fa = s_to_float32(a);
                   1048:     fr = float32_to_float64(fa, &FP_STATUS);
                   1049:     return float64_to_t(fr);
1.1       root     1050: }
                   1051: 
1.1.1.2   root     1052: uint64_t helper_cvtqs (uint64_t a)
1.1       root     1053: {
1.1.1.2   root     1054:     float32 fr = int64_to_float32(a, &FP_STATUS);
                   1055:     return float32_to_s(fr);
1.1       root     1056: }
                   1057: 
1.1.1.6   root     1058: /* Implement float64 to uint64 conversion without saturation -- we must
                   1059:    supply the truncated result.  This behaviour is used by the compiler
                   1060:    to get unsigned conversion for free with the same instruction.
                   1061: 
                   1062:    The VI flag is set when overflow or inexact exceptions should be raised.  */
                   1063: 
                   1064: static inline uint64_t helper_cvttq_internal(uint64_t a, int roundmode, int VI)
1.1       root     1065: {
1.1.1.6   root     1066:     uint64_t frac, ret = 0;
                   1067:     uint32_t exp, sign, exc = 0;
                   1068:     int shift;
                   1069: 
                   1070:     sign = (a >> 63);
                   1071:     exp = (uint32_t)(a >> 52) & 0x7ff;
                   1072:     frac = a & 0xfffffffffffffull;
                   1073: 
                   1074:     if (exp == 0) {
                   1075:         if (unlikely(frac != 0)) {
                   1076:             goto do_underflow;
                   1077:         }
                   1078:     } else if (exp == 0x7ff) {
                   1079:         exc = (frac ? float_flag_invalid : VI ? float_flag_overflow : 0);
                   1080:     } else {
                   1081:         /* Restore implicit bit.  */
                   1082:         frac |= 0x10000000000000ull;
                   1083: 
                   1084:         shift = exp - 1023 - 52;
                   1085:         if (shift >= 0) {
                   1086:             /* In this case the number is so large that we must shift
                   1087:                the fraction left.  There is no rounding to do.  */
                   1088:             if (shift < 63) {
                   1089:                 ret = frac << shift;
                   1090:                 if (VI && (ret >> shift) != frac) {
                   1091:                     exc = float_flag_overflow;
                   1092:                 }
                   1093:             }
                   1094:         } else {
                   1095:             uint64_t round;
                   1096: 
                   1097:             /* In this case the number is smaller than the fraction as
                   1098:                represented by the 52 bit number.  Here we must think
                   1099:                about rounding the result.  Handle this by shifting the
                   1100:                fractional part of the number into the high bits of ROUND.
                   1101:                This will let us efficiently handle round-to-nearest.  */
                   1102:             shift = -shift;
                   1103:             if (shift < 63) {
                   1104:                 ret = frac >> shift;
                   1105:                 round = frac << (64 - shift);
                   1106:             } else {
                   1107:                 /* The exponent is so small we shift out everything.
                   1108:                    Leave a sticky bit for proper rounding below.  */
                   1109:             do_underflow:
                   1110:                 round = 1;
                   1111:             }
                   1112: 
                   1113:             if (round) {
                   1114:                 exc = (VI ? float_flag_inexact : 0);
                   1115:                 switch (roundmode) {
                   1116:                 case float_round_nearest_even:
                   1117:                     if (round == (1ull << 63)) {
                   1118:                         /* Fraction is exactly 0.5; round to even.  */
                   1119:                         ret += (ret & 1);
                   1120:                     } else if (round > (1ull << 63)) {
                   1121:                         ret += 1;
                   1122:                     }
                   1123:                     break;
                   1124:                 case float_round_to_zero:
                   1125:                     break;
                   1126:                 case float_round_up:
                   1127:                     ret += 1 - sign;
                   1128:                     break;
                   1129:                 case float_round_down:
                   1130:                     ret += sign;
                   1131:                     break;
                   1132:                 }
                   1133:             }
                   1134:         }
                   1135:         if (sign) {
                   1136:             ret = -ret;
                   1137:         }
                   1138:     }
                   1139:     if (unlikely(exc)) {
                   1140:         float_raise(exc, &FP_STATUS);
                   1141:     }
                   1142: 
                   1143:     return ret;
                   1144: }
                   1145: 
                   1146: uint64_t helper_cvttq(uint64_t a)
                   1147: {
                   1148:     return helper_cvttq_internal(a, FP_STATUS.float_rounding_mode, 1);
                   1149: }
                   1150: 
                   1151: uint64_t helper_cvttq_c(uint64_t a)
                   1152: {
                   1153:     return helper_cvttq_internal(a, float_round_to_zero, 0);
                   1154: }
                   1155: 
                   1156: uint64_t helper_cvttq_svic(uint64_t a)
                   1157: {
                   1158:     return helper_cvttq_internal(a, float_round_to_zero, 1);
1.1       root     1159: }
                   1160: 
1.1.1.2   root     1161: uint64_t helper_cvtqt (uint64_t a)
1.1       root     1162: {
1.1.1.2   root     1163:     float64 fr = int64_to_float64(a, &FP_STATUS);
                   1164:     return float64_to_t(fr);
1.1       root     1165: }
                   1166: 
1.1.1.2   root     1167: uint64_t helper_cvtqf (uint64_t a)
1.1       root     1168: {
1.1.1.2   root     1169:     float32 fr = int64_to_float32(a, &FP_STATUS);
                   1170:     return float32_to_f(fr);
1.1       root     1171: }
                   1172: 
1.1.1.2   root     1173: uint64_t helper_cvtgf (uint64_t a)
1.1       root     1174: {
1.1.1.2   root     1175:     float64 fa;
                   1176:     float32 fr;
                   1177: 
                   1178:     fa = g_to_float64(a);
                   1179:     fr = float64_to_float32(fa, &FP_STATUS);
                   1180:     return float32_to_f(fr);
1.1       root     1181: }
                   1182: 
1.1.1.2   root     1183: uint64_t helper_cvtgq (uint64_t a)
1.1       root     1184: {
1.1.1.2   root     1185:     float64 fa = g_to_float64(a);
                   1186:     return float64_to_int64_round_to_zero(fa, &FP_STATUS);
1.1       root     1187: }
                   1188: 
1.1.1.2   root     1189: uint64_t helper_cvtqg (uint64_t a)
1.1       root     1190: {
1.1.1.2   root     1191:     float64 fr;
                   1192:     fr = int64_to_float64(a, &FP_STATUS);
                   1193:     return float64_to_g(fr);
1.1       root     1194: }
                   1195: 
1.1.1.2   root     1196: /* PALcode support special instructions */
1.1       root     1197: #if !defined (CONFIG_USER_ONLY)
1.1.1.2   root     1198: void helper_hw_ret (uint64_t a)
                   1199: {
                   1200:     env->pc = a & ~3;
1.1.1.6   root     1201:     env->intr_flag = 0;
                   1202:     env->lock_addr = -1;
1.1.1.8 ! root     1203:     if ((a & 1) == 0) {
        !          1204:         env->pal_mode = 0;
        !          1205:         swap_shadow_regs(env);
        !          1206:     }
1.1       root     1207: }
                   1208: 
1.1.1.8 ! root     1209: void helper_tbia(void)
1.1       root     1210: {
1.1.1.8 ! root     1211:     tlb_flush(env, 1);
1.1       root     1212: }
                   1213: 
1.1.1.8 ! root     1214: void helper_tbis(uint64_t p)
1.1       root     1215: {
1.1.1.8 ! root     1216:     tlb_flush_page(env, p);
1.1       root     1217: }
                   1218: #endif
                   1219: 
                   1220: /*****************************************************************************/
                   1221: /* Softmmu support */
                   1222: #if !defined (CONFIG_USER_ONLY)
1.1.1.8 ! root     1223: uint64_t helper_ldl_phys(uint64_t p)
1.1.1.2   root     1224: {
1.1.1.8 ! root     1225:     return (int32_t)ldl_phys(p);
1.1.1.2   root     1226: }
                   1227: 
1.1.1.8 ! root     1228: uint64_t helper_ldq_phys(uint64_t p)
1.1.1.2   root     1229: {
1.1.1.8 ! root     1230:     return ldq_phys(p);
1.1.1.2   root     1231: }
                   1232: 
1.1.1.8 ! root     1233: uint64_t helper_ldl_l_phys(uint64_t p)
1.1.1.2   root     1234: {
1.1.1.8 ! root     1235:     env->lock_addr = p;
        !          1236:     return env->lock_value = (int32_t)ldl_phys(p);
1.1.1.2   root     1237: }
                   1238: 
1.1.1.8 ! root     1239: uint64_t helper_ldq_l_phys(uint64_t p)
1.1.1.2   root     1240: {
1.1.1.8 ! root     1241:     env->lock_addr = p;
        !          1242:     return env->lock_value = ldl_phys(p);
1.1.1.2   root     1243: }
                   1244: 
1.1.1.8 ! root     1245: void helper_stl_phys(uint64_t p, uint64_t v)
1.1.1.2   root     1246: {
1.1.1.8 ! root     1247:     stl_phys(p, v);
1.1.1.2   root     1248: }
                   1249: 
1.1.1.8 ! root     1250: void helper_stq_phys(uint64_t p, uint64_t v)
1.1.1.2   root     1251: {
1.1.1.8 ! root     1252:     stq_phys(p, v);
1.1.1.2   root     1253: }
                   1254: 
1.1.1.8 ! root     1255: uint64_t helper_stl_c_phys(uint64_t p, uint64_t v)
1.1.1.2   root     1256: {
1.1.1.8 ! root     1257:     uint64_t ret = 0;
1.1.1.2   root     1258: 
1.1.1.8 ! root     1259:     if (p == env->lock_addr) {
        !          1260:         int32_t old = ldl_phys(p);
        !          1261:         if (old == (int32_t)env->lock_value) {
        !          1262:             stl_phys(p, v);
        !          1263:             ret = 1;
        !          1264:         }
        !          1265:     }
        !          1266:     env->lock_addr = -1;
1.1.1.2   root     1267: 
1.1.1.8 ! root     1268:     return ret;
1.1.1.2   root     1269: }
                   1270: 
1.1.1.8 ! root     1271: uint64_t helper_stq_c_phys(uint64_t p, uint64_t v)
1.1.1.2   root     1272: {
1.1.1.8 ! root     1273:     uint64_t ret = 0;
1.1.1.2   root     1274: 
1.1.1.8 ! root     1275:     if (p == env->lock_addr) {
        !          1276:         uint64_t old = ldq_phys(p);
        !          1277:         if (old == env->lock_value) {
        !          1278:             stq_phys(p, v);
        !          1279:             ret = 1;
        !          1280:         }
        !          1281:     }
        !          1282:     env->lock_addr = -1;
1.1.1.2   root     1283: 
                   1284:     return ret;
                   1285: }
                   1286: 
1.1.1.8 ! root     1287: static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write,
        !          1288:                                               int is_user, void *retaddr)
1.1.1.2   root     1289: {
1.1.1.8 ! root     1290:     uint64_t pc;
        !          1291:     uint32_t insn;
1.1.1.2   root     1292: 
1.1.1.8 ! root     1293:     do_restore_state(retaddr);
1.1.1.2   root     1294: 
1.1.1.8 ! root     1295:     pc = env->pc;
        !          1296:     insn = ldl_code(pc);
1.1.1.2   root     1297: 
1.1.1.8 ! root     1298:     env->trap_arg0 = addr;
        !          1299:     env->trap_arg1 = insn >> 26;                /* opcode */
        !          1300:     env->trap_arg2 = (insn >> 21) & 31;         /* dest regno */
        !          1301:     helper_excp(EXCP_UNALIGN, 0);
        !          1302: }
        !          1303: 
        !          1304: void QEMU_NORETURN cpu_unassigned_access(CPUState *env1,
        !          1305:                                          target_phys_addr_t addr, int is_write,
        !          1306:                                          int is_exec, int unused, int size)
        !          1307: {
        !          1308:     env = env1;
        !          1309:     env->trap_arg0 = addr;
        !          1310:     env->trap_arg1 = is_write;
        !          1311:     dynamic_excp(EXCP_MCHK, 0);
1.1       root     1312: }
                   1313: 
                   1314: #define MMUSUFFIX _mmu
1.1.1.8 ! root     1315: #define ALIGNED_ONLY
1.1       root     1316: 
                   1317: #define SHIFT 0
                   1318: #include "softmmu_template.h"
                   1319: 
                   1320: #define SHIFT 1
                   1321: #include "softmmu_template.h"
                   1322: 
                   1323: #define SHIFT 2
                   1324: #include "softmmu_template.h"
                   1325: 
                   1326: #define SHIFT 3
                   1327: #include "softmmu_template.h"
                   1328: 
                   1329: /* try to fill the TLB and return an exception if error. If retaddr is
                   1330:    NULL, it means that the function was called in C code (i.e. not
                   1331:    from generated code or from helper.c) */
                   1332: /* XXX: fix it to restore all registers */
                   1333: void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
                   1334: {
                   1335:     CPUState *saved_env;
                   1336:     int ret;
                   1337: 
                   1338:     /* XXX: hack to restore env in all cases, even if not called from
                   1339:        generated code */
                   1340:     saved_env = env;
                   1341:     env = cpu_single_env;
                   1342:     ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1.1.1.8 ! root     1343:     if (unlikely(ret != 0)) {
        !          1344:         do_restore_state(retaddr);
1.1       root     1345:         /* Exception index and error code are already set */
1.1.1.8 ! root     1346:         cpu_loop_exit(env);
1.1       root     1347:     }
                   1348:     env = saved_env;
                   1349: }
                   1350: #endif

unix.superglobalmegacorp.com

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