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

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

unix.superglobalmegacorp.com

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